From 0086de9e36ee07fadaceac9a40548769836e7aab Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Tue, 20 Nov 2018 19:39:17 +0100 Subject: [PATCH] Fix CsrPlugin catch illegalAccess Add dhrystone optimized divider cleaning --- README.md | 3 ++- src/main/scala/vexriscv/Stage.scala | 3 ++- src/main/scala/vexriscv/VexRiscv.scala | 11 ++++---- .../demo/GenNoCacheNoMmuMaxPerf.scala | 2 +- src/main/scala/vexriscv/ip/DataCache.scala | 23 ++++++++++++++++ .../scala/vexriscv/plugin/CsrPlugin.scala | 4 ++- .../plugin/MulDivIterativePlugin.scala | 26 ++++++++++++++++++- 7 files changed, 62 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a5f64d8..043ab87 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ This repository hosts a RISC-V implementation written in SpinalHDL. Here are som - RV32I[M] instruction set - Pipelined with 5 stages (Fetch, Decode, Execute, Memory, WriteBack) -- 1.44 DMIPS/Mhz when all features are enabled +- 1.44 DMIPS/Mhz --no-inline when nearly all features are enabled (1.57 DMIPS/Mhz when the divider lookup table is enabled) - Optimized for FPGA, fully portable - AXI4 and Avalon ready - Optional MUL/DIV extensions @@ -38,6 +38,7 @@ This repository hosts a RISC-V implementation written in SpinalHDL. Here are som - Optional interrupts and exception handling with Machine and User modes as defined in the [RISC-V Privileged ISA Specification v1.9](https://riscv.org/specifications/privileged-isa/). - Two implementations of shift instructions: Single cycle and shiftNumber cycles - Each stage can have optional bypass or interlock hazard logic +- Zephyr RISC-V port compatible - [FreeRTOS port](https://github.com/Dolu1990/FreeRTOS-RISCV) - The data cache supports atomic LR/SC - Optional RV32 compressed instruction support in the reworkFetch branch for configurations without instruction cache (will be merge in master, WIP) diff --git a/src/main/scala/vexriscv/Stage.scala b/src/main/scala/vexriscv/Stage.scala index 22a7e9f..d54127c 100644 --- a/src/main/scala/vexriscv/Stage.scala +++ b/src/main/scala/vexriscv/Stage.scala @@ -6,7 +6,8 @@ import spinal.lib._ import scala.collection.mutable -class Stageable[T <: Data](val dataType : T) extends HardType[T](dataType) with Nameable{ +class Stageable[T <: Data](_dataType : => T) extends HardType[T](_dataType) with Nameable{ + def dataType = apply() setWeakName(this.getClass.getSimpleName.replace("$","")) } diff --git a/src/main/scala/vexriscv/VexRiscv.scala b/src/main/scala/vexriscv/VexRiscv.scala index 6698586..01ce0ca 100644 --- a/src/main/scala/vexriscv/VexRiscv.scala +++ b/src/main/scala/vexriscv/VexRiscv.scala @@ -82,11 +82,12 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{ type T = VexRiscv import config._ - stages ++= List.fill(2 + (if(withMemoryStage) 1 else 0) + (if(withWriteBackStage) 1 else 0))(new Stage()) - val decode = stages(0) - val execute = stages(1) - val memory = ifGen(withMemoryStage) (stages(2)) - val writeBack = ifGen(withWriteBackStage) (stages(3)) + //Define stages + def newStage(): Stage = { val s = new Stage; stages += s; s } + val decode = newStage() + val execute = newStage() + val memory = ifGen(config.withMemoryStage) (newStage()) + val writeBack = ifGen(config.withWriteBackStage) (newStage()) def stagesFromExecute = stages.dropWhile(_ != execute) diff --git a/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala b/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala index b727b37..89dffe0 100644 --- a/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala +++ b/src/main/scala/vexriscv/demo/GenNoCacheNoMmuMaxPerf.scala @@ -52,7 +52,7 @@ object GenNoCacheNoMmuMaxPerf extends App{ pessimisticAddressMatch = false ), new MulPlugin, - new DivPlugin, + new MulDivIterativePlugin(genMul = false, genDiv = true, mulUnrollFactor = 1, divUnrollFactor = 1,dhrystoneOpt = false), new CsrPlugin(CsrPluginConfig.small), new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new BranchPlugin( diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index 3ce2a8b..8853820 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -6,6 +6,7 @@ import spinal.lib._ import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4Shared} import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig} import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig} +import vexriscv.demo.SimpleBus case class DataCacheConfig( cacheSize : Int, bytePerLine : Int, @@ -342,6 +343,28 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave rsp.error := False //TODO bus } + + + + def toSimpleBus(): SimpleBus = { + val bus = SimpleBus(32,32) + + val counter = Reg(UInt(log2Up(p.burstSize) bits)) init(0) + when(bus.cmd.fire){ counter := counter + 1 } + when( cmd.fire && cmd.last){ counter := 0 } + + bus.cmd.valid := cmd.valid + bus.cmd.address := (cmd.address(31 downto 2) | counter.resized) @@ U"00" + bus.cmd.wr := cmd.wr + bus.cmd.mask := cmd.mask + bus.cmd.data := cmd.data + cmd.ready := bus.cmd.ready && (cmd.wr || counter === cmd.length) + rsp.valid := bus.rsp.valid + rsp.data := bus.rsp.payload.data + rsp.error := False + bus + } + } diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index e209e68..6ad56a6 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -761,7 +761,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception def previousStage = decode val blockedBySideEffects = stagesFromExecute.tail.map(s => s.arbitration.isValid).asBits().orR // && s.input(HAS_SIDE_EFFECT) to improve be less pessimistic - val illegalAccess = arbitration.isValid && input(IS_CSR) + val illegalAccess = True val illegalInstruction = False if(selfException != null) { selfException.valid := False @@ -879,7 +879,9 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception } } } + illegalAccess setWhen(privilege < csrAddress(9 downto 8).asUInt) + illegalAccess clearWhen(!arbitration.isValid || !input(IS_CSR)) }) } } diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala index 0619a27..f366854 100644 --- a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala @@ -10,8 +10,16 @@ object MulDivIterativePlugin{ object IS_REM extends Stageable(Bool) object IS_RS1_SIGNED extends Stageable(Bool) object IS_RS2_SIGNED extends Stageable(Bool) + object FAST_DIV_VALID extends Stageable(Bool) + object FAST_DIV_VALUE extends Stageable(UInt(4 bits)) } -class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mulUnrollFactor : Int = 1, divUnrollFactor : Int = 1, customMul : (UInt, UInt, Stage, VexRiscv) => Area = null) extends Plugin[VexRiscv]{ + +class MulDivIterativePlugin(genMul : Boolean = true, + genDiv : Boolean = true, + mulUnrollFactor : Int = 1, + divUnrollFactor : Int = 1, + dhrystoneOpt : Boolean = false, + customMul : (UInt, UInt, Stage, VexRiscv) => Area = null) extends Plugin[VexRiscv]{ import MulDivIterativePlugin._ override def setup(pipeline: VexRiscv): Unit = { @@ -131,6 +139,11 @@ class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mu } output(REGFILE_WRITE_DATA) := result +// when(input(INSTRUCTION)(13 downto 12) === "00" && counter === 0 && rs2 =/= 0 && rs1 < 16 && rs2 < 16 && !input(RS1).msb && !input(RS2).msb) { +// output(REGFILE_WRITE_DATA) := B(rs1(3 downto 0) / rs2(3 downto 0)).resized +// counter.willIncrement := False +// arbitration.haltItself := False +// } } }) @@ -148,6 +161,17 @@ class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mu if(genDiv) div.needRevert := (rs1NeedRevert ^ (rs2NeedRevert && !execute.input(INSTRUCTION)(13))) && !(execute.input(RS2) === 0 && execute.input(IS_RS2_SIGNED) && !execute.input(INSTRUCTION)(13)) if(genDiv) div.counter.clear() } + + if(dhrystoneOpt) { + execute.insert(FAST_DIV_VALID) := execute.input(IS_DIV) && execute.input(INSTRUCTION)(13 downto 12) === "00" && !execute.input(RS1).msb && !execute.input(RS2).msb && execute.input(RS1).asUInt < 16 && execute.input(RS2).asUInt < 16 && execute.input(RS2) =/= 0 + execute.insert(FAST_DIV_VALUE) := (0 to 15).flatMap(n => (0 to 15).map(d => U(if (d == 0) 0 else n / d, 4 bits))).read(U(execute.input(RS1)(3 downto 0)) @@ U(execute.input(RS2)(3 downto 0))) //(U(execute.input(RS1)(3 downto 0)) / U(execute.input(RS2)(3 downto 0)) + when(execute.input(FAST_DIV_VALID)) { + execute.output(IS_DIV) := False + } + when(input(FAST_DIV_VALID)) { + output(REGFILE_WRITE_DATA) := B(0, 28 bits) ## input(FAST_DIV_VALUE) + } + } } } }