Add IRsp/dRsp ready + error capabilities to stall the bus and to generate access error exceptions

This commit is contained in:
Charles Papon 2017-03-28 01:24:29 +02:00
parent eecc1e6b18
commit 62a55c4cf4
4 changed files with 100 additions and 44 deletions

View file

@ -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

View file

@ -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)
}
}
}

View file

@ -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),

View file

@ -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