Fix CsrPlugin catch illegalAccess
Add dhrystone optimized divider cleaning
This commit is contained in:
parent
75d4d049d7
commit
0086de9e36
|
@ -28,7 +28,7 @@ This repository hosts a RISC-V implementation written in SpinalHDL. Here are som
|
||||||
|
|
||||||
- RV32I[M] instruction set
|
- RV32I[M] instruction set
|
||||||
- Pipelined with 5 stages (Fetch, Decode, Execute, Memory, WriteBack)
|
- 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
|
- Optimized for FPGA, fully portable
|
||||||
- AXI4 and Avalon ready
|
- AXI4 and Avalon ready
|
||||||
- Optional MUL/DIV extensions
|
- 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/).
|
- 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
|
- Two implementations of shift instructions: Single cycle and shiftNumber cycles
|
||||||
- Each stage can have optional bypass or interlock hazard logic
|
- Each stage can have optional bypass or interlock hazard logic
|
||||||
|
- Zephyr RISC-V port compatible
|
||||||
- [FreeRTOS port](https://github.com/Dolu1990/FreeRTOS-RISCV)
|
- [FreeRTOS port](https://github.com/Dolu1990/FreeRTOS-RISCV)
|
||||||
- The data cache supports atomic LR/SC
|
- 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)
|
- Optional RV32 compressed instruction support in the reworkFetch branch for configurations without instruction cache (will be merge in master, WIP)
|
||||||
|
|
|
@ -6,7 +6,8 @@ import spinal.lib._
|
||||||
import scala.collection.mutable
|
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("$",""))
|
setWeakName(this.getClass.getSimpleName.replace("$",""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,11 +82,12 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
|
||||||
type T = VexRiscv
|
type T = VexRiscv
|
||||||
import config._
|
import config._
|
||||||
|
|
||||||
stages ++= List.fill(2 + (if(withMemoryStage) 1 else 0) + (if(withWriteBackStage) 1 else 0))(new Stage())
|
//Define stages
|
||||||
val decode = stages(0)
|
def newStage(): Stage = { val s = new Stage; stages += s; s }
|
||||||
val execute = stages(1)
|
val decode = newStage()
|
||||||
val memory = ifGen(withMemoryStage) (stages(2))
|
val execute = newStage()
|
||||||
val writeBack = ifGen(withWriteBackStage) (stages(3))
|
val memory = ifGen(config.withMemoryStage) (newStage())
|
||||||
|
val writeBack = ifGen(config.withWriteBackStage) (newStage())
|
||||||
|
|
||||||
def stagesFromExecute = stages.dropWhile(_ != execute)
|
def stagesFromExecute = stages.dropWhile(_ != execute)
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ object GenNoCacheNoMmuMaxPerf extends App{
|
||||||
pessimisticAddressMatch = false
|
pessimisticAddressMatch = false
|
||||||
),
|
),
|
||||||
new MulPlugin,
|
new MulPlugin,
|
||||||
new DivPlugin,
|
new MulDivIterativePlugin(genMul = false, genDiv = true, mulUnrollFactor = 1, divUnrollFactor = 1,dhrystoneOpt = false),
|
||||||
new CsrPlugin(CsrPluginConfig.small),
|
new CsrPlugin(CsrPluginConfig.small),
|
||||||
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
|
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
|
||||||
new BranchPlugin(
|
new BranchPlugin(
|
||||||
|
|
|
@ -6,6 +6,7 @@ import spinal.lib._
|
||||||
import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4Shared}
|
import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4Shared}
|
||||||
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
|
||||||
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
|
||||||
|
import vexriscv.demo.SimpleBus
|
||||||
|
|
||||||
case class DataCacheConfig( cacheSize : Int,
|
case class DataCacheConfig( cacheSize : Int,
|
||||||
bytePerLine : Int,
|
bytePerLine : Int,
|
||||||
|
@ -342,6 +343,28 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave
|
||||||
rsp.error := False //TODO
|
rsp.error := False //TODO
|
||||||
bus
|
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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -761,7 +761,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
def previousStage = decode
|
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 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
|
val illegalInstruction = False
|
||||||
if(selfException != null) {
|
if(selfException != null) {
|
||||||
selfException.valid := False
|
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 setWhen(privilege < csrAddress(9 downto 8).asUInt)
|
||||||
|
illegalAccess clearWhen(!arbitration.isValid || !input(IS_CSR))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,16 @@ object MulDivIterativePlugin{
|
||||||
object IS_REM extends Stageable(Bool)
|
object IS_REM extends Stageable(Bool)
|
||||||
object IS_RS1_SIGNED extends Stageable(Bool)
|
object IS_RS1_SIGNED extends Stageable(Bool)
|
||||||
object IS_RS2_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._
|
import MulDivIterativePlugin._
|
||||||
|
|
||||||
override def setup(pipeline: VexRiscv): Unit = {
|
override def setup(pipeline: VexRiscv): Unit = {
|
||||||
|
@ -131,6 +139,11 @@ class MulDivIterativePlugin(genMul : Boolean = true, genDiv : Boolean = true, mu
|
||||||
}
|
}
|
||||||
|
|
||||||
output(REGFILE_WRITE_DATA) := result
|
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.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(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue