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