Add GenMicro experiment to reduce ice40 area usage.

IBusSimplePlugin now require cmdFork parameters to be set (no default)
This commit is contained in:
Dolu1990 2018-10-03 22:08:57 +02:00
parent 48bff80653
commit 0662cc2797
19 changed files with 180 additions and 30 deletions

View File

@ -33,14 +33,14 @@ object TestsWorkspace {
plugins = List( plugins = List(
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
cmdForkOnSecondStage = true, cmdForkOnSecondStage = false,
cmdForkPersistence = true, cmdForkPersistence = false,
prediction = NONE, prediction = NONE,
historyRamSizeLog2 = 10, historyRamSizeLog2 = 10,
catchAccessFault = true, catchAccessFault = true,
compressedGen = false, compressedGen = false,
busLatencyMin = 1, busLatencyMin = 1,
injectorStage = true injectorStage = false
), ),
// new IBusCachedPlugin( // new IBusCachedPlugin(
// resetVector = 0x80000000l, // resetVector = 0x80000000l,

View File

@ -16,6 +16,7 @@ object FormalSimple extends App{
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x00000000l, resetVector = 0x00000000l,
cmdForkOnSecondStage = false, cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = DYNAMIC_TARGET, prediction = DYNAMIC_TARGET,
catchAccessFault = false, catchAccessFault = false,
compressedGen = true compressedGen = true

View File

@ -19,6 +19,7 @@ object GenCustomCsr extends App{
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x00000000l, resetVector = 0x00000000l,
cmdForkOnSecondStage = false, cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = NONE, prediction = NONE,
catchAccessFault = false, catchAccessFault = false,
compressedGen = false compressedGen = false

View File

@ -15,6 +15,7 @@ object GenCustomSimdAdd extends App{
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x00000000l, resetVector = 0x00000000l,
cmdForkOnSecondStage = false, cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = NONE, prediction = NONE,
catchAccessFault = false, catchAccessFault = false,
compressedGen = false compressedGen = false

View File

@ -14,6 +14,7 @@ object GenDeterministicVex extends App{
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
cmdForkOnSecondStage = false, cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = STATIC, prediction = STATIC,
catchAccessFault = true, catchAccessFault = true,
compressedGen = false compressedGen = false

View File

@ -15,6 +15,7 @@ object GenFullNoMmuNoCache extends App{
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
cmdForkOnSecondStage = false, cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = STATIC, prediction = STATIC,
catchAccessFault = false, catchAccessFault = false,
compressedGen = false compressedGen = false

View File

@ -15,6 +15,7 @@ object GenNoCacheNoMmuMaxPerf extends App{
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
cmdForkOnSecondStage = false, cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = DYNAMIC_TARGET, prediction = DYNAMIC_TARGET,
historyRamSizeLog2 = 8, historyRamSizeLog2 = 8,
catchAccessFault = true, catchAccessFault = true,

View File

@ -14,6 +14,7 @@ object GenSmallAndProductive extends App{
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
cmdForkOnSecondStage = false, cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = NONE, prediction = NONE,
catchAccessFault = false, catchAccessFault = false,
compressedGen = false compressedGen = false

View File

@ -14,6 +14,7 @@ object GenSmallest extends App{
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
cmdForkOnSecondStage = false, cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = NONE, prediction = NONE,
catchAccessFault = false, catchAccessFault = false,
compressedGen = false compressedGen = false

View File

@ -19,6 +19,7 @@ object GenSmallestNoCsr extends App{
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
cmdForkOnSecondStage = false, cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = NONE, prediction = NONE,
catchAccessFault = false, catchAccessFault = false,
compressedGen = false compressedGen = false

View File

@ -498,6 +498,7 @@ object MuraxDhrystoneReadyMulDivStatic{
config.cpuPlugins += new IBusSimplePlugin( config.cpuPlugins += new IBusSimplePlugin(
resetVector = 0x80000000l, resetVector = 0x80000000l,
cmdForkOnSecondStage = true, cmdForkOnSecondStage = true,
cmdForkPersistence = false,
prediction = STATIC, prediction = STATIC,
catchAccessFault = false, catchAccessFault = false,
compressedGen = false compressedGen = false

View File

@ -29,6 +29,7 @@ object VexRiscvAvalonForSim{
new IBusSimplePlugin( new IBusSimplePlugin(
resetVector = 0x00000000l, resetVector = 0x00000000l,
cmdForkOnSecondStage = false, cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = STATIC, prediction = STATIC,
catchAccessFault = false, catchAccessFault = false,
compressedGen = false compressedGen = false

View File

@ -182,7 +182,10 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
} }
class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFault : Boolean = false, earlyInjection : Boolean = false/*, idempotentRegions : (UInt) => Bool = (x) => False*/) extends Plugin[VexRiscv]{ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
catchAccessFault : Boolean = false,
earlyInjection : Boolean = false,/*, idempotentRegions : (UInt) => Bool = (x) => False*/
onlyLoadWords : Boolean = false) extends Plugin[VexRiscv]{
var dBus : DBusSimpleBus = null var dBus : DBusSimpleBus = null
@ -220,7 +223,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
decoderService.addDefault(MEMORY_ENABLE, False) decoderService.addDefault(MEMORY_ENABLE, False)
decoderService.add( decoderService.add(
List(LB, LH, LW, LBU, LHU, LWU).map(_ -> loadActions) ++ (if(onlyLoadWords) List(LW) else List(LB, LH, LW, LBU, LHU, LWU)).map(_ -> loadActions) ++
List(SB, SH, SW).map(_ -> storeActions) List(SB, SH, SW).map(_ -> storeActions)
) )
@ -329,7 +332,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
) )
when(arbitration.isValid && input(MEMORY_ENABLE)) { when(arbitration.isValid && input(MEMORY_ENABLE)) {
output(REGFILE_WRITE_DATA) := rspFormated output(REGFILE_WRITE_DATA) := (if(!onlyLoadWords) rspFormated else input(MEMORY_READ_DATA))
} }
if(!earlyInjection) if(!earlyInjection)

View File

@ -28,7 +28,7 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
var dynamicTargetFailureCorrection : Flow[UInt] = null var dynamicTargetFailureCorrection : Flow[UInt] = null
var externalResetVector : UInt = null var externalResetVector : UInt = null
assert(cmdToRspStageCount >= 1) assert(cmdToRspStageCount >= 1)
assert(!(cmdToRspStageCount == 1 && !injectorStage)) // assert(!(cmdToRspStageCount == 1 && !injectorStage))
assert(!(compressedGen && !decodePcGen)) assert(!(compressedGen && !decodePcGen))
var fetcherHalt : Bool = null var fetcherHalt : Bool = null
var fetcherflushIt : Bool = null var fetcherflushIt : Bool = null

View File

@ -7,6 +7,13 @@ import spinal.lib._
class HazardPessimisticPlugin() extends Plugin[VexRiscv] { class HazardPessimisticPlugin() extends Plugin[VexRiscv] {
import Riscv._ import Riscv._
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(HAS_SIDE_EFFECT, False)
}
override def build(pipeline: VexRiscv): Unit = { override def build(pipeline: VexRiscv): Unit = {
import pipeline._ import pipeline._
import pipeline.config._ import pipeline.config._

View File

@ -143,16 +143,17 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
class IBusSimplePlugin(resetVector : BigInt, class IBusSimplePlugin(resetVector : BigInt,
cmdForkOnSecondStage : Boolean,
cmdForkPersistence : Boolean,
catchAccessFault : Boolean = false, catchAccessFault : Boolean = false,
cmdForkOnSecondStage : Boolean = false,
cmdForkPersistence : Boolean = false,
prediction : BranchPrediction = NONE, prediction : BranchPrediction = NONE,
historyRamSizeLog2 : Int = 10, historyRamSizeLog2 : Int = 10,
keepPcPlus4 : Boolean = false, keepPcPlus4 : Boolean = false,
compressedGen : Boolean = false, compressedGen : Boolean = false,
busLatencyMin : Int = 1, busLatencyMin : Int = 1,
pendingMax : Int = 7, pendingMax : Int = 7,
injectorStage : Boolean = true injectorStage : Boolean = true,
rspHoldValue : Boolean = false
) extends IBusFetcherImpl( ) extends IBusFetcherImpl(
catchAccessFault = catchAccessFault, catchAccessFault = catchAccessFault,
resetVector = resetVector, resetVector = resetVector,
@ -168,6 +169,7 @@ class IBusSimplePlugin(resetVector : BigInt,
var iBus : IBusSimpleBus = null var iBus : IBusSimpleBus = null
var decodeExceptionPort : Flow[ExceptionCause] = null var decodeExceptionPort : Flow[ExceptionCause] = null
if(rspHoldValue) assert(busLatencyMin == 1)
override def setup(pipeline: VexRiscv): Unit = { override def setup(pipeline: VexRiscv): Unit = {
super.setup(pipeline) super.setup(pipeline)
@ -221,22 +223,29 @@ class IBusSimplePlugin(resetVector : BigInt,
discardCounter := (if(cmdForkOnSecondStage) pendingCmdNext else pendingCmd - iBus.rsp.fire.asUInt) discardCounter := (if(cmdForkOnSecondStage) pendingCmdNext else pendingCmd - iBus.rsp.fire.asUInt)
} }
val rspBuffer = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0)) val rspBufferOutput = Stream(IBusSimpleRsp())
rspBuffer.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
rspBuffer.io.flush := flush val rspBuffer = if(!rspHoldValue) new Area{
val c = StreamFifoLowLatency(IBusSimpleRsp(), busLatencyMin + (if(cmdForkOnSecondStage && cmdForkPersistence) 1 else 0))
c.io.push << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
c.io.flush := flush
rspBufferOutput << c.io.pop
} else new Area{
rspBufferOutput << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
}
val fetchRsp = FetchRsp() val fetchRsp = FetchRsp()
fetchRsp.pc := stages.last.output.payload fetchRsp.pc := stages.last.output.payload
fetchRsp.rsp := rspBuffer.io.pop.payload fetchRsp.rsp := rspBufferOutput.payload
fetchRsp.rsp.error.clearWhen(!rspBuffer.io.pop.valid) //Avoid interference with instruction injection from the debug plugin fetchRsp.rsp.error.clearWhen(!rspBufferOutput.valid) //Avoid interference with instruction injection from the debug plugin
var issueDetected = False var issueDetected = False
val join = Stream(FetchRsp()) val join = Stream(FetchRsp())
join.valid := stages.last.output.valid && rspBuffer.io.pop.valid join.valid := stages.last.output.valid && rspBufferOutput.valid
join.payload := fetchRsp join.payload := fetchRsp
stages.last.output.ready := stages.last.output.valid ? join.fire | join.ready stages.last.output.ready := stages.last.output.valid ? join.fire | join.ready
rspBuffer.io.pop.ready := join.fire rspBufferOutput.ready := join.fire
output << join.haltWhen(issueDetected) output << join.haltWhen(issueDetected)
if(catchAccessFault){ if(catchAccessFault){

View File

@ -11,10 +11,14 @@ trait RegFileReadKind
object ASYNC extends RegFileReadKind object ASYNC extends RegFileReadKind
object SYNC extends RegFileReadKind object SYNC extends RegFileReadKind
class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = false, writeRfInMemoryStage : Boolean = false) extends Plugin[VexRiscv]{ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
zeroBoot : Boolean = false,
writeRfInMemoryStage : Boolean = false,
readInExecute : Boolean = false) extends Plugin[VexRiscv]{
import Riscv._ import Riscv._
assert(!writeRfInMemoryStage) // assert(!writeRfInMemoryStage)
override def setup(pipeline: VexRiscv): Unit = { override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._ import pipeline.config._
@ -33,19 +37,21 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = fals
if(zeroBoot) regFile.init(List.fill(32)(B(0, 32 bits))) if(zeroBoot) regFile.init(List.fill(32)(B(0, 32 bits)))
} }
//Read register file
decode plug new Area{
import decode._
//Disable rd0 write in decoding stage //Disable rd0 write in decoding stage
when(decode.input(INSTRUCTION)(rdRange) === 0) { when(decode.input(INSTRUCTION)(rdRange) === 0) {
decode.input(REGFILE_WRITE_VALID) := False decode.input(REGFILE_WRITE_VALID) := False
} }
//Read register file
val readStage = if(readInExecute) execute else decode
readStage plug new Area{
import readStage._
//read register file //read register file
val srcInstruction = regFileReadyKind match{ val srcInstruction = regFileReadyKind match{
case `ASYNC` => input(INSTRUCTION) case `ASYNC` => input(INSTRUCTION)
case `SYNC` => input(INSTRUCTION_ANTICIPATED) case `SYNC` if !readInExecute => input(INSTRUCTION_ANTICIPATED)
case `SYNC` if readInExecute => Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION))
} }
val regFileReadAddress1 = srcInstruction(Riscv.rs1Range).asUInt val regFileReadAddress1 = srcInstruction(Riscv.rs1Range).asUInt
@ -61,8 +67,9 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,zeroBoot : Boolean = fals
} }
//Write register file //Write register file
(if(writeRfInMemoryStage) memory else writeBack) plug new Area { val writeStage = if(writeRfInMemoryStage) memory else writeBack
import writeBack._ writeStage plug new Area {
import writeStage._
val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public) val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public)
regFileWrite.valid := output(REGFILE_WRITE_VALID) && arbitration.isFiring regFileWrite.valid := output(REGFILE_WRITE_VALID) && arbitration.isFiring

View File

@ -0,0 +1,113 @@
package vexriscv.experimental
import spinal.core._
import spinal.lib.eda.bench.{AlteraStdTargets, Bench, Rtl, XilinxStdTargets}
import spinal.lib.eda.icestorm.IcestormStdTargets
import vexriscv.demo.{GenSmallestNoCsr, Murax, MuraxConfig}
import vexriscv.plugin._
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
/**
* Created by spinalvm on 15.06.17.
*/
object GenMicro extends App{
def cpu() = {
val removeOneFetchStage = true
val writeBackOpt = true
val onlyLoadWords = true
val rspHoldValue = true
val earlyBranch = false
val noShifter = true
val pessimisticHazard = true
new VexRiscv(
config = VexRiscvConfig(
plugins = List(
// new PcManagerSimplePlugin(
// resetVector = 0x00000000l,
// relaxedPcCalculation = false
// ),
new IBusSimplePlugin(
resetVector = 0x80000000l,
cmdForkOnSecondStage = false,
cmdForkPersistence = false,
prediction = NONE,
catchAccessFault = false,
compressedGen = false,
injectorStage = !removeOneFetchStage,
rspHoldValue = rspHoldValue
),
new DBusSimplePlugin(
catchAddressMisaligned = false,
catchAccessFault = false,
earlyInjection = writeBackOpt,
onlyLoadWords = onlyLoadWords
),
new DecoderSimplePlugin(
catchIllegalInstruction = false
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
zeroBoot = false,
readInExecute = removeOneFetchStage,
writeRfInMemoryStage = writeBackOpt
),
new IntAluPlugin,
new SrcPlugin(
separatedAddSub = false,
executeInsertion = removeOneFetchStage
),
if(!pessimisticHazard)
new HazardSimplePlugin(
bypassExecute = false,
bypassMemory = false,
bypassWriteBack = false,
bypassWriteBackBuffer = false,
pessimisticUseSrc = false,
pessimisticWriteRegFile = false,
pessimisticAddressMatch = false
)
else
new HazardPessimisticPlugin(),
new BranchPlugin(
earlyBranch = earlyBranch,
catchAddressMisaligned = false
),
new YamlPlugin("cpu0.yaml")
) ++ (if(noShifter) Nil else List(new LightShifterPlugin))
)
)
}
SpinalConfig(mergeAsyncProcess = false).generateVerilog(cpu())
}
object GenMicroSynthesis {
def main(args: Array[String]) {
val microNoCsr = new Rtl {
override def getName(): String = "MicroNoCsr"
override def getRtlPath(): String = "MicroNoCsr.v"
SpinalVerilog(GenMicro.cpu().setDefinitionName(getRtlPath().split("\\.").head))
}
val smallestNoCsr = new Rtl {
override def getName(): String = "SmallestNoCsr"
override def getRtlPath(): String = "SmallestNoCsr.v"
SpinalVerilog(GenSmallestNoCsr.cpu().setDefinitionName(getRtlPath().split("\\.").head))
}
val rtls = List(microNoCsr)
// val rtls = List(smallestNoCsr)
val targets = IcestormStdTargets().take(1) ++ XilinxStdTargets(
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
) ++ AlteraStdTargets(
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin/",
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin/"
)
Bench(rtls, targets, "/eda/tmp/")
}
}

View File

@ -12,7 +12,7 @@ object Presentation extends App{
val config = VexRiscvConfig() val config = VexRiscvConfig()
config.plugins ++= List( config.plugins ++= List(
new IBusSimplePlugin(resetVector = 0x80000000l), // new IBusSimplePlugin(resetVector = 0x80000000l),
new DBusSimplePlugin, new DBusSimplePlugin,
new CsrPlugin(CsrPluginConfig.smallest), new CsrPlugin(CsrPluginConfig.smallest),
new DecoderSimplePlugin, new DecoderSimplePlugin,