From 2b24cbc8e1ce2b841672821c0def0dee670a7fa7 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Tue, 4 Apr 2017 00:25:39 +0200 Subject: [PATCH] Add pessimistic harzard options Add separated add/sum option in srcPlugin --- .../Plugin/HazardSimplePlugin.scala | 22 +++-- .../scala/SpinalRiscv/Plugin/SrcPlugin.scala | 37 ++++++--- src/main/scala/SpinalRiscv/TopLevel.scala | 81 +++++++++++++++++-- src/test/cpp/testA/main.cpp | 3 +- 4 files changed, 120 insertions(+), 23 deletions(-) diff --git a/src/main/scala/SpinalRiscv/Plugin/HazardSimplePlugin.scala b/src/main/scala/SpinalRiscv/Plugin/HazardSimplePlugin.scala index 921e8a4..8b8f489 100644 --- a/src/main/scala/SpinalRiscv/Plugin/HazardSimplePlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/HazardSimplePlugin.scala @@ -5,7 +5,13 @@ import spinal.core._ import spinal.lib._ -class HazardSimplePlugin(bypassExecute : Boolean,bypassMemory: Boolean,bypassWriteBack: Boolean, bypassWriteBackBuffer : Boolean) extends Plugin[VexRiscv] { +class HazardSimplePlugin(bypassExecute : Boolean, + bypassMemory: Boolean, + bypassWriteBack: Boolean, + bypassWriteBackBuffer : Boolean, + pessimisticUseSrc : Boolean = false, + pessimisticWriteRegFile : Boolean = false, + pessimisticAddressMatch : Boolean = false) extends Plugin[VexRiscv] { import Riscv._ override def build(pipeline: VexRiscv): Unit = { import pipeline._ @@ -15,8 +21,8 @@ class HazardSimplePlugin(bypassExecute : Boolean,bypassMemory: Boolean,bypassWri def trackHazardWithStage(stage : Stage,bypassable : Boolean, runtimeBypassable : Stageable[Bool]): Unit ={ val runtimeBypassableValue = if(runtimeBypassable != null) stage.input(runtimeBypassable) else True - val addr0Match = stage.input(INSTRUCTION)(rdRange) === decode.input(INSTRUCTION)(rs1Range) - val addr1Match = stage.input(INSTRUCTION)(rdRange) === decode.input(INSTRUCTION)(rs2Range) + val addr0Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === decode.input(INSTRUCTION)(rs1Range) + val addr1Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === decode.input(INSTRUCTION)(rs2Range) when(stage.arbitration.isValid && stage.input(REGFILE_WRITE_VALID)) { if (bypassable) { when(runtimeBypassableValue) { @@ -28,6 +34,8 @@ class HazardSimplePlugin(bypassExecute : Boolean,bypassMemory: Boolean,bypassWri } } } + } + when(stage.arbitration.isValid && (if(pessimisticWriteRegFile) True else stage.input(REGFILE_WRITE_VALID))) { when((Bool(!bypassable) || !runtimeBypassableValue)) { when(addr0Match) { src0Hazard := True @@ -49,8 +57,8 @@ class HazardSimplePlugin(bypassExecute : Boolean,bypassMemory: Boolean,bypassWri writeBackWrites.data := writeBack.output(REGFILE_WRITE_DATA) val writeBackBuffer = writeBackWrites.stage() - val addr0Match = writeBackBuffer.address === decode.input(INSTRUCTION)(rs1Range) - val addr1Match = writeBackBuffer.address === decode.input(INSTRUCTION)(rs2Range) + val addr0Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === decode.input(INSTRUCTION)(rs1Range) + val addr1Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === decode.input(INSTRUCTION)(rs2Range) when(writeBackBuffer.valid) { if (bypassWriteBackBuffer) { when(addr0Match) { @@ -74,10 +82,10 @@ class HazardSimplePlugin(bypassExecute : Boolean,bypassMemory: Boolean,bypassWri trackHazardWithStage(execute ,bypassExecute ,BYPASSABLE_EXECUTE_STAGE) - when(decode.input(INSTRUCTION)(rs1Range) === 0 || !decode.input(REG1_USE)){ + when(decode.input(INSTRUCTION)(rs1Range) === 0 || (if(pessimisticUseSrc) False else !decode.input(REG1_USE))){ src0Hazard := False } - when(decode.input(INSTRUCTION)(rs2Range) === 0 || !decode.input(REG2_USE)){ + when(decode.input(INSTRUCTION)(rs2Range) === 0 || (if(pessimisticUseSrc) False else !decode.input(REG2_USE))){ src1Hazard := False } diff --git a/src/main/scala/SpinalRiscv/Plugin/SrcPlugin.scala b/src/main/scala/SpinalRiscv/Plugin/SrcPlugin.scala index 51e32e1..eef7f79 100644 --- a/src/main/scala/SpinalRiscv/Plugin/SrcPlugin.scala +++ b/src/main/scala/SpinalRiscv/Plugin/SrcPlugin.scala @@ -4,7 +4,7 @@ import SpinalRiscv.{Riscv, VexRiscv} import spinal.core._ -class SrcPlugin extends Plugin[VexRiscv]{ +class SrcPlugin(separatedAddSub : Boolean) extends Plugin[VexRiscv]{ override def build(pipeline: VexRiscv): Unit = { import pipeline._ import pipeline.config._ @@ -28,18 +28,35 @@ class SrcPlugin extends Plugin[VexRiscv]{ ) } - execute plug new Area{ - import execute._ + if(separatedAddSub) { + execute plug new Area { + import execute._ - // ADD, SUB - val addSub = (input(SRC1).asSInt + Mux(input(SRC_USE_SUB_LESS), ~input(SRC2), input(SRC2)).asSInt + Mux(input(SRC_USE_SUB_LESS),S(1),S(0))).asBits + // ADD, SUB + val add = (input(SRC1).asUInt + input(SRC2).asUInt).asBits + val sub = (input(SRC1).asUInt - input(SRC2).asUInt).asBits - // SLT, SLTU - val less = Mux(input(SRC1).msb === input(SRC2).msb, addSub.msb, - Mux(input(SRC_LESS_UNSIGNED), input(SRC2).msb, input(SRC1).msb)) + // SLT, SLTU + val less = Mux(input(SRC1).msb === input(SRC2).msb, sub.msb, + Mux(input(SRC_LESS_UNSIGNED), input(SRC2).msb, input(SRC1).msb)) - insert(SRC_ADD_SUB) := addSub.resized - insert(SRC_LESS) := less + insert(SRC_ADD_SUB) := input(SRC_USE_SUB_LESS) ? sub | add + insert(SRC_LESS) := less + } + }else{ + execute plug new Area { + import execute._ + + // ADD, SUB + val addSub = (input(SRC1).asSInt + Mux(input(SRC_USE_SUB_LESS), ~input(SRC2), input(SRC2)).asSInt + Mux(input(SRC_USE_SUB_LESS), S(1), S(0))).asBits + + // SLT, SLTU + val less = Mux(input(SRC1).msb === input(SRC2).msb, addSub.msb, + Mux(input(SRC_LESS_UNSIGNED), input(SRC2).msb, input(SRC1).msb)) + + insert(SRC_ADD_SUB) := addSub + insert(SRC_LESS) := less + } } } } diff --git a/src/main/scala/SpinalRiscv/TopLevel.scala b/src/main/scala/SpinalRiscv/TopLevel.scala index 0e7bc3a..f7c390b 100644 --- a/src/main/scala/SpinalRiscv/TopLevel.scala +++ b/src/main/scala/SpinalRiscv/TopLevel.scala @@ -118,10 +118,20 @@ object TopLevel { zeroBoot = true ), new IntAluPlugin, - new SrcPlugin, + new SrcPlugin( + separatedAddSub = false + ), new FullBarrielShifterPlugin, // new LightShifterPlugin, - new HazardSimplePlugin(true, true, true, true), + new HazardSimplePlugin( + bypassExecute = true, + bypassMemory = true, + bypassWriteBack = true, + bypassWriteBackBuffer = true, + pessimisticUseSrc = false, + pessimisticWriteRegFile = false, + pessimisticAddressMatch = false + ), // new HazardSimplePlugin(false, true, false, true), // new HazardSimplePlugin(false, false, false, false), new MulPlugin, @@ -153,16 +163,26 @@ object TopLevel { catchIllegalInstruction = false ), new RegFilePlugin( - regFileReadyKind = Plugin.SYNC, + regFileReadyKind = Plugin.ASYNC, zeroBoot = false ), new IntAluPlugin, - new SrcPlugin, + new SrcPlugin( + separatedAddSub = false + ), // new FullBarrielShifterPlugin, new LightShifterPlugin, // new HazardSimplePlugin(true, true, true, true), // new HazardSimplePlugin(false, true, false, true), - new HazardSimplePlugin(false, false, false, false), + new HazardSimplePlugin( + bypassExecute = false, + bypassMemory = false, + bypassWriteBack = false, + bypassWriteBackBuffer = false, + pessimisticUseSrc = false, + pessimisticWriteRegFile = false, + pessimisticAddressMatch = false + ), // new MulPlugin, // new DivPlugin, // new MachineCsr(csrConfig), @@ -173,8 +193,59 @@ object TopLevel { ) ) + + val configTest = VexRiscvConfig( + pcWidth = 32 + ) + + configTest.plugins ++= List( + new PcManagerSimplePlugin(0x00000000l, false), + new IBusSimplePlugin( + interfaceKeepData = true, + catchAccessFault = false + ), + + new DBusSimplePlugin( + catchAddressMisaligned = false, + catchAccessFault = false + ), + new DecoderSimplePlugin( + catchIllegalInstruction = false + ), + new RegFilePlugin( + regFileReadyKind = Plugin.ASYNC, + zeroBoot = false + ), + new IntAluPlugin, + new SrcPlugin( + separatedAddSub = false + ), + new FullBarrielShifterPlugin, +// new LightShifterPlugin, + // new HazardSimplePlugin(true, true, true, true), + // new HazardSimplePlugin(false, true, false, true), + new HazardSimplePlugin( + bypassExecute = true, + bypassMemory = true, + bypassWriteBack = true, + bypassWriteBackBuffer = true, + pessimisticUseSrc = false, + pessimisticWriteRegFile = false, + pessimisticAddressMatch = false + ), +// new MulPlugin, +// new DivPlugin, + // new MachineCsr(csrConfig), + new BranchPlugin( + earlyBranch = false, + catchAddressMisaligned = false, + prediction = NONE + ) + ) + val toplevel = new VexRiscv(configFull) // val toplevel = new VexRiscv(configLight) +// val toplevel = new VexRiscv(configTest) toplevel.decode.input(toplevel.config.INSTRUCTION).addAttribute("verilator public") toplevel.decode.input(toplevel.config.PC).addAttribute("verilator public") toplevel.decode.arbitration.isValid.addAttribute("verilator public") diff --git a/src/test/cpp/testA/main.cpp b/src/test/cpp/testA/main.cpp index 09011d1..0b50faf 100644 --- a/src/test/cpp/testA/main.cpp +++ b/src/test/cpp/testA/main.cpp @@ -194,7 +194,7 @@ public: virtual void iBusAccess(uint32_t addr, uint32_t *data, bool *error) { - assert(addr % 4 == 0); + assertEq(addr % 4, 0); *data = ( (mem[addr + 0] << 0) | (mem[addr + 1] << 8) | (mem[addr + 2] << 16) @@ -202,6 +202,7 @@ public: *error = addr == 0xF00FFF60u; } virtual void dBusAccess(uint32_t addr,bool wr, uint32_t size,uint32_t mask, uint32_t *data, bool *error) { + assertEq(addr % (1 << size), 0); *error = addr == 0xF00FFF60u; if(wr){ memTraces <<