diff --git a/src_Core/CHERI/ScrFile.bsv b/src_Core/CHERI/ScrFile.bsv index 5d471fd..e69de29 100644 --- a/src_Core/CHERI/ScrFile.bsv +++ b/src_Core/CHERI/ScrFile.bsv @@ -1,231 +0,0 @@ - -// Copyright (c) 2017 Massachusetts Institute of Technology -// Portions Copyright (c) 2019-2020 Bluespec, Inc. -// CHERI modifications: -// Copyright (c) 2020 Jonathan Woodruff -// All rights reserved. -// -// This software was developed by SRI International and the University of -// Cambridge Computer Laboratory (Department of Computer Science and -// Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the -// DARPA SSITH research programme. -// -// 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 "ProcConfig.bsv" -import Types::*; -import ProcTypes::*; -import DefaultValue::*; -import ConfigReg::*; -import Ehr::*; -import GetPut::*; -import Vector::*; -import CHERICap::*; -import CHERICC_Fat::*; -import ISA_Decls_CHERI::*; - -// ================================================================ -// BSV additional libs - -import Cur_Cycle::*; - -// ================================================================ -// Project imports from Toooba - -import SoC_Map::*; - -// ================================================================ -// Information returned on traps and mret/sret/uret - -typedef struct { - CapMem new_pcc; - } Scr_Trap_Updates -deriving (Bits, FShow); - -typedef struct { - CapMem new_pcc; - } Scr_RET_Updates -deriving (Bits, FShow); - -typedef struct { - Addr top; - Addr base; - HardPerms perms; - } ScrVMInfo -deriving (Bits, FShow); - -typedef struct { - Bool cap_mode; - } ScrDecodeInfo -deriving (Bits, FShow); - -// ================================================================ - -interface ScrFile; - // Read - method CapReg rd(SCR csr); - // normal write by RWSpecialCap inst to any SCR - method Action scrInstWr(SCR csr, CapReg x); - - interface Vector#(SupSize, Put#(CapReg)) pccWr; - // The WARL transform performed during CSRRx writes to a CSR - method CapReg warl_xform (SCR csr, CapReg x); - - // Methods for handling traps - method ActionValue#(Scr_Trap_Updates) trap(CapPipe pc, Bit#(2) prv); - method ActionValue#(Scr_RET_Updates) sret; - method ActionValue#(Scr_RET_Updates) mret; - - // Outputs for CSRs that the rest of the processor needs to know about - method ScrVMInfo pccCheck; - method ScrVMInfo ddcCheck; - method ScrDecodeInfo decodeInfo; - - // terminate - method ActionValue#(void) terminate; - -endinterface - -// same as EHR except that read port 0 is not ordered with other methods. Read -// port 1 will still get bypassing from write port 0. -module mkConfigEhr#(t init)(Ehr#(n, t)) provisos(Bits#(t, w)); - Ehr#(n, t) data <- mkEhr(init); - Wire#(t) read <- mkBypassWire; - - (* fire_when_enabled, no_implicit_conditions *) - rule setRead; - read <= data[0]; - endrule - - Ehr#(n, t) ifc = ?; - ifc[0] = (interface Reg; - method _read = read._read; - method _write = data[0]._write; - endinterface); - for(Integer i = 1; i < valueOf(n); i = i+1) begin - ifc[i] = (interface Reg; - method _read = data[i]._read; - method _write = data[i]._write; - endinterface); - end - return ifc; -endmodule - -module mkScrFile (ScrFile); - RiscVISASubset isa = defaultValue; - - let mkCsrReg = mkConfigReg; - let mkCsrEhr = mkConfigEhr; - - // User level SCRs - Ehr#(SupSize, CapReg) pcc_reg <- mkConfigEhr(defaultValue); - Reg#(CapReg) ddc_reg <- mkCsrReg(defaultValue); - - // User level SCRs with accessSysRegs - // Reg#(CapReg) utcc_reg <- mkCsrReg(defaultValue); - // Reg#(CapReg) utdc_reg <- mkCsrReg(nullCap); - // Reg#(CapReg) uScratchC_reg <- mkCsrReg(nullCap); - // Reg#(CapReg) uepcc_reg <- mkCsrReg(defaultValue); - - // System level SCRs with accessSysRegs - Reg#(CapReg) stcc_reg <- mkCsrReg(defaultValue); - Reg#(CapReg) stdc_reg <- mkCsrReg(nullCap); - Reg#(CapReg) sScratchC_reg <- mkCsrReg(nullCap); - Reg#(CapReg) sepcc_reg <- mkCsrReg(defaultValue); - - // Machine level SCRs with accessSysRegs - Reg#(CapReg) mtcc_reg <- mkCsrReg(defaultValue); - Reg#(CapReg) mtdc_reg <- mkCsrReg(nullCap); - Reg#(CapReg) mScratchC_reg <- mkCsrReg(nullCap); - Ehr#(2, CapReg) mepcc_reg <- mkConfigEhr(defaultValue); - - // Function for getting a csr given an index - function Reg#(CapReg) get_scr(SCR scr); - return (case (scr) - // User SCRs - SCR_PCC: pcc_reg[0]; - SCR_DDC: ddc_reg; - // User CSRs with accessSysRegs - // SCR_UTCC: utcc_reg; - // SCR_UTDC: utdc_reg; - // SCR_UScratchC: uScratchC_reg; - // SCR_UEPCC: uepcc_reg; - // System CSRs with accessSysRegs - SCR_STCC: stcc_reg; - SCR_STDC: stdc_reg; - SCR_SScratchC: sScratchC_reg; - SCR_SEPCC: sepcc_reg; - // Machine CSRs with accessSysRegs - SCR_MTCC: mtcc_reg; - SCR_MTDC: mtdc_reg; - SCR_MScratchC: mScratchC_reg; - SCR_MEPCC: mepcc_reg[1]; - endcase); - endfunction - - // ================================================================ - // INTERFACE - - method CapReg rd(SCR scr); - return get_scr(scr)._read; - endmethod - - method Action scrInstWr(SCR csr, CapReg x); - get_scr(csr)._write(x); - endmethod - - interface pccWr = map(toPut,pcc_reg); - - method ActionValue#(Scr_Trap_Updates) trap(CapPipe pc, Bit#(2) prv); - mepcc_reg[0] <= cast(pc); - pcc_reg[0] <= mtcc_reg; - return Scr_Trap_Updates{new_pcc: cast(mtcc_reg)}; - endmethod - - method ActionValue#(Scr_RET_Updates) mret; - return Scr_RET_Updates{new_pcc: cast(mepcc_reg[0])}; - endmethod - - method ActionValue#(Scr_RET_Updates) sret; - return Scr_RET_Updates{new_pcc: cast(mepcc_reg[0])}; - endmethod - - method ScrVMInfo pccCheck; - return ScrVMInfo { - top: truncate(getTop(pcc_reg[0])), - base: truncate(getBase(pcc_reg[0])), - perms: getHardPerms(pcc_reg[0]) - }; - endmethod - - method ScrVMInfo ddcCheck; - // for load/store, need to consider MPRV - return ScrVMInfo { - top: truncate(getTop(ddc_reg)), - base: truncate(getBase(ddc_reg)), - perms: getHardPerms(ddc_reg) - }; - endmethod - - method ScrDecodeInfo decodeInfo = - ScrDecodeInfo{cap_mode: getFlags(pcc_reg[0])==1'b1}; - -endmodule diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 4e32d19..27ce885 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -255,8 +255,6 @@ module mkCore#(CoreId coreId)(Core); // Bluespec: CsrFile including external interrupt request methods CsrFile csrf <- mkCsrFile(zeroExtend(coreId)); // hartid in CSRF should be core id - // Special Capability register file - ScrFile scaprf <- mkScrFile(); RegRenamingTable regRenamingTable <- mkRegRenamingTable; EpochManager epochManager <- mkEpochManager; @@ -358,7 +356,7 @@ module mkCore#(CoreId coreId)(Core); method rf_rd1 = cast(rf.read[aluRdPort(i)].rd1); method rf_rd2 = cast(rf.read[aluRdPort(i)].rd2); method csrf_rd = csrf.rd; - method scaprf_rd = scaprf.rd; + method scaprf_rd = csrf.scrRd; method rob_getPC = rob.getOrigPC[i].get; method rob_getPredPC = rob.getOrigPredPC[i].get; method rob_getOrig_Inst = rob.getOrig_Inst[i].get; @@ -402,7 +400,7 @@ module mkCore#(CoreId coreId)(Core); method rf_rd2 = cast(rf.read[fpuMulDivRdPort(i)].rd2); method rf_rd3 = cast(rf.read[fpuMulDivRdPort(i)].rd3); method csrf_rd = csrf.rd; - method scaprf_rd = scaprf.rd; + method scaprf_rd = csrf.scrRd; method rob_setExecuted = rob.setExecuted_doFinishFpuMulDiv[i].set; method Action writeRegFile(PhyRIndx dst, CapPipe data); writeAggr(fpuMulDivWrAggrPort(i), dst); @@ -419,7 +417,7 @@ module mkCore#(CoreId coreId)(Core); method rf_rd1 = cast(rf.read[memRdPort].rd1); method rf_rd2 = cast(rf.read[memRdPort].rd2); method csrf_rd = csrf.rd; - method scaprf_rd = scaprf.rd; + method scaprf_rd = csrf.scrRd; method rob_getPC = rob.getOrigPC[valueof(AluExeNum)].get; // last getPC port method rob_setExecuted_doFinishMem = rob.setExecuted_doFinishMem; `ifdef INCLUDE_TANDEM_VERIF @@ -548,7 +546,6 @@ module mkCore#(CoreId coreId)(Core); interface sbConsIfc = sbCons; interface sbAggrIfc = sbAggr; interface csrfIfc = csrf; - interface scaprfIfc = scaprf; interface emIfc = epochManager; interface smIfc = specTagManager; interface rsAluIfc = reservationStationAlu; @@ -576,7 +573,6 @@ module mkCore#(CoreId coreId)(Core); interface robIfc = rob; interface rtIfc = regRenamingTable; interface csrfIfc = csrf; - interface scaprfIfc = scaprf; method stbEmpty = stb.isEmpty; method stqEmpty = lsq.stqEmpty; method lsqSetAtCommit = lsq.setAtCommit; diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index 566743b..ffeb6ab 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -2,6 +2,16 @@ // Copyright (c) 2017 Massachusetts Institute of Technology // Portions Copyright (c) 2019-2020 Bluespec, Inc. // +// CHERI modifications: +// Copyright (c) 2020 Jonathan Woodruff +// Copyright (c) 2020 Peter Rugg +// All rights reserved. +// +// This software was developed by SRI International and the University of +// Cambridge Computer Laboratory (Department of Computer Science and +// Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the +// DARPA SSITH research programme. +// // 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 @@ -34,6 +44,8 @@ import Vector::*; import FIFO::*; import GetPut::*; import BuildVector::*; +import CHERICap::*; +import CHERICC_Fat::*; import ISA_Decls_CHERI::*; // ================================================================ @@ -52,21 +64,21 @@ import SoC_Map :: *; typedef Bit#(SizeOf#(Exception)) Cause; typedef struct { - Addr new_pc; + CapPipe new_pcc; `ifdef INCLUDE_TANDEM_VERIF // The fields below are for tandem verification only Bit #(2) prv; Data status; Data cause; - Data epc; + CapPipe epcc; Data tval; `endif } Trap_Updates deriving (Bits, FShow); typedef struct { - Addr new_pc; + CapPipe new_pcc; `ifdef INCLUDE_TANDEM_VERIF // The fields below are for tandem verification only @@ -81,8 +93,11 @@ deriving (Bits, FShow); interface CsrFile; // Read method Data rd(CSR csr); + method CapReg scrRd(SCR csr); // normal write by CSRXXX inst to any CSR method Action csrInstWr(CSR csr, Data x); + // normal write by RWSpecialCap inst to any SCR + method Action scrInstWr(SCR csr, CapReg x); // normal write by FPU inst to FPU CSR method Bool fpuInstNeedWr(Bit#(5) fflags, Bool fpu_dirty); method Action fpuInstWr(Bit#(5) fflags); // FPU must become dirty @@ -100,7 +115,7 @@ interface CsrFile; // Methods for handling traps method Maybe#(Interrupt) pending_interrupt; - method ActionValue#(Trap_Updates) trap(Trap t, Addr pc, Addr faultAddr, Bit #(32) orig_inst); + method ActionValue#(Trap_Updates) trap(Trap t, CapPipe pcc, Addr faultAddr, Bit #(32) orig_inst); method ActionValue#(RET_Updates) sret; method ActionValue#(RET_Updates) mret; @@ -421,12 +436,6 @@ module mkCsrFile #(Data hartid)(CsrFile); software_int_en_vec[prvM], readOnlyReg(1'b0), software_int_en_vec[prvS], readOnlyReg(1'b0) // only if misa.N: software_int_en_vec[prvU] ); - // mtvec - Reg#(Bit#(62)) mtvec_base_hi_reg <- mkCsrReg(0); // this is BASE[63:2] - Reg#(Bit#(1)) mtvec_mode_low_reg <- mkCsrReg(0); // this is MODE[0] - Reg#(Data) mtvec_csr = concatReg3( - mtvec_base_hi_reg, readOnlyReg(1'b0), mtvec_mode_low_reg - ); // mcounteren Reg#(Bit#(1)) mcounteren_ir_reg <- mkCsrReg(0); Reg#(Bit#(1)) mcounteren_tm_reg <- mkCsrReg(0); @@ -438,9 +447,6 @@ module mkCsrFile #(Data hartid)(CsrFile); ); // mscratch Reg#(Data) mscratch_csr <- mkCsrReg(0); - // mepc: FIXME Since we don't have C extension, mepc should be 4-byte - // aligned. However, spike is not checking this, so we don't implement it. - Reg#(Data) mepc_csr <- mkCsrReg(0); // mcause Reg#(Bit#(1)) mcause_interrupt_reg <- mkCsrReg(0); Reg#(Cause) mcause_code_reg <- mkCsrReg(0); @@ -540,12 +546,6 @@ module mkCsrFile #(Data hartid)(CsrFile); readOnlyReg(2'b0), software_int_en_vec[prvS], readOnlyReg(1'b0) // only if misa.N: software_int_en_vec[prvU] ); - // stvec - Reg#(Bit#(62)) stvec_base_hi_reg <- mkCsrReg(0); // BASE[63:2] - Reg#(Bit#(1)) stvec_mode_low_reg <- mkCsrReg(0); // MODE[0] - Reg#(Data) stvec_csr = concatReg3( - stvec_base_hi_reg, readOnlyReg(1'b0), stvec_mode_low_reg - ); // scounteren Reg#(Bit#(1)) scounteren_ir_reg <- mkCsrReg(0); Reg#(Bit#(1)) scounteren_tm_reg <- mkCsrReg(0); @@ -557,9 +557,6 @@ module mkCsrFile #(Data hartid)(CsrFile); ); // sscratch Reg#(Data) sscratch_csr <- mkCsrReg(0); - // sepc: FIXME Since we don't have C extension, sepc should be 4-byte - // aligned. However, spike is not checking this, so we don't implement it. - Reg#(Data) sepc_csr <- mkCsrReg(0); // scause Reg#(Bit#(1)) scause_interrupt_reg <- mkCsrReg(0); Reg#(Cause) scause_code_reg <- mkCsrReg(0); @@ -717,6 +714,27 @@ module mkCsrFile #(Data hartid)(CsrFile); Reg#(Data) trng_csr <- mkReadOnlyReg(0); //mkTRNG; `endif + //SCRs + Reg#(CapReg) ddc_reg <- mkCsrReg(defaultValue); + + // User level SCRs with accessSysRegs + // Reg#(CapReg) utcc_reg <- mkCsrReg(defaultValue); + // Reg#(CapReg) utdc_reg <- mkCsrReg(nullCap); + // Reg#(CapReg) uScratchC_reg <- mkCsrReg(nullCap); + // Reg#(CapReg) uepcc_reg <- mkCsrReg(defaultValue); + + // System level SCRs with accessSysRegs + Reg#(CapReg) stcc_reg <- mkCsrReg(defaultValue); + Reg#(CapReg) stdc_reg <- mkCsrReg(nullCap); + Reg#(CapReg) sScratchC_reg <- mkCsrReg(nullCap); + Ehr#(2, CapReg) sepcc_reg <- mkConfigEhr(defaultValue); + + // Machine level SCRs with accessSysRegs + Reg#(CapReg) mtcc_reg <- mkCsrReg(defaultValue); + Reg#(CapReg) mtdc_reg <- mkCsrReg(nullCap); + Reg#(CapReg) mScratchC_reg <- mkCsrReg(nullCap); + Ehr#(2, CapReg) mepcc_reg <- mkConfigEhr(defaultValue); + rule incCycle; mcycle_ehr[1] <= mcycle_ehr[1] + 1; endrule @@ -736,10 +754,8 @@ module mkCsrFile #(Data hartid)(CsrFile); // Supervisor CSRs CSRsstatus: sstatus_csr; CSRsie: sie_csr; - CSRstvec: stvec_csr; CSRscounteren: scounteren_csr; CSRsscratch: sscratch_csr; - CSRsepc: sepc_csr; CSRscause: scause_csr; CSRstval: stval_csr; CSRsip: sip_csr; @@ -750,10 +766,8 @@ module mkCsrFile #(Data hartid)(CsrFile); CSRmedeleg: medeleg_csr; CSRmideleg: mideleg_csr; CSRmie: mie_csr; - CSRmtvec: mtvec_csr; CSRmcounteren: mcounteren_csr; CSRmscratch: mscratch_csr; - CSRmepc: mepc_csr; CSRmcause: mcause_csr; CSRmtval: mtval_csr; CSRmip: mip_csr; @@ -794,6 +808,29 @@ module mkCsrFile #(Data hartid)(CsrFile); endcase); endfunction + // Function for getting a csr given an index + function Reg#(CapReg) get_scr(SCR scr); + return (case (scr) + // User SCRs + SCR_DDC: ddc_reg; + // User CSRs with accessSysRegs + // SCR_UTCC: utcc_reg; + // SCR_UTDC: utdc_reg; + // SCR_UScratchC: uScratchC_reg; + // SCR_UEPCC: uepcc_reg; + // System CSRs with accessSysRegs + SCR_STCC: stcc_reg; + SCR_STDC: stdc_reg; + SCR_SScratchC: sScratchC_reg; + SCR_SEPCC: sepcc_reg[1]; + // Machine CSRs with accessSysRegs + SCR_MTCC: mtcc_reg; + SCR_MTDC: mtdc_reg; + SCR_MScratchC: mScratchC_reg; + SCR_MEPCC: mepcc_reg[1]; + endcase); + endfunction + // ================================================================ // This function is the WARL (Write Any Read Legal) transform // performed during CSR writes. Currently it duplicates the logic @@ -831,7 +868,6 @@ module mkCsrFile #(Data hartid)(CsrFile); x [3], // ie_vec[prvM] x [1], // ie_vec[prvS] x [0]); // ie_vec[prvU] - CSRmtvec: { x[63:2], 1'b0, x[0]}; CSRmedeleg: { 48'b0, x[15], 1'b0, x[13:12], x[11], 1'b0, x[9:0]}; CSRmideleg: { 52'b0, x[11], 1'b0, x[9:8], x[7], 1'b0, x[5:4], x[3], 1'b0, x[1:0]}; CSRmip: ((mip_csr & (~ mip_mie_warl_mask)) | (x & mip_mie_warl_mask)); @@ -852,7 +888,6 @@ module mkCsrFile #(Data hartid)(CsrFile); x [4], // prev_ie_vec[prvU] x [1], // ie_vec[prvS] x [0]); // ie_vec[prvU] - CSRstvec: { x[63:2], 1'b0, x[0]}; CSRsip: ((sip_csr & (~ sip_sie_warl_mask)) | (x & sip_sie_warl_mask)); CSRsie: (x & sip_sie_warl_mask); CSRscounteren: { 61'b0, x[2:0]}; @@ -880,6 +915,10 @@ module mkCsrFile #(Data hartid)(CsrFile); return get_csr(csr)._read; endmethod + method CapReg scrRd(SCR scr); + return get_scr(scr)._read; + endmethod + method Action csrInstWr(CSR csr, Data x); get_csr(csr)._write(x); `ifdef INCLUDE_GDB_CONTROL @@ -890,6 +929,10 @@ module mkCsrFile #(Data hartid)(CsrFile); `endif endmethod + method Action scrInstWr(SCR csr, CapReg x); + get_scr(csr)._write(x); + endmethod + method Bool fpuInstNeedWr(Bit#(5) fflags, Bool fpu_dirty); Bool fflags_change = (fflags & fflags_reg) != fflags; // we need to set fs_reg as dirty in two cases @@ -962,7 +1005,7 @@ module mkCsrFile #(Data hartid)(CsrFile); end endmethod - method ActionValue#(Trap_Updates) trap(Trap t, Addr pc, Addr addr, Bit #(32) orig_inst); + method ActionValue#(Trap_Updates) trap(Trap t, CapPipe pcc, Addr addr, Bit #(32) orig_inst); // figure out trap cause & trap val Bit#(1) cause_interrupt = 0; Cause cause_code = 0; @@ -972,7 +1015,7 @@ module mkCsrFile #(Data hartid)(CsrFile); cause_code = pack(e); trap_val = (case(e) IllegalInst: zeroExtend (orig_inst); - InstAddrMisaligned, Breakpoint: return pc; + InstAddrMisaligned, Breakpoint: return getOffset(pcc); // TODO do we want getAddr? InstAccessFault, InstPageFault, LoadAddrMisaligned, LoadAccessFault, @@ -988,14 +1031,18 @@ module mkCsrFile #(Data hartid)(CsrFile); end endcase // function to figure out next PC - function Addr getNextPc(Bit#(1) mode_low, Bit#(62) base_hi); + function CapPipe getNextPcc(CapPipe tcc); + let tvec = getAddr(tcc); // Note this is not actually mtcc: addr rather than offset + let mode_low = tvec[0]; // Valid because bottom 2 bits of base must be zero (enforced on write) + // tvec[1] must be 1 here. + let base_hi = tvec[63:2]; Addr base = {base_hi, 2'b0}; if(mode_low == 1 && cause_interrupt == 1) begin // vector jump: only for interrupt - return base + zeroExtend({cause_code, 2'b0}); + return setAddr(tcc, base + zeroExtend({cause_code, 2'b0})).value; end else begin // direct jump - return base; + return setAddr(tcc, base).value; end endfunction // check if trap is delegated @@ -1012,12 +1059,11 @@ module mkCsrFile #(Data hartid)(CsrFile); prev_ie_vec[prvS] <= ie_vec[prvS]; ie_vec[prvS] <= 0; // record trap info - sepc_csr <= pc; + sepcc_reg[0] <= cast(pcc); scause_interrupt_reg <= cause_interrupt; scause_code_reg <= cause_code; stval_csr <= trap_val; // return next pc - // return getNextPc(stvec_mode_low_reg, stvec_base_hi_reg); Data sstatus_val = fn_sstatus_val (uxl_reg, mxr_reg, sum_reg, xs_reg, fs_reg, @@ -1027,12 +1073,12 @@ module mkCsrFile #(Data hartid)(CsrFile); /* ie_vec [prvS] */ 0, ie_vec [prvU]); Data scause_val = fn_scause_val (cause_interrupt, cause_code); - return Trap_Updates {new_pc: getNextPc(stvec_mode_low_reg, stvec_base_hi_reg) + return Trap_Updates {new_pcc: getNextPcc(cast(stcc_reg)) `ifdef INCLUDE_TANDEM_VERIF , prv: prvS, status: sstatus_val, cause: scause_val, - epc: pc, + epcc: pcc, tval: trap_val `endif }; @@ -1044,12 +1090,11 @@ module mkCsrFile #(Data hartid)(CsrFile); prev_ie_vec[prvM] <= ie_vec[prvM]; ie_vec[prvM] <= 0; // record trap info - mepc_csr <= pc; + mepcc_reg[0] <= cast(pcc); mcause_interrupt_reg <= cause_interrupt; mcause_code_reg <= cause_code; mtval_csr <= trap_val; // return next pc - // return getNextPc(mtvec_mode_low_reg, mtvec_base_hi_reg); Data mstatus_val = fn_mstatus_val (sxl_reg, uxl_reg, tsr_reg, tw_reg, tvm_reg, mxr_reg, sum_reg, mprv_reg, @@ -1062,12 +1107,12 @@ module mkCsrFile #(Data hartid)(CsrFile); ie_vec [prvS], ie_vec [prvU]); Data mcause_val = fn_mcause_val (cause_interrupt, cause_code); - return Trap_Updates {new_pc: getNextPc(mtvec_mode_low_reg, mtvec_base_hi_reg) + return Trap_Updates {new_pcc: getNextPcc(cast(mtcc_reg)) `ifdef INCLUDE_TANDEM_VERIF , prv: prvM, status: mstatus_val, cause: mcause_val, - epc: pc, + epcc: pcc, tval: trap_val `endif }; @@ -1093,7 +1138,7 @@ module mkCsrFile #(Data hartid)(CsrFile); /* ie_vec [prvM] */ prev_ie_vec[prvM], ie_vec [prvS], ie_vec [prvU]); - return RET_Updates {new_pc: mepc_csr + return RET_Updates {new_pcc: cast(mepcc_reg[0]) `ifdef INCLUDE_TANDEM_VERIF , prv: prev_prv_vec[prvM], status: mstatus_val @@ -1122,7 +1167,7 @@ module mkCsrFile #(Data hartid)(CsrFile); ie_vec [prvM], /* ie_vec [prvS] */ prev_ie_vec[prvS], ie_vec [prvU]); - return RET_Updates {new_pc: sepc_csr + return RET_Updates {new_pcc: cast(sepcc_reg[0]) `ifdef INCLUDE_TANDEM_VERIF , prv: prev_prv_vec[prvS], status: mstatus_val diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv index c59af20..a4ec801 100755 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv @@ -307,6 +307,12 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); doAssert(!exec_result.controlFlow.mispredict, "Csr inst cannot mispredict"); doAssert(cast(exec_result.controlFlow.nextPc) == x.ppc && x.ppc == addPc(x.pc, 4), "Csr inst ppc = pc+4"); end + // when inst needs to store scrData in ROB, it must have iType = Scr, cannot mispredict + if(isValid(x.dInst.scr)) begin + doAssert(x.dInst.iType == Scr, "Only Scr inst needs to update scrData in ROB"); + doAssert(!exec_result.controlFlow.mispredict, "Scr inst cannot mispredict"); + doAssert(cast(exec_result.controlFlow.nextPc) == x.ppc && x.ppc == addPc(x.pc, 4), "Csr inst ppc = pc+4"); + end // send bypass if(x.dst matches tagged Valid .dst) begin @@ -382,7 +388,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); doAssert(isValid(x.spec_tag), "mispredicted branch must have spec tag"); inIfc.redirect(cast(x.controlFlow.nextPc), validValue(x.spec_tag), x.tag); // must be a branch, train branch predictor - doAssert(x.iType == Jr || x.iType == Br, "only jr and br can mispredict"); + doAssert(x.iType == Jr || x.iType == CJALR || x.iType == CCall || x.iType == Br, "only jr, br, cjalr, and ccall can mispredict"); inIfc.fetch_train_predictors(FetchTrainBP { pc: cast(x.controlFlow.pc), nextPc: cast(x.controlFlow.nextPc), @@ -411,7 +417,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); // train branch predictor if needed // since we can only do 1 training in a cycle, split the rule // XXX not training JAL, reduce chance of conflicts - if(x.iType == Jr || x.iType == Br) begin + if(x.iType == Jr || x.iType == CJALR || x.iType == CCall || x.iType == Br) begin inIfc.fetch_train_predictors(FetchTrainBP { pc: cast(x.controlFlow.pc), nextPc: cast(x.controlFlow.nextPc), diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index f5c2021..4c31d52 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -82,7 +82,6 @@ interface CommitInput; interface ReorderBufferSynth robIfc; interface RegRenamingTable rtIfc; interface CsrFile csrfIfc; - interface ScrFile scaprfIfc; // no stores method Bool stbEmpty; method Bool stqEmpty; @@ -344,7 +343,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); ReorderBufferSynth rob = inIfc.robIfc; RegRenamingTable regRenamingTable = inIfc.rtIfc; CsrFile csrf = inIfc.csrfIfc; - ScrFile scaprf = inIfc.scaprfIfc; // FIXME FIXME FIXME wires to set atCommit in LSQ: avoid scheduling cycle. // Using wire should be fine, because LSQ does not need to see atCommit @@ -729,7 +727,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); : 1)); csrf.dcsr_cause_write (dcsr_cause); csrf.dpc_write (trap.pc); - scaprfIfc.trap(trap.pc,?); // Tell fetch stage to wait for redirect // Note: rule doCommitTrap_flush may have done this already; redundant call is ok. @@ -746,9 +743,8 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); if (! debugger_halt) begin // trap handling & redirect - let trap_updates <- csrf.trap(trap.trap, getAddr(trap.pc), trap.addr, trap.orig_inst); - let cap_trap_updates <- scaprf.trap(cast(trap.pc), ?); - CapPipe new_pc = setOffset(cast(cap_trap_updates.new_pcc), trap_updates.new_pc).value; + let trap_updates <- csrf.trap(trap.trap, cast(trap.pc), trap.addr, trap.orig_inst); + CapPipe new_pc = cast(trap_updates.new_pcc); inIfc.redirectPc(cast(new_pc) `ifdef RVFI_DII , trap.x.diid + 1 @@ -756,7 +752,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); ); `ifdef RVFI Rvfi_Traces rvfis = replicate(tagged Invalid); - rvfis[0] = genRVFI(trap.x, traceCnt, getTSB(), trap_updates.new_pc); + rvfis[0] = genRVFI(trap.x, traceCnt, getTSB(), getAddr(new_pc)); rvfiQ.enq(rvfis); traceCnt <= traceCnt + 1; `endif @@ -878,6 +874,19 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); flush_security = csr_idx == CSRmflush; `endif end + if(x.iType == Scr) begin + // inIfc.commitCsrInstOrInterrupt; // TODO Will there be statcounter for SCRs? + // write CSR + let scr_idx = validValue(x.scr); + CapPipe scr_data = ?; + if(x.ppc_vaddr_csrData matches tagged SCRData .d) begin + scr_data = d; + end + else begin + doAssert(False, "must have scr data"); + end + csrf.scrInstWr(scr_idx, cast(scr_data)); // TODO only needs a CapReg so we could avoid generating the CapPipe in the first place + end // redirect (Sret and Mret redirect pc is got from CSRF) CapMem next_pc = x.ppc_vaddr_csrData matches tagged PPC .ppc ? ppc : addPc(x.pc, 4); @@ -887,18 +896,14 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `endif if(x.iType == Sret) begin RET_Updates ret_updates <- csrf.sret; - Scr_RET_Updates scr_ret_updates <- scaprf.sret; - CapPipe tc = setOffset(cast(scr_ret_updates.new_pcc), ret_updates.new_pc).value; - next_pc = cast(tc); + next_pc = cast(ret_updates.new_pcc); `ifdef INCLUDE_TANDEM_VERIF - m_ret_updates = tagged Valid ret_updates; + m_ret_updates = tagged Valid ret_updates; `endif end else if(x.iType == Mret) begin RET_Updates ret_updates <- csrf.mret; - Scr_RET_Updates scr_ret_updates <- scaprf.sret; - CapPipe tc = setOffset(cast(scr_ret_updates.new_pcc), ret_updates.new_pc).value; - next_pc = cast(tc); + next_pc = cast(ret_updates.new_pcc); `ifdef INCLUDE_TANDEM_VERIF m_ret_updates = tagged Valid ret_updates; `endif @@ -1096,9 +1101,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); regRenamingTable.commit[i].commit; doAssert(x.claimed_phy_reg, "should have renamed"); - if (x.ppc_vaddr_csrData matches tagged PPC .ppc) - scaprf.pccWr[i].put(cast(ppc)); - `ifdef RENAME_DEBUG // send debug msg for rename error if(!x.claimed_phy_reg && !isValid(renameError)) begin diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 68c018d..3f255fa 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -937,7 +937,9 @@ module mkFetchStage(FetchStage); // rs1 is invalid, i.e., not link: push ras.ras[i].popPush(False, Valid (push_addr)); end - else if (dInst.iType == Jr) begin // jalr + else if (dInst.iType == Jr || dInst.iType == CJALR) begin // jalr TODO CCALL could be push + // pop or nop (if to trampoline) + // Add hint to architecture? if (!dst_link && src1_link) begin // rd is link while rs1 is not: pop nextPc = Valid (pop_addr); diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv index 6f97e31..b7867ef 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv @@ -41,7 +41,6 @@ import ReorderBufferSynth::*; import Scoreboard::*; import ScoreboardSynth::*; import CsrFile::*; -import ScrFile::*; import SpecTagManager::*; import EpochManager::*; import ReservationStationEhr::*; @@ -68,7 +67,6 @@ interface RenameInput; interface ScoreboardCons sbConsIfc; interface ScoreboardAggr sbAggrIfc; interface CsrFile csrfIfc; - interface ScrFile scaprfIfc; interface EpochManager emIfc; interface SpecTagManager smIfc; interface Vector#(AluExeNum, ReservationStationAlu) rsAluIfc; @@ -112,7 +110,6 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); ScoreboardCons sbCons = inIfc.sbConsIfc; ScoreboardAggr sbAggr = inIfc.sbAggrIfc; CsrFile csrf = inIfc.csrfIfc; - ScrFile scaprf = inIfc.scaprfIfc; EpochManager epochManager = inIfc.emIfc; SpecTagManager specTagManager = inIfc.smIfc; Vector#(AluExeNum, ReservationStationAlu) reservationStationAlu = inIfc.rsAluIfc; @@ -241,31 +238,8 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); let mstatus = csrf.rd (CSRmstatus); // Check CSR access permission - Bool csr_access_trap = False; - if (x.dInst.iType == Csr) begin - if (x.dInst.csr matches tagged Valid .c) begin - case (c) - CSRfcsr: fpr_access = True; - endcase - end - Bit #(12) csr_addr = case (x.dInst.csr) matches - tagged Valid .c: pack (c); - default: 12'hCFF; - endcase; - let rs1 = case (x.regs.src2) matches - tagged Valid (tagged Gpr .r) : r; - default: 0; - endcase; - let imm = case (x.dInst.imm) matches - tagged Valid .n: n; - default: 0; - endcase; - Bool writes_csr = ((x.dInst.execFunc == tagged Alu Csrw) || (rs1 != 0) || (imm != 0)); - Bool read_only = (csr_addr [11:10] == 2'b11); - Bool write_deny = (writes_csr && read_only); - Bool priv_deny = (csrf.decodeInfo.prv < csr_addr [9:8]); - Bool unimplemented = (csr_addr == 12'h8ff); // Added by Bluespec - csr_access_trap = (write_deny || priv_deny || unimplemented); + if (x.dInst.csr matches tagged Valid CSRfcsr &&& x.dInst.iType == Csr) begin + fpr_access = True; end Bool fs_trap = ((mstatus [14:13] == 2'b00) && fpr_access); @@ -294,7 +268,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); // newly found exception trap = tagged Valid (tagged Exception fromMaybe(?, new_exception)); end - else if (fs_trap || csr_access_trap || wfi_trap) begin + else if (fs_trap || wfi_trap) begin trap = tagged Valid (tagged Exception IllegalInst); end return trap; @@ -370,6 +344,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); store_data_BE: ?, `endif csr: dInst.csr, + scr: dInst.scr, claimed_phy_reg: False, // no renaming is done trap: trapWithCap, tval: tval, @@ -515,7 +490,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); Bool to_exec = False; if (dInst.execFunc matches tagged Alu .alu) begin to_exec = True; - doAssert(dInst.iType == Csr, "only CSR inst send to exe"); + doAssert(dInst.iType == Csr || dInst.iType == Scr, "only CSR or SCR inst send to exe"); end else begin doAssert(dInst.iType == FenceI || @@ -568,6 +543,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); store_data_BE: ?, `endif csr: dInst.csr, + scr: dInst.scr, claimed_phy_reg: True, // XXX we always claim a free reg in rename trap: Invalid, // no trap tval: 0, @@ -590,7 +566,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); }; rob.enqPort[0].enq(y); - // record if we issue an CSR inst + // record if we issue an CSR inst. TODO also for SCRs? if(dInst.iType == Csr) begin inIfc.issueCsrInstOrInterrupt; end @@ -964,10 +940,12 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); Bool to_exec = False; Bool to_mem = False; Bool to_FpuMulDiv = False; + case (dInst.capFunc) matches + tagged CapInspect .ci: to_exec = True; + tagged CapModify .cm: to_exec = True; + endcase case (dInst.execFunc) matches tagged Alu .alu: to_exec = True; - tagged CapInspect .ci: to_exec = True; - tagged CapModify .cm: to_exec = True; tagged Br .br: to_exec = True; tagged MulDiv .muldiv: to_FpuMulDiv = True; tagged Fpu .fpu: to_FpuMulDiv = True; @@ -1111,6 +1089,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); store_data_BE: ?, `endif csr: dInst.csr, + scr: dInst.scr, claimed_phy_reg: True, // XXX we always claim a free reg in rename trap: Invalid, // no trap tval: 0, diff --git a/src_Core/RISCY_OOO/procs/lib/BrPred.bsv b/src_Core/RISCY_OOO/procs/lib/BrPred.bsv index 11d8e18..14f6c0e 100644 --- a/src_Core/RISCY_OOO/procs/lib/BrPred.bsv +++ b/src_Core/RISCY_OOO/procs/lib/BrPred.bsv @@ -33,7 +33,7 @@ function Maybe#(CapMem) decodeBrPred( CapMem pc, DecodedInst dInst, Bool histTak Data imm_val = truncate(fromMaybe(?, getDInstImm(dInst))); Maybe#(CapMem) nextPc = tagged Invalid; CapPipe pcPipe = cast(pc); - CapMem jTarget = cast(modifyOffset(pcPipe, imm_val, True).value); + CapMem jTarget = cast(incOffset(pcPipe, imm_val).value); if( dInst.iType == J ) begin nextPc = tagged Valid jTarget; end else if( dInst.iType == Br ) begin @@ -42,7 +42,7 @@ function Maybe#(CapMem) decodeBrPred( CapMem pc, DecodedInst dInst, Bool histTak end else begin nextPc = tagged Valid pcPlusN; end - end else if( dInst.iType == Jr ) begin + end else if( dInst.iType == Jr || dInst.iType == CCall || dInst.iType == CJALR ) begin // target is unknown until RegFetch nextPc = tagged Invalid; end else begin diff --git a/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi b/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi index 4fd4435..77a3aa6 100644 --- a/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi +++ b/src_Core/RISCY_OOO/procs/lib/CapChecks.bsvi @@ -16,3 +16,4 @@ `CAP_CHECK_FIELD(src2_addr_valid_type,"src2_addr_valid_type") `CAP_CHECK_FIELD(src1_perm_subset_src2,"src1_perm_subset_src2") `CAP_CHECK_FIELD(src1_derivable,"src1_derivable") +`CAP_CHECK_FIELD(scr_read_only,"scr_read_only") diff --git a/src_Core/RISCY_OOO/procs/lib/Decode.bsv b/src_Core/RISCY_OOO/procs/lib/Decode.bsv index d339062..e4e5199 100755 --- a/src_Core/RISCY_OOO/procs/lib/Decode.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Decode.bsv @@ -150,6 +150,7 @@ function DecodeResult decode(Instruction inst); DecodedInst dInst = DecodedInst { iType: Unsupported, execFunc: tagged Other, + capFunc: tagged Other, csr: tagged Invalid, scr: tagged Invalid, imm: tagged Invalid, @@ -712,6 +713,7 @@ function DecodeResult decode(Instruction inst); dInst.imm = Invalid; end else begin // fnCSRRWI, fnCSRRW, fnCSRRSI, fnCSRRS, fnCSRRCI, fnCSRRC + // TODO change to SCR if r/w to x{epc,tvec}? dInst.iType = Csr; dInst.execFunc = (case (funct3) fnCSRRWI, fnCSRRW: tagged Alu Csrw; @@ -732,11 +734,11 @@ function DecodeResult decode(Instruction inst); f3_cap_CIncOffsetImmediate: begin dInst.capChecks.src1_unsealed = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Valid(immI); - dInst.execFunc = CapModify (ModifyOffset (IncOffset)); + dInst.capFunc = CapModify (ModifyOffset (IncOffset)); end f3_cap_CSetBoundsImmediate: begin dInst.capChecks.src1_tag = True; @@ -748,19 +750,17 @@ function DecodeResult decode(Instruction inst); dInst.capChecks.check_high_src = ResultTop; dInst.capChecks.check_inclusive = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Invalid; dInst.imm = Valid (immIunsigned); - dInst.execFunc = CapModify (SetBounds (SetBounds)); + dInst.capFunc = CapModify (SetBounds (SetBounds)); end f3_cap_ThreeOp: begin case (funct7) f7_cap_CSpecialRW: begin - // TODO capChecks - - dInst.iType = Alu; + dInst.iType = Scr; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Invalid; @@ -772,7 +772,11 @@ function DecodeResult decode(Instruction inst); default: Normal; endcase; - dInst.execFunc = CapModify (SpecialRW (scrType)); + if (dInst.scr.Valid == SCR_PCC) begin + dInst.capChecks.scr_read_only = True; + end + + dInst.capFunc = CapModify (SpecialRW (scrType)); end f7_cap_CSetBounds: begin dInst.capChecks.src1_tag = True; @@ -784,12 +788,12 @@ function DecodeResult decode(Instruction inst); dInst.capChecks.check_high_src = ResultTop; dInst.capChecks.check_inclusive = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (SetBounds (SetBounds)); + dInst.capFunc = CapModify (SetBounds (SetBounds)); end f7_cap_CSetBoundsExact: begin illegalInst = True; @@ -803,42 +807,42 @@ function DecodeResult decode(Instruction inst); dInst.capChecks.check_high_src = ResultTop; dInst.capChecks.check_inclusive = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (SetBounds (SetBounds)); + dInst.capFunc = CapModify (SetBounds (SetBounds)); end f7_cap_CSetOffset: begin dInst.capChecks.src1_unsealed = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (ModifyOffset (SetOffset)); + dInst.capFunc = CapModify (ModifyOffset (SetOffset)); end f7_cap_CSetAddr: begin dInst.capChecks.src1_unsealed = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (SetAddr (Src2Addr)); + dInst.capFunc = CapModify (SetAddr (Src2Addr)); end f7_cap_CIncOffset: begin dInst.capChecks.src1_unsealed = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (ModifyOffset (IncOffset)); + dInst.capFunc = CapModify (ModifyOffset (IncOffset)); end f7_cap_CSeal: begin dInst.capChecks.src1_tag = True; @@ -854,12 +858,12 @@ function DecodeResult decode(Instruction inst); dInst.capChecks.check_high_src = Src2Addr; dInst.capChecks.check_inclusive = False; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (Seal); + dInst.capFunc = CapModify (Seal); end f7_cap_CCSeal: begin illegalInst = True; @@ -878,7 +882,8 @@ function DecodeResult decode(Instruction inst); dInst.capChecks.src1_permit_ccall = True; dInst.capChecks.src2_permit_ccall = True; - dInst.iType = Jr; + dInst.iType = CCall; + dInst.capFunc = CapModify (Unseal (Src2)); dInst.execFunc = tagged Br AT; regs.dst = Valid(tagged Gpr 31); regs.src1 = Valid(tagged Gpr rs1); @@ -904,22 +909,22 @@ function DecodeResult decode(Instruction inst); dInst.capChecks.check_high_src = Src2Addr; dInst.capChecks.check_inclusive = False; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (Unseal (Src1)); + dInst.capFunc = CapModify (Unseal (Src1)); end f7_cap_CTestSubset: begin illegalInst = True; // TODO - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapInspect (TestSubset); + dInst.capFunc = CapInspect (TestSubset); end f7_cap_CCopyType: begin dInst.capChecks.src1_tag = True; @@ -931,39 +936,39 @@ function DecodeResult decode(Instruction inst); dInst.capChecks.check_high_src = Src2Type; dInst.capChecks.check_inclusive = False; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (SetAddr (Src2Type)); + dInst.capFunc = CapModify (SetAddr (Src2Type)); end f7_cap_CAndPerm: begin dInst.capChecks.src1_tag = True; dInst.capChecks.src1_unsealed = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (AndPerm); + dInst.capFunc = CapModify (AndPerm); end f7_cap_CSetFlags: begin dInst.capChecks.src1_unsealed = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (SetFlags); + dInst.capFunc = CapModify (SetFlags); end f7_cap_CToPtr: begin dInst.capChecks.src1_unsealed = True; dInst.capChecks.src2_tag = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); if (rs2 == 0) begin @@ -974,7 +979,7 @@ function DecodeResult decode(Instruction inst); dInst.scr = Invalid; end dInst.imm = Invalid; - dInst.execFunc = CapInspect (ToPtr); + dInst.capFunc = CapInspect (ToPtr); end f7_cap_CFromPtr: begin illegalInst = True; @@ -982,12 +987,12 @@ function DecodeResult decode(Instruction inst); dInst.capChecks.src1_tag = True; dInst.capChecks.src1_unsealed = True; - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); regs.src2 = Valid(tagged Gpr rs2); dInst.imm = Invalid; - dInst.execFunc = CapModify (SetAddr (Src2Addr)); + dInst.capFunc = CapModify (SetAddr (Src2Addr)); end f7_cap_CSub: begin // CSub is just a riscv subtract @@ -1012,7 +1017,7 @@ function DecodeResult decode(Instruction inst); dInst.capChecks.check_inclusive = True; // Swap arguments so SCR possibly goes in RS2 - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs2); if (rs1 == 0) begin @@ -1021,7 +1026,7 @@ function DecodeResult decode(Instruction inst); regs.src2 = Valid(tagged Gpr rs1); end dInst.imm = Invalid; - dInst.execFunc = CapModify (BuildCap); + dInst.capFunc = CapModify (BuildCap); end f7_cap_Loads: begin illegalInst = True; @@ -1034,90 +1039,90 @@ function DecodeResult decode(Instruction inst); f7_cap_TwoOp: begin case (funct5rs2) f5rs2_cap_CGetLen: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapInspect (GetLen); + dInst.capFunc = CapInspect (GetLen); end f5rs2_cap_CGetBase: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapInspect (GetBase); + dInst.capFunc = CapInspect (GetBase); end f5rs2_cap_CGetTag: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapInspect (GetTag); + dInst.capFunc = CapInspect (GetTag); end f5rs2_cap_CGetSealed: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapInspect (GetSealed); + dInst.capFunc = CapInspect (GetSealed); end f5rs2_cap_CRRL: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr 0); // Operate on nullcap regs.src2 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapModify (SetBounds (CRRL)); + dInst.capFunc = CapModify (SetBounds (CRRL)); end f5rs2_cap_CRAM: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr 0); // Operate on nullcap regs.src2 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapModify (SetBounds (CRAM)); + dInst.capFunc = CapModify (SetBounds (CRAM)); end f5rs2_cap_CMove: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapModify (Move); + dInst.capFunc = CapModify (Move); end f5rs2_cap_CClearTag: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapModify (ClearTag); + dInst.capFunc = CapModify (ClearTag); end f5rs2_cap_CGetAddr: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapInspect (GetAddr); + dInst.capFunc = CapInspect (GetAddr); end f5rs2_cap_CGetOffset: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapInspect (GetOffset); + dInst.capFunc = CapInspect (GetOffset); end f5rs2_cap_CGetFlags: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapInspect (GetFlags); + dInst.capFunc = CapInspect (GetFlags); end f5rs2_cap_CGetPerm: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapInspect (GetPerm); + dInst.capFunc = CapInspect (GetPerm); end f5rs2_cap_CJALR: begin dInst.capChecks.src1_tag = True; @@ -1130,7 +1135,7 @@ function DecodeResult decode(Instruction inst); dInst.capChecks.check_high_src = Src1AddrPlus2; dInst.capChecks.check_inclusive = False; - dInst.iType = Jr; + dInst.iType = CJALR; dInst.execFunc = tagged Br AT; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); @@ -1138,11 +1143,11 @@ function DecodeResult decode(Instruction inst); dInst.imm = Invalid; end f5rs2_cap_CGetType: begin - dInst.iType = Alu; + dInst.iType = Cap; regs.dst = Valid(tagged Gpr rd); regs.src1 = Valid(tagged Gpr rs1); dInst.imm = Invalid; - dInst.execFunc = CapInspect (GetType); + dInst.capFunc = CapInspect (GetType); end default: begin illegalInst = True; diff --git a/src_Core/RISCY_OOO/procs/lib/Exec.bsv b/src_Core/RISCY_OOO/procs/lib/Exec.bsv index 8a3efe3..9787fc7 100755 --- a/src_Core/RISCY_OOO/procs/lib/Exec.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Exec.bsv @@ -72,6 +72,8 @@ function Maybe#(CapException) capChecks(CapPipe a, CapPipe b, CapChecks toCheck, result = e2(SoftwarePermViolation); else if (toCheck.src1_derivable && !isDerivable(a)) result = e1(LengthViolation); + else if (toCheck.scr_read_only && (toCheck.rn1 != 0)) + result = Valid(CapException{cheri_exc_reg: {1,pack(SCR_PCC)}, cheri_exc_code: PermitASRViolation}); return result; endfunction @@ -142,14 +144,25 @@ endfunction function CapPipe setBoundsALU(CapPipe cap, Data len, SetBoundsFunc boundsOp); let combinedResult = setBoundsCombined(cap, len); CapPipe res = (case (boundsOp) matches - SetBounds: combinedResult.cap; - CRRL: nullWithAddr(combinedResult.length); - CRAM: nullWithAddr(combinedResult.mask); - endcase); + SetBounds: combinedResult.cap; + CRRL: nullWithAddr(combinedResult.length); + CRAM: nullWithAddr(combinedResult.mask); + endcase); // TODO exfiltrate exact somehow... return res; endfunction +(* noinline *) +function CapPipe specialRWALU(CapPipe cap, SpecialRWFunc scrType); + let offset = getOffset(cap); + CapPipe res = (case (scrType) matches + TCC: update_scr_via_csr(cap, offset & ~64'h2); // Mask out bit 1 + EPCC: update_scr_via_csr(cap, offset & ~64'h1); // Mask out bit 0 TODO factor out update_scr_via_csr + Normal: cap; + endcase); + return res; +endfunction + (* noinline *) function CapPipe capModify(CapPipe a, CapPipe b, CapModifyFunc func); CapPipe res = (case(func) matches @@ -158,7 +171,7 @@ function CapPipe capModify(CapPipe a, CapPipe b, CapModifyFunc func); tagged SetBounds .boundsOp : setBoundsALU(a, getAddr(b), boundsOp); tagged SpecialRW .scrType : - a; //TODO masking of various bits + b; tagged SetAddr .addrSource : if (addrSource == Src2Type && !isSealed(b)) return nullWithAddr(-1); else return setAddr(a, (addrSource == Src2Type) ? zeroExtend(getType(b)) : getAddr(b) ).value; @@ -215,6 +228,16 @@ function Data capInspect(CapPipe a, CapPipe b, CapInspectFunc func); return res; endfunction +function CapPipe capALU(CapPipe a, CapPipe b, CapFunc func); + CapPipe res = (case (func) matches + tagged CapInspect .x: + nullWithAddr(capInspect(a,b,func.CapInspect)); + default: + capModify(a,b,func.CapModify); + endcase); + return res; +endfunction + (* noinline *) function Bool aluBr(Data a, Data b, BrFunc brFunc); Bool brTaken = (case(brFunc) @@ -240,7 +263,7 @@ function CapPipe brAddrCalc(CapPipe pc, CapPipe val, IType iType, Data imm, Bool jumpTarget = setAddrUnsafe(jumpTarget, {truncateLSB(getAddr(jumpTarget)), 1'b0}); CapPipe targetAddr = (case (iType) J : branchTarget; - Jr : jumpTarget; + Jr,CCall,CJALR : jumpTarget; Br : (taken? branchTarget : pcPlusN); default : pcPlusN; endcase); @@ -269,14 +292,9 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C CapPipe data = nullCap; Data csr_data = 0; CapPipe addr = nullCap; - Bool cjalr = False; - Bool ccall = False; - if (dInst.iType == Jr) begin - if (dInst.capChecks.src1_src2_types_match) ccall = True; - else if (dInst.capChecks.src1_tag) cjalr = True; - end - ControlFlow cf = ControlFlow{pc: pcc, nextPc: nullCap, taken: False, newPcc: cjalr, mispredict: False}; + Bool newPcc = dInst.iType == CJALR || dInst.iType == CCall; + ControlFlow cf = ControlFlow{pc: pcc, nextPc: nullCap, taken: False, newPcc: newPcc, mispredict: False}; CapPipe aluVal2 = rVal2; if (getDInstImm(dInst) matches tagged Valid .imm) aluVal2 = nullWithAddr(imm); //isValid(dInst.imm) ? fromMaybe(?, dInst.imm) : rVal2; @@ -284,23 +302,15 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C AluFunc alu_f = dInst.execFunc matches tagged Alu .alu_f ? alu_f : Add; Data alu_result = alu(getAddr(rVal1), getAddr(aluVal2), alu_f); - Data inspect_result = capInspect(rVal1, aluVal2, dInst.execFunc.CapInspect); - CapModifyFunc modFunc = ccall ? (Unseal (Src2)):dInst.execFunc.CapModify; - CapPipe modify_result = capModify(rVal1, aluVal2, modFunc); + CapPipe cap_alu_result = capALU(rVal1, aluVal2, dInst.capFunc); CapPipe link_pcc = addPc(pcc, ((orig_inst [1:0] == 2'b11) ? 4 : 2)); Maybe#(CapException) capException = capChecks(rVal1, aluVal2, dInst.capChecks, link_pcc); Maybe#(BoundsCheck) boundsCheck = prepareBoundsCheck(rVal1, aluVal2, dInst.capChecks); - CapPipe cap_alu_result = case (dInst.execFunc) matches tagged CapInspect .x: nullWithAddr(inspect_result); - tagged CapModify .x: modify_result; - tagged Br .x: modify_result; - default: nullWithAddr(alu_result); - endcase; - // Default branch function is not taken BrFunc br_f = dInst.execFunc matches tagged Br .br_f ? br_f : NT; cf.taken = aluBr(getAddr(rVal1), getAddr(rVal2), br_f); - cf.nextPc = brAddrCalc(pcc, rVal1, dInst.iType, fromMaybe(0,getDInstImm(dInst)), cf.taken, orig_inst, (ccall || cjalr)); + cf.nextPc = brAddrCalc(pcc, rVal1, dInst.iType, fromMaybe(0,getDInstImm(dInst)), cf.taken, orig_inst, newPcc); cf.mispredict = cf.nextPc != ppc; data = (case (dInst.iType) matches @@ -308,19 +318,22 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C Sc : rVal2; Amo : rVal2; J : nullWithAddr(getAddr(link_pcc)); - Jr &&& (ccall): cap_alu_result; // Depending on defaults falling through! - Jr &&& (cjalr): link_pcc; + CCall : cap_alu_result; + CJALR : link_pcc; Jr : nullWithAddr(getOffset(link_pcc)); Auipc : (getFlags(pcc)[0] == 1'b0 ? nullWithAddr(getOffset(pcc) + fromMaybe(?, getDInstImm(dInst))) : incOffset(pcc, fromMaybe(?, getDInstImm(dInst))).value); // could be computed with alu Csr : rVal1; - default : cap_alu_result; + Scr : rVal2; + Cap : cap_alu_result; + default : nullWithAddr(alu_result); endcase); csr_data = alu_result; addr = (case (dInst.iType) Ld, St, Lr, Sc, Amo : nullWithAddr(alu_result); - default : cf.nextPc; + default : cf.nextPc; //TODO should this be nullified? endcase); - CapPipe scr_data = modify_result; + + CapPipe scr_data = specialRWALU(rVal1, dInst.capFunc.CapModify.SpecialRW); return ExecResult{data: data, csrData: csr_data, scrData: scr_data, addr: addr, controlFlow: cf, capException: capException, boundsCheck: boundsCheck}; endfunction @@ -364,7 +377,7 @@ function Maybe#(Exception) checkForException( end end else if(dInst.iType == Csr) begin - let csr = pack(fromMaybe(?, dInst.csr)); + let csr = pack(fromMaybe(CSRnone, dInst.csr)); Bool csr_has_priv = (prv >= csr[9:8]); if(!csr_has_priv) begin exception = Valid (IllegalInst); @@ -373,8 +386,29 @@ function Maybe#(Exception) checkForException( validValue(dInst.csr) == CSRsatp) begin exception = Valid (IllegalInst); end - // TODO check permission for accessing cycle/inst/time, and check - // read-only CSRs being written + let rs1 = case (regs.src2) matches + tagged Valid (tagged Gpr .r) : r; + default: 0; + endcase; + let imm = case (dInst.imm) matches + tagged Valid .n: n; + default: 0; + endcase; + Bool writes_csr = ((dInst.execFunc == tagged Alu Csrw) || (rs1 != 0) || (imm != 0)); + Bool read_only = (csr [11:10] == 2'b11); + Bool write_deny = (writes_csr && read_only); + Bool unimplemented = (csr == pack(CSRnone)); // Added by Bluespec + if (write_deny || !csr_has_priv || unimplemented) begin + exception = Valid (IllegalInst); + end + end + else if(dInst.iType == Scr) begin + let scr = pack(fromMaybe(SCR_None, dInst.scr)); + Bool scr_has_priv = (prv >= scr[4:3]); + Bool unimplemented = (scr == pack(SCR_None)); // Added by Bluespec + if(!scr_has_priv || unimplemented) begin // TODO only PCC read only, and decoded as AUIPCC + exception = Valid (IllegalInst); + end end else if(dInst.iType == Fpu) begin if(dInst.execFunc matches tagged Fpu .fpu_f) begin diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index b197633..c4f5a06 100755 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -217,9 +217,11 @@ typedef enum { Alu, Ld, St, Lr, Sc, J, Jr, Br, + CCall, CJALR, Cap, Auipc, Fpu, Csr, + Scr, Fence, FenceI, SFence, Ecall, Ebreak, @@ -332,11 +334,15 @@ typedef union tagged { MemInst Mem; MulDivInst MulDiv; FpuInst Fpu; - CapInspectFunc CapInspect; - CapModifyFunc CapModify; void Other; } ExecFunc deriving(Bits, Eq, FShow); +typedef union tagged { + CapInspectFunc CapInspect; + CapModifyFunc CapModify; + void Other; +} CapFunc deriving(Bits, Eq, FShow); + // Rounding Modes (encoding by risc-v, not general fpu) typedef enum { RNE = 3'b000, @@ -574,6 +580,7 @@ typedef CSR_XCapCause CapException; typedef struct { IType iType; ExecFunc execFunc; + CapFunc capFunc; CapChecks capChecks; Maybe#(CSR) csr; Maybe#(SCR) scr; // Special Capability Register. @@ -767,7 +774,7 @@ Bit#(7) privSFENCEVMA = 7'h9; function Bool isSystem(IType iType) = ( iType == Unsupported || iType == Interrupt || - iType == Ecall || iType == Ebreak || iType == Csr || + iType == Ecall || iType == Ebreak || iType == Csr || iType == Scr || iType == SFence || iType == FenceI || iType == Sret || iType == Mret ); diff --git a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv index b0f0cf4..7d42921 100755 --- a/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ReorderBuffer.bsv @@ -71,6 +71,7 @@ typedef struct { Data store_data; ByteEn store_data_BE; `endif + Maybe#(SCR) scr; Maybe#(CSR) csr; Bool claimed_phy_reg; // whether we need to commmit renaming Maybe#(TrapWithCap)trap; @@ -249,6 +250,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p Reg #(ByteEn) rg_store_data_BE <- mkRegU; `endif Reg#(Maybe#(CSR)) csr <- mkRegU; + Reg#(Maybe#(SCR)) scr <- mkRegU; Reg#(Bool) claimed_phy_reg <- mkRegU; Ehr#(TAdd#(TAdd#(2, TDiv#(aluExeNum,2)), aluExeNum), Maybe#(TrapWithCap)) trap <- mkEhr(?); Ehr#(3, Maybe#(TrapWithCap)) mem_early_trap <- mkEhr(?); @@ -414,6 +416,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p // rg_store_data will be written in Mem pipeline // rg_store_data_BE will be written in Mem pipeline csr <= x.csr; + scr <= x.scr; claimed_phy_reg <= x.claimed_phy_reg; trap[trap_enq_port] <= x.trap; tval[trap_enq_port] <= x.tval; @@ -461,6 +464,7 @@ module mkReorderBufferRowEhr(ReorderBufferRowEhr#(aluExeNum, fpuMulDivExeNum)) p store_data_BE: rg_store_data_BE, `endif csr: csr, + scr: scr, claimed_phy_reg: claimed_phy_reg, trap: trap[trap_deq_port], tval: tval[trap_deq_port],