URL
https://opencores.org/ocsvn/thor/thor/trunk
Subversion Repositories thor
Compare Revisions
- This comparison shows the changes necessary to convert path
/thor
- from Rev 41 to Rev 42
- ↔ Reverse comparison
Rev 41 → Rev 42
/trunk/rtl/verilog/Thor.v
101,7 → 101,7
// |
`include "Thor_defines.v" |
|
module Thor(corenum, rst_i, clk_i, clk_o, km, nmi_i, irq_i, vec_i, bte_o, cti_o, bl_o, lock_o, resv_o, resv_i, cres_o, |
module Thor(corenum, rst_i, clk_i, clk2x_i, clk_o, km, nmi_i, irq_i, vec_i, bte_o, cti_o, bl_o, lock_o, resv_o, resv_i, cres_o, |
cyc_o, stb_o, ack_i, err_i, we_o, sel_o, adr_o, dat_i, dat_o); |
parameter DBW = 32; // databus width |
parameter ABW = 32; // address bus width |
122,7 → 122,11
parameter IBUF3 = 4'd7; |
parameter IBUF4 = 4'd8; |
parameter IBUF5 = 4'd9; |
`ifdef VECTOROPS |
parameter NREGS = 511; |
`else |
parameter NREGS = 127; |
`endif |
parameter PF = 4'd0; |
parameter PT = 4'd1; |
parameter PEQ = 4'd2; |
138,6 → 142,7
input [63:0] corenum; |
input rst_i; |
input clk_i; |
input clk2x_i; |
output clk_o; |
output km; |
input nmi_i; |
162,6 → 167,8
|
integer n,i; |
reg [1:0] mode; |
reg [1:0] smode; |
reg [2:0] regset; |
reg [DBW/8-1:0] rsel; |
reg [3:0] cstate; |
reg [ABW:0] pc; // program counter (virtual) |
173,9 → 180,20
reg [DBW-1:0] cregs [0:15]; // code address registers |
reg [ 3:0] pregs [0:15]; // predicate registers |
`ifdef SEGMENTATION |
reg [DBW-1:12] sregs [0:7]; // segment registers |
reg [DBW-1:12] sregs_lmt [0:7]; |
reg [31:0] LDT; |
reg [DBW-1:0] GDT; |
reg [3:0] segsw; // |
reg [31:0] sregs [0:8]; // segment selector registers |
reg [DBW-1:12] sregs_base [0:8]; |
reg [DBW-1:12] sregs_lmt [0:8]; |
reg [15:0] sregs_acr [0:8]; |
wire [7:0] CPL = sregs[7][31:24]; // currently running privilege level |
`endif |
`ifdef VECTOROPS |
reg [3:0] vpregs [1:0][0:15]; // two, sixteen element |
`endif |
reg [7:0] VL = 0; |
reg [DBW-1:0] intarg1; |
reg [2:0] rrmapno; // register rename map number |
wire ITLBMiss; |
wire DTLBMiss; |
192,8 → 210,8
reg ic_invalidate,dc_invalidate; |
reg ic_invalidate_line,dc_invalidate_line; |
reg [ABW-1:0] ic_lineno,dc_lineno; |
reg ierr,derr; // err_i during icache load |
wire insnerr; // err_i during icache load |
reg ierr,derr; // err_i during icache load |
wire insnerr; // err_i during icache load |
wire [127:0] insn; |
wire iuncached; |
reg [NREGS:0] rf_v; |
215,7 → 233,7
wire dbg_commit; |
`ifdef SEGMENTATION |
wire [DBW-1:0] spc = (pc[ABW]==1'b1) ? pc[ABW-1:0] : |
(pc[ABW-1:ABW-4]==4'hF) ? pc[ABW-1:0] : {sregs[3'd7],12'h000} + pc[ABW-1:0]; |
(pc[ABW-1:ABW-4]==4'hF) ? pc[ABW-1:0] : {sregs_base[3'd7],12'h000} + pc[ABW-1:0]; |
`else |
wire [DBW-1:0] spc = pc; |
`endif |
223,6 → 241,7
reg [DBW-1:0] string_pc; |
reg stmv_flag; |
reg [7:0] asid; |
wire [DBW-1:0] operandA0, operandA1; |
|
wire clk; |
|
243,6 → 262,7
reg iqentry_br [0:7]; // branch instruction decode |
reg iqentry_agen [0:7]; // memory address is generated |
reg iqentry_mem [0:7]; // touches memory: 1 if LW/SW |
reg iqentry_vec [0:7]; // is a vector instruction |
reg iqentry_ndx [0:7]; // TRUE if indexed memory op |
reg iqentry_cas [0:7]; |
reg iqentry_pushpop [0:7]; |
267,25 → 287,33
reg [7:0] iqentry_op [0:7]; // instruction opcode |
reg [5:0] iqentry_fn [0:7]; // instruction function |
reg [2:0] iqentry_renmapno [0:7]; // register rename map number |
reg [6:0] iqentry_tgt [0:7]; // Rt field or ZERO -- this is the instruction's target (if any) |
reg [9:0] iqentry_tgt [0:7]; // Rt field or ZERO -- this is the instruction's target (if any) |
reg [DBW-1:0] iqentry_a0 [0:7]; // argument 0 (immediate) |
reg [DBW-1:0] iqentry_a1 [0:7]; // argument 1 |
reg [6:0] iqentry_r1 [0:7]; |
reg [7:0] iqentry_r1 [0:7]; |
reg iqentry_a1_v [0:7]; // arg1 valid |
reg [3:0] iqentry_a1_s [0:7]; // arg1 source (iq entry # with top bit representing ALU/DRAM bus) |
reg [6:0] iqentry_r2 [0:7]; |
reg [7:0] iqentry_r2 [0:7]; |
reg [DBW-1:0] iqentry_a2 [0:7]; // argument 2 |
reg iqentry_a2_v [0:7]; // arg2 valid |
reg [3:0] iqentry_a2_s [0:7]; // arg2 source (iq entry # with top bit representing ALU/DRAM bus) |
reg [6:0] iqentry_r3 [0:7]; |
reg iqentry_a2_sv [0:7]; // source is vector register |
reg [7:0] iqentry_r3 [0:7]; |
reg [DBW-1:0] iqentry_a3 [0:7]; // argument 3 |
reg iqentry_a3_v [0:7]; // arg3 valid |
reg [3:0] iqentry_a3_s [0:7]; // arg3 source (iq entry # with top bit representing ALU/DRAM bus) |
reg [6:0] iqentry_rt [0:7]; |
`ifdef VECTOROPS |
reg [7:0] iqentry_r4 [0:7]; |
reg [DBW-1:0] iqentry_a4 [0:7]; // argument 4 |
reg iqentry_a4_v [0:7]; |
reg [3:0] iqentry_a4_s [0:7]; |
`endif |
reg [7:0] iqentry_rt [0:7]; |
reg [DBW-1:0] iqentry_T [0:7]; |
reg iqentry_T_v [0:7]; |
reg [3:0] iqentry_T_s [0:7]; |
reg [DBW-1:0] iqentry_pc [0:7]; // program counter for this instruction |
reg iqentry_velv [0:7]; |
|
reg [7:0] iqentry_source; |
wire iqentry_imm [0:7]; |
319,6 → 347,8
|
reg queued1,queued2; |
reg queued3; // for three-way config |
reg queued1v,queued2v; |
reg queued3v; // for three-way config |
reg allowq; |
|
wire [NREGS:1] livetarget; |
368,6 → 398,7
reg [DBW-1:0] fetchbuf0_pc; |
reg fetchbuf0_v; |
wire fetchbuf0_mem; |
wire fetchbuf0_vec; |
wire fetchbuf0_jmp; |
wire fetchbuf0_fp; |
wire fetchbuf0_rfw; |
376,6 → 407,7
reg [DBW-1:0] fetchbuf1_pc; |
reg fetchbuf1_v; |
wire fetchbuf1_mem; |
wire fetchbuf1_vec; |
wire fetchbuf1_jmp; |
wire fetchbuf1_fp; |
wire fetchbuf1_rfw; |
385,6 → 417,7
reg [DBW-1:0] fetchbuf2_pc; |
reg fetchbuf2_v; |
wire fetchbuf2_mem; |
wire fetchbuf2_vec; |
wire fetchbuf2_jmp; |
wire fetchbuf2_fp; |
wire fetchbuf2_rfw; |
427,7 → 460,7
reg [DBW-1:0] alu0_pc; |
reg [DBW-1:0] alu0_bus; |
reg [3:0] alu0_id; |
wire [3:0] alu0_exc; |
wire [8:0] alu0_exc; |
reg alu0_v; |
wire alu0_branchmiss; |
reg [ABW:0] alu0_misspc; |
451,7 → 484,7
reg [DBW-1:0] alu1_pc; |
reg [DBW-1:0] alu1_bus; |
reg [3:0] alu1_id; |
wire [3:0] alu1_exc; |
wire [8:0] alu1_exc; |
reg alu1_v; |
wire alu1_branchmiss; |
reg [ABW:0] alu1_misspc; |
505,9 → 538,9
reg [ABW-1:12] dram0_lmt; // value of segment limit associated with memory operation |
reg [7:0] dram0_op; |
reg [5:0] dram0_fn; |
reg [8:0] dram0_tgt; |
reg [9:0] dram0_tgt; |
reg [3:0] dram0_id; |
reg [3:0] dram0_exc; |
reg [8:0] dram0_exc; |
reg [ABW-1:0] dram0_misspc; |
reg dram1_owns_bus; |
reg [DBW-1:0] dram1_data; |
515,22 → 548,22
reg [DBW-1:0] dram1_addr; |
reg [7:0] dram1_op; |
reg [5:0] dram1_fn; |
reg [6:0] dram1_tgt; |
reg [9:0] dram1_tgt; |
reg [3:0] dram1_id; |
reg [3:0] dram1_exc; |
reg [8:0] dram1_exc; |
reg [DBW-1:0] dram2_data; |
reg [DBW-1:0] dram2_datacmp; |
reg [DBW-1:0] dram2_addr; |
reg [7:0] dram2_op; |
reg [5:0] dram2_fn; |
reg [6:0] dram2_tgt; |
reg [9:0] dram2_tgt; |
reg [3:0] dram2_id; |
reg [3:0] dram2_exc; |
reg [8:0] dram2_exc; |
|
reg [DBW-1:0] dram_bus; |
reg [6:0] dram_tgt; |
reg [9:0] dram_tgt; |
reg [3:0] dram_id; |
reg [3:0] dram_exc; |
reg [8:0] dram_exc; |
reg dram_v; |
|
reg [DBW-1:0] index; |
542,12 → 575,16
|
wire commit0_v; |
wire [3:0] commit0_id; |
wire [6:0] commit0_tgt; |
wire [7:0] commit0_tgt; |
wire [DBW-1:0] commit0_bus; |
wire commit1_v; |
wire [3:0] commit1_id; |
wire [6:0] commit1_tgt; |
wire [7:0] commit1_tgt; |
wire [DBW-1:0] commit1_bus; |
wire commit2_v; |
wire [3:0] commit2_id; |
wire [7:0] commit2_tgt; |
wire [DBW-1:0] commit2_bus; |
wire limit_cmt; |
wire committing2; |
|
870,18 → 907,29
// If there aren't enough read ports available then the second instruction |
// isn't enqueued (it'll be enqueued in the next cycle). |
reg [1:0] ports_avail; // available read ports for instruction #3. |
reg [6:0] pRa0,pRb0,pRa1,pRb1,pRt0,pRt1; |
reg [9:0] pRa0,pRb0,pRa1,pRb1,pRt0,pRt1; |
wire [9:0] pRc0,pRd0,pRc1,pRd1; |
wire [DBW-1:0] prfoa0,prfob0,prfoa1,prfob1; |
wire [DBW-1:0] pvrfoa0,pvrfob0,pvrfoa1,pvrfob1,pvrfoc0,pvrfoc1; |
wire [DBW-1:0] prfot0,prfot1; |
wire [DBW-1:0] vrfot0,vrfot1; |
|
wire [6:0] Ra0 = fnRa(fetchbuf0_instr); |
wire [6:0] Rb0 = fnRb(fetchbuf0_instr); |
wire [6:0] Rc0 = fnRc(fetchbuf0_instr); |
wire [6:0] Ra1 = fnRa(fetchbuf1_instr); |
wire [6:0] Rb1 = fnRb(fetchbuf1_instr); |
wire [6:0] Rc1 = fnRc(fetchbuf1_instr); |
wire [6:0] Rt0 = fnTargetReg(fetchbuf0_instr); |
wire [6:0] Rt1 = fnTargetReg(fetchbuf1_instr); |
reg [2:0] vele; |
wire [7:0] Ra0 = fnRa(fetchbuf0_instr); |
wire [7:0] Rb0 = fnRb(fetchbuf0_instr); |
wire [7:0] Rc0 = fnRc(fetchbuf0_instr); |
wire [7:0] Rd0 = fnRd(fetchbuf0_instr); |
wire [7:0] Ra1 = fnRa(fetchbuf1_instr); |
wire [7:0] Rb1 = fnRb(fetchbuf1_instr); |
wire [7:0] Rc1 = fnRc(fetchbuf1_instr); |
wire [7:0] Rd1 = fnRd(fetchbuf1_instr); |
wire [7:0] Rt0 = fnTargetReg(fetchbuf0_instr); |
wire [7:0] Rt1 = fnTargetReg(fetchbuf1_instr); |
assign pRc0 = Rc0; |
assign pRd0 = Rd0; |
assign pRc1 = Rc1; |
assign pRd1 = Rd1; |
|
always @* |
begin |
pRt0 = Rt0; |
889,8 → 937,8
rfot0 = prfot0; |
rfot1 = prfot1; |
case(fetchbuf0_v ? fnNumReadPorts(fetchbuf0_instr) : 2'd0) |
2'd0: begin |
pRa0 = 7'd0; |
3'd0: begin |
pRa0 = 8'd0; |
pRb0 = Rc1; |
pRa1 = Ra1; |
pRb1 = Rb1; |
902,7 → 950,7
rfoc1 = prfob0; |
ports_avail = 2'd3; |
end |
2'd1: begin |
3'd1: begin |
pRa0 = Ra0; |
pRb0 = Rc1; |
pRa1 = Ra1; |
915,7 → 963,7
rfoc1 = prfob0; |
ports_avail = 2'd3; |
end |
2'd2: begin |
3'd2: begin |
pRa0 = Ra0; |
pRb0 = Rb0; |
pRa1 = Ra1; |
928,7 → 976,7
rfoc1 = 64'd0; |
ports_avail = 2'd2; |
end |
2'd3: begin |
3'd3: begin |
pRa0 = Ra0; |
pRb0 = Rb0; |
pRa1 = Rc0; |
941,6 → 989,19
rfoc1 = 64'd0; |
ports_avail = 2'd1; |
end |
default: begin |
pRa0 = 8'd0; |
pRb0 = Rc1; |
pRa1 = Ra1; |
pRb1 = Rb1; |
rfoa0 = 64'd0; |
rfob0 = 64'd0; |
rfoc0 = 64'd0; |
rfoa1 = prfoa1; |
rfob1 = prfob1; |
rfoc1 = prfob0; |
ports_avail = 2'd3; |
end |
endcase |
end |
|
962,24 → 1023,23
wire [3:0] cond0 = fetchbuf0_instr[3:0]; |
wire [3:0] cond1 = fetchbuf1_instr[3:0]; |
wire [3:0] Pn0 = fetchbuf0_instr[7:4]; |
wire [3:0] Pt0 = fetchbuf0_instr[11:8]; |
wire [3:0] Pn1 = fetchbuf1_instr[7:4]; |
wire [3:0] Pt1 = fetchbuf1_instr[11:8]; |
|
wire [6:0] r27 = 7'd27 + mode; |
|
function [6:0] fnRa; |
function [7:0] fnRa; |
input [63:0] isn; |
case(isn[15:8]) |
`RTS2: fnRa = 7'h51; |
`RTI: fnRa = 7'h5E; |
`RTD: fnRa = 7'h5B; |
`RTE: fnRa = 7'h5D; |
`RTF,`JSF: fnRa = 8'h5C; // cregs[12] |
`RTS2: fnRa = 8'h51; |
`RTI: fnRa = 8'h5E; |
`RTD: fnRa = 8'h5B; |
`RTE: fnRa = 8'h5D; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS: |
fnRa = {3'h5,isn[23:20]}; |
`TLB: fnRa = {1'b0,isn[29:24]}; |
`P: fnRa = 7'h70; |
`LOOP: fnRa = 7'h73; |
fnRa = {4'h5,isn[23:20]}; |
`TLB: fnRa = {4'b0,isn[29:24]}; |
`P: fnRa = 8'h70; |
`LOOP: fnRa = 8'h73; |
`PUSH: fnRa = r27; |
`ifdef STACKOPS |
`PEA,`POP,`LINK: fnRa = r27; |
986,18 → 1046,18
`endif |
`MFSPR,`MOVS: |
if (isn[`INSTRUCTION_RA]==`USP) |
fnRa = 7'd27; |
fnRa = 8'd27; |
else |
fnRa = {1'b1,isn[`INSTRUCTION_RA]}; |
fnRa = {4'd1,isn[`INSTRUCTION_RA]}; |
default: |
if (isn[`INSTRUCTION_RA]==6'd27) |
fnRa = r27; |
else |
fnRa = {1'b0,isn[`INSTRUCTION_RA]}; |
fnRa = {4'b0,isn[`INSTRUCTION_RA]}; |
endcase |
endfunction |
|
function [6:0] fnRb; |
function [7:0] fnRb; |
input [63:0] isn; |
case(isn[15:8]) |
// `LOOP: fnRb = 7'h73; |
1013,6 → 1073,20
`LINK: fnRb = {1'b0,isn[27:22]}; |
`PEA: fnRb = {1'b0,isn[21:16]}; |
`endif |
`ifdef VECTOROPS |
`VR: |
case(isn[39:34]) |
`VBITS2V: fnRb = {4'd0,isn[25:22]}; |
`VEINS: fnRb = {4'd0,isn[25:22]}; |
default: fnRb = {1'b1,vele,isn[25:22]}; |
endcase |
`VRR: |
case(isn[47:43]) |
`VSCALE: fnRb = {4'd0,isn[25:22]}; |
`VSCALEL: fnRb = {4'd0,isn[25:22]}; |
default: fnRb = {1'b1,vele,isn[25:22]}; |
endcase |
`endif |
default: |
if (isn[`INSTRUCTION_RB]==6'd27) |
fnRb = r27; |
1021,14 → 1095,25
endcase |
endfunction |
|
function [6:0] fnRc; |
function [7:0] fnRc; |
input [63:0] isn; |
if (isn[`INSTRUCTION_RC]==6'd27) |
fnRc = r27; |
else |
fnRc = {1'b0,isn[`INSTRUCTION_RC]}; |
case(isn[15:8]) |
`VRR,`VMAC: |
fnRc = {1'b1,vele,isn[37:34]}; |
default: |
if (isn[39:34]==6'd27) |
fnRc = r27; |
else |
fnRc = {4'b0,isn[`INSTRUCTION_RC]}; |
endcase |
|
endfunction |
|
function [7:0] fnRd; |
input [63:0] isn; |
fnRd = {1'b1,vele,isn[43:40]}; |
endfunction |
|
function [3:0] fnCar; |
input [63:0] isn; |
case(isn[15:8]) |
1089,11 → 1174,38
`PUSH,`PEA: fnFunc = km ? 6'b0 : 6'b110000; // select segment register #6 |
`JMPI: fnFunc = {isn[39:37],1'b0,isn[27:26]}; |
`JMPIX: fnFunc = {isn[39:37],1'b0,isn[33:32]}; |
`MTSPR: fnFunc = isn[31:28]; |
`ifdef VECTOROPS |
`VRR: fnFunc = isn[47:43]; |
`VR: fnFunc = isn[39:34]; |
`endif |
default: |
fnFunc = isn[39:34]; |
endcase |
endfunction |
|
function fnVelv; |
input [63:0] isn; |
case(isn[15:8]) |
`VR: |
case(isn[39:34]) |
6'd0: fnVelv = `FALSE; |
default: fnVelv = `TRUE; |
endcase |
default: fnVelv = `TRUE; |
endcase |
endfunction |
|
function fnVecL; |
input [63:0] isn; |
case(isn[15:8]) |
`VRR: fnVecL = isn[47]; |
`VR: fnVecL = isn[39]; |
`VMAC: fnVecL = isn[55]; |
default: fnVecL = 1'b0; |
endcase |
endfunction |
|
// Returns true if the operation is limited to ALU #0 |
function fnIsAlu0Op; |
input [7:0] opcode; |
1108,6 → 1220,7
`R2: fnIsAlu0Op = `TRUE; |
`RR: |
case(func) |
`MUL,`MULU: fnIsAlu0Op = `TRUE; |
`DIV,`DIVU: fnIsAlu0Op = `TRUE; |
`MOD,`MODU: fnIsAlu0Op = `TRUE; |
`MIN,`MAX: fnIsAlu0Op = `TRUE; |
1114,6 → 1227,7
default: fnIsAlu0Op = `FALSE; |
endcase |
`BCD: fnIsAlu0Op = `TRUE; |
`MULI,`MULUI: fnIsAlu0Op = `TRUE; |
`DIVI,`DIVUI: fnIsAlu0Op = `TRUE; |
`MODI,`MODUI: fnIsAlu0Op = `TRUE; |
//`DOUBLE: fnIsAlu0Op = `TRUE; |
1143,9 → 1257,11
Thor_regfile2w6r #(DBW) urf1 |
( |
.clk(clk), |
.clk2x(clk2x_i), |
.rclk(~clk), |
.wr0(commit0_v && ~commit0_tgt[6]), |
.wr1(commit1_v && ~commit1_tgt[6]), |
.regset(regset), |
.wr0(commit0_v && commit0_tgt[7:6]==2'h0), |
.wr1(commit1_v && commit1_tgt[7:6]==2'h0), |
.wa0(commit0_tgt[5:0]), |
.wa1(commit1_tgt[5:0]), |
.ra0(pRa0[5:0]), |
1164,6 → 1280,36
.o5(prfot1) |
); |
|
`ifdef VECTOROPS |
Thor_vregfile2w6r #(DBW) uvrf1 |
( |
.clk(clk), |
.rclk(~clk), |
.wr0(commit0_v && commit0_tgt[7]), |
.wr1(commit1_v && commit1_tgt[7]), |
.wa0(commit0_tgt[6:0]), |
.wa1(commit1_tgt[6:0]), |
.ra0(pRb0[6:0]), |
.ra1(pRc0[6:0]), |
.ra2(pRd0[6:0]), |
.ra3(pRb1[6:0]), |
.ra4(pRc1[6:0]), |
.ra5(pRd1[6:0]), |
.ra6(pRt0[6:0]), |
.ra7(pRt1[6:0]), |
.i0(commit0_bus), |
.i1(commit1_bus), |
.o0(pvrfoa0), |
.o1(pvrfob0), |
.o2(pvrfoc0), |
.o3(pvrfoa1), |
.o4(pvrfob1), |
.o5(pvrfoc1), |
.o6(vrfot0), |
.o7(vrfot1) |
); |
`endif |
|
wire [63:0] cregs0 = fnCar(fetchbuf0_instr)==4'd0 ? 64'd0 : fnCar(fetchbuf0_instr)==4'hF ? fetchbuf0_pc : cregs[fnCar(fetchbuf0_instr)]; |
wire [63:0] cregs1 = fnCar(fetchbuf1_instr)==4'd0 ? 64'd0 : fnCar(fetchbuf1_instr)==4'hF ? fetchbuf1_pc : cregs[fnCar(fetchbuf1_instr)]; |
// |
1172,7 → 1318,7
function fnSource1_v; |
input [7:0] opcode; |
case(opcode) |
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`STP: |
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`STP,`RTF,`JSF: |
fnSource1_v = 1'b1; |
`LDI,`LDIS,`IMM: fnSource1_v = 1'b1; |
default: |
1265,7 → 1411,7
`LVB,`LVC,`LVH,`LVW,`LVWAR, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`STI,`INC: |
fnSource2_v = 1'b1; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2: |
`JSR,`JSRS,`JSRZ,`JSF,`SYS,`INT,`RTS,`RTS2,`RTF: |
fnSource2_v = 1'b1; |
`MTSPR,`MFSPR,`POP,`UNLINK: |
fnSource2_v = 1'b1; |
1291,7 → 1437,7
case(opcode) |
`RR: |
case(func) |
`CHK: fnSource3_v = 1'b0; |
`CHK,`CHKX: fnSource3_v = 1'b0; |
default: fnSource3_v = 1'b1; |
endcase |
`SBX,`SCX,`SHX,`SWX,`CAS,`STMV,`STCMP,`STFND: fnSource3_v = 1'b0; |
1300,6 → 1446,20
endcase |
endfunction |
|
// Source #4 valid |
// Since most instructions don't use a fourth source the default it to return |
// a valid status. |
// 1 if the the operand is automatically valid, |
// 0 if we need a RF value |
function fnSource4_v; |
input [7:0] opcode; |
input [5:0] func; |
case(opcode) |
`VMAC: fnSource4_v = 1'b0; |
default: fnSource4_v = 1'b1; |
endcase |
endfunction |
|
function fnSourceT_v; |
input [7:0] opcode; |
input [5:0] func; |
1306,7 → 1466,7
case(opcode) |
`RR: |
case(func) |
`CHK: fnSourceT_v = 1'b1; |
`CHK,`CHKX: fnSourceT_v = 1'b1; |
default: fnSourceT_v = 1'b0; |
endcase |
// BR |
1314,8 → 1474,8
8'h34,8'h35,8'h36,8'h37, |
8'h38,8'h39,8'h3A,8'h3B, |
8'h3C,8'h3D,8'h3E,8'h3F, |
`SB,`SC,`SH,`SW,`SBX,`SCX,`SHX,`SWX,`SWS, |
`CACHE,`CHKI, |
`SB,`SC,`SH,`SW,`SBX,`SCX,`SHX,`SWX,`SWS,`SV,`SVWS,`SVX, |
`CACHE,`CHKI,`CHKXI, |
`SEI,`CLI,`NOP,`STP,`RTI,`RTD,`RTE, |
`MEMSB,`MEMDB,`SYNC: |
fnSourceT_v = 1'b1; |
1331,7 → 1491,7
fnNumReadPorts = 3'd0; |
`LDI,`LDIS,`IMM: fnNumReadPorts = 3'd0; |
`R,`P,`STI,`LOOP,`JMPI: fnNumReadPorts = 3'd1; |
`RTI,`RTD,`RTE: fnNumReadPorts = 3'd1; |
`RTI,`RTD,`RTE,`RTF,`JSF: fnNumReadPorts = 3'd1; |
`ADDI,`ADDUI,`ADDUIS: |
fnNumReadPorts = 3'd1; |
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI: |
1358,7 → 1518,7
`STFND: fnNumReadPorts = 3'd2; // *** TLB reads on Rb we say 2 for simplicity |
`RR: |
case(ins[39:34]) |
`CHK: fnNumReadPorts = 3'd3; |
`CHK,`CHKX: fnNumReadPorts = 3'd3; |
default: fnNumReadPorts = 3'd2; |
endcase |
`BITFIELD: |
1625,23 → 1785,44
// 7C = breakout index register |
// 7D = broken out register |
// 7F = power shift register |
function [6:0] fnTargetReg; |
// 80 vector reg #0, element #0 |
// 81 vector reg #1, element #0 |
// ... |
// 8F vector reg #15, element #0 |
// 90 vector reg #0, element #1 |
// ... |
// FF vector reg #15, element #7 |
|
function [7:0] fnTargetReg; |
input [63:0] ir; |
begin |
// Process special predicates (NOP, IMM) |
// Note that BRK (00) is already translated to a SYS instruction |
if (ir[3:0]==4'h0) |
fnTargetReg = 7'h000; |
fnTargetReg = 10'h000; |
else |
case(fnOpcode(ir)) |
`ifdef VECTOROPS |
`VR: |
case(ir[39:34]) |
`VEX: fnTargetReg = {5'h0,ir[30:28]}; |
default: fnTargetReg = {1'b1,vele,ir[30:28]}; |
endcase |
`LV: fnTargetReg = {1'b1,vele,ir[24:22]}; |
`LVWS,`LVX: fnTargetReg = {1'b1,vele,ir[30:28]}; |
`VLOG,`VADDSUB,`VMULDIV: fnTargetReg = {1'b1,vele,ir[30:28]}; |
// ToDo: assign register range for vector predicates |
// `VCMPS: |
`VMAC: fnTargetReg = {1'b1,vele,ir[43:40]}; |
`endif |
`POP: fnTargetReg = ir[22:16]; |
`LDI,`ADDUIS,`STS,`LINK,`UNLINK: |
if (ir[21:16]==6'd27) |
fnTargetReg = r27; |
else |
fnTargetReg = {1'b0,ir[21:16]}; |
fnTargetReg = {4'b0,ir[21:16]}; |
`LDIS: |
fnTargetReg = {1'b1,ir[21:16]}; |
fnTargetReg = {4'd1,ir[21:16]}; |
`RR, |
`SHIFT, |
`BCD, |
1650,7 → 1831,7
if (ir[33:28]==6'd27) |
fnTargetReg = r27; |
else |
fnTargetReg = {1'b0,ir[33:28]}; |
fnTargetReg = {4'b0,ir[33:28]}; |
`R,`R2,`DOUBLE_R,`SINGLE_R, |
`ADDI,`ADDUI,`SUBI,`SUBUI, |
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI, |
1662,16 → 1843,18
if (ir[27:22]==6'd27) |
fnTargetReg = r27; |
else |
fnTargetReg = {1'b0,ir[27:22]}; |
fnTargetReg = {4'b0,ir[27:22]}; |
`CAS: |
fnTargetReg = {1'b0,ir[39:34]}; |
fnTargetReg = {4'b0,ir[39:34]}; |
`TLB: |
if (ir[19:16]==`TLB_RDREG) |
fnTargetReg = {1'b0,ir[29:24]}; |
fnTargetReg = {4'b0,ir[29:24]}; |
else |
fnTargetReg = 7'h00; |
fnTargetReg = 10'h00; |
`BITI: |
fnTargetReg = {3'h4,ir[25:22]}; |
fnTargetReg = {6'h4,ir[25:22]}; |
`CHKI: |
fnTargetReg = {6'h4,ir[43:40]}; |
// TST |
8'h00,8'h01,8'h02,8'h03, |
8'h04,8'h05,8'h06,8'h07, |
1688,20 → 1871,21
8'h28,8'h29,8'h2A,8'h2B, |
8'h2C,8'h2D,8'h2E,8'h2F: |
begin |
fnTargetReg = {3'h4,ir[11:8]}; |
fnTargetReg = {6'h4,ir[11:8]}; |
end |
`SWCR: fnTargetReg = {3'h4,4'h0}; |
`SWCR: fnTargetReg = {6'h4,4'h0}; |
`JSR,`JSRZ,`JSRS,`SYS,`INT: |
fnTargetReg = {3'h5,ir[19:16]}; |
fnTargetReg = {4'h5,ir[19:16]}; |
`JSF: fnTargetReg = 8'h51; |
`JMPI: |
fnTargetReg = {3'h5,ir[25:22]}; |
fnTargetReg = {4'h5,ir[25:22]}; |
`JMPIX: |
fnTargetReg = {3'h5,ir[31:28]}; |
fnTargetReg = {4'h5,ir[31:28]}; |
`MTSPR,`MOVS,`LWS: |
if (ir[27:22]==`USP) |
fnTargetReg = {1'b0,6'd27}; |
fnTargetReg = {4'b0,6'd27}; |
else |
fnTargetReg = {1'b1,ir[27:22]}; |
fnTargetReg = {4'd1,ir[27:22]}; |
/* |
if (ir[27:26]==2'h1) // Move to code address register |
fnTargetReg = {3'h5,ir[25:22]}; |
1713,10 → 1897,10
fnTargetReg = 7'h00; |
*/ |
`PUSH: fnTargetReg = r27; |
`LOOP: fnTargetReg = 7'h73; |
`STP: fnTargetReg = 7'h7F; |
`P: fnTargetReg = 7'h70; |
default: fnTargetReg = 7'h00; |
`LOOP: fnTargetReg = 10'h73; |
`STP: fnTargetReg = 10'h7F; |
`P: fnTargetReg = 10'h70; |
default: fnTargetReg = 10'h00; |
endcase |
end |
endfunction |
1733,7 → 1917,7
fnTargetsCa = `FALSE; |
else begin |
case(fnOpcode(ir)) |
`JSR,`JSRZ,`JSRS,`SYS,`INT: |
`JSR,`JSRZ,`JSRS,`JSF,`SYS,`INT: |
fnTargetsCa = `TRUE; |
`JMPI,`JMPIX: |
fnTargetsCa = `TRUE; |
1767,17 → 1951,17
else |
case(fnOpcode(ir)) |
`LWS: |
if (ir[27:26]==2'h2) |
if (ir[27:25]==3'h4) |
fnTargetsSegreg = `TRUE; |
else |
fnTargetsSegreg = `FALSE; |
`LDIS: |
if (ir[21:20]==2'h2) |
if (ir[21:19]==3'h4) |
fnTargetsSegreg = `TRUE; |
else |
fnTargetsSegreg = `FALSE; |
`MTSPR,`MOVS: |
if (ir[27:26]==2'h2) |
if (ir[27:25]==3'h4) |
fnTargetsSegreg = `TRUE; |
else |
fnTargetsSegreg = `FALSE; |
1791,7 → 1975,7
`BFCLR,`BFSET,`BFCHG,`BFEXT,`BFEXTU,`BFINS, |
`LDI,`LDIS,`ADDUIS, |
`ADDI,`SUBI,`ADDUI,`SUBUI,`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI, |
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI,`CHKI, |
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI,`CHKI,`CHKXI, |
// CMPI |
8'h20,8'h21,8'h22,8'h23, |
8'h24,8'h25,8'h26,8'h27, |
1807,7 → 1991,7
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`INC, |
`LVB,`LVC,`LVH,`LVW,`LVWAR,`STI,`JMPI, |
`SB,`SC,`SH,`SW,`SWCR,`CAS,`SWS, |
`RTI,`RTD,`RTE,`LLA, |
`RTI,`RTD,`RTE,`RTF,`JSF,`LLA, |
`JSR,`JSRS,`SYS,`INT,`LOOP,`PEA,`LINK,`UNLINK: |
fnHasConst = 1'b1; |
default: |
1821,7 → 2005,7
begin |
case(opcode) |
`JMPI,`JMPIX, |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`LOOP,`RTS,`RTS2,`RTI,`RTD,`RTE: |
`JSR,`JSRS,`JSRZ,`JSF,`SYS,`INT,`LOOP,`RTS,`RTF,`RTS2,`RTI,`RTD,`RTE: |
fnIsFlowCtrl = 1'b1; |
default: |
if (opcode[7:4]==`BR) |
1859,10 → 2043,10
`SINGLE_R: |
if (func==`FTX) fnCanException = `TRUE; |
else fnCanException = `FALSE; |
`ADDI,`SUBI,`DIVI,`MODI,`MULI,`CHKI: |
`ADDI,`SUBI,`DIVI,`MODI,`MULI,`CHKXI: |
fnCanException = `TRUE; |
`RR: |
if (func==`ADD || func==`SUB || func==`MUL || func==`DIV || func==`MOD || func==`CHK) |
if (func==`ADD || func==`SUB || func==`MUL || func==`DIV || func==`MOD || func==`CHKX) |
fnCanException = `TRUE; |
else |
fnCanException = `FALSE; |
1891,7 → 2075,7
8'b10000000: fnInsnLength = 4'd8; |
default: |
case(isn[15:8]) |
`NOP,`SEI,`CLI,`RTI,`RTD,`RTE,`RTS2,`MEMSB,`MEMDB,`SYNC: |
`NOP,`SEI,`CLI,`RTI,`RTD,`RTE,`RTS2,`RTF,`JSF,`MEMSB,`MEMDB,`SYNC: |
fnInsnLength = 4'd2; |
`JSRZ,`RTS,`CACHE,`LOOP,`PUSH,`POP,`UNLINK: |
fnInsnLength = 4'd3; |
1899,8 → 2083,13
fnInsnLength = 4'd4; |
`BITFIELD,`JSR,`MUX,`BCD,`INC: |
fnInsnLength = 4'd6; |
`CAS: |
`CAS,`CHKI: |
fnInsnLength = 4'd6; |
`ifdef VECTOROPS |
`LV,`SV: fnInsnLength = 4'd4; |
`VMAC: fnInsnLength = 4'd6; |
// Others are default 5 |
`endif |
default: |
begin |
case(isn[15:12]) |
1958,6 → 2147,7
or fetchbufB_instr or fetchbufB_v or fetchbufB_pc |
or fetchbufC_instr or fetchbufC_v or fetchbufC_pc |
or fetchbufD_instr or fetchbufD_v or fetchbufD_pc |
or int_pending or string_pc |
) |
begin |
fetchbuf0_instr <= (fetchbuf == 1'b0) ? fetchbufA_instr : fetchbufC_instr; |
1988,6 → 2178,10
opcode==`LBX || opcode==`LWX || opcode==`LBUX || opcode==`LHX || opcode==`LHUX || opcode==`LCX || opcode==`LCUX || |
opcode==`SB || opcode==`SC || opcode==`SH || opcode==`SW || |
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX || |
`ifdef VECTOROPS |
opcode==`LV || opcode==`LVWS || opcode==`LVX || |
opcode==`SV || opcode==`SVWS || opcode==`SVX || |
`endif |
opcode==`STS || opcode==`LCL || |
opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`SWCR || |
opcode==`TLB || opcode==`CAS || opcode==`STMV || opcode==`STCMP || opcode==`STFND || |
1998,6 → 2192,15
; |
endfunction |
|
function fnIsVec; |
input [7:0] opcode; |
`ifdef VECTOROPS |
fnIsVec = opcode==`VMAC || opcode==`VR || opcode==`VRR;// || opcode==`VLD || opcode==`VLDX || opcode==`VST || opcode==`VSTX; |
`else |
fnIsVec = `FALSE; |
`endif |
endfunction |
|
// Determines which instruction write to the register file |
function fnIsRFW; |
input [7:0] opcode; |
2016,17 → 2219,22
opcode==`_2ADDUI || opcode==`_4ADDUI || opcode==`_8ADDUI || opcode==`_16ADDUI || |
opcode==`ANDI || opcode==`ORI || opcode==`EORI || |
opcode==`SHIFT || opcode==`LOGIC || |
opcode==`R || opcode==`R2 || opcode==`RR || opcode==`P || opcode==`LOOP || |
opcode==`BITI || opcode==`CMP || opcode==`CMPI || opcode==`TST || |
opcode==`R || opcode==`R2 || (opcode==`RR && (ir[39:34]!=`CHKX)) || opcode==`LOOP || |
opcode==`CHKI || opcode==`CMP || opcode==`CMPI || opcode==`TST || |
opcode==`LDI || opcode==`LDIS || opcode==`ADDUIS || opcode==`MFSPR || |
`ifdef VECTOROPS |
opcode==`LV || opcode==`LVWS || opcode==`LVX || |
opcode==`VLOG || opcode==`VADDSUB | opcode==`VCMPS || opcode==`VMULDIV || |
opcode==`VMAC || opcode==`VR || |
`endif |
`ifdef FLOATING_POINT |
opcode==`DOUBLE_R || opcode==`FLOAT_RR || opcode==`SINGLE_R || |
`endif |
// Branch registers / Segment registers |
((opcode==`MTSPR || opcode==`MOVS) /*&& (fnTargetsCa(ir) || fnTargetsSegreg(ir))*/) || |
opcode==`JSR || opcode==`JSRS || opcode==`JSRZ || opcode==`SYS || opcode==`INT || |
opcode==`JSR || opcode==`JSRS || opcode==`JSRZ || opcode==`JSF || opcode==`SYS || opcode==`INT || |
// predicate registers |
(opcode[7:4] < 4'h3) || |
(opcode[7:4] < 4'h3) || opcode==`P || opcode==`BITI || |
(opcode==`TLB && ir[19:16]==`TLB_RDREG) || |
opcode==`BCD |
; |
2039,6 → 2247,7
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX || |
opcode==`STS || opcode==`SWCR || |
opcode==`SWS || opcode==`STI || |
opcode==`SV || opcode==`SVWS || opcode==`SVX || |
opcode==`PUSH || opcode==`PEA || opcode==`LINK; |
endfunction |
|
2048,17 → 2257,20
opcode==`LBX || opcode==`LBUX || opcode==`LCX || opcode==`LCUX || opcode==`LHX || opcode==`LHUX || opcode==`LWX || |
opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`LCL || |
opcode==`LWS || opcode==`UNLINK || opcode==`JMPI || opcode==`JMPIX || |
opcode==`LV || opcode==`LVWS || opcode==`LVX || |
opcode==`POP; |
endfunction |
|
function fnIsLoadV; |
input [7:0] opcode; |
fnIsLoadV = opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`LCL; |
fnIsLoadV = opcode==`LVB || opcode==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`LCL || |
opcode==`LV || opcode==`LVWS || opcode==`LVX; |
endfunction |
|
function fnIsIndexed; |
input [7:0] opcode; |
fnIsIndexed = opcode==`LBX || opcode==`LBUX || opcode==`LCX || opcode==`LCUX || opcode==`LHX || opcode==`LHUX || opcode==`LWX || |
opcode==`LVX || opcode==`SVX || |
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX || opcode==`JMPIX; |
endfunction |
|
2072,11 → 2284,14
function fnIsIllegal; |
input [7:0] op; |
input [5:0] fn; |
if (`TRUE) |
fnIsIllegal = `FALSE; |
else |
casex(op) |
8'h40: |
if (fn > 6'h17) |
fnIsIllegal = `TRUE; |
else if (fn==6'hC || fn==6'hD || fn==6'hE || fn==6'hF || fn==6'h12 || fn==6'h15 || fn==6'h16) |
else if (fn==6'hC || fn==6'hD || fn==6'hE || fn==6'hF || fn==6'h12 || fn==6'h16) |
fnIsIllegal = `TRUE; |
else fnIsIllegal = `FALSE; |
8'h41: |
2118,20 → 2333,24
fnIsIllegal = `TRUE; |
else |
fnIsIllegal = `FALSE; |
8'h43,8'h44,8'h45: fnIsIllegal = `TRUE; |
8'h52,8'h56,8'h57,8'h59,8'h5A,8'h5C,8'h5E: |
8'h43,8'h44: fnIsIllegal = `TRUE; |
`ifndef VECTOROPS |
8'h52,8'h56,8'h57,8'h5A,8'h5C,8'h5E,8'hCD,8'hCE,8'hCF,8'hBD,8'hBE,8'hBF: |
fnIsIllegal = `TRUE; |
`endif |
8'h59: |
fnIsIllegal = `TRUE; |
8'h60,8'h61,8'h62,8'h63,8'h64,8'h65,8'h66,8'h67,8'h68,8'h69: |
fnIsIllegal = `TRUE; |
8'h73,8'h74,8'h75,8'h76,8'h7A,8'h7B,8'h7C,8'h7D,8'h7E,8'h7F: |
fnIsIllegal = `TRUE; |
8'h87,8'h88,8'h89,8'h8A: |
8'h87,8'h88,8'h8A: |
fnIsIllegal = `TRUE; |
8'h94,8'h95,8'h9C: |
fnIsIllegal = `TRUE; |
8'hB9,8'hBA,8'hBB,8'hBC,8'hBD,8'hBE,8'hBF: |
8'hBA,8'hBB,8'hBC: |
fnIsIllegal = `TRUE; |
8'hC4,8'hC5,8'b11001xxx: |
8'hC8,8'hC9,8'hCA,8'hCB,8'hCD: |
fnIsIllegal = `TRUE; |
8'hDx: fnIsIllegal = `TRUE; |
8'hEx: fnIsIllegal = `TRUE; |
2191,6 → 2410,7
`LH,`LHU,`SH,`LVH,`LHX,`LHUX,`SHX: |
fnSelect = 8'hFF; |
`LW,`LWX,`SW,`SWCR,`LVW,`LVWAR,`SWX,`CAS,`LWS,`SWS,`STI,`LCL, |
`LV,`LVWS,`LVX,`SV,`SVWS,`SVX, |
`PUSH,`PEA,`POP,`LINK,`UNLINK: |
fnSelect = 8'hFF; |
default: fnSelect = 8'h00; |
2267,6 → 2487,7
1'b1: fnSelect = 8'hF0; |
endcase |
`LW,`LWX,`SW,`SWCR,`LVW,`LVWAR,`SWX,`CAS,`LWS,`SWS,`STI,`LCL, |
`LV,`LVWS,`LVX,`SV,`SVWS,`SVX, |
`PUSH,`PEA,`POP,`LINK,`UNLINK: |
fnSelect = 8'hFF; |
default: fnSelect = 8'h00; |
2340,7 → 2561,9
4'hC: fnDatai = dat[31:16]; |
default: fnDatai = {DBW{1'b1}}; |
endcase |
`LH,`LHU,`LW,`LWX,`LVH,`LVW,`LVWAR,`LHX,`LHUX,`CAS,`LCL,`LWS,`POP,`UNLINK: |
`LH,`LHU,`LW,`LWX,`LVH,`LVW,`LVWAR,`LHX,`LHUX, |
`LV,`LVWS,`LVX, |
`CAS,`LCL,`LWS,`POP,`UNLINK: |
fnDatai = dat[31:0]; |
default: fnDatai = {DBW{1'b1}}; |
endcase |
2447,7 → 2670,9
8'hF0: fnDatai = dat[DBW-1:DBW/2]; |
default: fnDatai = {DBW{1'b1}}; |
endcase |
`LW,`LWX,`LVW,`LVWAR,`CAS,`LCL,`LWS,`POP,`UNLINK: |
`LW,`LWX,`LVW,`LVWAR, |
`LV,`LVWS,`LVX, |
`CAS,`LCL,`LWS,`POP,`UNLINK: |
case(sel) |
8'hFF: fnDatai = dat; |
default: fnDatai = {DBW{1'b1}}; |
2469,7 → 2694,7
3'd1,3'd5: fnDatao = {2{dat[15:8]}}; |
default: fnDatao = dat; |
endcase |
`SW,`SWCR,`SWX,`CAS,`SWS,`STI, |
`SW,`SWCR,`SWX,`CAS,`SWS,`STI,`SV,`SVWS,`SVX, |
`PUSH,`PEA,`LINK: fnDatao = dat; |
`SH,`SHX: fnDatao = dat; |
`SC,`SCX: fnDatao = {2{dat[15:0]}}; |
2485,7 → 2710,7
3'd2,3'd6: fnDatao = {2{dat[DBW/2-1:0]}}; |
3'd3,3'd7: fnDatao = dat; |
endcase |
`SW,`SWCR,`SWX,`CAS,`SWS,`STI, |
`SW,`SWCR,`SWX,`CAS,`SWS,`STI,`SV,`SVWS,`SVX, |
`PUSH,`PEA,`LINK: fnDatao = dat; |
`SH,`SHX: fnDatao = {2{dat[DBW/2-1:0]}}; |
`SC,`SCX: fnDatao = {4{dat[DBW/4-1:0]}}; |
2495,11 → 2720,13
endfunction |
|
assign fetchbuf0_mem = fnIsMem(opcode0); |
assign fetchbuf0_vec = fnIsVec(opcode0); |
assign fetchbuf0_jmp = fnIsFlowCtrl(opcode0); |
assign fetchbuf0_fp = fnIsFP(opcode0); |
assign fetchbuf0_rfw = fnIsRFW(opcode0,fetchbuf0_instr); |
assign fetchbuf0_pfw = fnIsPFW(opcode0); |
assign fetchbuf1_mem = fnIsMem(opcode1); |
assign fetchbuf1_vec = fnIsVec(opcode1); |
assign fetchbuf1_jmp = fnIsFlowCtrl(opcode1); |
assign fetchbuf1_fp = fnIsFP(opcode1); |
assign fetchbuf1_rfw = fnIsRFW(opcode1,fetchbuf1_instr); |
2636,6 → 2863,8
8'h2C,8'h2D,8'h2E,8'h2F, |
`LDI,`LDIS,`ADDUIS: |
fnImm = {{54{insn[31]}},insn[31:22]}; |
`RTF: fnImm = {9'h264,4'h0}; |
`JSF: fnImm = {9'h265,4'h0}; |
`RTS: fnImm = insn[19:16]; |
`RTD,`RTE,`RTI,`RTS2,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS: fnImm = 64'h0; |
`STI: fnImm = {{58{insn[33]}},insn[33:28]}; |
2668,6 → 2897,7
8'h28,8'h29,8'h2A,8'h2B, |
8'h2C,8'h2D,8'h2E,8'h2F, |
`LDI,`LDIS,`ADDUIS: fnImm8 = insn[29:22]; |
`RTF,`JSF: fnImm8 = 8'h80; |
`RTS: fnImm8 = insn[19:16]; |
`RTD,`RTE,`RTI,`RTS2,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS: fnImm8 = 8'h00; |
`STI: fnImm8 = insn[35:28]; |
2705,7 → 2935,7
fnImmMSB = insn[31]; |
`SYS,`INT,`CACHE,`LINK: |
fnImmMSB = 1'b0; // SYS,INT are unsigned |
`RTS,`RTD,`RTE,`RTI,`JSRZ,`STMV,`STCMP,`STFND,`RTS2,`STS: |
`JSF,`RTS,`RTF,`RTD,`RTE,`RTI,`JSRZ,`STMV,`STCMP,`STFND,`RTS2,`STS: |
fnImmMSB = 1'b0; // RTS is unsigned |
`PUSH: fnImmMSB = 1'b1; |
`LBX,`LBUX,`LCX,`LCUX,`LHX,`LHUX,`LWX, |
2735,6 → 2965,21
endcase |
endfunction |
|
// In the works: multiplexing for the immediate operand |
function fnOp0; |
input [7:0] opcode; |
input [5:0] vel; |
input [63:0] ins; |
input [2:0] tail; |
fnOp0 = |
`ifdef VECTOROPS |
(opcode==`LVX || opcode==`SVX) ? vel : |
`endif |
(opcode==`INT || opcode==`SYS || opcode==`RTF || opcode==`JSF) ? fnImm(ins) : |
fnIsBranch(opcode) ? {{DBW-12{ins[11]}},ins[11:8],ins[23:16]} : |
(iqentry_op[(tail-3'd1)&7]==`IMM && iqentry_v[tail-3'd1]) ? {iqentry_a0[(tail-3'd1)&7][DBW-1:8],fnImm8(ins)}: |
opcode==`IMM ? fnImmImm(ins) : fnImm(ins); |
endfunction |
|
// Used during enque |
// Operand A is a little more work than B or C as it may read from special |
2741,7 → 2986,7
// purpose registers. |
function [63:0] fnOpa; |
input [7:0] opcode; |
input [6:0] Ra; |
input [7:0] Ra; |
input [63:0] ins; |
input [63:0] rfo; |
input [63:0] epc; |
2751,7 → 2996,7
fnOpa = ins[21:16]; |
else |
`endif |
if (Ra[6]) |
if (Ra[7:6]==2'h1) |
fnOpa = fnSpr(Ra[5:0],epc); |
else |
fnOpa = rfo; |
2760,9 → 3005,10
|
function [DBW-1:0] fnOpb; |
input [7:0] opcode; |
input [6:0] Rb; |
input [9:0] Rb; |
input [63:0] ins; |
input [63:0] rfo; |
input [63:0] vrfo; |
input [63:0] epc; |
begin |
fnOpb = fnIsShiftiop(ins) ? {{DBW-6{1'b0}},ins[`INSTRUCTION_RB]} : |
2769,7 → 3015,10
fnIsFPCtrl(ins) ? {{DBW-6{1'b0}},ins[`INSTRUCTION_RB]} : |
opcode==`INC ? {{56{ins[47]}},ins[47:40]} : |
opcode==`STI ? ins[27:22] : |
Rb[6] ? fnSpr(Rb[5:0],epc) : |
Rb[7:6]==2'h1 ? fnSpr(Rb[5:0],epc) : |
`ifdef VECTOROPS |
Rb[7] ? vrfo : |
`endif |
rfo; |
end |
endfunction |
2776,12 → 3025,17
|
// Used during enque |
function [63:0] fnOpt; |
input [6:0] tgt; |
input [7:0] tgt; |
input [63:0] rfo; |
input [63:0] vrfo; |
input [63:0] epc; |
begin |
if (tgt[6]) |
if (tgt[7:6]==2'b01) |
fnOpt = fnSpr(tgt[5:0],epc); |
`ifdef VECTOROPS |
else if (tgt[7]) |
fnOpt = vrfo; |
`endif |
else |
fnOpt = rfo; |
end |
2800,7 → 3054,7
endfunction |
|
function fnIsKMOnlyReg; |
input [6:0] regx; |
input [7:0] regx; |
`ifdef PRIVCHKS |
fnIsKMOnlyReg = regx==7'd28 || regx==7'd29 || regx==7'd30 || regx==7'd31 || |
regx==7'h5B || regx==7'h5C || regx==7'h5D || regx==7'h5E |
2812,7 → 3066,7
|
// Returns TRUE if the register is automatically valid. |
function fnRegIsAutoValid; |
input [6:0] regno; // r0, c0, c15, tick |
input [7:0] regno; // r0, c0, c15, tick |
fnRegIsAutoValid = regno==7'h00 || regno==7'h50 || regno==7'h5F || regno==7'h72; |
endfunction |
|
2836,9 → 3090,9
endfunction |
|
function [7:0] fnRegstr; |
input [6:0] Rn; |
input [7:0] Rn; |
begin |
if (!Rn[6]) begin |
if (Rn[7:6]==2'b00) begin |
fnRegstr = Rn[5:0]; |
end |
else |
2846,6 → 3100,9
end |
endfunction |
|
assign operandA0 = fnOpa(opcode0,Ra0,fetchbuf0_instr,rfoa0,fetchbuf0_pc); |
assign operandA1 = fnOpa(opcode1,Ra1,fetchbuf1_instr,rfoa1,fetchbuf1_pc); |
|
initial begin |
// |
// set up panic messages |
2912,12 → 3169,18
&& (iqentry_a3_v[g] |
|| (iqentry_a3_s[g] == alu0_sourceid && alu0_v) |
|| (iqentry_a3_s[g] == alu1_sourceid && alu1_v)) |
`ifdef VECTOROPS |
&& (iqentry_a4_v[g] |
|| (iqentry_a4_s[g] == alu0_sourceid && alu0_v) |
|| (iqentry_a4_s[g] == alu1_sourceid && alu1_v)) |
`endif |
&& (iqentry_T_v[g] |
|| (iqentry_T_s[g] == alu0_sourceid && alu0_v) |
|| (iqentry_T_s[g] == alu1_sourceid && alu1_v)) |
; |
|
assign could_issue[g] = iqentry_v[g] && !iqentry_done[g] && !iqentry_out[g] && args_valid[g] && |
assign could_issue[g] = iqentry_v[g] && !iqentry_done[g] && |
!iqentry_out[g] && args_valid[g] && |
(iqentry_mem[g] ? !iqentry_agen[g] : 1'b1); |
|
end |
2940,154 → 3203,162
iqentry_islot[5] = 2'b00; |
iqentry_islot[6] = 2'b00; |
iqentry_islot[7] = 2'b00; |
if (could_issue[head0] & !iqentry_fp[head0] & alu0_idle) begin |
iqentry_issue[head0] = `TRUE; |
iqentry_islot[head0] = 2'b00; |
// See if we can issue to the first alu. |
if (alu0_idle) begin |
if (could_issue[head0] && !iqentry_fp[head0]) begin |
iqentry_issue[head0] = `TRUE; |
iqentry_islot[head0] = 2'b00; |
end |
else if (could_issue[head1] && !iqentry_fp[head1] |
&& !(iqentry_v[head0] && iqentry_sync[head0])) |
begin |
iqentry_issue[head1] = `TRUE; |
iqentry_islot[head1] = 2'b00; |
end |
else if (could_issue[head2] && !iqentry_fp[head2] |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
) |
begin |
iqentry_issue[head2] = `TRUE; |
iqentry_islot[head2] = 2'b00; |
end |
else if (could_issue[head3] && !iqentry_fp[head3] |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
) begin |
iqentry_issue[head3] = `TRUE; |
iqentry_islot[head3] = 2'b00; |
end |
else if (could_issue[head4] && !iqentry_fp[head4] |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
) begin |
iqentry_issue[head4] = `TRUE; |
iqentry_islot[head4] = 2'b00; |
end |
else if (could_issue[head5] && !iqentry_fp[head5] |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
) begin |
iqentry_issue[head5] = `TRUE; |
iqentry_islot[head5] = 2'b00; |
end |
else if (could_issue[head6] && !iqentry_fp[head6] |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
&& !(iqentry_v[head5] && iqentry_sync[head5]) |
) begin |
iqentry_issue[head6] = `TRUE; |
iqentry_islot[head6] = 2'b00; |
end |
else if (could_issue[head7] && !iqentry_fp[head7] |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
&& !(iqentry_v[head5] && iqentry_sync[head5]) |
&& !(iqentry_v[head6] && iqentry_sync[head6]) |
) begin |
iqentry_issue[head7] = `TRUE; |
iqentry_islot[head7] = 2'b00; |
end |
end |
else if (could_issue[head1] & !iqentry_fp[head1] & alu0_idle |
&& !(iqentry_v[head0] && iqentry_sync[head0])) |
begin |
iqentry_issue[head1] = `TRUE; |
iqentry_islot[head1] = 2'b00; |
end |
else if (could_issue[head2] & !iqentry_fp[head2] & alu0_idle |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
) |
begin |
iqentry_issue[head2] = `TRUE; |
iqentry_islot[head2] = 2'b00; |
end |
else if (could_issue[head3] & !iqentry_fp[head3] & alu0_idle |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
) begin |
iqentry_issue[head3] = `TRUE; |
iqentry_islot[head3] = 2'b00; |
end |
else if (could_issue[head4] & !iqentry_fp[head4] & alu0_idle |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
) begin |
iqentry_issue[head4] = `TRUE; |
iqentry_islot[head4] = 2'b00; |
end |
else if (could_issue[head5] & !iqentry_fp[head5] & alu0_idle |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
) begin |
iqentry_issue[head5] = `TRUE; |
iqentry_islot[head5] = 2'b00; |
end |
else if (could_issue[head6] & !iqentry_fp[head6] & alu0_idle |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
&& !(iqentry_v[head5] && iqentry_sync[head5]) |
) begin |
iqentry_issue[head6] = `TRUE; |
iqentry_islot[head6] = 2'b00; |
end |
else if (could_issue[head7] & !iqentry_fp[head7] & alu0_idle |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
&& !(iqentry_v[head5] && iqentry_sync[head5]) |
&& !(iqentry_v[head6] && iqentry_sync[head6]) |
) begin |
iqentry_issue[head7] = `TRUE; |
iqentry_islot[head7] = 2'b00; |
end |
|
// Don't bother checking head0, it should have issued to the first |
// instruction. |
if (could_issue[head1] && !iqentry_fp[head1] && !iqentry_issue[head1] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head1],iqentry_fn[head1]) |
&& !(iqentry_v[head0] && iqentry_sync[head0])) |
begin |
iqentry_issue[head1] = `TRUE; |
iqentry_islot[head1] = 2'b01; |
end |
else if (could_issue[head2] && !iqentry_fp[head2] && !iqentry_issue[head2] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head2],iqentry_fn[head2]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
) |
begin |
iqentry_issue[head2] = `TRUE; |
iqentry_islot[head2] = 2'b01; |
end |
else if (could_issue[head3] & !iqentry_fp[head3] && !iqentry_issue[head3] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head3],iqentry_fn[head3]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
) begin |
iqentry_issue[head3] = `TRUE; |
iqentry_islot[head3] = 2'b01; |
end |
else if (could_issue[head4] & !iqentry_fp[head4] && !iqentry_issue[head4] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head4],iqentry_fn[head4]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
) begin |
iqentry_issue[head4] = `TRUE; |
iqentry_islot[head4] = 2'b01; |
end |
else if (could_issue[head5] & !iqentry_fp[head5] && !iqentry_issue[head5] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head5],iqentry_fn[head5]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
) begin |
iqentry_issue[head5] = `TRUE; |
iqentry_islot[head5] = 2'b01; |
end |
else if (could_issue[head6] & !iqentry_fp[head6] && !iqentry_issue[head6] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head6],iqentry_fn[head6]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
&& !(iqentry_v[head5] && iqentry_sync[head5]) |
) begin |
iqentry_issue[head6] = `TRUE; |
iqentry_islot[head6] = 2'b01; |
end |
else if (could_issue[head7] & !iqentry_fp[head7] && !iqentry_issue[head7] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head7],iqentry_fn[head7]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
&& !(iqentry_v[head5] && iqentry_sync[head5]) |
&& !(iqentry_v[head6] && iqentry_sync[head6]) |
) begin |
iqentry_issue[head7] = `TRUE; |
iqentry_islot[head7] = 2'b01; |
end |
if (alu1_idle) begin |
if (could_issue[head0] && !iqentry_fp[head0] |
&& !fnIsAlu0Op(iqentry_op[head0],iqentry_fn[head0]) |
&& !iqentry_issue[head0]) begin |
iqentry_issue[head0] = `TRUE; |
iqentry_islot[head0] = 2'b01; |
end |
else if (could_issue[head1] && !iqentry_fp[head1] && !iqentry_issue[head1] |
&& !fnIsAlu0Op(iqentry_op[head1],iqentry_fn[head1]) |
&& !(iqentry_v[head0] && iqentry_sync[head0])) |
begin |
iqentry_issue[head1] = `TRUE; |
iqentry_islot[head1] = 2'b01; |
end |
else if (could_issue[head2] && !iqentry_fp[head2] && !iqentry_issue[head2] |
&& !fnIsAlu0Op(iqentry_op[head2],iqentry_fn[head2]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
) |
begin |
iqentry_issue[head2] = `TRUE; |
iqentry_islot[head2] = 2'b01; |
end |
else if (could_issue[head3] && !iqentry_fp[head3] && !iqentry_issue[head3] |
&& !fnIsAlu0Op(iqentry_op[head3],iqentry_fn[head3]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
) begin |
iqentry_issue[head3] = `TRUE; |
iqentry_islot[head3] = 2'b01; |
end |
else if (could_issue[head4] && !iqentry_fp[head4] && !iqentry_issue[head4] |
&& !fnIsAlu0Op(iqentry_op[head4],iqentry_fn[head4]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
) begin |
iqentry_issue[head4] = `TRUE; |
iqentry_islot[head4] = 2'b01; |
end |
else if (could_issue[head5] && !iqentry_fp[head5] && !iqentry_issue[head5] |
&& !fnIsAlu0Op(iqentry_op[head5],iqentry_fn[head5]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
) begin |
iqentry_issue[head5] = `TRUE; |
iqentry_islot[head5] = 2'b01; |
end |
else if (could_issue[head6] & !iqentry_fp[head6] && !iqentry_issue[head6] |
&& !fnIsAlu0Op(iqentry_op[head6],iqentry_fn[head6]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
&& !(iqentry_v[head5] && iqentry_sync[head5]) |
) begin |
iqentry_issue[head6] = `TRUE; |
iqentry_islot[head6] = 2'b01; |
end |
else if (could_issue[head7] && !iqentry_fp[head7] && !iqentry_issue[head7] |
&& !fnIsAlu0Op(iqentry_op[head7],iqentry_fn[head7]) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
&& !(iqentry_v[head3] && iqentry_sync[head3]) |
&& !(iqentry_v[head4] && iqentry_sync[head4]) |
&& !(iqentry_v[head5] && iqentry_sync[head5]) |
&& !(iqentry_v[head6] && iqentry_sync[head6]) |
) begin |
iqentry_issue[head7] = `TRUE; |
iqentry_islot[head7] = 2'b01; |
end |
end |
end |
|
|
`ifdef FLOATING_POINT |
reg [3:0] fpispot; |
always @(could_issue or head0 or head1 or head2 or head3 or head4 or head5 or head6 or head7) |
always @* //(could_issue or head0 or head1 or head2 or head3 or head4 or head5 or head6 or head7) |
begin |
iqentry_fpissue = 8'h00; |
iqentry_fpislot[0] = 2'b00; |
3759,10 → 4030,16
dbg_adr3 <= 0; |
`endif |
end |
`ifdef SEGMENTATION |
if (ABW==32) |
sregs_lmt[7] = 20'hFFFFF; |
else |
sregs_lmt[7] = 52'hFFFFFFFFFFFFF; |
// The pc wraps around to address zero while fetching the reset vector. |
// This causes the processor to use the code segement register so the |
// CS has to be defined for reset. |
sregs_base[7] <= RSTCSEG; |
`endif |
rf_source[0] <= 4'd0; |
// rf_v[0] = `VAL; |
// rf_v[7'h50] = `VAL; |
3784,10 → 4061,6
tlb_state <= 3'd0; |
panic <= `PANIC_NONE; |
string_pc <= 64'd0; |
// The pc wraps around to address zero while fetching the reset vector. |
// This causes the processor to use the code segement register so the |
// CS has to be defined for reset. |
sregs[7] <= RSTCSEG; |
for (i=0; i < 16; i=i+1) |
pregs[i] <= 4'd0; |
asid <= 8'h00; |
3794,6 → 4067,8
rrmapno <= 3'd0; |
dram0_id <= 0; |
alu1_sourceid <= 0; |
smode <= 2'b00; |
regset <= 3'd0; |
end |
|
// The following registers are always valid |
3848,13 → 4123,13
if (!rf_v[ commit0_tgt ]) begin |
rf_v[ commit0_tgt ] = (rf_source[ commit0_tgt ] == commit0_id) || ((branchmiss) && iqentry_source[ commit0_id[2:0] ]); |
end |
if (commit0_tgt != 7'd0) $display("r%d <- %h", commit0_tgt, commit0_bus); |
if (commit0_tgt != 8'd0) $display("r%d <- %h", commit0_tgt, commit0_bus); |
end |
if (commit1_v) begin |
if (!rf_v[ commit1_tgt ]) begin |
rf_v[ commit1_tgt ] = (rf_source[ commit1_tgt ] == commit1_id)|| ((branchmiss) && iqentry_source[ commit1_id[2:0] ]); |
end |
if (commit1_tgt != 7'd0) $display("r%d <- %h", commit1_tgt, commit1_bus); |
if (commit1_tgt != 8'd0) $display("r%d <- %h", commit1_tgt, commit1_bus); |
end |
|
// This chunk of code has to be before the enqueue stage so that the agen bit |
3874,32 → 4149,31
end |
|
if (alu0_v) begin |
if (|alu0_exc) |
set_exception(alu0_id, |
alu0_exc==`EXC_PRIV ? 8'd245 : |
alu0_exc==`EXC_DBZ ? 8'd241 : |
alu0_exc==`EXC_CHK ? 8'd239 : 8'h00); |
else begin |
if (iqentry_op[alu0_id[2:0]]!=`IMM) |
iqentry_done[ alu0_id[2:0] ] <= (!iqentry_mem[ alu0_id[2:0] ] || !alu0_cmt); |
if (iqentry_jmpi[alu0_id[2:0]] && alu0_cmt) |
iqentry_res [alu0_id[2:0]] <= alu0_pc + alu0_insnsz; |
else |
iqentry_res [ alu0_id[2:0] ] <= alu0_bus; |
iqentry_out [ alu0_id[2:0] ] <= `FALSE; |
iqentry_cmt [ alu0_id[2:0] ] <= alu0_cmt; |
iqentry_agen[ alu0_id[2:0] ] <= `TRUE; |
end |
if (|alu0_exc) begin |
set_exception(alu0_id, alu0_exc); |
iqentry_a1[alu0_id[2:0]] <= alu0_bus; |
end |
else begin |
if (iqentry_op[alu0_id[2:0]]!=`IMM) |
iqentry_done[ alu0_id[2:0] ] <= (!iqentry_mem[ alu0_id[2:0] ] || !alu0_cmt); |
if (iqentry_jmpi[alu0_id[2:0]] && alu0_cmt) |
iqentry_res [alu0_id[2:0]] <= alu0_pc + alu0_insnsz; |
else |
iqentry_res [ alu0_id[2:0] ] <= alu0_bus; |
iqentry_out [ alu0_id[2:0] ] <= `FALSE; |
iqentry_cmt [ alu0_id[2:0] ] <= alu0_cmt; |
iqentry_agen[ alu0_id[2:0] ] <= `TRUE; |
end |
end |
|
|
if (((alu1_op==`RR && (alu1_fn==`MUL || alu1_fn==`MULU)) || alu1_op==`MULI || alu1_op==`MULUI) && ALU1BIG) begin |
if (((alu1_op==`RR && (alu1_fn==`MUL || alu1_fn==`MULU)) || alu1_op==`MULI || alu1_op==`MULUI)) begin |
if (alu1_done) begin |
alu1_dataready <= `TRUE; |
end |
end |
else if (((alu1_op==`RR && (alu1_fn==`DIV || alu1_fn==`DIVU || alu1_fn==`MOD || alu1_fn==`MODU)) || |
alu1_op==`DIVI || alu1_op==`DIVUI || alu1_op==`MODI || alu1_op==`MODUI) && ALU1BIG) begin |
alu1_op==`DIVI || alu1_op==`DIVUI || alu1_op==`MODI || alu1_op==`MODUI)) begin |
if (alu1_done) begin |
alu1_dataready <= `TRUE; |
end |
3906,23 → 4180,22
end |
|
if (alu1_v) begin |
if (|alu1_exc) |
set_exception(alu1_id, |
alu1_exc==`EXC_PRIV ? 8'd245 : |
alu1_exc==`EXC_DBZ ? 8'd241 : |
alu1_exc==`EXC_CHK ? 8'd239 : 8'h00); |
if (|alu1_exc) begin |
set_exception(alu1_id, alu1_exc); |
iqentry_a1[alu1_id[2:0]] <= alu1_bus; |
end |
else begin |
if (iqentry_op[alu1_id[2:0]]!=`IMM) |
iqentry_done[ alu1_id[2:0] ] <= (!iqentry_mem[ alu1_id[2:0] ] || !alu1_cmt); |
if (iqentry_jmpi[alu1_id[2:0]] && alu1_cmt) |
iqentry_res [alu1_id[2:0]] <= alu1_pc + alu1_insnsz; |
else |
iqentry_res [ alu1_id[2:0] ] <= alu1_bus; |
iqentry_out [ alu1_id[2:0] ] <= `FALSE; |
iqentry_cmt [ alu1_id[2:0] ] <= alu1_cmt; |
iqentry_agen[ alu1_id[2:0] ] <= `TRUE; |
end |
if (iqentry_op[alu1_id[2:0]]!=`IMM) |
iqentry_done[ alu1_id[2:0] ] <= (!iqentry_mem[ alu1_id[2:0] ] || !alu1_cmt); |
if (iqentry_jmpi[alu1_id[2:0]] && alu1_cmt) |
iqentry_res [alu1_id[2:0]] <= alu1_pc + alu1_insnsz; |
else |
iqentry_res [ alu1_id[2:0] ] <= alu1_bus; |
iqentry_out [ alu1_id[2:0] ] <= `FALSE; |
iqentry_cmt [ alu1_id[2:0] ] <= alu1_cmt; |
iqentry_agen[ alu1_id[2:0] ] <= `TRUE; |
end |
end |
|
`ifdef FLOATING_POINT |
if (fp0_v) begin |
3959,6 → 4232,8
exception_set = `FALSE; |
queued1 = `FALSE; |
queued2 = `FALSE; |
queued1v = `FALSE; |
queued2v = `FALSE; |
allowq = `TRUE; |
qstomp = `FALSE; |
if (branchmiss) // don't bother doing anything if there's been a branch miss |
3966,15 → 4241,25
else begin |
case ({fetchbuf0_v, fetchbuf1_v && fnNumReadPorts(fetchbuf1_instr) <= ports_avail}) |
2'b00: ; // do nothing |
2'b01: enque1(tail0,1,0,1); |
2'b10: enque0(tail0,1,0,1); |
2'b01: enque1(tail0,1,0,1,vele); |
2'b10: enque0(tail0,1,0,1,vele); |
2'b11: begin |
enque0(tail0,1,1,1); |
enque0(tail0,1,1,1,vele); |
if (allowq) |
enque1(tail1,2,0,0); |
enque1(tail1,2,0,0,vele+1); |
validate_args(); |
end |
endcase |
`ifdef VECTOROPS |
// Once instruction is completely queued reset vector element count to zero. |
// Otherwise increment it according to the number of elements queued. |
if (queued1|queued2) |
vele <= 8'd0; |
else if (queued2v) |
vele <= vele + 2; |
else if (queued1v) |
vele <= vele + 1; |
`endif |
end |
|
//------------------------------------------------------------------------------ |
4270,12 → 4555,8
// slot. The instruction will re-issue as an ALU operation. We can change |
// the queued instruction because it isn't finished yet. |
if (|dram_exc) begin |
set_exception(dram_id, |
dram_exc==`EXC_DBE ? 8'hFB : |
dram_exc==`EXC_DBG ? 8'd243 : |
dram_exc==`EXC_SEGV ? 8'd244 : |
8'hF8); // F8 = TLBMiss exception 243 = debug |
$stop; |
set_exception(dram_id, dram_exc); |
$stop; |
end |
else begin |
// Note that the predicate was already evaluated to TRUE before the |
4323,6 → 4604,14
// - commit0_bus |
// - commit1_bus |
// |
setargs (alu0_id, alu0_v, alu0_bus); |
setargs (alu1_id, alu1_v, alu1_bus); |
`ifdef FLOATING_POINT |
setargs (fp0_id, fp0_v, fp0_bus); |
`endif |
setargs (dram_id, dram_v, dram_bus); |
setargs (commit0_id, commit0_v, commit0_bus); |
setargs (commit1_id, commit1_v, commit1_bus); |
|
for (n = 0; n < QENTRIES; n = n + 1) |
begin |
4330,127 → 4619,23
iqentry_pred[n] <= alu0nyb[iqentry_preg[n]]; |
iqentry_p_v[n] <= `VAL; |
end |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin |
iqentry_a1[n] <= alu0_bus; |
iqentry_a1_v[n] <= `VAL; |
end |
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin |
iqentry_a2[n] <= alu0_bus; |
iqentry_a2_v[n] <= `VAL; |
end |
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin |
iqentry_a3[n] <= alu0_bus; |
iqentry_a3_v[n] <= `VAL; |
end |
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin |
iqentry_T[n] <= alu0_bus; |
iqentry_T_v[n] <= `VAL; |
end |
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin |
iqentry_pred[n] <= alu1nyb[iqentry_preg[n]]; |
iqentry_p_v[n] <= `VAL; |
end |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin |
iqentry_a1[n] <= alu1_bus; |
iqentry_a1_v[n] <= `VAL; |
end |
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin |
iqentry_a2[n] <= alu1_bus; |
iqentry_a2_v[n] <= `VAL; |
end |
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin |
iqentry_a3[n] <= alu1_bus; |
iqentry_a3_v[n] <= `VAL; |
end |
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin |
iqentry_T[n] <= alu1_bus; |
iqentry_T_v[n] <= `VAL; |
end |
`ifdef FLOATING_POINT |
/* |
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin |
iqentry_pred[n] <= fp0_bus[3:0]; |
iqentry_p_v[n] <= `VAL; |
end |
*/ |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin |
iqentry_a1[n] <= fp0_bus; |
iqentry_a1_v[n] <= `VAL; |
end |
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin |
iqentry_a2[n] <= fp0_bus; |
iqentry_a2_v[n] <= `VAL; |
end |
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin |
iqentry_a3[n] <= fp0_bus; |
iqentry_a3_v[n] <= `VAL; |
end |
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == fp0_id && iqentry_v[n] == `VAL && fp0_v == `VAL) begin |
iqentry_T[n] <= fp0_bus; |
iqentry_T_v[n] <= `VAL; |
end |
`endif |
// For SWCR |
if (iqentry_p_v[n] == `INV && iqentry_p_s[n]==dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin |
iqentry_pred[n] <= dram_bus[3:0]; |
iqentry_p_v[n] <= `VAL; |
end |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin |
iqentry_a1[n] <= dram_bus; |
iqentry_a1_v[n] <= `VAL; |
end |
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin |
iqentry_a2[n] <= dram_bus; |
iqentry_a2_v[n] <= `VAL; |
end |
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin |
iqentry_a3[n] <= dram_bus; |
iqentry_a3_v[n] <= `VAL; |
end |
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == dram_id && iqentry_v[n] == `VAL && dram_v == `VAL) begin |
iqentry_T[n] <= dram_bus; |
iqentry_T_v[n] <= `VAL; |
end |
if (iqentry_p_v[n] == `INV && iqentry_p_s[n]==commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin |
iqentry_pred[n] <= cmt0nyb[iqentry_preg[n]]; |
iqentry_p_v[n] <= `VAL; |
end |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin |
iqentry_a1[n] <= commit0_bus; |
iqentry_a1_v[n] <= `VAL; |
end |
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin |
iqentry_a2[n] <= commit0_bus; |
iqentry_a2_v[n] <= `VAL; |
end |
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin |
iqentry_a3[n] <= commit0_bus; |
iqentry_a3_v[n] <= `VAL; |
end |
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin |
iqentry_T[n] <= commit0_bus; |
iqentry_T_v[n] <= `VAL; |
end |
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin |
iqentry_pred[n] <= cmt1nyb[iqentry_preg[n]]; |
iqentry_p_v[n] <= `VAL; |
end |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin |
iqentry_a1[n] <= commit1_bus; |
iqentry_a1_v[n] <= `VAL; |
end |
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin |
iqentry_a2[n] <= commit1_bus; |
iqentry_a2_v[n] <= `VAL; |
end |
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin |
iqentry_a3[n] <= commit1_bus; |
iqentry_a3_v[n] <= `VAL; |
end |
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin |
iqentry_T[n] <= commit1_bus; |
iqentry_T_v[n] <= `VAL; |
end |
end |
|
//`include "Thor_issue.v" |
4504,7 → 4689,7
end |
else if (iqentry_issue[n]) begin |
case (iqentry_islot[n]) |
2'd0: if (alu0_available) begin |
2'd0: if (alu0_available && alu0_done) begin |
alu0_ld <= 1'b1; |
alu0_sourceid <= n[3:0]; |
alu0_insnsz <= iqentry_insnsz[n]; |
4526,7 → 4711,9
: 64'hDEADDEADDEADDEAD; |
alu0_argC <= |
`ifdef SEGMENTATION |
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} : |
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs_base[iqentry_fn[n][5:3]],12'h000} : |
`else |
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? 64'd0 : |
`endif |
iqentry_a3_v[n] ? iqentry_a3[n] |
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus |
4540,7 → 4727,7
alu0_dataready <= fnAluValid(iqentry_op[n],iqentry_fn[n]); |
iqentry_out[n] <= `TRUE; |
end |
2'd1: if (alu1_available) begin |
2'd1: if (alu1_available && alu1_done) begin |
alu1_ld <= 1'b1; |
alu1_sourceid <= n[3:0]; |
alu1_insnsz <= iqentry_insnsz[n]; |
4562,7 → 4749,9
: 64'hDEADDEADDEADDEAD; |
alu1_argC <= |
`ifdef SEGMENTATION |
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} : |
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs_base[iqentry_fn[n][5:3]],12'h000} : |
`else |
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? 64'd0 : |
`endif |
iqentry_a3_v[n] ? iqentry_a3[n] |
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus |
4604,22 → 4793,23
fp0_pred <= iqentry_p_v[n] ? iqentry_pred[n] : |
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] : |
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0; |
fp0_argA <= iqentry_a1_v[n] ? iqentry_a1[n] |
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus |
: 64'hDEADDEADDEADDEAD; |
fp0_argB <= iqentry_a2_v[n] ? iqentry_a2[n] |
: (iqentry_a2_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a2_s[n] == alu1_id) ? alu1_bus |
: 64'hDEADDEADDEADDEAD; |
fp0_argC <= iqentry_a3_v[n] ? iqentry_a3[n] |
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a3_s[n] == alu1_id) ? alu1_bus |
: 64'hDEADDEADDEADDEAD; |
fp0_argA <= iqentry_a1_v[n] ? iqentry_a1[n] |
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus |
: 64'hDEADDEADDEADDEAD; |
fp0_argB <= iqentry_a2_v[n] ? iqentry_a2[n] |
: (iqentry_a2_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a2_s[n] == alu1_id) ? alu1_bus |
: 64'hDEADDEADDEADDEAD; |
fp0_argC <= iqentry_a3_v[n] ? iqentry_a3[n] |
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a3_s[n] == alu1_id) ? alu1_bus |
: 64'hDEADDEADDEADDEAD; |
fp0_argT <= iqentry_T_v[n] ? iqentry_T[n] |
: (iqentry_T_s[n] == alu0_id) ? alu0_bus |
: (iqentry_T_s[n] == alu1_id) ? alu1_bus |
: 64'hDEADDEADDEADDEAD; |
|
fp0_argI <= iqentry_a0[n]; |
end |
default: panic <= `PANIC_INVALIDISLOT; |
4652,7 → 4842,7
dram_v <= `TRUE; |
dram_id <= tlb_id; |
dram_tgt <= tlb_tgt; |
dram_exc <= `EXC_NONE; |
dram_exc <= `EX_NONE; |
dram_bus <= tlb_dato; |
tlb_op <= 4'h0; |
tlb_state <= 3'd0; |
4668,7 → 4858,7
dram_v <= `TRUE; |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
dram_exc <= `EXC_DBG; |
dram_exc <= `EX_DBG; |
dram_bus <= 64'h0; |
dram0 <= 3'd0; |
end |
4678,7 → 4868,7
dram_v <= `TRUE; // we are finished the memory cycle |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
dram_exc <= `EXC_SEGV; //dram0_exc; |
dram_exc <= `EX_SEGV; //dram0_exc; |
dram_bus <= 64'h0; |
dram0 <= 3'd0; |
end |
4695,7 → 4885,7
dram_v <= `TRUE; // we are finished the memory cycle |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
dram_exc <= `EXC_TLBMISS; //dram0_exc; |
dram_exc <= `EX_TLBMISS; //dram0_exc; |
dram_bus <= 64'h0; |
dram0 <= 3'd0; |
end |
4749,7 → 4939,7
dram_v <= dram0_op != `CAS && dram0_op != `INC && dram0_op != `STS && dram0_op != `STMV && dram0_op != `STCMP && dram0_op != `STFND; |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EXC_DBE : `EXC_NONE;//dram0_exc; |
dram_exc <= (err_i & (dram0_tgt!=7'd0 || !fnIsLoad(dram0_op))) ? `EX_DBE : `EX_NONE;//dram0_exc; |
if (dram0_op==`SWCR) |
dram_bus <= {63'd0,resv_i}; |
else |
4872,7 → 5062,7
if (ack_i|err_i) begin |
$display("MEM ack2"); |
dram_v <= `VAL; |
dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EXC_DBE : `EXC_NONE; |
dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EX_DBE : `EX_NONE; |
dram0_owns_bus <= `FALSE; |
wb_nack(); |
lock_o <= 1'b0; |
4966,7 → 5156,7
dram_v <= `TRUE; |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
dram_exc <= `EXC_NONE; |
dram_exc <= `EX_NONE; |
dram_bus <= fnDatai(dram0_op,dram0_fn,cdat,rsel); |
dram0 <= 3'd0; |
end |
5066,15 → 5256,15
dram0_datacmp <= iqentry_a2[n]; |
`ifdef SEGMENTATION |
if (iqentry_cmpmv[n]) |
dram0_addr <= iqentry_a1[n] + {sregs[iqentry_fn[n][5:3]],12'h000}; |
dram0_addr <= iqentry_a1[n] + {sregs_base[iqentry_fn[n][5:3]],12'h000}; |
else |
dram0_addr <= iqentry_a1[n]; |
dram0_seg <= {sregs[iqentry_fn[n][5:3]],12'h000}; |
dram0_lmt <= sregs[iqentry_fn[n][5:3]] + sregs_lmt[iqentry_fn[n][5:3]]; |
dram0_seg <= {sregs_base[iqentry_fn[n][5:3]],12'h000}; |
dram0_lmt <= sregs_base[iqentry_fn[n][5:3]] + sregs_lmt[iqentry_fn[n][5:3]]; |
// dram0_exc <= (iqentry_a1[n][ABW-1:12] >= sregs_lmt[iqentry_fn[n][5:3]]) ? `EXC_SEGV : `EXC_NONE; |
`ifdef STRINGOPS |
src_addr <= iqentry_a1[n] + {sregs[iqentry_fn[n][5:3]],12'h000}; |
dst_addr <= iqentry_a2[n] + {sregs[iqentry_fn[n][5:3]],12'h000}; |
src_addr <= iqentry_a1[n] + {sregs_base[iqentry_fn[n][5:3]],12'h000}; |
dst_addr <= iqentry_a2[n] + {sregs_base[iqentry_fn[n][5:3]],12'h000}; |
`endif |
`else |
dram0_addr <= iqentry_a1[n]; |
5503,11 → 5693,11
|
task commit_spr; |
input commit_v; |
input [6:0] commit_tgt; |
input [7:0] commit_tgt; |
input [DBW-1:0] commit_bus; |
input which; |
begin |
if (commit_v && commit_tgt[6]) begin |
if (commit_v && commit_tgt[7:6]==2'h1) begin |
casex(commit_tgt[5:0]) |
6'b00xxxx: begin |
pregs[commit_tgt[3:0]] <= which ? cmt1nyb[commit_tgt[3:0]] : cmt0nyb[commit_tgt[3:0]];//commit_bus[3:0]; |
5520,10 → 5710,15
end |
`ifdef SEGMENTATION |
6'b100xxx: begin |
sregs[commit_tgt[2:0]] <= commit_bus[DBW-1:12]; |
sregs[{1'b0,commit_tgt[2:0]}] <= commit_bus[31:0]; |
$display("sregs[%d]<=%h", commit_tgt[2:0], commit_bus); |
end |
6'b101xxx: sregs_lmt[commit_tgt[2:0]] <= commit_bus[DBW-1:12]; |
6'b101000: sregs[{1'b1,commit_tgt[2:0]}] <= commit_bus[31:0]; |
6'b101001: GDT <= commit_bus; |
6'b101011: segsw <= commit_bus[4:0]; |
6'b101100: sregs_base[segsw] <= commit_bus[DBW-1:12]; |
6'b101101: sregs_lmt[segsw] <= commit_bus[DBW-1:12]; |
6'b101111: sregs_acr[segsw] <= commit_bus[15:0]; |
`endif |
6'b110000: |
begin |
5548,8 → 5743,12
end |
`LCTR: begin lc <= commit_bus; $display("LC <= %h", commit_bus); end |
`ASID: asid <= commit_bus; |
`ifdef VECTOROPS |
`VL: VL <= commit_bus; |
`endif |
`SR: begin |
GM <= commit_bus[7:0]; |
regset <= commit_bus[10:8]; |
GMB <= commit_bus[23:16]; |
imb <= commit_bus[31]; |
im <= commit_bus[15]; |
5620,8 → 5819,12
6'b00xxxx: fnSpr = {DBW/4{pregs[regno[3:0]]}}; |
6'b01xxxx: fnSpr = cregs[regno[3:0]]; |
`ifdef SEGMENTATION |
6'b100xxx: fnSpr = {sregs[regno[2:0]],12'h000}; |
6'b101xxx: fnSpr = {sregs_lmt[regno[2:0]],12'h000}; |
6'b100xxx: fnSpr = sregs[{1'b0,regno[2:0]}]; |
6'b101000: fnSpr = sregs[{1'b1,regno[2:0]}]; |
6'b101001: fnSpr = GDT; |
6'b101100: fnSpr = {sregs_base[segsw],12'h000}; |
6'b101101: fnSpr = {sregs_lmt[segsw],12'h000}; |
6'b101111: fnSpr = sregs_acr[segsw]; |
`endif |
6'b110000: if (DBW==64) |
fnSpr = {pregs[15],pregs[14],pregs[13],pregs[12], |
5633,14 → 5836,19
pregs[3],pregs[2],pregs[1],pregs[0]}; |
`TICK: fnSpr = tick; |
`LCTR: fnSpr = lc; |
`ASID: fnSpr = asid; |
`ASID: fnSpr = asid; |
`ifdef VECTOROPS |
`VL: fnSpr = VL; |
`endif |
`SR: begin |
fnSpr[7:0] = GM; |
fnSpr[10:8] = regset; |
fnSpr[23:16] = GMB; |
fnSpr[31] = imb; |
fnSpr[15] = im; |
fnSpr[12] = fxe; |
end |
`ARG1: fnSpr = intarg1; |
6'd60: fnSpr = spr_bir; |
6'd61: |
casex(spr_bir[5:0]) |
5702,6 → 5910,7
begin |
if (commit_v) |
case(iqentry_op[head]) |
`INT: intarg1 <= iqentry_a1[head]; |
`CLI: begin imcd <= IMCD; imb <= 1'b0; end |
`SEI: begin im <= 1'b1; imb <= 1'b1; end |
// When the RTI instruction commits clear the hardware interrupt status to enable interrupts. |
5729,12 → 5938,20
6'd0: ic_invalidate <= `TRUE; |
6'd1: begin |
ic_invalidate_line <= `TRUE; |
ic_lineno <= iqentry_a1[head] + {sregs[3'd7],12'h000}; |
`ifdef SEGMENTATION |
ic_lineno <= iqentry_a1[head] + {sregs_base[3'd7],12'h000}; |
`else |
ic_lineno <= iqentry_a1[head]; |
`endif |
end |
6'd32: dc_invalidate <= `TRUE; |
6'd33: begin |
dc_invalidate_line <= `TRUE; |
dc_lineno <= iqentry_a1[head] + {sregs[iqentry_fn[head][5:3]],12'h000}; |
`ifdef SEGMENTATION |
dc_lineno <= iqentry_a1[head] + {sregs_base[iqentry_fn[head][5:3]],12'h000}; |
`else |
dc_lineno <= iqentry_a1[head]; |
`endif |
end |
default: ; // do nothing |
endcase |
5752,6 → 5969,7
input [2:0] tail; |
input [2:0] inc; |
input unlink; |
input [2:0] vel; |
begin |
if (fetchbuf0_pc==32'h0) |
$stop; |
5763,17 → 5981,17
`ifdef SEGLIMITS |
// If segment limit exceeded and not in the non-segmented area. |
if (fetchbuf0_pc >= {sregs_lmt[3'd7],12'h000} && fetchbuf0_pc[ABW-1:ABW-4]!=4'hF) |
set_exception(tail,8'd244); |
set_exception(tail,`EX_SEGV); |
`endif |
`endif |
// If targeting a kernel mode register and not in kernel mode. |
// But okay if it is an SYS or INT instruction. |
if (fnIsKMOnlyReg(Rt0) && !km && !(opcode0==`SYS || opcode0==`INT)) |
set_exception(tail,8'd245); |
set_exception(tail,`EX_PRIV); |
// If attempting to use an undefined instruction |
`ifdef TRAP_ILLEGALOPS |
if (fnIsIllegal(opcode0,opcode0==`MLO ? rfoc0[5:0] : fnFunc(fetchbuf0_instr))) |
set_exception(tail,8'd250); |
set_exception(tail,9'd250); |
`endif |
`ifdef DEBUG_LOGIC |
if (dbg_ctrl[0] && dbg_ctrl[17:16]==2'b00 && fetchbuf0_pc==dbg_adr0) |
5787,7 → 6005,7
if (dbg_imatchA0|dbg_imatchA1|dbg_imatchA2|dbg_imatchA3) |
dbg_imatchA = `TRUE; |
if (dbg_imatchA) |
set_exception(tail,8'd243); // Debug exception |
set_exception(tail,9'd243); // Debug exception |
`endif |
if (!exception_set) begin |
interrupt_pc = |
5813,6 → 6031,7
iqentry_agen [tail] <= `INV; |
iqentry_pc [tail] <= (opcode0==`INT && Rt0[3:0]==4'hE) ? interrupt_pc : fetchbuf0_pc; |
iqentry_mem [tail] <= fetchbuf0_mem; |
iqentry_vec [tail] <= fetchbuf0_vec; |
iqentry_ndx [tail] <= fnIsIndexed(opcode0); |
iqentry_cas [tail] <= opcode0==`CAS; |
iqentry_pushpop[tail] <= opcode0==`PUSH || opcode0==`POP; |
5832,11 → 6051,16
// Need the bypassing on the preg file for write-through register effect. |
iqentry_pred [tail] <= fnSpr({2'h0,Pn0},fetchbuf0_pc);//pregs[Pn0]; |
// Look at the previous queue slot to see if an immediate prefix is enqueued |
iqentry_a0[tail] <= (opcode0==`INT || opcode0==`SYS) ? fnImm(fetchbuf0_instr) : |
fnIsBranch(opcode0) ? {{DBW-12{fetchbuf0_instr[11]}},fetchbuf0_instr[11:8],fetchbuf0_instr[23:16]} : |
(iqentry_op[(tail-3'd1)&7]==`IMM && iqentry_v[tail-3'd1]) ? {iqentry_a0[(tail-3'd1)&7][DBW-1:8],fnImm8(fetchbuf0_instr)}: |
opcode0==`IMM ? fnImmImm(fetchbuf0_instr) : |
fnImm(fetchbuf0_instr); |
iqentry_a0[tail] <= |
`ifdef VECTOROPS |
(opcode0==`LVX || opcode0==`SVX) ? {vel,3'b0} : |
`endif |
(opcode0==`INT || opcode0==`SYS || opcode0==`RTF || opcode0==`JSF) ? fnImm(fetchbuf0_instr) : |
fnIsBranch(opcode0) ? {{DBW-12{fetchbuf0_instr[11]}},fetchbuf0_instr[11:8],fetchbuf0_instr[23:16]} : |
(iqentry_op[(tail-3'd1)&7]==`IMM && iqentry_v[tail-3'd1]) ? {iqentry_a0[(tail-3'd1)&7][DBW-1:8],fnImm8(fetchbuf0_instr)}: |
opcode0==`IMM ? fnImmImm(fetchbuf0_instr) : |
fnImm(fetchbuf0_instr); |
|
// These register recordings for simulation debug. They should be stripped |
// out of synthesis because they don't drive any signals. |
`ifdef SIMULATION |
5846,17 → 6070,22
iqentry_rt [tail] <= Rt0; |
`endif |
iqentry_a1 [tail] <= fnOpa(opcode0,Ra0,fetchbuf0_instr,rfoa0,fetchbuf0_pc); |
iqentry_a2 [tail] <= fnOpb(opcode0,Rb0,fetchbuf0_instr,rfob0,fetchbuf0_pc); |
iqentry_a3 [tail] <= rfoc0; |
iqentry_T [tail] <= fnOpt(Rt0,rfot0,fetchbuf0_pc); |
iqentry_a2 [tail] <= fnOpb(opcode0,Rb0,fetchbuf0_instr,rfob0,pvrfoa0,fetchbuf0_pc); |
iqentry_a3 [tail] <= fetchbuf0_vec ? pvrfob0 : rfoc0; |
iqentry_T [tail] <= fnOpt(Rt0,rfot0,vrfot0,fetchbuf0_pc); |
// The source is set even though the arg might be automatically valid (less logic). |
// This is harmless to do. Note there is no source for the 'I' argument. |
iqentry_p_s [tail] <= rf_source[{1'b1,2'h0,Pn0}]; |
iqentry_a1_s [tail] <= //unlink ? {1'b0, (tail-1)&7} : |
rf_source[Ra0]; |
rf_source[Ra0]; |
iqentry_a2_s [tail] <= rf_source[Rb0]; |
iqentry_a3_s [tail] <= rf_source[Rc0]; |
`ifdef VECTOROPS |
iqentry_a4 [tail] <= pvrfoc0; |
iqentry_a4_s [tail] <= rf_source[Rd0]; |
`endif |
iqentry_T_s [tail] <= rf_source[Rt0]; |
|
// Always do this because it's the first queue slot. |
validate_args10(tail); |
end |
5863,7 → 6092,32
tail0 <= tail0 + inc; |
tail1 <= tail1 + inc; |
tail2 <= tail2 + inc; |
queued1 = `TRUE; |
// If it's a vector instruction it isn't finished queuing until all the elements |
// have queued. We still need to know however when each element queues so that |
// the element counter can be incremented. |
// Note that the element can't be queued until the vector length is known which |
// is always found in a1. |
`ifdef VECTOROPS |
if (fetchbuf0_vec) begin |
if (fnVecL(fetchbuf0_instr) begin |
queued1v = `VAL; |
queued1 = vel >= VL[6:0]; |
// We set allowq to FALSE to disallow a second instruction queue if a vector instruction |
// is being queued. |
allowq = `FALSE; |
end |
// For a specific element we need to wait until after the ele is set and |
// the register file has a chance to be read. |
else begin |
ele <= iqentry_a1[tail]; |
queued1 = iqentry_a1_v[tail]; |
end |
end |
else |
`endif |
begin |
queued1 = `TRUE; |
end |
rrmapno <= rrmapno + 3'd1; |
end |
endtask |
5920,6 → 6174,9
iqentry_a1_s [tail] <= rf_source[Ra0]; |
iqentry_a2_s [tail] <= rf_source[Rb0]; |
iqentry_a3_s [tail] <= rf_source[Rc0]; |
`ifdef VECTOROPS |
iqentry_a4_s [tail] <= rf_source[Rd0]; |
`endif |
iqentry_T_s [tail] <= rf_source[Ra0]; |
// Always do this because it's the first queue slot. |
iqentry_p_v [tail] <= rf_v [{1'b1,2'h0,which ? Pn1:Pn0}] || ((which ? cond1 : cond0) < 4'h2); |
5939,7 → 6196,18
input [2:0] inc; |
input test_stomp; |
input validate_args; |
input [2:0] vel; |
begin |
/* |
`ifdef VECTOROPS |
if (fetchbuf0_vec && VM[vel]==1'b0) begin |
queued1v = iqentry_a1_v[tail]; |
if (vel >= iqentry_a1[tail] && iqentry_a1_v[tail]) |
queued1 = `TRUE; |
end |
else |
`endif |
*/ |
if (opcode0==`NOP) |
queued1 = `TRUE; // to update fetch buffers |
`ifdef DEBUG_LOGIC |
5946,8 → 6214,8
else |
if (dbg_ctrl[7] && !StatusDBG) begin |
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin |
enque0a(tail,3'd2,1'b0); |
set_exception((tail+1)&7,8'd243); |
enque0a(tail,3'd2,1'b0,vel); |
set_exception((tail+1)&7,9'd243); |
allowq = `FALSE; |
end |
end |
5958,7 → 6226,7
$display("0 found push/pop"); |
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin |
$display("enqueing2"); |
enque0a(tail,3'd2,1'b0); |
enque0a(tail,3'd2,1'b0,vel); |
enquePushpopAdd((tail+1)&7,fnIsPop(fetchbuf0_instr),opcode0==`LINK,0,0); |
allowq = `FALSE; |
end |
5967,16 → 6235,27
else if (opcode0==`UNLINK) begin |
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin |
enquePushpopAdd(tail,1'b0,1'b0,1'b1,0); |
enque0a((tail+1)&7,3'd2,1'b1); |
enque0a((tail+1)&7,3'd2,1'b1,vel); |
allowq = `FALSE; |
end |
end |
`endif |
`endif |
/* |
`ifdef SEGMENTATION |
else if (fnTargetsSegreg(fetchbuf0_instr)) begin |
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin |
enque0a(tail,2'd2,0,vel); |
set_exception((tail+1)&7,{6'b100000,Rt0[2:0]}); // Seg load |
allowq = `FALSE; |
end |
end |
`endif |
*/ |
else if (iqentry_v[tail] == `INV) begin |
if ((({fnIsBranch(opcode0), predict_taken0} == {`TRUE, `TRUE})||(opcode0==`LOOP)) && test_stomp) |
qstomp = `TRUE; |
enque0a(tail,inc,0); |
enque0a(tail,inc,0,vel); |
end |
end |
endtask |
5986,6 → 6265,7
input [2:0] inc; |
input validate_args; |
input unlink; |
input [2:0] vel; |
begin |
if (fetchbuf1_pc==32'h0) |
$stop; |
5996,14 → 6276,14
`ifdef SEGMENTATION |
`ifdef SEGLIMITS |
if (fetchbuf1_pc >= {sregs_lmt[3'd7],12'h000} && fetchbuf1_pc[ABW-1:ABW-4]!=4'hF) |
set_exception(tail,8'd244); |
set_exception(tail,9'd244); |
`endif |
`endif |
if (fnIsKMOnlyReg(Rt1) && !km && !(opcode1==`SYS || opcode1==`INT)) |
set_exception(tail,8'd245); |
set_exception(tail,9'd245); |
`ifdef TRAP_ILLEGALOPS |
if (fnIsIllegal(opcode1,opcode1==`MLO ? rfoc1[5:0] : fnFunc(fetchbuf1_instr))) |
set_exception(tail,8'd250); |
set_exception(tail,9'd250); |
`endif |
`ifdef DEBUG_LOGIC |
if (dbg_ctrl[0] && dbg_ctrl[17:16]==2'b00 && fetchbuf1_pc==dbg_adr0) |
6017,7 → 6297,7
if (dbg_imatchB0|dbg_imatchB1|dbg_imatchB2|dbg_imatchB3) |
dbg_imatchB = `TRUE; |
if (dbg_imatchB) |
set_exception(tail,8'd243); // debug excpetion |
set_exception(tail,9'd243); // debug excpetion |
`endif |
if (!exception_set) begin |
// If an instruction wasn't enqueued or it wasn't an interrupt instruction then |
6028,7 → 6308,7
(string_pc != 0 ? string_pc : iqentry_pc[(tail-3'd1)&7]) : |
(iqentry_op[(tail-3'd1)&7]==`IMM && iqentry_v[(tail-3'd1)&7]==`VAL) ? (string_pc != 0 ? string_pc : |
iqentry_pc[(tail-3'd1)&7]) : (string_pc != 0 ? string_pc : fetchbuf1_pc); |
iqentry_v [tail] <= `VAL; |
iqentry_v [tail] <= fetchbuf1_vec ? vel < iqentry_a1[tail][2:0] : `VAL; |
iqentry_done [tail] <= `INV; |
iqentry_cmt [tail] <= `TRUE; |
iqentry_out [tail] <= `INV; |
6067,16 → 6347,20
iqentry_pred [tail] <= fnSpr({2'h0,Pn1},fetchbuf1_pc);//pregs[Pn1]; |
// Look at the previous queue slot to see if an immediate prefix is enqueued |
// But don't allow it for a branch |
iqentry_a0[tail] <= (opcode1==`INT || opcode1==`SYS) ? fnImm(fetchbuf1_instr) : |
fnIsBranch(opcode1) ? {{DBW-12{fetchbuf1_instr[11]}},fetchbuf1_instr[11:8],fetchbuf1_instr[23:16]} : |
(queued1 && opcode0==`IMM) ? {fnImmImm(fetchbuf0_instr)|fnImm8(fetchbuf1_instr)} : |
(!queued1 && iqentry_op[(tail-3'd1)&7]==`IMM) && iqentry_v[(tail-3'd1)&7] ? {iqentry_a0[(tail-3'd1)&7][DBW-1:8],fnImm8(fetchbuf1_instr)} : |
opcode1==`IMM ? fnImmImm(fetchbuf1_instr) : |
fnImm(fetchbuf1_instr); |
iqentry_a0[tail] <= |
`ifdef VECTOROPS |
(opcode1==`LVX || opcode1==`SVX) ? {vel,3'b0} : |
`endif |
(opcode1==`INT || opcode1==`SYS || opcode1==`RTF || opcode1==`JSF) ? fnImm(fetchbuf1_instr) : |
fnIsBranch(opcode1) ? {{DBW-12{fetchbuf1_instr[11]}},fetchbuf1_instr[11:8],fetchbuf1_instr[23:16]} : |
(queued1 && opcode0==`IMM) ? {fnImmImm(fetchbuf0_instr)|fnImm8(fetchbuf1_instr)} : |
(!queued1 && iqentry_op[(tail-3'd1)&7]==`IMM) && iqentry_v[(tail-3'd1)&7] ? {iqentry_a0[(tail-3'd1)&7][DBW-1:8],fnImm8(fetchbuf1_instr)} : |
opcode1==`IMM ? fnImmImm(fetchbuf1_instr) : |
fnImm(fetchbuf1_instr); |
iqentry_a1 [tail] <= fnOpa(opcode1,Ra1,fetchbuf1_instr,rfoa1,fetchbuf1_pc); |
iqentry_a2 [tail] <= fnOpb(opcode1,Rb1,fetchbuf1_instr,rfob1,fetchbuf1_pc); |
iqentry_a3 [tail] <= rfoc1; |
iqentry_T [tail] <= fnOpt(Rt1,rfot1,fetchbuf1_pc); |
iqentry_a2 [tail] <= fnOpb(opcode1,Rb1,fetchbuf1_instr,rfob1,pvrfoa1,fetchbuf1_pc); |
iqentry_a3 [tail] <= fetchbuf1_vec ? pvrfob1 : rfoc1; |
iqentry_T [tail] <= fnOpt(Rt1,rfot1,vrfot1,fetchbuf1_pc); |
`ifdef SIMULATION |
iqentry_r1 [tail] <= Ra1; |
iqentry_r2 [tail] <= Rb1; |
6090,6 → 6374,10
rf_source[Ra1]; |
iqentry_a2_s [tail] <= rf_source[Rb1]; |
iqentry_a3_s [tail] <= rf_source[Rc1]; |
`ifdef VECTOROPS |
iqentry_a4 [tail] <= pvrfoc1; |
iqentry_a4_s [tail] <= rf_source[Rd1]; |
`endif |
iqentry_T_s [tail] <= rf_source[Rt1]; |
if (validate_args) |
validate_args11(tail); |
6106,7 → 6394,19
input [2:0] inc; |
input test_stomp; |
input validate_args; |
input [2:0] vel; |
begin |
/* |
This bit of code being superceded by vector predicate bits |
`ifdef VECTOROPS |
if (fetchbuf1_vec && VM[vel]==1'b0) begin |
queued1v = iqentry_vl_v[tail]; |
if (vel >= iqentry_vl[tail] && iqentry_vl_v[tail]) |
queued1 = `TRUE; |
end |
else |
`endif |
*/ |
if (opcode1==`NOP) begin |
if (queued1==`TRUE) queued2 = `TRUE; |
queued1 = `TRUE; |
6115,8 → 6415,8
else |
if (dbg_ctrl[7] && !StatusDBG) begin |
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin |
enque1a(tail,3'd2,1,0); |
set_exception((tail+1)&7,8'd243); |
enque1a(tail,3'd2,1,0,vel); |
set_exception((tail+1)&7,9'd243); |
allowq = `FALSE; |
end |
end |
6130,7 → 6430,7
$display("qd1:%d", queued1); |
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV && validate_args && !queued1) begin |
$display("1 enq 2 "); |
enque1a(tail,3'd2,1,0); |
enque1a(tail,3'd2,1,0,vel); |
enquePushpopAdd((tail+1)&7,fnIsPop(fetchbuf1_instr),opcode1==`LINK,0,1); |
allowq = `FALSE; |
end |
6139,18 → 6439,38
else if (opcode1==`UNLINK) begin |
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin |
enquePushpopAdd(tail,1'b0,1'b0,1'b1,1); |
enque1a((tail+1)&7,3'd2,1,1); |
enque1a((tail+1)&7,3'd2,1,1,vel); |
allowq = `FALSE; |
end |
end |
`endif |
`endif |
/* |
`ifdef SEGMENTATION |
else if (fnTargetsSegreg(fetchbuf1_instr)) begin |
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin |
enque1a(tail,2'd2,1,0,vel); |
set_exception((tail+1)&7,{6'b100000,Rt1[2:0]}); // Seg load |
allowq = `FALSE; |
end |
end |
`endif |
*/ |
else if (iqentry_v[tail] == `INV && !qstomp) begin |
if ((({fnIsBranch(opcode1), predict_taken1} == {`TRUE, `TRUE})||(opcode1==`LOOP)) && test_stomp) |
qstomp = `TRUE; |
enque1a(tail,inc,validate_args,0); |
enque1a(tail,inc,validate_args,0,vel); |
// Note that if there are two instructions ready to queue and the first instruction is a |
// vector instruction then we shouldn't get here because allowq would be false. |
`ifdef VECTOROPS |
if (queued1v==`TRUE) queued2v = fetchbuf1_vec; |
else queued1v = fetchbuf1_vec; |
if (queued1==`TRUE) queued2 = fetchbuf1_vec ? vele >= VL[6:0] : `TRUE; |
else queued1 = fetchbuf1_vec ? vele >= VL[6:0] : `TRUE; |
`else |
if (queued1==`TRUE) queued2 = `TRUE; |
else queued1 = `TRUE; |
`endif |
end |
end |
endtask |
6160,9 → 6480,13
begin |
iqentry_p_v [tail] <= rf_v [{1'b1,2'h0,Pn0}] || cond0 < 4'h2; |
iqentry_a1_v [tail] <= fnSource1_v( opcode0 ) | rf_v[ Ra0 ]; |
iqentry_a2_v [tail] <= fnSource2_v( opcode0, fnFunc(fetchbuf0_instr)) | rf_v[Rb0]; |
iqentry_a2_v [tail] <= (fnSource2_v( opcode0, fnFunc(fetchbuf0_instr)) | rf_v[Rb0]);// & fnVelv(fetchbuf0_instr); |
iqentry_a3_v [tail] <= fnSource3_v( opcode0, fnFunc(fetchbuf0_instr)) | rf_v[ Rc0 ]; |
`ifdef VECTOROPS |
iqentry_a4_v [tail] <= fnSource4_v( opcode0, fnFunc(fetchbuf0_instr)) | rf_v[ Rd0 ]; |
`endif |
iqentry_T_v [tail] <= fnSourceT_v( opcode0, fnFunc(fetchbuf0_instr)) | rf_v[ Rt0 ]; |
iqentry_velv [tail] <= fnVelv(fetchbuf0_instr); |
if (fetchbuf0_rfw|fetchbuf0_pfw) begin |
$display("regv[%d] = %d", Rt0,rf_v[ Rt0 ]); |
rf_v[ Rt0 ] = fnRegIsAutoValid(Rt0); |
6180,9 → 6504,13
// The predicate is automatically valid for condiitions 0 and 1 (always false or always true). |
iqentry_p_v [tail] <= rf_v [{1'b1,2'h0,Pn1}] || cond1 < 4'h2; |
iqentry_a1_v [tail] <= fnSource1_v( opcode1 ) | rf_v[ Ra1 ]; |
iqentry_a2_v [tail] <= fnSource2_v( opcode1, fnFunc(fetchbuf1_instr)) | rf_v[ Rb1 ]; |
iqentry_a2_v [tail] <= (fnSource2_v( opcode1, fnFunc(fetchbuf1_instr)) | rf_v[ Rb1 ]);// & fnVelv(fetchbuf1_instr); |
iqentry_a3_v [tail] <= fnSource3_v( opcode1, fnFunc(fetchbuf1_instr)) | rf_v[ Rc1 ]; |
`ifdef VECTOROPS |
iqentry_a4_v [tail] <= fnSource3_v( opcode1, fnFunc(fetchbuf1_instr)) | rf_v[ Rd1 ]; |
`endif |
iqentry_T_v [tail] <= fnSourceT_v( opcode1, fnFunc(fetchbuf1_instr)) | rf_v[ Rt1 ]; |
iqentry_velv [tail] <= fnVelv(fetchbuf1_instr); |
if (fetchbuf1_rfw|fetchbuf1_pfw) begin |
$display("1:regv[%d] = %d", Rt1,rf_v[ Rt1 ]); |
rf_v[ Rt1 ] = fnRegIsAutoValid(Rt1); |
6198,7 → 6526,7
// |
task validate_args; |
begin |
if (queued2) begin |
if (queued2|queued2v) begin |
// SOURCE 1 ... this is relatively straightforward, because all instructions |
// that have a source (i.e. every instruction but LUI) read from RB |
// |
6215,7 → 6543,7
iqentry_a1_s [tail1] <= rf_source [Ra1]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rt0 != 7'd0 && Ra1 == Rt0) begin |
else if (Rt0 != 10'd0 && Ra1 == Rt0) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
$display("invalidating iqentry_a1_v[%d]", tail1); |
iqentry_a1_v [tail1] <= `INV; |
6228,11 → 6556,11
$display("2:iqentry_a1_s[%d] <= %d", tail1, rf_source [Ra1]); |
end |
|
if (!fetchbuf0_pfw) begin |
if (!fetchbuf0_rfw) begin |
iqentry_p_v [tail1] <= rf_v [{1'b1,2'h0,Pn1}] || cond1 < 4'h2; |
iqentry_p_s [tail1] <= rf_source [{1'b1,2'h0,Pn1}]; |
end |
else if ((Rt0 != 7'd0 && (Pn1==Rt0[3:0] || Rt0==7'h70)) && ((Rt0 & 7'h70)==7'h40)||Rt0==7'h70) begin |
else if ((Rt0 != 8'd0 && (Pn1==Rt0[3:0] || Rt0==8'h70)) && ((Rt0 & 8'h70)==8'h40)||Rt0==8'h70) begin |
iqentry_p_v [tail1] <= cond1 < 4'h2; |
iqentry_p_s [tail1] <= {fetchbuf0_mem, tail0}; |
end |
6256,7 → 6584,7
iqentry_a2_s [tail1] <= rf_source[Rb1]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rt0 != 7'd0 && Rb1 == Rt0) begin |
else if (Rt0 != 8'd0 && Rb1 == Rt0) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a2_v [tail1] <= `INV; |
iqentry_a2_s [tail1] <= {fetchbuf0_mem,tail0}; |
6283,7 → 6611,7
iqentry_a3_s [tail1] <= rf_source [Rc1]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rt0 != 7'd0 && Rc1 == Rt0) begin |
else if (Rt0 != 8'd0 && Rc1 == Rt0) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a3_v [tail1] <= `INV; |
iqentry_a3_s [tail1] <= {fetchbuf0_mem,tail0}; |
6293,8 → 6621,27
iqentry_a3_v [tail1] <= rf_v [Rc1]; |
iqentry_a3_s [tail1] <= rf_source [Rc1]; |
end |
|
|
`ifdef VECTOROPS |
if (fnSource4_v( opcode1,fnFunc(fetchbuf1_instr) ) == `VAL) begin |
iqentry_a4_v [tail1] <= `VAL; |
end |
// if previous instruction writes nothing to RF, then get info from rf_v and rf_source |
else if (!fetchbuf0_rfw) begin |
iqentry_a4_v [tail1] <= rf_v [Rd1]; |
iqentry_a4_s [tail1] <= rf_source [Rd1]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rt0 != 10'd0 && Rd1 == Rt0) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_a4_v [tail1] <= `INV; |
iqentry_a4_s [tail1] <= {fetchbuf0_mem,tail0}; |
end |
// if no overlap, get info from rf_v and rf_source |
else begin |
iqentry_a4_v [tail1] <= rf_v [Rd1]; |
iqentry_a4_s [tail1] <= rf_source [Rd1]; |
end |
`endif |
// |
// Target 3 ... this is relatively straightforward, because all instructions |
// that have a source (i.e. every instruction but LUI) read from RC |
6310,7 → 6657,7
iqentry_T_s [tail1] <= rf_source [Rt1]; |
end |
// otherwise, previous instruction does write to RF ... see if overlap |
else if (Rt0 != 7'd0 && Rt1 == Rt0) begin |
else if (Rt0 != 8'd0 && Rt1 == Rt0) begin |
// if the previous instruction is a LW, then grab result from memq, not the iq |
iqentry_T_v [tail1] <= `INV; |
iqentry_T_s [tail1] <= {fetchbuf0_mem,tail0}; |
6442,7 → 6789,7
|
task set_exception; |
input [2:0] id; // instruction queue id |
input [7:0] exc; // exception number |
input [8:0] exc; // exception number |
begin |
iqentry_op [id[2:0] ] <= `INT; |
iqentry_cond [id[2:0]] <= 4'd1; // always execute |
6454,10 → 6801,13
iqentry_a1_v [id[2:0]] <= `TRUE; // Flag arguments as valid |
iqentry_a2_v [id[2:0]] <= `TRUE; |
iqentry_a3_v [id[2:0]] <= `TRUE; |
`ifdef VECTOROPS |
iqentry_a4_v [id[2:0]] <= `TRUE; |
`endif |
iqentry_T_v [id[2:0]] <= `TRUE; |
iqentry_out [id[2:0]] <= `FALSE; |
iqentry_agen [id[2:0]] <= `FALSE; |
iqentry_tgt[id[2:0]] <= {1'b1,2'h1,(exc==8'd243)?4'hB:4'hD}; // Target EPC |
iqentry_tgt[id[2:0]] <= {1'b1,2'h1,(exc==9'd243 || exc[8])?4'hB:4'hD}; // Target EPC |
exception_set = `TRUE; |
end |
endtask |
6473,44 → 6823,86
// To be fixed one day. |
task invalidate_pregs; |
input [2:0] tail; |
input [6:0] Rt; |
input [7:0] Rt; |
input mem; |
begin |
if (Rt==7'h70) begin |
rf_v[7'h40] = `INV; |
rf_v[7'h41] = `INV; |
rf_v[7'h42] = `INV; |
rf_v[7'h43] = `INV; |
rf_v[7'h44] = `INV; |
rf_v[7'h45] = `INV; |
rf_v[7'h46] = `INV; |
rf_v[7'h47] = `INV; |
rf_v[7'h48] = `INV; |
rf_v[7'h49] = `INV; |
rf_v[7'h4A] = `INV; |
rf_v[7'h4B] = `INV; |
rf_v[7'h4C] = `INV; |
rf_v[7'h4D] = `INV; |
rf_v[7'h4E] = `INV; |
rf_v[7'h4F] = `INV; |
rf_source[7'h40] <= { mem, tail }; |
rf_source[7'h41] <= { mem, tail }; |
rf_source[7'h42] <= { mem, tail }; |
rf_source[7'h43] <= { mem, tail }; |
rf_source[7'h44] <= { mem, tail }; |
rf_source[7'h45] <= { mem, tail }; |
rf_source[7'h46] <= { mem, tail }; |
rf_source[7'h47] <= { mem, tail }; |
rf_source[7'h48] <= { mem, tail }; |
rf_source[7'h49] <= { mem, tail }; |
rf_source[7'h4A] <= { mem, tail }; |
rf_source[7'h4B] <= { mem, tail }; |
rf_source[7'h4C] <= { mem, tail }; |
rf_source[7'h4D] <= { mem, tail }; |
rf_source[7'h4E] <= { mem, tail }; |
rf_source[7'h4F] <= { mem, tail }; |
if (Rt==8'h70) begin |
rf_v[8'h40] = `INV; |
rf_v[8'h41] = `INV; |
rf_v[8'h42] = `INV; |
rf_v[8'h43] = `INV; |
rf_v[8'h44] = `INV; |
rf_v[8'h45] = `INV; |
rf_v[8'h46] = `INV; |
rf_v[8'h47] = `INV; |
rf_v[8'h48] = `INV; |
rf_v[8'h49] = `INV; |
rf_v[8'h4A] = `INV; |
rf_v[8'h4B] = `INV; |
rf_v[8'h4C] = `INV; |
rf_v[8'h4D] = `INV; |
rf_v[8'h4E] = `INV; |
rf_v[8'h4F] = `INV; |
rf_source[8'h40] <= { mem, tail }; |
rf_source[8'h41] <= { mem, tail }; |
rf_source[8'h42] <= { mem, tail }; |
rf_source[8'h43] <= { mem, tail }; |
rf_source[8'h44] <= { mem, tail }; |
rf_source[8'h45] <= { mem, tail }; |
rf_source[8'h46] <= { mem, tail }; |
rf_source[8'h47] <= { mem, tail }; |
rf_source[8'h48] <= { mem, tail }; |
rf_source[8'h49] <= { mem, tail }; |
rf_source[8'h4A] <= { mem, tail }; |
rf_source[8'h4B] <= { mem, tail }; |
rf_source[8'h4C] <= { mem, tail }; |
rf_source[8'h4D] <= { mem, tail }; |
rf_source[8'h4E] <= { mem, tail }; |
rf_source[8'h4F] <= { mem, tail }; |
end |
end |
endtask |
|
// The following task looks at a functional unit output bus and assigns results |
// to waiting arguments. |
|
task setargs; |
input [3:0] id; |
input v; |
input [DBW-1:0] bus; |
begin |
for (n = 0; n < QENTRIES; n = n + 1) |
begin |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == id && iqentry_v[n] == `VAL && v == `VAL) begin |
iqentry_a1[n] <= bus; |
iqentry_a1_v[n] <= `VAL; |
end |
if (iqentry_a2_v[n] == `INV && iqentry_a2_s[n] == id && iqentry_v[n] == `VAL && v == `VAL) begin |
iqentry_a2[n] <= bus; |
iqentry_a2_v[n] <= `VAL; |
end |
/* |
if (iqentry_a2_v[n] == `INV && iqentry_a2_sv[n]==`TRUE && iqentry_v[n] && rf_v [{ele,iqentry_rb[n]}]) begin |
iqentry_a2[n] <= vrfob0; |
iqentry_a2_v[n] <= iqentry_velv[n]; |
end |
*/ |
if (iqentry_a3_v[n] == `INV && iqentry_a3_s[n] == id && iqentry_v[n] == `VAL && v == `VAL) begin |
iqentry_a3[n] <= bus; |
iqentry_a3_v[n] <= `VAL; |
end |
`ifdef VECTOROPS |
if (iqentry_a4_v[n] == `INV && iqentry_a4_s[n] == id && iqentry_v[n] == `VAL && v == `VAL) begin |
iqentry_a4[n] <= bus; |
iqentry_a4_v[n] <= `VAL; |
end |
`endif |
if (iqentry_T_v[n] == `INV && iqentry_T_s[n] == id && iqentry_v[n] == `VAL && v == `VAL) begin |
iqentry_T[n] <= bus; |
iqentry_T_v[n] <= `VAL; |
end |
end |
end |
endtask |
|
endmodule |
/trunk/rtl/verilog/Thor_alu.v
208,7 → 208,7
`MUL,`MULU: o <= BIG ? alu_prod[63:0] : 64'hDEADDEADDEADDEAD; |
`DIV,`DIVU: o <= BIG ? alu_divq : 64'hDEADDEADDEADDEAD; |
`MOD,`MODU: o <= BIG ? alu_rem : 64'hDEADDEADDEADDEAD; |
`CHK: o <= ($signed(alu_argC) >= $signed(alu_argA)) && ($signed(alu_argC) < $signed(alu_argB)); |
`CHK,`CHKX: o <= ($signed(alu_argC) >= $signed(alu_argA)) && ($signed(alu_argC) < $signed(alu_argB)); |
default: o <= 64'hDEADDEADDEADDEAD; |
endcase |
`MULI,`MULUI: o <= BIG ? alu_prod[63:0] : 64'hDEADDEADDEADDEAD; |
409,12 → 409,17
2'd2: o <= alu_argA + alu_argC + {alu_argB,2'b0}; |
2'd3: o <= alu_argA + alu_argC + {alu_argB,3'b0}; |
endcase |
`ifdef VECTOROPS |
`LV,`SV: o <= alu_argA + alu_argC + alu_argI; |
`LVWS,`SVWS: o <= alu_argA + alu_argC + alu_argB * alu_argI[8:3]; |
`LVX,`SVX: o <= alu_argA + alu_argC + alu_argB; |
`endif |
`ifdef STACKOPS |
`PEA,`LINK: o <= alu_argA + alu_argC - 64'd8; |
`UNLINK: o <= alu_argA + alu_argC + 64'd8; |
`POP: o <= alu_argA + alu_argC; |
`endif |
`JSR,`JSRS,`JSRZ,`SYS: o <= alu_pc + insnsz; |
`JSR,`JSRS,`JSRZ,`SYS,`JSF: o <= alu_pc + insnsz; |
`INT: o <= alu_pc; |
`MFSPR,`MTSPR: begin |
o <= alu_argA; |
438,7 → 443,15
`BITFIELD: o <= BIG ? bf_out : 64'hDEADDEADDEADDEAD; |
`endif |
`LOOP: o <= alu_argA > 0 ? alu_argA - 64'd1 : alu_argA; |
`CHKI: o <= ($signed(alu_argB) >= $signed(alu_argA)) && ($signed(alu_argB) < $signed(alu_argI)); |
`CHKXI: o <= ($signed(alu_argB) >= $signed(alu_argA)) && ($signed(alu_argB) < $signed(alu_argI)); |
`CHKI: |
begin |
o1[0] = ($signed(alu_argB) >= $signed(alu_argA)) && ($signed(alu_argB) < $signed(alu_argI)); |
o1[1] = 1'b0; |
o1[2] = 1'b0; |
o1[3] = 1'b0; |
o <= {16{o1}}; |
end |
default: o <= 64'hDEADDEADDEADDEAD; |
endcase |
end |
/trunk/rtl/verilog/Thor_execute_combo.v
125,7 → 125,7
alu0_misspc <= alu0_pc + alu0_insnsz; |
`RTS: |
alu0_misspc <= alu0_argA + alu0_fn[3:0]; |
`SYS,`INT: |
`SYS,`INT,`RTF,`JSF: |
alu0_misspc <= {1'b1,alu0_argA + alu0_argI}; |
default: |
alu0_misspc <= (alu0_bt ? alu0_pc + alu0_insnsz : alu0_pc + alu0_insnsz + alu0_argI); |
139,7 → 139,7
alu1_misspc <= alu1_pc + alu1_insnsz; |
`RTS: |
alu1_misspc <= alu1_argA + alu1_fn[3:0]; |
`SYS,`INT: |
`SYS,`INT,`RTF,`JSF: |
alu1_misspc <= {1'b1,alu1_argA + alu1_argI}; |
default: |
alu1_misspc <= (alu1_bt ? alu1_pc + alu1_insnsz : alu1_pc + alu1_insnsz + alu1_argI); |
153,21 → 153,28
default: jmpi_misspc <= 32'h00000FA0; // unimplemented instruction vector |
endcase |
|
assign alu0_exc = (fnIsKMOnly(alu0_op) && !km && alu0_cmt) ? `EXC_PRIV : |
(alu0_done && alu0_divByZero && alu0_cmt) ? `EXC_DBZ : |
((alu0_op==`CHKI||(alu0_op==`RR && alu0_fn==`CHK)) && !alu0_out && alu0_cmt) ? `EXC_CHK : |
`EXC_NONE; |
wire dbze0 = alu0_op==`DIVI || alu0_op==`MODI || (alu0_op==`RR && (alu0_fn==`DIV || alu0_fn==`MOD)); |
wire dbze1 = alu1_op==`DIVI || alu1_op==`MODI || (alu1_op==`RR && (alu1_fn==`DIV || alu1_fn==`MOD)); |
|
assign alu1_exc = (fnIsKMOnly(alu1_op) && !km && alu1_cmt) ? `EXC_PRIV : |
(alu1_done && alu1_divByZero && alu1_cmt) ? `EXC_DBZ : |
((alu1_op==`CHKI ||(alu1_op==`RR && alu1_fn==`CHK)) && !alu1_out && alu1_cmt) ? `EXC_CHK : |
`EXC_NONE; |
assign alu0_exc = (fnIsKMOnly(alu0_op) && !km && alu0_cmt) ? `EX_PRIV : |
(alu0_done && dbze0 && alu0_divByZero && alu0_cmt) ? `EX_DBZ : |
((alu0_op==`CHKXI||(alu0_op==`RR && alu0_fn==`CHKX)) && !alu0_out && alu0_cmt) ? `EX_CHK : |
(((alu0_op==`MTSPR && alu0_fn==0)|| alu0_op==`LDIS) && iqentry_tgt[alu0_id[2:0]][7:3]==5'h6) ? |
{6'h20,iqentry_tgt[alu0_id[2:0]][2:0]} : |
`EX_NONE; |
|
assign alu1_exc = (fnIsKMOnly(alu1_op) && !km && alu1_cmt) ? `EX_PRIV : |
(alu1_done && dbze1 && alu1_divByZero && alu1_cmt) ? `EX_DBZ : |
((alu1_op==`CHKXI ||(alu1_op==`RR && alu1_fn==`CHKX)) && !alu1_out && alu1_cmt) ? `EX_CHK : |
(((alu1_op==`MTSPR && alu1_fn==0)|| alu1_op==`LDIS) && iqentry_tgt[alu1_id[2:0]][7:3]==5'h6) ? |
{6'h20,iqentry_tgt[alu1_id[2:0]][2:0]} : |
`EX_NONE; |
|
assign alu0_branchmiss = alu0_dataready && |
((fnIsBranch(alu0_op)) ? ((alu0_cmt && !alu0_bt) || (!alu0_cmt && alu0_bt)) |
: !alu0_cmt ? (alu0_op==`LOOP) |
: (alu0_cmt && (alu0_op==`SYNC || alu0_op == `JSR || alu0_op == `JSRS || alu0_op == `JSRZ || |
alu0_op==`SYS || alu0_op==`INT || |
alu0_op==`SYS || alu0_op==`INT || alu0_op==`RTF || alu0_op==`JSF || |
alu0_op==`RTS || alu0_op==`RTS2 || alu0_op==`RTD || alu0_op == `RTE || alu0_op==`RTI || ((alu0_op==`LOOP) && (alu0_argA == 64'd0))))); |
|
assign alu1_branchmiss = alu1_dataready && |
174,7 → 181,7
((fnIsBranch(alu1_op)) ? ((alu1_cmt && !alu1_bt) || (!alu1_cmt && alu1_bt)) |
: !alu1_cmt ? (alu1_op==`LOOP) |
: (alu1_cmt && (alu1_op==`SYNC || alu1_op == `JSR || alu1_op == `JSRS || alu1_op == `JSRZ || |
alu1_op==`SYS || alu1_op==`INT || |
alu1_op==`SYS || alu1_op==`INT || alu1_op==`RTF || alu1_op==`JSF || |
alu1_op==`RTS || alu1_op==`RTS2 || alu1_op==`RTD || alu1_op == `RTE || alu1_op==`RTI || ((alu1_op==`LOOP) && (alu1_argA == 64'd0))))); |
|
assign branchmiss = (alu0_branchmiss | alu1_branchmiss | mem_stringmiss | jmpi_miss), |
243,7 → 250,7
end |
|
assign fp0_cmt = fnPredicate(fp0_pred, fp0_cond); |
assign fp0_exc = fp0_exception ? 8'd242 : 8'd0; |
assign fp0_exc = fp0_exception ? `EX_FP : 9'd0; |
|
assign fp0_v = fp0_dataready; |
assign fp0_id = fp0_sourceid; |
/trunk/rtl/verilog/Thor_vregfile2w6r.v
0,0 → 1,143
`timescale 1ns / 1ps |
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2013,2015 Robert Finch, Stratford |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
// |
// This source file is free software: you can redistribute it and/or modify |
// it under the terms of the GNU Lesser General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or |
// (at your option) any later version. |
// |
// This source file is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// You should have received a copy of the GNU General Public License |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
// |
// |
// Register file with two write ports and six read ports. |
// ============================================================================ |
// |
module Thor_vregfile2w6r(clk, wr0, wr1, wa0, wa1, i0, i1, |
rclk, ra0, ra1, ra2, ra3, ra4, ra5, ra6, ra7, |
o0, o1, o2, o3, o4, o5, o6, o7); |
parameter WID=32; |
input clk; |
input wr0; |
input wr1; |
input [6:0] wa0; |
input [6:0] wa1; |
input [WID-1:0] i0; |
input [WID-1:0] i1; |
input rclk; |
input [6:0] ra0; |
input [6:0] ra1; |
input [6:0] ra2; |
input [6:0] ra3; |
input [6:0] ra4; |
input [6:0] ra5; |
input [6:0] ra6; |
input [6:0] ra7; |
output [WID-1:0] o0; |
output [WID-1:0] o1; |
output [WID-1:0] o2; |
output [WID-1:0] o3; |
output [WID-1:0] o4; |
output [WID-1:0] o5; |
output [WID-1:0] o6; |
output [WID-1:0] o7; |
|
reg [WID-1:0] regs0 [0:127]; |
reg [WID-1:0] regs1 [0:127]; |
reg [6:0] rra0,rra1,rra2,rra3,rra4,rra5,rra6,rra7; |
|
reg whichreg [0:127]; // tracks which register file is the valid one for a given register |
|
// We only care about what's in the regs to begin with in simulation. In sim |
// the 'x' values propagate screwing things up. In real hardware there's no such |
// thing as an 'x'. |
`define SIMULATION |
`ifdef SIMULATION |
integer n; |
initial begin |
for (n = 0; n < 128; n = n + 1) |
begin |
regs0[n] = 0; |
regs1[n] = 0; |
whichreg[n] = 0; |
end |
end |
`endif |
|
|
assign o0 = |
(wr1 && (rra0==wa1)) ? i1 : |
(wr0 && (rra0==wa0)) ? i0 : |
whichreg[rra0]==1'b0 ? regs0[rra0] : regs1[rra0]; |
assign o1 = |
(wr1 && (rra1==wa1)) ? i1 : |
(wr0 && (rra1==wa0)) ? i0 : |
whichreg[rra1]==1'b0 ? regs0[rra1] : regs1[rra1]; |
assign o2 = |
(wr1 && (rra2==wa1)) ? i1 : |
(wr0 && (rra2==wa0)) ? i0 : |
whichreg[rra2]==1'b0 ? regs0[rra2] : regs1[rra2]; |
assign o3 = |
(wr1 && (rra3==wa1)) ? i1 : |
(wr0 && (rra3==wa0)) ? i0 : |
whichreg[rra3]==1'b0 ? regs0[rra3] : regs1[rra3]; |
assign o4 = |
(wr1 && (rra4==wa1)) ? i1 : |
(wr0 && (rra4==wa0)) ? i0 : |
whichreg[rra4]==1'b0 ? regs0[rra4] : regs1[rra4]; |
assign o5 = |
(wr1 && (rra5==wa1)) ? i1 : |
(wr0 && (rra5==wa0)) ? i0 : |
whichreg[rra5]==1'b0 ? regs0[rra5] : regs1[rra5]; |
assign o6 = |
(wr1 && (rra6==wa1)) ? i1 : |
(wr0 && (rra6==wa0)) ? i0 : |
whichreg[rra6]==1'b0 ? regs0[rra6] : regs1[rra6]; |
assign o7 = |
(wr1 && (rra7==wa1)) ? i1 : |
(wr0 && (rra7==wa0)) ? i0 : |
whichreg[rra7]==1'b0 ? regs0[rra7] : regs1[rra7]; |
|
always @(posedge clk) |
if (wr0) |
regs0[wa0] <= i0; |
|
always @(posedge clk) |
if (wr1) |
regs1[wa1] <= i1; |
|
always @(posedge rclk) rra0 <= ra0; |
always @(posedge rclk) rra1 <= ra1; |
always @(posedge rclk) rra2 <= ra2; |
always @(posedge rclk) rra3 <= ra3; |
always @(posedge rclk) rra4 <= ra4; |
always @(posedge rclk) rra5 <= ra5; |
always @(posedge rclk) rra6 <= ra6; |
always @(posedge rclk) rra7 <= ra7; |
|
always @(posedge clk) |
// writing three registers at once |
if (wr0 && wr1 && wa0==wa1) // Two ports writing the same address |
whichreg[wa0] <= 1'b1; // port one is the valid one |
// writing two registers |
else if (wr0 && wr1) begin |
whichreg[wa0] <= 1'b0; |
whichreg[wa1] <= 1'b1; |
end |
// writing a single register |
else if (wr0) |
whichreg[wa0] <= 1'b0; |
else if (wr1) |
whichreg[wa1] <= 1'b1; |
|
endmodule |
/trunk/rtl/verilog/Thor_divider.v
53,7 → 53,7
reg [2:0] state; |
reg [7:0] cnt; |
wire cnt_done = cnt==8'd0; |
assign done = state==DONE; |
assign done = state==DONE||(state==IDLE && !ld); |
assign idle = state==IDLE; |
reg ce1; |
reg [WID-1:0] q; |
77,6 → 77,7
qo <= {WID{1'b0}}; |
ro <= {WID{1'b0}}; |
cnt <= 8'd0; |
dvByZr <= 1'b0; |
state <= IDLE; |
end |
else |
/trunk/rtl/verilog/Thor_multiplier.v
1,6 → 1,6
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2013,2015 Robert Finch, Stratford |
// \\__/ o\ (C) 2013-2016 Robert Finch, Stratford |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
50,9 → 50,8
reg [2:0] state; |
reg [7:0] cnt; |
wire cnt_done = cnt==8'd0; |
assign done = state==DONE; |
assign done = state==DONE || (state==IDLE && !ld); // State == DONE |
assign idle = state==IDLE; |
reg ce1; |
reg [WID*2-1:0] prod; |
//wire [64:0] p1 = aa[0] ? prod[127:64] + b : prod[127:64]; |
//wire [65:0] p2 = aa[1] ? p1 + {b,1'b0} : p1; |
/trunk/rtl/verilog/Thor_regfile2w6r.v
29,17 → 29,17
input clk; |
input wr0; |
input wr1; |
input [5:0] wa0; |
input [5:0] wa1; |
input [7:0] wa0; |
input [7:0] wa1; |
input [WID-1:0] i0; |
input [WID-1:0] i1; |
input rclk; |
input [5:0] ra0; |
input [5:0] ra1; |
input [5:0] ra2; |
input [5:0] ra3; |
input [5:0] ra4; |
input [5:0] ra5; |
input [7:0] ra0; |
input [7:0] ra1; |
input [7:0] ra2; |
input [7:0] ra3; |
input [7:0] ra4; |
input [7:0] ra5; |
output [WID-1:0] o0; |
output [WID-1:0] o1; |
output [WID-1:0] o2; |
47,11 → 47,11
output [WID-1:0] o4; |
output [WID-1:0] o5; |
|
reg [WID-1:0] regs0 [0:63]; |
reg [WID-1:0] regs1 [0:63]; |
reg [5:0] rra0,rra1,rra2,rra3,rra4,rra5; |
reg [WID-1:0] regs0 [0:255]; |
reg [WID-1:0] regs1 [0:255]; |
reg [7:0] rra0,rra1,rra2,rra3,rra4,rra5; |
|
reg whichreg [0:63]; // tracks which register file is the valid one for a given register |
reg whichreg [0:255]; // tracks which register file is the valid one for a given register |
|
// We only care about what's in the regs to begin with in simulation. In sim |
// the 'x' values propagate screwing things up. In real hardware there's no such |
70,27 → 70,27
`endif |
|
|
assign o0 = rra0==6'd0 ? {WID{1'b0}} : |
assign o0 = rra0[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra0==wa1)) ? i1 : |
(wr0 && (rra0==wa0)) ? i0 : |
whichreg[rra0]==1'b0 ? regs0[rra0] : regs1[rra0]; |
assign o1 = rra1==6'd0 ? {WID{1'b0}} : |
assign o1 = rra1[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra1==wa1)) ? i1 : |
(wr0 && (rra1==wa0)) ? i0 : |
whichreg[rra1]==1'b0 ? regs0[rra1] : regs1[rra1]; |
assign o2 = rra2==6'd0 ? {WID{1'b0}} : |
assign o2 = rra2[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra2==wa1)) ? i1 : |
(wr0 && (rra2==wa0)) ? i0 : |
whichreg[rra2]==1'b0 ? regs0[rra2] : regs1[rra2]; |
assign o3 = rra3==6'd0 ? {WID{1'b0}} : |
assign o3 = rra3[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra3==wa1)) ? i1 : |
(wr0 && (rra3==wa0)) ? i0 : |
whichreg[rra3]==1'b0 ? regs0[rra3] : regs1[rra3]; |
assign o4 = rra4==6'd0 ? {WID{1'b0}} : |
assign o4 = rra4[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra4==wa1)) ? i1 : |
(wr0 && (rra4==wa0)) ? i0 : |
whichreg[rra4]==1'b0 ? regs0[rra4] : regs1[rra4]; |
assign o5 = rra5==6'd0 ? {WID{1'b0}} : |
assign o5 = rra5[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra5==wa1)) ? i1 : |
(wr0 && (rra5==wa0)) ? i0 : |
whichreg[rra5]==1'b0 ? regs0[rra5] : regs1[rra5]; |
/trunk/rtl/verilog/Thor_regfile2w6rA.v
0,0 → 1,124
`timescale 1ns / 1ps |
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2013-2016 Robert Finch, Stratford |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
// |
// This source file is free software: you can redistribute it and/or modify |
// it under the terms of the GNU Lesser General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or |
// (at your option) any later version. |
// |
// This source file is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// You should have received a copy of the GNU General Public License |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
// |
// |
// Register file with two write ports and six read ports. |
// ============================================================================ |
// |
module Thor_regfile2w6r(clk, clk2x, regset, wr0, wr1, wa0, wa1, i0, i1, |
rclk, ra0, ra1, ra2, ra3, ra4, ra5, o0, o1, o2, o3, o4, o5); |
parameter WID=64; |
input clk; |
input clk2x; |
input [2:0] regset; |
input wr0; |
input wr1; |
input [5:0] wa0; |
input [5:0] wa1; |
input [WID-1:0] i0; |
input [WID-1:0] i1; |
input rclk; |
input [5:0] ra0; |
input [5:0] ra1; |
input [5:0] ra2; |
input [5:0] ra3; |
input [5:0] ra4; |
input [5:0] ra5; |
output [WID-1:0] o0; |
output [WID-1:0] o1; |
output [WID-1:0] o2; |
output [WID-1:0] o3; |
output [WID-1:0] o4; |
output [WID-1:0] o5; |
|
reg [WID-1:0] regs [0:511]; |
reg [8:0] wa2; |
reg wr2; |
reg [WID-1:0] i2; |
wire [8:0] wa; |
wire wr; |
wire [WID-1:0] i; |
reg [8:0] rra0,rra1,rra2,rra3,rra4,rra5; |
|
// We only care about what's in the regs to begin with in simulation. In sim |
// the 'x' values propagate screwing things up. In real hardware there's no such |
// thing as an 'x'. |
`define SIMULATION |
`ifdef SIMULATION |
integer n; |
initial begin |
for (n = 0; n < 512; n = n + 1) |
begin |
regs[n] = 0; |
end |
end |
`endif |
|
|
assign o0 = rra0[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra0==wa1)) ? i1 : |
(wr0 && (rra0==wa0)) ? i0 : |
regs[rra0]; |
assign o1 = rra1[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra1==wa1)) ? i1 : |
(wr0 && (rra1==wa0)) ? i0 : |
regs[rra1]; |
assign o2 = rra2[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra2==wa1)) ? i1 : |
(wr0 && (rra2==wa0)) ? i0 : |
regs[rra2]; |
assign o3 = rra3[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra3==wa1)) ? i1 : |
(wr0 && (rra3==wa0)) ? i0 : |
regs[rra3]; |
assign o4 = rra4[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra4==wa1)) ? i1 : |
(wr0 && (rra4==wa0)) ? i0 : |
regs[rra4]; |
assign o5 = rra5[5:0]==6'd0 ? {WID{1'b0}} : |
(wr1 && (rra5==wa1)) ? i1 : |
(wr0 && (rra5==wa0)) ? i0 : |
regs[rra5]; |
|
always @(posedge clk) |
wa2 <= wa1; |
always @(posedge clk) |
wr2 <= wr1; |
always @(posedge clk) |
i2 <= i1; |
|
assign wa = clk ? wa2 : wa0; |
assign wr = clk ? wr2 : wr0; |
assign i = clk ? i2 : i0; |
|
always @(posedge clk2x) |
if (wr) begin |
regs[{regset,wa}] <= i; |
end |
|
always @(posedge rclk) rra0 <= {regset,ra0}; |
always @(posedge rclk) rra1 <= {regset,ra1}; |
always @(posedge rclk) rra2 <= {regset,ra2}; |
always @(posedge rclk) rra3 <= {regset,ra3}; |
always @(posedge rclk) rra4 <= {regset,ra4}; |
always @(posedge rclk) rra5 <= {regset,ra5}; |
|
endmodule |
/trunk/rtl/verilog/Thor_defines.v
1,6 → 1,6
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2013,2015 Robert Finch, Stratford |
// \\__/ o\ (C) 2013-2016 Robert Finch, Stratford |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
26,8 → 26,9
`ifndef THOR_DEFINES |
`define THOR_DEFINES 1'b1 |
|
`define SIMULATION 1'b1 |
`define SEGMENTATION 1'b1 |
//`define SIMULATION 1'b1 |
//`define SEGMENTATION 1'b1 |
//`define VECTOROPS 1'b1 |
//`define SEGLIMITS 1'b1 |
//`define STACKOPS 1'b1 |
//`define UNLINKOP 1'b1 |
68,7 → 69,8
`define MIN 6'h10 |
`define MAX 6'h11 |
`define MOD 6'h13 |
`define CHK 6'h14 |
`define CHKX 6'h14 |
`define CHK 6'h15 |
`define MODU 6'h17 |
`define R2 8'h41 |
`define CPUID 4'h0 |
84,6 → 86,7
`define PENOR 6'd5 |
`define PANDC 6'd6 |
`define PORC 6'd7 |
`define CHKI 8'h45 |
`define BITI 8'h46 |
`define ADDUIS 8'h47 |
`define ADDI 8'h48 |
107,6 → 110,33
`define ANDI 8'h53 |
`define ORI 8'h54 |
`define EORI 8'h55 |
`define VR 8'h56 |
`define VEX 6'h0 |
`define VEINS 6'h1 |
`define VSHLV 6'h2 |
`define VSHRV 6'h3 |
`define VFLT2INT 6'h4 |
`define VINT2FLT 6'h5 |
`define VBITS2V 6'h6 |
`define VRR 8'h57 |
`define VADD 5'h00 |
`define VSUB 5'h01 |
`define VMUL 5'h02 |
`define VDIV 5'h03 |
`define VSCALE 5'h05 |
`define VCMP 5'h06 |
`define VAND 5'h08 |
`define VOR 5'h09 |
`define VEOR 5'h0A |
`define VADDL 5'h10 |
`define VSUBL 5'h11 |
`define VMULL 5'h12 |
`define VDIVL 5'h13 |
`define VSCALEL 5'h15 |
`define VCMPL 5'h16 |
`define VANDL 5'h18 |
`define VORL 5'h19 |
`define VEORL 5'h1A |
|
`define SHIFT 8'h58 |
`define SHL 6'h00 |
121,11 → 151,12
`define SHRUI 6'h13 |
`define ROLI 6'h14 |
`define RORI 6'h15 |
`define MODI 8'h5B |
`define CHKI 8'h5D |
`define MODUI 8'h5F |
`define VMAC 8'h5A |
`define MODI 8'h5B |
`define CHKXI 8'h5D |
`define MODUI 8'h5F |
|
`define LLA 8'h6A // compute linear address |
`define LLA 8'h6A // compute linear address |
`define _2ADDUI 8'h6B |
`define _4ADDUI 8'h6C |
`define _8ADDUI 8'h6D |
182,11 → 213,11
`define LW 8'h86 |
`define LFS 8'h87 |
`define LFD 8'h88 |
`define LVWAR 8'h8B |
`define SWCR 8'h8C |
`define LVWAR 8'h8B |
`define SWCR 8'h8C |
`define JMPI 8'h8D |
`define LWS 8'h8E |
`define LCL 8'h8F |
`define LCL 8'h8F |
|
`define SB 8'h90 |
`define SC 8'h91 |
256,20 → 287,26
`define LHX 8'hB4 |
`define LHUX 8'hB5 |
`define LWX 8'hB6 |
`define JMPIX 8'hB7 |
`define LLAX 8'hB8 |
`define JMPIX 8'hB7 |
`define LLAX 8'hB8 |
`define LV 8'hBD |
`define LVWS 8'hBE |
`define LVX 8'hBF |
|
`define SBX 8'hC0 |
`define SCX 8'hC1 |
`define SHX 8'hC2 |
`define SWX 8'hC3 |
`define STIX 8'hC6 |
`define INC 8'hC7 |
`define PUSH 8'hC8 |
`define PEA 8'hC9 |
`define POP 8'hCA |
`define LINK 8'hCB |
`define UNLINK 8'hCC |
`define STIX 8'hC6 |
`define INC 8'hC7 |
`define PUSH 8'hC8 |
`define PEA 8'hC9 |
`define POP 8'hCA |
`define LINK 8'hCB |
`define UNLINK 8'hCC |
`define SV 8'hCD |
`define SVWS 8'hCE |
`define SVX 8'hCF |
|
`define TLB 8'hF0 |
`define TLB_NOP 4'd0 |
309,7 → 346,9
`define MEMDB 8'hF9 // data barrier |
`define CLI 8'hFA |
`define SEI 8'hFB |
`define RTD 8'hFC |
`define RTD 8'hFC |
`define RTF 8'hFD |
`define JSF 8'hFE |
`define IMM 8'hFF |
|
`define PREDC 3:0 |
320,6 → 359,7
`define INSTRUCTION_RA 21:16 |
`define INSTRUCTION_RB 27:22 |
`define INSTRUCTION_RC 33:28 |
`define INSTRUCTION_RD 39:34 |
|
`define XTBL 4'd12 |
`define EPC 4'd13 |
329,12 → 369,15
`define PREGS 6'h0x |
`define CREGS 6'h1x |
`define SREGS 6'h2x |
`define PREGS_ALL 6'h30 |
`define USP 6'h31 |
`define TICK 6'h32 |
`define LCTR 6'h33 |
`define ASID 6'h36 |
`define SR 6'h37 |
`define FPSCR 6'h38 |
`define PREGS_ALL 6'd52 |
`define ASID 6'd53 |
`define VL 6'd54 |
`define SR 6'h55 |
`define FPSCR 6'd56 |
`define ARG1 6'd58 |
`define CLK_THROTTLE 6'h3F |
|
// exception types: |
352,6 → 395,19
`define EXC_DBG 4'd11 |
`define EXC_PRIV 4'd12 |
`define EXC_CHK 4'd13 |
`define EXC_SEGLD 4'd14 |
|
`define EX_NONE 9'd000 |
`define EX_CHK 9'd239 |
`define EX_DBZ 9'd241 |
`define EX_FP 9'd242 |
`define EX_DBG 9'd243 |
`define EX_SEGV 9'd244 |
`define EX_PRIV 9'd245 |
`define EX_TLBMISS 9'd248 |
`define EX_DBE 9'd251 |
`define EX_SEGLD 9'd256 |
|
// |
// define PANIC types |
// |