Refactoring around SCRs

This commit is contained in:
Peter Rugg
2020-05-07 16:19:26 +01:00
parent e5b7ba6b13
commit 27947f4df7
13 changed files with 284 additions and 434 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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),

View File

@@ -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

View File

@@ -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);

View File

@@ -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,

View File

@@ -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

View File

@@ -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")

View File

@@ -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;

View File

@@ -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

View File

@@ -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
);

View File

@@ -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],