Compare commits
No commits in common. "c22d2639ebcda33b38732d54a16558bc8ef2e8b5" and "9881cf00d4dc36d37b699ef3dd963b81b845eed3" have entirely different histories.
c22d2639eb
...
9881cf00d4
181
src/Cpu/Alu.bsv
181
src/Cpu/Alu.bsv
@ -5,78 +5,86 @@
|
|||||||
// reponsible for mathematical operations inside the CPU.
|
// reponsible for mathematical operations inside the CPU.
|
||||||
//
|
//
|
||||||
import RV_ISA::*;
|
import RV_ISA::*;
|
||||||
export AluCfg, AluIfc(..), mkAlu, Execute(..);
|
export RV_ISA::*, AluCfg, AluIfc(..), mkAlu;
|
||||||
|
|
||||||
|
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 Maybe#(Bit#(32)) execute(RVALUOperator operator, Bit#(32) operand1, Bit#(32) operand2);
|
function execute = execute32;
|
||||||
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 Maybe#(Bit#(64)) execute(RVALUOperator operator, Bit#(64) operand1, Bit#(64) operand2);
|
function execute = execute64;
|
||||||
let sum = operand1 + operand2;
|
endinstance
|
||||||
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];
|
instance Execute#(n);
|
||||||
let sra = signedShiftRight(operand1, operand2[5:0]);
|
function execute = tagged Invalid;
|
||||||
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 {
|
||||||
@ -86,12 +94,51 @@ 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
|
||||||
|
|||||||
@ -1,44 +0,0 @@
|
|||||||
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
|
|
||||||
@ -5,7 +5,6 @@ import Trap::*;
|
|||||||
|
|
||||||
import IsaCfg::*;
|
import IsaCfg::*;
|
||||||
import MachineInformation::*;
|
import MachineInformation::*;
|
||||||
import MachineISA::*;
|
|
||||||
import MachineStatus::*;
|
import MachineStatus::*;
|
||||||
import RV_ISA::*;
|
import RV_ISA::*;
|
||||||
|
|
||||||
@ -19,18 +18,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 CsrFileIfc#(numeric type xlen);
|
interface CsrFile#(numeric type xlen);
|
||||||
method Action incrementCycleCounters;
|
method Action incrementCycleCounters;
|
||||||
method Action incrementInstructionsRetiredCounter;
|
method Action incrementInstructionsRetiredCounter;
|
||||||
|
|
||||||
@ -38,14 +37,14 @@ interface CsrFileIfc#(numeric type xlen);
|
|||||||
interface CsrWritePort#(xlen) csrWritePort;
|
interface CsrWritePort#(xlen) csrWritePort;
|
||||||
interface CsrWritePermission csrWritePermission;
|
interface CsrWritePermission csrWritePermission;
|
||||||
|
|
||||||
interface TrapControllerIfc#(xlen) trapController;
|
interface TrapController#(xlen) trapController;
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(xlen))
|
typedef struct {
|
||||||
provisos(
|
IsaCfg#(xlen) isa_cfg;
|
||||||
Add#(xlen, 0, 32),
|
} CsrFileCfg#(numeric type xlen);
|
||||||
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
|
||||||
@ -65,17 +64,19 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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);
|
||||||
@ -89,7 +90,7 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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) ||
|
||||||
@ -102,8 +103,8 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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;
|
||||||
@ -114,7 +115,7 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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.extS) begin // S mode supported?
|
if (cfg.s_mode_supported) 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) :
|
||||||
@ -125,7 +126,7 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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.extU) begin
|
if (currentPriv == priv_USER && cfg.u_level_interrupts_supported) 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));
|
||||||
@ -138,7 +139,7 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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.extU) begin
|
if (cfg.u_level_interrupts_supported) 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));
|
||||||
@ -156,9 +157,9 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(xlen))
|
|||||||
//
|
//
|
||||||
// readInternal
|
// readInternal
|
||||||
//
|
//
|
||||||
function ActionValue#(CsrReadResult#(xlen)) readInternal(RVCSRIndex index);
|
function ActionValue#(CsrReadResult#(xlen)) readInternal(RVCsrIndex index);
|
||||||
actionvalue
|
actionvalue
|
||||||
CsrReadResult#(xlen) result = CsrReadResult {
|
let result = CsrReadResult {
|
||||||
value: 0,
|
value: 0,
|
||||||
denied: False
|
denied: False
|
||||||
};
|
};
|
||||||
@ -166,12 +167,14 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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 = misa.pack;
|
csr_MISA: result.value = pack(cfg);
|
||||||
|
|
||||||
csr_MCAUSE: result.value = mcause;
|
csr_MCAUSE: result.value = mcause;
|
||||||
csr_MTVEC: result.value = mtvec;
|
csr_MTVEC: result.value = mtvec;
|
||||||
@ -180,12 +183,15 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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.get;
|
csr_MSTATUS: begin
|
||||||
|
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;
|
||||||
@ -210,7 +216,7 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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
|
||||||
@ -226,7 +232,7 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(xlen))
|
|||||||
// No-Op
|
// No-Op
|
||||||
end
|
end
|
||||||
csr_MSCRATCH: mscratch <= value;
|
csr_MSCRATCH: mscratch <= value;
|
||||||
csr_MSTATUS: mstatus.put(value);
|
csr_MSTATUS: mstatus.unpack(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;
|
||||||
@ -246,14 +252,14 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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;
|
||||||
@ -273,7 +279,7 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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
|
||||||
@ -291,7 +297,7 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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
|
||||||
};
|
};
|
||||||
@ -308,7 +314,7 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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
|
||||||
@ -316,21 +322,28 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(xlen))
|
|||||||
//
|
//
|
||||||
// trapController
|
// trapController
|
||||||
//
|
//
|
||||||
interface TrapControllerIfc trapController;
|
interface TrapController 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);
|
||||||
|
|
||||||
mstatus.beginTrap(currentPriv);
|
// CurPriv => MSTATUS::MPP
|
||||||
|
let mstatus_ <- mstatus.getMachineStatus.get;
|
||||||
|
mstatus_.mpp = currentPriv;
|
||||||
|
|
||||||
|
// MSTATUS::MIE => MSTATUS::MPIE
|
||||||
|
mstatus_.mpie = mstatus_.mie;
|
||||||
|
mstatus_.mie = False; // Disable interrupts
|
||||||
|
mstatus.putMachineStatus.put(mstatus_);
|
||||||
|
|
||||||
// cause => CAUSE
|
// cause => CAUSE
|
||||||
writeWithOffset1(trapPrivilegeLevel, csr_CAUSE, cause);
|
writeWithOffset1(trapPrivilegeLevel, csr_CAUSE, cause);
|
||||||
@ -341,13 +354,14 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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;
|
||||||
@ -358,14 +372,15 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(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);
|
/*
|
||||||
let newPrivilegeLevel = mstatus_.mpp;
|
MachineStatus#(xlen) mstatus = unpack(readStatus.value);
|
||||||
mstatus_.mie = mstatus_.mpie;
|
let newPrivilegeLevel = mstatus.mpp;
|
||||||
mstatus_.mpie = False;
|
mstatus.mie = mstatus.mpie;
|
||||||
|
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, mstatus_pack(mstatus_));
|
let writeStatus <- writeInternal(csr_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);
|
||||||
@ -373,6 +388,7 @@ module mkCsrFile#(IsaCfg#(xlen) cfg)(CsrFileIfc#(xlen))
|
|||||||
newProgramCounter = readStatus.value;
|
newProgramCounter = readStatus.value;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
*/
|
||||||
end
|
end
|
||||||
return newProgramCounter;
|
return newProgramCounter;
|
||||||
endmethod
|
endmethod
|
||||||
@ -1,129 +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 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
|
|
||||||
179
src/Cpu/CSRs/MachineISA.bsv.remove
Normal file
179
src/Cpu/CSRs/MachineISA.bsv.remove
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
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
|
||||||
@ -1,49 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
export MachineInformationCfg(..);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Bit#(32) mvendorid;
|
Bit#(32) mvendorid;
|
||||||
Bit#(xlen) marchid;
|
Bit#(xlen) marchid;
|
||||||
|
|||||||
180
src/Cpu/CSRs/MachineStatus copy.bsv
Normal file
180
src/Cpu/CSRs/MachineStatus copy.bsv
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
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
|
||||||
@ -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 deriving(Bits, Eq, FShow);
|
} MachineStatus;
|
||||||
|
|
||||||
instance DefaultValue#(MachineStatus);
|
instance DefaultValue#(MachineStatus);
|
||||||
defaultValue = MachineStatus {
|
defaultValue = MachineStatus {
|
||||||
@ -72,13 +72,8 @@ instance DefaultValue#(MachineStatus);
|
|||||||
};
|
};
|
||||||
endinstance
|
endinstance
|
||||||
|
|
||||||
typeclass MachineStatusBits#(numeric type xlen);
|
instance Bits#(MachineStatus, 32);
|
||||||
function Bit#(xlen) mstatus_pack(MachineStatus mstatus);
|
function Bit#(32) 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,
|
||||||
@ -105,13 +100,13 @@ instance MachineStatusBits#(32);
|
|||||||
};
|
};
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function MachineStatus mstatus_unpack(Bit#(32) mstatus_packed);
|
function MachineStatus unpack(Bit#(32) value);
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
endfunction
|
endfunction
|
||||||
endinstance
|
endinstance
|
||||||
|
|
||||||
instance MachineStatusBits#(64);
|
instance Bits#(MachineStatus, 64);
|
||||||
function Bit#(64) mstatus_pack(MachineStatus mstatus);
|
function Bit#(64) 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,
|
||||||
@ -139,64 +134,46 @@ instance MachineStatusBits#(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 mstatus_unpack(Bit#(64) mstatus_packed);
|
function MachineStatus unpack(Bit#(64) value);
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
endfunction
|
endfunction
|
||||||
endinstance
|
endinstance
|
||||||
|
|
||||||
interface MachineStatusIfc#(numeric type xlen);
|
interface MachineStatus_Ifc;
|
||||||
method Action beginTrap(RVPrivilegeLevel currentPriv);
|
interface Get#(MachineStatus) getMachineStatus;
|
||||||
method Bit#(xlen) get;
|
interface Put#(MachineStatus) putMachineStatus;
|
||||||
method Action put(Bit#(xlen) newMachineStatus);
|
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatusIfc#(xlen))
|
module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc);
|
||||||
provisos(
|
Reg#(MachineStatus) mstatus <- mkReg(defaultValue);
|
||||||
MachineStatusBits#(xlen)
|
|
||||||
);
|
|
||||||
Reg#(Bit#(xlen)) mstatus <- mkReg(defaultValue);
|
|
||||||
|
|
||||||
method Action beginTrap(RVPrivilegeLevel currentPriv);
|
|
||||||
// CurPriv => MSTATUS::MPP
|
|
||||||
let mstatus_ = mstatus_unpack(mstatus);
|
|
||||||
mstatus_.mpp = currentPriv;
|
|
||||||
|
|
||||||
// MSTATUS::MIE => MSTATUS::MPIE
|
interface Get getMachineStatus = toGet(mstatus);
|
||||||
mstatus_.mpie = mstatus_.mie;
|
interface Put putMachineStatus;
|
||||||
mstatus_.mie = False; // Disable interrupts
|
method Action put(MachineStatus value);
|
||||||
|
//
|
||||||
|
// Only MPP, MIE, and MIE are writable.
|
||||||
|
//
|
||||||
|
MachineStatus mstatus_ = mstatus;
|
||||||
|
|
||||||
mstatus <= mstatus_pack(mstatus_);
|
if (cfg.extS) begin
|
||||||
endmethod
|
mstatus_.mpp = value.mpp;
|
||||||
|
end else begin
|
||||||
method Bit#(xlen) get;
|
// Supervisor mode not supported, ensure only USER and MACHINE
|
||||||
return mstatus;
|
// mode are set in MPP.
|
||||||
endmethod
|
RVPrivilegeLevel requestedMPP = value.mpp;
|
||||||
|
if (requestedMPP == priv_USER || requestedMPP == priv_MACHINE) begin
|
||||||
method Action put(Bit#(xlen) newMachineStatus);
|
mstatus_.mpp = requestedMPP;
|
||||||
//
|
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_pack(mstatus_);
|
mstatus <= mstatus_;
|
||||||
endmethod
|
endmethod
|
||||||
|
endinterface
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
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
|
|
||||||
@ -17,7 +17,7 @@ typedef struct {
|
|||||||
} CpuCfg#(numeric type xlen, numeric type icacheFetchByteCount);
|
} CpuCfg#(numeric type xlen, numeric type icacheFetchByteCount);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Cpu
|
// CpuIfc
|
||||||
//
|
//
|
||||||
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 {};
|
||||||
GprFileIfc#(xlen) gprfile <- mkGprFile(gpr_cfg);
|
GprFile#(xlen) gpr <- 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)
|
||||||
gprfile.gprWritePort.write(truncate(gprInitIndex), 0);
|
gpr.gprWritePort.write(truncate(gprInitIndex), 0);
|
||||||
|
|
||||||
state <= FETCH;
|
state <= FETCH;
|
||||||
endseq);
|
endseq);
|
||||||
|
|||||||
@ -1,23 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,165 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import IsaCfg::*;
|
import IsaCfg::*;
|
||||||
import MemoryIO::*;
|
import MemoryTypes::*;
|
||||||
import PipelineRegisters::*;
|
import PipelineRegisters::*;
|
||||||
import RV_ISA::*;
|
import RV_ISA::*;
|
||||||
import Trap::*;
|
import Trap::*;
|
||||||
@ -10,38 +10,34 @@ import FIFOF::*;
|
|||||||
import GetPut::*;
|
import GetPut::*;
|
||||||
import Memory::*;
|
import Memory::*;
|
||||||
|
|
||||||
typedef ReadOnlyMemoryRequest#(xlen, 32) InstructionMemoryRequest#(numeric type xlen);
|
interface FetchStage_Ifc#(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 mkFetchModule#(IsaCfg#(xlen) cfg)(FetchModuleIfc#(xlen));
|
module mkFetchStage#(IsaCfg#(xlen) cfg)(FetchStage_Ifc#(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#(InstructionMemoryRequest#(xlen))) inflightMemoryRequest <- mkReg(tagged Invalid);
|
Reg#(Maybe#(ReadOnlyMemoryRequest#(xlen))) inflightMemoryRequest <- mkReg(tagged Invalid);
|
||||||
Wire#(InstructionMemoryRequest#(xlen)) memoryRequest <- mkWire;
|
Wire#(ReadOnlyMemoryRequest#(xlen)) memoryRequest <- mkWire;
|
||||||
|
|
||||||
// Memory response input (FIFO)
|
// Memory response input (FIFO)
|
||||||
// Note: This is an unguarded FIFO so status must be checked before attempting to enq() and deq().
|
// Note: This is an unguarded FIFO so status much be checked before attempting to enq() and deq().
|
||||||
FIFOF#(FallibleMemoryResponse#(32)) memoryResponses <- mkUGFIFOF1;
|
FIFOF#(ReadOnlyMemoryResponse#(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(FallibleMemoryResponse#(32) response);
|
function IF_ID#(xlen) processMemoryResponse(ReadOnlyMemoryResponse#(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.npc = updatedPc + 4;
|
if_id.common.isBubble = False;
|
||||||
if_id.epoch = requestEpoch;
|
if_id.npc = updatedPc;
|
||||||
|
|
||||||
if (!response.accessFault) begin
|
if (!response.accessFault) begin
|
||||||
if_id.common.ir.value = response.data;
|
if_id.common.ir.value = response.data;
|
||||||
@ -77,18 +73,10 @@ module mkFetchModule#(IsaCfg#(xlen) cfg)(FetchModuleIfc#(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 fetched from. It's either the calculated PC
|
// Determine the PC the instruction will be fetchted 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...
|
||||||
@ -99,11 +87,11 @@ module mkFetchModule#(IsaCfg#(xlen) cfg)(FetchModuleIfc#(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.
|
||||||
InstructionMemoryRequest#(xlen) request = ReadOnlyMemoryRequest {
|
ReadOnlyMemoryRequest#(xlen) request = ReadOnlyMemoryRequest {
|
||||||
address: updatedPc_,
|
address: updatedPc_
|
||||||
byteen: 'b1111
|
|
||||||
};
|
};
|
||||||
memoryRequest <= request;
|
memoryRequest <= request;
|
||||||
inflightMemoryRequest <= tagged Valid request;
|
inflightMemoryRequest <= tagged Valid request;
|
||||||
@ -118,42 +106,10 @@ module mkFetchModule#(IsaCfg#(xlen) cfg)(FetchModuleIfc#(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(FallibleMemoryResponse#(32) response);
|
method Action put(ReadOnlyMemoryResponse#(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
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import FetchStage::*;
|
import FetchStage::*;
|
||||||
import IsaCfg::*;
|
import IsaCfg::*;
|
||||||
import MemoryIO::*;
|
import MemoryTypes::*;
|
||||||
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
|
||||||
};
|
};
|
||||||
FetchModuleIfc#(32) fetchModule32 <- mkFetchModule(rv32);
|
FetchStage_Ifc#(32) fetchStage32 <- mkFetchStage(rv32);
|
||||||
|
|
||||||
FIFOF#(InstructionMemoryRequest#(32)) memoryRequests32 <- mkUGFIFOF1();
|
FIFOF#(ReadOnlyMemoryRequest#(32)) memoryRequests32 <- mkUGFIFOF1();
|
||||||
mkConnection(fetchModule32.memoryClient.request, toPut(asIfc(memoryRequests32)));
|
mkConnection(fetchStage32.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 <- fetchModule32.step(pc_if);
|
let if_id <- fetchStage32.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 (step 1 - request submit)
|
// Memory request denied trap (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 <- fetchModule32.step(pc_if);
|
let if_id <- fetchStage32.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 (step 2 - request receipt)
|
// Memory request denied trap (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 <- fetchModule32.step(pc_if);
|
let if_id <- fetchStage32.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,41 +64,40 @@ 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");
|
||||||
dynamicAssert(memoryRequest.byteen == 'b1111, "Fetch - Memory request denied trap check - memory request byte enable should be 'b1111");
|
fetchStage32.memoryClient.response.put(ReadOnlyMemoryResponse {
|
||||||
fetchModule32.memoryClient.response.put(FallibleMemoryResponse {
|
|
||||||
data: 'h-1,
|
data: 'h-1,
|
||||||
accessFault: True
|
accessFault: True
|
||||||
});
|
});
|
||||||
end
|
end
|
||||||
|
|
||||||
// Memory request denied trap (step 3 - return trap check)
|
// Memory request denied trap (return trap check)
|
||||||
3: begin
|
3: begin
|
||||||
pc_if.pc = 'h100;
|
pc_if.pc = 'h100;
|
||||||
|
|
||||||
let if_id <- fetchModule32.step(pc_if);
|
// The fetch should proceed and return a bubble.
|
||||||
|
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 (step 1 - request submit)
|
// Normal memory request (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 <- fetchModule32.step(pc_if);
|
let if_id <- fetchStage32.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 (step 2 - request receipt)
|
// Normal memory request (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 <- fetchModule32.step(pc_if);
|
let if_id <- fetchStage32.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");
|
||||||
@ -106,69 +105,26 @@ 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");
|
||||||
dynamicAssert(memoryRequest.byteen == 'b1111, "Fetch - Normal request - memory request byte enable should be 'b1111");
|
fetchStage32.memoryClient.response.put(ReadOnlyMemoryResponse {
|
||||||
fetchModule32.memoryClient.response.put(FallibleMemoryResponse {
|
|
||||||
data: 'haabb_ccdd,
|
data: 'haabb_ccdd,
|
||||||
accessFault: False
|
accessFault: False
|
||||||
});
|
});
|
||||||
end
|
end
|
||||||
|
|
||||||
// Normal memory request (step 3 - return value check)
|
// Normal memory request (return value check)
|
||||||
6: begin
|
6: begin
|
||||||
pc_if.pc = 'h100;
|
pc_if.pc = 'h100;
|
||||||
|
|
||||||
let if_id <- fetchModule32.step(pc_if);
|
// The fetch should proceed and return a bubble.
|
||||||
|
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 == 10, "Fetch - not all tests run");
|
dynamicAssert(stepNumber == 7, "Fetch - not all tests run");
|
||||||
$display(">>>PASS");
|
$display(">>>PASS");
|
||||||
$finish();
|
$finish();
|
||||||
end
|
end
|
||||||
|
|||||||
@ -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(RVGPRIndex index);
|
method Bit#(xlen) read(GprIndex index);
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
interface GprWritePort#(numeric type xlen);
|
interface GprWritePort#(numeric type xlen);
|
||||||
method Action write(RVGPRIndex index, Bit#(xlen) value);
|
method Action write(GprIndex index, Bit#(xlen) value);
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
interface GprFileIfc#(numeric type xlen);
|
interface GprFile#(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)(GprFileIfc#(xlen));
|
module mkGprFile#(GprFileCfg#(xlen) cfg)(GprFile#(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(RVGPRIndex index);
|
method Bit#(xlen) read(GprIndex index);
|
||||||
return reg_file[index];
|
return reg_file[index];
|
||||||
endmethod
|
endmethod
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
interface GprReadPort gprReadPort2;
|
interface GprReadPort gprReadPort2;
|
||||||
method Bit#(xlen) read(RVGPRIndex index);
|
method Bit#(xlen) read(GprIndex index);
|
||||||
return reg_file[index];
|
return reg_file[index];
|
||||||
endmethod
|
endmethod
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
interface GprWritePort gprWritePort;
|
interface GprWritePort gprWritePort;
|
||||||
method Action write(RVGPRIndex index, Bit#(xlen) value);
|
method Action write(GprIndex index, Bit#(xlen) value);
|
||||||
if (index != 0) begin
|
if (index != 0) begin
|
||||||
reg_file[index] <= value;
|
reg_file[index] <= value;
|
||||||
end
|
end
|
||||||
|
|||||||
@ -9,18 +9,18 @@ import FIFOF::*;
|
|||||||
import GetPut::*;
|
import GetPut::*;
|
||||||
import Memory::*;
|
import Memory::*;
|
||||||
|
|
||||||
interface MemoryAccessModuleIfc#(numeric type xlen);
|
interface MemoryAccessStage_Ifc#(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 mkMemoryAccessModule#(IsaCfg#(xlen) cfg)(MemoryAccessModuleIfc#(xlen));
|
module mkMemoryAccessStage#(IsaCfg#(xlen) cfg)(MemoryAccessStage_Ifc#(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 must be checked before attempting to enq() and deq().
|
// Note: This is an unguarded FIFO so status much be checked before attempting to enq() and deq().
|
||||||
FIFOF#(MemoryResponse#(xlen)) memoryResponses <- mkUGFIFOF1;
|
FIFOF#(MemoryResponse#(xlen)) memoryResponses <- mkUGFIFOF1;
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -29,17 +29,8 @@ module mkMemoryAccessModule#(IsaCfg#(xlen) cfg)(MemoryAccessModuleIfc#(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
|
||||||
case (mem_wb.common.ir.value[6:0])
|
end
|
||||||
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
|
||||||
@ -54,32 +45,3 @@ module mkMemoryAccessModule#(IsaCfg#(xlen) cfg)(MemoryAccessModuleIfc#(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
|
|
||||||
|
|||||||
@ -20,11 +20,11 @@ module mkTopModule(Empty);
|
|||||||
extS: False,
|
extS: False,
|
||||||
extU: False
|
extU: False
|
||||||
};
|
};
|
||||||
MemoryAccessModuleIfc#(32) memoryAccessModule32 <- mkMemoryAccessModule(rv32);
|
MemoryAccessStage_Ifc#(32) memoryAccessStage32 <- mkMemoryAccessStage(rv32);
|
||||||
|
|
||||||
FIFOF#(MemoryRequest#(32, 32)) memoryRequests32 <- mkUGFIFOF1();
|
FIFOF#(MemoryRequest#(32, 32)) memoryRequests32 <- mkUGFIFOF1();
|
||||||
|
|
||||||
mkConnection(memoryAccessModule32.memoryClient.request, toPut(asIfc(memoryRequests32)));
|
mkConnection(memoryAccessStage32.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 <- memoryAccessModule32.step(ex_mem);
|
let mem_wb <- memoryAccessStage32.step(ex_mem);
|
||||||
dynamicAssert(mem_wb == defaultValue, "MemoryAccess - Bubble passthrough check");
|
dynamicAssert(mem_wb == defaultValue, "MemoryAccess - Bubble passthrough check");
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,6 @@
|
|||||||
import CsrFile::*;
|
|
||||||
import Trap::*;
|
import Trap::*;
|
||||||
import DefaultValue::*;
|
import DefaultValue::*;
|
||||||
|
|
||||||
//
|
|
||||||
// Epoch
|
|
||||||
//
|
|
||||||
typedef Bit#(1) Epoch;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Instruction
|
// Instruction
|
||||||
//
|
//
|
||||||
@ -31,14 +25,12 @@ 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
|
||||||
|
|
||||||
@ -48,6 +40,7 @@ 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);
|
||||||
|
|
||||||
@ -55,6 +48,7 @@ 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
|
||||||
@ -64,14 +58,14 @@ endinstance
|
|||||||
//
|
//
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PipelineRegisterCommon#(xlen) common;
|
PipelineRegisterCommon#(xlen) common;
|
||||||
Epoch epoch;
|
Bit#(1) 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: defaultValue,
|
epoch: 'h-1,
|
||||||
npc: defaultValue
|
npc: defaultValue
|
||||||
};
|
};
|
||||||
endinstance
|
endinstance
|
||||||
@ -81,26 +75,23 @@ endinstance
|
|||||||
//
|
//
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PipelineRegisterCommon#(xlen) common;
|
PipelineRegisterCommon#(xlen) common;
|
||||||
Epoch epoch;
|
Bit#(1) 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
|
||||||
Bit#(xlen) imm; // Sign extended immediate
|
Bool isBValid; // In the case of a CSR, this will indicate if 'b' is valid
|
||||||
CsrReadResult#(xlen) csr; // CSR read result
|
Bit#(xlen) imm; // Sign extended immediate
|
||||||
} 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: defaultValue,
|
epoch: 0,
|
||||||
npc: defaultValue,
|
npc: defaultValue,
|
||||||
a: 'h-1,
|
a: 'h-1,
|
||||||
b: 'h-1,
|
b: 'h-1,
|
||||||
imm: 'h-1,
|
isBValid: True,
|
||||||
csr: CsrReadResult {
|
imm: 'h-1
|
||||||
value: 'h-1,
|
|
||||||
denied: False
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
endinstance
|
endinstance
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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 TrapControllerIfc#(numeric type xlen);
|
interface TrapController#(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
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
import Soc::*;
|
import Soc::*;
|
||||||
|
|
||||||
//!topmodule mkE001
|
//!topmodule mkE001
|
||||||
module mkE001(Soc#(32, 32));
|
module mkE001(SocIfc#(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(Soc#(32, 32));
|
|||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
//!topmodule mkE003
|
//!topmodule mkE003
|
||||||
module mkE003(Soc#(64, 32));
|
module mkE003(SocIfc#(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
|
||||||
@ -1,25 +0,0 @@
|
|||||||
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);
|
|
||||||
13
src/Memory/MemoryTypes.bsv
Normal file
13
src/Memory/MemoryTypes.bsv
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
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);
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import Cpu::*;
|
import Cpu::*;
|
||||||
export CpuCfg(..), mkSoc, SocCfg(..), Soc(..);
|
export CpuCfg(..), mkSoc, SocCfg(..), SocIfc(..);
|
||||||
|
|
||||||
//
|
//
|
||||||
// SocConfig
|
// SocConfig
|
||||||
@ -9,14 +9,14 @@ typedef struct {
|
|||||||
} SocCfg#(numeric type xlen, numeric type ifetchByteCount);
|
} SocCfg#(numeric type xlen, numeric type ifetchByteCount);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Soc
|
// SocIfc
|
||||||
//
|
//
|
||||||
interface Soc#(numeric type xlen, numeric type ifetchByteCount);
|
interface SocIfc#(numeric type xlen, numeric type ifetchByteCount);
|
||||||
endinterface
|
endinterface
|
||||||
|
|
||||||
//
|
//
|
||||||
// mkSoc()
|
// mkSoc()
|
||||||
//
|
//
|
||||||
module mkSoc#(SocCfg#(xlen, ifetchByteCount) cfg)(Soc#(xlen, ifetchByteCount));
|
module mkSoc#(SocCfg#(xlen, ifetchByteCount) cfg)(SocIfc#(xlen, ifetchByteCount));
|
||||||
let cpu <- mkCpu(cfg.cpu_cfg);
|
let cpu <- mkCpu(cfg.cpu_cfg);
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user