This commit is contained in:
bbracker 2021-10-03 00:30:49 -04:00
commit 07ff0940a3
19 changed files with 434 additions and 439 deletions

View File

@ -43,7 +43,7 @@ view wave
do ./wave-dos/peripheral-waves.do do ./wave-dos/peripheral-waves.do
-- Run the Simulation -- Run the Simulation
#run 5000 #run 3600
run -all run -all
#quit #quit
noview ../testbench/testbench-imperas.sv noview ../testbench/testbench-imperas.sv

View File

@ -35,6 +35,24 @@ add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
#add wave /testbench/dut/hart/ieu/dp/PCSrcE #add wave /testbench/dut/hart/ieu/dp/PCSrcE
add wave /testbench/dut/hart/mdu/genblk1/div/StartDivideE
add wave /testbench/dut/hart/mdu/DivBusyE
add wave /testbench/dut/hart/mdu/DivDoneE
add wave -hex /testbench/dut/hart/mdu/genblk1/div/DE
add wave -hex /testbench/dut/hart/mdu/genblk1/div/Din
add wave -hex /testbench/dut/hart/mdu/genblk1/div/XE
add wave -hex /testbench/dut/hart/mdu/genblk1/div/Win
add wave -hex /testbench/dut/hart/mdu/genblk1/div/XQin
add wave -hex /testbench/dut/hart/mdu/genblk1/div/Wshift
add wave -hex /testbench/dut/hart/mdu/genblk1/div/XQshift
add wave -hex /testbench/dut/hart/mdu/genblk1/div/Wnext
add wave -hex /testbench/dut/hart/mdu/genblk1/div/qi
add wave -hex /testbench/dut/hart/mdu/genblk1/div/Wprime
add wave -hex /testbench/dut/hart/mdu/genblk1/div/W
add wave -hex /testbench/dut/hart/mdu/genblk1/div/XQ
add wave -hex /testbench/dut/hart/mdu/genblk1/div/RemM
add wave -hex /testbench/dut/hart/mdu/genblk1/div/QuotM
add wave -divider add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCM add wave -hex /testbench/dut/hart/ifu/PCM
add wave -hex /testbench/dut/hart/ifu/InstrM add wave -hex /testbench/dut/hart/ifu/InstrM
@ -48,9 +66,9 @@ add wave -hex /testbench/dut/hart/lsu/dcache/ReadDataM
add wave -hex /testbench/dut/hart/ebu/ReadDataM add wave -hex /testbench/dut/hart/ebu/ReadDataM
add wave -divider add wave -divider
add wave -hex /testbench/PCW add wave -hex /testbench/PCW
add wave -hex /testbench/InstrW #add wave -hex /testbench/InstrW
add wave -hex /testbench/dut/hart/ieu/c/InstrValidW add wave -hex /testbench/dut/hart/ieu/c/InstrValidW
add wave /testbench/InstrWName #add wave /testbench/InstrWName
add wave -hex /testbench/dut/hart/ReadDataW add wave -hex /testbench/dut/hart/ReadDataW
add wave -hex /testbench/dut/hart/ieu/dp/ResultW add wave -hex /testbench/dut/hart/ieu/dp/ResultW
add wave -hex /testbench/dut/hart/ieu/dp/RegWriteW add wave -hex /testbench/dut/hart/ieu/dp/RegWriteW

View File

@ -25,8 +25,6 @@
`include "wally-config.vh" `include "wally-config.vh"
/* verilator lint_off DECLFILENAME */ /* verilator lint_off DECLFILENAME */
// Note that non-zero RESET_VAL's are only ever intended for simulation purposes (to start mid-execution from a checkpoint)
// ordinary flip-flop // ordinary flip-flop
module flop #(parameter WIDTH = 8) ( module flop #(parameter WIDTH = 8) (
@ -42,11 +40,10 @@ endmodule
module flopr #(parameter WIDTH = 8) ( module flopr #(parameter WIDTH = 8) (
input logic clk, reset, input logic clk, reset,
input logic [WIDTH-1:0] d, input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q, output logic [WIDTH-1:0] q);
input var [WIDTH-1:0] RESET_VAL=0);
always_ff @(posedge clk, posedge reset) always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 RESET_VAL; if (reset) q <= #1 0;
else q <= #1 d; else q <= #1 d;
endmodule endmodule
@ -64,11 +61,10 @@ endmodule
module flopenrc #(parameter WIDTH = 8) ( module flopenrc #(parameter WIDTH = 8) (
input logic clk, reset, clear, en, input logic clk, reset, clear, en,
input logic [WIDTH-1:0] d, input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q, output logic [WIDTH-1:0] q);
input var [WIDTH-1:0] RESET_VAL=0);
always_ff @(posedge clk, posedge reset) always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 RESET_VAL; if (reset) q <= #1 0;
else if (en) else if (en)
if (clear) q <= #1 0; if (clear) q <= #1 0;
else q <= #1 d; else q <= #1 d;
@ -78,11 +74,10 @@ endmodule
module flopenr #(parameter WIDTH = 8) ( module flopenr #(parameter WIDTH = 8) (
input logic clk, reset, en, input logic clk, reset, en,
input logic [WIDTH-1:0] d, input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q, output logic [WIDTH-1:0] q);
input var [WIDTH-1:0] RESET_VAL=0);
always_ff @(posedge clk, posedge reset) always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 RESET_VAL; if (reset) q <= #1 0;
else if (en) q <= #1 d; else if (en) q <= #1 d;
endmodule endmodule
@ -104,11 +99,10 @@ module floprc #(parameter WIDTH = 8) (
input logic reset, input logic reset,
input logic clear, input logic clear,
input logic [WIDTH-1:0] d, input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q, output logic [WIDTH-1:0] q);
input var RESET_VAL=0);
always_ff @(posedge clk, posedge reset) always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 RESET_VAL; if (reset) q <= #1 0;
else else
if (clear) q <= #1 0; if (clear) q <= #1 0;
else q <= #1 d; else q <= #1 d;

View File

@ -0,0 +1,34 @@
///////////////////////////////////////////
// neg.sv
//
// Written: David_Harris@hmc.edu 28 September 2021
// Modified:
//
// Purpose: 2's complement negator
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module neg #(parameter WIDTH = 8) (
input logic [WIDTH-1:0] a,
output logic [WIDTH-1:0] y);
assign y = ~a + 1;
endmodule

View File

@ -33,6 +33,7 @@ module forward(
input logic DivDoneE, DivBusyE, input logic DivDoneE, DivBusyE,
input logic FWriteIntE, FWriteIntM, FWriteIntW, input logic FWriteIntE, FWriteIntM, FWriteIntW,
input logic SCE, input logic SCE,
input logic StallD,
// Forwarding controls // Forwarding controls
output logic [1:0] ForwardAE, ForwardBE, output logic [1:0] ForwardAE, ForwardBE,
output logic FPUStallD, LoadStallD, MulDivStallD, CSRRdStallD output logic FPUStallD, LoadStallD, MulDivStallD, CSRRdStallD
@ -53,7 +54,7 @@ module forward(
// Stall on dependent operations that finish in Mem Stage and can't bypass in time // Stall on dependent operations that finish in Mem Stage and can't bypass in time
assign FPUStallD = FWriteIntE & ((Rs1D == RdE) | (Rs2D == RdE)); assign FPUStallD = FWriteIntE & ((Rs1D == RdE) | (Rs2D == RdE));
assign LoadStallD = (MemReadE|SCE) & ((Rs1D == RdE) | (Rs2D == RdE)); assign LoadStallD = (MemReadE|SCE) & ((Rs1D == RdE) | (Rs2D == RdE));
assign MulDivStallD = MulDivE & ((Rs1D == RdE) | (Rs2D == RdE)) | MulDivE | DivBusyE; // *** extend with stalls for divide assign MulDivStallD = MulDivE & ((Rs1D == RdE) | (Rs2D == RdE)) /*| DivBusyE */; // *** extend with stalls for divide
assign CSRRdStallD = CSRReadE & ((Rs1D == RdE) | (Rs2D == RdE)); assign CSRRdStallD = CSRReadE & ((Rs1D == RdE) | (Rs2D == RdE));
endmodule endmodule

View File

@ -44,13 +44,7 @@ module regfile (
// reset is intended for simulation only, not synthesis // reset is intended for simulation only, not synthesis
always_ff @(negedge clk or posedge reset) always_ff @(negedge clk or posedge reset)
if (reset) if (reset) for(i=1; i<32; i++) rf[i] <= 0;
`ifdef CHECKPOINT
$readmemh({`LINUX_CHECKPOINT,"checkpoint-regfile.txt"}, rf);
`else
for(i=1; i<32; i++) rf[i] <= 0;
`endif
else if (we3) rf[a3] <= wd3; else if (we3) rf[a3] <= wd3;
assign #2 rd1 = (a1 != 0) ? rf[a1] : 0; assign #2 rd1 = (a1 != 0) ? rf[a1] : 0;

View File

@ -1,76 +0,0 @@
///////////////////////////////////////////
// intdiv_restoring.sv
//
// Written: David_Harris@hmc.edu 12 September 2021
// Modified:
//
// Purpose: Restoring integer division using a shift register a subtractor
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module intdiv_restoring (
input logic clk,
input logic reset,
input logic signedDivide,
input logic start,
input logic [`XLEN-1:0] X, D,
output logic busy, done,
output logic [`XLEN-1:0] Q, REM
);
logic [`XLEN-1:0] W, Win, Wshift, Wprime, Wnext, XQ, XQin, XQshift;
logic qi; // curent quotient bit
localparam STEPBITS = $clog2(`XLEN);
logic [STEPBITS:0] step;
logic div0;
// restoring division
mux2 #(`XLEN) wmux(W, 0, start, Win);
mux2 #(`XLEN) xmux(0, X, start, XQin);
assign {Wshift, XQshift} = {Win[`XLEN-2:0], XQin, qi};
assign {qi, Wprime} = Wshift - D; // subtractor, carry out determines quotient bit
mux2 #(`XLEN) wrestoremux(Wshift, Wprime, qi, Wnext);
flopen #(`XLEN) wreg(clk, busy, Wnext, W);
flopen #(`XLEN) xreg(clk, busy, XQshift, XQ);
// outputs
// *** sign extension, handling W instructions
assign div0 = (D == 0);
mux2 #(`XLEN) qmux(XQ, {`XLEN{1'b1}}, div0, Q); // Q taken from XQ register, or all 1s when dividing by zero
mux2 #(`XLEN) remmux(W, X, div0, REM); // REM taken from W register, or from X when dividing by zero
// busy logic
always_ff @(posedge clk)
if (start) begin
busy = 1; done = 0; step = 0;
end else if (busy) begin
step = step + 1;
if (step[STEPBITS] | div0) begin // *** early terminate on division by 0
step = 0;
busy = 0;
done = 1;
end
end else if (done) begin
done = 0;
end
endmodule // muldiv

View File

@ -0,0 +1,112 @@
///////////////////////////////////////////
// intdivrestoring.sv
//
// Written: David_Harris@hmc.edu 12 September 2021
// Modified:
//
// Purpose: Restoring integer division using a shift register and subtractor
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module intdivrestoring (
input logic clk,
input logic reset,
input logic StallM, FlushM,
input logic SignedDivideE,
input logic StartDivideE,
input logic [`XLEN-1:0] XE, DE,
output logic BusyE, done,
output logic [`XLEN-1:0] QuotM, RemM
);
logic [`XLEN-1:0] W, W2, Win, Wshift, Wprime, Wn, Wnn, Wnext, XQ, XQin, XQshift, XQn, XQnn, XQnext, DSavedE, Din, Dabs, D2, DnE, XnE, Xabs, X2, XSavedE, Xinit, DAbsB, W1, XQ1;
logic qi, qib; // curent quotient bit
localparam STEPBITS = $clog2(`XLEN)-1;
logic [STEPBITS:0] step;
logic div0;
logic init, startd, SignX, SignD, NegW, NegQ;
logic SignedDivideM;
// *** add pipe stages to everything
// save inputs on the negative edge of the execute clock.
// This is unusual practice, but the inputs are not guaranteed to be stable due to some hazard and forwarding logic.
// Saving the inputs is the most hardware-efficient way to fix the issue.
flopen #(`XLEN) dsavereg(~clk, StartDivideE, DE, DSavedE);
flopen #(`XLEN) xsavereg(~clk, StartDivideE, XE, XSavedE);
flopenrc #(1) SignedDivideMReg(clk, reset, FlushM, ~StallM, SignedDivideE, SignedDivideM);
assign SignD = DSavedE[`XLEN-1]; // *** do some of these need pipelining for consecutive divides?
assign SignX = XSavedE[`XLEN-1];
assign div0 = (DSavedE == 0);
// Take absolute value for signed operations
neg #(`XLEN) negd(DSavedE, DnE);
mux2 #(`XLEN) dabsmux(DSavedE, DnE, SignedDivideE & SignD, Din); // take absolute value for signed operations
neg #(`XLEN) negx(XSavedE, XnE);
mux2 #(`XLEN) xabsmux(XSavedE, XnE, SignedDivideE & SignX, Xinit); // need original X as remainder if doing divide by 0
// Negate D for subtraction
assign DAbsB = ~Din;
// initialization multiplexers on first cycle of operation (one cycle after start is asserted)
mux2 #(`XLEN) wmux(W, {`XLEN{1'b0}}, init, Win);
mux2 #(`XLEN) xmux(XQ, Xinit, init, XQin);
// *** parameterize steps per cycle
intdivrestoringstep step1(Win, XQin, DAbsB, W1, XQ1);
intdivrestoringstep step2(W1, XQ1, DAbsB, Wnext, XQnext);
flopen #(`XLEN) wreg(clk, BusyE, Wnext, W);
flopen #(`XLEN) xreg(clk, BusyE, XQnext, XQ);
// Output selection logic in Memory Stage
// On final setp of signed operations, negate outputs as needed
assign NegW = SignedDivideM & SignX;
assign NegQ = SignedDivideM & (SignX ^ SignD);
neg #(`XLEN) wneg(W, Wn);
neg #(`XLEN) qneg(XQ, XQn);
// Select appropriate output: normal, negated, or for divide by zero
mux3 #(`XLEN) qmux(XQ, XQn, {`XLEN{1'b1}}, {div0, NegQ}, QuotM); // Q taken from XQ register, negated if necessary, or all 1s when dividing by zero
mux3 #(`XLEN) remmux(W, Wn, XSavedE, {div0, NegW}, RemM); // REM taken from W register, negated if necessary, or from X when dividing by zero
// busy logic
always_ff @(posedge clk)
if (reset) begin
BusyE = 0; done = 0; step = 0; init = 0;
end else if (StartDivideE & ~StallM) begin
if (div0) done = 1;
else begin
BusyE = 1; step = 0; init = 1;
end
end else if (BusyE & ~done) begin // pause one cycle at beginning of signed operations for absolute value
init = 0;
step = step + 1;
if (step[STEPBITS]) begin
step = 0;
BusyE = 0;
done = 1;
end
end else if (done) begin
done = 0;
BusyE = 0;
end
endmodule
// *** clean up internal signals

View File

@ -0,0 +1,40 @@
///////////////////////////////////////////
// intdivrestoringstep.sv
//
// Written: David_Harris@hmc.edu 2 October 2021
// Modified:
//
// Purpose: Restoring integer division using a shift register and subtractor
//
// A component of the Wally configurable RISC-V project.
//
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////
`include "wally-config.vh"
module intdivrestoringstep(
input logic [`XLEN-1:0] W, XQ, DAbsB,
output logic [`XLEN-1:0] WOut, XQOut);
logic [`XLEN-1:0] WShift, WPrime;
logic qi, qib;
assign {WShift, XQOut} = {W[`XLEN-2:0], XQ, qi};
assign {qib, WPrime} = {1'b0, WShift} + {1'b1, DAbsB} + 1; // subtractor, carry out determines quotient bit ***replace with add
assign qi = ~qib;
mux2 #(`XLEN) wrestoremux(WShift, WPrime, qi, WOut);
endmodule

View File

@ -31,7 +31,7 @@ module muldiv (
input logic [31:0] InstrD, input logic [31:0] InstrD,
// Execute Stage interface // Execute Stage interface
input logic [`XLEN-1:0] SrcAE, SrcBE, input logic [`XLEN-1:0] SrcAE, SrcBE,
input logic [2:0] Funct3E, input logic [2:0] Funct3E, Funct3M,
input logic MulDivE, W64E, input logic MulDivE, W64E,
// Writeback stage // Writeback stage
output logic [`XLEN-1:0] MulDivResultW, output logic [`XLEN-1:0] MulDivResultW,
@ -45,98 +45,67 @@ module muldiv (
generate generate
if (`M_SUPPORTED) begin if (`M_SUPPORTED) begin
logic [`XLEN-1:0] MulDivResultE, MulDivResultM; logic [`XLEN-1:0] MulDivResultE, MulDivResultM;
logic [`XLEN-1:0] PrelimResultE; logic [`XLEN-1:0] PrelimResultM;
logic [`XLEN-1:0] QuotE, RemE; logic [`XLEN-1:0] QuotM, RemM;
logic [`XLEN*2-1:0] ProdE; logic [`XLEN*2-1:0] ProdE, ProdM;
logic enable_q; logic enable_q;
logic [2:0] Funct3E_Q; //logic [2:0] Funct3E_Q;
logic div0error; // ***unused logic div0error; // ***unused
logic [`XLEN-1:0] N, D; logic [`XLEN-1:0] XE, DE;
logic [`XLEN-1:0] Num0, Den0; //logic [`XLEN-1:0] Num0, Den0;
// logic gclk;
logic StartDivideE, BusyE;
logic SignedDivideE;
logic W64M;
logic gclk;
logic DivStartE;
logic startDivideE;
logic signedDivide;
// Multiplier // Multiplier
mul mul(.*); mul mul(.*);
// Divide flopenrc #(`XLEN*2) ProdMReg(clk, reset, FlushM, ~StallM, ProdE, ProdM);
// *** replace this clock gater // Divide
always @(negedge clk) begin
enable_q <= ~StallM;
end
assign gclk = enable_q & clk;
// Handle sign extension for W-type instructions // Handle sign extension for W-type instructions
if (`XLEN == 64) begin // RV64 has W-type instructions if (`XLEN == 64) begin // RV64 has W-type instructions
assign Num0 = W64E ? {{32{SrcAE[31]&signedDivide}}, SrcAE[31:0]} : SrcAE; assign XE = W64E ? {{32{SrcAE[31]&SignedDivideE}}, SrcAE[31:0]} : SrcAE;
assign Den0 = W64E ? {{32{SrcBE[31]&signedDivide}}, SrcBE[31:0]} : SrcBE; assign DE = W64E ? {{32{SrcBE[31]&SignedDivideE}}, SrcBE[31:0]} : SrcBE;
end else begin // RV32 has no W-type instructions end else begin // RV32 has no W-type instructions
assign Num0 = SrcAE; assign XE = SrcAE;
assign Den0 = SrcBE; assign DE = SrcBE;
end end
// capture the Numerator/Denominator assign SignedDivideE = ~Funct3E[0]; // simplified from (Funct3E[2]&~Funct3E[1]&~Funct3E[0]) | (Funct3E[2]&Funct3E[1]&~Funct3E[0]);
flopenrc #(`XLEN) reg_num (.d(Num0), .q(N), //intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, StartDivideE, SignedDivideE);
.en(startDivideE), .clear(DivDoneE), intdivrestoring div(.clk, .reset, .StallM, .FlushM,
.reset(reset), .clk(~gclk)); .SignedDivideE, .StartDivideE, .XE, .DE, .BusyE, .done(DivDoneE), .QuotM, .RemM);
flopenrc #(`XLEN) reg_den (.d(Den0), .q(D),
.en(startDivideE), .clear(DivDoneE),
.reset(reset), .clk(~gclk));
assign signedDivide = (Funct3E[2]&~Funct3E[1]&~Funct3E[0]) | (Funct3E[2]&Funct3E[1]&~Funct3E[0]); // Start a divide when a new division instruction is received and the divider isn't already busy or finishing
intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, startDivideE, signedDivide); assign StartDivideE = MulDivE & Funct3E[2] & ~BusyE & ~DivDoneE; // *** mabye DivDone should be M stage
//intdiv_restoring div(.clk, .reset, .signedDivide, .start(startDivideE), .X(N), .D(D), .busy(DivBusyE), .done(DivDoneE), .Q(QuotE), .REM(RemE)); assign DivBusyE = StartDivideE | BusyE;
// Added for debugging of start signal for divide
assign startDivideE = MulDivE&DivStartE&~DivBusyE;
// capture the start control signals since they are not held constant.
// *** appears to be unused
flopenrc #(3) funct3ereg (.d(Funct3E),
.q(Funct3E_Q),
.en(DivStartE),
.clear(DivDoneE),
.reset(reset),
.clk(clk));
// Select result // Select result
always_comb always_comb
case (Funct3E) case (Funct3M)
3'b000: PrelimResultE = ProdE[`XLEN-1:0]; 3'b000: PrelimResultM = ProdM[`XLEN-1:0];
3'b001: PrelimResultE = ProdE[`XLEN*2-1:`XLEN]; 3'b001: PrelimResultM = ProdM[`XLEN*2-1:`XLEN];
3'b010: PrelimResultE = ProdE[`XLEN*2-1:`XLEN]; 3'b010: PrelimResultM = ProdM[`XLEN*2-1:`XLEN];
3'b011: PrelimResultE = ProdE[`XLEN*2-1:`XLEN]; 3'b011: PrelimResultM = ProdM[`XLEN*2-1:`XLEN];
3'b100: PrelimResultE = QuotE; 3'b100: PrelimResultM = QuotM;
3'b101: PrelimResultE = QuotE; 3'b101: PrelimResultM = QuotM;
3'b110: PrelimResultE = RemE; 3'b110: PrelimResultM = RemM;
3'b111: PrelimResultE = RemE; 3'b111: PrelimResultM = RemM;
endcase // case (Funct3E)
// Start Divide process. This simplifies to DivStartE = Funct3E[2];
always_comb
case (Funct3E)
3'b000: DivStartE = 1'b0;
3'b001: DivStartE = 1'b0;
3'b010: DivStartE = 1'b0;
3'b011: DivStartE = 1'b0;
3'b100: DivStartE = 1'b1;
3'b101: DivStartE = 1'b1;
3'b110: DivStartE = 1'b1;
3'b111: DivStartE = 1'b1;
endcase endcase
// Handle sign extension for W-type instructions // Handle sign extension for W-type instructions
flopenrc #(1) W64MReg(clk, reset, FlushM, ~StallM, W64E, W64M);
if (`XLEN == 64) begin // RV64 has W-type instructions if (`XLEN == 64) begin // RV64 has W-type instructions
assign MulDivResultE = W64E ? {{32{PrelimResultE[31]}}, PrelimResultE[31:0]} : PrelimResultE; assign MulDivResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM;
end else begin // RV32 has no W-type instructions end else begin // RV32 has no W-type instructions
assign MulDivResultE = PrelimResultE; assign MulDivResultM = PrelimResultM;
end end
flopenrc #(`XLEN) MulDivResultMReg(clk, reset, FlushM, ~StallM, MulDivResultE, MulDivResultM);
flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW); flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW);
end else begin // no M instructions supported end else begin // no M instructions supported

View File

@ -70,24 +70,24 @@ module csrc #(parameter
// ... more counters // ... more counters
//HPMCOUNTER31H = 12'hC9F //HPMCOUNTER31H = 12'hC9F
) ( ) (
input logic clk, reset, input logic clk, reset,
input logic StallD, StallE, StallM, StallW, input logic StallD, StallE, StallM, StallW,
input logic FlushD, FlushE, FlushM, FlushW, input logic FlushD, FlushE, FlushM, FlushW,
input logic InstrValidM, LoadStallD, CSRMWriteM, input logic InstrValidM, LoadStallD, CSRMWriteM,
input logic BPPredDirWrongM, input logic BPPredDirWrongM,
input logic BTBPredPCWrongM, input logic BTBPredPCWrongM,
input logic RASPredPCWrongM, input logic RASPredPCWrongM,
input logic BPPredClassNonCFIWrongM, input logic BPPredClassNonCFIWrongM,
input logic [4:0] InstrClassM, input logic [4:0] InstrClassM,
input logic DCacheMiss, input logic DCacheMiss,
input logic DCacheAccess, input logic DCacheAccess,
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic [1:0] PrivilegeModeW, input logic [1:0] PrivilegeModeW,
input logic [`XLEN-1:0] CSRWriteValM, input logic [`XLEN-1:0] CSRWriteValM,
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW, input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
input logic [63:0] MTIME_CLINT, MTIMECMP_CLINT, input logic [63:0] MTIME_CLINT, MTIMECMP_CLINT,
output logic [`XLEN-1:0] CSRCReadValM, output logic [`XLEN-1:0] CSRCReadValM,
output logic IllegalCSRCAccessM output logic IllegalCSRCAccessM
); );
generate generate
@ -97,22 +97,14 @@ module csrc #(parameter
logic [63:0] HPMCOUNTER3_REGW, HPMCOUNTER4_REGW; // add more performance counters here if desired logic [63:0] HPMCOUNTER3_REGW, HPMCOUNTER4_REGW; // add more performance counters here if desired
logic [63:0] CYCLEPlusM, INSTRETPlusM; logic [63:0] CYCLEPlusM, INSTRETPlusM;
logic [63:0] HPMCOUNTER3PlusM, HPMCOUNTER4PlusM; logic [63:0] HPMCOUNTER3PlusM, HPMCOUNTER4PlusM;
// logic [`XLEN-1:0] NextTIMEM; // logic [`XLEN-1:0] NextTIMEM;
logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM; logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM;
logic [`XLEN-1:0] NextHPMCOUNTER3M, NextHPMCOUNTER4M; logic [`XLEN-1:0] NextHPMCOUNTER3M, NextHPMCOUNTER4M;
logic WriteCYCLEM, WriteINSTRETM; logic WriteCYCLEM, WriteINSTRETM;
logic WriteHPMCOUNTER3M, WriteHPMCOUNTER4M; logic WriteHPMCOUNTER3M, WriteHPMCOUNTER4M;
logic [4:0] CounterNumM; logic [4:0] CounterNumM;
logic [`COUNTERS-1:3][`XLEN-1:0] HPMCOUNTER_REGW, HPMCOUNTERH_REGW; logic [`COUNTERS-1:3][`XLEN-1:0] HPMCOUNTER_REGW, HPMCOUNTERH_REGW;
var [`COUNTERS-1:3][`XLEN-1:0] initHPMCOUNTER; logic InstrValidNotFlushedM;
logic InstrValidNotFlushedM;
initial
`ifdef CHECKPOINT
$readmemh({`LINUX_CHECKPOINT,"checkpoint-HPMCOUNTER.txt"}, initHPMCOUNTER);
`else
initHPMCOUNTER = {(`COUNTERS-3){`XLEN'b0}};
`endif
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW; assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
@ -138,116 +130,121 @@ module csrc #(parameter
//assign NextHPMCOUNTER3M = WriteHPMCOUNTER3M ? CSRWriteValM : HPMCOUNTER3PlusM[`XLEN-1:0]; //assign NextHPMCOUNTER3M = WriteHPMCOUNTER3M ? CSRWriteValM : HPMCOUNTER3PlusM[`XLEN-1:0];
//assign NextHPMCOUNTER4M = WriteHPMCOUNTER4M ? CSRWriteValM : HPMCOUNTER4PlusM[`XLEN-1:0]; //assign NextHPMCOUNTER4M = WriteHPMCOUNTER4M ? CSRWriteValM : HPMCOUNTER4PlusM[`XLEN-1:0];
// parameterized number of additional counters // parameterized number of additional counters
if (`COUNTERS > 3) begin if (`COUNTERS > 3) begin
logic [`COUNTERS-1:3] WriteHPMCOUNTERM; logic [`COUNTERS-1:3] WriteHPMCOUNTERM;
logic [`COUNTERS-1:0] CounterEvent; logic [`COUNTERS-1:0] CounterEvent;
logic [63:0] /*HPMCOUNTER_REGW[`COUNTERS-1:3], */ HPMCOUNTERPlusM[`COUNTERS-1:3]; logic [63:0] /*HPMCOUNTER_REGW[`COUNTERS-1:3], */ HPMCOUNTERPlusM[`COUNTERS-1:3];
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:3]; logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:3];
genvar i; genvar i;
// could replace special counters 0-2 with this loop for all counters // could replace special counters 0-2 with this loop for all counters
assign CounterEvent[0] = 1'b1; assign CounterEvent[0] = 1'b1;
assign CounterEvent[1] = 1'b0; assign CounterEvent[1] = 1'b0;
if(`QEMU) assign CounterEvent[`COUNTERS-1:2] = 0; if(`QEMU) begin
else begin assign CounterEvent[`COUNTERS-1:2] = 0;
logic LoadStallE, LoadStallM; end else begin
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(FlushE), .en(~StallE), .d(LoadStallD), .q(LoadStallE));
flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
assign CounterEvent[2] = InstrValidNotFlushedM; logic LoadStallE, LoadStallM;
assign CounterEvent[3] = LoadStallM & InstrValidNotFlushedM;
assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM; flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(FlushE), .en(~StallE), .d(LoadStallD), .q(LoadStallE));
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM; flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM; assign CounterEvent[2] = InstrValidNotFlushedM;
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM; assign CounterEvent[3] = LoadStallM & InstrValidNotFlushedM;
assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM; assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM;
assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM; assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM;
assign CounterEvent[11] = DCacheAccess & InstrValidNotFlushedM; assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
assign CounterEvent[12] = DCacheMiss & InstrValidNotFlushedM; assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM;
assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM;
end assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM;
assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM;
assign CounterEvent[11] = DCacheAccess & InstrValidNotFlushedM;
assign CounterEvent[12] = DCacheMiss & InstrValidNotFlushedM;
assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
end
for (i = 3; i < `COUNTERS; i = i+1) begin for (i = 3; i < `COUNTERS; i = i+1) begin
assign WriteHPMCOUNTERM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERBASE + i); assign WriteHPMCOUNTERM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERBASE + i);
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0]; assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0];
always @(posedge clk, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 initHPMCOUNTER[i];
else if (~StallW) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
//flopr #(`XLEN) HPMCOUNTERreg[i](clk, reset, NextHPMCOUNTERM[i], HPMCOUNTER_REGW[i]);
if (`XLEN==32) begin
logic [`COUNTERS-1:3] WriteHPMCOUNTERHM;
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:3];
assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
assign WriteHPMCOUNTERHM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERHBASE + i);
assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32];
always @(posedge clk, posedge reset) // ModelSim doesn't like syntax of passing array element to flop always @(posedge clk, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0; if (reset) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 0;
else if (~StallW) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i]; else if (~StallW) HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
//flopr #(`XLEN) HPMCOUNTERHreg[i](clk, reset, NextHPMCOUNTERHM[i], HPMCOUNTER_REGW[i][63:32]); //flopr #(`XLEN) HPMCOUNTERreg[i](clk, reset, NextHPMCOUNTERM[i], HPMCOUNTER_REGW[i]);
end else begin
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]}; if (`XLEN==32) begin
end logic [`COUNTERS-1:3] WriteHPMCOUNTERHM;
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:3];
assign HPMCOUNTERPlusM[i] = {HPMCOUNTERH_REGW[i], HPMCOUNTER_REGW[i]} + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
assign WriteHPMCOUNTERHM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERHBASE + i);
assign NextHPMCOUNTERHM[i] = WriteHPMCOUNTERHM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][63:32];
always @(posedge clk, posedge reset) // ModelSim doesn't like syntax of passing array element to flop
if (reset) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 0;
else if (~StallW) HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
//flopr #(`XLEN) HPMCOUNTERHreg[i](clk, reset, NextHPMCOUNTERHM[i], HPMCOUNTER_REGW[i][63:32]);
end else begin
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
end
end end
end end
// Write / update counters // Write / update counters
// Only the Machine mode versions of the counter CSRs are writable // Only the Machine mode versions of the counter CSRs are writable
if (`XLEN==64) begin// 64-bit counters if (`XLEN==64) begin// 64-bit counters
// flopr #(64) TIMEreg(clk, reset, WriteTIMEM ? CSRWriteValM : TIME_REGW + 1, TIME_REGW); // may count off a different clock*** // flopr #(64) TIMEreg(clk, reset, WriteTIMEM ? CSRWriteValM : TIME_REGW + 1, TIME_REGW); // may count off a different clock***
// flopenr #(64) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW); // flopenr #(64) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW);
flopr #(64) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW); flopr #(64) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW);
flopr #(64) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW); flopr #(64) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW);
//flopr #(64) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW); //flopr #(64) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW);
//flopr #(64) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW); //flopr #(64) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW);
end else begin // 32-bit low and high counters end else begin // 32-bit low and high counters
logic WriteTIMEHM, WriteTIMECMPHM, WriteCYCLEHM, WriteINSTRETHM; logic WriteTIMEHM, WriteTIMECMPHM, WriteCYCLEHM, WriteINSTRETHM;
//logic WriteHPMCOUNTER3HM, WriteHPMCOUNTER4HM; //logic WriteHPMCOUNTER3HM, WriteHPMCOUNTER4HM;
logic [`XLEN-1:0] NextCYCLEHM, NextTIMEHM, NextINSTRETHM; logic [`XLEN-1:0] NextCYCLEHM, NextTIMEHM, NextINSTRETHM;
//logic [`XLEN-1:0] NextHPMCOUNTER3HM, NextHPMCOUNTER4HM; //logic [`XLEN-1:0] NextHPMCOUNTER3HM, NextHPMCOUNTER4HM;
// Write Enables // Write Enables
// assign WriteTIMEHM = CSRMWriteM && (CSRAdrM == MTIMEH); // assign WriteTIMEHM = CSRMWriteM && (CSRAdrM == MTIMEH);
// assign WriteTIMECMPHM = CSRMWriteM && (CSRAdrM == MTIMECMPH); // assign WriteTIMECMPHM = CSRMWriteM && (CSRAdrM == MTIMECMPH);
assign WriteCYCLEHM = CSRMWriteM && (CSRAdrM == MCYCLEH); assign WriteCYCLEHM = CSRMWriteM && (CSRAdrM == MCYCLEH);
assign WriteINSTRETHM = CSRMWriteM && (CSRAdrM == MINSTRETH); assign WriteINSTRETHM = CSRMWriteM && (CSRAdrM == MINSTRETH);
//assign WriteHPMCOUNTER3HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER3H); //assign WriteHPMCOUNTER3HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER3H);
//assign WriteHPMCOUNTER4HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER4H); //assign WriteHPMCOUNTER4HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER4H);
assign NextCYCLEHM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM[63:32]; assign NextCYCLEHM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM[63:32];
// assign NextTIMEHM = WriteTIMEHM ? CSRWriteValM : TIMEPlusM[63:32]; // assign NextTIMEHM = WriteTIMEHM ? CSRWriteValM : TIMEPlusM[63:32];
assign NextINSTRETHM = WriteINSTRETHM ? CSRWriteValM : INSTRETPlusM[63:32]; assign NextINSTRETHM = WriteINSTRETHM ? CSRWriteValM : INSTRETPlusM[63:32];
//assign NextHPMCOUNTER3HM = WriteHPMCOUNTER3HM ? CSRWriteValM : HPMCOUNTER3PlusM[63:32]; //assign NextHPMCOUNTER3HM = WriteHPMCOUNTER3HM ? CSRWriteValM : HPMCOUNTER3PlusM[63:32];
//assign NextHPMCOUNTER4HM = WriteHPMCOUNTER4HM ? CSRWriteValM : HPMCOUNTER4PlusM[63:32]; //assign NextHPMCOUNTER4HM = WriteHPMCOUNTER4HM ? CSRWriteValM : HPMCOUNTER4PlusM[63:32];
// Counter CSRs // Counter CSRs
// flopr #(32) TIMEreg(clk, reset, NextTIMEM, TIME_REGW); // may count off a different clock*** // flopr #(32) TIMEreg(clk, reset, NextTIMEM, TIME_REGW); // may count off a different clock***
// flopenr #(32) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW[31:0]); // flopenr #(32) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW[31:0]);
flopr #(32) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW[31:0]); flopr #(32) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW[31:0]);
flopr #(32) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW[31:0]); flopr #(32) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW[31:0]);
// flopr #(32) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW[31:0]); //flopr #(32) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW[31:0]);
// flopr #(32) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW[31:0]); //flopr #(32) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW[31:0]);
// flopr #(32) TIMEHreg(clk, reset, NextTIMEHM, TIME_REGW); // may count off a different clock*** // flopr #(32) TIMEHreg(clk, reset, NextTIMEHM, TIME_REGW); // may count off a different clock***
// flopenr #(32) TIMECMPHreg(clk, reset, WriteTIMECMPHM, CSRWriteValM, TIMECMP_REGW[63:32]); // flopenr #(32) TIMECMPHreg(clk, reset, WriteTIMECMPHM, CSRWriteValM, TIMECMP_REGW[63:32]);
flopr #(32) CYCLEHreg(clk, reset, NextCYCLEHM, CYCLE_REGW[63:32]); flopr #(32) CYCLEHreg(clk, reset, NextCYCLEHM, CYCLE_REGW[63:32]);
flopr #(32) INSTRETHreg(clk, reset, NextINSTRETHM, INSTRET_REGW[63:32]); flopr #(32) INSTRETHreg(clk, reset, NextINSTRETHM, INSTRET_REGW[63:32]);
//flopr #(32) HPMCOUNTER3Hreg(clk, reset, NextHPMCOUNTER3HM, HPMCOUNTER3_REGW[63:32]); //flopr #(32) HPMCOUNTER3Hreg(clk, reset, NextHPMCOUNTER3HM, HPMCOUNTER3_REGW[63:32]);
//flopr #(32) HPMCOUNTER4Hreg(clk, reset, NextHPMCOUNTER4HM, HPMCOUNTER4_REGW[63:32]); //flopr #(32) HPMCOUNTER4Hreg(clk, reset, NextHPMCOUNTER4HM, HPMCOUNTER4_REGW[63:32]);
end end
// eventually move TIME and TIMECMP to the CLINT -- Ben 06/17/21: sure let's give that a shot! // eventually move TIME and TIMECMP to the CLINT -- Ben 06/17/21: sure let's give that a shot!
// run TIME off asynchronous reference clock // run TIME off asynchronous reference clock
// synchronize write enable to TIME // synchronize write enable to TIME
// four phase handshake to synchronize reads from TIME // four phase handshake to synchronize reads from TIME
// interrupt on timer compare // interrupt on timer compare
// ability to disable optional CSRs // ability to disable optional CSRs
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags // Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
assign CounterNumM = CSRAdrM[4:0]; // which counter to read? assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
if (`XLEN==64) // 64-bit counter reads if (`XLEN==64) // 64-bit counter reads
always_comb always_comb
if (PrivilegeModeW == `M_MODE || MCOUNTEREN_REGW[CounterNumM] && (PrivilegeModeW == `S_MODE || SCOUNTEREN_REGW[CounterNumM])) begin if (PrivilegeModeW == `M_MODE ||
MCOUNTEREN_REGW[CounterNumM] && (PrivilegeModeW == `S_MODE || SCOUNTEREN_REGW[CounterNumM])) begin
IllegalCSRCAccessM = 0; IllegalCSRCAccessM = 0;
if (CSRAdrM >= MHPMCOUNTERBASE+3 && CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CSRAdrM-MHPMCOUNTERBASE]; if (CSRAdrM >= MHPMCOUNTERBASE+3 && CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CSRAdrM-MHPMCOUNTERBASE];
else if (CSRAdrM >= HPMCOUNTERBASE+3 && CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CSRAdrM-HPMCOUNTERBASE]; else if (CSRAdrM >= HPMCOUNTERBASE+3 && CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CSRAdrM-HPMCOUNTERBASE];
@ -312,7 +309,7 @@ module csrc #(parameter
IllegalCSRCAccessM = 1; // no privileges for this csr IllegalCSRCAccessM = 1; // no privileges for this csr
CSRCReadValM = 0; CSRCReadValM = 0;
end end
end else begin // not `ZICOUNTERS_SUPPORTED end else begin
assign CSRCReadValM = 0; assign CSRCReadValM = 0;
assign IllegalCSRCAccessM = 1; assign IllegalCSRCAccessM = 1;
end end
@ -359,20 +356,20 @@ module csrc #(parameter
MPHMEVENTBASE = 12'h320, MPHMEVENTBASE = 12'h320,
HPMCOUNTERBASE = 12'hC00, HPMCOUNTERBASE = 12'hC00,
HPMCOUNTERHBASE = 12'hC80, HPMCOUNTERHBASE = 12'hC80,
)(input logic clk, reset, )(input logic clk, reset,
input logic StallD, StallE, StallM, StallW, input logic StallD, StallE, StallM, StallW,
input logic InstrValidM, LoadStallD, CSRMWriteM, input logic InstrValidM, LoadStallD, CSRMWriteM,
input logic BPPredDirWrongM, input logic BPPredDirWrongM,
input logic BTBPredPCWrongM, input logic BTBPredPCWrongM,
input logic RASPredPCWrongM, input logic RASPredPCWrongM,
input logic BPPredClassNonCFIWrongM, input logic BPPredClassNonCFIWrongM,
input logic [4:0] InstrClassM, input logic [4:0] InstrClassM,
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic [1:0] PrivilegeModeW, input logic [1:0] PrivilegeModeW,
input logic [`XLEN-1:0] CSRWriteValM, input logic [`XLEN-1:0] CSRWriteValM,
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW, input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
output logic [`XLEN-1:0] CSRCReadValM, output logic [`XLEN-1:0] CSRCReadValM,
output logic IllegalCSRCAccessM); output logic IllegalCSRCAccessM);
// counters // counters

View File

@ -79,24 +79,14 @@ module csri #(parameter
assign SIP_WRITE_MASK = 12'h000; assign SIP_WRITE_MASK = 12'h000;
end end
always @(posedge clk, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21 always @(posedge clk, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21
if (reset) if (reset) IP_REGW_writeable <= 10'b0;
`ifdef CHECKPOINT
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MIP.txt"}, IP_REGW_writeable);
`else
IP_REGW_writeable <= 10'b0;
`endif
else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable else if (WriteMIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & MIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable else if (WriteSIPM) IP_REGW_writeable <= (CSRWriteValM[9:0] & SIP_WRITE_MASK[9:0]) | IntInM[9:0]; // MTIP unclearable
// else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable // else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable
else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes else IP_REGW_writeable <= IP_REGW_writeable | IntInM[9:0]; // *** check this turns off interrupts properly even when MIDELEG changes
end end
always @(posedge clk, posedge reset) begin always @(posedge clk, posedge reset) begin
if (reset) if (reset) IE_REGW <= 12'b0;
`ifdef CHECKPOINT
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MIE.txt"}, IE_REGW);
`else
IE_REGW <= 12'b0;
`endif
else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields else if (WriteMIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'hAAA); // MIE controls M and S fields
else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields else if (WriteSIEM) IE_REGW <= (CSRWriteValM[11:0] & 12'h222) | (IE_REGW & 12'h888); // only S fields
// else if (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field // else if (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field

View File

@ -85,45 +85,15 @@ module csrm #(parameter
logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW; logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW;
logic [`XLEN-1:0] MSCRATCH_REGW, MCAUSE_REGW, MTVAL_REGW; logic [`XLEN-1:0] MSCRATCH_REGW, MCAUSE_REGW, MTVAL_REGW;
var [`XLEN-1:0] initMSCRATCH, initMCAUSE, initMEPC, initMTVEC, initMEDELEG, initMIDELEG; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
var [31:0] initMCOUNTEREN, initMCOUNTINHIBIT; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
var [`PMP_ENTRIES-1:0][7:0] initPMPCFG_ARRAY; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
var [`PMP_ENTRIES-1:0][`XLEN-1:0] initPMPADDR_ARRAY;
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
logic [`PMP_ENTRIES-1:0] WritePMPCFGM; logic [`PMP_ENTRIES-1:0] WritePMPCFGM;
logic [`PMP_ENTRIES-1:0] WritePMPADDRM ; logic [`PMP_ENTRIES-1:0] WritePMPADDRM ;
logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked; logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
localparam MISA_26 = (`MISA) & 32'h03ffffff; localparam MISA_26 = (`MISA) & 32'h03ffffff;
initial begin
`ifdef CHECKPOINT
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MSCRATCH.txt"}, initMSCRATCH);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MCAUSE.txt"}, initMCAUSE);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MEPC.txt"}, initMEPC);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MTVEC.txt"}, initMTVEC);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MEDELEG.txt"}, initMEDELEG);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MIDELEG.txt"}, initMIDELEG);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MCOUNTEREN.txt"}, initMCOUNTEREN);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-PMPCFG.txt"}, initPMPCFG_ARRAY);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-PMPADDR.txt"}, initPMPADDR_ARRAY);
`else
initMSCRATCH = `XLEN'b0;
initMCAUSE = `XLEN'b0;
initMEPC = `XLEN'b0;
initMTVEC = `XLEN'b0;
initMEDELEG = `XLEN'b0;
initMIDELEG = `XLEN'b0;
initMCOUNTEREN = 32'b0;
initMCOUNTINHIBIT = 32'b0;
initPMPCFG_ARRAY = {`PMP_ENTRIES{8'b0}};
initPMPADDR_ARRAY = {`PMP_ENTRIES{`XLEN'b0}};
`endif
end
// MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally // MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally
assign MISA_REGW = {(`XLEN == 32 ? 2'b01 : 2'b10), {(`XLEN-28){1'b0}}, MISA_26[25:0]}; assign MISA_REGW = {(`XLEN == 32 ? 2'b01 : 2'b10), {(`XLEN-28){1'b0}}, MISA_26[25:0]};
@ -145,31 +115,33 @@ module csrm #(parameter
assign IllegalCSRMWriteReadonlyM = CSRMWriteM && (CSRAdrM == MVENDORID || CSRAdrM == MARCHID || CSRAdrM == MIMPID || CSRAdrM == MHARTID); assign IllegalCSRMWriteReadonlyM = CSRMWriteM && (CSRAdrM == MVENDORID || CSRAdrM == MARCHID || CSRAdrM == MIMPID || CSRAdrM == MHARTID);
// CSRs // CSRs
flopenl #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, initMTVEC, MTVEC_REGW); //busybear: changed reset value to 0 flopenl #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `XLEN'b0, MTVEC_REGW); //busybear: changed reset value to 0
generate generate
if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin // DELEG registers should exist if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin // DELEG registers should exist
flopenl #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, initMEDELEG, MEDELEG_REGW); flopenl #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, `XLEN'b0, MEDELEG_REGW);
flopenl #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, initMIDELEG, MIDELEG_REGW); flopenl #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, `XLEN'b0, MIDELEG_REGW);
end else begin end else begin
assign MEDELEG_REGW = 0; assign MEDELEG_REGW = 0;
assign MIDELEG_REGW = 0; assign MIDELEG_REGW = 0;
end end
endgenerate endgenerate
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW, initMSCRATCH); // flopenl #(`XLEN) MIPreg(clk, reset, WriteMIPM, CSRWriteValM, zero, MIP_REGW);
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW, initMEPC); // flopenl #(`XLEN) MIEreg(clk, reset, WriteMIEM, CSRWriteValM, zero, MIE_REGW);
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW, initMCAUSE); flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW);
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW);
if(`QEMU) assign MTVAL_REGW = `XLEN'b0; if(`QEMU) assign MTVAL_REGW = `XLEN'b0;
else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW); else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
generate generate
if (`BUSYBEAR == 1) if (`BUSYBEAR == 1)
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, MCOUNTEREN_REGW); flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, MCOUNTEREN_REGW);
else if (`BUILDROOT == 1) else if (`BUILDROOT == 1)
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], initMCOUNTEREN, MCOUNTEREN_REGW); flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], 32'h0, MCOUNTEREN_REGW);
else else
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, MCOUNTEREN_REGW); flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, MCOUNTEREN_REGW);
endgenerate endgenerate
flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], initMCOUNTINHIBIT, MCOUNTINHIBIT_REGW); flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], 32'h0, MCOUNTINHIBIT_REGW);
// There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop // There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop
@ -186,14 +158,14 @@ module csrm #(parameter
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01); assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01);
assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~StallW & ~ADDRLocked[i]; assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~StallW & ~ADDRLocked[i];
flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i], initPMPADDR_ARRAY[i]); flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]);
if (`XLEN==64) begin if (`XLEN==64) begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i]; assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i];
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i], initPMPCFG_ARRAY[i]); flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]);
end else begin end else begin
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i]; assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i];
// assign WritePMPCFGHM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i+1)) && ~StallW; // assign WritePMPCFGHM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i+1)) && ~StallW;
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i], initPMPCFG_ARRAY[i]); flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]);
// flopenr #(`XLEN) PMPCFGHreg(clk, reset, WritePMPCFGHM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i][63:32]); // flopenr #(`XLEN) PMPCFGHreg(clk, reset, WritePMPCFGHM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i][63:32]);
end end
end end

View File

@ -74,30 +74,6 @@ module csrs #(parameter
logic WriteSSCRATCHM, WriteSEPCM; logic WriteSSCRATCHM, WriteSEPCM;
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW; logic [`XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW;
var [`XLEN-1:0] initSSCRATCH, initSCAUSE, initSEPC, initSTVEC, initSEDELEG, initSIDELEG, initSATP;
var [31:0] initSCOUNTEREN;
initial begin
`ifdef CHECKPOINT
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SSCRATCH.txt"}, initSSCRATCH);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SCAUSE.txt"}, initSCAUSE);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SEPC.txt"}, initSEPC);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-STVEC.txt"}, initSTVEC);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SEDELEG.txt"}, initSEDELEG);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SIDELEG.txt"}, initSIDELEG);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SCOUNTEREN.txt"}, initSCOUNTEREN);
$readmemh({`LINUX_CHECKPOINT,"checkpoint-SATP.txt"}, initSATP);
`else
initSSCRATCH = `XLEN'b0;
initSCAUSE = `XLEN'b0;
initSEPC = `XLEN'b0;
initSTVEC = `XLEN'b0;
initSEDELEG = `XLEN'b0;
initSIDELEG = `XLEN'b0;
initSCOUNTEREN = 32'b0;
initSATP = `XLEN'b0;
`endif
end
assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS) && ~StallW; assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS) && ~StallW;
assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC) && ~StallW; assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC) && ~StallW;
@ -109,28 +85,28 @@ module csrs #(parameter
assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN) && ~StallW; assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN) && ~StallW;
// CSRs // CSRs
flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, initSTVEC, STVEC_REGW); //busybear: change reset to 0 flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `XLEN'b0, STVEC_REGW); //busybear: change reset to 0
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW, initSSCRATCH); flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW, initSEPC); flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
flopenl #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, initSCAUSE, SCAUSE_REGW); flopenl #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, `XLEN'b0, SCAUSE_REGW);
if(`QEMU) assign STVAL_REGW = `XLEN'b0; if(`QEMU) assign STVAL_REGW = `XLEN'b0;
else flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW); else flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
if (`MEM_VIRTMEM) if (`MEM_VIRTMEM)
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW, initSATP); flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
else else
assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported
if (`BUSYBEAR == 1) if (`BUSYBEAR == 1)
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW); flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW);
else if (`BUILDROOT == 1) else if (`BUILDROOT == 1)
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], initSCOUNTEREN, SCOUNTEREN_REGW); flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], 32'h0, SCOUNTEREN_REGW);
else else
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, SCOUNTEREN_REGW); flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, SCOUNTEREN_REGW);
if (`N_SUPPORTED) begin if (`N_SUPPORTED) begin
logic WriteSEDELEGM, WriteSIDELEGM; logic WriteSEDELEGM, WriteSIDELEGM;
assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG); assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG);
assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG); assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG);
flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK /* 12'h1FF */, initSEDELEG, SEDELEG_REGW); flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK /* 12'h1FF */, `XLEN'b0, SEDELEG_REGW);
flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, initSIDELEG, SIDELEG_REGW); flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, `XLEN'b0, SIDELEG_REGW);
end else begin end else begin
assign SEDELEG_REGW = 0; assign SEDELEG_REGW = 0;
assign SIDELEG_REGW = 0; assign SIDELEG_REGW = 0;

View File

@ -46,15 +46,6 @@ module csrsr (
logic [1:0] STATUS_SXL, STATUS_UXL, STATUS_XS, STATUS_FS, STATUS_FS_INT, STATUS_MPP_NEXT; logic [1:0] STATUS_SXL, STATUS_UXL, STATUS_XS, STATUS_FS, STATUS_FS_INT, STATUS_MPP_NEXT;
logic STATUS_MPIE, STATUS_SPIE, STATUS_UPIE, STATUS_UIE; logic STATUS_MPIE, STATUS_SPIE, STATUS_UPIE, STATUS_UIE;
var [`XLEN-1:0] initMSTATUS;
initial begin
`ifdef CHECKPOINT
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MSTATUS.txt"}, initMSTATUS);
`else
initMSTATUS = `XLEN'b0;
`endif
end
// STATUS REGISTER FIELD // STATUS REGISTER FIELD
// See Privileged Spec Section 3.1.6 // See Privileged Spec Section 3.1.6
// Lower privilege status registers are a subset of the full status register // Lower privilege status registers are a subset of the full status register
@ -117,33 +108,23 @@ module csrsr (
// registers for STATUS bits // registers for STATUS bits
// complex register with reset, write enable, and the ability to update other bits in certain cases // complex register with reset, write enable, and the ability to update other bits in certain cases
// these null things are needed to make the following LHS assignment legal; this is probably a crappy way of doing things
always_ff @(posedge clk, posedge reset) always_ff @(posedge clk, posedge reset)
if (reset) begin if (reset) begin
//STATUS_TSR_INT <= #1 0; STATUS_TSR_INT <= #1 0;
//STATUS_TW_INT <= #1 0; STATUS_TW_INT <= #1 0;
//STATUS_TVM_INT <= #1 0; STATUS_TVM_INT <= #1 0;
//STATUS_MXR_INT <= #1 0; STATUS_MXR_INT <= #1 0;
//STATUS_SUM_INT <= #1 0; STATUS_SUM_INT <= #1 0;
//STATUS_MPRV_INT <= #1 0; // Per Priv 3.3 STATUS_MPRV_INT <= #1 0; // Per Priv 3.3
//STATUS_FS_INT <= #1 0; //2'b01; // busybear: change all these reset values to 0 STATUS_FS_INT <= #1 0; //2'b01; // busybear: change all these reset values to 0
//STATUS_MPP <= #1 0; //`M_MODE; STATUS_MPP <= #1 0; //`M_MODE;
//STATUS_SPP <= #1 0; //1'b1; STATUS_SPP <= #1 0; //1'b1;
//STATUS_MPIE <= #1 0; //1; STATUS_MPIE <= #1 0; //1;
//STATUS_SPIE <= #1 0; //`S_SUPPORTED; STATUS_SPIE <= #1 0; //`S_SUPPORTED;
//STATUS_UPIE <= #1 0; // `U_SUPPORTED; STATUS_UPIE <= #1 0; // `U_SUPPORTED;
//STATUS_MIE <= #1 0; // Per Priv 3.3 STATUS_MIE <= #1 0; // Per Priv 3.3
//STATUS_SIE <= #1 0; //`S_SUPPORTED; STATUS_SIE <= #1 0; //`S_SUPPORTED;
//STATUS_UIE <= #1 0; //`U_SUPPORTED; STATUS_UIE <= #1 0; //`U_SUPPORTED;
//
// *** this assumes XLEN == 64.
// I don't like using generates to respond to XLEN.
// I'd rather have an XLEN64 so that we could use `ifdefs -- Ben 9/21
{STATUS_TSR_INT,STATUS_TW_INT,STATUS_TVM_INT,STATUS_MXR_INT,STATUS_SUM_INT,STATUS_MPRV_INT} <= #1 initMSTATUS[22:17];
{STATUS_FS_INT,STATUS_MPP} <= #1 initMSTATUS[14:11];
{STATUS_SPP,STATUS_MPIE} <= #1 initMSTATUS[8:7];
{STATUS_SPIE,STATUS_UPIE,STATUS_MIE} <= #1 initMSTATUS[5:3];
{STATUS_SIE,STATUS_UIE} <= #1 initMSTATUS[1:0];
end else if (~StallW) begin end else if (~StallW) begin
if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #12'b11; // mark Float State dirty *** this should happen in M stage, be part of if/else; if (FRegWriteM | WriteFRMM | WriteFFLAGSM) STATUS_FS_INT <= #12'b11; // mark Float State dirty *** this should happen in M stage, be part of if/else;

View File

@ -13,5 +13,5 @@ module instrTrackerTB(
instrNameDecTB ddec(InstrD, InstrDName); instrNameDecTB ddec(InstrD, InstrDName);
instrNameDecTB edec(InstrE, InstrEName); instrNameDecTB edec(InstrE, InstrEName);
instrNameDecTB mdec(InstrM, InstrMName); instrNameDecTB mdec(InstrM, InstrMName);
instrNameDecTB wdec(InstrW, InstrWName); instrNameDecTB wdec(InstrW, InstrWName); // *** delete this because InstrW is deleted from IFU
endmodule endmodule

View File

@ -430,7 +430,7 @@ string tests32f[] = '{
// tests = {tests64p,tests64i, tests64periph}; // tests = {tests64p,tests64i, tests64periph};
if (`C_SUPPORTED) tests = {tests, tests64ic}; if (`C_SUPPORTED) tests = {tests, tests64ic};
// else tests = {tests, tests64iNOc}; // else tests = {tests, tests64iNOc};
if (`M_SUPPORTED) tests = {tests, tests64m}; if (`M_SUPPORTED) tests = {tests64m, tests};
/* if (`F_SUPPORTED) tests = {tests64f, tests}; /* if (`F_SUPPORTED) tests = {tests64f, tests};
if (`D_SUPPORTED) tests = {tests64d, tests}; if (`D_SUPPORTED) tests = {tests64d, tests};
if (`MEM_VIRTMEM) tests = {tests64mmu, tests}; if (`MEM_VIRTMEM) tests = {tests64mmu, tests};
@ -449,7 +449,7 @@ string tests32f[] = '{
tests = {tests32priv, tests32i}; tests = {tests32priv, tests32i};
//tests = {tests32i, tests32priv}; //tests = {tests32i, tests32priv};
if (`C_SUPPORTED) tests = {tests, tests32ic}; if (`C_SUPPORTED) tests = {tests, tests32ic};
if (`M_SUPPORTED) tests = {tests, tests32m}; if (`M_SUPPORTED) tests = {tests32m, tests};
//if (`C_SUPPORTED) tests = {tests32ic, tests}; //if (`C_SUPPORTED) tests = {tests32ic, tests};
//if (`M_SUPPORTED) tests = {tests32m, tests}; //if (`M_SUPPORTED) tests = {tests32m, tests};
/* tests = {tests32i, tests32p};//,tests32periph}; *** broken at the moment /* tests = {tests32i, tests32p};//,tests32periph}; *** broken at the moment

View File

@ -318,14 +318,14 @@ string tests32f[] = '{
}; };
string tests32m[] = '{ string tests32m[] = '{
"rv32m/I-DIVU-01", "2000",
"rv32m/I-REMU-01", "2000",
"rv32m/I-DIV-01", "2000",
"rv32m/I-REM-01", "2000",
"rv32m/I-MUL-01", "2000", "rv32m/I-MUL-01", "2000",
"rv32m/I-MULH-01", "2000", "rv32m/I-MULH-01", "2000",
"rv32m/I-MULHSU-01", "2000", "rv32m/I-MULHSU-01", "2000",
"rv32m/I-MULHU-01", "2000", "rv32m/I-MULHU-01", "2000"
"rv32m/I-DIV-01", "2000",
"rv32m/I-DIVU-01", "2000",
"rv32m/I-REM-01", "2000",
"rv32m/I-REMU-01", "2000"
}; };
string tests32ic[] = '{ string tests32ic[] = '{
@ -551,12 +551,12 @@ string tests32f[] = '{
tests = tests32p; tests = tests32p;
else begin else begin
tests = {tests32i, tests32p};//,tests32periph}; *** broken at the moment tests = {tests32i, tests32p};//,tests32periph}; *** broken at the moment
if (`C_SUPPORTED % 2 == 1) tests = {tests, tests32ic}; if (`C_SUPPORTED) tests = {tests, tests32ic};
else tests = {tests, tests32iNOc}; else tests = {tests, tests32iNOc};
if (`M_SUPPORTED % 2 == 1) tests = {tests, tests32m};
if (`F_SUPPORTED) tests = {tests32f, tests}; if (`F_SUPPORTED) tests = {tests32f, tests};
if (`MEM_VIRTMEM) tests = {tests32mmu, tests}; if (`MEM_VIRTMEM) tests = {tests32mmu, tests};
if (`A_SUPPORTED) tests = {tests32a, tests}; if (`A_SUPPORTED) tests = {tests32a, tests};
if (`M_SUPPORTED) tests = {tests32m, tests};
end end
end end
end end
@ -607,9 +607,9 @@ string tests32f[] = '{
end end
// read test vectors into memory // read test vectors into memory
memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"}; memfilename = {"../../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
romfilename = {"../../imperas-riscv-tests/imperas-boottim.txt"}; // romfilename = {"../../imperas-riscv-tests/imperas-boottim.txt"};
$readmemh(memfilename, dut.uncore.dtim.RAM); $readmemh(memfilename, dut.uncore.dtim.RAM);
$readmemh(romfilename, dut.uncore.bootdtim.bootdtim.RAM); // $readmemh(romfilename, dut.uncore.bootdtim.bootdtim.RAM);
ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"}; ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"};
ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"}; ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"};
$display("Read memfile %s", memfilename); $display("Read memfile %s", memfilename);

View File

@ -27,9 +27,6 @@
`include "wally-config.vh" `include "wally-config.vh"
//`define CHECKPOINT
`define LINUX_CHECKPOINT "../linux-testgen/linux-testvectors/checkpoint1K"
`define DEBUG_TRACE 0 `define DEBUG_TRACE 0
// Debug Levels // Debug Levels
// 0: don't check against QEMU // 0: don't check against QEMU
@ -411,11 +408,7 @@ module testbench();
// initial loading of memories // initial loading of memories
initial begin initial begin
$readmemh({`LINUX_TEST_VECTORS,"bootmem.txt"}, dut.uncore.bootdtim.bootdtim.RAM, 'h1000 >> 3); $readmemh({`LINUX_TEST_VECTORS,"bootmem.txt"}, dut.uncore.bootdtim.bootdtim.RAM, 'h1000 >> 3);
`ifdef CHECKPOINT $readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
$readmemh({`LINUX_CHECKPOINT,"ram.txt"}, dut.uncore.dtim.RAM);
`else
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
`endif
$readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.memory); $readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.memory);
$readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.bpred.TargetPredictor.memory.memory); $readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.bpred.TargetPredictor.memory.memory);
ProgramAddrMapFile = {`LINUX_TEST_VECTORS,"vmlinux.objdump.addr"}; ProgramAddrMapFile = {`LINUX_TEST_VECTORS,"vmlinux.objdump.addr"};