WIP
This commit is contained in:
parent
0df29d8284
commit
637d71432c
134
src/Cpu/Alu.bsv
134
src/Cpu/Alu.bsv
@ -7,6 +7,86 @@
|
||||
import RV_ISA::*;
|
||||
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);
|
||||
function Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) operand2);
|
||||
endtypeclass
|
||||
|
||||
instance Execute#(32);
|
||||
function execute = execute32;
|
||||
endinstance
|
||||
|
||||
instance Execute#(64);
|
||||
function execute = execute64;
|
||||
endinstance
|
||||
|
||||
instance Execute#(n);
|
||||
function execute = tagged Invalid;
|
||||
endinstance
|
||||
|
||||
typedef struct {
|
||||
} AluCfg#(numeric type xlen);
|
||||
|
||||
@ -16,59 +96,7 @@ endinterface
|
||||
|
||||
module mkAlu#(AluCfg#(xlen) cfg)(AluIfc#(xlen));
|
||||
method Maybe#(Bit#(xlen)) execute(RVALUOperator operator, Bit#(xlen) operand1, Bit#(xlen) 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#(xlen) signedOperand1 = unpack(pack(operand1));
|
||||
Int#(xlen) signedOperand2 = unpack(pack(operand2));
|
||||
(signedOperand1 < signedOperand2 ? 1 : 0);
|
||||
end);
|
||||
|
||||
Maybe#(Bit#(xlen)) result = ?;
|
||||
if (valueOf(xlen) == 32) begin
|
||||
let sll = operand1 << operand2[4:0];
|
||||
let sra = signedShiftRight(operand1, operand2[4:0]);
|
||||
let srl = operand1 >> operand2[4:0];
|
||||
|
||||
result = 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;
|
||||
end else if (valueOf(xlen) == 64) begin
|
||||
let sll = operand1 << operand2[5:0];
|
||||
let sra = signedShiftRight(operand1, operand2[5:0]);
|
||||
let srl = operand1 >> operand2[5:0];
|
||||
|
||||
result = 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;
|
||||
end
|
||||
|
||||
return result;
|
||||
return execute(operator, operand1, operand2);
|
||||
|
||||
// return case(operator)
|
||||
// alu_ADD: tagged Valid (operand1 + operand2);
|
||||
|
||||
396
src/Cpu/CSRs/CsrFile.bsv
Normal file
396
src/Cpu/CSRs/CsrFile.bsv
Normal file
@ -0,0 +1,396 @@
|
||||
import Cntrs::*;
|
||||
import GetPut::*;
|
||||
import ReadOnly::*;
|
||||
import Trap::*;
|
||||
|
||||
import IsaCfg::*;
|
||||
import MachineInformation::*;
|
||||
import MachineStatus::*;
|
||||
import RV_ISA::*;
|
||||
|
||||
typedef struct {
|
||||
Bit#(xlen) value;
|
||||
Bool denied;
|
||||
} CsrReadResult#(numeric type xlen) deriving(Bits, Eq, FShow);
|
||||
|
||||
typedef struct {
|
||||
Bool denied;
|
||||
} CsrWriteResult deriving(Bits, Eq, FShow);
|
||||
|
||||
interface CsrReadPort#(numeric type xlen);
|
||||
method ActionValue#(CsrReadResult#(xlen)) read(RVCsrIndex index);
|
||||
endinterface
|
||||
|
||||
interface CsrWritePort#(numeric type xlen);
|
||||
method ActionValue#(CsrWriteResult) write(RVCsrIndex index, Bit#(xlen) value);
|
||||
endinterface
|
||||
|
||||
interface CsrWritePermission;
|
||||
method Bool isWriteable(RVCsrIndex index);
|
||||
endinterface
|
||||
|
||||
interface CsrFile#(numeric type xlen);
|
||||
method Action incrementCycleCounters;
|
||||
method Action incrementInstructionsRetiredCounter;
|
||||
|
||||
interface CsrReadPort#(xlen) csrReadPort;
|
||||
interface CsrWritePort#(xlen) csrWritePort;
|
||||
interface CsrWritePermission csrWritePermission;
|
||||
|
||||
interface TrapController#(xlen) trapController;
|
||||
endinterface
|
||||
|
||||
typedef struct {
|
||||
IsaCfg#(xlen) isa_cfg;
|
||||
} CsrFileCfg#(numeric type xlen);
|
||||
|
||||
module mkCsrFile#(CsrFileCfg#(xlen) cfg)(CsrFile#(xlen));
|
||||
Reg#(RVPrivilegeLevel) currentPriv <- mkReg(priv_MACHINE);
|
||||
|
||||
// Counters
|
||||
Count#(Bit#(64)) cycleCounter <- mkCount(0);
|
||||
Count#(Bit#(64)) timeCounter <- mkCount(0);
|
||||
Count#(Bit#(64)) retiredCounter <- mkCount(0);
|
||||
|
||||
// Csrs
|
||||
|
||||
// MINFO (mvendorid, marchid, mpimpid, mhardit, mconfigptr)
|
||||
MachineInformationCfg#(xlen) machineInfoCfg = MachineInformationCfg {
|
||||
mvendorid: 0,
|
||||
marchid: 0,
|
||||
mimpid: 0,
|
||||
mhartid: 0,
|
||||
mconfigptr: 0
|
||||
};
|
||||
|
||||
MachineStatusIfc#(xlen) mstatus <- mkMachineStatus(cfg);
|
||||
/*
|
||||
ReadOnly#(Bit#(xlen)) mcycle <- mkReadOnly(truncate(cycleCounter));
|
||||
ReadOnly#(Bit#(xlen)) mtimer <- mkReadOnly(truncate(timeCounter));
|
||||
ReadOnly#(Bit#(xlen)) minstret <- mkReadOnly(truncate(retiredCounter));
|
||||
*/
|
||||
|
||||
/*
|
||||
if (valueof(xlen) == 32) begin
|
||||
ReadOnly#(Bit#(xlen)) mcycleh <- mkReadOnly(truncateLSB(cycleCounter));
|
||||
ReadOnly#(Bit#(xlen)) mtimeh <- mkReadOnly(truncateLSB(timeCounter));
|
||||
ReadOnly#(Bit#(xlen)) minstreth <- mkReadOnly(truncateLSB(retiredCounter));
|
||||
end
|
||||
*/
|
||||
Reg#(Bit#(xlen)) mcause <- mkReg(0);
|
||||
Reg#(Bit#(xlen)) mtvec <- mkReg('hC0DEC0DE);
|
||||
Reg#(Bit#(xlen)) mepc <- mkReg(0);
|
||||
Reg#(Bit#(xlen)) mscratch <- mkReg(0);
|
||||
Reg#(Bit#(xlen)) mip <- mkReg(0);
|
||||
Reg#(Bit#(xlen)) mie <- mkReg(0);
|
||||
Reg#(Bit#(xlen)) mtval <- mkReg(0);
|
||||
Reg#(Bit#(xlen)) mideleg <- mkReg(0);
|
||||
Reg#(Bit#(xlen)) medeleg <- mkReg(0);
|
||||
|
||||
Reg#(Bit#(xlen)) sideleg <- mkReg(0);
|
||||
Reg#(Bit#(xlen)) sedeleg <- mkReg(0);
|
||||
|
||||
function Bool isWARLIgnore(RVCsrIndex index);
|
||||
Bool result = False;
|
||||
if ((index >= csr_PMPADDR0 && index <= csr_PMPADDR63) ||
|
||||
(index >= csr_PMPCFG0 && index <= csr_PMPCFG15) ||
|
||||
index == csr_SATP ||
|
||||
index == csr_MIDELEG ||
|
||||
index == csr_MEDELEG) begin
|
||||
result = True;
|
||||
end
|
||||
|
||||
return result;
|
||||
endfunction
|
||||
|
||||
function RVCsrIndex getIndex(RVPrivilegeLevel privilege_level, RVCsrIndexOffset offset);
|
||||
RVCsrIndex index = 0;
|
||||
index[9:8] = privilege_level[1:0];
|
||||
index[7:0] = offset;
|
||||
return index;
|
||||
endfunction
|
||||
|
||||
// Based on fv_new_priv_on_exception from Flute processor.
|
||||
function RVPrivilegeLevel getTrapPrivilegeLevel(Trap#(xlen) trap);
|
||||
let trap_privilege_level = priv_MACHINE;
|
||||
|
||||
if (currentPriv < priv_MACHINE) begin
|
||||
if (cfg.s_mode_supported) begin // S mode supported?
|
||||
// See if this trap should be delegated to SUPERVISOR mode
|
||||
let delegated = (trap.isInterrupt ?
|
||||
(mideleg[trap.cause] == 0 ? False : True) :
|
||||
(medeleg[trap.cause] == 0 ? False : True));
|
||||
|
||||
if (delegated) begin
|
||||
trap_privilege_level = priv_SUPERVISOR;
|
||||
|
||||
// If the current priv mode is U, and user mode traps are supported,
|
||||
// then consult sedeleg/sideleg to determine if delegated to USER mode.
|
||||
if (currentPriv == priv_USER && cfg.u_level_interrupts_supported) begin
|
||||
delegated = (trap.isInterrupt ?
|
||||
(sideleg[trap.cause] == 0 ? False : True) :
|
||||
(sedeleg[trap.cause] == 0 ? False : True));
|
||||
|
||||
if (delegated) begin
|
||||
trap_privilege_level = priv_USER;
|
||||
end
|
||||
end
|
||||
end
|
||||
end else begin // S mode *NOT* supported
|
||||
// If user mode traps are supported, then consult sedeleg/sideleg to determine
|
||||
// if delegated to USER mode.
|
||||
if (cfg.u_level_interrupts_supported) begin
|
||||
let delegated = (trap.isInterrupt ?
|
||||
(mideleg[trap.cause] == 0 ? False : True) :
|
||||
(medeleg[trap.cause] == 0 ? False : True));
|
||||
|
||||
if (delegated) begin
|
||||
trap_privilege_level = priv_USER;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return trap_privilege_level;
|
||||
endfunction
|
||||
|
||||
//
|
||||
// readInternal
|
||||
//
|
||||
function ActionValue#(CsrReadResult#(xlen)) readInternal(RVCsrIndex index);
|
||||
actionvalue
|
||||
let result = CsrReadResult {
|
||||
value: 0,
|
||||
denied: False
|
||||
};
|
||||
|
||||
if (!isWARLIgnore(index)) begin
|
||||
case(index)
|
||||
// Machine Information Registers (MRO)
|
||||
/*
|
||||
csr_MVENDORID: result.value = extend(machineInfoCfg.mvendorid);
|
||||
*/
|
||||
csr_MARCHID: result.value = machineInfoCfg.marchid;
|
||||
csr_MIMPID: result.value = machineInfoCfg.mimpid;
|
||||
csr_MHARTID: result.value = machineInfoCfg.mhartid;
|
||||
|
||||
csr_MISA: result.value = pack(cfg);
|
||||
|
||||
csr_MCAUSE: result.value = mcause;
|
||||
csr_MTVEC: result.value = mtvec;
|
||||
csr_MEPC: result.value = mepc;
|
||||
csr_MTVAL: result.value = mtval;
|
||||
csr_MIDELEG: result.value = mideleg;
|
||||
csr_MEDELEG: result.value = medeleg;
|
||||
|
||||
csr_MSTATUS: begin
|
||||
let mstatus_ <- mstatus.getMachineStatus.get;
|
||||
result.value = pack(mstatus_);
|
||||
end
|
||||
/*
|
||||
csr_MCYCLE, csr_CYCLE: begin
|
||||
result.value = mcycle;
|
||||
end
|
||||
*/
|
||||
csr_MSCRATCH: result.value = mscratch;
|
||||
csr_MIP: result.value = mip;
|
||||
csr_MIE: result.value = mie;
|
||||
|
||||
// !bugbug - TSELECT is hardcoded to all 1s. This is to keep
|
||||
// the ISA debug test happy. It *should* report a
|
||||
// pass if reading TSELECT failed with a trap (to reflect what's in the spec)
|
||||
// This is a bug in the debug test.
|
||||
csr_TSELECT: result.value = 'hFFFF_FFFF;
|
||||
default: begin
|
||||
result.denied = True;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
$display("---- Csr Read Index : ", fshow(index));
|
||||
$display("---- Csr Read Result: ", fshow(result));
|
||||
return result;
|
||||
endactionvalue
|
||||
endfunction
|
||||
|
||||
//
|
||||
// writeInternal
|
||||
//
|
||||
function ActionValue#(CsrWriteResult) writeInternal(RVCsrIndex index, Bit#(xlen) value);
|
||||
actionvalue
|
||||
let result = CsrWriteResult {
|
||||
denied: False
|
||||
};
|
||||
|
||||
// Access and write to read-only Csr check.
|
||||
if (!isWARLIgnore(index)) begin
|
||||
case(index)
|
||||
csr_MCAUSE: mcause <= value;
|
||||
csr_MCYCLE: cycleCounter <= zeroExtend(value);
|
||||
csr_MEPC: mepc <= value;
|
||||
csr_MISA: begin
|
||||
// No-Op
|
||||
end
|
||||
csr_MSCRATCH: mscratch <= value;
|
||||
csr_MSTATUS: mstatus.unpack(value);
|
||||
csr_MTVAL: mtval <= value;
|
||||
csr_MTVEC: mtvec <= value;
|
||||
csr_MIE: mie <= value;
|
||||
csr_MIP: mip <= value;
|
||||
csr_TSELECT: begin
|
||||
// No-Op
|
||||
end
|
||||
default: result.denied = True;
|
||||
endcase
|
||||
end
|
||||
|
||||
$display("---- Csr Write Index : ", fshow(index));
|
||||
$display("---- Csr Write Value : ", value);
|
||||
$display("---- Csr Write Result: ", fshow(result));
|
||||
|
||||
return result;
|
||||
endactionvalue
|
||||
endfunction
|
||||
|
||||
function ActionValue#(CsrReadResult#(xlen)) readWithOffset1(RVPrivilegeLevel privilegeLevel, RVCsrIndexOffset offset);
|
||||
actionvalue
|
||||
let csrReadResult <- readInternal(getIndex(privilegeLevel, offset));
|
||||
return csrReadResult;
|
||||
endactionvalue
|
||||
endfunction
|
||||
|
||||
function ActionValue#(CsrWriteResult) writeWithOffset1(RVPrivilegeLevel privilegeLevel, RVCsrIndexOffset offset, Bit#(xlen) value);
|
||||
actionvalue
|
||||
let csrWriteResult <- writeInternal(getIndex(privilegeLevel, offset), value);
|
||||
return csrWriteResult;
|
||||
endactionvalue
|
||||
endfunction
|
||||
|
||||
method Action incrementCycleCounters;
|
||||
cycleCounter.incr(1);
|
||||
timeCounter.incr(1);
|
||||
endmethod
|
||||
|
||||
method Action incrementInstructionsRetiredCounter;
|
||||
retiredCounter.incr(1);
|
||||
endmethod
|
||||
|
||||
//
|
||||
// CsrReadport
|
||||
//
|
||||
interface CsrReadPort csrReadPort;
|
||||
method ActionValue#(CsrReadResult#(xlen)) read(RVCsrIndex index);
|
||||
let result = CsrReadResult {
|
||||
value: 0,
|
||||
denied: True
|
||||
};
|
||||
|
||||
if (currentPriv >= index[9:8]) begin
|
||||
result <- readInternal(index);
|
||||
end
|
||||
|
||||
return result;
|
||||
endmethod
|
||||
endinterface
|
||||
|
||||
//
|
||||
// CsrWritePort
|
||||
//
|
||||
interface CsrWritePort csrWritePort;
|
||||
method ActionValue#(CsrWriteResult) write(RVCsrIndex index, Bit#(xlen) value);
|
||||
let result = CsrWriteResult {
|
||||
denied: True
|
||||
};
|
||||
|
||||
if (currentPriv >= index[9:8] && index[11:10] != 'b11) begin
|
||||
result <- writeInternal(index, value);
|
||||
end
|
||||
|
||||
return result;
|
||||
endmethod
|
||||
endinterface
|
||||
|
||||
//
|
||||
// CsrWritePermission
|
||||
//
|
||||
interface CsrWritePermission csrWritePermission;
|
||||
method Bool isWriteable(RVCsrIndex index);
|
||||
return (currentPriv >= index[9:8] && index[11:10] != 'b11);
|
||||
endmethod
|
||||
endinterface
|
||||
|
||||
//
|
||||
// trapController
|
||||
//
|
||||
interface TrapController trapController;
|
||||
method ActionValue#(Bit#(xlen)) beginTrap(Bit#(xlen) trapProgramCounter, Trap#(xlen) trap);
|
||||
Bit#(xlen) cause = 0;
|
||||
|
||||
let trapPrivilegeLevel = getTrapPrivilegeLevel(trap);
|
||||
/*
|
||||
cause = zeroExtend(trap.cause);
|
||||
if (!trap.isInterrupt) begin
|
||||
cause[valueOf(xlen)-1] = 1;
|
||||
end
|
||||
*/
|
||||
// PC => MEPC
|
||||
writeWithOffset1(trapPrivilegeLevel, csr_EPC, trapProgramCounter);
|
||||
|
||||
// CurPriv => MSTATUS::MPP
|
||||
let mstatus_ <- mstatus.getMachineStatus.get;
|
||||
mstatus_.mpp = currentPriv;
|
||||
|
||||
// MSTATUS::MIE => MSTATUS::MPIE
|
||||
mstatus_.mpie = mstatus_.mie;
|
||||
mstatus_.mie = False; // Disable interrupts
|
||||
mstatus.putMachineStatus.put(mstatus_);
|
||||
|
||||
// cause => CAUSE
|
||||
writeWithOffset1(trapPrivilegeLevel, csr_CAUSE, cause);
|
||||
writeWithOffset1(trapPrivilegeLevel, csr_TVAL, trap.tval);
|
||||
|
||||
let readResult <- readWithOffset1(trapPrivilegeLevel, csr_TVEC);
|
||||
Bit#(xlen) vectorTableBase = readResult.value;
|
||||
let trapHandler = vectorTableBase;
|
||||
|
||||
// Check and handle a vectored trap handler table
|
||||
/*
|
||||
if (trapHandler[1:0] == 1) begin
|
||||
trapHandler[1:0] = 0;
|
||||
if(trap.isInterrupt) begin
|
||||
trapHandler = trapHandler + extend(4 * trap.cause);
|
||||
end
|
||||
end
|
||||
*/
|
||||
currentPriv <= trapPrivilegeLevel;
|
||||
|
||||
return trapHandler;
|
||||
endmethod
|
||||
|
||||
method ActionValue#(Bit#(xlen)) endTrap;
|
||||
Bit#(xlen) newProgramCounter = 'hDEADDEAD;
|
||||
|
||||
let readStatus <- readWithOffset1(currentPriv, csr_STATUS);
|
||||
if (readStatus.denied == False) begin
|
||||
/*
|
||||
MachineStatus#(xlen) mstatus = unpack(readStatus.value);
|
||||
let newPrivilegeLevel = mstatus.mpp;
|
||||
mstatus.mie = mstatus.mpie;
|
||||
mstatus.mpie = False;
|
||||
*/
|
||||
// Attempt to update MSTATUS. The current privilege level may prevent this.
|
||||
/*
|
||||
let writeStatus <- writeInternal(csr_MSTATUS, pack(mstatus));
|
||||
if (writeStatus.denied == False) begin
|
||||
currentPriv <= newPrivilegeLevel;
|
||||
readStatus <- readWithOffset1(currentPriv, csr_EPC);
|
||||
if (readStatus.denied == False) begin
|
||||
newProgramCounter = readStatus.value;
|
||||
end
|
||||
end
|
||||
*/
|
||||
end
|
||||
return newProgramCounter;
|
||||
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
|
||||
9
src/Cpu/CSRs/MachineInformation.bsv
Normal file
9
src/Cpu/CSRs/MachineInformation.bsv
Normal file
@ -0,0 +1,9 @@
|
||||
export MachineInformationCfg(..);
|
||||
|
||||
typedef struct {
|
||||
Bit#(32) mvendorid;
|
||||
Bit#(xlen) marchid;
|
||||
Bit#(xlen) mimpid;
|
||||
Bit#(xlen) mhartid;
|
||||
Bit#(xlen) mconfigptr;
|
||||
} MachineInformationCfg#(numeric type xlen);
|
||||
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
|
||||
179
src/Cpu/CSRs/MachineStatus.bsv
Normal file
179
src/Cpu/CSRs/MachineStatus.bsv
Normal file
@ -0,0 +1,179 @@
|
||||
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;
|
||||
|
||||
instance DefaultValue#(MachineStatus);
|
||||
defaultValue = MachineStatus {
|
||||
sie: False,
|
||||
mie: False,
|
||||
spie: False,
|
||||
ube: False,
|
||||
mpie: False,
|
||||
spp: False,
|
||||
vs: fsvs_OFF,
|
||||
mpp: priv_MACHINE,
|
||||
fs: fsvs_OFF,
|
||||
xs: xs_ALL_OFF,
|
||||
mprv: False,
|
||||
sum: False,
|
||||
mxr: False,
|
||||
tvm: False,
|
||||
tw: False,
|
||||
tsr: False,
|
||||
|
||||
uxl: xlen_64,
|
||||
sxl: xlen_64,
|
||||
|
||||
sbe: False,
|
||||
mbe: False
|
||||
};
|
||||
endinstance
|
||||
|
||||
instance Bits#(MachineStatus, 32);
|
||||
function Bit#(32) pack(MachineStatus 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 unpack(Bit#(32) value);
|
||||
return defaultValue;
|
||||
endfunction
|
||||
endinstance
|
||||
|
||||
instance Bits#(MachineStatus, 64);
|
||||
function Bit#(64) pack(MachineStatus mstatus);
|
||||
Bit#(1) sd = ((mstatus.vs | mstatus.fs | mstatus.xs) == 0 ? 0 : 1);
|
||||
return {
|
||||
sd,
|
||||
25'b0,
|
||||
pack(mstatus.mbe),
|
||||
pack(mstatus.sbe),
|
||||
pack(mstatus.sxl),
|
||||
pack(mstatus.uxl),
|
||||
9'b0,
|
||||
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 unpack(Bit#(64) value);
|
||||
return defaultValue;
|
||||
endfunction
|
||||
endinstance
|
||||
|
||||
interface MachineStatus_Ifc;
|
||||
interface Get#(MachineStatus) getMachineStatus;
|
||||
interface Put#(MachineStatus) putMachineStatus;
|
||||
endinterface
|
||||
|
||||
module mkMachineStatus#(IsaCfg#(xlen) cfg)(MachineStatus_Ifc);
|
||||
Reg#(MachineStatus) mstatus <- mkReg(defaultValue);
|
||||
|
||||
interface Get getMachineStatus = toGet(mstatus);
|
||||
interface Put putMachineStatus;
|
||||
method Action put(MachineStatus value);
|
||||
//
|
||||
// Only MPP, MIE, and MIE are writable.
|
||||
//
|
||||
MachineStatus mstatus_ = mstatus;
|
||||
|
||||
if (cfg.extS) begin
|
||||
mstatus_.mpp = value.mpp;
|
||||
end else begin
|
||||
// Supervisor mode not supported, ensure only USER and MACHINE
|
||||
// mode are set in MPP.
|
||||
RVPrivilegeLevel requestedMPP = value.mpp;
|
||||
if (requestedMPP == priv_USER || requestedMPP == priv_MACHINE) begin
|
||||
mstatus_.mpp = requestedMPP;
|
||||
end
|
||||
end
|
||||
|
||||
mstatus_.mpie = value.mpie;
|
||||
mstatus_.mie = value.mie;
|
||||
|
||||
mstatus <= mstatus_;
|
||||
endmethod
|
||||
endinterface
|
||||
endmodule
|
||||
17
src/Cpu/Caches.bsv
Normal file
17
src/Cpu/Caches.bsv
Normal file
@ -0,0 +1,17 @@
|
||||
typedef struct {
|
||||
Bit#(xlen) requestAddress;
|
||||
} ICacheRequest#(numeric type xlen) deriving(Bits);
|
||||
|
||||
typedef struct {
|
||||
// data - data bytes returned from cache
|
||||
Bit#(TMul#(fetchByteCount,8)) data;
|
||||
// replay - if true, cache requests replay request.
|
||||
Bool replay;
|
||||
// access exception - if true, the request caused an access exception.
|
||||
Bool accessException;
|
||||
} ICacheResponse#(numeric type fetchByteCount) deriving(Bits);
|
||||
|
||||
typedef struct {
|
||||
Bit#(xlen) requestAddress;
|
||||
Bool write;
|
||||
} DCacheRequest#(numeric type xlen) deriving(Bits);
|
||||
1
src/Cpu/Common.bsv
Normal file
1
src/Cpu/Common.bsv
Normal file
@ -0,0 +1 @@
|
||||
//!submodule CSRs
|
||||
@ -1,23 +1,86 @@
|
||||
import ALU::*;
|
||||
//!submodule CSRs
|
||||
import FIFO::*;
|
||||
import GetPut::*;
|
||||
import StmtFSM::*;
|
||||
|
||||
import Caches::*;
|
||||
import GprFile::*;
|
||||
import PipelineRegisters::*;
|
||||
|
||||
export CpuCfg(..), CpuIfc, mkCpu;
|
||||
|
||||
//
|
||||
// CpuConfig
|
||||
//
|
||||
typedef struct {
|
||||
} CpuCfg#(numeric type xlen);
|
||||
Bit#(xlen) initial_program_counter;
|
||||
} CpuCfg#(numeric type xlen, numeric type icacheFetchByteCount);
|
||||
|
||||
//
|
||||
// CpuIfc
|
||||
//
|
||||
interface CpuIfc#(type cfg);
|
||||
interface CpuIfc#(numeric type xlen, numeric type icacheFetchByteCount);
|
||||
interface Get#(ICacheRequest#(xlen)) getCacheRequest;
|
||||
interface Put#(ICacheResponse#(icacheFetchByteCount)) putCacheResponse;
|
||||
endinterface
|
||||
|
||||
//
|
||||
// State
|
||||
//
|
||||
typedef enum {
|
||||
RESET,
|
||||
INITIALIZING,
|
||||
FETCH,
|
||||
DECODE,
|
||||
EXECUTE,
|
||||
MEMORY_ACCESS,
|
||||
WRITEBACK
|
||||
} State deriving(Bits, Eq, FShow);
|
||||
|
||||
//
|
||||
// mkCpu()
|
||||
//
|
||||
module mkCpu#(CpuCfg#(xlen) cfg)(CpuIfc#(cfg));
|
||||
AluCfg#(xlen) alu_cfg = AluCfg {};
|
||||
let alu <- mkAlu(alu_cfg);
|
||||
endmodule
|
||||
module mkCpu#(CpuCfg#(xlen, icacheFetchByteCount) cfg)(CpuIfc#(xlen, icacheFetchByteCount));
|
||||
// Cache FIFOs
|
||||
FIFO#(ICacheRequest#(xlen)) icacheRequests <- mkFIFO;
|
||||
FIFO#(ICacheResponse#(icacheFetchByteCount)) icacheResponses <- mkFIFO;
|
||||
|
||||
export CpuCfg(..), CpuIfc, mkCpu;
|
||||
// State
|
||||
Reg#(State) state <- mkReg(RESET);
|
||||
|
||||
// Pipeline registers
|
||||
Reg#(Bit#(xlen)) pc <- mkReg(cfg.initial_program_counter);
|
||||
Reg#(IF_ID#(xlen)) if_id <- mkReg(defaultValue);
|
||||
Reg#(ID_EX#(xlen)) id_ex <- mkReg(defaultValue);
|
||||
Reg#(EX_MEM#(xlen)) ex_mem <- mkReg(defaultValue);
|
||||
Reg#(MEM_WB#(xlen)) mem_wb <- mkReg(defaultValue);
|
||||
Reg#(WB_OUT#(xlen)) wb_out <- mkReg(defaultValue);
|
||||
|
||||
// General purpose register (GPR) file
|
||||
GprFileCfg#(xlen) gpr_cfg = GprFileCfg {};
|
||||
GprFile#(xlen) gpr <- mkGprFile(gpr_cfg);
|
||||
|
||||
//
|
||||
// INITIALIZATION
|
||||
//
|
||||
Reg#(Bit#(10)) gprInitIndex <- mkRegU;
|
||||
Stmt initializationStatements = (seq
|
||||
//
|
||||
// Zero the GPRs
|
||||
//
|
||||
for (gprInitIndex <= 0; gprInitIndex <= 32; gprInitIndex <= gprInitIndex + 1)
|
||||
gpr.gprWritePort.write(truncate(gprInitIndex), 0);
|
||||
|
||||
state <= FETCH;
|
||||
endseq);
|
||||
|
||||
FSM initializationMachine <- mkFSMWithPred(initializationStatements, state == INITIALIZING);
|
||||
|
||||
rule initialization(state == RESET);
|
||||
state <= INITIALIZING;
|
||||
initializationMachine.start;
|
||||
endrule
|
||||
|
||||
interface getCacheRequest = toGet(icacheRequests);
|
||||
interface putCacheResponse = toPut(icacheResponses);
|
||||
endmodule
|
||||
|
||||
101
src/Cpu/FetchStage.bsv
Normal file
101
src/Cpu/FetchStage.bsv
Normal file
@ -0,0 +1,101 @@
|
||||
import IsaCfg::*;
|
||||
import MemoryTypes::*;
|
||||
import PipelineRegisters::*;
|
||||
import RV_ISA::*;
|
||||
import Trap::*;
|
||||
|
||||
import ClientServer::*;
|
||||
import FIFOF::*;
|
||||
import GetPut::*;
|
||||
import Memory::*;
|
||||
import RWire::*;
|
||||
|
||||
typedef struct {
|
||||
} FetchStage_Cfg#(numeric type xlen);
|
||||
|
||||
interface FetchStage_Ifc#(numeric type xlen);
|
||||
interface Put#(PC_IF#(xlen)) putPC_IF;
|
||||
interface Get#(IF_ID#(xlen)) getIF_ID;
|
||||
|
||||
interface ReadOnlyMemoryClient#(xlen, 32) memoryClient;
|
||||
endinterface
|
||||
|
||||
module mkFetchStage#(FetchStage_Cfg#(xlen) cfg)(FetchStage_Ifc#(xlen));
|
||||
Wire#(PC_IF#(xlen)) pc_if <- mkWire;
|
||||
Wire#(IF_ID#(xlen)) if_id <- mkWire;
|
||||
|
||||
// Memory request output
|
||||
Reg#(Bool) memoryRequestInFlight <- mkReg(False);
|
||||
Wire#(ReadOnlyMemoryRequest#(xlen)) memoryRequest <- mkWire;
|
||||
|
||||
// Memory response input (FIFO)
|
||||
FIFOF#(ReadOnlyMemoryResponse#(32)) memoryResponses <- mkFIFOF;
|
||||
|
||||
function IF_ID#(xlen) processMemoryResponse(ReadOnlyMemoryResponse#(32) response);
|
||||
IF_ID#(xlen) if_id_ = defaultValue;
|
||||
if_id_.common.pc = pc_if.common.pc;
|
||||
if_id_.common.isBubble = False;
|
||||
|
||||
if (!response.accessFault) begin
|
||||
if_id_.common.ir = response.data;
|
||||
if_id_.common.trap = tagged Invalid;
|
||||
end else begin
|
||||
Trap#(xlen) trap = Trap {
|
||||
cause: exception_INSTRUCTION_ACCESS_FAULT,
|
||||
isInterrupt: False,
|
||||
tval: 0
|
||||
};
|
||||
|
||||
if_id_.common.trap = tagged Valid(trap);
|
||||
end
|
||||
return if_id_;
|
||||
endfunction
|
||||
|
||||
rule fetch;
|
||||
IF_ID#(xlen) if_id_ = defaultValue;
|
||||
if_id_.common.pc = pc_if.common.pc;
|
||||
if_id_.common.isBubble = True;
|
||||
|
||||
if (!pc_if.common.isBubble) begin
|
||||
// If there's an active request, handle it if it's returned
|
||||
if (memoryRequestInFlight) begin
|
||||
if (memoryResponses.notEmpty) begin
|
||||
if_id_ = processMemoryResponse(memoryResponses.first);
|
||||
memoryResponses.deq;
|
||||
memoryRequestInFlight <= False;
|
||||
end else begin
|
||||
// Memory request is in flight but hasn't returned yet.
|
||||
end
|
||||
end else begin
|
||||
// No memory request is in flight...
|
||||
|
||||
// Check for a misaligned request
|
||||
if (pc_if.common.pc[1:0] != 0) begin
|
||||
// Address request was misaligned...
|
||||
Trap#(xlen) trap = Trap {
|
||||
cause: exception_INSTRUCTION_ADDRESS_MISALIGNED,
|
||||
isInterrupt: False,
|
||||
tval: 0
|
||||
};
|
||||
if_id_.common.trap = tagged Valid(trap);
|
||||
if_id_.common.isBubble = False;
|
||||
end else begin
|
||||
// Construct a memory request and send it out.
|
||||
ReadOnlyMemoryRequest#(xlen) request = ReadOnlyMemoryRequest {
|
||||
address: pc_if.common.pc
|
||||
};
|
||||
memoryRequest <= request;
|
||||
memoryRequestInFlight <= True;
|
||||
|
||||
if_id_.common.isBubble = True;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if_id <= if_id_;
|
||||
endrule
|
||||
|
||||
interface Put putPC_IF = toPut(asIfc(pc_if));
|
||||
interface Get getIF_ID = toGet(if_id);
|
||||
interface ReadOnlyMemoryClient memoryClient = toGPClient(memoryRequest, memoryResponses);
|
||||
endmodule
|
||||
35
src/Cpu/FetchStage_tb.bsv
Normal file
35
src/Cpu/FetchStage_tb.bsv
Normal file
@ -0,0 +1,35 @@
|
||||
import FetchStage::*;
|
||||
import IsaCfg::*;
|
||||
import PipelineRegisters::*;
|
||||
|
||||
import Connectable::*;
|
||||
import GetPut::*;
|
||||
|
||||
module mkTopModule(Empty);
|
||||
// 32 bit
|
||||
FetchStage_Cfg#(32) fetchStageConfig32 = FetchStage_Cfg{};
|
||||
FetchStage_Ifc#(32) fetchStage32 <- mkFetchStage(fetchStageConfig32);
|
||||
|
||||
Wire#(PC_IF#(32)) pc_if32 <- mkWire;
|
||||
Wire#(IF_ID#(32)) if_id32 <- mkWire;
|
||||
|
||||
mkConnection(toGet(pc_if32), fetchStage32.putPC_IF);
|
||||
mkConnection(fetchStage32.getIF_ID, toPut(asIfc(if_id32)));
|
||||
|
||||
// 64 bit
|
||||
FetchStage_Cfg#(64) fetchStageConfig64 = FetchStage_Cfg{};
|
||||
FetchStage_Ifc#(64) fetchStage64 <- mkFetchStage(fetchStageConfig64);
|
||||
|
||||
Wire#(PC_IF#(64)) pc_if64 <- mkWire;
|
||||
Wire#(IF_ID#(64)) if_id64 <- mkWire;
|
||||
|
||||
mkConnection(toGet(pc_if64), fetchStage64.putPC_IF);
|
||||
mkConnection(fetchStage64.getIF_ID, toPut(asIfc(if_id64)));
|
||||
|
||||
rule test;
|
||||
//pc_if32 <= defaultValue;
|
||||
|
||||
$display(">>>PASS");
|
||||
$finish();
|
||||
endrule
|
||||
endmodule
|
||||
47
src/Cpu/GprFile.bsv
Normal file
47
src/Cpu/GprFile.bsv
Normal file
@ -0,0 +1,47 @@
|
||||
import ClientServer::*;
|
||||
import GetPut::*;
|
||||
import Vector::*;
|
||||
|
||||
typedef Bit#(5) GprIndex;
|
||||
|
||||
interface GprReadPort#(numeric type xlen);
|
||||
method Bit#(xlen) read(GprIndex index);
|
||||
endinterface
|
||||
|
||||
interface GprWritePort#(numeric type xlen);
|
||||
method Action write(GprIndex index, Bit#(xlen) value);
|
||||
endinterface
|
||||
|
||||
interface GprFile#(numeric type xlen);
|
||||
interface GprReadPort#(xlen) gprReadPort1;
|
||||
interface GprReadPort#(xlen) gprReadPort2;
|
||||
|
||||
interface GprWritePort#(xlen) gprWritePort;
|
||||
endinterface
|
||||
|
||||
typedef struct {
|
||||
} GprFileCfg#(numeric type xlen);
|
||||
|
||||
module mkGprFile#(GprFileCfg#(xlen) cfg)(GprFile#(xlen));
|
||||
Vector#(32, Reg#(Bit#(xlen))) reg_file <- replicateM(mkReg(0));
|
||||
|
||||
interface GprReadPort gprReadPort1;
|
||||
method Bit#(xlen) read(GprIndex index);
|
||||
return reg_file[index];
|
||||
endmethod
|
||||
endinterface
|
||||
|
||||
interface GprReadPort gprReadPort2;
|
||||
method Bit#(xlen) read(GprIndex index);
|
||||
return reg_file[index];
|
||||
endmethod
|
||||
endinterface
|
||||
|
||||
interface GprWritePort gprWritePort;
|
||||
method Action write(GprIndex index, Bit#(xlen) value);
|
||||
if (index != 0) begin
|
||||
reg_file[index] <= value;
|
||||
end
|
||||
endmethod
|
||||
endinterface
|
||||
endmodule
|
||||
105
src/Cpu/IsaCfg.bsv
Normal file
105
src/Cpu/IsaCfg.bsv
Normal file
@ -0,0 +1,105 @@
|
||||
typedef struct {
|
||||
// userLevelInterruptsSupported - N extension
|
||||
Bool extN;
|
||||
|
||||
// supervisorModeSupported - S extension
|
||||
Bool extS;
|
||||
|
||||
// userModeSupported - U extension
|
||||
Bool extU;
|
||||
} IsaCfg#(numeric type xlen);
|
||||
|
||||
typedef Bit#(2) MXL;
|
||||
MXL mxl_32bit = 2'b01;
|
||||
MXL mxl_64bit = 2'b10;
|
||||
MXL mxl_128bit = 2'b11;
|
||||
|
||||
instance DefaultValue#(IsaCfg#(xlen));
|
||||
defaultValue = IsaCfg {
|
||||
extN: False,
|
||||
extS: False,
|
||||
extU: False
|
||||
};
|
||||
endinstance
|
||||
|
||||
// Bits#() instance - serializing to Bit#() creates a MISA register compatible bit pattern.
|
||||
instance Bits#(IsaCfg#(64), 64);
|
||||
function Bit#(64) pack(IsaCfg#(64) misa);
|
||||
MXL mxl = mxl_64bit;
|
||||
return {
|
||||
mxl,
|
||||
36'b0,
|
||||
1'b0, // pack(misa.extZ),
|
||||
1'b0, // pack(misa.extY),
|
||||
1'b0, // pack(misa.extX),
|
||||
1'b0, // pack(misa.extW),
|
||||
1'b0, // pack(misa.extV),
|
||||
pack(misa.extU),
|
||||
1'b0, // pack(misa.extT),
|
||||
pack(misa.extS),
|
||||
1'b0, // pack(misa.extR),
|
||||
1'b0, // pack(misa.extQ),
|
||||
1'b0, // pack(misa.extP),
|
||||
1'b0, // pack(misa.extO),
|
||||
pack(misa.extN),
|
||||
1'b0, // pack(misa.extM),
|
||||
1'b0, // pack(misa.extL),
|
||||
1'b0, // pack(misa.extK),
|
||||
1'b0, // pack(misa.extJ),
|
||||
1'b1, // pack(misa.extI), // Always 1 to indicate RV32I, RV64I, RV128I
|
||||
1'b0, // pack(misa.extH),
|
||||
1'b0, // pack(misa.extH),
|
||||
1'b0, // pack(misa.extF),
|
||||
1'b0, // pack(misa.extE),
|
||||
1'b0, // pack(misa.extD),
|
||||
1'b0, // pack(misa.extC),
|
||||
1'b0, // pack(misa.extB),
|
||||
1'b0 // pack(misa.extA)
|
||||
};
|
||||
endfunction
|
||||
|
||||
function IsaCfg#(64) unpack(Bit#(64) value);
|
||||
return defaultValue;
|
||||
endfunction
|
||||
endinstance
|
||||
|
||||
// Bits#() instance - serializing to Bit#() creates a MISA register compatible bit pattern.
|
||||
instance Bits#(IsaCfg#(32), 32);
|
||||
function Bit#(32) pack(IsaCfg#(32) misa);
|
||||
MXL mxl = mxl_32bit;
|
||||
return {
|
||||
mxl,
|
||||
4'b0,
|
||||
1'b0, // pack(misa.extZ),
|
||||
1'b0, // pack(misa.extY),
|
||||
1'b0, // pack(misa.extX),
|
||||
1'b0, // pack(misa.extW),
|
||||
1'b0, // pack(misa.extV),
|
||||
pack(misa.extU),
|
||||
1'b0, // pack(misa.extT),
|
||||
pack(misa.extS),
|
||||
1'b0, // pack(misa.extR),
|
||||
1'b0, // pack(misa.extQ),
|
||||
1'b0, // pack(misa.extP),
|
||||
1'b0, // pack(misa.extO),
|
||||
pack(misa.extN),
|
||||
1'b0, // pack(misa.extM),
|
||||
1'b0, // pack(misa.extL),
|
||||
1'b0, // pack(misa.extK),
|
||||
1'b0, // pack(misa.extJ),
|
||||
1'b1, // pack(misa.extI), // Always 1 to indicate RV32I, RV64I, RV128I
|
||||
1'b0, // pack(misa.extH),
|
||||
1'b0, // pack(misa.extH),
|
||||
1'b0, // pack(misa.extF),
|
||||
1'b0, // pack(misa.extE),
|
||||
1'b0, // pack(misa.extD),
|
||||
1'b0, // pack(misa.extC),
|
||||
1'b0, // pack(misa.extB),
|
||||
1'b0 // pack(misa.extA)
|
||||
};
|
||||
endfunction
|
||||
|
||||
function IsaCfg#(32) unpack(Bit#(32) value);
|
||||
return defaultValue;
|
||||
endfunction
|
||||
endinstance
|
||||
129
src/Cpu/PipelineRegisters.bsv
Normal file
129
src/Cpu/PipelineRegisters.bsv
Normal file
@ -0,0 +1,129 @@
|
||||
import Trap::*;
|
||||
import DefaultValue::*;
|
||||
|
||||
//
|
||||
// PipelineRegisterCommon
|
||||
//
|
||||
typedef struct {
|
||||
Bit#(32) ir;
|
||||
Bit#(xlen) pc;
|
||||
Bool isBubble;
|
||||
Maybe#(Trap#(xlen)) trap;
|
||||
} PipelineRegisterCommon#(numeric type xlen) deriving(Bits, Eq, FShow);
|
||||
|
||||
instance DefaultValue #(PipelineRegisterCommon#(xlen));
|
||||
defaultValue = PipelineRegisterCommon {
|
||||
ir: 32'b0000000_00000_00000_000_00000_0110011, // ADD x0, x0, x0
|
||||
pc: 'hf000c0de,
|
||||
isBubble: True,
|
||||
trap: tagged Invalid
|
||||
};
|
||||
endinstance
|
||||
|
||||
//
|
||||
// PC_IF
|
||||
//
|
||||
typedef struct {
|
||||
PipelineRegisterCommon#(xlen) common;
|
||||
} PC_IF#(numeric type xlen) deriving(Bits, Eq, FShow);
|
||||
|
||||
instance DefaultValue #(PC_IF#(xlen));
|
||||
defaultValue = PC_IF {
|
||||
common: defaultValue
|
||||
};
|
||||
endinstance
|
||||
|
||||
//
|
||||
// IF_ID
|
||||
//
|
||||
typedef struct {
|
||||
PipelineRegisterCommon#(xlen) common;
|
||||
Bit#(1) epoch;
|
||||
Bit#(xlen) npc; // Next program counter
|
||||
} IF_ID#(numeric type xlen) deriving(Bits, Eq, FShow);
|
||||
|
||||
instance DefaultValue #(IF_ID#(xlen));
|
||||
defaultValue = IF_ID {
|
||||
common: defaultValue,
|
||||
epoch: 0,
|
||||
npc: 'hbeefbeef
|
||||
};
|
||||
endinstance
|
||||
|
||||
//
|
||||
// ID_EX
|
||||
//
|
||||
typedef struct {
|
||||
PipelineRegisterCommon#(xlen) common;
|
||||
Bit#(1) epoch;
|
||||
Bit#(xlen) npc; // Next program counter
|
||||
Bit#(xlen) a; // Operand 1
|
||||
Bit#(xlen) b; // Operand 2
|
||||
Bool isBValid; // In the case of a CSR, this will indicate if 'b' is valid
|
||||
Bit#(xlen) imm; // Sign extended immediate
|
||||
} ID_EX#(numeric type xlen) deriving(Bits, Eq, FShow);
|
||||
|
||||
instance DefaultValue #(ID_EX#(xlen));
|
||||
defaultValue = ID_EX {
|
||||
common: defaultValue,
|
||||
epoch: 0,
|
||||
npc: 'hbeefbeef,
|
||||
a: 0,
|
||||
b: 0,
|
||||
isBValid: True,
|
||||
imm: 0
|
||||
};
|
||||
endinstance
|
||||
|
||||
//
|
||||
// EX_MEM
|
||||
//
|
||||
typedef struct {
|
||||
PipelineRegisterCommon#(xlen) common;
|
||||
Bit#(xlen) aluOutput;
|
||||
Bit#(xlen) storeValueOrCSRWriteback;
|
||||
Bool cond; // Branch taken?
|
||||
} EX_MEM#(numeric type xlen) deriving(Bits, Eq, FShow);
|
||||
|
||||
instance DefaultValue #(EX_MEM#(xlen));
|
||||
defaultValue = EX_MEM {
|
||||
common: defaultValue,
|
||||
aluOutput: 0,
|
||||
storeValueOrCSRWriteback: 0,
|
||||
cond: False
|
||||
};
|
||||
endinstance
|
||||
|
||||
//
|
||||
// MEM_WB
|
||||
//
|
||||
typedef struct {
|
||||
PipelineRegisterCommon#(xlen) common;
|
||||
Bit#(xlen) gprWritebackValue;
|
||||
Bit#(xlen) csrWritebackValue;
|
||||
} MEM_WB#(numeric type xlen) deriving(Bits, Eq, FShow);
|
||||
|
||||
instance DefaultValue #(MEM_WB#(xlen));
|
||||
defaultValue = MEM_WB {
|
||||
common: defaultValue,
|
||||
gprWritebackValue: 0,
|
||||
csrWritebackValue: 0
|
||||
};
|
||||
endinstance
|
||||
|
||||
//
|
||||
// WB_OUT
|
||||
//
|
||||
typedef struct {
|
||||
PipelineRegisterCommon#(xlen) common;
|
||||
Bit#(xlen) csr_writeback_value;
|
||||
Bit#(xlen) gpr_writeback_value;
|
||||
} WB_OUT#(numeric type xlen) deriving(Bits, Eq, FShow);
|
||||
|
||||
instance DefaultValue#(WB_OUT#(xlen));
|
||||
defaultValue = WB_OUT {
|
||||
common: defaultValue,
|
||||
gpr_writeback_value: 0,
|
||||
csr_writeback_value: 0
|
||||
};
|
||||
endinstance
|
||||
@ -43,105 +43,102 @@ RVBranchOperator branch_BLTU = 3'b110;
|
||||
RVBranchOperator branch_BGEU = 3'b111;
|
||||
|
||||
//
|
||||
// RVCSRIndex
|
||||
// RVCsrIndex
|
||||
//
|
||||
typedef Bit#(12) RVCSRIndex;
|
||||
typedef Bit#(12) RVCsrIndex;
|
||||
// Supervisor Trap Setup
|
||||
RVCSRIndex csr_SSTATUS = 12'h100; // Supervisor Status 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_SCOUNTEREN = 12'h106; // Supervisor Counter Enable Register (SRW)
|
||||
RVCsrIndex csr_SSTATUS = 12'h100; // Supervisor Status 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_SCOUNTEREN = 12'h106; // Supervisor Counter Enable Register (SRW)
|
||||
// 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
|
||||
RVCSRIndex csr_SSCRATCH = 12'h140; // Scratch register for supervisor trap handlers (SRW)
|
||||
RVCSRIndex csr_SEPC = 12'h141; // Supervisor exception program counter (SRW)
|
||||
RVCSRIndex csr_SCAUSE = 12'h142; // Supervisor trap cause (SRW)
|
||||
RVCSRIndex csr_STVAL = 12'h143; // Supervisor bad address or instruction (SRW)
|
||||
RVCSRIndex csr_SIP = 12'h144; // Supervisor interrupt pending (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_SCAUSE = 12'h142; // Supervisor trap cause (SRW)
|
||||
RVCsrIndex csr_STVAL = 12'h143; // Supervisor bad address or instruction (SRW)
|
||||
RVCsrIndex csr_SIP = 12'h144; // Supervisor interrupt pending (SRW)
|
||||
// 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
|
||||
RVCSRIndex csr_MSTATUS = 12'h300; // Machine Status 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_MIDELEG = 12'h303; // Machine Interrupt Delegation 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_MCOUNTEREN = 12'h306; // Machine Counter Enable Register (MRW)
|
||||
`ifdef RV32
|
||||
RVCSRIndex csr_MSTATUSH = 12'h310; // Additional machine status register, RV32 only (MRW)
|
||||
`endif
|
||||
RVCsrIndex csr_MSTATUS = 12'h300; // Machine Status 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_MIDELEG = 12'h303; // Machine Interrupt Delegation 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_MCOUNTEREN = 12'h306; // Machine Counter Enable Register (MRW)
|
||||
RVCsrIndex csr_MSTATUSH = 12'h310; // Additional machine status register, RV32 only (MRW)
|
||||
|
||||
// Machine Trap Handling
|
||||
RVCSRIndex csr_MSCRATCH = 12'h340; // Scratch register for machine trap handlers (MRW)
|
||||
RVCSRIndex csr_MEPC = 12'h341; // Machine exception program counter (MRW)
|
||||
RVCSRIndex csr_MCAUSE = 12'h342; // Machine trap cause (MRW)
|
||||
RVCSRIndex csr_MTVAL = 12'h343; // Machine bad address or instruction (MRW)
|
||||
RVCSRIndex csr_MIP = 12'h344; // Machine interrupt pending (MRW)
|
||||
RVCSRIndex csr_MTINST = 12'h34A; // Machine trap instruction (transformed) (MRW)
|
||||
RVCSRIndex csr_MTVAL2 = 12'h34B; // Machine bad guest physical address (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_MCAUSE = 12'h342; // Machine trap cause (MRW)
|
||||
RVCsrIndex csr_MTVAL = 12'h343; // Machine bad address or instruction (MRW)
|
||||
RVCsrIndex csr_MIP = 12'h344; // Machine interrupt pending (MRW)
|
||||
RVCsrIndex csr_MTINST = 12'h34A; // Machine trap instruction (transformed) (MRW)
|
||||
RVCsrIndex csr_MTVAL2 = 12'h34B; // Machine bad guest physical address (MRW)
|
||||
// Machine Memory Protection
|
||||
RVCSRIndex csr_PMPCFG0 = 12'h3A0; // Physical memory protection configuration (MRW)
|
||||
RVCSRIndex csr_PMPCFG15 = 12'h3AF;
|
||||
RVCSRIndex csr_PMPADDR0 = 12'h3B0; // Physical memory protection address register (MRW)
|
||||
RVCSRIndex csr_PMPADDR63 = 12'h3EF;
|
||||
RVCsrIndex csr_PMPCFG0 = 12'h3A0; // Physical memory protection configuration (MRW)
|
||||
RVCsrIndex csr_PMPCFG15 = 12'h3AF;
|
||||
RVCsrIndex csr_PMPADDR0 = 12'h3B0; // Physical memory protection address register (MRW)
|
||||
RVCsrIndex csr_PMPADDR63 = 12'h3EF;
|
||||
// Debug/Trace Registers
|
||||
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_TDATA2 = 12'h7A2; // Second 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_TSELECT = 12'h7A0; // Debug/Trace trigger register select (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_TDATA3 = 12'h7A3; // Third Debug/Trace trigger data register (MRW)
|
||||
RVCsrIndex csr_MCONTEXT = 12'h7A8; // Machine-mode context register (MRW)
|
||||
// Debug Mode Registers
|
||||
RVCSRIndex csr_DCSR = 12'h7B0; // Debug Control and Status
|
||||
RVCSRIndex csr_DPC = 12'h7B1; // Debug Program Counter
|
||||
RVCSRIndex csr_DSCRATCH0 = 12'h7B2; // Debug Scratch Register 0
|
||||
RVCSRIndex csr_DSCRATCH1 = 12'h7B3; // Debug Scratch Register 1
|
||||
RVCsrIndex csr_DCSR = 12'h7B0; // Debug Control and Status
|
||||
RVCsrIndex csr_DPC = 12'h7B1; // Debug Program Counter
|
||||
RVCsrIndex csr_DSCRATCH0 = 12'h7B2; // Debug Scratch Register 0
|
||||
RVCsrIndex csr_DSCRATCH1 = 12'h7B3; // Debug Scratch Register 1
|
||||
// Machine Counters/Timers
|
||||
RVCSRIndex csr_MCYCLE = 12'hB00; // Cycle counter for RDCYCLE instruction (MRW)
|
||||
RVCSRIndex csr_MINSTRET = 12'hB02; // Machine instructions-retired counter (MRW)
|
||||
RVCSRIndex csr_MHPMCOUNTER3 = 12'hB03; // 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_MHPMCOUNTER6 = 12'hB06; // 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_MHPMCOUNTER9 = 12'hB09; // Machine performance-monitoring counter (MRW)
|
||||
`ifdef RV32
|
||||
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_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_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_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_MHPMCOUNTER9H = 12'hB89; // Machine performance-monitoring counter (upper 32 bits) (MRW)
|
||||
`endif
|
||||
RVCSRIndex csr_CYCLE = 12'hC00; // Read only mirror of MCYCLE
|
||||
RVCsrIndex csr_MCYCLE = 12'hB00; // Cycle counter for RDCYCLE instruction (MRW)
|
||||
RVCsrIndex csr_MINSTRET = 12'hB02; // Machine instructions-retired counter (MRW)
|
||||
RVCsrIndex csr_MHPMCOUNTER3 = 12'hB03; // 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_MHPMCOUNTER6 = 12'hB06; // 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_MHPMCOUNTER9 = 12'hB09; // Machine performance-monitoring counter (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_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_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_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_MHPMCOUNTER9H = 12'hB89; // Machine performance-monitoring counter (upper 32 bits) (MRW)
|
||||
RVCsrIndex csr_CYCLE = 12'hC00; // Read only mirror of MCYCLE
|
||||
// Machine Information Registers
|
||||
RVCSRIndex csr_MVENDORID = 12'hF11; // Vendor ID (MRO)
|
||||
RVCSRIndex csr_MARCHID = 12'hF12; // Architecture ID (MRO)
|
||||
RVCSRIndex csr_MIMPID = 12'hF13; // Implementation ID (MRO)
|
||||
RVCSRIndex csr_MHARTID = 12'hF14; // Hardware thread ID (MRO)
|
||||
RVCSRIndex csr_MCONFIGPTR = 12'hF15; // Pointer to configuration data structure (MRO)
|
||||
RVCsrIndex csr_MVENDORID = 12'hF11; // Vendor ID (MRO)
|
||||
RVCsrIndex csr_MARCHID = 12'hF12; // Architecture ID (MRO)
|
||||
RVCsrIndex csr_MIMPID = 12'hF13; // Implementation ID (MRO)
|
||||
RVCsrIndex csr_MHARTID = 12'hF14; // Hardware thread ID (MRO)
|
||||
RVCsrIndex csr_MCONFIGPTR = 12'hF15; // Pointer to configuration data structure (MRO)
|
||||
|
||||
//
|
||||
// RVCSRIndexOffset
|
||||
// RVCsrIndexOffset
|
||||
//
|
||||
typedef Bit#(8) RVCSRIndexOffset;
|
||||
typedef Bit#(8) RVCsrIndexOffset;
|
||||
// Trap Setup
|
||||
RVCSRIndexOffset csr_STATUS = 8'h00; // Status
|
||||
RVCSRIndexOffset csr_EDELEG = 8'h02; // Exception Delegation
|
||||
RVCSRIndexOffset csr_IDELEG = 8'h03; // Interrupt Delegation
|
||||
RVCSRIndexOffset csr_IE = 8'h04; // Interrupt Enable
|
||||
RVCSRIndexOffset csr_TVEC = 8'h05; // Vector Table
|
||||
RVCSRIndexOffset csr_COUNTEREN = 8'h06; // Counter Enable
|
||||
RVCsrIndexOffset csr_STATUS = 8'h00; // Status
|
||||
RVCsrIndexOffset csr_EDELEG = 8'h02; // Exception Delegation
|
||||
RVCsrIndexOffset csr_IDELEG = 8'h03; // Interrupt Delegation
|
||||
RVCsrIndexOffset csr_IE = 8'h04; // Interrupt Enable
|
||||
RVCsrIndexOffset csr_TVEC = 8'h05; // Vector Table
|
||||
RVCsrIndexOffset csr_COUNTEREN = 8'h06; // Counter Enable
|
||||
// Trap Handling
|
||||
RVCSRIndexOffset csr_SCRATCH = 8'h40; // Scratch Register
|
||||
RVCSRIndexOffset csr_EPC = 8'h41; // Exception Program Counter
|
||||
RVCSRIndexOffset csr_CAUSE = 8'h42; // Exception/Interrupt Cause
|
||||
RVCSRIndexOffset csr_TVAL = 8'h43; // Bad address or instruction
|
||||
RVCSRIndexOffset csr_IP = 8'h44; // Interrupt Pending
|
||||
RVCsrIndexOffset csr_SCRATCH = 8'h40; // Scratch Register
|
||||
RVCsrIndexOffset csr_EPC = 8'h41; // Exception Program Counter
|
||||
RVCsrIndexOffset csr_CAUSE = 8'h42; // Exception/Interrupt Cause
|
||||
RVCsrIndexOffset csr_TVAL = 8'h43; // Bad address or instruction
|
||||
RVCsrIndexOffset csr_IP = 8'h44; // Interrupt Pending
|
||||
|
||||
//
|
||||
// RVCSROperator(s)
|
||||
@ -229,18 +226,12 @@ typedef RVFunc3 RVLoadOperator;
|
||||
RVLoadOperator load_LB = 3'b000;
|
||||
RVLoadOperator load_LH = 3'b001;
|
||||
RVLoadOperator load_LW = 3'b010;
|
||||
`ifdef RV32
|
||||
RVLoadOperator load_UNSUPPORTED_011 = 3'b011;
|
||||
`elsif RV64
|
||||
RVLoadOperator load_LD = 3'b011;
|
||||
`endif
|
||||
RVLoadOperator load_UNSUPPORTED_011 = 3'b011; // RV32
|
||||
RVLoadOperator load_LD = 3'b011; // RV64
|
||||
RVLoadOperator load_LBU = 3'b100;
|
||||
RVLoadOperator load_LHU = 3'b101;
|
||||
`ifdef RV32
|
||||
RVLoadOperator load_UNSUPPORTED_110 = 3'b110;
|
||||
`elsif RV64
|
||||
RVLoadOperator load_LWU = 3'b110;
|
||||
`endif
|
||||
RVLoadOperator load_UNSUPPORTED_110 = 3'b110; // RV32
|
||||
RVLoadOperator load_LWU = 3'b110; // RV64
|
||||
RVLoadOperator load_UNSUPPORTED_111 = 3'b111;
|
||||
|
||||
//
|
||||
@ -275,11 +266,8 @@ typedef RVFunc3 RVStoreOperator;
|
||||
RVStoreOperator store_SB = 3'b000;
|
||||
RVStoreOperator store_SH = 3'b001;
|
||||
RVStoreOperator store_SW = 3'b010;
|
||||
`ifdef RV32
|
||||
RVStoreOperator store_UNSUPPORTED_011 = 3'b011;
|
||||
`elsif RV64
|
||||
RVStoreOperator store_SD = 3'b011;
|
||||
`endif
|
||||
RVStoreOperator store_UNSUPPORTED_011 = 3'b011; // RV32
|
||||
RVStoreOperator store_SD = 3'b011; // RV64
|
||||
RVStoreOperator store_UNSUPPORTED_100 = 3'b100;
|
||||
RVStoreOperator store_UNSUPPORTED_101 = 3'b101;
|
||||
RVStoreOperator store_UNSUPPORTED_110 = 3'b110;
|
||||
|
||||
10
src/Cpu/Trap.bsv
Normal file
10
src/Cpu/Trap.bsv
Normal file
@ -0,0 +1,10 @@
|
||||
typedef struct {
|
||||
Bit#(4) cause; // Either exception or interrupt
|
||||
Bool isInterrupt;
|
||||
Bit#(xlen) tval;
|
||||
} Trap#(numeric type xlen) deriving(Bits, Eq, FShow);
|
||||
|
||||
interface TrapController#(numeric type xlen);
|
||||
method ActionValue#(Bit#(xlen)) beginTrap(Bit#(xlen) trap_program_counter, Trap#(xlen) trap);
|
||||
method ActionValue#(Bit#(xlen)) endTrap;
|
||||
endinterface
|
||||
@ -1,18 +1,24 @@
|
||||
//!submodule Cpu
|
||||
//!submodule Memory
|
||||
//!submodule Util
|
||||
import Soc::*;
|
||||
|
||||
//!topmodule mkE001
|
||||
module mkE001(SocIfc#(32));
|
||||
SocCfg#(32) cfg = SocCfg {
|
||||
cpu_cfg: CpuCfg {}
|
||||
module mkE001(SocIfc#(32, 32));
|
||||
SocCfg#(32, 32) cfg = SocCfg {
|
||||
cpu_cfg: CpuCfg {
|
||||
initial_program_counter: 'h8000_0000
|
||||
}
|
||||
};
|
||||
let soc <- mkSoc(cfg);
|
||||
endmodule
|
||||
|
||||
//!topmodule mkE003
|
||||
module mkE003(SocIfc#(64));
|
||||
SocCfg#(64) cfg = SocCfg{
|
||||
cpu_cfg: CpuCfg {}
|
||||
module mkE003(SocIfc#(64, 32));
|
||||
SocCfg#(64, 32) cfg = SocCfg{
|
||||
cpu_cfg: CpuCfg {
|
||||
initial_program_counter: 'h8000_0000
|
||||
}
|
||||
};
|
||||
let soc <- mkSoc(cfg);
|
||||
endmodule
|
||||
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);
|
||||
@ -5,18 +5,18 @@ export CpuCfg(..), mkSoc, SocCfg(..), SocIfc(..);
|
||||
// SocConfig
|
||||
//
|
||||
typedef struct {
|
||||
CpuCfg#(xlen) cpu_cfg;
|
||||
} SocCfg#(numeric type xlen);
|
||||
CpuCfg#(xlen, ifetchByteCount) cpu_cfg;
|
||||
} SocCfg#(numeric type xlen, numeric type ifetchByteCount);
|
||||
|
||||
//
|
||||
// SocIfc
|
||||
//
|
||||
interface SocIfc#(numeric type xlen);
|
||||
interface SocIfc#(numeric type xlen, numeric type ifetchByteCount);
|
||||
endinterface
|
||||
|
||||
//
|
||||
// mkSoc()
|
||||
//
|
||||
module mkSoc#(SocCfg#(xlen) cfg)(SocIfc#(xlen));
|
||||
module mkSoc#(SocCfg#(xlen, ifetchByteCount) cfg)(SocIfc#(xlen, ifetchByteCount));
|
||||
let cpu <- mkCpu(cfg.cpu_cfg);
|
||||
endmodule
|
||||
|
||||
9
src/Util/ReadOnly.bsv
Normal file
9
src/Util/ReadOnly.bsv
Normal file
@ -0,0 +1,9 @@
|
||||
module mkReadOnly#(t x)(ReadOnly#(t));
|
||||
function ReadOnly#(t) readOnlyReg(t r);
|
||||
return (interface ReadOnly;
|
||||
method t _read = r;
|
||||
endinterface);
|
||||
endfunction
|
||||
|
||||
return readOnlyReg(x);
|
||||
endmodule
|
||||
Loading…
x
Reference in New Issue
Block a user