This commit is contained in:
John Terrell 2023-04-23 10:45:13 -07:00
parent 086a91ae5b
commit fda8dafad7
Signed by untrusted user who does not match committer: johnt
GPG Key ID: 2E424258DD3731F4
5 changed files with 154 additions and 128 deletions

View File

@ -7,80 +7,76 @@
import RV_ISA::*; import RV_ISA::*;
export AluCfg, AluIfc(..), mkAlu, Execute(..); 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); typeclass Execute#(numeric type xlen);
function Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2); function Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2);
endtypeclass endtypeclass
instance Execute#(32); 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 endinstance
instance Execute#(64); 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 endinstance
typedef struct { typedef struct {

View File

@ -72,21 +72,54 @@ instance DefaultValue#(MachineStatus);
}; };
endinstance endinstance
interface MachineStatus_Ifc#(numeric type xlen); typeclass MachineStatusBits#(numeric type xlen);
method Bit#(xlen) pack; function Bit#(xlen) mstatus_pack(MachineStatus mstatus);
method Action unpack(Bit#(xlen) bits); function MachineStatus mstatus_unpack(Bit#(xlen) mstatus_packed);
interface Get#(MachineStatus) getMachineStatus; endtypeclass
interface Put#(MachineStatus) putMachineStatus;
endinterface
module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc#(xlen)) instance MachineStatusBits#(32);
provisos( function Bit#(32) mstatus_pack(MachineStatus mstatus);
Add#(a__, 32, xlen) Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1);
);
Reg#(MachineStatus) mstatus <- mkReg(defaultValue);
function Bit#(32) packLower;
return { return {
sd,
8'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 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 {
sd,
25'b0,
pack(mstatus.mbe),
pack(mstatus.sbe),
pack(mstatus.sxl),
pack(mstatus.uxl),
9'b0, 9'b0,
pack(mstatus.tsr), pack(mstatus.tsr),
pack(mstatus.tw), pack(mstatus.tw),
@ -110,41 +143,44 @@ module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc#(xlen))
}; };
endfunction endfunction
function Bit#(32) packUpper; function MachineStatus mstatus_unpack(Bit#(64) mstatus_packed);
return { return defaultValue;
26'b0,
pack(mstatus.mbe),
pack(mstatus.sbe),
pack(mstatus.sxl),
pack(mstatus.uxl)
};
endfunction endfunction
endinstance
method Bit#(xlen) pack; interface MachineStatus_Ifc#(numeric type xlen);
Bit#(32) lower = packLower; method Action beginTrap(RVPrivilegeLevel currentPriv);
Bit#(xlen) mstatus_ = 0; interface Get#(Bit#(xlen)) getMachineStatus;
interface Put#(Bit#(xlen)) putMachineStatus;
endinterface
Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1); module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc#(xlen))
mstatus_[valueof(xlen)-1] = sd; provisos(
mstatus_[31:0] = lower; Add#(a__, 32, xlen),
MachineStatusBits#(xlen)
);
Reg#(Bit#(xlen)) mstatus <- mkReg(defaultValue);
if (valueof(xlen) == 64) begin method Action beginTrap(RVPrivilegeLevel currentPriv);
mstatus_[valueof(xlen)-2:32] = packUpper; // CurPriv => MSTATUS::MPP
end let mstatus_ = mstatus_unpack(mstatus);
mstatus_.mpp = currentPriv;
return mstatus_; // MSTATUS::MIE => MSTATUS::MPIE
endmethod mstatus_.mpie = mstatus_.mie;
mstatus_.mie = False; // Disable interrupts
method Action unpack(Bit#(xlen) bits); mstatus <= mstatus_pack(mstatus_);
endmethod endmethod
interface Get getMachineStatus = toGet(mstatus); interface Get getMachineStatus = toGet(mstatus);
interface Put putMachineStatus; interface Put putMachineStatus;
method Action put(MachineStatus value); method Action put(Bit#(xlen) newValue);
// //
// Only MPP, MIE, and MIE are writable. // Only MPP, MIE, and MIE are writable.
// //
MachineStatus mstatus_ = mstatus; MachineStatus mstatus_ = mstatus_unpack(mstatus);
MachineStatus value = mstatus_unpack(newValue);
if (cfg.extS) begin if (cfg.extS) begin
mstatus_.mpp = value.mpp; mstatus_.mpp = value.mpp;
@ -160,7 +196,7 @@ module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc#(xlen))
mstatus_.mpie = value.mpie; mstatus_.mpie = value.mpie;
mstatus_.mie = value.mie; mstatus_.mie = value.mie;
mstatus <= mstatus_; mstatus <= mstatus_pack(mstatus_);
endmethod endmethod
endinterface endinterface
endmodule endmodule

View File

@ -6,6 +6,12 @@ import Assert::*;
module mkTopModule(Empty); module mkTopModule(Empty);
Reg#(Bit#(20)) stepNumber <- mkReg(0); 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 *) (* no_implicit_conditions *)
rule test; rule test;
case(stepNumber) case(stepNumber)

View File

@ -170,9 +170,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen))
if (!isWARLIgnore(index)) begin if (!isWARLIgnore(index)) begin
case(index) case(index)
// Machine Information Registers (MRO) // Machine Information Registers (MRO)
/*
csr_MVENDORID: result.value = extend(machineInfoCfg.mvendorid); csr_MVENDORID: result.value = extend(machineInfoCfg.mvendorid);
*/
csr_MARCHID: result.value = machineInfoCfg.marchid; csr_MARCHID: result.value = machineInfoCfg.marchid;
csr_MIMPID: result.value = machineInfoCfg.mimpid; csr_MIMPID: result.value = machineInfoCfg.mimpid;
csr_MHARTID: result.value = machineInfoCfg.mhartid; csr_MHARTID: result.value = machineInfoCfg.mhartid;
@ -186,12 +184,12 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen))
csr_MIDELEG: result.value = mideleg; csr_MIDELEG: result.value = mideleg;
csr_MEDELEG: result.value = medeleg; csr_MEDELEG: result.value = medeleg;
csr_MSTATUS: result.value = mstatus.pack; csr_MSTATUS: result.value <- mstatus.getMachineStatus.get;
/*
csr_MCYCLE, csr_CYCLE: begin csr_MCYCLE, csr_CYCLE: begin
result.value = mcycle; result.value = mcycle;
end end
*/
csr_MSCRATCH: result.value = mscratch; csr_MSCRATCH: result.value = mscratch;
csr_MIP: result.value = mip; csr_MIP: result.value = mip;
csr_MIE: result.value = mie; csr_MIE: result.value = mie;
@ -232,7 +230,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen))
// No-Op // No-Op
end end
csr_MSCRATCH: mscratch <= value; csr_MSCRATCH: mscratch <= value;
csr_MSTATUS: mstatus.unpack(value); csr_MSTATUS: mstatus.putMachineStatus.put(value);
csr_MTVAL: mtval <= value; csr_MTVAL: mtval <= value;
csr_MTVEC: mtvec <= value; csr_MTVEC: mtvec <= value;
csr_MIE: mie <= value; csr_MIE: mie <= value;
@ -327,23 +325,16 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen))
Bit#(xlen) cause = 0; Bit#(xlen) cause = 0;
let trapPrivilegeLevel = getTrapPrivilegeLevel(trap); let trapPrivilegeLevel = getTrapPrivilegeLevel(trap);
/*
cause = zeroExtend(trap.cause); cause = zeroExtend(trap.cause);
if (!trap.isInterrupt) begin if (!trap.isInterrupt) begin
cause[valueOf(xlen)-1] = 1; cause[valueOf(xlen)-1] = 1;
end end
*/
// PC => MEPC // PC => MEPC
writeWithOffset1(trapPrivilegeLevel, csr_EPC, trapProgramCounter); writeWithOffset1(trapPrivilegeLevel, csr_EPC, trapProgramCounter);
// CurPriv => MSTATUS::MPP mstatus.beginTrap(currentPriv);
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_);
// cause => CAUSE // cause => CAUSE
writeWithOffset1(trapPrivilegeLevel, csr_CAUSE, cause); writeWithOffset1(trapPrivilegeLevel, csr_CAUSE, cause);
@ -354,14 +345,13 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen))
let trapHandler = vectorTableBase; let trapHandler = vectorTableBase;
// Check and handle a vectored trap handler table // Check and handle a vectored trap handler table
/*
if (trapHandler[1:0] == 1) begin if (trapHandler[1:0] == 1) begin
trapHandler[1:0] = 0; trapHandler[1:0] = 0;
if(trap.isInterrupt) begin if(trap.isInterrupt) begin
trapHandler = trapHandler + extend(4 * trap.cause); trapHandler = trapHandler + extend(4 * trap.cause);
end end
end end
*/
currentPriv <= trapPrivilegeLevel; currentPriv <= trapPrivilegeLevel;
return trapHandler; return trapHandler;
@ -372,15 +362,14 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen))
let readStatus <- readWithOffset1(currentPriv, csr_STATUS); let readStatus <- readWithOffset1(currentPriv, csr_STATUS);
if (readStatus.denied == False) begin if (readStatus.denied == False) begin
/* MachineStatus mstatus_ = mstatus_unpack(readStatus.value);
MachineStatus#(xlen) mstatus = unpack(readStatus.value); let newPrivilegeLevel = mstatus_.mpp;
let newPrivilegeLevel = mstatus.mpp; mstatus_.mie = mstatus_.mpie;
mstatus.mie = mstatus.mpie; mstatus_.mpie = False;
mstatus.mpie = False;
*/
// Attempt to update MSTATUS. The current privilege level may prevent this. // 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 if (writeStatus.denied == False) begin
currentPriv <= newPrivilegeLevel; currentPriv <= newPrivilegeLevel;
readStatus <- readWithOffset1(currentPriv, csr_EPC); readStatus <- readWithOffset1(currentPriv, csr_EPC);
@ -388,7 +377,6 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen))
newProgramCounter = readStatus.value; newProgramCounter = readStatus.value;
end end
end end
*/
end end
return newProgramCounter; return newProgramCounter;
endmethod endmethod