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 12 to Rev 13
- ↔ Reverse comparison
Rev 12 → Rev 13
/trunk/rtl/verilog/Thor.v
105,8 → 105,10
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 |
parameter RSTADDR = 64'hFFFFFFFFFFFFEFF0; |
parameter RSTCSEG = 52'h0; |
parameter RSTPC = 64'hFFFFFFFFFFFFEFF0; |
parameter STARTUP_POWER = 16'hFFFF; |
parameter IMCD = 6'h3E; |
localparam AMSB = ABW-1; |
parameter QENTRIES = 8; |
parameter ALU1BIG = 0; |
161,8 → 163,8
integer n,i; |
reg [DBW/8-1:0] rsel; |
reg [3:0] cstate; |
reg [ABW+3:0] pc; // program counter (virtual) |
wire [DBW-1:0] ppc; // physical pc address |
reg [ABW:0] pc; // program counter (virtual) |
wire [ABW-1:0] ppc; // physical pc address |
reg [ABW-1:0] interrupt_pc; // working register for interrupt pc |
reg [DBW-1:0] vadr; // data virtual address |
reg [3:0] panic; // indexes the message structure |
170,7 → 172,7
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 [0:7]; // segment registers |
reg [DBW-1:12] sregs_lmt [0:7]; |
`endif |
reg [2:0] rrmapno; // register rename map number |
196,6 → 198,7
reg [NREGS:0] rf_v; |
//reg [15:0] pf_v; |
reg im,imb; |
reg [5:0] imcd; |
reg fxe; |
reg nmi1,nmi_edge; |
reg StatusHWI; |
210,8 → 213,8
wire sys_commit; |
wire dbg_commit; |
`ifdef SEGMENTATION |
wire [DBW-1:0] spc = (pc[ABW+3:ABW]==4'hF) ? pc[ABW-1:0] : |
(pc[ABW-1:ABW-4]==4'hF) ? pc[ABW-1:0] : {sregs[7],12'h000} + pc[ABW-1:0]; |
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]; |
`else |
wire [DBW-1:0] spc = pc; |
`endif |
236,6 → 239,7
reg iqentry_done [0:7]; // instruction result valid |
reg [7:0] iqentry_cmt; // commit result to machine state |
reg iqentry_bt [0:7]; // branch-taken (used only for branches) |
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_ndx [0:7]; // TRUE if indexed memory op |
243,9 → 247,13
reg iqentry_pushpop [0:7]; |
reg iqentry_pea [0:7]; |
reg iqentry_cmpmv [0:7]; |
reg iqentry_lla [0:7]; // load linear address |
reg iqentry_tlb [0:7]; |
reg iqentry_jmp [0:7]; // changes control flow: 1 if BEQ/JALR |
reg iqentry_jmpi [0:7]; |
reg iqentry_sync [0:7]; // sync instruction |
reg iqentry_memsb[0:7]; |
reg iqentry_memdb[0:7]; |
reg iqentry_fp [0:7]; // is an floating point operation |
reg iqentry_rfw [0:7]; // writes to register file |
reg [DBW-1:0] iqentry_res [0:7]; // instruction result |
421,7 → 429,7
wire [3:0] alu0_exc; |
reg alu0_v; |
wire alu0_branchmiss; |
reg [ABW+3:0] alu0_misspc; |
reg [ABW:0] alu0_misspc; |
|
reg alu1_ld; |
reg alu1_available; |
445,7 → 453,7
wire [3:0] alu1_exc; |
reg alu1_v; |
wire alu1_branchmiss; |
reg [ABW+3:0] alu1_misspc; |
reg [ABW:0] alu1_misspc; |
|
wire jmpi_miss; |
reg [ABW-1:0] jmpi_misspc; |
452,7 → 460,7
wire mem_stringmissx; |
reg mem_stringmiss; |
wire branchmiss; |
wire [ABW+3:0] misspc; |
wire [ABW:0] misspc; |
|
`ifdef FLOATING_POINT |
reg fp0_ld; |
636,8 → 644,8
wire dbg_stat2 = dbg_imatchA2 | dbg_imatchB2 | dbg_lmatch2 | dbg_smatch2; |
wire dbg_stat3 = dbg_imatchA3 | dbg_imatchB3 | dbg_lmatch3 | dbg_smatch3; |
assign dbg_stat1x = {dbg_stat3,dbg_stat2,dbg_stat1,dbg_stat0}; |
wire debug_on = |dbg_ctrl[3:0]|dbg_ctrl[7]; |
|
|
reg [11:0] spr_bir; |
|
// |
935,8 → 943,7
function [7:0] fnOpcode; |
input [63:0] ins; |
fnOpcode = (ins[3:0]==4'h0 && ins[7:4] > 4'h1 && ins[7:4] < 4'h9) ? `IMM : |
ins[7:0]==8'h10 ? `NOP : |
ins[7:0]==8'h11 ? `RTS : ins[15:8]; |
ins[7:0]==8'h10 ? `NOP : ins[15:8]; |
endfunction |
|
wire [7:0] opcode0 = fnOpcode(fetchbuf0_instr); |
950,14 → 957,12
|
function [6:0] fnRa; |
input [63:0] isn; |
case(isn[7:0]) |
8'h11: fnRa = 7'h51; // RTS short form |
default: |
case(isn[15:8]) |
`RTS2: fnRa = 7'h51; |
`RTI: fnRa = 7'h5E; |
`RTD: fnRa = 7'h5B; |
`RTE: fnRa = 7'h5D; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2: |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS: |
fnRa = {3'h5,isn[23:20]}; |
`TLB: fnRa = {1'b0,isn[29:24]}; |
`P: fnRa = 7'h70; |
969,16 → 974,11
`MFSPR,`MOVS: fnRa = {1'b1,isn[`INSTRUCTION_RA]}; |
default: fnRa = {1'b0,isn[`INSTRUCTION_RA]}; |
endcase |
endcase |
endfunction |
|
function [6:0] fnRb; |
input [63:0] isn; |
if (isn[7:0]==8'h11) // RTS short form |
fnRb = 7'h51; |
else |
case(isn[15:8]) |
`RTS2: fnRb = km ? 7'd31 : 7'd27; |
// `LOOP: fnRb = 7'h73; |
// `RTS,`STP,`TLB,`POP: fnRb = 7'd0; |
`JSR,`JSRS,`JSRZ,`SYS,`INT: |
1000,14 → 1000,12
|
function [3:0] fnCar; |
input [63:0] isn; |
if (isn[7:0]==8'h11) // RTS short form |
fnCar = 4'h1; |
else |
case(isn[15:8]) |
`RTS2: fnCar = 4'h1; |
`RTI: fnCar = 4'hE; |
`RTD: fnCar = 4'hB; |
`RTE: fnCar = 4'hD; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2: |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS: |
fnCar = {isn[23:20]}; |
default: fnCar = 4'h0; |
endcase |
1015,9 → 1013,6
|
function [5:0] fnFunc; |
input [63:0] isn; |
if (isn[7:0]==8'h11) // RTS short form |
fnFunc = 6'h00; // func is used as a small immediate |
else |
case(isn[15:8]) |
`BITFIELD: fnFunc = isn[43:40]; |
`R: fnFunc = isn[31:28]; |
1058,7 → 1053,7
8'h0F: fnFunc = isn[23:22]; |
`INC: fnFunc = isn[24:22]; |
`TLB: fnFunc = isn[19:16]; |
`RTS,`RTS2: fnFunc = isn[19:16]; // used to pass a small immediate |
`RTS: fnFunc = isn[19:16]; // used to pass a small immediate |
`CACHE: fnFunc = isn[31:26]; |
`PUSH,`PEA: fnFunc = km ? 6'b0 : 6'b110000; // select segment register #6 |
`JMPI: fnFunc = {isn[39:37],1'b0,isn[27:26]}; |
1082,11 → 1077,13
`RR: |
case(func) |
`DIV,`DIVU: fnIsAlu0Op = `TRUE; |
`MOD,`MODU: fnIsAlu0Op = `TRUE; |
`MIN,`MAX: fnIsAlu0Op = `TRUE; |
default: fnIsAlu0Op = `FALSE; |
endcase |
`BCD: fnIsAlu0Op = `TRUE; |
`DIVI,`DIVUI: fnIsAlu0Op = `TRUE; |
`MODI,`MODUI: fnIsAlu0Op = `TRUE; |
//`DOUBLE: fnIsAlu0Op = `TRUE; |
`SHIFT: fnIsAlu0Op = `TRUE; |
`BITFIELD: fnIsAlu0Op = `TRUE; |
1103,10 → 1100,10
`R: fnAluValid = `TRUE; |
`RR: |
case(func) |
`MUL,`MULU,`DIV,`DIVU: fnAluValid = `FALSE; |
`MUL,`MULU,`DIV,`DIVU,`MOD,`MODU: fnAluValid = `FALSE; |
default: fnAluValid = `TRUE; |
endcase |
`MULI,`MULUI,`DIVI,`DIVUI: fnAluValid = `FALSE; |
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI: fnAluValid = `FALSE; |
default: fnAluValid = `TRUE; |
endcase |
endfunction |
1115,8 → 1112,8
( |
.clk(clk), |
.rclk(~clk), |
.wr0(commit0_v && ~commit0_tgt[6] && iqentry_op[head0]!=`MTSPR), |
.wr1(commit1_v && ~commit1_tgt[6] && iqentry_op[head1]!=`MTSPR), |
.wr0(commit0_v && ~commit0_tgt[6]), |
.wr1(commit1_v && ~commit1_tgt[6]), |
.wa0(commit0_tgt[5:0]), |
.wa1(commit1_tgt[5:0]), |
.ra0(pRa0[5:0]), |
1222,7 → 1219,7
8'h3D: fnSource2_v = 1'b1; |
8'h3E: fnSource2_v = 1'b1; |
8'h3F: fnSource2_v = 1'b1; |
`MULI,`MULUI,`DIVI,`DIVUI: |
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI: |
fnSource2_v = 1'b1; |
`ANDI,`BITI: fnSource2_v = 1'b1; |
`ORI: fnSource2_v = 1'b1; |
1232,11 → 1229,11
fnSource2_v = `TRUE; |
else |
fnSource2_v = `FALSE; |
`CACHE,`LCL,`TLB, |
`CACHE,`LCL,`TLB,`LLA, |
`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: |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2: |
fnSource2_v = 1'b1; |
`MTSPR,`MFSPR,`POP,`UNLINK: |
fnSource2_v = 1'b1; |
1296,7 → 1293,7
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI: |
fnNumReadPorts = 3'd1; |
`SUBI,`SUBUI: fnNumReadPorts = 3'd1; |
`MULI,`MULUI,`DIVI,`DIVUI: |
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI: |
fnNumReadPorts = 3'd1; |
`BITI, |
`ANDI,`ORI,`EORI: fnNumReadPorts = 3'd1; |
1305,10 → 1302,10
fnNumReadPorts = 3'd1; |
else |
fnNumReadPorts = 3'd2; |
`RTS2,`CACHE,`LCL,`TLB, |
`CACHE,`LCL,`TLB,`LLA, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,`LWS,`INC: |
fnNumReadPorts = 3'd1; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`BR: |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2,`BR: |
fnNumReadPorts = 3'd1; |
`SBX,`SCX,`SHX,`SWX, |
`MUX,`CAS,`STMV,`STCMP: |
1357,15 → 1354,29
opcode==`STS; |
endfunction |
|
wire xbr = (iqentry_op[head0][7:4]==`BR) || (iqentry_op[head1][7:4]==`BR); |
wire takb = (iqentry_op[head0][7:4]==`BR) ? commit0_v : commit1_v; |
wire [DBW-1:0] xbrpc = (iqentry_op[head0][7:4]==`BR) ? iqentry_pc[head0] : iqentry_pc[head1]; |
reg [DBW-1:0] branch_pc; |
wire xbr = iqentry_br[head0] | iqentry_br[head1]; |
wire takb = iqentry_br[head0] ? commit0_v : commit1_v; |
wire [DBW-1:0] xbrpc = iqentry_br[head0] ? iqentry_pc[head0] : iqentry_pc[head1]; |
|
wire predict_takenA,predict_takenB,predict_takenC,predict_takenD; |
wire predict_taken0; |
wire predict_taken1; |
|
// There are really only two branch tables required one for fetchbuf0 and one |
// for fetchbuf1. Synthesis removes the extra tables. |
// This is really just a single history table with three read ports. |
// One for fetchbuf0, one for fetchbuf1 and one for the branch_pc. |
// Ideally, there really needs to be two write ports as well (for |
// head0 and head1). |
// There is only a single write port for branches committing at |
// head0 or head1. If there are two branches one after the other |
// in code, then the prediction will be off because the taken/ |
// not taken status for the second branch won't be updated. It |
// doesn't happen that often that branches are piled together and |
// executing during the same clock cycle. |
// There's usually at least an intervening compare operation. |
// Needs more work yet. |
// |
// ToDo: add return address stack predictor. |
// |
Thor_BranchHistory #(DBW) ubhtA |
( |
.rst(rst_i), |
1372,10 → 1383,10
.clk(clk), |
.advanceX(xbr), |
.xisBranch(xbr), |
.pc(pc), |
.pc(branch_pc), |
.xpc(xbrpc), |
.takb(takb), |
.predict_taken(predict_takenA) |
.predict_taken(predict_takenBr) |
); |
|
Thor_BranchHistory #(DBW) ubhtB |
1384,10 → 1395,10
.clk(clk), |
.advanceX(xbr), |
.xisBranch(xbr), |
.pc(pc+fnInsnLength(insn)), |
.pc(fetchbuf0_pc), |
.xpc(xbrpc), |
.takb(takb), |
.predict_taken(predict_takenB) |
.predict_taken(predict_taken0) |
); |
|
Thor_BranchHistory #(DBW) ubhtC |
1396,6 → 1407,19
.clk(clk), |
.advanceX(xbr), |
.xisBranch(xbr), |
.pc(fetchbuf1_pc), |
.xpc(xbrpc), |
.takb(takb), |
.predict_taken(predict_taken1) |
); |
|
/* |
Thor_BranchHistory #(DBW) ubhtC |
( |
.rst(rst_i), |
.clk(clk), |
.advanceX(xbr), |
.xisBranch(xbr), |
.pc(pc), |
.xpc(xbrpc), |
.takb(takb), |
1413,6 → 1437,20
.takb(takb), |
.predict_taken(predict_takenD) |
); |
*/ |
`ifdef PCHIST |
wire [63:0] pc_histo; |
reg pc_cap; |
reg [5:0] pc_ndx; |
vtdl #(.WID(64),.DEP(64)) uvtl1 |
( |
.clk(clk), |
.ce(pc_cap), |
.a(pc_ndx), |
.d({fetchbuf1_pc,fetcbuf0_pc}), |
.q(pc_histo) |
); |
`endif |
|
Thor_icachemem #(DBW) uicm1 |
( |
1561,9 → 1599,10
`SHIFT: |
fnTargetReg = {1'b0,ir[33:28]}; |
`R,`R2,`DOUBLE_R,`SINGLE_R, |
`ADDI,`ADDUI,`SUBI,`SUBUI,`MULI,`MULUI,`DIVI,`DIVUI, |
`ADDI,`ADDUI,`SUBI,`SUBUI, |
`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI, |
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI, |
`ANDI,`ORI,`EORI, |
`ANDI,`ORI,`EORI,`LLA, |
`LVB,`LVC,`LVH,`LVW,`LVWAR, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LINK: |
fnTargetReg = {1'b0,ir[27:22]}; |
1617,7 → 1656,7
else |
fnTargetReg = 7'h00; |
*/ |
`RTS2,`PUSH: fnTargetReg = km ? 7'd31 : 7'd27; |
`PUSH: fnTargetReg = km ? 7'd31 : 7'd27; |
`LOOP: fnTargetReg = 7'h73; |
`STP: fnTargetReg = 7'h7F; |
`P: fnTargetReg = 7'h70; |
1695,7 → 1734,7
case(opcode) |
`BFCLR,`BFSET,`BFCHG,`BFEXT,`BFEXTU,`BFINS, |
`LDI,`LDIS,`ADDUIS, |
`ADDI,`SUBI,`ADDUI,`SUBUI,`MULI,`MULUI,`DIVI,`DIVUI, |
`ADDI,`SUBI,`ADDUI,`SUBUI,`MULI,`MULUI,`DIVI,`DIVUI,`MODI,`MODUI, |
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI, |
// CMPI |
8'h20,8'h21,8'h22,8'h23, |
1712,8 → 1751,8
`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, |
`JSR,`JSRS,`SYS,`INT,`RTS2,`LOOP,`PEA,`LINK,`UNLINK: |
`RTI,`RTD,`RTE,`LLA, |
`JSR,`JSRS,`SYS,`INT,`LOOP,`PEA,`LINK,`UNLINK: |
fnHasConst = 1'b1; |
default: |
fnHasConst = 1'b0; |
1738,12 → 1777,21
endfunction |
|
// fnCanException |
// |
// Used by memory issue logic. |
// Returns TRUE if the instruction can cause an exception |
// Returns TRUE if the instruction can cause an exception. |
// In debug mode any instruction could potentially cause a breakpoint exception. |
// Rather than check all the addresses for potential debug exceptions it's |
// simpler to just have it so that all instructions could exception. This will |
// slow processing down somewhat as stores will only be done at the head of the |
// instruction queue, but it's debug mode so we probably don't care. |
// |
function fnCanException; |
input [7:0] op; |
input [5:0] func; |
if (debug_on) |
fnCanException = `TRUE; |
else |
case(op) |
`FLOAT: |
case(func) |
1755,8 → 1803,13
`SINGLE_R: |
if (func==`FTX) fnCanException = `TRUE; |
else fnCanException = `FALSE; |
`ADD,`ADDI,`SUB,`SUBI,`DIV,`DIVI,`MUL,`MULI: |
`ADDI,`SUBI,`DIVI,`MODI,`MULI: |
fnCanException = `TRUE; |
`RR: |
if (func==`ADD || func==`SUB || func==`MUL || func==`DIV || func==`MOD) |
fnCanException = `TRUE; |
else |
fnCanException = `FALSE; |
`TLB,`RTI,`RTD,`RTE,`CLI,`SEI: |
fnCanException = `TRUE; |
default: |
1780,14 → 1833,13
8'b01100000: fnInsnLength = 4'd6; |
8'b01110000: fnInsnLength = 4'd7; |
8'b10000000: fnInsnLength = 4'd8; |
8'b00010001: fnInsnLength = 4'd1; // RTS short form |
default: |
case(isn[15:8]) |
`NOP,`SEI,`CLI,`RTI,`RTD,`RTE,`MEMSB,`MEMDB,`SYNC: |
`NOP,`SEI,`CLI,`RTI,`RTD,`RTE,`RTS2,`MEMSB,`MEMDB,`SYNC: |
fnInsnLength = 4'd2; |
`JSRZ,`RTS,`CACHE,`LOOP,`PUSH,`POP,`UNLINK: |
fnInsnLength = 4'd3; |
`SYS,`MTSPR,`MFSPR,`LDI,`LDIS,`ADDUIS,`R,`TLB,`MOVS,`RTS2,`STP: |
`SYS,`MTSPR,`MFSPR,`LDI,`LDIS,`ADDUIS,`R,`TLB,`MOVS,`STP: |
fnInsnLength = 4'd4; |
`BITFIELD,`JSR,`MUX,`BCD,`INC: |
fnInsnLength = 4'd6; |
1869,10 → 1921,10
fetchbuf1_pc <= (fetchbuf == 1'b0) ? fetchbufB_pc : fetchbufD_pc ; |
end |
|
wire [7:0] opcodeA = fetchbufA_instr[`OPCODE]; |
wire [7:0] opcodeB = fetchbufB_instr[`OPCODE]; |
wire [7:0] opcodeC = fetchbufC_instr[`OPCODE]; |
wire [7:0] opcodeD = fetchbufD_instr[`OPCODE]; |
wire [7:0] opcodeA = fnOpcode(fetchbufA_instr); |
wire [7:0] opcodeB = fnOpcode(fetchbufB_instr); |
wire [7:0] opcodeC = fnOpcode(fetchbufC_instr); |
wire [7:0] opcodeD = fnOpcode(fetchbufD_instr); |
|
function fnIsMem; |
input [7:0] opcode; |
1890,14 → 1942,6
; |
endfunction |
|
function fnIsNdxd; |
input [7:0] opcode; |
fnIsNdxd = opcode==`LBX || opcode==`LWX || opcode==`LBUX || opcode==`LHX || opcode==`LHUX || opcode==`LCX || opcode==`LCUX || |
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX || |
opcode==`JMPIX |
; |
endfunction |
|
// Determines which instruction write to the register file |
function fnIsRFW; |
input [7:0] opcode; |
1907,19 → 1951,21
opcode==`LB || opcode==`LBU || opcode==`LC || opcode==`LCU || opcode==`LH || opcode==`LHU || opcode==`LW || |
opcode==`LBX || opcode==`LBUX || opcode==`LCX || opcode==`LCUX || opcode==`LHX || opcode==`LHUX || opcode==`LWX || |
opcode==`LVB || opcode==`LVH || opcode==`LVC || opcode==`LVW || opcode==`LVWAR || opcode==`SWCR || |
opcode==`RTS2 || opcode==`STP || |
opcode==`STP || opcode==`LLA || opcode==`LLAX || |
opcode==`CAS || opcode==`LWS || opcode==`STMV || opcode==`STCMP || opcode==`STFND || |
opcode==`STS || opcode==`PUSH || opcode==`POP || opcode==`LINK || opcode==`UNLINK || |
opcode==`JMPI || opcode==`JMPIX || |
opcode==`ADDI || opcode==`SUBI || opcode==`ADDUI || opcode==`SUBUI || opcode==`MULI || opcode==`MULUI || opcode==`DIVI || opcode==`DIVUI || |
opcode==`ADDI || opcode==`SUBI || opcode==`ADDUI || opcode==`SUBUI || |
opcode==`MULI || opcode==`MULUI || opcode==`DIVI || opcode==`DIVUI || opcode==`MODI || opcode==`MODUI || |
opcode==`_2ADDUI || opcode==`_4ADDUI || opcode==`_8ADDUI || opcode==`_16ADDUI || |
opcode==`ANDI || opcode==`ORI || opcode==`EORI || |
opcode==`ADD || opcode==`SUB || opcode==`ADDU || opcode==`SUBU || opcode==`MUL || opcode==`MULU || opcode==`DIV || opcode==`DIVU || |
opcode==`AND || opcode==`OR || opcode==`EOR || opcode==`NAND || opcode==`NOR || opcode==`ENOR || opcode==`ANDC || opcode==`ORC || |
opcode==`SHIFT || |
opcode==`R || opcode==`RR || opcode==`P || opcode==`LOOP || |
opcode==`SHIFT || opcode==`LOGIC || |
opcode==`R || opcode==`R2 || opcode==`RR || opcode==`P || opcode==`LOOP || |
opcode==`BITI || opcode==`CMP || opcode==`CMPI || opcode==`TST || |
opcode==`LDI || opcode==`LDIS || opcode==`ADDUIS || opcode==`MFSPR || |
`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 || |
1972,9 → 2018,9
input [5:0] fn; |
casex(op) |
8'h40: |
if (fn > 6'h11) |
if (fn > 6'h17) |
fnIsIllegal = `TRUE; |
else if (fn==6'hC || fn==6'hD || fn==6'hE || fn==6'hF) |
else if (fn==6'hC || fn==6'hD || fn==6'hE || fn==6'hF || fn==6'h12 || fn==6'h14 || fn==6'h15 || fn==6'h16) |
fnIsIllegal = `TRUE; |
else fnIsIllegal = `FALSE; |
8'h41: |
2017,9 → 2063,9
else |
fnIsIllegal = `FALSE; |
8'h43,8'h44,8'h45: fnIsIllegal = `TRUE; |
8'h52,8'h56,8'h57,8'h59,8'h5A,8'h5B,8'h5C,8'h5D,8'h5E,8'h5F: |
8'h52,8'h56,8'h57,8'h59,8'h5A,8'h5C,8'h5D,8'h5E: |
fnIsIllegal = `TRUE; |
8'h60,8'h61,8'h62,8'h63,8'h64,8'h65,8'h66,8'h67,8'h68,8'h69,8'h6A: |
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; |
2027,7 → 2073,7
fnIsIllegal = `TRUE; |
8'h94,8'h95,8'h9C: |
fnIsIllegal = `TRUE; |
8'b10111xxx: |
8'hB9,8'hBA,8'hBB,8'hBC,8'hBD,8'hBE,8'hBF: |
fnIsIllegal = `TRUE; |
8'hC4,8'hC5,8'b11001xxx: |
fnIsIllegal = `TRUE; |
2392,19 → 2438,17
endcase |
endfunction |
|
assign fetchbuf0_mem = fetchbuf ? fnIsMem(opcodeC) : fnIsMem(opcodeA); |
assign fetchbuf0_mem = fnIsMem(opcode0); |
assign fetchbuf0_jmp = fnIsFlowCtrl(opcode0); |
assign fetchbuf0_fp = fnIsFP(opcode0); |
assign fetchbuf0_rfw = fetchbuf ? fnIsRFW(opcodeC,fetchbufC_instr) : fnIsRFW(opcodeA,fetchbufA_instr); |
assign fetchbuf0_pfw = fetchbuf ? fnIsPFW(opcodeC) : fnIsPFW(opcodeA); |
assign fetchbuf1_mem = fetchbuf ? fnIsMem(opcodeD) : fnIsMem(opcodeB); |
assign fetchbuf0_rfw = fnIsRFW(opcode0,fetchbuf0_instr); |
assign fetchbuf0_pfw = fnIsPFW(opcode0); |
assign fetchbuf1_mem = fnIsMem(opcode1); |
assign fetchbuf1_jmp = fnIsFlowCtrl(opcode1); |
assign fetchbuf1_fp = fnIsFP(opcode1); |
assign fetchbuf1_rfw = fetchbuf ? fnIsRFW(opcodeD,fetchbufD_instr) : fnIsRFW(opcodeB,fetchbufB_instr); |
assign fetchbuf1_pfw = fetchbuf ? fnIsPFW(opcodeD) : fnIsPFW(opcodeB); |
assign fetchbuf1_rfw = fnIsRFW(opcode1,fetchbuf1_instr); |
assign fetchbuf1_pfw = fnIsPFW(opcode1); |
|
wire predict_taken0 = fetchbuf ? predict_takenC : predict_takenA; |
wire predict_taken1 = fetchbuf ? predict_takenD : predict_takenB; |
// |
// set branchback and backpc values ... ignore branches in fetchbuf slots not ready for enqueue yet |
// |
2417,10 → 2461,6
assign take_branch = take_branch0 || take_branch1 |
; |
|
reg [DBW-1:0] branch_pc;// = |
// ({fetchbuf0_v, fnIsBranch(opcode0), predict_taken0} == {`VAL, `TRUE, `TRUE}) ? (ihit ? |
// fetchbuf0_pc + {{DBW-12{fetchbuf0_instr[11]}},fetchbuf0_instr[11:8],fetchbuf0_instr[23:16]} + 64'd3 : fetchbuf0_pc): |
// (ihit ? fetchbuf1_pc + {{DBW-12{fetchbuf1_instr[11]}},fetchbuf1_instr[11:8],fetchbuf1_instr[23:16]} + 64'd3 : fetchbuf1_pc); |
always @* |
if (fnIsBranch(opcode0) && fetchbuf0_v && predict_taken0) begin |
branch_pc <= fetchbuf0_pc + {{ABW-12{fetchbuf0_instr[11]}},fetchbuf0_instr[11:8],fetchbuf0_instr[23:16]} + 64'd3; |
2435,13 → 2475,13
branch_pc <= fetchbuf1_pc + {{ABW-8{fetchbuf1_instr[23]}},fetchbuf1_instr[23:16]} + 64'd3; |
end |
else begin |
branch_pc <= RSTADDR; // set to something to prevent a latch |
branch_pc <= RSTPC; // set to something to prevent a latch |
end |
|
assign int_pending = (nmi_edge & ~StatusHWI & ~int_commit) || (irq_i & ~im & ~StatusHWI & ~int_commit); |
|
assign mem_stringmissx = ((dram0_op==`STS || dram0_op==`STFND) && int_pending && lc != 0) || |
((dram0_op==`STMV || dram0_op==`STCMP) && int_pending && lc != 0 && stmv_flag); |
assign mem_stringmissx = ((dram0_op==`STS || dram0_op==`STFND) && int_pending && lc != 0 && !mem_stringmiss) || |
((dram0_op==`STMV || dram0_op==`STCMP) && int_pending && lc != 0 && !mem_stringmiss && stmv_flag); |
|
assign jmpi_miss = dram_v && (dram0_op==`JMPI || dram0_op==`JMPIX); |
|
2522,10 → 2562,6
// Return the immediate field of an instruction |
function [63:0] fnImm; |
input [127:0] insn; |
case(insn[7:0]) |
8'b00010001: // RTS short form |
fnImm = 64'd0; |
default: |
case(insn[15:8]) |
`P: fnImm = insn[33:16]; |
`CAS: fnImm = {{56{insn[47]}},insn[47:40]}; |
2536,8 → 2572,7
`JSR: fnImm = {{40{insn[47]}},insn[47:24]}; |
`JSRS: fnImm = {{48{insn[39]}},insn[39:24]}; |
`BITFIELD: fnImm = insn[47:32]; |
`SYS,`INT: fnImm = insn[31:24]; |
`RTS2: fnImm = {insn[31:27],3'b000}; |
`SYS,`INT: fnImm = {insn[31:24],4'h0}; |
//`CMPI, |
8'h20,8'h21,8'h22,8'h23, |
8'h24,8'h25,8'h26,8'h27, |
2546,11 → 2581,11
`LDI,`LDIS,`ADDUIS: |
fnImm = {{54{insn[31]}},insn[31:22]}; |
`RTS: fnImm = insn[19:16]; |
`RTD,`RTE,`RTI,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS: fnImm = 64'h0; |
`RTD,`RTE,`RTI,`RTS2,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS: fnImm = 64'h0; |
`STI: fnImm = {{58{insn[33]}},insn[33:28]}; |
`PUSH: fnImm = 64'hFFFFFFFFFFFFFFF8; //-8 |
//`LINK: fnImm = {insn[39:28],3'b000}; |
`JMPI, |
`JMPI,`LLA, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR, |
`SB,`SC,`SH,`SW,`SWCR,`LWS,`SWS,`INC,`LCL,`PEA: |
fnImm = {{55{insn[36]}},insn[36:28]}; |
2557,15 → 2592,11
default: |
fnImm = {{52{insn[39]}},insn[39:28]}; |
endcase |
endcase |
|
endfunction |
|
function [7:0] fnImm8; |
input [127:0] insn; |
if (insn[7:0]==8'h11) |
fnImm8 = 8'h00; |
else |
case(insn[15:8]) |
`CAS: fnImm8 = insn[47:40]; |
`BCD: fnImm8 = insn[47:40]; |
2572,9 → 2603,9
`TLB: fnImm8 = insn[23:16]; |
`LOOP: fnImm8 = insn[23:16]; |
`STP: fnImm8 = insn[23:16]; |
`JSR,`JSRS,`RTS2: fnImm8 = insn[31:24]; |
`JSR,`JSRS: fnImm8 = insn[31:24]; |
`BITFIELD: fnImm8 = insn[39:32]; |
`SYS,`INT: fnImm8 = insn[31:24]; |
`SYS,`INT: fnImm8 = {insn[27:24],4'h0}; |
//`CMPI, |
8'h20,8'h21,8'h22,8'h23, |
8'h24,8'h25,8'h26,8'h27, |
2582,13 → 2613,13
8'h2C,8'h2D,8'h2E,8'h2F, |
`LDI,`LDIS,`ADDUIS: fnImm8 = insn[29:22]; |
`RTS: fnImm8 = insn[19:16]; |
`RTD,`RTE,`RTI,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS: fnImm8 = 8'h00; |
`RTD,`RTE,`RTI,`RTS2,`JSRZ,`STMV,`STCMP,`STFND,`CACHE,`STS: fnImm8 = 8'h00; |
`STI: fnImm8 = insn[35:28]; |
`PUSH: fnImm8 = 8'hF8; |
`ifdef STACKOPS |
`LINK: fnImm8 = {insn[32:28],3'b000}; |
`endif |
`JMPI, |
`JMPI,`LLA, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR, |
`SB,`SC,`SH,`SW,`SWCR,`LWS,`SWS,`INC,`LCL,`PEA: |
fnImm8 = insn[35:28]; |
2599,9 → 2630,6
// Return MSB of immediate value for instruction |
function fnImmMSB; |
input [127:0] insn; |
if (insn[7:0]==8'h11) |
fnImmMSB = 1'b0; |
else |
case(insn[15:8]) |
`CAS: fnImmMSB = insn[47]; |
`TLB,`BCD,`STP: |
2627,7 → 2655,7
`LBX,`LBUX,`LCX,`LCUX,`LHX,`LHUX,`LWX, |
`SBX,`SCX,`SHX,`SWX: |
fnImmMSB = insn[47]; |
`JMPI, |
`JMPI,`LLA, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW, |
`SB,`SC,`SH,`SW,`SWCR,`STI,`LWS,`SWS,`INC,`LCL,`PEA: |
fnImmMSB = insn[36]; |
2706,16 → 2734,24
// Returns TRUE if instruction is only allowed in kernel mode. |
function fnIsKMOnly; |
input [7:0] op; |
`ifdef PRIVCHKS |
fnIsKMOnly = op==`RTI || op==`RTE || op==`RTD || op==`TLB || op==`CLI || op==`SEI || |
op==`STP |
; |
`else |
fnIsKMOnly = `FALSE; |
`endif |
endfunction |
|
function fnIsKMOnlyReg; |
input [6: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 || |
regx==7'h60 || regx==7'h68; |
`else |
fnIsKMOnlyReg = `FALSE; |
`endif |
endfunction |
|
// Returns TRUE if the register is automatically valid. |
2835,6 → 2871,8
// The (old) simulator didn't handle the asynchronous race loop properly in the |
// original code. It would issue two instructions to the same islot. So the |
// issue logic has been re-written to eliminate the asynchronous loop. |
// Can't issue to the ALU if it's busy doing a long running operation like a |
// divide. |
always @*//(could_issue or head0 or head1 or head2 or head3 or head4 or head5 or head6 or head7) |
begin |
iqentry_issue = 8'h00; |
2846,70 → 2884,70
iqentry_islot[5] = 2'b00; |
iqentry_islot[6] = 2'b00; |
iqentry_islot[7] = 2'b00; |
if (could_issue[head0] & !iqentry_fp[head0]) begin |
if (could_issue[head0] & !iqentry_fp[head0] & alu0_idle) begin |
iqentry_issue[head0] = `TRUE; |
iqentry_islot[head0] = 2'b00; |
end |
else if (could_issue[head1] & !iqentry_fp[head1] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC)) |
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] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
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] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
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] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
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] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`SYNC) |
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] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`SYNC) |
&& !(iqentry_v[head5] && iqentry_op[head5]==`SYNC) |
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] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`SYNC) |
&& !(iqentry_v[head5] && iqentry_op[head5]==`SYNC) |
&& !(iqentry_v[head6] && iqentry_op[head6]==`SYNC) |
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; |
2917,73 → 2955,73
|
// Don't bother checking head0, it should have issued to the first |
// instruction. |
if (could_issue[head1] && !iqentry_fp[head1] && !iqentry_issue[head1] |
if (could_issue[head1] && !iqentry_fp[head1] && !iqentry_issue[head1] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head1],iqentry_fn[head1]) |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC)) |
&& !(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] |
else if (could_issue[head2] && !iqentry_fp[head2] && !iqentry_issue[head2] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head2],iqentry_fn[head2]) |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(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] |
else if (could_issue[head3] & !iqentry_fp[head3] && !iqentry_issue[head3] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head3],iqentry_fn[head3]) |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(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] |
else if (could_issue[head4] & !iqentry_fp[head4] && !iqentry_issue[head4] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head4],iqentry_fn[head4]) |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(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] |
else if (could_issue[head5] & !iqentry_fp[head5] && !iqentry_issue[head5] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head5],iqentry_fn[head5]) |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`SYNC) |
&& !(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] |
else if (could_issue[head6] & !iqentry_fp[head6] && !iqentry_issue[head6] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head6],iqentry_fn[head6]) |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`SYNC) |
&& !(iqentry_v[head5] && iqentry_op[head5]==`SYNC) |
&& !(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] |
else if (could_issue[head7] & !iqentry_fp[head7] && !iqentry_issue[head7] & alu1_idle |
&& !fnIsAlu0Op(iqentry_op[head7],iqentry_fn[head7]) |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`SYNC) |
&& !(iqentry_v[head5] && iqentry_op[head5]==`SYNC) |
&& !(iqentry_v[head6] && iqentry_op[head6]==`SYNC) |
&& !(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; |
3011,7 → 3049,7
fpispot = head0; |
end |
else if (could_issue[head1] & iqentry_fp[head1] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC)) |
&& !(iqentry_v[head0] && iqentry_sync[head0])) |
begin |
iqentry_fpissue[head1] = `TRUE; |
iqentry_fpislot[head1] = 2'b00; |
3018,8 → 3056,8
fpispot = head1; |
end |
else if (could_issue[head2] & iqentry_fp[head2] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
) |
begin |
iqentry_fpissue[head2] = `TRUE; |
3027,9 → 3065,9
fpispot = head2; |
end |
else if (could_issue[head3] & iqentry_fp[head3] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head0] && iqentry_sync[head0]) |
&& !(iqentry_v[head1] && iqentry_sync[head1]) |
&& !(iqentry_v[head2] && iqentry_sync[head2]) |
) begin |
iqentry_fpissue[head3] = `TRUE; |
iqentry_fpislot[head3] = 2'b00; |
3036,10 → 3074,10
fpispot = head3; |
end |
else if (could_issue[head4] & iqentry_fp[head4] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(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_fpissue[head4] = `TRUE; |
iqentry_fpislot[head4] = 2'b00; |
3046,11 → 3084,11
fpispot = head4; |
end |
else if (could_issue[head5] & iqentry_fp[head5] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`SYNC) |
&& !(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_fpissue[head5] = `TRUE; |
iqentry_fpislot[head5] = 2'b00; |
3057,12 → 3095,12
fpispot = head5; |
end |
else if (could_issue[head6] & iqentry_fp[head6] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`SYNC) |
&& !(iqentry_v[head5] && iqentry_op[head5]==`SYNC) |
&& !(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_fpissue[head6] = `TRUE; |
iqentry_fpislot[head6] = 2'b00; |
3069,13 → 3107,13
fpispot = head6; |
end |
else if (could_issue[head7] & iqentry_fp[head7] |
&& !(iqentry_v[head0] && iqentry_op[head0]==`SYNC) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`SYNC) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`SYNC) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`SYNC) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`SYNC) |
&& !(iqentry_v[head5] && iqentry_op[head5]==`SYNC) |
&& !(iqentry_v[head6] && iqentry_op[head6]==`SYNC) |
&& !(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_fpissue[head7] = `TRUE; |
iqentry_fpislot[head7] = 2'b00; |
3122,6 → 3160,12
// Stores can only issue if there is no possibility of a change of program flow. |
// That means no flow control operations or instructions that can cause an |
// exception can be before the store. |
|
// ToDo: if debugging matches are enabled in theory any instruction could cause |
// a debug exception. The memory issue logic should check to see a debug address |
// match will occur, and avoid a store operation. It may be simpler to have stores |
// only occur if they are at the head of the queue if debugging matches are turned |
// on. |
assign iqentry_memissue_head0 = iqentry_memready[ head0 ] && cstate==IDLE && !dcache_access_pending && dram0==0; // first in line ... go as soon as ready |
|
assign iqentry_memissue_head1 = ~iqentry_stomp[head1] && iqentry_memready[ head1 ] // addr and data are valid |
3133,9 → 3177,9
// ... and, if it is a SW, there is no chance of it being undone |
&& (fnIsStore(iqentry_op[head1]) ? !fnIsFlowCtrl(iqentry_op[head0]) |
&& !fnCanException(iqentry_op[head0],iqentry_fn[head0]) : `TRUE) |
&& (iqentry_op[head1]!=`CAS) |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_op[head0]==`MEMDB) |
&& !(iqentry_v[head0] && iqentry_op[head0]==`MEMSB) |
&& (!iqentry_cas[head1]) |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0]) |
&& !(iqentry_v[head0] && iqentry_memsb[head0]) |
&& cstate==IDLE && !dcache_access_pending && dram0==0 |
; |
|
3153,12 → 3197,12
!fnIsFlowCtrl(iqentry_op[head0]) && !fnCanException(iqentry_op[head0],iqentry_fn[head0]) && |
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) |
: `TRUE) |
&& (iqentry_op[head2]!=`CAS) |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_op[head0]==`MEMDB) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_op[head1]==`MEMDB) |
&& (!iqentry_cas[head2]) |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0]) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1]) |
// ... and there is no instruction barrier |
&& !(iqentry_v[head0] && iqentry_op[head0]==`MEMSB) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`MEMSB) |
&& !(iqentry_v[head0] && iqentry_memsb[head0]) |
&& !(iqentry_v[head1] && iqentry_memsb[head1]) |
&& cstate==IDLE && !dcache_access_pending && dram0==0 |
; |
// ( !fnIsFlowCtrl(iqentry_op[head0]) |
3182,15 → 3226,15
!fnIsFlowCtrl(iqentry_op[head1]) && !fnCanException(iqentry_op[head1],iqentry_fn[head1]) && |
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) |
: `TRUE) |
&& (iqentry_op[head3]!=`CAS) |
&& (!iqentry_cas[head3]) |
// ... and there is no memory barrier |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_op[head0]==`MEMDB) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_op[head1]==`MEMDB) |
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_op[head2]==`MEMDB) |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0]) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1]) |
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2]) |
// ... and there is no instruction barrier |
&& !(iqentry_v[head0] && iqentry_op[head0]==`MEMSB) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`MEMSB) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`MEMSB) |
&& !(iqentry_v[head0] && iqentry_memsb[head0]) |
&& !(iqentry_v[head1] && iqentry_memsb[head1]) |
&& !(iqentry_v[head2] && iqentry_memsb[head2]) |
&& cstate==IDLE && !dcache_access_pending && dram0==0 |
; |
/* ( !fnIsFlowCtrl(iqentry_op[head0]) |
3219,17 → 3263,17
!fnIsFlowCtrl(iqentry_op[head2]) && !fnCanException(iqentry_op[head2],iqentry_fn[head2]) && |
!fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3]) |
: `TRUE) |
&& (iqentry_op[head4]!=`CAS) |
&& (!iqentry_cas[head4]) |
// ... and there is no memory barrier |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_op[head0]==`MEMDB) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_op[head1]==`MEMDB) |
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_op[head2]==`MEMDB) |
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_op[head3]==`MEMDB) |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0]) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1]) |
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2]) |
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3]) |
// ... and there is no instruction barrier |
&& !(iqentry_v[head0] && iqentry_op[head0]==`MEMSB) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`MEMSB) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`MEMSB) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`MEMSB) |
&& !(iqentry_v[head0] && iqentry_memsb[head0]) |
&& !(iqentry_v[head1] && iqentry_memsb[head1]) |
&& !(iqentry_v[head2] && iqentry_memsb[head2]) |
&& !(iqentry_v[head3] && iqentry_memsb[head3]) |
&& cstate==IDLE && !dcache_access_pending && dram0==0 |
; |
/* || |
3264,19 → 3308,19
!fnIsFlowCtrl(iqentry_op[head3]) && !fnCanException(iqentry_op[head3],iqentry_fn[head3]) && |
!fnIsFlowCtrl(iqentry_op[head4]) && !fnCanException(iqentry_op[head4],iqentry_fn[head4]) |
: `TRUE) |
&& (iqentry_op[head5]!=`CAS) |
&& (!iqentry_cas[head5]) |
// ... and there is no memory barrier |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_op[head0]==`MEMDB) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_op[head1]==`MEMDB) |
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_op[head2]==`MEMDB) |
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_op[head3]==`MEMDB) |
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_op[head4]==`MEMDB) |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0]) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1]) |
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2]) |
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3]) |
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4]) |
// ... and there is no instruction barrier |
&& !(iqentry_v[head0] && iqentry_op[head0]==`MEMSB) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`MEMSB) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`MEMSB) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`MEMSB) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`MEMSB) |
&& !(iqentry_v[head0] && iqentry_memsb[head0]) |
&& !(iqentry_v[head1] && iqentry_memsb[head1]) |
&& !(iqentry_v[head2] && iqentry_memsb[head2]) |
&& !(iqentry_v[head3] && iqentry_memsb[head3]) |
&& !(iqentry_v[head4] && iqentry_memsb[head4]) |
&& cstate==IDLE && !dcache_access_pending && dram0==0 |
; |
/*|| |
3316,21 → 3360,21
!fnIsFlowCtrl(iqentry_op[head4]) && !fnCanException(iqentry_op[head4],iqentry_fn[head4]) && |
!fnIsFlowCtrl(iqentry_op[head5]) && !fnCanException(iqentry_op[head5],iqentry_fn[head5]) |
: `TRUE) |
&& (iqentry_op[head6]!=`CAS) |
&& (!iqentry_cas[head6]) |
// ... and there is no memory barrier |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_op[head0]==`MEMDB) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_op[head1]==`MEMDB) |
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_op[head2]==`MEMDB) |
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_op[head3]==`MEMDB) |
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_op[head4]==`MEMDB) |
&& !(iqentry_v[head5] && fnIsMem(iqentry_op[head5]) && iqentry_op[head5]==`MEMDB) |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0]) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1]) |
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2]) |
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3]) |
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4]) |
&& !(iqentry_v[head5] && fnIsMem(iqentry_op[head5]) && iqentry_memdb[head5]) |
// ... and there is no instruction barrier |
&& !(iqentry_v[head0] && iqentry_op[head0]==`MEMSB) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`MEMSB) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`MEMSB) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`MEMSB) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`MEMSB) |
&& !(iqentry_v[head5] && iqentry_op[head5]==`MEMSB) |
&& !(iqentry_v[head0] && iqentry_memsb[head0]) |
&& !(iqentry_v[head1] && iqentry_memsb[head1]) |
&& !(iqentry_v[head2] && iqentry_memsb[head2]) |
&& !(iqentry_v[head3] && iqentry_memsb[head3]) |
&& !(iqentry_v[head4] && iqentry_memsb[head4]) |
&& !(iqentry_v[head5] && iqentry_memsb[head5]) |
&& cstate==IDLE && !dcache_access_pending && dram0==0 |
; |
/*|| |
3375,23 → 3419,23
!fnIsFlowCtrl(iqentry_op[head5]) && !fnCanException(iqentry_op[head5],iqentry_fn[head5]) && |
!fnIsFlowCtrl(iqentry_op[head6]) && !fnCanException(iqentry_op[head6],iqentry_fn[head6]) |
: `TRUE) |
&& (iqentry_op[head7]!=`CAS) |
&& (!iqentry_cas[head7]) |
// ... and there is no memory barrier |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_op[head0]==`MEMDB) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_op[head1]==`MEMDB) |
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_op[head2]==`MEMDB) |
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_op[head3]==`MEMDB) |
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_op[head4]==`MEMDB) |
&& !(iqentry_v[head5] && fnIsMem(iqentry_op[head5]) && iqentry_op[head5]==`MEMDB) |
&& !(iqentry_v[head6] && fnIsMem(iqentry_op[head6]) && iqentry_op[head6]==`MEMDB) |
&& !(iqentry_v[head0] && fnIsMem(iqentry_op[head0]) && iqentry_memdb[head0]) |
&& !(iqentry_v[head1] && fnIsMem(iqentry_op[head1]) && iqentry_memdb[head1]) |
&& !(iqentry_v[head2] && fnIsMem(iqentry_op[head2]) && iqentry_memdb[head2]) |
&& !(iqentry_v[head3] && fnIsMem(iqentry_op[head3]) && iqentry_memdb[head3]) |
&& !(iqentry_v[head4] && fnIsMem(iqentry_op[head4]) && iqentry_memdb[head4]) |
&& !(iqentry_v[head5] && fnIsMem(iqentry_op[head5]) && iqentry_memdb[head5]) |
&& !(iqentry_v[head6] && fnIsMem(iqentry_op[head6]) && iqentry_memdb[head6]) |
// ... and there is no instruction barrier |
&& !(iqentry_v[head0] && iqentry_op[head0]==`MEMSB) |
&& !(iqentry_v[head1] && iqentry_op[head1]==`MEMSB) |
&& !(iqentry_v[head2] && iqentry_op[head2]==`MEMSB) |
&& !(iqentry_v[head3] && iqentry_op[head3]==`MEMSB) |
&& !(iqentry_v[head4] && iqentry_op[head4]==`MEMSB) |
&& !(iqentry_v[head5] && iqentry_op[head5]==`MEMSB) |
&& !(iqentry_v[head6] && iqentry_op[head6]==`MEMSB) |
&& !(iqentry_v[head0] && iqentry_memsb[head0]) |
&& !(iqentry_v[head1] && iqentry_memsb[head1]) |
&& !(iqentry_v[head2] && iqentry_memsb[head2]) |
&& !(iqentry_v[head3] && iqentry_memsb[head3]) |
&& !(iqentry_v[head4] && iqentry_memsb[head4]) |
&& !(iqentry_v[head5] && iqentry_memsb[head5]) |
&& !(iqentry_v[head6] && iqentry_memsb[head6]) |
&& cstate==IDLE && !dcache_access_pending && dram0==0 |
; |
|
3428,8 → 3472,8
begin : memr |
for (g = 0; g < QENTRIES; g = g + 1) |
begin |
assign iqentry_memopsvalid[g] = (iqentry_mem[g] & iqentry_a2_v[g] & iqentry_a3_v[g] & iqentry_agen[g]); |
assign iqentry_memready[g] = (iqentry_v[g] & iqentry_memopsvalid[g] & ~iqentry_memissue[g] & !iqentry_issue[g] & ~iqentry_done[g] & ~iqentry_out[g] & ~iqentry_stomp[g]); |
assign iqentry_memopsvalid[g] = (iqentry_mem[g] & iqentry_a2_v[g] & iqentry_a3_v[g] & iqentry_agen[g] & iqentry_T_v[g]); |
assign iqentry_memready[g] = (iqentry_v[g] & iqentry_memopsvalid[g] & ~iqentry_memissue[g] /*& !iqentry_issue[g]*/ & ~iqentry_done[g] & ~iqentry_out[g] & ~iqentry_stomp[g]); |
end |
end |
endgenerate |
3436,24 → 3480,7
|
/* |
assign |
iqentry_memopsvalid[0] = (iqentry_mem[0] & iqentry_a2_v[0] & iqentry_a3_v[0] & iqentry_agen[0]), |
iqentry_memopsvalid[1] = (iqentry_mem[1] & iqentry_a2_v[1] & iqentry_a3_v[1] & iqentry_agen[1]), |
iqentry_memopsvalid[2] = (iqentry_mem[2] & iqentry_a2_v[2] & iqentry_a3_v[2] & iqentry_agen[2]), |
iqentry_memopsvalid[3] = (iqentry_mem[3] & iqentry_a2_v[3] & iqentry_a3_v[3] & iqentry_agen[3]), |
iqentry_memopsvalid[4] = (iqentry_mem[4] & iqentry_a2_v[4] & iqentry_a3_v[4] & iqentry_agen[4]), |
iqentry_memopsvalid[5] = (iqentry_mem[5] & iqentry_a2_v[5] & iqentry_a3_v[5] & iqentry_agen[5]), |
iqentry_memopsvalid[6] = (iqentry_mem[6] & iqentry_a2_v[6] & iqentry_a3_v[6] & iqentry_agen[6]), |
iqentry_memopsvalid[7] = (iqentry_mem[7] & iqentry_a2_v[7] & iqentry_a3_v[7] & iqentry_agen[7]); |
|
assign |
iqentry_memready[0] = (iqentry_v[0] & iqentry_memopsvalid[0] & ~iqentry_memissue[0] & ~iqentry_done[0] & ~iqentry_out[0] & ~iqentry_stomp[0]), |
iqentry_memready[1] = (iqentry_v[1] & iqentry_memopsvalid[1] & ~iqentry_memissue[1] & ~iqentry_done[1] & ~iqentry_out[1] & ~iqentry_stomp[1]), |
iqentry_memready[2] = (iqentry_v[2] & iqentry_memopsvalid[2] & ~iqentry_memissue[2] & ~iqentry_done[2] & ~iqentry_out[2] & ~iqentry_stomp[2]), |
iqentry_memready[3] = (iqentry_v[3] & iqentry_memopsvalid[3] & ~iqentry_memissue[3] & ~iqentry_done[3] & ~iqentry_out[3] & ~iqentry_stomp[3]), |
iqentry_memready[4] = (iqentry_v[4] & iqentry_memopsvalid[4] & ~iqentry_memissue[4] & ~iqentry_done[4] & ~iqentry_out[4] & ~iqentry_stomp[4]), |
iqentry_memready[5] = (iqentry_v[5] & iqentry_memopsvalid[5] & ~iqentry_memissue[5] & ~iqentry_done[5] & ~iqentry_out[5] & ~iqentry_stomp[5]), |
iqentry_memready[6] = (iqentry_v[6] & iqentry_memopsvalid[6] & ~iqentry_memissue[6] & ~iqentry_done[6] & ~iqentry_out[6] & ~iqentry_stomp[6]), |
iqentry_memready[7] = (iqentry_v[7] & iqentry_memopsvalid[7] & ~iqentry_memissue[7] & ~iqentry_done[7] & ~iqentry_out[7] & ~iqentry_stomp[7]); |
*/ |
assign outstanding_stores = (dram0 && fnIsStore(dram0_op)) || (dram1 && fnIsStore(dram1_op)) || (dram2 && fnIsStore(dram2_op)); |
|
3469,13 → 3496,7
iqentry_memissue_head7 |
; |
|
wire [DBW-1:0] argA = iqentry_a1_v[n] ? iqentry_a1[n] |
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus |
: (iqentry_a1_s[n] == commit1_id) ? commit1_bus |
: (iqentry_a1_s[n] == commit0_id) ? commit0_bus |
: 64'hDEADDEADDEADDEAD; |
|
// Nybble slices for predicate register forwarding |
wire [3:0] alu0nyb[0:15]; |
wire [3:0] alu1nyb[0:15]; |
wire [3:0] cmt0nyb[0:15]; |
3494,20 → 3515,10
endgenerate |
|
//`include "Thor_commit_combo.v" |
// If trying to write to two branch registers at once, or trying to write |
// to two predicate registers at once, then limit the processor to single |
// commit. |
// The processor does not support writing two registers in the same register |
// group at the same time for anything other than the general purpose |
// registers. It is possible for the processor to write to two diffent groups |
// at the same time. |
//assign limit_cmt = (iqentry_rfw[head0] && iqentry_rfw[head1] && iqentry_tgt[head0][8]==1'b1 && iqentry_tgt[head1][8]==1'b1); |
assign limit_cmt = 1'b0; |
//assign committing2 = (iqentry_v[head0] && iqentry_v[head1] && !limit_cmt) || (head0 != tail0 && head1 != tail0); |
|
assign commit0_v = ({iqentry_v[head0], iqentry_done[head0]} == 2'b11 && ~|panic); |
assign commit1_v = ({iqentry_v[head0], iqentry_done[head0]} != 2'b10 |
&& {iqentry_v[head1], iqentry_done[head1]} == 2'b11 && ~|panic && !limit_cmt); |
&& {iqentry_v[head1], iqentry_done[head1]} == 2'b11 && ~|panic); |
|
assign commit0_id = {iqentry_mem[head0], head0}; // if a memory op, it has a DRAM-bus id |
assign commit1_id = {iqentry_mem[head1], head1}; // if a memory op, it has a DRAM-bus id |
3601,10 → 3612,18
fp0_ld <= 1'b0; |
`endif |
|
// Interrupt enable countdown delay. |
if (imcd!=6'h3f) |
imcd <= {imcd[4:0],1'b0}; |
if (imcd==6'd0) begin |
im <= 1'b0; |
imcd <= 6'h3f; |
end |
|
mem_stringmiss <= `FALSE; |
if (mem_stringmissx) begin |
mem_stringmiss <= `TRUE; |
dram0_op <= `NOP; // clears string miss |
// dram0_op <= `NOP; // clears string miss |
end |
ic_invalidate <= `FALSE; |
dc_invalidate <= `FALSE; |
3615,16 → 3634,20
|
// Reset segmentation flag once operating in non-segmented area. |
if (pc[ABW-1:ABW-4]==4'hF) |
pc[ABW+3:ABW] <= 4'h0; |
pc[ABW] <= 1'b0; |
|
if (rst_i) |
cstate <= RESET1; |
if (rst_i||cstate==RESET1||cstate==RESET2) begin |
imcd <= 6'h3F; |
wb_nack(); |
`ifdef PCHIST |
pc_cap <= `TRUE; |
`endif |
ierr <= 1'b0; |
GM <= 8'hFF; |
nmi_edge <= 1'b0; |
pc <= RSTADDR[ABW-1:0]; |
pc <= RSTPC[ABW-1:0]; |
StatusHWI <= `TRUE; // disables interrupts at startup until an RTI instruction is executed. |
im <= 1'b1; |
imb <= 1'b1; |
3708,7 → 3731,7
// 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] <= 52'd0; |
sregs[7] <= RSTCSEG; |
for (i=0; i < 16; i=i+1) |
pregs[i] <= 4'd0; |
asid <= 8'h00; |
3785,13 → 3808,12
if ((alu0_op==`RR && (alu0_fn==`MUL || alu0_fn==`MULU)) || alu0_op==`MULI || alu0_op==`MULUI) begin |
if (alu0_done) begin |
alu0_dataready <= `TRUE; |
alu0_op <= `NOP; |
end |
end |
else if ((alu0_op==`RR && (alu0_fn==`DIV || alu0_fn==`DIVU)) || alu0_op==`DIVI || alu0_op==`DIVUI) begin |
else if ((alu0_op==`RR && (alu0_fn==`DIV || alu0_fn==`DIVU || alu0_fn==`MOD || alu0_fn==`MODU)) || |
alu0_op==`DIVI || alu0_op==`DIVUI || alu0_op==`MODI || alu0_op==`MODUI) begin |
if (alu0_done) begin |
alu0_dataready <= `TRUE; |
alu0_op <= `NOP; |
end |
end |
|
3815,13 → 3837,12
if (((alu1_op==`RR && (alu1_fn==`MUL || alu1_fn==`MULU)) || alu1_op==`MULI || alu1_op==`MULUI) && ALU1BIG) begin |
if (alu1_done) begin |
alu1_dataready <= `TRUE; |
alu1_op <= `NOP; |
end |
end |
else if (((alu1_op==`RR && (alu1_fn==`DIV || alu1_fn==`DIVU)) || alu1_op==`DIVI || alu1_op==`DIVUI) && ALU1BIG) begin |
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 |
if (alu1_done) begin |
alu1_dataready <= `TRUE; |
alu1_op <= `NOP; |
end |
end |
|
3968,7 → 3989,7
// Note that there is no point to loading C,D here because |
// there is a predicted taken branch that would stomp on the |
// instructions anyways. |
if ((fnIsBranch(opcodeA) && predict_takenA)||opcodeA==`LOOP) begin |
if ((fnIsBranch(opcodeA) && predict_takenBr)||opcodeA==`LOOP) begin |
pc <= branch_pc; |
fetchbufA_v <= !(queued1|queued2); |
fetchbufB_v <= `INV; // stomp on it |
4048,7 → 4069,7
panic <= `PANIC_INVALIDIQSTATE; |
end |
4'b1100: |
if ((fnIsBranch(opcodeC) && predict_takenC)||opcodeC==`LOOP) begin |
if ((fnIsBranch(opcodeC) && predict_takenBr)||opcodeC==`LOOP) begin |
pc <= branch_pc; |
fetchbufC_v <= !(queued1|queued2); |
fetchbufD_v <= `INV; // stomp on it |
4443,7 → 4464,7
: 64'hDEADDEADDEADDEAD; |
alu0_argC <= |
`ifdef SEGMENTATION |
(iqentry_mem[n] && !iqentry_cmpmv[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} : |
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} : |
`endif |
iqentry_a3_v[n] ? iqentry_a3[n] |
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus |
4455,6 → 4476,7
: 64'hDEADDEADDEADDEAD; |
alu0_argI <= iqentry_a0[n]; |
alu0_dataready <= fnAluValid(iqentry_op[n],iqentry_fn[n]); |
iqentry_out[n] <= `TRUE; |
end |
2'd1: if (alu1_available) begin |
alu1_ld <= 1'b1; |
4478,7 → 4500,7
: 64'hDEADDEADDEADDEAD; |
alu1_argC <= |
`ifdef SEGMENTATION |
(iqentry_mem[n] && !iqentry_cmpmv[n])? {sregs[iqentry_fn[n][5:3]],12'h000} : |
((iqentry_mem[n] && !iqentry_cmpmv[n]) || iqentry_lla[n]) ? {sregs[iqentry_fn[n][5:3]],12'h000} : |
`endif |
iqentry_a3_v[n] ? iqentry_a3[n] |
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus |
4490,10 → 4512,11
: 64'hDEADDEADDEADDEAD; |
alu1_argI <= iqentry_a0[n]; |
alu1_dataready <= fnAluValid(iqentry_op[n],iqentry_fn[n]); |
iqentry_out[n] <= `TRUE; |
end |
default: panic <= `PANIC_INVALIDISLOT; |
endcase |
iqentry_out[n] <= `TRUE; |
// iqentry_out[n] <= `TRUE; |
// if it is a memory operation, this is the address-generation step ... collect result into arg1 |
if (iqentry_mem[n] && !iqentry_tlb[n]) begin |
iqentry_a1_v[n] <= `INV; |
4679,11 → 4702,12
dram0_addr <= dram0_addr + fnIndexAmt(dram0_fn); |
lc <= lc - 64'd1; |
dram0 <= 3'd1; |
dram_bus <= dram0_addr + fnIndexAmt(dram0_fn); |
// dram_bus <= dram0_addr + fnIndexAmt(dram0_fn) - dram0_seg; |
end |
else begin |
dram_bus <= dram0_addr + fnIndexAmt(dram0_fn) - dram0_seg; |
dram_v <= `VAL; |
dram0_op <= `NOP; |
end |
`STMV,`STCMP: |
begin |
4711,6 → 4735,7
end |
else begin |
dram_v <= `VAL; |
dram0_op <= `NOP; |
end |
end |
`STFND: |
4728,6 → 4753,7
else begin |
dram_bus <= index; |
dram_v <= `VAL; |
dram0_op <= `NOP; |
end |
`endif |
`CAS: |
4837,6 → 4863,7
else begin |
dram_v <= `VAL; |
dram0 <= 3'd7; |
dram0_op <= `NOP; |
end |
end |
`STFND: |
4857,6 → 4884,7
else begin |
dram_v <= `VAL; |
dram0 <= 3'd7; |
dram0_op <= `NOP; |
end |
end |
`endif |
5037,6 → 5065,9
(iqentry_a0[head1][7:0]==8'hFE && commit1_v && iqentry_op[head1]==`INT)) |
nmi_edge <= 1'b0; |
string_pc <= 64'd0; |
`ifdef PCHIST |
pc_cap <= `FALSE; |
`endif |
end |
|
if (sys_commit) |
5471,6 → 5502,9
6'd3: dbg_adr3 <= commit_bus; |
6'd4: dbg_ctrl <= commit_bus; |
6'd5: dbg_stat <= commit_bus; |
`ifdef PCHIST |
6'd18: pc_ndx <= commit_bus[5:0]; |
`endif |
default: ; |
endcase |
6'b111111: |
5547,7 → 5581,7
end |
6'd60: fnSpr = spr_bir; |
6'd61: |
case(spr_bir[5:0]) |
casex(spr_bir[5:0]) |
6'd0: fnSpr = dbg_adr0; |
6'd1: fnSpr = dbg_adr1; |
6'd2: fnSpr = dbg_adr2; |
5554,6 → 5588,10
6'd3: fnSpr = dbg_adr3; |
6'd4: fnSpr = dbg_ctrl; |
6'd5: fnSpr = dbg_stat; |
`ifdef PCHIST |
6'd16: fnSpr = pc_histo[31:0]; |
6'd17: fnSpr = pc_histo[63:31]; |
`endif |
default: fnSpr = 64'd0; |
endcase |
default: fnSpr = 64'd0; |
5563,10 → 5601,26
// Shaves a clock cycle off register updates. rf_v is being set valid on the |
// clock cycle of the commit. |
// If an spr is committing... |
if (commit0_v && commit0_tgt=={1'b1,regno}) |
fnSpr = commit0_bus; |
if (commit1_v && commit1_tgt=={1'b1,regno}) |
fnSpr = commit1_bus; |
if (commit0_v && commit0_tgt=={1'b1,regno}) begin |
if (regno[5:4]==2'b00) begin |
if (DBW==32) |
fnSpr = {8{cmt0nyb[regno[2:0]]}}; |
else |
fnSpr = {16{cmt0nyb[regno[3:0]]}}; |
end |
else |
fnSpr = commit0_bus; |
end |
if (commit1_v && commit1_tgt=={1'b1,regno}) begin |
if (regno[5:4]==2'b00) begin |
if (DBW==32) |
fnSpr = {8{cmt1nyb[regno[2:0]]}}; |
else |
fnSpr = {16{cmt1nyb[regno[3:0]]}}; |
end |
else |
fnSpr = commit1_bus; |
end |
|
// Special cases where the register would not be read from the commit bus |
case(regno) |
5586,12 → 5640,15
begin |
if (commit_v) |
case(iqentry_op[head]) |
`CLI: begin im <= 1'b0; imb <= 1'b0; end |
`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. |
`RTI: begin |
StatusHWI <= `FALSE; |
im <= imb; |
if (imb) |
im <= 1'b1; |
else |
imcd <= IMCD; |
end |
`RTD: |
begin |
5638,12 → 5695,12
$stop; |
if (fetchbuf0_pc==32'hF44) |
$stop; |
if (fetchbuf0_pc==32'hFFFFda49) |
if (fetchbuf0_pc==32'hFFFFD09B) |
$stop; |
`ifdef SEGMENTATION |
`ifdef SEGLIMITS |
// If segment limit exceeded and not in the non-segmented area. |
if (fetchbuf0_pc >= {sregs_lmt[7],12'h000} && fetchbuf0_pc[ABW-1:ABW-4]!=4'hF) |
if (fetchbuf0_pc >= {sregs_lmt[3'd7],12'h000} && fetchbuf0_pc[ABW-1:ABW-4]!=4'hF) |
set_exception(tail,8'd244); |
`endif |
`endif |
5689,7 → 5746,8
iqentry_op [tail] <= opcode0; |
iqentry_fn [tail] <= opcode0==`MLO ? rfoc0[5:0] : fnFunc(fetchbuf0_instr); |
iqentry_cond [tail] <= cond0; |
iqentry_bt [tail] <= fnIsFlowCtrl(opcode0) && predict_taken0; |
iqentry_bt [tail] <= fnIsFlowCtrl(opcode0) && predict_taken0; |
iqentry_br [tail] <= opcode0[7:4]==`BR; |
iqentry_agen [tail] <= `INV; |
iqentry_pc [tail] <= (opcode0==`INT && Rt0[3:0]==4'hE) ? interrupt_pc : fetchbuf0_pc; |
iqentry_mem [tail] <= fetchbuf0_mem; |
5698,18 → 5756,23
iqentry_pushpop[tail] <= opcode0==`PUSH || opcode0==`POP; |
iqentry_pea [tail] <= opcode0==`PEA; |
iqentry_cmpmv[tail] <= opcode0==`STCMP || opcode0==`STMV; |
iqentry_lla [tail] <= opcode0==`LLA || opcode0==`LLAX; |
iqentry_tlb [tail] <= opcode0==`TLB; |
iqentry_jmp [tail] <= fetchbuf0_jmp; |
iqentry_jmpi [tail] <= opcode0==`JMPI || opcode0==`JMPIX; |
iqentry_sync [tail] <= opcode0==`SYNC; |
iqentry_memsb[tail] <= opcode0==`MEMSB; |
iqentry_memdb[tail] <= opcode0==`MEMDB; |
iqentry_fp [tail] <= fetchbuf0_fp; |
iqentry_rfw [tail] <= fetchbuf0_rfw; |
iqentry_tgt [tail] <= Rt0; |
iqentry_preg [tail] <= Pn0; |
iqentry_pred [tail] <= pregs[Pn0]; |
// 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 ? fnImm(fetchbuf0_instr) : |
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)}: |
(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 |
5769,9 → 5832,13
iqentry_pushpop[tail] <= 1'b0; |
iqentry_pea [tail] <= 1'b0; |
iqentry_cmpmv[tail] <= 1'b0; |
iqentry_lla [tail] <= 1'b0; |
iqentry_tlb [tail] <= 1'b0; |
iqentry_jmp [tail] <= 1'b0; |
iqentry_jmpi [tail] <= 1'b0; |
iqentry_sync [tail] <= 1'b0; |
iqentry_memsb[tail] <= 1'b0; |
iqentry_memdb[tail] <= 1'b0; |
iqentry_fp [tail] <= 1'b0; |
iqentry_rfw [tail] <= 1'b1; |
iqentry_tgt [tail] <= 7'd27; |
5864,11 → 5931,11
$stop; |
if (fetchbuf1_pc==32'hF44) |
$stop; |
if (fetchbuf1_pc==32'hFFFFDA49) |
if (fetchbuf1_pc==32'hFFFFD09B) |
$stop; |
`ifdef SEGMENTATION |
`ifdef SEGLIMITS |
if (fetchbuf1_pc >= {sregs_lmt[7],12'h000} && fetchbuf1_pc[ABW-1:ABW-4]!=4'hF) |
if (fetchbuf1_pc >= {sregs_lmt[3'd7],12'h000} && fetchbuf1_pc[ABW-1:ABW-4]!=4'hF) |
set_exception(tail,8'd244); |
`endif |
`endif |
5911,6 → 5978,7
iqentry_fn [tail] <= opcode1==`MLO ? rfoc1[5:0] : fnFunc(fetchbuf1_instr); |
iqentry_cond [tail] <= cond1; |
iqentry_bt [tail] <= fnIsFlowCtrl(opcode1) && predict_taken1; |
iqentry_br [tail] <= opcode1[7:4]==`BR; |
iqentry_agen [tail] <= `INV; |
// If an interrupt is being enqueued and the previous instruction was an immediate prefix, then |
// inherit the address of the previous instruction, so that the prefix will be executed on return |
5925,17 → 5993,21
iqentry_pushpop[tail] <= opcode1==`PUSH || opcode1==`POP; |
iqentry_pea [tail] <= opcode1==`PEA; |
iqentry_cmpmv[tail] <= opcode1==`STCMP || opcode1==`STMV; |
iqentry_lla [tail] <= opcode1==`LLA || opcode1==`LLAX; |
iqentry_tlb [tail] <= opcode1==`TLB; |
iqentry_jmp [tail] <= fetchbuf1_jmp; |
iqentry_jmpi [tail] <= opcode1==`JMPI || opcode1==`JMPIX; |
iqentry_sync [tail] <= opcode1==`SYNC; |
iqentry_memsb[tail] <= opcode1==`MEMSB; |
iqentry_memdb[tail] <= opcode1==`MEMDB; |
iqentry_fp [tail] <= fetchbuf1_fp; |
iqentry_rfw [tail] <= fetchbuf1_rfw; |
iqentry_tgt [tail] <= Rt1; |
iqentry_preg [tail] <= Pn1; |
iqentry_pred [tail] <= pregs[Pn1]; |
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 ? fnImm(fetchbuf1_instr) : |
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)} : |
/trunk/rtl/verilog/Thor_alu.v
26,7 → 26,7
// |
`include "Thor_defines.v" |
|
module Thor_alu(corenum, rst, clk, alu_ld, alu_op, alu_fn, alu_argA, alu_argB, alu_argC, alu_argI, alu_pc, insnsz, o, alu_done, alu_divByZero); |
module Thor_alu(corenum, rst, clk, alu_ld, alu_abort, alu_op, alu_fn, alu_argA, alu_argB, alu_argC, alu_argI, alu_pc, insnsz, o, alu_done, alu_idle, alu_divByZero); |
parameter DBW=64; |
parameter BIG=1; |
parameter FEATURES = 0; |
34,6 → 34,7
input rst; |
input clk; |
input alu_ld; |
input alu_abort; |
input [7:0] alu_op; |
input [5:0] alu_fn; |
input [DBW-1:0] alu_argA; |
44,6 → 45,7
input [3:0] insnsz; |
output reg [DBW-1:0] o; |
output reg alu_done; |
output reg alu_idle; |
output alu_divByZero; |
|
wire signed [DBW-1:0] alu_argAs = alu_argA; |
58,6 → 60,7
wire [DBW-1:0] bf_out; |
wire [DBW-1:0] shfto; |
wire alu_mult_done,alu_div_done; |
wire alu_mult_idle,alu_div_idle; |
wire [DBW-1:0] p_out; |
reg [3:0] o1; |
|
68,6 → 71,7
.rst(rst), |
.clk(clk), |
.ld(alu_ld && ((alu_op==`RR && (alu_fn==`MUL || alu_fn==`MULU)) || alu_op==`MULI || alu_op==`MULUI)), |
.abort(alu_abort), |
.sgn((alu_op==`RR && alu_op==`MUL) || alu_op==`MULI), |
.isMuli(alu_op==`MULI || alu_op==`MULUI), |
.a(alu_argA), |
74,7 → 78,8
.b(alu_argB), |
.imm(alu_argI), |
.o(alu_prod), |
.done(alu_mult_done) |
.done(alu_mult_done), |
.idle(alu_mult_idle) |
); |
|
Thor_divider #(DBW) udiv1 |
81,9 → 86,11
( |
.rst(rst), |
.clk(clk), |
.ld(alu_ld && ((alu_op==`RR && (alu_fn==`DIV || alu_fn==`DIVU)) || alu_op==`DIVI || alu_op==`DIVUI)), |
.sgn((alu_op==`RR && alu_fn==`DIV) || alu_op==`DIVI), |
.isDivi(alu_op==`DIVI || alu_op==`DIVUI), |
.ld(alu_ld && ((alu_op==`RR && (alu_fn==`DIV || alu_fn==`DIVU || alu_fn==`MOD || alu_fn==`MODU)) |
|| alu_op==`DIVI || alu_op==`DIVUI || alu_op==`MODI || alu_op==`MODUI)), |
.abort(alu_abort), |
.sgn((alu_op==`RR && (alu_fn==`DIV || alu_fn==`MOD)) || alu_op==`DIVI || alu_op==`MODI), |
.isDivi(alu_op==`DIVI || alu_op==`DIVUI || alu_op==`MODI || alu_op==`MODUI), |
.a(alu_argA), |
.b(alu_argB), |
.imm(alu_argI), |
90,7 → 97,8
.qo(alu_divq), |
.ro(alu_rem), |
.dvByZr(alu_divByZero), |
.done(alu_div_done) |
.done(alu_div_done), |
.idle(alu_div_idle) |
); |
|
Thor_shifter #(DBW) ushft0 |
199,10 → 207,12
`MAX: o <= BIG ? (alu_argA < alu_argB ? alu_argB : alu_argA) : 64'hDEADDEADDEADDEAD; |
`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; |
default: o <= 64'hDEADDEADDEADDEAD; |
endcase |
`MULI,`MULUI: o <= BIG ? alu_prod[63:0] : 64'hDEADDEADDEADDEAD; |
`DIVI,`DIVUI: o <= BIG ? alu_divq : 64'hDEADDEADDEADDEAD; |
`MODI,`MODUI: o <= BIG ? alu_rem : 64'hDEADDEADDEADDEAD; |
`_2ADDUI: o <= {alu_argA[DBW-2:0],1'b0} + alu_argI; |
`_4ADDUI: o <= {alu_argA[DBW-3:0],2'b0} + alu_argI; |
`_8ADDUI: o <= {alu_argA[DBW-4:0],3'b0} + alu_argI; |
347,7 → 357,7
case(alu_fn) |
2'd0: begin // ICMP |
o1[0] = alu_argA == alu_argB; |
o1[1] = alu_argAs < alu_argBs; |
o1[1] = ($signed(alu_argA) < $signed(alu_argB)); |
o1[2] = alu_argA < alu_argB; |
o1[3] = 1'b0; |
o <= {16{o1}}; |
375,13 → 385,14
8'h20,8'h21,8'h22,8'h23,8'h24,8'h25,8'h26,8'h27,8'h28,8'h29,8'h2A,8'h2B,8'h2C,8'h2D,8'h2E,8'h2f: |
begin |
o1[0] = alu_argA == alu_argI; |
o1[1] = alu_argAs < alu_argIs; |
o1[1] = ($signed(alu_argA) < $signed(alu_argI)); |
o1[2] = alu_argA < alu_argI; |
o1[3] = 1'b0; |
o <= {16{o1}}; |
end |
`LLA, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`SB,`SC,`SH,`SW,`CAS,`LVB,`LVC,`LVH,`LVW,`STI, |
`LWS,`SWS,`RTS2,`STS,`STFND,`STCMP,`PUSH: |
`LWS,`SWS,`STS,`STFND,`STCMP,`PUSH: |
begin |
o <= alu_argA + alu_argC + alu_argI; |
end |
389,7 → 400,7
`LBX,`LBUX,`SBX, |
`LCX,`LCUX,`SCX, |
`LHX,`LHUX,`SHX, |
`LWX,`SWX, |
`LWX,`SWX,`LLAX, |
`JMPIX: |
case(alu_fn[1:0]) |
2'd0: o <= alu_argA + alu_argC + alu_argB; |
436,12 → 447,26
`RR: |
case(alu_fn) |
`MUL,`MULU: alu_done <= alu_mult_done; |
`DIV,`DIVU: alu_done <= alu_div_done; |
`DIV,`DIVU,`MOD,`MODU: alu_done <= alu_div_done; |
default: alu_done <= `TRUE; |
endcase |
`MULI,`MULUI: alu_done <= alu_mult_done; |
`DIVI,`DIVUI: alu_done <= alu_div_done; |
`DIVI,`DIVUI,`MODI,`MODUI: alu_done <= alu_div_done; |
default: alu_done <= `TRUE; |
endcase |
|
// Generate idle signal |
always @* |
case(alu_op) |
`RR: |
case(alu_fn) |
`MUL,`MULU: alu_idle <= alu_mult_idle; |
`DIV,`DIVU,`MOD,`MODU: alu_idle <= alu_div_idle; |
default: alu_idle <= `TRUE; |
endcase |
`MULI,`MULUI: alu_idle <= alu_mult_idle; |
`DIVI,`DIVUI,`MODI,`MODUI: alu_idle <= alu_div_idle; |
default: alu_idle <= `TRUE; |
endcase |
|
endmodule |
/trunk/rtl/verilog/Thor_execute_combo.v
26,14 → 26,17
// |
wire [DBW-1:0] alu0_out, alu1_out; |
wire alu0_done,alu1_done; |
wire alu0_idle,alu1_idle; |
wire alu0_divByZero, alu1_divByZero; |
wire alu0_abort,alu1_abort; |
|
Thor_alu #(.DBW(DBW),.BIG(1)) ualu0 |
( |
.corenum(corenum), |
.rst(rst), |
.rst(rst_i), |
.clk(clk), |
.alu_ld(alu0_ld), |
.alu_abort(alu0_abort), |
.alu_op(alu0_op), |
.alu_fn(alu0_fn), |
.alu_argA(alu0_argA), |
44,6 → 47,7
.insnsz(alu0_insnsz), |
.o(alu0_out), |
.alu_done(alu0_done), |
.alu_idle(alu0_idle), |
.alu_divByZero(alu0_divByZero) |
); |
|
50,9 → 54,10
Thor_alu #(.DBW(DBW),.BIG(ALU1BIG)) ualu1 |
( |
.corenum(corenum), |
.rst(rst), |
.rst(rst_i), |
.clk(clk), |
.alu_ld(alu1_ld), |
.alu_abort(alu1_abort), |
.alu_op(alu1_op), |
.alu_fn(alu1_fn), |
.alu_argA(alu1_argA), |
63,6 → 68,7
.insnsz(alu1_insnsz), |
.o(alu1_out), |
.alu_done(alu1_done), |
.alu_idle(alu1_idle), |
.alu_divByZero(alu1_divByZero) |
); |
|
105,6 → 111,8
alu0_id <= alu0_sourceid; |
alu1_id <= alu1_sourceid; |
end |
assign alu0_abort = !alu0_cmt; |
assign alu1_abort = !alu1_cmt; |
|
// Special flag nybble is used for INT and SYS instructions in order to turn off |
// segmentation while the vector jump is taking place. |
111,14 → 119,14
|
always @(alu0_op or alu0_fn or alu0_argA or alu0_argI or alu0_insnsz or alu0_pc or alu0_bt) |
case(alu0_op) |
`JSR,`JSRS,`JSRZ,`RTD,`RTE,`RTI: |
`JSR,`JSRS,`JSRZ,`RTD,`RTE,`RTI,`RTS2: |
alu0_misspc <= alu0_argA + alu0_argI; |
`LOOP,`SYNC: |
alu0_misspc <= alu0_pc + alu0_insnsz; |
`RTS,`RTS2: |
`RTS: |
alu0_misspc <= alu0_argA + alu0_fn[3:0]; |
`SYS,`INT: |
alu0_misspc <= {4'hF,alu0_argA + {alu0_argI[DBW-5:0],4'b0}}; |
alu0_misspc <= {1'b1,alu0_argA + alu0_argI}; |
default: |
alu0_misspc <= (alu0_bt ? alu0_pc + alu0_insnsz : alu0_pc + alu0_insnsz + alu0_argI); |
endcase |
125,14 → 133,14
|
always @(alu1_op or alu1_fn or alu1_argA or alu1_argI or alu1_insnsz or alu1_pc or alu1_bt) |
case(alu1_op) |
`JSR,`JSRS,`JSRZ,`RTD,`RTE,`RTI: |
`JSR,`JSRS,`JSRZ,`RTD,`RTE,`RTI,`RTS2: |
alu1_misspc <= alu1_argA + alu1_argI; |
`LOOP,`SYNC: |
alu1_misspc <= alu1_pc + alu1_insnsz; |
`RTS,`RTS2: |
`RTS: |
alu1_misspc <= alu1_argA + alu1_fn[3:0]; |
`SYS,`INT: |
alu1_misspc <= {4'hF,alu1_argA + {alu1_argI[DBW-5:0],4'b0}}; |
alu1_misspc <= {1'b1,alu1_argA + alu1_argI}; |
default: |
alu1_misspc <= (alu1_bt ? alu1_pc + alu1_insnsz : alu1_pc + alu1_insnsz + alu1_argI); |
endcase |
184,13 → 192,15
|
assign alu0_branchmiss = alu0_dataready && |
((fnIsBranch(alu0_op)) ? ((alu0_cmt && !alu0_bt) || (!alu0_cmt && alu0_bt)) |
: (alu0_cmtw && (alu0_op==`SYNC || alu0_op == `JSR || alu0_op == `JSRS || alu0_op == `JSRZ || |
: !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==`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 && |
((fnIsBranch(alu1_op)) ? ((alu1_cmt && !alu1_bt) || (!alu1_cmt && alu1_bt)) |
: (alu1_cmtw && (alu1_op==`SYNC || alu1_op == `JSR || alu1_op == `JSRS || alu1_op == `JSRZ || |
: !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==`RTS || alu1_op==`RTS2 || alu1_op==`RTD || alu1_op == `RTE || alu1_op==`RTI || ((alu1_op==`LOOP) && (alu1_argA == 64'd0))))); |
|
/trunk/rtl/verilog/Thor_divider.v
1,6 → 1,6
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2013 Robert Finch, Stratford |
// \\__/ o\ (C) 2013,2015 Robert Finch, Stratford |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
25,7 → 25,7
// |
// ============================================================================ |
// |
module Thor_divider(rst, clk, ld, sgn, isDivi, a, b, imm, qo, ro, dvByZr, done); |
module Thor_divider(rst, clk, ld, abort, sgn, isDivi, a, b, imm, qo, ro, dvByZr, done, idle); |
parameter WID=64; |
parameter DIV=3'd3; |
parameter IDLE=3'd4; |
33,6 → 33,7
input clk; |
input rst; |
input ld; |
input abort; |
input sgn; |
input isDivi; |
input [WID-1:0] a; |
43,6 → 44,7
output [WID-1:0] ro; |
reg [WID-1:0] ro; |
output done; |
output idle; |
output dvByZr; |
reg dvByZr; |
|
52,6 → 54,7
reg [7:0] cnt; |
wire cnt_done = cnt==8'd0; |
assign done = state==DONE; |
assign idle = state==IDLE; |
reg ce1; |
reg [WID-1:0] q; |
reg [WID:0] r; |
78,7 → 81,9
end |
else |
begin |
if (!cnt_done) |
if (abort) |
cnt <= 8'd00; |
else if (!cnt_done) |
cnt <= cnt - 8'd1; |
|
case(state) |
/trunk/rtl/verilog/Thor_multiplier.v
1,6 → 1,6
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2013 Robert Finch, Stratford |
// \\__/ o\ (C) 2013,2015 Robert Finch, Stratford |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
25,7 → 25,7
// |
// ============================================================================ |
// |
module Thor_multiplier(rst, clk, ld, sgn, isMuli, a, b, imm, o, done); |
module Thor_multiplier(rst, clk, ld, abort, sgn, isMuli, a, b, imm, o, done, idle); |
parameter WID=64; |
parameter SGNADJO=3'd2; |
parameter MULT=3'd3; |
34,6 → 34,7
input clk; |
input rst; |
input ld; |
input abort; |
input sgn; |
input isMuli; |
input [WID-1:0] a; |
42,6 → 43,7
output [WID*2-1:0] o; |
reg [WID*2-1:0] o; |
output done; |
output idle; |
|
reg [WID-1:0] aa,bb; |
reg so; |
49,6 → 51,7
reg [7:0] cnt; |
wire cnt_done = cnt==8'd0; |
assign done = 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]; |
70,7 → 73,9
end |
else |
begin |
if (!cnt_done) |
if (abort) |
cnt <= 8'd00; |
else if (!cnt_done) |
cnt <= cnt - 8'd1; |
|
case(state) |
/trunk/rtl/verilog/Thor_defines.v
37,6 → 37,8
//`define DEBUG_LOGIC 1'b1 |
//`define THREEWAY 1'b1 |
//`define TRAP_ILLEGALOPS 1'b1 |
//`define PRIVCHKS 1'b1 |
//`define PCHIST 1'b1 // Primarily for debugging the processor |
|
`define TRUE 1'b1 |
`define FALSE 1'b0 |
65,6 → 67,8
`define _16ADDU 6'h0B |
`define MIN 6'h10 |
`define MAX 6'h11 |
`define MOD 6'h13 |
`define MODU 6'h17 |
`define R2 8'h41 |
`define CPUID 4'h0 |
`define REDOR 4'h1 // reduction or |
116,7 → 120,10
`define SHRUI 6'h13 |
`define ROLI 6'h14 |
`define RORI 6'h15 |
`define MODI 8'h5B |
`define MODUI 8'h5F |
|
`define LLA 8'h6A // compute linear address |
`define _2ADDUI 8'h6B |
`define _4ADDUI 8'h6C |
`define _8ADDUI 8'h6D |
248,6 → 255,7
`define LHUX 8'hB5 |
`define LWX 8'hB6 |
`define JMPIX 8'hB7 |
`define LLAX 8'hB8 |
|
`define SBX 8'hC0 |
`define SCX 8'hC1 |