URL
https://opencores.org/ocsvn/thor/thor/trunk
Subversion Repositories thor
Compare Revisions
- This comparison shows the changes necessary to convert path
/thor/trunk/rtl
- from Rev 8 to Rev 9
- ↔ Reverse comparison
Rev 8 → Rev 9
/verilog/Thor_BranchHistory.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 |
// || |
41,6 → 41,7
// For simulation only, initialize the history table to zeros. |
// In the real world we don't care. |
initial begin |
gbl_branch_hist = 0; |
for (n = 0; n < 256; n = n + 1) |
branch_history_table[n] = 0; |
end |
/verilog/Thor.v
93,7 → 93,7
// An instruction and data cache were added. |
// A WISHBONE bus interface was added, |
// |
// 52,635 (84,500 LC's) |
// 53,950 (86,500 LC's) |
// with segmentation |
// no bitfield, stack or FP ops |
// |
106,6 → 106,7
parameter DBW = 32; // databus width |
parameter ABW = 32; // address bus width |
parameter RSTADDR = 64'hFFFFFFFFFFFFEFF0; |
parameter STARTUP_POWER = 16'hFFFF; |
localparam AMSB = ABW-1; |
parameter QENTRIES = 8; |
parameter ALU1BIG = 0; |
228,7 → 229,6
//reg [3:0] pf_source [15:0]; |
|
// instruction queue (ROB) |
reg iq_cmt[0:7]; |
reg [7:0] iqentry_v; // entry valid? -- this should be the first bit |
reg iqentry_out [0:7]; // instruction has been issued to an ALU ... |
reg iqentry_done [0:7]; // instruction result valid |
242,6 → 242,7
reg [DBW-1:0] iqentry_res [0:7]; // instruction result |
reg [3:0] iqentry_insnsz [0:7]; // the size of the instruction |
reg [3:0] iqentry_cond [0:7]; // predicating condition |
reg [3:0] iqentry_preg [0:7]; // predicate regno |
reg [3:0] iqentry_pred [0:7]; // predicate value |
reg iqentry_p_v [0:7]; // predicate is valid |
reg [3:0] iqentry_p_s [0:7]; // predicate source |
264,7 → 265,7
reg [3:0] iqentry_T_s [0:7]; |
reg [DBW-1:0] iqentry_pc [0:7]; // program counter for this instruction |
|
wire iqentry_source [0:7]; |
reg [7:0] iqentry_source; |
wire iqentry_imm [0:7]; |
wire iqentry_memready [0:7]; |
wire iqentry_memopsvalid [0:7]; |
433,7 → 434,8
wire alu1_branchmiss; |
reg [ABW+3:0] alu1_misspc; |
|
wire mem_stringmiss; |
wire mem_stringmissx; |
reg mem_stringmiss; |
wire branchmiss; |
wire [ABW+3:0] misspc; |
|
482,6 → 484,7
reg [8:0] dram0_tgt; |
reg [3:0] dram0_id; |
reg [3:0] dram0_exc; |
reg [ABW-1:0] dram0_misspc; |
reg dram1_owns_bus; |
reg [DBW-1:0] dram1_data; |
reg [DBW-1:0] dram1_datacmp; |
537,11 → 540,14
wire [127:0] alu1_prod; |
wire alu1_mult_done; |
|
reg exception_set; |
|
//----------------------------------------------------------------------------- |
// Debug |
//----------------------------------------------------------------------------- |
|
wire [DBW-1:0] dbg_stat; |
wire [DBW-1:0] dbg_stat1x; |
reg [DBW-1:0] dbg_stat; |
reg [DBW-1:0] dbg_ctrl; |
reg [ABW-1:0] dbg_adr0; |
reg [ABW-1:0] dbg_adr1; |
614,7 → 620,7
wire dbg_stat1 = dbg_imatchA1 | dbg_imatchB1 | dbg_lmatch1 | dbg_smatch1; |
wire dbg_stat2 = dbg_imatchA2 | dbg_imatchB2 | dbg_lmatch2 | dbg_smatch2; |
wire dbg_stat3 = dbg_imatchA3 | dbg_imatchB3 | dbg_lmatch3 | dbg_smatch3; |
assign dbg_stat = {dbg_stat3,dbg_stat2,dbg_stat1,dbg_stat0}; |
assign dbg_stat1x = {dbg_stat3,dbg_stat2,dbg_stat1,dbg_stat0}; |
|
|
reg [11:0] spr_bir; |
625,7 → 631,7
// livetarget implies that there is a not-to-be-stomped instruction that targets the register in question |
// therefore, if it is zero it implies the rf_v value should become VALID on a branchmiss |
// |
|
/* |
Thor_livetarget #(NREGS) ultgt1 |
( |
iqentry_v, |
722,8 → 728,100
iqentry_source[5] = | iqentry_5_latestID, |
iqentry_source[6] = | iqentry_6_latestID, |
iqentry_source[7] = | iqentry_7_latestID; |
*/ |
always @* |
begin |
iqentry_source = 8'h00; |
if (missid==head0) begin |
if (iqentry_v[head0] && !iqentry_stomp[head0]) |
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]); |
end |
else if (missid==head1) begin |
if (iqentry_v[head0] && !iqentry_stomp[head0]) |
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]); |
if (iqentry_v[head1] && !iqentry_stomp[head1]) |
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]); |
end |
else if (missid==head2) begin |
if (iqentry_v[head0] && !iqentry_stomp[head0]) |
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]); |
if (iqentry_v[head1] && !iqentry_stomp[head1]) |
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]); |
if (iqentry_v[head2] && !iqentry_stomp[head2]) |
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]); |
end |
else if (missid==head3) begin |
if (iqentry_v[head0] && !iqentry_stomp[head0]) |
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]); |
if (iqentry_v[head1] && !iqentry_stomp[head1]) |
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]); |
if (iqentry_v[head2] && !iqentry_stomp[head2]) |
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]); |
if (iqentry_v[head3] && !iqentry_stomp[head3]) |
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]); |
end |
else if (missid==head4) begin |
if (iqentry_v[head0] && !iqentry_stomp[head0]) |
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]); |
if (iqentry_v[head1] && !iqentry_stomp[head1]) |
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]); |
if (iqentry_v[head2] && !iqentry_stomp[head2]) |
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]); |
if (iqentry_v[head3] && !iqentry_stomp[head3]) |
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]); |
if (iqentry_v[head4] && !iqentry_stomp[head4]) |
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]); |
end |
else if (missid==head5) begin |
if (iqentry_v[head0] && !iqentry_stomp[head0]) |
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]); |
if (iqentry_v[head1] && !iqentry_stomp[head1]) |
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]); |
if (iqentry_v[head2] && !iqentry_stomp[head2]) |
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]); |
if (iqentry_v[head3] && !iqentry_stomp[head3]) |
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]); |
if (iqentry_v[head4] && !iqentry_stomp[head4]) |
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]); |
if (iqentry_v[head5] && !iqentry_stomp[head5]) |
iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]); |
end |
else if (missid==head6) begin |
if (iqentry_v[head0] && !iqentry_stomp[head0]) |
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]); |
if (iqentry_v[head1] && !iqentry_stomp[head1]) |
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]); |
if (iqentry_v[head2] && !iqentry_stomp[head2]) |
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]); |
if (iqentry_v[head3] && !iqentry_stomp[head3]) |
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]); |
if (iqentry_v[head4] && !iqentry_stomp[head4]) |
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]); |
if (iqentry_v[head5] && !iqentry_stomp[head5]) |
iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]); |
if (iqentry_v[head6] && !iqentry_stomp[head6]) |
iqentry_source[head6] = !fnRegIsAutoValid(iqentry_tgt[head6]); |
end |
else if (missid==head7) begin |
if (iqentry_v[head0] && !iqentry_stomp[head0]) |
iqentry_source[head0] = !fnRegIsAutoValid(iqentry_tgt[head0]); |
if (iqentry_v[head1] && !iqentry_stomp[head1]) |
iqentry_source[head1] = !fnRegIsAutoValid(iqentry_tgt[head1]); |
if (iqentry_v[head2] && !iqentry_stomp[head2]) |
iqentry_source[head2] = !fnRegIsAutoValid(iqentry_tgt[head2]); |
if (iqentry_v[head3] && !iqentry_stomp[head3]) |
iqentry_source[head3] = !fnRegIsAutoValid(iqentry_tgt[head3]); |
if (iqentry_v[head4] && !iqentry_stomp[head4]) |
iqentry_source[head4] = !fnRegIsAutoValid(iqentry_tgt[head4]); |
if (iqentry_v[head5] && !iqentry_stomp[head5]) |
iqentry_source[head5] = !fnRegIsAutoValid(iqentry_tgt[head5]); |
if (iqentry_v[head6] && !iqentry_stomp[head6]) |
iqentry_source[head6] = !fnRegIsAutoValid(iqentry_tgt[head6]); |
if (iqentry_v[head7] && !iqentry_stomp[head7]) |
iqentry_source[head7] = !fnRegIsAutoValid(iqentry_tgt[head7]); |
end |
end |
|
|
//assign iqentry_0_islot = iqentry_islot[0]; |
//assign iqentry_1_islot = iqentry_islot[1]; |
//assign iqentry_2_islot = iqentry_islot[2]; |
836,82 → 934,115
wire [3:0] Pt1 = fetchbuf1_instr[11:8]; |
|
function [6:0] fnRa; |
input [63:0] insn; |
case(insn[7:0]) |
input [63:0] isn; |
case(isn[7:0]) |
8'h11: fnRa = 7'h51; // RTS short form |
default: |
case(insn[15:8]) |
case(isn[15:8]) |
`RTI: fnRa = 7'h5E; |
`RTD: fnRa = 7'h5B; |
`RTE: fnRa = 7'h5D; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2: |
fnRa = {3'h5,insn[23:20]}; |
`TLB: fnRa = {1'b0,insn[29:24]}; |
fnRa = {3'h5,isn[23:20]}; |
`TLB: fnRa = {1'b0,isn[29:24]}; |
`P: fnRa = 7'h70; |
// `PUSH,`PEA,`POP,`LINK: fnRa = 7'd27; |
default: fnRa = {1'b0,insn[`INSTRUCTION_RA]}; |
`LOOP: fnRa = 7'h5F; |
`ifdef STACKOPS |
`PUSH,`PEA,`POP,`LINK: fnRa = 7'd27; |
`endif |
default: fnRa = {1'b0,isn[`INSTRUCTION_RA]}; |
endcase |
endcase |
endfunction |
|
function [6:0] fnRb; |
input [63:0] insn; |
if (insn[7:0]==8'h11) // RTS short form |
input [63:0] isn; |
if (isn[7:0]==8'h11) // RTS short form |
fnRb = 7'h51; |
else |
case(insn[15:8]) |
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; |
`LOOP: fnRb = 7'h73; |
`JSR,`JSRS,`JSRZ,`SYS,`INT: |
fnRb = {3'h5,insn[23:20]}; |
`SWS: fnRb = {1'b1,insn[27:22]}; |
fnRb = {3'h5,isn[23:20]}; |
`SWS: fnRb = {1'b1,isn[27:22]}; |
`ifdef STACKOPS |
`PUSH: fnRb = insn[22:16]; |
`LINK: fnRb = {1'b0,insn[27:22]}; |
`PEA: fnRb = {1'b0,insn[21:16]}; |
`PUSH: fnRb = isn[22:16]; |
`LINK: fnRb = {1'b0,isn[27:22]}; |
`PEA: fnRb = {1'b0,isn[21:16]}; |
`endif |
default: fnRb = {1'b0,insn[`INSTRUCTION_RB]}; |
default: fnRb = {1'b0,isn[`INSTRUCTION_RB]}; |
endcase |
endfunction |
|
function [6:0] fnRc; |
input [63:0] insn; |
fnRc = {1'b0,insn[`INSTRUCTION_RC]}; |
input [63:0] isn; |
fnRc = {1'b0,isn[`INSTRUCTION_RC]}; |
endfunction |
|
function [3:0] fnCar; |
input [63:0] insn; |
if (insn[7:0]==8'h11) // RTS short form |
input [63:0] isn; |
if (isn[7:0]==8'h11) // RTS short form |
fnCar = 4'h1; |
else |
case(insn[15:8]) |
case(isn[15:8]) |
`RTI: fnCar = 4'hE; |
`RTD: fnCar = 4'hB; |
`RTE: fnCar = 4'hD; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`RTS2: |
fnCar = {insn[23:20]}; |
fnCar = {isn[23:20]}; |
default: fnCar = 4'h0; |
endcase |
endfunction |
|
function [5:0] fnFunc; |
input [63:0] insn; |
if (insn[7:0]==8'h11) // RTS short form |
input [63:0] isn; |
if (isn[7:0]==8'h11) // RTS short form |
fnFunc = 6'h00; // func is used as a small immediate |
else |
casex(insn[15:8]) |
`BITFIELD: fnFunc = insn[43:40]; |
`CMP: fnFunc = insn[31:28]; |
`TST: fnFunc = insn[23:22]; |
`INC: fnFunc = insn[24:22]; |
`RTS,`RTS2: fnFunc = insn[19:16]; // used to pass a small immediate |
`CACHE: fnFunc = insn[31:26]; |
case(isn[15:8]) |
`BITFIELD: fnFunc = isn[43:40]; |
8'h10: fnFunc = isn[31:28]; |
8'h11: fnFunc = isn[31:28]; |
8'h12: fnFunc = isn[31:28]; |
8'h13: fnFunc = isn[31:28]; |
8'h14: fnFunc = isn[31:28]; |
8'h15: fnFunc = isn[31:28]; |
8'h16: fnFunc = isn[31:28]; |
8'h17: fnFunc = isn[31:28]; |
8'h18: fnFunc = isn[31:28]; |
8'h19: fnFunc = isn[31:28]; |
8'h1A: fnFunc = isn[31:28]; |
8'h1B: fnFunc = isn[31:28]; |
8'h1C: fnFunc = isn[31:28]; |
8'h1D: fnFunc = isn[31:28]; |
8'h1E: fnFunc = isn[31:28]; |
8'h1F: fnFunc = isn[31:28]; |
8'h00: fnFunc = isn[23:22]; |
8'h01: fnFunc = isn[23:22]; |
8'h02: fnFunc = isn[23:22]; |
8'h03: fnFunc = isn[23:22]; |
8'h04: fnFunc = isn[23:22]; |
8'h05: fnFunc = isn[23:22]; |
8'h06: fnFunc = isn[23:22]; |
8'h07: fnFunc = isn[23:22]; |
8'h08: fnFunc = isn[23:22]; |
8'h09: fnFunc = isn[23:22]; |
8'h0A: fnFunc = isn[23:22]; |
8'h0B: fnFunc = isn[23:22]; |
8'h0C: fnFunc = isn[23:22]; |
8'h0D: fnFunc = isn[23:22]; |
8'h0E: fnFunc = isn[23:22]; |
8'h0F: fnFunc = isn[23:22]; |
`INC: fnFunc = isn[24:22]; |
`RTS,`RTS2: fnFunc = isn[19:16]; // used to pass a small immediate |
`CACHE: fnFunc = isn[31:26]; |
default: |
fnFunc = insn[39:34]; |
fnFunc = isn[39:34]; |
endcase |
endfunction |
|
989,12 → 1120,15
// 0 if we need a RF value |
function fnSource1_v; |
input [7:0] opcode; |
casex(opcode) |
case(opcode) |
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`STP: |
fnSource1_v = 1'b1; |
`BR,`LOOP: fnSource1_v = 1'b1; |
`LDI,`LDIS,`IMM: fnSource1_v = 1'b1; |
default: fnSource1_v = 1'b0; |
default: |
case(opcode[7:4]) |
`BR: fnSource1_v = 1'b1; |
default: fnSource1_v = 1'b0; |
endcase |
endcase |
endfunction |
|
1004,19 → 1138,68
function fnSource2_v; |
input [7:0] opcode; |
input [5:0] func; |
casex(opcode) |
case(opcode) |
`R,`P: fnSource2_v = 1'b1; |
`LDI,`STI,`LDIS,`IMM,`NOP,`STP: fnSource2_v = 1'b1; |
`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; |
`TST: fnSource2_v = 1'b1; |
// TST |
8'h00: fnSource2_v = 1'b1; |
8'h01: fnSource2_v = 1'b1; |
8'h02: fnSource2_v = 1'b1; |
8'h03: fnSource2_v = 1'b1; |
8'h04: fnSource2_v = 1'b1; |
8'h05: fnSource2_v = 1'b1; |
8'h06: fnSource2_v = 1'b1; |
8'h07: fnSource2_v = 1'b1; |
8'h08: fnSource2_v = 1'b1; |
8'h09: fnSource2_v = 1'b1; |
8'h0A: fnSource2_v = 1'b1; |
8'h0B: fnSource2_v = 1'b1; |
8'h0C: fnSource2_v = 1'b1; |
8'h0D: fnSource2_v = 1'b1; |
8'h0E: fnSource2_v = 1'b1; |
8'h0F: fnSource2_v = 1'b1; |
`ADDI,`ADDUI,`ADDUIS: |
fnSource2_v = 1'b1; |
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI: |
fnSource2_v = 1'b1; |
`SUBI,`SUBUI: fnSource2_v = 1'b1; |
`CMPI: fnSource2_v = 1'b1; |
// CMPI |
8'h20: fnSource2_v = 1'b1; |
8'h21: fnSource2_v = 1'b1; |
8'h22: fnSource2_v = 1'b1; |
8'h23: fnSource2_v = 1'b1; |
8'h24: fnSource2_v = 1'b1; |
8'h25: fnSource2_v = 1'b1; |
8'h26: fnSource2_v = 1'b1; |
8'h27: fnSource2_v = 1'b1; |
8'h28: fnSource2_v = 1'b1; |
8'h29: fnSource2_v = 1'b1; |
8'h2A: fnSource2_v = 1'b1; |
8'h2B: fnSource2_v = 1'b1; |
8'h2C: fnSource2_v = 1'b1; |
8'h2D: fnSource2_v = 1'b1; |
8'h2E: fnSource2_v = 1'b1; |
8'h2F: fnSource2_v = 1'b1; |
// BR |
8'h30: fnSource2_v = 1'b1; |
8'h31: fnSource2_v = 1'b1; |
8'h32: fnSource2_v = 1'b1; |
8'h33: fnSource2_v = 1'b1; |
8'h34: fnSource2_v = 1'b1; |
8'h35: fnSource2_v = 1'b1; |
8'h36: fnSource2_v = 1'b1; |
8'h37: fnSource2_v = 1'b1; |
8'h38: fnSource2_v = 1'b1; |
8'h39: fnSource2_v = 1'b1; |
8'h3A: fnSource2_v = 1'b1; |
8'h3B: fnSource2_v = 1'b1; |
8'h3C: fnSource2_v = 1'b1; |
8'h3D: fnSource2_v = 1'b1; |
8'h3E: fnSource2_v = 1'b1; |
8'h3F: fnSource2_v = 1'b1; |
`MULI,`MULUI,`DIVI,`DIVUI: |
fnSource2_v = 1'b1; |
`ANDI,`BITI: fnSource2_v = 1'b1; |
1031,13 → 1214,17
`LVB,`LVC,`LVH,`LVW,`LVWAR, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWS,`LEA,`STI,`INC: |
fnSource2_v = 1'b1; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`BR: |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS: |
fnSource2_v = 1'b1; |
`MTSPR,`MFSPR,`POP,`UNLINK: |
fnSource2_v = 1'b1; |
// `BFSET,`BFCLR,`BFCHG,`BFEXT,`BFEXTU: // but not BFINS |
// fnSource2_v = 1'b1; |
default: fnSource2_v = 1'b0; |
`BITFIELD: |
if (func==`BFINS) |
fnSource2_v = 1'b0; |
else |
fnSource2_v = 1'b1; |
`LOOP: fnSource2_v = 1'b0; |
default: fnSource2_v = 1'b0; |
endcase |
endfunction |
|
1049,7 → 1236,7
// 0 if we need a RF value |
function fnSource3_v; |
input [7:0] opcode; |
casex(opcode) |
case(opcode) |
`SBX,`SCX,`SHX,`SWX,`CAS,`STMV,`STCMP,`STFND: fnSource3_v = 1'b0; |
`MUX: fnSource3_v = 1'b0; |
default: fnSource3_v = 1'b1; |
1058,11 → 1245,15
|
function fnSourceT_v; |
input [7:0] opcode; |
casex(opcode) |
`BR, |
case(opcode) |
// 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, |
`SB,`SC,`SH,`SW,`SBX,`SCX,`SHX,`SWX,`SWS, |
`CACHE, |
`SEI,`CLI,`NOP,`STP, |
`SEI,`CLI,`NOP,`STP,`RTI,`RTD,`RTE, |
`MEMSB,`MEMDB,`SYNC: |
fnSourceT_v = 1'b1; |
default: fnSourceT_v = 1'b0; |
1072,21 → 1263,17
// Return the number of register read ports required for an instruction. |
function [2:0] fnNumReadPorts; |
input [63:0] ins; |
casex(fnOpcode(ins)) |
case(fnOpcode(ins)) |
`SEI,`CLI,`MEMSB,`MEMDB,`SYNC,`NOP,`MOVS,`STP: |
fnNumReadPorts = 3'd0; |
`BR: fnNumReadPorts = 3'd0; |
`LOOP: fnNumReadPorts = 3'd0; |
`LDI,`LDIS,`IMM: fnNumReadPorts = 3'd0; |
`R,`P,`STI: fnNumReadPorts = 3'd1; |
`R,`P,`STI: fnNumReadPorts = 3'd1; |
`RTI,`RTD,`RTE: fnNumReadPorts = 3'd1; |
`TST: fnNumReadPorts = 3'd1; |
`ADDI,`ADDUI,`ADDUIS: |
fnNumReadPorts = 3'd1; |
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI: |
fnNumReadPorts = 3'd1; |
`SUBI,`SUBUI: fnNumReadPorts = 3'd1; |
`CMPI: fnNumReadPorts = 3'd1; |
`MULI,`MULUI,`DIVI,`DIVUI: |
fnNumReadPorts = 3'd1; |
`BITI, |
1099,7 → 1286,7
`RTS2,`CACHE,`LCL,`TLB, |
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LVB,`LVC,`LVH,`LVW,`LVWAR,`LWS,`LEA,`INC: |
fnNumReadPorts = 3'd1; |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`BR,`LOOP: |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`RTS,`BR: |
fnNumReadPorts = 3'd1; |
`SBX,`SCX,`SHX,`SWX, |
`MUX,`CAS,`STMV,`STCMP: |
1108,18 → 1295,25
`STFND: fnNumReadPorts = 3'd2; // *** TLB reads on Rb we say 2 for simplicity |
`BITFIELD: |
case(ins[43:40]) |
`BFSET,`BFCLR,`BFCHG,`BFEXT,`BFEXTU: |
`BFSET,`BFCLR,`BFCHG,`BFEXT,`BFEXTU,`BFINSI: |
fnNumReadPorts = 3'd1; |
`BFINS: fnNumReadPorts = 3'd2; |
default: fnNumReadPorts = 3'd0; |
endcase |
default: fnNumReadPorts = 3'd2; |
default: |
case(ins[15:12]) |
`TST: fnNumReadPorts = 3'd1; |
`CMPI: fnNumReadPorts = 3'd1; |
`CMP: fnNumReadPorts = 3'd2; |
`BR: fnNumReadPorts = 3'd0; |
default: fnNumReadPorts = 3'd2; |
endcase |
endcase |
endfunction |
|
function fnIsBranch; |
input [7:0] opcode; |
casex(opcode) |
case(opcode[7:4]) |
`BR: fnIsBranch = `TRUE; |
default: fnIsBranch = `FALSE; |
endcase |
1126,13 → 1320,13
endfunction |
|
function fnIsPush; |
input [63:0] insn; |
fnIsPush = insn[15:8]==`PUSH || insn[15:8]==`PEA; |
input [63:0] isn; |
fnIsPush = isn[15:8]==`PUSH || isn[15:8]==`PEA; |
endfunction |
|
function fnIsPop; |
input [63:0] insn; |
fnIsPop = insn[15:8]==`POP; |
input [63:0] isn; |
fnIsPop = isn[15:8]==`POP; |
endfunction |
|
function fnIsStoreString; |
1141,9 → 1335,9
opcode==`STS; |
endfunction |
|
wire xbr = (iqentry_op[head0]==`BR) || (iqentry_op[head1]==`BR); |
wire takb = (iqentry_op[head0]==`BR) ? commit0_v : commit1_v; |
wire [DBW-1:0] xbrpc = (iqentry_op[head0]==`BR) ? iqentry_pc[head0] : iqentry_pc[head1]; |
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]; |
|
wire predict_takenA,predict_takenB,predict_takenC,predict_takenD; |
|
1198,31 → 1392,6
.predict_taken(predict_takenD) |
); |
|
`ifdef THREEWAY |
Thor_BranchHistory #(DBW) ubhtE |
( |
.rst(rst_i), |
.clk(clk), |
.advanceX(xbr), |
.xisBranch(xbr), |
.pc(pc+fnInsnLength(insn)+fnInsnLength1(insn)), |
.xpc(xbrpc), |
.takb(takb), |
.predict_taken(predict_takenE) |
); |
Thor_BranchHistory #(DBW) ubhtF |
( |
.rst(rst_i), |
.clk(clk), |
.advanceX(xbr), |
.xisBranch(xbr), |
.pc(pc+fnInsnLength(insn)+fnInsnLength1(insn)), |
.xpc(xbrpc), |
.takb(takb), |
.predict_taken(predict_takenF) |
); |
`endif |
|
Thor_icachemem #(DBW) uicm1 |
( |
.wclk(clk), |
1297,11 → 1466,11
wire [DBW-1:0] shfto0,shfto1; |
|
function fnIsShiftiop; |
input [63:0] insn; |
fnIsShiftiop = insn[15:8]==`SHIFT && ( |
insn[39:34]==`SHLI || insn[39:34]==`SHLUI || |
insn[39:34]==`SHRI || insn[39:34]==`SHRUI || |
insn[39:34]==`ROLI || insn[39:34]==`RORI |
input [63:0] isn; |
fnIsShiftiop = isn[15:8]==`SHIFT && ( |
isn[39:34]==`SHLI || isn[39:34]==`SHLUI || |
isn[39:34]==`SHRI || isn[39:34]==`SHRUI || |
isn[39:34]==`ROLI || isn[39:34]==`RORI |
) |
; |
endfunction |
1323,15 → 1492,15
endfunction |
|
function fnIsFPCtrl; |
input [63:0] insn; |
fnIsFPCtrl = (insn[15:8]==`SINGLE_R && (insn[31:28]==`FTX||insn[31:28]==`FCX||insn[31:28]==`FDX||insn[31:28]==`FEX)) || |
(insn[15:8]==`DOUBLE_R && (insn[31:28]==`FRM)) |
input [63:0] isn; |
fnIsFPCtrl = (isn[15:8]==`SINGLE_R && (isn[31:28]==`FTX||isn[31:28]==`FCX||isn[31:28]==`FDX||isn[31:28]==`FEX)) || |
(isn[15:8]==`DOUBLE_R && (isn[31:28]==`FRM)) |
; |
endfunction |
|
function fnIsBitfield; |
input [7:0] opcode; |
fnIsBitfield = opcode==`BFSET || opcode==`BFCLR || opcode==`BFCHG || opcode==`BFINS || opcode==`BFEXT || opcode==`BFEXTU; |
fnIsBitfield = opcode==`BITFIELD; |
endfunction |
|
//wire [3:0] Pn = ir[7:4]; |
1341,6 → 1510,7
// 40-4F = predicate register |
// 50-5F = code address register |
// 60-67 = segment base register |
// 68-6F = segment limit register |
// 70 = predicate register horizontal |
// 73 = loop counter |
function [6:0] fnTargetReg; |
1349,7 → 1519,7
if (ir[3:0]==4'h0) // Process special predicates |
fnTargetReg = 7'h000; |
else |
casex(fnOpcode(ir)) |
case(fnOpcode(ir)) |
`POP: fnTargetReg = ir[22:16]; |
`LDI,`ADDUIS,`STS,`LINK,`UNLINK: |
fnTargetReg = {1'b0,ir[21:16]}; |
1383,7 → 1553,57
fnTargetReg = {1'b0,ir[27:22]}; |
`BITI: |
fnTargetReg = {3'h4,ir[25:22]}; |
`CMP,`CMPI,`TST: |
// 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, |
// 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, |
// 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: |
begin |
fnTargetReg = {3'h4,ir[11:8]}; |
end |
1475,18 → 1695,51
|
function fnHasConst; |
input [7:0] opcode; |
casex(opcode) |
case(opcode) |
`BFCLR,`BFSET,`BFCHG,`BFEXT,`BFEXTU,`BFINS, |
`LDI,`LDIS,`ADDUIS, |
`ADDI,`SUBI,`ADDUI,`SUBUI,`MULI,`MULUI,`DIVI,`DIVUI, |
`_2ADDUI,`_4ADDUI,`_8ADDUI,`_16ADDUI, |
`CMPI, |
// 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, |
// 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, |
`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, |
`SB,`SC,`SH,`SW,`SWCR,`CAS,`SWS, |
`JSR,`JSRS,`SYS,`INT,`BR,`RTS2,`LOOP,`PEA,`LINK,`UNLINK: |
`JSR,`JSRS,`SYS,`INT,`RTS2,`LOOP,`PEA,`LINK,`UNLINK: |
fnHasConst = 1'b1; |
default: |
fnHasConst = 1'b0; |
1496,10 → 1749,14
function fnIsFlowCtrl; |
input [7:0] opcode; |
begin |
casex(opcode) |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`LOOP,`BR,`RTS,`RTS2,`RTI,`RTD,`RTE: |
case(opcode) |
`JSR,`JSRS,`JSRZ,`SYS,`INT,`LOOP,`RTS,`RTS2,`RTI,`RTD,`RTE: |
fnIsFlowCtrl = 1'b1; |
default: fnIsFlowCtrl = 1'b0; |
default: |
if (opcode[7:4]==`BR) |
fnIsFlowCtrl = 1'b1; |
else |
fnIsFlowCtrl = 1'b0; |
endcase |
end |
endfunction |
1517,9 → 1774,11
`FDIVS,`FMULS,`FADDS,`FSUBS, |
`FDIV,`FMUL,`FADD,`FSUB: |
fnCanException = `TRUE; |
default: fnCanException = `FALSE; |
endcase |
`SINGLE_R: |
if (func==`FTX) fnCanException = `TRUE; |
else fnCanException = `FALSE; |
`ADD,`ADDI,`SUB,`SUBI,`DIV,`DIVI,`MUL,`MULI: |
fnCanException = `TRUE; |
`TLB,`RTI,`RTD,`RTE,`CLI,`SEI: |
1534,25 → 1793,25
// Return the length of an instruction. |
// |
function [3:0] fnInsnLength; |
input [127:0] insn; |
casex(insn[15:0]) |
16'bxxxxxxxx00000000: fnInsnLength = 4'd1; // BRK |
16'bxxxxxxxx00010000: fnInsnLength = 4'd1; // NOP |
16'bxxxxxxxx00100000: fnInsnLength = 4'd2; |
16'bxxxxxxxx00110000: fnInsnLength = 4'd3; |
16'bxxxxxxxx01000000: fnInsnLength = 4'd4; |
16'bxxxxxxxx01010000: fnInsnLength = 4'd5; |
16'bxxxxxxxx01100000: fnInsnLength = 4'd6; |
16'bxxxxxxxx01110000: fnInsnLength = 4'd7; |
16'bxxxxxxxx10000000: fnInsnLength = 4'd8; |
16'bxxxxxxxx00010001: fnInsnLength = 4'd1; // RTS short form |
input [127:0] isn; |
case(isn[7:0]) |
8'b00000000: fnInsnLength = 4'd1; // BRK |
8'b00010000: fnInsnLength = 4'd1; // NOP |
8'b00100000: fnInsnLength = 4'd2; |
8'b00110000: fnInsnLength = 4'd3; |
8'b01000000: fnInsnLength = 4'd4; |
8'b01010000: fnInsnLength = 4'd5; |
8'b01100000: fnInsnLength = 4'd6; |
8'b01110000: fnInsnLength = 4'd7; |
8'b10000000: fnInsnLength = 4'd8; |
8'b00010001: fnInsnLength = 4'd1; // RTS short form |
default: |
casex(insn[15:8]) |
case(isn[15:8]) |
`NOP,`SEI,`CLI,`RTI,`RTD,`RTE,`MEMSB,`MEMDB,`SYNC: |
fnInsnLength = 4'd2; |
`TST,`BR,`JSRZ,`RTS,`CACHE,`LOOP,`PUSH,`POP,`UNLINK: |
`JSRZ,`RTS,`CACHE,`LOOP,`PUSH,`POP,`UNLINK: |
fnInsnLength = 4'd3; |
`SYS,`CMP,`CMPI,`MTSPR,`MFSPR,`LDI,`LDIS,`ADDUIS,`R,`TLB,`MOVS,`RTS2,`STP: |
`SYS,`MTSPR,`MFSPR,`LDI,`LDIS,`ADDUIS,`R,`TLB,`MOVS,`RTS2,`STP: |
fnInsnLength = 4'd4; |
`BITFIELD,`JSR,`MUX,`BCD,`INC: |
fnInsnLength = 4'd6; |
1559,43 → 1818,50
`CAS: |
fnInsnLength = 4'd6; |
default: |
fnInsnLength = 4'd5; |
begin |
case(isn[15:12]) |
`TST: fnInsnLength = 4'd3; |
`BR: fnInsnLength = 4'd3; |
`CMP,`CMPI: fnInsnLength = 4'd4; |
default: fnInsnLength = 4'd5; |
endcase |
end |
endcase |
endcase |
endfunction |
|
function [3:0] fnInsnLength1; |
input [127:0] insn; |
case(fnInsnLength(insn)) |
4'd1: fnInsnLength1 = fnInsnLength(insn[127: 8]); |
4'd2: fnInsnLength1 = fnInsnLength(insn[127:16]); |
4'd3: fnInsnLength1 = fnInsnLength(insn[127:24]); |
4'd4: fnInsnLength1 = fnInsnLength(insn[127:32]); |
4'd5: fnInsnLength1 = fnInsnLength(insn[127:40]); |
4'd6: fnInsnLength1 = fnInsnLength(insn[127:48]); |
4'd7: fnInsnLength1 = fnInsnLength(insn[127:56]); |
4'd8: fnInsnLength1 = fnInsnLength(insn[127:64]); |
input [127:0] isn; |
case(fnInsnLength(isn)) |
4'd1: fnInsnLength1 = fnInsnLength(isn[127: 8]); |
4'd2: fnInsnLength1 = fnInsnLength(isn[127:16]); |
4'd3: fnInsnLength1 = fnInsnLength(isn[127:24]); |
4'd4: fnInsnLength1 = fnInsnLength(isn[127:32]); |
4'd5: fnInsnLength1 = fnInsnLength(isn[127:40]); |
4'd6: fnInsnLength1 = fnInsnLength(isn[127:48]); |
4'd7: fnInsnLength1 = fnInsnLength(isn[127:56]); |
4'd8: fnInsnLength1 = fnInsnLength(isn[127:64]); |
default: fnInsnLength1 = 4'd0; |
endcase |
endfunction |
|
function [3:0] fnInsnLength2; |
input [127:0] insn; |
case(fnInsnLength(insn)+fnInsnLength1(insn)) |
4'd2: fnInsnLength2 = fnInsnLength(insn[127:16]); |
4'd3: fnInsnLength2 = fnInsnLength(insn[127:24]); |
4'd4: fnInsnLength2 = fnInsnLength(insn[127:32]); |
4'd5: fnInsnLength2 = fnInsnLength(insn[127:40]); |
4'd6: fnInsnLength2 = fnInsnLength(insn[127:48]); |
4'd7: fnInsnLength2 = fnInsnLength(insn[127:56]); |
4'd8: fnInsnLength2 = fnInsnLength(insn[127:64]); |
4'd9: fnInsnLength2 = fnInsnLength(insn[127:72]); |
4'd10: fnInsnLength2 = fnInsnLength(insn[127:80]); |
4'd11: fnInsnLength2 = fnInsnLength(insn[127:88]); |
4'd12: fnInsnLength2 = fnInsnLength(insn[127:96]); |
4'd13: fnInsnLength2 = fnInsnLength(insn[127:104]); |
4'd14: fnInsnLength2 = fnInsnLength(insn[127:112]); |
4'd15: fnInsnLength2 = fnInsnLength(insn[127:120]); |
input [127:0] isn; |
case(fnInsnLength(isn)+fnInsnLength1(isn)) |
4'd2: fnInsnLength2 = fnInsnLength(isn[127:16]); |
4'd3: fnInsnLength2 = fnInsnLength(isn[127:24]); |
4'd4: fnInsnLength2 = fnInsnLength(isn[127:32]); |
4'd5: fnInsnLength2 = fnInsnLength(isn[127:40]); |
4'd6: fnInsnLength2 = fnInsnLength(isn[127:48]); |
4'd7: fnInsnLength2 = fnInsnLength(isn[127:56]); |
4'd8: fnInsnLength2 = fnInsnLength(isn[127:64]); |
4'd9: fnInsnLength2 = fnInsnLength(isn[127:72]); |
4'd10: fnInsnLength2 = fnInsnLength(isn[127:80]); |
4'd11: fnInsnLength2 = fnInsnLength(isn[127:88]); |
4'd12: fnInsnLength2 = fnInsnLength(isn[127:96]); |
4'd13: fnInsnLength2 = fnInsnLength(isn[127:104]); |
4'd14: fnInsnLength2 = fnInsnLength(isn[127:112]); |
4'd15: fnInsnLength2 = fnInsnLength(isn[127:120]); |
default: fnInsnLength2 = 4'd0; |
endcase |
endfunction |
1608,10 → 1874,6
or fetchbufB_instr or fetchbufB_v or fetchbufB_pc |
or fetchbufC_instr or fetchbufC_v or fetchbufC_pc |
or fetchbufD_instr or fetchbufD_v or fetchbufD_pc |
`ifdef THREEWAY |
or fetchbufE_instr or fetchbufE_v or fetchbufE_pc |
or fetchbufF_instr or fetchbufF_v or fetchbufF_pc |
`endif |
) |
begin |
fetchbuf0_instr <= (fetchbuf == 1'b0) ? fetchbufA_instr : fetchbufC_instr; |
1674,8 → 1936,9
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==`SHIFT || |
opcode==`R || opcode==`RR || opcode==`LEA || opcode==`P || opcode==`LOOP || |
opcode==`BITI || opcode==`CMP || opcode==`CMPI || opcode==`TST || |
opcode==`LDI || opcode==`LDIS || opcode==`ADDUIS || opcode==`MFSPR || |
// Branch registers / Segment registers |
((opcode==`MTSPR || opcode==`MOVS) /*&& (fnTargetsCa(ir) || fnTargetsSegreg(ir))*/) || |
1717,12 → 1980,84
opcode==`SBX || opcode==`SCX || opcode==`SHX || opcode==`SWX; |
endfunction |
|
// *** check these |
// |
function fnIsPFW; |
input [7:0] opcode; |
fnIsPFW = opcode[7:4]<4'h3 || opcode==`BITI || opcode==`P;//opcode==`CMP || opcode==`CMPI || opcode==`TST; |
endfunction |
|
// Decoding for illegal opcodes |
function fnIsIllegal; |
input [7:0] op; |
input [5:0] fn; |
casex(op) |
8'h40: |
if (fn > 6'h11) |
fnIsIllegal = `TRUE; |
else if (fn==6'hC || fn==6'hD || fn==6'hE || fn==6'hF) |
fnIsIllegal = `TRUE; |
else fnIsIllegal = `FALSE; |
8'h41: |
if (fn > 6'd3) fnIsIllegal = `TRUE; |
else fnIsIllegal = `FALSE; |
8'h42: |
if (fn > 6'd7) fnIsIllegal = `TRUE; |
else fnIsIllegal = `FALSE; |
8'h50: |
if (fn > 6'd7) fnIsIllegal = `TRUE; |
else fnIsIllegal = `FALSE; |
8'h58: |
if (fn > 6'h15 || (fn > 6'h5 && fn < 6'h10)) |
fnIsIllegal = `TRUE; |
else |
fnIsIllegal = `FALSE; |
8'h77: |
if (fn==8'h99 || fn==8'h9A || fn==8'h9B || fn==8'h9E || fn==8'h9F) |
fnIsIllegal = `TRUE; |
else |
fnIsIllegal = `FALSE; |
8'h78: |
if ((fn >= 8'h07 && fn <= 8'h0B) || (fn >= 8'h17 && fn <= 8'h1B)) |
fnIsIllegal = `FALSE; |
else |
fnIsIllegal = `TRUE; |
8'h79: |
if (fn==8'h99 || fn==8'h9A || fn==8'h9B) |
fnIsIllegal = `TRUE; |
else |
fnIsIllegal = `FALSE; |
8'hAA: |
if (fn > 4'd6) |
fnIsIllegal = `TRUE; |
else |
fnIsIllegal = `FALSE; |
8'hF5: |
if (fn > 4'd2) |
fnIsIllegal = `TRUE; |
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: |
fnIsIllegal = `TRUE; |
8'h60,8'h61,8'h62,8'h63,8'h64,8'h65,8'h66,8'h67,8'h68,8'h69,8'h6A: |
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: |
fnIsIllegal = `TRUE; |
8'h94,8'h95,8'h9C: |
fnIsIllegal = `TRUE; |
8'hB7,8'b10111xxx: |
fnIsIllegal = `TRUE; |
8'hC4,8'hC5,8'b11001xxx: |
fnIsIllegal = `TRUE; |
8'hDx: fnIsIllegal = `TRUE; |
8'hEx: fnIsIllegal = `TRUE; |
8'hFD,8'hFE: fnIsIllegal = `TRUE; |
default: fnIsIllegal = `FALSE; |
endcase |
endfunction |
|
function [7:0] fnSelect; |
input [7:0] opcode; |
input [5:0] fn; |
1884,7 → 2219,7
4'hC: fnDatai = dat[31:16]; |
default: fnDatai = {DBW{1'b1}}; |
endcase |
`LH,`LHU,`LW,`LWX,`LVH,`LVW,`LVWAR,`LHX,`LHUX,`CAS,`LWS,`LCL,`POP,`UNLINK: |
`LH,`LHU,`LW,`LWX,`LVH,`LVW,`LVWAR,`LHX,`LHUX,`CAS,`LCL,`LWS,`POP,`UNLINK: |
fnDatai = dat[31:0]; |
default: fnDatai = {DBW{1'b1}}; |
endcase |
1972,7 → 2307,7
8'hF0: fnDatai = dat[DBW-1:DBW/2]; |
default: fnDatai = {DBW{1'b1}}; |
endcase |
`LW,`LWX,`LVW,`LVWAR,`CAS,`LWS,`LCL,`POP,`UNLINK: |
`LW,`LWX,`LVW,`LVWAR,`CAS,`LCL,`LWS,`POP,`UNLINK: |
case(sel) |
8'hFF: fnDatai = dat; |
default: fnDatai = {DBW{1'b1}}; |
2079,7 → 2414,7
|
assign int_pending = (nmi_edge & ~StatusHWI & ~int_commit) || (irq_i & ~im & ~StatusHWI & ~int_commit); |
|
assign mem_stringmiss = ((dram0_op==`STS || dram0_op==`STFND) && int_pending && lc != 0) || |
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); |
|
// "Stream" interrupt instructions into the instruction stream until an INT |
2159,11 → 2494,11
// Return the immediate field of an instruction |
function [63:0] fnImm; |
input [127:0] insn; |
casex(insn[15:0]) |
16'bxxxxxxxx00010001: // RTS short form |
case(insn[7:0]) |
8'b00010001: // RTS short form |
fnImm = 64'd0; |
default: |
casex(insn[15:8]) |
case(insn[15:8]) |
`P: fnImm = insn[33:16]; |
`CAS: fnImm = {{56{insn[47]}},insn[47:40]}; |
`BCD: fnImm = insn[47:40]; |
2175,7 → 2510,24
`BITFIELD: fnImm = insn[47:32]; |
`SYS,`INT: fnImm = insn[31:24]; |
`RTS2: fnImm = {insn[31:27],3'b000}; |
`CMPI,`LDI,`LDIS,`ADDUIS: |
//`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, |
`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; |
2196,7 → 2548,7
if (insn[7:0]==8'h11) |
fnImm8 = 8'h00; |
else |
casex(insn[15:8]) |
case(insn[15:8]) |
`CAS: fnImm8 = insn[47:40]; |
`BCD: fnImm8 = insn[47:40]; |
`TLB: fnImm8 = insn[23:16]; |
2205,11 → 2557,30
`JSR,`JSRS,`RTS2: fnImm8 = insn[31:24]; |
`BITFIELD: fnImm8 = insn[39:32]; |
`SYS,`INT: fnImm8 = insn[31:24]; |
`CMPI,`LDI,`LDIS,`ADDUIS: fnImm8 = insn[29:22]; |
//`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, |
`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]; |
//`LINK: fnImm8 = {insn[32:28],3'b000}; |
`ifdef STACKOPS |
`LINK: fnImm8 = {insn[32:28],3'b000}; |
`endif |
`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]; |
2223,7 → 2594,7
if (insn[7:0]==8'h11) |
fnImmMSB = 1'b0; |
else |
casex(insn[15:8]) |
case(insn[15:8]) |
`CAS: fnImmMSB = insn[47]; |
`TLB,`BCD,`STP: |
fnImmMSB = 1'b0; // TLB regno is unsigned |
2233,7 → 2604,24
fnImmMSB = insn[47]; |
`JSRS: |
fnImmMSB = insn[39]; |
`CMPI,`LDI,`LDIS,`ADDUIS: |
//`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, |
`LDI,`LDIS,`ADDUIS: |
fnImmMSB = insn[31]; |
`SYS,`INT,`CACHE,`LINK: |
fnImmMSB = 1'b0; // SYS,INT are unsigned |
2265,6 → 2653,8
endcase |
endfunction |
|
|
// Used during enque |
function [63:0] fnOpa; |
input [7:0] opcode; |
input [63:0] ins; |
2272,7 → 2662,7
input [63:0] epc; |
begin |
`ifdef BITFIELDOPS |
if (opcode==`BITFIELD && ins[43:40]==4'd6) // BFINSI |
if (opcode==`BITFIELD && ins[43:40]==`BFINSI) |
fnOpa = ins[21:16]; |
else |
`endif |
2292,47 → 2682,13
fnOpa = fnSpr(6'h30,epc); |
else if (opcode==`MFSPR || opcode==`MOVS) |
fnOpa = fnSpr(ins[`INSTRUCTION_RA],epc); |
/* |
casex(ins[21:16]) |
`TICK: fnOpa = tick; |
`LCTR: fnOpa = lc; |
`PREGS_ALL: |
begin |
fnOpa[3:0] = pregs[0]; |
fnOpa[7:4] = pregs[1]; |
fnOpa[11:8] = pregs[2]; |
fnOpa[15:12] = pregs[3]; |
fnOpa[19:16] = pregs[4]; |
fnOpa[23:20] = pregs[5]; |
fnOpa[27:24] = pregs[6]; |
fnOpa[31:28] = pregs[7]; |
fnOpa[35:32] = pregs[8]; |
fnOpa[39:36] = pregs[9]; |
fnOpa[43:40] = pregs[10]; |
fnOpa[47:44] = pregs[11]; |
fnOpa[51:48] = pregs[12]; |
fnOpa[55:52] = pregs[13]; |
fnOpa[59:56] = pregs[14]; |
fnOpa[63:60] = pregs[15]; |
end |
`ASID: fnOpa = asid; |
`SR: fnOpa = sr; |
6'h1x: fnOpa = ins[19:16]==4'h0 ? 64'd0 : ins[19:16]==4'hF ? epc : |
(commit0_v && commit0_tgt[6:4]==3'h5 && commit0_tgt[3:0]==ins[19:16]) ? commit0_bus : |
cregs[ins[19:16]]; |
`ifdef SEGMENTATION |
6'h2x: fnOpa = |
(commit0_v && commit0_tgt[6:4]==3'h6 && commit0_tgt[3:0]==ins[18:16]) ? {commit0_bus[DBW-1:12],12'h000} : |
{sregs[ins[18:16]],12'h000}; |
`endif |
default: fnOpa = 64'h0; |
endcase |
*/ |
else |
fnOpa = rfo; |
end |
endfunction |
|
|
// Returns TRUE if instruction is only allowed in kernel mode. |
function fnIsKMOnly; |
input [7:0] op; |
fnIsKMOnly = op==`RTI || op==`RTE || op==`RTD || op==`TLB || op==`CLI || op==`SEI || |
2340,6 → 2696,18
; |
endfunction |
|
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; |
endfunction |
|
// Returns TRUE if the register is automatically valid. |
function fnRegIsAutoValid; |
input [6:0] regno; // r0, c0, c15, tick |
fnRegIsAutoValid = regno==7'h00 || regno==7'h50 || regno==7'h5F || regno==7'h72; |
endfunction |
|
function [15:0] fnRegstrGrp; |
input [6:0] Rn; |
if (!Rn[6]) begin |
2405,12 → 2773,12
// that will become valid in the next cycle. instead, these have to propagate |
// their results into the IQ entry directly, at which point it becomes issue-able |
// |
|
/* |
always @* |
for (n = 0; n < QENTRIES; n = n + 1) |
iq_cmt[n] <= fnPredicate(iqentry_pred[n], iqentry_cond[n]) || |
(iqentry_cond[n] < 4'h2 && ({iqentry_pred[n],iqentry_cond[n]}!=8'h90)); |
|
*/ |
wire [QENTRIES-1:0] args_valid; |
wire [QENTRIES-1:0] could_issue; |
|
2442,7 → 2810,7
; |
|
assign could_issue[g] = iqentry_v[g] && !iqentry_done[g] && !iqentry_out[g] && args_valid[g] && |
(iqentry_mem[g] ? !iqentry_agen[g] : 1'b1);// && iq_cmt[g]; |
(iqentry_mem[g] ? !iqentry_agen[g] : 1'b1); |
|
end |
end |
2706,45 → 3074,27
// |
// additional logic for handling a branch miss (STOMP logic) |
// |
assign iqentry_stomp[0] = branchmiss & (iqentry_v[0] && head0 != 3'd0 && (missid == 3'd7 || iqentry_stomp[7])); |
assign iqentry_stomp[1] = branchmiss & (iqentry_v[1] && head0 != 3'd1 && (missid == 3'd0 || iqentry_stomp[0])); |
assign iqentry_stomp[2] = branchmiss & (iqentry_v[2] && head0 != 3'd2 && (missid == 3'd1 || iqentry_stomp[1])); |
assign iqentry_stomp[3] = branchmiss & (iqentry_v[3] && head0 != 3'd3 && (missid == 3'd2 || iqentry_stomp[2])); |
assign iqentry_stomp[4] = branchmiss & (iqentry_v[4] && head0 != 3'd4 && (missid == 3'd3 || iqentry_stomp[3])); |
assign iqentry_stomp[5] = branchmiss & (iqentry_v[5] && head0 != 3'd5 && (missid == 3'd4 || iqentry_stomp[4])); |
assign iqentry_stomp[6] = branchmiss & (iqentry_v[6] && head0 != 3'd6 && (missid == 3'd5 || iqentry_stomp[5])); |
assign iqentry_stomp[7] = branchmiss & (iqentry_v[7] && head0 != 3'd7 && (missid == 3'd6 || iqentry_stomp[6])); |
wire [QENTRIES-1:0] alu0_issue_; |
wire [QENTRIES-1:0] alu1_issue_; |
wire [QENTRIES-1:0] fp0_issue_; |
generate |
begin : stomp_logic |
assign iqentry_stomp[0] = branchmiss & (iqentry_v[0] && head0 != 3'd0 && ((missid == QENTRIES-1) || iqentry_stomp[QENTRIES-1])); |
for (g = 1; g < QENTRIES; g = g + 1) |
assign iqentry_stomp[g] = branchmiss & (iqentry_v[g] && head0 != g && ((missid == g-1) || iqentry_stomp[g-1])); |
for (g = 0; g < QENTRIES; g = g + 1) |
begin |
assign alu0_issue_[g] = (!(iqentry_v[g] && iqentry_stomp[g]) && iqentry_issue[g] && iqentry_islot[g]==2'd0); |
assign alu1_issue_[g] = (!(iqentry_v[g] && iqentry_stomp[g]) && iqentry_issue[g] && iqentry_islot[g]==2'd1); |
assign fp0_issue_[g] = (!(iqentry_v[g] && iqentry_stomp[g]) && iqentry_fpissue[g] && iqentry_islot[g]==2'd0); |
end |
end |
endgenerate |
|
assign alu0_issue = (!(iqentry_v[0] && iqentry_stomp[0]) && iqentry_issue[0] && iqentry_islot[0]==2'd0) || |
(!(iqentry_v[1] && iqentry_stomp[1]) && iqentry_issue[1] && iqentry_islot[1]==2'd0) || |
(!(iqentry_v[2] && iqentry_stomp[2]) && iqentry_issue[2] && iqentry_islot[2]==2'd0) || |
(!(iqentry_v[3] && iqentry_stomp[3]) && iqentry_issue[3] && iqentry_islot[3]==2'd0) || |
(!(iqentry_v[4] && iqentry_stomp[4]) && iqentry_issue[4] && iqentry_islot[4]==2'd0) || |
(!(iqentry_v[5] && iqentry_stomp[5]) && iqentry_issue[5] && iqentry_islot[5]==2'd0) || |
(!(iqentry_v[6] && iqentry_stomp[6]) && iqentry_issue[6] && iqentry_islot[6]==2'd0) || |
(!(iqentry_v[7] && iqentry_stomp[7]) && iqentry_issue[7] && iqentry_islot[7]==2'd0) |
; |
|
assign alu1_issue = (!(iqentry_v[0] && iqentry_stomp[0]) && iqentry_issue[0] && iqentry_islot[0]==2'd1) || |
(!(iqentry_v[1] && iqentry_stomp[1]) && iqentry_issue[1] && iqentry_islot[1]==2'd1) || |
(!(iqentry_v[2] && iqentry_stomp[2]) && iqentry_issue[2] && iqentry_islot[2]==2'd1) || |
(!(iqentry_v[3] && iqentry_stomp[3]) && iqentry_issue[3] && iqentry_islot[3]==2'd1) || |
(!(iqentry_v[4] && iqentry_stomp[4]) && iqentry_issue[4] && iqentry_islot[4]==2'd1) || |
(!(iqentry_v[5] && iqentry_stomp[5]) && iqentry_issue[5] && iqentry_islot[5]==2'd1) || |
(!(iqentry_v[6] && iqentry_stomp[6]) && iqentry_issue[6] && iqentry_islot[6]==2'd1) || |
(!(iqentry_v[7] && iqentry_stomp[7]) && iqentry_issue[7] && iqentry_islot[7]==2'd1) |
; |
|
assign alu0_issue = |alu0_issue_; |
assign alu1_issue = |alu1_issue_; |
`ifdef FLOATING_POINT |
assign fp0_issue = (!(iqentry_v[0] && iqentry_stomp[0]) && iqentry_fpissue[0] && iqentry_islot[0]==2'd0) || |
(!(iqentry_v[1] && iqentry_stomp[1]) && iqentry_fpissue[1] && iqentry_islot[1]==2'd0) || |
(!(iqentry_v[2] && iqentry_stomp[2]) && iqentry_fpissue[2] && iqentry_islot[2]==2'd0) || |
(!(iqentry_v[3] && iqentry_stomp[3]) && iqentry_fpissue[3] && iqentry_islot[3]==2'd0) || |
(!(iqentry_v[4] && iqentry_stomp[4]) && iqentry_fpissue[4] && iqentry_islot[4]==2'd0) || |
(!(iqentry_v[5] && iqentry_stomp[5]) && iqentry_fpissue[5] && iqentry_islot[5]==2'd0) || |
(!(iqentry_v[6] && iqentry_stomp[6]) && iqentry_fpissue[6] && iqentry_islot[6]==2'd0) || |
(!(iqentry_v[7] && iqentry_stomp[7]) && iqentry_fpissue[7] && iqentry_islot[7]==2'd0) |
; |
assign fp0_issue = |fp0_issue_; |
`endif |
|
wire dcache_access_pending = dram0 == 3'd6 && (!rhit || (dram0_op==`LCL && dram0_tgt==7'd1)); |
3110,6 → 3460,23
: (iqentry_a1_s[n] == commit0_id) ? commit0_bus |
: 64'hDEADDEADDEADDEAD; |
|
wire [3:0] alu0nyb[0:15]; |
wire [3:0] alu1nyb[0:15]; |
wire [3:0] cmt0nyb[0:15]; |
wire [3:0] cmt1nyb[0:15]; |
|
generate |
begin : nybs |
for (g = 0; g < DBW/4; g = g + 1) |
begin |
assign alu0nyb[g] = alu0_bus[g*4+3:g*4]; |
assign alu1nyb[g] = alu1_bus[g*4+3:g*4]; |
assign cmt0nyb[g] = commit0_bus[g*4+3:g*4]; |
assign cmt1nyb[g] = commit1_bus[g*4+3:g*4]; |
end |
end |
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 |
3176,7 → 3543,7
if (rst_i) begin |
cpu_clk_en <= 1'b1; |
lct1 <= 1'b0; |
clk_throttle <= 16'hAAAA; // 50% power |
clk_throttle <= STARTUP_POWER; // 50% power |
end |
else begin |
lct1 <= ld_clk_throttle; |
3185,7 → 3552,7
clk_throttle <= clk_throttle_new; |
end |
if (nmi_i) |
clk_throttle <= 16'hAAAA; |
clk_throttle <= STARTUP_POWER; |
cpu_clk_en <= clk_throttle[15]; |
end |
|
3212,6 → 3579,11
fp0_ld <= 1'b0; |
`endif |
|
mem_stringmiss <= `FALSE; |
if (mem_stringmissx) begin |
mem_stringmiss <= `TRUE; |
dram0_op <= `NOP; // clears string miss |
end |
ic_invalidate <= `FALSE; |
dc_invalidate <= `FALSE; |
ic_invalidate_line <= `FALSE; |
3331,11 → 3703,14
queued1 = `FALSE; |
queued2 = `FALSE; |
allowq = `TRUE; |
dbg_stat <= dbg_stat | dbg_stat1x; |
|
did_branchback <= take_branch; |
did_branchback0 <= take_branch0; |
did_branchback1 <= take_branch1; |
|
`include "Thor_Retarget.v" |
/* |
if (branchmiss) begin |
for (n = 1; n < NREGS; n = n + 1) |
if (rf_v[n] == `INV && ~livetarget[n]) begin |
3353,7 → 3728,7
if (|iqentry_7_latestID[NREGS:1]) rf_source[ iqentry_tgt[7] ] <= { iqentry_mem[7], 3'd7 }; |
|
end |
|
*/ |
if (ihit) begin |
$display("\r\n"); |
$display("TIME %0d", $time); |
3370,13 → 3745,13
// |
if (commit0_v) begin |
if (!rf_v[ commit0_tgt ]) begin |
rf_v[ commit0_tgt ] = (rf_source[ commit0_tgt ] == commit0_id) || (branchmiss && iqentry_source[ commit0_id[2:0] ]); |
rf_v[ commit0_tgt ] = (rf_source[ commit0_tgt ] == commit0_id) || ((branchmiss) && iqentry_source[ commit0_id[2:0] ]); |
end |
if (commit0_tgt != 7'd0) $display("r%d <- %h", commit0_tgt, commit0_bus); |
end |
if (commit1_v) begin |
if (!rf_v[ commit1_tgt ]) begin |
rf_v[ commit1_tgt ] = (rf_source[ commit1_tgt ] == commit1_id)|| (branchmiss && iqentry_source[ commit1_id[2:0] ]); |
rf_v[ commit1_tgt ] = (rf_source[ commit1_tgt ] == commit1_id)|| ((branchmiss) && iqentry_source[ commit1_id[2:0] ]); |
end |
if (commit1_tgt != 7'd0) $display("r%d <- %h", commit1_tgt, commit1_bus); |
end |
3472,6 → 3847,7
// assignments are used for these vars. |
//------------------------------------------------------------------------------- |
// |
exception_set = `FALSE; |
queued1 = `FALSE; |
queued2 = `FALSE; |
allowq = `TRUE; |
3734,23 → 4110,23
$display("insn=%h", insn); |
$display("%c insn0=%h insn1=%h", nmi_edge ? "*" : " ",insn0, insn1); |
$display("takb=%d br_pc=%h #", take_branch, branch_pc); |
$display("%c%c A: %d %h %h #", |
45, fetchbuf?45:62, fetchbufA_v, fetchbufA_instr, fetchbufA_pc); |
$display("%c%c B: %d %h %h #", |
45, fetchbuf?45:62, fetchbufB_v, fetchbufB_instr, fetchbufB_pc); |
$display("%c%c C: %d %h %h #", |
45, fetchbuf?62:45, fetchbufC_v, fetchbufC_instr, fetchbufC_pc); |
$display("%c%c D: %d %h %h #", |
45, fetchbuf?62:45, fetchbufD_v, fetchbufD_instr, fetchbufD_pc); |
$display("%c%c A: %d %h %h # %d", |
45, fetchbuf?45:62, fetchbufA_v, fetchbufA_instr, fetchbufA_pc, fnInsnLength(fetchbufA_instr)); |
$display("%c%c B: %d %h %h # %d", |
45, fetchbuf?45:62, fetchbufB_v, fetchbufB_instr, fetchbufB_pc, fnInsnLength(fetchbufB_instr)); |
$display("%c%c C: %d %h %h # %d", |
45, fetchbuf?62:45, fetchbufC_v, fetchbufC_instr, fetchbufC_pc, fnInsnLength(fetchbufC_instr)); |
$display("%c%c D: %d %h %h # %d", |
45, fetchbuf?62:45, fetchbufD_v, fetchbufD_instr, fetchbufD_pc, fnInsnLength(fetchbufD_instr)); |
$display("fetchbuf=%d",fetchbuf); |
end |
|
// if (ihit) begin |
for (i=0; i<QENTRIES; i=i+1) |
$display("%c%c %d: %c%c%c%c%c%c%c%c%c %d %c %c%h %d%s %h %h %h %c %o %h %c %o %h %c %o %h %c %o %h #", |
$display("%c%c %d: %c%c%c%c%c%c%c%c %d %c %c%h %d%s %h %h %h %c %o %h %c %o %h %c %o %h %c %o %h #", |
(i[2:0]==head0)?72:46, (i[2:0]==tail0)?84:46, i, |
iqentry_v[i]?"v":"-", iqentry_done[i]?"d":"-", |
iqentry_cmt[i]?"c":"-", iq_cmt[i]?"C":"-",iqentry_out[i]?"o":"-", iqentry_bt[i]?"b":"-", iqentry_memissue[i]?"m":"-", |
iqentry_cmt[i]?"c":"-", iqentry_out[i]?"o":"-", iqentry_bt[i]?"b":"-", iqentry_memissue[i]?"m":"-", |
iqentry_agen[i]?"a":"-", iqentry_issue[i]?"i":"-", |
iqentry_islot[i], |
// ((i==0) ? iqentry_0_islot : (i==1) ? iqentry_1_islot : (i==2) ? iqentry_2_islot : (i==3) ? iqentry_3_islot : |
3794,7 → 4170,11
// dram operation started. |
iqentry_cmt[dram_id[2:0]] <= `TRUE; |
iqentry_done[ dram_id[2:0] ] <= `TRUE; |
if (iqentry_op[dram_id[2:0]]==`STS && lc==64'd0) begin |
if ((iqentry_op[dram_id[2:0]]==`STS || |
iqentry_op[dram_id[2:0]]==`STCMP || |
iqentry_op[dram_id[2:0]]==`STMV || |
iqentry_op[dram_id[2:0]]==`STFND |
) && lc==64'd0) begin |
string_pc <= 64'd0; |
end |
end |
3827,7 → 4207,7
// - alu0_bus |
// - alu1_bus |
// - fp0_bus |
// - dram_bus |
// - mem_bus |
// - commit0_bus |
// - commit1_bus |
// |
3835,7 → 4215,7
for (n = 0; n < QENTRIES; n = n + 1) |
begin |
if (iqentry_p_v[n] == `INV && iqentry_p_s[n]==alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin |
iqentry_pred[n] <= alu0_bus[3:0]; |
iqentry_pred[n] <= alu0nyb[iqentry_preg[n]]; |
iqentry_p_v[n] <= `VAL; |
end |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == alu0_id && iqentry_v[n] == `VAL && alu0_v == `VAL) begin |
3855,7 → 4235,7
iqentry_T_v[n] <= `VAL; |
end |
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin |
iqentry_pred[n] <= alu1_bus[3:0]; |
iqentry_pred[n] <= alu1nyb[iqentry_preg[n]]; |
iqentry_p_v[n] <= `VAL; |
end |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == alu1_id && iqentry_v[n] == `VAL && alu1_v == `VAL) begin |
3920,7 → 4300,7
iqentry_T_v[n] <= `VAL; |
end |
if (iqentry_p_v[n] == `INV && iqentry_p_s[n]==commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin |
iqentry_pred[n] <= commit0_bus[3:0]; |
iqentry_pred[n] <= cmt0nyb[iqentry_preg[n]]; |
iqentry_p_v[n] <= `VAL; |
end |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == commit0_id && iqentry_v[n] == `VAL && commit0_v == `VAL) begin |
3940,7 → 4320,7
iqentry_T_v[n] <= `VAL; |
end |
if (iqentry_p_v[n] == `INV && iqentry_p_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin |
iqentry_pred[n] <= commit1_bus[3:0]; |
iqentry_pred[n] <= cmt1nyb[iqentry_preg[n]]; |
iqentry_p_v[n] <= `VAL; |
end |
if (iqentry_a1_v[n] == `INV && iqentry_a1_s[n] == commit1_id && iqentry_v[n] == `VAL && commit1_v == `VAL) begin |
4022,8 → 4402,8
alu0_bt <= iqentry_bt[n]; |
alu0_pc <= iqentry_pc[n]; |
alu0_pred <= iqentry_p_v[n] ? iqentry_pred[n] : |
(iqentry_p_s[n] == alu0_id) ? alu0_bus[3:0] : |
(iqentry_p_s[n] == alu1_id) ? alu1_bus[3:0] : 4'h0; |
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] : |
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0; |
alu0_argA <= iqentry_a1_v[n] ? iqentry_a1[n] |
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus |
4032,8 → 4412,13
: (iqentry_a2_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a2_s[n] == alu1_id) ? alu1_bus |
: 64'hDEADDEADDEADDEAD; |
alu0_argC <= (iqentry_op[n]==`POP || iqentry_op[n]==`PUSH || iqentry_op[n]==`PEA) ? {sregs[3'd6],12'h000} : |
iqentry_mem[n] ? {sregs[iqentry_fn[n][5:3]],12'h000} : |
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} : |
`endif |
iqentry_a3_v[n] ? iqentry_a3[n] |
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a3_s[n] == alu1_id) ? alu1_bus |
4055,8 → 4440,8
alu1_bt <= iqentry_bt[n]; |
alu1_pc <= iqentry_pc[n]; |
alu1_pred <= iqentry_p_v[n] ? iqentry_pred[n] : |
(iqentry_p_s[n] == alu0_id) ? alu0_bus[3:0] : |
(iqentry_p_s[n] == alu1_id) ? alu1_bus[3:0] : 4'h0; |
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] : |
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0; |
alu1_argA <= iqentry_a1_v[n] ? iqentry_a1[n] |
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus |
4065,8 → 4450,13
: (iqentry_a2_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a2_s[n] == alu1_id) ? alu1_bus |
: 64'hDEADDEADDEADDEAD; |
alu1_argC <= (iqentry_op[n]==`POP || iqentry_op[n]==`PUSH || iqentry_op[n]==`PEA) ? {sregs[3'd6],12'h000} : |
iqentry_mem[n] ? {sregs[iqentry_fn[n][5:3]],12'h000} : |
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} : |
`endif |
iqentry_a3_v[n] ? iqentry_a3[n] |
: (iqentry_a3_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a3_s[n] == alu1_id) ? alu1_bus |
4104,8 → 4494,8
fp0_fn <= iqentry_fn[n]; |
fp0_cond <= iqentry_cond[n]; |
fp0_pred <= iqentry_p_v[n] ? iqentry_pred[n] : |
(iqentry_p_s[n] == alu0_id) ? alu0_bus[3:0] : |
(iqentry_p_s[n] == alu1_id) ? alu1_bus[3:0] : 4'h0; |
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] : |
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] : 4'h0; |
fp0_argA <= iqentry_a1_v[n] ? iqentry_a1[n] |
: (iqentry_a1_s[n] == alu0_id) ? alu0_bus |
: (iqentry_a1_s[n] == alu1_id) ? alu1_bus |
4162,9 → 4552,10
|
case(dram0) |
// The first state is to translate the virtual to physical address. |
// Also a good spot to check for debug match and segment limit violation. |
3'd1: |
begin |
$display("0MEM %c:%h %h cycle started",fnIsLoad(dram0_op)?"L" : "S", dram0_addr, dram0_data); |
$display("0MEM %c:%h %h cycle started",fnIsStore(dram0_op)?"S" : "L", dram0_addr, dram0_data); |
if (dbg_lmatch|dbg_smatch) begin |
dram_v <= `TRUE; |
dram_id <= dram0_id; |
4255,67 → 4646,54
dram_bus <= fnDatai(dram0_op,dram0_fn,dat_i,rsel); |
dram0_owns_bus <= `FALSE; |
wb_nack(); |
dram0 <= 3'd7; |
dram0 <= 3'd7; |
case(dram0_op) |
`ifdef STRINGOPS |
`STS: |
if (lc != 0 && !int_pending) begin |
dram0_owns_bus <= `TRUE; |
dram0_addr <= dram0_addr + |
(dram0_fn[2:0]==3'd0 ? 64'd1 : |
dram0_fn[2:0]==3'd1 ? 64'd2 : |
dram0_fn[2:0]==3'd2 ? 64'd4 : |
64'd8); |
dram0_addr <= dram0_addr + fnIndexAmt(dram0_fn); |
lc <= lc - 64'd1; |
dram0 <= 3'd1; |
dram_bus <= dram0_addr + |
(dram0_fn[2:0]==3'd0 ? 64'd1 : |
dram0_fn[2:0]==3'd1 ? 64'd2 : |
dram0_fn[2:0]==3'd2 ? 64'd4 : |
64'd8); |
dram_bus <= dram0_addr + fnIndexAmt(dram0_fn); |
end |
else begin |
dram_bus <= dram0_addr + |
(dram0_fn[2:0]==3'd0 ? 64'd1 : |
dram0_fn[2:0]==3'd1 ? 64'd2 : |
dram0_fn[2:0]==3'd2 ? 64'd4 : |
64'd8) - dram0_seg; |
dram_bus <= dram0_addr + fnIndexAmt(dram0_fn) - dram0_seg; |
dram_v <= `VAL; |
end |
`STMV,`STCMP: |
if (lc != 0 && !(int_pending && stmv_flag)) begin |
dram0 <= 3'd1; |
dram0_owns_bus <= `TRUE; |
if (stmv_flag) begin |
dram0_addr <= src_addr + index; |
if (dram0_op==`STCMP) begin |
if (dram0_data != fnDatai(dram0_op,dram0_fn,dat_i,rsel)) begin |
lc <= 64'd0; |
dram0 <= 3'd7; |
dram_v <= `VAL; |
dram_bus <= index; |
begin |
dram_bus <= index; |
if (lc != 0 && !(int_pending && stmv_flag)) begin |
dram0 <= 3'd1; |
dram0_owns_bus <= `TRUE; |
if (stmv_flag) begin |
dram0_addr <= src_addr + index; |
if (dram0_op==`STCMP) begin |
if (dram0_data != fnDatai(dram0_op,dram0_fn,dat_i,rsel)) begin |
lc <= 64'd0; |
dram0 <= 3'd7; |
dram_v <= `VAL; |
end |
end |
end |
else begin |
dram0_addr <= dst_addr + index; |
dram0_data <= fnDatai(dram0_op,dram0_fn,dat_i,rsel); |
end |
end |
if (!stmv_flag) |
inc_index(dram0_fn); |
stmv_flag <= ~stmv_flag; |
end |
else begin |
dram0_addr <= dst_addr + index; |
dram0_data <= fnDatai(dram0_op,dram0_fn,dat_i,rsel); |
dram_v <= `VAL; |
end |
if (!stmv_flag) |
inc_index(dram0_fn); |
stmv_flag <= ~stmv_flag; |
end |
else begin |
dram_bus <= index; |
dram_v <= `VAL; |
end |
`STFND: |
if (lc != 0 && !int_pending) begin |
dram0_addr <= src_addr + index; |
inc_index(dram0_fn); |
if (dram0_data == dram_bus) begin |
if (dram0_data == fnDatai(dram0_op,dram0_fn,dat_i,rsel)) begin |
lc <= 64'd0; |
dram0 <= 3'd7; |
dram_v <= `VAL; |
dram_bus <= index; |
end |
4334,19 → 4712,27
cyc_o <= 1'b1; // hold onto cyc_o |
dram0 <= dram0 + 3'd1; |
end |
else |
else begin |
dram_v <= `VAL; |
dram0 <= 3'd0; |
end |
`INC: |
begin |
if (stmv_flag) begin |
dram_v <= `VAL; |
dram0 <= 3'd0; |
end |
else begin |
dram0_data <= fnDatai(dram0_op,dram0_fn,dat_i,rsel); |
stmv_flag <= ~stmv_flag; |
dram0 <= 3'd2; |
dram0 <= 3'd1; |
end |
end |
`NOP: |
begin |
dram_v <= `VAL; |
dram0 <= 3'd0; |
end |
default: ; |
endcase |
end |
4367,16 → 4753,18
// Wait for a memory ack for the second bus transaction of a CAS |
// |
3'd5: |
if (ack_i|err_i) begin |
$display("MEM ack2"); |
dram_v <= `VAL; |
begin |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EXC_DBE : `EXC_NONE; |
dram0_owns_bus <= `FALSE; |
wb_nack(); |
lock_o <= 1'b0; |
dram0 <= 3'd7; |
if (ack_i|err_i) begin |
$display("MEM ack2"); |
dram_v <= `VAL; |
dram_exc <= (err_i & dram0_tgt!=7'd0) ? `EXC_DBE : `EXC_NONE; |
dram0_owns_bus <= `FALSE; |
wb_nack(); |
lock_o <= 1'b0; |
dram0 <= 3'd7; |
end |
end |
|
// State 6: |
4392,62 → 4780,72
stmv_flag <= `TRUE; |
dram0_addr <= dst_addr + index; |
dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel); |
dram0 <= 3'd2; |
dram0 <= 3'd1; |
end |
`STCMP: |
if (lc != 0 && !int_pending && stmv_flag) begin |
dram0_addr <= src_addr + index; |
stmv_flag <= ~stmv_flag; |
if (dram0_data != dram_bus) begin |
lc <= 64'd0; |
begin |
dram_bus <= index; |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
if (lc != 0 && !int_pending && stmv_flag) begin |
dram0_addr <= src_addr + index; |
stmv_flag <= ~stmv_flag; |
$display("*****************************"); |
$display("STCMP READ2:%H",fnDatai(dram0_op,dram0_fn,cdat,rsel)); |
$display("*****************************"); |
if (dram0_data != fnDatai(dram0_op,dram0_fn,cdat,rsel)) begin |
lc <= 64'd0; |
dram0 <= 3'd7; |
dram_v <= `VAL; |
end |
end |
else if (!stmv_flag) begin |
stmv_flag <= ~stmv_flag; |
dram0_addr <= dst_addr + index; |
dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel); |
$display("*****************************"); |
$display("STCMP READ1:%H",fnDatai(dram0_op,dram0_fn,cdat,rsel)); |
$display("*****************************"); |
dram0 <= 3'd1; |
inc_index(dram0_fn); |
end |
else begin |
dram_v <= `VAL; |
dram0 <= 3'd7; |
dram_v <= `VAL; |
dram_bus <= index; |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
end |
end |
else if (!stmv_flag) begin |
stmv_flag <= ~stmv_flag; |
dram0_addr <= dst_addr + index; |
dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel); |
dram0 <= 3'd2; |
inc_index(dram0_fn); |
end |
else begin |
`STFND: |
begin |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
dram_bus <= index; |
dram_v <= `VAL; |
dram0 <= 3'd7; |
end |
`STFND: |
if (lc != 0 && !int_pending) begin |
dram0_addr <= src_addr + index; |
inc_index(dram0_fn); |
if (dram0_data == dram_bus) begin |
lc <= 64'd0; |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
if (lc != 0 && !int_pending) begin |
dram0 <= 3'd1; |
dram0_addr <= src_addr + index; |
inc_index(dram0_fn); |
if (dram0_data == fnDatai(dram0_op,dram0_fn,cdat,rsel)) begin |
lc <= 64'd0; |
dram0 <= 3'd7; |
dram_v <= `VAL; |
end |
end |
else begin |
dram_v <= `VAL; |
dram0 <= 3'd7; |
dram_v <= `VAL; |
dram_bus <= index; |
end |
end |
else begin |
dram_id <= dram0_id; |
dram_tgt <= dram0_tgt; |
dram_bus <= index; |
dram_v <= `VAL; |
dram0 <= 3'd7; |
end |
`endif |
`INC: |
begin |
dram0_data <= fnDatai(dram0_op,dram0_fn,cdat,rsel); |
stmv_flag <= `TRUE; |
dram0 <= 3'd2; |
dram0 <= 3'd1; |
end |
// Set to NOP on a string miss |
`NOP: begin |
dram_v <= `VAL; |
dram0 <= 3'd0; |
end |
default: begin |
$display("Read hit [%h]",dram0_addr); |
dram_v <= `TRUE; |
4460,7 → 4858,10
endcase |
end |
3'd7: |
begin |
dram0 <= 3'd0; |
end |
default: dram0 <= 3'd0; |
endcase |
|
// |
4502,8 → 4903,7
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 |
$display("TLB issue"); |
if (!iq_cmt[n]) begin |
iqentry_cmt[n] <= `FALSE; |
if (!iqentry_cmt[n]) begin |
iqentry_done[n] <= `TRUE; |
iqentry_out[n] <= `FALSE; |
iqentry_agen[n] <= `FALSE; |
4523,8 → 4923,7
end |
end |
else if (!iqentry_stomp[n] && iqentry_memissue[n] && iqentry_agen[n] && !iqentry_out[n]) begin |
if (!iq_cmt[n]) begin |
iqentry_cmt[n] <= `FALSE; |
if (!iqentry_cmt[n]) begin |
iqentry_done[n] <= `TRUE; |
iqentry_out[n] <= `FALSE; |
iqentry_agen[n] <= `FALSE; |
4540,6 → 4939,7
if (dram0 == `DRAMSLOT_AVAIL) begin |
dram0 <= 3'd1; |
dram0_id <= { 1'b1, n[2:0] }; |
dram0_misspc <= iqentry_pc[n]; |
dram0_op <= iqentry_op[n]; |
dram0_fn <= iqentry_fn[n]; |
dram0_tgt <= iqentry_tgt[n]; |
4550,7 → 4950,10
iqentry_a2[n]; |
dram0_datacmp <= iqentry_a2[n]; |
`ifdef SEGMENTATION |
dram0_addr <= iqentry_a1[n]; |
if (iqentry_op[n]==`STCMP || iqentry_op[n]==`STMV) |
dram0_addr <= iqentry_a1[n] + {sregs[iqentry_fn[n][5:3]],12'h000}; |
else |
dram0_addr <= iqentry_a1[n]; |
dram0_seg <= {sregs[iqentry_fn[n][5:3]],12'h000}; |
dram0_lmt <= sregs[iqentry_fn[n][5:3]] + sregs_lmt[iqentry_fn[n][5:3]]; |
// dram0_exc <= (iqentry_a1[n][ABW-1:12] >= sregs_lmt[iqentry_fn[n][5:3]]) ? `EXC_SEGV : `EXC_NONE; |
4566,7 → 4969,7
`endif |
`endif |
stmv_flag <= `FALSE; |
index <= iqentry_op[n]==`INC ? iqentry_a2[n] : iqentry_a3[n]; |
index <= iqentry_op[n]==`STS ? fnIndexAmt(iqentry_fn[n]) : iqentry_op[n]==`INC ? iqentry_a2[n] : iqentry_a3[n]; |
iqentry_out[n] <= `TRUE; |
end |
end |
4612,8 → 5015,8
// It didn't work in simulation when the following was declared under an |
// independant always clk block |
// |
commit_spr(commit0_v,commit0_tgt,commit0_bus); |
commit_spr(commit1_v,commit1_tgt,commit1_bus); |
commit_spr(commit0_v,commit0_tgt,commit0_bus,0); |
commit_spr(commit1_v,commit1_tgt,commit1_bus,1); |
|
// When the INT instruction commits set the hardware interrupt status to disable further interrupts. |
if (int_commit) |
4998,11 → 5401,12
input commit_v; |
input [6:0] commit_tgt; |
input [DBW-1:0] commit_bus; |
input which; |
begin |
if (commit_v && commit_tgt[6]) begin |
casex(commit_tgt[5:0]) |
6'b00xxxx: begin |
pregs[commit_tgt[3:0]] <= commit_bus[3:0]; |
pregs[commit_tgt[3:0]] <= which ? cmt1nyb[commit_tgt[3:0]] : cmt0nyb[commit_tgt[3:0]];//commit_bus[3:0]; |
$display("pregs[%d]<=%h", commit_tgt[3:0], commit_bus[3:0]); |
// $stop; |
end |
5055,6 → 5459,7
6'd2: dbg_adr2 <= commit_bus; |
6'd3: dbg_adr3 <= commit_bus; |
6'd4: dbg_ctrl <= commit_bus; |
6'd5: dbg_stat <= commit_bus; |
endcase |
6'b111111: |
begin |
5067,20 → 5472,31
endtask |
|
// For string memory operations. |
// Indexing amount, should synth to a ROM. |
// |
task inc_index; |
function [63:0] fnIndexAmt; |
input [5:0] fn; |
begin |
case(fn[2:0]) |
3'd0: index <= index + 64'd1; |
3'd1: index <= index + 64'd2; |
3'd2: index <= index + 64'd4; |
3'd3: index <= index + 64'd8; |
3'd4: index <= index - 64'd1; |
3'd5: index <= index - 64'd2; |
3'd6: index <= index - 64'd4; |
3'd7: index <= index - 64'd8; |
3'd0: fnIndexAmt = 64'd1; |
3'd1: fnIndexAmt = 64'd2; |
3'd2: fnIndexAmt = 64'd4; |
3'd3: fnIndexAmt = 64'd8; |
3'd4: fnIndexAmt = 64'd1; |
3'd5: fnIndexAmt = 64'd2; |
3'd6: fnIndexAmt = 64'd4; |
3'd7: fnIndexAmt = 64'd8; |
endcase |
end |
endfunction |
|
|
// For string memory operations. |
// |
task inc_index; |
input [5:0] fn; |
begin |
index <= index + fnIndexAmt(fn); |
lc <= lc - 64'd1; |
end |
endtask |
5092,10 → 5508,12
// Read from the special registers unless overridden by the |
// value on the commit bus. |
casex(regno) |
6'b00xxxx: fnSpr = pregs[regno[3:0]]; |
6'b00xxxx: fnSpr = {DBW/4{pregs[regno[3:0]]}}; |
6'b01xxxx: fnSpr = cregs[regno[3:0]]; |
`ifdef SEGMENTATION |
6'b100xxx: fnSpr = {sregs[regno[2:0]],12'h000}; |
6'b101xxx: fnSpr = {sregs_lmt[regno[2:0]],12'h000}; |
`endif |
6'b110000: if (DBW==64) |
fnSpr = {pregs[15],pregs[14],pregs[13],pregs[12], |
pregs[11],pregs[10],pregs[9],pregs[8], |
5185,15 → 5603,29
end |
endtask |
|
// The exception_set var is used to reduce the number of logic levels. Rather |
// than having an if/elseif tree for all the exceptional conditions that are |
// trapped. The exception_set var tracks these excaptions and reduces the |
// tree to a single if. |
task enque0a; |
input [2:0] tail; |
input [2:0] inc; |
input unlink; |
begin |
`ifdef SEGMENTATION |
// 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); |
else begin |
`endif |
// If targeting a kernel mode register and not in kernel mode. |
// But okay if it is an SYS or INT instruction. |
if (fnIsKMOnlyReg(Rt0) && !km && !(opcode0==`SYS || opcode0==`INT)) |
set_exception(tail,8'd245); |
// If attempting to use an undefined instruction |
`ifdef TRAP_ILLEGALOPS |
if (fnIsIllegal(opcode0,opcode0==`MLO ? rfoc0[5:0] : fnFunc(fetchbuf0_instr))) |
set_exception(tail,8'd250); |
`endif |
`ifdef DEBUG_LOGIC |
if (dbg_ctrl[0] && dbg_ctrl[17:16]==2'b00 && fetchbuf0_pc==dbg_adr0) |
dbg_imatchA0 = `TRUE; |
5207,9 → 5639,9
dbg_imatchA = `TRUE; |
if (dbg_imatchA) |
set_exception(tail,8'd243); // Debug exception |
else begin |
`endif |
interrupt_pc = |
if (!exception_set) begin |
interrupt_pc = |
// If the previous instruction was an interrupt, then inherit the address |
(iqentry_op[(tail-3'd1)&7]==`INT && iqentry_v[(tail-3'd1)&7]==`VAL && iqentry_tgt[(tail-3'd1)&7][3:0]==4'hE) ? |
(string_pc != 0 ? string_pc : iqentry_pc[(tail-3'd1)&7]) : |
5235,6 → 5667,7
iqentry_fp [tail] <= fetchbuf0_fp; |
iqentry_rfw [tail] <= fetchbuf0_rfw; |
iqentry_tgt [tail] <= Rt0; |
iqentry_preg [tail] <= Pn0; |
iqentry_pred [tail] <= pregs[Pn0]; |
// Look at the previous queue slot to see if an immediate prefix is enqueued |
iqentry_a0[tail] <= opcode0==`INT ? fnImm(fetchbuf0_instr) : |
5261,10 → 5694,7
iqentry_T_s [tail] <= rf_source[Rt0]; |
// Always do this because it's the first queue slot. |
validate_args10(tail); |
`ifdef DEBUG_LOGIC |
end |
`endif |
end |
tail0 <= tail0 + inc; |
tail1 <= tail1 + inc; |
tail2 <= tail2 + inc; |
5369,9 → 5799,16
input validate_args; |
input unlink; |
begin |
`ifdef SEGMENTATION |
if (fetchbuf1_pc >= {sregs_lmt[7],12'h000} && fetchbuf1_pc[ABW-1:ABW-4]!=4'hF) |
set_exception(tail,8'd244); |
else begin |
`endif |
if (fnIsKMOnlyReg(Rt1) && !km && !(opcode1==`SYS || opcode1==`INT)) |
set_exception(tail,8'd245); |
`ifdef TRAP_ILLEGALOPS |
if (fnIsIllegal(opcode1,opcode1==`MLO ? rfoc1[5:0] : fnFunc(fetchbuf1_instr))) |
set_exception(tail,8'd250); |
`endif |
`ifdef DEBUG_LOGIC |
if (dbg_ctrl[0] && dbg_ctrl[17:16]==2'b00 && fetchbuf1_pc==dbg_adr0) |
dbg_imatchB0 = `TRUE; |
5385,8 → 5822,8
dbg_imatchB = `TRUE; |
if (dbg_imatchB) |
set_exception(tail,8'd243); // debug excpetion |
else begin |
`endif |
if (!exception_set) begin |
// If an instruction wasn't enqueued or it wasn't an interrupt instruction then |
// the interrupt pc will need to be set. Othersise this enqueue will inherit |
// from the previous one. |
5418,6 → 5855,7
iqentry_fp [tail] <= fetchbuf1_fp; |
iqentry_rfw [tail] <= fetchbuf1_rfw; |
iqentry_tgt [tail] <= Rt1; |
iqentry_preg [tail] <= Pn1; |
iqentry_pred [tail] <= pregs[Pn1]; |
// Look at the previous queue slot to see if an immediate prefix is enqueued |
// But don't allow it for a branch |
5446,10 → 5884,7
iqentry_T_s [tail] <= rf_source[Rt1]; |
if (validate_args) |
validate_args11(tail); |
`ifdef DEBUG_LOGIC |
end |
`endif |
end |
tail0 <= tail0 + inc; |
tail1 <= tail1 + inc; |
tail2 <= tail2 + inc; |
5509,10 → 5944,11
iqentry_T_v [tail] <= fnSourceT_v( opcode0 ) | rf_v[ Rt0 ]; |
if (fetchbuf0_rfw|fetchbuf0_pfw) begin |
$display("regv[%d] = %d", Rt0,rf_v[ Rt0 ]); |
rf_v[ Rt0 ] = Rt0==7'd0; |
rf_v[ Rt0 ] = fnRegIsAutoValid(Rt0); |
$display("reg[%d] <= INV",Rt0); |
rf_source[ Rt0 ] <= { fetchbuf0_mem, tail }; // top bit indicates ALU/MEM bus |
$display("10:rf_src[%d] <= %d, insn=%h", Rt0, tail,fetchbuf0_instr); |
invalidate_pregs(tail, Rt0, fetchbuf0_mem); |
end |
end |
endtask |
5528,9 → 5964,10
iqentry_T_v [tail] <= fnSourceT_v( opcode1 ) | rf_v[ Rt1 ]; |
if (fetchbuf1_rfw|fetchbuf1_pfw) begin |
$display("1:regv[%d] = %d", Rt1,rf_v[ Rt1 ]); |
rf_v[ Rt1 ] = Rt1==7'd0; |
rf_v[ Rt1 ] = fnRegIsAutoValid(Rt1); |
$display("reg[%d] <= INV",Rt1); |
rf_source[ Rt1 ] <= { fetchbuf1_mem, tail }; // top bit indicates ALU/MEM bus |
invalidate_pregs(tail, Rt1, fetchbuf1_mem); |
$display("11:rf_src[%d] <= %d, insn=%h", Rt1, tail,fetchbuf0_instr); |
end |
end |
5574,7 → 6011,7
iqentry_p_v [tail1] <= rf_v [{1'b1,2'h0,Pn1}] || cond1 < 4'h2; |
iqentry_p_s [tail1] <= rf_source [{1'b1,2'h0,Pn1}]; |
end |
else if ((Rt0 != 7'd0 && Pn1==Rt0[3:0]) && (Rt0 & 7'h70)==7'h40) begin |
else if ((Rt0 != 7'd0 && (Pn1==Rt0[3:0] || Rt0==7'h70)) && ((Rt0 & 7'h70)==7'h40)||Rt0==7'h70) begin |
iqentry_p_v [tail1] <= cond1 < 4'h2; |
iqentry_p_s [tail1] <= {fetchbuf0_mem, tail0}; |
end |
5666,18 → 6103,20
if (queued1|queued2) begin |
if (fetchbuf0_rfw|fetchbuf0_pfw) begin |
$display("regv[%d] = %d", Rt0,rf_v[ Rt0 ]); |
rf_v[ Rt0 ] = Rt0==7'd0; |
rf_v[ Rt0 ] = fnRegIsAutoValid(Rt0); |
$display("reg[%d] <= INV",Rt0); |
rf_source[ Rt0 ] <= { fetchbuf0_mem, tail0 }; // top bit indicates ALU/MEM bus |
$display("12:rf_src[%d] <= %d, insn=%h", Rt0, tail0,fetchbuf0_instr); |
invalidate_pregs(tail0, Rt0, fetchbuf0_mem); |
end |
end |
if (queued2) begin |
if (fetchbuf1_rfw|fetchbuf1_pfw) begin |
$display("1:regv[%d] = %d", Rt1,rf_v[ Rt1 ]); |
rf_v[ Rt1 ] = Rt1==7'd0; |
rf_v[ Rt1 ] = fnRegIsAutoValid(Rt1); |
$display("reg[%d] <= INV",Rt1); |
rf_source[ Rt1 ] <= { fetchbuf1_mem, tail1 }; // top bit indicates ALU/MEM bus |
invalidate_pregs(tail1, Rt1, fetchbuf1_mem); |
end |
end |
end |
5798,7 → 6237,59
iqentry_out [id[2:0]] <= `FALSE; |
iqentry_agen [id[2:0]] <= `FALSE; |
iqentry_tgt[id[2:0]] <= {1'b1,2'h1,(exc==8'd243)?4'hB:4'hD}; // Target EPC |
exception_set = `TRUE; |
end |
endtask |
|
// The core should really invalidate all the predicate registers when the |
// sideways slice of all the pregs is manipulated. But then the problem is |
// reading the result register into all the predicate registers at once. |
// The source for each register would be a bit field of the result register |
// and the core does not support this sort of thing. |
// So. After manipulating the sideways slice of predicate registers the |
// instruction should be followed with a SYNC instruction to ensure that |
// the results are picked up. |
// To be fixed one day. |
task invalidate_pregs; |
input [2:0] tail; |
input [6:0] Rt; |
input mem; |
begin |
if (Rt==7'h70) begin |
rf_v[7'h40] <= `INV; |
rf_v[7'h41] <= `INV; |
rf_v[7'h42] <= `INV; |
rf_v[7'h43] <= `INV; |
rf_v[7'h44] <= `INV; |
rf_v[7'h45] <= `INV; |
rf_v[7'h46] <= `INV; |
rf_v[7'h47] <= `INV; |
rf_v[7'h48] <= `INV; |
rf_v[7'h49] <= `INV; |
rf_v[7'h4A] <= `INV; |
rf_v[7'h4B] <= `INV; |
rf_v[7'h4C] <= `INV; |
rf_v[7'h4D] <= `INV; |
rf_v[7'h4E] <= `INV; |
rf_v[7'h4F] <= `INV; |
rf_source[7'h40] <= { mem, tail }; |
rf_source[7'h41] <= { mem, tail }; |
rf_source[7'h42] <= { mem, tail }; |
rf_source[7'h43] <= { mem, tail }; |
rf_source[7'h44] <= { mem, tail }; |
rf_source[7'h45] <= { mem, tail }; |
rf_source[7'h46] <= { mem, tail }; |
rf_source[7'h47] <= { mem, tail }; |
rf_source[7'h48] <= { mem, tail }; |
rf_source[7'h49] <= { mem, tail }; |
rf_source[7'h4A] <= { mem, tail }; |
rf_source[7'h4B] <= { mem, tail }; |
rf_source[7'h4C] <= { mem, tail }; |
rf_source[7'h4D] <= { mem, tail }; |
rf_source[7'h4E] <= { mem, tail }; |
rf_source[7'h4F] <= { mem, tail }; |
end |
end |
endtask |
|
endmodule |
/verilog/Thor_alu.v
59,6 → 59,7
wire [DBW-1:0] shfto; |
wire alu_mult_done,alu_div_done; |
wire [DBW-1:0] p_out; |
reg [3:0] o1; |
|
integer n; |
|
184,7 → 185,7
|
always @* |
begin |
casex(alu_op) |
case(alu_op) |
`LDI,`LDIS: o <= alu_argI; |
`RR: |
case(alu_fn) |
298,81 → 299,86
endcase |
`BITI: |
begin |
o[0] <= andi_res==64'd0; |
o[1] <= andi_res[DBW-1]; |
o[2] <= andi_res[0]; |
o[3] <= 1'b0; |
o[DBW-1:4] <= 60'd0; |
o1[0] = andi_res==64'd0; |
o1[1] = andi_res[DBW-1]; |
o1[2] = andi_res[0]; |
o1[3] = 1'b0; |
o <= {16{o1}}; |
end |
`TST: |
// 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: |
case(alu_fn) |
6'd0: // TST - integer |
begin |
o[0] <= alu_argA == 64'd0; |
o[1] <= alu_argA[DBW-1]; |
o[2] <= 1'b0; |
o[3] <= 1'b0; |
o[DBW-1:4] <= 60'd0; |
o1[0] = alu_argA == 64'd0; |
o1[1] = alu_argA[DBW-1]; |
o1[2] = 1'b0; |
o1[3] = 1'b0; |
o <= {16{o1}}; |
end |
`ifdef FLOATING_POINT |
6'd1: // FSTST - float single |
begin |
o[0] <= alu_argA[30:0]==31'd0; // + or - zero |
o[1] <= alu_argA[31]; // signed less than |
o[2] <= alu_argA[31]; |
o1[0] = alu_argA[30:0]==31'd0; // + or - zero |
o1[1] = alu_argA[31]; // signed less than |
o1[2] = alu_argA[31]; |
// unordered |
o[3] <= alu_argA[30:23]==8'hFF && alu_argA[22:0]!=23'd0; // NaN |
o[DBW-1:4] <= 60'd0; |
o1[3] = alu_argA[30:23]==8'hFF && alu_argA[22:0]!=23'd0; // NaN |
o <= {16{o1}}; |
end |
6'd2: // FTST - float double |
begin |
o[0] <= alu_argA[DBW-2:0]==63'd0; // + or - zero |
o[1] <= alu_argA[DBW-1]; // signed less than |
o[2] <= alu_argA[DBW-1]; |
o1[0] = alu_argA[DBW-2:0]==63'd0; // + or - zero |
o1[1] = alu_argA[DBW-1]; // signed less than |
o1[2] = alu_argA[DBW-1]; |
// unordered |
if (DBW==64) |
o[3] <= alu_argA[62:52]==11'h7FF && alu_argA[51:0]!=52'd0; // NaN |
o1[3] = alu_argA[62:52]==11'h7FF && alu_argA[51:0]!=52'd0; // NaN |
else |
o[3] <= 1'b0; |
o[DBW-1:4] <= 60'd0; |
o1[3] = 1'b0; |
o <= {16{o1}}; |
end |
`endif |
default: o <= 64'd0; |
endcase |
`CMP: begin |
// 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: |
begin |
case(alu_fn) |
2'd0: begin // ICMP |
o[0] <= alu_argA == alu_argB; |
o[1] <= alu_argAs < alu_argBs; |
o[2] <= alu_argA < alu_argB; |
o[3] <= 1'b0; |
o[DBW-1:4] <= 60'd0; |
o1[0] = alu_argA == alu_argB; |
o1[1] = alu_argAs < alu_argBs; |
o1[2] = alu_argA < alu_argB; |
o1[3] = 1'b0; |
o <= {16{o1}}; |
end |
`ifdef FLOATING_POINT |
2'd1: begin // FSCMP |
o[0] <= fseq; |
o[1] <= fslt; |
o[2] <= fslt1; |
o[3] <= snanA | snanB; |
o[DBW-1:4] <= 60'd0; |
o1[0] = fseq; |
o1[1] = fslt; |
o1[2] = fslt1; |
o1[3] = snanA | snanB; |
o <= {16{o1}}; |
end |
2'd2: begin // FCMP |
o[0] <= feq; |
o[1] <= flt; |
o[2] <= flt1; |
o[3] <= nanA | nanB; |
o[DBW-1:4] <= 60'd0; |
o1[0] = feq; |
o1[1] = flt; |
o1[2] = flt1; |
o1[3] = nanA | nanB; |
o <= {16{o1}}; |
end |
`endif |
default: o <= 64'hDEADDEADDEADDEAD; |
endcase |
end |
`CMPI: begin |
o[0] <= alu_argA == alu_argI; |
o[1] <= alu_argAs < alu_argIs; |
o[2] <= alu_argA < alu_argI; |
o[3] <= 1'b0; |
o[DBW-1:4] <= 64'd0; |
// 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: |
begin |
o1[0] = alu_argA == alu_argI; |
o1[1] = alu_argAs < alu_argIs; |
o1[2] = alu_argA < alu_argI; |
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: |
/verilog/Thor_execute_combo.v
186,9 → 186,9
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))))); |
|
assign branchmiss = (alu0_branchmiss | alu1_branchmiss), |
misspc = (alu0_branchmiss ? alu0_misspc : alu1_misspc), |
missid = (alu0_branchmiss ? alu0_sourceid : alu1_sourceid); |
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); |
|
`ifdef FLOATING_POINT |
wire fp0_exception; |
/verilog/Thor_defines.v
34,6 → 34,7
`define STRINGOPS 1'b1 |
`define DEBUG_LOGIC 1'b1 |
//`define THREEWAY 1'b1 |
`define TRAP_ILLEGALOPS 1'b1 |
|
`define TRUE 1'b1 |
`define FALSE 1'b0 |
42,10 → 43,10
`define ZERO 64'd0 |
|
|
`define TST 8'b0000xxxx |
`define CMP 8'b0001xxxx |
`define CMPI 8'b0010xxxx |
`define BR 8'b0011xxxx |
`define TST 4'b0000 |
`define CMP 4'b0001 |
`define CMPI 4'b0010 |
`define BR 4'b0011 |
|
`define RR 8'h40 |
`define ADD 6'h00 |
228,6 → 229,7
`define BFCHG 4'h3 |
`define BFEXTU 4'h4 |
`define BFEXT 4'h5 |
`define BFINSI 4'd6 |
|
`define MOVS 8'hAB |
// Uncached access instructions |
/verilog/Thor_Retarget.v
0,0 → 1,134
// ============================================================================ |
// __ |
// \\__/ o\ (C) 2015 Robert Finch, Stratford |
// \ __ / All rights reserved. |
// \/_// robfinch<remove>@finitron.ca |
// || |
// |
// This source file is free software: you can redistribute it and/or modify |
// it under the terms of the GNU Lesser General Public License as published |
// by the Free Software Foundation, either version 3 of the License, or |
// (at your option) any later version. |
// |
// This source file is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// You should have received a copy of the GNU General Public License |
// along with this program. If not, see <http://www.gnu.org/licenses/>. |
// |
// |
// Establish the source queue id for a target register after a branch. |
// Makes use of the fact that in Verilog later instructions override |
// earlier ones. So if there are two queue entries that use the same |
// target register, the later queue entry will become the valid source |
// as it's written after the earlier queue entry. |
// |
// This code uses a tree approach rather than loop logic which races to the |
// the right value. The timing from the toolset is a little more reliable |
// that way. |
// |
// ============================================================================ |
// |
if (branchmiss) begin |
// Default the entire register file as valid, then invalidate target |
// registers as they are found in the queue. |
for (n = 1; n < NREGS; n = n + 1) |
rf_v[n] = `VAL; |
// Missed at head0, one instruction (current one) to worry about. |
if (missid==head0) begin |
rf_source[iqentry_tgt[head0]] <= { iqentry_mem[head0], head0}; |
rf_v[iqentry_tgt[head0]] = `INV; |
end |
else if (missid==head1) begin |
rf_source[iqentry_tgt[head0]] <= { iqentry_mem[head0], head0}; |
rf_v[iqentry_tgt[head0]] = `INV; |
rf_source[iqentry_tgt[head1]] <= { iqentry_mem[head1], head1}; |
rf_v[iqentry_tgt[head1]] = `INV; |
end |
else if (missid==head2) begin |
rf_source[iqentry_tgt[head0]] <= { iqentry_mem[head0], head0}; |
rf_v[iqentry_tgt[head0]] = `INV; |
rf_source[iqentry_tgt[head1]] <= { iqentry_mem[head1], head1}; |
rf_v[iqentry_tgt[head1]] = `INV; |
rf_source[iqentry_tgt[head2]] <= { iqentry_mem[head2], head2}; |
rf_v[iqentry_tgt[head2]] = `INV; |
end |
else if (missid==head3) begin |
rf_source[iqentry_tgt[head0]] <= { iqentry_mem[head0], head0}; |
rf_v[iqentry_tgt[head0]] = `INV; |
rf_source[iqentry_tgt[head1]] <= { iqentry_mem[head1], head1}; |
rf_v[iqentry_tgt[head1]] = `INV; |
rf_source[iqentry_tgt[head2]] <= { iqentry_mem[head2], head2}; |
rf_v[iqentry_tgt[head2]] = `INV; |
rf_source[iqentry_tgt[head3]] <= { iqentry_mem[head3], head3}; |
rf_v[iqentry_tgt[head3]] = `INV; |
end |
else if (missid==head4) begin |
rf_source[iqentry_tgt[head0]] <= { iqentry_mem[head0], head0}; |
rf_v[iqentry_tgt[head0]] = `INV; |
rf_source[iqentry_tgt[head1]] <= { iqentry_mem[head1], head1}; |
rf_v[iqentry_tgt[head1]] = `INV; |
rf_source[iqentry_tgt[head2]] <= { iqentry_mem[head2], head2}; |
rf_v[iqentry_tgt[head2]] = `INV; |
rf_source[iqentry_tgt[head3]] <= { iqentry_mem[head3], head3}; |
rf_v[iqentry_tgt[head3]] = `INV; |
rf_source[iqentry_tgt[head4]] <= { iqentry_mem[head4], head4}; |
rf_v[iqentry_tgt[head4]] = `INV; |
end |
else if (missid==head5) begin |
rf_source[iqentry_tgt[head0]] <= { iqentry_mem[head0], head0}; |
rf_v[iqentry_tgt[head0]] = `INV; |
rf_source[iqentry_tgt[head1]] <= { iqentry_mem[head1], head1}; |
rf_v[iqentry_tgt[head1]] = `INV; |
rf_source[iqentry_tgt[head2]] <= { iqentry_mem[head2], head2}; |
rf_v[iqentry_tgt[head2]] = `INV; |
rf_source[iqentry_tgt[head3]] <= { iqentry_mem[head3], head3}; |
rf_v[iqentry_tgt[head3]] = `INV; |
rf_source[iqentry_tgt[head4]] <= { iqentry_mem[head4], head4}; |
rf_v[iqentry_tgt[head4]] = `INV; |
rf_source[iqentry_tgt[head5]] <= { iqentry_mem[head5], head5}; |
rf_v[iqentry_tgt[head5]] = `INV; |
end |
else if (missid==head6) begin |
rf_source[iqentry_tgt[head0]] <= { iqentry_mem[head0], head0}; |
rf_v[iqentry_tgt[head0]] = `INV; |
rf_source[iqentry_tgt[head1]] <= { iqentry_mem[head1], head1}; |
rf_v[iqentry_tgt[head1]] = `INV; |
rf_source[iqentry_tgt[head2]] <= { iqentry_mem[head2], head2}; |
rf_v[iqentry_tgt[head2]] = `INV; |
rf_source[iqentry_tgt[head3]] <= { iqentry_mem[head3], head3}; |
rf_v[iqentry_tgt[head3]] = `INV; |
rf_source[iqentry_tgt[head4]] <= { iqentry_mem[head4], head4}; |
rf_v[iqentry_tgt[head4]] = `INV; |
rf_source[iqentry_tgt[head5]] <= { iqentry_mem[head5], head5}; |
rf_v[iqentry_tgt[head5]] = `INV; |
rf_source[iqentry_tgt[head6]] <= { iqentry_mem[head6], head6}; |
rf_v[iqentry_tgt[head6]] = `INV; |
end |
else if (missid==head7) begin |
rf_source[iqentry_tgt[head0]] <= { iqentry_mem[head0], head0}; |
rf_v[iqentry_tgt[head0]] = `INV; |
rf_source[iqentry_tgt[head1]] <= { iqentry_mem[head1], head1}; |
rf_v[iqentry_tgt[head1]] = `INV; |
rf_source[iqentry_tgt[head2]] <= { iqentry_mem[head2], head2}; |
rf_v[iqentry_tgt[head2]] = `INV; |
rf_source[iqentry_tgt[head3]] <= { iqentry_mem[head3], head3}; |
rf_v[iqentry_tgt[head3]] = `INV; |
rf_source[iqentry_tgt[head4]] <= { iqentry_mem[head4], head4}; |
rf_v[iqentry_tgt[head4]] = `INV; |
rf_source[iqentry_tgt[head5]] <= { iqentry_mem[head5], head5}; |
rf_v[iqentry_tgt[head5]] = `INV; |
rf_source[iqentry_tgt[head6]] <= { iqentry_mem[head6], head6}; |
rf_v[iqentry_tgt[head6]] = `INV; |
rf_source[iqentry_tgt[head7]] <= { iqentry_mem[head7], head7}; |
rf_v[iqentry_tgt[head7]] = `INV; |
end |
// The following registers are always valid |
rf_v[7'h00] = `VAL; |
rf_v[7'h50] = `VAL; // C0 |
rf_v[7'h5F] = `VAL; // C15 (PC) |
rf_v[7'h72] = `VAL; // tick |
end |
|