diff --git a/LICENSE b/LICENSE index 456dceb8..21432e09 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ 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 of this software and associated documentation files (the "Software"), to deal diff --git a/riscv-o3 b/riscv-o3 new file mode 160000 index 00000000..afb27bd5 --- /dev/null +++ b/riscv-o3 @@ -0,0 +1 @@ +Subproject commit afb27bd558a9b6fabb6b768ae81ef122b4db9eea diff --git a/wally-pipelined/.#modelsim.ini b/wally-pipelined/.#modelsim.ini new file mode 120000 index 00000000..ce45fa11 --- /dev/null +++ b/wally-pipelined/.#modelsim.ini @@ -0,0 +1 @@ +harris@Tera.Eng.HMC.Edu.6921:1604012407 \ No newline at end of file diff --git a/wally-pipelined/sim-wally b/wally-pipelined/sim-wally new file mode 100755 index 00000000..a7bfe373 --- /dev/null +++ b/wally-pipelined/sim-wally @@ -0,0 +1 @@ +vsim -do wally-pipelined.do diff --git a/wally-pipelined/sim-wally-batch b/wally-pipelined/sim-wally-batch new file mode 100755 index 00000000..27cd41d7 --- /dev/null +++ b/wally-pipelined/sim-wally-batch @@ -0,0 +1 @@ +vsim -c -do wally-pipelined-batch.do diff --git a/wally-pipelined/src/alu.sv b/wally-pipelined/src/alu.sv new file mode 100644 index 00000000..3abf601f --- /dev/null +++ b/wally-pipelined/src/alu.sv @@ -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 + diff --git a/wally-pipelined/src/clint.sv b/wally-pipelined/src/clint.sv new file mode 100644 index 00000000..9f709840 --- /dev/null +++ b/wally-pipelined/src/clint.sv @@ -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 + diff --git a/wally-pipelined/src/controller.sv b/wally-pipelined/src/controller.sv new file mode 100644 index 00000000..7b0b8925 --- /dev/null +++ b/wally-pipelined/src/controller.sv @@ -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 diff --git a/wally-pipelined/src/csr.sv b/wally-pipelined/src/csr.sv new file mode 100644 index 00000000..9a827313 --- /dev/null +++ b/wally-pipelined/src/csr.sv @@ -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 diff --git a/wally-pipelined/src/csrc.sv b/wally-pipelined/src/csrc.sv new file mode 100644 index 00000000..f523d110 --- /dev/null +++ b/wally-pipelined/src/csrc.sv @@ -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 + diff --git a/wally-pipelined/src/csri.sv b/wally-pipelined/src/csri.sv new file mode 100644 index 00000000..75448011 --- /dev/null +++ b/wally-pipelined/src/csri.sv @@ -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 diff --git a/wally-pipelined/src/csrm.sv b/wally-pipelined/src/csrm.sv new file mode 100644 index 00000000..efb190e4 --- /dev/null +++ b/wally-pipelined/src/csrm.sv @@ -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 diff --git a/wally-pipelined/src/csrn.sv b/wally-pipelined/src/csrn.sv new file mode 100644 index 00000000..1ef6164d --- /dev/null +++ b/wally-pipelined/src/csrn.sv @@ -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 \ No newline at end of file diff --git a/wally-pipelined/src/csrs.sv b/wally-pipelined/src/csrs.sv new file mode 100644 index 00000000..f1b9571b --- /dev/null +++ b/wally-pipelined/src/csrs.sv @@ -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 diff --git a/wally-pipelined/src/csrsr.sv b/wally-pipelined/src/csrsr.sv new file mode 100644 index 00000000..7a27b9ac --- /dev/null +++ b/wally-pipelined/src/csrsr.sv @@ -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 \ No newline at end of file diff --git a/wally-pipelined/src/csru.sv b/wally-pipelined/src/csru.sv new file mode 100644 index 00000000..bf91a79f --- /dev/null +++ b/wally-pipelined/src/csru.sv @@ -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 \ No newline at end of file diff --git a/wally-pipelined/src/datapath.sv b/wally-pipelined/src/datapath.sv new file mode 100644 index 00000000..dc549bb4 --- /dev/null +++ b/wally-pipelined/src/datapath.sv @@ -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 diff --git a/wally-pipelined/src/dmem.sv b/wally-pipelined/src/dmem.sv new file mode 100644 index 00000000..dbe1401e --- /dev/null +++ b/wally-pipelined/src/dmem.sv @@ -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 + diff --git a/wally-pipelined/src/dtim.sv b/wally-pipelined/src/dtim.sv new file mode 100644 index 00000000..8c15edcd --- /dev/null +++ b/wally-pipelined/src/dtim.sv @@ -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 + diff --git a/wally-pipelined/src/extend.sv b/wally-pipelined/src/extend.sv new file mode 100644 index 00000000..63452e77 --- /dev/null +++ b/wally-pipelined/src/extend.sv @@ -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 diff --git a/wally-pipelined/src/flop.sv b/wally-pipelined/src/flop.sv new file mode 100644 index 00000000..904ed6fd --- /dev/null +++ b/wally-pipelined/src/flop.sv @@ -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 diff --git a/wally-pipelined/src/hazard.sv b/wally-pipelined/src/hazard.sv new file mode 100644 index 00000000..ad9ae1af --- /dev/null +++ b/wally-pipelined/src/hazard.sv @@ -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 diff --git a/wally-pipelined/src/imem.sv b/wally-pipelined/src/imem.sv new file mode 100644 index 00000000..6104b74f --- /dev/null +++ b/wally-pipelined/src/imem.sv @@ -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 + diff --git a/wally-pipelined/src/instrDecompress.sv b/wally-pipelined/src/instrDecompress.sv new file mode 100644 index 00000000..51bf7024 --- /dev/null +++ b/wally-pipelined/src/instrDecompress.sv @@ -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 + \ No newline at end of file diff --git a/wally-pipelined/src/memdp.sv b/wally-pipelined/src/memdp.sv new file mode 100644 index 00000000..932e1cc1 --- /dev/null +++ b/wally-pipelined/src/memdp.sv @@ -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 diff --git a/wally-pipelined/src/mux.sv b/wally-pipelined/src/mux.sv new file mode 100644 index 00000000..fbb5cc39 --- /dev/null +++ b/wally-pipelined/src/mux.sv @@ -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 + diff --git a/wally-pipelined/src/pcadder.sv b/wally-pipelined/src/pcadder.sv new file mode 100644 index 00000000..bc13712f --- /dev/null +++ b/wally-pipelined/src/pcadder.sv @@ -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 + diff --git a/wally-pipelined/src/pclogic.sv b/wally-pipelined/src/pclogic.sv new file mode 100644 index 00000000..be9a62e4 --- /dev/null +++ b/wally-pipelined/src/pclogic.sv @@ -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 + diff --git a/wally-pipelined/src/privilegeDecoder.sv b/wally-pipelined/src/privilegeDecoder.sv new file mode 100644 index 00000000..784bb749 --- /dev/null +++ b/wally-pipelined/src/privilegeDecoder.sv @@ -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 diff --git a/wally-pipelined/src/privilegeModeReg.sv b/wally-pipelined/src/privilegeModeReg.sv new file mode 100644 index 00000000..ae4cd04c --- /dev/null +++ b/wally-pipelined/src/privilegeModeReg.sv @@ -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 diff --git a/wally-pipelined/src/privileged.sv b/wally-pipelined/src/privileged.sv new file mode 100644 index 00000000..563a3181 --- /dev/null +++ b/wally-pipelined/src/privileged.sv @@ -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 + + + + diff --git a/wally-pipelined/src/regfile.sv b/wally-pipelined/src/regfile.sv new file mode 100644 index 00000000..a92497d0 --- /dev/null +++ b/wally-pipelined/src/regfile.sv @@ -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 diff --git a/wally-pipelined/src/shifter.sv b/wally-pipelined/src/shifter.sv new file mode 100644 index 00000000..374584c7 --- /dev/null +++ b/wally-pipelined/src/shifter.sv @@ -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 + + diff --git a/wally-pipelined/src/testbench.sv b/wally-pipelined/src/testbench.sv new file mode 100644 index 00000000..91c77217 --- /dev/null +++ b/wally-pipelined/src/testbench.sv @@ -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 diff --git a/wally-pipelined/src/trap.sv b/wally-pipelined/src/trap.sv new file mode 100644 index 00000000..6bffecbf --- /dev/null +++ b/wally-pipelined/src/trap.sv @@ -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 \ No newline at end of file diff --git a/wally-pipelined/src/wally-macros.sv b/wally-pipelined/src/wally-macros.sv new file mode 100644 index 00000000..9ff61617 --- /dev/null +++ b/wally-pipelined/src/wally-macros.sv @@ -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 */ diff --git a/wally-pipelined/src/wallypipelined.sv b/wally-pipelined/src/wallypipelined.sv new file mode 100644 index 00000000..e57fcc36 --- /dev/null +++ b/wally-pipelined/src/wallypipelined.sv @@ -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 \ No newline at end of file diff --git a/wally-pipelined/src/wallypipelinedhart.sv b/wally-pipelined/src/wallypipelinedhart.sv new file mode 100644 index 00000000..9664f186 --- /dev/null +++ b/wally-pipelined/src/wallypipelinedhart.sv @@ -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 diff --git a/wally-pipelined/wally-pipelined-batch.do b/wally-pipelined/wally-pipelined-batch.do new file mode 100644 index 00000000..308f97a1 --- /dev/null +++ b/wally-pipelined/wally-pipelined-batch.do @@ -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 diff --git a/wally-pipelined/wally-pipelined.do b/wally-pipelined/wally-pipelined.do new file mode 100644 index 00000000..5a0f95f1 --- /dev/null +++ b/wally-pipelined/wally-pipelined.do @@ -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 diff --git a/wally-pipelined/wally.old b/wally-pipelined/wally.old new file mode 100644 index 00000000..06ba917f --- /dev/null +++ b/wally-pipelined/wally.old @@ -0,0 +1,13 @@ +// riscvfullpipelined.sv + + + +`include "wally-macros.sv" + + + + + + + +