Refactoring around SCRs
This commit is contained in:
@@ -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