Add many little options to reduce area

This commit is contained in:
Dolu1990 2018-11-12 14:14:34 +01:00
parent fb9ea11a5e
commit 0d92a5e5cd
11 changed files with 105 additions and 41 deletions

View File

@ -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)

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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)
}
}

View File

@ -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
}
}
}

View File

@ -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()

View File

@ -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)
}
}

View File

@ -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
}
}
}
}
}
}

View File

@ -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

View File

@ -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 ..