Line 19... |
Line 19... |
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
//
|
//
|
// ============================================================================
|
// ============================================================================
|
//
|
//
|
|
//`define RAS_PREDICTION 1
|
|
//`define BTB 1
|
|
//`define TLB 1
|
|
//`define BRANCH_PREDICTION_SIMPLE 1
|
|
|
`define RESET_VECTOR 64'hFFFF_FFFF_FFFF_FFF0
|
`define RESET_VECTOR 64'hFFFF_FFFF_FFFF_FFF0
|
`define NMI_VECTOR 64'hFFFF_FFFF_FFFF_FFE0
|
`define NMI_VECTOR 64'hFFFF_FFFF_FFFF_FFE0
|
`define IRQ_VECTOR 64'hFFFF_FFFF_FFFF_FFD0
|
`define IRQ_VECTOR 64'hFFFF_FFFF_FFFF_FFD0
|
`define TRAP_VECTOR 64'h0000_0000_0000_0000
|
`define TRAP_VECTOR 64'h0000_0000_0000_0000
|
|
|
Line 67... |
Line 72... |
|
|
|
|
`define MISC 7'd0
|
`define MISC 7'd0
|
`define BRK 7'd0
|
`define BRK 7'd0
|
`define IRQ 7'd1
|
`define IRQ 7'd1
|
|
`define ICACHE_ON 7'd10
|
|
`define ICACHE_OFF 7'd11
|
`define FIP 7'd20
|
`define FIP 7'd20
|
`define IRET 7'd32
|
`define IRET 7'd32
|
`define ERET 7'd33
|
`define ERET 7'd33
|
`define WAIT 7'd40
|
`define WAIT 7'd40
|
`define TLBP 7'd49
|
`define TLBP 7'd49
|
Line 114... |
Line 121... |
`define AXC 6'd21
|
`define AXC 6'd21
|
`define Tick 6'd22
|
`define Tick 6'd22
|
`define EPC 6'd23
|
`define EPC 6'd23
|
`define CauseCode 6'd24
|
`define CauseCode 6'd24
|
`define TBA 6'd25
|
`define TBA 6'd25
|
|
`define NON_ICACHE_SEG 6'd26
|
`define OMG 7'd50
|
`define OMG 7'd50
|
`define CMG 7'd51
|
`define CMG 7'd51
|
`define OMGI 7'd52
|
`define OMGI 7'd52
|
`define CMGI 7'd53
|
`define CMGI 7'd53
|
`define MFTBA 7'd58
|
`define EXEC 7'd58
|
`define MTTBA 7'd59
|
|
`define RR 7'd2
|
`define RR 7'd2
|
`define ADD 7'd2
|
`define ADD 7'd2
|
`define ADDU 7'd3
|
`define ADDU 7'd3
|
`define SUB 7'd4
|
`define SUB 7'd4
|
`define SUBU 7'd5
|
`define SUBU 7'd5
|
Line 413... |
Line 420... |
reg [1:0] rm; // fp rounding mode
|
reg [1:0] rm; // fp rounding mode
|
reg [41:0] dIR;
|
reg [41:0] dIR;
|
reg [41:0] xIR;
|
reg [41:0] xIR;
|
reg [63:0] pc;
|
reg [63:0] pc;
|
reg [63:0] ErrorEPC,EPC,IPC;
|
reg [63:0] ErrorEPC,EPC,IPC;
|
reg [63:0] dpc,m1pc,m2pc,m3pc,m4pc,wpc;
|
reg [63:0] dpc,m1pc,m2pc,wpc;
|
reg dpcv,xpcv,m1pcv,m2pcv,m3pcv,m4pcv,wpcv; // PC valid indicators
|
reg dpcv,xpcv,m1pcv,m2pcv,wpcv; // PC valid indicators
|
reg [63:0] xpc;
|
reg [63:0] xpc;
|
reg [63:0] tlbra; // return address for a TLB exception
|
reg [63:0] tlbra; // return address for a TLB exception
|
reg [8:0] dRa,dRb,dRc;
|
reg [8:0] dRa,dRb,dRc;
|
reg [8:0] wRt,mRt,m1Rt,m2Rt,m3Rt,m4Rt,tRt,dRt;
|
reg [8:0] wRt,mRt,m1Rt,m2Rt,tRt,dRt;
|
reg [8:0] xRt;
|
reg [8:0] xRt;
|
reg [63:0] dImm;
|
reg [63:0] dImm;
|
reg [63:0] ea;
|
reg [63:0] ea;
|
reg [63:0] iadr_o;
|
reg [63:0] iadr_o;
|
reg [31:0] idat;
|
reg [31:0] idat;
|
reg [4:0] cstate;
|
reg [4:0] cstate;
|
reg dbranch_taken,xbranch_taken;
|
reg dbranch_taken,xbranch_taken;
|
reg [63:0] mutex_gate;
|
reg [63:0] mutex_gate;
|
reg [63:0] TBA;
|
reg [63:0] TBA;
|
reg [1:0] dhwxtype,xhwxtype,m1hwxtype,m2hwxtype,m3hwxtype,m4hwxtype,whwxtype;
|
reg [1:0] dhwxtype,xhwxtype,m1hwxtype,m2hwxtype,whwxtype;
|
reg [3:0] AXC,dAXC,xAXC;
|
reg [3:0] AXC,dAXC,xAXC;
|
reg dtinit;
|
reg dtinit;
|
|
reg [63:32] nonICacheSeg;
|
|
|
//reg wr_icache;
|
//reg wr_icache;
|
reg dccyc;
|
reg dccyc;
|
wire [63:0] cdat;
|
wire [63:0] cdat;
|
reg [63:0] wr_addr;
|
reg [63:0] wr_addr;
|
Line 466... |
Line 474... |
|
|
wire KernelMode = StatusEXL;
|
wire KernelMode = StatusEXL;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// TLB
|
// TLB
|
|
// The TLB contains 64 entries, that are 8 way set associative.
|
|
// The TLB is dual ported and shared between the instruction and data streams.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
|
wire unmappedArea = pc[63:52]==12'hFFD || pc[63:52]==12'hFFE || pc[63:52]==12'hFFF;
|
|
wire unmappedDataArea = ea[63:52]==12'hFFD || ea[63:52]==12'hFFE || ea[63:52]==12'hFFF;
|
|
wire [63:0] ppc;
|
|
wire [63:0] pea;
|
|
|
|
`ifdef TLB
|
reg [24:13] TLBPageMask;
|
reg [24:13] TLBPageMask;
|
reg [63:13] TLBVirtPage;
|
reg [63:13] TLBVirtPage;
|
reg [63:13] TLBPhysPage0;
|
reg [63:13] TLBPhysPage0;
|
reg [63:13] TLBPhysPage1;
|
reg [63:13] TLBPhysPage1;
|
reg [7:0] TLBASID;
|
reg [7:0] TLBASID;
|
reg TLBG;
|
reg TLBG;
|
reg TLBD;
|
reg TLBD;
|
reg TLBValid;
|
reg TLBValid;
|
reg [63:0] Index;
|
reg [63:0] Index;
|
reg [3:0] Random;
|
reg [2:0] Random;
|
reg [3:0] Wired;
|
reg [2:0] Wired;
|
reg [15:0] IMatch,DMatch;
|
reg [15:0] IMatch,DMatch;
|
|
|
reg [4:0] m;
|
reg [3:0] m;
|
reg [3:0] i;
|
reg [5:0] i;
|
reg [24:13] ITLBPageMask [15:0];
|
reg [24:13] ITLBPageMask [63:0];
|
reg [63:13] ITLBVirtPage [15:0];
|
reg [63:13] ITLBVirtPage [63:0];
|
reg [63:13] ITLBPhysPage0 [15:0];
|
reg [63:13] ITLBPhysPage0 [63:0];
|
reg [63:13] ITLBPhysPage1 [15:0];
|
reg [63:13] ITLBPhysPage1 [63:0];
|
reg [15:0] ITLBG;
|
reg [63:0] ITLBG;
|
reg [15:0] ITLBD;
|
reg [63:0] ITLBD;
|
reg [7:0] ITLBASID [15:0];
|
reg [7:0] ITLBASID [63:0];
|
reg [15:0] ITLBValid;
|
reg [15:0] ITLBValid;
|
initial begin
|
initial begin
|
for (n = 0; n < 16; n = n + 1)
|
for (n = 0; n < 64; n = n + 1)
|
begin
|
begin
|
ITLBPageMask[n] = 0;
|
ITLBPageMask[n] = 0;
|
ITLBVirtPage[n] = 0;
|
ITLBVirtPage[n] = 0;
|
ITLBPhysPage0[n] = 0;
|
ITLBPhysPage0[n] = 0;
|
ITLBPhysPage1[n] = 0;
|
ITLBPhysPage1[n] = 0;
|
Line 504... |
Line 520... |
ITLBASID[n] = 0;
|
ITLBASID[n] = 0;
|
ITLBValid[n] = 0;
|
ITLBValid[n] = 0;
|
end
|
end
|
end
|
end
|
always @*
|
always @*
|
for (n = 0; n < 16; n = n + 1)
|
for (n = 0; n < 8; n = n + 1)
|
IMatch[n] = ((pc[63:13]|ITLBPageMask[n])==(ITLBVirtPage[n]|ITLBPageMask[n])) &&
|
IMatch[n] = ((pc[63:13]|ITLBPageMask[{n[2:0],pc[15:13]}])==(ITLBVirtPage[{n[2:0],pc[15:13]}]|ITLBPageMask[{n[2:0],pc[15:13]}])) &&
|
((ITLBASID[n]==ASID) || ITLBG[n]) &&
|
((ITLBASID[{n,pc[15:13]}]==ASID) || ITLBG[{n,pc[15:13]}]) &&
|
ITLBValid[n];
|
ITLBValid[{n,pc[15:13]}];
|
always @(IMatch)
|
always @(IMatch)
|
if (IMatch[0]) m <= 5'd0;
|
if (IMatch[0]) m <= 4'd0;
|
else if (IMatch[1]) m <= 5'd1;
|
else if (IMatch[1]) m <= 4'd1;
|
else if (IMatch[2]) m <= 5'd2;
|
else if (IMatch[2]) m <= 4'd2;
|
else if (IMatch[3]) m <= 5'd3;
|
else if (IMatch[3]) m <= 4'd3;
|
else if (IMatch[4]) m <= 5'd4;
|
else if (IMatch[4]) m <= 4'd4;
|
else if (IMatch[5]) m <= 5'd5;
|
else if (IMatch[5]) m <= 4'd5;
|
else if (IMatch[6]) m <= 5'd6;
|
else if (IMatch[6]) m <= 4'd6;
|
else if (IMatch[7]) m <= 5'd7;
|
else if (IMatch[7]) m <= 4'd7;
|
else if (IMatch[8]) m <= 5'd8;
|
else m <= 4'd15;
|
else if (IMatch[9]) m <= 5'd9;
|
|
else if (IMatch[10]) m <= 5'd10;
|
|
else if (IMatch[11]) m <= 5'd11;
|
|
else if (IMatch[12]) m <= 5'd12;
|
|
else if (IMatch[13]) m <= 5'd13;
|
|
else if (IMatch[14]) m <= 5'd14;
|
|
else if (IMatch[15]) m <= 5'd15;
|
|
else m <= 5'd31;
|
|
|
|
wire ioddpage = |({ITLBPageMask[q]+19'd1,13'd0}&pc);
|
wire ioddpage = |({ITLBPageMask[{m[2:0],pc[15:13]}]+19'd1,13'd0}&pc);
|
wire [63:13] IPFN = ioddpage ? ITLBPhysPage1[q] : ITLBPhysPage0[q];
|
wire [63:13] IPFN = ioddpage ? ITLBPhysPage1[{m[2:0],pc[15:13]}] : ITLBPhysPage0[{m[2:0],pc[15:13]}];
|
|
|
wire unmappedArea = pc[63:52]==12'hFFD || pc[63:52]==12'hFFE || pc[63:52]==12'hFFF;
|
wire ITLBMiss = !unmappedArea & m[3];
|
wire [63:0] ppc;
|
|
wire ITLBMiss = !unmappedArea & m[4];
|
|
|
|
assign ppc[63:13] = unmappedArea ? pc[63:13] : m[4] ? `TLBMissPage: IPFN;
|
assign ppc[63:13] = unmappedArea ? pc[63:13] : m[3] ? `TLBMissPage: IPFN;
|
assign ppc[12:0] = pc[12:0];
|
assign ppc[12:0] = pc[12:0];
|
|
|
reg [4:0] q;
|
reg [3:0] q;
|
always @(ea)
|
always @(ea)
|
for (n = 0; n < 16; n = n + 1)
|
for (n = 0; n < 7; n = n + 1)
|
DMatch[n] = ((ea[63:13]|ITLBPageMask[n])==(ITLBVirtPage[n]|ITLBPageMask[n])) &&
|
DMatch[n] = ((ea[63:13]|ITLBPageMask[{n,ea[15:13]}])==(ITLBVirtPage[{n,ea[15:13]}]|ITLBPageMask[{n,ea[15:13]}])) &&
|
((ITLBASID[n]==ASID) || ITLBG[n]) &&
|
((ITLBASID[{n,ea[15:13]}]==ASID) || ITLBG[{n,ea[15:13]}]) &&
|
ITLBValid[n];
|
ITLBValid[{n,ea[15:13]}];
|
always @(DMatch)
|
always @(DMatch)
|
if (DMatch[0]) q <= 5'd0;
|
if (DMatch[0]) q <= 4'd0;
|
else if (DMatch[1]) q <= 5'd1;
|
else if (DMatch[1]) q <= 4'd1;
|
else if (DMatch[2]) q <= 5'd2;
|
else if (DMatch[2]) q <= 4'd2;
|
else if (DMatch[3]) q <= 5'd3;
|
else if (DMatch[3]) q <= 4'd3;
|
else if (DMatch[4]) q <= 5'd4;
|
else if (DMatch[4]) q <= 4'd4;
|
else if (DMatch[5]) q <= 5'd5;
|
else if (DMatch[5]) q <= 4'd5;
|
else if (DMatch[6]) q <= 5'd6;
|
else if (DMatch[6]) q <= 4'd6;
|
else if (DMatch[7]) q <= 5'd7;
|
else if (DMatch[7]) q <= 4'd7;
|
else if (DMatch[8]) q <= 5'd8;
|
else q <= 4'd15;
|
else if (DMatch[9]) q <= 5'd9;
|
|
else if (DMatch[10]) q <= 5'd10;
|
|
else if (DMatch[11]) q <= 5'd11;
|
|
else if (DMatch[12]) q <= 5'd12;
|
|
else if (DMatch[13]) q <= 5'd13;
|
|
else if (DMatch[14]) q <= 5'd14;
|
|
else if (DMatch[15]) q <= 5'd15;
|
|
else q <= 5'd31;
|
|
|
|
wire doddpage = |({ITLBPageMask[q]+19'd1,13'd0}&ea);
|
wire doddpage = |({ITLBPageMask[{q[2:0],ea[15:13]}]+19'd1,13'd0}&ea);
|
wire [63:13] DPFN = doddpage ? ITLBPhysPage1[q] : ITLBPhysPage0[q];
|
wire [63:13] DPFN = doddpage ? ITLBPhysPage1[{q[2:0],ea[15:13]}] : ITLBPhysPage0[{q[2:0],ea[15:13]}];
|
|
|
wire unmappedDataArea = ea[63:52]==12'hFFD || ea[63:52]==12'hFFE || ea[63:52]==12'hFFF;
|
wire DTLBMiss = !unmappedDataArea & q[3];
|
wire DTLBMiss = !unmappedDataArea & q[4];
|
|
wire m1UnmappedDataArea = pea[63:13]>=12'hFFD;
|
|
|
|
wire [63:0] pea;
|
assign pea[63:13] = unmappedDataArea ? ea[63:13] : q[3] ? `TLBMissPage: DPFN;
|
assign pea[63:13] = unmappedDataArea ? ea[63:13] : q[4] ? `TLBMissPage: DPFN;
|
|
assign pea[12:0] = ea[12:0];
|
assign pea[12:0] = ea[12:0];
|
|
`else
|
|
assign ppc = pc;
|
|
assign pea = ea;
|
|
`endif
|
|
wire m1UnmappedDataArea = pea[63:13]>=12'hFFD;
|
|
|
wire dram_bus = !pea[63];
|
wire dram_bus = !pea[63];
|
wire m2_dram_bus = !m2Addr[63];
|
wire m2_dram_bus = !m2Addr[63];
|
wire m3_dram_bus = !m3Addr[63];
|
|
wire m4_dram_bus = !m4Addr[63];
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Clock control
|
// Clock control
|
// - reset or NMI reenables the clock
|
// - reset or NMI reenables the clock
|
// - this circuit must be under the clk_i domain
|
// - this circuit must be under the clk_i domain
|
Line 602... |
Line 601... |
// Instruction Cache
|
// Instruction Cache
|
// 8kB
|
// 8kB
|
//
|
//
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
reg icaccess;
|
reg icaccess;
|
|
//wire nonICachedArea;
|
|
|
//Raptor64_icache_ram_x32 u1
|
//Raptor64_icache_ram_x32 u1
|
//(
|
//(
|
// .clk(clk),
|
// .clk(clk),
|
// .wr(icaccess & ack_i),
|
// .wr(icaccess & ack_i),
|
// .adr_i(adr_o[12:0]),
|
// .adr_i(adr_o[12:0]),
|
// .dat_i(dat_i),
|
// .dat_i(dat_i),
|
// .pc(pc),
|
// .pc(pc),
|
// .insn(insn)
|
// .insn(insn)
|
//);
|
//);
|
|
reg ICacheOn;
|
|
wire ibufrdy;
|
|
reg [63:0] tmpbuf;
|
wire [127:0] insnbundle;
|
wire [127:0] insnbundle;
|
|
reg [127:0] insnbuf;
|
|
reg [63:4] ibuftag;
|
|
wire isICached = ppc[63:32]!=nonICacheSeg;
|
|
wire ICacheAct = ICacheOn & isICached;
|
|
|
Raptor64_icache_ram u1
|
Raptor64_icache_ram u1
|
(
|
(
|
.clka(clk), // input clka
|
.clka(clk), // input clka
|
.wea(icaccess & ack_i), // input [0 : 0] wea
|
.wea(icaccess & ack_i), // input [0 : 0] wea
|
Line 625... |
Line 632... |
.clkb(~clk), // input clkb
|
.clkb(~clk), // input clkb
|
.addrb(pc[12:4]), // input [9 : 0] addrb
|
.addrb(pc[12:4]), // input [9 : 0] addrb
|
.doutb(insnbundle) // output [63 : 0] doutb
|
.doutb(insnbundle) // output [63 : 0] doutb
|
);
|
);
|
|
|
always @(pc or insnbundle)
|
always @(pc or insnbundle or ICacheAct or insnbuf)
|
begin
|
begin
|
case(pc[3:2])
|
case({ICacheAct,pc[3:2]})
|
2'd0: insn <= insnbundle[ 41: 0];
|
3'd0: insn <= insnbuf[ 41: 0];
|
2'd1: insn <= insnbundle[ 83:42];
|
3'd1: insn <= insnbuf[ 83:42];
|
2'd2: insn <= insnbundle[125:84];
|
3'd2: insn <= insnbuf[125:84];
|
2'd3: insn <= 42'h37800000000; // NOP instruction
|
3'd3: insn <= 42'h37800000000;
|
|
3'd4: insn <= insnbundle[ 41: 0];
|
|
3'd5: insn <= insnbundle[ 83:42];
|
|
3'd6: insn <= insnbundle[125:84];
|
|
3'd7: insn <= 42'h37800000000; // NOP instruction
|
endcase
|
endcase
|
end
|
end
|
|
|
|
|
reg [63:13] tmem [127:0];
|
reg [63:13] tmem [127:0];
|
Line 649... |
Line 660... |
end
|
end
|
|
|
wire [64:13] tgout;
|
wire [64:13] tgout;
|
assign tgout = {tvalid[pc[12:6]],tmem[pc[12:6]]};
|
assign tgout = {tvalid[pc[12:6]],tmem[pc[12:6]]};
|
assign ihit = (tgout=={1'b1,ppc[63:13]});
|
assign ihit = (tgout=={1'b1,ppc[63:13]});
|
|
assign ibufrdy = ibuftag==ppc[63:4];
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Data Cache
|
// Data Cache
|
// No-allocate on write
|
// No-allocate on write
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Line 726... |
Line 737... |
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
reg [64:0] xData;
|
reg [64:0] xData;
|
wire xisCacheElement = xData[63:52] != 12'hFFD;
|
wire xisCacheElement = xData[63:52] != 12'hFFD && xData[63:52]!=12'hFFF;
|
reg m1IsCacheElement;
|
reg m1IsCacheElement;
|
|
|
reg nopI;
|
reg nopI;
|
wire [6:0] iFunc = insn[6:0];
|
wire [6:0] iFunc = insn[6:0];
|
wire [6:0] dFunc = dIR[6:0];
|
wire [6:0] dFunc = dIR[6:0];
|
wire [6:0] xFunc = xIR[6:0];
|
wire [6:0] xFunc = xIR[6:0];
|
wire [6:0] iOpcode = insn[41:35];
|
wire [6:0] iOpcode = insn[41:35];
|
wire [6:0] xOpcode = xIR[41:35];
|
wire [6:0] xOpcode = xIR[41:35];
|
wire [6:0] dOpcode = dIR[41:35];
|
wire [6:0] dOpcode = dIR[41:35];
|
reg [6:0] m1Opcode,m2Opcode,m3Opcode,m4Opcode;
|
reg [6:0] m1Opcode,m2Opcode;
|
reg [6:0] m1Func,m2Func,m3Func,m4Func;
|
reg [6:0] m1Func,m2Func;
|
reg [63:0] m1Data,m2Data,m3Data,m4Data,wData,tData;
|
reg [63:0] m1Data,m2Data,wData,tData;
|
reg [63:0] m2Addr,m3Addr,m4Addr;
|
reg [63:0] m2Addr;
|
reg [63:0] tick;
|
reg [63:0] tick;
|
reg [63:0] tba;
|
reg [63:0] tba;
|
reg [63:0] exception_address,ipc;
|
reg [63:0] exception_address,ipc;
|
reg [63:0] a,b,c,imm,m1b;
|
reg [63:0] a,b,c,imm,m1b;
|
reg prev_ihit;
|
reg prev_ihit;
|
reg rsf;
|
reg rsf;
|
reg [63:5] resv_address;
|
reg [63:5] resv_address;
|
reg dirqf,rirqf,m1irqf,m2irqf,m3irqf,m4irqf,wirqf,tirqf;
|
reg dirqf,rirqf,m1irqf,m2irqf,wirqf,tirqf;
|
reg xirqf;
|
reg xirqf;
|
reg [7:0] dextype,m1extype,m2extype,m3extype,m4extype,wextype,textype,exception_type;
|
reg [7:0] dextype,m1extype,m2extype,wextype,textype,exception_type;
|
reg [7:0] xextype;
|
reg [7:0] xextype;
|
wire advanceX_edge;
|
wire advanceX_edge;
|
reg takb;
|
reg takb;
|
|
|
wire [127:0] mult_out;
|
wire [127:0] mult_out;
|
Line 922... |
Line 933... |
endfunction
|
endfunction
|
|
|
wire [63:0] jmp_tgt = dOpcode[6:4]==`IMM ? {dIR[26:0],insn[34:0],2'b00} : {pc[63:37],insn[34:0],2'b00};
|
wire [63:0] jmp_tgt = dOpcode[6:4]==`IMM ? {dIR[26:0],insn[34:0],2'b00} : {pc[63:37],insn[34:0],2'b00};
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
`ifdef RAS_PREDICTION
|
|
reg [63:0] ras [63:0]; // return address stack, return predictions
|
|
reg [5:0] ras_sp;
|
|
`endif
|
|
`ifdef BTB
|
|
reg [63:0] btb [63:0]; // branch target buffer
|
|
`endif
|
|
|
|
`ifdef BRANCH_PREDICTION_SIMPLE
|
|
//-----------------------------------------------------------------------------
|
|
// Simple predictor:
|
|
// - backwards branches are predicted taken, others predicted not taken.
|
|
//-----------------------------------------------------------------------------
|
|
reg predict_taken;
|
|
|
|
always @(iOpcode or insn)
|
|
case(iOpcode)
|
|
`BTRR:
|
|
case(insn[4:0])
|
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BNR:
|
|
predict_taken = insn[24];
|
|
default: predict_taken = 1'd0;
|
|
endcase
|
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
|
predict_taken = insn[29];
|
|
default:
|
|
predict_taken = 1'd0;
|
|
endcase
|
|
`else
|
|
//-----------------------------------------------------------------------------
|
// Branch history table.
|
// Branch history table.
|
// The history table is updated by the EX stage and read in
|
// The history table is updated by the EX stage and read in
|
// both the EX and IF stages.
|
// both the EX and IF stages.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
reg [2:0] gbl_branch_hist;
|
reg [2:0] gbl_branch_hist;
|
Line 963... |
Line 1005... |
// In the real world we don't care.
|
// In the real world we don't care.
|
initial begin
|
initial begin
|
for (n = 0; n < 256; n = n + 1)
|
for (n = 0; n < 256; n = n + 1)
|
branch_history_table[n] = 0;
|
branch_history_table[n] = 0;
|
end
|
end
|
|
`endif
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Evaluate branch conditions.
|
// Evaluate branch conditions.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
wire signed [63:0] as = a;
|
wire signed [63:0] as = a;
|
Line 975... |
Line 1018... |
wire aeqz = a==64'd0;
|
wire aeqz = a==64'd0;
|
wire beqz = b==64'd0;
|
wire beqz = b==64'd0;
|
wire immeqz = imm==64'd0;
|
wire immeqz = imm==64'd0;
|
wire eq = a==b;
|
wire eq = a==b;
|
wire eqi = a==imm;
|
wire eqi = a==imm;
|
wire lt = as < bs;
|
wire lt = $signed(a) < $signed(b);
|
wire lti = as < imms;
|
wire lti = as < imms;
|
wire ltu = a < b;
|
wire ltu = a < b;
|
wire ltui = a < imm;
|
wire ltui = a < imm;
|
|
|
always @(xOpcode or xFunc or a or eq or eqi or lt or lti or ltu or ltui or aeqz or beqz or rsf or xIR)
|
always @(xOpcode or xFunc or a or eq or eqi or lt or lti or ltu or ltui or aeqz or beqz or rsf or xIR)
|
Line 1109... |
Line 1152... |
);
|
);
|
|
|
always @(xOpcode or xFunc or a or b or imm or as or bs or imms or xpc or
|
always @(xOpcode or xFunc or a or b or imm or as or bs or imms or xpc or
|
sqrt_out or cntlzo or cntloo or tick or ipc or tba or AXC or
|
sqrt_out or cntlzo or cntloo or tick or ipc or tba or AXC or
|
lt or eq or ltu or mult_out or lti or eqi or ltui or xIR or div_q or div_r or
|
lt or eq or ltu or mult_out or lti or eqi or ltui or xIR or div_q or div_r or
|
shfto or masko or bcdaddo or bcdsubo or fpLooOut or fpZLOut or
|
shfto or masko or bcdaddo or bcdsubo or fpLooOut or fpZLOut
|
Wired or Index or Random or TLBPhysPage0 or TLBPhysPage1 or TLBVirtPage or TLBASID or
|
`ifdef TLB
|
|
or Wired or Index or Random or TLBPhysPage0 or TLBPhysPage1 or TLBVirtPage or TLBASID or
|
PageTableAddr or BadVAddr or ASID or TLBPageMask
|
PageTableAddr or BadVAddr or ASID or TLBPageMask
|
|
`endif
|
)
|
)
|
casex(xOpcode)
|
casex(xOpcode)
|
`R:
|
`R:
|
casex(xFunc)
|
casex(xFunc)
|
`COM: xData = ~a;
|
`COM: xData = ~a;
|
Line 1146... |
Line 1191... |
`SEXT16: xData = {{48{a[15]}},a[15:0]};
|
`SEXT16: xData = {{48{a[15]}},a[15:0]};
|
`SEXT32: xData = {{32{a[31]}},a[31:0]};
|
`SEXT32: xData = {{32{a[31]}},a[31:0]};
|
|
|
`MFSPR:
|
`MFSPR:
|
case(xIR[12:7])
|
case(xIR[12:7])
|
|
`ifdef TLB
|
`Wired: xData = Wired;
|
`Wired: xData = Wired;
|
`TLBIndex: xData = Index;
|
`TLBIndex: xData = Index;
|
`TLBRandom: xData = Random;
|
`TLBRandom: xData = Random;
|
`TLBPhysPage0: xData = {TLBPhysPage0,13'd0};
|
`TLBPhysPage0: xData = {TLBPhysPage0,13'd0};
|
`TLBPhysPage1: xData = {TLBPhysPage1,13'd0};
|
`TLBPhysPage1: xData = {TLBPhysPage1,13'd0};
|
Line 1162... |
Line 1208... |
xData[2] = TLBG;
|
xData[2] = TLBG;
|
xData[15:8] = TLBASID;
|
xData[15:8] = TLBASID;
|
end
|
end
|
`PageTableAddr: xData = {PageTableAddr,13'd0};
|
`PageTableAddr: xData = {PageTableAddr,13'd0};
|
`BadVAddr: xData = {BadVAddr,13'd0};
|
`BadVAddr: xData = {BadVAddr,13'd0};
|
|
`endif
|
`ASID: xData = ASID;
|
`ASID: xData = ASID;
|
`Tick: xData = tick;
|
`Tick: xData = tick;
|
`EPC: xData = EPC;
|
`EPC: xData = EPC;
|
`CauseCode: xData = CauseCode;
|
`CauseCode: xData = CauseCode;
|
`TBA: xData = TBA;
|
`TBA: xData = TBA;
|
`AXC: xData = xAXC;
|
`AXC: xData = xAXC;
|
|
`NON_ICACHE_SEG: xData = nonICacheSeg;
|
default: xData = 65'd0;
|
default: xData = 65'd0;
|
endcase
|
endcase
|
`OMG: xData = mutex_gate[a[5:0]];
|
`OMG: xData = mutex_gate[a[5:0]];
|
`CMG: xData = mutex_gate[a[5:0]];
|
`CMG: xData = mutex_gate[a[5:0]];
|
`OMGI: begin
|
`OMGI: begin
|
Line 1293... |
Line 1341... |
wire v_ri,v_rr;
|
wire v_ri,v_rr;
|
overflow u2 (.op(xOpcode==`SUBI), .a(a[63]), .b(imm[63]), .s(xData[63]), .v(v_ri));
|
overflow u2 (.op(xOpcode==`SUBI), .a(a[63]), .b(imm[63]), .s(xData[63]), .v(v_ri));
|
overflow u3 (.op(xOpcode==`RR && xFunc==`SUB), .a(a[63]), .b(b[63]), .s(xData[63]), .v(v_rr));
|
overflow u3 (.op(xOpcode==`RR && xFunc==`SUB), .a(a[63]), .b(b[63]), .s(xData[63]), .v(v_rr));
|
|
|
wire dbz_error = (xOpcode==`DIVSI||xOpcode==`DIVUI) && b==64'd0;
|
wire dbz_error = (xOpcode==`DIVSI||xOpcode==`DIVUI) && b==64'd0;
|
wire ovr_error = ((xOpcode==`ADDI || xOpcode==`SUBI) || (xOpcode==`RR && (xFunc==`SUB || xFunc==`ADD))) && v_ri;
|
wire ovr_error = ((xOpcode==`ADDI || xOpcode==`SUBI) && v_ri) || ((xOpcode==`RR && (xFunc==`SUB || xFunc==`ADD)) && v_rr);
|
wire priv_violation = !KernelMode && (xOpcode==`MISC &&
|
wire priv_violation = !KernelMode && (xOpcode==`MISC &&
|
(xFunc==`IRET || xFunc==`ERET || xFunc==`CLI || xFunc==`SEI ||
|
(xFunc==`IRET || xFunc==`ERET || xFunc==`CLI || xFunc==`SEI ||
|
xFunc==`TLBP || xFunc==`TLBR || xFunc==`TLBWR || xFunc==`TLBWI
|
xFunc==`TLBP || xFunc==`TLBR || xFunc==`TLBWR || xFunc==`TLBWI
|
));
|
));
|
wire xIsSqrt = xOpcode==`R && xFunc==`SQRT;
|
wire xIsSqrt = xOpcode==`R && xFunc==`SQRT;
|
Line 1344... |
Line 1392... |
;
|
;
|
wire m1IsIO =
|
wire m1IsIO =
|
m1IsIn ||
|
m1IsIn ||
|
m1Opcode==`OUTW || m1Opcode==`OUTH || m1Opcode==`OUTC || m1Opcode==`OUTB
|
m1Opcode==`OUTW || m1Opcode==`OUTH || m1Opcode==`OUTC || m1Opcode==`OUTB
|
;
|
;
|
|
|
wire m2IsLoad =
|
wire m2IsLoad =
|
m2Opcode==`LW || m2Opcode==`LH || m2Opcode==`LB || m2Opcode==`LC || m2Opcode==`LWR ||
|
m2Opcode==`LW || m2Opcode==`LH || m2Opcode==`LB || m2Opcode==`LC || m2Opcode==`LWR ||
|
m2Opcode==`LHU || m2Opcode==`LBU || m2Opcode==`LCU
|
m2Opcode==`LHU || m2Opcode==`LBU || m2Opcode==`LCU
|
;
|
;
|
wire m2IsStore =
|
wire m2IsStore =
|
m2Opcode==`SW || m2Opcode==`SWC || m2Opcode==`SH || m2Opcode==`SC || m2Opcode==`SB;
|
m2Opcode==`SW || m2Opcode==`SWC || m2Opcode==`SH || m2Opcode==`SC || m2Opcode==`SB;
|
|
|
wire xIsFPLoo = xOpcode==`FPLOO;
|
wire xIsFPLoo = xOpcode==`FPLOO;
|
|
|
wire xneedBus = xIsIO;
|
wire xneedBus = xIsIO;
|
wire m1needBus = ((m1IsLoad & !dhit)| m1IsStore) || m1IsIO;
|
wire m1needBus = (m1IsLoad & !m1IsCacheElement) || m1IsStore || m1IsIO;
|
wire m2needBus = (m2IsLoad | m2IsStore);
|
wire m2needBus = (m2IsLoad | m2IsStore);
|
|
|
// Stall on SWC allows rsf flag to be loaded for the next instruction
|
// Stall on SWC allows rsf flag to be loaded for the next instruction
|
// Currently stalls on load of R0, but doesn't need to.
|
// Currently stalls on load of R0, but doesn't need to.
|
wire StallR = (((xIsLoad||xIsIn) && ((xRt==dRa)||(xRt==dRb)||(xRt==dRt))) || xIsSWC) ||
|
wire StallR = (((xIsLoad||xIsIn) && ((xRt==dRa)||(xRt==dRb)||(xRt==dRt))) || xIsSWC) ||
|
(((m1IsLoad||m1IsIn) && ((m1Rt==dRa)||(m1Rt==dRb)||(m1Rt==dRt)))) ||
|
(((m1IsLoad||m1IsIn) && ((m1Rt==dRa)||(m1Rt==dRb)||(m1Rt==dRt)))) ||
|
(((m2IsLoad||m2IsInW) && ((m2Rt==dRa)||(m2Rt==dRb)||(m2Rt==dRt))))
|
(((m2IsLoad) && ((m2Rt==dRa)||(m2Rt==dRb)||(m2Rt==dRt))))
|
;
|
;
|
wire StallX = xneedBus & (m1needBus|m2needBus|icaccess|dcaccess);
|
wire StallX = xneedBus & (m1needBus|m2needBus|icaccess|dcaccess);
|
wire StallM1 = m1needBus & (m2needBus|icaccess|dcaccess);
|
wire StallM1 = m1needBus & (m2needBus|icaccess|dcaccess);
|
wire StallM2 = icaccess|dcaccess;
|
wire StallM2 = icaccess|dcaccess;
|
|
|
Line 1387... |
Line 1434... |
xIsDiv ? div_done :
|
xIsDiv ? div_done :
|
xIsFPLoo ? fpLooDone :
|
xIsFPLoo ? fpLooDone :
|
1'b1) &
|
1'b1) &
|
!StallX;
|
!StallX;
|
wire advanceR = advanceX & !StallR;
|
wire advanceR = advanceX & !StallR;
|
wire advanceI = advanceR & ihit;
|
wire advanceI = advanceR & (ICacheOn ? ihit : ibufrdy);
|
|
|
wire triggerDCacheLoad = (m1IsLoad & m1IsCacheElement & !dhit) && // there is a miss
|
wire triggerDCacheLoad = (m1IsLoad & m1IsCacheElement & !dhit) && // there is a miss
|
!(icaccess | dcaccess) && // caches are not active
|
!(icaccess | dcaccess) && // caches are not active
|
m2Opcode==`NOPI // and the pipeline is free of memory-ops
|
m2Opcode==`NOPI // and the pipeline is free of memory-ops
|
;
|
;
|
// Since IMM is "sticky" we have to check for it.
|
// Since IMM is "sticky" we have to check for it.
|
wire triggerICacheLoad = !ihit & !triggerDCacheLoad & // There is a miss
|
wire triggerICacheLoad = (ICacheAct ? !ihit : !ibufrdy) && !triggerDCacheLoad && // There is a miss
|
|
!(icaccess | dcaccess) && // caches are not active
|
(dOpcode==`NOPI || dOpcode[6:4]==`IMM) && // and the pipeline is flushed
|
(dOpcode==`NOPI || dOpcode[6:4]==`IMM) && // and the pipeline is flushed
|
(xOpcode==`NOPI || xOpcode[6:4]==`IMM) &&
|
(xOpcode==`NOPI || xOpcode[6:4]==`IMM) &&
|
m1Opcode==`NOPI &&
|
m1Opcode==`NOPI &&
|
m2Opcode==`NOPI
|
m2Opcode==`NOPI
|
;
|
;
|
wire EXexception_pending = ovr_error || dbz_error || priv_violation || xOpcode==`TRAPcci || xOpcode==`TRAPcc;
|
wire EXexception_pending = ovr_error || dbz_error || priv_violation || xOpcode==`TRAPcci || xOpcode==`TRAPcc;
|
|
`ifdef TLB
|
wire M1exception_pending = advanceM1 & (m1IsLoad|m1IsStore) & DTLBMiss;
|
wire M1exception_pending = advanceM1 & (m1IsLoad|m1IsStore) & DTLBMiss;
|
|
`else
|
|
wire M1exception_pending = 1'b0;
|
|
`endif
|
wire exception_pending = EXexception_pending | M1exception_pending;
|
wire exception_pending = EXexception_pending | M1exception_pending;
|
|
|
wire xWillLoadStore = (xIsLoad||xIsStore) & advanceX;
|
wire xWillLoadStore = (xIsLoad||xIsStore) & advanceX;
|
wire stallCacheLoad = xWillLoadStore;
|
wire stallCacheLoad = xWillLoadStore;
|
|
|
Line 1459... |
Line 1511... |
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
adr_o <= 64'd0;
|
adr_o <= 64'd0;
|
dat_o <= 64'd0;
|
dat_o <= 64'd0;
|
dccyc <= 1'b0;
|
dccyc <= 1'b0;
|
|
|
|
nonICacheSeg <= 32'hFFFF_FFFD;
|
TBA <= 64'd0;
|
TBA <= 64'd0;
|
pc <= `RESET_VECTOR;
|
pc <= `RESET_VECTOR;
|
m1Opcode <= `NOPI;
|
m1Opcode <= `NOPI;
|
m2Opcode <= `NOPI;
|
m2Opcode <= `NOPI;
|
m3Opcode <= `NOPI;
|
|
m4Opcode <= `NOPI;
|
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
dRt <= 9'd0;
|
dRt <= 9'd0;
|
tRt <= 9'd0;
|
tRt <= 9'd0;
|
wRt <= 9'd0;
|
wRt <= 9'd0;
|
m1Rt <= 9'd0;
|
m1Rt <= 9'd0;
|
m2Rt <= 9'd0;
|
m2Rt <= 9'd0;
|
m3Rt <= 9'd0;
|
|
m4Rt <= 9'd0;
|
|
tData <= 64'd0;
|
tData <= 64'd0;
|
wData <= 64'd0;
|
wData <= 64'd0;
|
m1Data <= 64'd0;
|
m1Data <= 64'd0;
|
m2Data <= 64'd0;
|
m2Data <= 64'd0;
|
m3Data <= 64'd0;
|
|
m4Data <= 64'd0;
|
|
icaccess <= 1'b0;
|
icaccess <= 1'b0;
|
dcaccess <= 1'b0;
|
dcaccess <= 1'b0;
|
nopI <= 1'b0;
|
nopI <= 1'b0;
|
prev_ihit <= 1'b0;
|
prev_ihit <= 1'b0;
|
dhwxtype <= 2'b00;
|
dhwxtype <= 2'b00;
|
xhwxtype <= 2'b00;
|
xhwxtype <= 2'b00;
|
m1hwxtype <= 2'b00;
|
m1hwxtype <= 2'b00;
|
m2hwxtype <= 2'b00;
|
m2hwxtype <= 2'b00;
|
m3hwxtype <= 2'b00;
|
|
m4hwxtype <= 2'b00;
|
|
whwxtype <= 2'b00;
|
whwxtype <= 2'b00;
|
wFip <= 1'b0;
|
wFip <= 1'b0;
|
m4Fip <= 1'b0;
|
|
m3Fip <= 1'b0;
|
|
m2Fip <= 1'b0;
|
m2Fip <= 1'b0;
|
m1Fip <= 1'b0;
|
m1Fip <= 1'b0;
|
xFip <= 1'b0;
|
xFip <= 1'b0;
|
dFip <= 1'b0;
|
dFip <= 1'b0;
|
dirqf <= 1'b0;
|
dirqf <= 1'b0;
|
Line 1517... |
Line 1560... |
a <= 64'd0;
|
a <= 64'd0;
|
b <= 64'd0;
|
b <= 64'd0;
|
imm <= 64'd0;
|
imm <= 64'd0;
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
clk_en <= 1'b1;
|
clk_en <= 1'b1;
|
|
`ifdef TLB
|
Random <= 4'hF;
|
Random <= 4'hF;
|
Wired <= 4'd0;
|
Wired <= 4'd0;
|
|
`endif
|
StatusEXL <= 1'b1;
|
StatusEXL <= 1'b1;
|
StatusHWI <= 1'b0;
|
StatusHWI <= 1'b0;
|
resetA <= 1'b1;
|
resetA <= 1'b1;
|
mutex_gate <= 64'h0;
|
mutex_gate <= 64'h0;
|
|
`ifndef BRANCH_PREDICTION_SIMPLE
|
gbl_branch_hist <= 3'b000;
|
gbl_branch_hist <= 3'b000;
|
|
`endif
|
|
ICacheOn <= 1'b0;
|
|
ibuftag <= 64'h0;
|
m1IsCacheElement <= 1'b0;
|
m1IsCacheElement <= 1'b0;
|
dtinit <= 1'b1;
|
dtinit <= 1'b1;
|
|
`ifdef RAS_PREDICTION
|
|
ras_sp <= 6'd63;
|
|
`endif
|
end
|
end
|
else begin
|
else begin
|
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// Initialize program counters
|
// Initialize program counters
|
Line 1542... |
Line 1594... |
dtinit <= 1'b0;
|
dtinit <= 1'b0;
|
resetA <= 1'b0;
|
resetA <= 1'b0;
|
end
|
end
|
end
|
end
|
|
|
|
`ifdef TLB
|
if (Random==Wired)
|
if (Random==Wired)
|
Random <= 4'hF;
|
Random <= 3'd7;
|
else
|
else
|
Random <= Random - 4'd1;
|
Random <= Random - 3'd1;
|
|
`endif
|
|
|
tick <= tick + 64'd1;
|
tick <= tick + 64'd1;
|
|
|
prev_nmi <= nmi_i;
|
prev_nmi <= nmi_i;
|
if (!prev_nmi & nmi_i)
|
if (!prev_nmi & nmi_i)
|
Line 1590... |
Line 1644... |
if (|whwxtype) begin
|
if (|whwxtype) begin
|
dhwxtype <= 2'b00;
|
dhwxtype <= 2'b00;
|
xhwxtype <= 2'b00;
|
xhwxtype <= 2'b00;
|
m1hwxtype <= 2'b00;
|
m1hwxtype <= 2'b00;
|
m2hwxtype <= 2'b00;
|
m2hwxtype <= 2'b00;
|
m3hwxtype <= 2'b00;
|
|
m4hwxtype <= 2'b00;
|
|
whwxtype <= 2'b00;
|
whwxtype <= 2'b00;
|
end
|
end
|
clk_en <= 1'b1;
|
clk_en <= 1'b1;
|
if (wclkoff)
|
if (wclkoff)
|
clk_en <= 1'b0;
|
clk_en <= 1'b0;
|
wclkoff <= 1'b0;
|
wclkoff <= 1'b0;
|
m1clkoff <= 1'b0;
|
m1clkoff <= 1'b0;
|
m2clkoff <= 1'b0;
|
m2clkoff <= 1'b0;
|
m3clkoff <= 1'b0;
|
|
m4clkoff <= 1'b0;
|
|
if (wFip) begin
|
if (wFip) begin
|
wFip <= 1'b0;
|
wFip <= 1'b0;
|
m4Fip <= 1'b0;
|
|
m3Fip <= 1'b0;
|
|
m2Fip <= 1'b0;
|
m2Fip <= 1'b0;
|
m1Fip <= 1'b0;
|
m1Fip <= 1'b0;
|
xFip <= 1'b0;
|
xFip <= 1'b0;
|
dFip <= 1'b0;
|
dFip <= 1'b0;
|
end
|
end
|
Line 1642... |
Line 1690... |
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
we_o <= 1'b0;
|
we_o <= 1'b0;
|
sel_o <= 4'h0;
|
sel_o <= 4'h0;
|
m3Opcode <= `NOPI;
|
|
end
|
end
|
`LH:
|
`LH:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
m3Data <= sel_o[7] ? {{32{dat_i[63]}},dat_i[63:32]}:{{32{dat_i[31]}},dat_i[31: 0]};
|
wData <= sel_o[7] ? {{32{dat_i[63]}},dat_i[63:32]}:{{32{dat_i[31]}},dat_i[31: 0]};
|
m3Opcode <= `NOPI;
|
|
end
|
end
|
`LW,`LWR:
|
`LW,`LWR:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
m3Data <= dat_i;
|
wData <= dat_i;
|
m3Opcode <= `NOPI;
|
|
end
|
end
|
`LHU:
|
`LHU:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
m3Data <= sel_o[7] ? dat_i[63:32] : dat_i[31: 0];
|
wData <= sel_o[7] ? dat_i[63:32] : dat_i[31: 0];
|
m3Opcode <= `NOPI;
|
|
end
|
end
|
`LC:
|
`LC:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
case(sel_o)
|
case(sel_o)
|
8'b00000011: m3Data <= {{48{dat_i[15]}},dat_i[15: 0]};
|
8'b00000011: wData <= {{48{dat_i[15]}},dat_i[15: 0]};
|
8'b00001100: m3Data <= {{48{dat_i[31]}},dat_i[31:16]};
|
8'b00001100: wData <= {{48{dat_i[31]}},dat_i[31:16]};
|
8'b00110000: m3Data <= {{48{dat_i[47]}},dat_i[47:32]};
|
8'b00110000: wData <= {{48{dat_i[47]}},dat_i[47:32]};
|
8'b11000000: m3Data <= {{48{dat_i[63]}},dat_i[63:48]};
|
8'b11000000: wData <= {{48{dat_i[63]}},dat_i[63:48]};
|
default: m3Data <= 64'hDEADDEADDEADDEAD;
|
default: wData <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
m3Opcode <= `NOPI;
|
|
end
|
end
|
`LCU:
|
`LCU:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
case(sel_o)
|
case(sel_o)
|
8'b00000011: m3Data <= dat_i[15: 0];
|
8'b00000011: wData <= dat_i[15: 0];
|
8'b00001100: m3Data <= dat_i[31:16];
|
8'b00001100: wData <= dat_i[31:16];
|
8'b00110000: m3Data <= dat_i[47:32];
|
8'b00110000: wData <= dat_i[47:32];
|
8'b11000000: m3Data <= dat_i[63:48];
|
8'b11000000: wData <= dat_i[63:48];
|
default: m3Data <= 64'hDEADDEADDEADDEAD;
|
default: wData <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
m3Opcode <= `NOPI;
|
|
end
|
end
|
`LB:
|
`LB:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
case(sel_o)
|
case(sel_o)
|
8'b00000001: m3Data <= {{56{dat_i[ 7]}},dat_i[ 7: 0]};
|
8'b00000001: wData <= {{56{dat_i[ 7]}},dat_i[ 7: 0]};
|
8'b00000010: m3Data <= {{56{dat_i[15]}},dat_i[15: 8]};
|
8'b00000010: wData <= {{56{dat_i[15]}},dat_i[15: 8]};
|
8'b00000100: m3Data <= {{56{dat_i[23]}},dat_i[23:16]};
|
8'b00000100: wData <= {{56{dat_i[23]}},dat_i[23:16]};
|
8'b00001000: m3Data <= {{56{dat_i[31]}},dat_i[31:24]};
|
8'b00001000: wData <= {{56{dat_i[31]}},dat_i[31:24]};
|
8'b00010000: m3Data <= {{56{dat_i[39]}},dat_i[39:32]};
|
8'b00010000: wData <= {{56{dat_i[39]}},dat_i[39:32]};
|
8'b00100000: m3Data <= {{56{dat_i[47]}},dat_i[47:40]};
|
8'b00100000: wData <= {{56{dat_i[47]}},dat_i[47:40]};
|
8'b01000000: m3Data <= {{56{dat_i[55]}},dat_i[55:48]};
|
8'b01000000: wData <= {{56{dat_i[55]}},dat_i[55:48]};
|
8'b10000000: m3Data <= {{56{dat_i[63]}},dat_i[63:56]};
|
8'b10000000: wData <= {{56{dat_i[63]}},dat_i[63:56]};
|
default: m3Data <= 64'hDEADDEADDEADDEAD;
|
default: wData <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
m3Opcode = `NOPI;
|
|
end
|
end
|
`LBU:
|
`LBU:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
case(sel_o)
|
case(sel_o)
|
8'b00000001: m3Data <= dat_i[ 7: 0];
|
8'b00000001: wData <= dat_i[ 7: 0];
|
8'b00000010: m3Data <= dat_i[15: 8];
|
8'b00000010: wData <= dat_i[15: 8];
|
8'b00000100: m3Data <= dat_i[23:16];
|
8'b00000100: wData <= dat_i[23:16];
|
8'b00001000: m3Data <= dat_i[31:24];
|
8'b00001000: wData <= dat_i[31:24];
|
8'b00010000: m3Data <= dat_i[39:32];
|
8'b00010000: wData <= dat_i[39:32];
|
8'b00100000: m3Data <= dat_i[47:40];
|
8'b00100000: wData <= dat_i[47:40];
|
8'b01000000: m3Data <= dat_i[55:48];
|
8'b01000000: wData <= dat_i[55:48];
|
8'b10000000: m3Data <= dat_i[63:56];
|
8'b10000000: wData <= dat_i[63:56];
|
default: m3Data <= 64'hDEADDEADDEADDEAD;
|
default: wData <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
m3Opcode <= `NOPI;
|
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
Line 1774... |
Line 1814... |
|
|
if (m1extype == `EX_NON) begin
|
if (m1extype == `EX_NON) begin
|
case(m1Opcode)
|
case(m1Opcode)
|
`MISC:
|
`MISC:
|
case(m1Func)
|
case(m1Func)
|
|
`ifdef TLB
|
`TLBP:
|
`TLBP:
|
begin
|
begin
|
Index[63] <= ~|DMatch;
|
Index[63] <= ~|DMatch;
|
end
|
end
|
`TLBR:
|
`TLBR:
|
Line 1800... |
Line 1841... |
ITLBPageMask[i] <= TLBPageMask;
|
ITLBPageMask[i] <= TLBPageMask;
|
ITLBASID[i] <= TLBASID;
|
ITLBASID[i] <= TLBASID;
|
ITLBD[i] <= TLBD;
|
ITLBD[i] <= TLBD;
|
ITLBG[i] <= TLBG;
|
ITLBG[i] <= TLBG;
|
end
|
end
|
|
`endif
|
endcase
|
endcase
|
`INW:
|
`INW:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
Line 2073... |
Line 2115... |
|
|
`SW:
|
`SW:
|
begin
|
begin
|
m2Addr <= {pea[63:3],3'b000};
|
m2Addr <= {pea[63:3],3'b000};
|
wrhit <= dhit;
|
wrhit <= dhit;
|
if (!m1UnmappedDataArea & !q[4])
|
`ifdef TLB
|
ITLBD[q] <= 1'b1;
|
if (!m1UnmappedDataArea & !q[3])
|
|
ITLBD[{q[2:0],pea[15:13]}] <= 1'b1;
|
|
`endif
|
if (resv_address==pea[63:5])
|
if (resv_address==pea[63:5])
|
resv_address <= 59'd0;
|
resv_address <= 59'd0;
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= 8'hFF;
|
sel_o <= 8'hFF;
|
adr_o <= {pea[63:3],3'b000};
|
adr_o <= {pea[63:3],3'b000};
|
dat_o <= m1b;
|
dat_o <= m1Data;
|
end
|
end
|
|
|
`SH:
|
`SH:
|
begin
|
begin
|
wrhit <= dhit;
|
wrhit <= dhit;
|
m2Addr <= {pea[63:2],2'b00};
|
m2Addr <= {pea[63:2],2'b00};
|
if (!m1UnmappedDataArea & !q[4])
|
`ifdef TLB
|
ITLBD[q] <= 1'b1;
|
if (!m1UnmappedDataArea & !q[3])
|
|
ITLBD[{q[2:0],pea[15:13]}] <= 1'b1;
|
|
`endif
|
if (resv_address==pea[63:5])
|
if (resv_address==pea[63:5])
|
resv_address <= 59'd0;
|
resv_address <= 59'd0;
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= pea[2] ? 8'b11110000 : 8'b00001111;
|
sel_o <= pea[2] ? 8'b11110000 : 8'b00001111;
|
adr_o <= {pea[63:2],2'b00};
|
adr_o <= {pea[63:2],2'b00};
|
dat_o <= {2{m1b[31:0]}};
|
dat_o <= {2{m1Data[31:0]}};
|
end
|
end
|
|
|
`SC:
|
`SC:
|
begin
|
begin
|
$display("Storing char to %h, ea=%h",pea,ea);
|
$display("Storing char to %h, ea=%h",pea,ea);
|
wrhit <= dhit;
|
wrhit <= dhit;
|
m2Addr <= {pea[63:2],2'b00};
|
m2Addr <= {pea[63:2],2'b00};
|
if (!m1UnmappedDataArea & !q[4])
|
`ifdef TLB
|
ITLBD[q] <= 1'b1;
|
if (!m1UnmappedDataArea & !q[3])
|
|
ITLBD[{q[2:0],pea[15:13]}] <= 1'b1;
|
|
`endif
|
if (resv_address==pea[63:5])
|
if (resv_address==pea[63:5])
|
resv_address <= 59'd0;
|
resv_address <= 59'd0;
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
Line 2120... |
Line 2168... |
2'b01: sel_o <= 8'b00001100;
|
2'b01: sel_o <= 8'b00001100;
|
2'b10: sel_o <= 8'b00110000;
|
2'b10: sel_o <= 8'b00110000;
|
2'b11: sel_o <= 8'b11000000;
|
2'b11: sel_o <= 8'b11000000;
|
endcase
|
endcase
|
adr_o <= {pea[63:1],1'b0};
|
adr_o <= {pea[63:1],1'b0};
|
dat_o <= {4{m1b[15:0]}};
|
dat_o <= {4{m1Data[15:0]}};
|
end
|
end
|
|
|
`SB:
|
`SB:
|
begin
|
begin
|
wrhit <= dhit;
|
wrhit <= dhit;
|
m2Addr <= {pea[63:2],2'b00};
|
m2Addr <= {pea[63:2],2'b00};
|
if (resv_address==pea[63:5])
|
if (resv_address==pea[63:5])
|
resv_address <= 59'd0;
|
resv_address <= 59'd0;
|
if (!m1UnmappedDataArea & !q[4])
|
`ifdef TLB
|
ITLBD[q] <= 1'b1;
|
if (!m1UnmappedDataArea & !q[3])
|
|
ITLBD[{q[2:0],pea[15:13]}] <= 1'b1;
|
|
`endif
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
case(pea[2:0])
|
case(pea[2:0])
|
3'b000: sel_o <= 8'b00000001;
|
3'b000: sel_o <= 8'b00000001;
|
Line 2145... |
Line 2195... |
3'b101: sel_o <= 8'b00100000;
|
3'b101: sel_o <= 8'b00100000;
|
3'b110: sel_o <= 8'b01000000;
|
3'b110: sel_o <= 8'b01000000;
|
3'b111: sel_o <= 8'b10000000;
|
3'b111: sel_o <= 8'b10000000;
|
endcase
|
endcase
|
adr_o <= {pea[63:2],2'b00};
|
adr_o <= {pea[63:2],2'b00};
|
dat_o <= {8{m1b[7:0]}};
|
dat_o <= {8{m1Data[7:0]}};
|
end
|
end
|
|
|
`SWC:
|
`SWC:
|
begin
|
begin
|
rsf <= 1'b0;
|
rsf <= 1'b0;
|
if (resv_address==pea[63:5]) begin
|
if (resv_address==pea[63:5]) begin
|
if (!m1UnmappedDataArea & !q[4])
|
`ifdef TLB
|
ITLBD[q] <= 1'b1;
|
if (!m1UnmappedDataArea & !q[3])
|
|
ITLBD[{q[2:0],pea[15:13]}] <= 1'b1;
|
|
`endif
|
wrhit <= dhit;
|
wrhit <= dhit;
|
m2Addr <= {pea[63:3],3'b00};
|
m2Addr <= {pea[63:3],3'b00};
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= 8'hFF;
|
sel_o <= 8'hFF;
|
adr_o <= {pea[63:3],3'b000};
|
adr_o <= {pea[63:3],3'b000};
|
dat_o <= m1b;
|
dat_o <= m1Data;
|
resv_address <= 59'd0;
|
resv_address <= 59'd0;
|
rsf <= 1'b1;
|
rsf <= 1'b1;
|
end
|
end
|
else
|
else
|
m2Opcode <= `NOPI;
|
m2Opcode <= `NOPI;
|
Line 2209... |
Line 2261... |
// xpc <= 64'd0;
|
// xpc <= 64'd0;
|
case(xOpcode)
|
case(xOpcode)
|
`MISC:
|
`MISC:
|
case(xFunc)
|
case(xFunc)
|
`WAIT: m1clkoff <= 1'b1;
|
`WAIT: m1clkoff <= 1'b1;
|
|
`ICACHE_ON: ICacheOn <= 1'b1;
|
|
`ICACHE_OFF: ICacheOn <= 1'b0;
|
|
`ifdef TLB
|
`TLBP: ea <= TLBVirtPage;
|
`TLBP: ea <= TLBVirtPage;
|
`TLBR,`TLBWI:
|
`TLBR,`TLBWI:
|
begin
|
begin
|
i <= Index;
|
i <= {Index[2:0],TLBVirtPage[15:13]};
|
end
|
end
|
`TLBWR:
|
`TLBWR:
|
begin
|
begin
|
i <= Random;
|
i <= {Random,TLBVirtPage[15:13]};
|
end
|
end
|
|
`endif
|
default: ;
|
default: ;
|
endcase
|
endcase
|
`R:
|
`R:
|
case(xFunc)
|
case(xFunc)
|
`MTSPR:
|
`MTSPR:
|
case(xIR[12:7])
|
case(xIR[12:7])
|
`Wired: Wired <= xData[3:0];
|
`ifdef TLB
|
`ASID: ASID <= xData[7:0];
|
`Wired: Wired <= a[2:0];
|
`TLBIndex: Index <= xData[3:0];
|
`TLBIndex: Index <= a[2:0];
|
`TLBVirtPage: TLBVirtPage <= xData[63:13];
|
`TLBVirtPage: TLBVirtPage <= a[63:13];
|
`TLBPhysPage0: TLBPhysPage0 <= xData[63:13];
|
`TLBPhysPage0: TLBPhysPage0 <= a[63:13];
|
`TLBPhysPage1: TLBPhysPage1 <= xData[63:13];
|
`TLBPhysPage1: TLBPhysPage1 <= a[63:13];
|
`TLBPageMask: TLBPageMask <= xData[24:13];
|
`TLBPageMask: TLBPageMask <= a[24:13];
|
`TLBASID: begin
|
`TLBASID: begin
|
TLBValid <= xData[0];
|
TLBValid <= a[0];
|
TLBD <= xData[1];
|
TLBD <= a[1];
|
TLBG <= xData[2];
|
TLBG <= a[2];
|
TLBASID <= xData[15:8];
|
TLBASID <= a[15:8];
|
end
|
end
|
`PageTableAddr: PageTableAddr <= xData[63:13];
|
`PageTableAddr: PageTableAddr <= a[63:13];
|
`BadVAddr: BadVAddr <= xData[63:13];
|
`BadVAddr: BadVAddr <= a[63:13];
|
`EPC: EPC <= xData;
|
`endif
|
`TBA: TBA <= xData;
|
`ASID: ASID <= a[7:0];
|
`AXC: AXC <= xData[3:0];
|
`EPC: EPC <= a;
|
|
`TBA: TBA <= {a[63:12],12'h000};
|
|
`AXC: AXC <= a[3:0];
|
|
`NON_ICACHE_SEG: nonICacheSeg <= a[63:32];
|
default: ;
|
default: ;
|
endcase
|
endcase
|
`MTTBA: tba <= {xData[63:2],2'b00};
|
|
`OMG: mutex_gate[a[5:0]] <= 1'b1;
|
`OMG: mutex_gate[a[5:0]] <= 1'b1;
|
`CMG: mutex_gate[a[5:0]] <= 1'b0;
|
`CMG: mutex_gate[a[5:0]] <= 1'b0;
|
`OMGI: mutex_gate[xIR[12:7]] <= 1'b1;
|
`OMGI: mutex_gate[xIR[12:7]] <= 1'b1;
|
`CMGI: mutex_gate[xIR[12:7]] <= 1'b0;
|
`CMGI: mutex_gate[xIR[12:7]] <= 1'b0;
|
default: ;
|
default: ;
|
Line 2346... |
Line 2404... |
adr_o <= xData;
|
adr_o <= xData;
|
dat_o <= {8{b[7:0]}};
|
dat_o <= {8{b[7:0]}};
|
end
|
end
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWR,`SW,`SH,`SC,`SB,`SWC:
|
`LB,`LBU,`LC,`LCU,`LH,`LHU,`LW,`LWR,`SW,`SH,`SC,`SB,`SWC:
|
begin
|
begin
|
m1b <= b;
|
m1Data <= b;
|
ea <= xData;
|
ea <= xData;
|
end
|
end
|
`MEMNDX:
|
`MEMNDX:
|
begin
|
begin
|
m1Opcode <= xFunc;
|
m1Opcode <= xFunc;
|
m1b <= c;
|
m1Data <= c;
|
ea <= xData;
|
ea <= xData;
|
end
|
end
|
`DIVSI,`DIVUI:
|
`DIVSI,`DIVUI:
|
if (b==64'd0) begin
|
if (b==64'd0) begin
|
xextype <= `EX_DBZ;
|
xextype <= `EX_DBZ;
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
|
`ifndef BRANCH_PREDICTION_SIMPLE
|
// Update the branch history
|
// Update the branch history
|
if (isxBranch) begin
|
if (isxBranch) begin
|
gbl_branch_hist <= {gbl_branch_hist,takb};
|
gbl_branch_hist <= {gbl_branch_hist,takb};
|
branch_history_table[bht_wa] <= xbits_new;
|
branch_history_table[bht_wa] <= xbits_new;
|
end
|
end
|
|
`endif
|
end
|
end
|
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// RFETCH:
|
// RFETCH:
|
// Register fetch stage
|
// Register fetch stage
|
Line 2509... |
Line 2569... |
// Are we filling the pipeline with NOP's as a result of a previous
|
// Are we filling the pipeline with NOP's as a result of a previous
|
// hardware interrupt ?
|
// hardware interrupt ?
|
else if (|dhwxtype|dFip) begin
|
else if (|dhwxtype|dFip) begin
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
end
|
end
|
|
`ifdef TLB
|
else if (ITLBMiss)
|
else if (ITLBMiss)
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
|
`endif
|
else begin
|
else begin
|
dIR <= insn;
|
dIR <= insn;
|
`include "insn_dumpsc.v"
|
`include "insn_dumpsc.v"
|
end
|
end
|
nopI <= 1'b0;
|
nopI <= 1'b0;
|
Line 2527... |
Line 2589... |
`SETHI: dRa <= {AXC,insn[36:32]};
|
`SETHI: dRa <= {AXC,insn[36:32]};
|
default: dRa <= {AXC,insn[34:30]};
|
default: dRa <= {AXC,insn[34:30]};
|
endcase
|
endcase
|
dRb <= {AXC,insn[29:25]};
|
dRb <= {AXC,insn[29:25]};
|
dRc <= {AXC,insn[24:20]};
|
dRc <= {AXC,insn[24:20]};
|
|
`ifdef TLB
|
if (ITLBMiss) begin
|
if (ITLBMiss) begin
|
$display("TLB miss on instruction fetch.");
|
$display("TLB miss on instruction fetch.");
|
CauseCode <= `EX_TLBI;
|
CauseCode <= `EX_TLBI;
|
StatusEXL <= 1'b1;
|
StatusEXL <= 1'b1;
|
BadVAddr <= pc[63:13];
|
BadVAddr <= pc[63:13];
|
pc <= `ITLB_MissHandler;
|
pc <= `ITLB_MissHandler;
|
EPC <= pc;
|
EPC <= pc;
|
end
|
end
|
else begin
|
else
|
|
`endif
|
|
begin
|
dbranch_taken <= 1'b0;
|
dbranch_taken <= 1'b0;
|
pc <= fnIncPC(pc);
|
pc <= fnIncPC(pc);
|
case(iOpcode)
|
case(iOpcode)
|
`MISC:
|
`MISC:
|
case(iFunc)
|
case(iFunc)
|
`FIP: dFip <= 1'b1;
|
`FIP: dFip <= 1'b1;
|
default: ;
|
default: ;
|
endcase
|
endcase
|
`JMP,`CALL:
|
// We predict the return address by storing it in a return address stack
|
|
// during a call instruction, then popping it off the stack in a return
|
|
// instruction. The prediction will not always be correct, if it's wrong
|
|
// it's corrected by the EX stage branching to the right address.
|
|
`CALL:
|
|
begin
|
|
`ifdef RAS_PREDICTION
|
|
ras[ras_sp] <= fnIncPC(pc);
|
|
ras_sp <= ras_sp - 6'd1;
|
|
`endif
|
|
dbranch_taken <= 1'b1;
|
|
pc <= jmp_tgt;
|
|
end
|
|
`RET:
|
|
begin
|
|
`ifdef RAS_PREDICTION
|
|
// $display("predicted return address=%h.%h",{ras[ras_sp + 6'd1][63:4],4'b0000},ras[ras_sp + 6'd1][3:2]);
|
|
pc <= ras[ras_sp + 6'd1];
|
|
ras_sp <= ras_sp + 6'd1;
|
|
`endif
|
|
end
|
|
`JMP:
|
begin
|
begin
|
dbranch_taken <= 1'b1;
|
dbranch_taken <= 1'b1;
|
pc <= jmp_tgt;
|
pc <= jmp_tgt;
|
end
|
end
|
`BTRR:
|
`BTRR:
|
case(insn[4:0])
|
case(insn[4:0])
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BNR:
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BNR:
|
if (predict_taken) begin
|
if (predict_taken) begin
|
$display("Taking predicted branch: %h",{pc[63:4] + {{42{insn[24]}},insn[24:7]},insn[6:5],2'b00});
|
// $display("Taking predicted branch: %h",{pc[63:4] + {{42{insn[24]}},insn[24:7]},insn[6:5],2'b00});
|
dbranch_taken <= 1'b1;
|
dbranch_taken <= 1'b1;
|
pc <= {pc[63:4] + {{42{insn[24]}},insn[24:7]},insn[6:5],2'b00};
|
pc <= {pc[63:4] + {{42{insn[24]}},insn[24:7]},insn[6:5],2'b00};
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
|
`ifdef BTB
|
|
`BTRI:
|
|
if (predict_taken) begin
|
|
dbranch_taken <= 1'b1;
|
|
pc <= btb[pc[7:2]];
|
|
end
|
|
`endif
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
begin
|
begin
|
if (predict_taken) begin
|
if (predict_taken) begin
|
dbranch_taken <= 1'b1;
|
dbranch_taken <= 1'b1;
|
pc <= {pc[63:4] + {{50{insn[29]}},insn[29:20]},insn[19:18],2'b00};
|
pc <= {pc[63:4] + {{50{insn[29]}},insn[29:20]},insn[19:18],2'b00};
|
Line 2608... |
Line 2701... |
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
|
`R:
|
|
case(xFunc)
|
|
`EXEC:
|
|
begin
|
|
pc <= fnIncPC(xpc);
|
|
dIR <= b;
|
|
xIR <= `NOP_INSN;
|
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
|
default: ;
|
|
endcase
|
`BTRR:
|
`BTRR:
|
case(xIR[4:0])
|
case(xIR[4:0])
|
// BEQ r1,r2,label
|
// BEQ r1,r2,label
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BNR:
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BNR:
|
if (!takb & xbranch_taken) begin
|
if (!takb & xbranch_taken) begin
|
Line 2636... |
Line 2742... |
// BEQ r1,r2,r10
|
// BEQ r1,r2,r10
|
`BEQR,`BNER,`BLTR,`BLER,`BGTR,`BGER,`BLTUR,`BLEUR,`BGTUR,`BGEUR://,`BANDR,`BORR,`BNRR:
|
`BEQR,`BNER,`BLTR,`BLER,`BGTR,`BGER,`BLTUR,`BLEUR,`BGTUR,`BGEUR://,`BANDR,`BORR,`BNRR:
|
if (takb) begin
|
if (takb) begin
|
pc[63:2] <= c[63:2];
|
pc[63:2] <= c[63:2];
|
pc[1:0] <= 2'b00;
|
pc[1:0] <= 2'b00;
|
|
`ifdef BTB
|
|
btb[xpc[7:2]] <= c;
|
|
`endif
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
Line 2657... |
Line 2766... |
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
end
|
|
|
|
// Check the pc of the instruction after the RET instruction (the dpc), to
|
|
// see if it's equal to the RET target. If it's the same as the target then
|
|
// we predicted the RET return correctly, so there's nothing to do. Otherwise
|
|
// we need to branch to the RET location.
|
`RET:
|
`RET:
|
|
`ifdef RAS_PREDICTION
|
|
if (dpc[63:2]!=b[63:2]) begin
|
|
`else
|
begin
|
begin
|
$display("returning to: %h", {b,2'b00});
|
`endif
|
|
// $display("returning to: %h.%h", {b[63:4],4'b0},b[3:2]);
|
pc[63:2] <= b[63:2];
|
pc[63:2] <= b[63:2];
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
end
|
|
// else
|
|
// $display("RET address %h predicted correctly.", {b[63:4],4'b0},b[3:2]);
|
// BEQ r1,#3,r10
|
// BEQ r1,#3,r10
|
`BTRI:
|
`BTRI:
|
|
`ifdef BTB
|
|
if (takb) begin
|
|
if ((xbranch_taken && b!=btb[xpc[7:2]]) || // took branch, but not to right target
|
|
!xbranch_taken) begin // didn't take branch, and were supposed to
|
|
pc[63:2] <= b[63:2];
|
|
pc[1:0] <= 2'b00;
|
|
btb[xpc[7:2]] <= b;
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
|
end
|
|
else if (xbranch_taken) begin // took the branch, and weren't supposed to
|
|
pc <= fnIncPC(xpc);
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
|
`else
|
if (takb) begin
|
if (takb) begin
|
pc[63:2] <= b[63:2];
|
pc[63:2] <= b[63:2];
|
pc[1:0] <= 2'b00;
|
pc[1:0] <= 2'b00;
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
end
|
|
`endif
|
// BEQI r1,#3,label
|
// BEQI r1,#3,label
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
if (takb) begin
|
if (takb) begin
|
if (!xbranch_taken) begin
|
if (!xbranch_taken) begin
|
pc[63:4] <= xpc[63:4] + {{50{xIR[29]}},xIR[29:20]};
|
pc[63:4] <= xpc[63:4] + {{50{xIR[29]}},xIR[29:20]};
|
Line 2693... |
Line 2837... |
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
if (xbranch_taken) begin
|
if (xbranch_taken) begin
|
$display("Taking mispredicted branch %h",fnIncPC(xpc));
|
// $display("Taking mispredicted branch %h",fnIncPC(xpc));
|
pc <= fnIncPC(xpc);
|
pc <= fnIncPC(xpc);
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
Line 2718... |
Line 2862... |
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
if (xbranch_taken) begin
|
if (xbranch_taken) begin
|
$display("Taking mispredicted branch %h",fnIncPC(xpc));
|
// $display("Taking mispredicted branch %h",fnIncPC(xpc));
|
pc <= fnIncPC(xpc);
|
pc <= fnIncPC(xpc);
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRt <= 9'd0;
|
xRt <= 9'd0;
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
Line 2772... |
Line 2916... |
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// MEMORY1 (M1') - part two:
|
// MEMORY1 (M1') - part two:
|
// Check for a TLB miss.
|
// Check for a TLB miss.
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
|
`ifdef TLB
|
if (advanceM1) begin
|
if (advanceM1) begin
|
if (m1IsLoad|m1IsStore) begin
|
if (m1IsLoad|m1IsStore) begin
|
if (DTLBMiss) begin
|
if (DTLBMiss) begin
|
$display("DTLB miss on address: %h",ea);
|
$display("DTLB miss on address: %h",ea);
|
m1extype <= `EX_TLBD;
|
m1extype <= `EX_TLBD;
|
Line 2793... |
Line 2938... |
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
`endif
|
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// MEMORY2 (M2')
|
// MEMORY2 (M2')
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
if (advanceM2) begin
|
if (advanceM2) begin
|
Line 2886... |
Line 3032... |
end
|
end
|
else if (triggerICacheLoad) begin
|
else if (triggerICacheLoad) begin
|
icaccess <= 1'b1;
|
icaccess <= 1'b1;
|
bte_o <= 2'b00; // linear burst
|
bte_o <= 2'b00; // linear burst
|
cti_o <= 3'b010; // burst access
|
cti_o <= 3'b010; // burst access
|
bl_o <= 5'd8;
|
|
cyc_o <= 1'b1;
|
cyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
|
if (ICacheAct) begin
|
|
bl_o <= 5'd8;
|
adr_o <= {ppc[63:6],6'h00};
|
adr_o <= {ppc[63:6],6'h00};
|
cstate <= ICACT1;
|
cstate <= ICACT1;
|
end
|
end
|
|
else begin
|
|
bl_o <= 5'd2;
|
|
adr_o <= {ppc[63:4],4'b0000};
|
|
cstate <= ICACT2;
|
|
end
|
|
end
|
// WISHBONE burst accesses
|
// WISHBONE burst accesses
|
//
|
//
|
ICACT1:
|
ICACT1:
|
if (ack_i) begin
|
if (ack_i) begin
|
adr_o[5:3] <= adr_o[5:3] + 3'd1;
|
adr_o[5:3] <= adr_o[5:3] + 3'd1;
|
if (adr_o[5:3]==3'h6)
|
if (adr_o[5:3]==3'd6)
|
cti_o <= 3'b111; // Last cycle ahead
|
cti_o <= 3'b111; // Last cycle ahead
|
if (adr_o[5:3]==3'h7) begin
|
else if (adr_o[5:3]==3'd7) begin
|
cti_o <= 3'b000; // back to non-burst mode
|
cti_o <= 3'b000; // back to non-burst mode
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
tmem[adr_o[12:6]] <= {1'b1,adr_o[63:13]}; // This will cause ihit to go high
|
tmem[adr_o[12:6]] <= {1'b1,adr_o[63:13]}; // This will cause ihit to go high
|
tvalid[adr_o[12:6]] <= 1'b1;
|
tvalid[adr_o[12:6]] <= 1'b1;
|
icaccess <= 1'b0;
|
icaccess <= 1'b0;
|
cstate <= IDLE;
|
cstate <= IDLE;
|
end
|
end
|
end
|
end
|
|
ICACT2:
|
|
if (ack_i) begin
|
|
adr_o <= adr_o + 64'd8;
|
|
if (adr_o[3]==1'b0) begin
|
|
cti_o <= 3'b111; // Last cycle ahead
|
|
tmpbuf <= dat_i;
|
|
end
|
|
else begin
|
|
insnbuf <= {dat_i,tmpbuf};
|
|
cti_o <= 3'b000; // back to non-burst mode
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
icaccess <= 1'b0;
|
|
ibuftag <= adr_o[63:4];
|
|
cstate <= IDLE;
|
|
end
|
|
end
|
|
|
DCACT:
|
DCACT:
|
if (ack_i) begin
|
if (ack_i) begin
|
adr_o[5:3] <= adr_o[5:3] + 3'd1;
|
adr_o[5:3] <= adr_o[5:3] + 3'd1;
|
if (adr_o[5:3]==3'h6)
|
if (adr_o[5:3]==3'h6)
|
cti_o <= 3'b111; // Last cycle ahead
|
cti_o <= 3'b111; // Last cycle ahead
|