Refactoring around SCRs
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -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],
|
||||
|
||||
Reference in New Issue
Block a user