OpenCores
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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.