Compare commits

...

10 Commits

Author SHA1 Message Date
John Terrell
c22d2639eb
Divided stage modules into seperate "Module" and "Stage" modules. 2023-06-03 14:59:06 -07:00
John Terrell
11e527eea0
Moved MemoryTypes.bsv to MemoryIO.bsv 2023-04-26 13:14:41 -07:00
John Terrell
96b36317b3
WIP 2023-04-25 16:45:58 -07:00
John Terrell
b82a6a9a79
WIP 2023-04-23 22:05:29 -07:00
John Terrell
73ae766dc1
WIP 2023-04-23 11:18:03 -07:00
John Terrell
fda8dafad7
WIP 2023-04-23 10:45:13 -07:00
John Terrell
086a91ae5b
WIP 2023-04-22 22:41:47 -07:00
John Terrell
032a258f71
WIP 2023-04-20 19:06:30 -07:00
John Terrell
2ec9fb9645
Removed bubble flag in pipeline registers. Will rely on the default NO-OP behavior instead. 2023-04-04 22:21:00 -07:00
John Terrell
61d2a7cab4
Fixed up NPC and Epoch handling. 2023-03-24 14:48:05 -07:00
26 changed files with 973 additions and 744 deletions

View File

@ -5,86 +5,78 @@
// reponsible for mathematical operations inside the CPU. // reponsible for mathematical operations inside the CPU.
// //
import RV_ISA::*; import RV_ISA::*;
export RV_ISA::*, AluCfg, AluIfc(..), mkAlu; 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);
endinstance 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);
instance Execute#(n); let sll = operand1 << operand2[5:0];
function execute = tagged Invalid; 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 {
@ -94,51 +86,12 @@ interface AluIfc#(numeric type xlen);
method Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2); method Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2);
endinterface endinterface
module mkAlu#(AluCfg#(xlen) cfg)(AluIfc#(xlen)); module mkAlu#(AluCfg#(xlen) cfg)(AluIfc#(xlen))
provisos(
Execute#(xlen)
);
method Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2); method Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2);
return execute(operator, operand1, operand2); return execute(operator, operand1, operand2);
// return case(operator)
// alu_ADD: tagged Valid (operand1 + operand2);
// alu_SUB: tagged Valid (operand1 - operand2);
// alu_AND: tagged Valid (operand1 & operand2);
// alu_OR: tagged Valid (operand1 | operand2);
// alu_XOR: tagged Valid (operand1 ^ operand2);
// alu_SLTU: tagged Valid setLessThanUnsigned(operand1, operand2);
// alu_SLT: tagged Valid setLessThan(operand1, operand2);
// alu_SLL: (xlen == 32 ? tagged Valid (operand1 << operand2[4:0]) : tagged Invalid);
// alu_SRA: (xlen == 32 ? tagged Valid signedShiftRight(operand1, operand2[4:0]) : tagged Invalid);
// alu_SRL: (xlen == 32 ? tagged Valid (operand1 >> operand2[4:0]) : tagged Invalid);
// end else if (xlen == 64) begin
// alu_SLL: tagged Valid (operand1 << operand2[5:0]);
// alu_SRA: tagged Valid signedShiftRight(operand1, operand2[5:0]);
// alu_SRL: tagged Valid (operand1 >> operand2[5:0]);
// alu_ADD32: begin
// let result = operand1[31:0] + operand2[31:0];
// return tagged Valid signExtend(result[31:0]);
// end
// alu_SUB32: begin
// let result = (operand1[31:0] - operand2[31:0]);
// return tagged Valid signExtend(result[31:0]);
// end
// alu_SLL32: begin
// let result = (operand1[31:0] << operand2[4:0]);
// return tagged Valid signExtend(result[31:0]);
// end
// alu_SRA32: begin
// let result = signedShiftRight(operand1[31:0], operand2[4:0]);
// return tagged Valid signExtend(result[31:0]);
// end
// alu_SRL32: begin
// let result = (operand1[31:0] >> operand2[4:0]);
// return tagged Valid signExtend(result[31:0]);
// end
// end
// default: tagged Invalid;
// endcase;
endmethod endmethod
endmodule endmodule

44
src/Cpu/Alu_tb.bsv Normal file
View File

@ -0,0 +1,44 @@
import Alu::*;
import IsaCfg::*;
import RV_ISA::*;
import Assert::*;
module mkTopModule(Empty);
Reg#(Bit#(20)) stepNumber <- mkReg(0);
// 32 bit ALU
AluCfg#(32) alucfg32 = AluCfg {
};
AluIfc#(32) alu32 <- mkAlu(alucfg32);
// 64 bit ALU
AluCfg#(64) alucfg64 = AluCfg {
};
AluIfc#(64) alu64 <- mkAlu(alucfg64);
(* no_implicit_conditions *)
rule test;
case(stepNumber)
0: begin
Maybe#(Bit#(32)) result32 = execute(alu_ADD, 3, 1);
dynamicAssert(isValid(result32), "ALU32 - add returned invalid");
dynamicAssert(result32.Valid == 4, "ALU32 - add result incorrect");
Maybe#(Bit#(64)) result64 = execute(alu_ADD, 3, 1);
dynamicAssert(isValid(result64), "ALU64 - add incorrect");
dynamicAssert(result32.Valid == 4, "ALU64 - add result incorrect");
end
default: begin
dynamicAssert(stepNumber == 1, "ALU - not all tests run");
$display(">>>PASS");
$finish();
end
endcase
endrule
rule increment_step_number;
stepNumber <= stepNumber + 1;
endrule
endmodule

129
src/Cpu/CSRs/MachineISA.bsv Normal file
View File

@ -0,0 +1,129 @@
import IsaCfg::*;
import GetPut::*;
typedef Bit#(2) MXL;
MXL mxl_32bit = 2'b01;
MXL mxl_64bit = 2'b10;
MXL mxl_128bit = 2'b11;
typedef struct {
Bool extZ; // ** RESERVED **
Bool extY; // ** RESERVED **
Bool extX; // Non-standard extensions present
Bool extW; // ** RESERVED **
Bool extV; // Vector extension
Bool extU; // User mode implemented
Bool extT; // ** RESERVED **
Bool extS; // Supervisor mode implemented
Bool extR; // ** RESERVED **
Bool extQ; // Quad precision floating-point extension
Bool extP; // Packed-SIMD extension
Bool extO; // ** RESERVED **
Bool extN; // User level interrupts extension
Bool extM; // Integer multiply/divide extension
Bool extL; // ** RESERVED **
Bool extK; // ** RESERVED **
Bool extJ; // Dynamically translated language extension
Bool extI; // RV32I/64I/128I base ISA
Bool extH; // Hypervisor extension
Bool extG; // ** RESERVED **
Bool extF; // Single precision floating-point extension
Bool extE; // RV32E base ISA
Bool extD; // Double precision floating-point extension
Bool extC; // Compressed instruction extension
Bool extB; // Bit manipulation extension
Bool extA; // Atomic extension
} MachineISA deriving(Bits, Eq, FShow);
instance DefaultValue#(MachineISA);
defaultValue = MachineISA {
extA: False,
extB: False,
extC: False,
extD: False,
extE: False,
extF: False,
extG: False,
extH: False,
extI: True, // RV32I/64I/128I base ISA
extJ: False,
extK: False,
extL: False,
extM: False,
extN: False,
extO: False,
extP: False,
extQ: False,
extR: False,
extS: False,
extT: False,
extU: False,
extV: False,
extW: False,
extX: False,
extY: False,
extZ: False
};
endinstance
interface MachineISAIfc#(numeric type xlen);
method Bit#(xlen) pack;
interface Get#(MachineISA) getMachineISA;
interface Put#(MachineISA) putMachineISA;
endinterface
module mkMachineISA#(IsaCfg#(xlen) cfg)(MachineISAIfc#(xlen))
provisos(
Add#(a__, 26, xlen),
Add#(b__, 2, xlen)
);
function MachineISA getMISA;
MachineISA misa_ = defaultValue;
// Check for user level interrupts
if (cfg.extN) begin
misa_.extN = True;
end
// Check for supervisor mode support.
if (cfg.extS) begin
misa_.extS = True;
end
// Check for user mode support.
if (cfg.extU) begin
misa_.extU = True;
end
return misa_;
endfunction
function MXL getMXL;
MXL mxl = fromInteger((log2(valueof(xlen))) - 4);
return mxl;
endfunction
method Bit#(xlen) pack;
Bit#(xlen) misa = 0;
misa[valueof(xlen)-1:valueof(xlen)-2] = getMXL;
Bit#(26) extensions = pack(getMISA);
misa[25:0] = extensions;
return misa;
endmethod
interface Get getMachineISA;
method ActionValue#(MachineISA) get;
return getMISA;
endmethod
endinterface
interface Put putMachineISA;
method Action put(MachineISA misa);
// Writing to MISA not supported
endmethod
endinterface
endmodule

View File

@ -1,179 +0,0 @@
import IsaCfg::*;
import GetPut::*;
typedef Bit#(2) MXL;
MXL mxl_32bit = 2'b01;
MXL mxl_64bit = 2'b10;
MXL mxl_128bit = 2'b11;
typedef struct {
Bool extA; // Atomic extension
Bool extB; // Bit manipulation extension
Bool extC; // Compressed instruction extension
Bool extD; // Double precision floating-point extension
Bool extE; // RV32E base ISA
Bool extF; // Single precision floating-point extension
Bool extG; // ** RESERVED **
Bool extH; // Hypervisor extension
Bool extI; // RV32I/64I/128I base ISA
Bool extJ; // Dynamically translated language extension
Bool extK; // ** RESERVED **
Bool extL; // ** RESERVED **
Bool extM; // Integer multiply/divide extension
Bool extN; // User level interrupts extension
Bool extO; // ** RESERVED **
Bool extP; // Packed-SIMD extension
Bool extQ; // Quad precision floating-point extension
Bool extR; // ** RESERVED **
Bool extS; // Supervisor mode implemented
Bool extT; // ** RESERVED **
Bool extU; // User mode implemented
Bool extV; // Vector extension
Bool extW; // ** RESERVED **
Bool extX; // Non-standard extensions present
Bool extY; // ** RESERVED **
Bool extZ; // ** RESERVED **
} MachineISA#(numeric type xlen);
instance DefaultValue#(MachineISA#(xlen));
defaultValue = MachineISA {
extA: False,
extB: False,
extC: False,
extD: False,
extE: False,
extF: False,
extG: False,
extH: False,
extI: True, // RV32I/64I/128I base ISA
extJ: False,
extK: False,
extL: False,
extM: False,
extN: False,
extO: False,
extP: False,
extQ: False,
extR: False,
extS: False,
extT: False,
extU: False,
extV: False,
extW: False,
extX: False,
extY: False,
extZ: False
};
endinstance
instance Bits#(MachineISA#(64), 64);
function Bit#(64) pack(MachineISA#(64) misa);
MXL mxl = mxl_64bit;
return {
mxl,
36'b0,
pack(misa.extZ),
pack(misa.extY),
pack(misa.extX),
pack(misa.extW),
pack(misa.extV),
pack(misa.extU),
pack(misa.extT),
pack(misa.extS),
pack(misa.extR),
pack(misa.extQ),
pack(misa.extP),
pack(misa.extO),
pack(misa.extN),
pack(misa.extM),
pack(misa.extL),
pack(misa.extK),
pack(misa.extJ),
pack(misa.extI),
pack(misa.extH),
pack(misa.extH),
pack(misa.extF),
pack(misa.extE),
pack(misa.extD),
pack(misa.extC),
pack(misa.extB),
pack(misa.extA)
};
endfunction
function MachineISA#(64) unpack(Bit#(64) value);
return defaultValue;
endfunction
endinstance
instance Bits#(MachineISA#(32), 32);
function Bit#(32) pack(MachineISA#(32) misa);
MXL mxl = mxl_32bit;
return {
mxl,
4'b0,
pack(misa.extZ),
pack(misa.extY),
pack(misa.extX),
pack(misa.extW),
pack(misa.extV),
pack(misa.extU),
pack(misa.extT),
pack(misa.extS),
pack(misa.extR),
pack(misa.extQ),
pack(misa.extP),
pack(misa.extO),
pack(misa.extN),
pack(misa.extM),
pack(misa.extL),
pack(misa.extK),
pack(misa.extJ),
pack(misa.extI),
pack(misa.extH),
pack(misa.extH),
pack(misa.extF),
pack(misa.extE),
pack(misa.extD),
pack(misa.extC),
pack(misa.extB),
pack(misa.extA)
};
endfunction
function MachineISA#(32) unpack(Bit#(32) value);
return defaultValue;
endfunction
endinstance
interface MachineISAIfc#(numeric type xlen);
interface Get#(MachineISA#(xlen)) getMachineISA;
interface Put#(MachineISA#(xlen)) putMachineISA;
endinterface
module mkMachineISA#(IsaCfg#(xlen) cfg)(MachineISAIfc#(xlen));
interface Get getMachineISA;
method ActionValue#(MachineISA#(xlen)) get;
MachineISA#(xlen) misa_ = defaultValue;
// Check for user mode support.
if (cfg.u_mode_supported) begin
misa_.extU = True;
end
// Check for supervisor mode support.
if (cfg.s_mode_supported) begin
misa_.extS = True;
end
return misa_;
endmethod
endinterface
interface Put putMachineISA;
method Action put(MachineISA#(xlen) misa);
// Writing to MISA not supported
endmethod
endinterface
endmodule

View File

@ -0,0 +1,49 @@
import DecodeStage::*;
import IsaCfg::*;
import MachineISA::*;
import Assert::*;
module mkTopModule(Empty);
Reg#(Bit#(20)) stepNumber <- mkReg(0);
IsaCfg#(32) rv32i_cfg = IsaCfg {
extN: False,
extS: False,
extU: False
};
MachineISAIfc#(32) rv32i <- mkMachineISA(rv32i_cfg);
IsaCfg#(64) rv64i_cfg = IsaCfg {
extN: False,
extS: False,
extU: False
};
MachineISAIfc#(64) rv64i <- mkMachineISA(rv64i_cfg);
(* no_implicit_conditions *)
rule test;
case(stepNumber)
0: begin
let misa = rv32i.pack;
dynamicAssert(misa == 32'b01_0000_00000000000000000100000000, "MachineISA RV32I invalid");
end
1: begin
let misa = rv64i.pack;
$display("MISA: %b", misa);
dynamicAssert(misa == 64'b10_000000000000000000000000000000000000_00000000000000000100000000, "MachineISA RV64I invalid");
end
default: begin
dynamicAssert(stepNumber == 2, "MachineISA - not all tests run");
$display(">>>PASS");
$finish();
end
endcase
endrule
rule increment_step_number;
stepNumber <= stepNumber + 1;
endrule
endmodule

View File

@ -1,5 +1,3 @@
export MachineInformationCfg(..);
typedef struct { typedef struct {
Bit#(32) mvendorid; Bit#(32) mvendorid;
Bit#(xlen) marchid; Bit#(xlen) marchid;

View File

@ -1,180 +0,0 @@
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#(numeric type xlen) deriving(Bits, Eq);
instance DefaultValue#(MachineStatus#(xlen));
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, // RV64 only
sxl: xlen_64, // RV64 only
sbe: False,
mbe: False
};
endinstance
instance Bits#(MachineStatus#(64), 64);
function Bit#(64) pack(MachineStatus#(64) 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,
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#(64) unpack(Bit#(64) value);
return defaultValue;
endfunction
endinstance
instance Bits#(MachineStatus#(32), 32);
function Bit#(32) pack(MachineStatus#(32) mstatus);
Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1);
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#(32) unpack(Bit#(32) value);
return defaultValue;
endfunction
endinstance
interface MachineStatusIfc#(numeric type xlen);
interface Get#(MachineStatus#(xlen)) getMachineStatus;
interface Put#(MachineStatus#(xlen)) putMachineStatus;
endinterface
module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatusIfc#(xlen));
Reg#(MachineStatus#(xlen)) mstatus <- mkReg(defaultValue);
interface Get getMachineStatus = toGet(mstatus);
interface Put putMachineStatus;
method Action put(MachineStatus#(xlen) value);
//
// Only MPP, MIE, and MIE are writable. The rest
// are written with defaults
//
MachineStatus#(xlen) mstatus_ = defaultValue;
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

View File

@ -43,7 +43,7 @@ typedef struct {
Bool sbe; // Supervisor Mode Data Accesses are Big Endian Bool sbe; // Supervisor Mode Data Accesses are Big Endian
Bool mbe; // Machine Mode Data Accesses are Big Endian Bool mbe; // Machine Mode Data Accesses are Big Endian
} MachineStatus; } MachineStatus deriving(Bits, Eq, FShow);
instance DefaultValue#(MachineStatus); instance DefaultValue#(MachineStatus);
defaultValue = MachineStatus { defaultValue = MachineStatus {
@ -72,8 +72,13 @@ instance DefaultValue#(MachineStatus);
}; };
endinstance endinstance
instance Bits#(MachineStatus, 32); typeclass MachineStatusBits#(numeric type xlen);
function Bit#(32) pack(MachineStatus mstatus); function Bit#(xlen) mstatus_pack(MachineStatus mstatus);
function MachineStatus mstatus_unpack(Bit#(xlen) mstatus_packed);
endtypeclass
instance MachineStatusBits#(32);
function Bit#(32) mstatus_pack(MachineStatus mstatus);
Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1); Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1);
return { return {
sd, sd,
@ -100,13 +105,13 @@ instance Bits#(MachineStatus, 32);
}; };
endfunction endfunction
function MachineStatus unpack(Bit#(32) value); function MachineStatus mstatus_unpack(Bit#(32) mstatus_packed);
return defaultValue; return defaultValue;
endfunction endfunction
endinstance endinstance
instance Bits#(MachineStatus, 64); instance MachineStatusBits#(64);
function Bit#(64) pack(MachineStatus mstatus); function Bit#(64) mstatus_pack(MachineStatus mstatus);
Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1); Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1);
return { return {
sd, sd,
@ -134,46 +139,64 @@ instance Bits#(MachineStatus, 64);
pack(mstatus.mie), pack(mstatus.mie),
1'b0, 1'b0,
pack(mstatus.sie), pack(mstatus.sie),
1'b0 1'b0
}; };
endfunction endfunction
function MachineStatus unpack(Bit#(64) value); function MachineStatus mstatus_unpack(Bit#(64) mstatus_packed);
return defaultValue; return defaultValue;
endfunction endfunction
endinstance endinstance
interface MachineStatus_Ifc; interface MachineStatusIfc#(numeric type xlen);
interface Get#(MachineStatus) getMachineStatus; method Action beginTrap(RVPrivilegeLevel currentPriv);
interface Put#(MachineStatus) putMachineStatus; method Bit#(xlen) get;
method Action put(Bit#(xlen) newMachineStatus);
endinterface endinterface
module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc); module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatusIfc#(xlen))
Reg#(MachineStatus) mstatus <- mkReg(defaultValue); provisos(
MachineStatusBits#(xlen)
);
Reg#(Bit#(xlen)) mstatus <- mkReg(defaultValue);
method Action beginTrap(RVPrivilegeLevel currentPriv);
// CurPriv => MSTATUS::MPP
let mstatus_ = mstatus_unpack(mstatus);
mstatus_.mpp = currentPriv;
interface Get getMachineStatus = toGet(mstatus); // MSTATUS::MIE => MSTATUS::MPIE
interface Put putMachineStatus; mstatus_.mpie = mstatus_.mie;
method Action put(MachineStatus value); mstatus_.mie = False; // Disable interrupts
//
// Only MPP, MIE, and MIE are writable.
//
MachineStatus mstatus_ = mstatus;
if (cfg.extS) begin mstatus <= mstatus_pack(mstatus_);
mstatus_.mpp = value.mpp; endmethod
end else begin
// Supervisor mode not supported, ensure only USER and MACHINE method Bit#(xlen) get;
// mode are set in MPP. return mstatus;
RVPrivilegeLevel requestedMPP = value.mpp; endmethod
if (requestedMPP == priv_USER || requestedMPP == priv_MACHINE) begin
mstatus_.mpp = requestedMPP; method Action put(Bit#(xlen) newMachineStatus);
end //
// Only MPP, MIE, and MIE are writable.
//
MachineStatus mstatus_ = mstatus_unpack(mstatus);
MachineStatus value = mstatus_unpack(newMachineStatus);
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
end
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
endmodule endmodule

View File

@ -0,0 +1,29 @@
import MachineStatus::*;
import IsaCfg::*;
import Assert::*;
module mkTopModule(Empty);
Reg#(Bit#(20)) stepNumber <- mkReg(0);
IsaCfg#(32) rv32icfg = defaultValue;
MachineStatusIfc#(32) rv32i <- mkMachineStatus(rv32icfg);
IsaCfg#(64) rv64icfg = defaultValue;
MachineStatusIfc#(64) rv64i <- mkMachineStatus(rv64icfg);
(* no_implicit_conditions *)
rule test;
case(stepNumber)
default: begin
dynamicAssert(stepNumber == 0, "MachineStatus - not all tests run");
$display(">>>PASS");
$finish();
end
endcase
endrule
rule increment_step_number;
stepNumber <= stepNumber + 1;
endrule
endmodule

View File

@ -17,7 +17,7 @@ typedef struct {
} CpuCfg#(numeric type xlen, numeric type icacheFetchByteCount); } CpuCfg#(numeric type xlen, numeric type icacheFetchByteCount);
// //
// CpuIfc // Cpu
// //
interface CpuIfc#(numeric type xlen, numeric type icacheFetchByteCount); interface CpuIfc#(numeric type xlen, numeric type icacheFetchByteCount);
interface Get#(ICacheRequest#(xlen)) getCacheRequest; interface Get#(ICacheRequest#(xlen)) getCacheRequest;
@ -58,7 +58,7 @@ module mkCpu#(CpuCfg#(xlen, icacheFetchByteCount) cfg)(CpuIfc#(xlen, icacheFetch
// General purpose register (GPR) file // General purpose register (GPR) file
GprFileCfg#(xlen) gpr_cfg = GprFileCfg {}; GprFileCfg#(xlen) gpr_cfg = GprFileCfg {};
GprFile#(xlen) gpr <- mkGprFile(gpr_cfg); GprFileIfc#(xlen) gprfile <- mkGprFile(gpr_cfg);
// //
// INITIALIZATION // INITIALIZATION
@ -69,7 +69,7 @@ module mkCpu#(CpuCfg#(xlen, icacheFetchByteCount) cfg)(CpuIfc#(xlen, icacheFetch
// Zero the GPRs // Zero the GPRs
// //
for (gprInitIndex <= 0; gprInitIndex <= 32; gprInitIndex <= gprInitIndex + 1) for (gprInitIndex <= 0; gprInitIndex <= 32; gprInitIndex <= gprInitIndex + 1)
gpr.gprWritePort.write(truncate(gprInitIndex), 0); gprfile.gprWritePort.write(truncate(gprInitIndex), 0);
state <= FETCH; state <= FETCH;
endseq); endseq);

View File

@ -5,6 +5,7 @@ import Trap::*;
import IsaCfg::*; import IsaCfg::*;
import MachineInformation::*; import MachineInformation::*;
import MachineISA::*;
import MachineStatus::*; import MachineStatus::*;
import RV_ISA::*; import RV_ISA::*;
@ -18,18 +19,18 @@ typedef struct {
} CsrWriteResult deriving(Bits, Eq, FShow); } CsrWriteResult deriving(Bits, Eq, FShow);
interface CsrReadPort#(numeric type xlen); interface CsrReadPort#(numeric type xlen);
method ActionValue#(CsrReadResult#(xlen)) read(RVCsrIndex index); method ActionValue#(CsrReadResult#(xlen)) read(RVCSRIndex index);
endinterface endinterface
interface CsrWritePort#(numeric type xlen); interface CsrWritePort#(numeric type xlen);
method ActionValue#(CsrWriteResult) write(RVCsrIndex index, Bit#(xlen) value); method ActionValue#(CsrWriteResult) write(RVCSRIndex index, Bit#(xlen) value);
endinterface endinterface
interface CsrWritePermission; interface CsrWritePermission;
method Bool isWriteable(RVCsrIndex index); method Bool isWriteable(RVCSRIndex index);
endinterface endinterface
interface CsrFile#(numeric type xlen); interface CsrFileIfc#(numeric type xlen);
method Action incrementCycleCounters; method Action incrementCycleCounters;
method Action incrementInstructionsRetiredCounter; method Action incrementInstructionsRetiredCounter;
@ -37,14 +38,14 @@ interface CsrFile#(numeric type xlen);
interface CsrWritePort#(xlen) csrWritePort; interface CsrWritePort#(xlen) csrWritePort;
interface CsrWritePermission csrWritePermission; interface CsrWritePermission csrWritePermission;
interface TrapController#(xlen) trapController; interface TrapControllerIfc#(xlen) trapController;
endinterface endinterface
typedef struct { module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(xlen))
IsaCfg#(xlen) isa_cfg; provisos(
} CsrFileCfg#(numeric type xlen); Add#(xlen, 0, 32),
Add#(xlen, 0, 64)
module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen)); );
Reg#(RVPrivilegeLevel) currentPriv <- mkReg(priv_MACHINE); Reg#(RVPrivilegeLevel) currentPriv <- mkReg(priv_MACHINE);
// Counters // Counters
@ -64,19 +65,17 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
}; };
MachineStatusIfc#(xlen) mstatus <- mkMachineStatus(cfg); MachineStatusIfc#(xlen) mstatus <- mkMachineStatus(cfg);
/* MachineISAIfc#(xlen) misa <- mkMachineISA(cfg);
ReadOnly#(Bit#(xlen)) mcycle <- mkReadOnly(truncate(cycleCounter)); ReadOnly#(Bit#(xlen)) mcycle <- mkReadOnly(truncate(cycleCounter));
ReadOnly#(Bit#(xlen)) mtimer <- mkReadOnly(truncate(timeCounter)); ReadOnly#(Bit#(xlen)) mtimer <- mkReadOnly(truncate(timeCounter));
ReadOnly#(Bit#(xlen)) minstret <- mkReadOnly(truncate(retiredCounter)); ReadOnly#(Bit#(xlen)) minstret <- mkReadOnly(truncate(retiredCounter));
*/
/*
if (valueof(xlen) == 32) begin if (valueof(xlen) == 32) begin
ReadOnly#(Bit#(xlen)) mcycleh <- mkReadOnly(truncateLSB(cycleCounter)); ReadOnly#(Bit#(xlen)) mcycleh <- mkReadOnly(truncateLSB(cycleCounter));
ReadOnly#(Bit#(xlen)) mtimeh <- mkReadOnly(truncateLSB(timeCounter)); ReadOnly#(Bit#(xlen)) mtimeh <- mkReadOnly(truncateLSB(timeCounter));
ReadOnly#(Bit#(xlen)) minstreth <- mkReadOnly(truncateLSB(retiredCounter)); ReadOnly#(Bit#(xlen)) minstreth <- mkReadOnly(truncateLSB(retiredCounter));
end end
*/
Reg#(Bit#(xlen)) mcause <- mkReg(0); Reg#(Bit#(xlen)) mcause <- mkReg(0);
Reg#(Bit#(xlen)) mtvec <- mkReg('hC0DEC0DE); Reg#(Bit#(xlen)) mtvec <- mkReg('hC0DEC0DE);
Reg#(Bit#(xlen)) mepc <- mkReg(0); Reg#(Bit#(xlen)) mepc <- mkReg(0);
@ -90,7 +89,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
Reg#(Bit#(xlen)) sideleg <- mkReg(0); Reg#(Bit#(xlen)) sideleg <- mkReg(0);
Reg#(Bit#(xlen)) sedeleg <- mkReg(0); Reg#(Bit#(xlen)) sedeleg <- mkReg(0);
function Bool isWARLIgnore(RVCsrIndex index); function Bool isWARLIgnore(RVCSRIndex index);
Bool result = False; Bool result = False;
if ((index >= csr_PMPADDR0 && index <= csr_PMPADDR63) || if ((index >= csr_PMPADDR0 && index <= csr_PMPADDR63) ||
(index >= csr_PMPCFG0 && index <= csr_PMPCFG15) || (index >= csr_PMPCFG0 && index <= csr_PMPCFG15) ||
@ -103,8 +102,8 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
return result; return result;
endfunction endfunction
function RVCsrIndex getIndex(RVPrivilegeLevel privilege_level, RVCsrIndexOffset offset); function RVCSRIndex getIndex(RVPrivilegeLevel privilege_level, RVCSRIndexOffset offset);
RVCsrIndex index = 0; RVCSRIndex index = 0;
index[9:8] = privilege_level[1:0]; index[9:8] = privilege_level[1:0];
index[7:0] = offset; index[7:0] = offset;
return index; return index;
@ -115,7 +114,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
let trap_privilege_level = priv_MACHINE; let trap_privilege_level = priv_MACHINE;
if (currentPriv < priv_MACHINE) begin if (currentPriv < priv_MACHINE) begin
if (cfg.s_mode_supported) begin // S mode supported? if (cfg.extS) begin // S mode supported?
// See if this trap should be delegated to SUPERVISOR mode // See if this trap should be delegated to SUPERVISOR mode
let delegated = (trap.isInterrupt ? let delegated = (trap.isInterrupt ?
(mideleg[trap.cause] == 0 ? False : True) : (mideleg[trap.cause] == 0 ? False : True) :
@ -126,7 +125,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
// If the current priv mode is U, and user mode traps are supported, // If the current priv mode is U, and user mode traps are supported,
// then consult sedeleg/sideleg to determine if delegated to USER mode. // then consult sedeleg/sideleg to determine if delegated to USER mode.
if (currentPriv == priv_USER && cfg.u_level_interrupts_supported) begin if (currentPriv == priv_USER && cfg.extU) begin
delegated = (trap.isInterrupt ? delegated = (trap.isInterrupt ?
(sideleg[trap.cause] == 0 ? False : True) : (sideleg[trap.cause] == 0 ? False : True) :
(sedeleg[trap.cause] == 0 ? False : True)); (sedeleg[trap.cause] == 0 ? False : True));
@ -139,7 +138,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
end else begin // S mode *NOT* supported end else begin // S mode *NOT* supported
// If user mode traps are supported, then consult sedeleg/sideleg to determine // If user mode traps are supported, then consult sedeleg/sideleg to determine
// if delegated to USER mode. // if delegated to USER mode.
if (cfg.u_level_interrupts_supported) begin if (cfg.extU) begin
let delegated = (trap.isInterrupt ? let delegated = (trap.isInterrupt ?
(mideleg[trap.cause] == 0 ? False : True) : (mideleg[trap.cause] == 0 ? False : True) :
(medeleg[trap.cause] == 0 ? False : True)); (medeleg[trap.cause] == 0 ? False : True));
@ -157,9 +156,9 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
// //
// readInternal // readInternal
// //
function ActionValue#(CsrReadResult#(xlen)) readInternal(RVCsrIndex index); function ActionValue#(CsrReadResult#(xlen)) readInternal(RVCSRIndex index);
actionvalue actionvalue
let result = CsrReadResult { CsrReadResult#(xlen) result = CsrReadResult {
value: 0, value: 0,
denied: False denied: False
}; };
@ -167,14 +166,12 @@ 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;
csr_MISA: result.value = pack(cfg); csr_MISA: result.value = misa.pack;
csr_MCAUSE: result.value = mcause; csr_MCAUSE: result.value = mcause;
csr_MTVEC: result.value = mtvec; csr_MTVEC: result.value = mtvec;
@ -183,15 +180,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: begin csr_MSTATUS: result.value = mstatus.get;
let mstatus_ <- mstatus.getMachineStatus.get;
result.value = pack(mstatus_);
end
/*
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;
@ -216,7 +210,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
// //
// writeInternal // writeInternal
// //
function ActionValue#(CsrWriteResult) writeInternal(RVCsrIndex index, Bit#(xlen) value); function ActionValue#(CsrWriteResult) writeInternal(RVCSRIndex index, Bit#(xlen) value);
actionvalue actionvalue
let result = CsrWriteResult { let result = CsrWriteResult {
denied: False denied: False
@ -232,7 +226,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.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;
@ -252,14 +246,14 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
endactionvalue endactionvalue
endfunction endfunction
function ActionValue#(CsrReadResult#(xlen)) readWithOffset1(RVPrivilegeLevel privilegeLevel, RVCsrIndexOffset offset); function ActionValue#(CsrReadResult#(xlen)) readWithOffset1(RVPrivilegeLevel privilegeLevel, RVCSRIndexOffset offset);
actionvalue actionvalue
let csrReadResult <- readInternal(getIndex(privilegeLevel, offset)); let csrReadResult <- readInternal(getIndex(privilegeLevel, offset));
return csrReadResult; return csrReadResult;
endactionvalue endactionvalue
endfunction endfunction
function ActionValue#(CsrWriteResult) writeWithOffset1(RVPrivilegeLevel privilegeLevel, RVCsrIndexOffset offset, Bit#(xlen) value); function ActionValue#(CsrWriteResult) writeWithOffset1(RVPrivilegeLevel privilegeLevel, RVCSRIndexOffset offset, Bit#(xlen) value);
actionvalue actionvalue
let csrWriteResult <- writeInternal(getIndex(privilegeLevel, offset), value); let csrWriteResult <- writeInternal(getIndex(privilegeLevel, offset), value);
return csrWriteResult; return csrWriteResult;
@ -279,7 +273,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
// CsrReadport // CsrReadport
// //
interface CsrReadPort csrReadPort; interface CsrReadPort csrReadPort;
method ActionValue#(CsrReadResult#(xlen)) read(RVCsrIndex index); method ActionValue#(CsrReadResult#(xlen)) read(RVCSRIndex index);
let result = CsrReadResult { let result = CsrReadResult {
value: 0, value: 0,
denied: True denied: True
@ -297,7 +291,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
// CsrWritePort // CsrWritePort
// //
interface CsrWritePort csrWritePort; interface CsrWritePort csrWritePort;
method ActionValue#(CsrWriteResult) write(RVCsrIndex index, Bit#(xlen) value); method ActionValue#(CsrWriteResult) write(RVCSRIndex index, Bit#(xlen) value);
let result = CsrWriteResult { let result = CsrWriteResult {
denied: True denied: True
}; };
@ -314,7 +308,7 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
// CsrWritePermission // CsrWritePermission
// //
interface CsrWritePermission csrWritePermission; interface CsrWritePermission csrWritePermission;
method Bool isWriteable(RVCsrIndex index); method Bool isWriteable(RVCSRIndex index);
return (currentPriv >= index[9:8] && index[11:10] != 'b11); return (currentPriv >= index[9:8] && index[11:10] != 'b11);
endmethod endmethod
endinterface endinterface
@ -322,28 +316,21 @@ module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
// //
// trapController // trapController
// //
interface TrapController trapController; interface TrapControllerIfc trapController;
method ActionValue#(Bit#(xlen)) beginTrap(Bit#(xlen) trapProgramCounter, Trap#(xlen) trap); method ActionValue#(Bit#(xlen)) beginTrap(Bit#(xlen) trapProgramCounter, Trap#(xlen) trap);
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 +341,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 +358,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 +373,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

23
src/Cpu/CsrFile_tb.bsv Normal file
View File

@ -0,0 +1,23 @@
import CsrFile::*;
import IsaCfg::*;
import Assert::*;
module mkTopModule(Empty);
Reg#(Bit#(20)) stepNumber <- mkReg(0);
(* no_implicit_conditions *)
rule test;
case(stepNumber)
default: begin
dynamicAssert(stepNumber == 0, "CsrFile - not all tests run");
$display(">>>PASS");
$finish();
end
endcase
endrule
rule increment_step_number;
stepNumber <= stepNumber + 1;
endrule
endmodule

165
src/Cpu/DecodeStage.bsv Normal file
View File

@ -0,0 +1,165 @@
import CsrFile::*;
import IsaCfg::*;
import GprFile::*;
import PipelineRegisters::*;
import RV_ISA::*;
import Trap::*;
import GetPut::*;
interface DecodeModuleIfc#(numeric type xlen);
method ActionValue#(ID_EX#(xlen)) step(
IF_ID#(xlen) if_id,
GprReadPort#(xlen) gprReadPort1,
GprReadPort#(xlen) gprReadPort2,
CsrReadPort#(xlen) csrReadPort
);
endinterface
module mkDecodeModule#(IsaCfg#(xlen) cfg)(DecodeModuleIfc#(xlen))
provisos(
Add#(a__, 20, xlen),
Add#(b__, 5, xlen),
Add#(c__, 13, xlen),
Add#(d__, 21, xlen),
Add#(e__, 12, xlen)
);
function RVGPRIndex extractRs1(Instruction inst);
return inst.value[19:15];
endfunction
function RVGPRIndex extractRs2(Instruction inst);
return inst.value[24:20];
endfunction
function RVCSRIndex extractCsrIndex(Instruction inst);
return inst.value[31:20];
endfunction
function Bit#(xlen) decodeImmediate(Instruction inst);
return case(inst.value[6:0])
7'b0110111: begin // LUI
signExtend(inst.value[31:12]);
end
7'b0010111: begin // AUIPC
signExtend(inst.value[31:12]);
end
7'b1101111: begin // JAL
signExtend({
inst.value[31],
inst.value[19:12],
inst.value[20],
inst.value[30:21],
1'b0
});
end
7'b1100111: begin // JALR
signExtend(inst.value[31:20]);
end
7'b1100011: begin // BRANCH
signExtend({
inst.value[31],
inst.value[7],
inst.value[30:25],
inst.value[11:8],
1'b0
});
end
7'b0000011: begin // LOAD
signExtend(inst.value[31:20]);
end
7'b0100011: begin // STORE
signExtend({
inst.value[31:25],
inst.value[11:7]
});
end
7'b0010011: begin // OPIMM
signExtend(inst.value[31:20]);
end
7'b1110011: begin // SYSTEM (CSR)
zeroExtend(inst.value[19:15]); // UIMM stored in RS1
end
default: begin
0;
end
endcase;
endfunction
method ActionValue#(ID_EX#(xlen)) step(
IF_ID#(xlen) if_id,
GprReadPort#(xlen) gprReadPort1,
GprReadPort#(xlen) gprReadPort2,
CsrReadPort#(xlen) csrReadPort
);
ID_EX#(xlen) id_ex = defaultValue;
id_ex.common = if_id.common;
id_ex.epoch = if_id.epoch;
id_ex.npc = if_id.npc;
// Read GPRs
let rs1 = extractRs1(if_id.common.ir);
let rs2 = extractRs2(if_id.common.ir);
id_ex.a = gprReadPort1.read(rs1);
id_ex.b = gprReadPort2.read(rs2);
// Decode immediate
id_ex.imm = decodeImmediate(if_id.common.ir);
// CSR read
let csrIndex = extractCsrIndex(if_id.common.ir);
id_ex.csr <- csrReadPort.read(csrIndex);
return id_ex;
endmethod
endmodule
interface DecodeStageIfc#(numeric type xlen);
interface Put#(IF_ID#(xlen)) put;
interface Get#(ID_EX#(xlen)) get;
endinterface
module mkDecodeStage#(IsaCfg#(xlen) cfg,
GprReadPort#(xlen) gprReadPort1,
GprReadPort#(xlen) gprReadPort2,
CsrReadPort#(xlen) csrReadPort)(DecodeStageIfc#(xlen))
provisos(
Add#(a__, 20, xlen),
Add#(b__, 5, xlen),
Add#(c__, 13, xlen),
Add#(d__, 21, xlen),
Add#(e__, 12, xlen)
);
//
// State
//
Wire#(IF_ID#(xlen)) if_id <- mkWire;
Reg#(ID_EX#(xlen)) id_ex <- mkRegU;
DecodeModuleIfc#(xlen) decodeModule <- mkDecodeModule(cfg);
//
// Rules
//
(* no_implicit_conditions *)
rule step;
let id_ex_ <- decodeModule.step(if_id, gprReadPort1, gprReadPort2, csrReadPort);
id_ex <= id_ex_;
endrule
//
// Interfaces
//
interface Put put = toPut(asIfc(if_id));
interface Get get = toGet(id_ex);
endmodule

View File

@ -0,0 +1,44 @@
import DecodeStage::*;
import GprFile::*;
import IsaCfg::*;
import PipelineRegisters::*;
import RV_ISA::*;
import Trap::*;
import Assert::*;
module mkTopModule(Empty);
Reg#(Bit#(20)) stepNumber <- mkReg(0);
// 32 bit
IsaCfg#(32) rv32 = IsaCfg{
extN: False,
extS: False,
extU: False
};
DecodeModuleIfc#(32) decodeModule32 <- mkDecodeModule(rv32);
//
// GPR
//
GprFileCfg#(32) gprFileCfg32 = GprFileCfg {
};
GprFileIfc#(32) gprFile32 <- mkGprFile(gprFileCfg32);
(* no_implicit_conditions *)
rule test;
IF_ID#(32) if_id = defaultValue;
case(stepNumber)
default: begin
dynamicAssert(stepNumber == 0, "Decode - not all tests run");
$display(">>>PASS");
$finish();
end
endcase
endrule
rule increment_step_number;
stepNumber <= stepNumber + 1;
endrule
endmodule

View File

@ -1,5 +1,5 @@
import IsaCfg::*; import IsaCfg::*;
import MemoryTypes::*; import MemoryIO::*;
import PipelineRegisters::*; import PipelineRegisters::*;
import RV_ISA::*; import RV_ISA::*;
import Trap::*; import Trap::*;
@ -10,34 +10,38 @@ import FIFOF::*;
import GetPut::*; import GetPut::*;
import Memory::*; import Memory::*;
interface FetchStage_Ifc#(numeric type xlen); typedef ReadOnlyMemoryRequest#(xlen, 32) InstructionMemoryRequest#(numeric type xlen);
interface FetchModuleIfc#(numeric type xlen);
method ActionValue#(IF_ID#(xlen)) step(PC_IF#(xlen) pc_if); method ActionValue#(IF_ID#(xlen)) step(PC_IF#(xlen) pc_if);
interface ReadOnlyMemoryClient#(xlen, 32) memoryClient; interface ReadOnlyMemoryClient#(xlen, 32) memoryClient;
endinterface endinterface
module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen)); module mkFetchModule#(IsaCfg#(xlen) cfg)(FetchModuleIfc#(xlen));
Reg#(ProgramCounter#(xlen)) updatedPc <- mkRegU; // Holds the updated PC that is calculated when a fetch is issued Reg#(ProgramCounter#(xlen)) updatedPc <- mkRegU; // Holds the updated PC that is calculated when a fetch is issued
// that is used to update the PC when the fetch completes. // that is used to update the PC when the fetch completes.
Reg#(Epoch) requestEpoch <- mkRegU; // Holds the epoch of the initiating request.
// Memory request output // Memory request output
Reg#(Maybe#(ReadOnlyMemoryRequest#(xlen))) inflightMemoryRequest <- mkReg(tagged Invalid); Reg#(Maybe#(InstructionMemoryRequest#(xlen))) inflightMemoryRequest <- mkReg(tagged Invalid);
Wire#(ReadOnlyMemoryRequest#(xlen)) memoryRequest <- mkWire; Wire#(InstructionMemoryRequest#(xlen)) memoryRequest <- mkWire;
// Memory response input (FIFO) // Memory response input (FIFO)
// Note: This is an unguarded FIFO so status much be checked before attempting to enq() and deq(). // Note: This is an unguarded FIFO so status must be checked before attempting to enq() and deq().
FIFOF#(ReadOnlyMemoryResponse#(32)) memoryResponses <- mkUGFIFOF1; FIFOF#(FallibleMemoryResponse#(32)) memoryResponses <- mkUGFIFOF1;
// //
// processMemoryResponse - Takes a memory response and returns an IF_ID containing // processMemoryResponse - Takes a memory response and returns an IF_ID containing
// the encoded instruction (or a trap if the original request // the encoded instruction (or a trap if the original request
// was denied by the memory system) // was denied by the memory system)
// //
function IF_ID#(xlen) processMemoryResponse(ReadOnlyMemoryResponse#(32) response); function IF_ID#(xlen) processMemoryResponse(FallibleMemoryResponse#(32) response);
IF_ID#(xlen) if_id = defaultValue; IF_ID#(xlen) if_id = defaultValue;
if_id.common.pc = inflightMemoryRequest.Valid.address; if_id.common.pc = inflightMemoryRequest.Valid.address;
if_id.common.isBubble = False; if_id.npc = updatedPc + 4;
if_id.npc = updatedPc; if_id.epoch = requestEpoch;
if (!response.accessFault) begin if (!response.accessFault) begin
if_id.common.ir.value = response.data; if_id.common.ir.value = response.data;
@ -73,10 +77,18 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen));
end else begin end else begin
// No memory request is in flight... // No memory request is in flight...
// Determine the PC the instruction will be fetchted from. It's either the calculated PC // Determine the PC the instruction will be fetched from. It's either the calculated PC
// or a redirected PC (due to a branch, jump, exception, etc) // or a redirected PC (due to a branch, jump, exception, etc)
ProgramCounter#(xlen) updatedPc_ = fromMaybe(pc_if.pc, pc_if.redirection); ProgramCounter#(xlen) updatedPc_ = fromMaybe(pc_if.pc, pc_if.redirection);
// If a redirection was specified, reflect that with a change in the epoch.
let epoch = pc_if.epoch;
if (isValid(pc_if.redirection)) begin
epoch = ~epoch;
end
requestEpoch <= epoch;
// Check for a misaligned request // Check for a misaligned request
if (updatedPc_[1:0] != 0) begin if (updatedPc_[1:0] != 0) begin
// Address request was misaligned... // Address request was misaligned...
@ -87,11 +99,11 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen));
}; };
if_id.common.pc = updatedPc_; if_id.common.pc = updatedPc_;
if_id.common.trap = tagged Valid(trap); if_id.common.trap = tagged Valid(trap);
if_id.common.isBubble = False;
end else begin end else begin
// Construct a memory request and send it out. // Construct a memory request and send it out.
ReadOnlyMemoryRequest#(xlen) request = ReadOnlyMemoryRequest { InstructionMemoryRequest#(xlen) request = ReadOnlyMemoryRequest {
address: updatedPc_ address: updatedPc_,
byteen: 'b1111
}; };
memoryRequest <= request; memoryRequest <= request;
inflightMemoryRequest <= tagged Valid request; inflightMemoryRequest <= tagged Valid request;
@ -106,10 +118,42 @@ module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(xlen));
interface ReadOnlyMemoryClient memoryClient; interface ReadOnlyMemoryClient memoryClient;
interface Get request = toGet(memoryRequest); interface Get request = toGet(memoryRequest);
interface Put response; interface Put response;
method Action put(ReadOnlyMemoryResponse#(32) response); method Action put(FallibleMemoryResponse#(32) response);
dynamicAssert(memoryResponses.notFull, "FetchStage - attempt to put a memory respnose on a full queue"); dynamicAssert(memoryResponses.notFull, "FetchStage - attempt to put a memory respnose on a full queue");
memoryResponses.enq(response); memoryResponses.enq(response);
endmethod endmethod
endinterface endinterface
endinterface endinterface
endmodule endmodule
interface FetchStageIfc#(numeric type xlen);
interface Put#(PC_IF#(xlen)) put;
interface Get#(IF_ID#(xlen)) get;
interface ReadOnlyMemoryClient#(xlen, 32) memoryClient;
endinterface
module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStageIfc#(xlen));
//
// State
//
Wire#(PC_IF#(xlen)) pc_if <- mkWire;
Reg#(IF_ID#(xlen)) if_id <- mkRegU;
FetchModuleIfc#(xlen) fetchModule <- mkFetchModule(cfg);
//
// Rules
//
(* no_implicit_conditions *)
rule step;
let if_id_ <- fetchModule.step(pc_if);
if_id <= if_id_;
endrule
//
// Interfaces
//
interface Put put = toPut(asIfc(pc_if));
interface Get get = toGet(if_id);
interface MemoryClient memoryClient = fetchModule.memoryClient;
endmodule

View File

@ -1,6 +1,6 @@
import FetchStage::*; import FetchStage::*;
import IsaCfg::*; import IsaCfg::*;
import MemoryTypes::*; import MemoryIO::*;
import PipelineRegisters::*; import PipelineRegisters::*;
import RV_ISA::*; import RV_ISA::*;
import Trap::*; import Trap::*;
@ -20,10 +20,10 @@ module mkTopModule(Empty);
extS: False, extS: False,
extU: False extU: False
}; };
FetchStage_Ifc#(32) fetchStage32 <- mkFetchStage(rv32); FetchModuleIfc#(32) fetchModule32 <- mkFetchModule(rv32);
FIFOF#(ReadOnlyMemoryRequest#(32)) memoryRequests32 <- mkUGFIFOF1(); FIFOF#(InstructionMemoryRequest#(32)) memoryRequests32 <- mkUGFIFOF1();
mkConnection(fetchStage32.memoryClient.request, toPut(asIfc(memoryRequests32))); mkConnection(fetchModule32.memoryClient.request, toPut(asIfc(memoryRequests32)));
(* no_implicit_conditions *) (* no_implicit_conditions *)
rule test; rule test;
@ -34,29 +34,29 @@ module mkTopModule(Empty);
0: begin 0: begin
pc_if.pc = 'h101; pc_if.pc = 'h101;
let if_id <- fetchStage32.step(pc_if); let if_id <- fetchModule32.step(pc_if);
dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Misaligned instruction trap check - common.pc"); dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Misaligned instruction trap check - common.pc");
dynamicAssert(if_id.common.ir == defaultValue, "Fetch - Misaligned instruction trap check - common.ir"); dynamicAssert(if_id.common.ir == defaultValue, "Fetch - Misaligned instruction trap check - common.ir");
dynamicAssert(!if_id.common.isBubble, "Fetch - Misaligned instruction trap check - common.isBubble");
dynamicAssert(isValid(if_id.common.trap), "Fetch - Misaligned instruction trap check - contains trap"); dynamicAssert(isValid(if_id.common.trap), "Fetch - Misaligned instruction trap check - contains trap");
dynamicAssert(if_id.common.trap.Valid.cause == exception_INSTRUCTION_ADDRESS_MISALIGNED, "Fetch - Misaligned instruction trap check - cause is misaligned address"); dynamicAssert(if_id.common.trap.Valid.cause == exception_INSTRUCTION_ADDRESS_MISALIGNED, "Fetch - Misaligned instruction trap check - cause is misaligned address");
dynamicAssert(if_id.npc == defaultValue, "Fetch - Misaligned instruction trap check - NPC incorrect");
end end
// Memory request denied trap (request submit) // Memory request denied trap (step 1 - request submit)
1: begin 1: begin
pc_if.pc = 'h100; pc_if.pc = 'h100;
// The fetch should proceed and return a bubble. // The fetch should proceed and return a bubble.
let if_id <- fetchStage32.step(pc_if); let if_id <- fetchModule32.step(pc_if);
dynamicAssert(if_id == defaultValue, "Fetch - Memory request denied trap check - request should return a bubble"); dynamicAssert(if_id == defaultValue, "Fetch - Memory request denied trap check - request should return a bubble");
end end
// Memory request denied trap (request receipt) // Memory request denied trap (step 2 - request receipt)
2: begin 2: begin
pc_if.pc = 'h100; pc_if.pc = 'h100;
// Ensure the fetch returns a bubble while the memory request is in flight // Ensure the fetch returns a bubble while the memory request is in flight
let if_id <- fetchStage32.step(pc_if); let if_id <- fetchModule32.step(pc_if);
dynamicAssert(if_id == defaultValue, "Fetch - Memory request denied trap check - request should return a bubble while fetch is in flight"); dynamicAssert(if_id == defaultValue, "Fetch - Memory request denied trap check - request should return a bubble while fetch is in flight");
dynamicAssert(memoryRequests32.notEmpty, "Fetch - Memory request denied trap check - memory request queue should not be empty"); dynamicAssert(memoryRequests32.notEmpty, "Fetch - Memory request denied trap check - memory request queue should not be empty");
@ -64,40 +64,41 @@ module mkTopModule(Empty);
memoryRequests32.deq; memoryRequests32.deq;
dynamicAssert(memoryRequest.address == 'h100, "Fetch - Memory request denied trap check - memory request should have correct address"); dynamicAssert(memoryRequest.address == 'h100, "Fetch - Memory request denied trap check - memory request should have correct address");
fetchStage32.memoryClient.response.put(ReadOnlyMemoryResponse { dynamicAssert(memoryRequest.byteen == 'b1111, "Fetch - Memory request denied trap check - memory request byte enable should be 'b1111");
fetchModule32.memoryClient.response.put(FallibleMemoryResponse {
data: 'h-1, data: 'h-1,
accessFault: True accessFault: True
}); });
end end
// Memory request denied trap (return trap check) // Memory request denied trap (step 3 - return trap check)
3: begin 3: begin
pc_if.pc = 'h100; pc_if.pc = 'h100;
// The fetch should proceed and return a bubble. let if_id <- fetchModule32.step(pc_if);
let if_id <- fetchStage32.step(pc_if);
dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Memory request denied trap check - common.pc"); dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Memory request denied trap check - common.pc");
dynamicAssert(if_id.common.ir == defaultValue, "Fetch - Memory request denied trap check - common.ir"); dynamicAssert(if_id.common.ir == defaultValue, "Fetch - Memory request denied trap check - common.ir");
dynamicAssert(!if_id.common.isBubble, "Fetch - Memory request denied trap check - common.isBubble");
dynamicAssert(isValid(if_id.common.trap), "Fetch - Memory request denied trap check - contains trap"); dynamicAssert(isValid(if_id.common.trap), "Fetch - Memory request denied trap check - contains trap");
dynamicAssert(if_id.common.trap.Valid.cause == exception_INSTRUCTION_ACCESS_FAULT, "Memory request denied trap check - cause is access fault"); dynamicAssert(if_id.common.trap.Valid.cause == exception_INSTRUCTION_ACCESS_FAULT, "Memory request denied trap check - cause is access fault");
dynamicAssert(if_id.npc == 'h104, "Fetch - Misaligned instruction trap check - NPC incorrect");
dynamicAssert(if_id.epoch == defaultValue, "Fetch - Misaligned instruction trap check - Verify epoch unchanged");
end end
// Normal memory request (request submit) // Normal memory request (step 1 - request submit)
4: begin 4: begin
pc_if.pc = 'h100; pc_if.pc = 'h100;
// The fetch should proceed and return a bubble. // The fetch should proceed and return a bubble.
let if_id <- fetchStage32.step(pc_if); let if_id <- fetchModule32.step(pc_if);
dynamicAssert(if_id == defaultValue, "Fetch - Normal request - request should return a bubble"); dynamicAssert(if_id == defaultValue, "Fetch - Normal request - request should return a bubble");
end end
// Normal memory request (request receipt) // Normal memory request (step 2 - request receipt)
5: begin 5: begin
pc_if.pc = 'h100; pc_if.pc = 'h100;
// Ensure the fetch returns a bubble while the memory request is in flight // Ensure the fetch returns a bubble while the memory request is in flight
let if_id <- fetchStage32.step(pc_if); let if_id <- fetchModule32.step(pc_if);
dynamicAssert(if_id == defaultValue, "Fetch - Normal request - request should return a bubble while fetch is in flight"); dynamicAssert(if_id == defaultValue, "Fetch - Normal request - request should return a bubble while fetch is in flight");
dynamicAssert(memoryRequests32.notEmpty, "Fetch - Normal request - memory request queue should not be empty"); dynamicAssert(memoryRequests32.notEmpty, "Fetch - Normal request - memory request queue should not be empty");
@ -105,26 +106,69 @@ module mkTopModule(Empty);
memoryRequests32.deq; memoryRequests32.deq;
dynamicAssert(memoryRequest.address == 'h100, "Fetch - Normal request - memory request should have correct address"); dynamicAssert(memoryRequest.address == 'h100, "Fetch - Normal request - memory request should have correct address");
fetchStage32.memoryClient.response.put(ReadOnlyMemoryResponse { dynamicAssert(memoryRequest.byteen == 'b1111, "Fetch - Normal request - memory request byte enable should be 'b1111");
fetchModule32.memoryClient.response.put(FallibleMemoryResponse {
data: 'haabb_ccdd, data: 'haabb_ccdd,
accessFault: False accessFault: False
}); });
end end
// Normal memory request (return value check) // Normal memory request (step 3 - return value check)
6: begin 6: begin
pc_if.pc = 'h100; pc_if.pc = 'h100;
// The fetch should proceed and return a bubble. let if_id <- fetchModule32.step(pc_if);
let if_id <- fetchStage32.step(pc_if);
dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Normal request - common.pc"); dynamicAssert(if_id.common.pc == pc_if.pc, "Fetch - Normal request - common.pc");
dynamicAssert(!if_id.common.isBubble, "Fetch - Normal request - common.isBubble");
dynamicAssert(!isValid(if_id.common.trap), "Fetch - Normal request - contains no trap"); dynamicAssert(!isValid(if_id.common.trap), "Fetch - Normal request - contains no trap");
dynamicAssert(if_id.common.ir.value == 'haabb_ccdd, "Fetch - Normal request - contains expected instruction data"); dynamicAssert(if_id.common.ir.value == 'haabb_ccdd, "Fetch - Normal request - contains expected instruction data");
dynamicAssert(if_id.npc == 'h104, "Fetch - Normal request - NPC incorrect");
dynamicAssert(if_id.epoch == defaultValue, "Fetch - Normal request - Verify epoch unchanged");
end
// Redirect handling check (step 1 - request submit)
7: begin
pc_if.pc = 'h100;
pc_if.redirection = tagged Valid 'h8000;
// The fetch should proceed and return a bubble.
let if_id <- fetchModule32.step(pc_if);
dynamicAssert(if_id == defaultValue, "Fetch - Redirect check - request should return a bubble");
end
// Redirect handling check (step 2 - request receipt)
8: begin
pc_if.pc = 'h100;
// Ensure the fetch returns a bubble while the memory request is in flight
let if_id <- fetchModule32.step(pc_if);
dynamicAssert(if_id == defaultValue, "Fetch - Redirect check - request should return a bubble while fetch is in flight");
dynamicAssert(memoryRequests32.notEmpty, "Fetch - Redirect check - memory request queue should not be empty");
let memoryRequest = memoryRequests32.first;
memoryRequests32.deq;
dynamicAssert(memoryRequest.address == 'h8000, "Fetch - Redirect check - memory request should have correct address");
dynamicAssert(memoryRequest.byteen == 'b1111, "Fetch - Redirect check - memory request byte enable should be 'b1111");
fetchModule32.memoryClient.response.put(FallibleMemoryResponse {
data: 'haabb_ccee,
accessFault: False
});
end
// Redirect handling check (step 3 - return value check)
9: begin
pc_if.pc = 'h100;
let if_id <- fetchModule32.step(pc_if);
dynamicAssert(if_id.common.pc == 'h8000, "Fetch - Redirect check - common.pc");
dynamicAssert(!isValid(if_id.common.trap), "Fetch - Redirect check - contains no trap");
dynamicAssert(if_id.common.ir.value == 'haabb_ccee, "Fetch - Redirect check - contains expected instruction data");
dynamicAssert(if_id.npc == 'h8004, "Fetch - Redirect check - NPC incorrect");
dynamicAssert(if_id.epoch == 'h1, "Fetch - Redirect check - Verify epoch changed");
end end
default: begin default: begin
dynamicAssert(stepNumber == 7, "Fetch - not all tests run"); dynamicAssert(stepNumber == 10, "Fetch - not all tests run");
$display(">>>PASS"); $display(">>>PASS");
$finish(); $finish();
end end

View File

@ -1,18 +1,18 @@
import RV_ISA::*;
import ClientServer::*; import ClientServer::*;
import GetPut::*; import GetPut::*;
import Vector::*; import Vector::*;
typedef Bit#(5) GprIndex;
interface GprReadPort#(numeric type xlen); interface GprReadPort#(numeric type xlen);
method Bit#(xlen) read(GprIndex index); method Bit#(xlen) read(RVGPRIndex index);
endinterface endinterface
interface GprWritePort#(numeric type xlen); interface GprWritePort#(numeric type xlen);
method Action write(GprIndex index, Bit#(xlen) value); method Action write(RVGPRIndex index, Bit#(xlen) value);
endinterface endinterface
interface GprFile#(numeric type xlen); interface GprFileIfc#(numeric type xlen);
interface GprReadPort#(xlen) gprReadPort1; interface GprReadPort#(xlen) gprReadPort1;
interface GprReadPort#(xlen) gprReadPort2; interface GprReadPort#(xlen) gprReadPort2;
@ -22,23 +22,23 @@ endinterface
typedef struct { typedef struct {
} GprFileCfg#(numeric type xlen); } GprFileCfg#(numeric type xlen);
module mkGprFile#(GprFileCfg#(xlen) cfg)(GprFile#(xlen)); module mkGprFile#(GprFileCfg#(xlen) cfg)(GprFileIfc#(xlen));
Vector#(32, Reg#(Bit#(xlen))) reg_file <- replicateM(mkReg(0)); Vector#(32, Reg#(Bit#(xlen))) reg_file <- replicateM(mkReg(0));
interface GprReadPort gprReadPort1; interface GprReadPort gprReadPort1;
method Bit#(xlen) read(GprIndex index); method Bit#(xlen) read(RVGPRIndex index);
return reg_file[index]; return reg_file[index];
endmethod endmethod
endinterface endinterface
interface GprReadPort gprReadPort2; interface GprReadPort gprReadPort2;
method Bit#(xlen) read(GprIndex index); method Bit#(xlen) read(RVGPRIndex index);
return reg_file[index]; return reg_file[index];
endmethod endmethod
endinterface endinterface
interface GprWritePort gprWritePort; interface GprWritePort gprWritePort;
method Action write(GprIndex index, Bit#(xlen) value); method Action write(RVGPRIndex index, Bit#(xlen) value);
if (index != 0) begin if (index != 0) begin
reg_file[index] <= value; reg_file[index] <= value;
end end

View File

@ -9,18 +9,18 @@ import FIFOF::*;
import GetPut::*; import GetPut::*;
import Memory::*; import Memory::*;
interface MemoryAccessStage_Ifc#(numeric type xlen); interface MemoryAccessModuleIfc#(numeric type xlen);
method ActionValue#(MEM_WB#(xlen)) step(EX_MEM#(xlen) ex_mem); method ActionValue#(MEM_WB#(xlen)) step(EX_MEM#(xlen) ex_mem);
interface MemoryClient#(xlen, xlen) memoryClient; interface MemoryClient#(xlen, xlen) memoryClient;
endinterface endinterface
module mkMemoryAccessStage#(IsaCfg#(xlen) cfg)(MemoryAccessStage_Ifc#(xlen)); module mkMemoryAccessModule#(IsaCfg#(xlen) cfg)(MemoryAccessModuleIfc#(xlen));
// Memory request output // Memory request output
Reg#(Bool) memoryRequestInFlight <- mkReg(False); Reg#(Bool) memoryRequestInFlight <- mkReg(False);
Wire#(MemoryRequest#(xlen, xlen)) memoryRequest <- mkWire; Wire#(MemoryRequest#(xlen, xlen)) memoryRequest <- mkWire;
// Memory response input (FIFO) // Memory response input (FIFO)
// Note: This is an unguarded FIFO so status much be checked before attempting to enq() and deq(). // Note: This is an unguarded FIFO so status must be checked before attempting to enq() and deq().
FIFOF#(MemoryResponse#(xlen)) memoryResponses <- mkUGFIFOF1; FIFOF#(MemoryResponse#(xlen)) memoryResponses <- mkUGFIFOF1;
// //
@ -29,8 +29,17 @@ module mkMemoryAccessStage#(IsaCfg#(xlen) cfg)(MemoryAccessStage_Ifc#(xlen));
// //
method ActionValue#(MEM_WB#(xlen)) step(EX_MEM#(xlen) ex_mem); method ActionValue#(MEM_WB#(xlen)) step(EX_MEM#(xlen) ex_mem);
MEM_WB#(xlen) mem_wb = defaultValue; MEM_WB#(xlen) mem_wb = defaultValue;
if (!ex_mem.common.isBubble) begin
end case (mem_wb.common.ir.value[6:0])
matches 7'b0?00011: begin
// LOAD/STORE
end
default: begin
// All other opcodes
mem_wb.common = ex_mem.common;
end
endcase
return mem_wb; return mem_wb;
endmethod endmethod
@ -45,3 +54,32 @@ module mkMemoryAccessStage#(IsaCfg#(xlen) cfg)(MemoryAccessStage_Ifc#(xlen));
endinterface endinterface
endinterface endinterface
endmodule endmodule
interface MemoryAccessStageIfc#(numeric type xlen);
interface Put#(EX_MEM#(xlen)) put;
interface Get#(MEM_WB#(xlen)) get;
endinterface
module mkMemoryAccessStage#(IsaCfg#(xlen) cfg)(MemoryAccessStageIfc#(xlen));
//
// State
//
Wire#(EX_MEM#(xlen)) ex_mem <- mkWire;
Reg#(MEM_WB#(xlen)) mem_wb <- mkRegU;
MemoryAccessModuleIfc#(xlen) memoryAccessModule <- mkMemoryAccessModule(cfg);
//
// Rules
//
(* no_implicit_conditions *)
rule step;
let mem_wb_ <- memoryAccessModule.step(ex_mem);
mem_wb <= mem_wb_;
endrule
//
// Interfaces
//
interface Put put = toPut(asIfc(ex_mem));
interface Get get = toGet(mem_wb);
endmodule

View File

@ -20,11 +20,11 @@ module mkTopModule(Empty);
extS: False, extS: False,
extU: False extU: False
}; };
MemoryAccessStage_Ifc#(32) memoryAccessStage32 <- mkMemoryAccessStage(rv32); MemoryAccessModuleIfc#(32) memoryAccessModule32 <- mkMemoryAccessModule(rv32);
FIFOF#(MemoryRequest#(32, 32)) memoryRequests32 <- mkUGFIFOF1(); FIFOF#(MemoryRequest#(32, 32)) memoryRequests32 <- mkUGFIFOF1();
mkConnection(memoryAccessStage32.memoryClient.request, toPut(asIfc(memoryRequests32))); mkConnection(memoryAccessModule32.memoryClient.request, toPut(asIfc(memoryRequests32)));
(* no_implicit_conditions *) (* no_implicit_conditions *)
rule test; rule test;
@ -33,7 +33,7 @@ module mkTopModule(Empty);
case(testNumber) case(testNumber)
// Simple bubble passthrough // Simple bubble passthrough
0: begin 0: begin
let mem_wb <- memoryAccessStage32.step(ex_mem); let mem_wb <- memoryAccessModule32.step(ex_mem);
dynamicAssert(mem_wb == defaultValue, "MemoryAccess - Bubble passthrough check"); dynamicAssert(mem_wb == defaultValue, "MemoryAccess - Bubble passthrough check");
end end

View File

@ -1,6 +1,12 @@
import CsrFile::*;
import Trap::*; import Trap::*;
import DefaultValue::*; import DefaultValue::*;
//
// Epoch
//
typedef Bit#(1) Epoch;
// //
// Instruction // Instruction
// //
@ -25,12 +31,14 @@ typedef Bit#(xlen) ProgramCounter#(numeric type xlen);
typedef struct { typedef struct {
ProgramCounter#(xlen) pc; ProgramCounter#(xlen) pc;
Maybe#(ProgramCounter#(xlen)) redirection; Maybe#(ProgramCounter#(xlen)) redirection;
Epoch epoch;
} PC_IF#(numeric type xlen) deriving(Bits, Eq, FShow); } PC_IF#(numeric type xlen) deriving(Bits, Eq, FShow);
instance DefaultValue #(PC_IF#(xlen)); instance DefaultValue#(PC_IF#(xlen));
defaultValue = PC_IF { defaultValue = PC_IF {
pc: 'h-1, pc: 'h-1,
redirection: tagged Invalid redirection: tagged Invalid,
epoch: defaultValue
}; };
endinstance endinstance
@ -40,7 +48,6 @@ endinstance
typedef struct { typedef struct {
Instruction ir; Instruction ir;
ProgramCounter#(xlen) pc; ProgramCounter#(xlen) pc;
Bool isBubble;
Maybe#(Trap#(xlen)) trap; Maybe#(Trap#(xlen)) trap;
} PipelineRegisterCommon#(numeric type xlen) deriving(Bits, Eq, FShow); } PipelineRegisterCommon#(numeric type xlen) deriving(Bits, Eq, FShow);
@ -48,7 +55,6 @@ instance DefaultValue #(PipelineRegisterCommon#(xlen));
defaultValue = PipelineRegisterCommon { defaultValue = PipelineRegisterCommon {
ir: defaultValue, ir: defaultValue,
pc: defaultValue, pc: defaultValue,
isBubble: True,
trap: tagged Invalid trap: tagged Invalid
}; };
endinstance endinstance
@ -58,14 +64,14 @@ endinstance
// //
typedef struct { typedef struct {
PipelineRegisterCommon#(xlen) common; PipelineRegisterCommon#(xlen) common;
Bit#(1) epoch; Epoch epoch;
ProgramCounter#(xlen) npc; // Next program counter ProgramCounter#(xlen) npc; // Next program counter
} IF_ID#(numeric type xlen) deriving(Bits, Eq, FShow); } IF_ID#(numeric type xlen) deriving(Bits, Eq, FShow);
instance DefaultValue #(IF_ID#(xlen)); instance DefaultValue #(IF_ID#(xlen));
defaultValue = IF_ID { defaultValue = IF_ID {
common: defaultValue, common: defaultValue,
epoch: 'h-1, epoch: defaultValue,
npc: defaultValue npc: defaultValue
}; };
endinstance endinstance
@ -75,23 +81,26 @@ endinstance
// //
typedef struct { typedef struct {
PipelineRegisterCommon#(xlen) common; PipelineRegisterCommon#(xlen) common;
Bit#(1) epoch; Epoch epoch;
ProgramCounter#(xlen) npc; // Next program counter ProgramCounter#(xlen) npc; // Next program counter
Bit#(xlen) a; // Operand 1 Bit#(xlen) a; // Operand 1
Bit#(xlen) b; // Operand 2 Bit#(xlen) b; // Operand 2
Bool isBValid; // In the case of a CSR, this will indicate if 'b' is valid Bit#(xlen) imm; // Sign extended immediate
Bit#(xlen) imm; // Sign extended immediate CsrReadResult#(xlen) csr; // CSR read result
} ID_EX#(numeric type xlen) deriving(Bits, Eq, FShow); } ID_EX#(numeric type xlen) deriving(Bits, Eq, FShow);
instance DefaultValue #(ID_EX#(xlen)); instance DefaultValue #(ID_EX#(xlen));
defaultValue = ID_EX { defaultValue = ID_EX {
common: defaultValue, common: defaultValue,
epoch: 0, epoch: defaultValue,
npc: defaultValue, npc: defaultValue,
a: 'h-1, a: 'h-1,
b: 'h-1, b: 'h-1,
isBValid: True, imm: 'h-1,
imm: 'h-1 csr: CsrReadResult {
value: 'h-1,
denied: False
}
}; };
endinstance endinstance

View File

@ -43,102 +43,102 @@ RVBranchOperator branch_BLTU = 3'b110;
RVBranchOperator branch_BGEU = 3'b111; RVBranchOperator branch_BGEU = 3'b111;
// //
// RVCsrIndex // RVCSRIndex
// //
typedef Bit#(12) RVCsrIndex; typedef Bit#(12) RVCSRIndex;
// Supervisor Trap Setup // Supervisor Trap Setup
RVCsrIndex csr_SSTATUS = 12'h100; // Supervisor Status Register (SRW) RVCSRIndex csr_SSTATUS = 12'h100; // Supervisor Status Register (SRW)
RVCsrIndex csr_SIE = 12'h104; // Supervisor Interrupt Enable Register (SRW) RVCSRIndex csr_SIE = 12'h104; // Supervisor Interrupt Enable Register (SRW)
RVCsrIndex csr_STVEC = 12'h105; // Supervisor Trap-Handler base address (SRW) RVCSRIndex csr_STVEC = 12'h105; // Supervisor Trap-Handler base address (SRW)
RVCsrIndex csr_SCOUNTEREN = 12'h106; // Supervisor Counter Enable Register (SRW) RVCSRIndex csr_SCOUNTEREN = 12'h106; // Supervisor Counter Enable Register (SRW)
// Supervisor Configuration // Supervisor Configuration
RVCsrIndex csr_SENVCFG = 12'h10A; // Supervisor environment configuration register (SRW) RVCSRIndex csr_SENVCFG = 12'h10A; // Supervisor environment configuration register (SRW)
// Supervisor Trap Handling // Supervisor Trap Handling
RVCsrIndex csr_SSCRATCH = 12'h140; // Scratch register for supervisor trap handlers (SRW) RVCSRIndex csr_SSCRATCH = 12'h140; // Scratch register for supervisor trap handlers (SRW)
RVCsrIndex csr_SEPC = 12'h141; // Supervisor exception program counter (SRW) RVCSRIndex csr_SEPC = 12'h141; // Supervisor exception program counter (SRW)
RVCsrIndex csr_SCAUSE = 12'h142; // Supervisor trap cause (SRW) RVCSRIndex csr_SCAUSE = 12'h142; // Supervisor trap cause (SRW)
RVCsrIndex csr_STVAL = 12'h143; // Supervisor bad address or instruction (SRW) RVCSRIndex csr_STVAL = 12'h143; // Supervisor bad address or instruction (SRW)
RVCsrIndex csr_SIP = 12'h144; // Supervisor interrupt pending (SRW) RVCSRIndex csr_SIP = 12'h144; // Supervisor interrupt pending (SRW)
// Supervisor Protection and Translation // Supervisor Protection and Translation
RVCsrIndex csr_SATP = 12'h180; // Supervisor address translation and protection (SRW) RVCSRIndex csr_SATP = 12'h180; // Supervisor address translation and protection (SRW)
// Machine Trap Setup // Machine Trap Setup
RVCsrIndex csr_MSTATUS = 12'h300; // Machine Status Register (MRW) RVCSRIndex csr_MSTATUS = 12'h300; // Machine Status Register (MRW)
RVCsrIndex csr_MISA = 12'h301; // Machine ISA and Extensions Register (MRW) RVCSRIndex csr_MISA = 12'h301; // Machine ISA and Extensions Register (MRW)
RVCsrIndex csr_MEDELEG = 12'h302; // Machine Exception Delegation Register (MRW) RVCSRIndex csr_MEDELEG = 12'h302; // Machine Exception Delegation Register (MRW)
RVCsrIndex csr_MIDELEG = 12'h303; // Machine Interrupt Delegation Register (MRW) RVCSRIndex csr_MIDELEG = 12'h303; // Machine Interrupt Delegation Register (MRW)
RVCsrIndex csr_MIE = 12'h304; // Machine Interrupt Enable Register (MRW) RVCSRIndex csr_MIE = 12'h304; // Machine Interrupt Enable Register (MRW)
RVCsrIndex csr_MTVEC = 12'h305; // Machine Trap-Handler base address (MRW) RVCSRIndex csr_MTVEC = 12'h305; // Machine Trap-Handler base address (MRW)
RVCsrIndex csr_MCOUNTEREN = 12'h306; // Machine Counter Enable Register (MRW) RVCSRIndex csr_MCOUNTEREN = 12'h306; // Machine Counter Enable Register (MRW)
RVCsrIndex csr_MSTATUSH = 12'h310; // Additional machine status register, RV32 only (MRW) RVCSRIndex csr_MSTATUSH = 12'h310; // Additional machine status register, RV32 only (MRW)
// Machine Trap Handling // Machine Trap Handling
RVCsrIndex csr_MSCRATCH = 12'h340; // Scratch register for machine trap handlers (MRW) RVCSRIndex csr_MSCRATCH = 12'h340; // Scratch register for machine trap handlers (MRW)
RVCsrIndex csr_MEPC = 12'h341; // Machine exception program counter (MRW) RVCSRIndex csr_MEPC = 12'h341; // Machine exception program counter (MRW)
RVCsrIndex csr_MCAUSE = 12'h342; // Machine trap cause (MRW) RVCSRIndex csr_MCAUSE = 12'h342; // Machine trap cause (MRW)
RVCsrIndex csr_MTVAL = 12'h343; // Machine bad address or instruction (MRW) RVCSRIndex csr_MTVAL = 12'h343; // Machine bad address or instruction (MRW)
RVCsrIndex csr_MIP = 12'h344; // Machine interrupt pending (MRW) RVCSRIndex csr_MIP = 12'h344; // Machine interrupt pending (MRW)
RVCsrIndex csr_MTINST = 12'h34A; // Machine trap instruction (transformed) (MRW) RVCSRIndex csr_MTINST = 12'h34A; // Machine trap instruction (transformed) (MRW)
RVCsrIndex csr_MTVAL2 = 12'h34B; // Machine bad guest physical address (MRW) RVCSRIndex csr_MTVAL2 = 12'h34B; // Machine bad guest physical address (MRW)
// Machine Memory Protection // Machine Memory Protection
RVCsrIndex csr_PMPCFG0 = 12'h3A0; // Physical memory protection configuration (MRW) RVCSRIndex csr_PMPCFG0 = 12'h3A0; // Physical memory protection configuration (MRW)
RVCsrIndex csr_PMPCFG15 = 12'h3AF; RVCSRIndex csr_PMPCFG15 = 12'h3AF;
RVCsrIndex csr_PMPADDR0 = 12'h3B0; // Physical memory protection address register (MRW) RVCSRIndex csr_PMPADDR0 = 12'h3B0; // Physical memory protection address register (MRW)
RVCsrIndex csr_PMPADDR63 = 12'h3EF; RVCSRIndex csr_PMPADDR63 = 12'h3EF;
// Debug/Trace Registers // Debug/Trace Registers
RVCsrIndex csr_TSELECT = 12'h7A0; // Debug/Trace trigger register select (MRW) RVCSRIndex csr_TSELECT = 12'h7A0; // Debug/Trace trigger register select (MRW)
RVCsrIndex csr_TDATA1 = 12'h7A1; // First Debug/Trace trigger data register (MRW) RVCSRIndex csr_TDATA1 = 12'h7A1; // First Debug/Trace trigger data register (MRW)
RVCsrIndex csr_TDATA2 = 12'h7A2; // Second Debug/Trace trigger data register (MRW) RVCSRIndex csr_TDATA2 = 12'h7A2; // Second Debug/Trace trigger data register (MRW)
RVCsrIndex csr_TDATA3 = 12'h7A3; // Third Debug/Trace trigger data register (MRW) RVCSRIndex csr_TDATA3 = 12'h7A3; // Third Debug/Trace trigger data register (MRW)
RVCsrIndex csr_MCONTEXT = 12'h7A8; // Machine-mode context register (MRW) RVCSRIndex csr_MCONTEXT = 12'h7A8; // Machine-mode context register (MRW)
// Debug Mode Registers // Debug Mode Registers
RVCsrIndex csr_DCSR = 12'h7B0; // Debug Control and Status RVCSRIndex csr_DCSR = 12'h7B0; // Debug Control and Status
RVCsrIndex csr_DPC = 12'h7B1; // Debug Program Counter RVCSRIndex csr_DPC = 12'h7B1; // Debug Program Counter
RVCsrIndex csr_DSCRATCH0 = 12'h7B2; // Debug Scratch Register 0 RVCSRIndex csr_DSCRATCH0 = 12'h7B2; // Debug Scratch Register 0
RVCsrIndex csr_DSCRATCH1 = 12'h7B3; // Debug Scratch Register 1 RVCSRIndex csr_DSCRATCH1 = 12'h7B3; // Debug Scratch Register 1
// Machine Counters/Timers // Machine Counters/Timers
RVCsrIndex csr_MCYCLE = 12'hB00; // Cycle counter for RDCYCLE instruction (MRW) RVCSRIndex csr_MCYCLE = 12'hB00; // Cycle counter for RDCYCLE instruction (MRW)
RVCsrIndex csr_MINSTRET = 12'hB02; // Machine instructions-retired counter (MRW) RVCSRIndex csr_MINSTRET = 12'hB02; // Machine instructions-retired counter (MRW)
RVCsrIndex csr_MHPMCOUNTER3 = 12'hB03; // Machine performance-monitoring counter (MRW) RVCSRIndex csr_MHPMCOUNTER3 = 12'hB03; // Machine performance-monitoring counter (MRW)
RVCsrIndex csr_MHPMCOUNTER4 = 12'hB04; // Machine performance-monitoring counter (MRW) RVCSRIndex csr_MHPMCOUNTER4 = 12'hB04; // Machine performance-monitoring counter (MRW)
RVCsrIndex csr_MHPMCOUNTER5 = 12'hB05; // Machine performance-monitoring counter (MRW) RVCSRIndex csr_MHPMCOUNTER5 = 12'hB05; // Machine performance-monitoring counter (MRW)
RVCsrIndex csr_MHPMCOUNTER6 = 12'hB06; // Machine performance-monitoring counter (MRW) RVCSRIndex csr_MHPMCOUNTER6 = 12'hB06; // Machine performance-monitoring counter (MRW)
RVCsrIndex csr_MHPMCOUNTER7 = 12'hB07; // Machine performance-monitoring counter (MRW) RVCSRIndex csr_MHPMCOUNTER7 = 12'hB07; // Machine performance-monitoring counter (MRW)
RVCsrIndex csr_MHPMCOUNTER8 = 12'hB08; // Machine performance-monitoring counter (MRW) RVCSRIndex csr_MHPMCOUNTER8 = 12'hB08; // Machine performance-monitoring counter (MRW)
RVCsrIndex csr_MHPMCOUNTER9 = 12'hB09; // Machine performance-monitoring counter (MRW) RVCSRIndex csr_MHPMCOUNTER9 = 12'hB09; // Machine performance-monitoring counter (MRW)
RVCsrIndex csr_MCYCLEH = 12'hB80; // Upper 32 bits of mcycle, RV32I only (MRW) RVCSRIndex csr_MCYCLEH = 12'hB80; // Upper 32 bits of mcycle, RV32I only (MRW)
RVCsrIndex csr_MINSTRETH = 12'hB82; // Upper 32 bits of minstret, RV32I only (MRW) RVCSRIndex csr_MINSTRETH = 12'hB82; // Upper 32 bits of minstret, RV32I only (MRW)
RVCsrIndex csr_MHPMCOUNTER3H = 12'hB83; // Machine performance-monitoring counter (upper 32 bits) (MRW) RVCSRIndex csr_MHPMCOUNTER3H = 12'hB83; // Machine performance-monitoring counter (upper 32 bits) (MRW)
RVCsrIndex csr_MHPMCOUNTER4H = 12'hB84; // Machine performance-monitoring counter (upper 32 bits) (MRW) RVCSRIndex csr_MHPMCOUNTER4H = 12'hB84; // Machine performance-monitoring counter (upper 32 bits) (MRW)
RVCsrIndex csr_MHPMCOUNTER5H = 12'hB85; // Machine performance-monitoring counter (upper 32 bits) (MRW) RVCSRIndex csr_MHPMCOUNTER5H = 12'hB85; // Machine performance-monitoring counter (upper 32 bits) (MRW)
RVCsrIndex csr_MHPMCOUNTER6H = 12'hB86; // Machine performance-monitoring counter (upper 32 bits) (MRW) RVCSRIndex csr_MHPMCOUNTER6H = 12'hB86; // Machine performance-monitoring counter (upper 32 bits) (MRW)
RVCsrIndex csr_MHPMCOUNTER7H = 12'hB87; // Machine performance-monitoring counter (upper 32 bits) (MRW) RVCSRIndex csr_MHPMCOUNTER7H = 12'hB87; // Machine performance-monitoring counter (upper 32 bits) (MRW)
RVCsrIndex csr_MHPMCOUNTER8H = 12'hB88; // Machine performance-monitoring counter (upper 32 bits) (MRW) RVCSRIndex csr_MHPMCOUNTER8H = 12'hB88; // Machine performance-monitoring counter (upper 32 bits) (MRW)
RVCsrIndex csr_MHPMCOUNTER9H = 12'hB89; // Machine performance-monitoring counter (upper 32 bits) (MRW) RVCSRIndex csr_MHPMCOUNTER9H = 12'hB89; // Machine performance-monitoring counter (upper 32 bits) (MRW)
RVCsrIndex csr_CYCLE = 12'hC00; // Read only mirror of MCYCLE RVCSRIndex csr_CYCLE = 12'hC00; // Read only mirror of MCYCLE
// Machine Information Registers // Machine Information Registers
RVCsrIndex csr_MVENDORID = 12'hF11; // Vendor ID (MRO) RVCSRIndex csr_MVENDORID = 12'hF11; // Vendor ID (MRO)
RVCsrIndex csr_MARCHID = 12'hF12; // Architecture ID (MRO) RVCSRIndex csr_MARCHID = 12'hF12; // Architecture ID (MRO)
RVCsrIndex csr_MIMPID = 12'hF13; // Implementation ID (MRO) RVCSRIndex csr_MIMPID = 12'hF13; // Implementation ID (MRO)
RVCsrIndex csr_MHARTID = 12'hF14; // Hardware thread ID (MRO) RVCSRIndex csr_MHARTID = 12'hF14; // Hardware thread ID (MRO)
RVCsrIndex csr_MCONFIGPTR = 12'hF15; // Pointer to configuration data structure (MRO) RVCSRIndex csr_MCONFIGPTR = 12'hF15; // Pointer to configuration data structure (MRO)
// //
// RVCsrIndexOffset // RVCSRIndexOffset
// //
typedef Bit#(8) RVCsrIndexOffset; typedef Bit#(8) RVCSRIndexOffset;
// Trap Setup // Trap Setup
RVCsrIndexOffset csr_STATUS = 8'h00; // Status RVCSRIndexOffset csr_STATUS = 8'h00; // Status
RVCsrIndexOffset csr_EDELEG = 8'h02; // Exception Delegation RVCSRIndexOffset csr_EDELEG = 8'h02; // Exception Delegation
RVCsrIndexOffset csr_IDELEG = 8'h03; // Interrupt Delegation RVCSRIndexOffset csr_IDELEG = 8'h03; // Interrupt Delegation
RVCsrIndexOffset csr_IE = 8'h04; // Interrupt Enable RVCSRIndexOffset csr_IE = 8'h04; // Interrupt Enable
RVCsrIndexOffset csr_TVEC = 8'h05; // Vector Table RVCSRIndexOffset csr_TVEC = 8'h05; // Vector Table
RVCsrIndexOffset csr_COUNTEREN = 8'h06; // Counter Enable RVCSRIndexOffset csr_COUNTEREN = 8'h06; // Counter Enable
// Trap Handling // Trap Handling
RVCsrIndexOffset csr_SCRATCH = 8'h40; // Scratch Register RVCSRIndexOffset csr_SCRATCH = 8'h40; // Scratch Register
RVCsrIndexOffset csr_EPC = 8'h41; // Exception Program Counter RVCSRIndexOffset csr_EPC = 8'h41; // Exception Program Counter
RVCsrIndexOffset csr_CAUSE = 8'h42; // Exception/Interrupt Cause RVCSRIndexOffset csr_CAUSE = 8'h42; // Exception/Interrupt Cause
RVCsrIndexOffset csr_TVAL = 8'h43; // Bad address or instruction RVCSRIndexOffset csr_TVAL = 8'h43; // Bad address or instruction
RVCsrIndexOffset csr_IP = 8'h44; // Interrupt Pending RVCSRIndexOffset csr_IP = 8'h44; // Interrupt Pending
// //
// RVCSROperator(s) // RVCSROperator(s)

View File

@ -4,7 +4,7 @@ typedef struct {
Bit#(xlen) tval; Bit#(xlen) tval;
} Trap#(numeric type xlen) deriving(Bits, Eq, FShow); } Trap#(numeric type xlen) deriving(Bits, Eq, FShow);
interface TrapController#(numeric type xlen); interface TrapControllerIfc#(numeric type xlen);
method ActionValue#(Bit#(xlen)) beginTrap(Bit#(xlen) trap_program_counter, Trap#(xlen) trap); method ActionValue#(Bit#(xlen)) beginTrap(Bit#(xlen) trap_program_counter, Trap#(xlen) trap);
method ActionValue#(Bit#(xlen)) endTrap; method ActionValue#(Bit#(xlen)) endTrap;
endinterface endinterface

View File

@ -4,7 +4,7 @@
import Soc::*; import Soc::*;
//!topmodule mkE001 //!topmodule mkE001
module mkE001(SocIfc#(32, 32)); module mkE001(Soc#(32, 32));
SocCfg#(32, 32) cfg = SocCfg { SocCfg#(32, 32) cfg = SocCfg {
cpu_cfg: CpuCfg { cpu_cfg: CpuCfg {
initial_program_counter: 'h8000_0000 initial_program_counter: 'h8000_0000
@ -14,11 +14,11 @@ module mkE001(SocIfc#(32, 32));
endmodule endmodule
//!topmodule mkE003 //!topmodule mkE003
module mkE003(SocIfc#(64, 32)); module mkE003(Soc#(64, 32));
SocCfg#(64, 32) cfg = SocCfg{ SocCfg#(64, 32) cfg = SocCfg{
cpu_cfg: CpuCfg { cpu_cfg: CpuCfg {
initial_program_counter: 'h8000_0000 initial_program_counter: 'h8000_0000
} }
}; };
let soc <- mkSoc(cfg); let soc <- mkSoc(cfg);
endmodule endmodule

25
src/Memory/MemoryIO.bsv Normal file
View File

@ -0,0 +1,25 @@
import ClientServer::*;
import GetPut::*;
import Memory::*;
typedef struct {
Bit#(dataSz) data;
Bool accessFault; // The memory request faulted
} FallibleMemoryResponse#(numeric type dataSz) deriving(Bits, Eq, FShow);
//
// ReadWriteMemory
//
typedef Client#(MemoryRequest#(addrSz, dataSz), FallibleMemoryResponse#(dataSz)) ReadWriteMemoryClient#(numeric type addrSz, numeric type dataSz);
typedef Server#(MemoryRequest#(addrSz, dataSz), FallibleMemoryResponse#(dataSz)) ReadWriteMemoryServer#(numeric type addrSz, numeric type dataSz);
//
// ReadOnlyMemory
//
typedef struct {
Bit#(TDiv#(dataSz,8)) byteen;
Bit#(addrSz) address;
} ReadOnlyMemoryRequest#(numeric type addrSz, numeric type dataSz) deriving(Bits, Eq, FShow);
typedef Client#(ReadOnlyMemoryRequest#(addrSz, dataSz), FallibleMemoryResponse#(dataSz)) ReadOnlyMemoryClient#(numeric type addrSz, numeric type dataSz);
typedef Server#(ReadOnlyMemoryRequest#(addrSz, dataSz), FallibleMemoryResponse#(dataSz)) ReadOnlyMemoryServer#(numeric type addrSz, numeric type dataSz);

View File

@ -1,13 +0,0 @@
import ClientServer::*;
typedef struct {
Bit#(a) address;
} ReadOnlyMemoryRequest#(numeric type a) deriving(Bits, Eq);
typedef struct {
Bit#(d) data;
Bool accessFault;
} ReadOnlyMemoryResponse#(numeric type d) deriving(Bits, Eq);
typedef Client#(ReadOnlyMemoryRequest#(a), ReadOnlyMemoryResponse#(d))
ReadOnlyMemoryClient#(numeric type a, numeric type d);

View File

@ -1,5 +1,5 @@
import Cpu::*; import Cpu::*;
export CpuCfg(..), mkSoc, SocCfg(..), SocIfc(..); export CpuCfg(..), mkSoc, SocCfg(..), Soc(..);
// //
// SocConfig // SocConfig
@ -9,14 +9,14 @@ typedef struct {
} SocCfg#(numeric type xlen, numeric type ifetchByteCount); } SocCfg#(numeric type xlen, numeric type ifetchByteCount);
// //
// SocIfc // Soc
// //
interface SocIfc#(numeric type xlen, numeric type ifetchByteCount); interface Soc#(numeric type xlen, numeric type ifetchByteCount);
endinterface endinterface
// //
// mkSoc() // mkSoc()
// //
module mkSoc#(SocCfg#(xlen, ifetchByteCount) cfg)(SocIfc#(xlen, ifetchByteCount)); module mkSoc#(SocCfg#(xlen, ifetchByteCount) cfg)(Soc#(xlen, ifetchByteCount));
let cpu <- mkCpu(cfg.cpu_cfg); let cpu <- mkCpu(cfg.cpu_cfg);
endmodule endmodule