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]}; |