OpenCores
URL https://opencores.org/ocsvn/thor/thor/trunk

Subversion Repositories thor

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /thor
    from Rev 12 to Rev 13
    Reverse comparison

Rev 12 → Rev 13

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

powered by: WebSVN 2.1.0

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