From 91c52f4e46fae7ceb3f6e5240b262ff5acd3f637 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sun, 26 Mar 2017 18:02:48 +0200 Subject: [PATCH] Decoder now catch illegal instructions --- .../SpinalRiscv/Plugin/BranchPlugin.scala | 10 ++++----- .../SpinalRiscv/Plugin/DBusSimplePlugin.scala | 6 ++--- .../Plugin/DecoderSimplePlugin.scala | 16 +++++++++++++- src/main/scala/SpinalRiscv/TopLevel.scala | 8 ++++--- src/test/cpp/testA/main.cpp | 22 ++++++++++++++----- src/test/cpp/testA/makefile | 2 +- src/test/resources/asm/machineCsr.asm | 4 ++++ src/test/resources/hex/machineCsr.hex | 2 +- 8 files changed, 50 insertions(+), 20 deletions(-) diff --git a/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala b/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala index 9d4eac0..5e13fec 100644 --- a/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/BranchPlugin.scala @@ -11,7 +11,7 @@ object STATIC extends BranchPrediction object DYNAMIC extends BranchPrediction class BranchPlugin(earlyBranch : Boolean, - unalignedExceptionGen : Boolean, + catchUnalignedException : Boolean, prediction : BranchPrediction, historyRamSizeLog2 : Int = 10, historyWidth : Int = 2) extends Plugin[VexRiscv]{ @@ -71,7 +71,7 @@ class BranchPlugin(earlyBranch : Boolean, if (prediction != NONE) predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.decode) - if (unalignedExceptionGen) { + if (catchUnalignedException) { val exceptionService = pipeline.service(classOf[ExceptionService]) branchExceptionPort = exceptionService.newExceptionPort(if (earlyBranch) pipeline.execute else pipeline.memory) if (prediction != NONE) @@ -129,7 +129,7 @@ class BranchPlugin(earlyBranch : Boolean, stages(indexOf(branchStage) - 1).arbitration.flushAll := True } - if(unalignedExceptionGen) { + if(catchUnalignedException) { branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0 branchExceptionPort.code := 0 } @@ -179,7 +179,7 @@ class BranchPlugin(earlyBranch : Boolean, fetch.arbitration.flushAll := True } - if(unalignedExceptionGen) { + if(catchUnalignedException) { predictionExceptionPort.valid := input(PREDICTION_HAD_BRANCHED) && arbitration.isValid && predictionJumpInterface.payload(1 downto 0) =/= 0 predictionExceptionPort.code := 0 } @@ -234,7 +234,7 @@ class BranchPlugin(earlyBranch : Boolean, stages(indexOf(branchStage) - 1).arbitration.flushAll := True } - if(unalignedExceptionGen) { + if(catchUnalignedException) { branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0 branchExceptionPort.code := 0 } diff --git a/src/main/scala/SpinalRiscv/Plugin/DBusSimplePlugin.scala b/src/main/scala/SpinalRiscv/Plugin/DBusSimplePlugin.scala index 6fb207f..28232d3 100644 --- a/src/main/scala/SpinalRiscv/Plugin/DBusSimplePlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/DBusSimplePlugin.scala @@ -16,7 +16,7 @@ case class DBusSimpleRsp() extends Bundle{ val data = Bits(32 bit) } -class DBusSimplePlugin(unalignedExceptionGen : Boolean) extends Plugin[VexRiscv]{ +class DBusSimplePlugin(catchUnalignedException : Boolean) extends Plugin[VexRiscv]{ var dCmd : Stream[DBusSimpleCmd] = null var dRsp : DBusSimpleRsp = null @@ -71,7 +71,7 @@ class DBusSimplePlugin(unalignedExceptionGen : Boolean) extends Plugin[VexRiscv] SW -> (storeActions) )) - if(unalignedExceptionGen) { + if(catchUnalignedException) { val exceptionService = pipeline.service(classOf[ExceptionService]) executeExceptionPort = exceptionService.newExceptionPort(pipeline.execute) } @@ -101,7 +101,7 @@ class DBusSimplePlugin(unalignedExceptionGen : Boolean) extends Plugin[VexRiscv] insert(MEMORY_ADDRESS_LOW) := dCmd.address(1 downto 0) - if(unalignedExceptionGen){ + if(catchUnalignedException){ executeExceptionPort.code := (dCmd.wr ? U(6) | U(4)).resized executeExceptionPort.valid := (arbitration.isValid && input(MEMORY_ENABLE) && ((dCmd.size === 2 && dCmd.address(1 downto 0) =/= 0) || (dCmd.size === 1 && dCmd.address(0 downto 0) =/= 0))) diff --git a/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala b/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala index f0dc2b8..5dde835 100644 --- a/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/DecoderSimplePlugin.scala @@ -12,7 +12,7 @@ case class Masked(value : BigInt,care : BigInt){ } -class DecoderSimplePlugin extends Plugin[VexRiscv] with DecoderService { +class DecoderSimplePlugin(catchIllegalInstruction : Boolean) extends Plugin[VexRiscv] with DecoderService { override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: BaseType], Any)])]): Unit = encoding.foreach(e => this.add(e._1,e._2)) override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: BaseType], Any)]): Unit = { assert(!encodings.contains(key)) @@ -32,9 +32,17 @@ class DecoderSimplePlugin extends Plugin[VexRiscv] with DecoderService { val defaults = mutable.HashMap[Stageable[_ <: BaseType], BaseType]() val encodings = mutable.HashMap[MaskedLiteral,Seq[(Stageable[_ <: BaseType], BaseType)]]() + var decodeExceptionPort : Flow[ExceptionCause] = null + + override def setup(pipeline: VexRiscv): Unit = { import pipeline.config._ addDefault(LEGAL_INSTRUCTION, False) + + if(catchIllegalInstruction) { + val exceptionService = pipeline.plugins.filter(_.isInstanceOf[ExceptionService]).head.asInstanceOf[ExceptionService] + decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode).setName("decodeExceptionPort") + } } override def build(pipeline: VexRiscv): Unit = { @@ -112,6 +120,12 @@ class DecoderSimplePlugin extends Plugin[VexRiscv] with DecoderService { // insert(e).assignFromBits(RegNext(decodedBits(offset, e.dataType.getBitsWidth bits))) offset += e.dataType.getBitsWidth }) + + + if(catchIllegalInstruction){ + decodeExceptionPort.valid := arbitration.isValid && !input(LEGAL_INSTRUCTION) + decodeExceptionPort.code := 2 + } } def bench(toplevel : VexRiscv): Unit ={ diff --git a/src/main/scala/SpinalRiscv/TopLevel.scala b/src/main/scala/SpinalRiscv/TopLevel.scala index 535e798..ac7084f 100644 --- a/src/main/scala/SpinalRiscv/TopLevel.scala +++ b/src/main/scala/SpinalRiscv/TopLevel.scala @@ -72,7 +72,9 @@ object TopLevel { new IBusSimplePlugin( interfaceKeepData = true ), - new DecoderSimplePlugin, + new DecoderSimplePlugin( + catchIllegalInstruction = true + ), new RegFilePlugin( regFileReadyKind = Plugin.SYNC, zeroBoot = false @@ -82,7 +84,7 @@ object TopLevel { new FullBarrielShifterPlugin, // new LightShifterPlugin, new DBusSimplePlugin( - unalignedExceptionGen = true + catchUnalignedException = true ), new HazardSimplePlugin(true, true, true, true), // new HazardSimplePlugin(false, true, false, true), @@ -92,7 +94,7 @@ object TopLevel { new MachineCsr(csrConfig), new BranchPlugin( earlyBranch = false, - unalignedExceptionGen = true, + catchUnalignedException = true, prediction = DYNAMIC ) ) diff --git a/src/test/cpp/testA/main.cpp b/src/test/cpp/testA/main.cpp index 07102b7..736a497 100644 --- a/src/test/cpp/testA/main.cpp +++ b/src/test/cpp/testA/main.cpp @@ -176,7 +176,7 @@ public: } Workspace* bootAt(uint32_t pc) { bootPc = pc;} - + virtual uint32_t iRspOverride(uint32_t value) { return value; } virtual void postReset() {} virtual void checks(){} virtual void pass(){ throw success();} @@ -241,10 +241,12 @@ public: assertEq(top->iCmd_payload_pc & 3,0); //printf("%d\n",top->iCmd_payload_pc); - iRsp_inst_next = (mem[top->iCmd_payload_pc + 0] << 0) - | (mem[top->iCmd_payload_pc + 1] << 8) - | (mem[top->iCmd_payload_pc + 2] << 16) - | (mem[top->iCmd_payload_pc + 3] << 24); + iRsp_inst_next = iRspOverride((mem[top->iCmd_payload_pc + 0] << 0) + | (mem[top->iCmd_payload_pc + 1] << 8) + | (mem[top->iCmd_payload_pc + 2] << 16) + | (mem[top->iCmd_payload_pc + 3] << 24)); + + } if (top->dCmd_valid && top->dCmd_ready) { @@ -447,6 +449,14 @@ public: } } } + + + virtual uint32_t iRspOverride(uint32_t value) { + switch(value){ + case 0x0ff0000f: return 0x00000013; + default: return value; + } + } }; #endif class Dhrystone : public Workspace{ @@ -587,7 +597,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}; + 8,6,9,6,10,4,11,4, 12,13,0, 14,2,15 }; redo(REDO,TestX28("machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).run(2e3);) #endif #endif diff --git a/src/test/cpp/testA/makefile b/src/test/cpp/testA/makefile index edda6f2..a97ae6a 100644 --- a/src/test/cpp/testA/makefile +++ b/src/test/cpp/testA/makefile @@ -2,7 +2,7 @@ TRACE=no TRACE_START=0 CSR=yes DHRYSTONE=yes -FREE_RTOS=no +FREE_RTOS=yes REDO=10 REF=no TRACE_WITH_TIME=no diff --git a/src/test/resources/asm/machineCsr.asm b/src/test/resources/asm/machineCsr.asm index 5fdd8be..d1d7483 100644 --- a/src/test/resources/asm/machineCsr.asm +++ b/src/test/resources/asm/machineCsr.asm @@ -261,6 +261,10 @@ unalignedPcA: li x28, 14 1a4: 00e00e13 li t3,14 + hret + 1a8: 20200073 hret + li x28, 15 + 1ac: 00f00e13 li t3,15 Disassembly of section .text: diff --git a/src/test/resources/hex/machineCsr.hex b/src/test/resources/hex/machineCsr.hex index 24a329d..3a34e92 100644 --- a/src/test/resources/hex/machineCsr.hex +++ b/src/test/resources/hex/machineCsr.hex @@ -24,7 +24,7 @@ :100170009301100023A04100130E90002390410032 :10018000130EA00003A20100130EB00003920100A1 :10019000130EC000130ED000832000006F0020005B -:0801A00083200000130EE000B3 +:1001A00083200000130EE00073002020130EF000E7 :020000044000BA :1000000013050000678000001305000067800000F2 :1000100097020000678082FF1305000067800000E0