Line 30... |
Line 30... |
//`define FLOATING_POINT 1
|
//`define FLOATING_POINT 1
|
//`define BTB 1
|
//`define BTB 1
|
//`define TLB 1
|
//`define TLB 1
|
//`define SIMD 1
|
//`define SIMD 1
|
`define SEGMENTATION 1
|
`define SEGMENTATION 1
|
|
`define SIMPLE_MMU 1
|
|
|
`define RESET_VECTOR 64'hFFFF_FFFF_FFFF_FFF0
|
`define RESET_VECTOR 64'hFFFF_FFFF_FFFF_FFF0
|
|
|
`define EX_NON 9'd000
|
`define EX_NON 9'd000
|
`define EX_TRAP 9'd32 // Trap exception
|
`define EX_TRAP 9'd32 // Trap exception
|
Line 50... |
Line 51... |
`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, irq_no, bte_o, cti_o, bl_o, iocyc_o,
|
module Raptor64sc(rst_i, clk_i, nmi_i, irq_i, irq_no, 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
|
advanceI, advanceR, advanceX, advanceM1, advanceM2, advanceW, advanceT
|
|
);
|
);
|
parameter IDLE = 5'd1;
|
parameter IDLE = 5'd1;
|
parameter ICACT = 5'd2;
|
parameter ICACT = 5'd2;
|
parameter ICACT1 = 5'd4;
|
parameter ICACT1 = 5'd4;
|
parameter ICACT2 = 5'd5;
|
parameter ICACT2 = 5'd5;
|
Line 97... |
Line 97... |
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;
|
|
|
output advanceI;
|
|
output advanceR;
|
|
output advanceX;
|
|
output advanceM1;
|
|
output advanceM2;
|
|
output advanceW;
|
|
output advanceT;
|
|
|
|
wire clk;
|
wire clk;
|
reg [3:0] state;
|
reg [3:0] state;
|
reg [5:0] fltctr;
|
reg [5:0] fltctr;
|
wire fltdone = fltctr==6'd0;
|
wire fltdone = fltctr==6'd0;
|
|
reg inta;
|
reg bu_im; // interrupt mask
|
reg bu_im; // interrupt mask
|
reg im1; // temporary interrupt mask for LM/SM
|
reg im1; // temporary interrupt mask for LM/SM
|
reg [7:0] ie_fuse; // interrupt enable fuse
|
reg [7:0] ie_fuse; // interrupt enable fuse
|
wire im = ~ie_fuse[7];
|
wire im = ~ie_fuse[7];
|
reg [1:0] rm; // fp rounding mode
|
reg [1:0] rm; // fp rounding mode
|
Line 126... |
Line 119... |
reg pccap; // flag 1=capture PC history
|
reg pccap; // flag 1=capture PC history
|
reg [63:0] ErrorEPC;
|
reg [63:0] ErrorEPC;
|
reg [63:0] EPC [0:15]; // Exception return address
|
reg [63:0] EPC [0:15]; // Exception return address
|
reg [63:0] IPC [0:15]; // Interrupt return address
|
reg [63:0] IPC [0:15]; // Interrupt return address
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
reg [63:16] CS [0:15]; // Code segment
|
reg [63:12] segs [0:255];
|
reg [63:16] DS [0:15]; // Data segment
|
|
reg [63:16] SS [0:15]; // Stack segment
|
|
reg [63:16] ES [0:15]; // BSS segment
|
|
`endif
|
`endif
|
reg dStatusHWI,xStatusHWI,m1StatusHWI,m2StatusHWI;
|
reg dStatusHWI,xStatusHWI,m1StatusHWI,m2StatusHWI;
|
reg dIm,xIm,m1Im,m2Im;
|
reg dIm,xIm,m1Im,m2Im;
|
reg dNmi,xNmi,m1Nmi,m2Nmi,wNmi;
|
reg dNmi,xNmi,m1Nmi,m2Nmi,wNmi;
|
reg [15:0] StatusEXL; // 1= context in exception state
|
reg [15:0] StatusEXL; // 1= context in exception state
|
Line 145... |
Line 135... |
reg [4:0] cstate; // cache state
|
reg [4:0] cstate; // cache state
|
reg dbranch_taken,xbranch_taken; // flag: 1=branch taken
|
reg dbranch_taken,xbranch_taken; // flag: 1=branch taken
|
reg [63:0] mutex_gate;
|
reg [63:0] mutex_gate;
|
reg [63:0] TBA; // Trap Base Address
|
reg [63:0] TBA; // Trap Base Address
|
reg [8:0] dextype,d1extype,xextype,m1extype,m2extype,wextype,textype;
|
reg [8:0] dextype,d1extype,xextype,m1extype,m2extype,wextype,textype;
|
reg [3:0] epat [0:255];
|
reg [3:0] epat [0:255]; // execution pattern table
|
reg [7:0] eptr;
|
reg [7:0] eptr;
|
reg [3:0] dAXC,d1AXC,xAXC,m1AXC,m2AXC,wAXC; // context active per pipeline stage
|
reg [3:0] dAXC,d1AXC,xAXC,m1AXC,m2AXC,wAXC; // context active per pipeline stage
|
wire [3:0] AXC = (eptr==8'h00) ? 4'h0 : epat[eptr];
|
wire [3:0] AXC = (eptr==8'h00) ? 4'h0 : epat[eptr];
|
reg dtinit; // 1=data cache tags are being intialized
|
reg dtinit; // 1=data cache tags are being intialized
|
reg dcache_on; // 1= data cache is enabled
|
reg dcache_on; // 1= data cache is enabled
|
Line 183... |
Line 173... |
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 mmu_ack;
|
|
wire [15:0] mmu_dato;
|
|
wire ack_i1 = ack_i | mmu_ack;
|
|
wire [63:0] dat_i1 = dat_i|{4{mmu_dato}};
|
|
|
wire [6:0] iOpcode = insn[31:25];
|
wire [6:0] iOpcode = insn[31:25];
|
wire [6:0] iFunc = insn[6:0];
|
wire [6:0] iFunc = insn[6:0];
|
wire [5:0] iFunc6 = insn[5:0];
|
wire [5:0] iFunc6 = insn[5:0];
|
wire [6:0] dOpcode = dIR[31:25];
|
wire [6:0] dOpcode = dIR[31:25];
|
Line 272... |
Line 266... |
reg [7:0] data8;
|
reg [7:0] data8;
|
reg [15:0] data16;
|
reg [15:0] data16;
|
reg [31:0] data32;
|
reg [31:0] data32;
|
reg [63:0] data64;
|
reg [63:0] data64;
|
|
|
always @(sel_o or dat_i)
|
always @(sel_o or dat_i1)
|
case(sel_o)
|
case(sel_o)
|
8'b00000001: data8 <= #1 dat_i[ 7: 0];
|
8'b00000001: data8 <= #1 dat_i1[ 7: 0];
|
8'b00000010: data8 <= #1 dat_i[15: 8];
|
8'b00000010: data8 <= #1 dat_i1[15: 8];
|
8'b00000100: data8 <= #1 dat_i[23:16];
|
8'b00000100: data8 <= #1 dat_i1[23:16];
|
8'b00001000: data8 <= #1 dat_i[31:24];
|
8'b00001000: data8 <= #1 dat_i1[31:24];
|
8'b00010000: data8 <= #1 dat_i[39:32];
|
8'b00010000: data8 <= #1 dat_i1[39:32];
|
8'b00100000: data8 <= #1 dat_i[47:40];
|
8'b00100000: data8 <= #1 dat_i1[47:40];
|
8'b01000000: data8 <= #1 dat_i[55:48];
|
8'b01000000: data8 <= #1 dat_i1[55:48];
|
8'b10000000: data8 <= #1 dat_i[63:56];
|
8'b10000000: data8 <= #1 dat_i1[63:56];
|
default: data8 <= 8'h00;
|
default: data8 <= 8'h00;
|
endcase
|
endcase
|
|
|
always @(sel_o or dat_i)
|
always @(sel_o or dat_i1)
|
case(sel_o)
|
case(sel_o)
|
8'b00000011: data16 <= #1 dat_i[15: 0];
|
8'b00000011: data16 <= #1 dat_i1[15: 0];
|
8'b00001100: data16 <= #1 dat_i[31:16];
|
8'b00001100: data16 <= #1 dat_i1[31:16];
|
8'b00110000: data16 <= #1 dat_i[47:32];
|
8'b00110000: data16 <= #1 dat_i1[47:32];
|
8'b11000000: data16 <= #1 dat_i[63:48];
|
8'b11000000: data16 <= #1 dat_i1[63:48];
|
default: data16 <= #1 16'hDEAD;
|
default: data16 <= #1 16'hDEAD;
|
endcase
|
endcase
|
|
|
always @(sel_o or dat_i)
|
always @(sel_o or dat_i1)
|
case(sel_o)
|
case(sel_o)
|
8'b00001111: data32 <= #1 dat_i[31: 0];
|
8'b00001111: data32 <= #1 dat_i1[31: 0];
|
8'b11110000: data32 <= #1 dat_i[63:32];
|
8'b11110000: data32 <= #1 dat_i1[63:32];
|
default: data32 <= #1 32'hDEADDEAD;
|
default: data32 <= #1 32'hDEADDEAD;
|
endcase
|
endcase
|
|
|
always @(sel_o or dat_i)
|
always @(sel_o or dat_i1)
|
data64 <= #1 dat_i;
|
data64 <= #1 dat_i1;
|
|
|
assign KernelMode = StatusEXL[xAXC]|StatusHWI;
|
assign KernelMode = StatusEXL[xAXC]|StatusHWI;
|
|
|
//wire iIsLSPair = iOpcode==`SP || iOpcode==`LP || iOpcode==`SFP || iOpcode==`LFP || iOpcode==`SFDP || iOpcode==`LFDP ||
|
//wire iIsLSPair = iOpcode==`SP || iOpcode==`LP || iOpcode==`SFP || iOpcode==`LFP || iOpcode==`SFDP || iOpcode==`LFDP ||
|
// (iOpcode==`MEMNDX && (iFunc6==`SPX || iFunc6==`LPX || iFunc6==`SFPX || iFunc6==`LFPX || iFunc6==`SFDPX || iFunc6==`LFDPX));
|
// (iOpcode==`MEMNDX && (iFunc6==`SPX || iFunc6==`LPX || iFunc6==`SFPX || iFunc6==`LFPX || iFunc6==`SFDPX || iFunc6==`LFDPX));
|
Line 317... |
Line 311... |
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Segmentation
|
// Segmentation
|
//
|
//
|
// If the upper nybble of the address is 'F' then segmentation is not applied.
|
// Paradoxically, it's less expensive to provide an array of 16 segment
|
// This allows for bootstrapping and operating system use. Also when in kernel
|
// registers as opposed to several independent registers. The 16 registers
|
// mode the lowest 64k of memory is unsegmented to allow easier access to
|
// are lower cost than the independent CS,DS,ES, and SS registers were.
|
// operating system variables.
|
|
//
|
|
// Otherwise: the CS register is always in use for code addresses.
|
|
// Which segment is used for data addresses depends on the upper nybble of
|
|
// the address.
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
`ifdef SEGMENTATION
|
`ifdef SEGMENTATION
|
wire [63:0] spc; // segmented PC
|
wire [63:0] spc; // segmented PC
|
reg [63:0] sea; // segmented effective address
|
wire [63:0] sea; // segmented effective address
|
assign spc = pc[63:60]==4'hF ? pc : {CS[AXC][63:16] + pc[59:16],pc[15:0]};
|
assign spc = {segs[{pc[63:60], AXC}][63:12] + pc[59:12],pc[11:0]};
|
always @(ea or KernelMode)
|
assign sea = {segs[{ea[63:60],xAXC}][63:12] + ea[59:12],ea[11:0]};
|
if (KernelMode && ea[63:16]==48'h0)
|
initial begin
|
sea <= ea;
|
for (n = 0; n < 256; n = n + 1)
|
else
|
segs[n] = 52'd0;
|
case(ea[63:60])
|
end
|
4'hF: sea <= ea;
|
|
4'hE: sea <= {SS[xAXC][63:16] + ea[59:16],ea[15:0]};
|
|
4'hD: sea <= {ES[xAXC][63:16] + ea[59:16],ea[15:0]};
|
|
default:
|
|
sea <= {DS[xAXC][63:16] + ea[59:16],ea[15:0]};
|
|
endcase
|
|
`else
|
`else
|
wire [63:0] spc = pc;
|
wire [63:0] spc = pc;
|
wire [63:0] sea = ea;
|
wire [63:0] sea = ea;
|
`endif
|
`endif
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
`ifdef SIMPLE_MMU
|
|
SimpleMMU ummu1
|
|
(
|
|
.num(3'd0),
|
|
.rst_i(rst_i),
|
|
.clk_i(clk),
|
|
.dma_i(1'b0),
|
|
.kernel_mode(KernelMode),
|
|
.cyc_i(iocyc_o),
|
|
.stb_i(stb_o),
|
|
.ack_o(mmu_ack),
|
|
.we_i(we_o),
|
|
.adr_i(adr_o[23:0]),
|
|
.dat_i(dat_o[15:0]),
|
|
.dat_o(mmu_dato),
|
|
.rclk(~clk),
|
|
.pc_i(spc[27:0]),
|
|
.pc_o(ppc[27:0]),
|
|
.ea_i(sea[27:0]),
|
|
.ea_o(pea[27:0])
|
|
);
|
|
assign pea[63:28]=sea[63:28];
|
|
assign ppc[63:28]=spc[63:28];
|
|
`endif
|
|
|
|
//-----------------------------------------------------------------------------
|
// 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.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
wire [63:0] ppc;
|
wire [63:0] ppc;
|
Line 394... |
Line 404... |
.DTLBMiss(DTLBMiss),
|
.DTLBMiss(DTLBMiss),
|
.HTLBVirtPage(TLBVirtPage)
|
.HTLBVirtPage(TLBVirtPage)
|
);
|
);
|
|
|
`else
|
`else
|
|
`ifndef SIMPLE_MMU
|
assign ppc = spc;
|
assign ppc = spc;
|
assign pea = sea;
|
assign pea = sea;
|
`endif
|
`endif
|
|
`endif
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// 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 477... |
Line 489... |
.wclk(clk),
|
.wclk(clk),
|
.we(icaccess & (ack_i|err_i)),
|
.we(icaccess & (ack_i|err_i)),
|
.adr(icadr[13:0]),
|
.adr(icadr[13:0]),
|
.d(err_i ? bevect : dat_i),
|
.d(err_i ? bevect : dat_i),
|
.rclk(~clk),
|
.rclk(~clk),
|
.pc(pc[13:0]),
|
.pc(ppc[13:0]),
|
.insn(insnbundle)
|
.insn(insnbundle)
|
);
|
);
|
|
|
always @(insnbundle or ICacheAct or insnbuf)
|
always @(insnbundle or ICacheAct or insnbuf)
|
begin
|
begin
|
Line 504... |
Line 516... |
for (n=0; n < 256; n = n + 1)
|
for (n=0; n < 256; n = n + 1)
|
tvalid[n] = 0;
|
tvalid[n] = 0;
|
end
|
end
|
|
|
wire [64:14] tgout;
|
wire [64:14] tgout;
|
assign tgout = {tvalid[pc[13:6]],tmem[pc[13:6]]};
|
assign tgout = {tvalid[ppc[13:6]],tmem[ppc[13:6]]};
|
assign ihit = (tgout=={1'b1,ppc[63:14]});
|
assign ihit = (tgout=={1'b1,ppc[63:14]});
|
assign ibufrdy = ibufadr[63:2]==ppc[63:2];
|
assign ibufrdy = ibufadr[63:2]==ppc[63:2];
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Data Cache
|
// Data Cache
|
Line 1093... |
Line 1105... |
wire eqi = a==imm;
|
wire eqi = a==imm;
|
wire lt = $signed(a) < $signed(b);
|
wire lt = $signed(a) < $signed(b);
|
wire lti = $signed(a) < $signed(imm);
|
wire lti = $signed(a) < $signed(imm);
|
wire ltu = a < b;
|
wire ltu = a < b;
|
wire ltui = a < imm;
|
wire ltui = a < imm;
|
|
wire [7:0] segndx = xFunc6==`MFSEG ? {xIR[9:6],xAXC} : {a[63:60],xAXC};
|
|
|
always @(xOpcode or xFunc or xFunc5 or a or b or c or imm or xpc or aeqz or xFunc6 or
|
always @(xOpcode or xFunc or xFunc5 or a or b or c or imm or xpc or aeqz or xFunc6 or
|
sqrt_out or cntlzo or cntloo or tick or AXC or scale or
|
sqrt_out or cntlzo or cntloo or tick or AXC or scale 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 bcdmulo or fpLooOut or fpZLOut or m_z or m_w or
|
shfto or masko or bcdmulo or fpLooOut or fpZLOut or m_z or m_w or
|
Line 1168... |
Line 1181... |
xData1[15:8] = tlbo[15:8];
|
xData1[15:8] = tlbo[15:8];
|
end
|
end
|
`PageTableAddr: xData1 = {PageTableAddr,13'd0};
|
`PageTableAddr: xData1 = {PageTableAddr,13'd0};
|
`BadVAddr: xData1 = {BadVAddr,13'd0};
|
`BadVAddr: xData1 = {BadVAddr,13'd0};
|
`endif
|
`endif
|
`ifdef SEGMENTATION
|
|
`CS: xData1 = {CS[xAXC],16'h0};
|
|
`DS: xData1 = {DS[xAXC],16'h0};
|
|
`ES: xData1 = {ES[xAXC],16'b0};
|
|
`SS: xData1 = {SS[xAXC],16'h0};
|
|
`endif
|
|
`ASID: xData1 = ASID;
|
`ASID: xData1 = ASID;
|
`Tick: xData1 = tick;
|
`Tick: xData1 = tick;
|
`EPC: xData1 = EPC[xAXC];
|
`EPC: xData1 = EPC[xAXC];
|
`IPC: xData1 = IPC[xAXC];
|
`IPC: xData1 = IPC[xAXC];
|
`TBA: xData1 = TBA;
|
`TBA: xData1 = TBA;
|
Line 1190... |
Line 1197... |
`SRAND2: xData1 = m_w;
|
`SRAND2: xData1 = m_w;
|
`INSNKEY: xData1 = insnkey;
|
`INSNKEY: xData1 = insnkey;
|
`PCHISTORIC: xData1 = pchistoric;
|
`PCHISTORIC: xData1 = pchistoric;
|
default: xData1 = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
|
`ifdef SEGMENTATION
|
|
`MFSEG,`MFSEGI: xData1 = segs[segndx];
|
|
`MTSEG: xData1 = a;
|
|
`endif
|
`OMG: xData1 = mutex_gate[a[5:0]];
|
`OMG: xData1 = mutex_gate[a[5:0]];
|
`CMG: xData1 = mutex_gate[a[5:0]];
|
`CMG: xData1 = mutex_gate[a[5:0]];
|
`OMGI: begin
|
`OMGI: begin
|
xData1 = mutex_gate[xIR[11:6]];
|
xData1 = mutex_gate[xIR[11:6]];
|
$display("mutex_gate[%d]=%d",xIR[11:6],mutex_gate[xIR[11:6]]);
|
$display("mutex_gate[%d]=%d",xIR[11:6],mutex_gate[xIR[11:6]]);
|
Line 1217... |
Line 1228... |
`DIVU: xData1 = div_q;
|
`DIVU: xData1 = div_q;
|
`MODU: xData1 = div_r;
|
`MODU: xData1 = div_r;
|
`MODS: xData1 = div_r;
|
`MODS: xData1 = div_r;
|
`BCD_MUL: xData1 = bcdmulo;
|
`BCD_MUL: xData1 = bcdmulo;
|
`MFEP: xData1 = epat[a[7:0]];
|
`MFEP: xData1 = epat[a[7:0]];
|
|
`ifdef SEGMENTATION
|
|
`MTSEGI: xData1 = b;
|
|
`endif
|
default: xData1 = 64'd0;
|
default: xData1 = 64'd0;
|
endcase
|
endcase
|
`ifdef SIMD
|
`ifdef SIMD
|
`SIMD:
|
`SIMD:
|
case(xFunc6)
|
case(xFunc6)
|
Line 1534... |
Line 1548... |
wire tForwardingActive = (tRt==dRa || tRt==dRb || tRt==dRc) & !tRtz;
|
wire tForwardingActive = (tRt==dRa || tRt==dRb || tRt==dRc) & !tRtz;
|
wire wForwardingActive = (wRt==dRa || wRt==dRb || wRt==dRc) & !wRtz;
|
wire wForwardingActive = (wRt==dRa || wRt==dRb || wRt==dRc) & !wRtz;
|
wire m2ForwardingActive = (m2Rt==dRa || m2Rt==dRb || m2Rt==dRc) & !m2Rtz;
|
wire m2ForwardingActive = (m2Rt==dRa || m2Rt==dRb || m2Rt==dRc) & !m2Rtz;
|
wire m1ForwardingActive = (m1Rt==dRa || m1Rt==dRb || m1Rt==dRc) & !m1Rtz;
|
wire m1ForwardingActive = (m1Rt==dRa || m1Rt==dRb || m1Rt==dRc) & !m1Rtz;
|
wire xForwardingActive = (xRt==dRa || xRt==dRb || xRt==dRc) & !xRtz;
|
wire xForwardingActive = (xRt==dRa || xRt==dRb || xRt==dRc) & !xRtz;
|
wire memCycleActive = ((iocyc_o & !(ack_i|err_i)) || (cyc_o & !(ack_i|err_i)));
|
wire memCycleActive = ((iocyc_o & !(ack_i1|err_i)) || (cyc_o & !(ack_i1|err_i)));
|
wire StallI = 1'b0;
|
wire StallI = 1'b0;
|
|
|
// 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
|
// Could check for dRa,dRb,dRc==0, for non-stalling
|
// Could check for dRa,dRb,dRc==0, for non-stalling
|
wire StallR = ((( xIsLoad||xIsIn||xIsCnt) && xForwardingActive) || xIsSWC) ||
|
wire StallR = ((( xIsLoad||xIsIn||xIsCnt) && xForwardingActive) || xIsSWC) ||
|
Line 1556... |
Line 1570... |
wire StallW = (wForwardingActive && ((m1IsLoad & m1IsCacheElement & !dhit) || memCycleActive));
|
wire StallW = (wForwardingActive && ((m1IsLoad & m1IsCacheElement & !dhit) || memCycleActive));
|
wire StallT = (tForwardingActive && ((m1IsLoad & m1IsCacheElement & !dhit) || memCycleActive)) || dcaccess;
|
wire StallT = (tForwardingActive && ((m1IsLoad & m1IsCacheElement & !dhit) || memCycleActive)) || dcaccess;
|
|
|
assign advanceT = (state==RUN) && !StallT;
|
assign advanceT = (state==RUN) && !StallT;
|
assign advanceW = advanceT & !StallW;
|
assign advanceW = advanceT & !StallW;
|
assign advanceM2 = advanceW && (cyc_o ? (ack_i|err_i) : 1'b1) && !StallM2;
|
assign advanceM2 = advanceW && (cyc_o ? (ack_i1|err_i) : 1'b1) && !StallM2;
|
assign advanceM1 = advanceM2 &
|
assign advanceM1 = advanceM2 &
|
(iocyc_o ? (ack_i|err_i) : 1'b1) &
|
(iocyc_o ? (ack_i1|err_i) : 1'b1) &
|
((m1IsLoad & m1IsCacheElement) ? dhit : 1'b1) &
|
((m1IsLoad & m1IsCacheElement) ? dhit : 1'b1) &
|
!StallM1
|
!StallM1
|
;
|
;
|
assign advanceX = advanceM1 & (
|
assign advanceX = advanceM1 & (
|
xIsSqrt ? sqrt_done :
|
xIsSqrt ? sqrt_done :
|
Line 1799... |
Line 1813... |
m2Rt <= 9'd0;
|
m2Rt <= 9'd0;
|
tData <= 64'd0;
|
tData <= 64'd0;
|
wData <= 64'd0;
|
wData <= 64'd0;
|
m1Data <= 64'd0;
|
m1Data <= 64'd0;
|
m2Data <= 64'd0;
|
m2Data <= 64'd0;
|
|
wData <= 64'd0;
|
icaccess <= 1'b0;
|
icaccess <= 1'b0;
|
dcaccess <= 1'b0;
|
dcaccess <= 1'b0;
|
wFip <= 1'b0;
|
wFip <= 1'b0;
|
m2Fip <= 1'b0;
|
m2Fip <= 1'b0;
|
m1Fip <= 1'b0;
|
m1Fip <= 1'b0;
|
xFip <= 1'b0;
|
xFip <= 1'b0;
|
dFip <= 1'b0;
|
dFip <= 1'b0;
|
dirqf <= 1'b0;
|
dirqf <= 1'b0;
|
|
inta <= 1'b0;
|
dNmi <= 1'b0;
|
dNmi <= 1'b0;
|
xNmi <= 1'b0;
|
xNmi <= 1'b0;
|
m1Nmi <= 1'b0;
|
m1Nmi <= 1'b0;
|
m2Nmi <= 1'b0;
|
m2Nmi <= 1'b0;
|
tick <= 64'd0;
|
tick <= 64'd0;
|
Line 1855... |
Line 1871... |
|
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
// Initialize program counters
|
// Initialize program counters
|
// Initialize data tags to zero.
|
// Initialize data tags to zero.
|
// Initialize execution pattern register to zero.
|
// Initialize execution pattern register to zero.
|
|
// Initialize segment registers to zero.
|
//---------------------------------------------------------
|
//---------------------------------------------------------
|
case(state)
|
case(state)
|
RESET:
|
RESET:
|
begin
|
begin
|
pc <= `RESET_VECTOR;
|
$display("Resetting %h",adr_o[14:6]);
|
adr_o[14:6] <= adr_o[14:6]+9'd1;
|
adr_o[14:6] <= adr_o[14:6]+9'd1;
|
if (adr_o[14:6]==9'h1FF) begin
|
if (adr_o[14:6]==9'h1FF) begin
|
dtinit <= 1'b0;
|
dtinit <= 1'b0;
|
state <= RUN;
|
state <= RUN;
|
end
|
end
|
epat[a[7:0]] <= b[3:0]; /// b=0, to make this line the same as MTEP
|
epat[a[7:0]] <= b[3:0]; /// b=0, to make this line the same as MTEP
|
a[7:0] <= a[7:0] + 8'h1;
|
a[7:0] <= a[7:0] + 8'h1;
|
|
wIR[9:6] <= a[7:4];
|
|
wAXC <= wAXC + 4'd1;
|
|
segs[{wIR[9:6],wAXC}] <= wData; // same line as in WB stage, wData =0
|
end
|
end
|
RUN:
|
RUN:
|
begin
|
begin
|
|
|
ie_fuse <= {ie_fuse[6:0],ie_fuse[0]}; // shift counter
|
ie_fuse <= {ie_fuse[6:0],ie_fuse[0]}; // shift counter
|
|
|
tick <= tick + 64'd1;
|
tick <= tick + 64'd1;
|
|
$display("tick: %d", tick[31:0]);
|
|
|
prev_nmi <= nmi_i;
|
prev_nmi <= nmi_i;
|
if (!prev_nmi & nmi_i)
|
if (!prev_nmi & nmi_i)
|
nmi_edge <= 1'b1;
|
nmi_edge <= 1'b1;
|
|
|
Line 2301... |
Line 2322... |
default: ;
|
default: ;
|
endcase
|
endcase
|
`RR:
|
`RR:
|
case(xFunc6)
|
case(xFunc6)
|
`MTEP: epat[a[7:0]] <= b[3:0];
|
`MTEP: epat[a[7:0]] <= b[3:0];
|
|
`MTSEGI: m1IR[9:6] <= a[63:60];
|
default: ;
|
default: ;
|
endcase
|
endcase
|
// JMP and CALL change the program counter immediately in the IF stage.
|
// 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.
|
// There's no work to do here. The pipeline does not need to be cleared.
|
`JMP: ;
|
`JMP: ;
|
Line 3292... |
Line 3314... |
endcase
|
endcase
|
`R:
|
`R:
|
case(wFunc6)
|
case(wFunc6)
|
`MTSPR:
|
`MTSPR:
|
case(wIR[11:6])
|
case(wIR[11:6])
|
`ifdef SEGMENTATION
|
|
`CS: CS[wAXC][63:16] <= wData[63:16];
|
|
`DS: DS[wAXC][63:16] <= wData[63:16];
|
|
`ES: ES[wAXC][63:16] <= wData[63:16];
|
|
`SS: SS[wAXC][63:16] <= wData[63:16];
|
|
`endif
|
|
`IPC: begin
|
`IPC: begin
|
$display("mtspr IPC[%d]=%h",wAXC,wData);
|
$display("mtspr IPC[%d]=%h",wAXC,wData);
|
IPC[wAXC] <= wData;
|
IPC[wAXC] <= wData;
|
end
|
end
|
`EPC: EPC[wAXC] <= wData;
|
`EPC: EPC[wAXC] <= wData;
|
default: ;
|
default: ;
|
endcase
|
endcase
|
|
`ifdef SEGMENTATION
|
|
`MTSEG: segs[{wIR[9:6],wAXC}] <= wData[63:12];
|
|
`endif
|
|
endcase
|
|
`RR:
|
|
case(wFunc6)
|
|
`ifdef SEGMENTATION
|
|
`MTSEGI: segs[{wIR[9:6],wAXC}] <= wData[63:12];
|
|
`endif
|
|
default: ;
|
endcase
|
endcase
|
|
default: ;
|
endcase
|
endcase
|
if (wclkoff)
|
if (wclkoff)
|
clk_en <= 1'b0;
|
clk_en <= 1'b0;
|
else
|
else
|
clk_en <= 1'b1;
|
clk_en <= 1'b1;
|
Line 3433... |
Line 3460... |
adr_o <= {ppc[63:6],6'h00};
|
adr_o <= {ppc[63:6],6'h00};
|
icadr <= {ppc[63:6],6'h00};
|
icadr <= {ppc[63:6],6'h00};
|
cstate <= ICACT1;
|
cstate <= ICACT1;
|
end
|
end
|
else begin
|
else begin
|
|
$display("Fetching %h", {ppc[31:2],2'b00});
|
cti_o <= 3'b000;
|
cti_o <= 3'b000;
|
bl_o <= 5'd0;
|
bl_o <= 5'd0;
|
adr_o <= {ppc[63:2],2'b00};
|
adr_o <= {ppc[63:2],2'b00};
|
cstate <= ICACT2;
|
cstate <= ICACT2;
|
end
|
end
|
Line 3466... |
Line 3494... |
ibufadr <= adr_o;
|
ibufadr <= adr_o;
|
if (err_i)
|
if (err_i)
|
insnbuf <= syscall509;
|
insnbuf <= syscall509;
|
else
|
else
|
insnbuf <= adr_o[2] ? dat_i[63:32] : dat_i[31:0];
|
insnbuf <= adr_o[2] ? dat_i[63:32] : dat_i[31:0];
|
|
$display("Fetched: %h", adr_o[2] ? dat_i[63:32] : dat_i[31:0]);
|
cti_o <= 3'b000; // back to non-burst mode
|
cti_o <= 3'b000; // back to non-burst mode
|
cyc_o <= 1'b0;
|
cyc_o <= 1'b0;
|
stb_o <= 1'b0;
|
stb_o <= 1'b0;
|
sel_o <= 8'h00;
|
sel_o <= 8'h00;
|
icaccess <= 1'b0;
|
icaccess <= 1'b0;
|