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/FT64v7/rtl
    from Rev 60 to Rev 61
    Reverse comparison

Rev 60 → Rev 61

/common/FT64_EvalBranch.v
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2017-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
24,6 → 24,7
// ============================================================================
//
`define TRUE 1'b1
`define BNEI 6'h12
`define BBc 6'h26
`define Bcc 6'h30
`define BEQI 6'h32
36,6 → 37,12
`define BGE 3'h3
`define BLTU 3'h6
`define BGEU 3'h7
`define BAND 3'h0
`define BOR 3'h1
`define BXOR 3'd2
`define BNAND 3'h4
`define BNOR 3'h5
`define BXNOR 3'd6
 
`define IBNE 2'd2
`define DBNZ 2'd3
63,7 → 70,18
`BGEU: takb <= a >= b;
default: takb <= `TRUE;
endcase
`BLcc:
case(instr[15:13])
`BAND: takb <= a != 0 && b != 0;
`BOR: takb <= a != 0 || b != 0;
`BXOR: takb <= (a != 0) ^ (b != 0);
`BNAND: takb <= !(a != 0 && b != 0);
`BNOR: takb <= !(a != 0 || b != 0);
`BXNOR: takb <= !((a != 0) ^ (b != 0));
default: takb <= `TRUE;
endcase
`BEQI: takb <= a=={{56{instr[22]}},instr[22:18],instr[15:13]};
`BNEI: takb <= a!={{56{instr[22]}},instr[22:18],instr[15:13]};
`BBc:
case(instr[14:13])
2'd0: takb <= a[{instr[22:18],instr[15]}]; // BBS
/common/FT64_FCU_Calc.v
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2017-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
/common/FT64_InsLength.v
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2018-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
/common/FT64_alu.v
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2017-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
25,15 → 25,10
`include "FT64_defines.vh"
`include "FT64_config.vh"
 
module FT64_alu(rst, clk, ld, abort, instr, sz, tlb, store, a, b, c, pc, Ra, tgt, tgt2, ven, vm,
module FT64_alu(rst, clk, ld, abort, instr, sz, tlb, store, a, b, c, t, pc, Ra, tgt, tgt2, ven, vm,
csr, o, ob, done, idle, excen, exc, thrd, ptrmask, state, mem, shift,
ol, dl, ASID, icl_i, cyc_i, we_i, vadr_i, cyc_o, we_o, padr_o, uncached, tlb_miss,
exv_o, rdv_o, wrv_o
`ifdef SUPPORT_SEGMENTATION
, zs_base, ds_base, es_base, fs_base, gs_base, hs_base, ss_base, cs_base,
zsub, dsub, esub, fsub, gsub, hsub, ssub, csub,
zslb, dslb, eslb, fslb, gslb, hslb, sslb, cslb
`endif
`ifdef SUPPORT_BBMS
, pb, cbl, cbu, ro, dbl, dbu, sbl, sbu, en
`endif
45,6 → 40,7
parameter TRUE = 1'b1;
parameter FALSE = 1'b0;
parameter PTR = 20'hFFF01;
parameter BASE_SHIFT = 13'd0;
input rst;
input clk;
input ld;
56,6 → 52,7
input [63:0] a;
input [63:0] b;
input [63:0] c;
input [63:0] t; // target register value
input [31:0] pc;
input [11:0] Ra;
input [11:0] tgt;
89,32 → 86,6
output wrv_o;
output rdv_o;
output exv_o;
`ifdef SUPPORT_SEGMENTATION
input [63:0] zs_base;
input [63:0] ds_base;
input [63:0] es_base;
input [63:0] fs_base;
input [63:0] gs_base;
input [63:0] hs_base;
input [63:0] ss_base;
input [63:0] cs_base;
input [63:0] zslb;
input [63:0] dslb;
input [63:0] eslb;
input [63:0] fslb;
input [63:0] gslb;
input [63:0] hslb;
input [63:0] sslb;
input [63:0] cslb;
input [63:0] zsub;
input [63:0] dsub;
input [63:0] esub;
input [63:0] fsub;
input [63:0] gsub;
input [63:0] hsub;
input [63:0] ssub;
input [63:0] csub;
`endif
`ifdef SUPPORT_BBMS
input [63:0] pb;
input [63:0] cbl;
140,48 → 111,9
 
reg adrDone, adrIdle;
reg [63:0] usa; // unsegmented address
`ifdef SUPPORT_SEGMENTATION
reg [63:0] pb;
reg [63:0] ub;
reg [63:0] lb;
always @*
case(usa[63:61])
3'd0: pb <= zs_base;
3'd1: pb <= ds_base;
3'd2: pb <= es_base;
3'd3: pb <= fs_base;
3'd4: pb <= gs_base;
3'd5: pb <= hs_base;
3'd6: pb <= ss_base;
3'd7: pb <= cs_base;
endcase
always @*
case(usa[63:61])
3'd0: ub <= zsub;
3'd1: ub <= dsub;
3'd2: ub <= esub;
3'd3: ub <= fsub;
3'd4: ub <= gsub;
3'd5: ub <= hsub;
3'd6: ub <= ssub;
3'd7: ub <= csub;
endcase
always @*
case(usa[63:61])
3'd0: lb <= zslb;
3'd1: lb <= dslb;
3'd2: lb <= eslb;
3'd3: lb <= fslb;
3'd4: lb <= gslb;
3'd5: lb <= hslb;
3'd6: lb <= sslb;
3'd7: lb <= cslb;
endcase
`else
`ifndef SUPPORT_BBMS
reg [63:0] pb = 64'h0;
`endif
`endif
reg [63:0] addro;
reg [63:0] adr; // load / store address
reg [63:0] shift8;
317,15 → 249,38
 
function IsShiftAndOp;
input [47:0] isn;
IsShiftAndOp = FALSE;
if (isn[`INSTRUCTION_L2]==2'b01) begin
case(isn[`INSTRUCTION_OP])
`R2:
case(isn[47:42])
`SHIFTR: IsShiftAndOp = TRUE;
default: IsShiftAndOp = FALSE;
endcase
default: IsShiftAndOp = FALSE;
endcase
end
else
IsShiftAndOp = FALSE;
endfunction
 
wire [63:0] bfout,shfto;
wire [63:0] shftob;
wire [63:0] shftco;
reg [63:0] shift10;
 
always @(posedge clk)
shift9 <= shift8;
always @*
case (instr[41:36])
`ADD: shift10 <= shift9 + c;
`SUB: shift10 <= shift9 - c;
`AND: shift10 <= shift9 & c;
`OR: shift10 <= shift9 | c;
`XOR: shift10 <= shift9 ^ c;
6'h20: shift10 <= ~shift9; // COM
6'h21: shift10 <= !shift9; // NOT
default: shift10 <= shift9;
endcase
 
wire tlb_done, tlb_idle;
wire [DBW-1:0] tlbo;
623,7 → 578,8
.idle(div_idle)
);
 
wire [5:0] bshift = instr[31:26]==`SHIFTR ? b[5:0] : {instr[30],instr[22:18]};
wire [5:0] bshift = IsShiftAndOp(instr) ? ( instr[29] ? {instr[28],instr[22:18]} : b[5:0])
: (instr[31:26]==`SHIFTR ? b[5:0] : {instr[30],instr[22:18]});
 
FT64_shift ushft1
(
800,6 → 756,11
wire [63:0] redor16 = {15'd0,|a[63:48],15'd0,|a[47:32],15'd0,|a[31:16],15'd0,|a[15:0]};
wire [63:0] redor8 = {7'b0,|a[63:56],6'b0,|a[55:48],7'd0,|a[47:40],7'd0,|a[39:32],7'd0,
|a[31:24],7'd0,|a[23:16],7'd0,|a[15:8],7'd0,|a[7:0]};
wire [63:0] redand64 = {63'd0,&a};
wire [63:0] redand32 = {31'd0,&a[63:32],31'd0,&a[31:0]};
wire [63:0] redand16 = {15'd0,&a[63:48],15'd0,&a[47:32],15'd0,&a[31:16],15'd0,&a[15:0]};
wire [63:0] redand8 = {7'b0,&a[63:56],6'b0,&a[55:48],7'd0,&a[47:40],7'd0,&a[39:32],7'd0,
&a[31:24],7'd0,&a[23:16],7'd0,&a[15:8],7'd0,&a[7:0]};
wire [63:0] zxb10 = {54'd0,b[9:0]};
wire [63:0] sxb10 = {{54{b[9]}},b[9:0]};
wire [63:0] zxb26 = {38'd0,instr[47:32],instr[27:18]};
978,7 → 939,7
endcase
case(instr[35:33])
`ASL,`ASR,`SHL,`SHR,`ROL,`ROR:
o[63:0] = shift9;
o[63:0] = shift10;
default: o[63:0] = 64'hDCDCDCDCDCDCDCDC;
endcase
end
1039,6 → 1000,13
2'd2: o = {-a[63:32],-a[31:0]};
2'd3: o = -a;
endcase
`REDAND:
case(sz[1:0])
2'd0: o = redand8;
2'd1: o = redand16;
2'd2: o = redand32;
2'd3: o = redand64;
endcase
`REDOR: case(sz[1:0])
2'd0: o = redor8;
2'd1: o = redor16;
1056,13 → 1024,22
endcase
`BMM: o[63:0] = BIG ? bmmo : 64'hCCCCCCCCCCCCCCCC;
`SHIFT31,
`SHIFT63,
`SHIFT63:
begin
if (instr[25:23]==`SHL || instr[25:23]==`ASL)
o = shfto;
else
o = BIG ? shfto : 64'hCCCCCCCCCCCCCCCC;
$display("BIG=%d",BIG);
if(!BIG)
$stop;
end
`SHIFTR:
begin
if (instr[25:23]==`SHL || instr[25:23]==`ASL)
o[63:0] = shfto;
o = shfto;
else
o[63:0] = BIG ? shfto : 64'hCCCCCCCCCCCCCCCC;
o = BIG ? shfto : 64'hCCCCCCCCCCCCCCCC;
$display("BIG=%d",BIG);
if(!BIG)
$stop;
1101,12 → 1078,18
`else
o = a + b;
`endif
// If the operation is SIMD the target register must be passed in arg T.
`SUB:
`ifdef SIMD
case(sz)
3'd0,3'd4:
3'd0:
begin
o[7:0] = a[7:0] - b[7:0];
o[63:8] = t[63:8];
end
3'd4:
begin
o[7:0] = a[7:0] - b[7:0];
o[15:8] = a[15:8] - b[15:8];
o[23:16] = a[23:16] - b[23:16];
o[31:24] = a[31:24] - b[31:24];
1135,6 → 1118,7
`else
o = a - b;
`endif
`SEQ: tskSeq(instr,instr[25:23],a,b,o);
`SLT: tskSlt(instr,instr[25:23],a,b,o);
`SLTU: tskSltu(instr,instr[25:23],a,b,o);
`SLE: tskSle(instr,instr[25:23],a,b,o);
1175,37 → 1159,56
end
`MIN:
`ifdef SIMD
case(sz)
3'd0,3'd4:
begin
o[7:0] = BIG ? ($signed(a[7:0]) < $signed(b[7:0]) ? a[7:0] : b[7:0]) : 8'hCC;
o[15:8] = BIG ? ($signed(a[15:8]) < $signed(b[15:8]) ? a[15:8] : b[15:8]) : 64'hCCCCCCCCCCCCCCCC;
o[23:16] = BIG ? ($signed(a[23:16]) < $signed(b[23:16]) ? a[23:16] : b[23:16]) : 64'hCCCCCCCCCCCCCCCC;
o[31:24] = BIG ? ($signed(a[31:24]) < $signed(b[31:24]) ? a[31:24] : b[31:24]) : 64'hCCCCCCCCCCCCCCCC;
o[39:32] = BIG ? ($signed(a[39:32]) < $signed(b[39:32]) ? a[39:32] : b[39:32]) : 64'hCCCCCCCCCCCCCCCC;
o[47:40] = BIG ? ($signed(a[47:40]) < $signed(b[47:40]) ? a[47:40] : b[47:40]) : 64'hCCCCCCCCCCCCCCCC;
o[55:48] = BIG ? ($signed(a[55:48]) < $signed(b[55:48]) ? a[55:48] : b[55:48]) : 64'hCCCCCCCCCCCCCCCC;
o[63:56] = BIG ? ($signed(a[63:56]) < $signed(b[63:56]) ? a[63:56] : b[63:56]) : 64'hCCCCCCCCCCCCCCCC;
end
3'd1,3'd5:
begin
o[15:0] = BIG ? ($signed(a[15:0]) < $signed(b[15:0]) ? a[15:0] : b[15:0]) : 64'hCCCCCCCCCCCCCCCC;
o[32:16] = BIG ? ($signed(a[32:16]) < $signed(b[32:16]) ? a[32:16] : b[32:16]) : 64'hCCCCCCCCCCCCCCCC;
o[47:32] = BIG ? ($signed(a[47:32]) < $signed(b[47:32]) ? a[47:32] : b[47:32]) : 64'hCCCCCCCCCCCCCCCC;
o[63:48] = BIG ? ($signed(a[63:48]) < $signed(b[63:48]) ? a[63:48] : b[63:48]) : 64'hCCCCCCCCCCCCCCCC;
end
3'd2,3'd6:
begin
o[31:0] = BIG ? ($signed(a[31:0]) < $signed(b[31:0]) ? a[31:0] : b[31:0]) : 64'hCCCCCCCCCCCCCCCC;
o[63:32] = BIG ? ($signed(a[63:32]) < $signed(b[63:32]) ? a[63:32] : b[63:32]) : 64'hCCCCCCCCCCCCCCCC;
end
3'd3,3'd7:
case(sz)
3'd0:
begin
o[7:0] = BIG ? ($signed(a[7:0]) < $signed(b[7:0]) ? a[7:0] : b[7:0]) : 8'hCC;
o[63:8] = BIG ? t[63:8] : 56'hCCCCCCCCCCCCCC;
end
3'd1:
begin
o[15:0] = BIG ? ($signed(a[15:0]) < $signed(b[15:0]) ? a[15:0] : b[15:0]) : 16'hCCCC;
o[63:16] = BIG ? t[63:16] : 48'hCCCCCCCCCCCC;
end
3'd2:
begin
o[31:0] = BIG ? ($signed(a[31:0]) < $signed(b[31:0]) ? a[31:0] : b[31:0]) : 32'hCCCCCCCC;
o[63:32] = BIG ? t[63:32] : 32'hCCCCCCCC;
end
3'd3:
begin
o[63:0] = BIG ? ($signed(a) < $signed(b) ? a : b) : 64'hCCCCCCCCCCCCCCCC;
end
endcase
o = BIG ? ($signed(a) < $signed(b) ? a : b) : 64'hCCCCCCCCCCCCCCCC;
end
3'd4:
begin
o[7:0] = BIG ? ($signed(a[7:0]) < $signed(b[7:0]) ? a[7:0] : b[7:0]) : 8'hCC;
o[15:8] = BIG ? ($signed(a[15:8]) < $signed(b[15:8]) ? a[15:8] : b[15:8]) : 64'hCCCCCCCCCCCCCCCC;
o[23:16] = BIG ? ($signed(a[23:16]) < $signed(b[23:16]) ? a[23:16] : b[23:16]) : 64'hCCCCCCCCCCCCCCCC;
o[31:24] = BIG ? ($signed(a[31:24]) < $signed(b[31:24]) ? a[31:24] : b[31:24]) : 64'hCCCCCCCCCCCCCCCC;
o[39:32] = BIG ? ($signed(a[39:32]) < $signed(b[39:32]) ? a[39:32] : b[39:32]) : 64'hCCCCCCCCCCCCCCCC;
o[47:40] = BIG ? ($signed(a[47:40]) < $signed(b[47:40]) ? a[47:40] : b[47:40]) : 64'hCCCCCCCCCCCCCCCC;
o[55:48] = BIG ? ($signed(a[55:48]) < $signed(b[55:48]) ? a[55:48] : b[55:48]) : 64'hCCCCCCCCCCCCCCCC;
o[63:56] = BIG ? ($signed(a[63:56]) < $signed(b[63:56]) ? a[63:56] : b[63:56]) : 64'hCCCCCCCCCCCCCCCC;
end
3'd5:
begin
o[15:0] = BIG ? ($signed(a[15:0]) < $signed(b[15:0]) ? a[15:0] : b[15:0]) : 64'hCCCCCCCCCCCCCCCC;
o[32:16] = BIG ? ($signed(a[32:16]) < $signed(b[32:16]) ? a[32:16] : b[32:16]) : 64'hCCCCCCCCCCCCCCCC;
o[47:32] = BIG ? ($signed(a[47:32]) < $signed(b[47:32]) ? a[47:32] : b[47:32]) : 64'hCCCCCCCCCCCCCCCC;
o[63:48] = BIG ? ($signed(a[63:48]) < $signed(b[63:48]) ? a[63:48] : b[63:48]) : 64'hCCCCCCCCCCCCCCCC;
end
3'd6:
begin
o[31:0] = BIG ? ($signed(a[31:0]) < $signed(b[31:0]) ? a[31:0] : b[31:0]) : 64'hCCCCCCCCCCCCCCCC;
o[63:32] = BIG ? ($signed(a[63:32]) < $signed(b[63:32]) ? a[63:32] : b[63:32]) : 64'hCCCCCCCCCCCCCCCC;
end
3'd7:
begin
o = BIG ? ($signed(a) < $signed(b) ? a : b) : 64'hCCCCCCCCCCCCCCCC;
end
endcase
`else
o[63:0] = BIG ? ($signed(a) < $signed(b) ? a : b) : 64'hCCCCCCCCCCCCCCCC;
o = BIG ? ($signed(a) < $signed(b) ? a : b) : 64'hCCCCCCCCCCCCCCCC;
`endif
`MAX:
`ifdef SIMD
1287,7 → 1290,7
`LHX,`LHUX,`LWX,`LWRX:
if (BIG) begin
usa = a + (c << instr[19:18]);
o = {pb[50:0],13'd0} + usa;
o = {pb[50:0],BASE_SHIFT} + usa;
end
else
o = 64'hCCCCCCCCEEEEEEEE;
1294,7 → 1297,7
`LVX,`SVX:
if (BIG) begin
usa = a + (c << 2'd3);
o = {pb[50:0],13'd0} + usa;
o = {pb[50:0],BASE_SHIFT} + usa;
end
else
o = 64'hCCCCCCCCCCCCCCCC;
1301,7 → 1304,7
`LVWS,`SVWS:
if (BIG) begin
usa = a + ({c * ven,3'b000});
o = {pb[50:0],13'd0} + usa;
o = {pb[50:0],BASE_SHIFT} + usa;
end
else
o = 64'hCCCCCCCCCCCCCCCC;
1312,18 → 1315,18
`PUSH:
begin
usa = a - 4'd8;
o = {pb[50:0],13'd0} + usa;
o = {pb[50:0],BASE_SHIFT} + usa;
end
`SBX,`SCX,`SHX,`SWX,`SWCX:
if (BIG) begin
usa = a + (c << instr[14:13]);
o = {pb[50:0],13'd0} + usa;
o = {pb[50:0],BASE_SHIFT} + usa;
end
else
o = 64'hCCCCCCCCEEEEEEEE;
`SVX: if (BIG) begin
usa = a + (c << 2'd3);
o = {pb[50:0],13'd0} + usa;
o = {pb[50:0],BASE_SHIFT} + usa;
end
else
o = 64'hCCCCCCCCCCCCCCCC;
1330,7 → 1333,7
`SVWS:
if (BIG) begin
usa = a + ({c * ven,3'b000});
o = {pb[50:0],13'd0} + usa;
o = {pb[50:0],BASE_SHIFT} + usa;
end
else
o = 64'hCCCCCCCCCCCCCCCC;
1356,6 → 1359,7
o = {{15{instr[31]}},instr[31:18],instr[12:8],30'd0};
end
`ADDI: o = a + b;
`SEQI: o = a == b;
`SLTI: o = $signed(a) < $signed(b);
`SLTUI: o = a < b;
`SGTI: o = $signed(a) > $signed(b);
1373,37 → 1377,40
`LB,`LBU,`SB:
begin
usa = a + b;
o = {pb[50:0],13'd0} + usa;
o = {pb[50:0],BASE_SHIFT} + usa;
end
`Lx,`LxU,`Sx,`LVx,`LVxU:
casez(b[2:0])
3'b100:
begin
usa = a + {b[63:3],3'b0}; // LW / SW
o = {pb[50:0],BASE_SHIFT} + usa;
end
3'b?10:
begin
usa = a + {b[63:2],2'b0}; // LH / LHU / SH
o = {pb[50:0],BASE_SHIFT} + usa;
end
default:
begin
usa = a + {b[63:1],1'b0}; // LC / LCU / SC
o = {pb[50:0],BASE_SHIFT} + usa;
end
endcase
`PUSHC:
begin
casez(b[2:0])
3'b100:
begin
usa = a + {b[63:3],3'b0}; // LW / SW
o = {pb[50:0],13'd0} + usa;
end
3'b?10:
begin
usa = a + {b[63:2],2'b0}; // LH / LHU / SH
o = {pb[50:0],13'd0} + usa;
end
default:
begin
usa = a + {b[63:1],1'b0}; // LC / LCU / SC
o = {pb[50:0],13'd0} + usa;
end
endcase
usa = a - 4'd8;
o = {pb[50:0],BASE_SHIFT} + usa;
end
`LWR,`SWC,`CAS,`CACHE:
begin
usa = a + b;
o = {pb[50:0],13'd0} + usa;
o = {pb[50:0],BASE_SHIFT} + usa;
end
`LV,`SV:
begin
usa = a + b + {ven,3'b0};
o = {pb[50:0],13'd0} + usa;
o = {pb[50:0],BASE_SHIFT} + usa;
end
`CSRRW:
case(instr[27:18])
1569,11 → 1576,6
`CSRRW: exc <= (instr[27:21]==7'b0011011) ? `FLT_SEG : `FLT_NONE;
`MEMNDX:
begin
`ifdef SUPPORT_SEGMENTATION
if (usa < {lb[50:0],13'h0000} && usa > {ub[50:0],13'h1fff} && dl!=2'b00)
exc <= (Ra[4:0]==5'd30 || Ra[4:0]==5'd31) ? `FLT_STK : `FLT_SGB;
else
`endif
`ifdef SUPPORT_BBMS
if ((Ra[4:0]==5'd30 || Ra[4:0]==5'd31) && (usa < {sbl[50:0],13'd0} || usa > {sbu[50:0],13'h1FF8}) && dl!=2'b00)
exc <= `FLT_STK;
1602,7 → 1604,7
if (BIG) begin
case({instr[31:28],instr[22:21]})
`LBX,`LBUX,`LVBX,`LVBUX: exc <= `FLT_NONE;
`LCX,`LCUX,`LVCX,`LVCUX: exc <= |o[ 0] ? `FLT_ALN : `FLT_NONE;
`LCX,`LCUX,`LVCX,`LVCUX: exc <= o[ 0] ? `FLT_ALN : `FLT_NONE;
`LVHX,`LVHUX,`LHX,`LHUX: exc <= |o[1:0] ? `FLT_ALN : `FLT_NONE;
`LWX,`LVWX,`LWRX,
`CACHEX,`LVX: exc <= |o[2:0] ? `FLT_ALN : `FLT_NONE;
1618,7 → 1620,7
case({instr[31:28],instr[17:16]})
`PUSH: exc <= |o[2:0] ? `FLT_ALN : `FLT_NONE;
`SBX: exc <= `FLT_NONE;
`SCX: exc <= |o[ 0] ? `FLT_ALN : `FLT_NONE;
`SCX: exc <= o[ 0] ? `FLT_ALN : `FLT_NONE;
`SHX: exc <= |o[1:0] ? `FLT_ALN : `FLT_NONE;
`SWX,`SWCX: exc <= |o[2:0] ? `FLT_ALN : `FLT_NONE;
`SVX: exc <= |o[2:0] ? `FLT_ALN : `FLT_NONE;
1634,11 → 1636,6
exc <= `FLT_UNIMP;
end
end
`ifdef SUPPORT_SEGMENTATION
`LB,`LBU,`SB:
if (usa < {lb[50:0],13'h0000} && usa > {ub[50:0],13'h1fff} && dl!=2'b00)
exc <= (Ra[4:0]==5'd30 || Ra[4:0]==5'd31) ? `FLT_STK : `FLT_SGB;
`endif
`ifdef SUPPORT_BBMS
`LB,`LBU,`SB:
if ((Ra[4:0]==5'd30 || Ra[4:0]==5'd31) && (usa < {sbl[50:0],13'd0} || usa > {sbu[50:0],13'h1FF8}) && dl!=2'b00)
1654,11 → 1651,6
`endif
`Lx,`Sx,`LxU,`LVx,`LVxU:
begin
`ifdef SUPPORT_SEGMENTATION
if (usa < {lb[50:0],13'h0000} && usa > {ub[50:0],13'h1fff} && dl!=2'b00)
exc <= (Ra[4:0]==5'd30 || Ra[4:0]==5'd31) ? `FLT_STK : `FLT_SGB;
else
`endif
`ifdef SUPPORT_BBMS
if ((Ra[4:0]==5'd30 || Ra[4:0]==5'd31) && (usa < {sbl[50:0],13'd0} || usa > {sbu[50:0],13'h1FF8}) && dl!=2'b00)
exc <= `FLT_STK;
1673,18 → 1665,13
else
`endif
casez(b[2:0])
3'b100: exc <= |o[2:0] ? `FLT_ALN : `FLT_NONE; // LW / SW
3'b?10: exc <= |o[1:0] ? `FLT_ALN : `FLT_NONE; // LH / LHU / SH
default: exc <= |o[ 0] ? `FLT_ALN : `FLT_NONE; // LC / LCU / SC
3'b100: exc <= o[2:0]!=3'b0 ? `FLT_NONE : `FLT_NONE; // LW / SW
3'b?10: exc <= o[1:0]!=2'b0 ? `FLT_ALN : `FLT_NONE; // LH / LHU / SH
default: exc <= o[ 0] ? `FLT_ALN : `FLT_NONE; // LC / LCU / SC
endcase
end
`LWR,`SWC,`CAS,`CACHE:
begin
`ifdef SUPPORT_SEGMENTATION
if (usa < {lb[50:0],13'h0000} && usa > {ub[50:0],13'h1fff} && dl!=2'b00)
exc <= (Ra[4:0]==5'd30 || Ra[4:0]==5'd31) ? `FLT_STK : `FLT_SGB;
else
`endif
`ifdef SUPPORT_BBMS
if ((Ra[4:0]==5'd30 || Ra[4:0]==5'd31) && (usa < {sbl[50:0],13'd0} || usa > {sbu[50:0],13'h1FF8}) && dl!=2'b00)
exc <= `FLT_STK;
1698,7 → 1685,7
exc <= `FLT_WRV;
else
`endif
exc <= |o[2:0] ? `FLT_ALN : `FLT_NONE;
exc <= o[2:0]!=3'b0 ? `FLT_ALN : `FLT_NONE;
end
default: exc <= `FLT_NONE;
endcase
1712,6 → 1699,47
bb <= c;
end
 
task tskSeq;
input [47:0] instr;
input [2:0] sz;
input [63:0] a;
input [63:0] b;
output [63:0] o;
begin
`ifdef SIMD
case(sz[2:0])
3'd0: o[63:0] = $signed(a[7:0]) == $signed(b[7:0]);
3'd1: o[63:0] = $signed(a[15:0]) == $signed(b[15:0]);
3'd2: o[63:0] = $signed(a[31:0]) == $signed(b[31:0]);
3'd3: o[63:0] = $signed(a) == $signed(b);
3'd4: o[63:0] = {
7'h0,$signed(a[7:0]) == $signed(b[7:0]),
7'h0,$signed(a[15:8]) == $signed(b[15:8]),
7'h0,$signed(a[23:16]) == $signed(b[23:16]),
7'h0,$signed(a[31:24]) == $signed(b[31:24]),
7'h0,$signed(a[39:32]) == $signed(b[39:32]),
7'h0,$signed(a[47:40]) == $signed(b[47:40]),
7'h0,$signed(a[55:48]) == $signed(b[55:48]),
7'h0,$signed(a[63:56]) == $signed(b[63:56])
};
3'd5: o[63:0] = {
15'h0,$signed(a[15:0]) == $signed(b[15:0]),
15'h0,$signed(a[31:16]) == $signed(b[31:16]),
15'h0,$signed(a[47:32]) == $signed(b[47:32]),
15'h0,$signed(a[63:48]) == $signed(b[63:48])
};
3'd6: o[63:0] = {
31'h0,$signed(a[31:0]) == $signed(b[31:0]),
31'h0,$signed(a[63:32]) == $signed(b[63:32])
};
3'd7: o[63:0] = $signed(a[63:0]) == $signed(b[63:0]);
endcase
`else
o = $signed(a) == $signed(b);
`endif
end
endtask
 
task tskSlt;
input [47:0] instr;
input [2:0] sz;
1789,7 → 1817,7
3'd7: o[63:0] = $signed(a[63:0]) <= $signed(b[63:0]);
endcase
`else
o[63:0] = $signed(a[63:0]) <= $signed(b[63:0]);
o = $signed(a) <= $signed(b);
`endif
end
endtask
/common/FT64_config.vh
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2017-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
33,6 → 33,10
//`define SUPPORT_SEGMENTATION 1'b1
//`define SUPPORT_PREDICATION 1'b1
//`define DEBUG_LOGIC 1'b1
 
// The following define generates rtl to support 40-bit jumps and calls,
// otherwise only 24-bit jumps and calls are supported.
//`define JMP40 1'b1
`define L1_ICACHE_SIZE 2 // 2 or 4 for 2 or 4 kB
 
// One way to tweak the size of the core a little bit is to limit the number
89,7 → 93,7
// Comment out the following to remove FCU enhancements (branch predictor, BTB, RSB)
//`define FCU_ENH 1
// Comment out the following to remove bypassing logic on the functional units
//`define FU_BYPASS 1
`define FU_BYPASS 1
 
//`define SUPPORT_TLB 1
 
/common/FT64_defines.vh
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2017-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
126,9 → 126,11
`define MEMDB 5'h10
`define MEMSB 5'h11
`define SYNC 5'h12
`define EXEC 5'h13
`define CHAIN_OFF 5'h14
`define CHAIN_ON 5'h15
`define SETWB 5'h16
`define REDAND 5'h17
`define SXH 5'h18
`define SXC 5'h19
`define SXB 5'h1A
142,6 → 144,7
`define AND 6'h08
`define OR 6'h09
`define XOR 6'h0A
`define SEQ 6'h0B
`define NAND 6'h0C
`define NOR 6'h0D
`define XNOR 6'h0E
172,6 → 175,7
`define RTI 6'h32
`define RTE 6'h32
`define VMOV 6'h33
`define MOV2SEG 6'h37
`define MULU 6'h38
`define MULSU 6'h39
`define MUL 6'h3A
188,14 → 192,21
`define ANDI 6'h08
`define ORI 6'h09
`define XORI 6'h0A
`define EXEC 6'h0B
`define SEQI 6'h0B
`define REX 6'h0D
`define XNORI 6'h0E
`define FLOAT 6'h0F
`define LDCS 6'h10
`define BLcc 6'h10
`define BAND 3'd0
`define BOR 3'd1
`define BXOR 3'd2
`define BNAND 3'd4
`define BNOR 3'd5
`define BXOR 3'd6
`define LVxU 6'h11
`define CMPI 6'h12
`define BNEI 6'h12
`define LB 6'h13
`define PUSHC 6'h14
`define SB 6'h15
`define MEMNDX 6'h16
`define LVBX 6'h00
313,6 → 324,7
`define EXR 8'h7F
 
`define NOP_INSN {42'd0,`NOP}
`define PFI 16'h1F80 // reserved for PFI
`define INSN_FLT_EXF 16'h1180
`define INSN_FLT_IBE 16'h10A0
`define INSN_FLT_TLB 16'h1280
374,6 → 386,7
`define CSR_BM_CTR 10'h3C1
`define CSR_ICL_CTR 10'h3C2
`define CSR_IRQ_CTR 10'h3C3
`define CSR_BR_CTR 10'h3C4
`define CSR_TIME 10'h3E0
`define CSR_INFO 10'b11_1111_????
 
425,16 → 438,9
`define FLT_BD 8'd55
`define FLT_STK 8'd56
`define FLT_DBE 8'd60
`define FLT_RET 8'd230
`define FLT_CS 8'd231
`define FLT_ZS_LD 8'd232
`define FLT_DS_LD 8'd233
`define FLT_ES_LD 8'd234
`define FLT_FS_LD 8'd235
`define FLT_GS_LD 8'd236
`define FLT_HS_LD 8'd237
`define FLT_SS_LD 8'd238
`define FLT_CS_LD 8'd239
`define FLT_STP 8'd232 // segment type
`define FLT_STZ 8'd233 // stack segment zero
`define FLT_SNP 8'd234 // segment not present
 
`define INSTRUCTION_OP 5:0
`define INSTRUCTION_L2 7:6
485,6 → 491,7
`define IB_RC 70:66
`define IB_RB 65:61
`define IB_RA 60:56
`define IB_LOADSEG 53
`define IB_PRFW 52
`define IB_CMP 51
`define IB_PUSH 47
/common/FT64_icache.v
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2017-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
34,16 → 34,16
 
module FT64_L1_icache_mem(rst, clk, wr, en, lineno, i, o, ov, invall, invline);
parameter pLines = 64;
parameter pLineWidth = 298;
parameter pLineWidth = 306;
localparam pLNMSB = pLines==128 ? 6 : 5;
input rst;
input clk;
input wr;
input [8:0] en;
input [9:0] en;
input [pLNMSB:0] lineno;
input [pLineWidth-1:0] i;
output [pLineWidth-1:0] o;
output [8:0] ov;
output [9:0] ov;
input invall;
input invline;
 
60,6 → 60,7
reg [pLines-1:0] valid6;
reg [pLines-1:0] valid7;
reg [pLines-1:0] valid8;
reg [pLines-1:0] valid9;
 
initial begin
for (n = 0; n < pLines; n = n + 1)
83,8 → 84,10
always @(posedge clk)
if (wr & en[7]) mem[lineno][255:224] <= i[255:224];
always @(posedge clk)
if (wr & en[8]) mem[lineno][297:256] <= i[297:256];
if (wr & en[8]) mem[lineno][287:256] <= i[287:256];
always @(posedge clk)
if (wr & en[9]) mem[lineno][305:288] <= i[305:288];
always @(posedge clk)
if (rst) begin
valid0 <= 64'd0;
valid1 <= 64'd0;
95,6 → 98,7
valid6 <= 64'd0;
valid7 <= 64'd0;
valid8 <= 64'd0;
valid9 <= 64'd0;
end
else begin
if (invall) begin
107,6 → 111,7
valid6 <= 64'd0;
valid7 <= 64'd0;
valid8 <= 64'd0;
valid9 <= 64'd0;
end
else if (invline) begin
valid0[lineno] <= 1'b0;
118,6 → 123,7
valid6[lineno] <= 1'b0;
valid7[lineno] <= 1'b0;
valid8[lineno] <= 1'b0;
valid9[lineno] <= 1'b0;
end
else if (wr) begin
if (en[0]) valid0[lineno] <= 1'b1;
129,6 → 135,7
if (en[6]) valid6[lineno] <= 1'b1;
if (en[7]) valid7[lineno] <= 1'b1;
if (en[8]) valid8[lineno] <= 1'b1;
if (en[9]) valid9[lineno] <= 1'b1;
end
end
 
142,6 → 149,7
assign ov[6] = valid6[lineno];
assign ov[7] = valid7[lineno];
assign ov[8] = valid8[lineno];
assign ov[9] = valid9[lineno];
 
endmodule
 
214,6 → 222,10
reg [AMSB+8-5:0] mem2 [0:pLines/4-1];
reg [AMSB+8-5:0] mem3 [0:pLines/4-1];
reg [AMSB+8:0] rradr;
reg [pLines/4-1:0] mem0v;
reg [pLines/4-1:0] mem1v;
reg [pLines/4-1:0] mem2v;
reg [pLines/4-1:0] mem3v;
integer n;
initial begin
for (n = 0; n < pLines/4; n = n + 1)
242,10 → 254,29
end
end
 
wire hit0 = mem0[adr[pMSB:5]]==adr[AMSB+8:5];
wire hit1 = mem1[adr[pMSB:5]]==adr[AMSB+8:5];
wire hit2 = mem2[adr[pMSB:5]]==adr[AMSB+8:5];
wire hit3 = mem3[adr[pMSB:5]]==adr[AMSB+8:5];
always @(posedge clk)
if (rst) begin
mem0v <= 1'd0;
mem1v <= 1'd0;
mem2v <= 1'd0;
mem3v <= 1'd0;
end
else begin
if (wr) begin
case(lfsro[1:0])
2'b00: begin mem0v[adr[pMSB:5]] <= 1'b1; end
2'b01: begin mem1v[adr[pMSB:5]] <= 1'b1; end
2'b10: begin mem2v[adr[pMSB:5]] <= 1'b1; end
2'b11: begin mem3v[adr[pMSB:5]] <= 1'b1; end
endcase
end
end
 
 
wire hit0 = mem0[adr[pMSB:5]]==adr[AMSB+8:5] & mem0v[adr[pMSB:5]];
wire hit1 = mem1[adr[pMSB:5]]==adr[AMSB+8:5] & mem1v[adr[pMSB:5]];
wire hit2 = mem2[adr[pMSB:5]]==adr[AMSB+8:5] & mem2v[adr[pMSB:5]];
wire hit3 = mem3[adr[pMSB:5]]==adr[AMSB+8:5] & mem3v[adr[pMSB:5]];
always @*
//if (wr2) lineno = wlineno;
if (hit0) lineno = {2'b00,adr[pMSB:5]};
324,10 → 355,10
input nxt;
input wr;
output wr_ack;
input [8:0] en;
input [9:0] en;
input [AMSB+8:0] adr;
input [AMSB+8:0] wadr;
input [297:0] i;
input [305:0] i;
output reg [55:0] o;
output reg [1:0] fault;
output hit;
334,14 → 365,14
input invall;
input invline;
 
wire [297:0] ic;
reg [297:0] i1, i2;
wire [8:0] lv; // line valid
wire [305:0] ic;
reg [305:0] i1, i2;
wire [9:0] lv; // line valid
wire [pLNMSB:0] lineno;
wire [pLNMSB:0] wlineno;
wire taghit;
reg wr1,wr2;
reg [8:0] en1, en2;
reg [9:0] en1, en2;
reg invline1, invline2;
 
// Must update the cache memory on the cycle after a write to the tag memmory.
351,7 → 382,7
always @(posedge clk)
wr2 <= wr1;
always @(posedge clk)
i1 <= i[297:0];
i1 <= i[305:0];
always @(posedge clk)
i2 <= i1;
always @(posedge clk)
424,13 → 455,13
endgenerate
 
// Valid if a 64-bit area encompassing a potential 48-bit instruction is valid.
assign hit = taghit & lv[adr[4:2]] & lv[adr[4:2]+4'd1];
assign hit = taghit & |lv;//[adr[4:2]];// & lv[adr[4:2]+4'd1];
 
//always @(radr or ic0 or ic1)
always @(adr or ic)
o <= ic >> {adr[4:0],3'h0};
always @*
fault <= ic[297:296];
fault <= ic[305:304];
 
assign wr_ack = wr2;
 
446,7 → 477,7
input [2:0] sel;
input [63:0] i;
input [1:0] fault;
output [297:0] o;
output [305:0] o;
output reg ov;
input invall;
input invline;
456,7 → 487,7
reg [63:0] mem1 [0:511];
reg [63:0] mem2 [0:511];
reg [63:0] mem3 [0:511];
reg [39:0] mem4 [0:511];
reg [47:0] mem4 [0:511];
reg [1:0] memf [0:511];
reg [511:0] valid;
reg [8:0] rrcl;
484,7 → 515,7
3'd1: begin mem1[lineno] <= i; memf[lineno] <= memf[lineno] | fault; end
3'd2: begin mem2[lineno] <= i; memf[lineno] <= memf[lineno] | fault; end
3'd3: begin mem3[lineno] <= i; memf[lineno] <= memf[lineno] | fault; end
3'd4: begin mem4[lineno] <= i[39:0]; memf[lineno] <= memf[lineno] | fault; end
3'd4: begin mem4[lineno] <= i[47:0]; memf[lineno] <= memf[lineno] | fault; end
endcase
end
end
523,7 → 554,7
input exv_i;
input [63:0] i;
input err_i;
output [297:0] o;
output [305:0] o;
output hit;
input invall;
input invline;
/common/FT64_idecoder.v
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2017-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
48,6 → 48,7
parameter wyde = 3'd1;
parameter tetra = 3'd2;
parameter octa = 3'd3;
parameter hexi = 3'd4;
 
// Really IsPredictableBranch
// Does not include BccR's
97,8 → 98,10
IsALU = TRUE;
`BRK: IsALU = FALSE;
`Bcc: IsALU = FALSE;
`BLcc: IsALU = FALSE;
`BBc: IsALU = FALSE;
`BEQI: IsALU = FALSE;
`BNEI: IsALU = FALSE;
`CHK: IsALU = FALSE;
`JAL: IsALU = FALSE;
`JMP: IsALU = FALSE;
178,8 → 181,10
default: IsFlowCtrl <= FALSE;
endcase
`Bcc: IsFlowCtrl <= TRUE;
`BLcc: IsFlowCtrl <= TRUE;
`BBc: IsFlowCtrl <= TRUE;
`BEQI: IsFlowCtrl <= TRUE;
`BNEI: IsFlowCtrl <= TRUE;
`CHK: IsFlowCtrl <= TRUE;
`JAL: IsFlowCtrl <= TRUE;
`JMP: IsFlowCtrl <= TRUE;
250,7 → 255,7
// Had branches that could exception if looping to self. But in a tight loop
// it affects store performance.
// -> A branch may only exception if it loops back to itself.
`Bcc,`BBc,`BEQI: fnCanException = isn[7] ? brdisp == 11'h7FF : brdisp == 11'h7FE;
`Bcc,`BLcc,`BBc,`BEQI,`BNEI: fnCanException = isn[7] ? brdisp == 11'h7FF : brdisp == 11'h7FE;
`CHK: fnCanException = TRUE;
default:
// Stores can stil exception if there is a write buffer, but we allow following
257,9 → 262,9
// stores to be issued by ignoring the fact they can exception because the stores
// can be undone by invalidating the write buffer.
`ifdef HAS_WB
fnCanException = IsMem(isn) && !IsStore(isn);
fnCanException = IsMem && !IsStore(isn);
`else
fnCanException = IsMem(isn);
fnCanException = IsMem;
`endif
endcase
end
281,9 → 286,32
endcase
endfunction
 
function IsMov2Seg;
input [47:0] isn;
case(isn[`INSTRUCTION_OP])
`R2:
if (isn[6])
IsMov2Seg = isn[47:42]==`MOV2SEG;
else
case(isn[`INSTRUCTION_S2])
`MOV2SEG: IsMov2Seg = TRUE;
`RTI: IsMov2Seg = TRUE;
default: IsMov2Seg = FALSE;
endcase
`RET:
IsMov2Seg = TRUE;
default: IsMov2Seg = FALSE;
endcase
endfunction
 
function IsVolatileLoad;
input [47:0] isn;
case(isn[`INSTRUCTION_OP])
`R2:
if (isn[6])
IsVolatileLoad = isn[47:42]==`MOV2SEG;
else
IsVolatileLoad = isn[31:26]==`MOV2SEG;
`MEMNDX:
if (isn[`INSTRUCTION_L2]==2'b00)
case({isn[31:28],isn[22:21]})
334,6 → 362,7
endcase
else
IsStore = FALSE;
`PUSHC: IsStore = TRUE;
`SB: IsStore = TRUE;
`Sx: IsStore = TRUE;
`SWC: IsStore = TRUE;
365,13 → 394,33
endcase
else
IsPush = FALSE;
`PUSHC: IsPush = TRUE;
default: IsPush = FALSE;
endcase
endfunction
 
function [0:0] IsMem;
function IsPushc;
input [47:0] isn;
case(isn[`INSTRUCTION_OP])
`PUSHC: IsPushc = TRUE;
default: IsPushc = FALSE;
endcase
endfunction
 
//function [0:0] IsMem;
reg IsMem;
always @*
//input [47:0] isn;
case(instr[`INSTRUCTION_OP])
`R2:
if (instr[6])
IsMem = instr[47:42]==`MOV2SEG;
else
case(instr[`INSTRUCTION_S2])
`MOV2SEG: IsMem = TRUE;
`RTI: IsMem = TRUE;
default: IsMem = FALSE;
endcase
`MEMNDX: IsMem = TRUE;
`AMO: IsMem = TRUE;
`LB: IsMem = TRUE;
381,6 → 430,7
`LWR: IsMem = TRUE;
`LV,`SV: IsMem = TRUE;
`INC: IsMem = TRUE;
`PUSHC: IsMem = TRUE;
`SB: IsMem = TRUE;
`Sx: IsMem = TRUE;
`SWC: IsMem = TRUE;
387,9 → 437,10
`CAS: IsMem = TRUE;
`LVx: IsMem = TRUE;
`LVxU: IsMem = TRUE;
//`RET: IsMem = TRUE;???
default: IsMem = FALSE;
endcase
endfunction
//endfunction
 
function IsMemNdx;
input [47:0] isn;
441,10 → 492,11
MemSize = octa;
`LB,`LBU: MemSize = byt;
`Lx,`LxU,`LVx,`LVxU:
casez(isn[20:18])
3'b100: MemSize = octa;
3'b?10: MemSize = tetra;
3'b??1: MemSize = wyde;
casez(isn[21:18])
4'b1000: MemSize = hexi;
4'b?100: MemSize = octa;
4'b??10: MemSize = tetra;
4'b???1: MemSize = wyde;
default: MemSize = octa;
endcase
`LWR: MemSize = octa;
459,14 → 511,16
endcase
`SB: MemSize = byt;
`Sx:
casez(isn[15:13])
3'b100: MemSize = octa;
3'b?10: MemSize = tetra;
3'b??1: MemSize = wyde;
casez(isn[16:13])
4'b1000: MemSize = hexi;
4'b?100: MemSize = octa;
4'b??10: MemSize = tetra;
4'b???1: MemSize = wyde;
default: MemSize = octa;
endcase
`SWC: MemSize = octa;
`SV: MemSize = octa;
`PUSHC: MemSize = octa;
default: MemSize = octa;
endcase
endfunction
563,22 → 617,6
endcase
endfunction
 
function IsCmp;
input [47:0] isn;
case(isn[`INSTRUCTION_OP])
`R2:
if (isn[`INSTRUCTION_L2]==2'b00)
case(isn[31:26])
`CMP: IsCmp = TRUE;
default: IsCmp = FALSE;
endcase
else
IsCmp = FALSE;
`CMPI: IsCmp = TRUE;
default: IsCmp = FALSE;
endcase
endfunction
 
function IsLWRX;
input [47:0] isn;
case(isn[`INSTRUCTION_OP])
621,8 → 659,10
input [47:0] isn;
casez(isn[`INSTRUCTION_OP])
`Bcc: IsBranch = TRUE;
`BLcc: IsBranch = TRUE;
`BBc: IsBranch = TRUE;
`BEQI: IsBranch = TRUE;
`BNEI: IsBranch = TRUE;
`CHK: IsBranch = TRUE;
default: IsBranch = FALSE;
endcase
655,7 → 695,7
 
function IsSync;
input [47:0] isn;
IsSync = (isn[`INSTRUCTION_OP]==`R2 && isn[`INSTRUCTION_L2]==2'b00 && isn[`INSTRUCTION_S2]==`R1 && isn[22:18]==`SYNC) || IsRti(isn);
IsSync = (isn[`INSTRUCTION_OP]==`R2 && isn[`INSTRUCTION_L2]==2'b00 && isn[`INSTRUCTION_S2]==`R1 && isn[22:18]==`SYNC) || IsRti(isn) || IsMov2Seg(isn);
endfunction
 
// Has an extendable 14-bit constant
663,6 → 703,7
input [47:0] isn;
casez(isn[`INSTRUCTION_OP])
`ADDI: HasConst = TRUE;
`SEQI: HasConst = TRUE;
`SLTI: HasConst = TRUE;
`SLTUI: HasConst = TRUE;
`SGTI: HasConst = TRUE;
694,6 → 735,7
`RET: HasConst = TRUE;
`LVx: HasConst = TRUE;
`LVxU: HasConst = TRUE;
`PUSHC: HasConst = TRUE;
default: HasConst = FALSE;
endcase
endfunction
742,6 → 784,7
endcase
`ADD: IsRFW = TRUE;
`SUB: IsRFW = TRUE;
`SEQ: IsRFW = TRUE;
`SLT: IsRFW = TRUE;
`SLTU: IsRFW = TRUE;
`SLE: IsRFW = TRUE;
839,6 → 882,7
`BBc: IsRFW = FALSE;
`BITFIELD: IsRFW = TRUE;
`ADDI: IsRFW = TRUE;
`SEQI: IsRFW = TRUE;
`SLTI: IsRFW = TRUE;
`SLTUI: IsRFW = TRUE;
`SGTI: IsRFW = TRUE;
864,6 → 908,7
`LV: IsRFW = TRUE;
`LVx: IsRFW = TRUE;
`LVxU: IsRFW = TRUE;
`PUSHC: IsRFW = TRUE;
`CAS: IsRFW = TRUE;
`AMO: IsRFW = TRUE;
`CSRRW: IsRFW = TRUE;
882,7 → 927,6
`CMP: fnWe = 8'h00; // CMP sets predicate registers so doesn't update general register file.
default: fnWe = 8'hFF;
endcase
`CMPI: fnWe = 8'h00;
default: fnWe = 8'hFF;
endcase
/*
932,8 → 976,10
casez(isn[`INSTRUCTION_OP])
`BRK: Source1Valid = TRUE;
`Bcc: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`BLcc: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`BBc: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`BEQI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`BNEI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`CHK: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`R2: case(isn[`INSTRUCTION_S2])
`SHIFT31: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
943,6 → 989,7
endcase
`MEMNDX: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`ADDI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SEQI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SLTI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SLTUI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SGTI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
964,6 → 1011,7
`Sx: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SWC: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SV: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`PUSHC: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`INC: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`CAS: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`JAL: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
984,14 → 1032,15
casez(isn[`INSTRUCTION_OP])
`BRK: Source2Valid = TRUE;
`Bcc: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`BLcc: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`BBc: Source2Valid = TRUE;
`BEQI: Source2Valid = TRUE;
`BNEI: Source2Valid = TRUE;
`CHK: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`R2: case(isn[`INSTRUCTION_S2])
`R1: Source2Valid = TRUE;
`SHIFTR: Source2Valid = isn[25] ? 1'b1 : isn[`INSTRUCTION_RB]==5'd0;
`SHIFT31: Source2Valid = isn[25] ? 1'b1 : isn[`INSTRUCTION_RB]==5'd0;
`SHIFT63: Source2Valid = isn[25] ? 1'b1 : isn[`INSTRUCTION_RB]==5'd0;
`SHIFT31: Source2Valid = TRUE;
`SHIFT63: Source2Valid = TRUE;
default: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
endcase
`MEMNDX:
1006,6 → 1055,7
default: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
endcase
`ADDI: Source2Valid = TRUE;
`SEQI: Source2Valid = TRUE;
`SLTI: Source2Valid = TRUE;
`SLTUI: Source2Valid = TRUE;
`SGTI: Source2Valid = TRUE;
1025,6 → 1075,7
`SB: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`Sx: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`SWC: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`PUSHC: Source2Valid = TRUE;
`CAS: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`JAL: Source2Valid = TRUE;
`RET: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
1096,8 → 1147,9
`endif
begin
bus <= 144'h0;
bus[`IB_CMP] <= IsCmp(instr);
if (IsStore(instr))
bus[`IB_LOADSEG] <= IsMov2Seg(instr);
bus[`IB_CMP] <= 1'b0;//IsCmp(instr);
if (IsStore(instr) & !IsPushc(instr))
bus[`IB_CONST] <= instr[6]==1'b1 ? {{34{instr[47]}},instr[47:23],instr[17:13]} :
{{50{instr[31]}},instr[31:23],instr[17:13]};
else
1143,7 → 1195,7
bus[`IB_PUSH] <= IsPush(instr);
bus[`IB_ODDBALL] <= IsOddball(instr);
bus[`IB_MEMSZ] <= MemSize(instr);
bus[`IB_MEM] <= IsMem(instr);
bus[`IB_MEM] <= IsMem;
bus[`IB_MEMNDX] <= IsMemNdx(instr);
bus[`IB_RMW] <= IsCAS(instr) || IsAMO(instr) || IsInc(instr);
bus[`IB_MEMDB] <= IsMemdb(instr);
1157,7 → 1209,7
bus[`IB_SYNC] <= IsSync(instr)||IsBrk(instr)||IsRti(instr);
bus[`IB_FSYNC] <= IsFSync(instr);
bus[`IB_RFW] <= (Rt==5'd0) ? 1'b0 : IsRFW(instr);// && !IsCmp(instr);
bus[`IB_PRFW] <= IsCmp(instr);
bus[`IB_PRFW] <= 1'b0;//IsCmp(instr);
bus[`IB_WE] <= fnWe(instr);
id_o <= id_i;
idv_o <= idv_i;
1184,8 → 1236,10
IsALU = TRUE;
`BRK: IsALU = FALSE;
`Bcc: IsALU = FALSE;
`BLcc: IsALU = FALSE;
`BBc: IsALU = FALSE;
`BEQI: IsALU = FALSE;
`BNEI: IsALU = FALSE;
`CHK: IsALU = FALSE;
`JAL: IsALU = FALSE;
`JMP: IsALU = FALSE;
/common/FT64_iexpander.v
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2017-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
157,7 → 157,7
expand[17:13] = fnRp(cinstr[2:0]);
expand[12:8] = fnRp(cinstr[2:0]);
expand[7:6] = 2'b10;
expand[5:0] = 8'h02; // R2 instruction
expand[5:0] = 6'h02; // R2 instruction
end
2'd1: begin
expand[47:32] = 16'h0000;
167,7 → 167,7
expand[17:13] = fnRp(cinstr[2:0]);
expand[12:8] = fnRp(cinstr[2:0]);
expand[7:6] = 2'b10;
expand[5:0] = 8'h02; // R2 instruction
expand[5:0] = 6'h02; // R2 instruction
end
2'd2: begin
expand[47:32] = 16'h0000;
177,7 → 177,7
expand[17:13] = fnRp(cinstr[2:0]);
expand[12:8] = fnRp(cinstr[2:0]);
expand[7:6] = 2'b10;
expand[5:0] = 8'h02; // R2 instruction
expand[5:0] = 6'h02; // R2 instruction
end
2'd3: begin
expand[47:32] = 16'h0000;
187,7 → 187,7
expand[17:13] = fnRp(cinstr[2:0]);
expand[12:8] = fnRp(cinstr[2:0]);
expand[7:6] = 2'b10;
expand[5:0] = 8'h02; // R2 instruction
expand[5:0] = 6'h02; // R2 instruction
end
endcase
endcase
198,7 → 198,7
expand[22:18] = 5'd0; // Rb = 0
expand[17:16] = cinstr[1:0];
expand[15:13] = 3'd0; // BEQ
expand[12:8] = 5'd0; // r0==r0
expand[12:8] = 5'd0; // Ra = r0
expand[7:6] = 2'b10;
expand[5:0] = `Bcc; // 0x38
end
/common/FT64_ipt.v
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2018-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
27,13 → 27,15
`define TRUE 1'b1
`define FALSE 1'b0
`endif
//`define BYPASS 1'b1
 
module FT64_ipt(rst, clk, pkeys_i, ol_i, cti_i, cs_i, icl_i, cyc_i, stb_i, ack_o, we_i, sel_i, vadr_i, dat_i, dat_o,
cyc_o, ack_i, we_o, padr_o, exv_o, rdv_o, wrv_o, prv_o, page_fault);
module FT64_ipt(rst, clk, pkeys_i, ol_i, bte_i, cti_i, cs_i, icl_i, cyc_i, stb_i, ack_o, we_i, sel_i, vadr_i, dat_i, dat_o,
bte_o, cti_o, cyc_o, ack_i, we_o, sel_o, padr_o, exv_o, rdv_o, wrv_o, prv_o, page_fault);
input rst;
input clk;
input [63:0] pkeys_i;
input [1:0] ol_i;
input [1:0] bte_i;
input [2:0] cti_i;
input cs_i;
input icl_i;
45,9 → 47,12
input [63:0] vadr_i;
input [63:0] dat_i;
output reg [63:0] dat_o;
output reg [1:0] bte_o;
output reg [2:0] cti_o;
output reg cyc_o;
input ack_i;
output reg we_o;
output reg [7:0] sel_o;
output reg [31:0] padr_o;
output reg exv_o;
output reg rdv_o;
64,6 → 69,7
parameter S_CMP6 = 4'd6;
parameter S_WAIT1 = 4'd7;
parameter S_ACK = 4'd8;
parameter S_RESET = 4'd9;
 
integer n;
wire [9:0] pkey [0:5];
105,7 → 111,7
reg keymatch;
always @*
begin
keymatch = 1'b0;
keymatch = ol_i==2'b00;
for (n = 0; n < 6; n = n + 1)
if (pt_key==pkey[n] || pt_key==10'h0)
keymatch = 1'b1;
143,6 → 149,30
endcase
 
always @(posedge clk)
bte_o <= bte_i;
always @(posedge clk)
cti_o <= cti_i;
always @(posedge clk)
sel_o <= sel_i;
`ifdef BYPASS
always @(posedge clk)
cyc_o <= cyc_i;
always @(posedge clk)
we_o <= we_i;
always @(posedge clk)
padr_o <= vadr_i[31:0];
always @(posedge clk)
exv_o <= 1'b0;
always @(posedge clk)
rdv_o <= 1'b0;
always @(posedge clk)
wrv_o <= 1'b0;
always @(posedge clk)
prv_o <= 1'b0;
always @(posedge clk)
page_fault <= 1'b0;
`else
always @(posedge clk)
if (rst) begin
cyc_o <= 1'b0;
padr_o <= 32'hFFFC0100;
151,7 → 181,9
rdv_o <= 1'b0;
wrv_o <= 1'b0;
prv_o <= 1'b0;
pt_wr <= 1'b0;
pt_wr <= 1'b1;
pt_ad <= 1'b0;
pt_dati <= 1'b0;
upd <= 1'b0;
probe <= 1'b0;
upd_done <= 1'b0;
163,9 → 195,18
page_fault <= 1'b0;
ack_o <= 1'b0;
case(state)
// Clear page table ram on reset.
S_RESET:
begin
pt_ad <= pt_ad + 2'd1;
if (&pt_ad) begin
pt_wr <= 1'b0;
state <= S_IDLE;
end
end
S_IDLE:
if (cyc_i) begin
if (cs_i) begin
if (cs_i & stb_i) begin
ack_o <= 1'b1;
case(vadr_i[5:3])
3'd0:
202,7 → 243,7
if (ol_i==2'b0) begin
cyc_o <= 1'b1;
we_o <= we_i;
padr_o <= vadr_i;
padr_o <= vadr_i[31:0];
goto(S_ACK);
end
else begin
211,7 → 252,7
if (vadr_i[31:24]==8'hFF || vadr_i[31:24]==8'h00) begin
cyc_o <= 1'b1;
we_o <= we_i;
padr_o <= vadr_i;
padr_o <= vadr_i[31:0];
goto(S_ACK);
end
else begin
294,7 → 335,7
else begin
cyc_o <= 1'b1;
we_o <= 1'b0;
padr_o <= 64'hFFFFFFFFFFFFFFF8;
padr_o <= 32'hFFFFFFF8;
prv_o <= 1'b1;
end
goto(S_ACK);
374,7 → 415,7
else begin
cyc_o <= 1'b1;
we_o <= 1'b0;
padr_o <= 64'hFFFFFFFFFFFFFFF8;
padr_o <= 32'hFFFFFFF8;
prv_o <= 1'b1;
end
goto(S_ACK);
400,6 → 441,7
 
endcase
end
`endif
 
task goto;
input [3:0] nst;
/common/FT64_mpu.v
1,7 → 1,7
`timescale 1ns / 1ps
// ============================================================================
// __
// \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2017-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
71,8 → 71,8
input i26;
input i27;
input i28;
output reg [2:0] cti_o;
output reg [1:0] bte_o;
output [2:0] cti_o;
output [1:0] bte_o;
input bok_i;
output cyc_o;
output reg stb_o;
79,7 → 79,7
input ack_i;
input err_i;
output we_o;
output reg [7:0] sel_o;
output [7:0] sel_o;
output [31:0] adr_o;
output reg [63:0] dat_o;
input [63:0] dat_i;
91,6 → 91,7
wire [2:0] bte;
wire cyc,stb,we;
wire [7:0] sel;
(* mark_debug="true" *)
wire [63:0] adr;
reg [63:0] dati;
wire [63:0] dato;
115,10 → 116,6
wire sptr_o;
wire [63:0] pkeys;
 
always @(posedge clk_i)
cti_o <= cti;
always @(posedge clk_i)
bte_o <= bte;
//always @(posedge clk_i)
// cyc_o <= cyc;
always @(posedge clk_i)
125,8 → 122,6
stb_o <= stb;
//always @(posedge clk_i)
// we_o <= we;
always @(posedge clk_i)
sel_o <= sel;
//always @(posedge clk_i)
// adr_o <= adr;
always @(posedge clk_i)
243,6 → 238,7
.clk(clk_i),
.pkeys_i(pkeys),
.ol_i(ol),
.bte_i(bte),
.cti_i(cti),
.cs_i(cs_ipt),
.icl_i(icl),
254,9 → 250,12
.vadr_i(adr),
.dat_i(dato),
.dat_o(ipt_dato),
.bte_o(bte_o),
.cti_o(cti_o),
.cyc_o(cyc_o),
.ack_i(ack),
.we_o(we_o),
.sel_o(sel_o),
.padr_o(adr_o),
.exv_o(exv),
.rdv_o(rdv),
264,12 → 263,13
);
 
always @(posedge clk_i)
casez({pic_ack,pit_ack,crd_ack,cs_ipt})
4'b1???: dati <= {2{pic_dato}};
4'b01??: dati <= {2{pit_dato}};
4'b001?: dati <= crd_dato;
4'b0001: dati <= ipt_dato;
default: dati <= dat_i;
casez({pic_ack,pit_ack,crd_ack,cs_ipt,ack_i})
5'b1????: dati <= {2{pic_dato}};
5'b01???: dati <= {2{pit_dato}};
5'b001??: dati <= crd_dato;
5'b0001?: dati <= ipt_dato;
5'b00001: dati <= dat_i;
default: dati <= dati;
endcase
 
always @(posedge clk_i)
/common/FT64_pic.v
1,7 → 1,7
`timescale 1ns / 1ps
// ============================================================================
// __
// \\__/ o\ (C) 2013-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2013-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
55,6 → 55,10
// This register resets the edge sense circuitry
// indicated by the low order five bits of the input data.
//
// 0x18 - write only
// This register triggers the interrupt indicated by the low
// order five bits of the input data.
//
// 0x80 - irq control for irq #0
// 0x84 - irq control for irq #1
// bits 0 to 7 = cause code to issue
82,10 → 86,11
output [3:0] irqo, // normally connected to the processor irq
input nmii, // nmi input connected to nmi requester
output nmio, // normally connected to the nmi of cpu
output [6:0] causeo
output [7:0] causeo
);
parameter pIOAddress = 32'hFFDC_0F00;
 
reg [31:0] trig;
reg [31:0] ie; // interrupt enable register
reg rdy1;
reg [4:0] irqenc;
121,9 → 126,11
if (rst_i) begin
ie <= 32'h0;
rste <= 32'h0;
trig <= 32'h0;
end
else begin
rste <= 32'h0;
trig <= 32'h0;
if (cs & wr_i) begin
casez (adr_i[7:2])
6'd0: ;
135,6 → 142,7
ie[dat_i[4:0]] <= adr_i[2];
6'd4: es <= dat_i[31:0];
6'd5: rste[dat_i[4:0]] <= 1'b1;
6'd6: trig[dat_i[4:0]] <= 1'b1;
6'b1?????:
begin
cause[adr_i[6:2]] <= dat_i[7:0];
161,7 → 169,7
dat_o <= 32'h0000;
end
 
assign irqo = (irqenc == 5'h0) ? 4'd0 : irq[irqenc];
assign irqo = (irqenc == 5'h0) ? 4'd0 : irq[irqenc] & {4{ie[irqenc]}};
assign causeo = (irqenc == 5'h0) ? 8'd0 : cause[irqenc];
assign nmio = nmii & ie[0];
 
171,6 → 179,7
for (n = 1; n < 32; n = n + 1)
begin
ib[n] <= i[n];
if (trig[n]) iedge[n] <= 1'b1;
if (i[n] & !ib[n]) iedge[n] <= 1'b1;
if (rste[n]) iedge[n] <= 1'b0;
end
183,7 → 192,7
begin
irqenc <= 5'd0;
for (n = 31; n > 0; n = n - 1)
if (ie[n] & (es[n] ? iedge[n] : i[n])) irqenc <= n;
if ((es[n] ? iedge[n] : i[n])) irqenc <= n;
end
 
endmodule
/common/FT64_shift.v
1,7 → 1,7
`timescale 1ns / 1ps
// ============================================================================
// __
// \\__/ o\ (C) 2016-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2016-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
/twoway/FT64.v
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2017-2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2017-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
42,7 → 42,7
`include "FT64_defines.vh"
 
module FT64(hartid, rst, clk_i, clk4x, tm_clk_i, irq_i, vec_i, bte_o, cti_o, bok_i, cyc_o, stb_o, ack_i, err_i, we_o, sel_o, adr_o, dat_o, dat_i,
ol_o, pcr_o, pcr2_o, pkeys_o, icl_o, sr_o, cr_o, rbi_i, signal_i);
ol_o, pcr_o, pcr2_o, pkeys_o, icl_o, sr_o, cr_o, rbi_i, signal_i, exc_o);
input [63:0] hartid;
input rst;
input clk_i;
71,6 → 71,8
output reg sr_o;
input rbi_i;
input [31:0] signal_i;
(* mark_debug="true" *)
output [7:0] exc_o;
 
parameter TM_CLKFREQ = 20000000;
parameter QENTRIES = `QENTRIES;
108,6 → 110,7
parameter wyde = 3'd1;
parameter tetra = 3'd2;
parameter octa = 3'd3;
parameter hexi = 3'd4;
// IQ states
parameter IQS_INVALID = 3'd0;
parameter IQS_QUEUED = 3'd1;
179,151 → 182,8
*/
`endif
 
`ifdef SUPPORT_PREDICATION
reg [3:0] pregs [0:1023];
`endif
 
reg [63:0] wbrcd;
wire [5:0] brgs;
`ifdef SUPPORT_SEGMENTATION
reg [23:0] currentCSSelector;
reg [63:0] zs_base [0:63];
reg [63:0] ds_base [0:63];
reg [63:0] es_base [0:63];
reg [63:0] fs_base [0:63];
reg [63:0] gs_base [0:63];
reg [63:0] hs_base [0:63];
reg [63:0] ss_base [0:63];
reg [63:0] cs_base [0:63];
reg [63:0] zsx_base;
reg [63:0] dsx_base;
reg [63:0] esx_base;
reg [63:0] fsx_base;
reg [63:0] gsx_base;
reg [63:0] hsx_base;
reg [63:0] ssx_base;
reg [63:0] csx_base;
reg [63:0] zs_lb [0:63];
reg [63:0] ds_lb [0:63];
reg [63:0] es_lb [0:63];
reg [63:0] fs_lb [0:63];
reg [63:0] gs_lb [0:63];
reg [63:0] hs_lb [0:63];
reg [63:0] ss_lb [0:63];
reg [63:0] cs_lb [0:63];
reg [63:0] zslb;
reg [63:0] dslb;
reg [63:0] eslb;
reg [63:0] fslb;
reg [63:0] gslb;
reg [63:0] hslb;
reg [63:0] sslb;
reg [63:0] cslb;
reg [63:0] zs_ub [0:63];
reg [63:0] ds_ub [0:63];
reg [63:0] es_ub [0:63];
reg [63:0] fs_ub [0:63];
reg [63:0] gs_ub [0:63];
reg [63:0] hs_ub [0:63];
reg [63:0] ss_ub [0:63];
reg [63:0] cs_ub [0:63];
reg [63:0] zsub;
reg [63:0] dsub;
reg [63:0] esub;
reg [63:0] fsub;
reg [63:0] gsub;
reg [63:0] hsub;
reg [63:0] ssub;
reg [63:0] csub;
reg [23:0] zs_sel [0:63];
reg [23:0] ds_sel [0:63];
reg [23:0] es_sel [0:63];
reg [23:0] fs_sel [0:63];
reg [23:0] gs_sel [0:63];
reg [23:0] hs_sel [0:63];
reg [23:0] ss_sel [0:63];
reg [23:0] cs_sel [0:63];
reg [15:0] zs_acr [0:63];
reg [15:0] ds_acr [0:63];
reg [15:0] es_acr [0:63];
reg [15:0] fs_acr [0:63];
reg [15:0] gs_acr [0:63];
reg [15:0] hs_acr [0:63];
reg [15:0] ss_acr [0:63];
reg [15:0] cs_acr [0:63];
initial begin
for (n = 0; n < 64; n = n + 1) begin
zs_base[n] <= 64'h0;
ds_base[n] <= 64'h0;
es_base[n] <= 64'h0;
fs_base[n] <= 64'h0;
gs_base[n] <= 64'h0;
hs_base[n] <= 64'h0;
ss_base[n] <= 64'h0;
cs_base[n] <= 64'h0;
zs_lb[n] <= 64'h0;
ds_lb[n] <= 64'h0;
es_lb[n] <= 64'h0;
fs_lb[n] <= 64'h0;
gs_lb[n] <= 64'h0;
hs_lb[n] <= 64'h0;
ss_lb[n] <= 64'h0;
cs_lb[n] <= 64'h0;
zs_ub[n] <= 64'hFFFFFFFFFFFFFFFF;
ds_ub[n] <= 64'hFFFFFFFFFFFFFFFF;
es_ub[n] <= 64'hFFFFFFFFFFFFFFFF;
fs_ub[n] <= 64'hFFFFFFFFFFFFFFFF;
gs_ub[n] <= 64'hFFFFFFFFFFFFFFFF;
hs_ub[n] <= 64'hFFFFFFFFFFFFFFFF;
ss_ub[n] <= 64'hFFFFFFFFFFFFFFFF;
cs_ub[n] <= 64'hFFFFFFFFFFFFFFFF;
zs_sel[n] <= 24'h0;
ds_sel[n] <= 24'h0;
es_sel[n] <= 24'h0;
fs_sel[n] <= 24'h0;
gs_sel[n] <= 24'h0;
hs_sel[n] <= 24'h0;
ss_sel[n] <= 24'h0;
cs_sel[n] <= 24'h0;
zs_acr[n] <= 16'h8000;
ds_acr[n] <= 16'h9200;
es_acr[n] <= 16'h8000;
fs_acr[n] <= 16'h8000;
gs_acr[n] <= 16'h8000;
hs_acr[n] <= 16'h8000;
ss_acr[n] <= 16'h9600;
cs_acr[n] <= 16'h9A00;
end
end
always @(posedge clk_i)
begin
zsx_base <= zs_base[brgs];
dsx_base <= ds_base[brgs];
esx_base <= es_base[brgs];
fsx_base <= fs_base[brgs];
gsx_base <= gs_base[brgs];
hsx_base <= hs_base[brgs];
ssx_base <= ss_base[brgs];
csx_base <= cs_base[brgs];
zsub <= zs_ub[brgs];
dsub <= ds_ub[brgs];
esub <= es_ub[brgs];
fsub <= fs_ub[brgs];
gsub <= gs_ub[brgs];
hsub <= hs_ub[brgs];
ssub <= ss_ub[brgs];
csub <= cs_ub[brgs];
zslb <= zs_lb[brgs];
dslb <= ds_lb[brgs];
eslb <= es_lb[brgs];
fslb <= fs_lb[brgs];
gslb <= gs_lb[brgs];
hslb <= hs_lb[brgs];
sslb <= ss_lb[brgs];
cslb <= cs_lb[brgs];
currentCSSelector <= cs_sel[brgs];
end
`endif
`ifdef SUPPORT_BBMS
reg [15:0] thrd_handle [0:63];
reg [63:0] prg_base [0:63];
424,11 → 284,6
wire [`ABITS] pc0a;
wire [`ABITS] pc1a;
wire [`ABITS] pc2a;
`ifdef SUPPORT_SEGMENTATION
wire [`ABITS] pc0 = (pc0a[47:40]==8'hFF||ol==2'b00) ? pc0a : {csx_base[50:0],13'd0} + pc0a[47:0];
wire [`ABITS] pc1 = (pc1a[47:40]==8'hFF||ol==2'b00) ? pc1a : {csx_base[50:0],13'd0} + pc1a[47:0];
wire [`ABITS] pc2 = (pc2a[47:40]==8'hFF||ol==2'b00) ? pc2a : {csx_base[50:0],13'd0} + pc2a[47:0];
`else
`ifdef SUPPORT_BBMS
wire [`ABITS] pc0 = (pc0a[47:40]==8'hFF||ol==2'b00) ? pc0a : {pb[50:0],13'd0} + pc0a[47:0];
wire [`ABITS] pc1 = (pc1a[47:40]==8'hFF||ol==2'b00) ? pc1a : {pb[50:0],13'd0} + pc1a[47:0];
438,7 → 293,6
wire [`ABITS] pc1 = pc1a;
wire [`ABITS] pc2 = pc2a;
`endif
`endif
 
reg excmiss;
reg [`ABITS] excmisspc;
464,11 → 318,7
wire wbm = cr0[34];
wire sple = cr0[35]; // speculative load enable
wire ctgtxe = cr0[33];
`ifdef SUPPORT_PREDICATION
wire pred_on = cr0[36]; // predicated execution mode on
`else
wire pred_on = 1'b0;
`endif
reg [63:0] pmr;
wire id1_available = pmr[0];
wire id2_available = pmr[1];
489,9 → 339,11
wire thread_en = 1'b0;
`endif
wire vechain = cr0[18];
// Performance CSR's
reg [39:0] iq_ctr;
reg [39:0] irq_ctr; // count of number of interrupts
reg [39:0] bm_ctr; // branch miss counter
reg [39:0] br_ctr; // branch counter
reg [39:0] icl_ctr; // instruction cache load counter
 
reg [7:0] fcu_timeout;
502,6 → 354,7
assign pcr_o = pcr;
assign pcr2_o = pcr2;
reg [63:0] aec;
(* mark_debug = "true" *)
reg [15:0] cause[0:15];
`ifdef SUPPORT_SMT
reg [`ABITS] epc [0:NTHREAD];
679,7 → 532,7
// the queue plus an extra count for skipping on branch misses. In this case
// that would be four bits minimum (count 0 to 8).
wire [63:0] rdat0,rdat1,rdat2;
reg [63:0] xdati;
reg [127:0] xdati;
 
reg canq1, canq2, canq3;
(* mark_debug = "true" *)
716,6 → 569,7
reg [QENTRIES-1:0] iqentry_oddball = 8'h00; // writes to register file
reg [QENTRIES-1:0] iqentry_load; // is a memory load instruction
reg [QENTRIES-1:0] iqentry_loadv; // is a volatile memory load instruction
reg [QENTRIES-1:0] iqentry_loadseg;
reg [QENTRIES-1:0] iqentry_store; // is a memory store instruction
reg [QENTRIES-1:0] iqentry_preload; // is a memory preload instruction
reg [QENTRIES-1:0] iqentry_ldcmp;
745,6 → 599,10
reg [QENTRIES-1:0] iqentry_prfw = 1'b0;
reg [7:0] iqentry_we [0:QENTRIES-1]; // enable strobe
reg [63:0] iqentry_res [0:QENTRIES-1]; // instruction result
reg [63:0] iqentry_seg_base [0:QENTRIES-1]; //
reg [63:0] iqentry_seg_lb [0:QENTRIES-1]; //
reg [63:0] iqentry_seg_ub [0:QENTRIES-1]; //
reg [63:0] iqentry_seg_acr [0:QENTRIES-1]; //
reg [63:0] iqentry_ares [0:QENTRIES-1]; // alternate instruction result
reg [47:0] iqentry_instr[0:QENTRIES-1]; // instruction opcode
reg [2:0] iqentry_insln[0:QENTRIES-1]; // instruction length
803,13 → 661,6
reg [PREGS-1:1] iqentry_livetarget [0:QENTRIES-1];
reg [PREGS-1:1] iqentry_latestID [0:QENTRIES-1];
reg [PREGS-1:1] iqentry_cumulative [0:QENTRIES-1];
`ifdef SUPPORT_PREDICATION
reg [QENTRIES-1:0] iqentry_psource = {QENTRIES{1'b0}};
reg [15:0] plivetarget;
reg [15:0] iqentry_plivetarget [0:QENTRIES-1];
reg [15:0] iqentry_platestID [0:QENTRIES-1];
reg [15:0] iqentry_pcumulative [0:QENTRIES-1];
`endif
wire [PREGS-1:1] iq_out [0:QENTRIES-1];
 
reg [`QBITS] tail0;
852,14 → 703,6
wire fetchbuf2_thrd;
wire fetchbuf2_mem;
wire fetchbuf2_rfw;
`ifdef SUPPORT_PREDICATION
wire fetchbuf0_prfw;
wire [7:0] fetchbuf0_pbyte;
wire fetchbuf1_prfw;
wire [7:0] fetchbuf1_pbyte;
wire fetchbuf2_prfw;
wire [7:0] fetchbuf2_pbyte;
`endif
wire [47:0] fetchbufA_instr;
wire [`ABITS] fetchbufA_pc;
wire fetchbufA_v;
1054,6 → 897,9
reg [63:0] fcu_argI; // only used by BEQ
reg [63:0] fcu_argT;
reg [63:0] fcu_argT2;
reg [63:0] fcu_epc;
reg [23:0] fcu_ecs; // excepted code segment
reg [23:0] fcu_rs; // return selector
reg [`ABITS] fcu_pc;
reg [`ABITS] fcu_nextpc;
reg [`ABITS] fcu_brdisp;
1107,10 → 953,10
reg dram0_preload;
reg [RBIT:0] dram0_tgt;
reg [`QBITSP1] dram0_id;
reg [`XBITS] dram0_exc;
reg dram0_unc;
reg [2:0] dram0_memsize;
reg dram0_load; // is a load operation
reg dram0_loadseg;
reg dram0_store;
reg [1:0] dram0_ol;
reg [63:0] dram1_data;
1120,10 → 966,10
reg dram1_preload;
reg [RBIT:0] dram1_tgt;
reg [`QBITSP1] dram1_id;
reg [`XBITS] dram1_exc;
reg dram1_unc;
reg [2:0] dram1_memsize;
reg dram1_load;
reg dram1_loadseg;
reg dram1_store;
reg [1:0] dram1_ol;
reg [63:0] dram2_data;
1133,10 → 979,10
reg dram2_preload;
reg [RBIT:0] dram2_tgt;
reg [`QBITSP1] dram2_id;
reg [`XBITS] dram2_exc;
reg dram2_unc;
reg [2:0] dram2_memsize;
reg dram2_load;
reg dram2_loadseg;
reg dram2_store;
reg [1:0] dram2_ol;
 
1143,15 → 989,12
reg dramA_v;
reg [`QBITSP1] dramA_id;
reg [63:0] dramA_bus;
reg [`XBITS] dramA_exc;
reg dramB_v;
reg [`QBITSP1] dramB_id;
reg [63:0] dramB_bus;
reg [`XBITS] dramB_exc;
reg dramC_v;
reg [`QBITSP1] dramC_id;
reg [63:0] dramC_bus;
reg [`XBITS] dramC_exc;
 
wire outstanding_stores;
reg [63:0] I; // instruction count
1194,7 → 1037,7
parameter B16 = 5'd16;
parameter B17 = 5'd17;
parameter B18 = 5'd18;
parameter B19 = 5'd19;
parameter B_LSNAck = 5'd19;
parameter B2a = 5'd20;
parameter B2b = 5'd21;
parameter B2c = 5'd22;
1202,6 → 1045,14
parameter B20 = 5'd24;
parameter B21 = 5'd25;
parameter B_DCacheLoadWait3 = 5'd26;
parameter B_LoadDesc = 5'd27;
parameter B_LoadDescStb = 5'd28;
parameter B_WaitSeg = 5'd29;
parameter B_DLoadNack = 5'd30;
parameter SEG_IDLE = 2'd0;
parameter SEG_CHK = 2'd1;
parameter SEG_UPD = 2'd2;
parameter SEG_DONE = 2'd3;
reg [1:0] bwhich;
reg [3:0] icstate,picstate;
parameter IDLE = 4'd0;
1226,13 → 1077,15
always @*
phit <= ihit&&icstate==IDLE;
reg [2:0] iccnt;
(* mark_debug="true" *)
reg icack;
reg L1_wr0,L1_wr1,L1_wr2;
reg L1_invline;
wire [1:0] ic0_fault,ic1_fault,ic2_fault;
reg [8:0] L1_en;
reg [9:0] L1_en;
reg [71:0] L1_adr, L2_adr;
reg [297:0] L2_rdat;
wire [297:0] L2_dato;
reg [305:0] L1_dati;
wire [305:0] L2_dato;
reg L2_xsel;
 
generate begin : gRegfileInst
1371,7 → 1224,7
.en(L1_en),
.adr((icstate==IDLE||icstate==IC_Next) ? {pcr[7:0],pc0} : L1_adr),
.wadr(L1_adr),
.i(L2_rdat),
.i(L1_dati),
.o(insn0a),
.fault(ic0_fault),
.hit(ihit0),
1390,7 → 1243,7
.en(L1_en),
.adr((icstate==IDLE||icstate==IC_Next) ? (thread_en ? {pcr[7:0],pc1}: {pcr[7:0],pc0plus6} ): L1_adr),
.wadr(L1_adr),
.i(L2_rdat),
.i(L1_dati),
.o(insn1b),
.fault(ic1_fault),
.hit(ihit1),
1412,7 → 1265,7
.en(L1_en),
.adr((icstate==IDLE||icstate==IC_Next) ? (thread_en ? {pcr[7:0],pc2} : {pcr[7:0],pc0plus12}) : L1_adr),
.wadr(L1_adr),
.i(L2_rdat),
.i(L1_dati),
.o(insn2b),
.fault(ic2_fault),
.hit(ihit2),
1995,7 → 1848,7
wire freezePC = (irq_i > im) && !int_commit;
always @*
if (freezePC) begin
insn0 <= {8'h00,6'd0,5'd0,irq_i,1'b0,vec_i,2'b00,`BRK};
insn0 <= {32'h00,6'd0,5'd0,irq_i,1'b0,vec_i,2'b00,`BRK};
end
else if (phit) begin
// if (insn0a[`INSTRUCTION_OP]==`BRK && insn0a[25:21]==5'd0 && insn0a[`INSTRUCTION_L2]==2'b00)
2002,10 → 1855,21
// insn0 <= {6'd1,5'd0,4'b0,1'b0,`FLT_PRIV,2'b00,`BRK};
// else
insn0 <= insn0a;
if (insn0a[15:0]==16'hFF00) begin // BRK #255
if (~|irq_i)
insn0 <= {8'h00,`NOP_INSN};
else
insn0[20:0] <= {irq_i,1'b0,vec_i,2'b00,`BRK};
end
else if (ic0_fault[1])
insn0 <= {32'h00,6'd0,5'd0,4'h0,1'b0,`FLT_IBE,2'b00,`BRK};
else if (ic0_fault[0])
insn0 <= {32'h00,6'd0,5'd0,4'h0,1'b0,`FLT_EXF,2'b00,`BRK};
end
else begin
insn0 <= {8'h00,`NOP_INSN};
end
 
generate begin : gInsnMux
if (`WAYS > 1) begin
always @*
2017,6 → 1881,16
// insn1 <= {6'd1,5'd0,4'b0,1'b0,`FLT_PRIV,2'b00,`BRK};
// else
insn1 <= insn1a;
if (insn1a[15:0]==16'hFF00) begin
if (~|irq_i)
insn1 <= {8'h00,`NOP_INSN};
else
insn1[20:0] <= {irq_i,1'b0,vec_i,2'b00,`BRK};
end
else if (ic1_fault[1])
insn1 <= {32'h00,6'd0,5'd0,4'h0,1'b0,`FLT_IBE,2'b00,`BRK};
else if (ic1_fault[0])
insn1 <= {32'h00,6'd0,5'd0,4'h0,1'b0,`FLT_EXF,2'b00,`BRK};
end
else begin
insn1 <= {8'h00,`NOP_INSN};
2031,6 → 1905,16
// insn2 <= {6'd1,5'd0,4'b0,1'b0,`FLT_PRIV,2'b00,`BRK};
// else
insn2 <= insn2a;
if (insn2a[15:0]==16'hFF00) begin
if (~|irq_i)
insn2 <= {8'h00,`NOP_INSN};
else
insn2[20:0] <= {irq_i,1'b0,vec_i,2'b00,`BRK};
end
else if (ic2_fault[1])
insn2 <= {32'h00,6'd0,5'd0,4'h0,1'b0,`FLT_IBE,2'b00,`BRK};
else if (ic2_fault[0])
insn2 <= {32'h00,6'd0,5'd0,4'h0,1'b0,`FLT_EXF,2'b00,`BRK};
end
else
insn2 <= `NOP_INSN;
2039,9 → 1923,9
endgenerate
 
wire [63:0] dc0_out, dc1_out, dc2_out;
assign rdat0 = dram0_unc ? xdati : dc0_out;
assign rdat1 = dram1_unc ? xdati : dc1_out;
assign rdat2 = dram2_unc ? xdati : dc2_out;
assign rdat0 = dram0_unc ? xdati[63:0] : dc0_out;
assign rdat1 = dram1_unc ? xdati[63:0] : dc1_out;
assign rdat2 = dram2_unc ? xdati[63:0] : dc2_out;
 
reg preload;
reg [1:0] dccnt;
2076,9 → 1960,9
assign dhit2 = dhit2a && !wb_hit2;
wire whit0, whit1, whit2;
 
wire wr_dcache0 = (bstate==B_DCacheLoadAck && ack_i)||(((bstate==B_StoreAck && StoreAck1) || (bstate==B19 && isStore)) && whit0);
wire wr_dcache1 = (bstate==B_DCacheLoadAck && ack_i)||(((bstate==B_StoreAck && StoreAck1) || (bstate==B19 && isStore)) && whit1);
wire wr_dcache2 = (bstate==B_DCacheLoadAck && ack_i)||(((bstate==B_StoreAck && StoreAck1) || (bstate==B19 && isStore)) && whit2);
wire wr_dcache0 = (bstate==B_DCacheLoadAck && ack_i)||(((bstate==B_StoreAck && StoreAck1) || (bstate==B_LSNAck && isStore)) && whit0);
wire wr_dcache1 = (bstate==B_DCacheLoadAck && ack_i)||(((bstate==B_StoreAck && StoreAck1) || (bstate==B_LSNAck && isStore)) && whit1);
wire wr_dcache2 = (bstate==B_DCacheLoadAck && ack_i)||(((bstate==B_StoreAck && StoreAck1) || (bstate==B_LSNAck && isStore)) && whit2);
 
FT64_dcache udc0
(
2335,11 → 2219,13
`BRK: fnRt = 12'd0;
`REX: fnRt = 12'd0;
`CHK: fnRt = 12'd0;
`EXEC: fnRt = 12'd0;
//`EXEC: fnRt = 12'd0;
`Bcc: fnRt = 12'd0;
`BLcc: fnRt = 12'd0;
`BBc: fnRt = 12'd0;
`NOP: fnRt = 12'd0;
`BEQI: fnRt = 12'd0;
`BNEI: fnRt = 12'd0;
`SB,`Sx,`SWC,`CACHE:
fnRt = 12'd0;
`JMP: fnRt = 12'd0;
2567,11 → 2453,13
`BRK: fnRt = 12'd0;
`REX: fnRt = 12'd0;
`CHK: fnRt = 12'd0;
`EXEC: fnRt = 12'd0;
//`EXEC: fnRt = 12'd0;
`Bcc: fnRt = 12'd0;
`BLcc: fnRt = 12'd0;
`BBc: fnRt = 12'd0;
`NOP: fnRt = 12'd0;
`BEQI: fnRt = 12'd0;
`BNEI: fnRt = 12'd0;
`SB,`Sx,`SWC,`CACHE:
fnRt = 12'd0;
`JMP: fnRt = 12'd0;
2594,7 → 2482,6
`CMP: fnWe = 8'h00;
default: fnWe = 8'hFF;
endcase
`CMPI: fnWe = 8'h00;
default: fnWe = 8'hFF;
endcase
/*
2644,8 → 2531,10
casez(isn[`INSTRUCTION_OP])
`BRK: Source1Valid = isn[16] ? isn[`INSTRUCTION_RA]==5'd0 : TRUE;
`Bcc: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`BLcc: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`BBc: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`BEQI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`BNEI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`CHK: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`RR: case(isn[`INSTRUCTION_S2])
`SHIFT31: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
2655,6 → 2544,7
endcase
`MEMNDX:Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`ADDI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SEQI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SLTI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SLTUI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SGTI: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
2681,6 → 2571,7
`Sx: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SWC: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`SV: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`PUSHC: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`INC: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`CAS: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
`CACHE: Source1Valid = isn[`INSTRUCTION_RA]==5'd0;
2702,16 → 2593,17
casez(isn[`INSTRUCTION_OP])
`BRK: Source2Valid = TRUE;
`Bcc: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`BLcc: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`BBc: Source2Valid = TRUE;
`BEQI: Source2Valid = TRUE;
`BNEI: Source2Valid = TRUE;
`CHK: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`R2: casez(isn[`INSTRUCTION_S2])
`TLB: Source2Valid = TRUE;
`R1: Source2Valid = TRUE;
`MOV: Source2Valid = TRUE;
`SHIFTR: Source2Valid = isn[25] ? 1'b1 : isn[`INSTRUCTION_RB]==5'd0;
`SHIFT31: Source2Valid = isn[25] ? 1'b1 : isn[`INSTRUCTION_RB]==5'd0;
`SHIFT63: Source2Valid = isn[25] ? 1'b1 : isn[`INSTRUCTION_RB]==5'd0;
`SHIFT31: Source2Valid = TRUE;
`SHIFT63: Source2Valid = TRUE;
`LVX,`SVX: Source2Valid = FALSE;
default: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
endcase
2732,6 → 2624,7
endcase
end
`ADDI: Source2Valid = TRUE;
`SEQI: Source2Valid = TRUE;
`SLTI: Source2Valid = TRUE;
`SLTUI: Source2Valid = TRUE;
`SGTI: Source2Valid = TRUE;
2753,6 → 2646,7
`SB: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`Sx: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`SWC: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`PUSHC: Source2Valid = TRUE;
`CAS: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
`JAL: Source2Valid = TRUE;
`RET: Source2Valid = isn[`INSTRUCTION_RB]==5'd0;
2821,50 → 2715,6
endcase
endfunction
 
// For predication logic
function SourceTValid;
input [47:0] isn;
case(isn[`INSTRUCTION_OP])
`BRK: SourceTValid = TRUE;
`Bcc: SourceTValid = TRUE;
`BBc: SourceTValid = TRUE;
`BEQI: SourceTValid = TRUE;
`IVECTOR:
case(isn[`INSTRUCTION_S2])
`VEX: SourceTValid = TRUE;
default: SourceTValid = TRUE;
endcase
`CHK: SourceTValid = isn[`INSTRUCTION_RT]==5'd0;
`R2:
if (isn[`INSTRUCTION_L2]==2'b01)
case(isn[47:42])
`CMOVEZ,`CMOVNZ: SourceTValid = isn[`INSTRUCTION_RT]==5'd0;
default: SourceTValid = TRUE;
endcase
else
case(isn[`INSTRUCTION_S2])
`MAJ: SourceTValid = isn[`INSTRUCTION_RT]==5'd0;
default: SourceTValid = TRUE;
endcase
`MEMNDX:
if (!isn[31])
case({isn[31:28],isn[22:21]})
`CACHEX,
`LVBX,`LVBUX,`LVCX,`LVCUX,`LVHX,`LVHUX,`LVWX,
`LBX,`LBUX,`LCX,`LCUX,`LHX,`LHUX,`LWX,`LWRX:
SourceTValid = isn[`INSTRUCTION_RT]==5'd0;
default: SourceTValid = TRUE;
endcase
else
SourceTValid = TRUE;
`SB: SourceTValid = TRUE;
`Sx: SourceTValid = TRUE;
`SWC: SourceTValid = TRUE;
`CAS: SourceTValid = TRUE;
`BITFIELD: SourceTValid = isn[`INSTRUCTION_RT]==5'd0 || isn[32]==1'b0;
default: SourceTValid = isn[`INSTRUCTION_RT]==5'd0;
endcase
endfunction
 
// Used to indicate to the queue logic that the instruction needs to be
// recycled to the queue VL number of times.
2957,25 → 2807,9
endcase
endfunction
 
function IsCmp;
function IsMem;
input [47:0] isn;
case(isn[`INSTRUCTION_OP])
`R2:
if (isn[`INSTRUCTION_L2]==2'b00)
case(isn[31:26])
`CMP: IsCmp = TRUE;
default: IsCmp = FALSE;
endcase
else
IsCmp = FALSE;
`CMPI: IsCmp = TRUE;
default: IsCmp = FALSE;
endcase
endfunction
 
function [0:0] IsMem;
input [47:0] isn;
case(isn[`INSTRUCTION_OP])
`MEMNDX: IsMem = TRUE;
`AMO: IsMem = TRUE;
`LB: IsMem = TRUE;
2988,6 → 2822,7
`SB: IsMem = TRUE;
`Sx: IsMem = TRUE;
`SWC: IsMem = TRUE;
`PUSHC: IsMem = TRUE;
`CAS: IsMem = TRUE;
`LVx: IsMem = TRUE;
`LVxU: IsMem = TRUE;
3128,8 → 2963,10
input [47:0] isn;
casez(isn[`INSTRUCTION_OP])
`Bcc: IsBranch = TRUE;
`BLcc: IsBranch = TRUE;
`BBc: IsBranch = TRUE;
`BEQI: IsBranch = TRUE;
`BNEI: IsBranch = TRUE;
`CHK: IsBranch = TRUE;
default: IsBranch = FALSE;
endcase
3159,8 → 2996,10
default: IsFlowCtrl = FALSE;
endcase
`Bcc: IsFlowCtrl = TRUE;
`BLcc: IsFlowCtrl = TRUE;
`BBc: IsFlowCtrl = TRUE;
`BEQI: IsFlowCtrl = TRUE;
`BNEI: IsFlowCtrl = TRUE;
`CHK: IsFlowCtrl = TRUE;
`JAL: IsFlowCtrl = TRUE;
`JMP: IsFlowCtrl = TRUE;
3228,6 → 3067,11
endcase
endfunction
 
function IsRet;
input [47:0] isn;
IsRet = isn[`INSTRUCTION_OP]==`RET;
endfunction
 
function IsRFW;
input [47:0] isn;
input [5:0] vqei;
3250,6 → 3094,7
endcase
`ADD: IsRFW = TRUE;
`SUB: IsRFW = TRUE;
`SEQ: IsRFW = TRUE;
`SLT: IsRFW = TRUE;
`SLTU: IsRFW = TRUE;
`SLE: IsRFW = TRUE;
3347,6 → 3192,7
`BBc: IsRFW = FALSE;
`BITFIELD: IsRFW = TRUE;
`ADDI: IsRFW = TRUE;
`SEQI: IsRFW = TRUE;
`SLTI: IsRFW = TRUE;
`SLTUI: IsRFW = TRUE;
`SGTI: IsRFW = TRUE;
3372,6 → 3218,7
`LV: IsRFW = TRUE;
`LVx: IsRFW = TRUE;
`LVxU: IsRFW = TRUE;
`PUSHC: IsRFW = TRUE;
`CAS: IsRFW = TRUE;
`AMO: IsRFW = TRUE;
`CSRRW: IsRFW = TRUE;
3478,14 → 3325,6
endcase
endfunction
 
function IsExec;
input [47:0] isn;
case(isn[`INSTRUCTION_OP])
`EXEC: IsExec = TRUE;
default: IsExec = FALSE;
endcase
endfunction
 
function [7:0] fnSelect;
input [47:0] ins;
input [`ABITS] adr;
3603,6 → 3442,7
endcase
default: fnSelect = 8'h00;
endcase
`PUSHC,
`INC,
`LWR,`SWC,`CAS: fnSelect = 8'hFF;
`LV,`SV: fnSelect = 8'hFF;
3867,26 → 3707,17
// FETCH
// ---------------------------------------------------------------------------
//
assign fetchbuf0_mem = IsMem(fetchbuf0_instr);// & IsLoad(fetchbuf0_instr);
assign fetchbuf0_mem = IsMem(fetchbuf0_instr) & ~IsRet(fetchbuf0_instr);// & IsLoad(fetchbuf0_instr);
assign fetchbuf0_rfw = IsRFW(fetchbuf0_instr,vqe0,vl,fetchbuf0_thrd);
`ifdef SUPPORT_PREDICATION
assign fetchbuf0_prfw = IsCmp(fetchbuf0_instr);
`endif
 
generate begin: gFetchbufDec
if (`WAYS > 1) begin
assign fetchbuf1_mem = IsMem(fetchbuf1_instr);// & IsLoad(fetchbuf1_instr);
assign fetchbuf1_mem = IsMem(fetchbuf1_instr) & ~IsRet(fetchbuf1_instr);// & IsLoad(fetchbuf1_instr);
assign fetchbuf1_rfw = IsRFW(fetchbuf1_instr,vqe1,vl,fetchbuf1_thrd);
`ifdef SUPPORT_PREDICATION
assign fetchbuf1_prfw = IsCmp(fetchbuf1_instr);
`endif
end
if (`WAYS > 2) begin
assign fetchbuf2_mem = IsMem(fetchbuf2_instr);// & IsLoad(fetchbuf2_instr);
assign fetchbuf2_mem = IsMem(fetchbuf2_instr) & ~IsRet(fetchbuf2_instr);// & IsLoad(fetchbuf2_instr);
assign fetchbuf2_rfw = IsRFW(fetchbuf2_instr,vqe2,vl,fetchbuf2_thrd);
`ifdef SUPPORT_PREDICATION
assign fetchbuf2_prfw = IsCmp(fetchbuf2_instr);
`endif
end
end
endgenerate
3966,9 → 3797,9
.fetchbuf0_insln(fetchbuf0_insln),
.fetchbuf1_insln(fetchbuf1_insln),
.fetchbuf2_insln(fetchbuf2_insln),
.codebuf0(codebuf[insn0[21:16]]),
.codebuf1(codebuf[insn1[21:16]]),
.codebuf2(codebuf[insn2[21:16]]),
.codebuf0(codebuf[insn0[13:8]]),
.codebuf1(codebuf[insn1[13:8]]),
.codebuf2(codebuf[insn2[13:8]]),
.btgtA(btgtA),
.btgtB(btgtB),
.btgtC(btgtC),
4043,8 → 3874,8
.fetchbuf1_v(fetchbuf1_v),
.fetchbuf0_insln(fetchbuf0_insln),
.fetchbuf1_insln(fetchbuf1_insln),
.codebuf0(codebuf[insn0[21:16]]),
.codebuf1(codebuf[insn1[21:16]]),
.codebuf0(codebuf[insn0[13:8]]),
.codebuf1(codebuf[insn1[13:8]]),
.btgtA(btgtA),
.btgtB(btgtB),
.btgtC(btgtC),
4100,7 → 3931,7
.fetchbuf0_v(fetchbuf0_v),
.fetchbuf0_insln(fetchbuf0_insln),
.fetchbuf0_pbyte(fetchbuf0_pbyte),
.codebuf0(codebuf[insn0[21:16]]),
.codebuf0(codebuf[insn0[13:8]]),
.btgtA(btgtA),
.btgtB(btgtB),
.nop_fetchbuf(nop_fetchbuf),
4114,6 → 3945,8
end
endgenerate
 
// Stores might exception so we don't want the heads to advance if a subsequent
// instruction is store even though there's no target register.
wire cmt_head1 = (!iqentry_rfw[heads[1]] && !iqentry_oddball[heads[1]] && ~|iqentry_exc[heads[1]]);
wire cmt_head2 = (!iqentry_rfw[heads[2]] && !iqentry_oddball[heads[2]] && ~|iqentry_exc[heads[2]]);
 
4262,25 → 4095,8
 
always @*
for (n = 0; n < QENTRIES; n = n + 1)
`ifdef SUPPORT_PREDICATION
iqentry_livetarget[n] = {PREGS {iqentry_v[n]}} & {PREGS {~iqentry_stomp[n] && iqentry_thrd[n]==branchmiss_thrd}} & iq_out[n] & ~{PREGS{iqentry_cmp[n]}};
`else
iqentry_livetarget[n] = {PREGS {iqentry_v[n]}} & {PREGS {~iqentry_stomp[n] && iqentry_thrd[n]==branchmiss_thrd}} & iq_out[n];
`endif
 
`ifdef SUPPORT_PREDICATION
always @*
for (j = 1; j < 16; j = j + 1) begin
plivetarget[j] = 1'b0;
for (n = 0; n < QENTRIES; n = n + 1)
plivetarget[j] = plivetarget[j] | iqentry_plivetarget[n][j];
end
 
always @*
for (n = 0; n < QENTRIES; n = n + 1)
iqentry_plivetarget[n] = {16 {iqentry_v[n]}} & {16 {~iqentry_stomp[n] && iqentry_thrd[n]==branchmiss_thrd}} & iq_out[n] & {16{iqentry_cmp[n]}};
`endif
 
//
// BRANCH-MISS LOGIC: latestID
//
4307,29 → 4123,6
for (n = 0; n < QENTRIES; n = n + 1)
iqentry_source[n] = | iqentry_latestID[n];
 
`ifdef SUPPORT_PREDICATION
always @*
for (n = 0; n < QENTRIES; n = n + 1) begin
iqentry_pcumulative[n] = 1'b0;
for (j = n; j < n + QENTRIES; j = j + 1) begin
if (missid==(j % QENTRIES))
for (k = n; k <= j; k = k + 1)
iqentry_pcumulative[n] = iqentry_pcumulative[n] | iqentry_plivetarget[k % QENTRIES];
end
end
 
always @*
for (n = 0; n < QENTRIES; n = n + 1)
iqentry_platestID[n] = (missid == n || ((iqentry_plivetarget[n] & iqentry_pcumulative[(n+1)%QENTRIES]) == {16{1'b0}}))
? iqentry_plivetarget[n]
: {16{1'b0}};
 
always @*
for (n = 0; n < QENTRIES; n = n + 1)
iqentry_psource[n] = | iqentry_platestID[n];
 
`endif
 
reg vqueued2;
assign Ra0 = fnRa(fetchbuf0_instr,vqe0,vl,fetchbuf0_thrd) | {fetchbuf0_thrd,7'b0};
assign Rb0 = fnRb(fetchbuf0_instr,1'b0,vqe0,rfoa0[5:0],rfoa1[5:0],fetchbuf0_thrd) | {fetchbuf0_thrd,7'b0};
4676,10 → 4469,10
always @*
begin
for (n = 0; n < QENTRIES; n = n + 1) begin
iqentry_v[n] <= iqentry_state[n] != IQS_INVALID;
iqentry_done[n] <= iqentry_state[n]==IQS_DONE || iqentry_state[n]==IQS_CMT;
iqentry_out[n] <= iqentry_state[n]==IQS_OUT;
iqentry_agen[n] <= iqentry_state[n]==IQS_AGEN;
iqentry_v[n] = iqentry_state[n] != IQS_INVALID;
iqentry_done[n] = iqentry_state[n]==IQS_DONE || iqentry_state[n]==IQS_CMT;
iqentry_out[n] = iqentry_state[n]==IQS_OUT;
iqentry_agen[n] = iqentry_state[n]==IQS_AGEN;
end
end
 
5489,7 → 5282,7
last_issue1 = QENTRIES;
last_issue2 = QENTRIES;
for (n = 0; n < QENTRIES; n = n + 1)
if (~iqentry_stomp[heads[n]] && iqentry_memissue[heads[n]]) begin
if (~iqentry_stomp[heads[n]] && iqentry_memissue[heads[n]] && !iqentry_done[heads[n]] && iqentry_v[heads[n]]) begin
if (mem1_available && dram0 == `DRAMSLOT_AVAIL) begin
last_issue0 = heads[n];
end
5765,9 → 5558,6
`CSR_SBU: csr_r <= sbu;
`CSR_ENU: csr_r <= en;
`endif
`ifdef SUPPORT_PREDICATION
`CSR_PREGS: read_pregs(csr_r);
`endif
`CSR_Q_CTR: csr_r <= iq_ctr;
`CSR_BM_CTR: csr_r <= bm_ctr;
`CSR_ICL_CTR: csr_r <= icl_ctr;
5854,33 → 5644,6
.exv_o(exv_i),
.wrv_o(wrv_i),
.rdv_o(rdv_i)
`ifdef SUPPORT_SEGMENTATION
,
.zs_base(zsx_base),
.ds_base(dsx_base),
.es_base(esx_base),
.fs_base(fsx_base),
.gs_base(gsx_base),
.hs_base(hsx_base),
.ss_base(ssx_base),
.cs_base(csx_base),
.zsub(zsub),
.dsub(dsub),
.esub(esub),
.fsub(fsub),
.gsub(gsub),
.hsub(hsub),
.ssub(ssub),
.csub(csub),
.zslb(zslb),
.dslb(dslb),
.eslb(eslb),
.fslb(fslb),
.gslb(gslb),
.hslb(hslb),
.sslb(sslb),
.cslb(cslb)
`endif
`ifdef SUPPORT_BBMS
.pb(dl==2'b00 ? 64'd0 : pb),
.cbl(cbl),
5935,33 → 5698,6
.exv_o(),
.wrv_o(),
.rdv_o()
`ifdef SUPPORT_SEGMENTATION
,
.zs_base(zsx_base),
.ds_base(dsx_base),
.es_base(esx_base),
.fs_base(fsx_base),
.gs_base(gsx_base),
.hs_base(hsx_base),
.ss_base(ssx_base),
.cs_base(csx_base),
.zsub(zsub),
.dsub(dsub),
.esub(esub),
.fsub(fsub),
.gsub(gsub),
.hsub(hsub),
.ssub(ssub),
.csub(csub),
.zslb(zslb),
.dslb(dslb),
.eslb(eslb),
.fslb(fslb),
.gslb(gslb),
.hslb(hslb),
.sslb(sslb),
.cslb(cslb)
`endif
`ifdef SUPPORT_BBMS
.pb(dl==2'b00 ? 64'd0 : pb),
.cbl(cbl),
6100,10 → 5836,6
begin
fcu_exc <= `FLT_NONE;
casez(fcu_instr[`INSTRUCTION_OP])
`ifdef SUPPORT_SEGMENTATION
`LDCS: fcu_exc <= fcu_instr[31:8] != fcu_pc[63:40] ? `FLT_CS : `FLT_NONE;
`RET: fcu_exc <= fcu_argB[63:40] != fcu_pc[63:40] ? `FLT_RET : `FLT_NONE;
`endif
`ifdef SUPPORT_BBMS
`LFCS: fcu_exc <= currentCSSelector != fcu_instr[31:8] ? `FLT_CS : `FLT_NONE;
`RET: fcu_exc <= fcu_argB[63:40] != currentCSSelector ? `FLT_RET : `FLT_NONE;
6117,6 → 5849,8
`OL_USER: fcu_exc <= `FLT_PRIV;
default: ;
endcase
// Could have long branches exceptioning and unimplmented in the fetch stage.
// `BBc: fcu_exc <= fcu_instr[6] ? `FLT_BRN : `FLT_NONE;
default: fcu_exc <= `FLT_NONE;
endcase
end
6148,7 → 5882,7
always @*
begin
case(fcu_instr[`INSTRUCTION_OP])
`R2: fcu_misspc = fcu_argB; // RTI (we don't bother fully decoding this as it's the only R2)
`R2: fcu_misspc = fcu_epc; // RTI (we don't bother fully decoding this as it's the only R2)
`RET: fcu_misspc = fcu_argB;
`REX: fcu_misspc = fcu_bus;
`BRK: fcu_misspc = {tvec[0][AMSB:8], 1'b0, olm, 5'h0};
6155,7 → 5889,7
`JAL: fcu_misspc = fcu_argA + fcu_argI;
//`CHK: fcu_misspc = fcu_nextpc + fcu_argI; // Handled as an instruction exception
// Default: branch
default: fcu_misspc = fcu_takb ? {fcu_pc[31:8] + fcu_brdisp[31:8],fcu_brdisp[7:0]} : fcu_nextpc;
default: fcu_misspc = fcu_pt ? fcu_nextpc : {fcu_pc[AMSB:32],fcu_pc[31:0] + fcu_brdisp[31:0]};
endcase
fcu_misspc[0] = 1'b0;
end
6464,7 → 6198,7
end
end
else
queuedNop <= TRUE;
queuedNop <= TRUE;
end
else if (fetchbuf1_v && fetchbuf1_thrd != branchmiss_thrd) begin
if (fetchbuf1_instr[`INSTRUCTION_OP]!=`NOP) begin
6511,9 → 6245,9
end
 
wire writing_wb =
(mem1_available && dram0==`DRAMSLOT_BUSY && dram0_store && !iqentry_stomp[dram0_id[`QBITS]] && wbptr<`WB_DEPTH-1)
|| (mem2_available && dram1==`DRAMSLOT_BUSY && dram1_store && !iqentry_stomp[dram1_id[`QBITS]] && `NUM_MEM > 1 && wbptr<`WB_DEPTH-1)
|| (mem3_available && dram2==`DRAMSLOT_BUSY && dram2_store && !iqentry_stomp[dram2_id[`QBITS]] && `NUM_MEM > 2 && wbptr<`WB_DEPTH-1)
(mem1_available && dram0==`DRAMSLOT_BUSY && dram0_store && wbptr<`WB_DEPTH-1)
|| (mem2_available && dram1==`DRAMSLOT_BUSY && dram1_store && `NUM_MEM > 1 && wbptr<`WB_DEPTH-1)
|| (mem3_available && dram2==`DRAMSLOT_BUSY && dram2_store && `NUM_MEM > 2 && wbptr<`WB_DEPTH-1)
;
 
// Monster clock domain.
6539,10 → 6273,10
wire [63:0] ralu1_bus = |alu1_exc ? {4{lfsro}} : alu1_bus;
wire [63:0] rfpu1_bus = |fpu1_exc ? {4{lfsro}} : fpu1_bus;
wire [63:0] rfpu2_bus = |fpu2_exc ? {4{lfsro}} : fpu2_bus;
wire [63:0] rfcu_bus = |fcu_exc ? {4{lfsro}} : fcu_bus;
wire [63:0] rdramA_bus = |dramA_exc ? {4{lfsro}} : dramA_bus;
wire [63:0] rdramB_bus = |dramB_exc ? {4{lfsro}} : dramB_bus;
wire [63:0] rdramC_bus = |dramC_exc ? {4{lfsro}} : dramC_bus;
wire [63:0] rfcu_bus = |fcu_exc ? {4{lfsro}} : fcu_bus;
wire [63:0] rdramA_bus = dramA_bus;
wire [63:0] rdramB_bus = dramB_bus;
wire [63:0] rdramC_bus = dramC_bus;
 
always @(posedge clk)
if (rst) begin
6614,10 → 6348,6
iqentry_a1_s[n] <= 5'd0;
iqentry_a2_s[n] <= 5'd0;
iqentry_a3_s[n] <= 5'd0;
`ifdef SUPPORT_PREDICATION
iqentry_aT[n] <= 64'd0;
iqentry_aT_s[n] <= 1'd0;
`endif
iqentry_canex[n] <= FALSE;
end
bwhich <= 2'b00;
6634,6 → 6364,7
dram1_id <= 1'b0;
dram2_id <= 1'b0;
L1_adr <= RSTPC;
L2_adr <= RSTPC;
invic <= FALSE;
tail0 <= 3'd0;
tail1 <= 3'd1;
6671,6 → 6402,7
`endif
fcu_dataready <= 0;
fcu_instr <= `NOP_INSN;
fcu_call <= 1'b0;
dramA_v <= 0;
dramB_v <= 0;
dramC_v <= 0;
6691,6 → 6423,7
cr_o <= `LOW;
vadr <= RSTPC;
icl_o <= `LOW; // instruction cache load
L1_dati <= 306'd0;
cr0 <= 64'd0;
cr0[13:8] <= 6'd0; // select compressed instruction group #0
cr0[30] <= TRUE; // enable data caching
6754,6 → 6487,7
iq_ctr <= 40'd0;
icl_ctr <= 40'd0;
bm_ctr <= 40'd0;
br_ctr <= 40'd0;
irq_ctr <= 40'd0;
cmt_timer <= 9'd0;
StoreAck1 <= `FALSE;
7332,43 → 7066,40
fcu_dataready <= `TRUE;
end
 
// If the return segment is not the same as the current code segment then a
// segment load is triggered via the memory unit by setting the iq state to
// AGEN. Otherwise the state is set to CMT which will cause a bypass of the
// segment load from memory.
 
if (fcu_v) begin
fcu_done <= `TRUE;
iqentry_ma [ fcu_id[`QBITS] ] <= fcu_misspc;
iqentry_res [ fcu_id[`QBITS] ] <= rfcu_bus;
iqentry_exc [ fcu_id[`QBITS] ] <= fcu_exc;
// iqentry_done[ fcu_id[`QBITS] ] <= `TRUE;
// iqentry_out [ fcu_id[`QBITS] ] <= `INV;
iqentry_state[fcu_id[`QBITS] ] <= IQS_CMT;
// takb is looked at only for branches to update the predictor. Here it is
// unconditionally set, the value will be ignored if it's not a branch.
iqentry_takb[ fcu_id[`QBITS] ] <= fcu_takb;
br_ctr <= br_ctr + fcu_branch;
fcu_dataready <= `INV;
end
 
// dramX_v only set on a load
if (mem1_available && dramA_v && iqentry_v[ dramA_id[`QBITS] ]) begin
if (dramA_v && iqentry_v[ dramA_id[`QBITS] ]) begin
iqentry_res [ dramA_id[`QBITS] ] <= rdramA_bus;
iqentry_exc [ dramA_id[`QBITS] ] <= dramA_exc;
// iqentry_done[ dramA_id[`QBITS] ] <= `VAL;
// iqentry_out [ dramA_id[`QBITS] ] <= `INV;
iqentry_state[dramA_id[`QBITS] ] <= IQS_CMT;
iqentry_aq [ dramA_id[`QBITS] ] <= `INV;
end
if (mem2_available && `NUM_MEM > 1 && dramB_v && iqentry_v[ dramB_id[`QBITS] ]) begin
if (`NUM_MEM > 1 && dramB_v && iqentry_v[ dramB_id[`QBITS] ]) begin
iqentry_res [ dramB_id[`QBITS] ] <= rdramB_bus;
iqentry_exc [ dramB_id[`QBITS] ] <= dramB_exc;
// iqentry_done[ dramB_id[`QBITS] ] <= `VAL;
iqentry_state[dramB_id[`QBITS] ] <= IQS_CMT;
// iqentry_out [ dramB_id[`QBITS] ] <= `INV;
iqentry_aq [ dramB_id[`QBITS] ] <= `INV;
end
if (mem3_available && `NUM_MEM > 2 && dramC_v && iqentry_v[ dramC_id[`QBITS] ]) begin
if (`NUM_MEM > 2 && dramC_v && iqentry_v[ dramC_id[`QBITS] ]) begin
iqentry_res [ dramC_id[`QBITS] ] <= rdramC_bus;
iqentry_exc [ dramC_id[`QBITS] ] <= dramC_exc;
// iqentry_done[ dramC_id[`QBITS] ] <= `VAL;
iqentry_state[dramC_id[`QBITS] ] <= IQS_CMT;
// iqentry_out [ dramC_id[`QBITS] ] <= `INV;
iqentry_aq [ dramC_id[`QBITS] ] <= `INV;
// if (iqentry_lptr[dram2_id[`QBITS]])
// wbrcd[pcr[5:0]] <= 1'b1;
7655,21 → 7386,6
`else
iqentry_a3[n];
`endif
`ifdef SUPPORT_PREDICATION
fpu1_pred <= iqentry_p_v[n] ? iqentry_pred[n] :
`ifdef FU_BYPASS
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] :
`endif
4'h0;
fpu1_argT <=
`ifdef FU_BYPASS
iqentry_aT_v[n] ? iqentry_aT[n]
: (iqentry_aT_s[n] == alu0_id) ? ralu0_bus : ralu1_bus;
`else
iqentry_aT[n];
`endif
`endif
fpu1_argI <= iqentry_a0[n];
fpu1_dataready <= `VAL;
fpu1_ld <= TRUE;
7710,21 → 7426,6
`else
iqentry_a3[n];
`endif
`ifdef SUPPORT_PREDICATION
fpu2_pred <= iqentry_p_v[n] ? iqentry_pred[n] :
`ifdef FU_BYPASS
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] :
`endif
4'h0;
fpu2_argT <=
`ifdef FU_BYPASS
iqentry_aT_v[n] ? iqentry_aT[n]
: (iqentry_aT_s[n] == alu0_id) ? ralu0_bus : ralu1_bus;
`else
iqentry_aT[n];
`endif
`endif
fpu2_argI <= iqentry_a0[n];
fpu2_dataready <= `VAL;
fpu2_ld <= TRUE;
7742,8 → 7443,8
fcu_pc <= iqentry_pc[n];
fcu_nextpc <= iqentry_pc[n] + iqentry_insln[n];
fcu_pt <= iqentry_pt[n];
fcu_brdisp <= iqentry_instr[n][6] ? {{37{iqentry_instr[n][47]}},iqentry_instr[n][47:23],iqentry_instr[n][17:16]}
: {{53{iqentry_instr[n][31]}},iqentry_instr[n][31:23],iqentry_instr[n][17:16]};
fcu_brdisp <= iqentry_instr[n][6] ? {{36{iqentry_instr[n][47]}},iqentry_instr[n][47:23],iqentry_instr[n][17:16],1'b0}
: {{52{iqentry_instr[n][31]}},iqentry_instr[n][31:23],iqentry_instr[n][17:16],1'b0};
fcu_branch <= iqentry_br[n];
fcu_call <= IsCall(iqentry_instr[n])|iqentry_jal[n];
fcu_jal <= iqentry_jal[n];
7756,11 → 7457,14
: (iqentry_a1_s[n] == fpu1_id && `NUM_FPU > 0) ? rfpu1_bus
: ralu1_bus;
`ifdef SUPPORT_SMT
fcu_argB <= iqentry_rti[n] ? epc0[iqentry_thrd[n]]
// fcu_argB <= iqentry_rti[n] ? epc0[iqentry_thrd[n]]
fcu_epc <= epc0[iqentry_thrd[n]];
`else
fcu_argB <= iqentry_rti[n] ? epc0
fcu_epc <= epc0;
// fcu_argB <= iqentry_rti[n] ? epc0
`endif
: (iqentry_a2_v[n] ? iqentry_a2[n]
fcu_argB <=
(iqentry_a2_v[n] ? iqentry_a2[n]
: (iqentry_a2_s[n] == alu0_id) ? ralu0_bus
: (iqentry_a2_s[n] == fpu1_id && `NUM_FPU > 0) ? rfpu1_bus
: ralu1_bus);
7771,21 → 7475,6
: ralu1_bus[47:0]);
fcu_argC <= iqentry_a3_v[n] ? iqentry_a3[n]
: (iqentry_a3_s[n] == alu0_id) ? ralu0_bus : ralu1_bus;
`ifdef SUPPORT_PREDICATION
fcu_pred <= iqentry_p_v[n] ? iqentry_pred[n] :
`ifdef FU_BYPASS
(iqentry_p_s[n] == alu0_id) ? alu0nyb[iqentry_preg[n]] :
(iqentry_p_s[n] == alu1_id) ? alu1nyb[iqentry_preg[n]] :
`endif
4'h0;
fcu_argT <=
`ifdef FU_BYPASS
iqentry_aT_v[n] ? iqentry_aT[n]
: (iqentry_aT_s[n] == alu0_id) ? ralu0_bus : ralu1_bus;
`else
iqentry_aT[n];
`endif
`endif
fcu_argI <= iqentry_a0[n];
fcu_thrd <= iqentry_thrd[n];
fcu_dataready <= !IsWait(iqentry_instr[n]);
7827,23 → 7516,21
dram2 <= `DRAMSLOT_AVAIL;
 
// grab requests that have finished and put them on the dram_bus
 
// If stomping on the instruction don't place the value on the argument
// bus to be loaded.
if (dram0 == `DRAMREQ_READY && dram0_load) begin
dramA_v <= `VAL;//!iqentry_stomp[dram0_id[`QBITS]];
dramA_v <= !iqentry_stomp[dram0_id[`QBITS]];
dramA_id <= dram0_id;
dramA_exc <= dram0_exc;
dramA_bus <= fnDatiAlign(dram0_instr,dram0_addr,rdat0);
end
if (dram1 == `DRAMREQ_READY && dram1_load && `NUM_MEM > 1) begin
dramB_v <= `VAL;//!iqentry_stomp[dram1_id[`QBITS]];
dramB_v <= !iqentry_stomp[dram1_id[`QBITS]];
dramB_id <= dram1_id;
dramB_exc <= dram1_exc;
dramB_bus <= fnDatiAlign(dram1_instr,dram1_addr,rdat1);
end
if (dram2 == `DRAMREQ_READY && dram2_load && `NUM_MEM > 2) begin
dramC_v <= `VAL;//!iqentry_stomp[dram2_id[`QBITS]];
dramC_v <= !iqentry_stomp[dram2_id[`QBITS]];
dramC_id <= dram2_id;
dramC_exc <= dram2_exc;
dramC_bus <= fnDatiAlign(dram2_instr,dram2_addr,rdat2);
end
 
7857,13 → 7544,12
//
// determine if the instructions ready to issue can, in fact, issue.
// "ready" means that the instruction has valid operands but has not gone yet
iqentry_memissue <= memissue;
for (n = 0; n < QENTRIES; n = n + 1)
if (memissue[n])
iqentry_memissue[n] <= `VAL;
//iqentry_memissue <= memissue;
missue_count <= issue_count;
 
if (dram0 == `DRAMSLOT_AVAIL) dram0_exc <= `FLT_NONE;
if (dram1 == `DRAMSLOT_AVAIL) dram1_exc <= `FLT_NONE;
if (dram2 == `DRAMSLOT_AVAIL) dram2_exc <= `FLT_NONE;
 
for (n = 0; n < QENTRIES; n = n + 1)
if (iqentry_v[n] && iqentry_stomp[n]) begin
iqentry_iv[n] <= `INV;
7875,32 → 7561,40
// iqentry_out[n] <= `INV;
// iqentry_done[n] <= `INV;
// iqentry_cmt[n] <= `INV;
if (dram0_id[`QBITS] == n[`QBITS]) begin
if (dram0==`DRAMSLOT_HASBUS)
wb_nack();
dram0_load <= `FALSE;
dram0_store <= `FALSE;
dram0_rmw <= `FALSE;
dram0 <= `DRAMSLOT_AVAIL;
end
if (dram1_id[`QBITS] == n[`QBITS]) begin
if (dram1==`DRAMSLOT_HASBUS)
wb_nack();
dram1_load <= `FALSE;
dram1_store <= `FALSE;
dram1_rmw <= `FALSE;
dram1 <= `DRAMSLOT_AVAIL;
end
if (dram2_id[`QBITS] == n[`QBITS]) begin
if (dram2==`DRAMSLOT_HASBUS)
wb_nack();
dram2_load <= `FALSE;
dram2_store <= `FALSE;
dram2_rmw <= `FALSE;
dram2 <= `DRAMSLOT_AVAIL;
end
end
 
// A store can't be stomped on, because a store won't issue unless there are
// no instructions that could change the flow of execution before it. Meaning
// stomp would never be true for a store.
// A load could be stomped on, but the memory access is allowed to complete
// to ensure the bus acknowledge doesn't get out of sync.
/*
if (iqentry_stomp[dram0_id[`QBITS]]) begin
if (dram0==`DRAMSLOT_HASBUS)
wb_nack();
dram0_load <= `FALSE;
dram0_store <= `FALSE;
dram0_rmw <= `FALSE;
dram0 <= `DRAMSLOT_AVAIL;
end
if (iqentry_stomp[dram1_id[`QBITS]]) begin
if (dram1==`DRAMSLOT_HASBUS)
wb_nack();
dram1_load <= `FALSE;
dram1_store <= `FALSE;
dram1_rmw <= `FALSE;
dram1 <= `DRAMSLOT_AVAIL;
end
if (iqentry_stomp[dram2_id[`QBITS]]) begin
if (dram2==`DRAMSLOT_HASBUS)
wb_nack();
dram2_load <= `FALSE;
dram2_store <= `FALSE;
dram2_rmw <= `FALSE;
dram2 <= `DRAMSLOT_AVAIL;
end
*/
 
if (last_issue0 < QENTRIES)
tDram0Issue(last_issue0);
if (last_issue1 < QENTRIES)
7920,7 → 7614,7
else
cmt_timer <= 12'd0;
 
if (cmt_timer==12'd1000) begin
if (cmt_timer==12'd1000 && icstate==IDLE) begin
iqentry_state[heads[0]] <= IQS_CMT;
iqentry_exc[heads[0]] <= `FLT_CMT;
cmt_timer <= 12'd0;
8055,6 → 7749,7
L1_wr0 <= FALSE;
L1_wr1 <= FALSE;
L1_wr2 <= FALSE;
L1_en <= 10'h000;
L1_invline <= FALSE;
icnxt <= FALSE;
L2_nxt <= FALSE;
8119,34 → 7814,30
// L2 cache.
IC_WaitL2:
if (ihitL2 && picstate==IC3a) begin
L1_en <= 9'h1FF;
L1_en <= 10'h3FF;
L1_wr0 <= TRUE;
L1_wr1 <= TRUE && `WAYS > 1;
L1_wr2 <= TRUE && `WAYS > 2;
L1_adr <= L2_adr;
L2_rdat <= L2_dato;
// L1_adr <= L2_adr;
// L1_dati is loaded dring an L2 icache load operation
// if (picstate==IC3a)
L1_dati <= L2_dato;
icstate <= IC5;
end
else if (bstate!=B_ICacheNack)
;
else begin
L1_en <= 9'h1FF;
L1_en <= 10'h3FF;
L1_wr0 <= TRUE;
L1_wr1 <= TRUE && `WAYS > 1;
L1_wr2 <= TRUE && `WAYS > 2;
L1_adr <= L2_adr;
// L2_rdat set below while loading cache line
//L2_rdat <= L2_dato;
// L1_adr <= L2_adr;
// L1_dati set below while loading cache line
//L1_dati <= L2_dato;
icstate <= IC5;
end
IC5:
begin
L1_en <= 9'h000;
L1_wr0 <= FALSE;
L1_wr1 <= FALSE;
L1_wr2 <= FALSE;
icstate <= IC6;
end
 
IC5: icstate <= IC6;
IC6: icstate <= IC7;
IC7: icstate <= IC_Next;
IC_Next:
8157,7 → 7848,7
default: icstate <= IDLE;
endcase
 
if (mem1_available && dram0_load)
if (dram0_load)
case(dram0)
`DRAMSLOT_AVAIL: ;
`DRAMSLOT_BUSY:
8182,22 → 7873,22
// dram0_load <= `FALSE;
// end
3'd4:
if (iqentry_v[dram0_id[`QBITS]] && !iqentry_stomp[dram0_id[`QBITS]]) begin
// if (iqentry_v[dram0_id[`QBITS]] && !iqentry_stomp[dram0_id[`QBITS]]) begin
if (dhit0)
dram0 <= `DRAMREQ_READY;
else
dram0 <= `DRAMSLOT_REQBUS;
end
else begin
dram0 <= `DRAMSLOT_AVAIL;
dram0_load <= `FALSE;
end
// end
// else begin
// dram0 <= `DRAMSLOT_AVAIL;
// dram0_load <= `FALSE;
// end
`DRAMSLOT_REQBUS: ;
`DRAMSLOT_HASBUS: ;
`DRAMREQ_READY: dram0 <= `DRAMSLOT_AVAIL;
endcase
 
if (mem2_available && dram1_load && `NUM_MEM > 1)
if (dram1_load && `NUM_MEM > 1)
case(dram1)
`DRAMSLOT_AVAIL: ;
`DRAMSLOT_BUSY:
8207,22 → 7898,22
3'd3:
dram1 <= dram1 + 3'd1;
3'd4:
if (iqentry_v[dram1_id[`QBITS]] && !iqentry_stomp[dram1_id[`QBITS]]) begin
// if (iqentry_v[dram1_id[`QBITS]] && !iqentry_stomp[dram1_id[`QBITS]]) begin
if (dhit1)
dram1 <= `DRAMREQ_READY;
else
dram1 <= `DRAMSLOT_REQBUS;
end
else begin
// end
/* else begin
dram1 <= `DRAMSLOT_AVAIL;
dram1_load <= `FALSE;
end
end*/
`DRAMSLOT_REQBUS: ;
`DRAMSLOT_HASBUS: ;
`DRAMREQ_READY: dram1 <= `DRAMSLOT_AVAIL;
endcase
 
if (mem3_available && dram2_load && `NUM_MEM > 2)
if (dram2_load && `NUM_MEM > 2)
case(dram2)
`DRAMSLOT_AVAIL: ;
`DRAMSLOT_BUSY:
8232,16 → 7923,16
3'd3:
dram2 <= dram2 + 3'd1;
3'd4:
if (iqentry_v[dram2_id[`QBITS]] && !iqentry_stomp[dram2_id[`QBITS]]) begin
// if (iqentry_v[dram2_id[`QBITS]] && !iqentry_stomp[dram2_id[`QBITS]]) begin
if (dhit2)
dram2 <= `DRAMREQ_READY;
else
dram2 <= `DRAMSLOT_REQBUS;
end
else begin
// end
/* else begin
dram2 <= `DRAMSLOT_AVAIL;
dram2_load <= `FALSE;
end
end*/
`DRAMSLOT_REQBUS: ;
`DRAMSLOT_HASBUS: ;
`DRAMREQ_READY: dram2 <= `DRAMSLOT_AVAIL;
8265,20 → 7956,16
end
if (mem2_available && `NUM_MEM > 1 && dram1 == `DRAMSLOT_BUSY && dram1_store) begin
if ((alu0_v && (dram1_id[`QBITS] == alu0_id[`QBITS])) || (alu1_v && (dram1_id[`QBITS] == alu1_id[`QBITS]))) panic <= `PANIC_MEMORYRACE;
// iqentry_done[ dram1_id[`QBITS] ] <= `VAL;
// iqentry_out[ dram1_id[`QBITS] ] <= `INV;
iqentry_state[ dram1_id[`QBITS] ] <= IQS_DONE;
end
if (mem3_available && `NUM_MEM > 2 && dram2 == `DRAMSLOT_BUSY && dram2_store) begin
if ((alu0_v && (dram2_id[`QBITS] == alu0_id[`QBITS])) || (alu1_v && (dram2_id[`QBITS] == alu1_id[`QBITS]))) panic <= `PANIC_MEMORYRACE;
// iqentry_done[ dram2_id[`QBITS] ] <= `VAL;
// iqentry_out[ dram2_id[`QBITS] ] <= `INV;
iqentry_state[ dram2_id[`QBITS] ] <= IQS_DONE;
end
`endif
 
`ifdef HAS_WB
if (mem1_available && dram0==`DRAMSLOT_BUSY && dram0_store && !iqentry_stomp[dram0_id[`QBITS]]) begin
if (dram0==`DRAMSLOT_BUSY && dram0_store) begin
if (wbptr<`WB_DEPTH-1) begin
dram0 <= `DRAMSLOT_AVAIL;
dram0_instr[`INSTRUCTION_OP] <= `NOP;
8295,7 → 7982,7
iqentry_state[ dram0_id[`QBITS] ] <= IQS_DONE;
end
end
else if (mem2_available && dram1==`DRAMSLOT_BUSY && dram1_store && !iqentry_stomp[dram1_id[`QBITS]] && `NUM_MEM > 1) begin
else if (dram1==`DRAMSLOT_BUSY && dram1_store && `NUM_MEM > 1) begin
if (wbptr<`WB_DEPTH-1) begin
dram1 <= `DRAMSLOT_AVAIL;
dram1_instr[`INSTRUCTION_OP] <= `NOP;
8310,7 → 7997,7
iqentry_state[ dram1_id[`QBITS] ] <= IQS_DONE;
end
end
else if (mem3_available && dram2==`DRAMSLOT_BUSY && dram2_store && !iqentry_stomp[dram2_id[`QBITS]] && `NUM_MEM > 2) begin
else if (dram2==`DRAMSLOT_BUSY && dram2_store && `NUM_MEM > 2) begin
if (wbptr<`WB_DEPTH-1) begin
dram2 <= `DRAMSLOT_AVAIL;
dram2_instr[`INSTRUCTION_OP] <= `NOP;
8371,13 → 8058,13
end
 
`endif
if (~|wb_v && mem1_available && dram0==`DRAMSLOT_BUSY && dram0_rmw) begin
if (~|wb_v && dram0==`DRAMSLOT_BUSY && dram0_rmw) begin
`ifdef SUPPORT_DBG
if (dbg_smatch0|dbg_lmatch0) begin
dramA_v <= `TRUE;
dramA_id <= dram0_id;
dramA_exc <= `FLT_DBG;
dramA_bus <= 64'h0;
iqentry_exc[dram0_id[`QBITS]] <= `FLT_DBG;
dram0 <= `DRAMSLOT_AVAIL;
end
else
8399,13 → 8086,13
bstate <= B12;
end
end
else if (~|wb_v && mem2_available && dram1==`DRAMSLOT_BUSY && dram1_rmw && `NUM_MEM > 1) begin
else if (~|wb_v && dram1==`DRAMSLOT_BUSY && dram1_rmw && `NUM_MEM > 1) begin
`ifdef SUPPORT_DBG
if (dbg_smatch1|dbg_lmatch1) begin
dramB_v <= `TRUE;
dramB_id <= dram1_id;
dramB_exc <= `FLT_DBG;
dramB_bus <= 64'h0;
iqentry_exc[dram1_id[`QBITS]] <= `FLT_DBG;
dram1 <= `DRAMSLOT_AVAIL;
end
else
8427,13 → 8114,13
bstate <= B12;
end
end
else if (~|wb_v && mem3_available && dram2==`DRAMSLOT_BUSY && dram2_rmw && `NUM_MEM > 2) begin
else if (~|wb_v && dram2==`DRAMSLOT_BUSY && dram2_rmw && `NUM_MEM > 2) begin
`ifdef SUPPORT_DBG
if (dbg_smatch2|dbg_lmatch2) begin
dramC_v <= `TRUE;
dramC_id <= dram2_id;
dramC_exc <= `FLT_DBG;
dramC_bus <= 64'h0;
iqentry_exc[dram2_id[`QBITS]] <= `FLT_DBG;
dram2 <= `DRAMSLOT_AVAIL;
end
else
8457,13 → 8144,13
end
`ifndef HAS_WB
// Check write buffer enable ?
else if (mem1_available && dram0==`DRAMSLOT_BUSY && dram0_store) begin
else if (dram0==`DRAMSLOT_BUSY && dram0_store) begin
`ifdef SUPPORT_DBG
if (dbg_smatch0) begin
dramA_v <= `TRUE;
dramA_id <= dram0_id;
dramA_exc <= `FLT_DBG;
dramA_bus <= 64'h0;
iqentry_exc[dram0_id[`QBITS]] <= `FLT_DBG;
dram0 <= `DRAMSLOT_AVAIL;
end
else
8475,6 → 8162,7
dram0_instr[`INSTRUCTION_OP] <= `NOP;
cyc <= `HIGH;
stb_o <= `HIGH;
we <= `HIGH;
sel_o <= fnSelect(dram0_instr,dram0_addr);
vadr <= dram0_addr;
dat_o <= fnDato(dram0_instr,dram0_data);
8485,13 → 8173,13
// cr_o <= IsSWC(dram0_instr);
end
end
else if (mem2_available && dram1==`DRAMSLOT_BUSY && dram1_store && `NUM_MEM > 1) begin
else if (dram1==`DRAMSLOT_BUSY && dram1_store && `NUM_MEM > 1) begin
`ifdef SUPPORT_DBG
if (dbg_smatch1) begin
dramB_v <= `TRUE;
dramB_id <= dram1_id;
dramB_exc <= `FLT_DBG;
dramB_bus <= 64'h0;
iqentry_exc[dram1_id[`QBITS]] <= `FLT_DBG;
dram1 <= `DRAMSLOT_AVAIL;
end
else
8503,6 → 8191,7
dram1_instr[`INSTRUCTION_OP] <= `NOP;
cyc <= `HIGH;
stb_o <= `HIGH;
we <= `HIGH;
sel_o <= fnSelect(dram1_instr,dram1_addr);
vadr <= dram1_addr;
dat_o <= fnDato(dram1_instr,dram1_data);
8513,13 → 8202,13
// cr_o <= IsSWC(dram0_instr);
end
end
else if (mem3_available && dram2==`DRAMSLOT_BUSY && dram2_store && `NUM_MEM > 2) begin
else if (dram2==`DRAMSLOT_BUSY && dram2_store && `NUM_MEM > 2) begin
`ifdef SUPPORT_DBG
if (dbg_smatch2) begin
dramC_v <= `TRUE;
dramC_id <= dram2_id;
dramC_exc <= `FLT_DBG;
dramC_bus <= 64'h0;
iqentry_exc[dram2_id[`QBITS]] <= `FLT_DBG;
dram2 <= `DRAMSLOT_AVAIL;
end
else
8531,6 → 8220,7
dram2_instr[`INSTRUCTION_OP] <= `NOP;
cyc <= `HIGH;
stb_o <= `HIGH;
we <= `HIGH;
sel_o <= fnSelect(dram2_instr,dram2_addr);
vadr <= dram2_addr;
dat_o <= fnDato(dram2_instr,dram2_data);
8543,13 → 8233,13
end
`endif
// Check for read misses on the data cache
else if (~|wb_v && mem1_available && !dram0_unc && dram0==`DRAMSLOT_REQBUS && dram0_load) begin
else if (~|wb_v && !dram0_unc && dram0==`DRAMSLOT_REQBUS && dram0_load) begin
`ifdef SUPPORT_DBG
if (dbg_lmatch0) begin
dramA_v <= `TRUE;
dramA_id <= dram0_id;
dramA_exc <= `FLT_DBG;
dramA_bus <= 64'h0;
iqentry_exc[dram0_id[`QBITS]] <= `FLT_DBG;
dram0 <= `DRAMSLOT_AVAIL;
end
else
8561,13 → 8251,13
bstate <= B_DCacheLoadStart;
end
end
else if (~|wb_v && mem2_available && !dram1_unc && dram1==`DRAMSLOT_REQBUS && dram1_load && `NUM_MEM > 1) begin
else if (~|wb_v && !dram1_unc && dram1==`DRAMSLOT_REQBUS && dram1_load && `NUM_MEM > 1) begin
`ifdef SUPPORT_DBG
if (dbg_lmatch1) begin
dramB_v <= `TRUE;
dramB_id <= dram1_id;
dramB_exc <= `FLT_DBG;
dramB_bus <= 64'h0;
iqentry_exc[dram1_id[`QBITS]] <= `FLT_DBG;
dram1 <= `DRAMSLOT_AVAIL;
end
else
8579,13 → 8269,13
bstate <= B_DCacheLoadStart;
end
end
else if (~|wb_v && mem3_available && !dram2_unc && dram2==`DRAMSLOT_REQBUS && dram2_load && `NUM_MEM > 2) begin
else if (~|wb_v && !dram2_unc && dram2==`DRAMSLOT_REQBUS && dram2_load && `NUM_MEM > 2) begin
`ifdef SUPPORT_DBG
if (dbg_lmatch2) begin
dramC_v <= `TRUE;
dramC_id <= dram2_id;
dramC_exc <= `FLT_DBG;
dramC_bus <= 64'h0;
iqentry_exc[dram2_id[`QBITS]] <= `FLT_DBG;
dram2 <= `DRAMSLOT_AVAIL;
end
else
8597,13 → 8287,13
bstate <= B_DCacheLoadStart;
end
end
else if (~|wb_v && mem1_available && dram0_unc && dram0==`DRAMSLOT_BUSY && dram0_load) begin
else if (~|wb_v && dram0_unc && dram0==`DRAMSLOT_BUSY && dram0_load) begin
`ifdef SUPPORT_DBG
if (dbg_lmatch0) begin
dramA_v <= `TRUE;
dramA_id <= dram0_id;
dramA_exc <= `FLT_DBG;
dramA_bus <= 64'h0;
iqentry_exc[dram0_id[`QBITS]] <= `FLT_DBG;
dram0 <= `DRAMSLOT_AVAIL;
end
else
8616,16 → 8306,17
vadr <= {dram0_addr[AMSB:3],3'b0};
sr_o <= IsLWR(dram0_instr);
ol_o <= dram0_ol;
dccnt <= 2'd0;
bstate <= B_DLoadAck;
end
end
else if (~|wb_v && mem2_available && dram1_unc && dram1==`DRAMSLOT_BUSY && dram1_load && `NUM_MEM > 1) begin
else if (~|wb_v && dram1_unc && dram1==`DRAMSLOT_BUSY && dram1_load && `NUM_MEM > 1) begin
`ifdef SUPPORT_DBG
if (dbg_lmatch1) begin
dramB_v <= `TRUE;
dramB_id <= dram1_id;
dramB_exc <= `FLT_DBG;
dramB_bus <= 64'h0;
iqentry_exc[dram1_id[`QBITS]] <= `FLT_DBG;
dram1 <= `DRAMSLOT_AVAIL;
end
else
8638,16 → 8329,17
vadr <= {dram1_addr[AMSB:3],3'b0};
sr_o <= IsLWR(dram1_instr);
ol_o <= dram1_ol;
dccnt <= 2'd0;
bstate <= B_DLoadAck;
end
end
else if (~|wb_v && mem3_available && dram2_unc && dram2==`DRAMSLOT_BUSY && dram2_load && `NUM_MEM > 2) begin
else if (~|wb_v && dram2_unc && dram2==`DRAMSLOT_BUSY && dram2_load && `NUM_MEM > 2) begin
`ifdef SUPPORT_DBG
if (dbg_lmatch2) begin
dramC_v <= `TRUE;
dramC_id <= dram2_id;
dramC_exc <= `FLT_DBG;
dramC_bus <= 64'h0;
iqentry_exc[dram2_id[`QBITS]] <= `FLT_DBG;
dram2 <= 2'd0;
end
else
8660,11 → 8352,13
vadr <= {dram2_addr[AMSB:3],3'b0};
sr_o <= IsLWR(dram2_instr);
ol_o <= dram2_ol;
dccnt <= 2'd0;
bstate <= B_DLoadAck;
end
end
// Check for L2 cache miss
else if (~|wb_v && !ihitL2 && !acki) begin
else if (~|wb_v && !ihitL2 && !acki)
begin
cti_o <= 3'b001;
bte_o <= 2'b00;//2'b01; // 4 beat burst wrap
cyc <= `HIGH;
8672,10 → 8366,14
sel_o <= 8'hFF;
icl_o <= `HIGH;
iccnt <= 3'd0;
icack <= 1'b0;
// adr_o <= icwhich ? {pc0[31:5],5'b0} : {pc1[31:5],5'b0};
// L2_adr <= icwhich ? {pc0[31:5],5'b0} : {pc1[31:5],5'b0};
vadr <= {pcr[7:0],L1_adr[AMSB:5],5'h0};
ol_o <= ol[0];
`ifdef SUPPORT_SMT
`else
ol_o <= ol;//???
`endif
L2_adr <= {pcr[7:0],L1_adr[AMSB:5],5'h0};
L2_xsel <= 1'b0;
bstate <= B_ICacheAck;
8708,7 → 8406,7
wb_v <= 1'b0; // Invalidate write buffer if there is a problem with the store
wb_en <= `FALSE; // and disable write buffer
end
iqentry_state[n] <= IQS_CMT;
iqentry_state[n] <= IQS_CMT;
iqentry_aq[n] <= `INV;
end
end
8738,7 → 8436,7
default: ;
endcase
`endif
bstate <= B19;
bstate <= B_LSNAck;
end
end
 
8778,7 → 8476,7
 
// Data cache load terminal state
B_DCacheLoadAck:
if (ack_i|err_i|tlb_miss|rdv_i) begin
if (acki|err_i|tlb_miss|rdv_i) begin
if (!bok_i) begin
stb_o <= `LOW;
bstate <= B_DCacheLoadStb;
8787,20 → 8485,13
rdvq <= rdvq | rdv_i;
if (!preload) // A preload instruction ignores any error
case(bwhich)
2'd0: if (err_i|rdv_i|tlb_miss) begin
iqentry_exc[dram0_id[`QBITS]] <= tlb_miss ? `FLT_TLB : err_i ? `FLT_DBE : `FLT_DRF;
end
2'd1: if ((err_i|rdv_i|tlb_miss) && `NUM_MEM > 1) begin
iqentry_exc[dram1_id[`QBITS]] <= tlb_miss ? `FLT_TLB : err_i ? `FLT_DBE : `FLT_DRF;
end
2'd2: if ((err_i|rdv_i|tlb_miss) && `NUM_MEM > 2) begin
iqentry_exc[dram2_id[`QBITS]] <= tlb_miss ? `FLT_TLB : err_i ? `FLT_DBE : `FLT_DRF;
end
2'd0: iqentry_exc[dram0_id[`QBITS]] <= tlb_miss ? `FLT_TLB : err_i ? `FLT_DBE : rdv_i ? `FLT_DRF : `FLT_NONE;
2'd1: iqentry_exc[dram1_id[`QBITS]] <= tlb_miss ? `FLT_TLB : err_i ? `FLT_DBE : rdv_i ? `FLT_DRF : `FLT_NONE;
2'd2: iqentry_exc[dram2_id[`QBITS]] <= tlb_miss ? `FLT_TLB : err_i ? `FLT_DBE : rdv_i ? `FLT_DRF : `FLT_NONE;
default: ;
endcase
dccnt <= dccnt + 2'd1;
vadr[4:3] <= vadr[4:3] + 2'd1;
bstate <= B_DCacheLoadAck;
if (dccnt==2'd2)
cti_o <= 3'b111;
if (dccnt==2'd3) begin
8808,7 → 8499,6
bstate <= B_DCacheLoadWait1;
end
end
 
B_DCacheLoadStb:
begin
stb_o <= `HIGH;
8817,44 → 8507,46
B_DCacheLoadWait1: bstate <= B_DCacheLoadWait2;
B_DCacheLoadWait2: bstate <= B_DCacheLoadResetBusy;
//B_DCacheLoadWait3: bstate <= B_DCacheLoadResetBusy;
B_DCacheLoadResetBusy: begin
// There could be more than one memory cycle active. We reset the state
// of all the machines to retest for a hit because otherwise sequential
// loading of memory will cause successive machines to miss resulting in
// multiple dcache loads that aren't needed.
// There could be more than one memory cycle active. We reset the state
// of all the machines to retest for a hit because otherwise sequential
// loading of memory will cause successive machines to miss resulting in
// multiple dcache loads that aren't needed.
B_DCacheLoadResetBusy:
begin
if (dram0 != `DRAMSLOT_AVAIL && dram0_addr[AMSB:5]==vadr[AMSB:5]) dram0 <= `DRAMSLOT_BUSY; // causes retest of dhit
if (dram1 != `DRAMSLOT_AVAIL && dram1_addr[AMSB:5]==vadr[AMSB:5]) dram1 <= `DRAMSLOT_BUSY;
if (dram2 != `DRAMSLOT_AVAIL && dram2_addr[AMSB:5]==vadr[AMSB:5]) dram2 <= `DRAMSLOT_BUSY;
if (~ack_i) bstate <= BIDLE;
end
bstate <= BIDLE;
end
 
// Ack state for instruction cache load
// Once the first ack is received in burst mode, further acks are not necessary
// as the core counts the number of data items. Occasionally missing acks were
// causing a problem.
B_ICacheAck:
if (ack_i|err_i|tlb_miss|exv_i) begin
if (acki|err_i|tlb_miss|exv_i|icack) begin
if (!bok_i) begin
stb_o <= `LOW;
bstate <= B_ICacheNack2;
end
else
icack <= 1'b1;
errq <= errq | err_i;
exvq <= exvq | exv_i;
// L1_en <= 9'h3 << {L2_xsel,L2_adr[4:3],1'b0};
// L1_wr0 <= `TRUE;
// L1_wr1 <= `TRUE;
// L1_adr <= L2_adr;
if (tlb_miss) begin
L2_rdat <= {18{`INSN_FLT_TLB}};
L1_dati <= {19{`INSN_FLT_TLB}};
wb_nack();
icl_o <= `LOW;
bstate <= B_ICacheNack;
end
else if (exv_i) begin
L2_rdat <= {18{`INSN_FLT_EXF}};
L1_dati <= {19{`INSN_FLT_EXF}};
wb_nack();
icl_o <= `LOW;
bstate <= B_ICacheNack;
end
else if (err_i) begin
L2_rdat <= {18{`INSN_FLT_IBE}};
L1_dati <= {19{`INSN_FLT_IBE}};
wb_nack();
icl_o <= `LOW;
bstate <= B_ICacheNack;
8861,16 → 8553,14
end
else
case(iccnt)
3'd0: L2_rdat[63:0] <= dat_i;
3'd1: L2_rdat[127:64] <= dat_i;
3'd2: L2_rdat[191:128] <= dat_i;
3'd3: L2_rdat[255:192] <= dat_i;
3'd4: L2_rdat[297:256] <= {2'b00,dat_i[39:0]};
default: ;
3'd0: L1_dati[63:0] <= dat_i;
3'd1: L1_dati[127:64] <= dat_i;
3'd2: L1_dati[191:128] <= dat_i;
3'd3: L1_dati[255:192] <= dat_i;
3'd4: L1_dati[305:256] <= {2'b00,dat_i[47:0]};
default: L1_dati <= L1_dati;
endcase
//L2_rdat <= {dat_i[31:0],{4{dat_i}}};
iccnt <= iccnt + 3'd1;
//stb_o <= `LOW;
if (iccnt==3'd3)
cti_o <= 3'b111;
if (iccnt==3'd4) begin
8892,19 → 8582,17
end
B_ICacheNack:
begin
L1_wr0 <= `FALSE;
L1_wr1 <= `FALSE;
L1_wr2 <= `FALSE;
L1_en <= 9'h1FF;
L2_xsel <= 1'b0;
if (~ack_i) begin
if (~acki) begin
icl_ctr <= icl_ctr + 40'd1;
bstate <= BIDLE;
L2_nxt <= TRUE;
vadr <= 32'hCCCCCCC8;
end
end
 
B12:
if (ack_i|err_i|tlb_miss|rdv_i) begin
if (acki|err_i|tlb_miss|rdv_i) begin
if (isCAS) begin
iqentry_res [ casid[`QBITS] ] <= (dat_i == cas);
iqentry_exc [ casid[`QBITS] ] <= tlb_miss ? `FLT_TLB : err_i ? `FLT_DRF : rdv_i ? `FLT_DRF : `FLT_NONE;
8928,7 → 8616,7
2'b10: dram2 <= `DRAMREQ_READY;
default: ;
endcase
bstate <= B19;
bstate <= B_LSNAck;
end
end
else if (isRMW) begin
8956,13 → 8644,31
 
// Regular load
B_DLoadAck:
if (ack_i|err_i|tlb_miss|rdv_i) begin
if (acki|err_i|tlb_miss|rdv_i) begin
wb_nack();
sr_o <= `LOW;
xdati <= dat_i;
case(dccnt)
2'd0: xdati[63:0] <= dat_i;
2'd1: xdati[127:64] <= dat_i;
endcase
case(bwhich)
2'b00: begin
dram0 <= `DRAMREQ_READY;
if (dram0_memsize==hexi) begin
if (dccnt==2'd1) begin
dram0 <= `DRAMREQ_READY;
iqentry_seg_base[dram0_id[`QBITS]] <= xdati[63:0];
iqentry_seg_acr[dram0_id[`QBITS]] <= dat_i;
end
else begin
dccnt <= dccnt + 2'd1;
cyc <= `HIGH;
sel_o <= 8'hFF;
vadr <= vadr + 64'd8;
bstate <= B_DLoadNack;
end
end
else
dram0 <= `DRAMREQ_READY;
iqentry_exc [ dram0_id[`QBITS] ] <= tlb_miss ? `FLT_TLB : err_i ? `FLT_DRF : rdv_i ? `FLT_DRF : `FLT_NONE;
end
2'b01: if (`NUM_MEM > 1) begin
8975,8 → 8681,13
end
default: ;
endcase
bstate <= B19;
bstate <= B_LSNAck;
end
B_DLoadNack:
if (~acki) begin
stb_o <= `HIGH;
bstate <= B_DLoadAck;
end
 
// Three cycles to detemrine if there's a cache hit during a store.
B16: begin
8988,15 → 8699,15
endcase
end
B17: bstate <= B18;
B18: bstate <= B19;
B19: if (~acki) begin
sel_o <= 8'h00;
bstate <= BIDLE;
StoreAck1 <= `FALSE;
isStore <= `FALSE;
end
B18: bstate <= B_LSNAck;
B_LSNAck:
begin
bstate <= BIDLE;
StoreAck1 <= `FALSE;
isStore <= `FALSE;
end
B20:
if (~ack_i) begin
if (~acki) begin
stb_o <= `HIGH;
we <= `HIGH;
dat_o <= fnDato(rmw_instr,rmw_res);
9003,7 → 8714,7
bstate <= B_StoreAck;
end
B21:
if (~ack_i) begin
if (~acki) begin
stb_o <= `HIGH;
bstate <= B12;
end
9010,39 → 8721,40
default: bstate <= BIDLE;
endcase
 
 
if (!branchmiss) begin
case({fetchbuf0_v, fetchbuf1_v})
2'b00: ;
2'b01:
if (canq1) begin
case({fetchbuf0_v, fetchbuf1_v})
2'b00: ;
2'b01:
if (canq1) begin
tail0 <= (tail0+2'd1) % QENTRIES;
tail1 <= (tail1+2'd1) % QENTRIES;
end
2'b10:
if (canq1) begin
tail0 <= (tail0+2'd1) % QENTRIES;
tail1 <= (tail1+2'd1) % QENTRIES;
end
2'b11:
if (canq1) begin
if (IsBranch(fetchbuf0_instr) && predict_taken0 && fetchbuf0_thrd==fetchbuf1_thrd) begin
tail0 <= (tail0+2'd1) % QENTRIES;
tail1 <= (tail1+2'd1) % QENTRIES;
end
else begin
if (vqe0 < vl || !IsVector(fetchbuf0_instr)) begin
if (canq2) begin
tail0 <= (tail0 + 3'd2) % QENTRIES;
tail1 <= (tail1 + 3'd2) % QENTRIES;
end
else begin // queued1 will be true
tail0 <= (tail0+2'd1) % QENTRIES;
tail1 <= (tail1+2'd1) % QENTRIES;
end
2'b10:
if (canq1) begin
tail0 <= (tail0+2'd1) % QENTRIES;
tail1 <= (tail1+2'd1) % QENTRIES;
end
2'b11:
if (canq1) begin
if (IsBranch(fetchbuf0_instr) && predict_taken0 && fetchbuf0_thrd==fetchbuf1_thrd) begin
tail0 <= (tail0+2'd1) % QENTRIES;
tail1 <= (tail1+2'd1) % QENTRIES;
end
else begin
if (vqe0 < vl || !IsVector(fetchbuf0_instr)) begin
if (canq2) begin
tail0 <= (tail0 + 3'd2) % QENTRIES;
tail1 <= (tail1 + 3'd2) % QENTRIES;
end
else begin // queued1 will be true
tail0 <= (tail0+2'd1) % QENTRIES;
tail1 <= (tail1+2'd1) % QENTRIES;
end
end
end
end
endcase
tail1 <= (tail1+2'd1) % QENTRIES;
end
end
end
end
endcase
end
else if (!thread_en) begin // if branchmiss
for (n = QENTRIES-1; n >= 0; n = n - 1)
9130,7 → 8842,14
(i[`QBITS]==heads[0])?"C":".",
(i[`QBITS]==tail0)?"Q":".",
i[`QBITS],
iqentry_v[i] ? "v" : "-",
iqentry_state[i]==IQS_INVALID ? "-" :
iqentry_state[i]==IQS_QUEUED ? "Q" :
iqentry_state[i]==IQS_OUT ? "O" :
iqentry_state[i]==IQS_AGEN ? "A" :
iqentry_state[i]==IQS_MEM ? "M" :
iqentry_state[i]==IQS_DONE ? "D" :
iqentry_state[i]==IQS_CMT ? "C" : "?",
// iqentry_v[i] ? "v" : "-",
iqentry_iv[i] ? "I" : "-",
iqentry_done[i]?"d":"-",
iqentry_out[i]?"o":"-",
9161,11 → 8880,11
$display("%d %h %h %c%h %o #",
dram2, dram2_addr, dram2_data, (IsFlowCtrl(dram2_instr) ? 98 : (IsMem(dram2_instr)) ? 109 : 97),
dram2_instr, dram2_id);
$display("%d %h %o %h #", dramA_v, dramA_bus, dramA_id, dramA_exc);
$display("%d %h %o #", dramA_v, dramA_bus, dramA_id);
if (`NUM_MEM > 1)
$display("%d %h %o %h #", dramB_v, dramB_bus, dramB_id, dramB_exc);
$display("%d %h %o #", dramB_v, dramB_bus, dramB_id);
if (`NUM_MEM > 2)
$display("%d %h %o %h #", dramC_v, dramC_bus, dramC_id, dramC_exc);
$display("%d %h %o #", dramC_v, dramC_bus, dramC_id);
$display("ALU");
$display("%d %h %h %h %c%h %o %h #",
alu0_dataready, alu0_argI, alu0_argA, alu0_argB,
9392,6 → 9111,7
end
end
*/
assign exc_o = iqentry_exc[heads[0]][7:0];
 
// Update the write buffer.
task wb_update;
9553,6 → 9273,7
iqentry_canex[nn] <= bus[`IB_CANEX];
iqentry_loadv[nn] <= bus[`IB_LOADV];
iqentry_load [nn] <= bus[`IB_LOAD];
iqentry_loadseg[nn]<= bus[`IB_LOADSEG];
iqentry_preload[nn]<= bus[`IB_PRELOAD];
iqentry_store[nn] <= bus[`IB_STORE];
iqentry_push [nn] <= bus[`IB_PUSH];
9572,9 → 9293,6
iqentry_sync [nn] <= bus[`IB_SYNC];
iqentry_fsync[nn] <= bus[`IB_FSYNC];
iqentry_rfw [nn] <= bus[`IB_RFW];
`ifdef SUPPORT_PREDICATION
iqentry_prfw [nn] <= bus[`IB_PRFW];
`endif
iqentry_we [nn] <= bus[`IB_WE];
end
endtask
9685,7 → 9403,7
input [`SNBITS] seqnum;
input [5:0] venno;
begin
iqentry_exc[tail] <= `FLT_NONE;
iqentry_exc[tail] <= `FLT_NONE;
`ifdef SUPPORT_DBG
if (dbg_imatchA)
iqentry_exc[tail] <= `FLT_DBG;
9702,6 → 9420,7
iqentry_insln[tail] <= fetchbuf0_insln;
iqentry_fc [tail] <= `INV;
iqentry_mem [tail] <= `INV;
iqentry_memissue[tail] <= `INV;
iqentry_alu [tail] <= `INV;
iqentry_fpu [tail] <= `INV;
iqentry_load [tail] <= `INV;
9768,6 → 9487,7
iqentry_insln[tail] <= fetchbuf1_insln;
iqentry_fc [tail] <= `INV;
iqentry_mem [tail] <= `INV;
iqentry_memissue[tail] <= `INV;
iqentry_alu [tail] <= `INV;
iqentry_fpu [tail] <= `INV;
iqentry_load [tail] <= `INV;
9822,6 → 9542,71
end
endtask
 
task exc;
input [`QBITS] head;
input thread;
input [7:0] causecd;
begin
excmiss <= TRUE;
`ifdef SUPPORT_SMT
excmisspc <= {tvec[3'd0][AMSB:8],1'b0,ol[thread],5'h00};
excthrd <= iqentry_thrd[head];
badaddr[{thread,2'd0}] <= iqentry_ma[head];
bad_instr[{thread,2'd0}] <= iqentry_instr[head];
epc0[thread] <= iqentry_pc[head];
epc1[thread] <= epc0[thread];
epc2[thread] <= epc1[thread];
epc3[thread] <= epc2[thread];
epc4[thread] <= epc3[thread];
epc5[thread] <= epc4[thread];
epc6[thread] <= epc5[thread];
epc7[thread] <= epc6[thread];
epc8[thread] <= epc7[thread];
im_stack[thread] <= {im_stack[thread][27:0],im};
ol_stack[thread] <= {ol_stack[thread][13:0],ol[thread]};
dl_stack[thread] <= {dl_stack[thread][13:0],dl[thread]};
pl_stack[thread] <= {pl_stack[thread][55:0],cpl[thread]};
rs_stack[thread] <= {rs_stack[thread][59:0],`EXC_RGS};
brs_stack[thread] <= {brs_stack[thread][59:0],`EXC_RGS};
cause[{thread,2'd0}] <= {8'd0,causecd};
mstatus[thread][5:4] <= 2'd0;
mstatus[thread][13:6] <= 8'h00;
mstatus[thread][19:14] <= `EXC_RGS;
`else
excmisspc <= {tvec[3'd0][AMSB:8],1'b0,ol,5'h00};
excthrd <= 1'b0;
badaddr[{1'b0,2'd0}] <= iqentry_ma[head];
bad_instr[3'd0] <= iqentry_instr[head];
epc0 <= iqentry_pc[head];
epc1 <= epc0;
epc2 <= epc1;
epc3 <= epc2;
epc4 <= epc3;
epc5 <= epc4;
epc6 <= epc5;
epc7 <= epc6;
epc8 <= epc7;
im_stack <= {im_stack[27:0],im};
ol_stack <= {ol_stack[13:0],ol};
dl_stack <= {dl_stack[13:0],dl};
pl_stack <= {pl_stack[55:0],cpl};
rs_stack <= {rs_stack[59:0],`EXC_RGS};
brs_stack <= {rs_stack[59:0],`EXC_RGS};
cause[3'd0] <= {8'd0,causecd};
mstatus[5:4] <= 2'd0;
mstatus[13:6] <= 8'h00;
mstatus[19:14] <= `EXC_RGS;
`endif
wb_en <= `TRUE;
sema[0] <= 1'b0;
ve_hold <= {vqet1,10'd0,vqe1,10'd0,vqet0,10'd0,vqe0};
`ifdef SUPPORT_DBG
dbg_ctrl[62:55] <= {dbg_ctrl[61:55],dbg_ctrl[63]};
dbg_ctrl[63] <= FALSE;
`endif
end
endtask
 
// This task takes care of commits for things other than the register file.
task oddball_commit;
input v;
9832,70 → 9617,10
thread = iqentry_thrd[head];
if (v) begin
if (|iqentry_exc[head]) begin
excmiss <= TRUE;
`ifdef SUPPORT_SMT
excmisspc <= {tvec[3'd0][AMSB:8],1'b0,ol[thread],5'h00};
excthrd <= iqentry_thrd[head];
badaddr[{thread,2'd0}] <= iqentry_ma[head];
bad_instr[{thread,2'd0}] <= iqentry_instr[head];
epc0[thread] <= iqentry_pc[head];
epc1[thread] <= epc0[thread];
epc2[thread] <= epc1[thread];
epc3[thread] <= epc2[thread];
epc4[thread] <= epc3[thread];
epc5[thread] <= epc4[thread];
epc6[thread] <= epc5[thread];
epc7[thread] <= epc6[thread];
epc8[thread] <= epc7[thread];
im_stack[thread] <= {im_stack[thread][27:0],im};
ol_stack[thread] <= {ol_stack[thread][13:0],ol[thread]};
dl_stack[thread] <= {dl_stack[thread][13:0],dl[thread]};
pl_stack[thread] <= {pl_stack[thread][55:0],cpl[thread]};
rs_stack[thread] <= {rs_stack[thread][59:0],`EXC_RGS};
brs_stack[thread] <= {brs_stack[thread][59:0],`EXC_RGS};
cause[{thread,2'd0}] <= {8'd0,iqentry_exc[head]};
mstatus[thread][5:4] <= 2'd0;
mstatus[thread][13:6] <= 8'h00;
mstatus[thread][19:14] <= `EXC_RGS;
`else
excmisspc <= {tvec[3'd0][AMSB:8],1'b0,ol,5'h00};
excthrd <= 1'b0;
badaddr[{1'b0,2'd0}] <= iqentry_ma[head];
bad_instr[3'd0] <= iqentry_instr[head];
epc0 <= iqentry_pc[head];
epc1 <= epc0;
epc2 <= epc1;
epc3 <= epc2;
epc4 <= epc3;
epc5 <= epc4;
epc6 <= epc5;
epc7 <= epc6;
epc8 <= epc7;
im_stack <= {im_stack[27:0],im};
ol_stack <= {ol_stack[13:0],ol};
dl_stack <= {dl_stack[13:0],dl};
pl_stack <= {pl_stack[55:0],cpl};
rs_stack <= {rs_stack[59:0],`EXC_RGS};
brs_stack <= {rs_stack[59:0],`EXC_RGS};
cause[3'd0] <= {8'd0,iqentry_exc[head]};
mstatus[5:4] <= 2'd0;
mstatus[13:6] <= 8'h00;
mstatus[19:14] <= `EXC_RGS;
`endif
wb_en <= `TRUE;
sema[0] <= 1'b0;
ve_hold <= {vqet1,10'd0,vqe1,10'd0,vqet0,10'd0,vqe0};
`ifdef SUPPORT_DBG
dbg_ctrl[62:55] <= {dbg_ctrl[61:55],dbg_ctrl[63]};
dbg_ctrl[63] <= FALSE;
`endif
exc(head,thread,iqentry_exc[head]);
end
else
case(iqentry_instr[head][`INSTRUCTION_OP])
`ifdef SUPPORT_PREDICATION
`CMPI: pregs[{rgs,iqentry_tgt[head][3:0]}] <= which==2'd1 ? cmt1nyb[iqentry_tgt[head][3:0]] : cmt0nyb[iqentry_tgt[head][3:0]];//commit_bus[3:0];
`endif
 
`BRK:
// BRK is treated as a nop unless it's a software interrupt or a
// hardware interrupt at a higher priority than the current priority.
9991,9 → 9716,6
endcase
`R2:
case(iqentry_instr[head][`INSTRUCTION_S2])
`ifdef SUPPORT_PREDICATION
`CMP: pregs[{rgs,iqentry_tgt[head][3:0]}] <= which==2'd1 ? cmt1nyb[iqentry_tgt[head][3:0]] : cmt0nyb[iqentry_tgt[head][3:0]];//commit_bus[3:0];
`endif
`R1: case(iqentry_instr[head][20:16])
`CHAIN_OFF: cr0[18] <= 1'b0;
`CHAIN_ON: cr0[18] <= 1'b1;
10012,9 → 9734,10
`endif
`RTI: begin
excmiss <= TRUE;
excthrd <= thread;
excmisspc <= iqentry_ma[head];
`ifdef SUPPORT_SMT
excmisspc <= epc0[thread];
excthrd <= thread;
// excmisspc <= epc0[thread];
mstatus[thread][3:0] <= im_stack[thread][3:0];
mstatus[thread][5:4] <= ol_stack[thread][1:0];
mstatus[thread][21:20] <= dl_stack[thread][1:0];
10036,8 → 9759,7
epc7[thread] <= epc8[thread];
epc8[thread] <= {tvec[0][AMSB:8], 1'b0, ol[thread], 5'h0};
`else
excmisspc <= epc0;
excthrd <= thread;
// excmisspc <= epc0;
mstatus[3:0] <= im_stack[3:0];
mstatus[5:4] <= ol_stack[1:0];
mstatus[21:20] <= dl_stack[1:0];
10271,9 → 9993,6
`CSR_SBU: dat <= sbu;
`CSR_ENU: dat <= en;
`endif
`ifdef SUPPORT_PREDICATION
`CSR_PREGS: read_pregs(dat);
`endif
`CSR_Q_CTR: dat <= iq_ctr;
`CSR_BM_CTR: dat <= bm_ctr;
`CSR_ICL_CTR: dat <= icl_ctr;
10402,9 → 10121,6
`CSR_SBU: su_barrier[brgs] <= dat;
`CSR_ENU: en_barrier[brgs] <= dat;
`endif
`ifdef SUPPORT_PREDICATION
`CSR_PREGS: write_pregs(dat);
`endif
`CSR_TIME: begin
ld_time <= 6'h3f;
wc_time_dat <= dat;
10462,26 → 10178,28
task tDram0Issue;
input [`QBITSP1] n;
begin
if (iqentry_state[n]==IQS_AGEN) begin
// dramA_v <= `INV;
dram0 <= `DRAMSLOT_BUSY;
dram0_id <= { 1'b1, n[`QBITS] };
dram0_instr <= iqentry_instr[n];
dram0_rmw <= iqentry_rmw[n];
dram0_preload <= iqentry_preload[n];
dram0_tgt <= iqentry_tgt[n];
dram0_data <= iqentry_a2[n];
dram0_addr <= iqentry_ma[n];
// if (ol[iqentry_thrd[n]]==`OL_USER)
// dram0_seg <= (iqentry_Ra[n]==5'd30 || iqentry_Ra[n]==5'd31) ? {ss[iqentry_thrd[n]],13'd0} : {ds[iqentry_thrd[n]],13'd0};
// else
dram0_unc <= iqentry_ma[n][31:20]==12'hFFD || !dce || iqentry_loadv[n];
dram0_memsize <= iqentry_memsz[n];
dram0_load <= iqentry_load[n];
dram0_store <= iqentry_store[n];
dram0 <= `DRAMSLOT_BUSY;
dram0_id <= { 1'b1, n[`QBITS] };
dram0_instr <= iqentry_instr[n];
dram0_rmw <= iqentry_rmw[n];
dram0_preload <= iqentry_preload[n];
dram0_tgt <= iqentry_tgt[n];
if (iqentry_imm[n] & iqentry_push[n])
dram0_data <= iqentry_a0[n];
else
dram0_data <= iqentry_a2[n];
dram0_addr <= iqentry_ma[n];
dram0_unc <= iqentry_ma[n][31:20]==12'hFFD || !dce || iqentry_loadv[n];
dram0_memsize <= iqentry_memsz[n];
dram0_load <= iqentry_load[n];
dram0_loadseg <= iqentry_loadseg[n];
dram0_store <= iqentry_store[n];
`ifdef SUPPORT_SMT
dram0_ol <= (iqentry_Ra[n][4:0]==5'd31 || iqentry_Ra[n][4:0]==5'd30) ? ol[iqentry_thrd[n]] : dl[iqentry_thrd[n]];
dram0_ol <= (iqentry_Ra[n][4:0]==5'd31 || iqentry_Ra[n][4:0]==5'd30) ? ol[iqentry_thrd[n]] : dl[iqentry_thrd[n]];
`else
dram0_ol <= (iqentry_Ra[n][4:0]==5'd31 || iqentry_Ra[n][4:0]==5'd30) ? ol : dl;
dram0_ol <= (iqentry_Ra[n][4:0]==5'd31 || iqentry_Ra[n][4:0]==5'd30) ? ol : dl;
`endif
// Once the memory op is issued reset the a1_v flag.
// This will cause the a1 bus to look for new data from memory (a1_s is pointed to a memory bus)
10488,7 → 10206,8
// This is used for the load and compare instructions.
// must reset the a1 source too.
//iqentry_a1_v[n] <= `INV;
iqentry_state[n] <= IQS_MEM;
iqentry_state[n] <= IQS_MEM;
end
end
endtask
 
10495,7 → 10214,8
task tDram1Issue;
input [`QBITSP1] n;
begin
dramB_v <= `INV;
if (iqentry_state[n]==IQS_AGEN) begin
// dramB_v <= `INV;
dram1 <= `DRAMSLOT_BUSY;
dram1_id <= { 1'b1, n[`QBITS] };
dram1_instr <= iqentry_instr[n];
10502,7 → 10222,10
dram1_rmw <= iqentry_rmw[n];
dram1_preload <= iqentry_preload[n];
dram1_tgt <= iqentry_tgt[n];
dram1_data <= iqentry_a2[n];
if (iqentry_imm[n] & iqentry_push[n])
dram1_data <= iqentry_a0[n];
else
dram1_data <= iqentry_a2[n];
dram1_addr <= iqentry_ma[n];
// if (ol[iqentry_thrd[n]]==`OL_USER)
// dram1_seg <= (iqentry_Ra[n]==5'd30 || iqentry_Ra[n]==5'd31) ? {ss[iqentry_thrd[n]],13'd0} : {ds[iqentry_thrd[n]],13'd0};
10510,6 → 10233,7
dram1_unc <= iqentry_ma[n][31:20]==12'hFFD || !dce || iqentry_loadv[n];
dram1_memsize <= iqentry_memsz[n];
dram1_load <= iqentry_load[n];
dram1_loadseg <= iqentry_loadseg[n];
dram1_store <= iqentry_store[n];
`ifdef SUPPORT_SMT
dram1_ol <= (iqentry_Ra[n][4:0]==5'd31 || iqentry_Ra[n][4:0]==5'd30) ? ol[iqentry_thrd[n]] : dl[iqentry_thrd[n]];
10518,6 → 10242,7
`endif
//iqentry_a1_v[n] <= `INV;
iqentry_state[n] <= IQS_MEM;
end
end
endtask
 
10524,7 → 10249,8
task tDram2Issue;
input [`QBITSP1] n;
begin
dramC_v <= `INV;
if (iqentry_state[n]==IQS_AGEN) begin
// dramC_v <= `INV;
dram2 <= `DRAMSLOT_BUSY;
dram2_id <= { 1'b1, n[`QBITS] };
dram2_instr <= iqentry_instr[n];
10531,7 → 10257,10
dram2_rmw <= iqentry_rmw[n];
dram2_preload <= iqentry_preload[n];
dram2_tgt <= iqentry_tgt[n];
dram2_data <= iqentry_a2[n];
if (iqentry_imm[n] & iqentry_push[n])
dram2_data <= iqentry_a0[n];
else
dram2_data <= iqentry_a2[n];
dram2_addr <= iqentry_ma[n];
// if (ol[iqentry_thrd[n]]==`OL_USER)
// dram2_seg <= (iqentry_Ra[n]==5'd30 || iqentry_Ra[n]==5'd31) ? {ss[iqentry_thrd[n]],13'd0} : {ds[iqentry_thrd[n]],13'd0};
10539,6 → 10268,7
dram2_unc <= iqentry_ma[n][31:20]==12'hFFD || !dce || iqentry_loadv[n];
dram2_memsize <= iqentry_memsz[n];
dram2_load <= iqentry_load[n];
dram2_loadseg <= iqentry_loadseg[n];
dram2_store <= iqentry_store[n];
`ifdef SUPPORT_SMT
dram2_ol <= (iqentry_Ra[n][4:0]==5'd31 || iqentry_Ra[n][4:0]==5'd30) ? ol[iqentry_thrd[n]] : dl[iqentry_thrd[n]];
10547,6 → 10277,7
`endif
//iqentry_a1_v[n] <= `INV;
iqentry_state[n] <= IQS_MEM;
end
end
endtask
 
10558,6 → 10289,7
stb_o <= `LOW;
we <= `LOW;
sel_o <= 8'h00;
// vadr <= 32'hCCCCCCCC;
end
endtask
 
/twoway/FT64_fetchbuf.v
56,6 → 56,7
nop_fetchbuf,
take_branch0, take_branch1,
stompedRets,
pred_on,
panic
);
parameter AMSB = `AMSB;
128,6 → 129,7
output take_branch0;
output take_branch1;
input [3:0] stompedRets;
input pred_on;
output reg [3:0] panic;
integer n;
 
183,9 → 185,9
else
`endif
case(ins[7:6])
2'd0: fnInsLength = 3'd4;
2'd1: fnInsLength = 3'd6;
default: fnInsLength = 3'd2;
2'd0: fnInsLength = 3'd4|pred_on;
2'd1: fnInsLength = 3'd6|pred_on;
default: fnInsLength = 3'd2|pred_on;
endcase
endfunction
 
193,10 → 195,10
wire [2:0] fetchbufB_inslen;
wire [2:0] fetchbufC_inslen;
wire [2:0] fetchbufD_inslen;
FT64_InsLength uilA (fetchbufA_instr, fetchbufA_inslen);
FT64_InsLength uilB (fetchbufB_instr, fetchbufB_inslen);
FT64_InsLength uilC (fetchbufC_instr, fetchbufC_inslen);
FT64_InsLength uilD (fetchbufD_instr, fetchbufD_inslen);
FT64_InsLength uilA (fetchbufA_instr, fetchbufA_inslen, pred_on);
FT64_InsLength uilB (fetchbufB_instr, fetchbufB_inslen, pred_on);
FT64_InsLength uilC (fetchbufC_instr, fetchbufC_inslen, pred_on);
FT64_InsLength uilD (fetchbufD_instr, fetchbufD_inslen, pred_on);
 
wire [47:0] xinsn0;
wire [47:0] xinsn1;
/twoway/FT64_fetchbuf_x1.v
1,6 → 1,6
// ============================================================================
// __
// \\__/ o\ (C) 2018 Robert Finch, Waterloo
// \\__/ o\ (C) 2018-2019 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
120,8 → 120,10
input [47:0] isn;
casex(isn[`INSTRUCTION_OP])
`Bcc: IsBranch = TRUE;
`BLcc: IsBranch = TRUE;
`BBc: IsBranch = TRUE;
`BEQI: IsBranch = TRUE;
`BNEI: IsBranch = TRUE;
`BCHK: IsBranch = TRUE;
default: IsBranch = FALSE;
endcase
134,12 → 136,12
 
function IsJmp;
input [47:0] isn;
IsJmp = isn[`INSTRUCTION_OP]==`JMP;
IsJmp = isn[`INSTRUCTION_OP]==`JMP && isn[7]==1'b0;
endfunction
 
function IsCall;
input [47:0] isn;
IsCall = isn[`INSTRUCTION_OP]==`CALL;
IsCall = isn[`INSTRUCTION_OP]==`CALL && isn[7]==1'b0;
endfunction
 
function IsRet;
157,6 → 159,25
IsRTI = isn[`INSTRUCTION_OP]==`R2 && isn[`INSTRUCTION_S2]==`RTI;
endfunction
 
function IsExec;
input [47:0] isn;
if (isn[7:6]==2'b00)
case(isn[`INSTRUCTION_OP])
`R2:
case(isn[`INSTRUCTION_S2])
`R1:
case(isn[22:18])
`EXEC: IsExec = TRUE;
default: IsExec = FALSE;
endcase
default: IsExec = FALSE;
endcase
default: IsExec = FALSE;
endcase
else
IsExec = FALSE;
endfunction
 
function [2:0] fnInsLength;
input [47:0] ins;
`ifdef SUPPORT_DCI
217,7 → 238,11
`RET: branch_pcA = retpc0;
`JMP,`CALL:
begin
`ifdef JMP40
branch_pcA[39:0] = fetchbufA_instr[6] ? {fetchbufA_instr[47:8]} : {fetchbufA_pc[39:24],fetchbufA_instr[31:8]};
`else
branch_pcA[39:0] = {fetchbufA_pc[39:24],fetchbufA_instr[31:8]};
`endif
branch_pcA[63:40] = fetchbufA_pc[63:40];
end
`R2: branch_pcA = btgtA; // RTI
224,9 → 249,8
`BRK,`JAL: branch_pcA = btgtA;
default:
begin
branch_pcA[31:8] = fetchbufA_pc[31:8] +
((fetchbufA_instr[7:6]==2'b01) ? {{5{fetchbufA_instr[47]}},fetchbufA_instr[47:29]} : {{21{fetchbufA_instr[31]}},fetchbufA_instr[31:29]});
branch_pcA[7:0] = {fetchbufA_instr[28:23],fetchbufA_instr[17:16]};
branch_pcA[31:0] = fetchbufA_pc[31:0] +
((fetchbufA_instr[7:6]==2'b01) ? {{4{fetchbufA_instr[47]}},fetchbufA_instr[47:23],fetchbufA_instr[17:16],1'b0} : {{20{fetchbufA_instr[31]}},fetchbufA_instr[31:23],fetchbufA_instr[17:16],1'b0});
branch_pcA[63:32] = fetchbufA_pc[63:32];
end
endcase
238,7 → 262,11
`RET: branch_pcB = retpc0;
`JMP,`CALL:
begin
`ifdef JMP40
branch_pcB[39:0] = fetchbufB_instr[6] ? {fetchbufB_instr[47:8]} : {fetchbufB_pc[39:24],fetchbufB_instr[31:8]};
`else
branch_pcB[39:0] = {fetchbufB_pc[39:24],fetchbufB_instr[31:8]};
`endif
branch_pcB[63:40] = fetchbufB_pc[63:40];
end
`R2: branch_pcB = btgtB; // RTI
245,9 → 273,8
`BRK,`JAL: branch_pcB = btgtB;
default:
begin
branch_pcB[31:8] = fetchbufB_pc[31:8] +
((fetchbufB_instr[7:6]==2'b01) ? {{5{fetchbufB_instr[47]}},fetchbufB_instr[47:29]} : {{21{fetchbufB_instr[31]}},fetchbufB_instr[31:29]});
branch_pcB[7:0] = {fetchbufB_instr[28:23],fetchbufB_instr[17:16]};
branch_pcB[31:0] = fetchbufB_pc[31:0] +
((fetchbufB_instr[7:6]==2'b01) ? {{4{fetchbufB_instr[47]}},fetchbufB_instr[47:23],fetchbufB_instr[17:16],1'b0} : {{20{fetchbufB_instr[31]}},fetchbufB_instr[31:23],fetchbufB_instr[17:16],1'b0});
branch_pcB[63:32] = fetchbufB_pc[63:32];
end
endcase
470,8 → 497,8
insln0 <= 3'd2 | pred_on;
else
`endif
if (insn0[7:6]==2'b00 && insn0[`INSTRUCTION_OP]==`EXEC)
insln0 <= fnInsLength(codebuf0);
if (IsExec(insn0))
insln0 <= fnInsLength(codebuf0); //???? should be 4?
else
insln0 <= fnInsLength(insn0);
end
486,9 → 513,9
cinsn0 <= expand0;
else
`endif
if (insn0[7:6]==2'b00 && insn0[`INSTRUCTION_OP]==`EXEC && !pred_on)
if (IsExec(insn0) && !pred_on)
cinsn0 <= codebuf0;
else if (insn0[15:14]==2'b00 && insn0[`INSTRUCTION_OP]==`EXEC && pred_on)
else if (IsExec(insn0[55:8]) && pred_on)
cinsn0 <= codebuf0;
else if (insn0[15] & pred_on)
cinsn0 <= {xinsn0,insn0[7:0]};

powered by: WebSVN 2.1.0

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