E-Series/src/Cpu/CSRs/MachineStatus.bsv
John Terrell 032a258f71
WIP
2023-04-20 19:06:30 -07:00

167 lines
4.9 KiB
Plaintext

import GetPut::*;
import IsaCfg::*;
import RV_ISA::*;
typedef Bit#(2) XLENEncoding;
XLENEncoding xlen_32 = 2'b01;
XLENEncoding xlen_64 = 2'b10;
XLENEncoding xlen_128 = 2'b11;
typedef Bit#(2) FSVSState;
FSVSState fsvs_OFF = 2'b00;
FSVSState fsvs_INITIAL = 2'b01;
FSVSState fsvs_CLEAN = 2'b10;
FSVSState fsvs_DIRTY = 2'b11;
typedef Bit#(2) XSState;
XSState xs_ALL_OFF = 2'b00;
XSState xs_NONE_DIRTY_OR_CLEAN = 2'b01;
XSState xs_NONE_DIRTY_SOME_CLEAN = 2'b10;
XSState xs_SOME_DIRTY = 2'b11;
typedef struct {
Bool sie; // Supervisor Interrupt Enable
Bool mie; // Machine Interrupt Enable
Bool spie; // Supervisor Mode Interupts Enabled During Trap
Bool ube; // User Mode Data Accesses are Big Endian
Bool mpie; // Machine Mode Interrupts Enabled During Trap
Bool spp; // Supervisor Previous Privilege Mode
FSVSState vs; // Vector Extension State
RVPrivilegeLevel mpp; // Machine Previous Privilege Level
FSVSState fs; // Floating Point Status
XSState xs; // User Mode Extension Status
Bool mprv; // Modify Privilege Mode For Loads/Stores
Bool sum; // Permit Supervisor User Memory Access
Bool mxr; // Make Executable Pages Readable
Bool tvm; // Trap Virtual Memory Management Accesses
Bool tw; // Timeout-Wait
Bool tsr; // Trap SRET Instruction
XLENEncoding uxl; // User Mode XLEN value (RV64 only)
XLENEncoding sxl; // Supervisor Mode XLEN value (RV64 only)
Bool sbe; // Supervisor Mode Data Accesses are Big Endian
Bool mbe; // Machine Mode Data Accesses are Big Endian
} MachineStatus deriving(Bits, Eq, FShow);
instance DefaultValue#(MachineStatus);
defaultValue = MachineStatus {
sie: False,
mie: False,
spie: False,
ube: False,
mpie: False,
spp: False,
vs: fsvs_OFF,
mpp: priv_MACHINE,
fs: fsvs_OFF,
xs: xs_ALL_OFF,
mprv: False,
sum: False,
mxr: False,
tvm: False,
tw: False,
tsr: False,
uxl: xlen_64,
sxl: xlen_64,
sbe: False,
mbe: False
};
endinstance
interface MachineStatus_Ifc#(numeric type xlen);
method Bit#(xlen) pack;
method Action unpack(Bit#(xlen) bits);
interface Get#(MachineStatus) getMachineStatus;
interface Put#(MachineStatus) putMachineStatus;
endinterface
module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc#(xlen))
provisos(
Add#(a__, 32, xlen)
);
Reg#(MachineStatus) mstatus <- mkReg(defaultValue);
function Bit#(32) packLower;
return {
9'b0,
pack(mstatus.tsr),
pack(mstatus.tw),
pack(mstatus.tvm),
pack(mstatus.mxr),
pack(mstatus.sum),
pack(mstatus.mprv),
pack(mstatus.xs),
pack(mstatus.fs),
pack(mstatus.mpp),
pack(mstatus.vs),
pack(mstatus.spp),
pack(mstatus.mpie),
pack(mstatus.ube),
pack(mstatus.spie),
1'b0,
pack(mstatus.mie),
1'b0,
pack(mstatus.sie),
1'b0
};
endfunction
function Bit#(32) packUpper;
return {
26'b0,
pack(mstatus.mbe),
pack(mstatus.sbe),
pack(mstatus.sxl),
pack(mstatus.uxl)
};
endfunction
method Bit#(xlen) pack;
Bit#(32) lower = packLower;
Bit#(xlen) mstatus_ = 0;
Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1);
mstatus_[valueof(xlen)-1] = sd;
mstatus_[31:0] = lower;
if (valueof(xlen) == 64) begin
mstatus_[valueof(xlen)-2:32] = packUpper;
end
return mstatus_;
endmethod
method Action unpack(Bit#(xlen) bits);
endmethod
interface Get getMachineStatus = toGet(mstatus);
interface Put putMachineStatus;
method Action put(MachineStatus value);
//
// Only MPP, MIE, and MIE are writable.
//
MachineStatus mstatus_ = mstatus;
if (cfg.extS) begin
mstatus_.mpp = value.mpp;
end else begin
// Supervisor mode not supported, ensure only USER and MACHINE
// mode are set in MPP.
RVPrivilegeLevel requestedMPP = value.mpp;
if (requestedMPP == priv_USER || requestedMPP == priv_MACHINE) begin
mstatus_.mpp = requestedMPP;
end
end
mstatus_.mpie = value.mpie;
mstatus_.mie = value.mie;
mstatus <= mstatus_;
endmethod
endinterface
endmodule