Add many little options to reduce area
This commit is contained in:
parent
fb9ea11a5e
commit
0d92a5e5cd
|
@ -47,6 +47,11 @@ trait ExceptionInhibitor{
|
|||
def inhibateException() : Unit
|
||||
}
|
||||
|
||||
trait RegFileService{
|
||||
def readStage() : Stage
|
||||
}
|
||||
|
||||
|
||||
case class MemoryTranslatorCmd() extends Bundle{
|
||||
val isValid = Bool
|
||||
val virtualAddress = UInt(32 bits)
|
||||
|
|
|
@ -192,7 +192,7 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
//Apply branchs (JAL,JALR, Bxx)
|
||||
branchStage plug new Area {
|
||||
import branchStage._
|
||||
jumpInterface.valid := arbitration.isFiring && input(BRANCH_DO)
|
||||
jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO)
|
||||
jumpInterface.payload := input(BRANCH_CALC)
|
||||
|
||||
when(jumpInterface.valid) {
|
||||
|
@ -272,7 +272,7 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
val branchStage = if(earlyBranch) execute else memory
|
||||
branchStage plug new Area {
|
||||
import branchStage._
|
||||
jumpInterface.valid := input(BRANCH_DO) && arbitration.isFiring
|
||||
jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && input(BRANCH_DO)
|
||||
jumpInterface.payload := input(BRANCH_CALC)
|
||||
|
||||
when(jumpInterface.valid) {
|
||||
|
@ -349,7 +349,7 @@ class BranchPlugin(earlyBranch : Boolean,
|
|||
input(PC)
|
||||
}
|
||||
|
||||
jumpInterface.valid := arbitration.isFiring && predictionMissmatch //Probably just isValid instead of isFiring is better
|
||||
jumpInterface.valid := arbitration.isValid && !arbitration.isStuckByOthers && predictionMissmatch //Probably just isValid instead of isFiring is better
|
||||
jumpInterface.payload := (input(BRANCH_DO) ? input(BRANCH_CALC) | input(NEXT_PC))
|
||||
|
||||
|
||||
|
|
|
@ -763,9 +763,13 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
val illegalAccess = arbitration.isValid && input(IS_CSR)
|
||||
val illegalInstruction = False
|
||||
if(selfException != null) {
|
||||
selfException.valid := illegalAccess || illegalInstruction
|
||||
selfException.code := 2
|
||||
selfException.valid := False
|
||||
selfException.code.assignDontCare()
|
||||
selfException.badAddr.assignDontCare()
|
||||
if(catchIllegalAccess) when(illegalAccess || illegalInstruction){
|
||||
selfException.valid := True
|
||||
selfException.code := 2
|
||||
}
|
||||
}
|
||||
|
||||
//Manage MRET / SRET instructions
|
||||
|
@ -796,9 +800,9 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
val readData = B(0, 32 bits)
|
||||
val writeInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE)
|
||||
val readInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE)
|
||||
val writeEnable = writeInstruction && ! blockedBySideEffects // && readDataRegValid
|
||||
val readEnable = readInstruction && ! blockedBySideEffects // && !readDataRegValid
|
||||
|
||||
val writeEnable = writeInstruction && ! blockedBySideEffects && !arbitration.isStuckByOthers// && readDataRegValid
|
||||
val readEnable = readInstruction && ! blockedBySideEffects && !arbitration.isStuckByOthers// && !readDataRegValid
|
||||
//arbitration.isStuckByOthers, in case of the hazardPlugin is in the executeStage
|
||||
|
||||
|
||||
// def readDataReg = memory.input(REGFILE_WRITE_DATA) //PIPE OPT
|
||||
|
|
|
@ -197,9 +197,12 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
object ALIGNEMENT_FAULT extends Stageable(Bool)
|
||||
|
||||
var memoryExceptionPort : Flow[ExceptionCause] = null
|
||||
var rspStage : Stage = null
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import Riscv._
|
||||
import pipeline.config._
|
||||
import pipeline._
|
||||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
|
||||
|
@ -230,7 +233,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
|
||||
|
||||
|
||||
val rspStage = if(emitCmdInMemoryStage) pipeline.writeBack else pipeline.memory
|
||||
rspStage = if(stages.last == execute) execute else (if(emitCmdInMemoryStage) writeBack else memory)
|
||||
if(catchAccessFault || catchAddressMisaligned) {
|
||||
val exceptionService = pipeline.service(classOf[ExceptionService])
|
||||
memoryExceptionPort = exceptionService.newExceptionPort(rspStage)
|
||||
|
@ -243,11 +246,14 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
|
||||
dBus = master(DBusSimpleBus()).setName("dBus")
|
||||
|
||||
|
||||
//Emit dBus.cmd request
|
||||
val cmdStage = if(emitCmdInMemoryStage) memory else execute
|
||||
cmdStage plug new Area{
|
||||
import cmdStage._
|
||||
|
||||
val cmdSent = if(rspStage == execute) RegInit(False) setWhen(dBus.cmd.fire) clearWhen(!execute.arbitration.isStuck) else False
|
||||
|
||||
insert(ALIGNEMENT_FAULT) := {
|
||||
if (catchAddressMisaligned)
|
||||
(dBus.cmd.size === 2 && dBus.cmd.address(1 downto 0) =/= 0) || (dBus.cmd.size === 1 && dBus.cmd.address(0 downto 0) =/= 0)
|
||||
|
@ -255,7 +261,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
False
|
||||
}
|
||||
|
||||
dBus.cmd.valid := arbitration.isValid && input(MEMORY_ENABLE) && !arbitration.isStuckByOthers && !arbitration.isFlushed && !input(ALIGNEMENT_FAULT)
|
||||
dBus.cmd.valid := arbitration.isValid && input(MEMORY_ENABLE) && !arbitration.isStuckByOthers && !arbitration.isFlushed && !input(ALIGNEMENT_FAULT) && !cmdSent
|
||||
dBus.cmd.wr := input(INSTRUCTION)(5)
|
||||
dBus.cmd.address := input(SRC_ADD).asUInt
|
||||
dBus.cmd.size := input(INSTRUCTION)(13 downto 12).asUInt
|
||||
|
@ -264,7 +270,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
U(1) -> input(RS2)(15 downto 0) ## input(RS2)(15 downto 0),
|
||||
default -> input(RS2)(31 downto 0)
|
||||
)
|
||||
when(arbitration.isValid && input(MEMORY_ENABLE) && !dBus.cmd.ready && !input(ALIGNEMENT_FAULT)){
|
||||
when(arbitration.isValid && input(MEMORY_ENABLE) && !dBus.cmd.ready && !input(ALIGNEMENT_FAULT) && !cmdSent){
|
||||
arbitration.haltItself := True
|
||||
}
|
||||
|
||||
|
@ -283,9 +289,8 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
}
|
||||
|
||||
//Collect dBus.rsp read responses
|
||||
val rspStage = if(emitCmdInMemoryStage) writeBack else memory
|
||||
rspStage plug new Area {
|
||||
import rspStage._
|
||||
val s = rspStage; import s._
|
||||
|
||||
|
||||
insert(MEMORY_READ_DATA) := dBus.rsp.data
|
||||
|
@ -313,7 +318,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
}
|
||||
|
||||
|
||||
assert(!(dBus.rsp.ready && input(MEMORY_ENABLE) && arbitration.isValid && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend")
|
||||
if(rspStage != execute) assert(!(dBus.rsp.ready && input(MEMORY_ENABLE) && arbitration.isValid && arbitration.isStuck),"DBusSimplePlugin doesn't allow memory stage stall when read happend")
|
||||
}
|
||||
|
||||
//Reformat read responses, REGFILE_WRITE_DATA overriding
|
||||
|
|
|
@ -19,6 +19,6 @@ class HazardPessimisticPlugin() extends Plugin[VexRiscv] {
|
|||
import pipeline.config._
|
||||
|
||||
val writesInPipeline = stages.dropWhile(_ != execute).map(s => s.arbitration.isValid && s.input(REGFILE_WRITE_VALID)) :+ RegNext(stages.last.arbitration.isValid && stages.last.input(REGFILE_WRITE_VALID))
|
||||
decode.arbitration.haltItself.setWhen(decode.arbitration.isValid && writesInPipeline.orR)
|
||||
decode.arbitration.haltByOther.setWhen(decode.arbitration.isValid && writesInPipeline.orR)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,18 +26,20 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
|
|||
val src0Hazard = False
|
||||
val src1Hazard = False
|
||||
|
||||
val readStage = service(classOf[RegFileService]).readStage()
|
||||
|
||||
def trackHazardWithStage(stage : Stage,bypassable : Boolean, runtimeBypassable : Stageable[Bool]): Unit ={
|
||||
val runtimeBypassableValue = if(runtimeBypassable != null) stage.input(runtimeBypassable) else True
|
||||
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)
|
||||
val addr0Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs1Range)
|
||||
val addr1Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs2Range)
|
||||
when(stage.arbitration.isValid && stage.input(REGFILE_WRITE_VALID)) {
|
||||
if (bypassable) {
|
||||
when(runtimeBypassableValue) {
|
||||
when(addr0Match) {
|
||||
decode.input(RS1) := stage.output(REGFILE_WRITE_DATA)
|
||||
readStage.input(RS1) := stage.output(REGFILE_WRITE_DATA)
|
||||
}
|
||||
when(addr1Match) {
|
||||
decode.input(RS2) := stage.output(REGFILE_WRITE_DATA)
|
||||
readStage.input(RS2) := stage.output(REGFILE_WRITE_DATA)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,15 +66,15 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
|
|||
writeBackWrites.data := stages.last.output(REGFILE_WRITE_DATA)
|
||||
val writeBackBuffer = writeBackWrites.stage()
|
||||
|
||||
val addr0Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === decode.input(INSTRUCTION)(rs1Range)
|
||||
val addr1Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === decode.input(INSTRUCTION)(rs2Range)
|
||||
val addr0Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === readStage.input(INSTRUCTION)(rs1Range)
|
||||
val addr1Match = if(pessimisticAddressMatch) True else writeBackBuffer.address === readStage.input(INSTRUCTION)(rs2Range)
|
||||
when(writeBackBuffer.valid) {
|
||||
if (bypassWriteBackBuffer) {
|
||||
when(addr0Match) {
|
||||
decode.input(RS1) := writeBackBuffer.data
|
||||
readStage.input(RS1) := writeBackBuffer.data
|
||||
}
|
||||
when(addr1Match) {
|
||||
decode.input(RS2) := writeBackBuffer.data
|
||||
readStage.input(RS2) := writeBackBuffer.data
|
||||
}
|
||||
} else {
|
||||
when(addr0Match) {
|
||||
|
@ -86,20 +88,20 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
|
|||
|
||||
if(withWriteBackStage) trackHazardWithStage(writeBack,bypassWriteBack,null)
|
||||
if(withMemoryStage) trackHazardWithStage(memory ,bypassMemory ,BYPASSABLE_MEMORY_STAGE)
|
||||
trackHazardWithStage(execute ,bypassExecute , if(stages.last == execute) null else BYPASSABLE_EXECUTE_STAGE)
|
||||
if(readStage != execute) trackHazardWithStage(execute ,bypassExecute , if(stages.last == execute) null else BYPASSABLE_EXECUTE_STAGE)
|
||||
|
||||
|
||||
if(!pessimisticUseSrc) {
|
||||
when(!decode.input(RS1_USE)) {
|
||||
when(!readStage.input(RS1_USE)) {
|
||||
src0Hazard := False
|
||||
}
|
||||
when(!decode.input(RS2_USE)) {
|
||||
when(!readStage.input(RS2_USE)) {
|
||||
src1Hazard := False
|
||||
}
|
||||
}
|
||||
|
||||
when(decode.arbitration.isValid && (src0Hazard || src1Hazard)){
|
||||
decode.arbitration.haltItself := True
|
||||
when(readStage.arbitration.isValid && (src0Hazard || src1Hazard)){
|
||||
readStage.arbitration.haltByOther := True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,7 +153,8 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
busLatencyMin : Int = 1,
|
||||
pendingMax : Int = 7,
|
||||
injectorStage : Boolean = true,
|
||||
rspHoldValue : Boolean = false
|
||||
rspHoldValue : Boolean = false,
|
||||
singleInstructionPipeline : Boolean = false
|
||||
) extends IBusFetcherImpl(
|
||||
resetVector = resetVector,
|
||||
keepPcPlus4 = keepPcPlus4,
|
||||
|
@ -168,7 +169,7 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
|
||||
var iBus : IBusSimpleBus = null
|
||||
var decodeExceptionPort : Flow[ExceptionCause] = null
|
||||
if(rspHoldValue) assert(busLatencyMin == 1)
|
||||
if(rspHoldValue) assert(busLatencyMin <= 1)
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
super.setup(pipeline)
|
||||
|
@ -197,6 +198,11 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
//This implementation keep the cmd on the bus until it's executed or the the pipeline is flushed
|
||||
def stage = iBusRsp.stages(if(cmdForkOnSecondStage) 1 else 0)
|
||||
stage.halt setWhen(stage.input.valid && (!cmd.valid || !cmd.ready))
|
||||
if(singleInstructionPipeline) {
|
||||
cmd.valid := stage.input.valid && pendingCmd =/= pendingMax && !stages.map(_.arbitration.isValid).orR
|
||||
assert(injectorStage == false)
|
||||
assert(iBusRsp.stages.dropWhile(_ != stage).length <= 2)
|
||||
}else
|
||||
cmd.valid := stage.input.valid && stage.output.ready && pendingCmd =/= pendingMax
|
||||
cmd.pc := stage.input.payload(31 downto 2) @@ "00"
|
||||
} else new Area{
|
||||
|
@ -230,7 +236,10 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
c.io.flush := flush
|
||||
rspBufferOutput << c.io.pop
|
||||
} else new Area{
|
||||
rspBufferOutput << iBus.rsp.throwWhen(discardCounter =/= 0).toStream
|
||||
val rspStream = iBus.rsp.throwWhen(discardCounter =/= 0).toStream
|
||||
val validReg = RegInit(False) setWhen(rspStream.valid) clearWhen(rspBufferOutput.ready)
|
||||
rspBufferOutput << rspStream
|
||||
rspBufferOutput.valid setWhen(validReg)
|
||||
}
|
||||
|
||||
val fetchRsp = FetchRsp()
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package vexriscv.plugin
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import vexriscv._
|
||||
|
||||
|
||||
class NoPipeliningPlugin() extends Plugin[VexRiscv] {
|
||||
|
||||
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 = {
|
||||
import pipeline._
|
||||
import pipeline.config._
|
||||
|
||||
val writesInPipeline = stages.dropWhile(_ != execute).map(s => s.arbitration.isValid && s.input(REGFILE_WRITE_VALID)) :+ RegNext(stages.last.arbitration.isValid && stages.last.input(REGFILE_WRITE_VALID))
|
||||
decode.arbitration.haltByOther.setWhen(stagesFromExecute.map(_.arbitration.isValid).orR)
|
||||
}
|
||||
}
|
|
@ -13,13 +13,17 @@ object SYNC extends RegFileReadKind
|
|||
|
||||
class RegFilePlugin(regFileReadyKind : RegFileReadKind,
|
||||
zeroBoot : Boolean = false,
|
||||
x0Init : Boolean = true,
|
||||
writeRfInMemoryStage : Boolean = false,
|
||||
readInExecute : Boolean = false) extends Plugin[VexRiscv]{
|
||||
readInExecute : Boolean = false,
|
||||
syncUpdateOnStall : Boolean = true) extends Plugin[VexRiscv] with RegFileService{
|
||||
import Riscv._
|
||||
|
||||
// assert(!writeRfInMemoryStage)
|
||||
|
||||
|
||||
override def readStage(): Stage = if(readInExecute) pipeline.execute else pipeline.decode
|
||||
|
||||
override def setup(pipeline: VexRiscv): Unit = {
|
||||
import pipeline.config._
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
|
@ -51,7 +55,7 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
|
|||
val srcInstruction = regFileReadyKind match{
|
||||
case `ASYNC` => input(INSTRUCTION)
|
||||
case `SYNC` if !readInExecute => input(INSTRUCTION_ANTICIPATED)
|
||||
case `SYNC` if readInExecute => Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION))
|
||||
case `SYNC` if readInExecute => if(syncUpdateOnStall) Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION)) else decode.input(INSTRUCTION)
|
||||
}
|
||||
|
||||
val regFileReadAddress1 = srcInstruction(Riscv.rs1Range).asUInt
|
||||
|
@ -59,7 +63,9 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
|
|||
|
||||
val (rs1Data,rs2Data) = regFileReadyKind match{
|
||||
case `ASYNC` => (global.regFile.readAsync(regFileReadAddress1),global.regFile.readAsync(regFileReadAddress2))
|
||||
case `SYNC` => (global.regFile.readSync(regFileReadAddress1),global.regFile.readSync(regFileReadAddress2))
|
||||
case `SYNC` =>
|
||||
val enable = if(!syncUpdateOnStall) !readStage.arbitration.isStuck else null
|
||||
(global.regFile.readSync(regFileReadAddress1, enable),global.regFile.readSync(regFileReadAddress2, enable))
|
||||
}
|
||||
|
||||
insert(RS1) := rs1Data
|
||||
|
@ -77,10 +83,19 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind,
|
|||
regFileWrite.data := output(REGFILE_WRITE_DATA)
|
||||
|
||||
//CPU will initialise constant register zero in the first cycle
|
||||
regFileWrite.valid setWhen(RegNext(False) init(True))
|
||||
if(x0Init) {
|
||||
val boot = RegNext(False) init (True)
|
||||
regFileWrite.valid setWhen (boot)
|
||||
if (writeStage != execute) {
|
||||
inputInit[Bits](REGFILE_WRITE_DATA, 0)
|
||||
inputInit[Bits](INSTRUCTION, 0)
|
||||
}
|
||||
|
||||
} else {
|
||||
when(boot) {
|
||||
regFileWrite.address := 0
|
||||
regFileWrite.data := 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -152,7 +152,8 @@ class LightShifterPlugin extends Plugin[VexRiscv]{
|
|||
val isShift = input(SHIFT_CTRL) =/= ShiftCtrlEnum.DISABLE
|
||||
val amplitudeReg = Reg(UInt(5 bits))
|
||||
val amplitude = isActive ? amplitudeReg | input(SRC2)(4 downto 0).asUInt
|
||||
val shiftInput = isActive ? memory.input(REGFILE_WRITE_DATA) | input(SRC1)
|
||||
val shiftReg = ifGen(!withMemoryStage) (RegNextWhen(execute.output(REGFILE_WRITE_DATA), !arbitration.isStuckByOthers))
|
||||
val shiftInput = isActive ? (if(withMemoryStage) memory.input(REGFILE_WRITE_DATA) else shiftReg) | input(SRC1)
|
||||
val done = amplitude(4 downto 1) === 0
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ cd VexRiscv
|
|||
sudo git init
|
||||
sudo git add *
|
||||
sudo git commit -m miaou
|
||||
export VEXRISCV_REGRESSION_CONFIG_COUNT=16
|
||||
export VEXRISCV_REGRESSION_CONFIG_COUNT=64
|
||||
export VEXRISCV_REGRESSION_FREERTOS_COUNT=yes
|
||||
sbt test
|
||||
cd ..
|
||||
|
|
Loading…
Reference in New Issue