Removed generate statements

This commit is contained in:
David Harris 2022-01-05 14:35:25 +00:00
parent 98be8201b2
commit d66f7c841b
38 changed files with 929 additions and 2662 deletions

View File

@ -3,11 +3,14 @@ make all:
make -C ../../addins/riscv-arch-test make -C ../../addins/riscv-arch-test
make -C ../../addins/riscv-arch-test XLEN=32 make -C ../../addins/riscv-arch-test XLEN=32
exe2memfile.pl ../../addins/riscv-arch-test/work/*/*/*.elf exe2memfile.pl ../../addins/riscv-arch-test/work/*/*/*.elf
# extractFunctionRadix. ***
# Build wally-riscv-arch-test # Build wally-riscv-arch-test
make -C ../../tests/wally-riscv-arch-test/ make -C ../../tests/wally-riscv-arch-test/
make -C ../../tests/wally-riscv-arch-test/ XLEN=32 make -C ../../tests/wally-riscv-arch-test/ XLEN=32
exe2memfile.pl ../../tests/wally-riscv-arch-test/work/*/*/*.elf exe2memfile.pl ../../tests/wally-riscv-arch-test/work/*/*/*.elf
# ***extractFunctionRadix
# *** use elf2hex
# *** add optional imperas tests # *** add optional imperas tests

View File

@ -1,3 +1,3 @@
vsim -c <<! vsim -c <<!
do wally-pipelined-batch.do rv64gc imperas64i do wally-pipelined-batch.do rv32gc wally32priv
! !

View File

@ -174,3 +174,22 @@ module divconv_pipe (q1, qm1, qp1, q0, qm0, qp0, rega_out, regb_out, regc_out, r
flopenr #(60) regk (clk, reset, regs_pipe2, {qp_out0[59:35], (qp_out0[34:6] & {29{~P_pipe}}), 6'h0}, qp0); flopenr #(60) regk (clk, reset, regs_pipe2, {qp_out0[59:35], (qp_out0[34:6] & {29{~P_pipe}}), 6'h0}, qp0);
endmodule // divconv endmodule // divconv
// *** rewrote behaviorally dh 5 Jan 2021 for speed
module csa #(parameter WIDTH=8) (
input logic [WIDTH-1:0] a, b, c,
output logic [WIDTH-1:0] sum, carry);
assign sum = a ^ b ^ c;
assign carry = (a & (b | c)) | (b & c);
/*
logic [WIDTH:0] carry_temp;
genvar i;
generate
for (i=0;i<WIDTH;i=i+1) begin : genbit
fa fa_inst (a[i], b[i], c[i], sum[i], carry_temp[i+1]);
end
endgenerate
assign carry = {carry_temp[WIDTH-1:1], 1'b0};
*/
endmodule // csa

View File

@ -37,22 +37,17 @@ module redundantmul #(parameter WIDTH =8)(
input logic [WIDTH-1:0] a,b, input logic [WIDTH-1:0] a,b,
output logic [2*WIDTH-1:0] out0, out1); output logic [2*WIDTH-1:0] out0, out1);
// if (`DESIGN_COMPILER == 1) begin:mul
logic [2*WIDTH-1+2:0] tmp_out0;
generate logic [2*WIDTH-1+2:0] tmp_out1;
if (`DESIGN_COMPILER == 1) begin:mul
logic [2*WIDTH-1+2:0] tmp_out0;
logic [2*WIDTH-1+2:0] tmp_out1;
DW02_multp #(WIDTH, WIDTH, 2*WIDTH+2) mul(.a, .b, .tc(1'b0), .out0(tmp_out0), .out1(tmp_out1));
assign out0 = tmp_out0[2*WIDTH-1:0];
assign out1 = tmp_out1[2*WIDTH-1:0];
end else begin:mul // force a nonredunant multipler. This will simulate properly and also is appropriate for FPGAs.
assign out0 = a * b;
assign out1 = 0;
end
endgenerate
DW02_multp #(WIDTH, WIDTH, 2*WIDTH+2) mul(.a, .b, .tc(1'b0), .out0(tmp_out0), .out1(tmp_out1));
assign out0 = tmp_out0[2*WIDTH-1:0];
assign out1 = tmp_out1[2*WIDTH-1:0];
end else begin:mul // force a nonredunant multipler. This will simulate properly and also is appropriate for FPGAs.
assign out0 = a * b;
assign out1 = 0;
end
endmodule endmodule

View File

@ -1,195 +0,0 @@
///////////////////////////////////////////
// lzd.sv
//
// Written: James.Stine@okstate.edu 1 February 2021
// Modified:
//
// Purpose: Integer Divide instructions
//
// 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"
/* verilator lint_off DECLFILENAME */
// Original idea came from V. G. Oklobdzija, "An algorithmic and novel
// design of a leading zero detector circuit: comparison with logic
// synthesis," in IEEE Transactions on Very Large Scale Integration
// (VLSI) Systems, vol. 2, no. 1, pp. 124-128, March 1994, doi:
// 10.1109/92.273153.
// Modified to be more hierarchical
module lzd2 (P, V, B);
input logic [1:0] B;
output logic P;
output logic V;
assign V = B[0] | B[1];
assign P = B[0] & ~B[1];
endmodule // lzd2
module lzd_hier #(parameter WIDTH=8)
(input logic [WIDTH-1:0] B,
output logic [$clog2(WIDTH)-1:0] ZP,
output logic ZV);
if (WIDTH == 128)
lzd128 lz127 (ZP, ZV, B);
else if (WIDTH == 64)
lzd64 lz64 (ZP, ZV, B);
else if (WIDTH == 32)
lzd32 lz32 (ZP, ZV, B);
else if (WIDTH == 16)
lzd16 lz16 (ZP, ZV, B);
else if (WIDTH == 8)
lzd8 lz8 (ZP, ZV, B);
else if (WIDTH == 4)
lzd4 lz4 (ZP, ZV, B);
endmodule // lzd_hier
module lzd4 (ZP, ZV, B);
input logic [3:0] B;
logic ZPa;
logic ZPb;
logic ZVa;
logic ZVb;
output logic [1:0] ZP;
output logic ZV;
lzd2 l1(ZPa, ZVa, B[1:0]);
lzd2 l2(ZPb, ZVb, B[3:2]);
assign ZP[0] = ZVb ? ZPb : ZPa;
assign ZP[1] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd4
module lzd8 (ZP, ZV, B);
input logic [7:0] B;
logic [1:0] ZPa;
logic [1:0] ZPb;
logic ZVa;
logic ZVb;
output logic [2:0] ZP;
output logic ZV;
lzd4 l1(ZPa, ZVa, B[3:0]);
lzd4 l2(ZPb, ZVb, B[7:4]);
assign ZP[1:0] = ZVb ? ZPb : ZPa;
assign ZP[2] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd8
module lzd16 (ZP, ZV, B);
input logic [15:0] B;
logic [2:0] ZPa;
logic [2:0] ZPb;
logic ZVa;
logic ZVb;
output logic [3:0] ZP;
output logic ZV;
lzd8 l1(ZPa, ZVa, B[7:0]);
lzd8 l2(ZPb, ZVb, B[15:8]);
assign ZP[2:0] = ZVb ? ZPb : ZPa;
assign ZP[3] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd16
module lzd32 (ZP, ZV, B);
input logic [31:0] B;
logic [3:0] ZPa;
logic [3:0] ZPb;
logic ZVa;
logic ZVb;
output logic [4:0] ZP;
output logic ZV;
lzd16 l1(ZPa, ZVa, B[15:0]);
lzd16 l2(ZPb, ZVb, B[31:16]);
assign ZP[3:0] = ZVb ? ZPb : ZPa;
assign ZP[4] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd32
module lzd64 (ZP, ZV, B);
input logic [63:0] B;
logic [4:0] ZPa;
logic [4:0] ZPb;
logic ZVa;
logic ZVb;
output logic [5:0] ZP;
output logic ZV;
lzd32 l1(ZPa, ZVa, B[31:0]);
lzd32 l2(ZPb, ZVb, B[63:32]);
assign ZP[4:0] = ZVb ? ZPb : ZPa;
assign ZP[5] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd64
module lzd128 (ZP, ZV, B);
input logic [127:0] B;
logic [5:0] ZPa;
logic [5:0] ZPb;
logic ZVa;
logic ZVb;
output logic [6:0] ZP;
output logic ZV;
lzd64 l1(ZPa, ZVa, B[64:0]);
lzd64 l2(ZPb, ZVb, B[127:63]);
assign ZP[5:0] = ZVb ? ZPb : ZPa;
assign ZP[6] = ~ZVb;
assign ZV = ZVa | ZVb;
endmodule // lzd128
/* verilator lint_on DECLFILENAME */

View File

@ -33,18 +33,16 @@ module or_rows #(parameter ROWS = 8, COLS=2) (
input var logic [COLS-1:0] a[ROWS-1:0], input var logic [COLS-1:0] a[ROWS-1:0],
output logic [COLS-1:0] y); output logic [COLS-1:0] y);
logic [COLS-1:0] mid[ROWS-1:1]; genvar row;
genvar row, col; if(ROWS == 1)
generate assign y = a[0];
if(ROWS == 1) else begin
assign y = a[0]; logic [COLS-1:0] mid[ROWS-1:1];
else begin assign mid[1] = a[0] | a[1];
assign mid[1] = a[0] | a[1]; for (row=2; row < ROWS; row++)
for (row=2; row < ROWS; row++) assign mid[row] = mid[row-1] | a[row];
assign mid[row] = mid[row-1] | a[row]; assign y = mid[ROWS-1];
assign y = mid[ROWS-1]; end
end
endgenerate
endmodule endmodule
/* verilator lint_on UNOPTFLAT */ /* verilator lint_on UNOPTFLAT */

View File

@ -1,74 +0,0 @@
///////////////////////////////////////////
// shifters.sv
//
// Written: James.Stine@okstate.edu 1 February 2021
// Modified:
//
// Purpose: Integer Divide instructions
//
// 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"
/* verilator lint_off DECLFILENAME */
/* verilator lint_off UNOPTFLAT */
module shift_right #(parameter WIDTH=8)
(input logic [WIDTH-1:0] A,
input logic [$clog2(WIDTH)-1:0] Shift,
output logic [WIDTH-1:0] Z);
logic [WIDTH-1:0] stage [$clog2(WIDTH):0];
logic sign;
genvar i;
assign stage[0] = A;
generate
for (i=0;i<$clog2(WIDTH);i=i+1) begin : genbit
mux2 #(WIDTH) mux_inst (stage[i],
{{(WIDTH/(2**(i+1))){1'b0}}, stage[i][WIDTH-1:WIDTH/(2**(i+1))]},
Shift[$clog2(WIDTH)-i-1],
stage[i+1]);
end
endgenerate
assign Z = stage[$clog2(WIDTH)];
endmodule // shift_right
module shift_left #(parameter WIDTH=8)
(input logic [WIDTH-1:0] A,
input logic [$clog2(WIDTH)-1:0] Shift,
output logic [WIDTH-1:0] Z);
logic [WIDTH-1:0] stage [$clog2(WIDTH):0];
genvar i;
assign stage[0] = A;
generate
for (i=0;i<$clog2(WIDTH);i=i+1) begin : genbit
mux2 #(WIDTH) mux_inst (stage[i],
{stage[i][WIDTH-1-WIDTH/(2**(i+1)):0], {(WIDTH/(2**(i+1))){1'b0}}},
Shift[$clog2(WIDTH)-i-1],
stage[i+1]);
end
endgenerate
assign Z = stage[$clog2(WIDTH)];
endmodule // shift_left
/* verilator lint_on DECLFILENAME */
/* verilator lint_on UNOPTFLAT */

View File

@ -78,9 +78,7 @@ module alu #(parameter WIDTH=32) (
endcase endcase
// support W-type RV64I ADDW/SUBW/ADDIW/Shifts that sign-extend 32-bit result to 64 bits // support W-type RV64I ADDW/SUBW/ADDIW/Shifts that sign-extend 32-bit result to 64 bits
generate if (WIDTH==64) assign Result = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult;
if (WIDTH==64) assign Result = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult; else assign Result = FullResult;
else assign Result = FullResult;
endgenerate
endmodule endmodule

View File

@ -109,55 +109,53 @@ module controller(
assign Rs1D = InstrD[19:15]; assign Rs1D = InstrD[19:15];
// Main Instruction Decoder // Main Instruction Decoder
generate always_comb
always_comb case(OpD)
case(OpD) // RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MulDiv_Atomic_Illegal
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_ALUResultSrc_W64_CSRRead_Privileged_Fence_MulDiv_Atomic_Illegal 7'b0000000: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // illegal instruction
7'b0000000: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // illegal instruction 7'b0000011: ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // lw
7'b0000011: ControlsD = `CTRLW'b1_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // lw 7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // flw
7'b0000111: ControlsD = `CTRLW'b0_000_01_10_001_0_0_0_0_0_0_0_0_0_00_0; // flw 7'b0001111: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence
7'b0001111: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_1_0_00_0; // fence 7'b0010011: ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU
7'b0010011: ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU 7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc 7'b0011011: if (`XLEN == 64)
7'b0011011: if (`XLEN == 64) ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
7'b0100011: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // sw
7'b0100111: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // fsw
7'b0101111: if (`A_SUPPORTED) begin
if (InstrD[31:27] == 5'b00010)
ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0; // lr
else if (InstrD[31:27] == 5'b00011)
ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0; // sc
else else
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0;; // amo
7'b0100011: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // sw end else
7'b0100111: ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // fsw ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
7'b0101111: if (`A_SUPPORTED) begin 7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000)
if (InstrD[31:27] == 5'b00010) ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type
ControlsD = `CTRLW'b1_000_00_10_001_0_0_0_0_0_0_0_0_0_01_0; // lr else if (Funct7D == 7'b0000001 & `M_SUPPORTED)
else if (InstrD[31:27] == 5'b00011) ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/Divide
ControlsD = `CTRLW'b1_101_01_01_100_0_0_0_0_0_0_0_0_0_01_0; // sc else
else ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
ControlsD = `CTRLW'b1_101_01_11_001_0_0_0_0_0_0_0_0_0_10_0;; // amo 7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
end else 7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000) & `XLEN == 64)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000) else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64)
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
else if (Funct7D == 7'b0000001 & `M_SUPPORTED) else
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/Divide ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
else //7'b1010011: ControlsD = `CTRLW'b0_000_00_00_101_0_00_0_0_0_0_0_0_0_00_1; // FP
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction 7'b1100011: ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches
7'b0110111: ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui 7'b1100111: ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr
7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000) & `XLEN == 64) 7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0; // jal
ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i 7'b1110011: if (Funct3D == 3'b000)
else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64) ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules
ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide else
else ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction default: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
//7'b1010011: ControlsD = `CTRLW'b0_000_00_00_101_0_00_0_0_0_0_0_0_0_00_1; // FP endcase
7'b1100011: ControlsD = `CTRLW'b0_010_11_00_000_1_0_0_0_0_0_0_0_0_00_0; // branches
7'b1100111: ControlsD = `CTRLW'b1_000_01_00_000_0_0_1_1_0_0_0_0_0_00_0; // jalr
7'b1101111: ControlsD = `CTRLW'b1_011_11_00_000_0_0_1_1_0_0_0_0_0_00_0; // jal
7'b1110011: if (Funct3D == 3'b000)
ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_1_0_0_00_0; // privileged; decoded further in priveleged modules
else
ControlsD = `CTRLW'b1_000_00_00_010_0_0_0_0_0_1_0_0_0_00_0; // csrs
default: ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // non-implemented instruction
endcase
endgenerate
// unswizzle control bits // unswizzle control bits
// squash control signals if coming from an illegal compressed instruction // squash control signals if coming from an illegal compressed instruction
@ -181,17 +179,15 @@ module controller(
// Fences // Fences
// Ordinary fence is presently a nop // Ordinary fence is presently a nop
// FENCE.I flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented // FENCE.I flushes the D$ and invalidates the I$ if Zifencei is supported and I$ is implemented
generate if (`ZIFENCEI_SUPPORTED & `MEM_ICACHE) begin:fencei
if (`ZIFENCEI_SUPPORTED & `MEM_ICACHE) begin:fencei logic FenceID;
logic FenceID; assign FenceID = FenceD & (Funct3D == 3'b001); // is it a FENCE.I instruction?
assign FenceID = FenceD & (Funct3D == 3'b001); // is it a FENCE.I instruction? assign InvalidateICacheD = FenceID;
assign InvalidateICacheD = FenceID; assign FlushDCacheD = FenceID;
assign FlushDCacheD = FenceID; end else begin:fencei
end else begin:fencei assign InvalidateICacheD = 0;
assign InvalidateICacheD = 0; assign FlushDCacheD = 0;
assign FlushDCacheD = 0; end
end
endgenerate
// Decocde stage pipeline control register // Decocde stage pipeline control register
flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD); flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, 1'b1, InstrValidD);

View File

@ -124,19 +124,15 @@ module datapath (
mux5 #(`XLEN) resultmuxW(ResultW, ReadDataW, CSRReadValW, MulDivResultW, SCResultW, ResultSrcW, WriteDataW); mux5 #(`XLEN) resultmuxW(ResultW, ReadDataW, CSRReadValW, MulDivResultW, SCResultW, ResultSrcW, WriteDataW);
// floating point interactions: fcvt, fp stores // floating point interactions: fcvt, fp stores
generate if (`F_SUPPORTED) begin:fpmux
if (`F_SUPPORTED) begin:fpmux mux2 #(`XLEN) resultmuxM(IEUResultM, FIntResM, FWriteIntM, ResultM);
mux2 #(`XLEN) resultmuxM(IEUResultM, FIntResM, FWriteIntM, ResultM); mux2 #(`XLEN) writedatamux(ForwardedSrcBE, FWriteDataE, ~IllegalFPUInstrE, WriteDataE);
mux2 #(`XLEN) writedatamux(ForwardedSrcBE, FWriteDataE, ~IllegalFPUInstrE, WriteDataE); end else begin:fpmux
end else begin:fpmux assign ResultM = IEUResultM;
assign ResultM = IEUResultM; assign WriteDataE = ForwardedSrcBE;
assign WriteDataE = ForwardedSrcBE; end
end
endgenerate
// handle Store Conditional result if atomic extension supported // handle Store Conditional result if atomic extension supported
generate if (`A_SUPPORTED) assign SCResultW = {{(`XLEN-1){1'b0}}, SquashSCW};
if (`A_SUPPORTED) assign SCResultW = {{(`XLEN-1){1'b0}}, SquashSCW}; else assign SCResultW = 0;
else assign SCResultW = 0;
endgenerate
endmodule endmodule

View File

@ -32,23 +32,24 @@ module extend (
localparam [`XLEN-1:0] undefined = {(`XLEN){1'bx}}; // could change to 0 after debug localparam [`XLEN-1:0] undefined = {(`XLEN){1'bx}}; // could change to 0 after debug
// generate always_comb
always_comb case(ImmSrcD)
case(ImmSrcD) // I-type
// I-type 3'b000: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:20]};
3'b000: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:20]}; // S-type (stores)
// S-type (stores) 3'b001: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]};
3'b001: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[31:25], InstrD[11:7]}; // B-type (branches)
// B-type (branches) 3'b010: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0};
3'b010: ExtImmD = {{(`XLEN-12){InstrD[31]}}, InstrD[7], InstrD[30:25], InstrD[11:8], 1'b0}; // J-type (jal)
// J-type (jal) 3'b011: ExtImmD = {{(`XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0};
3'b011: ExtImmD = {{(`XLEN-20){InstrD[31]}}, InstrD[19:12], InstrD[20], InstrD[30:21], 1'b0}; // U-type (lui, auipc)
// U-type (lui, auipc) 3'b100: ExtImmD = {{(`XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0};
3'b100: ExtImmD = {{(`XLEN-31){InstrD[31]}}, InstrD[30:12], 12'b0}; // Store Conditional: zero offset
// Store Conditional: zero offset 3'b101: if (`A_SUPPORTED) ExtImmD = 0;
3'b101: if (`A_SUPPORTED) ExtImmD = 0; else ExtImmD = undefined;
else ExtImmD = undefined; default: begin
default: ExtImmD = undefined; // undefined ExtImmD = undefined; // undefined
endcase $error("Invalid ImmSrcD in extend");
// endgenerate end
endcase
endmodule endmodule

View File

@ -39,7 +39,7 @@ module shifter (
// For RV64, 32 and 64-bit shifts are needed, with sign extension. // For RV64, 32 and 64-bit shifts are needed, with sign extension.
// funnel shifter input (see CMOS VLSI Design 4e Section 11.8.1, note Table 11.11 shift types wrong) // funnel shifter input (see CMOS VLSI Design 4e Section 11.8.1, note Table 11.11 shift types wrong)
generate // generate
if (`XLEN==32) begin:shifter // RV32 if (`XLEN==32) begin:shifter // RV32
always_comb // funnel mux always_comb // funnel mux
if (Right) if (Right)
@ -62,7 +62,7 @@ module shifter (
end end
assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32 or 64-bit shift assign amttrunc = W64 ? {1'b0, Amt[4:0]} : Amt; // 32 or 64-bit shift
end end
endgenerate // endgenerate
// opposite offset for right shfits // opposite offset for right shfits
assign offset = Right ? amttrunc : ~amttrunc; assign offset = Right ? amttrunc : ~amttrunc;

View File

@ -93,18 +93,15 @@ module SRAM2P1R1W
// read port // read port
assign RD1 = mem[RA1Q]; assign RD1 = mem[RA1Q];
genvar index;
// write port // write port
generate genvar index;
for (index = 0; index < WIDTH; index = index + 1) begin:bitwrite for (index = 0; index < WIDTH; index = index + 1) begin:bitwrite
always_ff @ (posedge clk) begin always_ff @(posedge clk) begin
if (WEN1Q & BitWEN1[index]) begin if (WEN1Q & BitWEN1[index]) begin
mem[WA1Q][index] <= WD1Q[index]; mem[WA1Q][index] <= WD1Q[index];
end
end end
end end
endgenerate end
endmodule endmodule

View File

@ -38,36 +38,35 @@ module decompress (
logic [1:0] op; logic [1:0] op;
// if the system handles compressed instructions, decode appropriately // if the system handles compressed instructions, decode appropriately
generate if (!(`C_SUPPORTED)) begin:decompress // no compressed mode
if (!(`C_SUPPORTED)) begin:decompress // no compressed mode assign InstrD = InstrRawD;
assign InstrD = InstrRawD; assign IllegalCompInstrD = 0;
assign IllegalCompInstrD = 0; end else begin : decompress // COMPRESSED mode supported
end else begin : decompress // COMPRESSED mode supported assign instr16 = InstrRawD[15:0]; // instruction is alreay aligned
assign instr16 = InstrRawD[15:0]; // instruction is alreay aligned assign op = instr16[1:0];
assign op = instr16[1:0]; assign rds1 = instr16[11:7];
assign rds1 = instr16[11:7]; assign rs2 = instr16[6:2];
assign rs2 = instr16[6:2]; assign rs1p = {2'b01, instr16[9:7]};
assign rs1p = {2'b01, instr16[9:7]}; assign rds1p = {2'b01, instr16[9:7]};
assign rds1p = {2'b01, instr16[9:7]}; assign rs2p = {2'b01, instr16[4:2]};
assign rs2p = {2'b01, instr16[4:2]}; assign rdp = {2'b01, instr16[4:2]};
assign rdp = {2'b01, instr16[4:2]};
// many compressed immediate formats // many compressed immediate formats
assign immCILSP = {4'b0000, instr16[3:2], instr16[12], instr16[6:4], 2'b00}; assign immCILSP = {4'b0000, instr16[3:2], instr16[12], instr16[6:4], 2'b00};
assign immCILSPD = {3'b000, instr16[4:2], instr16[12], instr16[6:5], 3'b000}; assign immCILSPD = {3'b000, instr16[4:2], instr16[12], instr16[6:5], 3'b000};
assign immCSS = {4'b0000, instr16[8:7], instr16[12:9], 2'b00}; assign immCSS = {4'b0000, instr16[8:7], instr16[12:9], 2'b00};
assign immCSSD = {3'b000, instr16[9:7], instr16[12:10], 3'b000}; assign immCSSD = {3'b000, instr16[9:7], instr16[12:10], 3'b000};
assign immCL = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00}; assign immCL = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00};
assign immCLD = {4'b0, instr16[6:5], instr16[12:10], 3'b000}; assign immCLD = {4'b0, instr16[6:5], instr16[12:10], 3'b000};
assign immCS = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00}; assign immCS = {5'b0, instr16[5], instr16[12:10], instr16[6], 2'b00};
assign immCSD = {4'b0, instr16[6:5], instr16[12:10], 3'b000}; assign immCSD = {4'b0, instr16[6:5], instr16[12:10], 3'b000};
assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}}; assign immCJ = {instr16[12], instr16[8], instr16[10:9], instr16[6], instr16[7], instr16[2], instr16[11], instr16[5:3], {9{instr16[12]}}};
assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]}; assign immCB = {{4{instr16[12]}}, instr16[6:5], instr16[2], instr16[11:10], instr16[4:3], instr16[12]};
assign immCI = {{7{instr16[12]}}, instr16[6:2]}; assign immCI = {{7{instr16[12]}}, instr16[6:2]};
assign immCILUI = {{15{instr16[12]}}, instr16[6:2]}; assign immCILUI = {{15{instr16[12]}}, instr16[6:2]};
assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000}; assign immCIASP = {{3{instr16[12]}}, instr16[4:3], instr16[5], instr16[2], instr16[6], 4'b0000};
assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00}; assign immCIW = {2'b00, instr16[10:7], instr16[12:11], instr16[5], instr16[6], 2'b00};
assign immSH = {instr16[12], instr16[6:2]}; assign immSH = {instr16[12], instr16[6:2]};
// only for RV128 // only for RV128
// assign immCILSPQ = {2{instr16[5]}, instr16[5:2], instr16[12], instr16[6], 4'b0000}; // assign immCILSPQ = {2{instr16[5]}, instr16[5:2], instr16[12], instr16[6], 4'b0000};
@ -75,104 +74,103 @@ module decompress (
// assign immCLQ = {4{instr16[10]}, instr16[6:5], instr16[12:11], 4'b0000}; // assign immCLQ = {4{instr16[10]}, instr16[6:5], instr16[12:11], 4'b0000};
// assign immCSQ = {4{instr16[10]}, instr16[6:5], instr16[12:11], 4'b0000}; // assign immCSQ = {4{instr16[10]}, instr16[6:5], instr16[12:11], 4'b0000};
always_comb always_comb
if (op == 2'b11) begin // noncompressed instruction if (op == 2'b11) begin // noncompressed instruction
InstrD = InstrRawD; InstrD = InstrRawD;
IllegalCompInstrD = 0; IllegalCompInstrD = 0;
end else begin // convert compressed instruction into uncompressed end else begin // convert compressed instruction into uncompressed
IllegalCompInstrD = 0; IllegalCompInstrD = 0;
case ({op, instr16[15:13]}) case ({op, instr16[15:13]})
5'b00000: if (immCIW != 0) InstrD = {immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn 5'b00000: if (immCIW != 0) InstrD = {immCIW, 5'b00010, 3'b000, rdp, 7'b0010011}; // c.addi4spn
else begin // illegal instruction else begin // illegal instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00001: InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw
5'b00011: if (`XLEN==32)
InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
else
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld;
5'b00101: InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw
5'b00111: if (`XLEN==32)
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
else
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd
5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
5'b01001: if (`XLEN==32)
InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal
else
InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li
5'b01011: if (rds1 != 5'b00010)
InstrD = {immCILUI, rds1, 7'b0110111}; // c.lui
else
InstrD = {immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
5'b01100: if (instr16[11:10] == 2'b00)
InstrD = {6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli
else if (instr16[11:10] == 2'b01)
InstrD = {6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai
else if (instr16[11:10] == 2'b10)
InstrD = {immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
else if (instr16[12:10] == 3'b011)
if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
else if (instr16[6:5] == 2'b01)
InstrD = {7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
else if (instr16[6:5] == 2'b10)
InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
else // if (instr16[6:5] == 2'b11)
InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
else if (instr16[12:10] == 3'b111 & `XLEN > 32)
if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw
else if (instr16[6:5] == 2'b01)
InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw
else begin // reserved
IllegalCompInstrD = 1; IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end end
5'b00001: InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld else begin // illegal instruction
5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw IllegalCompInstrD = 1;
5'b00011: if (`XLEN==32) InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw end
5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j
5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz
5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez
5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli
5'b10001: InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
5'b10011: if (`XLEN == 32)
InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
else
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
5'b10100: if (instr16[12] == 0)
if (instr16[6:2] == 5'b00000)
InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr
else else
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld; InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv
5'b00101: InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd else
5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw if (rs2 == 5'b00000)
5'b00111: if (`XLEN==32) if (rds1 == 5'b00000)
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak
else
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd
5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
5'b01001: if (`XLEN==32)
InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal
else
InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
5'b01010: InstrD = {immCI, 5'b00000, 3'b000, rds1, 7'b0010011}; // c.li
5'b01011: if (rds1 != 5'b00010)
InstrD = {immCILUI, rds1, 7'b0110111}; // c.lui
else
InstrD = {immCIASP, rds1, 3'b000, rds1, 7'b0010011}; // c.addi16sp
5'b01100: if (instr16[11:10] == 2'b00)
InstrD = {6'b000000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srli
else if (instr16[11:10] == 2'b01)
InstrD = {6'b010000, immSH, rds1p, 3'b101, rds1p, 7'b0010011}; // c.srai
else if (instr16[11:10] == 2'b10)
InstrD = {immCI, rds1p, 3'b111, rds1p, 7'b0010011}; // c.andi
else if (instr16[12:10] == 3'b011)
if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.sub
else if (instr16[6:5] == 2'b01)
InstrD = {7'b0000000, rs2p, rds1p, 3'b100, rds1p, 7'b0110011}; // c.xor
else if (instr16[6:5] == 2'b10)
InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
else // if (instr16[6:5] == 2'b11)
InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
else if (instr16[12:10] == 3'b111 & `XLEN > 32)
if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw
else if (instr16[6:5] == 2'b01)
InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw
else begin // reserved
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else begin // illegal instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j
5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz
5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez
5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli
5'b10001: InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
5'b10011: if (`XLEN == 32)
InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
else
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
5'b10100: if (instr16[12] == 0)
if (instr16[6:2] == 5'b00000)
InstrD = {7'b0000000, 5'b00000, rds1, 3'b000, 5'b00000, 7'b1100111}; // c.jr
else else
InstrD = {7'b0000000, rs2, 5'b00000, 3'b000, rds1, 7'b0110011}; // c.mv InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr
else else
if (rs2 == 5'b00000) InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add
if (rds1 == 5'b00000) 5'b10101: InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
InstrD = {12'b1, 5'b00000, 3'b000, 5'b00000, 7'b1110011}; // c.ebreak 5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
else 5'b10111: if (`XLEN==32)
InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
else else
InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp
5'b10101: InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp default: begin // illegal instruction
5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp IllegalCompInstrD = 1;
5'b10111: if (`XLEN==32) InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp end
else endcase
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp end
default: begin // illegal instruction end
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
endcase
end
end
endgenerate
endmodule endmodule

View File

@ -38,77 +38,75 @@ module subwordread
// Funct3M[2] is the unsigned bit. mask upper bits. // Funct3M[2] is the unsigned bit. mask upper bits.
// Funct3M[1:0] is the size of the memory access. // Funct3M[1:0] is the size of the memory access.
generate if (`XLEN == 64) begin:swrmux
if (`XLEN == 64) begin:swrmux // ByteMe mux
// ByteMe mux always_comb
always_comb case(LsuPAdrM[2:0])
case(LsuPAdrM[2:0]) 3'b000: ByteM = ReadDataWordMuxM[7:0];
3'b000: ByteM = ReadDataWordMuxM[7:0]; 3'b001: ByteM = ReadDataWordMuxM[15:8];
3'b001: ByteM = ReadDataWordMuxM[15:8]; 3'b010: ByteM = ReadDataWordMuxM[23:16];
3'b010: ByteM = ReadDataWordMuxM[23:16]; 3'b011: ByteM = ReadDataWordMuxM[31:24];
3'b011: ByteM = ReadDataWordMuxM[31:24]; 3'b100: ByteM = ReadDataWordMuxM[39:32];
3'b100: ByteM = ReadDataWordMuxM[39:32]; 3'b101: ByteM = ReadDataWordMuxM[47:40];
3'b101: ByteM = ReadDataWordMuxM[47:40]; 3'b110: ByteM = ReadDataWordMuxM[55:48];
3'b110: ByteM = ReadDataWordMuxM[55:48]; 3'b111: ByteM = ReadDataWordMuxM[63:56];
3'b111: ByteM = ReadDataWordMuxM[63:56]; endcase
// halfword mux
always_comb
case(LsuPAdrM[2:1])
2'b00: HalfwordM = ReadDataWordMuxM[15:0];
2'b01: HalfwordM = ReadDataWordMuxM[31:16];
2'b10: HalfwordM = ReadDataWordMuxM[47:32];
2'b11: HalfwordM = ReadDataWordMuxM[63:48];
endcase
logic [31:0] WordM;
always_comb
case(LsuPAdrM[2])
1'b0: WordM = ReadDataWordMuxM[31:0];
1'b1: WordM = ReadDataWordMuxM[63:32];
endcase endcase
// halfword mux // sign extension
always_comb always_comb
case(LsuPAdrM[2:1]) case(Funct3M)
2'b00: HalfwordM = ReadDataWordMuxM[15:0]; 3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb
2'b01: HalfwordM = ReadDataWordMuxM[31:16]; 3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
2'b10: HalfwordM = ReadDataWordMuxM[47:32]; 3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw
2'b11: HalfwordM = ReadDataWordMuxM[63:48]; 3'b011: ReadDataM = ReadDataWordMuxM; // ld
endcase 3'b100: ReadDataM = {56'b0, ByteM[7:0]}; // lbu
3'b101: ReadDataM = {48'b0, HalfwordM[15:0]}; // lhu
3'b110: ReadDataM = {32'b0, WordM[31:0]}; // lwu
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
endcase
end else begin:swrmux // 32-bit
// byte mux
always_comb
case(LsuPAdrM[1:0])
2'b00: ByteM = ReadDataWordMuxM[7:0];
2'b01: ByteM = ReadDataWordMuxM[15:8];
2'b10: ByteM = ReadDataWordMuxM[23:16];
2'b11: ByteM = ReadDataWordMuxM[31:24];
endcase
logic [31:0] WordM; // halfword mux
always_comb
case(LsuPAdrM[1])
1'b0: HalfwordM = ReadDataWordMuxM[15:0];
1'b1: HalfwordM = ReadDataWordMuxM[31:16];
endcase
always_comb // sign extension
case(LsuPAdrM[2]) always_comb
1'b0: WordM = ReadDataWordMuxM[31:0]; case(Funct3M)
1'b1: WordM = ReadDataWordMuxM[63:32]; 3'b000: ReadDataM = {{24{ByteM[7]}}, ByteM}; // lb
endcase 3'b001: ReadDataM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: ReadDataM = ReadDataWordMuxM; // lw
// sign extension 3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu
always_comb 3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu
case(Funct3M) default: ReadDataM = ReadDataWordMuxM;
3'b000: ReadDataM = {{56{ByteM[7]}}, ByteM}; // lb endcase
3'b001: ReadDataM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh end
3'b010: ReadDataM = {{32{WordM[31]}}, WordM[31:0]}; // lw
3'b011: ReadDataM = ReadDataWordMuxM; // ld
3'b100: ReadDataM = {56'b0, ByteM[7:0]}; // lbu
3'b101: ReadDataM = {48'b0, HalfwordM[15:0]}; // lhu
3'b110: ReadDataM = {32'b0, WordM[31:0]}; // lwu
default: ReadDataM = ReadDataWordMuxM; // Shouldn't happen
endcase
end else begin :swrmux // 32-bit
// byte mux
always_comb
case(LsuPAdrM[1:0])
2'b00: ByteM = ReadDataWordMuxM[7:0];
2'b01: ByteM = ReadDataWordMuxM[15:8];
2'b10: ByteM = ReadDataWordMuxM[23:16];
2'b11: ByteM = ReadDataWordMuxM[31:24];
endcase
// halfword mux
always_comb
case(LsuPAdrM[1])
1'b0: HalfwordM = ReadDataWordMuxM[15:0];
1'b1: HalfwordM = ReadDataWordMuxM[31:16];
endcase
// sign extension
always_comb
case(Funct3M)
3'b000: ReadDataM = {{24{ByteM[7]}}, ByteM}; // lb
3'b001: ReadDataM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: ReadDataM = ReadDataWordMuxM; // lw
3'b100: ReadDataM = {24'b0, ByteM[7:0]}; // lbu
3'b101: ReadDataM = {16'b0, HalfwordM[15:0]}; // lhu
default: ReadDataM = ReadDataWordMuxM;
endcase
end
endgenerate
endmodule endmodule

View File

@ -52,7 +52,7 @@ module hptw
L1_ADR, L1_RD, L1_ADR, L1_RD,
L2_ADR, L2_RD, L2_ADR, L2_RD,
L3_ADR, L3_RD, L3_ADR, L3_RD,
LEAF, IDLE} statetype; // *** placed outside generate statement to remove synthesis errors LEAF, IDLE} statetype;
logic DTLBWalk; // register TLBs translation miss requests logic DTLBWalk; // register TLBs translation miss requests
logic [`PPN_BITS-1:0] BasePageTablePPN; logic [`PPN_BITS-1:0] BasePageTablePPN;

View File

@ -90,27 +90,25 @@ module mmu #(parameter TLB_ENTRIES = 8, // number of TLB Entries
// only instantiate TLB if Virtual Memory is supported // only instantiate TLB if Virtual Memory is supported
generate if (`MEM_VIRTMEM) begin:tlb
if (`MEM_VIRTMEM) begin:tlb logic ReadAccess, WriteAccess;
logic ReadAccess, WriteAccess; assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages
assign ReadAccess = ExecuteAccessF | ReadAccessM; // execute also acts as a TLB read. Execute and Read are never active for the same MMU, so safe to mix pipestages assign WriteAccess = WriteAccessM;
assign WriteAccess = WriteAccessM; tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU))
tlb #(.TLB_ENTRIES(TLB_ENTRIES), .ITLB(IMMU)) tlb(.clk, .reset,
tlb(.clk, .reset, .SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]),
.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), .SATP_ASID(SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]),
.SATP_ASID(SATP_REGW[`ASID_BASE+`ASID_BITS-1:`ASID_BASE]), .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP,
.VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW, .ReadAccess, .WriteAccess,
.PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .PTE, .PageTypeWriteVal,
.DisableTranslation, .PTE, .PageTypeWriteVal, .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit, .Translate, .TLBPageFault);
.Translate, .TLBPageFault); end else begin:tlb// just pass address through as physical
end else begin:tlb// just pass address through as physical assign Translate = 0;
assign Translate = 0; assign TLBMiss = 0;
assign TLBMiss = 0; assign TLBHit = 1; // *** is this necessary
assign TLBHit = 1; // *** is this necessary assign TLBPageFault = 0;
assign TLBPageFault = 0; end
end
endgenerate
// If translation is occuring, select translated physical address from TLB // If translation is occuring, select translated physical address from TLB
mux2 #(`PA_BITS) addressmux(PAdr, TLBPAdr, Translate, PhysicalAddress); mux2 #(`PA_BITS) addressmux(PAdr, TLBPAdr, Translate, PhysicalAddress);

View File

@ -68,7 +68,7 @@ module pmpadrdec (
assign NAMask[1:0] = {2'b11}; assign NAMask[1:0] = {2'b11};
assign NAMask[`PA_BITS-1:2] = (PMPAdr[`PA_BITS-3:0] + {{(`PA_BITS-3){1'b0}}, (AdrMode == NAPOT)}) ^ PMPAdr[`PA_BITS-3:0]; assign NAMask[`PA_BITS-1:2] = (PMPAdr[`PA_BITS-3:0] + {{(`PA_BITS-3){1'b0}}, (AdrMode == NAPOT)}) ^ PMPAdr[`PA_BITS-3:0];
// generates a mask where the bottom k bits are 1, corresponding to a size of 2^k bytes for this memory region. // form a mask where the bottom k bits are 1, corresponding to a size of 2^k bytes for this memory region.
// This assumes we're using at least an NA4 region, but works for any size NAPOT region. // This assumes we're using at least an NA4 region, but works for any size NAPOT region.
assign NABase = {(PMPAdr[`PA_BITS-3:0] & ~NAMask[`PA_BITS-1:2]), 2'b00}; // base physical address of the pmp. assign NABase = {(PMPAdr[`PA_BITS-3:0] & ~NAMask[`PA_BITS-1:2]), 2'b00}; // base physical address of the pmp.

View File

@ -47,37 +47,34 @@ module pmpchecker (
output logic PMPStoreAccessFaultM output logic PMPStoreAccessFaultM
); );
generate if (`PMP_ENTRIES > 0) begin: pmpchecker
if (`PMP_ENTRIES > 0) begin: pmpchecker // Bit i is high when the address falls in PMP region i
// Bit i is high when the address falls in PMP region i logic EnforcePMP;
logic EnforcePMP; logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges
logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address.
logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address. logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null
logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set
logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i]
pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0]( pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0](
.PhysicalAddress, .PhysicalAddress,
.PMPCfg(PMPCFG_ARRAY_REGW), .PMPCfg(PMPCFG_ARRAY_REGW),
.PMPAdr(PMPADDR_ARRAY_REGW), .PMPAdr(PMPADDR_ARRAY_REGW),
.PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}), .PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}),
.PAgePMPAdrOut(PAgePMPAdr), .PAgePMPAdrOut(PAgePMPAdr),
.FirstMatch, .Match, .Active, .L, .X, .W, .R); .FirstMatch, .Match, .Active, .L, .X, .W, .R);
priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches. priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
// Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region // Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region
assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active; assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active;
assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|X; assign PMPInstrAccessFaultF = EnforcePMP & ExecuteAccessF & ~|X;
assign PMPStoreAccessFaultM = EnforcePMP & WriteAccessM & ~|W; assign PMPStoreAccessFaultM = EnforcePMP & WriteAccessM & ~|W;
assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|R; assign PMPLoadAccessFaultM = EnforcePMP & ReadAccessM & ~|R;
end else begin: pmpchecker // no checker end else begin: pmpchecker // no checker
assign PMPInstrAccessFaultF = 0; assign PMPInstrAccessFaultF = 0;
assign PMPLoadAccessFaultM = 0; assign PMPLoadAccessFaultM = 0;
assign PMPStoreAccessFaultM = 0; assign PMPStoreAccessFaultM = 0;
end end
endgenerate
//assign PMPSquashBusAccess = PMPInstrAccessFaultF | PMPLoadAccessFaultM | PMPStoreAccessFaultM;
endmodule endmodule

View File

@ -34,25 +34,9 @@ module priorityonehot #(parameter ENTRIES = 8) (
input logic [ENTRIES-1:0] a, input logic [ENTRIES-1:0] a,
output logic [ENTRIES-1:0] y output logic [ENTRIES-1:0] y
); );
/* verilator lint_off UNOPTFLAT */
logic [ENTRIES-1:0] nolower; logic [ENTRIES-1:0] nolower;
// generate thermometer code mask // create thermometer code mask
prioritythermometer #(ENTRIES) maskgen(.a({a[ENTRIES-2:0], 1'b1}), .y(nolower)); prioritythermometer #(ENTRIES) maskgen(.a({a[ENTRIES-2:0], 1'b1}), .y(nolower));
// genvar i;
// generate
// assign nolower[0] = 1'b1;
// for (i=1; i<ENTRIES; i++) begin:therm
// assign nolower[i] = nolower[i-1] & ~a[i-1];
// end
// endgenerate
// *** replace mask generation logic ^^^ with priority thermometer
assign y = a & nolower; assign y = a & nolower;
/* verilator lint_on UNOPTFLAT */
endmodule endmodule

View File

@ -37,20 +37,15 @@ module prioritythermometer #(parameter N = 8) (
output logic [N-1:0] y output logic [N-1:0] y
); );
// Carefully crafted so design compiler would synthesize into a fast tree structure // Carefully crafted so design compiler will synthesize into a fast tree structure
// Rather than linear. // Rather than linear.
// generate thermometer code mask // create thermometer code mask
genvar i; genvar i;
generate assign y[0] = a[0];
assign y[0] = a[0]; for (i=1; i<N; i++) begin:therm
for (i=1; i<N; i++) begin:therm assign y[i] = y[i-1] & ~a[i];
assign y[i] = y[i-1] & ~a[i]; // *** made to be the same as onehot (without the inverter) to see if the probelme is something weird with synthesis end
// assign y[i] = y[i-1] & a[i];
end
endgenerate
endmodule endmodule

View File

@ -60,38 +60,36 @@ module tlbcamline #(parameter KEY_BITS = 20,
assign MatchASID = (SATP_ASID == Key_ASID) | PTE_G; assign MatchASID = (SATP_ASID == Key_ASID) | PTE_G;
generate if (`XLEN == 32) begin: match
if (`XLEN == 32) begin:match
assign {Key_ASID, Key1, Key0} = Key; assign {Key_ASID, Key1, Key0} = Key;
assign {Query1, Query0} = VPN; assign {Query1, Query0} = VPN;
// Calculate the actual match value based on the input vpn and the page type. // Calculate the actual match value based on the input vpn and the page type.
// For example, a megapage in SV32 only cares about VPN[1], so VPN[0] // For example, a megapage in SV32 only cares about VPN[1], so VPN[0]
// should automatically match. // should automatically match.
assign Match0 = (Query0 == Key0) | (PageType[0]); // least signifcant section assign Match0 = (Query0 == Key0) | (PageType[0]); // least signifcant section
assign Match1 = (Query1 == Key1); assign Match1 = (Query1 == Key1);
assign Match = Match0 & Match1 & MatchASID & Valid; assign Match = Match0 & Match1 & MatchASID & Valid;
end else begin:match end else begin: match
logic [SEGMENT_BITS-1:0] Key2, Key3, Query2, Query3; logic [SEGMENT_BITS-1:0] Key2, Key3, Query2, Query3;
logic Match2, Match3; logic Match2, Match3;
assign {Query3, Query2, Query1, Query0} = VPN; assign {Query3, Query2, Query1, Query0} = VPN;
assign {Key_ASID, Key3, Key2, Key1, Key0} = Key; assign {Key_ASID, Key3, Key2, Key1, Key0} = Key;
// Calculate the actual match value based on the input vpn and the page type. // Calculate the actual match value based on the input vpn and the page type.
// For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1] // For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1]
// should automatically match. // should automatically match.
assign Match0 = (Query0 == Key0) | (PageType > 2'd0); // least signifcant section assign Match0 = (Query0 == Key0) | (PageType > 2'd0); // least signifcant section
assign Match1 = (Query1 == Key1) | (PageType > 2'd1); assign Match1 = (Query1 == Key1) | (PageType > 2'd1);
assign Match2 = (Query2 == Key2) | (PageType > 2'd2); assign Match2 = (Query2 == Key2) | (PageType > 2'd2);
assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used
assign Match = Match0 & Match1 & Match2 & Match3 & MatchASID & Valid; assign Match = Match0 & Match1 & Match2 & Match3 & MatchASID & Valid;
end end
endgenerate
// On a write, update the type of the page referred to by this line. // On a write, update the type of the page referred to by this line.
flopenr #(2) pagetypeflop(clk, reset, WriteEnable, PageTypeWriteVal, PageType); flopenr #(2) pagetypeflop(clk, reset, WriteEnable, PageTypeWriteVal, PageType);

View File

@ -60,65 +60,59 @@ module tlbcontrol #(parameter ITLB = 0) (
logic UpperBitsUnequalPageFault; logic UpperBitsUnequalPageFault;
logic DAPageFault; logic DAPageFault;
logic TLBAccess; logic TLBAccess;
logic ImproperPrivilege;
// Grab the sv mode from SATP and determine whether translation should occur // Grab the sv mode from SATP and determine whether translation should occur
assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1 assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1
assign Translate = (SATP_MODE != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~DisableTranslation; assign Translate = (SATP_MODE != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~DisableTranslation;
generate if (`XLEN==64) begin:rv64
if (`XLEN==64) begin:rv64 assign SV39Mode = (SATP_MODE == `SV39);
assign SV39Mode = (SATP_MODE == `SV39); // page fault if upper bits aren't all the same
// generate page fault if upper bits aren't all the same logic UpperEqual39, UpperEqual48;
logic UpperEqual39, UpperEqual48; assign UpperEqual39 = &(VAdr[63:38]) | ~|(VAdr[63:38]);
assign UpperEqual39 = &(VAdr[63:38]) | ~|(VAdr[63:38]); assign UpperEqual48 = &(VAdr[63:47]) | ~|(VAdr[63:47]);
assign UpperEqual48 = &(VAdr[63:47]) | ~|(VAdr[63:47]); assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48;
assign UpperBitsUnequalPageFault = SV39Mode ? ~UpperEqual39 : ~UpperEqual48; end else begin
end else begin assign SV39Mode = 0;
assign SV39Mode = 0; assign UpperBitsUnequalPageFault = 0;
assign UpperBitsUnequalPageFault = 0; end
end
endgenerate
// Determine whether TLB is being used // Determine whether TLB is being used
assign TLBAccess = ReadAccess | WriteAccess; assign TLBAccess = ReadAccess | WriteAccess;
// Check whether upper bits of virtual addresss are all equal // Check whether upper bits of virtual addresss are all equal
// unswizzle useful PTE bits // unswizzle useful PTE bits
assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; assign {PTE_D, PTE_A} = PTEAccessBits[7:6];
assign {PTE_U, PTE_X, PTE_W, PTE_R, PTE_V} = PTEAccessBits[4:0]; assign {PTE_U, PTE_X, PTE_W, PTE_R, PTE_V} = PTEAccessBits[4:0];
// Check whether the access is allowed, page faulting if not. // Check whether the access is allowed, page faulting if not.
generate if (ITLB == 1) begin:itlb // Instruction TLB fault checking
if (ITLB == 1) begin:itlb // Instruction TLB fault checking // User mode may only execute user mode pages, and supervisor mode may
logic ImproperPrivilege; // only execute non-user mode pages.
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == `S_MODE) & PTE_U);
// fault for software handling if access bit is off
assign DAPageFault = ~PTE_A;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
end else begin:dtlb // Data TLB fault checking
logic InvalidRead, InvalidWrite;
// User mode may only execute user mode pages, and supervisor mode may // User mode may only load/store from user mode pages, and supervisor mode
// only execute non-user mode pages. // may only access user mode pages when STATUS_SUM is low.
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == `S_MODE) & PTE_U); ((EffectivePrivilegeMode == `S_MODE) & PTE_U & ~STATUS_SUM);
// fault for software handling if access bit is off // Check for read error. Reads are invalid when the page is not readable
assign DAPageFault = ~PTE_A; // (and executable pages are not readable) or when the page is neither
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); // readable nor executable (and executable pages are readable).
end else begin:dtlb // Data TLB fault checking assign InvalidRead = ReadAccess & ~PTE_R & (~STATUS_MXR | ~PTE_X);
logic ImproperPrivilege, InvalidRead, InvalidWrite; // Check for write error. Writes are invalid when the page's write bit is
// low.
// User mode may only load/store from user mode pages, and supervisor mode assign InvalidWrite = WriteAccess & ~PTE_W;
// may only access user mode pages when STATUS_SUM is low. // Fault for software handling if access bit is off or writing a page with dirty bit off
assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D;
((EffectivePrivilegeMode == `S_MODE) & PTE_U & ~STATUS_SUM); assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
// Check for read error. Reads are invalid when the page is not readable end
// (and executable pages are not readable) or when the page is neither
// readable nor executable (and executable pages are readable).
assign InvalidRead = ReadAccess & ~PTE_R & (~STATUS_MXR | ~PTE_X);
// Check for write error. Writes are invalid when the page's write bit is
// low.
assign InvalidWrite = WriteAccess & ~PTE_W;
// Fault for software handling if access bit is off or writing a page with dirty bit off
assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V));
end
endgenerate
assign TLBHit = CAMHit & TLBAccess; assign TLBHit = CAMHit & TLBAccess;
assign TLBMiss = (~CAMHit | TLBFlush) & Translate & TLBAccess; assign TLBMiss = (~CAMHit | TLBFlush) & Translate & TLBAccess;

View File

@ -43,18 +43,16 @@ module tlbmixer (
logic [`PPN_BITS-1:0] PPNMixed; logic [`PPN_BITS-1:0] PPNMixed;
// produce PageNumberMask with 1s where virtual page number bits should be untranslaetd for superpages // produce PageNumberMask with 1s where virtual page number bits should be untranslaetd for superpages
generate if (`XLEN == 32)
if (`XLEN == 32) // kilopage: 22 bits of PPN, 0 bits of VPN
// kilopage: 22 bits of PPN, 0 bits of VPN // megapage: 12 bits of PPN, 10 bits of VPN
// megapage: 12 bits of PPN, 10 bits of VPN mux2 #(22) pnm(22'h000000, 22'h0003FF, HitPageType[0], PageNumberMask);
mux2 #(22) pnm(22'h000000, 22'h0003FF, HitPageType[0], PageNumberMask); else
else // kilopage: 44 bits of PPN, 0 bits of VPN
// kilopage: 44 bits of PPN, 0 bits of VPN // megapage: 35 bits of PPN, 9 bits of VPN
// megapage: 35 bits of PPN, 9 bits of VPN // gigapage: 26 bits of PPN, 18 bits of VPN
// gigapage: 26 bits of PPN, 18 bits of VPN // terapage: 17 bits of PPN, 27 bits of VPN
// terapage: 17 bits of PPN, 27 bits of VPN mux4 #(44) pnm(44'h00000000000, 44'h000000001FF, 44'h0000003FFFF, 44'h00007FFFFFF, HitPageType, PageNumberMask);
mux4 #(44) pnm(44'h00000000000, 44'h000000001FF, 44'h0000003FFFF, 44'h00007FFFFFF, HitPageType, PageNumberMask);
endgenerate
// merge low segments of VPN with high segments of PPN decided by the pagetype. // merge low segments of VPN with high segments of PPN decided by the pagetype.
assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN. assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN.

File diff suppressed because it is too large Load Diff

View File

@ -60,15 +60,13 @@ module intdivrestoring (
assign DivBusyE = (state == BUSY) | DivStartE; assign DivBusyE = (state == BUSY) | DivStartE;
// Handle sign extension for W-type instructions // Handle sign extension for W-type instructions
generate if (`XLEN == 64) begin:rv64 // RV64 has W-type instructions
if (`XLEN == 64) begin:rv64 // RV64 has W-type instructions mux2 #(`XLEN) xinmux(ForwardedSrcAE, {ForwardedSrcAE[31:0], 32'b0}, W64E, XinE);
mux2 #(`XLEN) xinmux(ForwardedSrcAE, {ForwardedSrcAE[31:0], 32'b0}, W64E, XinE); mux2 #(`XLEN) dinmux(ForwardedSrcBE, {{32{ForwardedSrcBE[31]&DivSignedE}}, ForwardedSrcBE[31:0]}, W64E, DinE);
mux2 #(`XLEN) dinmux(ForwardedSrcBE, {{32{ForwardedSrcBE[31]&DivSignedE}}, ForwardedSrcBE[31:0]}, W64E, DinE); end else begin // RV32 has no W-type instructions
end else begin // RV32 has no W-type instructions assign XinE = ForwardedSrcAE;
assign XinE = ForwardedSrcAE; assign DinE = ForwardedSrcBE;
assign DinE = ForwardedSrcBE;
end end
endgenerate
// Extract sign bits and check fo division by zero // Extract sign bits and check fo division by zero
assign SignDE = DivSignedE & DinE[`XLEN-1]; assign SignDE = DivSignedE & DinE[`XLEN-1];
@ -97,11 +95,9 @@ module intdivrestoring (
flopen #(3) Div0eMReg(clk, DivStartE, {Div0E, NegQE, SignXE}, {Div0M, NegQM, NegWM}); flopen #(3) Div0eMReg(clk, DivStartE, {Div0E, NegQE, SignXE}, {Div0M, NegQM, NegWM});
// one copy of divstep for each bit produced per cycle // one copy of divstep for each bit produced per cycle
generate genvar i;
genvar i; for (i=0; i<`DIV_BITSPERCYCLE; i = i+1)
for (i=0; i<`DIV_BITSPERCYCLE; i = i+1) intdivrestoringstep divstep(WM[i], XQM[i], DAbsBM, WM[i+1], XQM[i+1]);
intdivrestoringstep divstep(WM[i], XQM[i], DAbsBM, WM[i+1], XQM[i+1]);
endgenerate
// On final setp of signed operations, negate outputs as needed to get correct sign // On final setp of signed operations, negate outputs as needed to get correct sign
neg #(`XLEN) qneg(XQM[0], XQnM); neg #(`XLEN) qneg(XQM[0], XQnM);

View File

@ -49,8 +49,8 @@ module mul (
// Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2) // Signed * Unsigned = P' + ( PA - PB)*2^(XLEN-1) - PP*2^(2XLEN-2)
// Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2) // Unsigned * Unsigned = P' + ( PA + PB)*2^(XLEN-1) + PP*2^(2XLEN-2)
logic [`XLEN*2-1:0] PP0E, PP1E, PP2E, PP3E, PP4E; logic [`XLEN*2-1:0] PP1E, PP2E, PP3E, PP4E;
logic [`XLEN*2-1:0] PP0M, PP1M, PP2M, PP3M, PP4M; logic [`XLEN*2-1:0] PP1M, PP2M, PP3M, PP4M;
logic [`XLEN-2:0] PA, PB; logic [`XLEN-2:0] PA, PB;
logic PP; logic PP;
logic MULH, MULHSU; logic MULH, MULHSU;
@ -62,7 +62,7 @@ module mul (
assign Aprime = {1'b0, ForwardedSrcAE[`XLEN-2:0]}; assign Aprime = {1'b0, ForwardedSrcAE[`XLEN-2:0]};
assign Bprime = {1'b0, ForwardedSrcBE[`XLEN-2:0]}; assign Bprime = {1'b0, ForwardedSrcBE[`XLEN-2:0]};
redundantmul #(`XLEN) bigmul(.a(Aprime), .b(Bprime), .out0(PP0E), .out1(PP1E)); assign PP1E = Aprime * Bprime;
assign PA = {(`XLEN-1){ForwardedSrcAE[`XLEN-1]}} & ForwardedSrcBE[`XLEN-2:0]; assign PA = {(`XLEN-1){ForwardedSrcAE[`XLEN-1]}} & ForwardedSrcBE[`XLEN-2:0];
assign PB = {(`XLEN-1){ForwardedSrcBE[`XLEN-1]}} & ForwardedSrcAE[`XLEN-2:0]; assign PB = {(`XLEN-1){ForwardedSrcBE[`XLEN-1]}} & ForwardedSrcAE[`XLEN-2:0];
assign PP = ForwardedSrcAE[`XLEN-1] & ForwardedSrcBE[`XLEN-1]; assign PP = ForwardedSrcAE[`XLEN-1] & ForwardedSrcBE[`XLEN-1];
@ -83,12 +83,11 @@ module mul (
// Memory Stage: Sum partial proudcts // Memory Stage: Sum partial proudcts
////////////////////////////// //////////////////////////////
flopenrc #(`XLEN*2) PP0Reg(clk, reset, FlushM, ~StallM, PP0E, PP0M);
flopenrc #(`XLEN*2) PP1Reg(clk, reset, FlushM, ~StallM, PP1E, PP1M); flopenrc #(`XLEN*2) PP1Reg(clk, reset, FlushM, ~StallM, PP1E, PP1M);
flopenrc #(`XLEN*2) PP2Reg(clk, reset, FlushM, ~StallM, PP2E, PP2M); flopenrc #(`XLEN*2) PP2Reg(clk, reset, FlushM, ~StallM, PP2E, PP2M);
flopenrc #(`XLEN*2) PP3Reg(clk, reset, FlushM, ~StallM, PP3E, PP3M); flopenrc #(`XLEN*2) PP3Reg(clk, reset, FlushM, ~StallM, PP3E, PP3M);
flopenrc #(`XLEN*2) PP4Reg(clk, reset, FlushM, ~StallM, PP4E, PP4M); flopenrc #(`XLEN*2) PP4Reg(clk, reset, FlushM, ~StallM, PP4E, PP4M);
assign ProdM = PP0M + PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE; assign ProdM = PP1M + PP2M + PP3M + PP4M; //ForwardedSrcAE * ForwardedSrcBE;
endmodule endmodule

View File

@ -74,13 +74,11 @@ module muldiv (
// Handle sign extension for W-type instructions // Handle sign extension for W-type instructions
flopenrc #(1) W64MReg(clk, reset, FlushM, ~StallM, W64E, W64M); flopenrc #(1) W64MReg(clk, reset, FlushM, ~StallM, W64E, W64M);
generate if (`XLEN == 64) begin:resmux // RV64 has W-type instructions
if (`XLEN == 64) begin:resmux // RV64 has W-type instructions assign MulDivResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM;
assign MulDivResultM = W64M ? {{32{PrelimResultM[31]}}, PrelimResultM[31:0]} : PrelimResultM; end else begin:resmux // RV32 has no W-type instructions
end else begin:resmux // RV32 has no W-type instructions assign MulDivResultM = PrelimResultM;
assign MulDivResultM = PrelimResultM; end
end
endgenerate
// Writeback stage pipeline register // Writeback stage pipeline register
flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW); flopenrc #(`XLEN) MulDivResultWReg(clk, reset, FlushW, ~StallW, MulDivResultM, MulDivResultW);

View File

@ -56,111 +56,109 @@ module csrc #(parameter
output logic IllegalCSRCAccessM output logic IllegalCSRCAccessM
); );
generate if (`ZICOUNTERS_SUPPORTED) begin:counters
if (`ZICOUNTERS_SUPPORTED) begin:counters (* mark_debug = "true" *) logic [63:0] CYCLE_REGW, INSTRET_REGW;
(* mark_debug = "true" *) logic [63:0] CYCLE_REGW, INSTRET_REGW; logic [63:0] CYCLEPlusM, INSTRETPlusM;
logic [63:0] CYCLEPlusM, INSTRETPlusM; logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM;
logic [`XLEN-1:0] NextCYCLEM, NextINSTRETM; logic WriteCYCLEM, WriteINSTRETM;
logic WriteCYCLEM, WriteINSTRETM; logic [4:0] CounterNumM;
logic [4:0] CounterNumM; logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0];
logic [`XLEN-1:0] HPMCOUNTER_REGW[`COUNTERS-1:0]; logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0];
logic [`XLEN-1:0] HPMCOUNTERH_REGW[`COUNTERS-1:0]; logic InstrValidNotFlushedM;
logic InstrValidNotFlushedM; logic LoadStallE, LoadStallM;
logic LoadStallE, LoadStallM; logic [`COUNTERS-1:0] WriteHPMCOUNTERM;
logic [`COUNTERS-1:0] WriteHPMCOUNTERM; logic [`COUNTERS-1:0] CounterEvent;
logic [`COUNTERS-1:0] CounterEvent; logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0];
logic [63:0] HPMCOUNTERPlusM[`COUNTERS-1:0]; logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0];
logic [`XLEN-1:0] NextHPMCOUNTERM[`COUNTERS-1:0]; genvar i;
genvar i;
// Interface signals // Interface signals
flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall. flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall.
flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM)); flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM));
assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW; assign InstrValidNotFlushedM = InstrValidM & ~StallW & ~FlushW;
// Determine when to increment each counter // Determine when to increment each counter
assign CounterEvent[0] = 1'b1; // MCYCLE always increments assign CounterEvent[0] = 1'b1; // MCYCLE always increments
assign CounterEvent[1] = 1'b0; // Counter 0 doesn't exist assign CounterEvent[1] = 1'b0; // Counter 0 doesn't exist
assign CounterEvent[2] = InstrValidNotFlushedM; assign CounterEvent[2] = InstrValidNotFlushedM;
if(`QEMU) begin // No other performance counters in QEMU if(`QEMU) begin: cevent // No other performance counters in QEMU
assign CounterEvent[`COUNTERS-1:3] = 0; assign CounterEvent[`COUNTERS-1:3] = 0;
end else begin // User-defined counters end else begin: cevent // User-defined counters
assign CounterEvent[3] = LoadStallM; // don't want to suppress on flush as this only happens if flushed. assign CounterEvent[3] = LoadStallM; // don't want to suppress on flush as this only happens if flushed.
assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM; assign CounterEvent[4] = BPPredDirWrongM & InstrValidNotFlushedM;
assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM; assign CounterEvent[5] = InstrClassM[0] & InstrValidNotFlushedM;
assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM; assign CounterEvent[6] = BTBPredPCWrongM & InstrValidNotFlushedM;
assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM; assign CounterEvent[7] = (InstrClassM[4] | InstrClassM[2] | InstrClassM[1]) & InstrValidNotFlushedM;
assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM; assign CounterEvent[8] = RASPredPCWrongM & InstrValidNotFlushedM;
assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM; assign CounterEvent[9] = InstrClassM[3] & InstrValidNotFlushedM;
assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM; assign CounterEvent[10] = BPPredClassNonCFIWrongM & InstrValidNotFlushedM;
assign CounterEvent[11] = DCacheAccess; assign CounterEvent[11] = DCacheAccess;
assign CounterEvent[12] = DCacheMiss; assign CounterEvent[12] = DCacheMiss;
assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions assign CounterEvent[`COUNTERS-1:13] = 0; // eventually give these sources, including FP instructions, I$/D$ misses, branches and mispredictions
end
// Counter update and write logic
for (i = 0; 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_ff @(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 HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
if (`XLEN==32) begin // write high and low separately
logic [`COUNTERS-1:0] WriteHPMCOUNTERHM;
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:0];
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_ff @(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 HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
end else begin // XLEN=64; write entire register
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
end
end
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
always_comb
if (PrivilegeModeW == `M_MODE |
MCOUNTEREN_REGW[CounterNumM] & (!`S_SUPPORTED | PrivilegeModeW == `S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin
IllegalCSRCAccessM = 0;
if (`XLEN==64) begin // 64-bit counter reads
// Veri lator doesn't realize this only occurs for XLEN=64
/* verilator lint_off WIDTH */
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT
/* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
end
end else begin // 32-bit counter reads
// Veri lator doesn't realize this only occurs for XLEN=32
/* verilator lint_off WIDTH */
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT
else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32];
/* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
end
end
end else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // no privileges for this csr
end
end else begin
assign CSRCReadValM = 0;
assign IllegalCSRCAccessM = 1; // counters aren't enabled
end end
endgenerate
// Counter update and write logic
for (i = 0; i < `COUNTERS; i = i+1) begin:cntr
assign WriteHPMCOUNTERM[i] = CSRMWriteM & (CSRAdrM == MHPMCOUNTERBASE + i);
assign NextHPMCOUNTERM[i][`XLEN-1:0] = WriteHPMCOUNTERM[i] ? CSRWriteValM : HPMCOUNTERPlusM[i][`XLEN-1:0];
always_ff @(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 HPMCOUNTER_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERM[i];
if (`XLEN==32) begin // write high and low separately
logic [`COUNTERS-1:0] WriteHPMCOUNTERHM;
logic [`XLEN-1:0] NextHPMCOUNTERHM[`COUNTERS-1:0];
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_ff @(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 HPMCOUNTERH_REGW[i][`XLEN-1:0] <= #1 NextHPMCOUNTERHM[i];
end else begin // XLEN=64; write entire register
assign HPMCOUNTERPlusM[i] = HPMCOUNTER_REGW[i] + {63'b0, CounterEvent[i] & ~MCOUNTINHIBIT_REGW[i]};
end
end
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
always_comb
if (PrivilegeModeW == `M_MODE |
MCOUNTEREN_REGW[CounterNumM] & (!`S_SUPPORTED | PrivilegeModeW == `S_MODE | SCOUNTEREN_REGW[CounterNumM])) begin
IllegalCSRCAccessM = 0;
if (`XLEN==64) begin // 64-bit counter reads
// Veri lator doesn't realize this only occurs for XLEN=64
/* verilator lint_off WIDTH */
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT
/* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
end
end else begin // 32-bit counter reads
// Veri lator doesn't realize this only occurs for XLEN=32
/* verilator lint_off WIDTH */
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT
else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32];
/* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // requested CSR doesn't exist
end
end
end else begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // no privileges for this csr
end
end else begin
assign CSRCReadValM = 0;
assign IllegalCSRCAccessM = 1; // counters aren't enabled
end
endmodule endmodule
// To Do: // To Do:

View File

@ -66,58 +66,54 @@ module csri #(parameter
assign WriteSIPM = CSRSWriteM & (CSRAdrM == SIP) & ~StallW; assign WriteSIPM = CSRSWriteM & (CSRAdrM == SIP) & ~StallW;
assign WriteSIEM = CSRSWriteM & (CSRAdrM == SIE) & ~StallW; assign WriteSIEM = CSRSWriteM & (CSRAdrM == SIE) & ~StallW;
// Interrupt Pending and Enable Registers // Interrupt Pending and Enable Registers
// MEIP, MTIP, MSIP are read-only // MEIP, MTIP, MSIP are read-only
// SEIP, STIP, SSIP is writable in MIP if S mode exists // SEIP, STIP, SSIP is writable in MIP if S mode exists
// SSIP is writable in SIP if S mode exists // SSIP is writable in SIP if S mode exists
generate if (`S_SUPPORTED) begin:mask
if (`S_SUPPORTED) begin:mask assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writable in MIP (20210108-draft 3.1.9)
assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writable in MIP (20210108-draft 3.1.9) assign SIP_WRITE_MASK = 12'h002; // SSIP is writable in SIP (privileged 20210108-draft 4.1.3)
assign SIP_WRITE_MASK = 12'h002; // SSIP is writable in SIP (privileged 20210108-draft 4.1.3) end else begin:mask
end else begin:mask assign MIP_WRITE_MASK = 12'h000;
assign MIP_WRITE_MASK = 12'h000; 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) IP_REGW_writeable <= 10'b0;
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 (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
always @(posedge clk) //, posedge reset) begin always @(posedge clk) //, posedge reset) begin
if (reset) IE_REGW <= 12'b0; if (reset) IE_REGW <= 12'b0;
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
endgenerate
// restricted views of registers // restricted views of registers
generate always_comb begin:regs
always_comb begin:regs // Add MEIP read-only signal
// Add MEIP read-only signal IP_REGW = {IntInM[11],1'b0,IP_REGW_writeable};
IP_REGW = {IntInM[11],1'b0,IP_REGW_writeable};
// Machine Mode // Machine Mode
MIP_REGW = IP_REGW; MIP_REGW = IP_REGW;
MIE_REGW = IE_REGW; MIE_REGW = IE_REGW;
// Supervisor mode // Supervisor mode
if (`S_SUPPORTED) begin if (`S_SUPPORTED) begin
SIP_REGW = IP_REGW & MIDELEG_REGW[11:0] & 'h222; // only delegated interrupts visible SIP_REGW = IP_REGW & MIDELEG_REGW[11:0] & 'h222; // only delegated interrupts visible
SIE_REGW = IE_REGW & MIDELEG_REGW[11:0] & 'h222; SIE_REGW = IE_REGW & MIDELEG_REGW[11:0] & 'h222;
end else begin end else begin
SIP_REGW = 12'b0; SIP_REGW = 12'b0;
SIE_REGW = 12'b0; SIE_REGW = 12'b0;
end
// User Modes iterrupts depricated
/*if (`U_SUPPORTED & `N_SUPPORTED) begin
UIP_REGW = IP_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
UIE_REGW = IE_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
end else begin
UIP_REGW = 12'b0;
UIE_REGW = 12'b0;
end */
end end
endgenerate
// User Modes iterrupts depricated
/*if (`U_SUPPORTED & `N_SUPPORTED) begin
UIP_REGW = IP_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
UIE_REGW = IE_REGW & MIDELEG_REGW & SIDELEG_REGW & 'h111; // only delegated interrupts visible
end else begin
UIP_REGW = 12'b0;
UIE_REGW = 12'b0;
end */
end
endmodule endmodule

View File

@ -92,32 +92,30 @@ module csrm #(parameter
// 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
genvar i; genvar i;
generate if (`PMP_ENTRIES > 0) begin:pmp
if (`PMP_ENTRIES > 0) begin:pmp 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; for(i=0; i<`PMP_ENTRIES; i++) begin
for(i=0; i<`PMP_ENTRIES; i++) begin // when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR
// when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR // also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR
// also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7];
assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7]; if (i == `PMP_ENTRIES-1)
if (i == `PMP_ENTRIES-1) assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7];
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7]; else
else 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]); 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]); 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];
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]); flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]);
end
end end
end end
endgenerate end
localparam MISA_26 = (`MISA) & 32'h03ffffff; localparam MISA_26 = (`MISA) & 32'h03ffffff;
@ -143,28 +141,24 @@ module csrm #(parameter
// CSRs // CSRs
flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); //busybear: changed reset value to 0 flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); //busybear: changed reset value to 0
generate if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin:deleg // DELEG registers should exist
if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin:deleg // DELEG registers should exist flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, MEDELEG_REGW);
flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK /*12'h7FF*/, MEDELEG_REGW); flopenr #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, MIDELEG_REGW);
flopenr #(`XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK /*12'h222*/, 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
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW); flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW);
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW); flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_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 // *** needs comment about bit 1 if (`BUSYBEAR == 1) begin:counters // counter 1 (TIME) enable tied to 0 to match simulator***
if (`BUSYBEAR == 1) begin:counters
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, MCOUNTEREN_REGW); flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, MCOUNTEREN_REGW);
end else begin:counters end else begin:counters
flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW); flopenr #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], MCOUNTEREN_REGW);
end end
endgenerate
flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW); flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW);

View File

@ -49,52 +49,50 @@ module csrn #(parameter
); );
// User mode CSRs below only needed when user mode traps are supported // User mode CSRs below only needed when user mode traps are supported
generate if (`N_SUPPORTED) begin:nmode // depricated; consider removing***
if (`N_SUPPORTED) begin:nmode logic WriteUTVECM;
logic WriteUTVECM; logic WriteUSCRATCHM, WriteUEPCM;
logic WriteUSCRATCHM, WriteUEPCM; logic WriteUCAUSEM, WriteUTVALM;
logic WriteUCAUSEM, WriteUTVALM; logic [`XLEN-1:0] UEDELEG_REGW, UIDELEG_REGW;
logic [`XLEN-1:0] UEDELEG_REGW, UIDELEG_REGW; logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW;
logic [`XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW;
// Write enables // Write enables
assign WriteUSTATUSM = CSRNWriteM & (CSRAdrM == USTATUS) & ~StallW; assign WriteUSTATUSM = CSRNWriteM & (CSRAdrM == USTATUS) & ~StallW;
assign WriteUTVECM = CSRNWriteM & (CSRAdrM == UTVEC) & ~StallW; assign WriteUTVECM = CSRNWriteM & (CSRAdrM == UTVEC) & ~StallW;
assign WriteUEPCM = UTrapM | (CSRNWriteM & (CSRAdrM == UEPC)) & ~StallW; assign WriteUEPCM = UTrapM | (CSRNWriteM & (CSRAdrM == UEPC)) & ~StallW;
assign WriteUCAUSEM = UTrapM | (CSRNWriteM & (CSRAdrM == UCAUSE)) & ~StallW; assign WriteUCAUSEM = UTrapM | (CSRNWriteM & (CSRAdrM == UCAUSE)) & ~StallW;
assign WriteUTVALM = UTrapM | (CSRNWriteM & (CSRAdrM == UTVAL)) & ~StallW; assign WriteUTVALM = UTrapM | (CSRNWriteM & (CSRAdrM == UTVAL)) & ~StallW;
// CSRs // CSRs
flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `RESET_VECTOR, UTVEC_REGW); flopenl #(`XLEN) UTVECreg(clk, reset, WriteUTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, `RESET_VECTOR, UTVEC_REGW);
flopenr #(`XLEN) USCRATCHreg(clk, reset, WriteUSCRATCHM, CSRWriteValM, USCRATCH_REGW); flopenr #(`XLEN) USCRATCHreg(clk, reset, WriteUSCRATCHM, CSRWriteValM, USCRATCH_REGW);
flopenr #(`XLEN) UEPCreg(clk, reset, WriteUEPCM, NextEPCM, UEPC_REGW); flopenr #(`XLEN) UEPCreg(clk, reset, WriteUEPCM, NextEPCM, UEPC_REGW);
flopenr #(`XLEN) UCAUSEreg(clk, reset, WriteUCAUSEM, NextCauseM, UCAUSE_REGW); flopenr #(`XLEN) UCAUSEreg(clk, reset, WriteUCAUSEM, NextCauseM, UCAUSE_REGW);
flopenr #(`XLEN) UTVALreg(clk, reset, WriteUTVALM, NextMtvalM, UTVAL_REGW); flopenr #(`XLEN) UTVALreg(clk, reset, WriteUTVALM, NextMtvalM, UTVAL_REGW);
// CSR Reads // CSR Reads
always_comb begin always_comb begin
IllegalCSRNAccessM = 0; IllegalCSRNAccessM = 0;
case (CSRAdrM) case (CSRAdrM)
USTATUS: CSRNReadValM = USTATUS_REGW; USTATUS: CSRNReadValM = USTATUS_REGW;
UTVEC: CSRNReadValM = UTVEC_REGW; UTVEC: CSRNReadValM = UTVEC_REGW;
UIP: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIP_REGW}; UIP: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIP_REGW};
UIE: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIE_REGW}; UIE: CSRNReadValM = {{(`XLEN-12){1'b0}}, UIE_REGW};
USCRATCH: CSRNReadValM = USCRATCH_REGW; USCRATCH: CSRNReadValM = USCRATCH_REGW;
UEPC: CSRNReadValM = UEPC_REGW; UEPC: CSRNReadValM = UEPC_REGW;
UCAUSE: CSRNReadValM = UCAUSE_REGW; UCAUSE: CSRNReadValM = UCAUSE_REGW;
UTVAL: CSRNReadValM = UTVAL_REGW; UTVAL: CSRNReadValM = UTVAL_REGW;
default: begin default: begin
CSRNReadValM = 0; CSRNReadValM = 0;
IllegalCSRNAccessM = 1; IllegalCSRNAccessM = 1;
end end
endcase endcase
end
end else begin // if not supported
assign WriteUSTATUSM = 0;
assign CSRNReadValM = 0;
assign UEPC_REGW = 0;
assign UTVEC_REGW = 0;
assign IllegalCSRNAccessM = 1;
end end
endgenerate end else begin // if not supported
endmodule assign WriteUSTATUSM = 0;
assign CSRNReadValM = 0;
assign UEPC_REGW = 0;
assign UTVEC_REGW = 0;
assign IllegalCSRNAccessM = 1;
end
endmodule

View File

@ -69,89 +69,87 @@ module csrs #(parameter
//logic [`XLEN-1:0] SEDELEG_MASK = ~(zero | 3'b111 << 9); // sedeleg[11:9] hardwired to zero per Privileged Spec 3.1.8 //logic [`XLEN-1:0] SEDELEG_MASK = ~(zero | 3'b111 << 9); // sedeleg[11:9] hardwired to zero per Privileged Spec 3.1.8
// Supervisor mode CSRs sometimes supported // Supervisor mode CSRs sometimes supported
generate if (`S_SUPPORTED) begin:csrs
if (`S_SUPPORTED) begin:csrs logic WriteSTVECM;
logic WriteSTVECM; logic WriteSSCRATCHM, WriteSEPCM;
logic WriteSSCRATCHM, WriteSEPCM; logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW;
logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW; (* mark_debug = "true" *) logic [`XLEN-1:0] SCAUSE_REGW;
(* mark_debug = "true" *) logic [`XLEN-1:0] SCAUSE_REGW;
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & ~StallW; assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & ~StallW;
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & ~StallW; assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & ~StallW;
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & ~StallW; assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & ~StallW;
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)) & ~StallW; assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)) & ~StallW;
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)) & ~StallW; assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)) & ~StallW;
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & ~StallW; assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & ~StallW;
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & ~StallW; assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & ~StallW;
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & ~StallW; assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & ~StallW;
// CSRs // CSRs
flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); //busybear: change reset to 0 flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); //busybear: change reset to 0
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW); flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW); flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW);
flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW); flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
if (`MEM_VIRTMEM) if (`MEM_VIRTMEM)
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW); 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) begin:scounteren if (`BUSYBEAR == 1) begin:scounteren
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, SCOUNTEREN_REGW); flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, {CSRWriteValM[31:2],1'b0,CSRWriteValM[0]}, SCOUNTEREN_REGW);
end else if (`BUILDROOT == 1) begin:scounteren end else if (`BUILDROOT == 1) begin:scounteren
flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW); flopenr #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
end else begin:scounteren end else begin:scounteren
flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW); flopens #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], SCOUNTEREN_REGW);
end end
if (`N_SUPPORTED) begin:nregs if (`N_SUPPORTED) begin:nregs
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);
flopenr #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, SEDELEG_REGW); flopenr #(`XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, SEDELEG_REGW);
flopenr #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, SIDELEG_REGW); flopenr #(`XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, SIDELEG_REGW);
end else begin
assign SEDELEG_REGW = 0;
assign SIDELEG_REGW = 0;
end
// CSR Reads
always_comb begin:csrr
IllegalCSRSAccessM = !(`N_SUPPORTED) & (CSRAdrM == SEDELEG | CSRAdrM == SIDELEG); // trap on DELEG register access when no N-mode
case (CSRAdrM)
SSTATUS: CSRSReadValM = SSTATUS_REGW;
STVEC: CSRSReadValM = STVEC_REGW;
// SIDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIDELEG_REGW};
// SEDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SEDELEG_REGW};
SIDELEG: CSRSReadValM = SIDELEG_REGW;
SEDELEG: CSRSReadValM = SEDELEG_REGW;
SIP: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIP_REGW};
SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIE_REGW};
SSCRATCH: CSRSReadValM = SSCRATCH_REGW;
SEPC: CSRSReadValM = SEPC_REGW;
SCAUSE: CSRSReadValM = SCAUSE_REGW;
STVAL: CSRSReadValM = STVAL_REGW;
SATP: if (`MEM_VIRTMEM & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW;
else begin
CSRSReadValM = 0;
if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1;
end
SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW};
default: begin
CSRSReadValM = 0;
IllegalCSRSAccessM = 1;
end
endcase
end
end else begin end else begin
assign WriteSSTATUSM = 0;
assign CSRSReadValM = 0;
assign SEPC_REGW = 0;
assign STVEC_REGW = 0;
assign SEDELEG_REGW = 0; assign SEDELEG_REGW = 0;
assign SIDELEG_REGW = 0; assign SIDELEG_REGW = 0;
assign SCOUNTEREN_REGW = 0;
assign SATP_REGW = 0;
assign IllegalCSRSAccessM = 1;
end end
endgenerate
// CSR Reads
always_comb begin:csrr
IllegalCSRSAccessM = !(`N_SUPPORTED) & (CSRAdrM == SEDELEG | CSRAdrM == SIDELEG); // trap on DELEG register access when no N-mode
case (CSRAdrM)
SSTATUS: CSRSReadValM = SSTATUS_REGW;
STVEC: CSRSReadValM = STVEC_REGW;
// SIDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIDELEG_REGW};
// SEDELEG: CSRSReadValM = {{(`XLEN-12){1'b0}}, SEDELEG_REGW};
SIDELEG: CSRSReadValM = SIDELEG_REGW;
SEDELEG: CSRSReadValM = SEDELEG_REGW;
SIP: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIP_REGW};
SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, SIE_REGW};
SSCRATCH: CSRSReadValM = SSCRATCH_REGW;
SEPC: CSRSReadValM = SEPC_REGW;
SCAUSE: CSRSReadValM = SCAUSE_REGW;
STVAL: CSRSReadValM = STVAL_REGW;
SATP: if (`MEM_VIRTMEM & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW;
else begin
CSRSReadValM = 0;
if (PrivilegeModeW == `S_MODE & STATUS_TVM) IllegalCSRSAccessM = 1;
end
SCOUNTEREN:CSRSReadValM = {{(`XLEN-32){1'b0}}, SCOUNTEREN_REGW};
default: begin
CSRSReadValM = 0;
IllegalCSRSAccessM = 1;
end
endcase
end
end else begin
assign WriteSSTATUSM = 0;
assign CSRSReadValM = 0;
assign SEPC_REGW = 0;
assign STVEC_REGW = 0;
assign SEDELEG_REGW = 0;
assign SIDELEG_REGW = 0;
assign SCOUNTEREN_REGW = 0;
assign SATP_REGW = 0;
assign IllegalCSRSAccessM = 1;
end
endmodule endmodule

View File

@ -50,54 +50,50 @@ module csrsr (
// 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
// *** consider adding MBE, SBE, UBE fields later from 20210108 draft spec // *** consider adding MBE, SBE, UBE fields later from 20210108 draft spec
generate if (`XLEN==64) begin: csrsr64 // RV64
if (`XLEN==64) begin: csrsr64 // RV64 assign MSTATUS_REGW = {STATUS_SD, 27'b0, STATUS_SXL, STATUS_UXL, 9'b0,
assign MSTATUS_REGW = {STATUS_SD, 27'b0, STATUS_SXL, STATUS_UXL, 9'b0, STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0, STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE,
STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE, STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE};
STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE}; assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ STATUS_UXL, /*9'b0, */ 12'b0,
assign SSTATUS_REGW = {STATUS_SD, /*27'b0, */ 29'b0, /*STATUS_SXL, */ STATUS_UXL, /*9'b0, */ 12'b0, /*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0, STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE, /*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE}; assign USTATUS_REGW = {/*STATUS_SD, */ 59'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */
assign USTATUS_REGW = {/*STATUS_SD, */ 59'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */ /*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/
/*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/ /* STATUS_XS, STATUS_FS, /*STATUS_MPP, 8'b0, */
/* STATUS_XS, STATUS_FS, /*STATUS_MPP, 8'b0, */ /*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE, /*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE}; end else begin: csrsr32 // RV32
end else begin: csrsr32 // RV32 assign MSTATUS_REGW = {STATUS_SD, 8'b0,
assign MSTATUS_REGW = {STATUS_SD, 8'b0, STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0,
STATUS_XS, STATUS_FS, STATUS_MPP, 2'b0, STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE, STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE};
STATUS_SPP, STATUS_MPIE, 1'b0, STATUS_SPIE, STATUS_UPIE, STATUS_MIE, 1'b0, STATUS_SIE, STATUS_UIE}; assign SSTATUS_REGW = {STATUS_SD, 11'b0,
assign SSTATUS_REGW = {STATUS_SD, 11'b0, /*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0,
/*STATUS_TSR, STATUS_TW, STATUS_TVM, */STATUS_MXR, STATUS_SUM, /* STATUS_MPRV, */ 1'b0, STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
STATUS_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0, STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE, /*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE}; assign USTATUS_REGW = {/*STATUS_SD, */ 27'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */
assign USTATUS_REGW = {/*STATUS_SD, */ 27'b0, /*STATUS_SXL, STATUS_UXL, 9'b0, */ /*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/
/*STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV, , 1'b0,*/ /*STATUS_XS, STATUS_FS, STATUS_MPP, 8'b0, */
/*STATUS_XS, STATUS_FS, STATUS_MPP, 8'b0, */ /*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE, /*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE}; end
end
endgenerate
// harwired STATUS bits // harwired STATUS bits
generate assign STATUS_TSR = `S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_TSR = `S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported assign STATUS_TW = (`S_SUPPORTED | `U_SUPPORTED) & STATUS_TW_INT; // override reigster with 0 if only machine mode supported
assign STATUS_TW = (`S_SUPPORTED | `U_SUPPORTED) & STATUS_TW_INT; // override reigster with 0 if only machine mode supported assign STATUS_TVM = `S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_TVM = `S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported assign STATUS_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_MXR = `S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported // SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not assign STATUS_SXL = `S_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if supervisor mode supported
assign STATUS_SXL = `S_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if supervisor mode supported assign STATUS_UXL = `U_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if user mode supported
assign STATUS_UXL = `U_SUPPORTED & ~`QEMU ? 2'b10 : 2'b00; // 10 if user mode supported assign STATUS_SUM = `S_SUPPORTED & `MEM_VIRTMEM & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
assign STATUS_SUM = `S_SUPPORTED & `MEM_VIRTMEM & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported assign STATUS_MPRV = `U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
assign STATUS_MPRV = `U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported assign STATUS_FS = (`S_SUPPORTED & (`F_SUPPORTED | `D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
assign STATUS_FS = (`S_SUPPORTED & (`F_SUPPORTED | `D_SUPPORTED)) ? STATUS_FS_INT : 2'b00; // off if no FP
endgenerate
assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic
assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty

View File

@ -44,42 +44,40 @@ module csru #(parameter
); );
// Floating Point CSRs in User Mode only needed if Floating Point is supported // Floating Point CSRs in User Mode only needed if Floating Point is supported
generate if (`F_SUPPORTED | `D_SUPPORTED) begin:csru
if (`F_SUPPORTED | `D_SUPPORTED) begin:csru logic [4:0] FFLAGS_REGW;
logic [4:0] FFLAGS_REGW; logic [2:0] NextFRMM;
logic [2:0] NextFRMM; logic [4:0] NextFFLAGSM;
logic [4:0] NextFFLAGSM;
// Write enables // Write enables
//assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & ~StallW; //assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & ~StallW;
assign WriteFRMM = (CSRUWriteM & (CSRAdrM == FRM | CSRAdrM == FCSR)) & ~StallW; assign WriteFRMM = (CSRUWriteM & (CSRAdrM == FRM | CSRAdrM == FCSR)) & ~StallW;
assign WriteFFLAGSM = (CSRUWriteM & (CSRAdrM == FFLAGS | CSRAdrM == FCSR)) & ~StallW; assign WriteFFLAGSM = (CSRUWriteM & (CSRAdrM == FFLAGS | CSRAdrM == FCSR)) & ~StallW;
// Write Values // Write Values
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0]; assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM; assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
// CSRs // CSRs
flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW); flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW);
flopr #(5) FFLAGSreg(clk, reset, NextFFLAGSM, FFLAGS_REGW); flopr #(5) FFLAGSreg(clk, reset, NextFFLAGSM, FFLAGS_REGW);
// CSR Reads // CSR Reads
always_comb begin always_comb begin
IllegalCSRUAccessM = 0; IllegalCSRUAccessM = 0;
case (CSRAdrM) case (CSRAdrM)
FFLAGS: CSRUReadValM = {{(`XLEN-5){1'b0}}, FFLAGS_REGW}; FFLAGS: CSRUReadValM = {{(`XLEN-5){1'b0}}, FFLAGS_REGW};
FRM: CSRUReadValM = {{(`XLEN-3){1'b0}}, FRM_REGW}; FRM: CSRUReadValM = {{(`XLEN-3){1'b0}}, FRM_REGW};
FCSR: CSRUReadValM = {{(`XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW}; FCSR: CSRUReadValM = {{(`XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW};
default: begin default: begin
CSRUReadValM = 0; CSRUReadValM = 0;
IllegalCSRUAccessM = 1; IllegalCSRUAccessM = 1;
end end
endcase endcase
end
end else begin // if not supported
assign FRM_REGW = 0;
assign CSRUReadValM = 0;
assign IllegalCSRUAccessM = 1;
end end
endgenerate end else begin // if not supported
assign FRM_REGW = 0;
assign CSRUReadValM = 0;
assign IllegalCSRUAccessM = 1;
end
endmodule endmodule

View File

@ -103,18 +103,16 @@ module trap (
// > implemented without a hardware adder circuit. // > implemented without a hardware adder circuit.
// For example, we could require m/stvec be aligned on 7 bits to let us replace the adder directly below with // For example, we could require m/stvec be aligned on 7 bits to let us replace the adder directly below with
// [untested] PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:7], CauseM[3:0], 4'b0000} // [untested] PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:7], CauseM[3:0], 4'b0000}
generate if(`VECTORED_INTERRUPTS_SUPPORTED) begin:vec
if(`VECTORED_INTERRUPTS_SUPPORTED) begin:vec always_comb
always_comb if (PrivilegedTrapVector[1:0] == 2'b01 & CauseM[`XLEN-1] == 1)
if (PrivilegedTrapVector[1:0] == 2'b01 & CauseM[`XLEN-1] == 1) PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2] + {CauseM[`XLEN-5:0], 2'b00}, 2'b00};
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2] + {CauseM[`XLEN-5:0], 2'b00}, 2'b00}; else
else PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00}; end
end else begin
else begin assign PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00};
assign PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00}; end
end
endgenerate
always_comb always_comb
if (mretM) PrivilegedNextPCM = MEPC_REGW; if (mretM) PrivilegedNextPCM = MEPC_REGW;

View File

@ -55,12 +55,8 @@ module clint (
assign HREADYCLINT = 1'b1; // *** needs to depend on DONE during accesses assign HREADYCLINT = 1'b1; // *** needs to depend on DONE during accesses
// word aligned reads // word aligned reads
generate if (`XLEN==64) assign #2 entry = {HADDR[15:3], 3'b000};
if (`XLEN==64) else assign #2 entry = {HADDR[15:2], 2'b00};
assign #2 entry = {HADDR[15:3], 3'b000};
else
assign #2 entry = {HADDR[15:2], 2'b00};
endgenerate
// DH 2/20/21: Eventually allow MTIME to run off a separate clock // DH 2/20/21: Eventually allow MTIME to run off a separate clock
// This will require synchronizing MTIME to the system clock // This will require synchronizing MTIME to the system clock
@ -69,74 +65,72 @@ module clint (
// Use req and ack signals synchronized across the clock domains. // Use req and ack signals synchronized across the clock domains.
// register access // register access
generate if (`XLEN==64) begin:clint // 64-bit
if (`XLEN==64) begin:clint // 64-bit always @(posedge HCLK) begin
always @(posedge HCLK) begin case(entry)
case(entry) 16'h0000: HREADCLINT <= {63'b0, MSIP};
16'h0000: HREADCLINT <= {63'b0, MSIP}; 16'h4000: HREADCLINT <= MTIMECMP;
16'h4000: HREADCLINT <= MTIMECMP; 16'hBFF8: HREADCLINT <= MTIME;
16'hBFF8: HREADCLINT <= MTIME; default: HREADCLINT <= 0;
default: HREADCLINT <= 0; endcase
endcase end
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MSIP <= 0;
MTIMECMP <= 0;
// MTIMECMP is not reset
end else if (memwrite) begin
if (entryd == 16'h0000) MSIP <= HWDATA[0];
if (entryd == 16'h4000) MTIMECMP <= HWDATA;
end end
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MSIP <= 0;
MTIMECMP <= 0;
// MTIMECMP is not reset
end else if (memwrite) begin
if (entryd == 16'h0000) MSIP <= HWDATA[0];
if (entryd == 16'h4000) MTIMECMP <= HWDATA;
end
// eventually replace MTIME logic below with timereg
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), 1'b0, HWDATA, MTIME, done);
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MTIME <= 0;
// MTIMECMP is not reset
end else if (memwrite & entryd == 16'hBFF8) begin
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
MTIME <= HWDATA;
end else MTIME <= MTIME + 1;
end else begin:clint // 32-bit
always @(posedge HCLK) begin
case(entry)
16'h0000: HREADCLINT <= {31'b0, MSIP};
16'h4000: HREADCLINT <= MTIMECMP[31:0];
16'h4004: HREADCLINT <= MTIMECMP[63:32];
16'hBFF8: HREADCLINT <= MTIME[31:0];
16'hBFFC: HREADCLINT <= MTIME[63:32];
default: HREADCLINT <= 0;
endcase
end
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MSIP <= 0;
MTIMECMP <= 0;
// MTIMECMP is not reset ***?
end else if (memwrite) begin
if (entryd == 16'h0000) MSIP <= HWDATA[0];
if (entryd == 16'h4000) MTIMECMP[31:0] <= HWDATA;
if (entryd == 16'h4004) MTIMECMP[63:32] <= HWDATA;
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
end
// eventually replace MTIME logic below with timereg // eventually replace MTIME logic below with timereg
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), memwrite & (entryd == 16'hBFFC), HWDATA, MTIME, done); // timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), 1'b0, HWDATA, MTIME, done);
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin always_ff @(posedge HCLK or negedge HRESETn)
MTIME <= 0; if (~HRESETn) begin
// MTIMECMP is not reset MTIME <= 0;
end else if (memwrite & (entryd == 16'hBFF8)) begin // MTIMECMP is not reset
MTIME[31:0] <= HWDATA; end else if (memwrite & entryd == 16'hBFF8) begin
end else if (memwrite & (entryd == 16'hBFFC)) begin // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed MTIME <= HWDATA;
MTIME[63:32]<= HWDATA; end else MTIME <= MTIME + 1;
end else MTIME <= MTIME + 1; end else begin:clint // 32-bit
always @(posedge HCLK) begin
case(entry)
16'h0000: HREADCLINT <= {31'b0, MSIP};
16'h4000: HREADCLINT <= MTIMECMP[31:0];
16'h4004: HREADCLINT <= MTIMECMP[63:32];
16'hBFF8: HREADCLINT <= MTIME[31:0];
16'hBFFC: HREADCLINT <= MTIME[63:32];
default: HREADCLINT <= 0;
endcase
end end
endgenerate always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MSIP <= 0;
MTIMECMP <= 0;
// MTIMECMP is not reset ***?
end else if (memwrite) begin
if (entryd == 16'h0000) MSIP <= HWDATA[0];
if (entryd == 16'h4000) MTIMECMP[31:0] <= HWDATA;
if (entryd == 16'h4004) MTIMECMP[63:32] <= HWDATA;
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
end
// eventually replace MTIME logic below with timereg
// timereg tr(HCLK, HRESETn, TIMECLK, memwrite & (entryd==16'hBFF8), memwrite & (entryd == 16'hBFFC), HWDATA, MTIME, done);
always_ff @(posedge HCLK or negedge HRESETn)
if (~HRESETn) begin
MTIME <= 0;
// MTIMECMP is not reset
end else if (memwrite & (entryd == 16'hBFF8)) begin
MTIME[31:0] <= HWDATA;
end else if (memwrite & (entryd == 16'hBFFC)) begin
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
MTIME[63:32]<= HWDATA;
end else MTIME <= MTIME + 1;
end
// Software interrupt when MSIP is set // Software interrupt when MSIP is set
assign SwIntM = MSIP; assign SwIntM = MSIP;
@ -234,13 +228,9 @@ module graytobinary #(parameter N = `XLEN) (
// B[N-1] = G[N-1]; B[i] = G[i] ^ B[i+1] for 0 <= i < N-1 // B[N-1] = G[N-1]; B[i] = G[i] ^ B[i+1] for 0 <= i < N-1
// requires rippling through N-1 XOR gates // requires rippling through N-1 XOR gates
generate genvar i;
begin assign b[N-1] = g[N-1];
genvar i; for (i=N-2; i >= 0; i--) begin:g2b
assign b[N-1] = g[N-1]; assign b[i] = g[i] ^ b[i+1];
for (i=N-2; i >= 0; i--) begin:g2b
assign b[i] = g[i] ^ b[i+1];
end
end end
endgenerate
endmodule endmodule

View File

@ -61,23 +61,13 @@ module gpio (
// account for subword read/write circuitry // account for subword read/write circuitry
// -- Note GPIO registers are 32 bits no matter what; access them with LW SW. // -- Note GPIO registers are 32 bits no matter what; access them with LW SW.
// (At least that's what I think when FE310 spec says "only naturally aligned 32-bit accesses are supported") // (At least that's what I think when FE310 spec says "only naturally aligned 32-bit accesses are supported")
generate if (`XLEN == 64) begin:gpio
if (`XLEN == 64) begin:gpio assign Din = entryd[2] ? HWDATA[63:32] : HWDATA[31:0];
always_comb assign HREADGPIO = entryd[2] ? {Dout,32'b0} : {32'b0,Dout};
if (entryd[2]) begin end else begin:gpio // 32-bit
Din = HWDATA[63:32]; assign Din = HWDATA[31:0];
HREADGPIO = {Dout,32'b0}; assign HREADGPIO = Dout;
end else begin end
Din = HWDATA[31:0];
HREADGPIO = {32'b0,Dout};
end
end else begin:gpio // 32-bit
always_comb begin
Din = HWDATA[31:0];
HREADGPIO = Dout;
end
end
endgenerate
// register access // register access
always_ff @(posedge HCLK, negedge HRESETn) begin always_ff @(posedge HCLK, negedge HRESETn) begin