Initial Checkin

This commit is contained in:
David Harris 2021-01-14 23:37:51 -05:00
parent a609876074
commit fd01e27a48
41 changed files with 4020 additions and 1 deletions

View File

@ -1,6 +1,7 @@
MIT License MIT License
Copyright (c) 2021 davidharrishmc Copyright (c) 2021 Harvey Mudd College & Oklahoma State University
Contact: Prof. David Harris David_Harris@hmc.edu
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

1
riscv-o3 Submodule

@ -0,0 +1 @@
Subproject commit afb27bd558a9b6fabb6b768ae81ef122b4db9eea

View File

@ -0,0 +1 @@
harris@Tera.Eng.HMC.Edu.6921:1604012407

1
wally-pipelined/sim-wally Executable file
View File

@ -0,0 +1 @@
vsim -do wally-pipelined.do

View File

@ -0,0 +1 @@
vsim -c -do wally-pipelined-batch.do

View File

@ -0,0 +1,88 @@
///////////////////////////////////////////
// alu.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: RISC-V Arithmetic/Logic Unit
//
// 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-macros.sv"
module alu #(parameter WIDTH=32) (
input logic [WIDTH-1:0] a, b,
input logic [4:0] alucontrol,
output logic [WIDTH-1:0] result,
output logic [2:0] flags);
logic [WIDTH-1:0] condinvb, presum, sum, shift, slt, sltu, bor;
logic right, arith, w64;
logic carry, zero, neg;
logic lt, ltu;
logic overflow;
// addition
assign condinvb = alucontrol[3] ? ~b : b;
assign {carry, presum} = a + condinvb + {{(WIDTH-1){1'b0}},alucontrol[3]};
// support W-type RV64I ADDW/SUBW/ADDIW that sign-extend 32-bit result to 64 bits
generate
if (WIDTH==64)
assign sum = w64 ? {{32{presum[31]}}, presum[31:0]} : presum;
else
assign sum = presum;
endgenerate
// shifts
assign arith = alucontrol[3]; // sra
assign w64 = alucontrol[4];
assign right = (alucontrol[2:0] == 3'b101); // sra or srl
shifter #(WIDTH) sh(a, b[5:0], right, arith, w64, shift);
// OR optionally passes zero when ALUControl[3] is set, supporting lui
assign bor = alucontrol[3] ? b : a|b;
// condition code flags based on add/subtract output
assign zero = (sum == 0);
assign neg = sum[WIDTH-1];
// overflow occurs when the numbers being added have the same sign
// and the result has the opposite sign
assign overflow = (a[WIDTH-1] ~^ condinvb[WIDTH-1]) & (a[WIDTH-1] ^ sum[WIDTH-1]);
assign lt = neg ^ overflow;
assign ltu = ~carry;
assign flags = {zero, lt, ltu};
// slt
assign slt = {{(WIDTH-1){1'b0}}, lt};
assign sltu = {{(WIDTH-1){1'b0}}, ltu};
always_comb
case (alucontrol[2:0])
3'b000: result = sum; // add or sub
3'b001: result = shift; // sll
3'b010: result = slt; // slt
3'b011: result = sltu; // sltu
3'b100: result = a ^ b; // xor
3'b101: result = shift; // sra or srl
3'b110: result = bor; // or / pass through input b for lui
3'b111: result = a & b; // and
endcase
endmodule

View File

@ -0,0 +1,131 @@
///////////////////////////////////////////
// clint.sv
//
// Written: David_Harris@hmc.edu 14 January 2021
// Modified:
//
// Purpose: Core-Local Interruptor
// See FE310-G002-Manual-v19p05 for specifications
//
// 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-macros.sv"
module clint #(parameter XLEN=32) (
input logic clk, reset,
input logic [1:0] MemRWM,
input logic [7:0] ByteMaskM,
input logic [15:0] AdrM,
input logic [XLEN-1:0] WdM,
output logic [XLEN-1:0] RdM,
output logic TimerIntM, SwIntM);
logic [63:0] MTIMECMP, MTIME;
logic MSIP;
logic [XLEN-1:0] read, write;
logic [15:0] entry;
logic memread, memwrite;
assign memread = MemRWM[1];
assign memwrite = MemRWM[0];
// word aligned reads
generate
if (XLEN==64)
assign #2 entry = {AdrM[15:3], 3'b000};
else
assign #2 entry = {AdrM[15:2], 2'b00};
endgenerate
// register access
generate
if (XLEN==64) begin
always_comb begin
case(entry)
16'h0000: read = {63'b0, MSIP};
16'h4000: read = MTIMECMP;
16'hBFF8: read = MTIME;
default: read = 0;
endcase
write=read;
if (ByteMaskM[0]) write[7:0] = WdM[7:0];
if (ByteMaskM[1]) write[15:8] = WdM[15:8];
if (ByteMaskM[2]) write[23:16] = WdM[23:16];
if (ByteMaskM[3]) write[31:24] = WdM[31:24];
if (ByteMaskM[4]) write[39:32] = WdM[39:32];
if (ByteMaskM[5]) write[47:40] = WdM[47:40];
if (ByteMaskM[6]) write[55:48] = WdM[55:48];
if (ByteMaskM[7]) write[63:56] = WdM[63:56];
end
always_ff @(posedge clk or posedge reset)
if (reset) begin
MSIP <= 0;
MTIME <= 0;
// MTIMECMP is not reset
end else begin
if (entry == 16'h0000) MSIP <= write[0];
if (entry == 16'h4000) MTIMECMP <= write;
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
if (entry == 16'hBFF8) MTIME <= write;
else MTIME <= MTIME + 1;
end
end else begin // 32-bit
always_comb begin
case(entry)
16'h0000: read = {31'b0, MSIP};
16'h4000: read = MTIMECMP[31:0];
16'h4004: read = MTIMECMP[63:32];
16'hBFF8: read = MTIME[31:0];
16'hBFFC: read = MTIME[63:32];
default: read = 0;
endcase
write=read;
if (ByteMaskM[0]) write[7:0] = WdM[7:0];
if (ByteMaskM[1]) write[15:8] = WdM[15:8];
if (ByteMaskM[2]) write[23:16] = WdM[23:16];
if (ByteMaskM[3]) write[31:24] = WdM[31:24];
end
always_ff @(posedge clk or posedge reset)
if (reset) begin
MSIP <= 0;
MTIME <= 0;
// MTIMECMP is not reset
end else begin
if (entry == 16'h0000) MSIP <= write[0];
if (entry == 16'h4000) MTIMECMP[31:0] <= write;
if (entry == 16'h4004) MTIMECMP[63:32] <= write;
// MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed
if (entry == 16'hBFF8) MTIME[31:0] <= write;
else if (entry == 16'hBFFC) MTIME[63:32]<= write;
else MTIME <= MTIME + 1;
end
end
endgenerate
// read
assign RdM = memread ? read: 0;
// Software interrupt when MSIP is set
assign SwIntM = MSIP;
// Timer interrupt when MTIME >= MTIMECMP
assign TimerIntM = ({1'b0, MTIME} >= {1'b0, MTIMECMP}); // unsigned comparison
endmodule

View File

@ -0,0 +1,171 @@
///////////////////////////////////////////
// controller.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Top level controller module
//
// 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-macros.sv"
module controller(
input logic clk, reset,
// Decode stage control signals
input logic [6:0] OpD,
input logic [2:0] Funct3D,
input logic Funct7b5D,
output logic [2:0] ImmSrcD,
input logic StallD, FlushD,
input logic IllegalCompInstrD,
// Execute stage control signals
input logic FlushE,
input logic [2:0] FlagsE,
output logic PCSrcE, // for datapath and Hazard Unit
output logic [4:0] ALUControlE,
output logic ALUSrcAE, ALUSrcBE,
output logic TargetSrcE,
output logic MemReadE, // for Hazard Unit
// Memory stage control signals
input logic FlushM,
output logic [1:0] MemRWM,
output logic CSRWriteM, PrivilegedM, IllegalInstrFaultM,
output logic [2:0] Funct3M,
output logic RegWriteM, // for Hazard Unit
// Writeback stage control signals
input logic FlushW,
output logic RegWriteW, // for datapath and Hazard Unit
output logic [1:0] ResultSrcW,
output logic InstrValidW,
// Stall during CSRs
output logic CSRWritePendingDEM,
// Exceptions
input logic InstrAccessFaultF,
output logic InstrAccessFaultM);
// pipelined control signals
logic RegWriteD, RegWriteE;
logic [1:0] ResultSrcD, ResultSrcE, ResultSrcM;
logic [1:0] MemRWD, MemRWE;
logic JumpD, JumpE;
logic BranchD, BranchE;
logic [1:0] ALUOpD;
logic [4:0] ALUControlD;
logic ALUSrcAD, ALUSrcBD;
logic TargetSrcD, W64D;
logic CSRWriteD, CSRWriteE;
logic [2:0] Funct3E;
logic InstrValidE, InstrValidM;
logic PrivilegedD, PrivilegedE;
logic InstrAccessFaultD, InstrAccessFaultE;
logic IllegalInstrFaultD, IllegalInstrMergedD, IllegalInstrFaultE;
logic [18:0] ControlsD;
logic PreIllegalInstrFaultD;
logic aluc3D;
logic subD, sraD, sltD, sltuD;
logic BranchTakenE;
logic zeroE, ltE, ltuE;
// Decode stage pipeline control register and logic
flopenrc #(1) controlregD(clk, reset, FlushD, ~StallD, InstrAccessFaultF, InstrAccessFaultD);
// Main Instruction Decoder
always_comb
case(OpD)
// RegWrite_ImmSrc_ALUSrc_MemRW_ResultSrc_Branch_ALUOp_Jump_TargetSrc_W64_CSRWrite_Privileged_Illegal
7'b0000011: ControlsD = 19'b1_000_01_10_01_0_00_0_0_0_0_0_0; // lw
7'b0100011: ControlsD = 19'b0_001_01_01_00_0_00_0_0_0_0_0_0; // sw
7'b0110011: ControlsD = 19'b1_000_00_00_00_0_10_0_0_0_0_0_0; // R-type
7'b0111011: ControlsD = 19'b1_000_00_00_00_0_10_0_0_1_0_0_0; // R-type W instructions for RV64i
7'b1100011: ControlsD = 19'b0_010_00_00_00_1_01_0_0_0_0_0_0; // beq
7'b0010011: ControlsD = 19'b1_000_01_00_00_0_10_0_0_0_0_0_0; // I-type ALU
7'b0011011: ControlsD = 19'b1_000_01_00_00_0_10_0_0_1_0_0_0; // IW-type ALU for RV64i
7'b1101111: ControlsD = 19'b1_011_00_00_10_0_00_1_0_0_0_0_0; // jal
7'b1100111: ControlsD = 19'b1_000_00_00_10_0_00_1_1_0_0_0_0; // jalr
7'b0010111: ControlsD = 19'b1_100_11_00_00_0_00_0_0_0_0_0_0; // auipc
7'b0110111: ControlsD = 19'b1_100_01_00_00_0_11_0_0_0_0_0_0; // lui
7'b0001111: ControlsD = 19'b0_000_00_00_00_0_00_0_0_0_0_0_0; // fence = nop
7'b1110011: if (Funct3D == 3'b000)
ControlsD = 19'b0_000_00_00_00_0_00_0_0_0_0_1_0; // privileged; decoded further in priveleged modules
else
ControlsD = 19'b1_000_00_00_11_0_00_0_0_0_1_0_0; // csrs
7'b0000000: ControlsD = 19'b0_000_00_00_00_0_00_0_0_0_0_0_1; // illegal instruction
default: ControlsD = 19'b0_000_00_00_00_0_00_0_0_0_0_0_1; // non-implemented instruction
endcase
// unswizzle control bits
// squash control signals if coming from an illegal compressed instruction
assign {RegWriteD, ImmSrcD, ALUSrcAD, ALUSrcBD, MemRWD,
ResultSrcD, BranchD, ALUOpD, JumpD, TargetSrcD, W64D, CSRWriteD,
PrivilegedD, PreIllegalInstrFaultD} = ControlsD & ~IllegalCompInstrD;
assign IllegalInstrFaultD = PreIllegalInstrFaultD | IllegalCompInstrD; // illegal if bad 32 or 16-bit instr
// ALU Decoding
assign sltD = (Funct3D == 3'b010);
assign sltuD = (Funct3D == 3'b011);
assign subD = (Funct3D == 3'b000 & Funct7b5D & OpD[5]);
assign sraD = (Funct3D == 3'b101 & Funct7b5D);
assign aluc3D = subD | sraD | sltD | sltuD; // TRUE for R-type subtracts and sra, slt, sltu
always_comb
case(ALUOpD)
2'b00: ALUControlD = 5'b00000; // addition
2'b01: ALUControlD = 5'b01000; // subtraction
2'b11: ALUControlD = 5'b01110; // pass B through for lui
default: ALUControlD = {W64D, aluc3D, Funct3D}; // R-type instructions
endcase
// Execute stage pipeline control register and logic
floprc #(23) controlregE(clk, reset, FlushE,
{RegWriteD, ResultSrcD, MemRWD, JumpD, BranchD, ALUControlD, ALUSrcAD, ALUSrcBD, TargetSrcD, CSRWriteD, PrivilegedD, IllegalInstrFaultD, InstrAccessFaultD, Funct3D, 1'b1},
{RegWriteE, ResultSrcE, MemRWE, JumpE, BranchE, ALUControlE, ALUSrcAE, ALUSrcBE, TargetSrcE, CSRWriteE, PrivilegedE, IllegalInstrFaultE, InstrAccessFaultE, Funct3E, InstrValidE});
// Branch Logic
assign {zeroE, ltE, ltuE} = FlagsE;
always_comb
case(Funct3E)
3'b000: BranchTakenE = zeroE; // beq
3'b001: BranchTakenE = ~zeroE; // bne
3'b100: BranchTakenE = ltE; // blt
3'b101: BranchTakenE = ~ltE; // bge
3'b110: BranchTakenE = ltuE; // bltu
3'b111: BranchTakenE = ~ltuE; // bgeu
default: BranchTakenE = 1'b0; // undefined mode
endcase
assign PCSrcE = JumpE | BranchE & BranchTakenE;
assign MemReadE = MemRWE[1];
// Memory stage pipeline control register
floprc #(13) controlregM(clk, reset, FlushM,
{RegWriteE, ResultSrcE, MemRWE, CSRWriteE, PrivilegedE, IllegalInstrFaultE, InstrAccessFaultE, Funct3E, InstrValidE},
{RegWriteM, ResultSrcM, MemRWM, CSRWriteM, PrivilegedM, IllegalInstrFaultM, InstrAccessFaultM, Funct3M, InstrValidM});
// Writeback stage pipeline control register
floprc #(4) controlregW(clk, reset, FlushW,
{RegWriteM, ResultSrcM, InstrValidM},
{RegWriteW, ResultSrcW, InstrValidW});
assign CSRWritePendingDEM = CSRWriteD | CSRWriteE | CSRWriteM;
endmodule

182
wally-pipelined/src/csr.sv Normal file
View File

@ -0,0 +1,182 @@
///////////////////////////////////////////
// csr.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Counter Control and Status Registers
// See RISC-V Privileged Mode Specification 20190608
//
// 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-macros.sv"
module csr #(parameter XLEN = 64, MISA = 0, ZCSR = 1, ZCOUNTERS = 1) (
input logic clk, reset,
input logic [31:0] InstrM,
input logic [XLEN-1:0] PCM, SrcAM,
input logic CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
input logic TimerIntM, ExtIntM, SwIntM,
input logic InstrValidW, FloatRegWriteW, LoadStallD,
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
input logic [XLEN-1:0] CauseM, NextFaultMtvalM,
output logic [1:0] STATUS_MPP,
output logic STATUS_SPP, STATUS_TSR,
output logic [XLEN-1:0] MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW,
output logic [XLEN-1:0] MEDELEG_REGW, MIDELEG_REGW, SEDELEG_REGW, SIDELEG_REGW,
output logic [11:0] MIP_REGW, MIE_REGW,
output logic STATUS_MIE, STATUS_SIE,
input logic [4:0] SetFflagsM,
output logic [2:0] FRM_REGW,
// output logic [11:0] MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW,
output logic [XLEN-1:0] CSRReadValM,
output logic IllegalCSRAccessM
);
logic [XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRNReadValM, CSRCReadValM;
logic [XLEN-1:0] CSRSrcM, CSRRWM, CSRRSM, CSRRCM, CSRWriteValM;
logic [XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, USTATUS_REGW;
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM;
logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
logic WriteMIPM, WriteSIPM, WriteUIPM, WriteMIEM, WriteSIEM, WriteUIEM;
logic [XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextCauseM, NextMtvalM;
logic [XLEN-1:0] zero = 0;
logic [XLEN-1:0] resetExceptionVector = {{(XLEN-32){1'b0}}, 32'h80000000}; // initial exception vector at reset
logic [11:0] CSRAdrM;
logic [11:0] SIP_REGW, SIE_REGW;
logic [11:0] UIP_REGW, UIE_REGW = 0; // N user-mode exceptions not supported
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM, IllegalCSRNAccessM, InsufficientCSRPrivilegeM;
generate
if (`ZCSR_SUPPORTED) begin
// modify CSRs
always_comb begin
// Choose either rs1 or uimm[4:0] as source
CSRSrcM = InstrM[14] ? {{(XLEN-5){1'b0}}, InstrM[19:15]} : SrcAM;
// Compute AND/OR modification
CSRRWM = CSRSrcM;
CSRRSM = CSRReadValM | CSRSrcM;
CSRRCM = CSRReadValM & ~CSRSrcM;
case (InstrM[13:12])
2'b01: CSRWriteValM = CSRRWM;
2'b10: CSRWriteValM = CSRRSM;
2'b11: CSRWriteValM = CSRRCM;
default: CSRWriteValM = CSRReadValM;
endcase
end
// write CSRs
assign CSRAdrM = InstrM[31:20];
assign UnalignedNextEPCM = TrapM ? PCM : CSRWriteValM;
assign NextEPCM = `C_SUPPORTED ? {UnalignedNextEPCM[XLEN-1:1], 1'b0} : {UnalignedNextEPCM[XLEN-1:2], 2'b00}; // 3.1.15 alignment
assign NextCauseM = TrapM ? CauseM : CSRWriteValM;
assign NextMtvalM = TrapM? NextFaultMtvalM : CSRWriteValM;
assign CSRMWriteM = CSRWriteM && (PrivilegeModeW == `M_MODE);
assign CSRSWriteM = CSRWriteM && (PrivilegeModeW[0]);
assign CSRUWriteM = CSRWriteM;
csri #(XLEN, MISA) csri(
clk, reset, CSRMWriteM, CSRSWriteM, CSRAdrM, ExtIntM, TimerIntM, SwIntM,
MIDELEG_REGW, MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW, CSRWriteValM);
csrsr #(XLEN, MISA) csrsr(
clk, reset,
WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM, TrapM, FloatRegWriteW,
NextPrivilegeModeM, PrivilegeModeW,
mretM, sretM, uretM,
CSRWriteValM,
MSTATUS_REGW, SSTATUS_REGW, USTATUS_REGW,
STATUS_MPP, STATUS_SPP, STATUS_TSR, STATUS_MIE, STATUS_SIE);
csrc #(XLEN, ZCOUNTERS) counters(
clk, reset,
InstrValidW, LoadStallD, CSRMWriteM, CSRAdrM, PrivilegeModeW, CSRWriteValM,
MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
CSRCReadValM, IllegalCSRCAccessM);
// Machine Mode CSRs
csrm #(XLEN, MISA) csrm(
clk, reset,
CSRMWriteM, MTrapM, CSRAdrM,
resetExceptionVector,
NextEPCM, NextCauseM, NextMtvalM, MSTATUS_REGW,
CSRWriteValM, CSRMReadValM, MEPC_REGW, MTVEC_REGW, MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
MEDELEG_REGW, MIDELEG_REGW, MIP_REGW, MIE_REGW, WriteMIPM, WriteMIEM, WriteMSTATUSM, IllegalCSRMAccessM
);
csrs #(XLEN, MISA) csrs(
clk, reset,
CSRSWriteM, STrapM, CSRAdrM,
resetExceptionVector,
NextEPCM, NextCauseM, NextMtvalM, SSTATUS_REGW,
CSRWriteValM, CSRSReadValM, SEPC_REGW, STVEC_REGW, SCOUNTEREN_REGW,
SEDELEG_REGW, SIDELEG_REGW, SIP_REGW, SIE_REGW, WriteSIPM, WriteSIEM, WriteSSTATUSM, IllegalCSRSAccessM
);
csrn #(XLEN, MISA) csrn( // User Mode Exception Registers
clk, reset,
CSRUWriteM, UTrapM, CSRAdrM,
resetExceptionVector,
NextEPCM, NextCauseM, NextMtvalM, USTATUS_REGW,
CSRWriteValM, CSRNReadValM, UEPC_REGW, UTVEC_REGW,
UIP_REGW, UIE_REGW, WriteUIPM, WriteUIEM, WriteUSTATUSM, IllegalCSRNAccessM
);
csru #(XLEN, MISA) csru( // Floating Point Flags are part of User MOde
clk, reset, CSRUWriteM, CSRAdrM,
CSRWriteValM, CSRUReadValM, SetFflagsM, FRM_REGW, IllegalCSRUAccessM
);
// merge CSR Reads
assign CSRReadValM = CSRUReadValM | CSRSReadValM | CSRMReadValM | CSRCReadValM | CSRNReadValM;
// merge illegal accesses: illegal if none of the CSR addresses is legal or privilege is insufficient
assign InsufficientCSRPrivilegeM = (CSRAdrM[9:8] == 2'b11 && PrivilegeModeW != `M_MODE) ||
(CSRAdrM[9:8] == 2'b01 && PrivilegeModeW == `U_MODE);
assign IllegalCSRAccessM = (IllegalCSRCAccessM && IllegalCSRMAccessM &&
IllegalCSRSAccessM && IllegalCSRUAccessM && IllegalCSRNAccessM ||
InsufficientCSRPrivilegeM) && CSRWriteM;
end else begin // CSRs not implemented
assign STATUS_MPP = 2'b11;
assign STATUS_SPP = 2'b0;
assign STATUS_TSR = 0;
assign MEPC_REGW = 0;
assign SEPC_REGW = 0;
assign UEPC_REGW = 0;
assign UTVEC_REGW = 0;
assign STVEC_REGW = 0;
assign MTVEC_REGW = 0;
assign MEDELEG_REGW = 0;
assign MIDELEG_REGW = 0;
assign SEDELEG_REGW = 0;
assign SIDELEG_REGW = 0;
assign MIP_REGW = 0;
assign MIE_REGW = 0;
assign STATUS_MIE = 0;
assign STATUS_SIE = 0;
assign FRM_REGW = 0;
assign CSRReadValM = 0;
assign IllegalCSRAccessM = CSRWriteM;
end
endgenerate
endmodule

226
wally-pipelined/src/csrc.sv Normal file
View File

@ -0,0 +1,226 @@
///////////////////////////////////////////
// csrc.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Counter CSRs
// See RISC-V Privileged Mode Specification 20190608 3.1.10-11
//
// 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-macros.sv"
module csrc #(parameter XLEN=64, ZCOUNTERS = 1,
MCYCLE = 12'hB00,
// MTIME = 12'hB01, // address not specified in privileged spec. Consider moving to CLINT to match SiFive
// MTIMECMP = 12'hB21, // not specified in privileged spec. Move to CLINT
MINSTRET = 12'hB02,
MHPMCOUNTER3 = 12'hB03,
MHPMCOUNTER4 = 12'hB04,
// ... more counters
MHPMCOUNTER31 = 12'hB1F,
MCYCLEH = 12'hB80,
// MTIMEH = 12'hB81, // address not specified in privileged spec. Consider moving to CLINT to match SiFive
// MTIMECMPH = 12'hBA1, // not specified in privileged spec. Move to CLINT
MINSTRETH = 12'hB82,
MHPMCOUNTER3H = 12'hB83,
MHPMCOUNTER4H = 12'hB84,
// ... more counters
MHPMCOUNTER31H = 12'hB9F,
MCOUNTERINHIBIT = 12'h320,
MHPMEVENT3 = 12'h323,
MHPMEVENT4 = 12'h324,
// ... more counters
MHPMEVENT31 = 12'h33F,
CYCLE = 12'hC00,
// TIME = 12'hC01, // not specified
INSTRET = 12'hC02,
HPMCOUNTER3 = 12'hC03,
HPMCOUNTER4 = 12'hC04,
// ...more counters
HPMCOUNTER31 = 12'hC1F,
CYCLEH = 12'hC80,
// TIMEH = 12'hC81, // not specified
INSTRETH = 12'hC82,
HPMCOUNTER3H = 12'hC83,
HPMCOUNTER4H = 12'hC84,
// ... more counters
HPMCOUNTER31H = 12'hC9F
) (
input logic clk, reset,
input logic InstrValidW, LoadStallD, CSRMWriteM,
input logic [11:0] CSRAdrM,
input logic [1:0] PrivilegeModeW,
input logic [XLEN-1:0] CSRWriteValM,
input logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW,
output logic [XLEN-1:0] CSRCReadValM,
output logic IllegalCSRCAccessM
);
generate
if (`ZCOUNTERS_SUPPORTED) begin
// logic [63:0] TIME_REGW, TIMECMP_REGW;
logic [63:0] CYCLE_REGW, INSTRET_REGW;
logic [63:0] HPMCOUNTER3_REGW, HPMCOUNTER4_REGW; // add more performance counters here if desired
logic [63:0] CYCLEPlusM, TIMEPlusM, INSTRETPlusM;
logic [63:0] HPMCOUNTER3PlusM, HPMCOUNTER4PlusM;
// logic [XLEN-1:0] NextTIMEM;
logic [XLEN-1:0] NextCYCLEM, NextINSTRETM;
logic [XLEN-1:0] NextHPMCOUNTER3M, NextHPMCOUNTER4M;
logic WriteTIMEM, WriteTIMECMPM, WriteCYCLEM, WriteINSTRETM;
logic WriteHPMCOUNTER3M, WriteHPMCOUNTER4M;
logic [4:0] CounterNumM;
// Write enables
// assign WriteTIMEM = CSRMWriteM && (CSRAdrM == MTIME);
// assign WriteTIMECMPM = CSRMWriteM && (CSRAdrM == MTIMECMP);
assign WriteCYCLEM = CSRMWriteM && (CSRAdrM == MCYCLE);
assign WriteINSTRETM = CSRMWriteM && (CSRAdrM == MINSTRET);
assign WriteHPMCOUNTER3M = CSRMWriteM && (CSRAdrM == MHPMCOUNTER3);
assign WriteHPMCOUNTER4M = CSRMWriteM && (CSRAdrM == MHPMCOUNTER4);
// Counter adders with inhibits for power savings
assign CYCLEPlusM = CYCLE_REGW + {63'b0, ~MCOUNTINHIBIT_REGW[0]};
// assign TIMEPlusM = TIME_REGW + 1; // can't be inhibited
assign INSTRETPlusM = INSTRET_REGW + {63'b0, InstrValidW & ~MCOUNTINHIBIT_REGW[2]};
assign HPMCOUNTER3PlusM = HPMCOUNTER3_REGW + {63'b0, LoadStallD & ~MCOUNTINHIBIT_REGW[3]}; // count load stalls
assign HPMCOUNTER4PlusM = HPMCOUNTER4_REGW + {63'b0, 1'b0 & ~MCOUNTINHIBIT_REGW[4]}; // change to count signals
assign NextCYCLEM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM[XLEN-1:0];
// assign NextTIMEM = WriteTIMEM ? CSRWriteValM : TIMEPlusM[XLEN-1:0];
assign NextINSTRETM = WriteINSTRETM ? CSRWriteValM : INSTRETPlusM[XLEN-1:0];
assign NextHPMCOUNTER3M = WriteHPMCOUNTER3M ? CSRWriteValM : HPMCOUNTER3PlusM[XLEN-1:0];
assign NextHPMCOUNTER4M = WriteHPMCOUNTER4M ? CSRWriteValM : HPMCOUNTER4PlusM[XLEN-1:0];
// Write / update counters
// Only the Machine mode versions of the counter CSRs are writable
if (XLEN==64) begin// 64-bit counters
// flopr #(64) TIMEreg(clk, reset, WriteTIMEM ? CSRWriteValM : TIME_REGW + 1, TIME_REGW); // may count off a different clock***
// flopenr #(64) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW);
flopr #(64) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW);
flopr #(64) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW);
flopr #(64) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW);
flopr #(64) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW);
end else begin // 32-bit low and high counters
logic WriteTIMEHM, WriteTIMECMPHM, WriteCYCLEHM, WriteINSTRETHM;
logic WriteHPMCOUNTER3HM, WriteHPMCOUNTER4HM;
logic [XLEN-1:0] NextCYCLEHM, NextTIMEHM, NextINSTRETHM;
logic [XLEN-1:0] NextHPMCOUNTER3HM, NextHPMCOUNTER4HM;
// Write Enables
// assign WriteTIMEHM = CSRMWriteM && (CSRAdrM == MTIMEH);
// assign WriteTIMECMPHM = CSRMWriteM && (CSRAdrM == MTIMECMPH);
assign WriteCYCLEHM = CSRMWriteM && (CSRAdrM == MCYCLEH);
assign WriteINSTRETHM = CSRMWriteM && (CSRAdrM == MINSTRETH);
assign WriteHPMCOUNTER3HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER3H);
assign WriteHPMCOUNTER4HM = CSRMWriteM && (CSRAdrM == MHPMCOUNTER4H);
assign NextCYCLEHM = WriteCYCLEM ? CSRWriteValM : CYCLEPlusM[63:32];
// assign NextTIMEHM = WriteTIMEHM ? CSRWriteValM : TIMEPlusM[63:32];
assign NextINSTRETHM = WriteINSTRETHM ? CSRWriteValM : INSTRETPlusM[63:32];
assign NextHPMCOUNTER3HM = WriteHPMCOUNTER3HM ? CSRWriteValM : HPMCOUNTER3PlusM[63:32];
assign NextHPMCOUNTER4HM = WriteHPMCOUNTER4HM ? CSRWriteValM : HPMCOUNTER4PlusM[63:32];
// Counter CSRs
// flopr #(32) TIMEreg(clk, reset, NextTIMEM, TIME_REGW); // may count off a different clock***
// flopenr #(32) TIMECMPreg(clk, reset, WriteTIMECMPM, CSRWriteValM, TIMECMP_REGW[31:0]);
flopr #(32) CYCLEreg(clk, reset, NextCYCLEM, CYCLE_REGW[31:0]);
flopr #(32) INSTRETreg(clk, reset, NextINSTRETM, INSTRET_REGW[31:0]);
flopr #(32) HPMCOUNTER3reg(clk, reset, NextHPMCOUNTER3M, HPMCOUNTER3_REGW[31:0]);
flopr #(32) HPMCOUNTER4reg(clk, reset, NextHPMCOUNTER4M, HPMCOUNTER4_REGW[31:0]);
// flopr #(32) TIMEHreg(clk, reset, NextTIMEHM, TIME_REGW); // may count off a different clock***
// flopenr #(32) TIMECMPHreg(clk, reset, WriteTIMECMPHM, CSRWriteValM, TIMECMP_REGW[63:32]);
flopr #(32) CYCLEHreg(clk, reset, NextCYCLEHM, CYCLE_REGW[63:32]);
flopr #(32) INSTRETHreg(clk, reset, NextINSTRETHM, INSTRET_REGW[63:32]);
flopr #(32) HPMCOUNTER3Hreg(clk, reset, NextHPMCOUNTER3HM, HPMCOUNTER3_REGW[63:32]);
flopr #(32) HPMCOUNTER4Hreg(clk, reset, NextHPMCOUNTER4HM, HPMCOUNTER4_REGW[63:32]);
end
// eventually move TIME and TIMECMP to the CLINT
// run TIME off asynchronous reference clock
// synchronize write enable to TIME
// four phase handshake to synchronize reads from TIME
// interrupt on timer compare
// ability to disable optional CSRs
// Read Counters, or cause excepiton if insufficient privilege in light of COUNTEREN flags
assign CounterNumM = CSRAdrM[4:0]; // which counter to read?
if (XLEN==64) // 64-bit counter reads
always_comb
if (PrivilegeModeW == `M_MODE ||
MCOUNTEREN_REGW[CounterNumM] && (PrivilegeModeW == `S_MODE || SCOUNTEREN_REGW[CounterNumM])) begin
IllegalCSRCAccessM = 0;
case (CSRAdrM)
// MTIME: CSRCReadValM = TIME_REGW;
// MTIMECMP: CSRCReadValM = TIMECMP_REGW;
MCYCLE: CSRCReadValM = CYCLE_REGW;
MINSTRET: CSRCReadValM = INSTRET_REGW;
MHPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW;
MHPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW;
// TIME: CSRCReadValM = TIME_REGW;
CYCLE: CSRCReadValM = CYCLE_REGW;
INSTRET: CSRCReadValM = INSTRET_REGW;
HPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW;
HPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW;
default: begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1;
end
endcase
end else IllegalCSRCAccessM = 1; // no privileges for this coute
else // 32-bit counter reads
always_comb
if (PrivilegeModeW == `M_MODE ||
MCOUNTEREN_REGW[CounterNumM] && (PrivilegeModeW == `S_MODE || SCOUNTEREN_REGW[CounterNumM])) begin
IllegalCSRCAccessM = 0;
case (CSRAdrM)
// MTIME: CSRCReadValM = TIME_REGW[31:0];
// MTIMECMP: CSRCReadValM = TIMECMP_REGW[31:0];
MCYCLE: CSRCReadValM = CYCLE_REGW[31:0];
MINSTRET: CSRCReadValM = INSTRET_REGW[31:0];
MHPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW[31:0];
MHPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW[31:0];
// TIME: CSRCReadValM = TIME_REGW[31:0];
CYCLE: CSRCReadValM = CYCLE_REGW[31:0];
INSTRET: CSRCReadValM = INSTRET_REGW[31:0];
HPMCOUNTER3: CSRCReadValM = HPMCOUNTER3_REGW[31:0];
HPMCOUNTER4: CSRCReadValM = HPMCOUNTER4_REGW[31:0];
// MTIMEH: CSRCReadValM = TIME_REGW[63:32];
// MTIMECMPH: CSRCReadValM = TIMECMP_REGW[63:32];
MCYCLEH: CSRCReadValM = CYCLE_REGW[63:32];
MINSTRETH: CSRCReadValM = INSTRET_REGW[63:32];
MHPMCOUNTER3H: CSRCReadValM = HPMCOUNTER3_REGW[63:32];
MHPMCOUNTER4H: CSRCReadValM = HPMCOUNTER4_REGW[63:32];
// TIMEH: CSRCReadValM = TIME_REGW[63:32];
CYCLEH: CSRCReadValM = CYCLE_REGW[63:32];
INSTRETH: CSRCReadValM = INSTRET_REGW[63:32];
HPMCOUNTER3H: CSRCReadValM = HPMCOUNTER3_REGW[63:32];
HPMCOUNTER4H: CSRCReadValM = HPMCOUNTER4_REGW[63:32];
default: begin
CSRCReadValM = 0;
IllegalCSRCAccessM = 1;
end
endcase
end else IllegalCSRCAccessM = 1;
end else begin
assign CSRCReadValM = 0;
assign IllegalCSRCAccessM = 1;
end
endgenerate
endmodule

121
wally-pipelined/src/csri.sv Normal file
View File

@ -0,0 +1,121 @@
///////////////////////////////////////////
// csri.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Interrupt Control & Status Registers (IP, EI)
// See RISC-V Privileged Mode Specification 20190608 & 20210108 draft
//
// 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-macros.sv"
module csri #(parameter XLEN=64, MISA=0,
// Machine CSRs
MIE = 12'h304,
MIP = 12'h344,
SIE = 12'h104,
SIP = 12'h144) (
input logic clk, reset,
input logic CSRMWriteM, CSRSWriteM,
input logic [11:0] CSRAdrM,
input logic ExtIntM, TimerIntM, SwIntM,
input logic [XLEN-1:0] MIDELEG_REGW,
output logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW,
input logic [XLEN-1:0] CSRWriteValM
);
logic [11:0] IntInM, IP_REGW, IE_REGW;
logic [11:0] MIP_WRITE_MASK, SIP_WRITE_MASK;
logic WriteMIPM, WriteMIEM, WriteSIPM, WriteSIEM;
logic [XLEN-1:0] zero = 0;
// Determine which interrupts need to be set
// assumes no N-mode user interrupts
always_comb begin
IntInM = 0;
IntInM[11] = ExtIntM & ~MIDELEG_REGW[9]; // MEIP
IntInM[9] = ExtIntM & MIDELEG_REGW[9]; // SEIP
IntInM[7] = TimerIntM & ~MIDELEG_REGW[5]; // MTIP
IntInM[5] = TimerIntM & MIDELEG_REGW[5]; // STIP
IntInM[3] = SwIntM & ~MIDELEG_REGW[1]; // MSIP
IntInM[1] = SwIntM & MIDELEG_REGW[1]; // SSIP
end
// Interrupt Write Enables
assign WriteMIPM = CSRMWriteM && (CSRAdrM == MIP);
assign WriteMIEM = CSRMWriteM && (CSRAdrM == MIE);
assign WriteSIPM = CSRSWriteM && (CSRAdrM == SIP);
assign WriteSIEM = CSRSWriteM && (CSRAdrM == SIE);
// Interrupt Pending and Enable Registers
// MEIP, MTIP, MSIP are read-only
// SEIP, STIP, SSIP is writable in MIP if S mode exists
// SSIP is writable in SIP if S mode exists
generate
if (`S_SUPPORTED) begin
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)
end else begin
assign MIP_WRITE_MASK = 12'h000;
assign SIP_WRITE_MASK = 12'h000;
end
always @(posedge clk, posedge reset) begin
if (reset) IP_REGW = zero;
else if (WriteMIPM) IP_REGW = (CSRWriteValM & MIP_WRITE_MASK) | IntInM; // MTIP unclearable
else if (WriteSIPM) IP_REGW = (CSRWriteValM & SIP_WRITE_MASK) | IntInM; // MTIP unclearable
// else if (WriteUIPM) IP_REGW = (CSRWriteValM & 12'hBBB) | (NextIPM & 12'h080); // MTIP unclearable
else IP_REGW = IP_REGW | IntInM; // *** check this turns off interrupts properly even when MIDELEG changes
end
always @(posedge clk, posedge reset) begin
if (reset) IE_REGW = zero;
else if (WriteMIEM) IE_REGW = (CSRWriteValM & 12'hAAA); // MIE controls M and S fields
else if (WriteSIEM) IE_REGW = (CSRWriteValM & 12'h222) | (IE_REGW & 12'h888); // only S fields
// else if (WriteUIEM) IE_REGW = (CSRWriteValM & 12'h111) | (IE_REGW & 12'hAAA); // only U field
end
endgenerate
// restricted views of registers
generate
always_comb begin
// Machine Mode
MIP_REGW = IP_REGW;
MIE_REGW = IE_REGW;
// Supervisor mode
if (`S_SUPPORTED) begin
SIP_REGW = IP_REGW & MIDELEG_REGW & 'h222; // only delegated interrupts visible
SIE_REGW = IE_REGW & MIDELEG_REGW & 'h222;
end else begin
SIP_REGW = zero;
SIE_REGW = zero;
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 = zero;
UIE_REGW = zero;
end */
end
endgenerate
endmodule

156
wally-pipelined/src/csrm.sv Normal file
View File

@ -0,0 +1,156 @@
///////////////////////////////////////////
// csrm.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Machine-Mode Control and Status Registers
// See RISC-V Privileged Mode Specification 20190608
//
// 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-macros.sv"
module csrm #(parameter XLEN=64, MISA=0,
// Machine CSRs
MVENDORID = 12'hF11,
MARCHID = 12'hF12,
MIMPID = 12'hF13,
MHARTID = 12'hF14,
MSTATUS = 12'h300,
MISA_ADR = 12'h301,
MEDELEG = 12'h302,
MIDELEG = 12'h303,
MIE = 12'h304,
MTVEC = 12'h305,
MCOUNTEREN = 12'h306,
MSTATUSH = 12'h310,
MCOUNTINHIBIT = 12'h320,
MSCRATCH = 12'h340,
MEPC = 12'h341,
MCAUSE = 12'h342,
MTVAL = 12'h343,
MIP = 12'h344,
PMPCFG0 = 12'h3A0,
PMPCFG1 = 12'h3A1,
PMPCFG2 = 12'h3A2,
PMPCFG3 = 12'h3A3,
PMPADDR0 = 12'h3B0,
//... more physical memory protection
PMPADDR15 = 12'h3BF,
TSELECT = 12'h7A0,
TDATA1 = 12'h7A1,
TDATA2 = 12'h7A2,
TDATA3 = 12'h7A3,
DCSR = 12'h7B0,
DPC = 12'h7B1,
DSCRATCH0 = 12'h7B2,
DSCRATCH1 = 12'h7B3) (
input logic clk, reset,
input logic CSRMWriteM, MTrapM,
input logic [11:0] CSRAdrM,
input logic [XLEN-1:0] resetExceptionVector,
input logic [XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, MSTATUS_REGW,
input logic [XLEN-1:0] CSRWriteValM,
output logic [XLEN-1:0] CSRMReadValM, MEPC_REGW, MTVEC_REGW,
output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
output logic [XLEN-1:0] MEDELEG_REGW, MIDELEG_REGW,
input logic [11:0] MIP_REGW, MIE_REGW,
output logic WriteMIPM, WriteMIEM,
output logic WriteMSTATUSM,
output logic IllegalCSRMAccessM
);
logic [XLEN-1:0] MISA_REGW;
logic [XLEN-1:0] MSCRATCH_REGW,MCAUSE_REGW, MTVAL_REGW;
logic [XLEN-1:0] zero = 0;
logic [31:0] allones = {32{1'b1}};
logic [XLEN-1:0] MEDELEG_MASK = ~(zero | 1'b1 << 11); // medeleg[11] hardwired to zero per Privileged Spec 3.1.8
logic [XLEN-1:0] MIDELEG_MASK = {{(XLEN-12){1'b0}}, 12'h222}; // only allow delegating interrupts to supervisor mode
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
// MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally
assign MISA_REGW = {(XLEN == 32 ? 2'b01 : 2'b10), {(XLEN-28){1'b0}}, MISA[25:0]};
// Write machine Mode CSRs
assign WriteMSTATUSM = CSRMWriteM && (CSRAdrM == MSTATUS);
assign WriteMTVECM = CSRMWriteM && (CSRAdrM == MTVEC);
assign WriteMEDELEGM = CSRMWriteM && (CSRAdrM == MEDELEG);
assign WriteMIDELEGM = CSRMWriteM && (CSRAdrM == MIDELEG);
assign WriteMIPM = CSRMWriteM && (CSRAdrM == MIP);
assign WriteMIEM = CSRMWriteM && (CSRAdrM == MIE);
assign WriteMSCRATCHM = CSRMWriteM && (CSRAdrM == MSCRATCH);
assign WriteMEPCM = MTrapM | (CSRMWriteM && (CSRAdrM == MEPC));
assign WriteMCAUSEM = MTrapM | (CSRMWriteM && (CSRAdrM == MCAUSE));
assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL));
assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN);
assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT);
// CSRs
flopenl #(XLEN) MTVECreg(clk, reset, WriteMTVECM, CSRWriteValM, resetExceptionVector, MTVEC_REGW);
generate
if (`S_SUPPORTED | (`U_SUPPORTED & `N_SUPPORTED)) begin // DELEG registers should exist
flopenl #(XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK, zero, MEDELEG_REGW);
flopenl #(XLEN) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM & MIDELEG_MASK, zero, MIDELEG_REGW);
end else begin
assign MEDELEG_REGW = 0;
assign MIDELEG_REGW = 0;
end
endgenerate
// flopenl #(XLEN) MIPreg(clk, reset, WriteMIPM, CSRWriteValM, zero, MIP_REGW);
// flopenl #(XLEN) MIEreg(clk, reset, WriteMIEM, CSRWriteValM, zero, MIE_REGW);
flopenr #(XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW);
flopenr #(XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
flopenl #(XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, zero, MCAUSE_REGW);
flopenr #(XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], allones, MCOUNTEREN_REGW);
flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], allones, MCOUNTINHIBIT_REGW);
// Read machine mode CSRs
always_comb begin
IllegalCSRMAccessM = !(`S_SUPPORTED | `U_SUPPORTED & `N_SUPPORTED) &&
(CSRAdrM == MEDELEG || CSRAdrM == MIDELEG); // trap on DELEG register access when no S or N-mode
case (CSRAdrM)
MISA_ADR: CSRMReadValM = MISA_REGW;
MVENDORID: CSRMReadValM = 0;
MARCHID: CSRMReadValM = 0;
MIMPID: CSRMReadValM = 'h100; // pipelined implementation
MHARTID: CSRMReadValM = 0;
MSTATUS: CSRMReadValM = MSTATUS_REGW;
MSTATUSH: CSRMReadValM = 0; // flush this out later if MBE and SBE fields are supported
MTVEC: CSRMReadValM = MTVEC_REGW;
MEDELEG: CSRMReadValM = MEDELEG_REGW;
MIDELEG: CSRMReadValM = MIDELEG_REGW;
MIP: CSRMReadValM = {{(XLEN-12){1'b0}}, MIP_REGW};
MIE: CSRMReadValM = {{(XLEN-12){1'b0}}, MIE_REGW};
MSCRATCH: CSRMReadValM = MSCRATCH_REGW;
MEPC: CSRMReadValM = MEPC_REGW;
MCAUSE: CSRMReadValM = MCAUSE_REGW;
MTVAL: CSRMReadValM = MTVAL_REGW;
MCOUNTEREN:CSRMReadValM = {{(XLEN-32){1'b0}}, MCOUNTEREN_REGW};
MCOUNTINHIBIT:CSRMReadValM = {{(XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW};
default: begin
CSRMReadValM = 0;
IllegalCSRMAccessM = 1;
end
endcase
end
endmodule

108
wally-pipelined/src/csrn.sv Normal file
View File

@ -0,0 +1,108 @@
///////////////////////////////////////////
// csrn.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: User-Mode Control and Status Registers for User Mode Exceptions
// See RISC-V Privileged Mode Specification 20190608 Table 2.2
//
// 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-macros.sv"
module csrn #(parameter XLEN=64, MISA=0,
USTATUS =12'h000,
UIE = 12'h004,
UTVEC = 12'h005,
USCRATCH = 12'h040,
UEPC = 12'h041,
UCAUSE = 12'h042,
UTVAL = 12'h043,
UIP = 12'h044) (
input logic clk, reset,
input logic CSRUWriteM, UTrapM,
input logic [11:0] CSRAdrM,
input logic [XLEN-1:0] resetExceptionVector,
input logic [XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, USTATUS_REGW,
input logic [XLEN-1:0] CSRWriteValM,
output logic [XLEN-1:0] CSRUReadValM, UEPC_REGW, UTVEC_REGW,
input logic [11:0] UIP_REGW, UIE_REGW,
output logic WriteUIPM, WriteUIEM,
output logic WriteUSTATUSM,
output logic IllegalCSRUAccessM
);
logic [XLEN-1:0] zero = 0;
// *** add floating point CSRs here. Maybe move stuff below to csrn to support reading
// User mode CSRs below only needed when user mode traps are supported
generate
if (`N_SUPPORTED) begin
logic WriteUTVECM;
logic WriteUSCRATCHM, WriteUEPCM;
logic WriteUCAUSEM, WriteUTVALM;
logic [XLEN-1:0] UEDELEG_REGW, UIDELEG_REGW, UIP_REGW, UIE_REGW;
logic [XLEN-1:0] USCRATCH_REGW, UCAUSE_REGW, UTVAL_REGW;
// Write enables
assign WriteUSTATUSM = CSRUWriteM && (CSRAdrM == USTATUS);
assign WriteUTVECM = CSRUWriteM && (CSRAdrM == UTVEC);
assign WriteUIPM = CSRUWriteM && (CSRAdrM == UIP);
assign WriteUIEM = CSRUWriteM && (CSRAdrM == UIE);
assign WriteUEPCM = UTrapM | (CSRUWriteM && (CSRAdrM == UEPC));
assign WriteUCAUSEM = UTrapM | (CSRUWriteM && (CSRAdrM == UCAUSE));
assign WriteUTVALM = UTrapM | (CSRUWriteM && (CSRAdrM == UTVAL));
// CSRs
flopenl #(XLEN) UTVECreg(clk, reset, WriteUTVECM, CSRWriteValM, resetExceptionVector, UTVEC_REGW);
// flopenl #(XLEN) UIPreg(clk, reset, WriteUIPM, CSRWriteValM, zero, UIP_REGW);
// flopenl #(XLEN) UIEreg(clk, reset, WriteUIEM, CSRWriteValM, zero, UIE_REGW);
flopenr #(XLEN) USCRATCHreg(clk, reset, WriteUSCRATCHM, CSRWriteValM, USCRATCH_REGW);
flopenr #(XLEN) UEPCreg(clk, reset, WriteUEPCM, NextEPCM, UEPC_REGW);
flopenr #(XLEN) UCAUSEreg(clk, reset, WriteUCAUSEM, NextCauseM, UCAUSE_REGW);
flopenr #(XLEN) UTVALreg(clk, reset, WriteUTVALM, NextMtvalM, UTVAL_REGW);
// CSR Reads
always_comb begin
IllegalCSRUAccessM = 0;
case (CSRAdrM)
USTATUS: CSRUReadValM = USTATUS_REGW;
UTVEC: CSRUReadValM = UTVEC_REGW;
UIP: CSRUReadValM = {{(XLEN-12){1'b0}}, UIP_REGW};
UIE: CSRUReadValM = {{(XLEN-12){1'b0}}, UIE_REGW};
USCRATCH: CSRUReadValM = USCRATCH_REGW;
UEPC: CSRUReadValM = UEPC_REGW;
UCAUSE: CSRUReadValM = UCAUSE_REGW;
UTVAL: CSRUReadValM = UTVAL_REGW;
default: begin
CSRUReadValM = 0;
IllegalCSRUAccessM = 1;
end
endcase
end
end else begin // if not supported
assign WriteUSTATUSM = 0;
assign CSRUReadValM = 0;
assign UEPC_REGW = 0;
assign UTVEC_REGW = 0;
assign IllegalCSRUAccessM = 1;
end
endgenerate
endmodule

126
wally-pipelined/src/csrs.sv Normal file
View File

@ -0,0 +1,126 @@
///////////////////////////////////////////
// csrs.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Supervisor-Mode Control and Status Registers
// See RISC-V Privileged Mode Specification 20190608
//
// 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-macros.sv"
module csrs #(parameter XLEN=64, MISA=0,
// Supervisor CSRs
SSTATUS = 12'h100,
SEDELEG = 12'h102,
SIDELEG = 12'h103,
SIE = 12'h104,
STVEC = 12'h105,
SCOUNTEREN = 12'h106,
SSCRATCH = 12'h140,
SEPC = 12'h141,
SCAUSE = 12'h142,
STVAL = 12'h143,
SIP= 12'h144,
SATP = 12'h180) (
input logic clk, reset,
input logic CSRSWriteM, STrapM,
input logic [11:0] CSRAdrM,
input logic [XLEN-1:0] resetExceptionVector,
input logic [XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, SSTATUS_REGW,
input logic [XLEN-1:0] CSRWriteValM,
output logic [XLEN-1:0] CSRSReadValM, SEPC_REGW, STVEC_REGW,
output logic [31:0] SCOUNTEREN_REGW,
output logic [XLEN-1:0] SEDELEG_REGW, SIDELEG_REGW,
input logic [11:0] SIP_REGW, SIE_REGW,
output logic WriteSIPM, WriteSIEM,
output logic WriteSSTATUSM,
output logic IllegalCSRSAccessM
);
logic [XLEN-1:0] zero = 0;
logic [31:0] allones = {32{1'b1}};
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
generate
if (`S_SUPPORTED) begin
logic WriteSTVECM, WriteSEDELEGM, WriteSIDELEGM;
logic WriteSSCRATCHM, WriteSEPCM;
logic WriteSCAUSEM, WriteSTVALM, WriteSCOUNTERENM;
logic [XLEN-1:0] SSCRATCH_REGW, SCAUSE_REGW, STVAL_REGW;
assign WriteSSTATUSM = CSRSWriteM && (CSRAdrM == SSTATUS);
assign WriteSTVECM = CSRSWriteM && (CSRAdrM == STVEC);
assign WriteSEDELEGM = CSRSWriteM && (CSRAdrM == SEDELEG);
assign WriteSIDELEGM = CSRSWriteM && (CSRAdrM == SIDELEG);
assign WriteSSCRATCHM = CSRSWriteM && (CSRAdrM == SSCRATCH);
assign WriteSEPCM = STrapM | (CSRSWriteM && (CSRAdrM == SEPC));
assign WriteSCAUSEM = STrapM | (CSRSWriteM && (CSRAdrM == SCAUSE));
assign WriteSTVALM = STrapM | (CSRSWriteM && (CSRAdrM == STVAL));
assign WriteSCOUNTERENM = CSRSWriteM && (CSRAdrM == SCOUNTEREN);
// CSRs
flopenl #(XLEN) STVECreg(clk, reset, WriteSTVECM, CSRWriteValM, resetExceptionVector, STVEC_REGW);
// flopenl #(XLEN) SIPreg(clk, reset, WriteSIPM, CSRWriteValM, zero, SIP_REGW);
// flopenl #(XLEN) SIEreg(clk, reset, WriteSIEM, CSRWriteValM, zero, SIE_REGW);
flopenr #(XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
flopenr #(XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
flopenl #(XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, zero, SCAUSE_REGW);
flopenr #(XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
flopenl #(32) SCOUNTERENreg(clk, reset, WriteSCOUNTERENM, CSRWriteValM[31:0], allones, SCOUNTEREN_REGW);
if (`N_SUPPORTED) begin
flopenl #(XLEN) SEDELEGreg(clk, reset, WriteSEDELEGM, CSRWriteValM & SEDELEG_MASK, zero, SEDELEG_REGW);
flopenl #(XLEN) SIDELEGreg(clk, reset, WriteSIDELEGM, CSRWriteValM, zero, SIDELEG_REGW);
end else begin
assign SEDELEG_REGW = 0;
assign SIDELEG_REGW = 0;
end
// CSR Reads
always_comb begin
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;
SEDELEG: CSRSReadValM = SEDELEG_REGW;
SIDELEG: CSRSReadValM = SIDELEG_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;
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 IllegalCSRSAccessM = 1;
end
endgenerate
endmodule

View File

@ -0,0 +1,181 @@
///////////////////////////////////////////
// crsr.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Status register
// See RISC-V Privileged Mode Specification 20190608
//
// 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-macros.sv"
module csrsr #(parameter XLEN=64, MISA = 0)(
input logic clk, reset,
input logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM, TrapM, FloatRegWriteW,
input logic [1:0] NextPrivilegeModeM, PrivilegeModeW,
input logic mretM, sretM, uretM,
input logic [XLEN-1:0] CSRWriteValM,
output logic [XLEN-1:0] MSTATUS_REGW, SSTATUS_REGW, USTATUS_REGW,
output logic [1:0] STATUS_MPP,
output logic STATUS_SPP, STAUTS_TSR,
output logic STATUS_MIE, STATUS_SIE
);
logic STATUS_SD, STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_SUM_INT, STATUS_MPRV, STATUS_MPRV_INT;
logic [1:0] STATUS_SXL, STATUS_UXL, STATUS_XS, STATUS_FS, STATUS_FS_INT, STATUS_MPP_NEXT;
logic STATUS_MPIE, STATUS_SPIE, STATUS_UPIE, STATUS_UIE;
// STATUS REGISTER FIELD
// See Privileged Spec Section 3.1.6
// Lower privilege status registers are a subset of the full status register
// *** consider adding MBE, SBE, UBE fields later from 20210108 draft spec
generate
if (XLEN==64) begin// RV64
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_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};
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_XS, STATUS_FS, /*STATUS_MPP, 2'b0*/ 4'b0,
STATUS_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
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_XS, STATUS_FS, /*STATUS_MPP, 8'b0, */
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
end else begin// RV32
assign MSTATUS_REGW = {STATUS_SD, 8'b0,
STATUS_TSR, STATUS_TW, STATUS_TVM, STATUS_MXR, STATUS_SUM, STATUS_MPRV,
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};
assign SSTATUS_REGW = {STATUS_SD, 11'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_SPP, /*STATUS_MPIE, 1'b0*/ 2'b0, STATUS_SPIE, STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 2'b0, STATUS_SIE, STATUS_UIE};
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_XS, STATUS_FS, STATUS_MPP, 8'b0, */
/*STATUS_SPP, STATUS_MPIE, 1'b0 2'b0, STATUS_SPIE,*/ STATUS_UPIE,
/*STATUS_MIE, 1'b0*/ 3'b0, /*STATUS_SIE, */STATUS_UIE};
end
endgenerate
// harwired STATUS bits
generate
// 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 ? 2'b10 : 2'b00; // 10 if supervisor mode supported
assign STATUS_UXL = `U_SUPPORTED ? 2'b10 : 2'b00; // 10 if user mode supported
assign STATUS_SUM = `S_SUPPORTED & 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_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_TSR = 0; // Trap SRET not supported; revisit whether this is necessary for an OS
assign STATUS_TW = 0; // Timeout Wait not supported
assign STATUS_TVM = 0; // Trap Virtual Memory not supported (revisit if supporting virtualizations)
assign STATUS_MXR = 0; // Make Executable Readable (may need to add support for VM later)
assign STATUS_XS = 2'b00; // No additional user-mode state to be dirty
always_comb
if (CSRWriteValM[12:11] == `U_MODE && `U_SUPPORTED) STATUS_MPP_NEXT = `U_MODE;
else if (CSRWriteValM[12:11] == `S_MODE && `S_SUPPORTED) STATUS_MPP_NEXT = `S_MODE;
else STATUS_MPP_NEXT = `M_MODE;
// registers for STATUS bits
// complex register with reset, write enable, and the ability to update other bits in certain cases
always_ff @(posedge clk, posedge reset)
if (reset) begin
STATUS_SUM_INT <= 0;
STATUS_MPRV_INT <= 0; // Per Priv 3.3
STATUS_FS_INT <= 2'b01; // initial
STATUS_MPP <= `M_MODE;
STATUS_SPP <= 1'b1;
STATUS_MPIE <= 1;
STATUS_SPIE <= `S_SUPPORTED;
STATUS_UPIE <= `U_SUPPORTED;
STATUS_MIE <= 0; // Per Priv 3.3
STATUS_SIE <= `S_SUPPORTED;
STATUS_UIE <= `U_SUPPORTED;
end else begin
if (WriteMSTATUSM) begin
STATUS_SUM_INT <= CSRWriteValM[18];
STATUS_MPRV_INT <= CSRWriteValM[17];
STATUS_FS_INT <= CSRWriteValM[14:13];
STATUS_MPP <= STATUS_MPP_NEXT;
STATUS_SPP <= `S_SUPPORTED & CSRWriteValM[8];
STATUS_MPIE <= CSRWriteValM[7];
STATUS_SPIE <= `S_SUPPORTED & CSRWriteValM[5];
STATUS_UPIE <= `U_SUPPORTED & CSRWriteValM[4];
STATUS_MIE <= CSRWriteValM[3];
STATUS_SIE <= `S_SUPPORTED & CSRWriteValM[1];
STATUS_UIE <= `U_SUPPORTED & CSRWriteValM[0];
end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits
STATUS_SUM_INT <= CSRWriteValM[18];
STATUS_FS_INT <= CSRWriteValM[14:13];
STATUS_SPP <= `S_SUPPORTED & CSRWriteValM[8];
STATUS_SPIE <= `S_SUPPORTED & CSRWriteValM[5];
STATUS_UPIE <= `U_SUPPORTED & CSRWriteValM[4];
STATUS_SIE <= `S_SUPPORTED & CSRWriteValM[1];
STATUS_UIE <= `U_SUPPORTED & CSRWriteValM[0];
end else if (WriteUSTATUSM) begin // write a subset of the STATUS bits
STATUS_FS_INT <= CSRWriteValM[14:13];
STATUS_UPIE <= `U_SUPPORTED & CSRWriteValM[4];
STATUS_UIE <= `U_SUPPORTED & CSRWriteValM[0];
end else begin
if (FloatRegWriteW) STATUS_FS_INT <=2'b11; // mark Float State dirty
if (TrapM) begin
// Update interrupt enables per Privileged Spec p. 21
// y = PrivilegeModeW
// x = NextPrivilegeModeM
// Modes: 11 = Machine, 01 = Supervisor, 00 = User
if (NextPrivilegeModeM == `M_MODE) begin
STATUS_MPIE <= STATUS_MIE;
STATUS_MIE <= 0;
STATUS_MPP <= PrivilegeModeW;
end else if (NextPrivilegeModeM == `S_MODE) begin
STATUS_SPIE <= STATUS_SIE;
STATUS_SIE <= 0;
STATUS_SPP <= PrivilegeModeW[0]; // *** seems to disagree with P. 56
end else begin // user mode
STATUS_UPIE <= STATUS_UIE;
STATUS_UIE <= 0;
end
end else if (mretM) begin // Privileged 3.1.6.1
STATUS_MIE <= STATUS_MPIE;
STATUS_MPIE <= 1;
STATUS_MPP <= `U_SUPPORTED ? `U_MODE : `M_MODE; // per spec, not sure why
STATUS_MPRV_INT <= 0; // per 20210108 draft spec
end else if (sretM) begin
STATUS_SIE <= STATUS_SPIE;
STATUS_SPIE <= `S_SUPPORTED;
STATUS_SPP <= 0; // Privileged 4.1.1
STATUS_MPRV_INT <= 0; // per 20210108 draft spec
end else if (uretM) begin
STATUS_UIE <= STATUS_UPIE;
STATUS_UPIE <= `U_SUPPORTED;
end
// *** add code to track STATUS_FS_INT for dirty floating point registers
end
end
endmodule

View File

@ -0,0 +1,84 @@
///////////////////////////////////////////
// csru.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: User-Mode Control and Status Registers for Floating Point
// See RISC-V Privileged Mode Specification 20190608 Table 2.2
//
// 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-macros.sv"
module csru #(parameter XLEN=64, MISA=0,
FFLAGS = 12'h001,
FRM = 12'h002,
FCSR = 12'h003) (
input logic clk, reset,
input logic CSRUWriteM,
input logic [11:0] CSRAdrM,
input logic [XLEN-1:0] CSRWriteValM,
output logic [XLEN-1:0] CSRUReadValM,
input logic [4:0] SetFflagsM,
output logic [2:0] FRM_REGW,
output logic IllegalCSRUAccessM
);
// Floating Point CSRs in User Mode only needed if Floating Point is supported
generate
if (`F_SUPPORTED) begin
logic [4:0] FFLAGS_REGW;
logic WriteFFLAGSM, WriteFRMM, WriteFCSRM;
logic [2:0] NextFRMM;
logic [4:0] NextFFLAGSM;
// Write enables
assign WriteFCSRM = CSRUWriteM && (CSRAdrM == FCSR);
assign WriteFFLAGSM = CSRUWriteM && (CSRAdrM == FFLAGS) | WriteFCSRM ;
assign WriteFRMM = CSRUWriteM && (CSRAdrM == FRM) | WriteFCSRM;
// Write Values
assign NextFRMM = WriteFCSRM ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
assign NextFFLAGSM = WriteFFLAGSM ? CSRWriteValM[4:0] : FFLAGS_REGW | SetFflagsM;
// CSRs
flopenr #(3) FRMreg(clk, reset, WriteFRMM, NextFRMM, FRM_REGW);
flopr #(5) FFLAGSreg(clk, reset, NextFFLAGSM, FFLAGS_REGW);
// CSR Reads
always_comb begin
IllegalCSRUAccessM = 0;
case (CSRAdrM)
FFLAGS: CSRUReadValM = {{(XLEN-5){1'b0}}, FFLAGS_REGW};
FRM: CSRUReadValM = {{(XLEN-3){1'b0}}, FRM_REGW};
FCSR: CSRUReadValM = {{(XLEN-8){1'b0}}, FRM_REGW, FFLAGS_REGW};
default: begin
CSRUReadValM = 0;
IllegalCSRUAccessM = 1;
end
endcase
end
end else begin // if not supported
assign FRM_REGW = 0;
assign CSRUReadValM = 0;
assign IllegalCSRUAccessM = 1;
end
endgenerate
endmodule

View File

@ -0,0 +1,181 @@
///////////////////////////////////////////
// datapath.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Wally Datapath
//
// 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-macros.sv"
module datapath #(parameter XLEN=32, MISA=0, ZCSR = 1, ZCOUNTERS = 1) (
input logic clk, reset,
// Fetch stage signals
input logic StallF,
output logic [XLEN-1:0] PCF,
input logic [31:0] InstrF,
// Decode stage signals
output logic [6:0] opD,
output logic [2:0] funct3D,
output logic funct7b5D,
input logic StallD, FlushD,
input logic [2:0] ImmSrcD,
input logic LoadStallD, // for performance counter
output logic IllegalCompInstrD,
// Execute stage signals
input logic FlushE,
input logic [1:0] ForwardAE, ForwardBE,
input logic PCSrcE,
input logic [4:0] ALUControlE,
input logic ALUSrcAE, ALUSrcBE,
input logic TargetSrcE,
output logic [2:0] FlagsE,
// Memory stage signals
input logic FlushM,
input logic [1:0] MemRWM,
input logic CSRWriteM, PrivilegedM,
input logic InstrAccessFaultM, IllegalInstrFaultM,
input logic TimerIntM, ExtIntM, SwIntM,
output logic InstrMisalignedFaultM,
input logic [2:0] Funct3M,
output logic [XLEN-1:0] WriteDataExtM, ALUResultM,
input logic [XLEN-1:0] ReadDataM,
output logic [7:0] ByteMaskM,
output logic RetM, TrapM,
input logic [4:0] SetFflagsM,
input logic DataAccessFaultM,
// Writeback stage signals
input logic FlushW,
input logic RegWriteW,
input logic [1:0] ResultSrcW,
input logic InstrValidW,
input logic FloatRegWriteW,
output logic [2:0] FRM_REGW,
// Hazard Unit signals
output logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E,
output logic [4:0] RdE, RdM, RdW);
// Fetch stage signals
logic [XLEN-1:0] PCPlus2or4F;
// Decode stage signals
logic [31:0] InstrD;
logic [XLEN-1:0] PCD, PCPlus2or4D;
logic [XLEN-1:0] RD1D, RD2D;
logic [XLEN-1:0] ExtImmD;
logic [31:0] InstrDecompD;
logic [4:0] RdD;
// Execute stage signals
logic [31:0] InstrE;
logic [XLEN-1:0] RD1E, RD2E;
logic [XLEN-1:0] PCE, ExtImmE;
logic [XLEN-1:0] PreSrcAE, SrcAE, SrcBE;
logic [XLEN-1:0] ALUResultE;
logic [XLEN-1:0] WriteDataE;
logic [XLEN-1:0] TargetBaseE, PCTargetE;
// Memory stage signals
logic [31:0] InstrM;
logic [XLEN-1:0] PCM;
logic [XLEN-1:0] SrcAM;
logic [XLEN-1:0] ReadDataExtM;
logic [XLEN-1:0] WriteDataM;
logic [XLEN-1:0] CSRReadValM;
logic [XLEN-1:0] PrivilegedNextPCM;
logic LoadMisalignedFaultM, LoadAccessFaultM;
logic StoreMisalignedFaultM, StoreAccessFaultM;
logic [XLEN-1:0] InstrMisalignedAdrM;
// Writeback stage signals
logic [XLEN-1:0] ALUResultW;
logic [XLEN-1:0] ReadDataW;
logic [XLEN-1:0] PCW;
logic [XLEN-1:0] CSRValW;
logic [XLEN-1:0] ResultW;
logic [31:0] nop = 32'h00000013; // instruction for NOP
// Fetch stage pipeline register and logic; also Ex stage for branches
pclogic #(XLEN, MISA) pclogic(clk, reset, StallF, PCSrcE,
InstrF, ExtImmE, TargetBaseE, RetM, TrapM, PrivilegedNextPCM, PCF, PCPlus2or4F,
InstrMisalignedFaultM, InstrMisalignedAdrM);
// Decode stage pipeline register and logic
flopenl #(32) InstrDReg(clk, reset, ~StallD, (FlushD ? nop : InstrF), nop, InstrD);
flopenrc #(XLEN) PCDReg(clk, reset, FlushD, ~StallD, PCF, PCD);
flopenrc #(XLEN) PCPlus2or4DReg(clk, reset, FlushD, ~StallD, PCPlus2or4F, PCPlus2or4D);
instrDecompress #(XLEN, MISA) decomp(InstrD, InstrDecompD, IllegalCompInstrD);
assign opD = InstrDecompD[6:0];
assign funct3D = InstrDecompD[14:12];
assign funct7b5D = InstrDecompD[30];
assign Rs1D = InstrDecompD[19:15];
assign Rs2D = InstrDecompD[24:20];
assign RdD = InstrDecompD[11:7];
regfile #(XLEN) regf(clk, reset, RegWriteW, Rs1D, Rs2D, RdW, ResultW, RD1D, RD2D);
extend #(XLEN) ext(InstrDecompD[31:7], ImmSrcD, ExtImmD);
// Execute stage pipeline register and logic
floprc #(XLEN) RD1EReg(clk, reset, FlushE, RD1D, RD1E);
floprc #(XLEN) RD2EReg(clk, reset, FlushE, RD2D, RD2E);
floprc #(XLEN) PCEReg(clk, reset, FlushE, PCD, PCE);
floprc #(XLEN) ExtImmEReg(clk, reset, FlushE, ExtImmD, ExtImmE);
flopr #(32) InstrEReg(clk, reset, FlushE ? nop : InstrDecompD, InstrE);
floprc #(5) Rs1EReg(clk, reset, FlushE, Rs1D, Rs1E);
floprc #(5) Rs2EReg(clk, reset, FlushE, Rs2D, Rs2E);
floprc #(5) RdEReg(clk, reset, FlushE, RdD, RdE);
mux3 #(XLEN) faemux(RD1E, ResultW, ALUResultM, ForwardAE, PreSrcAE);
mux3 #(XLEN) fbemux(RD2E, ResultW, ALUResultM, ForwardBE, WriteDataE);
mux2 #(XLEN) srcamux(PreSrcAE, PCE, ALUSrcAE, SrcAE);
mux2 #(XLEN) srcbmux(WriteDataE, ExtImmE, ALUSrcBE, SrcBE);
alu #(XLEN) alu(SrcAE, SrcBE, ALUControlE, ALUResultE, FlagsE);
mux2 #(XLEN) targetsrcmux(PCE, SrcAE, TargetSrcE, TargetBaseE);
// Memory stage pipeline register
floprc #(XLEN) SrcAMReg(clk, reset, FlushM, SrcAE, SrcAM);
floprc #(XLEN) ALUResultMReg(clk, reset, FlushM, ALUResultE, ALUResultM);
floprc #(XLEN) WriteDataMReg(clk, reset, FlushM, WriteDataE, WriteDataM);
floprc #(XLEN) PCMReg(clk, reset, FlushM, PCE, PCM);
flopr #(32) InstrMReg(clk, reset, FlushM ? nop : InstrE, InstrM);
floprc #(5) RdMEg(clk, reset, FlushM, RdE, RdM);
memdp #(XLEN) memdp(
MemRWM, ReadDataM, ALUResultM, Funct3M, ReadDataExtM, WriteDataM, WriteDataExtM, ByteMaskM,
DataAccessFaultM, LoadMisalignedFaultM, LoadAccessFaultM, StoreMisalignedFaultM, StoreAccessFaultM);
// Priveleged block operates in M and W stages, handling CSRs and exceptions
privileged #(XLEN, MISA, ZCSR, ZCOUNTERS) priv(
clk, reset, CSRWriteM, SrcAM, InstrM, PCM,
CSRReadValM, PrivilegedNextPCM, RetM, TrapM,
InstrValidW, FloatRegWriteW, LoadStallD, PrivilegedM,
InstrMisalignedFaultM, InstrAccessFaultM, IllegalInstrFaultM,
LoadMisalignedFaultM, LoadAccessFaultM, StoreMisalignedFaultM, StoreAccessFaultM,
TimerIntM, ExtIntM, SwIntM,
InstrMisalignedAdrM, ALUResultM,
SetFflagsM, FRM_REGW);
// Writeback stage pipeline register and logic
floprc #(XLEN) ALUResultWReg(clk, reset, FlushW, ALUResultM, ALUResultW);
floprc #(XLEN) ReadDataWReg(clk, reset, FlushW, ReadDataExtM, ReadDataW);
floprc #(XLEN) PCWReg(clk, reset, FlushW, PCM, PCW);
floprc #(XLEN) CSRValWReg(clk, reset, FlushW, CSRReadValM, CSRValW);
floprc #(5) RdWEg(clk, reset, FlushW, RdM, RdW);
mux4 #(XLEN) resultmux(ALUResultW, ReadDataW, PCW, CSRValW, ResultSrcW, ResultW);
endmodule

View File

@ -0,0 +1,60 @@
///////////////////////////////////////////
// dmem.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Data memory
//
// 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-macros.sv"
// *** need idiom to map onto cache RAM with byte writes
// *** and use memread signal to reduce power when reads aren't needed
module dmem #(parameter XLEN=32) (
input logic clk, reset,
input logic [1:0] MemRWM,
input logic [7:0] ByteMaskM,
input logic [XLEN-1:0] AdrM, WdM,
output logic [XLEN-1:0] RdM,
output logic AccessFaultM,
output logic TimerIntM, SwIntM);
logic [XLEN-1:0] RdTimM, RdClintM;
logic TimEnM, ClintEnM;
// Address decoding
assign TimEnM = AdrM[31] & ~(|AdrM[30:19]); // 0x80000000 - 0x8007FFFF *** check top bits too
assign ClintEnM = ~(|AdrM[XLEN-1:26]) & AdrM[25] & ~(|AdrM[24:16]); // 0x02000000-0x0200FFFF
// tightly integrated memory
dtim #(XLEN) dtim(clk, MemRWM & {2{TimEnM}}, ByteMaskM, AdrM[18:0], WdM, RdTimM);
// memory-mapped I/O peripherals
clint #(XLEN) clint(clk, reset, MemRWM & {2{ClintEnM}}, ByteMaskM, AdrM[15:0], WdM, RdClintM,
TimerIntM, SwIntM);
// *** add cache and interface to external memory & other peripherals
// merge reads
assign RdM = RdTimM | RdClintM;
assign AccessFaultM = ~(|TimEnM | ClintEnM);
endmodule

View File

@ -0,0 +1,85 @@
///////////////////////////////////////////
// dtim.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Data tightly integrated memory
//
// 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-macros.sv"
module dtim #(parameter XLEN=32) (
input logic clk,
input logic [1:0] MemRWM,
input logic [7:0] ByteMaskM,
input logic [18:0] AdrM,
// input logic [XLEN-1:0] AdrM,
input logic [XLEN-1:0] WdM,
output logic [XLEN-1:0] RdM);
logic [XLEN-1:0] RAM[0:65535];
logic [XLEN-1:0] read, write;
logic [15:0] entry;
logic memread, memwrite;
assign memread = MemRWM[1];
assign memwrite = MemRWM[0];
// word aligned reads
generate
if (XLEN==64)
assign #2 entry = AdrM[18:3];
else
assign #2 entry = AdrM[17:2];
endgenerate
assign read = RAM[entry];
assign RdM = memread ? read: 0;
// write each byte based on the byte mask
generate
if (XLEN==64) begin
always_comb begin
write=read;
if (ByteMaskM[0]) write[7:0] = WdM[7:0];
if (ByteMaskM[1]) write[15:8] = WdM[15:8];
if (ByteMaskM[2]) write[23:16] = WdM[23:16];
if (ByteMaskM[3]) write[31:24] = WdM[31:24];
if (ByteMaskM[4]) write[39:32] = WdM[39:32];
if (ByteMaskM[5]) write[47:40] = WdM[47:40];
if (ByteMaskM[6]) write[55:48] = WdM[55:48];
if (ByteMaskM[7]) write[63:56] = WdM[63:56];
end
always_ff @(posedge clk)
if (memwrite) RAM[AdrM[18:3]] <= write;
end else begin // 32-bit
always_comb begin
write=read;
if (ByteMaskM[0]) write[7:0] = WdM[7:0];
if (ByteMaskM[1]) write[15:8] = WdM[15:8];
if (ByteMaskM[2]) write[23:16] = WdM[23:16];
if (ByteMaskM[3]) write[31:24] = WdM[31:24];
end
always_ff @(posedge clk)
if (memwrite) RAM[AdrM[17:2]] <= write;
end
endgenerate
endmodule

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////
// extend.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose:
//
// 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-macros.sv"
module extend #(parameter XLEN=32) (
input logic [31:7] instr,
input logic [2:0] immsrc,
output logic [XLEN-1:0] immext);
always_comb
case(immsrc)
// I-type
3'b000: immext = {{(XLEN-12){instr[31]}}, instr[31:20]};
// S-type (stores)
3'b001: immext = {{(XLEN-12){instr[31]}}, instr[31:25], instr[11:7]};
// B-type (branches)
3'b010: immext = {{(XLEN-12){instr[31]}}, instr[7], instr[30:25], instr[11:8], 1'b0};
// J-type (jal)
3'b011: immext = {{(XLEN-20){instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0};
// U-type (lui, auipc)
3'b100: immext = {{(XLEN-31){instr[31]}}, instr[30:12], 12'b0};
/* verilator lint_off WIDTH */
default: immext = 'bx; // undefined
/* verilator lint_on WIDTH */
endcase
endmodule

View File

@ -0,0 +1,98 @@
///////////////////////////////////////////
// flop.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: arious flavors of flip-flops
//
// 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-macros.sv"
// ordinary flip-flop
module flop #(parameter WIDTH = 8) (
input logic clk,
input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q);
always_ff @(posedge clk)
q <= #1 d;
endmodule
// flop with asynchronous reset
module flopr #(parameter WIDTH = 8) (
input logic clk, reset,
input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q);
always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 0;
else q <= #1 d;
endmodule
// flop with enable, asynchronous reset, synchronous clear
module flopenrc #(parameter WIDTH = 8) (
input logic clk, reset, clear, en,
input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q);
always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 0;
else if (en)
if (clear) q <= #1 0;
else q <= #1 d;
endmodule
// flop with enable, asynchronous reset
module flopenr #(parameter WIDTH = 8) (
input logic clk, reset, en,
input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q);
always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 0;
else if (en) q <= #1 d;
endmodule
// flop with enable, asynchronous load
module flopenl #(parameter WIDTH = 8) (
input logic clk, load, en,
input logic [WIDTH-1:0] d,
input logic [WIDTH-1:0] val,
output logic [WIDTH-1:0] q);
always_ff @(posedge clk, posedge load)
if (load) q <= #1 val;
else if (en) q <= #1 d;
endmodule
// flop with asynchronous reset, synchronous clear
module floprc #(parameter WIDTH = 8) (
input logic clk,
input logic reset,
input logic clear,
input logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q);
always_ff @(posedge clk, posedge reset)
if (reset) q <= #1 0;
else
if (clear) q <= #1 0;
else q <= #1 d;
endmodule

View File

@ -0,0 +1,64 @@
///////////////////////////////////////////
// hazard.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Determine forwarding, stalls and flushes
//
// 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-macros.sv"
module hazard(
input logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
input logic PCSrcE, MemReadE,
input logic RegWriteM, RegWriteW, CSRWritePendingDEM, RetM, TrapM,
output logic [1:0] ForwardAE, ForwardBE,
output logic StallF, StallD, FlushD, FlushE, FlushM, FlushW,
output logic loadStallD);
// forwarding logic
always_comb begin
ForwardAE = 2'b00;
ForwardBE = 2'b00;
if (Rs1E != 5'b0)
if ((Rs1E == RdM) & RegWriteM) ForwardAE = 2'b10;
else if ((Rs1E == RdW) & RegWriteW) ForwardAE = 2'b01;
if (Rs2E != 5'b0)
if ((Rs2E == RdM) & RegWriteM) ForwardBE = 2'b10;
else if ((Rs2E == RdW) & RegWriteW) ForwardBE = 2'b01;
end
// stalls and flushes
// loads: stall for one cycle if the subsequent instruction depends on the load
// branches and jumps: flush the next two instructions if the branch is taken in EXE
// CSR Writes: stall all instructions after the CSR until it completes, except that PC must change when branch is resolved
// this also applies to other privileged instructions such as M/S/URET, ECALL/EBREAK
// Exceptions: flush entire pipeline
// Ret instructions: occur in M stage. Might be possible to move earlier, but be careful about hazards
assign loadStallD = MemReadE & ((Rs1D == RdE) | (Rs2D == RdE));
assign StallD = loadStallD;
assign StallF = loadStallD | CSRWritePendingDEM;
assign FlushD = PCSrcE | CSRWritePendingDEM | RetM | TrapM;
assign FlushE = loadStallD | PCSrcE | RetM | TrapM;
assign FlushM = RetM | TrapM;
assign FlushW = TrapM;
endmodule

View File

@ -0,0 +1,60 @@
///////////////////////////////////////////
// imem.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose:
//
// 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-macros.sv"
module imem #(parameter XLEN=32) (
input logic [XLEN-1:0] AdrF,
output logic [31:0] InstrF,
output logic InstrAccessFaultF);
logic [XLEN-1:0] RAM[0:65535];
logic [15:0] adrbits;
logic [XLEN-1:0] rd, rd2;
generate
if (XLEN==32) assign adrbits = AdrF[17:2];
else assign adrbits = AdrF[18:3];
endgenerate
assign #2 rd = RAM[adrbits]; // word aligned
// hack right now for unaligned 32-bit instructions
// eventually this will need to cause a stall like a cache miss
// when the instruction wraps around a cache line
// could be optimized to only stall when the instruction wrapping is 32 bits
assign #2 rd2 = RAM[adrbits+1];
generate
if (XLEN==32) begin
assign InstrF = AdrF[1] ? {rd2[15:0], rd[31:16]} : rd;
assign InstrAccessFaultF = ~AdrF[31] | (|AdrF[30:16]); // memory mapped to 0x80000000-0x8000FFFF
end else begin
assign InstrF = AdrF[2] ? (AdrF[1] ? {rd2[15:0], rd[63:48]} : rd[63:32])
: (AdrF[1] ? rd[47:16] : rd[31:0]);
assign InstrAccessFaultF = (|AdrF[XLEN-1:32]) | ~AdrF[31] | (|AdrF[30:16]); // memory mapped to 0x80000000-0x8000FFFF]
end
endgenerate
endmodule

View File

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

View File

@ -0,0 +1,189 @@
///////////////////////////////////////////
// memdp.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Memory datapath for subword accesses
//
// 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-macros.sv"
module memdp #(parameter XLEN=32) (
input logic [1:0] MemRWM,
input logic [XLEN-1:0] ReadDataM,
input logic [XLEN-1:0] AdrM,
input logic [2:0] Funct3M,
output logic [XLEN-1:0] ReadDataExtM,
input logic [XLEN-1:0] WriteDataM,
output logic [XLEN-1:0] WriteDataExtM,
output logic [7:0] ByteMaskM,
input logic DataAccessFaultM,
output logic LoadMisalignedFaultM, LoadAccessFaultM,
output logic StoreMisalignedFaultM, StoreAccessFaultM);
logic [7:0] bytM;
logic [15:0] HalfwordM;
logic UnalignedM, AccessFaultM;
generate
if (XLEN == 64) begin
// bytMe mux
always_comb
case(AdrM[2:0])
3'b000: bytM = ReadDataM[7:0];
3'b001: bytM = ReadDataM[15:8];
3'b010: bytM = ReadDataM[23:16];
3'b011: bytM = ReadDataM[31:24];
3'b100: bytM = ReadDataM[39:32];
3'b101: bytM = ReadDataM[47:40];
3'b110: bytM = ReadDataM[55:48];
3'b111: bytM = ReadDataM[63:56];
endcase
// halfword mux
always_comb
case(AdrM[2:1])
2'b00: HalfwordM = ReadDataM[15:0];
2'b01: HalfwordM = ReadDataM[31:16];
2'b10: HalfwordM = ReadDataM[47:32];
2'b11: HalfwordM = ReadDataM[63:48];
endcase
logic [31:0] word;
always_comb
case(AdrM[2])
1'b0: word = ReadDataM[31:0];
1'b1: word = ReadDataM[63:32];
endcase
// sign extension
always_comb
case(Funct3M)
3'b000: ReadDataExtM = {{56{bytM[7]}}, bytM}; // lb
3'b001: ReadDataExtM = {{48{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: ReadDataExtM = {{32{word[31]}}, word[31:0]}; // lw
3'b011: ReadDataExtM = ReadDataM; // ld
3'b100: ReadDataExtM = {56'b0, bytM[7:0]}; // lbu
3'b101: ReadDataExtM = {48'b0, HalfwordM[15:0]}; // lhu
3'b110: ReadDataExtM = {32'b0, word[31:0]}; // lwu
default: ReadDataExtM = 64'b0;
endcase
// Memory control
// Compute write mask
always_comb
if (StoreMisalignedFaultM || StoreAccessFaultM) ByteMaskM = 8'b00000000; // discard Unaligned stores
else case(Funct3M)
3'b000: begin ByteMaskM = 8'b00000000; ByteMaskM[AdrM[2:0]] = 1; end // sb
3'b001: case (AdrM[2:1])
2'b00: ByteMaskM = 8'b00000011;
2'b01: ByteMaskM = 8'b00001100;
2'b10: ByteMaskM = 8'b00110000;
2'b11: ByteMaskM = 8'b11000000;
endcase
3'b010: if (AdrM[2]) ByteMaskM = 8'b11110000;
else ByteMaskM = 8'b00001111;
3'b011: ByteMaskM = 8'b11111111;
default: ByteMaskM = 8'b00000000;
endcase
// Handle subword writes
always_comb
case(Funct3M)
3'b000: WriteDataExtM = {8{WriteDataM[7:0]}}; // sb
3'b001: WriteDataExtM = {4{WriteDataM[15:0]}}; // sh
3'b010: WriteDataExtM = {2{WriteDataM[31:0]}}; // sw
3'b011: WriteDataExtM = WriteDataM; // sw
default: WriteDataExtM = 64'b0;
endcase
end else begin // 32-bit
// byte mux
always_comb
case(AdrM[1:0])
2'b00: bytM = ReadDataM[7:0];
2'b01: bytM = ReadDataM[15:8];
2'b10: bytM = ReadDataM[23:16];
2'b11: bytM = ReadDataM[31:24];
endcase
// halfword mux
always_comb
case(AdrM[1])
1'b0: HalfwordM = ReadDataM[15:0];
1'b1: HalfwordM = ReadDataM[31:16];
endcase
// sign extension
always_comb
case(Funct3M)
3'b000: ReadDataExtM = {{24{bytM[7]}}, bytM}; // lb
3'b001: ReadDataExtM = {{16{HalfwordM[15]}}, HalfwordM[15:0]}; // lh
3'b010: ReadDataExtM = ReadDataM; // lw
3'b100: ReadDataExtM = {24'b0, bytM[7:0]}; // lbu
3'b101: ReadDataExtM = {16'b0, HalfwordM[15:0]}; // lhu
default: ReadDataExtM = 32'b0;
endcase
// Memory control
// Compute write mask
always_comb
if (StoreMisalignedFaultM || StoreAccessFaultM) ByteMaskM = 8'b0000; // discard Unaligned stores
else case(Funct3M)
3'b000: begin ByteMaskM = 8'b0000; ByteMaskM[{1'b0,AdrM[1:0]}] = 1; end // sb
3'b001: if (AdrM[1]) ByteMaskM = 8'b1100;
else ByteMaskM = 8'b0011;
3'b010: ByteMaskM = 8'b1111;
default: ByteMaskM = 8'b0000;
endcase
// Handle subword writes
always_comb
case(Funct3M)
3'b000: WriteDataExtM = {4{WriteDataM[7:0]}}; // sb
3'b001: WriteDataExtM = {2{WriteDataM[15:0]}}; // sh
3'b010: WriteDataExtM = WriteDataM; // sw
default: WriteDataExtM = 32'b0;
endcase
end
endgenerate
// Determine if an Unaligned access is taking place
always_comb
case(Funct3M)
3'b000: UnalignedM = 0; // lb, sb
3'b001: UnalignedM = AdrM[0]; // lh, sh
3'b010: UnalignedM = AdrM[1] | AdrM[0]; // lw, sw, flw, fsw
3'b011: UnalignedM = |AdrM[2:0]; // ld, sd, fld, fsd
3'b100: UnalignedM = 0; // lbu
3'b101: UnalignedM = AdrM[0]; // lhu
3'b110: UnalignedM = |AdrM[1:0]; // lwu
default: UnalignedM = 0;
endcase
// Determine if address is valid
assign LoadMisalignedFaultM = UnalignedM & MemRWM[1];
assign LoadAccessFaultM = DataAccessFaultM & MemRWM[0];
assign StoreMisalignedFaultM = UnalignedM & MemRWM[0];
assign StoreAccessFaultM = DataAccessFaultM & MemRWM[0];
endmodule

View File

@ -0,0 +1,52 @@
///////////////////////////////////////////
// mux.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Various flavors of multiplexers
//
// 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-macros.sv"
module mux2 #(parameter WIDTH = 8) (
input logic [WIDTH-1:0] d0, d1,
input logic s,
output logic [WIDTH-1:0] y);
assign y = s ? d1 : d0;
endmodule
module mux3 #(parameter WIDTH = 8) (
input logic [WIDTH-1:0] d0, d1, d2,
input logic [1:0] s,
output logic [WIDTH-1:0] y);
assign y = s[1] ? d2 : (s[0] ? d1 : d0);
endmodule
module mux4 #(parameter WIDTH = 8) (
input logic [WIDTH-1:0] d0, d1, d2, d3,
input logic [1:0] s,
output logic [WIDTH-1:0] y);
assign y = s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0);
endmodule

View File

@ -0,0 +1,50 @@
///////////////////////////////////////////
// pcadder.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Determine next PC = PC+2 or PC+4
//
// 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-macros.sv"
module pcadder #(parameter XLEN=32) (
input logic [XLEN-1:0] pc,
input logic [31:0] instr,
output logic [XLEN-1:0] pcplus);
logic [1:0] op;
logic [XLEN-3:0] pcplusupper;
logic compressed;
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
assign op = instr[1:0];
assign compressed = (op != 2'b11); // is it a 16-bit compressed instruction?
assign pcplusupper = pc[XLEN-1:2] + 1; // add 4 to PC
// choose PC+2 or PC+4
always_comb
if (compressed) // add 2
if (pc[1]) pcplus = {pcplusupper, 2'b00};
else pcplus = {pc[XLEN-1:2], 2'b10};
else pcplus = {pcplusupper, pc[1:0]}; // add 4
endmodule

View File

@ -0,0 +1,73 @@
///////////////////////////////////////////
// pclogic.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Determine Program Counter considering branches, exceptions, ret, reset
//
// 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-macros.sv"
module pclogic #(parameter XLEN=64, MISA=0) (
input logic clk, reset,
input logic StallF, PCSrcE,
input logic [31:0] InstrF,
input logic [XLEN-1:0] ExtImmE, TargetBaseE,
input logic RetM, TrapM,
input logic [XLEN-1:0] PrivilegedNextPCM,
output logic [XLEN-1:0] PCF, PCPlus2or4F,
output logic InstrMisalignedFaultM,
output logic [XLEN-1:0] InstrMisalignedAdrM);
logic [XLEN-1:0] UnalignedPCNextF, PCNextF, PCTargetE;
// logic [XLEN-1:0] ResetVector = 'h100;
// logic [XLEN-1:0] ResetVector = 'he4;
logic [XLEN-1:0] ResetVector = {{(XLEN-32){1'b0}}, 32'h80000000};
logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM;
logic StallExceptResolveBranchesF, PrivilegedChangePCM;
assign PrivilegedChangePCM = RetM | TrapM;
assign StallExceptResolveBranchesF = StallF & ~(PCSrcE | PrivilegedChangePCM);
assign PCTargetE = ExtImmE + TargetBaseE;
mux3 #(XLEN) pcmux(PCPlus2or4F, PCTargetE, PrivilegedNextPCM, {PrivilegedChangePCM, PCSrcE}, UnalignedPCNextF);
assign PCNextF = {UnalignedPCNextF[XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment
flopenl #(XLEN) pcreg(clk, reset, ~StallExceptResolveBranchesF, PCNextF, ResetVector, PCF);
pcadder #(XLEN) pcadd(PCF, InstrF, PCPlus2or4F);
// Misaligned PC logic
generate
if (`C_SUPPORTED) // C supports compressed instructions on halfword boundaries
assign misaligned = PCNextF[0];
else // instructions must be on word boundaries
assign misaligned = |PCNextF[1:0];
endgenerate
// pipeline misaligned faults to M stage
assign BranchMisalignedFaultE = misaligned & PCSrcE; // E-stage (Branch/Jump) misaligned
flopr #(1) InstrMisalginedReg(clk, reset, BranchMisalignedFaultE, BranchMisalignedFaultM);
flopr #(XLEN) InstrMisalignedAdrReg(clk, reset, PCNextF, InstrMisalignedAdrM);
assign TrapMisalignedFaultM = misaligned & PrivilegedChangePCM;
assign InstrMisalignedFaultM = BranchMisalignedFaultM; // | TrapMisalignedFaultM; *** put this back in without causing a cyclic path
endmodule

View File

@ -0,0 +1,54 @@
///////////////////////////////////////////
// privilegeDecoder.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Decode Privileged & related instructions
// See RISC-V Privileged Mode Specification 20190608 3.1.10-11
//
// 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-macros.sv"
module privilegeDecoder #(parameter MISA=0) (
input logic [31:20] InstrM,
input logic PrivilegedM, IllegalInstrFaultInM, IllegalCSRAccessM,
input logic [1:0] PrivilegeModeW,
input logic STATUS_TSR,
output logic IllegalInstrFaultM,
output logic uretM, sretM, mretM, ecallM, ebreakM, wfiM, sfencevmaM);
logic IllegalPrivilegedInstrM;
// xRET defined in Privileged Spect 3.2.2
assign uretM = PrivilegedM & (InstrM[31:20] == 12'b000000000010) & `N_SUPPORTED;
assign sretM = PrivilegedM & (InstrM[31:20] == 12'b000100000010) & `S_SUPPORTED &&
PrivilegeModeW[0] & ~STATUS_TSR;
assign mretM = PrivilegedM & (InstrM[31:20] == 12'b001100000010) && (PrivilegeModeW == `M_MODE);
assign ecallM = PrivilegedM & (InstrM[31:20] == 12'b000000000000);
assign ebreakM = PrivilegedM & (InstrM[31:20] == 12'b000000000001);
assign wfiM = PrivilegedM & (InstrM[31:20] == 12'b000100000101);
assign sfencevmaM = PrivilegedM & (InstrM[31:25] == 7'b0001001);
assign IllegalPrivilegedInstrM = PrivilegedM & ~(uretM|sretM|mretM|ecallM|ebreakM|wfiM|sfencevmaM);
assign IllegalInstrFaultM = IllegalInstrFaultInM | IllegalPrivilegedInstrM | IllegalCSRAccessM;
// *** initially, wfi and sfencevma are nop
// *** zfenci extension?
endmodule

View File

@ -0,0 +1,59 @@
///////////////////////////////////////////
// privilegeModeReg.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Track current privilege mode
// See RISC-V Privileged Mode Specification 20190608
//
// 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-macros.sv"
module privilegeModeReg #(parameter XLEN=32, MISA=0) (
input logic clk, reset,
input logic mretM, sretM, uretM, TrapM,
input logic [1:0] STATUS_MPP,
input logic STATUS_SPP,
input logic [XLEN-1:0] MEDELEG_REGW, MIDELEG_REGW, SEDELEG_REGW, SIDELEG_REGW, CauseM,
output logic [1:0] NextPrivilegeModeM, PrivilegeModeW);
logic md, sd;
// get bits of DELEG registers based on CAUSE
assign md = CauseM[XLEN-1] ? MIDELEG_REGW[CauseM[4:0]] : MEDELEG_REGW[CauseM[4:0]];
assign sd = CauseM[XLEN-1] ? SIDELEG_REGW[CauseM[4:0]] : SEDELEG_REGW[CauseM[4:0]]; // depricated
always_comb
if (reset) NextPrivilegeModeM = `M_MODE; // Privilege resets to 11 (Machine Mode)
else if (mretM) NextPrivilegeModeM = STATUS_MPP;
else if (sretM) NextPrivilegeModeM = {1'b0, STATUS_SPP};
else if (uretM) NextPrivilegeModeM = `U_MODE;
else if (TrapM) begin // Change privilege based on DELEG registers (see 3.1.8)
if (PrivilegeModeW == `U_MODE)
if (`N_SUPPORTED & `U_SUPPORTED & md & sd) NextPrivilegeModeM = `U_MODE;
else if (`S_SUPPORTED & md) NextPrivilegeModeM = `S_MODE;
else NextPrivilegeModeM = `M_MODE;
else if (PrivilegeModeW == `S_MODE)
if (`S_SUPPORTED & md) NextPrivilegeModeM = `S_MODE;
else NextPrivilegeModeM = `M_MODE;
else NextPrivilegeModeM = `M_MODE;
end else NextPrivilegeModeM = PrivilegeModeW; // stay at same level when there is no exception or return
flop #(2) PrivlegeReg(clk, NextPrivilegeModeM, PrivilegeModeW);
endmodule

View File

@ -0,0 +1,117 @@
///////////////////////////////////////////
// exceptions.sv
//
// Written: David_Harris@hmc.edu 5 January 2021
// Modified:
//
// Purpose: Implements the CSRs, Exceptions, and Privileged operations
// See RISC-V Privileged Mode Specification 20190608
//
// 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-macros.sv"
module privileged #(parameter XLEN=32, MISA = 0, ZCSR = 1, ZCOUNTERS = 1)(
input logic clk, reset,
input logic CSRWriteM,
input logic [XLEN-1:0] SrcAM,
input logic [31:0] InstrM,
input logic [XLEN-1:0] PCM,
output logic [XLEN-1:0] CSRReadValM,
output logic [XLEN-1:0] PrivilegedNextPCM,
output logic RetM, TrapM,
input logic InstrValidW, FloatRegWriteW, LoadStallD,
input logic PrivilegedM,
input logic InstrMisalignedFaultM, InstrAccessFaultM, IllegalInstrFaultInM,
input logic LoadMisalignedFaultM, LoadAccessFaultM,
input logic StoreMisalignedFaultM, StoreAccessFaultM,
input logic TimerIntM, ExtIntM, SwIntM,
input logic [XLEN-1:0] InstrMisalignedAdrM, ALUResultM,
input logic [4:0] SetFflagsM,
output logic [2:0] FRM_REGW
);
logic [1:0] NextPrivilegeModeM, PrivilegeModeW;
logic [XLEN-1:0] CauseM, NextFaultMtvalM;
logic [XLEN-1:0] MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW;
logic [XLEN-1:0] MEDELEG_REGW, MIDELEG_REGW, SEDELEG_REGW, SIDELEG_REGW;
// logic [11:0] MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW;
logic uretM, sretM, mretM, ecallM, ebreakM, wfiM, sfencevmaM;
logic IllegalCSRAccess, IllegalInstrFaultM;
logic SwInt, TimerInt, ExtInt;
logic BreakpointFaultM, EcallFaultM;
logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM;
logic MTrapM, STrapM, UTrapM;
logic [1:0] STATUS_MPP;
logic STATUS_SPP, STATUS_TSR;
logic STATUS_MIE, STATUS_SIE;
logic [11:0] MIP_REGW, MIE_REGW;
// track the current privilege level
privilegeModeReg #(XLEN, MISA) pmr (clk, reset, mretM, sretM, uretM, TrapM,
STATUS_MPP, STATUS_SPP, MEDELEG_REGW, MIDELEG_REGW, SEDELEG_REGW, SIDELEG_REGW,
CauseM, NextPrivilegeModeM, PrivilegeModeW);
// decode privileged instructions
privilegeDecoder #(MISA) pmd(InstrM[31:20], PrivilegedM, IllegalInstrFaultInM, IllegalCSRAccess, PrivilegeModeW, STATUS_TSR,
IllegalInstrFaultM, uretM, sretM, mretM, ecallM, ebreakM, wfiM, sfencevmaM);
// Extract exceptions by name and handle them
assign BreakpointFaultM = ebreakM; // could have other causes too
assign EcallFaultM = ecallM;
assign InstrPageFaultM = 0;
assign LoadPageFaultM = 0;
assign StorePageFaultM = 0;
trap #(XLEN, MISA) trap(clk, reset, InstrMisalignedFaultM, InstrAccessFaultM, IllegalInstrFaultM,
BreakpointFaultM, LoadMisalignedFaultM, StoreMisalignedFaultM,
LoadAccessFaultM, StoreAccessFaultM, EcallFaultM, InstrPageFaultM,
LoadPageFaultM, StorePageFaultM,
mretM, sretM, uretM, PrivilegeModeW, NextPrivilegeModeM,
MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW,
MIP_REGW, MIE_REGW, STATUS_MIE, STATUS_SIE,
InstrMisalignedAdrM, ALUResultM, InstrM,
TrapM, MTrapM, STrapM, UTrapM, RetM,
PrivilegedNextPCM, CauseM, NextFaultMtvalM
// MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW,
);
// Control and Status Registers
csr #(XLEN, MISA, ZCSR, ZCOUNTERS) csr(clk, reset,
InstrM, PCM, SrcAM,
CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM,
TimerIntM, ExtIntM, SwIntM,
InstrValidW, FloatRegWriteW, LoadStallD,
NextPrivilegeModeM, PrivilegeModeW,
CauseM, NextFaultMtvalM,
STATUS_MPP, STATUS_SPP, STATUS_TSR,
MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW,
MEDELEG_REGW, MIDELEG_REGW, SEDELEG_REGW, SIDELEG_REGW,
MIP_REGW, MIE_REGW, STATUS_MIE, STATUS_SIE,
SetFflagsM, FRM_REGW,
// MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW,
CSRReadValM, IllegalCSRAccess
);
endmodule

View File

@ -0,0 +1,52 @@
///////////////////////////////////////////
// regfile.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: 3-port register file
//
// 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-macros.sv"
module regfile #(parameter XLEN=32) (
input logic clk, reset,
input logic we3,
input logic [ 4:0] a1, a2, a3,
input logic [XLEN-1:0] wd3,
output logic [XLEN-1:0] rd1, rd2);
logic [XLEN-1:0] rf[31:0];
integer i;
// three ported register file
// read two ports combinationally (A1/RD1, A2/RD2)
// write third port on rising edge of clock (A3/WD3/WE3)
// write occurs on falling edge of clock
// register 0 hardwired to 0
// reset is intended for simulation only, not synthesis
always_ff @(negedge clk or posedge reset)
if (reset) for(i=0; i<32; i++) rf[i] <= 0;
else if (we3) rf[a3] <= wd3;
assign #2 rd1 = (a1 != 0) ? rf[a1] : 0;
assign #2 rd2 = (a2 != 0) ? rf[a2] : 0;
endmodule

View File

@ -0,0 +1,96 @@
///////////////////////////////////////////
// shifter.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: RISC-V 32/64 bit shifter
//
// 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-macros.sv"
module shifter #(parameter WIDTH=32) (
input logic [WIDTH-1:0] a,
input logic [5:0] amt,
input logic right, arith, w64,
output logic [WIDTH-1:0] y);
// The best shifter architecture differs based on XLEN.
// for RV32, only 32-bit shifts are needed. These are
// most efficiently implemented with a funnel shifter.
// For RV64, 32 and 64-bit shifts are needed, with sign
// extension.
generate
if (WIDTH==32) begin
// funnel shifter (see CMOS VLSI Design 4e Section 11.8.1, note Table 11.11 shift types wrong)
logic [62:0] z, zshift;
logic [4:0] offset;
// funnel input
always_comb
if (right)
if (arith) z = {{31{a[31]}}, a};
else z = {31'b0, a};
else z = {a, 31'b0};
// shift amount
assign offset = right ? amt[4:0] : ~amt[4:0];
// funnel operation
assign zshift = z >> offset;
assign y = zshift[WIDTH-1:0];
end else begin // RV64
// funnel shifter followed by masking
// research idea: investigate shifter designs for mixed 32/64-bit shifts
logic [126:0] z, zshift;
logic [31:0] ylower, yupper;
logic [5:0] offset, amt6;
// funnel input
always_comb
if (w64) begin // 32-bit shifts
if (right)
if (arith) z = {64'b0, {31{a[31]}}, a[31:0]};
else z = {95'b0, a[31:0]};
else z = {32'b0, a[31:0], 63'b0};
end else begin
if (right)
if (arith) z = {{63{a[63]}}, a};
else z = {63'b0, a};
else z = {a, 63'b0};
end
// shift amount
assign amt6 = w64 ? {1'b0, amt[4:0]} : amt[5:0]; // 32 or 64-bit shift
assign offset = right ? amt6 : ~amt6;
// funnel operation
assign zshift = z >> offset;
assign ylower = zshift[31:0];
// mask upper 32 bits for W-type 32-bit shifts
// harris: is there a clever way to get zshift[31] earlier for arithmetic right shifts to speed up critical path?
assign yupper = w64 ? {32{zshift[31]}} : zshift[63:32];
assign y = {yupper, ylower};
end
endgenerate
endmodule

View File

@ -0,0 +1,465 @@
///////////////////////////////////////////
// testbench.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Wally Testbench and helper modules
//
// 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-macros.sv"
module testbench #(parameter XLEN=64, MISA=32'h00000104, ZCSR = 1, ZCOUNTERS = 1)();
logic clk;
logic reset;
logic [XLEN-1:0] WriteData, DataAdr;
logic [1:0] MemRW;
int test, i, errors, totalerrors;
logic [31:0] sig32[0:10000];
logic [XLEN-1:0] signature[0:10000];
logic [XLEN-1:0] testadr;
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW;
logic [XLEN-1:0] meminit;
string tests64ic[] = '{
"rv64ic/I-C-ADD-01", "3000",
"rv64ic/I-C-ADDI-01", "3000",
"rv64ic/I-C-ADDIW-01", "3000",
"rv64ic/I-C-ADDW-01", "3000",
"rv64ic/I-C-AND-01", "3000",
"rv64ic/I-C-ANDI-01", "3000",
"rv64ic/I-C-BEQZ-01", "3000",
"rv64ic/I-C-BNEZ-01", "3000",
"rv64ic/I-C-EBREAK-01", "2000",
"rv64ic/I-C-J-01", "3000",
"rv64ic/I-C-JALR-01", "4000",
"rv64ic/I-C-JR-01", "4000",
"rv64ic/I-C-LD-01", "3420",
"rv64ic/I-C-LDSP-01", "3420",
"rv64ic/I-C-LI-01", "3000",
"rv64ic/I-C-LUI-01", "2000",
"rv64ic/I-C-LW-01", "3110",
"rv64ic/I-C-LWSP-01", "3110",
"rv64ic/I-C-MV-01", "3000",
"rv64ic/I-C-NOP-01", "2000",
"rv64ic/I-C-OR-01", "3000",
"rv64ic/I-C-SD-01", "3000",
"rv64ic/I-C-SDSP-01", "3000",
"rv64ic/I-C-SLLI-01", "3000",
"rv64ic/I-C-SRAI-01", "3000",
"rv64ic/I-C-SRLI-01", "3000",
"rv64ic/I-C-SUB-01", "3000",
"rv64ic/I-C-SUBW-01", "3000",
"rv64ic/I-C-SW-01", "3000",
"rv64ic/I-C-SWSP-01", "3000",
"rv64ic/I-C-XOR-01", "3000"
};
string tests64iNOc[] = {
"rv64i/I-MISALIGN_JMP-01","2000"
};
string tests64i[] = '{
"rv64i/I-ADD-01", "3000",
"rv64i/I-ADDI-01", "3000",
"rv64i/I-ADDIW-01", "3000",
"rv64i/I-ADDW-01", "3000",
"rv64i/I-AND-01", "3000",
"rv64i/I-ANDI-01", "3000",
"rv64i/I-AUIPC-01", "3000",
"rv64i/I-BEQ-01", "4000",
"rv64i/I-BGE-01", "4000",
"rv64i/I-BGEU-01", "4000",
"rv64i/I-BLT-01", "4000",
"rv64i/I-BLTU-01", "4000",
"rv64i/I-BNE-01", "4000",
"rv64i/I-DELAY_SLOTS-01", "2000",
"rv64i/I-EBREAK-01", "2000",
"rv64i/I-ECALL-01", "2000",
"rv64i/I-ENDIANESS-01", "2010",
"rv64i/I-IO-01", "2050",
"rv64i/I-JAL-01", "3000",
"rv64i/I-JALR-01", "4000",
"rv64i/I-LB-01", "4020",
"rv64i/I-LBU-01", "4020",
"rv64i/I-LD-01", "4420",
"rv64i/I-LH-01", "4050",
"rv64i/I-LHU-01", "4050",
"rv64i/I-LUI-01", "2000",
"rv64i/I-LW-01", "4110",
"rv64i/I-LWU-01", "4110",
"rv64i/I-MISALIGN_LDST-01", "2010",
"rv64i/I-NOP-01", "2000",
"rv64i/I-OR-01", "3000",
"rv64i/I-ORI-01", "3000",
"rv64i/I-RF_size-01", "2000",
"rv64i/I-RF_width-01", "2000",
"rv64i/I-RF_x0-01", "2010",
"rv64i/I-SB-01", "4000",
"rv64i/I-SD-01", "4000",
"rv64i/I-SH-01", "4000",
"rv64i/I-SLL-01", "3000",
"rv64i/I-SLLI-01", "3000",
"rv64i/I-SLLIW-01", "3000",
"rv64i/I-SLLW-01", "3000",
"rv64i/I-SLT-01", "3000",
"rv64i/I-SLTI-01", "3000",
"rv64i/I-SLTIU-01", "3000",
"rv64i/I-SLTU-01", "3000",
"rv64i/I-SRA-01", "3000",
"rv64i/I-SRAI-01", "3000",
"rv64i/I-SRAIW-01", "3000",
"rv64i/I-SRAW-01", "3000",
"rv64i/I-SRL-01", "3000",
"rv64i/I-SRLI-01", "3000",
"rv64i/I-SRLIW-01", "3000",
"rv64i/I-SRLW-01", "3000",
"rv64i/I-SUB-01", "3000",
"rv64i/I-SUBW-01", "3000",
"rv64i/I-SW-01", "4000",
"rv64i/I-XOR-01", "3000",
"rv64i/I-XORI-01", "3000"
};
string tests32ic[] = '{
// "rv32ic/WALLY-C-ADHOC-01", "2000",
"rv32ic/I-C-ADD-01", "2000",
"rv32ic/I-C-ADDI-01", "2000",
"rv32ic/I-C-AND-01", "2000",
"rv32ic/I-C-ANDI-01", "2000",
"rv32ic/I-C-BEQZ-01", "2000",
"rv32ic/I-C-BNEZ-01", "2000",
"rv32ic/I-C-EBREAK-01", "2000",
"rv32ic/I-C-J-01", "2000",
"rv32ic/I-C-JALR-01", "3000",
"rv32ic/I-C-JR-01", "3000",
"rv32ic/I-C-LI-01", "2000",
"rv32ic/I-C-LUI-01", "2000",
"rv32ic/I-C-LW-01", "2110",
"rv32ic/I-C-LWSP-01", "2110",
"rv32ic/I-C-MV-01", "2000",
"rv32ic/I-C-NOP-01", "2000",
"rv32ic/I-C-OR-01", "2000",
"rv32ic/I-C-SLLI-01", "2000",
"rv32ic/I-C-SRAI-01", "2000",
"rv32ic/I-C-SRLI-01", "2000",
"rv32ic/I-C-SUB-01", "2000",
"rv32ic/I-C-SW-01", "2000",
"rv32ic/I-C-SWSP-01", "2000",
"rv32ic/I-C-XOR-01", "2000"
};
string tests32iNOc[] = {
"rv32i/I-MISALIGN_JMP-01","2000"
};
string tests32i[] = {
"rv32i/I-ADD-01", "2000",
"rv32i/I-ADDI-01","2000",
"rv32i/I-AND-01","2000",
"rv32i/I-ANDI-01","2000",
"rv32i/I-AUIPC-01","2000",
"rv32i/I-BEQ-01","3000",
"rv32i/I-BGE-01","3000",
"rv32i/I-BGEU-01","3000",
"rv32i/I-BLT-01","3000",
"rv32i/I-BLTU-01","3000",
"rv32i/I-BNE-01","3000",
"rv32i/I-DELAY_SLOTS-01","2000",
"rv32i/I-EBREAK-01","2000",
"rv32i/I-ECALL-01","2000",
"rv32i/I-ENDIANESS-01","2010",
"rv32i/I-IO-01","2030",
"rv32i/I-JAL-01","3000",
"rv32i/I-JALR-01","3000",
"rv32i/I-LB-01","3020",
"rv32i/I-LBU-01","3020",
"rv32i/I-LH-01","3050",
"rv32i/I-LHU-01","3050",
"rv32i/I-LUI-01","2000",
"rv32i/I-LW-01","3110",
"rv32i/I-MISALIGN_LDST-01","2010",
"rv32i/I-NOP-01","2000",
"rv32i/I-OR-01","2000",
"rv32i/I-ORI-01","2000",
"rv32i/I-RF_size-01","2000",
"rv32i/I-RF_width-01","2000",
"rv32i/I-RF_x0-01","2010",
"rv32i/I-SB-01","3000",
"rv32i/I-SH-01","3000",
"rv32i/I-SLL-01","2000",
"rv32i/I-SLLI-01","2000",
"rv32i/I-SLT-01","2000",
"rv32i/I-SLTI-01","2000",
"rv32i/I-SLTIU-01","2000",
"rv32i/I-SLTU-01","2000",
"rv32i/I-SRA-01","2000",
"rv32i/I-SRAI-01","2000",
"rv32i/I-SRL-01","2000",
"rv32i/I-SRLI-01","2000",
"rv32i/I-SUB-01","2000",
"rv32i/I-SW-01","3000",
"rv32i/I-XOR-01","2000",
"rv32i/I-XORI-01","2000"
};
string tests[];
// pick tests based on modes supported
initial
if (XLEN == 64) begin // RV64
tests = {tests64i};
if (`C_SUPPORTED % 2 == 1) tests = {tests, tests64ic};
else tests = {tests, tests64iNOc};
end else begin // RV32
tests = {tests32i};
if (`C_SUPPORTED % 2 == 1) tests = {tests, tests32ic};
else tests = {tests, tests32iNOc};
end
string signame, memfilename;
// instantiate device to be tested
wallypipelined #(XLEN, MISA, ZCSR, ZCOUNTERS) dut(clk, reset, WriteData, DataAdr, MemRW);
// Track names of instructions
instrTrackerTB #(XLEN) it(clk, reset, dut.hart.dp.FlushE,
dut.hart.dp.InstrDecompD, dut.hart.dp.InstrE,
dut.hart.dp.InstrM, InstrW,
InstrDName, InstrEName, InstrMName, InstrWName);
// initialize test
initial
begin
test = 0;
totalerrors = 0;
testadr = 0;
// fill memory with defined values to reduce Xs in simulation
if (XLEN == 32) meminit = 32'hFEDC0123;
else meminit = 64'hFEDCBA9876543210;
for (i=0; i<=65535; i = i+1) begin
//dut.imem.RAM[i] = meminit;
// dut.dmem.RAM[i] = meminit;
end
// read test vectors into memory
memfilename = {"../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.dmem.dtim.RAM);
reset = 1; # 22; reset = 0;
end
// generate clock to sequence tests
always
begin
clk = 1; # 5; clk = 0; # 5;
end
// check results
always @(negedge clk)
begin
if (dut.hart.dp.priv.EcallFaultM &&
(dut.hart.dp.regf.rf[3] == 1 || (dut.hart.dp.regf.we3 && dut.hart.dp.regf.a3 == 3 && dut.hart.dp.regf.wd3 == 1))) begin
$display("Code ended with ecall with gp = 1");
#60; // give time for instructions in pipeline to finish
// clear signature to prevent contamination from previous tests
for(i=0; i<10000; i=i+1) begin
sig32[i] = 'bx;
end
// read signature, reformat in 64 bits if necessary
signame = {"../imperas-riscv-tests/work/", tests[test], ".signature.output"};
$readmemh(signame, sig32);
i = 0;
while (i < 10000) begin
if (XLEN == 32) begin
signature[i] = sig32[i];
i = i+1;
end else begin
signature[i/2] = {sig32[i+1], sig32[i]};
i = i + 2;
end
end
// Check errors
i = 0;
errors = 0;
if (XLEN == 32)
testadr = tests[test+1].atohex()/4;
else
testadr = tests[test+1].atohex()/8;
/* verilator lint_off INFINITELOOP */
while (signature[i] !== 'bx) begin
//$display("signature[%h] = %h", i, signature[i]);
if (signature[i] !== dut.dmem.dtim.RAM[testadr+i]) begin
if (signature[i+4] !== 'bx || signature[i] !== 32'hFFFFFFFF) begin
// report errors unless they are garbage at the end of the sim
// kind of hacky test for garbage right now
errors = errors+1;
$display(" Error on test %s result %d: adr = %h sim = %h, signature = %h",
tests[test], i, (testadr+i)*XLEN/8, dut.dmem.dtim.RAM[testadr+i], signature[i]);
end
end
i = i + 1;
end
/* verilator lint_on INFINITELOOP */
if (errors == 0) $display("%s succeeded. Brilliant!!!", tests[test]);
else begin
$display("%s failed with %d errors. :(", tests[test], errors);
totalerrors = totalerrors+1;
end
test = test + 2;
if (test == tests.size()) begin
if (totalerrors == 0) $display("SUCCESS! All tests ran without failures.");
else $display("FAIL: %d test programs had errors", totalerrors);
$stop;
end
else begin
memfilename = {"../imperas-riscv-tests/work/", tests[test], ".elf.memfile"};
$readmemh(memfilename, dut.imem.RAM);
$readmemh(memfilename, dut.dmem.dtim.RAM);
$display("Read memfile %s", memfilename);
reset = 1; # 17; reset = 0;
end
end
end
endmodule
/* verilator lint_on STMTDLY */
/* verilator lint_on WIDTH */
module instrTrackerTB #(parameter XLEN=32) (
input logic clk, reset, FlushE,
input logic [31:0] InstrD,
input logic [31:0] InstrE, InstrM,
output logic [31:0] InstrW,
output string InstrDName, InstrEName, InstrMName, InstrWName);
// stage Instr to Writeback for visualization
flopr #(32) InstrWReg(clk, reset, InstrM, InstrW);
instrNameDecTB ddec(InstrD, InstrDName);
instrNameDecTB edec(InstrE, InstrEName);
instrNameDecTB mdec(InstrM, InstrMName);
instrNameDecTB wdec(InstrW, InstrWName);
endmodule
// decode the instruction name, to help the test bench
module instrNameDecTB(
input logic [31:0] instr,
output string name);
logic [6:0] op;
logic [2:0] funct3;
logic [6:0] funct7;
logic [11:0] imm;
assign op = instr[6:0];
assign funct3 = instr[14:12];
assign funct7 = instr[31:25];
assign imm = instr[31:20];
// it would be nice to add the operands to the name
// create another variable called decoded
always_comb
casez({op, funct3})
10'b0000000_000: name = "BAD";
10'b0000011_000: name = "LB";
10'b0000011_001: name = "LH";
10'b0000011_010: name = "LW";
10'b0000011_011: name = "LD";
10'b0000011_100: name = "LBU";
10'b0000011_101: name = "LHU";
10'b0000011_110: name = "LWU";
10'b0010011_000: if (instr[31:15] == 0 && instr[11:7] ==0) name = "NOP/FLUSH";
else name = "ADDI";
10'b0010011_001: if (funct7[6:1] == 6'b000000) name = "SLLI";
else name = "ILLEGAL";
10'b0010011_010: name = "SLTI";
10'b0010011_011: name = "SLTIU";
10'b0010011_100: name = "XORI";
10'b0010011_101: if (funct7[6:1] == 6'b000000) name = "SRLI";
else if (funct7[6:1] == 6'b010000) name = "SRAI";
else name = "ILLEGAL";
10'b0010011_110: name = "ORI";
10'b0010011_111: name = "ANDI";
10'b0010111_???: name = "AUIPC";
10'b0100011_000: name = "SB";
10'b0100011_001: name = "SH";
10'b0100011_010: name = "SW";
10'b0100011_011: name = "SD";
10'b0011011_000: name = "ADDIW";
10'b0011011_001: name = "SLLIW";
10'b0011011_101: if (funct7 == 7'b0000000) name = "SRLIW";
else if (funct7 == 7'b0100000) name = "SRAIW";
else name = "ILLEGAL";
10'b0111011_000: if (funct7 == 7'b0000000) name = "ADDW";
else if (funct7 == 7'b0100000) name = "SUBW";
else name = "ILLEGAL";
10'b0111011_001: name = "SLLW";
10'b0111011_101: if (funct7 == 7'b0000000) name = "SRLW";
else if (funct7 == 7'b0100000) name = "SRAW";
else name = "ILLEGAL";
10'b0110011_000: if (funct7 == 7'b0000000) name = "ADD";
else if (funct7 == 7'b0000001) name = "MUL";
else if (funct7 == 7'b0100000) name = "SUB";
else name = "ILLEGAL";
10'b0110011_001: if (funct7 == 7'b0000000) name = "SLL";
else if (funct7 == 7'b0000001) name = "MULH";
else name = "ILLEGAL";
10'b0110011_010: if (funct7 == 7'b0000000) name = "SLT";
else if (funct7 == 7'b0000001) name = "MULHSU";
else name = "ILLEGAL";
10'b0110011_011: if (funct7 == 7'b0000000) name = "SLTU";
else if (funct7 == 7'b0000001) name = "DIV";
else name = "ILLEGAL";
10'b0110011_100: if (funct7 == 7'b0000000) name = "XOR";
else if (funct7 == 7'b0000001) name = "MUL";
else name = "ILLEGAL";
10'b0110011_101: if (funct7 == 7'b0000000) name = "SRL";
else if (funct7 == 7'b0000001) name = "DIVU";
else if (funct7 == 7'b0100000) name = "SRA";
else name = "ILLEGAL";
10'b0110011_110: if (funct7 == 7'b0000000) name = "OR";
else if (funct7 == 7'b0000001) name = "REM";
else name = "ILLEGAL";
10'b0110011_111: if (funct7 == 7'b0000000) name = "AND";
else if (funct7 == 7'b0000001) name = "REMU";
else name = "ILLEGAL";
10'b0110111_???: name = "LUI";
10'b1100011_000: name = "BEQ";
10'b1100011_001: name = "BNE";
10'b1100011_100: name = "BLT";
10'b1100011_101: name = "BGE";
10'b1100011_110: name = "BLTU";
10'b1100011_111: name = "BGEU";
10'b1100111_000: name = "JALR";
10'b1101111_???: name = "JAL";
10'b1110011_000: if (imm == 0) name = "ECALL";
else if (imm == 1) name = "EBREAK";
else if (imm == 2) name = "URET";
else if (imm == 258) name = "SRET";
else if (imm == 770) name = "MRET";
else name = "ILLEGAL";
10'b1110011_001: name = "CSRRW";
10'b1110011_010: name = "CSRRS";
10'b1110011_011: name = "CSRRC";
10'b1110011_101: name = "CSRRWI";
10'b1110011_110: name = "CSRRSI";
10'b1110011_111: name = "CSRRCI";
10'b0001111_???: name = "FENCE";
default: name = "ILLEGAL";
endcase
endmodule

117
wally-pipelined/src/trap.sv Normal file
View File

@ -0,0 +1,117 @@
///////////////////////////////////////////
// trap.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Handle Traps: Exceptions and Interrupt
// See RISC-V Privileged Mode Specification 20190608 3.1.10-11
//
// 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-macros.sv"
module trap #(parameter XLEN=32, MISA=0) (
input logic clk, reset,
input logic InstrMisalignedFaultM, InstrAccessFaultM, IllegalInstrFaultM,
input logic BreakpointFaultM, LoadMisalignedFaultM, StoreMisalignedFaultM,
input logic LoadAccessFaultM, StoreAccessFaultM, EcallFaultM, InstrPageFaultM,
input logic LoadPageFaultM, StorePageFaultM,
input logic mretM, sretM, uretM,
input logic [1:0] PrivilegeModeW, NextPrivilegeModeM,
input logic [XLEN-1:0] MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW,
input logic [11:0] MIP_REGW, MIE_REGW,
input logic STATUS_MIE, STATUS_SIE,
input logic [XLEN-1:0] InstrMisalignedAdrM, ALUResultM,
input logic [31:0] InstrM,
output logic TrapM, MTrapM, STrapM, UTrapM, RetM,
output logic [XLEN-1:0] PrivilegedNextPCM, CauseM, NextFaultMtvalM
// output logic [11:0] MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW,
// input logic WriteMIPM, WriteSIPM, WriteUIPM, WriteMIEM, WriteSIEM, WriteUIEM
);
logic [11:0] MIntGlobalEnM, SIntGlobalEnM, PendingIntsM;
logic InterruptM;
// Determine pending enabled interrupts
assign MIntGlobalEnM = (PrivilegeModeW != `M_MODE) || STATUS_MIE; // if M ints enabled or lower priv 3.1.9
assign SIntGlobalEnM = (PrivilegeModeW == `U_MODE) || STATUS_SIE; // if S ints enabled or lower priv 3.1.9
assign PendingIntsM = (MIP_REGW & MIE_REGW) & ((MIntGlobalEnM & 12'h888) | (SIntGlobalEnM & 12'h222));
assign InterruptM = |PendingIntsM; // interrupt if any sources are pending
// Trigger Traps and RET
assign TrapM = InstrMisalignedFaultM | InstrAccessFaultM | IllegalInstrFaultM |
BreakpointFaultM | LoadMisalignedFaultM | StoreMisalignedFaultM |
LoadAccessFaultM | StoreAccessFaultM | EcallFaultM | InstrPageFaultM |
LoadPageFaultM | StorePageFaultM | InterruptM;
assign MTrapM = TrapM & (NextPrivilegeModeM == `M_MODE);
assign STrapM = TrapM & (NextPrivilegeModeM == `S_MODE) & `S_SUPPORTED;
assign UTrapM = TrapM & (NextPrivilegeModeM == `U_MODE) & `N_SUPPORTED;
assign RetM = mretM | sretM | uretM;
always_comb
if (mretM) PrivilegedNextPCM = MEPC_REGW;
else if (sretM) PrivilegedNextPCM = SEPC_REGW;
else if (uretM) PrivilegedNextPCM = UEPC_REGW;
else if (NextPrivilegeModeM == `U_MODE) PrivilegedNextPCM = UTVEC_REGW;
else if (NextPrivilegeModeM == `S_MODE) PrivilegedNextPCM = STVEC_REGW;
else PrivilegedNextPCM = MTVEC_REGW;
// Cause priority defined in table 3.7 of 20190608 privileged spec
// Exceptions are of lower priority than all interrupts (3.1.9)
always_comb
if (reset) CauseM = 0; // hard reset 3.3
else if (PendingIntsM[11]) CauseM = (1 << (XLEN-1)) + 11; // Machine External Int
else if (PendingIntsM[3]) CauseM = (1 << (XLEN-1)) + 3; // Machine Sw Int
else if (PendingIntsM[7]) CauseM = (1 << (XLEN-1)) + 7; // Machine Timer Int
else if (PendingIntsM[9]) CauseM = (1 << (XLEN-1)) + 9; // Supervisor External Int
else if (PendingIntsM[1]) CauseM = (1 << (XLEN-1)) + 1; // Supervisor Sw Int
else if (PendingIntsM[5]) CauseM = (1 << (XLEN-1)) + 5; // Supervisor Timer Int
else if (InstrPageFaultM) CauseM = 12;
else if (InstrAccessFaultM) CauseM = 1;
else if (InstrMisalignedFaultM) CauseM = 0;
else if (IllegalInstrFaultM) CauseM = 2;
else if (BreakpointFaultM) CauseM = 3;
else if (EcallFaultM) CauseM = {{(XLEN-2){1'b0}}, PrivilegeModeW} + 8;
else if (LoadMisalignedFaultM) CauseM = 4;
else if (StoreMisalignedFaultM) CauseM = 6;
else if (LoadPageFaultM) CauseM = 13;
else if (StorePageFaultM) CauseM = 15;
else if (LoadAccessFaultM) CauseM = 5;
else if (StoreAccessFaultM) CauseM = 7;
else CauseM = 0;
// MTVAL
// 3.1.17: on instruction fetch, load, or store address misaligned access or page fault
// mtval is written with the faulting virtual address.
// On illegal instruction trap, mtval may be written with faulting instruction
// For other traps (including interrupts), mtval is set to 0
// *** hardware breakpoint is supposed to write faulting virtual address per priv p. 38
// *** Page faults not yet implemented
// Technically
always_comb
if (InstrMisalignedFaultM) NextFaultMtvalM = InstrMisalignedAdrM;
else if (LoadMisalignedFaultM) NextFaultMtvalM = ALUResultM;
else if (StoreMisalignedFaultM) NextFaultMtvalM = ALUResultM;
else if (InstrPageFaultM) NextFaultMtvalM = 0; // *** implement
else if (LoadPageFaultM) NextFaultMtvalM = ALUResultM;
else if (StorePageFaultM) NextFaultMtvalM = ALUResultM;
else if (IllegalInstrFaultM) NextFaultMtvalM = {{(XLEN-32){1'b0}}, InstrM};
else NextFaultMtvalM = 0;
endmodule

View File

@ -0,0 +1,24 @@
// wally-macros.sv
// David_Harris@hmc.edu 5 January 2021
// Macros to determine which mode is supported based on MISA
`define A_SUPPORTED ((MISA >> 0) % 2 == 1)
`define C_SUPPORTED ((MISA >> 2) % 2 == 1)
`define D_SUPPORTED ((MISA >> 3) % 2 == 1)
`define F_SUPPORTED ((MISA >> 5) % 2 == 1)
`define M_SUPPORTED ((MISA >> 12) % 2 == 1)
`define S_SUPPORTED ((MISA >> 18) % 2 == 1)
`define U_SUPPORTED ((MISA >> 20) % 2 == 1)
`define ZCSR_SUPPORTED (ZCSR != 0)
`define ZCOUNTERS_SUPPORTED (ZCOUNTERS != 0)
// N-mode user-level interrupts are depricated per Andrew Waterman 1/13/21
//`define N_SUPPORTED ((MISA >> 13) % 2 == 1)
`define N_SUPPORTED 0
`define M_MODE (2'b11)
`define S_MODE (2'b01)
`define U_MODE (2'b00)
/* verilator lint_off STMTDLY */
/* verilator lint_off WIDTH */

View File

@ -0,0 +1,75 @@
///////////////////////////////////////////
// wally-pipelined.sv
//
// Written: David_Harris@hmc.edu 6 November 2020
// Modified:
//
// Purpose: Top level module for pipelined processor and memories
// Full RV32/64IC instruction set
//
// To Do:
// Sort out terminology of faults, traps, interrputs, exceptions
// Long names for instruction decoder
// *Consitency in capitalizaiton
// *Divide into many files
// *Keep lint clean
// *Put in git repo
// Sort out memory map
// *Automate testing based on MISA
// Drop Funct3 from Controller pipeline if not needed
// Finish exceptions & test
// *Flushes caused by exceptions
// Generate statements to reduce hardware for unneeded exception logic
// *RET
// *Status register
// Misaligned instruction faults on other aults
//
//
// Note: the CSRs do not support the following features
//- Disabling portions of the instruction set with bits of the MISA register
//- Changing from RV64 to RV32 by writing the SXL/UXL bits of the STATUS register
// As of January 2020, virtual memory is not yet supported
//
// Reference MISA Values:
// 104: C compressed
//
// 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-macros.sv"
module wallypipelined #(parameter XLEN=32, MISA=0, ZCSR = 1, ZCOUNTERS = 1) (
input logic clk, reset,
output logic [XLEN-1:0] WriteDataM, DataAdrM,
output logic [1:0] MemRWM);
logic [XLEN-1:0] PCF, ReadDataM;
logic [31:0] InstrF;
logic [7:0] ByteMaskM;
logic InstrAccessFaultF, DataAccessFaultM;
logic TimerIntM, SwIntM; // from CLINT
logic ExtIntM = 0; // not yet connected
// instantiate processor and memories
wallypipelinedhart #(XLEN, MISA, ZCSR, ZCOUNTERS) hart(
clk, reset, PCF, InstrF, MemRWM, ByteMaskM, DataAdrM,
WriteDataM, ReadDataM, TimerIntM, ExtIntM, SwIntM, InstrAccessFaultF, DataAccessFaultM);
imem #(XLEN) imem(PCF, InstrF, InstrAccessFaultF);
dmem #(XLEN) dmem(clk, reset, MemRWM, ByteMaskM, DataAdrM, WriteDataM, ReadDataM,
DataAccessFaultM, TimerIntM, SwIntM);
endmodule

View File

@ -0,0 +1,100 @@
///////////////////////////////////////////
// wallypipelinedhart.sv
//
// Written: David_Harris@hmc.edu 9 January 2021
// Modified:
//
// Purpose: Pipelined RISC-V Processor
//
// 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-macros.sv"
module wallypipelinedhart #(parameter XLEN=32, MISA=0, ZCSR = 1, ZCOUNTERS = 1) (
input logic clk, reset,
output logic [XLEN-1:0] PCF,
input logic [31:0] InstrF,
output logic [1:0] MemRWM,
output logic [7:0] ByteMaskM,
output logic [XLEN-1:0] ALUResultM, WriteDataM,
input logic [XLEN-1:0] ReadDataM,
input logic TimerIntM, ExtIntM, SwIntM,
input logic InstrAccessFaultF,
input logic DataAccessFaultM);
logic [6:0] opD;
logic [2:0] funct3D;
logic funct7b5D;
logic [2:0] ImmSrcD;
logic IllegalCompInstrD;
logic [2:0] FlagsE;
logic PCSrcE;
logic [4:0] ALUControlE;
logic ALUSrcAE, ALUSrcBE;
logic MemReadE;
logic RegWriteM;
logic CSRWriteM;
logic PrivilegedM;
logic IllegalInstrFaultM;
logic InstrAccessFaultM;
logic [2:0] Funct3M;
logic [1:0] ResultSrcW;
logic RegWriteW;
logic InstrValidW, LoadStallD;
logic CSRWritePendingDEM;
logic InstrMisalignedFaultM;
logic [1:0] ForwardAE, ForwardBE;
logic StallF, StallD, FlushD, FlushE, FlushM, FlushW;
logic PrivilegedChangePCM, TrapM;
logic [4:0] Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW;
logic TargetSrcE;
logic [4:0] SetFflagsM;
logic [2:0] FRM_REGW;
logic FloatRegWriteW;
controller c(clk, reset,
opD, funct3D, funct7b5D, ImmSrcD,
StallD, FlushD, IllegalCompInstrD,
FlushE, FlagsE, PCSrcE, ALUControlE, ALUSrcAE, ALUSrcBE, TargetSrcE, MemReadE,
FlushM, MemRWM, CSRWriteM, PrivilegedM, IllegalInstrFaultM, Funct3M, RegWriteM,
FlushW, RegWriteW, ResultSrcW, InstrValidW, CSRWritePendingDEM,
InstrAccessFaultF, InstrAccessFaultM);
datapath #(XLEN, MISA, ZCSR, ZCOUNTERS)
dp(clk, reset,
StallF, PCF, InstrF,
opD, funct3D, funct7b5D, StallD, FlushD, ImmSrcD, LoadStallD, IllegalCompInstrD,
FlushE, ForwardAE, ForwardBE, PCSrcE, ALUControlE, ALUSrcAE, ALUSrcBE, TargetSrcE, FlagsE,
FlushM, MemRWM, CSRWriteM, PrivilegedM, InstrAccessFaultM, IllegalInstrFaultM,
TimerIntM, ExtIntM, SwIntM, InstrMisalignedFaultM,
Funct3M, WriteDataM, ALUResultM, ReadDataM, ByteMaskM, PrivilegedChangePCM, TrapM,
SetFflagsM, DataAccessFaultM,
FlushW, RegWriteW, ResultSrcW, InstrValidW, FloatRegWriteW, FRM_REGW,
Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW);
// add FPU here, with SetFflagsM, FRM_REGW
// presently stub out SetFlagsM and FloatRegWriteW
assign SetFflagsM = 0;
assign FloatRegWriteW = 0;
hazard hz(Rs1D, Rs2D, Rs1E, Rs2E, RdE, RdM, RdW,
PCSrcE, MemReadE, RegWriteM, RegWriteW, CSRWritePendingDEM, PrivilegedChangePCM, TrapM,
ForwardAE, ForwardBE, StallF, StallD, FlushD, FlushE, FlushM, FlushW, LoadStallD);
endmodule

View File

@ -0,0 +1,38 @@
# wally-pipelined-batch.do
#
# Modification by Oklahoma State University & Harvey Mudd College
# Use with Testbench
# James Stine, 2008; David Harris 2021
# Go Cowboys!!!!!!
#
# Takes 1:10 to run RV64IC tests using gui
# 11 seconds to run batch mode
# Use this wally-pipelined.do file to run this example.
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
# do wally-pipelined.do
# or, to run from a shell, type the following at the shell prompt:
# vsim -do wally-pipelined.do -c
# (omit the "-c" to see the GUI while running from the shell)
onbreak {resume}
# create library
if [file exists work] {
vdel -all
}
vlib work
# compile source files
# suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
vlog src/*.sv -suppress 2583
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt work.testbench -o workopt
vsim workopt
run -all
quit

View File

@ -0,0 +1,91 @@
# wally-pipelined.do
#
# Modification by Oklahoma State University & Harvey Mudd College
# Use with Testbench
# James Stine, 2008; David Harris 2021
# Go Cowboys!!!!!!
#
# Takes 1:10 to run RV64IC tests using gui
# Use this wally-pipelined.do file to run this example.
# Either bring up ModelSim and type the following at the "ModelSim>" prompt:
# do wally-pipelined.do
# or, to run from a shell, type the following at the shell prompt:
# vsim -do wally-pipelined.do -c
# (omit the "-c" to see the GUI while running from the shell)
onbreak {resume}
# create library
if [file exists work] {
vdel -all
}
vlib work
# compile source files
# suppress spurious warnngs about
# "Extra checking for conflicts with always_comb done at vopt time"
# because vsim will run vopt
vlog src/*.sv -suppress 2583
# start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt +acc work.testbench -o workopt
vsim workopt
view wave
-- display input and output signals as hexidecimal values
# Diplays All Signals recursively
add wave /testbench/clk
add wave /testbench/reset
add wave -divider
add wave -hex /testbench/dut/hart/dp/PCF
add wave -hex /testbench/dut/hart/dp/InstrF
add wave /testbench/InstrFName
#add wave -hex /testbench/dut/hart/dp/PCD
add wave -hex /testbench/dut/hart/dp/InstrD
add wave /testbench/InstrDName
add wave -divider
#add wave -hex /testbench/dut/hart/dp/PCE
#add wave -hex /testbench/dut/hart/dp/InstrE
add wave /testbench/InstrEName
add wave -hex /testbench/dut/hart/dp/SrcAE
add wave -hex /testbench/dut/hart/dp/SrcBE
add wave -hex /testbench/dut/hart/dp/ALUResultE
add wave /testbench/dut/hart/dp/PCSrcE
add wave -divider
#add wave -hex /testbench/dut/hart/dp/PCM
#add wave -hex /testbench/dut/hart/dp/InstrM
add wave /testbench/InstrMName
add wave /testbench/dut/dmem/dtim/memwrite
add wave -hex /testbench/dut/dmem/AdrM
add wave -hex /testbench/dut/dmem/WdM
add wave -divider
add wave -hex /testbench/dut/hart/dp/PCW
#add wave -hex /testbench/dut/hart/dp/InstrW
add wave /testbench/InstrWName
add wave /testbench/dut/hart/dp/RegWriteW
add wave -hex /testbench/dut/hart/dp/ResultW
add wave -hex /testbench/dut/hart/dp/RdW
add wave -divider
#add ww
add wave -hex -r /testbench/*
-- Set Wave Output Items
TreeUpdate [SetDefaultTree]
WaveRestoreZoom {0 ps} {100 ps}
configure wave -namecolwidth 250
configure wave -valuecolwidth 120
configure wave -justifyvalue left
configure wave -signalnamewidth 0
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
set DefaultRadix hexadecimal
-- Run the Simulation
#run 1000
run -all
#quit

13
wally-pipelined/wally.old Normal file
View File

@ -0,0 +1,13 @@
// riscvfullpipelined.sv
`include "wally-macros.sv"