mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-04-24 05:57:07 -04:00
Add IRsp/dRsp ready + error capabilities to stall the bus and to generate access error exceptions
This commit is contained in:
parent
eecc1e6b18
commit
62a55c4cf4
4 changed files with 100 additions and 44 deletions
|
@ -13,10 +13,12 @@ case class DBusSimpleCmd() extends Bundle{
|
|||
}
|
||||
|
||||
case class DBusSimpleRsp() extends Bundle{
|
||||
val ready = Bool
|
||||
val error = Bool
|
||||
val data = Bits(32 bit)
|
||||
}
|
||||
|
||||
class DBusSimplePlugin(catchUnalignedException : Boolean) extends Plugin[VexRiscv]{
|
||||
class DBusSimplePlugin(catchUnalignedException : Boolean, catchAccessFault : Boolean) extends Plugin[VexRiscv]{
|
||||
|
||||
var dCmd : Stream[DBusSimpleCmd] = null
|
||||
var dRsp : DBusSimpleRsp = null
|
||||
|
@ -31,7 +33,7 @@ class DBusSimplePlugin(catchUnalignedException : Boolean) extends Plugin[VexRisc
|
|||
object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
|
||||
|
||||
var executeExceptionPort : Flow[ExceptionCause] = null
|
||||
|
||||
var memoryExceptionPort : Flow[ExceptionCause] = null
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import Riscv._
|
||||
import pipeline.config._
|
||||
|
@ -39,11 +41,12 @@ class DBusSimplePlugin(catchUnalignedException : Boolean) extends Plugin[VexRisc
|
|||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
|
||||
val stdActions = List[(Stageable[_ <: BaseType],Any)](
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC_USE_SUB_LESS -> False,
|
||||
MEMORY_ENABLE -> True,
|
||||
REG1_USE -> True
|
||||
LEGAL_INSTRUCTION -> True,
|
||||
SRC1_CTRL -> Src1CtrlEnum.RS,
|
||||
SRC_USE_SUB_LESS -> False,
|
||||
MEMORY_ENABLE -> True,
|
||||
REG1_USE -> True,
|
||||
IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB //Used for assess fault bad address in memory stage
|
||||
)
|
||||
|
||||
val loadActions = stdActions ++ List(
|
||||
|
@ -75,6 +78,11 @@ class DBusSimplePlugin(catchUnalignedException : Boolean) extends Plugin[VexRisc
|
|||
val exceptionService = pipeline.service(classOf[ExceptionService])
|
||||
executeExceptionPort = exceptionService.newExceptionPort(pipeline.execute)
|
||||
}
|
||||
|
||||
if(catchAccessFault) {
|
||||
val exceptionService = pipeline.service(classOf[ExceptionService])
|
||||
memoryExceptionPort = exceptionService.newExceptionPort(pipeline.memory)
|
||||
}
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
|
@ -115,7 +123,15 @@ class DBusSimplePlugin(catchUnalignedException : Boolean) extends Plugin[VexRisc
|
|||
|
||||
dRsp = in(DBusSimpleRsp()).setName("dRsp")
|
||||
insert(MEMORY_READ_DATA) := dRsp.data
|
||||
assert(!(input(MEMORY_ENABLE) && (!input(INSTRUCTION)(5)) && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend")
|
||||
arbitration.haltIt setWhen(arbitration.isValid && input(MEMORY_ENABLE) && !dRsp.ready)
|
||||
|
||||
if(catchAccessFault){
|
||||
memoryExceptionPort.valid := arbitration.isValid && input(MEMORY_ENABLE) && dRsp.ready && dRsp.error
|
||||
memoryExceptionPort.code := 5
|
||||
memoryExceptionPort.badAddr := input(REGFILE_WRITE_DATA).asUInt //Drived by IntAluPlugin
|
||||
}
|
||||
|
||||
assert(!(dRsp.ready && input(MEMORY_ENABLE) && arbitration.isValid && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend")
|
||||
}
|
||||
|
||||
//Reformat read responses, REGFILE_WRITE_DATA overriding
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package SpinalRiscv.Plugin
|
||||
|
||||
import SpinalRiscv.VexRiscv
|
||||
import SpinalRiscv.{Stageable, ExceptionService, ExceptionCause, VexRiscv}
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
|
||||
|
@ -10,15 +10,24 @@ case class IBusSimpleCmd() extends Bundle{
|
|||
}
|
||||
|
||||
case class IBusSimpleRsp() extends Bundle{
|
||||
val inst = Bits(32 bits)
|
||||
val ready = Bool
|
||||
val error = Bool
|
||||
val inst = Bits(32 bits)
|
||||
}
|
||||
|
||||
class IBusSimplePlugin(interfaceKeepData : Boolean) extends Plugin[VexRiscv]{
|
||||
class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean) extends Plugin[VexRiscv]{
|
||||
var iCmd : Stream[IBusSimpleCmd] = null
|
||||
var iRsp : IBusSimpleRsp = null
|
||||
|
||||
object IBUS_ACCESS_ERROR extends Stageable(Bool)
|
||||
var decodeExceptionPort : Flow[ExceptionCause] = null
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
pipeline.unremovableStages += pipeline.prefetch
|
||||
|
||||
if(catchAccessFault) {
|
||||
val exceptionService = pipeline.service(classOf[ExceptionService])
|
||||
decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode)
|
||||
}
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
|
@ -35,5 +44,13 @@ class IBusSimplePlugin(interfaceKeepData : Boolean) extends Plugin[VexRiscv]{
|
|||
//Insert iRsp into INSTRUCTION
|
||||
iRsp = in(IBusSimpleRsp()).setName("iRsp")
|
||||
fetch.insert(INSTRUCTION) := iRsp.inst
|
||||
fetch.arbitration.haltIt setWhen(fetch.arbitration.isValid && !iRsp.ready)
|
||||
fetch.insert(IBUS_ACCESS_ERROR) := iRsp.error
|
||||
|
||||
if(catchAccessFault){
|
||||
decodeExceptionPort.valid := decode.arbitration.isValid && decode.input(IBUS_ACCESS_ERROR)
|
||||
decodeExceptionPort.code := 1
|
||||
decodeExceptionPort.badAddr := decode.input(PC)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,8 @@ object TopLevel {
|
|||
config.plugins ++= List(
|
||||
new PcManagerSimplePlugin(0x00000000l, false),
|
||||
new IBusSimplePlugin(
|
||||
interfaceKeepData = true
|
||||
interfaceKeepData = true,
|
||||
catchAccessFault = true
|
||||
),
|
||||
new DecoderSimplePlugin(
|
||||
catchIllegalInstruction = true
|
||||
|
@ -84,7 +85,8 @@ object TopLevel {
|
|||
new FullBarrielShifterPlugin,
|
||||
// new LightShifterPlugin,
|
||||
new DBusSimplePlugin(
|
||||
catchUnalignedException = true
|
||||
catchUnalignedException = true,
|
||||
catchAccessFault = true
|
||||
),
|
||||
new HazardSimplePlugin(true, true, true, true),
|
||||
// new HazardSimplePlugin(false, true, false, true),
|
||||
|
|
|
@ -204,6 +204,11 @@ public:
|
|||
top->reset = 0;
|
||||
top->iCmd_ready = 1;
|
||||
top->dCmd_ready = 1;
|
||||
top->iRsp_ready = 1;
|
||||
top->dRsp_ready = 1;
|
||||
top->iRsp_error = 0;
|
||||
top->dRsp_error = 0;
|
||||
|
||||
top->eval(); currentTime = 3;
|
||||
top->reset = 1;
|
||||
top->eval();
|
||||
|
@ -214,7 +219,7 @@ public:
|
|||
dump(0);
|
||||
top->reset = 0;
|
||||
top->eval(); currentTime = 2;
|
||||
top->clk = 1;
|
||||
|
||||
|
||||
postReset();
|
||||
|
||||
|
@ -226,6 +231,9 @@ public:
|
|||
|
||||
try {
|
||||
// run simulation for 100 clock periods
|
||||
uint32_t iRsp_inst_next = top->iRsp_inst;
|
||||
uint32_t dRsp_inst_next = VL_RANDOM_I(32);
|
||||
bool iRsp_ready_pending = false, dRsp_ready_pending = false;
|
||||
for (i = 16; i < timeout*2; i+=2) {
|
||||
mTime = i/2;
|
||||
#ifdef CSR
|
||||
|
@ -233,12 +241,21 @@ public:
|
|||
//if(mTime == mTimeCmp) printf("SIM timer tick\n");
|
||||
#endif
|
||||
currentTime = i;
|
||||
uint32_t iRsp_inst_next = top->iRsp_inst;
|
||||
uint32_t dRsp_inst_next = VL_RANDOM_I(32);
|
||||
|
||||
|
||||
if (top->iCmd_valid && top->iCmd_ready) {
|
||||
|
||||
|
||||
// dump variables into VCD file and toggle clock
|
||||
|
||||
dump(i);
|
||||
top->clk = 0;
|
||||
top->eval(); top->eval();top->eval();
|
||||
|
||||
|
||||
dump(i + 1);
|
||||
if (top->iCmd_valid && top->iCmd_ready && !iRsp_ready_pending) {
|
||||
assertEq(top->iCmd_payload_pc & 3,0);
|
||||
iRsp_ready_pending = true;
|
||||
//printf("%d\n",top->iCmd_payload_pc);
|
||||
|
||||
iRsp_inst_next = iRspOverride((mem[top->iCmd_payload_pc + 0] << 0)
|
||||
|
@ -246,11 +263,12 @@ public:
|
|||
| (mem[top->iCmd_payload_pc + 2] << 16)
|
||||
| (mem[top->iCmd_payload_pc + 3] << 24));
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (top->dCmd_valid && top->dCmd_ready) {
|
||||
if (top->dCmd_valid && top->dCmd_ready && ! dRsp_ready_pending) {
|
||||
// assertEq(top->iCmd_payload_pc & 3,0);
|
||||
dRsp_ready_pending = true;
|
||||
dRsp_inst_next = VL_RANDOM_I(32);
|
||||
//printf("%d\n",top->iCmd_payload_pc);
|
||||
|
||||
uint32_t addr = top->dCmd_payload_address;
|
||||
|
@ -307,34 +325,37 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// dump variables into VCD file and toggle clock
|
||||
for (uint32_t clk = 0; clk < 2; clk++) {
|
||||
dump(i+ clk);
|
||||
top->clk = !top->clk;
|
||||
|
||||
top->eval();
|
||||
if(top->clk == 0){
|
||||
if(iStall) top->iCmd_ready = VL_RANDOM_I(1);
|
||||
if(dStall) top->dCmd_ready = VL_RANDOM_I(1);
|
||||
if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address != 0){
|
||||
regTraces <<
|
||||
#ifdef TRACE_WITH_TIME
|
||||
currentTime <<
|
||||
#endif
|
||||
" : reg[" << (uint32_t)top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address << "] = " << top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data << endl;
|
||||
}
|
||||
checks();
|
||||
}
|
||||
if(top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_valid == 1 && top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address != 0){
|
||||
regTraces <<
|
||||
#ifdef TRACE_WITH_TIME
|
||||
currentTime <<
|
||||
#endif
|
||||
" : reg[" << (uint32_t)top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_address << "] = " << top->VexRiscv->writeBack_RegFilePlugin_regFileWrite_payload_data << endl;
|
||||
}
|
||||
|
||||
checks();
|
||||
top->clk = 1;
|
||||
top->eval(); top->eval();
|
||||
|
||||
cycles += 1;
|
||||
top->iRsp_ready = !iRsp_ready_pending;
|
||||
top->dRsp_ready = 0;
|
||||
if(iRsp_ready_pending && (!iStall || VL_RANDOM_I(8) < 100)){
|
||||
top->iRsp_inst = iRsp_inst_next;
|
||||
iRsp_ready_pending = false;
|
||||
top->iRsp_ready = 1;
|
||||
}
|
||||
if(dRsp_ready_pending && (!dStall || VL_RANDOM_I(8) < 100)){
|
||||
top->dRsp_data = dRsp_inst_next;
|
||||
dRsp_ready_pending = false;
|
||||
top->dRsp_ready = 1;
|
||||
} else{
|
||||
top->dRsp_data = VL_RANDOM_I(32);
|
||||
}
|
||||
|
||||
if(iStall) top->iCmd_ready = VL_RANDOM_I(8) < 100 && !iRsp_ready_pending;
|
||||
if(dStall) top->dCmd_ready = VL_RANDOM_I(8) < 100 && !dRsp_ready_pending;
|
||||
|
||||
top->iRsp_inst = iRsp_inst_next;
|
||||
top->dRsp_data = dRsp_inst_next;
|
||||
|
||||
if (Verilated::gotFinish())
|
||||
exit(0);
|
||||
|
@ -598,7 +619,7 @@ int main(int argc, char **argv, char **env) {
|
|||
#ifdef CSR
|
||||
uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u ,
|
||||
8,6,9,6,10,4,11,4, 12,13,0, 14,2,15 };
|
||||
redo(REDO,TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).run(2e3);)
|
||||
redo(REDO,TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).run(4e3);)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue