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

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