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 9 to Rev 10
- ↔ Reverse comparison
Rev 9 → Rev 10
/trunk/rtl/verilog/Thor.v
199,6 → 199,7
reg fxe; |
reg nmi1,nmi_edge; |
reg StatusHWI; |
reg StatusDBG; |
reg [7:0] StatusEXL; |
assign km = StatusHWI | |StatusEXL; |
reg [7:0] GM; // register group mask |
207,6 → 208,7
wire int_commit; |
wire int_pending; |
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]; |
236,7 → 238,14
reg iqentry_bt [0:7]; // branch-taken (used only for branches) |
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 |
reg iqentry_cas [0:7]; |
reg iqentry_pushpop [0:7]; |
reg iqentry_pea [0:7]; |
reg iqentry_cmpmv [0:7]; |
reg iqentry_tlb [0:7]; |
reg iqentry_jmp [0:7]; // changes control flow: 1 if BEQ/JALR |
reg iqentry_jmpi [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 |
252,14 → 261,18
reg [6: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 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 [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 [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]; |
reg [DBW-1:0] iqentry_T [0:7]; |
reg iqentry_T_v [0:7]; |
reg [3:0] iqentry_T_s [0:7]; |
434,6 → 447,8
wire alu1_branchmiss; |
reg [ABW+3:0] alu1_misspc; |
|
wire jmpi_miss; |
reg [ABW-1:0] jmpi_misspc; |
wire mem_stringmissx; |
reg mem_stringmiss; |
wire branchmiss; |
946,10 → 961,12
fnRa = {3'h5,isn[23:20]}; |
`TLB: fnRa = {1'b0,isn[29:24]}; |
`P: fnRa = 7'h70; |
`LOOP: fnRa = 7'h5F; |
`LOOP: fnRa = 7'h73; |
`PUSH: fnRa = km ? 7'd31 : 7'd27; |
`ifdef STACKOPS |
`PUSH,`PEA,`POP,`LINK: fnRa = 7'd27; |
`PEA,`POP,`LINK: fnRa = km ? 7'd31 : 7'd27; |
`endif |
`MFSPR,`MOVS: fnRa = {1'b1,isn[`INSTRUCTION_RA]}; |
default: fnRa = {1'b0,isn[`INSTRUCTION_RA]}; |
endcase |
endcase |
961,17 → 978,14
fnRb = 7'h51; |
else |
case(isn[15:8]) |
`RTI: fnRb = 7'h5E; |
`RTD: fnRb = 7'h5B; |
`RTE: fnRb = 7'h5D; |
`RTS2: fnRb = 7'd27; |
`LOOP: fnRb = 7'h73; |
`RTS,`STP,`TLB,`POP: fnRb = 7'd0; |
`RTS2: fnRb = km ? 7'd31 : 7'd27; |
// `LOOP: fnRb = 7'h73; |
// `RTS,`STP,`TLB,`POP: fnRb = 7'd0; |
`JSR,`JSRS,`JSRZ,`SYS,`INT: |
fnRb = {3'h5,isn[23:20]}; |
`SWS: fnRb = {1'b1,isn[27:22]}; |
`PUSH: fnRb = isn[22:16]; |
`ifdef STACKOPS |
`PUSH: fnRb = isn[22:16]; |
`LINK: fnRb = {1'b0,isn[27:22]}; |
`PEA: fnRb = {1'b0,isn[21:16]}; |
`endif |
1006,6 → 1020,10
else |
case(isn[15:8]) |
`BITFIELD: fnFunc = isn[43:40]; |
`R: fnFunc = isn[31:28]; |
`R2: fnFunc = isn[31:28]; |
`DOUBLE_R: fnFunc = isn[31:28]; |
`SINGLE_R: fnFunc = isn[31:28]; |
8'h10: fnFunc = isn[31:28]; |
8'h11: fnFunc = isn[31:28]; |
8'h12: fnFunc = isn[31:28]; |
1039,8 → 1057,12
8'h0E: fnFunc = isn[23:22]; |
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 |
`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]}; |
`JMPIX: fnFunc = {isn[39:37],1'b0,isn[33:32]}; |
default: |
fnFunc = isn[39:34]; |
endcase |
1143,7 → 1165,7
`LDI,`LDIS,`IMM,`NOP,`STP: fnSource2_v = 1'b1; |
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC: |
fnSource2_v = 1'b1; |
`RTI,`RTD,`RTE: fnSource2_v = 1'b1; |
`RTI,`RTD,`RTE,`JMPI: fnSource2_v = 1'b1; |
// TST |
8'h00: fnSource2_v = 1'b1; |
8'h01: fnSource2_v = 1'b1; |
1212,7 → 1234,7
fnSource2_v = `FALSE; |
`CACHE,`LCL,`TLB, |
`LVB,`LVC,`LVH,`LVW,`LVWAR, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`LEA,`STI,`INC: |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`STI,`INC: |
fnSource2_v = 1'b1; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS: |
fnSource2_v = 1'b1; |
1223,7 → 1245,7
fnSource2_v = 1'b0; |
else |
fnSource2_v = 1'b1; |
`LOOP: fnSource2_v = 1'b0; |
`LOOP: fnSource2_v = 1'b1; |
default: fnSource2_v = 1'b0; |
endcase |
endfunction |
1267,7 → 1289,7
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`MOVS,`STP: |
fnNumReadPorts = 3'd0; |
`LDI,`LDIS,`IMM: fnNumReadPorts = 3'd0; |
`R,`P,`STI: fnNumReadPorts = 3'd1; |
`R,`P,`STI,`LOOP,`JMPI: fnNumReadPorts = 3'd1; |
`RTI,`RTD,`RTE: fnNumReadPorts = 3'd1; |
`ADDI,`ADDUI,`ADDUIS: |
fnNumReadPorts = 3'd1; |
1284,7 → 1306,7
else |
fnNumReadPorts = 3'd2; |
`RTS2,`CACHE,`LCL,`TLB, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,`LWS,`LEA,`INC: |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,`LWS,`INC: |
fnNumReadPorts = 3'd1; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`BR: |
fnNumReadPorts = 3'd1; |
1513,10 → 1535,15
// 68-6F = segment limit register |
// 70 = predicate register horizontal |
// 73 = loop counter |
// 7C = breakout index register |
// 7D = broken out register |
// 7F = power shift register |
function [6:0] fnTargetReg; |
input [63:0] ir; |
begin |
if (ir[3:0]==4'h0) // Process special predicates |
// 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; |
else |
case(fnOpcode(ir)) |
1533,12 → 1560,12
fnTargetReg = {1'b0,ir[33:28]}; |
`SHIFT: |
fnTargetReg = {1'b0,ir[33:28]}; |
`R,`DOUBLE_R,`SINGLE_R, |
`R,`R2,`DOUBLE_R,`SINGLE_R, |
`ADDI,`ADDUI,`SUBI,`SUBUI,`MULI,`MULUI,`DIVI,`DIVUI, |
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI, |
`ANDI,`ORI,`EORI, |
`LVB,`LVC,`LVH,`LVW,`LVWAR, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LEA,`LINK: |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LINK: |
fnTargetReg = {1'b0,ir[27:22]}; |
`CAS: |
fnTargetReg = {1'b0,ir[39:34]}; |
1554,56 → 1581,20
`BITI: |
fnTargetReg = {3'h4,ir[25:22]}; |
// TST |
8'h00, |
8'h01, |
8'h02, |
8'h03, |
8'h04, |
8'h05, |
8'h06, |
8'h07, |
8'h08, |
8'h09, |
8'h0A, |
8'h0B, |
8'h0C, |
8'h0D, |
8'h0E, |
8'h0F, |
8'h00,8'h01,8'h02,8'h03, |
8'h04,8'h05,8'h06,8'h07, |
8'h08,8'h09,8'h0A,8'h0B, |
8'h0C,8'h0D,8'h0E,8'h0F, |
// CMP |
8'h10, |
8'h11, |
8'h12, |
8'h13, |
8'h14, |
8'h15, |
8'h16, |
8'h17, |
8'h18, |
8'h19, |
8'h1A, |
8'h1B, |
8'h1C, |
8'h1D, |
8'h1E, |
8'h1F, |
8'h10,8'h11,8'h12,8'h13, |
8'h14,8'h15,8'h16,8'h17, |
8'h18,8'h19,8'h1A,8'h1B, |
8'h1C,8'h1D,8'h1E,8'h1F, |
// CMPI |
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: |
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 |
fnTargetReg = {3'h4,ir[11:8]}; |
end |
1610,6 → 1601,10
`SWCR: fnTargetReg = {3'h4,4'h0}; |
`JSR,`JSRZ,`JSRS,`SYS,`INT: |
fnTargetReg = {3'h5,ir[19:16]}; |
`JMPI: |
fnTargetReg = {3'h5,ir[25:22]}; |
`JMPIX: |
fnTargetReg = {3'h5,ir[31:28]}; |
`MTSPR,`MOVS,`LWS: |
fnTargetReg = {1'b1,ir[27:22]}; |
/* |
1622,7 → 1617,7
else |
fnTargetReg = 7'h00; |
*/ |
`RTS2: fnTargetReg = 7'd27; |
`RTS2,`PUSH: fnTargetReg = km ? 7'd31 : 7'd27; |
`LOOP: fnTargetReg = 7'h73; |
`STP: fnTargetReg = 7'h7F; |
`P: fnTargetReg = 7'h70; |
1645,6 → 1640,8
case(fnOpcode(ir)) |
`JSR,`JSRZ,`JSRS,`SYS,`INT: |
fnTargetsCa = `TRUE; |
`JMPI,`JMPIX: |
fnTargetsCa = `TRUE; |
`LWS: |
if (ir[27:26]==2'h1) |
fnTargetsCa = `TRUE; |
1701,44 → 1698,21
`ADDI,`SUBI,`ADDUI,`SUBUI,`MULI,`MULUI,`DIVI,`DIVUI, |
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI, |
// CMPI |
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, |
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, |
// BR |
8'h30, |
8'h31, |
8'h32, |
8'h33, |
8'h34, |
8'h35, |
8'h36, |
8'h37, |
8'h38, |
8'h39, |
8'h3A, |
8'h3B, |
8'h3C, |
8'h3D, |
8'h3E, |
8'h3F, |
8'h30,8'h31,8'h32,8'h33, |
8'h34,8'h35,8'h36,8'h37, |
8'h38,8'h39,8'h3A,8'h3B, |
8'h3C,8'h3D,8'h3E,8'h3F, |
`ANDI,`ORI,`EORI,`BITI, |
// `SHLI,`SHLUI,`SHRI,`SHRUI,`ROLI,`RORI, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`LEA,`INC, |
`LVB,`LVC,`LVH,`LVW,`LVWAR,`STI, |
`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: |
fnHasConst = 1'b1; |
default: |
1746,10 → 1720,12
endcase |
endfunction |
|
// Used by memory issue logic. |
function fnIsFlowCtrl; |
input [7:0] opcode; |
begin |
case(opcode) |
`JMPI,`JMPIX, |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`LOOP,`RTS,`RTS2,`RTI,`RTD,`RTE: |
fnIsFlowCtrl = 1'b1; |
default: |
1762,7 → 1738,7
endfunction |
|
// fnCanException |
// Used by issue logic. |
// Used by memory issue logic. |
// Returns TRUE if the instruction can cause an exception |
// |
function fnCanException; |
1909,6 → 1885,7
opcode==`TLB || opcode==`CAS || opcode==`STMV || opcode==`STCMP || opcode==`STFND || |
opcode==`LWS || opcode==`SWS || opcode==`STI || |
opcode==`INC || |
opcode==`JMPI || opcode==`JMPIX || |
opcode==`PUSH || opcode==`POP || opcode==`PEA || opcode==`LINK || opcode==`UNLINK |
; |
endfunction |
1916,7 → 1893,8
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==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX || |
opcode==`JMPIX |
; |
endfunction |
|
1931,13 → 1909,15
opcode==`LVB || opcode==`LVH || opcode==`LVC || opcode==`LVW || opcode==`LVWAR || opcode==`SWCR || |
opcode==`RTS2 || opcode==`STP || |
opcode==`CAS || opcode==`LWS || opcode==`STMV || opcode==`STCMP || opcode==`STFND || |
opcode==`STS || opcode==`POP || opcode==`LINK || opcode==`UNLINK || |
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==`_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==`LEA || opcode==`P || opcode==`LOOP || |
opcode==`R || opcode==`RR || opcode==`P || opcode==`LOOP || |
opcode==`BITI || opcode==`CMP || opcode==`CMPI || opcode==`TST || |
opcode==`LDI || opcode==`LDIS || opcode==`ADDUIS || opcode==`MFSPR || |
// Branch registers / Segment registers |
1965,7 → 1945,7
fnIsLoad = 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==`LVC || opcode==`LVH || opcode==`LVW || opcode==`LVWAR || opcode==`LCL || |
opcode==`LWS || opcode==`UNLINK || |
opcode==`LWS || opcode==`UNLINK || opcode==`JMPI || opcode==`JMPIX || |
opcode==`POP; |
endfunction |
|
1977,7 → 1957,7
function fnIsIndexed; |
input [7:0] opcode; |
fnIsIndexed = opcode==`LBX || opcode==`LBUX || opcode==`LCX || opcode==`LCUX || opcode==`LHX || opcode==`LHUX || opcode==`LWX || |
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX; |
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX || opcode==`JMPIX; |
endfunction |
|
// |
2043,11 → 2023,11
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'h8D: |
8'h87,8'h88,8'h89,8'h8A: |
fnIsIllegal = `TRUE; |
8'h94,8'h95,8'h9C: |
fnIsIllegal = `TRUE; |
8'hB7,8'b10111xxx: |
8'b10111xxx: |
fnIsIllegal = `TRUE; |
8'hC4,8'hC5,8'b11001xxx: |
fnIsIllegal = `TRUE; |
2083,6 → 2063,17
fnSelect = 8'hFF; |
default: fnSelect = 8'h00; |
endcase |
`JMPI,`JMPIX: |
case(fn[1:0]) |
2'd1: |
case(adr[1]) |
1'b0: fnSelect = 8'h33; |
1'b1: fnSelect = 8'hCC; |
endcase |
2'd2: fnSelect = 8'hFF; |
2'd3: fnSelect = 8'hFF; |
default: fnSelect = 8'h00; |
endcase |
`LB,`LBU,`LBX,`LBUX,`SB,`SBX,`LVB: |
case(adr[1:0]) |
3'd0: fnSelect = 8'h11; |
2133,7 → 2124,24
fnSelect = 8'hFF; |
default: fnSelect = 8'h00; |
endcase |
`LB,`LBU,`LBX,`SB,`LVB,`LBUX,`SBX: |
`JMPI,`JMPIX: |
case(fn[1:0]) |
2'd1: |
case(adr[2:1]) |
2'd0: fnSelect = 8'h03; |
2'd1: fnSelect = 8'h0C; |
2'd2: fnSelect = 8'h30; |
2'd3: fnSelect = 8'hC0; |
endcase |
2'd2: |
case(adr[2]) |
1'b0: fnSelect = 8'h0F; |
1'b1: fnSelect = 8'hF0; |
endcase |
2'd3: fnSelect = 8'hFF; |
default: fnSelect = 8'h00; |
endcase |
`LB,`LBU,`LBX,`SB,`LVB,`LBUX,`SBX: |
case(adr[2:0]) |
3'd0: fnSelect = 8'h01; |
3'd1: fnSelect = 8'h02; |
2191,6 → 2199,17
default: |
fnDatai = dat[31:0]; |
endcase |
`JMPI,`JMPIX: |
case(func[1:0]) |
2'd1: |
case(sel[3:0]) |
4'h3: fnDatai = dat[15:0]; |
4'hC: fnDatai = dat[31:16]; |
default: fnDatai = {DBW{1'b1}}; |
endcase |
2'd2: fnDatai = dat[31:0]; |
default: fnDatai = dat[31:0]; |
endcase |
`LB,`LBX,`LVB: |
case(sel[3:0]) |
8'h1: fnDatai = {{24{dat[7]}},dat[7:0]}; |
2255,6 → 2274,25
endcase |
3'd3,3'd7: fnDatai = dat; |
endcase |
`JMPI,`JMPIX: |
case(func[1:0]) |
2'd1: |
case(sel[7:0]) |
8'h03: fnDatai = dat[15:0]; |
8'h0C: fnDatai = dat[31:16]; |
8'h30: fnDatai = dat[47:32]; |
8'hC0: fnDatai = dat[63:48]; |
default: fnDatai = dat[15:0]; |
endcase |
2'd2: |
case(sel[7:0]) |
8'h0F: fnDatai = dat[31:0]; |
8'hF0: fnDatai = dat[63:32]; |
default: fnDatai = dat[31:0]; |
endcase |
2'd3: fnDatai = dat; |
default: fnDatai = dat; |
endcase |
`LB,`LBX,`LVB: |
case(sel) |
8'h01: fnDatai = {{DBW*7/8{dat[DBW*1/8-1]}},dat[DBW*1/8-1:0]}; |
2385,31 → 2423,19
// (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 |
if (ihit) |
branch_pc <= fetchbuf0_pc + {{ABW-12{fetchbuf0_instr[11]}},fetchbuf0_instr[11:8],fetchbuf0_instr[23:16]} + 64'd3; |
else |
branch_pc <= fetchbuf0_pc; |
branch_pc <= fetchbuf0_pc + {{ABW-12{fetchbuf0_instr[11]}},fetchbuf0_instr[11:8],fetchbuf0_instr[23:16]} + 64'd3; |
end |
else if (opcode0==`LOOP && fetchbuf0_v) begin |
if (ihit) |
branch_pc <= fetchbuf0_pc + {{ABW-8{fetchbuf0_instr[23]}},fetchbuf0_instr[23:16]} + 64'd3; |
else |
branch_pc <= fetchbuf0_pc; |
branch_pc <= fetchbuf0_pc + {{ABW-8{fetchbuf0_instr[23]}},fetchbuf0_instr[23:16]} + 64'd3; |
end |
else if (fnIsBranch(opcode1) && fetchbuf1_v && predict_taken1) begin |
if (ihit) |
branch_pc <= fetchbuf1_pc + {{ABW-12{fetchbuf1_instr[11]}},fetchbuf1_instr[11:8],fetchbuf1_instr[23:16]} + 64'd3; |
else |
branch_pc <= fetchbuf1_pc; |
branch_pc <= fetchbuf1_pc + {{ABW-12{fetchbuf1_instr[11]}},fetchbuf1_instr[11:8],fetchbuf1_instr[23:16]} + 64'd3; |
end |
else if (opcode1==`LOOP && fetchbuf1_v) begin |
if (ihit) |
branch_pc <= fetchbuf1_pc + {{ABW-8{fetchbuf1_instr[23]}},fetchbuf1_instr[23:16]} + 64'd3; |
else |
branch_pc <= fetchbuf1_pc; |
branch_pc <= fetchbuf1_pc + {{ABW-8{fetchbuf1_instr[23]}},fetchbuf1_instr[23:16]} + 64'd3; |
end |
else begin |
branch_pc <= {{ABW-8{1'b1}},8'h80}; // set to something to prevent a latch |
branch_pc <= RSTADDR; // set to something to prevent a latch |
end |
|
assign int_pending = (nmi_edge & ~StatusHWI & ~int_commit) || (irq_i & ~im & ~StatusHWI & ~int_commit); |
2417,6 → 2443,8
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 jmpi_miss = dram_v && (dram0_op==`JMPI || dram0_op==`JMPIX); |
|
// "Stream" interrupt instructions into the instruction stream until an INT |
// instruction commits. This avoids the problem of an INT instruction being |
// stomped on by a previous branch instruction. |
2511,28 → 2539,18
`SYS,`INT: fnImm = insn[31:24]; |
`RTS2: fnImm = {insn[31:27],3'b000}; |
//`CMPI, |
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, |
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, |
`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 = 8'h00; |
`RTD,`RTE,`RTI,`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, |
`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]}; |
2558,29 → 2576,19
`BITFIELD: fnImm8 = insn[39:32]; |
`SYS,`INT: fnImm8 = insn[31:24]; |
//`CMPI, |
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, |
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, |
`LDI,`LDIS,`ADDUIS: fnImm8 = insn[29:22]; |
`RTS: fnImm8 = insn[19:16]; |
`RTD,`RTE,`RTI,`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, |
`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]; |
2605,22 → 2613,10
`JSRS: |
fnImmMSB = insn[39]; |
//`CMPI, |
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, |
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, |
`LDI,`LDIS,`ADDUIS: |
fnImmMSB = insn[31]; |
`SYS,`INT,`CACHE,`LINK: |
2627,9 → 2623,11
fnImmMSB = 1'b0; // SYS,INT are unsigned |
`RTS,`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, |
`SBX,`SCX,`SHX,`SWX: |
fnImmMSB = insn[47]; |
`JMPI, |
`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]; |
2655,8 → 2653,11
|
|
// Used during enque |
// Operand A is a little more work than B or C as it may read from special |
// purpose registers. |
function [63:0] fnOpa; |
input [7:0] opcode; |
input [6:0] Ra; |
input [63:0] ins; |
input [63:0] rfo; |
input [63:0] epc; |
2666,28 → 2667,42
fnOpa = ins[21:16]; |
else |
`endif |
if (opcode==`RTS) begin |
fnOpa = (commit1_v && commit1_tgt[6:0]==7'h51) ? commit1_bus : |
(commit0_v && commit0_tgt[6:0]==7'h51) ? commit0_bus : |
cregs[3'd1]; |
end |
else if (opcode==`LOOP) |
fnOpa = epc; |
else if (fnIsFlowCtrl(opcode)) |
fnOpa = fnCar(ins)==4'd0 ? 64'd0 : fnCar(ins)==4'd15 ? epc : |
(commit1_v && commit1_tgt[6:4]==3'h5 && commit1_tgt[3:0]==fnCar(ins)) ? commit1_bus : |
(commit0_v && commit0_tgt[6:4]==3'h5 && commit0_tgt[3:0]==fnCar(ins)) ? commit0_bus : |
cregs[fnCar(ins)]; |
else if (opcode==`P) |
fnOpa = fnSpr(6'h30,epc); |
else if (opcode==`MFSPR || opcode==`MOVS) |
fnOpa = fnSpr(ins[`INSTRUCTION_RA],epc); |
if (Ra[6]) |
fnOpa = fnSpr(Ra[5:0],epc); |
else |
fnOpa = rfo; |
end |
endfunction |
|
function [DBW-1:0] fnOpb; |
input [7:0] opcode; |
input [6:0] Rb; |
input [63:0] ins; |
input [63:0] rfo; |
input [63:0] epc; |
begin |
fnOpb = fnIsShiftiop(ins) ? {{DBW-6{1'b0}},ins[`INSTRUCTION_RB]} : |
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) : |
rfo; |
end |
endfunction |
|
// Used during enque |
function [63:0] fnOpt; |
input [6:0] tgt; |
input [63:0] rfo; |
input [63:0] epc; |
begin |
if (tgt[6]) |
fnOpt = fnSpr(tgt[5:0],epc); |
else |
fnOpt = rfo; |
end |
endfunction |
|
// Returns TRUE if instruction is only allowed in kernel mode. |
function fnIsKMOnly; |
input [7:0] op; |
2699,7 → 2714,8
function fnIsKMOnlyReg; |
input [6:0] regx; |
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'h5B || regx==7'h5C || regx==7'h5D || regx==7'h5E || |
regx==7'h60 || regx==7'h68; |
endfunction |
|
// Returns TRUE if the register is automatically valid. |
3512,6 → 3528,12
(iqentry_tgt[head0][3:0]==4'hD || iqentry_tgt[head0][3:0]==4'hB))) && commit0_v) || |
(commit0_v && (iqentry_op[head1]==`SYS || (iqentry_op[head1]==`INT && |
(iqentry_tgt[head1][3:0]==4'hD || iqentry_tgt[head1][3:0]==4'hB))) && commit1_v); |
`ifdef DEBUG_LOGIC |
assign dbg_commit = (((iqentry_op[head0]==`SYS && iqentry_tgt[head0][3:0]==4'hB) || |
(iqentry_op[head0]==`INT && (iqentry_tgt[head0][3:0]==4'hB))) && commit0_v) || |
(commit0_v && ((iqentry_op[head1]==`SYS && iqentry_tgt[head1][3:0]==4'hB)|| |
(iqentry_op[head1]==`INT && (iqentry_tgt[head1][3:0]==4'hB))) && commit1_v); |
`endif |
|
always @(posedge clk) |
if (rst_i) |
3779,11 → 3801,13
else begin |
if (iqentry_op[alu0_id[2:0]]!=`IMM) |
iqentry_done[ alu0_id[2:0] ] <= (!iqentry_mem[ alu0_id[2:0] ] || !alu0_cmt); |
iqentry_res [ alu0_id[2:0] ] <= alu0_bus; |
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; |
iqentry_out [ alu0_id[2:0] ] <= `FALSE; |
end |
end |
|
3807,11 → 3831,13
else begin |
if (iqentry_op[alu1_id[2:0]]!=`IMM) |
iqentry_done[ alu1_id[2:0] ] <= (!iqentry_mem[ alu1_id[2:0] ] || !alu1_cmt); |
iqentry_res [ alu1_id[2:0] ] <= alu1_bus; |
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; |
iqentry_out [ alu1_id[2:0] ] <= `FALSE; |
end |
end |
|
4155,16 → 4181,19
// |
if (dram_v && iqentry_v[ dram_id[2:0] ] && iqentry_mem[ dram_id[2:0] ] ) begin // if data for stomped instruction, ignore |
$display("dram results to iq[%d]=%h", dram_id[2:0],dram_bus); |
iqentry_res [ dram_id[2:0] ] <= dram_bus; |
if (!iqentry_jmpi[dram_id[2:0]]) |
iqentry_res [ dram_id[2:0] ] <= dram_bus; |
// If an exception occurred, stuff an interrupt instruction into the queue |
// 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) |
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; |
end |
else begin |
// Note that the predicate was already evaluated to TRUE before the |
// dram operation started. |
4183,19 → 4212,19
// What if there's a databus error during the store ? |
// set the IQ entry == DONE as soon as the SW is let loose to the memory system |
// |
if (dram0 == 2'd2 && fnIsStore(dram0_op) && dram0_op != `STS) begin |
if (dram0 == 2'd2 && fnIsStore(dram0_op) && dram0_op != `STS && dram0_op != `STMV) begin |
if ((alu0_v && dram0_id[2:0] == alu0_id[2:0]) || (alu1_v && dram0_id[2:0] == alu1_id[2:0])) panic <= `PANIC_MEMORYRACE; |
iqentry_done[ dram0_id[2:0] ] <= `TRUE; |
iqentry_cmt [ dram0_id[2:0]] <= `TRUE; |
iqentry_out[ dram0_id[2:0] ] <= `FALSE; |
end |
if (dram1 == 2'd2 && fnIsStore(dram1_op) && dram1_op != `STS) begin |
if (dram1 == 2'd2 && fnIsStore(dram1_op) && dram1_op != `STS && dram1_op != `STMV) begin |
if ((alu0_v && dram1_id[2:0] == alu0_id[2:0]) || (alu1_v && dram1_id[2:0] == alu1_id[2:0])) panic <= `PANIC_MEMORYRACE; |
iqentry_done[ dram1_id[2:0] ] <= `TRUE; |
iqentry_cmt [ dram1_id[2:0]] <= `TRUE; |
iqentry_out[ dram1_id[2:0] ] <= `FALSE; |
end |
if (dram2 == 2'd2 && fnIsStore(dram2_op) && dram2_op != `STS) begin |
if (dram2 == 2'd2 && fnIsStore(dram2_op) && dram2_op != `STS && dram2_op != `STMV) begin |
if ((alu0_v && dram2_id[2:0] == alu0_id[2:0]) || (alu1_v && dram2_id[2:0] == alu1_id[2:0])) panic <= `PANIC_MEMORYRACE; |
iqentry_done[ dram2_id[2:0] ] <= `TRUE; |
iqentry_cmt [ dram2_id[2:0]] <= `TRUE; |
4414,10 → 4443,7
: 64'hDEADDEADDEADDEAD; |
alu0_argC <= |
`ifdef SEGMENTATION |
`ifdef STACKOPS |
(iqentry_op[n]==`POP || iqentry_op[n]==`PUSH || iqentry_op[n]==`PEA) ? {sregs[3'd6],12'h000} : |
`endif |
(iqentry_mem[n] && iqentry_op[n]!=`STCMP && iqentry_op[n]!=`STMV) ? {sregs[iqentry_fn[n][5:3]],12'h000} : |
(iqentry_mem[n] && !iqentry_cmpmv[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 |
4452,10 → 4478,7
: 64'hDEADDEADDEADDEAD; |
alu1_argC <= |
`ifdef SEGMENTATION |
`ifdef STACKOPS |
(iqentry_op[n]==`POP || iqentry_op[n]==`PUSH || iqentry_op[n]==`PEA) ? {sregs[3'd6],12'h000} : |
`endif |
(iqentry_mem[n] && iqentry_op[n]!=`STCMP && iqentry_op[n]!=`STMV)? {sregs[iqentry_fn[n][5:3]],12'h000} : |
(iqentry_mem[n] && !iqentry_cmpmv[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 |
4472,7 → 4495,7
endcase |
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_op[n]!=`TLB) begin |
if (iqentry_mem[n] && !iqentry_tlb[n]) begin |
iqentry_a1_v[n] <= `INV; |
iqentry_a1_s[n] <= n[3:0]; |
end |
4565,6 → 4588,7
dram0 <= 3'd0; |
end |
`ifdef SEGMENTATION |
`ifdef SEGLIMITS |
else if (dram0_addr[ABW-1:12] >= dram0_lmt) begin |
dram_v <= `TRUE; // we are finished the memory cycle |
dram_id <= dram0_id; |
4574,6 → 4598,7
dram0 <= 3'd0; |
end |
`endif |
`endif |
else if (!cyc_o) dram0 <= dram0 + 3'd1; |
end |
|
4901,7 → 4926,7
// for rf_v[]. |
// |
for (n = 0; n < QENTRIES; n = n + 1) |
if (!iqentry_stomp[n] && iqentry_memissue[n] && iqentry_agen[n] && iqentry_op[n]==`TLB && !iqentry_out[n]) begin |
if (!iqentry_stomp[n] && iqentry_memissue[n] && iqentry_agen[n] && iqentry_tlb[n] && !iqentry_out[n]) begin |
$display("TLB issue"); |
if (!iqentry_cmt[n]) begin |
iqentry_done[n] <= `TRUE; |
4943,14 → 4968,14
dram0_op <= iqentry_op[n]; |
dram0_fn <= iqentry_fn[n]; |
dram0_tgt <= iqentry_tgt[n]; |
dram0_data <= (fnIsIndexed(iqentry_op[n]) || iqentry_op[n]==`CAS) ? iqentry_a3[n] : |
dram0_data <= (iqentry_ndx[n] || iqentry_cas[n]) ? iqentry_a3[n] : |
`ifdef STACKOPS |
iqentry_op[n]==`PEA ? iqentry_a2[n] + iqentry_a0[n] : |
iqentry_pea[n] ? iqentry_a2[n] + iqentry_a0[n] : |
`endif |
iqentry_a2[n]; |
dram0_datacmp <= iqentry_a2[n]; |
`ifdef SEGMENTATION |
if (iqentry_op[n]==`STCMP || iqentry_op[n]==`STMV) |
if (iqentry_cmpmv[n]) |
dram0_addr <= iqentry_a1[n] + {sregs[iqentry_fn[n][5:3]],12'h000}; |
else |
dram0_addr <= iqentry_a1[n]; |
4981,30 → 5006,8
((iqentry_pc[(n+1)&7]==iqentry_pc[n]+iqentry_insnsz[n]) || |
(iqentry_pc[(n+1)&7]==iqentry_pc[n]))) // address inherited due to interrupt |
iqentry_done[n] <= `TRUE; |
/* |
if (iqentry_v[n] && args_valid[n] && !iqentry_out[n] && !iq_cmt[n] && iqentry_op[n]!=`IMM) begin |
iqentry_done[n] <= `TRUE; |
iqentry_res[n] <= iqentry_T[n]; |
end |
*/ |
if (!iqentry_v[n]) |
iqentry_done[n] <= `FALSE; |
/* |
if (iqentry_v[n] && !iqentry_done[n]) begin |
if (!iqentry_a1_v[n] && iqentry_v[iqentry_a1_s[n][2:0]] && iqentry_done[iqentry_a1_s[n][2:0]]) begin |
iqentry_a1_v[n] <= `VAL; |
iqentry_a1[n] <= iqentry_res[iqentry_a1_s[n][2:0]]; |
end |
if (!iqentry_a2_v[n] && iqentry_v[iqentry_a2_s[n][2:0]] && iqentry_done[iqentry_a2_s[n][2:0]]) begin |
iqentry_a2_v[n] <= `VAL; |
iqentry_a2[n] <= iqentry_res[iqentry_a2_s[n][2:0]]; |
end |
if (!iqentry_a3_v[n] && iqentry_v[iqentry_a3_s[n][2:0]] && iqentry_done[iqentry_a3_s[n][2:0]]) begin |
iqentry_a3_v[n] <= `VAL; |
iqentry_a3[n] <= iqentry_res[iqentry_a3_s[n][2:0]]; |
end |
end |
*/ |
end |
|
|
5042,6 → 5045,14
StatusEXL <= StatusEXL + 8'd1; |
end |
|
// On a debug commit set status StatusDBG to prevent further single stepping. |
`ifdef DEBUG_LOGIC |
if (dbg_commit) |
begin |
StatusDBG <= `TRUE; |
end |
`endif |
|
oddball_commit(commit0_v,head0); |
oddball_commit(commit1_v,head1); |
|
5460,6 → 5471,7
6'd3: dbg_adr3 <= commit_bus; |
6'd4: dbg_ctrl <= commit_bus; |
6'd5: dbg_stat <= commit_bus; |
default: ; |
endcase |
6'b111111: |
begin |
5466,6 → 5478,7
ld_clk_throttle <= `TRUE; |
clk_throttle_new <= commit_bus[15:0]; |
end |
default: ; |
endcase |
end |
end |
5545,12 → 5558,15
endcase |
default: fnSpr = 64'd0; |
endcase |
|
// Not sure why bother read the commit bus here ? Why not the alu bus as well ? |
// Need bypassing for write-through register file, reg read at same time as write |
// 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; |
fnSpr = commit1_bus; |
|
// Special cases where the register would not be read from the commit bus |
case(regno) |
5577,11 → 5593,17
StatusHWI <= `FALSE; |
im <= imb; |
end |
`RTE,`RTD: |
`RTD: |
begin |
StatusDBG <= `FALSE; |
if (StatusEXL!=8'h00) |
StatusEXL <= StatusEXL - 8'd1; |
end |
`RTE: |
begin |
if (StatusEXL!=8'h00) |
StatusEXL <= StatusEXL - 8'd1; |
end |
`CACHE: |
begin |
case(iqentry_fn[head]) |
5612,11 → 5634,19
input [2:0] inc; |
input unlink; |
begin |
if (fetchbuf0_pc==32'h0) |
$stop; |
if (fetchbuf0_pc==32'hF44) |
$stop; |
if (fetchbuf0_pc==32'hFFFFda49) |
$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) |
set_exception(tail,8'd244); |
`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)) |
5663,7 → 5693,14
iqentry_agen [tail] <= `INV; |
iqentry_pc [tail] <= (opcode0==`INT && Rt0[3:0]==4'hE) ? interrupt_pc : fetchbuf0_pc; |
iqentry_mem [tail] <= fetchbuf0_mem; |
iqentry_ndx [tail] <= fnIsIndexed(opcode0); |
iqentry_cas [tail] <= opcode0==`CAS; |
iqentry_pushpop[tail] <= opcode0==`PUSH || opcode0==`POP; |
iqentry_pea [tail] <= opcode0==`PEA; |
iqentry_cmpmv[tail] <= opcode0==`STCMP || opcode0==`STMV; |
iqentry_tlb [tail] <= opcode0==`TLB; |
iqentry_jmp [tail] <= fetchbuf0_jmp; |
iqentry_jmpi [tail] <= opcode0==`JMPI || opcode0==`JMPIX; |
iqentry_fp [tail] <= fetchbuf0_fp; |
iqentry_rfw [tail] <= fetchbuf0_rfw; |
iqentry_tgt [tail] <= Rt0; |
5675,15 → 5712,18
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_a1 [tail] <= fnOpa(opcode0,fetchbuf0_instr,rfoa0,fetchbuf0_pc); |
iqentry_a2 [tail] <= fnIsShiftiop(fetchbuf0_instr) ? {{DBW-6{1'b0}},fetchbuf0_instr[`INSTRUCTION_RB]} : |
fnIsFPCtrl(fetchbuf0_instr) ? {{DBW-6{1'b0}},fetchbuf0_instr[`INSTRUCTION_RB]} : |
opcode0==`INC ? {{56{fetchbuf0_instr[47]}},fetchbuf0_instr[47:40]} : |
opcode0==`STI ? fetchbuf0_instr[27:22] : |
Rb0[6] ? fnSpr(Rb0[5:0],fetchbuf0_pc) : |
rfob0; |
// These register recordings for simulation debug. They should be stripped |
// out of synthesis because they don't drive any signals. |
`ifdef SIMULATION |
iqentry_r1 [tail] <= Ra0; |
iqentry_r2 [tail] <= Rb0; |
iqentry_r3 [tail] <= Rc0; |
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] <= rfot0; |
iqentry_T [tail] <= fnOpt(Rt0,rfot0,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}]; |
5724,7 → 5764,14
iqentry_agen [tail] <= `INV; |
iqentry_pc [tail] <= which ? fetchbuf1_pc : fetchbuf0_pc; |
iqentry_mem [tail] <= 1'b0; |
iqentry_ndx [tail] <= 1'b0; |
iqentry_cas [tail] <= 1'b0; |
iqentry_pushpop[tail] <= 1'b0; |
iqentry_pea [tail] <= 1'b0; |
iqentry_cmpmv[tail] <= 1'b0; |
iqentry_tlb [tail] <= 1'b0; |
iqentry_jmp [tail] <= 1'b0; |
iqentry_jmpi [tail] <= 1'b0; |
iqentry_fp [tail] <= 1'b0; |
iqentry_rfw [tail] <= 1'b1; |
iqentry_tgt [tail] <= 7'd27; |
5764,13 → 5811,25
input test_stomp; |
input validate_args; |
begin |
if (opcode0==`NOP) |
queued1 = `TRUE; // to update fetch buffers |
if (`FALSE) |
; |
// if (opcode0==`NOP) |
// queued1 = `TRUE; // to update fetch buffers |
`ifdef DEBUG_LOGIC |
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); |
allowq = `FALSE; |
end |
end |
`endif |
`ifdef STACKOPS |
// A pop instruction takes 2 queue entries. |
else if (fnIsPop(fetchbuf0_instr)|fnIsPush(fetchbuf0_instr)|opcode0==`LINK) begin |
$display("0 found push/pop"); |
if (iqentry_v[tail]==`INV && iqentry_v[tail+1]==`INV) begin |
if (iqentry_v[tail]==`INV && iqentry_v[(tail+1)&7]==`INV) begin |
$display("enqueing2"); |
enque0a(tail,3'd2,1'b0); |
enquePushpopAdd((tail+1)&7,fnIsPop(fetchbuf0_instr),opcode0==`LINK,0,0); |
5777,6 → 5836,7
allowq = `FALSE; |
end |
end |
`ifdef UNLINKOP |
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); |
5785,6 → 5845,7
end |
end |
`endif |
`endif |
else if (iqentry_v[tail] == `INV) begin |
if ((({fnIsBranch(opcode0), predict_taken0} == {`TRUE, `TRUE})||(opcode0==`LOOP)) && test_stomp) |
qstomp = `TRUE; |
5799,10 → 5860,18
input validate_args; |
input unlink; |
begin |
if (fetchbuf1_pc==32'h0) |
$stop; |
if (fetchbuf1_pc==32'hF44) |
$stop; |
if (fetchbuf1_pc==32'hFFFFDA49) |
$stop; |
`ifdef SEGMENTATION |
`ifdef SEGLIMITS |
if (fetchbuf1_pc >= {sregs_lmt[7],12'h000} && fetchbuf1_pc[ABW-1:ABW-4]!=4'hF) |
set_exception(tail,8'd244); |
`endif |
`endif |
if (fnIsKMOnlyReg(Rt1) && !km && !(opcode1==`SYS || opcode1==`INT)) |
set_exception(tail,8'd245); |
`ifdef TRAP_ILLEGALOPS |
5851,7 → 5920,14
|
iqentry_pc [tail] <= (opcode1==`INT && Rt1[3:0]==4'hE) ? interrupt_pc : fetchbuf1_pc; |
iqentry_mem [tail] <= fetchbuf1_mem; |
iqentry_ndx [tail] <= fnIsIndexed(opcode1); |
iqentry_cas [tail] <= opcode1==`CAS; |
iqentry_pushpop[tail] <= opcode1==`PUSH || opcode1==`POP; |
iqentry_pea [tail] <= opcode1==`PEA; |
iqentry_cmpmv[tail] <= opcode1==`STCMP || opcode1==`STMV; |
iqentry_tlb [tail] <= opcode1==`TLB; |
iqentry_jmp [tail] <= fetchbuf1_jmp; |
iqentry_jmpi [tail] <= opcode1==`JMPI || opcode1==`JMPIX; |
iqentry_fp [tail] <= fetchbuf1_fp; |
iqentry_rfw [tail] <= fetchbuf1_rfw; |
iqentry_tgt [tail] <= Rt1; |
5865,15 → 5941,16
(!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,fetchbuf1_instr,rfoa1,fetchbuf1_pc); |
iqentry_a2 [tail] <= fnIsShiftiop(fetchbuf1_instr) ? {{DBW-6{1'b0}},fetchbuf1_instr[`INSTRUCTION_RB]} : |
fnIsFPCtrl(fetchbuf1_instr) ? {{DBW-6{1'b0}},fetchbuf1_instr[`INSTRUCTION_RB]} : |
opcode1==`INC ? {{56{fetchbuf1_instr[47]}},fetchbuf1_instr[47:40]} : |
opcode1==`STI ? fetchbuf1_instr[27:22] : |
Rb1[6] ? fnSpr(Rb1[5:0],fetchbuf1_pc) : |
rfob1; |
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] <= rfot1; |
iqentry_T [tail] <= fnOpt(Rt1,rfot1,fetchbuf1_pc); |
`ifdef SIMULATION |
iqentry_r1 [tail] <= Ra1; |
iqentry_r2 [tail] <= Rb1; |
iqentry_r3 [tail] <= Rc1; |
iqentry_rt [tail] <= Rt1; |
`endif |
// The source is set even though the arg might be automatically valid (less logic). If |
// queueing two entries the source settings may be overridden in the argument valudation. |
iqentry_p_s [tail] <= rf_source[{1'b1,2'h0,Pn1}]; |
5898,10 → 5975,22
input test_stomp; |
input validate_args; |
begin |
if (opcode1==`NOP) begin |
if (queued1==`TRUE) queued2 = `TRUE; |
queued1 = `TRUE; |
if (`FALSE) |
; |
// if (opcode1==`NOP) begin |
// if (queued1==`TRUE) queued2 = `TRUE; |
// queued1 = `TRUE; |
// end |
`ifdef DEBUG_LOGIC |
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); |
allowq = `FALSE; |
end |
end |
`endif |
`ifdef STACKOPS |
else if (fnIsPop(fetchbuf1_instr)|fnIsPush(fetchbuf1_instr)|opcode1==`LINK) begin |
$display("1 found push/pop"); |
5916,6 → 6005,7
allowq = `FALSE; |
end |
end |
`ifdef UNLINKOP |
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); |
5924,6 → 6014,7
end |
end |
`endif |
`endif |
else if (iqentry_v[tail] == `INV && !qstomp) begin |
if ((({fnIsBranch(opcode1), predict_taken1} == {`TRUE, `TRUE})||(opcode1==`LOOP)) && test_stomp) |
qstomp = `TRUE; |
/trunk/rtl/verilog/Thor_TLB.v
158,6 → 158,7
`TLBIMissAdr: imiss_addr <= dati; |
`TLBPageTblAddr: PageTblAddr <= dati; |
`TLBPageTblCtrl: PageTblCtrl <= dati; |
default: ; |
endcase |
end |
`TLB_EN: |
166,6 → 167,7
TLBenabled <= 1'b0; |
`TLB_INVALL: |
TLBValid <= 64'd0; |
default: ; |
endcase |
end |
else if (state==3'd2) begin |
268,7 → 270,7
end |
|
wire [DBW-1:0] eas = ea[DBW-1:12] >> {PageSize,1'b0}; |
always @(ea) |
always @(eas or ASID or q or TLBG or TLBValid) |
for (n = 0; n < 8; n = n + 1) |
DMatch[n[2:0]] = (eas[DBW-1:3]==TLBVirtPage[{n,eas[2:0]}]) && |
((TLBASID[{n,eas[2:0]}]==ASID) || TLBG[{n,eas[2:0]}]) && |
/trunk/rtl/verilog/Thor_alu.v
380,15 → 380,17
o1[3] = 1'b0; |
o <= {16{o1}}; |
end |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`SB,`SC,`SH,`SW,`CAS,`LVB,`LVC,`LVH,`LVH,`STI, |
`LWS,`SWS,`LEA,`RTS2,`STS,`STFND,`STCMP: |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`SB,`SC,`SH,`SW,`CAS,`LVB,`LVC,`LVH,`LVW,`STI, |
`LWS,`SWS,`RTS2,`STS,`STFND,`STCMP,`PUSH: |
begin |
o <= alu_argA + alu_argC + alu_argI; |
end |
`JMPI: o <= {alu_argA << alu_fn[1:0]} + alu_argC + alu_argI; |
`LBX,`LBUX,`SBX, |
`LCX,`LCUX,`SCX, |
`LHX,`LHUX,`SHX, |
`LWX,`SWX: |
`LWX,`SWX, |
`JMPIX: |
case(alu_fn[1:0]) |
2'd0: o <= alu_argA + alu_argC + alu_argB; |
2'd1: o <= alu_argA + alu_argC + {alu_argB,1'b0}; |
396,7 → 398,7
2'd3: o <= alu_argA + alu_argC + {alu_argB,3'b0}; |
endcase |
`ifdef STACKOPS |
`PUSH,`PEA,`LINK: o <= alu_argA + alu_argC - 64'd8; |
`PEA,`LINK: o <= alu_argA + alu_argC - 64'd8; |
`UNLINK: o <= alu_argA + alu_argC + 64'd8; |
`POP: o <= alu_argA + alu_argC; |
`endif |
423,7 → 425,7
`ifdef BITFIELDOPS |
`BITFIELD: o <= BIG ? bf_out : 64'hDEADDEADDEADDEAD; |
`endif |
`LOOP: o <= alu_argB > 0 ? alu_argB - 64'd1 : alu_argB; |
`LOOP: o <= alu_argA > 0 ? alu_argA - 64'd1 : alu_argA; |
default: o <= 64'hDEADDEADDEADDEAD; |
endcase |
end |
/trunk/rtl/verilog/Thor_execute_combo.v
136,6 → 136,14
default: |
alu1_misspc <= (alu1_bt ? alu1_pc + alu1_insnsz : alu1_pc + alu1_insnsz + alu1_argI); |
endcase |
|
always @(dram0_fn or dram0_misspc or dram_bus) |
case (dram0_fn[1:0]) |
2'd1: jmpi_misspc <= {dram0_misspc[DBW-1:16],dram_bus[15:0]}; |
2'd2: jmpi_misspc <= (DBW==32) ? dram_bus[31:0] : {dram0_misspc[63:32],dram_bus[31:0]}; |
2'd3: jmpi_misspc <= dram_bus[DBW-1:0]; |
default: jmpi_misspc <= 32'h00000FA0; // unimplemented instruction vector |
endcase |
/* |
assign alu0_misspc = (alu0_op == `JSR || alu0_op==`JSRS || alu0_op==`JSRZ || |
alu0_op==`RTS || alu0_op==`RTS2 || alu0_op == `RTE || alu0_op==`RTI || alu0_op==`LOOP) ? alu0_argA + alu0_argI : |
178,17 → 186,17
((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_op==`SYS || alu0_op==`INT || |
alu0_op==`RTS || alu0_op==`RTS2 || alu0_op==`RTD || alu0_op == `RTE || alu0_op==`RTI || ((alu0_op==`LOOP) && (alu0_argB == 64'd0))))); |
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_op==`SYS || alu1_op==`INT || |
alu1_op==`RTS || alu1_op==`RTS2 || alu1_op==`RTD || alu1_op == `RTE || alu1_op==`RTI || ((alu1_op==`LOOP) && (alu1_argB == 64'd0))))); |
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), |
misspc = (mem_stringmiss ? dram0_misspc : alu0_branchmiss ? alu0_misspc : alu1_misspc), |
missid = (mem_stringmiss ? dram0_id : alu0_branchmiss ? alu0_sourceid : alu1_sourceid); |
assign branchmiss = (alu0_branchmiss | alu1_branchmiss | mem_stringmiss | jmpi_miss), |
misspc = (jmpi_miss ? jmpi_misspc : mem_stringmiss ? dram0_misspc : alu0_branchmiss ? alu0_misspc : alu1_misspc), |
missid = (jmpi_miss ? dram0_id : mem_stringmiss ? dram0_id : alu0_branchmiss ? alu0_sourceid : alu1_sourceid); |
|
`ifdef FLOATING_POINT |
wire fp0_exception; |
/trunk/rtl/verilog/Thor_defines.v
28,13 → 28,15
|
`define SIMULATION 1'b1 |
`define SEGMENTATION 1'b1 |
//`define SEGLIMITS 1'b1 |
//`define STACKOPS 1'b1 |
//`define UNLINKOP 1'b1 |
//`define BITFIELDOPS 1'b1 |
//`define FLOATING_POINT 1'b1 |
`define STRINGOPS 1'b1 |
`define DEBUG_LOGIC 1'b1 |
//`define DEBUG_LOGIC 1'b1 |
//`define THREEWAY 1'b1 |
`define TRAP_ILLEGALOPS 1'b1 |
//`define TRAP_ILLEGALOPS 1'b1 |
|
`define TRUE 1'b1 |
`define FALSE 1'b0 |
173,7 → 175,7
`define LFD 8'h88 |
`define LVWAR 8'h8B |
`define SWCR 8'h8C |
`define LEA 8'h8D |
`define JMPI 8'h8D |
`define LWS 8'h8E |
`define LCL 8'h8F |
|
245,6 → 247,7
`define LHX 8'hB4 |
`define LHUX 8'hB5 |
`define LWX 8'hB6 |
`define JMPIX 8'hB7 |
|
`define SBX 8'hC0 |
`define SCX 8'hC1 |