diff --git a/src/Cpu/Alu.bsv b/src/Cpu/Alu.bsv index 0edb15d..9b208ce 100644 --- a/src/Cpu/Alu.bsv +++ b/src/Cpu/Alu.bsv @@ -7,80 +7,76 @@ import RV_ISA::*; export AluCfg, AluIfc(..), mkAlu, Execute(..); -function Maybe#(Bit#(32)) execute32(RVALUOperator operator, Bit#(32) operand1, Bit#(32) operand2); - let sum = operand1 + operand2; - let difference = operand1 - operand2; - let bitwise_and = operand1 & operand2; - let bitwise_or = operand1 | operand2; - let bitwise_xor = operand1 ^ operand2; - let sltu = (operand1 < operand2 ? 1 : 0); - let slt = (begin - Int#(32) signedOperand1 = unpack(pack(operand1)); - Int#(32) signedOperand2 = unpack(pack(operand2)); - (signedOperand1 < signedOperand2 ? 1 : 0); - end); - - let sll = operand1 << operand2[4:0]; - let sra = signedShiftRight(operand1, operand2[4:0]); - let srl = operand1 >> operand2[4:0]; - - return case(operator) - alu_ADD: tagged Valid sum; - alu_SUB: tagged Valid difference; - alu_AND: tagged Valid bitwise_and; - alu_OR: tagged Valid bitwise_or; - alu_XOR: tagged Valid bitwise_xor; - alu_SLTU: tagged Valid sltu; - alu_SLT: tagged Valid slt; - alu_SLL: tagged Valid sll; - alu_SRA: tagged Valid sra; - alu_SRL: tagged Valid srl; - default: tagged Invalid; - endcase; -endfunction - -function Maybe#(Bit#(64)) execute64(RVALUOperator operator, Bit#(64) operand1, Bit#(64) operand2); - let sum = operand1 + operand2; - let difference = operand1 - operand2; - let bitwise_and = operand1 & operand2; - let bitwise_or = operand1 | operand2; - let bitwise_xor = operand1 ^ operand2; - let sltu = (operand1 < operand2 ? 1 : 0); - let slt = (begin - Int#(64) signedOperand1 = unpack(pack(operand1)); - Int#(64) signedOperand2 = unpack(pack(operand2)); - (signedOperand1 < signedOperand2 ? 1 : 0); - end); - - let sll = operand1 << operand2[5:0]; - let sra = signedShiftRight(operand1, operand2[5:0]); - let srl = operand1 >> operand2[5:0]; - - return case(operator) - alu_ADD: tagged Valid sum; - alu_SUB: tagged Valid difference; - alu_AND: tagged Valid bitwise_and; - alu_OR: tagged Valid bitwise_or; - alu_XOR: tagged Valid bitwise_xor; - alu_SLTU: tagged Valid sltu; - alu_SLT: tagged Valid slt; - alu_SLL: tagged Valid sll; - alu_SRA: tagged Valid sra; - alu_SRL: tagged Valid srl; - default: tagged Invalid; - endcase; -endfunction - typeclass Execute#(numeric type xlen); function Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2); endtypeclass instance Execute#(32); - function execute = execute32; + function Maybe#(Bit#(32)) execute(RVALUOperator operator, Bit#(32) operand1, Bit#(32) operand2); + let sum = operand1 + operand2; + let difference = operand1 - operand2; + let bitwise_and = operand1 & operand2; + let bitwise_or = operand1 | operand2; + let bitwise_xor = operand1 ^ operand2; + let sltu = (operand1 < operand2 ? 1 : 0); + let slt = (begin + Int#(32) signedOperand1 = unpack(pack(operand1)); + Int#(32) signedOperand2 = unpack(pack(operand2)); + (signedOperand1 < signedOperand2 ? 1 : 0); + end); + + let sll = operand1 << operand2[4:0]; + let sra = signedShiftRight(operand1, operand2[4:0]); + let srl = operand1 >> operand2[4:0]; + + return case(operator) + alu_ADD: tagged Valid sum; + alu_SUB: tagged Valid difference; + alu_AND: tagged Valid bitwise_and; + alu_OR: tagged Valid bitwise_or; + alu_XOR: tagged Valid bitwise_xor; + alu_SLTU: tagged Valid sltu; + alu_SLT: tagged Valid slt; + alu_SLL: tagged Valid sll; + alu_SRA: tagged Valid sra; + alu_SRL: tagged Valid srl; + default: tagged Invalid; + endcase; + endfunction endinstance instance Execute#(64); - function execute = execute64; + function Maybe#(Bit#(64)) execute(RVALUOperator operator, Bit#(64) operand1, Bit#(64) operand2); + let sum = operand1 + operand2; + let difference = operand1 - operand2; + let bitwise_and = operand1 & operand2; + let bitwise_or = operand1 | operand2; + let bitwise_xor = operand1 ^ operand2; + let sltu = (operand1 < operand2 ? 1 : 0); + let slt = (begin + Int#(64) signedOperand1 = unpack(pack(operand1)); + Int#(64) signedOperand2 = unpack(pack(operand2)); + (signedOperand1 < signedOperand2 ? 1 : 0); + end); + + let sll = operand1 << operand2[5:0]; + let sra = signedShiftRight(operand1, operand2[5:0]); + let srl = operand1 >> operand2[5:0]; + + return case(operator) + alu_ADD: tagged Valid sum; + alu_SUB: tagged Valid difference; + alu_AND: tagged Valid bitwise_and; + alu_OR: tagged Valid bitwise_or; + alu_XOR: tagged Valid bitwise_xor; + alu_SLTU: tagged Valid sltu; + alu_SLT: tagged Valid slt; + alu_SLL: tagged Valid sll; + alu_SRA: tagged Valid sra; + alu_SRL: tagged Valid srl; + default: tagged Invalid; + endcase; + endfunction endinstance typedef struct { diff --git a/src/Cpu/CSRs/MachineStatus.bsv b/src/Cpu/CSRs/MachineStatus.bsv index 09d0ada..bbdc793 100644 --- a/src/Cpu/CSRs/MachineStatus.bsv +++ b/src/Cpu/CSRs/MachineStatus.bsv @@ -72,22 +72,17 @@ instance DefaultValue#(MachineStatus); }; 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 +typeclass MachineStatusBits#(numeric type xlen); + function Bit#(xlen) mstatus_pack(MachineStatus mstatus); + function MachineStatus mstatus_unpack(Bit#(xlen) mstatus_packed); +endtypeclass -module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc#(xlen)) - provisos( - Add#(a__, 32, xlen) - ); - Reg#(MachineStatus) mstatus <- mkReg(defaultValue); - - function Bit#(32) packLower; +instance MachineStatusBits#(32); + function Bit#(32) mstatus_pack(MachineStatus mstatus); + Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1); return { - 9'b0, + sd, + 8'b0, pack(mstatus.tsr), pack(mstatus.tw), pack(mstatus.tvm), @@ -110,41 +105,82 @@ module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc#(xlen)) }; endfunction - function Bit#(32) packUpper; + function MachineStatus mstatus_unpack(Bit#(32) mstatus_packed); + return defaultValue; + endfunction +endinstance + +instance MachineStatusBits#(64); + function Bit#(64) mstatus_pack(MachineStatus mstatus); + Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1); return { - 26'b0, + sd, + 25'b0, pack(mstatus.mbe), pack(mstatus.sbe), pack(mstatus.sxl), - pack(mstatus.uxl) + pack(mstatus.uxl), + 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 - method Bit#(xlen) pack; - Bit#(32) lower = packLower; - Bit#(xlen) mstatus_ = 0; + function MachineStatus mstatus_unpack(Bit#(64) mstatus_packed); + return defaultValue; + endfunction +endinstance - Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1); - mstatus_[valueof(xlen)-1] = sd; - mstatus_[31:0] = lower; +interface MachineStatus_Ifc#(numeric type xlen); + method Action beginTrap(RVPrivilegeLevel currentPriv); + interface Get#(Bit#(xlen)) getMachineStatus; + interface Put#(Bit#(xlen)) putMachineStatus; +endinterface - if (valueof(xlen) == 64) begin - mstatus_[valueof(xlen)-2:32] = packUpper; - end - - return mstatus_; - endmethod - - method Action unpack(Bit#(xlen) bits); - endmethod +module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc#(xlen)) + provisos( + Add#(a__, 32, xlen), + MachineStatusBits#(xlen) + ); + Reg#(Bit#(xlen)) mstatus <- mkReg(defaultValue); + method Action beginTrap(RVPrivilegeLevel currentPriv); + // CurPriv => MSTATUS::MPP + let mstatus_ = mstatus_unpack(mstatus); + mstatus_.mpp = currentPriv; + + // MSTATUS::MIE => MSTATUS::MPIE + mstatus_.mpie = mstatus_.mie; + mstatus_.mie = False; // Disable interrupts + + mstatus <= mstatus_pack(mstatus_); + endmethod + interface Get getMachineStatus = toGet(mstatus); interface Put putMachineStatus; - method Action put(MachineStatus value); + method Action put(Bit#(xlen) newValue); // // Only MPP, MIE, and MIE are writable. // - MachineStatus mstatus_ = mstatus; + MachineStatus mstatus_ = mstatus_unpack(mstatus); + MachineStatus value = mstatus_unpack(newValue); if (cfg.extS) begin mstatus_.mpp = value.mpp; @@ -160,7 +196,7 @@ module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc#(xlen)) mstatus_.mpie = value.mpie; mstatus_.mie = value.mie; - mstatus <= mstatus_; + mstatus <= mstatus_pack(mstatus_); endmethod endinterface endmodule diff --git a/src/Cpu/CSRs/MachineStatus_tb.bsv b/src/Cpu/CSRs/MachineStatus_tb.bsv index 5469d3c..26da9b7 100644 --- a/src/Cpu/CSRs/MachineStatus_tb.bsv +++ b/src/Cpu/CSRs/MachineStatus_tb.bsv @@ -6,6 +6,12 @@ import Assert::*; module mkTopModule(Empty); Reg#(Bit#(20)) stepNumber <- mkReg(0); + IsaCfg#(32) rv32icfg = defaultValue; + MachineStatus_Ifc#(32) rv32i <- mkMachineStatus(rv32icfg); + + IsaCfg#(64) rv64icfg = defaultValue; + MachineStatus_Ifc#(64) rv64i <- mkMachineStatus(rv64icfg); + (* no_implicit_conditions *) rule test; case(stepNumber) diff --git a/src/Cpu/CSRs/CsrFile.bsv b/src/Cpu/CsrFile.bsv similarity index 94% rename from src/Cpu/CSRs/CsrFile.bsv rename to src/Cpu/CsrFile.bsv index de64964..13f54b4 100644 --- a/src/Cpu/CSRs/CsrFile.bsv +++ b/src/Cpu/CsrFile.bsv @@ -170,9 +170,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen)) if (!isWARLIgnore(index)) begin case(index) // Machine Information Registers (MRO) -/* csr_MVENDORID: result.value = extend(machineInfoCfg.mvendorid); -*/ csr_MARCHID: result.value = machineInfoCfg.marchid; csr_MIMPID: result.value = machineInfoCfg.mimpid; csr_MHARTID: result.value = machineInfoCfg.mhartid; @@ -186,12 +184,12 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen)) csr_MIDELEG: result.value = mideleg; csr_MEDELEG: result.value = medeleg; - csr_MSTATUS: result.value = mstatus.pack; -/* + csr_MSTATUS: result.value <- mstatus.getMachineStatus.get; + csr_MCYCLE, csr_CYCLE: begin result.value = mcycle; end -*/ + csr_MSCRATCH: result.value = mscratch; csr_MIP: result.value = mip; csr_MIE: result.value = mie; @@ -232,7 +230,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen)) // No-Op end csr_MSCRATCH: mscratch <= value; - csr_MSTATUS: mstatus.unpack(value); + csr_MSTATUS: mstatus.putMachineStatus.put(value); csr_MTVAL: mtval <= value; csr_MTVEC: mtvec <= value; csr_MIE: mie <= value; @@ -327,23 +325,16 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen)) Bit#(xlen) cause = 0; let trapPrivilegeLevel = getTrapPrivilegeLevel(trap); -/* + cause = zeroExtend(trap.cause); if (!trap.isInterrupt) begin cause[valueOf(xlen)-1] = 1; end -*/ + // PC => MEPC writeWithOffset1(trapPrivilegeLevel, csr_EPC, trapProgramCounter); - // CurPriv => MSTATUS::MPP - let mstatus_ <- mstatus.getMachineStatus.get; - mstatus_.mpp = currentPriv; - - // MSTATUS::MIE => MSTATUS::MPIE - mstatus_.mpie = mstatus_.mie; - mstatus_.mie = False; // Disable interrupts - mstatus.putMachineStatus.put(mstatus_); + mstatus.beginTrap(currentPriv); // cause => CAUSE writeWithOffset1(trapPrivilegeLevel, csr_CAUSE, cause); @@ -354,14 +345,13 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen)) let trapHandler = vectorTableBase; // Check and handle a vectored trap handler table -/* if (trapHandler[1:0] == 1) begin trapHandler[1:0] = 0; if(trap.isInterrupt) begin trapHandler = trapHandler + extend(4 * trap.cause); end end -*/ + currentPriv <= trapPrivilegeLevel; return trapHandler; @@ -372,15 +362,14 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen)) let readStatus <- readWithOffset1(currentPriv, csr_STATUS); if (readStatus.denied == False) begin -/* - MachineStatus#(xlen) mstatus = unpack(readStatus.value); - let newPrivilegeLevel = mstatus.mpp; - mstatus.mie = mstatus.mpie; - mstatus.mpie = False; -*/ + MachineStatus mstatus_ = mstatus_unpack(readStatus.value); + let newPrivilegeLevel = mstatus_.mpp; + mstatus_.mie = mstatus_.mpie; + mstatus_.mpie = False; + // Attempt to update MSTATUS. The current privilege level may prevent this. -/* - let writeStatus <- writeInternal(csr_MSTATUS, pack(mstatus)); + + let writeStatus <- writeInternal(csr_MSTATUS, mstatus_pack(mstatus_)); if (writeStatus.denied == False) begin currentPriv <= newPrivilegeLevel; readStatus <- readWithOffset1(currentPriv, csr_EPC); @@ -388,7 +377,6 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen)) newProgramCounter = readStatus.value; end end -*/ end return newProgramCounter; endmethod diff --git a/src/Cpu/CSRs/CsrFile_tb.bsv b/src/Cpu/CsrFile_tb.bsv similarity index 100% rename from src/Cpu/CSRs/CsrFile_tb.bsv rename to src/Cpu/CsrFile_tb.bsv