Initial attempt to allow reads/writes to xtvec, xepc via xtcc, xepcc
This commit is contained in:
@@ -858,19 +858,55 @@ function DecodeResult decode(Instruction inst, Bool cap_mode);
|
||||
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;
|
||||
fnCSRRSI, fnCSRRS: tagged Alu Csrs;
|
||||
fnCSRRCI, fnCSRRC: tagged Alu Csrc;
|
||||
endcase);
|
||||
if (truncate(immI) == pack(CSRmtvec) || truncate(immI) == pack(CSRmepc) || truncate(immI) == pack(CSRstvec) || truncate(immI) == pack(CSRsepc)) begin
|
||||
Bool shouldWrite = (funct3 == fnCSRRWI || funct3 == fnCSRRW) || rs1 != 0;
|
||||
dInst.iType = shouldWrite ? Scr : Cap;
|
||||
regs.dst = Valid(tagged Gpr rd);
|
||||
regs.src1 = (funct3[2] == 0 ? Valid(tagged Gpr rs1) : Invalid);
|
||||
dInst.imm = (funct3[2] == 0 ? Invalid : Valid(zeroExtend(rs1)));
|
||||
regs.src2 = Invalid;
|
||||
|
||||
regs.dst = Valid(tagged Gpr rd);
|
||||
regs.src1 = Invalid; // going to be CSR Reg
|
||||
regs.src2 = (funct3[2] == 0 ? Valid(tagged Gpr rs1) : Invalid);
|
||||
dInst.imm = (funct3[2] == 0 ? Invalid : Valid(zeroExtend(rs1)));
|
||||
dInst.csr = Valid(unpackCSR(truncate(immI)));
|
||||
CSRAccessFunc accessFunc = (case (funct3)
|
||||
fnCSRRWI, fnCSRRW: Write;
|
||||
fnCSRRSI, fnCSRRS: Set;
|
||||
fnCSRRCI, fnCSRRC: Clear;
|
||||
endcase);
|
||||
|
||||
let scrType = ?;
|
||||
case (truncate(immI))
|
||||
pack(CSRmepc): begin
|
||||
scrType = EPC (accessFunc);
|
||||
dInst.scr = Valid (SCR_MEPCC);
|
||||
end
|
||||
pack(CSRmtvec): begin
|
||||
scrType = TVEC (accessFunc);
|
||||
dInst.scr = Valid (SCR_MTCC);
|
||||
end
|
||||
pack(CSRsepc): begin
|
||||
scrType = EPC (accessFunc);
|
||||
dInst.scr = Valid (SCR_SEPCC);
|
||||
end
|
||||
pack(CSRstvec): begin
|
||||
scrType = TVEC (accessFunc);
|
||||
dInst.scr = Valid (SCR_STCC);
|
||||
end
|
||||
endcase
|
||||
|
||||
dInst.capFunc = CapModify (SpecialRW (scrType));
|
||||
end else begin
|
||||
dInst.iType = Csr;
|
||||
dInst.execFunc = (case (funct3)
|
||||
fnCSRRWI, fnCSRRW: tagged Alu Csrw;
|
||||
fnCSRRSI, fnCSRRS: tagged Alu Csrs;
|
||||
fnCSRRCI, fnCSRRC: tagged Alu Csrc;
|
||||
endcase);
|
||||
|
||||
regs.dst = Valid(tagged Gpr rd);
|
||||
regs.src1 = Invalid; // going to be CSR Reg
|
||||
regs.src2 = (funct3[2] == 0 ? Valid(tagged Gpr rs1) : Invalid);
|
||||
dInst.imm = (funct3[2] == 0 ? Invalid : Valid(zeroExtend(rs1)));
|
||||
dInst.csr = Valid(unpackCSR(truncate(immI)));
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -168,12 +168,20 @@ function CapPipe setBoundsALU(CapPipe cap, Data len, SetBoundsFunc boundsOp);
|
||||
endfunction
|
||||
|
||||
(* noinline *)
|
||||
function CapPipe specialRWALU(CapPipe cap, SpecialRWFunc scrType);
|
||||
function CapPipe specialRWALU(CapPipe cap, CapPipe oldCap, SpecialRWFunc scrType);
|
||||
function csrOp (oldOffset, val, f) =
|
||||
case (f)
|
||||
Write: val;
|
||||
Set: (oldOffset | val);
|
||||
Clear: (oldOffset & ~val);
|
||||
endcase;
|
||||
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;
|
||||
tagged TVEC .csrf: update_scr_via_csr(oldCap, csrOp(offset, getAddr(cap), csrf) & ~64'h2);
|
||||
tagged EPC .csrf: update_scr_via_csr(oldCap, csrOp(offset, getAddr(cap), csrf) & ~64'h1);
|
||||
tagged TCC: update_scr_via_csr(cap, offset & ~64'h2); // Mask out bit 1
|
||||
tagged EPCC: update_scr_via_csr(cap, offset & ~64'h1); // Mask out bit 0 TODO factor out update_scr_via_csr
|
||||
tagged Normal: cap;
|
||||
endcase);
|
||||
return res;
|
||||
endfunction
|
||||
@@ -186,7 +194,13 @@ function CapPipe capModify(CapPipe a, CapPipe b, CapModifyFunc func);
|
||||
tagged SetBounds .boundsOp :
|
||||
setBoundsALU(a, getAddr(b), boundsOp);
|
||||
tagged SpecialRW .scrType :
|
||||
b;
|
||||
case (scrType) matches
|
||||
tagged TCC: b;
|
||||
tagged EPCC: b;
|
||||
tagged Normal: b;
|
||||
tagged TVEC ._: nullWithAddr(getOffset(b));
|
||||
tagged EPC ._: nullWithAddr(getOffset(b));
|
||||
endcase
|
||||
tagged SetAddr .addrSource :
|
||||
if (addrSource == Src2Type && (getKind(b) == UNSEALED)) return nullWithAddr(-1); // TODO correct behaviour around reserved types
|
||||
else return setAddr(a, (addrSource == Src2Type) ? zeroExtend(getKind(b).SEALED_WITH_TYPE) : getAddr(b) ).value;
|
||||
@@ -317,8 +331,8 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C
|
||||
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;
|
||||
Maybe#(CapPipe) capImm = isValid(getDInstImm(dInst)) ? Valid (nullWithAddr(getDInstImm(dInst).Valid)) : Invalid;
|
||||
let aluVal2 = fromMaybe(rVal2, capImm);
|
||||
// Get the alu function. By default, it adds. This is used by memory instructions
|
||||
AluFunc alu_f = dInst.execFunc matches tagged Alu .alu_f ? alu_f : Add;
|
||||
Data alu_result = alu(getAddr(rVal1), getAddr(aluVal2), alu_f);
|
||||
@@ -350,8 +364,8 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C
|
||||
CCall : cap_alu_result;
|
||||
CJALR : link_pcc;
|
||||
Jr : nullWithAddr(getOffset(link_pcc));
|
||||
Auipc : nullWithAddr(getOffset(pcc) + fromMaybe(?, getDInstImm(dInst)));
|
||||
Auipcc : incOffset(pcc, fromMaybe(?, getDInstImm(dInst))).value; // could be computed with alu
|
||||
Auipc : nullWithAddr(getOffset(pcc) + getDInstImm(dInst).Valid);
|
||||
Auipcc : incOffset(pcc, getDInstImm(dInst).Valid).value; // could be computed with alu
|
||||
Csr : rVal1;
|
||||
Scr : rVal2;
|
||||
Cap : cap_alu_result;
|
||||
@@ -363,7 +377,7 @@ function ExecResult basicExec(DecodedInst dInst, CapPipe rVal1, CapPipe rVal2, C
|
||||
default : cf.nextPc; //TODO should this be nullified?
|
||||
endcase);
|
||||
|
||||
CapPipe scr_data = specialRWALU(rVal1, dInst.capFunc.CapModify.SpecialRW);
|
||||
CapPipe scr_data = specialRWALU(fromMaybe(rVal1, capImm), aluVal2, dInst.capFunc.CapModify.SpecialRW);
|
||||
|
||||
return ExecResult{data: data, csrData: csr_data, scrData: scr_data, addr: addr, controlFlow: cf, capException: capException, boundsCheck: boundsCheck};
|
||||
endfunction
|
||||
|
||||
@@ -252,7 +252,15 @@ typedef enum {
|
||||
} SetBoundsFunc deriving(Bits, Eq, FShow);
|
||||
|
||||
typedef enum {
|
||||
TCC, EPCC, Normal
|
||||
Write, Set, Clear
|
||||
} CSRAccessFunc deriving(Bits, Eq, FShow);
|
||||
|
||||
typedef union tagged {
|
||||
CSRAccessFunc TVEC;
|
||||
CSRAccessFunc EPC;
|
||||
void TCC;
|
||||
void EPCC;
|
||||
void Normal;
|
||||
} SpecialRWFunc deriving(Bits, Eq, FShow);
|
||||
|
||||
typedef enum {
|
||||
|
||||
Reference in New Issue
Block a user