Line 1... |
Line 1... |
|
`timescale 1ns / 1ps
|
// ============================================================================
|
// ============================================================================
|
// (C) 2012 Robert Finch
|
// (C) 2012 Robert Finch
|
// All Rights Reserved.
|
// All Rights Reserved.
|
// robfinch<remove>@opencores.org
|
// robfinch<remove>@opencores.org
|
//
|
//
|
Line 20... |
Line 21... |
// 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 ADDRESS_RESERVATION 1
|
`define ADDRESS_RESERVATION 1
|
`define RAS_PREDICTION 1
|
|
//`define FLOATING_POINT 1
|
//`define FLOATING_POINT 1
|
//`define BTB 1
|
//`define BTB 1
|
//`define TLB 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 IRQ_VECTOR 64'hFFFF_FFFF_FFFF_FFD0
|
|
`define TRAP_VECTOR 64'h0000_0000_0000_0000
|
|
|
|
`define ITLB_MissHandler 64'hFFFF_FFFF_FFFF_FFC0
|
`define ITLB_MissHandler 64'hFFFF_FFFF_FFFF_FFC0
|
`define DTLB_MissHandler 64'hFFFF_FFFF_FFFF_FFB0
|
`define DTLB_MissHandler 64'hFFFF_FFFF_FFFF_FFB0
|
|
|
`define EX_NON 9'd000
|
`define EX_NON 9'd000
|
`define EX_TRAP 9'd32 // Trap exception
|
`define EX_TRAP 9'd32 // Trap exception
|
`define EX_IRQ 9'd449 // interrupt
|
`define EX_IRQ 9'd449 // interrupt
|
`define EX_DBZ 9'd488 // divide by zero
|
`define EX_DBZ 9'd488 // divide by zero
|
`define EX_OFL 9'd489 // overflow
|
`define EX_OFL 9'd489 // overflow
|
|
`define EX_UNIMP_INSN 9'd495 // unimplemented instruction
|
`define EX_PRIV 9'd496 // priviledge violation
|
`define EX_PRIV 9'd496 // priviledge violation
|
`define EX_TLBD 9'd506 // TLB exception - data
|
`define EX_TLBD 9'd506 // TLB exception - data
|
`define EX_TLBI 9'd507 // TLB exception - ifetch
|
`define EX_TLBI 9'd507 // TLB exception - ifetch
|
`define EX_DBERR 9'd508 // Bus Error - load or store or I/O
|
`define EX_DBERR 9'd508 // Bus Error - load or store or I/O
|
`define EX_IBERR 9'd509 // Bus Error - instruction fetch
|
`define EX_IBERR 9'd509 // Bus Error - instruction fetch
|
`define EX_NMI 9'd510 // non-maskable interrupt
|
`define EX_NMI 9'd510 // non-maskable interrupt
|
`define EX_RST 9'd511 // Reset
|
`define EX_RST 9'd511 // Reset
|
|
|
`include "Raptor64_opcodes.v"
|
`include "Raptor64_opcodes.v"
|
|
|
module Raptor64sc(rst_i, clk_i, nmi_i, irq_i, bte_o, cti_o, bl_o,
|
module Raptor64sc(rst_i, clk_i, nmi_i, irq_i, bte_o, cti_o, bl_o, iocyc_o,
|
cyc_o, stb_o, ack_i, err_i, we_o, sel_o, rsv_o, adr_o, dat_i, dat_o, sys_adv, sys_adr
|
cyc_o, stb_o, ack_i, err_i, we_o, sel_o, rsv_o, adr_o, dat_i, dat_o, sys_adv, sys_adr
|
);
|
);
|
parameter IDLE = 5'd1;
|
parameter IDLE = 5'd1;
|
parameter ICACT = 5'd2;
|
parameter ICACT = 5'd2;
|
parameter ICACT0 = 5'd3;
|
|
parameter ICACT1 = 5'd4;
|
parameter ICACT1 = 5'd4;
|
parameter ICACT2 = 5'd5;
|
parameter ICACT2 = 5'd5;
|
parameter ICACT3 = 5'd6;
|
|
parameter ICACT4 = 5'd7;
|
|
parameter ICACT5 = 5'd8;
|
|
parameter ICACT6 = 5'd9;
|
|
parameter ICACT7 = 5'd10;
|
|
parameter ICDLY = 5'd11;
|
|
parameter DCIDLE = 5'd20;
|
parameter DCIDLE = 5'd20;
|
parameter DCACT = 5'd21;
|
parameter DCACT = 5'd21;
|
parameter DCACT0 = 5'd22;
|
parameter AMSB = 31;
|
parameter DCACT1 = 5'd23;
|
|
parameter DCACT2 = 5'd24;
|
|
parameter DCACT3 = 5'd25;
|
|
parameter DCACT4 = 5'd26;
|
|
parameter DCACT5 = 5'd27;
|
|
parameter DCACT6 = 5'd28;
|
|
parameter DCACT7 = 5'd29;
|
|
parameter DCDLY = 5'd30;
|
|
|
|
input rst_i;
|
input rst_i;
|
input clk_i;
|
input clk_i;
|
input nmi_i;
|
input nmi_i;
|
input irq_i;
|
input irq_i;
|
|
|
output [1:0] bte_o;
|
output [1:0] bte_o; // burst type
|
reg [1:0] bte_o;
|
reg [1:0] bte_o;
|
output [2:0] cti_o;
|
output [2:0] cti_o; // cycle type
|
reg [2:0] cti_o;
|
reg [2:0] cti_o;
|
output [4:0] bl_o;
|
output [4:0] bl_o; // burst length (non-WISHBONE)
|
reg [4:0] bl_o;
|
reg [4:0] bl_o;
|
output cyc_o;
|
output iocyc_o; // I/O cycle is valid
|
|
reg iocyc_o;
|
|
output cyc_o; // cycle is valid
|
reg cyc_o;
|
reg cyc_o;
|
output stb_o;
|
output stb_o; // data strobe
|
reg stb_o;
|
reg stb_o;
|
input ack_i;
|
input ack_i; // data transfer acknowledge
|
input err_i;
|
input err_i; // bus error
|
output we_o;
|
output we_o; // write enable
|
reg we_o;
|
reg we_o;
|
output [7:0] sel_o;
|
output [7:0] sel_o; // byte lane selects
|
reg [7:0] sel_o;
|
reg [7:0] sel_o;
|
output rsv_o;
|
output rsv_o; // reserve the address (non-WISHBONE)
|
reg rsv_o;
|
reg rsv_o;
|
output [63:0] adr_o;
|
output [63:0] adr_o; // address
|
reg [63:0] adr_o;
|
reg [63:0] adr_o;
|
input [63:0] dat_i;
|
input [63:0] dat_i; // data input
|
output [63:0] dat_o;
|
output [63:0] dat_o; // data output
|
reg [63:0] dat_o;
|
reg [63:0] dat_o;
|
|
|
input sys_adv;
|
input sys_adv;
|
input [63:5] sys_adr;
|
input [63:5] sys_adr;
|
|
|
reg [5:0] fltctr;
|
reg [5:0] fltctr;
|
wire fltdone = fltctr==6'd0;
|
wire fltdone = fltctr==6'd0;
|
reg resetA;
|
reg resetA;
|
reg im,bu_im; // interrupt mask
|
reg im,bu_im; // interrupt mask
|
reg im1; // temporary interrupt mask for LM/SM
|
reg im1; // temporary interrupt mask for LM/SM
|
reg [1:0] vtno; // vector table number
|
|
reg [1:0] rm; // fp rounding mode
|
reg [1:0] rm; // fp rounding mode
|
reg FXE; // fp exception enable
|
reg FXE; // fp exception enable
|
wire KernelMode;
|
wire KernelMode;
|
wire [31:0] sr = {bu_im,15'd0,im,1'b0,KernelMode,FXE,vtno,10'b0};
|
wire [31:0] sr = {bu_im,15'd0,im,1'b0,KernelMode,FXE,2'b00,10'b0};
|
reg [41:0] dIR,xIR,m1IR,m2IR,wIR;
|
reg [41:0] dIR,xIR,m1IR,m2IR,wIR;
|
reg [41:0] ndIR;
|
reg [41:0] ndIR; // next dIR
|
wire [6:0] dOpcode = dIR[41:35];
|
|
reg [63:0] pc;
|
reg [63:0] pc;
|
|
wire [63:0] pchistoric;
|
|
reg pccap;
|
reg [63:0] ErrorEPC,EPC,IPC;
|
reg [63:0] ErrorEPC,EPC,IPC;
|
reg [63:0] dpc,m1pc,m2pc,wpc;
|
reg [63:0] dpc,xpc,m1pc,m2pc,wpc;
|
reg dpcv,xpcv,m1pcv,m2pcv,wpcv; // PC valid indicators
|
reg dpcv,xpcv,m1pcv,m2pcv,wpcv; // PC valid indicators
|
reg [63:0] xpc;
|
wire [63:0] rfoa,rfob,rfoc;
|
reg [63:0] tlbra; // return address for a TLB exception
|
wire [8:0] dRa,dRb,dRc;
|
reg [8:0] dRa,dRb,dRc;
|
reg [8:0] wRt,m1Rt,m2Rt,tRt;
|
reg [8:0] wRt,mRt,m1Rt,m2Rt,tRt,dRt;
|
wire [8:0] xRt;
|
reg [8:0] xRt;
|
reg xRtZero;
|
reg [63:0] dImm;
|
|
reg [63:0] ea;
|
reg [63:0] ea;
|
reg [63:0] iadr_o;
|
|
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; // Trap Base Address
|
reg [1:0] dhwxtype,xhwxtype,m1hwxtype,m2hwxtype,whwxtype;
|
reg [1:0] dhwxtype,xhwxtype,m1hwxtype,m2hwxtype,whwxtype;
|
|
reg [8:0] dextype,xextype,m1extype,m2extype,wextype,textype;
|
reg [3:0] AXC,dAXC,xAXC;
|
reg [3:0] AXC,dAXC,xAXC;
|
reg dtinit;
|
reg dtinit;
|
reg dcache_on;
|
reg dcache_on;
|
reg [63:32] nonICacheSeg;
|
reg [63:32] nonICacheSeg;
|
|
|
Line 163... |
Line 145... |
16'd0
|
16'd0
|
};
|
};
|
wire [63:0] cdat;
|
wire [63:0] cdat;
|
reg [63:0] wr_addr;
|
reg [63:0] wr_addr;
|
reg [41:0] insn;
|
reg [41:0] insn;
|
wire [63:0] rfoa,rfob,rfoc;
|
|
reg clk_en;
|
reg clk_en;
|
reg cpu_clk_en;
|
reg cpu_clk_en;
|
reg StatusERL; // 1= in error processing
|
reg StatusERL; // 1= in error processing
|
reg StatusEXL; // 1= in exception processing
|
reg StatusEXL; // 1= in exception processing
|
reg StatusHWI; // 1= in interrupt processing
|
reg StatusHWI; // 1= in interrupt processing
|
reg StatusUM; // 1= user mode
|
reg StatusUM; // 1= user mode
|
reg [7:0] CauseCode;
|
|
reg [7:0] ASID; // address space identifier (process ID)
|
reg [7:0] ASID; // address space identifier (process ID)
|
integer n;
|
integer n;
|
reg [63:13] BadVAddr;
|
reg [63:13] BadVAddr;
|
reg [63:13] PageTableAddr;
|
reg [63:13] PageTableAddr;
|
reg [63:0] errorAddress;
|
reg [63:0] errorAddress;
|
|
|
|
wire [6:0] iOpcode = insn[41:35];
|
wire [6:0] iFunc = insn[6:0];
|
wire [6:0] iFunc = insn[6:0];
|
|
wire [6:0] dOpcode = dIR[41:35];
|
wire [6:0] dFunc = dIR[6:0];
|
wire [6:0] dFunc = dIR[6:0];
|
wire [5:0] dFunc6 = dIR[5:0];
|
wire [5:0] dFunc6 = dIR[5:0];
|
|
wire [6:0] xOpcode = xIR[41:35];
|
wire [6:0] xFunc = xIR[6:0];
|
wire [6:0] xFunc = xIR[6:0];
|
wire [5:0] xFunc6 = xIR[5:0];
|
wire [5:0] xFunc6 = xIR[5:0];
|
wire [4:0] xFunc5 = xIR[4:0];
|
wire [4:0] xFunc5 = xIR[4:0];
|
wire [6:0] iOpcode = insn[41:35];
|
|
wire [6:0] xOpcode = xIR[41:35];
|
|
reg [6:0] m1Opcode,m2Opcode,wOpcode;
|
reg [6:0] m1Opcode,m2Opcode,wOpcode;
|
reg [6:0] m1Func,m2Func,wFunc;
|
reg [6:0] m1Func,m2Func,wFunc;
|
reg [63:0] m1Data,m2Data,wData,tData;
|
reg [63:0] m1Data,m2Data,wData,tData;
|
reg [63:0] m2Addr;
|
reg [63:0] m2Addr;
|
reg [63:0] tick;
|
reg [63:0] tick;
|
reg [63:0] tba;
|
|
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,wirqf,tirqf;
|
reg dirqf,rirqf,m1irqf,m2irqf,wirqf,tirqf;
|
reg xirqf;
|
reg xirqf;
|
reg [8:0] dextype,m1extype,m2extype,wextype,textype,exception_type;
|
|
reg [8:0] xextype;
|
|
reg wLdPC,m2LdPC;
|
reg wLdPC,m2LdPC;
|
wire advanceX_edge;
|
wire advanceX_edge;
|
reg takb;
|
wire takb;
|
wire advanceX,advanceM1,advanceW;
|
wire advanceX,advanceM1,advanceW;
|
reg m1IsLoad,m2IsLoad;
|
reg m1IsLoad,m2IsLoad;
|
reg m1IsIO;
|
reg m1IsIO;
|
reg m1IsStore,m2IsStore,wIsStore;
|
reg m1IsStore,m2IsStore,wIsStore;
|
|
reg m1clkoff,m2clkoff,m3clkoff,m4clkoff,wclkoff;
|
|
reg dFip,xFip,m1Fip,m2Fip,m3Fip,m4Fip,wFip;
|
|
reg cyc1;
|
|
|
|
|
function [63:0] fnIncPC;
|
function [63:0] fnIncPC;
|
input [63:0] fpc;
|
input [63:0] fpc;
|
begin
|
begin
|
case(fpc[3:2])
|
case(fpc[3:2])
|
Line 222... |
Line 203... |
end
|
end
|
endfunction
|
endfunction
|
|
|
assign KernelMode = StatusEXL|StatusHWI;
|
assign KernelMode = StatusEXL|StatusHWI;
|
|
|
|
wire iIsLSPair = iOpcode==`SP || iOpcode==`LP || iOpcode==`SFP || iOpcode==`LFP || iOpcode==`SFDP || iOpcode==`LFDP;
|
|
wire dIsLSPair = dOpcode==`SP || dOpcode==`LP || dOpcode==`SFP || dOpcode==`LFP || dOpcode==`SFDP || dOpcode==`LFDP;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// TLB
|
// TLB
|
// The TLB contains 64 entries, that are 8 way set associative.
|
// The TLB contains 64 entries, that are 8 way set associative.
|
// The TLB is dual ported and shared between the instruction and data streams.
|
// The TLB is dual ported and shared between the instruction and data streams.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Line 274... |
Line 258... |
`else
|
`else
|
assign ppc = pc;
|
assign ppc = pc;
|
assign pea = ea;
|
assign pea = ea;
|
`endif
|
`endif
|
|
|
wire dram_bus = !pea[63];
|
|
wire m2_dram_bus = !m2Addr[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 300... |
Line 281... |
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Random number register:
|
// Random number register:
|
//
|
//
|
// Uses George Marsaglia's multiply method.
|
// Uses George Marsaglia's multiply method.
|
// Current method is to concatonate two 32 bit generators. This isn't a very
|
|
// good way to do it.
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
reg [31:0] m_z1,m_z2;
|
reg [63:0] m_z;
|
reg [31:0] m_w1,m_w2;
|
reg [63:0] m_w;
|
reg [31:0] next_m_z1,next_m_z2;
|
reg [63:0] next_m_z;
|
reg [31:0] next_m_w1,next_m_w2;
|
reg [63:0] next_m_w;
|
|
|
always @(m_z1 or m_w1)
|
|
begin
|
|
next_m_z1 <= (18'h36969 * m_z1[15:0]) + m_z1[31:16];
|
|
next_m_w1 <= (18'h18000 * m_w1[15:0]) + m_w1[31:16];
|
|
end
|
|
|
|
always @(m_z2 or m_w2)
|
always @(m_z or m_w)
|
begin
|
begin
|
next_m_z2 <= (18'h36969 * m_z2[15:0]) + m_z2[31:16];
|
next_m_z <= (36'h3696936969 * m_z[31:0]) + m_z[63:32];
|
next_m_w2 <= (18'h18000 * m_w2[15:0]) + m_w2[31:16];
|
next_m_w <= (36'h1800018000 * m_w[31:0]) + m_w[63:32];
|
end
|
end
|
|
|
wire [31:0] rand1 = {m_z1[15:0],16'd0} + m_w1;
|
wire [63:0] rand = {m_z[31:0],32'd0} + m_w;
|
wire [31:0] rand2 = {m_z2[15:0],16'd0} + m_w2;
|
|
wire [63:0] rand = {rand2,rand1};
|
|
|
|
wire [10:0] bias = 11'h3FF; // bias amount (eg 127)
|
wire [10:0] bias = 11'h3FF; // bias amount (eg 127)
|
wire [10:0] xl = rand[62:53];
|
wire [10:0] xl = rand[62:53];
|
wire sgn = 1'b0; // floating point: always generate a positive number
|
wire sgn = 1'b0; // floating point: always generate a positive number
|
wire [10:0] exp = xl > bias-1 ? bias-1 : xl; // 2^-1 otherwise number could be over 1
|
wire [10:0] exp = xl > bias-1 ? bias-1 : xl; // 2^-1 otherwise number could be over 1
|
Line 334... |
Line 305... |
wire [63:0] randfd = {sgn,exp,man};
|
wire [63:0] randfd = {sgn,exp,man};
|
reg [63:0] rando;
|
reg [63:0] rando;
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Instruction Cache / Instruction buffer
|
// Instruction Cache / Instruction buffer
|
// 8kB
|
//
|
|
// On a bus error, the instruction cache / buffer is loaded with a SYSCALL 509
|
|
// instruction, which is a call to the bus error handler.
|
//
|
//
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//reg lfdir;
|
//reg lfdir;
|
wire lfdir = (((dOpcode==`LM || dOpcode==`SM) && dIR[31:0]!=32'd0) && ndIR[31:0]!=32'd0) ||
|
wire lfdir = (((dOpcode==`LM || dOpcode==`SM) && dIR[31:0]!=32'd0) && ndIR[31:0]!=32'd0) || (dIsLSPair && dIR[25]!=1'b1);
|
((dOpcode==`LP || dOpcode==`SP || dOpcode==`LFP || dOpcode==`SFP || dOpcode==`LFDP || dOpcode==`SFDP) && dIR[25]!=1'b1);
|
wire ldnop = (((dOpcode==`LM || dOpcode==`SM) && (dIR[31:0]==32'd0 || ndIR[31:0]==32'd0)) || (dIsLSPair && dIR[25]==1'b1));
|
wire ldnop = (((dOpcode==`LM || dOpcode==`SM) && (dIR[31:0]==32'd0 || ndIR[31:0]==32'd0)) ||
|
|
((dOpcode==`LP || dOpcode==`SP || dOpcode==`LFP || dOpcode==`SFP || dOpcode==`LFDP || dOpcode==`SFDP) && dIR[25]==1'b1));
|
|
reg icaccess;
|
reg icaccess;
|
reg ICacheOn;
|
reg ICacheOn;
|
wire ibufrdy;
|
wire ibufrdy;
|
reg [63:0] tmpbuf;
|
reg [63:0] tmpbuf;
|
wire [127:0] insnbundle;
|
wire [127:0] insnbundle;
|
Line 356... |
Line 327... |
wire ICacheAct = ICacheOn & isICached;
|
wire ICacheAct = ICacheOn & isICached;
|
reg [41:0] insn1;
|
reg [41:0] insn1;
|
reg [41:0] insnkey;
|
reg [41:0] insnkey;
|
|
|
// SYSCALL 509
|
// SYSCALL 509
|
wire [127:0] bevect = 128'b00_00000000_00000000_00000000_11111110_10010111__00_00000000_00000000_00000000_11111110_10010111__00_00000000_00000000_00000000_11111110_10010111;
|
wire syscall509 = 42'b00_00000000_00000000_00000000_11111110_10010111;
|
|
wire [127:0] bevect = {2'b00,syscall509,syscall509,syscall509};
|
|
|
Raptor64_icache_ram u1
|
Raptor64_icache_ram u1
|
(
|
(
|
.clka(clk), // input clka
|
.clka(clk), // input clka
|
.wea(icaccess & (ack_i|err_i)), // input [0 : 0] wea
|
.wea(icaccess & (ack_i|err_i)), // input [0 : 0] wea
|
Line 372... |
Line 344... |
);
|
);
|
|
|
always @(ppc or insnbundle or ICacheAct or insnbuf0 or insnbuf1 or ndIR or lfdir or ldnop)
|
always @(ppc or insnbundle or ICacheAct or insnbuf0 or insnbuf1 or ndIR or lfdir or ldnop)
|
begin
|
begin
|
casex({ldnop,lfdir,ICacheAct,ibuftag1==ppc[63:4],pc[3:2]})
|
casex({ldnop,lfdir,ICacheAct,ibuftag1==ppc[63:4],pc[3:2]})
|
6'b1xxxxx: insn1 <= 42'h37800000000;
|
6'b1xxxxx: insn1 <= `NOP_INSN;
|
6'b01xxxx: insn1 <= ndIR;
|
6'b01xxxx: insn1 <= ndIR;
|
6'b001x00: insn1 <= insnbundle[ 41: 0];
|
6'b001x00: insn1 <= insnbundle[ 41: 0];
|
6'b001x01: insn1 <= insnbundle[ 83:42];
|
6'b001x01: insn1 <= insnbundle[ 83:42];
|
6'b001x10: insn1 <= insnbundle[125:84];
|
6'b001x10: insn1 <= insnbundle[125:84];
|
6'b001x11: insn1 <= 42'h37800000000; // NOP instruction
|
6'b001x11: insn1 <= `NOP_INSN;
|
6'b000000: insn1 <= insnbuf0[ 41: 0];
|
6'b000000: insn1 <= insnbuf0[ 41: 0];
|
6'b000001: insn1 <= insnbuf0[ 83:42];
|
6'b000001: insn1 <= insnbuf0[ 83:42];
|
6'b000010: insn1 <= insnbuf0[125:84];
|
6'b000010: insn1 <= insnbuf0[125:84];
|
6'b000011: insn1 <= 42'h37800000000;
|
6'b000011: insn1 <= `NOP_INSN;
|
6'b000100: insn1 <= insnbuf1[ 41: 0];
|
6'b000100: insn1 <= insnbuf1[ 41: 0];
|
6'b000101: insn1 <= insnbuf1[ 83:42];
|
6'b000101: insn1 <= insnbuf1[ 83:42];
|
6'b000110: insn1 <= insnbuf1[125:84];
|
6'b000110: insn1 <= insnbuf1[125:84];
|
6'b000111: insn1 <= 42'h37800000000;
|
6'b000111: insn1 <= `NOP_INSN;
|
endcase
|
endcase
|
end
|
end
|
|
|
// Decrypt the instruction set.
|
// Decrypt the instruction set.
|
always @(insn1,insnkey)
|
always @(insn1,insnkey)
|
Line 416... |
Line 388... |
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
reg dcaccess;
|
reg dcaccess;
|
wire dhit;
|
wire dhit;
|
wire [64:15] dtgout;
|
wire [64:15] dtgout;
|
reg wrhit;
|
reg wrhit;
|
reg [7:0] dsel_o;
|
|
reg [63:0] dadr_o;
|
|
reg [31:0] ddat;
|
|
reg wr_dcache;
|
reg wr_dcache;
|
|
|
// cache RAM 32Kb
|
// cache RAM 32Kb
|
Raptor64_dcache_ram u10
|
Raptor64_dcache_ram u10
|
(
|
(
|
Line 458... |
Line 427... |
|
|
reg [64:0] xData;
|
reg [64:0] xData;
|
wire xisCacheElement = (xData[63:52] != 12'hFFD && xData[63:52]!=12'hFFF) && dcache_on;
|
wire xisCacheElement = (xData[63:52] != 12'hFFD && xData[63:52]!=12'hFFF) && dcache_on;
|
reg m1IsCacheElement;
|
reg m1IsCacheElement;
|
|
|
reg nopI;
|
|
|
|
|
|
|
|
wire [127:0] mult_out;
|
wire [127:0] mult_out;
|
wire [63:0] sqrt_out;
|
wire [63:0] sqrt_out;
|
wire [63:0] div_q;
|
wire [63:0] div_q;
|
wire [63:0] div_r;
|
wire [63:0] div_r;
|
wire sqrt_done,mult_done,div_done;
|
wire sqrt_done,mult_done,div_done;
|
wire isSqrt = xOpcode==`R && xFunc==`SQRT;
|
wire isSqrt = xOpcode==`R && xFunc==`SQRT;
|
wire [7:0] bcdaddo,bcdsubo;
|
|
|
|
BCDAdd u40(.ci(1'b0),.a(a[7:0]),.b(b[7:0]),.o(bcdaddo),.c());
|
|
BCDSub u41(.ci(1'b0),.a(a[7:0]),.b(b[7:0]),.o(bcdsubo),.c());
|
|
|
|
isqrt #(64) u14
|
isqrt #(64) u14
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
Line 492... |
Line 454... |
wire isMult = xOpcode==`MULSI || xOpcode==`MULUI || (xOpcode==`RR && (xFunc==`MULS || xFunc==`MULU));
|
wire isMult = xOpcode==`MULSI || xOpcode==`MULUI || (xOpcode==`RR && (xFunc==`MULS || xFunc==`MULU));
|
wire isDivu = xOpcode==`RR && xFunc==`DIVU;
|
wire isDivu = xOpcode==`RR && xFunc==`DIVU;
|
wire isDivs = (xOpcode==`RR && xFunc==`DIVS) || xOpcode==`DIVSI;
|
wire isDivs = (xOpcode==`RR && xFunc==`DIVS) || xOpcode==`DIVSI;
|
wire isDivi = xOpcode==`DIVSI || xOpcode==`DIVUI;
|
wire isDivi = xOpcode==`DIVSI || xOpcode==`DIVUI;
|
wire isDiv = xOpcode==`DIVSI || xOpcode==`DIVUI || (xOpcode==`RR && (xFunc==`DIVS || xFunc==`DIVU));
|
wire isDiv = xOpcode==`DIVSI || xOpcode==`DIVUI || (xOpcode==`RR && (xFunc==`DIVS || xFunc==`DIVU));
|
|
wire isModu = (xOpcode==`RR && xFunc==`MODU);
|
wire disRRShift = dOpcode==`RR && (
|
wire isMods = (xOpcode==`RR && xFunc==`MODS);
|
dFunc==`SHL || dFunc==`ROL || dFunc==`SHR ||
|
wire isMod = isModu|isMods;
|
dFunc==`SHRU || dFunc==`ROR || dFunc==`ROLAM
|
|
);
|
|
wire disRightShift = dOpcode==`RR && (
|
|
dFunc==`SHR || dFunc==`SHRU || dFunc==`ROR
|
|
);
|
|
|
|
Raptor64Mult u18
|
Raptor64Mult u18
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
Line 519... |
Line 476... |
|
|
Raptor64Div u19
|
Raptor64Div u19
|
(
|
(
|
.rst(rst_i),
|
.rst(rst_i),
|
.clk(clk),
|
.clk(clk),
|
.ld(isDiv),
|
.ld(isDiv|isMod),
|
.sgn(isDivs),
|
.sgn(isDivs|isMods),
|
.isDivi(isDivi),
|
.isDivi(isDivi),
|
.a(a),
|
.a(a),
|
.b(b),
|
.b(b),
|
.imm(imm),
|
.imm(imm),
|
.qo(div_q),
|
.qo(div_q),
|
Line 779... |
Line 736... |
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};
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Stack for return address predictor
|
// Stack for return address predictor
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
`ifdef RAS_PREDICTION
|
|
reg [63:0] ras [63:0]; // return address stack, return predictions
|
reg [63:0] ras [63:0]; // return address stack, return predictions
|
reg [5:0] ras_sp; // stack pointer
|
reg [5:0] ras_sp; // stack pointer
|
`endif
|
|
`ifdef BTB
|
`ifdef BTB
|
reg [63:0] btb [63:0]; // branch target buffer
|
reg [63:0] btb [63:0]; // branch target buffer
|
`endif
|
`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.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Line 827... |
Line 760... |
.pc(pc),
|
.pc(pc),
|
.xpc(xpc),
|
.xpc(xpc),
|
.takb(takb),
|
.takb(takb),
|
.predict_taken(predict_taken)
|
.predict_taken(predict_taken)
|
);
|
);
|
`endif
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Evaluate branch conditions.
|
// Evaluate branch conditions.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
wire signed [63:0] as = a;
|
|
wire signed [63:0] bs = b;
|
|
wire signed [63:0] imms = imm;
|
|
wire aeqz = a==64'd0;
|
|
wire beqz = b==64'd0;
|
|
wire immeqz = imm==64'd0;
|
|
|
|
wire eqb0 = a[ 7: 0]==b[ 7: 0];
|
|
wire eqb1 = a[15: 8]==b[15: 8];
|
|
wire eqb2 = a[23:16]==b[23:16];
|
|
wire eqb3 = a[31:24]==b[31:24];
|
|
wire eqb4 = a[39:32]==b[39:32];
|
|
wire eqb5 = a[47:40]==b[47:40];
|
|
wire eqb6 = a[55:48]==b[55:48];
|
|
wire eqb7 = a[63:56]==b[63:56];
|
|
|
|
wire eqc0 = eqb0 & eqb1;
|
|
wire eqc1 = eqb2 & eqb3;
|
|
wire eqc2 = eqb4 & eqb5;
|
|
wire eqc3 = eqb6 & eqb7;
|
|
|
|
wire eqh0 = eqc0 & eqc1;
|
|
wire eqh1 = eqc2 & eqc3;
|
|
|
|
wire eqw = eqh0 & eqh1;
|
|
wire eq = eqw;
|
|
|
|
wire eqi = a==imm;
|
|
wire lt = $signed(a) < $signed(b);
|
|
wire lti = as < imms;
|
|
wire ltu = a < b;
|
|
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)
|
|
case (xOpcode)
|
|
`BTRR:
|
|
case(xFunc5)
|
|
`BRA: takb = 1'b1;
|
|
`BRN: takb = 1'b0;
|
|
`BEQ: takb = eq;
|
|
`BNE: takb = !eq;
|
|
`BLT: takb = lt;
|
|
`BLE: takb = lt|eq;
|
|
`BGT: takb = !(lt|eq);
|
|
`BGE: takb = !lt;
|
|
`BLTU: takb = ltu;
|
|
`BLEU: takb = ltu|eq;
|
|
`BGTU: takb = !(ltu|eq);
|
|
`BGEU: takb = !ltu;
|
|
`BOR: takb = !aeqz || !beqz;
|
|
`BAND: takb = !aeqz && !beqz;
|
|
`BNR: takb = !rsf;
|
|
`LOOP: takb = !beqz;
|
|
`BEQR: takb = eq;
|
|
`BNER: takb = !eq;
|
|
`BLTR: takb = lt;
|
|
`BLER: takb = lt|eq;
|
|
`BGTR: takb = !(lt|eq);
|
|
`BGER: takb = !lt;
|
|
`BLTUR: takb = ltu;
|
|
`BLEUR: takb = ltu|eq;
|
|
`BGTUR: takb = !(ltu|eq);
|
|
`BGEUR: takb = !ltu;
|
|
default: takb = 1'b0;
|
|
endcase
|
|
`BEQI: takb = eqi;
|
|
`BNEI: takb = !eqi;
|
|
`BLTI: takb = lti;
|
|
`BLEI: takb = lti|eqi;
|
|
`BGTI: takb = !(lti|eqi);
|
|
`BGEI: takb = !lti;
|
|
`BLTUI: takb = ltui;
|
|
`BLEUI: takb = ltui|eqi;
|
|
`BGTUI: takb = !(ltui|eqi);
|
|
`BGEUI: takb = !ltui;
|
|
`BTRI:
|
|
case(xIR[24:20])
|
|
`BRA: takb = 1'b1;
|
|
`BRN: takb = 1'b0;
|
|
`BEQ: takb = eqi;
|
|
`BNE: takb = !eqi;
|
|
`BLT: takb = lti;
|
|
`BLE: takb = lti|eqi;
|
|
`BGT: takb = !(lti|eqi);
|
|
`BGE: takb = !lti;
|
|
`BLTU: takb = ltui;
|
|
`BLEU: takb = ltui|eqi;
|
|
`BGTU: takb = !(ltui|eqi);
|
|
`BGEU: takb = !ltui;
|
|
default: takb = 1'b0;
|
|
endcase
|
|
`TRAPcc:
|
|
case(xFunc5)
|
|
`TEQ: takb = eq;
|
|
`TNE: takb = !eq;
|
|
`TLT: takb = lt;
|
|
`TLE: takb = lt|eq;
|
|
`TGT: takb = !(lt|eq);
|
|
`TGE: takb = !lt;
|
|
`TLTU: takb = ltu;
|
|
`TLEU: takb = ltu|eq;
|
|
`TGTU: takb = !(ltu|eq);
|
|
`TGEU: takb = !ltu;
|
|
default: takb = 1'b0;
|
|
endcase
|
|
`TRAPcci:
|
|
case(xIR[29:25])
|
|
`TEQI: takb = eqi;
|
|
`TNEI: takb = !eqi;
|
|
`TLTI: takb = lti;
|
|
`TLEI: takb = lti|eqi;
|
|
`TGTI: takb = !(lti|eqi);
|
|
`TGEI: takb = !lti;
|
|
`TLTUI: takb = ltui;
|
|
`TLEUI: takb = ltui|eqi;
|
|
`TGTUI: takb = !(ltui|eqi);
|
|
`TGEUI: takb = !ltui;
|
|
default: takb = 1'b0;
|
|
endcase
|
|
default:
|
|
takb = 1'b0;
|
|
endcase
|
|
|
|
|
Raptor64_EvaluateBranch u4
|
|
(
|
|
.ir(xIR),
|
|
.a(a),
|
|
.b(b),
|
|
.imm(imm),
|
|
.rsf(rsf),
|
|
.takb(takb)
|
|
);
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Datapath (ALU) operations.
|
// Datapath (ALU) operations.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
reg [63:0] xData1;
|
|
wire [63:0] xBitfieldo,xSeto,xLogico,xShifto,xAddsubo;
|
|
|
wire [6:0] cntlzo,cntloo;
|
wire [6:0] cntlzo,cntloo;
|
cntlz64 u12 (.clk(clk), .i(a), .o(cntlzo) );
|
cntlz64 u12 (.clk(clk), .i(a), .o(cntlzo) );
|
cntlo64 u13 (.clk(clk), .i(a), .o(cntloo) );
|
cntlo64 u13 (.clk(clk), .i(a), .o(cntloo) );
|
|
//cntlz64 u12 (.i(a), .o(cntlzo) );
|
|
//cntlo64 u13 (.i(a), .o(cntloo) );
|
|
|
reg [1:0] shftop;
|
reg [1:0] shftop;
|
wire [63:0] shfto;
|
wire [63:0] shfto;
|
reg [63:0] masko;
|
wire [63:0] masko;
|
reg [63:0] bfextd;
|
reg [63:0] bfextd;
|
wire [127:0] shlxo = {64'd0,a} << b[5:0];
|
wire [63:0] rolo;
|
wire [127:0] shruxo = {a,64'd0} >> b[5:0];
|
wire [15:0] bcdmulo;
|
wire [63:0] shlo = shlxo[63:0];
|
|
wire [63:0] shruo = shruxo[127:64];
|
Raptor64_addsub u21 (xIR,a,b,imm,xAddsubo);
|
wire [63:0] rolo = {shlxo[127:64]|shlxo[63:0]};
|
Raptor64_logic u9 (xIR,a,b,imm,xLogico);
|
wire [63:0] roro = {shruxo[127:64]|shruxo[63:0]};
|
Raptor64_set u15 (xIR,a,b,imm,xSeto);
|
wire [63:0] shro = ~(~a >> b[5:0]);
|
Raptor64_bitfield u16(xIR, rolo, b, xBitfieldo, masko);
|
// generate mask
|
Raptor64_shift u17 (xIR, a, b, masko, xShifto);
|
wire [5:0] mb = xIR[12:7];
|
BCDMul2 u22 (a[7:0],b[7:0],bcdmulo);
|
wire [5:0] me = xIR[18:13];
|
|
integer nn;
|
wire aeqz = a==64'd0;
|
always @(mb or me or nn)
|
wire eq = a==b;
|
for (nn = 0; nn < 64; nn = nn + 1)
|
wire eqi = a==imm;
|
masko[nn] <= (nn >= mb) ^ (nn <= me) ^ (me >= mb);
|
wire lt = $signed(a) < $signed(b);
|
|
wire lti = $signed(a) < $signed(imm);
|
|
wire ltu = a < b;
|
|
wire ltui = a < imm;
|
|
|
always @(xOpcode or xFunc or a or b or imm or as or bs or imms or xpc or
|
always @(xOpcode or xFunc or xFunc5 or a or b or imm or xpc or aeqz 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 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 bcdmulo or fpLooOut or fpZLOut or m_z or m_w or
|
`ifdef TLB
|
`ifdef TLB
|
PageTableAddr or BadVAddr or ASID or tlbo or
|
PageTableAddr or BadVAddr or ASID or tlbo or
|
`endif
|
`endif
|
ASID or EPC or mutex_gate or IPC or CauseCode or TBA or xAXC or nonICacheSeg or rm or
|
ASID or EPC or mutex_gate or IPC or TBA or xAXC or nonICacheSeg or rm or
|
rando
|
rando or errorAddress
|
)
|
)
|
casex(xOpcode)
|
casex(xOpcode)
|
`R:
|
`R:
|
casex(xFunc)
|
casex(xFunc)
|
`COM: xData = ~a;
|
`COM: xData1 = ~a;
|
`NOT: xData = ~|a;
|
`NOT: xData1 = ~|a;
|
`NEG: xData = -a;
|
`NEG: xData1 = -a;
|
`ABS: xData = a[63] ? -a : a;
|
`ABS: xData1 = a[63] ? -a : a;
|
`SGN: xData = a[63] ? 65'h1FFFFFFFF_FFFFFFFF : aeqz ? 65'd0 : 65'd1;
|
`SGN: xData1 = a[63] ? 64'hFFFFFFFF_FFFFFFFF : aeqz ? 64'd0 : 64'd1;
|
`MOV: xData = a;
|
`MOV: xData1 = a;
|
`SQRT: xData = sqrt_out;
|
`SQRT: xData1 = sqrt_out;
|
`SWAP: xData = {a[31:0],a[63:32]};
|
`SWAP: xData1 = {a[31:0],a[63:32]};
|
|
|
`REDOR: xData = |a;
|
`REDOR: xData1 = |a;
|
`REDAND: xData = &a;
|
`REDAND: xData1 = &a;
|
|
|
`CTLZ: xData = cntlzo;
|
`CTLZ: xData1 = cntlzo;
|
`CTLO: xData = cntloo;
|
`CTLO: xData1 = cntloo;
|
`CTPOP: xData = {4'd0,popcnt6(a[5:0])} +
|
`CTPOP: xData1 = {4'd0,popcnt6(a[5:0])} +
|
{4'd0,popcnt6(a[11:6])} +
|
{4'd0,popcnt6(a[11:6])} +
|
{4'd0,popcnt6(a[17:12])} +
|
{4'd0,popcnt6(a[17:12])} +
|
{4'd0,popcnt6(a[23:18])} +
|
{4'd0,popcnt6(a[23:18])} +
|
{4'd0,popcnt6(a[29:24])} +
|
{4'd0,popcnt6(a[29:24])} +
|
{4'd0,popcnt6(a[35:30])} +
|
{4'd0,popcnt6(a[35:30])} +
|
Line 1021... |
Line 848... |
{4'd0,popcnt6(a[47:42])} +
|
{4'd0,popcnt6(a[47:42])} +
|
{4'd0,popcnt6(a[53:48])} +
|
{4'd0,popcnt6(a[53:48])} +
|
{4'd0,popcnt6(a[59:54])} +
|
{4'd0,popcnt6(a[59:54])} +
|
{4'd0,popcnt6(a[63:60])}
|
{4'd0,popcnt6(a[63:60])}
|
;
|
;
|
`SEXT8: xData = {{56{a[7]}},a[7:0]};
|
`SEXT8: xData1 = {{56{a[7]}},a[7:0]};
|
`SEXT16: xData = {{48{a[15]}},a[15:0]};
|
`SEXT16: xData1 = {{48{a[15]}},a[15:0]};
|
`SEXT32: xData = {{32{a[31]}},a[31:0]};
|
`SEXT32: xData1 = {{32{a[31]}},a[31:0]};
|
|
|
`MTSPR: xData = a;
|
`MTSPR: xData1 = a;
|
`MFSPR:
|
`MFSPR:
|
case(xIR[12:7])
|
case(xIR[12:7])
|
`ifdef TLB
|
`ifdef TLB
|
`TLBWired: xData = tlbo;
|
`TLBWired: xData1 = tlbo;
|
`TLBIndex: xData = tlbo;
|
`TLBIndex: xData1 = tlbo;
|
`TLBRandom: xData = tlbo;
|
`TLBRandom: xData1 = tlbo;
|
`TLBPhysPage0: xData = tlbo;
|
`TLBPhysPage0: xData1 = tlbo;
|
`TLBPhysPage1: xData = tlbo;
|
`TLBPhysPage1: xData1 = tlbo;
|
`TLBVirtPage: xData = tlbo;
|
`TLBVirtPage: xData1 = tlbo;
|
`TLBPageMask: xData = tlbo;
|
`TLBPageMask: xData1 = tlbo;
|
`TLBASID: begin
|
`TLBASID: begin
|
xData = 65'd0;
|
xData1 = 64'd0;
|
xData[0] = tlbo[0];
|
xData1[0] = tlbo[0];
|
xData[1] = tlbo[1];
|
xData1[1] = tlbo[1];
|
xData[2] = tlbo[2];
|
xData1[2] = tlbo[2];
|
xData[15:8] = tlbo[15:8];
|
xData1[15:8] = tlbo[15:8];
|
end
|
end
|
`PageTableAddr: xData = {PageTableAddr,13'd0};
|
`PageTableAddr: xData1 = {PageTableAddr,13'd0};
|
`BadVAddr: xData = {BadVAddr,13'd0};
|
`BadVAddr: xData1 = {BadVAddr,13'd0};
|
`endif
|
`endif
|
`ASID: xData = ASID;
|
`ASID: xData1 = ASID;
|
`Tick: xData = tick;
|
`Tick: xData1 = tick;
|
`EPC: xData = EPC;
|
`EPC: xData1 = EPC;
|
`IPC: xData = IPC;
|
`IPC: xData1 = IPC;
|
`CauseCode: xData = CauseCode;
|
`TBA: xData1 = TBA;
|
`TBA: xData = TBA;
|
`ERRADR: xData1 = errorAddress;
|
`AXC: xData = xAXC;
|
`AXC: xData1 = xAXC;
|
`NON_ICACHE_SEG: xData = nonICacheSeg;
|
`NON_ICACHE_SEG: xData1 = nonICacheSeg;
|
`FPCR: xData = FPC;
|
`FPCR: xData1 = FPC;
|
`RAND: xData = rando;
|
`RAND: xData1 = rando;
|
`SRAND1: xData = {m_z2,m_z1};
|
`SRAND1: xData1 = m_z;
|
`SRAND2: xData = {m_w2,m_w1};
|
`SRAND2: xData1 = m_w;
|
`INSNKEY: xData = insnkey;
|
`INSNKEY: xData1 = insnkey;
|
default: xData = 65'd0;
|
// `PCHISTORIC: xData1 = pchistoric;
|
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`OMG: xData = mutex_gate[a[5:0]];
|
`OMG: xData1 = mutex_gate[a[5:0]];
|
`CMG: xData = mutex_gate[a[5:0]];
|
`CMG: xData1 = mutex_gate[a[5:0]];
|
`OMGI: begin
|
`OMGI: begin
|
xData = mutex_gate[xIR[12:7]];
|
xData1 = mutex_gate[xIR[12:7]];
|
$display("mutex_gate[%d]=%d",xIR[12:7],mutex_gate[xIR[12:7]]);
|
$display("mutex_gate[%d]=%d",xIR[12:7],mutex_gate[xIR[12:7]]);
|
end
|
end
|
`CMGI: xData = mutex_gate[xIR[12:7]];
|
`CMGI: xData1 = mutex_gate[xIR[12:7]];
|
default: xData = 65'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`RR:
|
`RR:
|
case(xFunc)
|
case(xFunc)
|
`ADD: xData = a + b;
|
`CMP: xData1 = lt ? 64'hFFFFFFFFFFFFF : eq ? 64'd0 : 64'd1;
|
`ADDU: xData = a + b;
|
`CMPU: xData1 = ltu ? 64'hFFFFFFFFFFFFF : eq ? 64'd0 : 64'd1;
|
`SUB: xData = a - b;
|
`MIN: xData1 = lt ? a : b;
|
`SUBU: xData = a - b;
|
`MAX: xData1 = lt ? b : a;
|
`CMP: xData = lt ? 64'hFFFFFFFFFFFFF : eq ? 64'd0 : 64'd1;
|
`MOVZ: xData1 = b;
|
`CMPU: xData = ltu ? 64'hFFFFFFFFFFFFF : eq ? 64'd0 : 64'd1;
|
`MOVNZ: xData1 = b;
|
`SEQ: xData = eq;
|
`MULS: xData1 = mult_out[63:0];
|
`SNE: xData = !eq;
|
`MULU: xData1 = mult_out[63:0];
|
`SLT: xData = lt;
|
`DIVS: xData1 = div_q;
|
`SLE: xData = lt|eq;
|
`DIVU: xData1 = div_q;
|
`SGT: xData = !(lt|eq);
|
`MODU: xData1 = div_r;
|
`SGE: xData = !lt;
|
`MODS: xData1 = div_r;
|
`SLTU: xData = ltu;
|
`BCD_MUL: xData1 = bcdmulo;
|
`SLEU: xData = ltu|eq;
|
default: xData1 = 64'd0;
|
`SGTU: xData = !(ltu|eq);
|
|
`SGEU: xData = !ltu;
|
|
`AND: xData = a & b;
|
|
`OR: xData = a | b;
|
|
`XOR: xData = a ^ b;
|
|
`ANDC: xData = a & ~b;
|
|
`NAND: xData = ~(a & b);
|
|
`NOR: xData = ~(a | b);
|
|
`XNOR: xData = ~(a ^ b);
|
|
`ORC: xData = a | ~b;
|
|
`MIN: xData = lt ? a : b;
|
|
`MAX: xData = lt ? b : a;
|
|
`MOVZ: xData = b;
|
|
`MOVNZ: xData = b;
|
|
`MULS: xData = mult_out[63:0];
|
|
`MULU: xData = mult_out[63:0];
|
|
`DIVS: xData = div_q;
|
|
`DIVU: xData = div_q;
|
|
`MOD: xData = div_r;
|
|
`SHL: xData = shlo;
|
|
`SHRU: xData = shruo;
|
|
`ROL: xData = rolo;
|
|
`ROR: xData = roro;
|
|
`SHR: xData = shro;
|
|
`ROLAM: xData = rolo & masko;
|
|
`BCD_ADD: xData = bcdaddo;
|
|
`BCD_SUB: xData = bcdsubo;
|
|
default: xData = 65'd0;
|
|
endcase
|
|
`SHFTI:
|
|
case(xFunc5)
|
|
`SHLI: xData = shlo;
|
|
`SHRUI: xData = shruo;
|
|
`ROLI: xData = rolo;
|
|
`RORI: xData = roro;
|
|
`SHRI: xData = shro;
|
|
`ROLAMI: xData = rolo & masko;
|
|
`BFINS: begin for (n = 0; n < 64; n = n + 1) xData[n] = masko[n] ? rolo[n] : b[n]; xData[64] = 1'b0; end
|
|
`BFSET: begin for (n = 0; n < 64; n = n + 1) xData[n] = masko[n] ? 1'b1 : b[n]; xData[64] = 1'b0; end
|
|
`BFCLR: begin for (n = 0; n < 64; n = n + 1) xData[n] = masko[n] ? 1'b0 : b[n]; xData[64] = 1'b0; end
|
|
`BFCHG: begin for (n = 0; n < 64; n = n + 1) xData[n] = masko[n] ? ~b[n] : b[n]; xData[64] = 1'b0; end
|
|
`BFEXT: begin for (n = 0; n < 64; n = n + 1) bfextd[n] = masko[n] ? b[n] : 1'b0; xData = bfextd >> mb; end
|
|
default: xData = 65'd0;
|
|
endcase
|
endcase
|
`BTRR:
|
`BTRR:
|
case(xFunc5)
|
case(xFunc5)
|
`LOOP: xData = b - 64'd1;
|
`LOOP: xData1 = b - 64'd1;
|
default: xData = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`SETLO: xData = {{32{xIR[31]}},xIR[31:0]};
|
`SETLO: xData1 = {{32{xIR[31]}},xIR[31:0]};
|
`SETHI: xData = {xIR[31:0],a[31:0]};
|
`SETHI: xData1 = {xIR[31:0],a[31:0]};
|
`ADDI: xData = a + imm;
|
`CMPI: xData1 = lti ? 64'hFFFFFFFFFFFFF : eqi ? 64'd0 : 64'd1;
|
`ADDUI: xData = a + imm;
|
`CMPUI: xData1 = ltui ? 64'hFFFFFFFFFFFFF : eqi ? 64'd0 : 64'd1;
|
`SUBI: xData = a - imm;
|
`MULSI: xData1 = mult_out[63:0];
|
`SUBUI: xData = a - imm;
|
`MULUI: xData1 = mult_out[63:0];
|
`CMPI: xData = lti ? 64'hFFFFFFFFFFFFF : eqi ? 64'd0 : 64'd1;
|
`DIVSI: xData1 = div_q;
|
`CMPUI: xData = ltui ? 64'hFFFFFFFFFFFFF : eqi ? 64'd0 : 64'd1;
|
`DIVUI: xData1 = div_q;
|
`MULSI: xData = mult_out[63:0];
|
|
`MULUI: xData = mult_out[63:0];
|
|
`DIVSI: xData = div_q;
|
|
`DIVUI: xData = div_q;
|
|
`ANDI: xData = a & imm;
|
|
`ORI: xData = a | imm;
|
|
`XORI: xData = a ^ imm;
|
|
`SEQI: xData = eqi;
|
|
`SNEI: xData = !eqi;
|
|
`SLTI: xData = lti;
|
|
`SLEI: xData = lti|eqi;
|
|
`SGTI: xData = !(lti|eqi);
|
|
`SGEI: xData = !lti;
|
|
`SLTUI: xData = ltui;
|
|
`SLEUI: xData = ltui|eqi;
|
|
`SGTUI: xData = !(ltui|eqi);
|
|
`SGEUI: xData = !ltui;
|
|
`INB,`INCH,`INH,`INW,`INCU,`INHU,`INBU:
|
`INB,`INCH,`INH,`INW,`INCU,`INHU,`INBU:
|
xData = a + imm;
|
xData1 = a + imm;
|
`OUTB,`OUTC,`OUTH,`OUTW:
|
`OUTB,`OUTC,`OUTH,`OUTW:
|
xData = a + imm;
|
xData1 = a + imm;
|
`LW,`LH,`LC,`LB,`LHU,`LCU,`LBU,`LWR,`LF,`LFD,`LP,`LFP,`LFDP,`LEA:
|
`LW,`LH,`LC,`LB,`LHU,`LCU,`LBU,`LWR,`LF,`LFD,`LP,`LFP,`LFDP,`LEA:
|
xData = a + imm;
|
xData1 = a + imm;
|
`SW,`SH,`SC,`SB,`SWC,`SF,`SFD,`SP,`SFP,`SFDP:
|
`SW,`SH,`SC,`SB,`SWC,`SF,`SFD,`SP,`SFP,`SFDP:
|
xData = a + imm;
|
xData1 = a + imm;
|
`MEMNDX:
|
`MEMNDX:
|
xData = a + b + imm;
|
xData1 = a + b + imm;
|
`SM: xData = a + {popcnt36(xIR[31:0]),3'b000}-64'd8;
|
`SM: xData1 = a + {popcnt36(xIR[31:0]),3'b000}-64'd8;
|
`LM: xData = a + {popcnt36(xIR[31:0]),3'b000}-64'd8;
|
`LM: xData1 = a + {popcnt36(xIR[31:0]),3'b000}-64'd8;
|
`TRAPcc: xData = fnIncPC(xpc);
|
`TRAPcc: xData1 = fnIncPC(xpc);
|
`TRAPcci: xData = fnIncPC(xpc);
|
`TRAPcci: xData1 = fnIncPC(xpc);
|
`CALL: xData = fnIncPC(xpc);
|
`CALL: xData1 = fnIncPC(xpc);
|
`JAL: xData = xpc + {xIR[29:25],2'b00};
|
`JAL: xData1 = xpc + {xIR[29:25],2'b00};
|
`RET: xData = a + imm;
|
`RET: xData1 = a + imm;
|
`FPLOO: xData = fpLooOut;
|
`FPLOO: xData1 = fpLooOut;
|
`FPZL: xData = fpZLOut;
|
`FPZL: xData1 = fpZLOut;
|
`ifdef FLOATING_POINT
|
`ifdef FLOATING_POINT
|
`FP:
|
`FP:
|
case(xFunc6)
|
case(xFunc6)
|
`FDADD: xData = daddsub_result;
|
`FDADD: xData1 = daddsub_result;
|
`FDSUB: xData = daddsub_result;
|
`FDSUB: xData1 = daddsub_result;
|
`FDMUL: xData = dmul_result;
|
`FDMUL: xData1 = dmul_result;
|
`FDDIV: xData = ddiv_result;
|
`FDDIV: xData1 = ddiv_result;
|
`FDI2F: xData = i2f_result;
|
`FDI2F: xData1 = i2f_result;
|
`FDF2I: xData = f2i_result;
|
`FDF2I: xData1 = f2i_result;
|
`FDCUN: xData = dcmp_result;
|
`FDCUN: xData1 = dcmp_result;
|
`FDCEQ: xData = dcmp_result;
|
`FDCEQ: xData1 = dcmp_result;
|
`FDCNE: xData = dcmp_result;
|
`FDCNE: xData1 = dcmp_result;
|
`FDCLT: xData = dcmp_result;
|
`FDCLT: xData1 = dcmp_result;
|
`FDCLE: xData = dcmp_result;
|
`FDCLE: xData1 = dcmp_result;
|
`FDCGT: xData = dcmp_result;
|
`FDCGT: xData1 = dcmp_result;
|
`FDCGE: xData = dcmp_result;
|
`FDCGE: xData1 = dcmp_result;
|
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`endif
|
`endif
|
default: xData = 65'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
|
|
|
always @(xData1,xBitfieldo,xLogico,xShifto,xSeto,xAddsubo)
|
|
xData = xData1|xBitfieldo|xLogico|xShifto|xSeto|xAddsubo;
|
|
|
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(xAddsubo[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(xAddsubo[63]), .v(v_rr));
|
|
|
wire dbz_error = ((xOpcode==`DIVSI||xOpcode==`DIVUI) && imm==64'd0) || (xOpcode==`RR && (xFunc==`DIVS || xFunc==`DIVU) && b==64'd0);
|
wire dbz_error = ((xOpcode==`DIVSI||xOpcode==`DIVUI) && imm==64'd0) || (xOpcode==`RR && (xFunc==`DIVS || xFunc==`DIVU) && b==64'd0);
|
wire ovr_error = ((xOpcode==`ADDI || xOpcode==`SUBI) && v_ri) || ((xOpcode==`RR && (xFunc==`SUB || xFunc==`ADD)) && v_rr);
|
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 illegal_insn = (xOpcode==7'd19 || xOpcode==7'd47 || xOpcode==7'd54 || xOpcode==7'd55 || xOpcode==7'd63 || xOpcode==7'd71 ||
|
|
xOpcode==7'd90 || xOpcode==7'd91 || xOpcode==7'd92 || xOpcode==7'd93 || xOpcode==7'd106 || xOpcode==7'd107)
|
|
;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Pipeline advance and stall logic
|
|
//-----------------------------------------------------------------------------
|
wire xIsSqrt = xOpcode==`R && xFunc==`SQRT;
|
wire xIsSqrt = xOpcode==`R && xFunc==`SQRT;
|
wire xIsMult = (xOpcode==`RR && (xFunc==`MULU || xFunc==`MULS)) ||
|
wire xIsMult = (xOpcode==`RR && (xFunc==`MULU || xFunc==`MULS)) || xOpcode==`MULSI || xOpcode==`MULUI;
|
xOpcode==`MULSI || xOpcode==`MULUI;
|
wire xIsDiv = (xOpcode==`RR && (xFunc==`DIVU || xFunc==`DIVS || xFunc==`MODU || xFunc==`MODS)) || xOpcode==`DIVSI || xOpcode==`DIVUI;
|
wire xIsDiv = (xOpcode==`RR && (xFunc==`DIVU || xFunc==`DIVS)) ||
|
|
xOpcode==`DIVSI || xOpcode==`DIVUI;
|
|
wire xIsCnt = xOpcode==`R && (xFunc==`CTLZ || xFunc==`CTLO || xFunc==`CTPOP);
|
wire xIsCnt = xOpcode==`R && (xFunc==`CTLZ || xFunc==`CTLO || xFunc==`CTPOP);
|
reg m1IsCnt,m2IsCnt;
|
reg m1IsCnt,m2IsCnt;
|
|
|
wire xIsLoad =
|
wire xIsLoad =
|
xOpcode==`LW || xOpcode==`LH || xOpcode==`LB || xOpcode==`LWR ||
|
xOpcode==`LW || xOpcode==`LH || xOpcode==`LB || xOpcode==`LWR ||
|
Line 1268... |
Line 1045... |
wire xIsFP = xOpcode==`FP;
|
wire xIsFP = xOpcode==`FP;
|
wire xneedBus = xIsIO;
|
wire xneedBus = xIsIO;
|
wire m1needBus = (m1IsLoad & !m1IsCacheElement) || m1IsStore || m1IsIO;
|
wire m1needBus = (m1IsLoad & !m1IsCacheElement) || m1IsStore || m1IsIO;
|
wire m2needBus = (m2IsLoad | m2IsStore);
|
wire m2needBus = (m2IsLoad | m2IsStore);
|
|
|
|
wire xRtz = xRt[4:0]==5'd0;
|
|
wire m1Rtz = m1Rt[4:0]==5'd0;
|
|
wire m2Rtz = m2Rt[4:0]==5'd0;
|
|
|
// 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.
|
wire StallR = (((xIsLoad||xIsIn||xIsCnt) && ((xRt==dRa)||(xRt==dRb)||(xRt==dRc)) && !xRtz) || xIsSWC) ||
|
wire StallR = (((xIsLoad||xIsIn||xIsCnt) && ((xRt==dRa)||(xRt==dRb)||(xRt==dRt))) || xIsSWC) ||
|
(((m1IsLoad||m1IsIn||m1IsCnt) && ((m1Rt==dRa)||(m1Rt==dRb)||(m1Rt==dRc)) && !m1Rtz)) ||
|
(((m1IsLoad||m1IsIn||m1IsCnt) && ((m1Rt==dRa)||(m1Rt==dRb)||(m1Rt==dRt)))) ||
|
(((m2IsLoad||m2IsCnt) && ((m2Rt==dRa)||(m2Rt==dRb)||(m2Rt==dRc)) && !m2Rtz))
|
(((m2IsLoad||m2IsCnt) && ((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)) ||
|
( m1IsLoad & m1IsCacheElement & (m2IsStore|wIsStore)) // wait for a preceding store to complete
|
( m1IsLoad & m1IsCacheElement & (m2IsStore|wIsStore)) // wait for a preceding store to complete
|
;
|
;
|
wire StallM2 = icaccess|dcaccess;
|
wire StallM2 = m2needBus & (icaccess|dcaccess);
|
|
|
wire advanceT = !resetA;
|
wire advanceT = !resetA;
|
assign advanceW = advanceT;
|
assign advanceW = advanceT;
|
wire advanceM2 = advanceW &&
|
wire advanceM2 = advanceW &&
|
((m2IsLoad || m2IsStore) ? (ack_i|err_i) : 1'b1) &&
|
((m2IsLoad || m2IsStore) ? (ack_i|err_i) : 1'b1) &&
|
Line 1302... |
Line 1082... |
1'b1) &
|
1'b1) &
|
!StallX;
|
!StallX;
|
wire advanceR = advanceX & !StallR;
|
wire advanceR = advanceX & !StallR;
|
wire advanceI = advanceR & (ICacheOn ? ihit : ibufrdy);
|
wire advanceI = advanceR & (ICacheOn ? ihit : ibufrdy);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Cache loading control
|
|
//-----------------------------------------------------------------------------
|
|
wire pipelineEmpty =
|
|
(dOpcode==`NOPI || dOpcode[6:4]==`IMM) && // and the pipeline is flushed
|
|
(xOpcode==`NOPI || xOpcode[6:4]==`IMM) &&
|
|
m1Opcode==`NOPI &&
|
|
m2Opcode==`NOPI
|
|
;
|
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 triggerICacheLoad1 = ICacheAct && !ihit && !triggerDCacheLoad && // There is a miss
|
wire triggerICacheLoad1 = ICacheAct && !ihit && !triggerDCacheLoad && // There is a miss
|
!(icaccess | dcaccess) && // caches are not active
|
!(icaccess | dcaccess) && // caches are not active
|
(dOpcode==`NOPI || dOpcode[6:4]==`IMM) && // and the pipeline is flushed
|
pipelineEmpty;
|
(xOpcode==`NOPI || xOpcode[6:4]==`IMM) &&
|
|
m1Opcode==`NOPI &&
|
|
m2Opcode==`NOPI
|
|
;
|
|
wire triggerICacheLoad2 = (!ICacheAct && !ibufrdy) && !triggerDCacheLoad && // There is a miss
|
wire triggerICacheLoad2 = (!ICacheAct && !ibufrdy) && !triggerDCacheLoad && // There is a miss
|
!(icaccess | dcaccess) // caches are not active
|
!(icaccess | dcaccess) && // caches are not active
|
;
|
pipelineEmpty;
|
|
|
wire triggerICacheLoad = triggerICacheLoad1 | triggerICacheLoad2;
|
wire triggerICacheLoad = triggerICacheLoad1 | triggerICacheLoad2;
|
|
|
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
|
`ifdef TLB
|
wire M1exception_pending = advanceM1 & (m1IsLoad|m1IsStore) & DTLBMiss;
|
wire M1exception_pending = advanceM1 & (m1IsLoad|m1IsStore) & DTLBMiss;
|
Line 1329... |
Line 1115... |
`endif
|
`endif
|
wire exception_pending = EXexception_pending | M1exception_pending;
|
wire exception_pending = EXexception_pending | M1exception_pending;
|
|
|
reg prev_nmi,nmi_edge;
|
reg prev_nmi,nmi_edge;
|
|
|
always @(dOpcode or dIR)
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
|
|
always @(dOpcode or dIR or dIsLSPair)
|
begin
|
begin
|
ndIR <= dIR;
|
ndIR <= dIR;
|
if (dOpcode==`SP || dOpcode==`LP || dOpcode==`SFP || dOpcode==`LFP || dOpcode==`SFDP || dOpcode==`LFDP) begin
|
if (dIsLSPair) begin
|
ndIR[25] <= 1'b1;
|
ndIR[25] <= 1'b1;
|
ndIR[3] <= 1'b1;
|
ndIR[3] <= 1'b1;
|
end
|
end
|
else if ((dOpcode==`LM || dOpcode==`SM) && dIR[31:0]!=32'd0) begin
|
else if ((dOpcode==`LM || dOpcode==`SM) && dIR[31:0]!=32'd0) begin
|
$display("LM/SM %h",dIR[31:0]);
|
$display("LM/SM %h",dIR[31:0]);
|
Line 1405... |
Line 1194... |
else
|
else
|
ndIR[31] <= 1'b0;
|
ndIR[31] <= 1'b0;
|
end
|
end
|
end
|
end
|
|
|
reg m1clkoff,m2clkoff,m3clkoff,m4clkoff,wclkoff;
|
//-----------------------------------------------------------------------------
|
reg dFip,xFip,m1Fip,m2Fip,m3Fip,m4Fip,wFip;
|
|
reg cyc1;
|
|
|
|
//---------------------------------------------------------
|
|
// Register file.
|
// Register file.
|
//---------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
wire [63:0] nxt_a, nxt_b, nxt_c;
|
wire [63:0] nxt_a, nxt_b, nxt_c;
|
|
|
Raptor64_regfile u5
|
Raptor64_regfile u5
|
(
|
(
|
Line 1439... |
Line 1224... |
.nxt_a(nxt_a),
|
.nxt_a(nxt_a),
|
.nxt_b(nxt_b),
|
.nxt_b(nxt_b),
|
.nxt_c(nxt_c)
|
.nxt_c(nxt_c)
|
);
|
);
|
|
|
|
Raptor64_SetOperandRegs u7
|
|
(
|
|
.rst(rst_i),
|
|
.clk(clk),
|
|
.advanceI(advanceI),
|
|
.advanceR(advanceR),
|
|
.advanceX(advanceX),
|
|
.b(b),
|
|
.AXC(AXC),
|
|
.insn(insn),
|
|
.xIR(xIR),
|
|
.dRa(dRa),
|
|
.dRb(dRb),
|
|
.dRc(dRc)
|
|
);
|
|
|
|
Raptor64_SetTargetRegister u8
|
|
(
|
|
.rst(rst_i),
|
|
.clk(clk),
|
|
.advanceR(advanceR),
|
|
.advanceX(advanceX),
|
|
.dIR(dIR),
|
|
.dAXC(dAXC),
|
|
.xRt(xRt)
|
|
);
|
|
|
|
reg [5:0] pchi;
|
|
//vtdl #(64,64) u23
|
|
//(
|
|
// .clk(clk),
|
|
// .ce(advanceI & pccap),
|
|
// .a(pchi),
|
|
// .d(pc),
|
|
// .q(pchistoric)
|
|
//);
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
if (rst_i) begin
|
if (rst_i) begin
|
bte_o <= 2'b00;
|
bte_o <= 2'b00;
|
cti_o <= 3'b000;
|
cti_o <= 3'b000;
|
|
iocyc_o <= 1'b0;
|
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 <= 8'h00;
|
sel_o <= 8'h00;
|
adr_o <= 64'd0;
|
adr_o <= 64'd0;
|
dat_o <= 64'd0;
|
dat_o <= 64'd0;
|
|
|
|
pccap <= 1'b1;
|
nonICacheSeg <= 32'hFFFF_FFFD;
|
nonICacheSeg <= 32'hFFFF_FFFD;
|
TBA <= 64'd0;
|
TBA <= 64'd0;
|
pc <= `RESET_VECTOR;
|
pc <= `RESET_VECTOR;
|
m1Opcode <= `NOPI;
|
m1Opcode <= `NOPI;
|
m2Opcode <= `NOPI;
|
m2Opcode <= `NOPI;
|
wOpcode <= `NOPI;
|
wOpcode <= `NOPI;
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
dRt <= 9'd0;
|
xRtZero <= 1'b0;
|
tRt <= 9'd0;
|
tRt <= 9'd0;
|
wRt <= 9'd0;
|
wRt <= 9'd0;
|
m1Rt <= 9'd0;
|
m1Rt <= 9'd0;
|
m2Rt <= 9'd0;
|
m2Rt <= 9'd0;
|
tData <= 64'd0;
|
tData <= 64'd0;
|
Line 1476... |
Line 1300... |
m2IsStore <= 1'b0;
|
m2IsStore <= 1'b0;
|
wIsStore <= 1'b0;
|
wIsStore <= 1'b0;
|
m1IsIO <= 1'b0;
|
m1IsIO <= 1'b0;
|
icaccess <= 1'b0;
|
icaccess <= 1'b0;
|
dcaccess <= 1'b0;
|
dcaccess <= 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;
|
Line 1494... |
Line 1317... |
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
m1pcv <= 1'b0;
|
m1pcv <= 1'b0;
|
m2pcv <= 1'b0;
|
m2pcv <= 1'b0;
|
wpcv <= 1'b0;
|
wpcv <= 1'b0;
|
tick <= 32'd0;
|
tick <= 64'd0;
|
cstate <= IDLE;
|
cstate <= IDLE;
|
dImm <= 64'd0;
|
|
AXC <= 4'd0;
|
AXC <= 4'd0;
|
dAXC <= 4'd0;
|
dAXC <= 4'd0;
|
xirqf <= 1'b0;
|
xirqf <= 1'b0;
|
xextype <= 8'h00;
|
dextype <= 9'h00;
|
|
xextype <= 9'h00;
|
|
m1extype <= 9'h00;
|
|
m2extype <= 9'h00;
|
|
wextype <= 9'h00;
|
|
textype <= 9'h00;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xpc <= 64'd0;
|
xpc <= 64'd0;
|
a <= 64'd0;
|
a <= 64'd0;
|
b <= 64'd0;
|
b <= 64'd0;
|
imm <= 64'd0;
|
imm <= 64'd0;
|
xRt <= 9'd0;
|
|
clk_en <= 1'b1;
|
clk_en <= 1'b1;
|
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;
|
Line 1518... |
Line 1344... |
ICacheOn <= 1'b0;
|
ICacheOn <= 1'b0;
|
ibuftag0 <= 64'h0;
|
ibuftag0 <= 64'h0;
|
ibuftag1 <= 64'h0;
|
ibuftag1 <= 64'h0;
|
m1IsCacheElement <= 1'b0;
|
m1IsCacheElement <= 1'b0;
|
dtinit <= 1'b1;
|
dtinit <= 1'b1;
|
`ifdef RAS_PREDICTION
|
|
ras_sp <= 6'd63;
|
ras_sp <= 6'd63;
|
`endif
|
|
im <= 1'b1;
|
im <= 1'b1;
|
im1 <= 1'b1;
|
im1 <= 1'b1;
|
// These must be non-zero in order to produce random numbers
|
// These must be non-zero in order to produce random numbers
|
// We set them here in case the user doesn't bother to set them.
|
// We set them here in case the user doesn't bother to set them.
|
m_z1 <= 32'h01234567;
|
m_z <= 64'h0123456789ABCDEF;
|
m_z2 <= 32'h89ABCDEF;
|
m_w <= 64'h8888888877777777;
|
m_w1 <= 32'h88888888;
|
|
m_w2 <= 32'h77777777;
|
|
insnkey <= 42'd0;
|
insnkey <= 42'd0;
|
end
|
end
|
else begin
|
else begin
|
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
Line 1561... |
Line 1383... |
|
|
if (sys_adv && sys_adr[63:5]==resv_address)
|
if (sys_adv && sys_adr[63:5]==resv_address)
|
resv_address <= 59'd0;
|
resv_address <= 59'd0;
|
`endif
|
`endif
|
|
|
//---------------------------------------------------------
|
wrhit <= 1'b0;
|
// TRAILER:
|
|
// - placeholder to allow the use of synchronous register
|
|
// memory
|
|
//---------------------------------------------------------
|
|
if (advanceT) begin
|
|
tRt <= 9'd0;
|
|
tData <= 64'd0;
|
|
end
|
|
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// WRITEBACK:
|
// IFETCH:
|
// - update the register file with results
|
// - check for external hardware interrupt
|
// - record exception address and type
|
// - fetch instruction
|
// - jump to exception handler routine (below)
|
// - increment PC
|
|
// - set special register defaults for some instructions
|
|
// Outputs:
|
|
// - d???? signals
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
if (advanceW) begin
|
if (advanceI) begin
|
textype <= wextype;
|
dpcv <= 1'b1;
|
wextype <= `EX_NON;
|
dAXC <= AXC;
|
if (wextype==`EX_IRQ)
|
dextype <= `EX_NON;
|
$display("wextype=IRQ");
|
if (nmi_edge & !StatusHWI & !im1) begin
|
tRt <= wRt;
|
$display("*****************");
|
tData <= wData;
|
$display("NMI edge detected");
|
if (wRt!=5'd0)
|
$display("*****************");
|
$display("Writing regfile[%d:%d] with %h", wRt[8:5],wRt[4:0], wData);
|
StatusHWI <= 1'b1;
|
case(wOpcode)
|
nmi_edge <= 1'b0;
|
`LSH:
|
dhwxtype <= 2'b01;
|
case (wRt)
|
dextype <= `EX_NMI;
|
`SR: begin
|
dIR <= `NOP_INSN;
|
bu_im <= wData[31];
|
|
im <= wData[15];
|
|
FXE <= wData[12];
|
|
end
|
end
|
default: ;
|
else if (irq_i & !im & !StatusHWI & !im1) begin
|
endcase
|
$display("*****************");
|
endcase
|
$display("IRQ detected");
|
wRt <= 9'd0;
|
$display("*****************");
|
wData <= 64'd0;
|
bu_im <= 1'b0;
|
wOpcode <= `NOPI;
|
im <= 1'b1;
|
wIsStore <= 1'b0;
|
StatusHWI <= 1'b1;
|
wLdPC <= 1'b0;
|
dhwxtype <= 2'b10;
|
if (|whwxtype) begin
|
dextype <= `EX_IRQ;
|
dhwxtype <= 2'b00;
|
dIR <= `NOP_INSN;
|
xhwxtype <= 2'b00;
|
|
m1hwxtype <= 2'b00;
|
|
m2hwxtype <= 2'b00;
|
|
whwxtype <= 2'b00;
|
|
end
|
end
|
clk_en <= 1'b1;
|
// Are we filling the pipeline with NOP's as a result of a previous
|
if (wclkoff)
|
// hardware interrupt ?
|
clk_en <= 1'b0;
|
else if (|dhwxtype|dFip)
|
wclkoff <= 1'b0;
|
dIR <= `NOP_INSN;
|
m1clkoff <= 1'b0;
|
`ifdef TLB
|
m2clkoff <= 1'b0;
|
else if (ITLBMiss)
|
if (wFip) begin
|
dIR <= `NOP_INSN;
|
wFip <= 1'b0;
|
`endif
|
m2Fip <= 1'b0;
|
else begin
|
m1Fip <= 1'b0;
|
if (((iOpcode==`SM || iOpcode==`LM) && insn[31:0]!=32'd0) || (iIsLSPair && !insn[25]))
|
xFip <= 1'b0;
|
im1 <= 1'b1;
|
dFip <= 1'b0;
|
else
|
|
im1 <= 1'b0;
|
|
if (iIsLSPair && insn[25]==1'b1) begin
|
|
dIR <= `NOP_INSN;
|
|
pc <= fnIncPC(pc);
|
end
|
end
|
|
else if ((iOpcode==`SM || iOpcode==`LM) && insn[31:0]==32'd0) begin
|
|
dIR <= `NOP_INSN;
|
|
pc <= fnIncPC(pc);
|
end
|
end
|
|
else
|
//---------------------------------------------------------
|
dIR <= insn;
|
// MEMORY:
|
`include "insn_dumpsc.v"
|
//---------------------------------------------------------
|
|
if (advanceM2) begin
|
|
wIsStore <= m2IsStore;
|
|
wIR <= m2IR;
|
|
wOpcode <= m2Opcode;
|
|
wFunc <= m2Func;
|
|
wData <= m2Data;
|
|
whwxtype <= m2hwxtype;
|
|
wextype <= (m2IsLoad|m2IsStore)&err_i ? `EX_DBERR : m2extype;
|
|
if (m2extype==`EX_IRQ)
|
|
$display("m2extype=IRQ");
|
|
wRt <= m2Rt;
|
|
wpc <= m2pc;
|
|
wpcv <= m2pcv;
|
|
wclkoff <= m2clkoff;
|
|
wFip <= m2Fip;
|
|
wLdPC <= m2LdPC;
|
|
|
|
m2Rt <= 9'd0;
|
|
m2Opcode <= `NOPI;
|
|
m2IsLoad <= 1'b0;
|
|
m2IsStore <= 1'b0;
|
|
m2IsCnt <= 1'b0;
|
|
m2Func <= 7'd0;
|
|
m2Addr <= 64'd0;
|
|
m2Data <= 64'd0;
|
|
m2clkoff <= 1'b0;
|
|
m2pc <= 64'd0;
|
|
m2extype <= `EX_NON;
|
|
m2LdPC <= 1'b0;
|
|
if ((m2IsLoad|m2IsStore)&err_i)
|
|
errorAddress <= adr_o;
|
|
if (m2extype==`EX_NON) begin
|
|
case(m2Opcode)
|
|
`MISC:
|
|
if (m2Func==`SYSJMP || m2Func==`SYSCALL)
|
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
wData <= {dat_i[63:2],2'b00};
|
|
end
|
end
|
`SH,`SC,`SB,`SW,`SWC,`SM,`SF,`SFD,`SSH,`SSW,`SP,`SFP,`SFDP:
|
// Cause the prefixed instruction to inherit the address of the immediate
|
|
// prefix, by not resetting the address.
|
|
if (dOpcode[6:4]!=`IMM)
|
|
dpc <= pc;
|
|
`ifdef TLB
|
|
if (ITLBMiss) begin
|
|
$display("TLB miss on instruction fetch.");
|
|
StatusEXL <= 1'b1;
|
|
BadVAddr <= pc[63:13];
|
|
dextype <= `EX_TLBI;
|
|
EPC <= pc;
|
|
end
|
|
else
|
|
`endif
|
begin
|
begin
|
cyc_o <= 1'b0;
|
dbranch_taken <= 1'b0;
|
stb_o <= 1'b0;
|
if (iIsLSPair && !insn[25])
|
we_o <= 1'b0;
|
;
|
sel_o <= 4'h0;
|
else if ((iOpcode==`LM || iOpcode==`SM) && insn[31:0]!=32'd0)
|
|
;
|
|
else begin
|
|
if (pc!=64'hC)
|
|
pc <= fnIncPC(pc);
|
end
|
end
|
`LH,`LF,`LSH,`LFP:
|
case(iOpcode)
|
|
`MISC:
|
|
case(iFunc)
|
|
`FIP: dFip <= 1'b1;
|
|
default: ;
|
|
endcase
|
|
// 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
|
begin
|
cyc_o <= 1'b0;
|
ras[ras_sp] <= fnIncPC(pc);
|
stb_o <= 1'b0;
|
ras_sp <= ras_sp - 6'd1;
|
sel_o <= 8'h00;
|
dbranch_taken <= 1'b1;
|
wData <= sel_o[7] ? {{32{dat_i[63]}},dat_i[63:32]}:{{32{dat_i[31]}},dat_i[31: 0]};
|
pc <= jmp_tgt;
|
end
|
end
|
`LW,`LWR,`LM,`LFD,`LSW,`LP,`LFDP:
|
`RET:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
pc <= ras[ras_sp + 6'd1];
|
stb_o <= 1'b0;
|
ras_sp <= ras_sp + 6'd1;
|
sel_o <= 8'h00;
|
if (ras[ras_sp+6'd1]==64'hFFFF_FFFF_FFFF_C100)
|
wData <= dat_i;
|
$display("****** C100 reached *****");
|
end
|
end
|
`LHU:
|
`JMP:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
dbranch_taken <= 1'b1;
|
stb_o <= 1'b0;
|
pc <= jmp_tgt;
|
sel_o <= 8'h00;
|
|
wData <= sel_o[7] ? dat_i[63:32] : dat_i[31: 0];
|
|
end
|
end
|
`LC:
|
`BTRR:
|
begin
|
case(insn[4:0])
|
cyc_o <= 1'b0;
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BRA,`BNR,`BRN,`LOOP:
|
stb_o <= 1'b0;
|
if (predict_taken) begin
|
sel_o <= 8'h00;
|
// $display("Taking predicted branch: %h",{pc[63:4] + {{42{insn[24]}},insn[24:7]},insn[6:5],2'b00});
|
case(sel_o)
|
dbranch_taken <= 1'b1;
|
8'b00000011: wData <= {{48{dat_i[15]}},dat_i[15: 0]};
|
pc <= {pc[63:4] + {{42{insn[24]}},insn[24:7]},insn[6:5],2'b00};
|
8'b00001100: wData <= {{48{dat_i[31]}},dat_i[31:16]};
|
|
8'b00110000: wData <= {{48{dat_i[47]}},dat_i[47:32]};
|
|
8'b11000000: wData <= {{48{dat_i[63]}},dat_i[63:48]};
|
|
default: wData <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
end
|
`LCU:
|
default: ;
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000011: wData <= dat_i[15: 0];
|
|
8'b00001100: wData <= dat_i[31:16];
|
|
8'b00110000: wData <= dat_i[47:32];
|
|
8'b11000000: wData <= dat_i[63:48];
|
|
default: wData <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
endcase
|
|
`ifdef BTB
|
|
`JAL: pc <= btb[pc[7:2]];
|
|
`BTRI:
|
|
if (predict_taken) begin
|
|
dbranch_taken <= 1'b1;
|
|
pc <= btb[pc[7:2]];
|
end
|
end
|
`LB:
|
`endif
|
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
begin
|
begin
|
cyc_o <= 1'b0;
|
if (predict_taken) begin
|
stb_o <= 1'b0;
|
dbranch_taken <= 1'b1;
|
sel_o <= 8'h00;
|
pc <= {pc[63:4] + {{50{insn[29]}},insn[29:20]},insn[19:18],2'b00};
|
case(sel_o)
|
|
8'b00000001: wData <= {{56{dat_i[ 7]}},dat_i[ 7: 0]};
|
|
8'b00000010: wData <= {{56{dat_i[15]}},dat_i[15: 8]};
|
|
8'b00000100: wData <= {{56{dat_i[23]}},dat_i[23:16]};
|
|
8'b00001000: wData <= {{56{dat_i[31]}},dat_i[31:24]};
|
|
8'b00010000: wData <= {{56{dat_i[39]}},dat_i[39:32]};
|
|
8'b00100000: wData <= {{56{dat_i[47]}},dat_i[47:40]};
|
|
8'b01000000: wData <= {{56{dat_i[55]}},dat_i[55:48]};
|
|
8'b10000000: wData <= {{56{dat_i[63]}},dat_i[63:56]};
|
|
default: wData <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
end
|
`LBU:
|
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000001: wData <= dat_i[ 7: 0];
|
|
8'b00000010: wData <= dat_i[15: 8];
|
|
8'b00000100: wData <= dat_i[23:16];
|
|
8'b00001000: wData <= dat_i[31:24];
|
|
8'b00010000: wData <= dat_i[39:32];
|
|
8'b00100000: wData <= dat_i[47:40];
|
|
8'b01000000: wData <= dat_i[55:48];
|
|
8'b10000000: wData <= dat_i[63:56];
|
|
default: wData <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
// Stage tail
|
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
|
else if (advanceR) begin
|
|
dbranch_taken <= 1'b0;
|
|
dextype <= `EX_NON;
|
|
// IMM is "sticky"
|
|
if (dOpcode[6:4]!=`IMM && dOpcode!=`LM && dOpcode!=`SM && !dIsLSPair) begin
|
|
dIR <= `NOP_INSN;
|
|
dpcv <= 1'b0;
|
|
dpc <= `RESET_VECTOR;
|
|
end
|
|
if ((((dOpcode==`SM || dOpcode==`LM) && dIR[31:0]!=32'd0)) || (dIsLSPair && !dIR[25]))
|
|
dIR <= ndIR;
|
|
end
|
|
|
wrhit <= 1'b0;
|
|
//---------------------------------------------------------
|
|
// MEMORY:
|
|
// - I/O instructions are finished
|
|
// - store instructions are started
|
|
// - missed loads are started
|
|
// On a data cache hit for a load, the load is essentially
|
|
// finished in this stage. We switch the opcode to 'NOPI'
|
|
// to cause the pipeline to advance as if a NOPs were
|
|
// present.
|
|
//---------------------------------------------------------
|
|
if (advanceM1) begin
|
|
m2IR <= m1IR;
|
|
m2Opcode <= m1Opcode;
|
|
m2Func <= m1Func;
|
|
m2IsLoad <= m1IsLoad;
|
|
m2IsStore <= m1IsStore;
|
|
m2IsCnt <= m1IsCnt;
|
|
m2Func <= m1Func;
|
|
m2Addr <= pea;
|
|
m2Data <= m1Data;
|
|
m2hwxtype <= m1hwxtype;
|
|
m2extype <= m1IsIO & err_i ? `EX_DBERR : m1extype;
|
|
if (m1extype==`EX_IRQ)
|
|
$display("m1extype=IRQ");
|
|
m2Rt <= m1Rt;
|
|
m2pc <= m1pc;
|
|
m2pcv <= m1pcv;
|
|
m2clkoff <= m1clkoff;
|
|
m2Fip <= m1Fip;
|
|
|
|
m1Rt <= 9'd0;
|
|
m1IsLoad <= 1'b0;
|
|
m1IsStore <= 1'b0;
|
|
m1IsCnt <= 1'b0;
|
|
m1IsIO <= 1'b0;
|
|
m1Opcode <= `NOPI;
|
|
m1Func <= 7'd0;
|
|
m1Data <= 64'd0;
|
|
m1clkoff <= 1'b0;
|
|
m1pc <= 64'd0;
|
|
m1IsCacheElement <= 1'b0;
|
|
m1extype <= `EX_NON;
|
|
|
|
if (m1IsIO&err_i)
|
//-----------------------------------------------------------------------------
|
errorAddress <= adr_o;
|
// RFETCH:
|
|
// Register fetch stage
|
|
//
|
|
// Inputs:
|
|
// - d???? signals
|
|
// Outputs:
|
|
// - x???? signals to EX stage
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
if (advanceR) begin
|
|
xAXC <= dAXC;
|
|
xhwxtype <= dhwxtype;
|
|
xFip <= dFip;
|
|
xextype <= dextype;
|
|
xpc <= dpc;
|
|
xpcv <= dpcv;
|
|
xbranch_taken <= dbranch_taken;
|
|
xRtZero <= 1'b0;
|
|
if (dOpcode==`R && dFunc==`MYST)
|
|
xIR <= nxt_c;
|
|
else
|
|
xIR <= dIR;
|
|
a <= nxt_a;
|
|
b <= nxt_b;
|
|
if (dOpcode==`SHFTI)
|
|
b <= {58'd0,dIR[24:19]};
|
|
c <= nxt_c;
|
|
|
if (m1extype == `EX_NON) begin
|
// Set immediate value
|
case(m1Opcode)
|
if (xOpcode[6:4]==`IMM) begin
|
`MISC:
|
imm <= {xIR[38:0],dIR[24:0]};
|
case(m1Func)
|
|
`SYSJMP,`SYSCALL:
|
|
begin
|
|
m2LdPC <= 1'b1;
|
|
if (!m1IsCacheElement) begin
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= 8'hFF;
|
|
adr_o <= {pea[63:3],3'b000};
|
|
m2Addr <= {pea[63:3],3'b000};
|
|
end
|
end
|
else if (dhit) begin
|
else
|
m2IsLoad <= 1'b0;
|
case(dOpcode)
|
m2Opcode <= `NOPI;
|
`BTRI: imm <= {{44{dIR[19]}},dIR[19:0]};
|
m2Data <= {cdat[63:2],2'b00};
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
|
imm <= {{46{dIR[17]}},dIR[17:0]};
|
|
`ORI: imm <= {39'h0000000000,dIR[24:0]};
|
|
`XORI: imm <= {39'h0000000000,dIR[24:0]};
|
|
`RET: imm <= {39'h00000000,dIR[24:3],3'b000};
|
|
`MEMNDX: imm <= {{50{dIR[19]}},dIR[19:6]};
|
|
default: imm <= {{39{dIR[24]}},dIR[24:0]};
|
|
endcase
|
end
|
end
|
|
// Stage tail
|
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
|
else if (advanceX) begin
|
|
xRtZero <= 1'b1;
|
|
xextype <= `EX_NON;
|
|
xbranch_taken <= 1'b0;
|
|
if (xOpcode[6:4]!=`IMM) begin
|
|
xIR <= `NOP_INSN;
|
|
xpcv <= 1'b0;
|
|
xpc <= `RESET_VECTOR;
|
end
|
end
|
endcase
|
|
`INW:
|
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
m2Data <= dat_i;
|
|
end
|
end
|
`INH:
|
|
begin
|
//---------------------------------------------------------
|
cyc_o <= 1'b0;
|
// EXECUTE:
|
stb_o <= 1'b0;
|
// - perform datapath operation
|
sel_o <= 8'h00;
|
// - perform virtual to physical address translation.
|
m2Data <= sel_o[7] ? {{32{dat_i[63]}},dat_i[63:32]}:{{32{dat_i[31]}},dat_i[31: 0]};
|
// Outputs:
|
|
// - m1???? signals to M1 stage
|
|
//---------------------------------------------------------
|
|
if (advanceX) begin
|
|
m1hwxtype <= xhwxtype;
|
|
m1extype <= xextype;
|
|
m1Fip <= xFip;
|
|
m1Func <= xFunc;
|
|
m1pcv <= xpcv;
|
|
m1pc <= xpc;
|
|
m1IR <= xIR;
|
|
m1IsLoad <= xIsLoad;
|
|
m1IsStore <= xIsStore;
|
|
m1IsCnt <= xIsCnt;
|
|
m1IsIO <= xIsIO;
|
|
m1Opcode <= xOpcode;
|
|
m1Rt <= xRtZero ? 9'd0 : xRt;
|
|
m1Data <= xData;
|
|
m1IsCacheElement <= xisCacheElement;
|
|
if (xOpcode==`MOVZ && !aeqz) begin
|
|
m1Rt <= 9'd0;
|
|
m1Data <= 64'd0;
|
end
|
end
|
`INHU:
|
if (xOpcode==`MOVNZ && aeqz) begin
|
begin
|
m1Rt <= 9'd0;
|
cyc_o <= 1'b0;
|
m1Data <= 64'd0;
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
m2Data <= sel_o[7] ? dat_i[63:32] : dat_i[31: 0];
|
|
end
|
|
`INCH:
|
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000011: m2Data <= {{48{dat_i[15]}},dat_i[15: 0]};
|
|
8'b00001100: m2Data <= {{48{dat_i[31]}},dat_i[31:16]};
|
|
8'b00110000: m2Data <= {{48{dat_i[47]}},dat_i[47:32]};
|
|
8'b11000000: m2Data <= {{48{dat_i[63]}},dat_i[63:48]};
|
|
default: m2Data <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
`INCU:
|
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000011: m2Data <= dat_i[15: 0];
|
|
8'b00001100: m2Data <= dat_i[31:16];
|
|
8'b00110000: m2Data <= dat_i[47:32];
|
|
8'b11000000: m2Data <= dat_i[63:48];
|
|
default: m2Data <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
`INB:
|
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000001: m2Data <= {{56{dat_i[ 7]}},dat_i[ 7: 0]};
|
|
8'b00000010: m2Data <= {{56{dat_i[15]}},dat_i[15: 8]};
|
|
8'b00000100: m2Data <= {{56{dat_i[23]}},dat_i[23:16]};
|
|
8'b00001000: m2Data <= {{56{dat_i[31]}},dat_i[31:24]};
|
|
8'b00010000: m2Data <= {{56{dat_i[39]}},dat_i[39:32]};
|
|
8'b00100000: m2Data <= {{56{dat_i[47]}},dat_i[47:40]};
|
|
8'b01000000: m2Data <= {{56{dat_i[55]}},dat_i[55:48]};
|
|
8'b10000000: m2Data <= {{56{dat_i[63]}},dat_i[63:56]};
|
|
default: m2Data <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
`INBU:
|
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000001: m2Data <= dat_i[ 7: 0];
|
|
8'b00000010: m2Data <= dat_i[15: 8];
|
|
8'b00000100: m2Data <= dat_i[23:16];
|
|
8'b00001000: m2Data <= dat_i[31:24];
|
|
8'b00010000: m2Data <= dat_i[39:32];
|
|
8'b00100000: m2Data <= dat_i[47:40];
|
|
8'b01000000: m2Data <= dat_i[55:48];
|
|
8'b10000000: m2Data <= dat_i[63:56];
|
|
default: m2Data <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
`OUTW,`OUTH,`OUTC,`OUTB:
|
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
we_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
end
|
|
`CACHE:
|
|
case(xIR[29:25])
|
|
`INVIL: tvalid[ea[12:6]] <= 1'b0;
|
|
default: ;
|
|
endcase
|
|
|
|
|
|
`LW,`LM,`LFD,`LSW,`LP,`LFDP:
|
|
if (!m1IsCacheElement) begin
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= 8'hFF;
|
|
adr_o <= {pea[63:3],3'b000};
|
|
m2Addr <= {pea[63:3],3'b000};
|
|
end
|
|
else if (dhit) begin
|
|
m2IsLoad <= 1'b0;
|
|
m2Opcode <= `NOPI;
|
|
m2Data <= cdat;
|
|
end
|
|
`ifdef ADDRESS_RESERVATION
|
|
`LWR:
|
|
if (!m1IsCacheElement) begin
|
|
rsv_o <= 1'b1;
|
|
resv_address <= pea[63:5];
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= 8'hFF;
|
|
adr_o <= {pea[63:3],3'b000};
|
|
m2Addr <= {pea[63:3],3'b000};
|
|
end
|
|
else if (dhit) begin
|
|
m2IsLoad <= 1'b0;
|
|
m2Opcode <= `NOPI;
|
|
m2Data <= cdat;
|
|
rsv_o <= 1'b1;
|
|
resv_address <= pea[63:5];
|
|
end
|
|
`endif
|
|
`LH,`LF,`LFP:
|
|
if (!m1IsCacheElement) begin
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= pea[2] ? 8'b11110000 : 8'b00001111;
|
|
adr_o <= {pea[63:2],2'b00};
|
|
m2Addr <= {pea[63:2],2'b00};
|
|
end
|
|
else if (dhit) begin
|
|
m2IsLoad <= 1'b0;
|
|
m2Opcode <= `NOPI;
|
|
if (pea[1])
|
|
m2Data <= {{32{cdat[31]}},cdat[31:0]};
|
|
else
|
|
m2Data <= {{32{cdat[63]}},cdat[63:32]};
|
|
end
|
|
|
|
`LHU,`LSH:
|
|
if (!m1IsCacheElement) begin
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= pea[2] ? 8'b11110000 : 8'b00001111;
|
|
adr_o <= {pea[63:2],2'b00};
|
|
m2Addr <= {pea[63:2],2'b00};
|
|
end
|
|
else if (dhit) begin
|
|
m2IsLoad <= 1'b0;
|
|
m2Opcode <= `NOPI;
|
|
if (pea[1])
|
|
m2Data <= {32'd0,cdat};
|
|
else
|
|
m2Data <= {32'd0,cdat[63:32]};
|
|
end
|
|
|
|
`LC:
|
|
if (!m1IsCacheElement) begin
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
case(pea[2:1])
|
|
2'b00: sel_o <= 8'b00000011;
|
|
2'b01: sel_o <= 8'b00001100;
|
|
2'b10: sel_o <= 8'b00110000;
|
|
2'b11: sel_o <= 8'b11000000;
|
|
endcase
|
|
adr_o <= {pea[63:1],1'b0};
|
|
m2Addr <= {pea[63:1],1'b0};
|
|
end
|
|
else if (dhit) begin
|
|
$display("dhit=1, cdat=%h",cdat);
|
|
m2IsLoad <= 1'b0;
|
|
m2Opcode <= `NOPI;
|
|
case(pea[2:1])
|
|
2'd0: m2Data <= {{48{cdat[15]}},cdat[15:0]};
|
|
2'd1: m2Data <= {{48{cdat[31]}},cdat[31:16]};
|
|
2'd2: m2Data <= {{48{cdat[47]}},cdat[47:32]};
|
|
2'd3: m2Data <= {{48{cdat[63]}},cdat[63:48]};
|
|
endcase
|
|
end
|
|
|
|
`LCU:
|
|
if (!m1IsCacheElement) begin
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
case(pea[2:1])
|
|
2'b00: sel_o <= 8'b00000011;
|
|
2'b01: sel_o <= 8'b00001100;
|
|
2'b10: sel_o <= 8'b00110000;
|
|
2'b11: sel_o <= 8'b11000000;
|
|
endcase
|
|
adr_o <= {pea[63:1],1'b0};
|
|
m2Addr <= {pea[63:1],1'b0};
|
|
end
|
|
else if (dhit) begin
|
|
m2IsLoad <= 1'b0;
|
|
m2Opcode <= `NOPI;
|
|
case(pea[2:1])
|
|
2'd0: m2Data <= {48'd0,cdat[15: 0]};
|
|
2'd1: m2Data <= {48'd0,cdat[31:16]};
|
|
2'd2: m2Data <= {48'd0,cdat[47:32]};
|
|
2'd3: m2Data <= {48'd0,cdat[63:48]};
|
|
endcase
|
|
end
|
end
|
|
|
`LB:
|
case(xOpcode)
|
if (!m1IsCacheElement) begin
|
`MISC:
|
$display("Load byte:");
|
case(xFunc)
|
cyc_o <= 1'b1;
|
`SEI: im <= 1'b1;
|
stb_o <= 1'b1;
|
`CLI: im <= 1'b0;
|
case(pea[2:0])
|
`WAIT: m1clkoff <= 1'b1;
|
3'b000: sel_o <= 8'b00000001;
|
`ICACHE_ON: ICacheOn <= 1'b1;
|
3'b001: sel_o <= 8'b00000010;
|
`ICACHE_OFF: ICacheOn <= 1'b0;
|
3'b010: sel_o <= 8'b00000100;
|
`DCACHE_ON: dcache_on <= 1'b1;
|
3'b011: sel_o <= 8'b00001000;
|
`DCACHE_OFF: dcache_on <= 1'b0;
|
3'b100: sel_o <= 8'b00010000;
|
`GRAN: begin
|
3'b101: sel_o <= 8'b00100000;
|
rando <= rand;
|
3'b110: sel_o <= 8'b01000000;
|
m_z <= next_m_z;
|
3'b111: sel_o <= 8'b10000000;
|
m_w <= next_m_w;
|
endcase
|
|
adr_o <= pea;
|
|
m2Addr <= pea;
|
|
end
|
|
else if (dhit) begin
|
|
m2IsLoad <= 1'b0;
|
|
m2Opcode <= `NOPI;
|
|
case(pea[2:0])
|
|
3'b000: m2Data <= {{56{cdat[ 7]}},cdat[ 7: 0]};
|
|
3'b001: m2Data <= {{56{cdat[15]}},cdat[15: 8]};
|
|
3'b010: m2Data <= {{56{cdat[23]}},cdat[23:16]};
|
|
3'b011: m2Data <= {{56{cdat[31]}},cdat[31:24]};
|
|
3'b100: m2Data <= {{56{cdat[39]}},cdat[39:32]};
|
|
3'b101: m2Data <= {{56{cdat[47]}},cdat[47:40]};
|
|
3'b110: m2Data <= {{56{cdat[55]}},cdat[55:48]};
|
|
3'b111: m2Data <= {{56{cdat[63]}},cdat[63:56]};
|
|
endcase
|
|
end
|
|
|
|
`LBU:
|
|
if (!m1IsCacheElement) begin
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
case(pea[2:0])
|
|
3'b000: sel_o <= 8'b00000001;
|
|
3'b001: sel_o <= 8'b00000010;
|
|
3'b010: sel_o <= 8'b00000100;
|
|
3'b011: sel_o <= 8'b00001000;
|
|
3'b100: sel_o <= 8'b00010000;
|
|
3'b101: sel_o <= 8'b00100000;
|
|
3'b110: sel_o <= 8'b01000000;
|
|
3'b111: sel_o <= 8'b10000000;
|
|
endcase
|
|
adr_o <= pea;
|
|
m2Addr <= pea;
|
|
end
|
end
|
else if (dhit) begin
|
`GRAFD: begin
|
m2IsLoad <= 1'b0;
|
rando <= randfd;
|
m2Opcode <= `NOPI;
|
m_z <= next_m_z;
|
case(pea[2:0])
|
m_w <= next_m_w;
|
3'b000: m2Data <= {56'd0,cdat[ 7: 0]};
|
|
3'b001: m2Data <= {56'd0,cdat[15: 8]};
|
|
3'b010: m2Data <= {56'd0,cdat[23:16]};
|
|
3'b011: m2Data <= {56'd0,cdat[31:23]};
|
|
3'b100: m2Data <= {56'd0,cdat[39:32]};
|
|
3'b101: m2Data <= {56'd0,cdat[47:40]};
|
|
3'b110: m2Data <= {56'd0,cdat[55:48]};
|
|
3'b111: m2Data <= {56'd0,cdat[63:56]};
|
|
endcase
|
|
end
|
end
|
|
`IRET:
|
`SW,`SM,`SFD,`SSW,`SP,`SFDP:
|
if (StatusHWI) begin
|
begin
|
StatusHWI <= 1'b0;
|
$display("SW/SM");
|
im <= 1'b0;
|
m2Addr <= {pea[63:3],3'b000};
|
pc <= IPC;
|
wrhit <= dhit;
|
dIR <= `NOP_INSN;
|
`ifdef ADDRESS_RESERVATION
|
xIR <= `NOP_INSN;
|
if (resv_address==pea[63:5])
|
xRtZero <= 1'b1;
|
resv_address <= 59'd0;
|
xpcv <= 1'b0;
|
`endif
|
dpcv <= 1'b0;
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
we_o <= 1'b1;
|
|
sel_o <= 8'hFF;
|
|
adr_o <= {pea[63:3],3'b000};
|
|
dat_o <= m1Data;
|
|
end
|
end
|
|
`ERET:
|
`SH,`SF,`SSH,`SFP:
|
if (StatusEXL) begin
|
begin
|
StatusEXL <= 1'b0;
|
wrhit <= dhit;
|
pc <= EPC;
|
m2Addr <= {pea[63:2],2'b00};
|
dIR <= `NOP_INSN;
|
`ifdef ADDRESS_RESERVATION
|
xIR <= `NOP_INSN;
|
if (resv_address==pea[63:5])
|
xRtZero <= 1'b1;
|
resv_address <= 59'd0;
|
xpcv <= 1'b0;
|
`endif
|
dpcv <= 1'b0;
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
we_o <= 1'b1;
|
|
sel_o <= pea[2] ? 8'b11110000 : 8'b00001111;
|
|
adr_o <= {pea[63:2],2'b00};
|
|
dat_o <= {2{m1Data[31:0]}};
|
|
end
|
end
|
|
`SYSJMP:
|
`SC:
|
|
begin
|
begin
|
$display("Storing char to %h, ea=%h",pea,ea);
|
if (xIR[15:7]!=`EX_NMI && xIR[15:7]!=`EX_IRQ) begin
|
wrhit <= dhit;
|
StatusEXL <= 1'b1;
|
m2Addr <= {pea[63:2],2'b00};
|
end
|
`ifdef ADDRESS_RESERVATION
|
pc <= 64'hC;
|
if (resv_address==pea[63:5])
|
dIR <= `NOP_INSN;
|
resv_address <= 59'd0;
|
xIR <= `NOP_INSN;
|
|
xRtZero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
ea <= {TBA[63:12],xIR[15:7],3'b000};
|
|
end
|
|
// SYSCALL EX_IRQ won't work.
|
|
`SYSCALL:
|
|
begin
|
|
StatusEXL <= 1'b1;
|
|
EPC <= fnIncPC(xpc);
|
|
pc <= 64'hC;
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRtZero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
ea <= {TBA[63:12],xIR[15:7],3'b000};
|
|
end
|
|
`ifdef TLB
|
|
`TLBP: ea <= TLBVirtPage;
|
`endif
|
`endif
|
cyc_o <= 1'b1;
|
default: ;
|
stb_o <= 1'b1;
|
|
we_o <= 1'b1;
|
|
case(pea[2:1])
|
|
2'b00: sel_o <= 8'b00000011;
|
|
2'b01: sel_o <= 8'b00001100;
|
|
2'b10: sel_o <= 8'b00110000;
|
|
2'b11: sel_o <= 8'b11000000;
|
|
endcase
|
endcase
|
adr_o <= {pea[63:1],1'b0};
|
`R:
|
dat_o <= {4{m1Data[15:0]}};
|
case(xFunc)
|
end
|
`EXEC:
|
|
|
`SB:
|
|
begin
|
begin
|
wrhit <= dhit;
|
pc <= fnIncPC(xpc);
|
m2Addr <= {pea[63:2],2'b00};
|
dIR <= b;
|
`ifdef ADDRESS_RESERVATION
|
xIR <= `NOP_INSN;
|
if (resv_address==pea[63:5])
|
xRtZero <= 1'b1;
|
resv_address <= 59'd0;
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
|
`MTSPR:
|
|
case(xIR[12:7])
|
|
`ifdef TLB
|
|
`PageTableAddr: PageTableAddr <= a[63:13];
|
|
`BadVAddr: BadVAddr <= a[63:13];
|
`endif
|
`endif
|
cyc_o <= 1'b1;
|
`ASID: ASID <= a[7:0];
|
stb_o <= 1'b1;
|
`EPC: EPC <= a;
|
we_o <= 1'b1;
|
`TBA: TBA <= {a[63:12],12'h000};
|
case(pea[2:0])
|
`AXC: AXC <= a[3:0];
|
3'b000: sel_o <= 8'b00000001;
|
`NON_ICACHE_SEG: nonICacheSeg <= a[63:32];
|
3'b001: sel_o <= 8'b00000010;
|
`FPCR: rm <= a[31:30];
|
3'b010: sel_o <= 8'b00000100;
|
`IPC: IPC <= a;
|
3'b011: sel_o <= 8'b00001000;
|
`SRAND1: begin
|
3'b100: sel_o <= 8'b00010000;
|
m_z <= a;
|
3'b101: sel_o <= 8'b00100000;
|
end
|
3'b110: sel_o <= 8'b01000000;
|
`SRAND2: begin
|
3'b111: sel_o <= 8'b10000000;
|
m_w <= a;
|
|
end
|
|
`INSNKEY: insnkey <= a[41:0];
|
|
// `PCHI: pchi <= a[5:0];
|
|
default: ;
|
endcase
|
endcase
|
adr_o <= {pea[63:2],2'b00};
|
`OMG: mutex_gate[a[5:0]] <= 1'b1;
|
dat_o <= {8{m1Data[7:0]}};
|
`CMG: mutex_gate[a[5:0]] <= 1'b0;
|
|
`OMGI: mutex_gate[xIR[12:7]] <= 1'b1;
|
|
`CMGI: mutex_gate[xIR[12:7]] <= 1'b0;
|
|
default: ;
|
|
endcase
|
|
// JMP and CALL change the program counter immediately in the IF stage.
|
|
// There's no work to do here. The pipeline does not need to be cleared.
|
|
`JMP: ;
|
|
`CALL: m1Data <= fnIncPC(xpc);
|
|
`JAL:
|
|
`ifdef BTB
|
|
if (dpc[63:2] != a[63:2] + imm[63:2]) begin
|
|
pc[63:2] <= a[63:2] + imm[63:2];
|
|
btb[xpc[7:2]] <= {a[63:2] + imm[63:2],2'b00};
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRtzero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
end
|
end
|
|
`else
|
`ifdef ADDRESS_RESERVATION
|
|
`SWC:
|
|
begin
|
begin
|
rsf <= 1'b0;
|
pc[63:2] <= a[63:2] + imm[63:2];
|
if (resv_address==pea[63:5]) begin
|
dIR <= `NOP_INSN;
|
wrhit <= dhit;
|
xIR <= `NOP_INSN;
|
m2Addr <= {pea[63:3],3'b00};
|
xRtZero <= 1'b1;
|
cyc_o <= 1'b1;
|
xpcv <= 1'b0;
|
stb_o <= 1'b1;
|
dpcv <= 1'b0;
|
we_o <= 1'b1;
|
|
sel_o <= 8'hFF;
|
|
adr_o <= {pea[63:3],3'b000};
|
|
dat_o <= m1Data;
|
|
resv_address <= 59'd0;
|
|
rsf <= 1'b1;
|
|
end
|
end
|
else
|
`endif
|
m2Opcode <= `NOPI;
|
// 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:
|
|
if (dpc[63:2]!=b[63:2]) begin
|
|
// $display("returning to: %h.%h", {b[63:4],4'b0},b[3:2]);
|
|
pc[63:2] <= b[63:2];
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRtZero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
|
`BTRR:
|
|
case(xFunc5)
|
|
// BEQ r1,r2,label
|
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BNR,`LOOP,`BRA,`BRN:
|
|
if (!takb & xbranch_taken) begin
|
|
$display("Taking mispredicted branch %h",fnIncPC(xpc));
|
|
pc <= fnIncPC(xpc);
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRtZero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
|
else if (takb & !xbranch_taken) begin
|
|
$display("Taking branch %h.%h",{xpc[63:4] + {{42{xIR[24]}},xIR[24:7]},4'b0000},xIR[6:5]);
|
|
pc[63:4] <= xpc[63:4] + {{42{xIR[24]}},xIR[24:7]};
|
|
pc[3:2] <= xIR[6:5];
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRtZero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
end
|
end
|
|
// BEQ r1,r2,r10
|
|
`BEQR,`BNER,`BLTR,`BLER,`BGTR,`BGER,`BLTUR,`BLEUR,`BGTUR,`BGEUR://,`BANDR,`BORR,`BNRR:
|
|
if (takb) begin
|
|
pc[63:2] <= c[63:2];
|
|
pc[1:0] <= 2'b00;
|
|
`ifdef BTB
|
|
btb[xpc[7:2]] <= c;
|
`endif
|
`endif
|
endcase
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRtZero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
end
|
end
|
|
default: ;
|
|
endcase
|
|
// BEQ r1,#3,r10
|
|
`BTRI:
|
|
`ifdef BTB
|
|
if (takb) begin
|
|
if ((xbranch_taken && b[63:2]!=dpc[63: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;
|
|
xRtzero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
end
|
end
|
|
|
//---------------------------------------------------------
|
|
// EXECUTE:
|
|
// - perform datapath operation
|
|
// - perform virtual to physical address translation.
|
|
//---------------------------------------------------------
|
|
if (advanceX) begin
|
|
m1IR <= xIR;
|
|
m1hwxtype <= xhwxtype;
|
|
m1Fip <= xFip;
|
|
m1extype <= xextype;
|
|
if (xextype==`EX_IRQ)
|
|
$display("xextype=IRQ");
|
|
m1IsLoad <= xIsLoad;
|
|
m1IsStore <= xIsStore;
|
|
m1IsCnt <= xIsCnt;
|
|
m1IsIO <= xIsIO;
|
|
m1Opcode <= xOpcode;
|
|
m1Func <= xFunc;
|
|
m1Rt <= xRt;
|
|
m1Data <= xData;
|
|
m1IsCacheElement <= xisCacheElement;
|
|
if (xOpcode==`MOVZ && !aeqz) begin
|
|
m1Rt <= 9'd0;
|
|
m1Data <= 64'd0;
|
|
end
|
end
|
if (xOpcode==`MOVNZ && aeqz) begin
|
else if (xbranch_taken) begin // took the branch, and weren't supposed to
|
m1Rt <= 9'd0;
|
pc <= fnIncPC(xpc);
|
m1Data <= 64'd0;
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRtzero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
end
|
end
|
m1pc <= xpc;
|
`else
|
m1pcv <= xpcv;
|
if (takb) begin
|
xRt <= 9'd0;
|
pc[63:2] <= b[63:2];
|
a <= 64'd0;
|
pc[1:0] <= 2'b00;
|
b <= 64'd0;
|
dIR <= `NOP_INSN;
|
imm <= 64'd0;
|
|
xextype <= `EX_NON;
|
|
if (xOpcode[6:4]!=`IMM) begin
|
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
|
xRtZero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
end
|
end
|
// xpc <= 64'd0;
|
`endif
|
case(xOpcode)
|
// BEQI r1,#3,label
|
`MISC:
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
case(xFunc)
|
if (takb) begin
|
`SEI: im <= 1'b1;
|
if (!xbranch_taken) begin
|
`CLI: im <= 1'b0;
|
pc[63:4] <= xpc[63:4] + {{50{xIR[29]}},xIR[29:20]};
|
`WAIT: m1clkoff <= 1'b1;
|
pc[3:2] <= xIR[19:18];
|
`ICACHE_ON: ICacheOn <= 1'b1;
|
dIR <= `NOP_INSN;
|
`ICACHE_OFF: ICacheOn <= 1'b0;
|
xIR <= `NOP_INSN;
|
`DCACHE_ON: dcache_on <= 1'b1;
|
xRtZero <= 1'b1;
|
`DCACHE_OFF: dcache_on <= 1'b0;
|
xpcv <= 1'b0;
|
`GRAN: begin
|
dpcv <= 1'b0;
|
rando <= rand;
|
|
m_z1 <= next_m_z1;
|
|
m_z2 <= next_m_z2;
|
|
m_w1 <= next_m_w1;
|
|
m_w2 <= next_m_w2;
|
|
end
|
end
|
`GRAFD: begin
|
|
rando <= randfd;
|
|
m_z1 <= next_m_z1;
|
|
m_z2 <= next_m_z2;
|
|
m_w1 <= next_m_w1;
|
|
m_w2 <= next_m_w2;
|
|
end
|
end
|
`SYSJMP,`SYSCALL:
|
else begin
|
begin
|
if (xbranch_taken) begin
|
ea <= {TBA[63:12],xIR[15:7],3'b000};
|
$display("Taking mispredicted branch %h",fnIncPC(xpc));
|
|
pc <= fnIncPC(xpc);
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRtZero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
end
|
end
|
`ifdef TLB
|
|
`TLBP: ea <= TLBVirtPage;
|
|
`endif
|
|
default: ;
|
|
endcase
|
|
`R:
|
|
case(xFunc)
|
|
`MTSPR:
|
|
case(xIR[12:7])
|
|
`ifdef TLB
|
|
`PageTableAddr: PageTableAddr <= a[63:13];
|
|
`BadVAddr: BadVAddr <= a[63:13];
|
|
`endif
|
|
`ASID: ASID <= a[7:0];
|
|
`EPC: EPC <= a;
|
|
`TBA: TBA <= {a[63:12],12'h000};
|
|
`AXC: AXC <= a[3:0];
|
|
`NON_ICACHE_SEG: nonICacheSeg <= a[63:32];
|
|
`FPCR: rm <= a[31:30];
|
|
`IPC: IPC <= a;
|
|
`SRAND1: begin
|
|
m_z1 <= a[31:0];
|
|
m_z2 <= a[63:32];
|
|
end
|
end
|
`SRAND2: begin
|
`TRAPcc,`TRAPcci:
|
m_w1 <= a[31:0];
|
if (takb) begin
|
m_w2 <= a[63:32];
|
StatusEXL <= 1'b1;
|
|
xextype <= `EX_TRAP;
|
|
pc <= 64'hC;
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRtZero <= 1'b1;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
end
|
end
|
`INSNKEY: insnkey <= a[41:0];
|
|
default: ;
|
|
endcase
|
|
`OMG: mutex_gate[a[5:0]] <= 1'b1;
|
|
`CMG: mutex_gate[a[5:0]] <= 1'b0;
|
|
`OMGI: mutex_gate[xIR[12:7]] <= 1'b1;
|
|
`CMGI: mutex_gate[xIR[12:7]] <= 1'b0;
|
|
default: ;
|
|
endcase
|
|
`CALL: m1Data <= fnIncPC(xpc);
|
|
`INW:
|
`INW:
|
begin
|
begin
|
cyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= 8'hFF;
|
sel_o <= 8'hFF;
|
adr_o <= {xData[63:3],3'b000};
|
adr_o <= {xData[63:3],3'b000};
|
end
|
end
|
`INH,`INHU:
|
`INH,`INHU:
|
begin
|
begin
|
cyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
sel_o <= xData[2] ? 8'b11110000 : 8'b00001111;
|
sel_o <= xData[2] ? 8'b11110000 : 8'b00001111;
|
adr_o <= {xData[63:2],2'b00};
|
adr_o <= {xData[63:2],2'b00};
|
end
|
end
|
`INCH,`INCU:
|
`INCH,`INCU:
|
begin
|
begin
|
cyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
case(xData[2:1])
|
case(xData[2:1])
|
2'b00: sel_o <= 8'b00000011;
|
2'b00: sel_o <= 8'b00000011;
|
2'b01: sel_o <= 8'b00001100;
|
2'b01: sel_o <= 8'b00001100;
|
2'b10: sel_o <= 8'b00110000;
|
2'b10: sel_o <= 8'b00110000;
|
Line 2342... |
Line 1921... |
endcase
|
endcase
|
adr_o <= {xData[63:1],1'b0};
|
adr_o <= {xData[63:1],1'b0};
|
end
|
end
|
`INB,`INBU:
|
`INB,`INBU:
|
begin
|
begin
|
cyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
case(xData[2:0])
|
case(xData[2:0])
|
3'b000: sel_o <= 8'b00000001;
|
3'b000: sel_o <= 8'b00000001;
|
3'b001: sel_o <= 8'b00000010;
|
3'b001: sel_o <= 8'b00000010;
|
3'b010: sel_o <= 8'b00000100;
|
3'b010: sel_o <= 8'b00000100;
|
Line 2358... |
Line 1937... |
endcase
|
endcase
|
adr_o <= xData;
|
adr_o <= xData;
|
end
|
end
|
`OUTW:
|
`OUTW:
|
begin
|
begin
|
cyc_o <= 1'b1;
|
iocyc_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 <= {xData[63:3],3'b000};
|
adr_o <= {xData[63:3],3'b000};
|
dat_o <= b;
|
dat_o <= b;
|
end
|
end
|
`OUTH:
|
`OUTH:
|
begin
|
begin
|
cyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
sel_o <= xData[2] ? 8'b11110000 : 8'b00001111;
|
sel_o <= xData[2] ? 8'b11110000 : 8'b00001111;
|
adr_o <= {xData[63:2],2'b00};
|
adr_o <= {xData[63:2],2'b00};
|
dat_o <= {2{b[31:0]}};
|
dat_o <= {2{b[31:0]}};
|
end
|
end
|
`OUTC:
|
`OUTC:
|
begin
|
begin
|
cyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
case(xData[2:1])
|
case(xData[2:1])
|
2'b00: sel_o <= 8'b00000011;
|
2'b00: sel_o <= 8'b00000011;
|
2'b01: sel_o <= 8'b00001100;
|
2'b01: sel_o <= 8'b00001100;
|
Line 2390... |
Line 1969... |
adr_o <= {xData[63:1],1'b0};
|
adr_o <= {xData[63:1],1'b0};
|
dat_o <= {4{b[15:0]}};
|
dat_o <= {4{b[15:0]}};
|
end
|
end
|
`OUTB:
|
`OUTB:
|
begin
|
begin
|
cyc_o <= 1'b1;
|
iocyc_o <= 1'b1;
|
stb_o <= 1'b1;
|
stb_o <= 1'b1;
|
we_o <= 1'b1;
|
we_o <= 1'b1;
|
case(xData[2:0])
|
case(xData[2:0])
|
3'b000: sel_o <= 8'b00000001;
|
3'b000: sel_o <= 8'b00000001;
|
3'b001: sel_o <= 8'b00000010;
|
3'b001: sel_o <= 8'b00000010;
|
Line 2414... |
Line 1993... |
begin
|
begin
|
m1Data <= b;
|
m1Data <= b;
|
ea <= xData;
|
ea <= xData;
|
end
|
end
|
`SSH: begin
|
`SSH: begin
|
case(xRt)
|
case(xRt)
|
`SR: m1Data <= {2{sr}};
|
`SR: m1Data <= {2{sr}};
|
default: m1Data <= 64'd0;
|
default: m1Data <= 64'd0;
|
endcase
|
endcase
|
ea <= xData;
|
ea <= xData;
|
end
|
|
`CACHE:
|
|
begin
|
|
m1Data <= b;
|
|
ea <= xData;
|
|
case(xIR[29:25])
|
|
`INVIALL: tvalid <= 128'd0;
|
|
default: ;
|
|
endcase
|
|
end
|
|
`MEMNDX:
|
|
begin
|
|
m1Opcode <= 7'd32+xFunc6;
|
|
case(xFunc6)
|
|
`LEAX:
|
|
begin
|
|
m1Data <= xData;
|
|
end
|
|
default:
|
|
begin
|
|
m1Data <= c;
|
|
ea <= xData;
|
|
end
|
|
endcase
|
|
end
|
|
`DIVSI,`DIVUI:
|
|
if (b==64'd0) begin
|
|
xextype <= `EX_DBZ;
|
|
end
|
|
default: ;
|
|
endcase
|
|
`ifdef FLOATING_POINT
|
|
if (xOpcode==`FP) begin
|
|
case (xFunc6)
|
|
`FDADD,`FDSUB:
|
|
begin
|
|
fp_uf <= fpaddsub_uf;
|
|
fp_ovr <= fpaddsub_ovr;
|
|
fp_iop <= fpaddsub_iop;
|
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SE <= xData[62:0]==63'd0;
|
|
end
|
|
`FPMUL:
|
|
begin
|
|
fp_uf <= fpmul_uf;
|
|
fp_ovr <= fpmul_ovr;
|
|
fp_iop <= fpmul_iop;
|
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SE <= xData[62:0]==63'd0;
|
|
end
|
|
`FPDIV:
|
|
begin
|
|
fp_uf <= fpdiv_uf;
|
|
fp_ovr <= fpdiv_ovr;
|
|
fp_iop <= fpdiv_iop;
|
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SE <= xData[62:0]==63'd0;
|
|
end
|
|
`FDF2I:
|
|
begin
|
|
fp_ovr <= f2i_ovr;
|
|
fp_iop <= f2i_iop;
|
|
end
|
|
`FDCLT,`FDCLE,`FDCEQ,`FDCNE,`FDCGT,`FDCGE,`FDCUN:
|
|
begin
|
|
fp_iop <= fpcmp_iop;
|
|
end
|
|
default: ;
|
|
endcase
|
|
end
|
|
`endif
|
|
end
|
|
|
|
//---------------------------------------------------------
|
|
// RFETCH:
|
|
// Register fetch stage
|
|
//---------------------------------------------------------
|
|
if (advanceR) begin
|
|
xAXC <= dAXC;
|
|
xhwxtype <= dhwxtype;
|
|
xFip <= dFip;
|
|
xextype <= dextype;
|
|
if (dextype==`EX_IRQ)
|
|
$display("dextype=IRQ");
|
|
if (dOpcode==`R && dFunc==`MYST)
|
|
xIR <= nxt_c;
|
|
else
|
|
xIR <= dIR;
|
|
xpc <= dpc;
|
|
xpcv <= dpcv;
|
|
xbranch_taken <= dbranch_taken;
|
|
dbranch_taken <= 1'b0;
|
|
dextype <= `EX_NON;
|
|
if (dOpcode[6:4]!=`IMM && dOpcode!=`LM && dOpcode!=`SM && dOpcode!=`SP && dOpcode!=`LP &&
|
|
dOpcode!=`SFP && dOpcode!=`LFP && dOpcode!=`SFDP && dOpcode!=`LFDP) // IMM is "sticky"
|
|
dIR <= `NOP_INSN;
|
|
dRa <= 9'd0;
|
|
dRb <= 9'd0;
|
|
|
|
a <= nxt_a;
|
|
b <= nxt_b;
|
|
if (dOpcode==`SHFTI)
|
|
b <= {58'd0,dIR[24:19]};
|
|
c <= nxt_c;
|
|
|
|
// Set the target register
|
|
casex(dOpcode)
|
|
`R:
|
|
case(dFunc)
|
|
`MTSPR,`CMG,`CMGI,`EXEC:
|
|
xRt <= 9'd0;
|
|
`MYST: xRt <= {dAXC,dIR[19:15]};
|
|
default: xRt <= {dAXC,dIR[29:25]};
|
|
endcase
|
|
`SETLO: xRt <= {dAXC,dIR[36:32]};
|
|
`SETHI: xRt <= {dAXC,dIR[36:32]};
|
|
`RR,`FP: xRt <= {dAXC,dIR[24:20]};
|
|
`BTRI: xRt <= 9'd0;
|
|
`BTRR:
|
|
case(dIR[4:0])
|
|
`LOOP: xRt <= {dAXC,dIR[29:25]};
|
|
default: xRt <= 9'd0;
|
|
endcase
|
|
`TRAPcc: xRt <= 9'd0;
|
|
`TRAPcci: xRt <= 9'd0;
|
|
`JMP: xRt <= 9'd00;
|
|
`CALL: xRt <= {dAXC,5'd31};
|
|
`RET: xRt <= {dAXC,5'd30};
|
|
`MEMNDX:
|
|
case(dFunc[5:0])
|
|
`SWX,`SHX,`SCX,`SBX,`SFX,`SFDX,`SPX,`SFPX,`SFDPX,`SSHX,`SSWX,
|
|
`OUTWX,`OUTHX,`OUTCX,`OUTBX:
|
|
xRt <= 9'd0;
|
|
default: xRt <= {dAXC,dIR[24:20]};
|
|
endcase
|
|
`LSH,`LSW,
|
|
`SW,`SH,`SC,`SB,`SF,`SFD,`SSH,`SSW,`SP,`SFP,`SFDP, // but not SWC!
|
|
`OUTW,`OUTH,`OUTC,`OUTB:
|
|
xRt <= 9'd0;
|
|
`NOPI: xRt <= 9'd0;
|
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
|
xRt <= 9'd0;
|
|
`SM: xRt <= 9'd0;
|
|
`LM:
|
|
casex(dIR[30:0])
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1: xRt <= {dAXC,5'd1};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxx10: xRt <= {dAXC,5'd2};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxxxxx100: xRt <= {dAXC,5'd3};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxxxx1000: xRt <= {dAXC,5'd4};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxxx10000: xRt <= {dAXC,5'd5};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxx100000: xRt <= {dAXC,5'd6};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxx1000000: xRt <= {dAXC,5'd7};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxx10000000: xRt <= {dAXC,5'd8};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxx100000000: xRt <= {dAXC,5'd9};
|
|
31'bxxxxxxxxxxxxxxxxxxxxx1000000000: xRt <= {dAXC,5'd10};
|
|
31'bxxxxxxxxxxxxxxxxxxxx10000000000: xRt <= {dAXC,5'd11};
|
|
31'bxxxxxxxxxxxxxxxxxxx100000000000: xRt <= {dAXC,5'd12};
|
|
31'bxxxxxxxxxxxxxxxxxx1000000000000: xRt <= {dAXC,5'd13};
|
|
31'bxxxxxxxxxxxxxxxxx10000000000000: xRt <= {dAXC,5'd14};
|
|
31'bxxxxxxxxxxxxxxxx100000000000000: xRt <= {dAXC,5'd15};
|
|
31'bxxxxxxxxxxxxxxx1000000000000000: xRt <= {dAXC,5'd16};
|
|
31'bxxxxxxxxxxxxxx10000000000000000: xRt <= {dAXC,5'd17};
|
|
31'bxxxxxxxxxxxxx100000000000000000: xRt <= {dAXC,5'd18};
|
|
31'bxxxxxxxxxxxx1000000000000000000: xRt <= {dAXC,5'd19};
|
|
31'bxxxxxxxxxxx10000000000000000000: xRt <= {dAXC,5'd20};
|
|
31'bxxxxxxxxxx100000000000000000000: xRt <= {dAXC,5'd21};
|
|
31'bxxxxxxxxx1000000000000000000000: xRt <= {dAXC,5'd22};
|
|
31'bxxxxxxxx10000000000000000000000: xRt <= {dAXC,5'd23};
|
|
31'bxxxxxxx100000000000000000000000: xRt <= {dAXC,5'd24};
|
|
31'bxxxxxx1000000000000000000000000: xRt <= {dAXC,5'd25};
|
|
31'bxxxxx10000000000000000000000000: xRt <= {dAXC,5'd26};
|
|
31'bxxxx100000000000000000000000000: xRt <= {dAXC,5'd27};
|
|
31'bxxx1000000000000000000000000000: xRt <= {dAXC,5'd28};
|
|
31'bxx10000000000000000000000000000: xRt <= {dAXC,5'd29};
|
|
31'bx100000000000000000000000000000: xRt <= {dAXC,5'd30};
|
|
31'b1000000000000000000000000000000: xRt <= {dAXC,5'd31};
|
|
default: xRt <= 9'h000;
|
|
endcase
|
|
|
|
default: xRt <= {dAXC,dIR[29:25]};
|
|
endcase
|
|
if (dOpcode[6:4]==`IMM)
|
|
xRt <= 9'd0;
|
|
|
|
// Set immediate value
|
|
if (xOpcode[6:4]==`IMM) begin
|
|
imm <= {xIR[38:0],dIR[24:0]};
|
|
end
|
|
else
|
|
case(dOpcode)
|
|
`BTRI: imm <= {{44{dIR[19]}},dIR[19:0]};
|
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
|
imm <= {{46{dIR[17]}},dIR[17:0]};
|
|
`ORI: imm <= {39'h0000000000,dIR[24:0]};
|
|
`XORI: imm <= {39'h0000000000,dIR[24:0]};
|
|
`RET: imm <= {39'h00000000,dIR[24:3],3'b000};
|
|
`MEMNDX: imm <= {{50{dIR[19]}},dIR[19:6]};
|
|
default: imm <= {{39{dIR[24]}},dIR[24:0]};
|
|
endcase
|
|
|
|
if ((((dOpcode==`SM || dOpcode==`LM) && dIR[31:0]!=32'd0)) ||
|
|
((dOpcode==`SP || dOpcode==`LP || dOpcode==`SFP || dOpcode==`LFP || dOpcode==`SFDP || dOpcode==`LFDP) && !dIR[25]))
|
|
dIR <= ndIR;
|
|
end
|
|
|
|
//---------------------------------------------------------
|
|
// IFETCH:
|
|
// - check for external hardware interrupt
|
|
// - fetch instruction
|
|
// - increment PC
|
|
// - set special register defaults for some instructions
|
|
//---------------------------------------------------------
|
|
if (advanceI) begin
|
|
dAXC <= AXC;
|
|
dextype <= `EX_NON;
|
|
if (nmi_edge & !StatusHWI & !im1) begin
|
|
$display("*****************");
|
|
$display("NMI edge detected");
|
|
$display("*****************");
|
|
StatusHWI <= 1'b1;
|
|
nmi_edge <= 1'b0;
|
|
dhwxtype <= 2'b01;
|
|
dIR <= `NOP_INSN;
|
|
dextype <= `EX_NMI;
|
|
end
|
|
else if (irq_i & !im & !StatusHWI & !im1) begin
|
|
$display("*****************");
|
|
$display("IRQ detected");
|
|
$display("*****************");
|
|
bu_im <= 1'b0;
|
|
im <= 1'b1;
|
|
StatusHWI <= 1'b1;
|
|
dhwxtype <= 2'b10;
|
|
dIR <= `NOP_INSN;
|
|
dextype <= `EX_IRQ;
|
|
end
|
|
// Are we filling the pipeline with NOP's as a result of a previous
|
|
// hardware interrupt ?
|
|
else if (|dhwxtype|dFip) begin
|
|
dIR <= `NOP_INSN;
|
|
end
|
|
`ifdef TLB
|
|
else if (ITLBMiss)
|
|
dIR <= `NOP_INSN;
|
|
`endif
|
|
else begin
|
|
if (((iOpcode==`SM || iOpcode==`LM) && insn[31:0]!=32'd0) ||
|
|
((iOpcode==`LP || iOpcode==`SP || iOpcode==`SFP || iOpcode==`LFP || iOpcode==`SFDP || iOpcode==`LFDP) && !insn[25]))
|
|
im1 <= 1'b1;
|
|
else
|
|
im1 <= 1'b0;
|
|
if ((iOpcode==`SP || iOpcode==`LP || iOpcode==`SFP || iOpcode==`LFP || iOpcode==`SFDP || iOpcode==`LFDP) && insn[25]==1'b1) begin
|
|
dIR <= `NOP_INSN;
|
|
pc <= fnIncPC(pc);
|
|
end
|
|
else if ((iOpcode==`SM || iOpcode==`LM) && insn[31:0]==32'd0) begin
|
|
dIR <= `NOP_INSN;
|
|
pc <= fnIncPC(pc);
|
|
end
|
|
else
|
|
dIR <= insn;
|
|
`include "insn_dumpsc.v"
|
|
end
|
|
nopI <= 1'b0;
|
|
if (dOpcode[6:4]!=`IMM) begin
|
|
dpc <= pc;
|
|
dpcv <= 1'b1;
|
|
end
|
|
dRb <= {AXC,insn[29:25]};
|
|
dRc <= {AXC,insn[24:20]};
|
|
casex(iOpcode)
|
|
`RET: begin
|
|
dRa <= {AXC,5'd30};
|
|
dRb <= {AXC,5'd31};
|
|
end
|
|
`SETLO: dRa <= {AXC,insn[36:32]};
|
|
`SETHI: dRa <= {AXC,insn[36:32]};
|
|
`SM,`LM:
|
|
begin
|
|
dRa <= {AXC,1'b1,insn[34:31]};
|
|
casex(insn[30:0])
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1: dRb <= {AXC,5'd1};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxx10: dRb <= {AXC,5'd2};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxxxxx100: dRb <= {AXC,5'd3};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxxxx1000: dRb <= {AXC,5'd4};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxxx10000: dRb <= {AXC,5'd5};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxxx100000: dRb <= {AXC,5'd6};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxxx1000000: dRb <= {AXC,5'd7};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxxx10000000: dRb <= {AXC,5'd8};
|
|
31'bxxxxxxxxxxxxxxxxxxxxxx100000000: dRb <= {AXC,5'd9};
|
|
31'bxxxxxxxxxxxxxxxxxxxxx1000000000: dRb <= {AXC,5'd10};
|
|
31'bxxxxxxxxxxxxxxxxxxxx10000000000: dRb <= {AXC,5'd11};
|
|
31'bxxxxxxxxxxxxxxxxxxx100000000000: dRb <= {AXC,5'd12};
|
|
31'bxxxxxxxxxxxxxxxxxx1000000000000: dRb <= {AXC,5'd13};
|
|
31'bxxxxxxxxxxxxxxxxx10000000000000: dRb <= {AXC,5'd14};
|
|
31'bxxxxxxxxxxxxxxxx100000000000000: dRb <= {AXC,5'd15};
|
|
31'bxxxxxxxxxxxxxxx1000000000000000: dRb <= {AXC,5'd16};
|
|
31'bxxxxxxxxxxxxxx10000000000000000: dRb <= {AXC,5'd17};
|
|
31'bxxxxxxxxxxxxx100000000000000000: dRb <= {AXC,5'd18};
|
|
31'bxxxxxxxxxxxx1000000000000000000: dRb <= {AXC,5'd19};
|
|
31'bxxxxxxxxxxx10000000000000000000: dRb <= {AXC,5'd20};
|
|
31'bxxxxxxxxxx100000000000000000000: dRb <= {AXC,5'd21};
|
|
31'bxxxxxxxxx1000000000000000000000: dRb <= {AXC,5'd22};
|
|
31'bxxxxxxxx10000000000000000000000: dRb <= {AXC,5'd23};
|
|
31'bxxxxxxx100000000000000000000000: dRb <= {AXC,5'd24};
|
|
31'bxxxxxx1000000000000000000000000: dRb <= {AXC,5'd25};
|
|
31'bxxxxx10000000000000000000000000: dRb <= {AXC,5'd26};
|
|
31'bxxxx100000000000000000000000000: dRb <= {AXC,5'd27};
|
|
31'bxxx1000000000000000000000000000: dRb <= {AXC,5'd28};
|
|
31'bxx10000000000000000000000000000: dRb <= {AXC,5'd29};
|
|
31'bx100000000000000000000000000000: dRb <= {AXC,5'd30};
|
|
31'b1000000000000000000000000000000: dRb <= {AXC,5'd31};
|
|
default: dRb <= {AXC,5'd0};
|
|
endcase
|
|
end
|
|
default: dRa <= {AXC,insn[34:30]};
|
|
endcase
|
|
`ifdef TLB
|
|
if (ITLBMiss) begin
|
|
$display("TLB miss on instruction fetch.");
|
|
CauseCode <= `EX_TLBI;
|
|
StatusEXL <= 1'b1;
|
|
BadVAddr <= pc[63:13];
|
|
pc <= `ITLB_MissHandler;
|
|
EPC <= pc;
|
|
end
|
end
|
else
|
`CACHE:
|
`endif
|
|
begin
|
begin
|
dbranch_taken <= 1'b0;
|
m1Data <= b;
|
if ((iOpcode==`SP || iOpcode==`LP || iOpcode==`SFP || iOpcode==`LFP || iOpcode==`SFDP || iOpcode==`LFDP) && !insn[25])
|
ea <= xData;
|
;
|
case(xIR[29:25])
|
else if ((iOpcode==`LM || iOpcode==`SM) && insn[31:0]!=32'd0)
|
`INVIALL: tvalid <= 128'd0;
|
;
|
|
else begin
|
|
if (pc!=64'hC)
|
|
pc <= fnIncPC(pc);
|
|
end
|
|
case(iOpcode)
|
|
`MISC:
|
|
case(iFunc)
|
|
`FIP: dFip <= 1'b1;
|
|
default: ;
|
default: ;
|
endcase
|
endcase
|
// 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
|
end
|
`RET:
|
`MEMNDX:
|
begin
|
begin
|
`ifdef RAS_PREDICTION
|
m1Opcode <= 7'd32+xFunc6;
|
// $display("predicted return address=%h.%h",{ras[ras_sp + 6'd1][63:4],4'b0000},ras[ras_sp + 6'd1][3:2]);
|
case(xFunc6)
|
pc <= ras[ras_sp + 6'd1];
|
`LEAX:
|
ras_sp <= ras_sp + 6'd1;
|
begin
|
`endif
|
m1Data <= xData;
|
end
|
end
|
`JMP:
|
default:
|
begin
|
begin
|
dbranch_taken <= 1'b1;
|
m1Data <= c;
|
pc <= jmp_tgt;
|
ea <= xData;
|
end
|
end
|
`BTRR:
|
endcase
|
case(insn[4:0])
|
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BRA,`BNR,`BRN,`LOOP:
|
|
if (predict_taken) begin
|
|
// $display("Taking predicted branch: %h",{pc[63:4] + {{42{insn[24]}},insn[24:7]},insn[6:5],2'b00});
|
|
dbranch_taken <= 1'b1;
|
|
pc <= {pc[63:4] + {{42{insn[24]}},insn[24:7]},insn[6:5],2'b00};
|
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
`ifdef BTB
|
`ifdef FLOATING_POINT
|
`BTRI:
|
if (xOpcode==`FP) begin
|
if (predict_taken) begin
|
case (xFunc6)
|
dbranch_taken <= 1'b1;
|
`FDADD,`FDSUB:
|
pc <= btb[pc[7:2]];
|
begin
|
|
fp_uf <= fpaddsub_uf;
|
|
fp_ovr <= fpaddsub_ovr;
|
|
fp_iop <= fpaddsub_iop;
|
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SE <= xData[62:0]==63'd0;
|
end
|
end
|
`endif
|
`FPMUL:
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
|
begin
|
begin
|
if (predict_taken) begin
|
fp_uf <= fpmul_uf;
|
dbranch_taken <= 1'b1;
|
fp_ovr <= fpmul_ovr;
|
pc <= {pc[63:4] + {{50{insn[29]}},insn[29:20]},insn[19:18],2'b00};
|
fp_iop <= fpmul_iop;
|
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SE <= xData[62:0]==63'd0;
|
|
end
|
|
`FPDIV:
|
|
begin
|
|
fp_uf <= fpdiv_uf;
|
|
fp_ovr <= fpdiv_ovr;
|
|
fp_iop <= fpdiv_iop;
|
|
FPC_SL <= xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SG <= !xData[63] && xData[62:0]!=63'd0;
|
|
FPC_SE <= xData[62:0]==63'd0;
|
end
|
end
|
|
`FDF2I:
|
|
begin
|
|
fp_ovr <= f2i_ovr;
|
|
fp_iop <= f2i_iop;
|
|
end
|
|
`FDCLT,`FDCLE,`FDCEQ,`FDCNE,`FDCGT,`FDCGE,`FDCUN:
|
|
begin
|
|
fp_iop <= fpcmp_iop;
|
end
|
end
|
default: ;
|
default: ;
|
endcase
|
endcase
|
end
|
end
|
end
|
`endif
|
|
if (dbz_error) begin
|
//`include "RPSTAGE.v"
|
$display("Divide by zero error");
|
//---------------------------------------------------------
|
xIR <= {`MISC,19'd0,`EX_DBZ,`SYSJMP};
|
// EXECUTE (EX')- part two:
|
pc <= 64'hC;
|
// - override the default program counter increment for
|
EPC <= xpc;
|
// control flow instructions
|
|
// - NOP out the instructions following a branch in the
|
|
// pipeline
|
|
//---------------------------------------------------------
|
|
if (advanceX) begin
|
|
case(xOpcode)
|
|
`MISC:
|
|
case(xFunc)
|
|
`IRET:
|
|
if (StatusHWI) begin
|
|
StatusHWI <= 1'b0;
|
|
im <= 1'b0;
|
|
pc <= IPC;
|
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRtZero <= 1'b1;
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
end
|
`ERET:
|
else if (ovr_error) begin
|
if (StatusEXL) begin
|
$display("Overflow error");
|
StatusEXL <= 1'b0;
|
xIR <= {`MISC,19'd0,`EX_OFL,`SYSJMP};
|
pc <= EPC;
|
pc <= 64'hC;
|
|
EPC <= xpc;
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRtZero <= 1'b1;
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
end
|
`SYSJMP:
|
else if (priv_violation) begin
|
begin
|
$display("Priviledge violation");
|
StatusEXL <= 1'b1;
|
xIR <= {`MISC,19'd0,`EX_PRIV,`SYSJMP};
|
pc <= 64'hC;
|
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRtZero <= 1'b1;
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
|
pc <= 64'hC;
|
|
EPC <= xpc;
|
end
|
end
|
`SYSCALL:
|
else if (illegal_insn) begin
|
begin
|
$display("Unimplemented Instruction");
|
StatusEXL <= 1'b1;
|
xIR <= {`MISC,19'd0,`EX_UNIMP_INSN,`SYSJMP};
|
EPC <= fnIncPC(xpc);
|
|
pc <= 64'hC;
|
pc <= 64'hC;
|
|
EPC <= xpc;
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRtZero <= 1'b1;
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
end
|
default: ;
|
end
|
|
// Stage tail
|
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
|
else if (advanceM1) begin
|
|
m1IR <= `NOP_INSN;
|
|
m1Opcode <= `NOPI;
|
|
m1Rt <= 9'd0;
|
|
m1clkoff <= 1'b0;
|
|
m1pc <= `RESET_VECTOR;
|
|
m1pcv <= 1'b0;
|
|
m1extype <= `EX_NON;
|
|
m1IsLoad <= #1 1'b0;
|
|
m1IsStore <= #1 1'b0;
|
|
m1IsCnt <= #1 1'b0;
|
|
m1IsIO <= #1 1'b0;
|
|
m1IsCacheElement <= #1 1'b0;
|
|
end
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// MEMORY:
|
|
// - I/O instructions are finished
|
|
// - store instructions are started
|
|
// - missed loads are started
|
|
// On a data cache hit for a load, the load is essentially
|
|
// finished in this stage. We switch the opcode to 'NOPI'
|
|
// to cause the pipeline to advance as if a NOPs were
|
|
// present.
|
|
//
|
|
// Inputs:
|
|
// - m1???? signals
|
|
// Outputs:
|
|
// - m2???? signals to M2 stage
|
|
//-----------------------------------------------------------------------------
|
|
if (advanceM1) begin
|
|
m2extype <= m1extype;
|
|
m2hwxtype <= m1hwxtype;
|
|
m2Addr <= pea;
|
|
m2Data <= m1Data;
|
|
m2Fip <= m1Fip;
|
|
m2pc <= m1pc;
|
|
m2pcv <= m1pcv;
|
|
m2IR <= m1IR;
|
|
m2Opcode <= m1Opcode;
|
|
m2Func <= m1Func;
|
|
m2IsLoad <= m1IsLoad;
|
|
m2IsStore <= #1 m1IsStore;
|
|
m2IsCnt <= m1IsCnt;
|
|
m2Func <= m1Func;
|
|
m2Rt <= m1Rt;
|
|
m2clkoff <= m1clkoff;
|
|
m2LdPC <= 1'b0;
|
|
if (m1IsIO & err_i) begin
|
|
m2extype <= `EX_DBERR;
|
|
errorAddress <= adr_o;
|
|
end
|
|
|
|
if (m1extype == `EX_NON) begin
|
|
case(m1Opcode)
|
|
`MISC:
|
|
case(m1Func)
|
|
`SYSJMP,`SYSCALL:
|
|
begin
|
|
m2LdPC <= 1'b1;
|
|
if (!m1IsCacheElement) begin
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= 8'hFF;
|
|
adr_o <= {pea[63:3],3'b000};
|
|
m2Addr <= {pea[63:3],3'b000};
|
|
end
|
|
else begin // dhit must be true
|
|
m2IsLoad <= 1'b0;
|
|
m2Opcode <= `NOPI;
|
|
m2Data <= {cdat[63:2],2'b00};
|
|
end
|
|
end
|
|
endcase
|
|
`INW:
|
|
begin
|
|
iocyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
m2Data <= dat_i;
|
|
end
|
|
`INH:
|
|
begin
|
|
iocyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
m2Data <= sel_o[7] ? {{32{dat_i[63]}},dat_i[63:32]}:{{32{dat_i[31]}},dat_i[31: 0]};
|
|
end
|
|
`INHU:
|
|
begin
|
|
iocyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
m2Data <= sel_o[7] ? dat_i[63:32] : dat_i[31: 0];
|
|
end
|
|
`INCH:
|
|
begin
|
|
iocyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000011: m2Data <= {{48{dat_i[15]}},dat_i[15: 0]};
|
|
8'b00001100: m2Data <= {{48{dat_i[31]}},dat_i[31:16]};
|
|
8'b00110000: m2Data <= {{48{dat_i[47]}},dat_i[47:32]};
|
|
8'b11000000: m2Data <= {{48{dat_i[63]}},dat_i[63:48]};
|
|
default: m2Data <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
`INCU:
|
|
begin
|
|
iocyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000011: m2Data <= dat_i[15: 0];
|
|
8'b00001100: m2Data <= dat_i[31:16];
|
|
8'b00110000: m2Data <= dat_i[47:32];
|
|
8'b11000000: m2Data <= dat_i[63:48];
|
|
default: m2Data <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
`INB:
|
|
begin
|
|
iocyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000001: m2Data <= {{56{dat_i[ 7]}},dat_i[ 7: 0]};
|
|
8'b00000010: m2Data <= {{56{dat_i[15]}},dat_i[15: 8]};
|
|
8'b00000100: m2Data <= {{56{dat_i[23]}},dat_i[23:16]};
|
|
8'b00001000: m2Data <= {{56{dat_i[31]}},dat_i[31:24]};
|
|
8'b00010000: m2Data <= {{56{dat_i[39]}},dat_i[39:32]};
|
|
8'b00100000: m2Data <= {{56{dat_i[47]}},dat_i[47:40]};
|
|
8'b01000000: m2Data <= {{56{dat_i[55]}},dat_i[55:48]};
|
|
8'b10000000: m2Data <= {{56{dat_i[63]}},dat_i[63:56]};
|
|
default: m2Data <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
`INBU:
|
|
begin
|
|
iocyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000001: m2Data <= dat_i[ 7: 0];
|
|
8'b00000010: m2Data <= dat_i[15: 8];
|
|
8'b00000100: m2Data <= dat_i[23:16];
|
|
8'b00001000: m2Data <= dat_i[31:24];
|
|
8'b00010000: m2Data <= dat_i[39:32];
|
|
8'b00100000: m2Data <= dat_i[47:40];
|
|
8'b01000000: m2Data <= dat_i[55:48];
|
|
8'b10000000: m2Data <= dat_i[63:56];
|
|
default: m2Data <= 64'hDEADDEADDEADDEAD;
|
endcase
|
endcase
|
`R:
|
end
|
case(xFunc)
|
`OUTW,`OUTH,`OUTC,`OUTB:
|
`EXEC:
|
|
begin
|
begin
|
pc <= fnIncPC(xpc);
|
iocyc_o <= #1 1'b0;
|
dRa <= b[34:30];
|
stb_o <= #1 1'b0;
|
dRb <= b[29:25];
|
we_o <= #1 1'b0;
|
dRc <= b[24:20];
|
sel_o <= #1 8'h00;
|
dIR <= b;
|
|
xIR <= `NOP_INSN;
|
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
end
|
|
`CACHE:
|
|
case(m1IR[29:25])
|
|
`INVIL: tvalid[ea[12:6]] <= 1'b0;
|
default: ;
|
default: ;
|
endcase
|
endcase
|
`BTRR:
|
|
case(xFunc5)
|
|
// BEQ r1,r2,label
|
`LW,`LM,`LFD,`LSW,`LP,`LFDP:
|
`BEQ,`BNE,`BLT,`BLE,`BGT,`BGE,`BLTU,`BLEU,`BGTU,`BGEU,`BAND,`BOR,`BNR,`LOOP,`BRA,`BRN:
|
if (!m1IsCacheElement) begin
|
if (!takb & xbranch_taken) begin
|
cyc_o <= 1'b1;
|
$display("Taking mispredicted branch %h",fnIncPC(xpc));
|
stb_o <= 1'b1;
|
pc <= fnIncPC(xpc);
|
sel_o <= 8'hFF;
|
dIR <= `NOP_INSN;
|
adr_o <= {pea[63:3],3'b000};
|
xIR <= `NOP_INSN;
|
m2Addr <= {pea[63:3],3'b000};
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
end
|
else if (takb & !xbranch_taken) begin
|
else begin
|
$display("Taking branch %h.%h",{xpc[63:4] + {{42{xIR[24]}},xIR[24:7]},4'b0000},xIR[6:5]);
|
m2IsLoad <= 1'b0;
|
pc[63:4] <= xpc[63:4] + {{42{xIR[24]}},xIR[24:7]};
|
m2Opcode <= `NOPI;
|
pc[3:2] <= xIR[6:5];
|
m2Data <= cdat;
|
dIR <= `NOP_INSN;
|
end
|
xIR <= `NOP_INSN;
|
`ifdef ADDRESS_RESERVATION
|
xRt <= 9'd0;
|
`LWR:
|
xpcv <= 1'b0;
|
if (!m1IsCacheElement) begin
|
dpcv <= 1'b0;
|
rsv_o <= 1'b1;
|
|
resv_address <= pea[63:5];
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
sel_o <= 8'hFF;
|
|
adr_o <= {pea[63:3],3'b000};
|
|
m2Addr <= {pea[63:3],3'b000};
|
|
end
|
|
else begin
|
|
m2IsLoad <= 1'b0;
|
|
m2Opcode <= `NOPI;
|
|
m2Data <= cdat;
|
|
rsv_o <= 1'b1;
|
|
resv_address <= pea[63:5];
|
end
|
end
|
// BEQ r1,r2,r10
|
|
`BEQR,`BNER,`BLTR,`BLER,`BGTR,`BGER,`BLTUR,`BLEUR,`BGTUR,`BGEUR://,`BANDR,`BORR,`BNRR:
|
|
if (takb) begin
|
|
pc[63:2] <= c[63:2];
|
|
pc[1:0] <= 2'b00;
|
|
`ifdef BTB
|
|
btb[xpc[7:2]] <= c;
|
|
`endif
|
`endif
|
dIR <= `NOP_INSN;
|
`LH,`LF,`LFP:
|
xIR <= `NOP_INSN;
|
if (!m1IsCacheElement) begin
|
xRt <= 9'd0;
|
cyc_o <= 1'b1;
|
xpcv <= 1'b0;
|
stb_o <= 1'b1;
|
dpcv <= 1'b0;
|
sel_o <= pea[2] ? 8'b11110000 : 8'b00001111;
|
|
adr_o <= {pea[63:2],2'b00};
|
|
m2Addr <= {pea[63:2],2'b00};
|
end
|
end
|
default: ;
|
else begin
|
endcase
|
m2IsLoad <= 1'b0;
|
// JMP and CALL change the program counter immediately in the IF stage.
|
m2Opcode <= `NOPI;
|
// There's no work to do here. The pipeline does not need to be cleared.
|
if (pea[1])
|
`JMP: ;
|
m2Data <= {{32{cdat[31]}},cdat[31:0]};
|
`CALL: ;
|
else
|
`JAL:
|
m2Data <= {{32{cdat[63]}},cdat[63:32]};
|
begin
|
|
pc[63:2] <= a[63:2] + imm[63:2];
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
end
|
|
|
// Check the pc of the instruction after the RET instruction (the dpc), to
|
`LHU,`LSH:
|
// see if it's equal to the RET target. If it's the same as the target then
|
if (!m1IsCacheElement) begin
|
// we predicted the RET return correctly, so there's nothing to do. Otherwise
|
cyc_o <= 1'b1;
|
// we need to branch to the RET location.
|
stb_o <= 1'b1;
|
`RET:
|
sel_o <= pea[2] ? 8'b11110000 : 8'b00001111;
|
`ifdef RAS_PREDICTION
|
adr_o <= {pea[63:2],2'b00};
|
if (dpc[63:2]!=b[63:2]) begin
|
m2Addr <= {pea[63:2],2'b00};
|
`else
|
|
begin
|
|
`endif
|
|
// $display("returning to: %h.%h", {b[63:4],4'b0},b[3:2]);
|
|
pc[63:2] <= b[63:2];
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
end
|
// else
|
else begin
|
// $display("RET address %h predicted correctly.", {b[63:4],4'b0},b[3:2]);
|
m2IsLoad <= 1'b0;
|
// BEQ r1,#3,r10
|
m2Opcode <= `NOPI;
|
`BTRI:
|
if (pea[1])
|
`ifdef BTB
|
m2Data <= {32'd0,cdat};
|
if (takb) begin
|
else
|
if ((xbranch_taken && b!=btb[xpc[7:2]]) || // took branch, but not to right target
|
m2Data <= {32'd0,cdat[63:32]};
|
!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
|
|
|
|
`LC:
|
|
if (!m1IsCacheElement) begin
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
case(pea[2:1])
|
|
2'b00: sel_o <= 8'b00000011;
|
|
2'b01: sel_o <= 8'b00001100;
|
|
2'b10: sel_o <= 8'b00110000;
|
|
2'b11: sel_o <= 8'b11000000;
|
|
endcase
|
|
adr_o <= {pea[63:1],1'b0};
|
|
m2Addr <= {pea[63:1],1'b0};
|
end
|
end
|
else if (xbranch_taken) begin // took the branch, and weren't supposed to
|
else begin
|
pc <= fnIncPC(xpc);
|
$display("dhit=1, cdat=%h",cdat);
|
dIR <= `NOP_INSN;
|
m2IsLoad <= 1'b0;
|
xIR <= `NOP_INSN;
|
m2Opcode <= `NOPI;
|
xRt <= 9'd0;
|
case(pea[2:1])
|
xpcv <= 1'b0;
|
2'd0: m2Data <= {{48{cdat[15]}},cdat[15:0]};
|
dpcv <= 1'b0;
|
2'd1: m2Data <= {{48{cdat[31]}},cdat[31:16]};
|
|
2'd2: m2Data <= {{48{cdat[47]}},cdat[47:32]};
|
|
2'd3: m2Data <= {{48{cdat[63]}},cdat[63:48]};
|
|
endcase
|
end
|
end
|
`else
|
|
if (takb) begin
|
`LCU:
|
pc[63:2] <= b[63:2];
|
if (!m1IsCacheElement) begin
|
pc[1:0] <= 2'b00;
|
cyc_o <= 1'b1;
|
dIR <= `NOP_INSN;
|
stb_o <= 1'b1;
|
xIR <= `NOP_INSN;
|
case(pea[2:1])
|
xRt <= 9'd0;
|
2'b00: sel_o <= 8'b00000011;
|
xpcv <= 1'b0;
|
2'b01: sel_o <= 8'b00001100;
|
dpcv <= 1'b0;
|
2'b10: sel_o <= 8'b00110000;
|
|
2'b11: sel_o <= 8'b11000000;
|
|
endcase
|
|
adr_o <= {pea[63:1],1'b0};
|
|
m2Addr <= {pea[63:1],1'b0};
|
end
|
end
|
`endif
|
else begin
|
// BEQI r1,#3,label
|
m2IsLoad <= 1'b0;
|
`BEQI,`BNEI,`BLTI,`BLEI,`BGTI,`BGEI,`BLTUI,`BLEUI,`BGTUI,`BGEUI:
|
m2Opcode <= `NOPI;
|
if (takb) begin
|
case(pea[2:1])
|
if (!xbranch_taken) begin
|
2'd0: m2Data <= {48'd0,cdat[15: 0]};
|
pc[63:4] <= xpc[63:4] + {{50{xIR[29]}},xIR[29:20]};
|
2'd1: m2Data <= {48'd0,cdat[31:16]};
|
pc[3:2] <= xIR[19:18];
|
2'd2: m2Data <= {48'd0,cdat[47:32]};
|
dIR <= `NOP_INSN;
|
2'd3: m2Data <= {48'd0,cdat[63:48]};
|
xIR <= `NOP_INSN;
|
endcase
|
xRt <= 9'd0;
|
end
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
`LB:
|
|
if (!m1IsCacheElement) begin
|
|
$display("Load byte:");
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
case(pea[2:0])
|
|
3'b000: sel_o <= 8'b00000001;
|
|
3'b001: sel_o <= 8'b00000010;
|
|
3'b010: sel_o <= 8'b00000100;
|
|
3'b011: sel_o <= 8'b00001000;
|
|
3'b100: sel_o <= 8'b00010000;
|
|
3'b101: sel_o <= 8'b00100000;
|
|
3'b110: sel_o <= 8'b01000000;
|
|
3'b111: sel_o <= 8'b10000000;
|
|
endcase
|
|
adr_o <= pea;
|
|
m2Addr <= pea;
|
|
end
|
|
else begin
|
|
m2IsLoad <= 1'b0;
|
|
m2Opcode <= `NOPI;
|
|
case(pea[2:0])
|
|
3'b000: m2Data <= {{56{cdat[ 7]}},cdat[ 7: 0]};
|
|
3'b001: m2Data <= {{56{cdat[15]}},cdat[15: 8]};
|
|
3'b010: m2Data <= {{56{cdat[23]}},cdat[23:16]};
|
|
3'b011: m2Data <= {{56{cdat[31]}},cdat[31:24]};
|
|
3'b100: m2Data <= {{56{cdat[39]}},cdat[39:32]};
|
|
3'b101: m2Data <= {{56{cdat[47]}},cdat[47:40]};
|
|
3'b110: m2Data <= {{56{cdat[55]}},cdat[55:48]};
|
|
3'b111: m2Data <= {{56{cdat[63]}},cdat[63:56]};
|
|
endcase
|
end
|
end
|
|
|
|
`LBU:
|
|
if (!m1IsCacheElement) begin
|
|
cyc_o <= 1'b1;
|
|
stb_o <= 1'b1;
|
|
case(pea[2:0])
|
|
3'b000: sel_o <= 8'b00000001;
|
|
3'b001: sel_o <= 8'b00000010;
|
|
3'b010: sel_o <= 8'b00000100;
|
|
3'b011: sel_o <= 8'b00001000;
|
|
3'b100: sel_o <= 8'b00010000;
|
|
3'b101: sel_o <= 8'b00100000;
|
|
3'b110: sel_o <= 8'b01000000;
|
|
3'b111: sel_o <= 8'b10000000;
|
|
endcase
|
|
adr_o <= pea;
|
|
m2Addr <= pea;
|
end
|
end
|
else begin
|
else begin
|
if (xbranch_taken) begin
|
m2IsLoad <= 1'b0;
|
$display("Taking mispredicted branch %h",fnIncPC(xpc));
|
m2Opcode <= `NOPI;
|
pc <= fnIncPC(xpc);
|
case(pea[2:0])
|
dIR <= `NOP_INSN;
|
3'b000: m2Data <= {56'd0,cdat[ 7: 0]};
|
xIR <= `NOP_INSN;
|
3'b001: m2Data <= {56'd0,cdat[15: 8]};
|
xRt <= 9'd0;
|
3'b010: m2Data <= {56'd0,cdat[23:16]};
|
xpcv <= 1'b0;
|
3'b011: m2Data <= {56'd0,cdat[31:23]};
|
dpcv <= 1'b0;
|
3'b100: m2Data <= {56'd0,cdat[39:32]};
|
|
3'b101: m2Data <= {56'd0,cdat[47:40]};
|
|
3'b110: m2Data <= {56'd0,cdat[55:48]};
|
|
3'b111: m2Data <= {56'd0,cdat[63:56]};
|
|
endcase
|
end
|
end
|
|
|
|
`SW,`SM,`SFD,`SSW,`SP,`SFDP:
|
|
begin
|
|
$display("SW/SM");
|
|
m2Addr <= #1 {pea[63:3],3'b000};
|
|
wrhit <= #1 dhit;
|
|
`ifdef ADDRESS_RESERVATION
|
|
if (resv_address==pea[63:5])
|
|
resv_address <= #1 59'd0;
|
|
`endif
|
|
cyc_o <= #1 1'b1;
|
|
stb_o <= #1 1'b1;
|
|
we_o <= #1 1'b1;
|
|
sel_o <= #1 8'hFF;
|
|
adr_o <= #1 {pea[63:3],3'b000};
|
|
dat_o <= #1 m1Data;
|
end
|
end
|
`TRAPcc,`TRAPcci:
|
|
if (takb) begin
|
`SH,`SF,`SSH,`SFP:
|
StatusEXL <= 1'b1;
|
begin
|
CauseCode <= `EX_TRAP;
|
wrhit <= #1 dhit;
|
xextype <= `EX_TRAP;
|
m2Addr <= #1 {pea[63:2],2'b00};
|
pc <= 64'hC;
|
`ifdef ADDRESS_RESERVATION
|
dIR <= `NOP_INSN;
|
if (resv_address==pea[63:5])
|
xIR <= `NOP_INSN;
|
resv_address <= #1 59'd0;
|
xRt <= 9'd0;
|
`endif
|
xpcv <= 1'b0;
|
cyc_o <= #1 1'b1;
|
dpcv <= 1'b0;
|
stb_o <= #1 1'b1;
|
|
we_o <= #1 1'b1;
|
|
sel_o <= #1 pea[2] ? 8'b11110000 : 8'b00001111;
|
|
adr_o <= #1 {pea[63:2],2'b00};
|
|
dat_o <= #1 {2{m1Data[31:0]}};
|
end
|
end
|
default: ;
|
|
|
`SC:
|
|
begin
|
|
$display("Storing char to %h, ea=%h",pea,ea);
|
|
wrhit <= #1 dhit;
|
|
m2Addr <= #1 {pea[63:2],2'b00};
|
|
`ifdef ADDRESS_RESERVATION
|
|
if (resv_address==pea[63:5])
|
|
resv_address <= #1 59'd0;
|
|
`endif
|
|
cyc_o <= #1 1'b1;
|
|
stb_o <= #1 1'b1;
|
|
we_o <= #1 1'b1;
|
|
case(pea[2:1])
|
|
2'b00: sel_o <= #1 8'b00000011;
|
|
2'b01: sel_o <= #1 8'b00001100;
|
|
2'b10: sel_o <= #1 8'b00110000;
|
|
2'b11: sel_o <= #1 8'b11000000;
|
endcase
|
endcase
|
|
adr_o <= #1 {pea[63:1],1'b0};
|
|
dat_o <= #1 {4{m1Data[15:0]}};
|
|
end
|
|
|
if (dbz_error) begin
|
`SB:
|
$display("Divide by zero error");
|
begin
|
CauseCode <= `EX_DBZ;
|
wrhit <= #1 dhit;
|
xextype <= `EX_DBZ;
|
m2Addr <= #1 {pea[63:2],2'b00};
|
StatusEXL <= 1'b1;
|
`ifdef ADDRESS_RESERVATION
|
pc <= 64'hC;
|
if (resv_address==pea[63:5])
|
dIR <= `NOP_INSN;
|
resv_address <= #1 59'd0;
|
xIR <= `NOP_INSN;
|
`endif
|
xRt <= 9'd0;
|
cyc_o <= #1 1'b1;
|
xpcv <= 1'b0;
|
stb_o <= #1 1'b1;
|
dpcv <= 1'b0;
|
we_o <= #1 1'b1;
|
|
case(pea[2:0])
|
|
3'b000: sel_o <= #1 8'b00000001;
|
|
3'b001: sel_o <= #1 8'b00000010;
|
|
3'b010: sel_o <= #1 8'b00000100;
|
|
3'b011: sel_o <= #1 8'b00001000;
|
|
3'b100: sel_o <= #1 8'b00010000;
|
|
3'b101: sel_o <= #1 8'b00100000;
|
|
3'b110: sel_o <= #1 8'b01000000;
|
|
3'b111: sel_o <= #1 8'b10000000;
|
|
endcase
|
|
adr_o <= #1 {pea[63:2],2'b00};
|
|
dat_o <= #1 {8{m1Data[7:0]}};
|
end
|
end
|
else if (ovr_error) begin
|
|
$display("Overflow error");
|
`ifdef ADDRESS_RESERVATION
|
CauseCode <= `EX_OFL;
|
`SWC:
|
xextype <= `EX_OFL;
|
begin
|
StatusEXL <= 1'b1;
|
rsf <= #1 1'b0;
|
pc <= 64'hC;
|
if (resv_address==pea[63:5]) begin
|
dIR <= `NOP_INSN;
|
wrhit <= #1 dhit;
|
xIR <= `NOP_INSN;
|
m2Addr <= #1 {pea[63:3],3'b00};
|
xRt <= 9'd0;
|
cyc_o <= #1 1'b1;
|
xpcv <= 1'b0;
|
stb_o <= #1 1'b1;
|
dpcv <= 1'b0;
|
we_o <= #1 1'b1;
|
|
sel_o <= #1 8'hFF;
|
|
adr_o <= #1 {pea[63:3],3'b000};
|
|
dat_o <= #1 m1Data;
|
|
resv_address <= #1 59'd0;
|
|
rsf <= #1 1'b1;
|
end
|
end
|
else if (priv_violation) begin
|
else
|
$display("Priviledge violation");
|
m2Opcode <= #1 `NOPI;
|
CauseCode <= `EX_PRIV;
|
|
xextype <= `EX_PRIV;
|
|
StatusEXL <= 1'b1;
|
|
pc <= 64'hC;
|
|
dIR <= `NOP_INSN;
|
|
xIR <= `NOP_INSN;
|
|
xRt <= 9'd0;
|
|
xpcv <= 1'b0;
|
|
dpcv <= 1'b0;
|
|
end
|
end
|
|
`endif
|
|
endcase
|
end
|
end
|
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// MEMORY1 (M1') - part two:
|
|
// Check for a TLB miss.
|
// Check for a TLB miss.
|
|
// On a prefetch load, just switch the opcode to a NOP
|
|
// instruction and ignore the error. Otherwise set the
|
|
// exception type.
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
`ifdef TLB
|
`ifdef TLB
|
if (advanceM1) begin
|
if (m1IsLoad && m1Rt[4:0]==5'd0 && DTLBMiss) begin
|
if (m1IsLoad|m1IsStore) begin
|
m1Opcode <= `NOPI;
|
|
end
|
|
if ((m1IsLoad&&m1Rt[4:0]!=5'd0)|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;
|
CauseCode <= `EX_TLBD;
|
|
StatusEXL <= 1'b1;
|
StatusEXL <= 1'b1;
|
BadVAddr <= ea[63:13];
|
BadVAddr <= ea[63:13];
|
EPC <= m1pc;
|
|
pc <= `DTLB_MissHandler;
|
|
m1Opcode <= `NOPI;
|
m1Opcode <= `NOPI;
|
m1Rt <= 9'd0;
|
m1Rt <= 9'd0;
|
|
pc <= 64'hC;
|
xIR <= `NOP_INSN;
|
xIR <= `NOP_INSN;
|
xRt <= 9'd0;
|
xRtzero <= 1'b1;
|
dIR <= `NOP_INSN;
|
dIR <= `NOP_INSN;
|
m1pcv <= 1'b0;
|
m1pcv <= 1'b0;
|
xpcv <= 1'b0;
|
xpcv <= 1'b0;
|
dpcv <= 1'b0;
|
dpcv <= 1'b0;
|
end
|
dhwxtype <= 2'b11;
|
end
|
end
|
end
|
end
|
`endif
|
`endif
|
|
end
|
|
// Stage tail
|
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
|
else if (advanceM2) begin
|
|
m2Rt <= #1 9'd0;
|
|
m2IR <= #1 `NOP_INSN;
|
|
m2Opcode <= #1 `NOPI;
|
|
m2IsLoad <= #1 1'b0;
|
|
m2IsStore <= #1 1'b0;
|
|
m2IsCnt <= #1 1'b0;
|
|
m2Func <= #1 7'd0;
|
|
m2Addr <= #1 64'd0;
|
|
m2Data <= #1 64'd0;
|
|
m2clkoff <= #1 1'b0;
|
|
m2pcv <= #1 1'b0;
|
|
m2pc <= #1 `RESET_VECTOR;
|
|
m2extype <= #1 `EX_NON;
|
|
m2LdPC <= #1 1'b0;
|
|
end
|
|
|
//---------------------------------------------------------
|
|
// MEMORY2 (M2')
|
//-----------------------------------------------------------------------------
|
//---------------------------------------------------------
|
// MEMORY:
|
|
// - complete the memory cycle
|
|
// - merge load data into pipeline
|
|
// Inputs:
|
|
// - m2???? type signals
|
|
// Outputs:
|
|
// - w???? signals to WB stage
|
|
//-----------------------------------------------------------------------------
|
if (advanceM2) begin
|
if (advanceM2) begin
|
|
wextype <= #1 m2extype;
|
|
whwxtype <= #1 m2hwxtype;
|
|
wpc <= #1 m2pc;
|
|
wpcv <= #1 m2pcv;
|
|
wFip <= #1 m2Fip;
|
|
wIsStore <= #1 m2IsStore;
|
|
wIR <= #1 m2IR;
|
|
wOpcode <= #1 m2Opcode;
|
|
wFunc <= #1 m2Func;
|
|
wData <= #1 m2Data;
|
|
wRt <= #1 m2Rt;
|
|
wclkoff <= #1 m2clkoff;
|
|
wLdPC <= #1 m2LdPC;
|
|
|
|
// There's not an error is a prefetch is taking place (m2Rt=0).
|
|
if (((m2IsLoad&&m2Rt[4:0]!=5'd0)|m2IsStore)&err_i) begin
|
|
wextype <= #1 `EX_DBERR;
|
|
errorAddress <= #1 adr_o;
|
|
end
|
|
|
|
if (m2extype==`EX_NON) begin
|
|
case(m2Opcode)
|
|
`MISC:
|
|
if (m2Func==`SYSJMP || m2Func==`SYSCALL)
|
|
begin
|
|
cyc_o <= #1 1'b0;
|
|
stb_o <= #1 1'b0;
|
|
sel_o <= #1 8'h00;
|
|
wData <= #1 {dat_i[63:2],2'b00};
|
|
end
|
|
`SH,`SC,`SB,`SW,`SWC,`SM,`SF,`SFD,`SSH,`SSW,`SP,`SFP,`SFDP:
|
|
begin
|
|
$display("negating write signals");
|
|
cyc_o <= #1 1'b0;
|
|
stb_o <= #1 1'b0;
|
|
we_o <= #1 1'b0;
|
|
sel_o <= #1 8'h00;
|
|
end
|
|
`LH,`LF,`LSH,`LFP:
|
|
begin
|
|
cyc_o <= #1 1'b0;
|
|
stb_o <= #1 1'b0;
|
|
sel_o <= #1 8'h00;
|
|
wData <= #1 sel_o[7] ? {{32{dat_i[63]}},dat_i[63:32]}:{{32{dat_i[31]}},dat_i[31: 0]};
|
|
end
|
|
`LW,`LWR,`LM,`LFD,`LSW,`LP,`LFDP:
|
|
begin
|
|
cyc_o <= #1 1'b0;
|
|
stb_o <= #1 1'b0;
|
|
sel_o <= #1 8'h00;
|
|
wData <= #1 dat_i;
|
|
end
|
|
`LHU:
|
|
begin
|
|
cyc_o <= #1 1'b0;
|
|
stb_o <= #1 1'b0;
|
|
sel_o <= #1 8'h00;
|
|
wData <= #1 sel_o[7] ? dat_i[63:32] : dat_i[31: 0];
|
|
end
|
|
`LC:
|
|
begin
|
|
cyc_o <= #1 1'b0;
|
|
stb_o <= #1 1'b0;
|
|
sel_o <= #1 8'h00;
|
|
case(sel_o)
|
|
8'b00000011: wData <= #1 {{48{dat_i[15]}},dat_i[15: 0]};
|
|
8'b00001100: wData <= #1 {{48{dat_i[31]}},dat_i[31:16]};
|
|
8'b00110000: wData <= #1 {{48{dat_i[47]}},dat_i[47:32]};
|
|
8'b11000000: wData <= #1 {{48{dat_i[63]}},dat_i[63:48]};
|
|
default: wData <= #1 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
`LCU:
|
|
begin
|
|
cyc_o <= #1 1'b0;
|
|
stb_o <= #1 1'b0;
|
|
sel_o <= #1 8'h00;
|
|
case(sel_o)
|
|
8'b00000011: wData <= #1 dat_i[15: 0];
|
|
8'b00001100: wData <= #1 dat_i[31:16];
|
|
8'b00110000: wData <= #1 dat_i[47:32];
|
|
8'b11000000: wData <= #1 dat_i[63:48];
|
|
default: wData <= #1 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
`LB:
|
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000001: wData <= {{56{dat_i[ 7]}},dat_i[ 7: 0]};
|
|
8'b00000010: wData <= {{56{dat_i[15]}},dat_i[15: 8]};
|
|
8'b00000100: wData <= {{56{dat_i[23]}},dat_i[23:16]};
|
|
8'b00001000: wData <= {{56{dat_i[31]}},dat_i[31:24]};
|
|
8'b00010000: wData <= {{56{dat_i[39]}},dat_i[39:32]};
|
|
8'b00100000: wData <= {{56{dat_i[47]}},dat_i[47:40]};
|
|
8'b01000000: wData <= {{56{dat_i[55]}},dat_i[55:48]};
|
|
8'b10000000: wData <= {{56{dat_i[63]}},dat_i[63:56]};
|
|
default: wData <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
`LBU:
|
|
begin
|
|
cyc_o <= 1'b0;
|
|
stb_o <= 1'b0;
|
|
sel_o <= 8'h00;
|
|
case(sel_o)
|
|
8'b00000001: wData <= dat_i[ 7: 0];
|
|
8'b00000010: wData <= dat_i[15: 8];
|
|
8'b00000100: wData <= dat_i[23:16];
|
|
8'b00001000: wData <= dat_i[31:24];
|
|
8'b00010000: wData <= dat_i[39:32];
|
|
8'b00100000: wData <= dat_i[47:40];
|
|
8'b01000000: wData <= dat_i[55:48];
|
|
8'b10000000: wData <= dat_i[63:56];
|
|
default: wData <= 64'hDEADDEADDEADDEAD;
|
|
endcase
|
|
end
|
|
default: ;
|
|
endcase
|
|
end
|
|
end
|
|
// Stage tail
|
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
|
else if (advanceW) begin
|
|
wextype <= `EX_NON;
|
|
wRt <= 9'd0;
|
|
wData <= 64'd0;
|
|
wIR <= `NOP_INSN;
|
|
wOpcode <= `NOPI;
|
|
wIsStore <= 1'b0;
|
|
wLdPC <= 1'b0;
|
|
wclkoff <= 1'b0;
|
|
wpcv <= 1'b0;
|
|
wpc <= `RESET_VECTOR;
|
end
|
end
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// WRITEBACK:
|
|
// - update the register file with results
|
|
// - record exception address and type
|
|
// - jump to exception handler routine (below)
|
|
// Inputs:
|
|
// - w???? type signals
|
|
// Outputs:
|
|
// - t???? signals
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
if (advanceW) begin
|
|
textype <= wextype;
|
|
tRt <= wRt;
|
|
tData <= wData;
|
|
if (wRt!=5'd0)
|
|
$display("Writing regfile[%d:%d] with %h", wRt[8:5],wRt[4:0], wData);
|
|
case(wOpcode)
|
|
`LSH:
|
|
case (wRt)
|
|
`SR: begin
|
|
bu_im <= wData[31];
|
|
im <= wData[15];
|
|
FXE <= wData[12];
|
|
end
|
|
default: ;
|
|
endcase
|
|
endcase
|
|
if (wclkoff)
|
|
clk_en <= 1'b0;
|
|
else
|
|
clk_en <= 1'b1;
|
|
if (|whwxtype) begin
|
|
dhwxtype <= 2'b00;
|
|
xhwxtype <= 2'b00;
|
|
m1hwxtype <= 2'b00;
|
|
m2hwxtype <= 2'b00;
|
|
whwxtype <= 2'b00;
|
|
end
|
|
if (wFip) begin
|
|
wFip <= 1'b0;
|
|
m2Fip <= 1'b0;
|
|
m1Fip <= 1'b0;
|
|
xFip <= 1'b0;
|
|
dFip <= 1'b0;
|
|
end
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// WRITEBACK (WB') - part two:
|
// WRITEBACK (WB') - part two:
|
// - vector to exception handler address
|
// - vector to exception handler address
|
// In the case of a hardware interrupt (NMI/IRQ) we know
|
// In the case of a hardware interrupt (NMI/IRQ) we know
|
// the pipeline following the interrupt is filled with
|
// the pipeline following the interrupt is filled with
|
Line 3127... |
Line 2823... |
// Tricky because we have to find the first valid
|
// Tricky because we have to find the first valid
|
// PC to record in the IPC register. The interrupt might
|
// PC to record in the IPC register. The interrupt might
|
// have occurred in a branch shadow, in which case the
|
// have occurred in a branch shadow, in which case the
|
// current PC isn't valid.
|
// current PC isn't valid.
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
if (advanceW) begin
|
|
case(wextype)
|
case(wextype)
|
`EX_NON: ;
|
`EX_NON: ;
|
`EX_RST:
|
`EX_RST:
|
begin
|
begin
|
pc <= `RESET_VECTOR;
|
pc <= `RESET_VECTOR;
|
end
|
end
|
`EX_NMI,`EX_IRQ,`EX_DBERR:
|
// Hardware exceptions
|
|
`EX_NMI,`EX_IRQ:
|
begin
|
begin
|
$display("Stuffing SYSJMP");
|
$display("Stuffing SYSJMP");
|
xIR <= {`MISC,19'd0,wextype,`SYSJMP};
|
xIR <= {`MISC,19'd0,wextype,`SYSJMP};
|
pc <= 64'hC;
|
pc <= 64'hC;
|
|
// One of the following three pc's MUST be valid.
|
|
// wpc will be valid if the interrupt occurred outside of a branch
|
|
// shadow. m1pc or m2pc (the branch target address) will be valid
|
|
// depending on where in the branch shadow the interrupt falls.
|
case(1'b1)
|
case(1'b1)
|
wpcv: IPC <= wpc;
|
wpcv: IPC <= wpc;
|
m2pcv: IPC <= m2pc;
|
m2pcv: IPC <= m2pc;
|
m1pcv: IPC <= m1pc;
|
default: IPC <= m1pc;
|
xpcv: IPC <= xpc;
|
// xpcv: IPC <= xpc;
|
dpcv: IPC <= dpc;
|
// dpcv: IPC <= dpc;
|
default: IPC <= pc;
|
// default: IPC <= pc;
|
endcase
|
endcase
|
end
|
end
|
`EX_OFL,`EX_DBZ,`EX_PRIV,`EX_TRAP:
|
// Software exceptions
|
|
// We probably want to return to the excepting instruction.
|
|
`EX_TLBD,`EX_DBERR:
|
begin
|
begin
|
|
pccap <= 1'b0;
|
xIR <= {`MISC,19'd0,wextype,`SYSJMP};
|
xIR <= {`MISC,19'd0,wextype,`SYSJMP};
|
pc <= 64'hC;
|
pc <= 64'hC;
|
EPC <= fnIncPC(wpc);
|
EPC <= wpc;
|
end
|
end
|
default:
|
default:
|
begin
|
begin
|
xIR <= {`MISC,19'd0,wextype,`SYSJMP};
|
xIR <= {`MISC,19'd0,wextype,`SYSJMP};
|
pc <= 64'hC;
|
pc <= 64'hC;
|
Line 3166... |
Line 2869... |
if (wLdPC) begin
|
if (wLdPC) begin
|
$display("Loading PC");
|
$display("Loading PC");
|
pc <= wData;
|
pc <= wData;
|
end
|
end
|
end
|
end
|
|
// Stage tail
|
|
// Pipeline annul for when a bubble in the pipeline occurs.
|
|
// T and W advance together, meaning an else would never be executed.
|
|
|
|
//-----------------------------------------------------------------------------
|
//---------------------------------------------------------
|
// TRAILER:
|
// Trailer (TR')
|
// - placeholder to allow the use of synchronous register memory
|
// - no exceptions
|
//-----------------------------------------------------------------------------
|
//---------------------------------------------------------
|
|
if (advanceT) begin
|
if (advanceT) begin
|
end
|
end
|
|
|
|
|
//---------------------------------------------------------
|
//=============================================================================
|
// Cache loader
|
// Cache loader
|
//---------------------------------------------------------
|
//=============================================================================
|
if (rst_i) begin
|
if (rst_i) begin
|
cstate <= IDLE;
|
cstate <= IDLE;
|
end
|
end
|
else begin
|
else begin
|
case(cstate)
|
case(cstate)
|