mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
commit
07ff0940a3
@ -43,7 +43,7 @@ view wave
|
||||
do ./wave-dos/peripheral-waves.do
|
||||
|
||||
-- Run the Simulation
|
||||
#run 5000
|
||||
#run 3600
|
||||
run -all
|
||||
#quit
|
||||
noview ../testbench/testbench-imperas.sv
|
||||
|
@ -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/ALUResultE
|
||||
#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 -hex /testbench/dut/hart/ifu/PCM
|
||||
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 -divider
|
||||
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 /testbench/InstrWName
|
||||
#add wave /testbench/InstrWName
|
||||
add wave -hex /testbench/dut/hart/ReadDataW
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/ResultW
|
||||
add wave -hex /testbench/dut/hart/ieu/dp/RegWriteW
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
`include "wally-config.vh"
|
||||
/* 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
|
||||
module flop #(parameter WIDTH = 8) (
|
||||
@ -42,11 +40,10 @@ endmodule
|
||||
module flopr #(parameter WIDTH = 8) (
|
||||
input logic clk, reset,
|
||||
input logic [WIDTH-1:0] d,
|
||||
output logic [WIDTH-1:0] q,
|
||||
input var [WIDTH-1:0] RESET_VAL=0);
|
||||
output logic [WIDTH-1:0] q);
|
||||
|
||||
always_ff @(posedge clk, posedge reset)
|
||||
if (reset) q <= #1 RESET_VAL;
|
||||
if (reset) q <= #1 0;
|
||||
else q <= #1 d;
|
||||
endmodule
|
||||
|
||||
@ -64,11 +61,10 @@ endmodule
|
||||
module flopenrc #(parameter WIDTH = 8) (
|
||||
input logic clk, reset, clear, en,
|
||||
input logic [WIDTH-1:0] d,
|
||||
output logic [WIDTH-1:0] q,
|
||||
input var [WIDTH-1:0] RESET_VAL=0);
|
||||
output logic [WIDTH-1:0] q);
|
||||
|
||||
always_ff @(posedge clk, posedge reset)
|
||||
if (reset) q <= #1 RESET_VAL;
|
||||
if (reset) q <= #1 0;
|
||||
else if (en)
|
||||
if (clear) q <= #1 0;
|
||||
else q <= #1 d;
|
||||
@ -78,11 +74,10 @@ endmodule
|
||||
module flopenr #(parameter WIDTH = 8) (
|
||||
input logic clk, reset, en,
|
||||
input logic [WIDTH-1:0] d,
|
||||
output logic [WIDTH-1:0] q,
|
||||
input var [WIDTH-1:0] RESET_VAL=0);
|
||||
output logic [WIDTH-1:0] q);
|
||||
|
||||
always_ff @(posedge clk, posedge reset)
|
||||
if (reset) q <= #1 RESET_VAL;
|
||||
if (reset) q <= #1 0;
|
||||
else if (en) q <= #1 d;
|
||||
endmodule
|
||||
|
||||
@ -104,11 +99,10 @@ module floprc #(parameter WIDTH = 8) (
|
||||
input logic reset,
|
||||
input logic clear,
|
||||
input logic [WIDTH-1:0] d,
|
||||
output logic [WIDTH-1:0] q,
|
||||
input var RESET_VAL=0);
|
||||
output logic [WIDTH-1:0] q);
|
||||
|
||||
always_ff @(posedge clk, posedge reset)
|
||||
if (reset) q <= #1 RESET_VAL;
|
||||
if (reset) q <= #1 0;
|
||||
else
|
||||
if (clear) q <= #1 0;
|
||||
else q <= #1 d;
|
||||
|
34
wally-pipelined/src/generic/neg.sv
Normal file
34
wally-pipelined/src/generic/neg.sv
Normal 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
|
||||
|
@ -33,6 +33,7 @@ module forward(
|
||||
input logic DivDoneE, DivBusyE,
|
||||
input logic FWriteIntE, FWriteIntM, FWriteIntW,
|
||||
input logic SCE,
|
||||
input logic StallD,
|
||||
// Forwarding controls
|
||||
output logic [1:0] ForwardAE, ForwardBE,
|
||||
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
|
||||
assign FPUStallD = FWriteIntE & ((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));
|
||||
|
||||
endmodule
|
||||
|
@ -44,13 +44,7 @@ module regfile (
|
||||
// reset is intended for simulation only, not synthesis
|
||||
|
||||
always_ff @(negedge clk or posedge reset)
|
||||
if (reset)
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-regfile.txt"}, rf);
|
||||
`else
|
||||
for(i=1; i<32; i++) rf[i] <= 0;
|
||||
`endif
|
||||
|
||||
if (reset) for(i=1; i<32; i++) rf[i] <= 0;
|
||||
else if (we3) rf[a3] <= wd3;
|
||||
|
||||
assign #2 rd1 = (a1 != 0) ? rf[a1] : 0;
|
||||
|
@ -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
|
||||
|
||||
|
112
wally-pipelined/src/muldiv/intdivrestoring.sv
Normal file
112
wally-pipelined/src/muldiv/intdivrestoring.sv
Normal 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
|
40
wally-pipelined/src/muldiv/intdivrestoringstep.sv
Normal file
40
wally-pipelined/src/muldiv/intdivrestoringstep.sv
Normal 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
|
||||
|
@ -31,7 +31,7 @@ module muldiv (
|
||||
input logic [31:0] InstrD,
|
||||
// Execute Stage interface
|
||||
input logic [`XLEN-1:0] SrcAE, SrcBE,
|
||||
input logic [2:0] Funct3E,
|
||||
input logic [2:0] Funct3E, Funct3M,
|
||||
input logic MulDivE, W64E,
|
||||
// Writeback stage
|
||||
output logic [`XLEN-1:0] MulDivResultW,
|
||||
@ -45,98 +45,67 @@ module muldiv (
|
||||
generate
|
||||
if (`M_SUPPORTED) begin
|
||||
logic [`XLEN-1:0] MulDivResultE, MulDivResultM;
|
||||
logic [`XLEN-1:0] PrelimResultE;
|
||||
logic [`XLEN-1:0] QuotE, RemE;
|
||||
logic [`XLEN*2-1:0] ProdE;
|
||||
logic [`XLEN-1:0] PrelimResultM;
|
||||
logic [`XLEN-1:0] QuotM, RemM;
|
||||
logic [`XLEN*2-1:0] ProdE, ProdM;
|
||||
|
||||
logic enable_q;
|
||||
logic [2:0] Funct3E_Q;
|
||||
//logic [2:0] Funct3E_Q;
|
||||
logic div0error; // ***unused
|
||||
logic [`XLEN-1:0] N, D;
|
||||
logic [`XLEN-1:0] Num0, Den0;
|
||||
logic [`XLEN-1:0] XE, DE;
|
||||
//logic [`XLEN-1:0] Num0, Den0;
|
||||
|
||||
logic gclk;
|
||||
logic DivStartE;
|
||||
logic startDivideE;
|
||||
logic signedDivide;
|
||||
// logic gclk;
|
||||
logic StartDivideE, BusyE;
|
||||
logic SignedDivideE;
|
||||
logic W64M;
|
||||
|
||||
|
||||
// Multiplier
|
||||
mul mul(.*);
|
||||
flopenrc #(`XLEN*2) ProdMReg(clk, reset, FlushM, ~StallM, ProdE, ProdM);
|
||||
|
||||
// Divide
|
||||
|
||||
// *** replace this clock gater
|
||||
always @(negedge clk) begin
|
||||
enable_q <= ~StallM;
|
||||
end
|
||||
assign gclk = enable_q & clk;
|
||||
|
||||
// Handle sign extension for W-type instructions
|
||||
if (`XLEN == 64) begin // RV64 has W-type instructions
|
||||
assign Num0 = W64E ? {{32{SrcAE[31]&signedDivide}}, SrcAE[31:0]} : SrcAE;
|
||||
assign Den0 = W64E ? {{32{SrcBE[31]&signedDivide}}, SrcBE[31:0]} : SrcBE;
|
||||
assign XE = W64E ? {{32{SrcAE[31]&SignedDivideE}}, SrcAE[31:0]} : SrcAE;
|
||||
assign DE = W64E ? {{32{SrcBE[31]&SignedDivideE}}, SrcBE[31:0]} : SrcBE;
|
||||
end else begin // RV32 has no W-type instructions
|
||||
assign Num0 = SrcAE;
|
||||
assign Den0 = SrcBE;
|
||||
assign XE = SrcAE;
|
||||
assign DE = SrcBE;
|
||||
end
|
||||
|
||||
// capture the Numerator/Denominator
|
||||
flopenrc #(`XLEN) reg_num (.d(Num0), .q(N),
|
||||
.en(startDivideE), .clear(DivDoneE),
|
||||
.reset(reset), .clk(~gclk));
|
||||
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]);
|
||||
intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, startDivideE, signedDivide);
|
||||
//intdiv_restoring div(.clk, .reset, .signedDivide, .start(startDivideE), .X(N), .D(D), .busy(DivBusyE), .done(DivDoneE), .Q(QuotE), .REM(RemE));
|
||||
assign SignedDivideE = ~Funct3E[0]; // simplified from (Funct3E[2]&~Funct3E[1]&~Funct3E[0]) | (Funct3E[2]&Funct3E[1]&~Funct3E[0]);
|
||||
//intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, StartDivideE, SignedDivideE);
|
||||
intdivrestoring div(.clk, .reset, .StallM, .FlushM,
|
||||
.SignedDivideE, .StartDivideE, .XE, .DE, .BusyE, .done(DivDoneE), .QuotM, .RemM);
|
||||
|
||||
// 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));
|
||||
|
||||
// Start a divide when a new division instruction is received and the divider isn't already busy or finishing
|
||||
assign StartDivideE = MulDivE & Funct3E[2] & ~BusyE & ~DivDoneE; // *** mabye DivDone should be M stage
|
||||
assign DivBusyE = StartDivideE | BusyE;
|
||||
|
||||
// Select result
|
||||
always_comb
|
||||
case (Funct3E)
|
||||
3'b000: PrelimResultE = ProdE[`XLEN-1:0];
|
||||
3'b001: PrelimResultE = ProdE[`XLEN*2-1:`XLEN];
|
||||
3'b010: PrelimResultE = ProdE[`XLEN*2-1:`XLEN];
|
||||
3'b011: PrelimResultE = ProdE[`XLEN*2-1:`XLEN];
|
||||
3'b100: PrelimResultE = QuotE;
|
||||
3'b101: PrelimResultE = QuotE;
|
||||
3'b110: PrelimResultE = RemE;
|
||||
3'b111: PrelimResultE = RemE;
|
||||
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
|
||||
case (Funct3M)
|
||||
3'b000: PrelimResultM = ProdM[`XLEN-1:0];
|
||||
3'b001: PrelimResultM = ProdM[`XLEN*2-1:`XLEN];
|
||||
3'b010: PrelimResultM = ProdM[`XLEN*2-1:`XLEN];
|
||||
3'b011: PrelimResultM = ProdM[`XLEN*2-1:`XLEN];
|
||||
3'b100: PrelimResultM = QuotM;
|
||||
3'b101: PrelimResultM = QuotM;
|
||||
3'b110: PrelimResultM = RemM;
|
||||
3'b111: PrelimResultM = RemM;
|
||||
endcase
|
||||
|
||||
// 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
|
||||
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
|
||||
assign MulDivResultE = PrelimResultE;
|
||||
assign MulDivResultM = PrelimResultM;
|
||||
end
|
||||
|
||||
flopenrc #(`XLEN) MulDivResultMReg(clk, reset, FlushM, ~StallM, MulDivResultE, MulDivResultM);
|
||||
flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW);
|
||||
|
||||
end else begin // no M instructions supported
|
||||
|
@ -70,24 +70,24 @@ module csrc #(parameter
|
||||
// ... more counters
|
||||
//HPMCOUNTER31H = 12'hC9F
|
||||
) (
|
||||
input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic FlushD, FlushE, FlushM, FlushW,
|
||||
input logic InstrValidM, LoadStallD, CSRMWriteM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic DCacheMiss,
|
||||
input logic DCacheAccess,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic InstrValidM, LoadStallD, CSRMWriteM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic DCacheMiss,
|
||||
input logic DCacheAccess,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
input logic [`XLEN-1:0] CSRWriteValM,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic [63:0] MTIME_CLINT, MTIMECMP_CLINT,
|
||||
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
|
||||
input logic [63:0] MTIME_CLINT, MTIMECMP_CLINT,
|
||||
output logic [`XLEN-1:0] CSRCReadValM,
|
||||
output logic IllegalCSRCAccessM
|
||||
output logic IllegalCSRCAccessM
|
||||
);
|
||||
|
||||
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] CYCLEPlusM, INSTRETPlusM;
|
||||
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] NextHPMCOUNTER3M, NextHPMCOUNTER4M;
|
||||
logic WriteCYCLEM, WriteINSTRETM;
|
||||
logic WriteHPMCOUNTER3M, WriteHPMCOUNTER4M;
|
||||
logic [4:0] CounterNumM;
|
||||
logic [`COUNTERS-1:3][`XLEN-1:0] HPMCOUNTER_REGW, HPMCOUNTERH_REGW;
|
||||
var [`COUNTERS-1:3][`XLEN-1:0] initHPMCOUNTER;
|
||||
logic InstrValidNotFlushedM;
|
||||
|
||||
initial
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-HPMCOUNTER.txt"}, initHPMCOUNTER);
|
||||
`else
|
||||
initHPMCOUNTER = {(`COUNTERS-3){`XLEN'b0}};
|
||||
`endif
|
||||
logic InstrValidNotFlushedM;
|
||||
|
||||
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
|
||||
|
||||
@ -138,116 +130,121 @@ module csrc #(parameter
|
||||
//assign NextHPMCOUNTER3M = WriteHPMCOUNTER3M ? CSRWriteValM : HPMCOUNTER3PlusM[`XLEN-1:0];
|
||||
//assign NextHPMCOUNTER4M = WriteHPMCOUNTER4M ? CSRWriteValM : HPMCOUNTER4PlusM[`XLEN-1:0];
|
||||
|
||||
// parameterized number of additional counters
|
||||
if (`COUNTERS > 3) begin
|
||||
// parameterized number of additional counters
|
||||
if (`COUNTERS > 3) begin
|
||||
logic [`COUNTERS-1:3] WriteHPMCOUNTERM;
|
||||
logic [`COUNTERS-1:0] CounterEvent;
|
||||
logic [63:0] /*HPMCOUNTER_REGW[`COUNTERS-1:3], */ HPMCOUNTERPlusM[`COUNTERS-1:3];
|
||||
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:3];
|
||||
genvar i;
|
||||
|
||||
// could replace special counters 0-2 with this loop for all counters
|
||||
assign CounterEvent[0] = 1'b1;
|
||||
assign CounterEvent[1] = 1'b0;
|
||||
if(`QEMU) assign CounterEvent[`COUNTERS-1:2] = 0;
|
||||
else begin
|
||||
logic LoadStallE, LoadStallM;
|
||||
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;
|
||||
assign CounterEvent[3] = LoadStallM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM;
|
||||
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM;
|
||||
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM;
|
||||
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
|
||||
assign WriteHPMCOUNTERM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERBASE + i);
|
||||
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(`QEMU) begin
|
||||
assign CounterEvent[`COUNTERS-1:2] = 0;
|
||||
end else begin
|
||||
|
||||
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
|
||||
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
|
||||
logic LoadStallE, LoadStallM;
|
||||
|
||||
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;
|
||||
assign CounterEvent[3] = LoadStallM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM;
|
||||
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
|
||||
assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM;
|
||||
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM;
|
||||
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
|
||||
assign WriteHPMCOUNTERM[i] = CSRMWriteM && (CSRAdrM == MHPMCOUNTERBASE + i);
|
||||
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 0;
|
||||
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
|
||||
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
|
||||
|
||||
// Write / update counters
|
||||
// Only the Machine mode versions of the counter CSRs are writable
|
||||
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***
|
||||
// flopenr #(64) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW);
|
||||
flopr #(64) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW);
|
||||
flopr #(64) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW);
|
||||
//flopr #(64) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW);
|
||||
//flopr #(64) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW);
|
||||
end else begin // 32-bit low and high counters
|
||||
logic WriteTIMEHM, WriteTIMECMPHM, WriteCYCLEHM, WriteINSTRETHM;
|
||||
//logic WriteHPMCOUNTER3HM, WriteHPMCOUNTER4HM;
|
||||
logic [`XLEN-1:0] NextCYCLEHM, NextTIMEHM, NextINSTRETHM;
|
||||
//logic [`XLEN-1:0] NextHPMCOUNTER3HM, NextHPMCOUNTER4HM;
|
||||
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***
|
||||
// flopenr #(64) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW);
|
||||
flopr #(64) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW);
|
||||
flopr #(64) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW);
|
||||
//flopr #(64) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW);
|
||||
//flopr #(64) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW);
|
||||
end else begin // 32-bit low and high counters
|
||||
logic WriteTIMEHM, WriteTIMECMPHM, WriteCYCLEHM, WriteINSTRETHM;
|
||||
//logic WriteHPMCOUNTER3HM, WriteHPMCOUNTER4HM;
|
||||
logic [`XLEN-1:0] NextCYCLEHM, NextTIMEHM, NextINSTRETHM;
|
||||
//logic [`XLEN-1:0] NextHPMCOUNTER3HM, NextHPMCOUNTER4HM;
|
||||
|
||||
// Write Enables
|
||||
// assign WriteTIMEHM = CSRMWriteM && (CSRAdrM == MTIMEH);
|
||||
// assign WriteTIMECMPHM = CSRMWriteM && (CSRAdrM == MTIMECMPH);
|
||||
assign WriteCYCLEHM = CSRMWriteM && (CSRAdrM == MCYCLEH);
|
||||
assign WriteINSTRETHM = CSRMWriteM && (CSRAdrM == MINSTRETH);
|
||||
//assign WriteHPMCOUNTER3HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER3H);
|
||||
//assign WriteHPMCOUNTER4HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER4H);
|
||||
assign NextCYCLEHM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM[63:32];
|
||||
// assign NextTIMEHM = WriteTIMEHM ? CSRWriteValM : TIMEPlusM[63:32];
|
||||
assign NextINSTRETHM = WriteINSTRETHM ? CSRWriteValM : INSTRETPlusM[63:32];
|
||||
//assign NextHPMCOUNTER3HM = WriteHPMCOUNTER3HM ? CSRWriteValM : HPMCOUNTER3PlusM[63:32];
|
||||
//assign NextHPMCOUNTER4HM = WriteHPMCOUNTER4HM ? CSRWriteValM : HPMCOUNTER4PlusM[63:32];
|
||||
// Write Enables
|
||||
// assign WriteTIMEHM = CSRMWriteM && (CSRAdrM == MTIMEH);
|
||||
// assign WriteTIMECMPHM = CSRMWriteM && (CSRAdrM == MTIMECMPH);
|
||||
assign WriteCYCLEHM = CSRMWriteM && (CSRAdrM == MCYCLEH);
|
||||
assign WriteINSTRETHM = CSRMWriteM && (CSRAdrM == MINSTRETH);
|
||||
//assign WriteHPMCOUNTER3HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER3H);
|
||||
//assign WriteHPMCOUNTER4HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER4H);
|
||||
assign NextCYCLEHM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM[63:32];
|
||||
// assign NextTIMEHM = WriteTIMEHM ? CSRWriteValM : TIMEPlusM[63:32];
|
||||
assign NextINSTRETHM = WriteINSTRETHM ? CSRWriteValM : INSTRETPlusM[63:32];
|
||||
//assign NextHPMCOUNTER3HM = WriteHPMCOUNTER3HM ? CSRWriteValM : HPMCOUNTER3PlusM[63:32];
|
||||
//assign NextHPMCOUNTER4HM = WriteHPMCOUNTER4HM ? CSRWriteValM : HPMCOUNTER4PlusM[63:32];
|
||||
|
||||
// Counter CSRs
|
||||
// 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]);
|
||||
flopr #(32) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_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) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW[31:0]);
|
||||
// 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]);
|
||||
flopr #(32) CYCLEHreg(clk, reset, NextCYCLEHM, CYCLE_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) HPMCOUNTER4Hreg(clk, reset, NextHPMCOUNTER4HM, HPMCOUNTER4_REGW[63:32]);
|
||||
end
|
||||
// Counter CSRs
|
||||
// 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]);
|
||||
flopr #(32) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_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) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW[31:0]);
|
||||
// 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]);
|
||||
flopr #(32) CYCLEHreg(clk, reset, NextCYCLEHM, CYCLE_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) HPMCOUNTER4Hreg(clk, reset, NextHPMCOUNTER4HM, HPMCOUNTER4_REGW[63:32]);
|
||||
end
|
||||
|
||||
// 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
|
||||
// synchronize write enable to TIME
|
||||
// four phase handshake to synchronize reads from TIME
|
||||
// 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
|
||||
// synchronize write enable to TIME
|
||||
// four phase handshake to synchronize reads from TIME
|
||||
|
||||
// interrupt on timer compare
|
||||
// ability to disable optional CSRs
|
||||
// interrupt on timer compare
|
||||
// ability to disable optional CSRs
|
||||
|
||||
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
|
||||
assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
|
||||
if (`XLEN==64) // 64-bit counter reads
|
||||
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;
|
||||
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];
|
||||
@ -312,7 +309,7 @@ module csrc #(parameter
|
||||
IllegalCSRCAccessM = 1; // no privileges for this csr
|
||||
CSRCReadValM = 0;
|
||||
end
|
||||
end else begin // not `ZICOUNTERS_SUPPORTED
|
||||
end else begin
|
||||
assign CSRCReadValM = 0;
|
||||
assign IllegalCSRCAccessM = 1;
|
||||
end
|
||||
@ -359,20 +356,20 @@ module csrc #(parameter
|
||||
MPHMEVENTBASE = 12'h320,
|
||||
HPMCOUNTERBASE = 12'hC00,
|
||||
HPMCOUNTERHBASE = 12'hC80,
|
||||
)(input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic InstrValidM, LoadStallD, CSRMWriteM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
)(input logic clk, reset,
|
||||
input logic StallD, StallE, StallM, StallW,
|
||||
input logic InstrValidM, LoadStallD, CSRMWriteM,
|
||||
input logic BPPredDirWrongM,
|
||||
input logic BTBPredPCWrongM,
|
||||
input logic RASPredPCWrongM,
|
||||
input logic BPPredClassNonCFIWrongM,
|
||||
input logic [4:0] InstrClassM,
|
||||
input logic [11:0] CSRAdrM,
|
||||
input logic [1:0] PrivilegeModeW,
|
||||
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 IllegalCSRCAccessM);
|
||||
output logic IllegalCSRCAccessM);
|
||||
|
||||
// counters
|
||||
|
||||
|
@ -79,24 +79,14 @@ module csri #(parameter
|
||||
assign SIP_WRITE_MASK = 12'h000;
|
||||
end
|
||||
always @(posedge clk, posedge reset) begin // *** I strongly feel that IntInM should go directly to IP_REGW -- Ben 9/7/21
|
||||
if (reset)
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MIP.txt"}, IP_REGW_writeable);
|
||||
`else
|
||||
IP_REGW_writeable <= 10'b0;
|
||||
`endif
|
||||
if (reset) IP_REGW_writeable <= 10'b0;
|
||||
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 (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
|
||||
end
|
||||
always @(posedge clk, posedge reset) begin
|
||||
if (reset)
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"checkpoint-MIE.txt"}, IE_REGW);
|
||||
`else
|
||||
IE_REGW <= 12'b0;
|
||||
`endif
|
||||
if (reset) IE_REGW <= 12'b0;
|
||||
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 (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field
|
||||
|
@ -85,45 +85,15 @@ module csrm #(parameter
|
||||
logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW;
|
||||
logic [`XLEN-1:0] MSCRATCH_REGW, MCAUSE_REGW, MTVAL_REGW;
|
||||
|
||||
var [`XLEN-1:0] initMSCRATCH, initMCAUSE, initMEPC, initMTVEC, initMEDELEG, initMIDELEG;
|
||||
var [31:0] initMCOUNTEREN, initMCOUNTINHIBIT;
|
||||
var [`PMP_ENTRIES-1:0][7:0] initPMPCFG_ARRAY;
|
||||
var [`PMP_ENTRIES-1:0][`XLEN-1:0] initPMPADDR_ARRAY;
|
||||
|
||||
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
|
||||
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
|
||||
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
|
||||
logic [`PMP_ENTRIES-1:0] WritePMPCFGM;
|
||||
logic [`PMP_ENTRIES-1:0] WritePMPADDRM ;
|
||||
logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked;
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
// 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
|
||||
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) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, initMIDELEG, MIDELEG_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*/, `XLEN'b0, MIDELEG_REGW);
|
||||
end else begin
|
||||
assign MEDELEG_REGW = 0;
|
||||
assign MIDELEG_REGW = 0;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW, initMSCRATCH);
|
||||
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW, initMEPC);
|
||||
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW, initMCAUSE);
|
||||
// flopenl #(`XLEN) MIPreg(clk, reset, WriteMIPM, CSRWriteValM, zero, MIP_REGW);
|
||||
// flopenl #(`XLEN) MIEreg(clk, reset, WriteMIEM, CSRWriteValM, zero, MIE_REGW);
|
||||
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;
|
||||
else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
|
||||
generate
|
||||
if (`BUSYBEAR == 1)
|
||||
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, MCOUNTEREN_REGW);
|
||||
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
|
||||
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, MCOUNTEREN_REGW);
|
||||
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
|
||||
|
||||
@ -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 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
|
||||
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
|
||||
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i];
|
||||
// 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]);
|
||||
end
|
||||
end
|
||||
|
@ -74,30 +74,6 @@ module csrs #(parameter
|
||||
logic WriteSSCRATCHM, WriteSEPCM;
|
||||
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
|
||||
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 WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC) && ~StallW;
|
||||
@ -109,28 +85,28 @@ module csrs #(parameter
|
||||
assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN) && ~StallW;
|
||||
|
||||
// CSRs
|
||||
flopenl #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, initSTVEC, STVEC_REGW); //busybear: change reset to 0
|
||||
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW, initSSCRATCH);
|
||||
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW, initSEPC);
|
||||
flopenl #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, initSCAUSE, SCAUSE_REGW);
|
||||
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);
|
||||
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
|
||||
flopenl #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, `XLEN'b0, SCAUSE_REGW);
|
||||
if(`QEMU) assign STVAL_REGW = `XLEN'b0;
|
||||
else flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
|
||||
if (`MEM_VIRTMEM)
|
||||
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW, initSATP);
|
||||
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
|
||||
else
|
||||
assign SATP_REGW = 0; // hardwire to zero if virtual memory not supported
|
||||
if (`BUSYBEAR == 1)
|
||||
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, 32'b0, SCOUNTEREN_REGW);
|
||||
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
|
||||
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], 32'hFFFFFFFF, SCOUNTEREN_REGW);
|
||||
if (`N_SUPPORTED) begin
|
||||
logic WriteSEDELEGM, WriteSIDELEGM;
|
||||
assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG);
|
||||
assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG);
|
||||
flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK /* 12'h1FF */, initSEDELEG, SEDELEG_REGW);
|
||||
flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, initSIDELEG, SIDELEG_REGW);
|
||||
flopenl #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK /* 12'h1FF */, `XLEN'b0, SEDELEG_REGW);
|
||||
flopenl #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, `XLEN'b0, SIDELEG_REGW);
|
||||
end else begin
|
||||
assign SEDELEG_REGW = 0;
|
||||
assign SIDELEG_REGW = 0;
|
||||
|
@ -46,15 +46,6 @@ module csrsr (
|
||||
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;
|
||||
|
||||
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
|
||||
// See Privileged Spec Section 3.1.6
|
||||
// Lower privilege status registers are a subset of the full status register
|
||||
@ -117,33 +108,23 @@ module csrsr (
|
||||
|
||||
// registers for STATUS bits
|
||||
// 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)
|
||||
if (reset) begin
|
||||
//STATUS_TSR_INT <= #1 0;
|
||||
//STATUS_TW_INT <= #1 0;
|
||||
//STATUS_TVM_INT <= #1 0;
|
||||
//STATUS_MXR_INT <= #1 0;
|
||||
//STATUS_SUM_INT <= #1 0;
|
||||
//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_MPP <= #1 0; //`M_MODE;
|
||||
//STATUS_SPP <= #1 0; //1'b1;
|
||||
//STATUS_MPIE <= #1 0; //1;
|
||||
//STATUS_SPIE <= #1 0; //`S_SUPPORTED;
|
||||
//STATUS_UPIE <= #1 0; // `U_SUPPORTED;
|
||||
//STATUS_MIE <= #1 0; // Per Priv 3.3
|
||||
//STATUS_SIE <= #1 0; //`S_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];
|
||||
STATUS_TSR_INT <= #1 0;
|
||||
STATUS_TW_INT <= #1 0;
|
||||
STATUS_TVM_INT <= #1 0;
|
||||
STATUS_MXR_INT <= #1 0;
|
||||
STATUS_SUM_INT <= #1 0;
|
||||
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_MPP <= #1 0; //`M_MODE;
|
||||
STATUS_SPP <= #1 0; //1'b1;
|
||||
STATUS_MPIE <= #1 0; //1;
|
||||
STATUS_SPIE <= #1 0; //`S_SUPPORTED;
|
||||
STATUS_UPIE <= #1 0; // `U_SUPPORTED;
|
||||
STATUS_MIE <= #1 0; // Per Priv 3.3
|
||||
STATUS_SIE <= #1 0; //`S_SUPPORTED;
|
||||
STATUS_UIE <= #1 0; //`U_SUPPORTED;
|
||||
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;
|
||||
|
||||
|
@ -13,5 +13,5 @@ module instrTrackerTB(
|
||||
instrNameDecTB ddec(InstrD, InstrDName);
|
||||
instrNameDecTB edec(InstrE, InstrEName);
|
||||
instrNameDecTB mdec(InstrM, InstrMName);
|
||||
instrNameDecTB wdec(InstrW, InstrWName);
|
||||
instrNameDecTB wdec(InstrW, InstrWName); // *** delete this because InstrW is deleted from IFU
|
||||
endmodule
|
||||
|
@ -430,7 +430,7 @@ string tests32f[] = '{
|
||||
// tests = {tests64p,tests64i, tests64periph};
|
||||
if (`C_SUPPORTED) tests = {tests, tests64ic};
|
||||
// else tests = {tests, tests64iNOc};
|
||||
if (`M_SUPPORTED) tests = {tests, tests64m};
|
||||
if (`M_SUPPORTED) tests = {tests64m, tests};
|
||||
/* if (`F_SUPPORTED) tests = {tests64f, tests};
|
||||
if (`D_SUPPORTED) tests = {tests64d, tests};
|
||||
if (`MEM_VIRTMEM) tests = {tests64mmu, tests};
|
||||
@ -449,7 +449,7 @@ string tests32f[] = '{
|
||||
tests = {tests32priv, tests32i};
|
||||
//tests = {tests32i, tests32priv};
|
||||
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 (`M_SUPPORTED) tests = {tests32m, tests};
|
||||
/* tests = {tests32i, tests32p};//,tests32periph}; *** broken at the moment
|
||||
|
@ -318,14 +318,14 @@ string tests32f[] = '{
|
||||
};
|
||||
|
||||
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-MULH-01", "2000",
|
||||
"rv32m/I-MULHSU-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"
|
||||
"rv32m/I-MULHU-01", "2000"
|
||||
};
|
||||
|
||||
string tests32ic[] = '{
|
||||
@ -551,12 +551,12 @@ string tests32f[] = '{
|
||||
tests = tests32p;
|
||||
else begin
|
||||
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};
|
||||
if (`M_SUPPORTED % 2 == 1) tests = {tests, tests32m};
|
||||
if (`F_SUPPORTED) tests = {tests32f, tests};
|
||||
if (`MEM_VIRTMEM) tests = {tests32mmu, tests};
|
||||
if (`A_SUPPORTED) tests = {tests32a, tests};
|
||||
if (`M_SUPPORTED) tests = {tests32m, tests};
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -607,9 +607,9 @@ string tests32f[] = '{
|
||||
end
|
||||
// read test vectors into memory
|
||||
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(romfilename, dut.uncore.bootdtim.bootdtim.RAM);
|
||||
// $readmemh(romfilename, dut.uncore.bootdtim.bootdtim.RAM);
|
||||
ProgramAddrMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.addr"};
|
||||
ProgramLabelMapFile = {"../../imperas-riscv-tests/work/", tests[test], ".elf.objdump.lab"};
|
||||
$display("Read memfile %s", memfilename);
|
||||
|
@ -27,9 +27,6 @@
|
||||
|
||||
`include "wally-config.vh"
|
||||
|
||||
//`define CHECKPOINT
|
||||
`define LINUX_CHECKPOINT "../linux-testgen/linux-testvectors/checkpoint1K"
|
||||
|
||||
`define DEBUG_TRACE 0
|
||||
// Debug Levels
|
||||
// 0: don't check against QEMU
|
||||
@ -411,11 +408,7 @@ module testbench();
|
||||
// initial loading of memories
|
||||
initial begin
|
||||
$readmemh({`LINUX_TEST_VECTORS,"bootmem.txt"}, dut.uncore.bootdtim.bootdtim.RAM, 'h1000 >> 3);
|
||||
`ifdef CHECKPOINT
|
||||
$readmemh({`LINUX_CHECKPOINT,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||
`else
|
||||
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||
`endif
|
||||
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||
$readmemb(`TWO_BIT_PRELOAD, dut.hart.ifu.bpred.bpred.Predictor.DirPredictor.PHT.memory);
|
||||
$readmemb(`BTB_PRELOAD, dut.hart.ifu.bpred.bpred.TargetPredictor.memory.memory);
|
||||
ProgramAddrMapFile = {`LINUX_TEST_VECTORS,"vmlinux.objdump.addr"};
|
||||
|
Loading…
Reference in New Issue
Block a user