diff --git a/src/main/scala/vexriscv/ip/InstructionCache.scala b/src/main/scala/vexriscv/ip/InstructionCache.scala index 508bf9f..8ba3ba4 100644 --- a/src/main/scala/vexriscv/ip/InstructionCache.scala +++ b/src/main/scala/vexriscv/ip/InstructionCache.scala @@ -6,6 +6,7 @@ import spinal.lib._ import spinal.lib.bus.amba4.axi.{Axi4Config, Axi4ReadOnly} import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig} import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig} +import vexriscv.demo.{SimpleBus, SimpleBusConfig} case class InstructionCacheConfig( cacheSize : Int, @@ -45,6 +46,11 @@ case class InstructionCacheConfig( cacheSize : Int, constantBurstBehavior = true ) + def getSimpleBusConfig() = SimpleBusConfig( + addressWidth = 32, + dataWidth = 32 + ) + def getWishboneConfig() = WishboneConfig( addressWidth = 30, dataWidth = 32, @@ -178,6 +184,24 @@ case class InstructionCacheMemBus(p : InstructionCacheConfig) extends Bundle wit mm } + + def toSimpleBus(): SimpleBus = { + val simpleBusConfig = p.getSimpleBusConfig() + val bus = SimpleBus(simpleBusConfig) + val counter = Counter(p.burstSize, bus.cmd.fire) + bus.cmd.valid := cmd.valid + bus.cmd.address := cmd.address(31 downto widthOf(counter.value) + 2) @@ counter @@ U"00" + bus.cmd.wr := False + bus.cmd.mask.assignDontCare() + bus.cmd.data.assignDontCare() + cmd.ready := counter.willOverflow + rsp.valid := bus.rsp.valid + rsp.data := bus.rsp.payload.data + rsp.error := False + bus + } + + def toWishbone(): Wishbone = { val wishboneConfig = p.getWishboneConfig() val bus = Wishbone(wishboneConfig) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index 7a68af6..e209e68 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -200,7 +200,8 @@ trait CsrInterface{ } def rw(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) rw(csrAddress,that._1, that._2) - def r [T <: Data](csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) r(csrAddress,that._1, that._2) + def w(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) w(csrAddress,that._1, that._2) + def r(csrAddress : Int, thats : (Int, Data)*) : Unit = for(that <- thats) r(csrAddress,that._1, that._2) def rw[T <: Data](csrAddress : Int, that : T): Unit = rw(csrAddress,0,that) def w[T <: Data](csrAddress : Int, that : T): Unit = w(csrAddress,0,that) def r [T <: Data](csrAddress : Int, that : T): Unit = r(csrAddress,0,that) diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala index 4c9ad88..3f4479c 100644 --- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala @@ -6,6 +6,7 @@ import spinal.lib._ import spinal.lib.bus.amba4.axi._ import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig} import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig} +import vexriscv.demo.SimpleBus import vexriscv.ip.DataCacheMemCmd @@ -131,11 +132,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{ mm.read := cmdStage.valid && !cmdStage.wr mm.write := cmdStage.valid && cmdStage.wr mm.address := (cmdStage.address >> 2) @@ U"00" - mm.writeData := cmdStage.size.mux ( - U(0) -> cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0) ## cmdStage.data(7 downto 0), - U(1) -> cmdStage.data(15 downto 0) ## cmdStage.data(15 downto 0), - default -> cmdStage.data(31 downto 0) - ) + mm.writeData := cmdStage.data(31 downto 0) mm.byteEnable := (cmdStage.size.mux ( U(0) -> B"0001", U(1) -> B"0011", @@ -179,6 +176,25 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{ rsp.error := False //TODO bus } + + def toSimpleBus() : SimpleBus = { + val bus = SimpleBus(32,32) + bus.cmd.valid := cmd.valid + bus.cmd.wr := cmd.wr + bus.cmd.address := cmd.address.resized + bus.cmd.data := cmd.data + bus.cmd.mask := cmd.size.mux( + 0 -> B"0001", + 1 -> B"0011", + default -> B"1111" + ) |<< cmd.address(1 downto 0) + cmd.ready := bus.cmd.ready + + rsp.ready := bus.rsp.valid + rsp.data := bus.rsp.data + + bus + } } @@ -311,9 +327,10 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, memoryExceptionPort.valid := True } } - when(!(arbitration.isValid && input(MEMORY_ENABLE))){ + when(!(arbitration.isValid && input(MEMORY_ENABLE) && (if(cmdStage == rspStage) !arbitration.isStuckByOthers else True))){ memoryExceptionPort.valid := False } + memoryExceptionPort.badAddr := input(REGFILE_WRITE_DATA).asUInt //Drived by IntAluPlugin } diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index cffc86a..756d372 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -6,6 +6,7 @@ import spinal.lib._ import spinal.lib.bus.amba4.axi._ import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig} import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig} +import vexriscv.demo.SimpleBus @@ -135,6 +136,18 @@ case class IBusSimpleBus(interfaceKeepData : Boolean = false) extends Bundle wit bus } + def toSimpleBus(): SimpleBus = { + val bus = SimpleBus(32,32) + bus.cmd.arbitrationFrom(cmd) + bus.cmd.address := cmd.pc.resized + bus.cmd.wr := False + bus.cmd.mask.assignDontCare() + bus.cmd.data.assignDontCare() + rsp.valid := bus.rsp.valid + rsp.inst := bus.rsp.payload.data + rsp.error := False + bus + } } @@ -202,8 +215,9 @@ class IBusSimplePlugin(resetVector : BigInt, cmd.valid := stage.input.valid && pendingCmd =/= pendingMax && !stages.map(_.arbitration.isValid).orR assert(injectorStage == false) assert(iBusRsp.stages.dropWhile(_ != stage).length <= 2) - }else + }else { cmd.valid := stage.input.valid && stage.output.ready && pendingCmd =/= pendingMax + } cmd.pc := stage.input.payload(31 downto 2) @@ "00" } else new Area{ //This implementation keep the cmd on the bus until it's executed, even if the pipeline is flushed diff --git a/src/main/scala/vexriscv/plugin/IntAluPlugin.scala b/src/main/scala/vexriscv/plugin/IntAluPlugin.scala index 2610aac..1b7467e 100644 --- a/src/main/scala/vexriscv/plugin/IntAluPlugin.scala +++ b/src/main/scala/vexriscv/plugin/IntAluPlugin.scala @@ -84,10 +84,10 @@ class IntAluPlugin extends Plugin[VexRiscv]{ import execute._ val bitwise = input(ALU_BITWISE_CTRL).mux( - AluBitwiseCtrlEnum.AND -> (input(SRC1) & input(SRC2)), - AluBitwiseCtrlEnum.OR -> (input(SRC1) | input(SRC2)), - AluBitwiseCtrlEnum.XOR -> (input(SRC1) ^ input(SRC2)), - AluBitwiseCtrlEnum.SRC1 -> input(SRC1) + AluBitwiseCtrlEnum.AND -> (input(SRC1) & input(SRC2)), + AluBitwiseCtrlEnum.OR -> (input(SRC1) | input(SRC2)), + AluBitwiseCtrlEnum.XOR -> (input(SRC1) ^ input(SRC2)), + AluBitwiseCtrlEnum.SRC1 -> input(SRC1) ) // mux results diff --git a/src/main/scala/vexriscv/plugin/RegFilePlugin.scala b/src/main/scala/vexriscv/plugin/RegFilePlugin.scala index 5f202b6..8bc561d 100644 --- a/src/main/scala/vexriscv/plugin/RegFilePlugin.scala +++ b/src/main/scala/vexriscv/plugin/RegFilePlugin.scala @@ -11,17 +11,17 @@ trait RegFileReadKind object ASYNC extends RegFileReadKind object SYNC extends RegFileReadKind + class RegFilePlugin(regFileReadyKind : RegFileReadKind, zeroBoot : Boolean = false, x0Init : Boolean = true, writeRfInMemoryStage : Boolean = false, readInExecute : Boolean = false, - syncUpdateOnStall : Boolean = true) extends Plugin[VexRiscv] with RegFileService{ + syncUpdateOnStall : Boolean = true, + withShadow : Boolean = false //shadow registers aren't transition hazard free + ) 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 = { @@ -36,9 +36,23 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind, import pipeline._ import pipeline.config._ + val readStage = if(readInExecute) execute else decode + val writeStage = if(writeRfInMemoryStage) memory else stages.last + val global = pipeline plug new Area{ - val regFile = Mem(Bits(32 bits),32) addAttribute(Verilator.public) - if(zeroBoot) regFile.init(List.fill(32)(B(0, 32 bits))) + val regFileSize = if(withShadow) 64 else 32 + val regFile = Mem(Bits(32 bits),regFileSize) addAttribute(Verilator.public) + if(zeroBoot) regFile.init(List.fill(regFileSize)(B(0, 32 bits))) + + val shadow = ifGen(withShadow)(new Area{ + val write, read, clear = RegInit(False) + + read clearWhen(clear && !readStage.arbitration.isStuck) + write clearWhen(clear && !writeStage.arbitration.isStuck) + + val csrService = pipeline.service(classOf[CsrInterface]) + csrService.w(0x7C0,2 -> clear, 1 -> read, 0 -> write) + }) } //Disable rd0 write in decoding stage @@ -47,7 +61,6 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind, } //Read register file - val readStage = if(readInExecute) execute else decode readStage plug new Area{ import readStage._ @@ -58,8 +71,9 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind, 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 - val regFileReadAddress2 = srcInstruction(Riscv.rs2Range).asUInt + def shadowPrefix(that : Bits) = if(withShadow) global.shadow.read ## that else that + val regFileReadAddress1 = U(shadowPrefix(srcInstruction(Riscv.rs1Range))) + val regFileReadAddress2 = U(shadowPrefix(srcInstruction(Riscv.rs2Range))) val (rs1Data,rs2Data) = regFileReadyKind match{ case `ASYNC` => (global.regFile.readAsync(regFileReadAddress1),global.regFile.readAsync(regFileReadAddress2)) @@ -73,13 +87,13 @@ class RegFilePlugin(regFileReadyKind : RegFileReadKind, } //Write register file - val writeStage = if(writeRfInMemoryStage) memory else stages.last writeStage plug new Area { import writeStage._ + def shadowPrefix(that : Bits) = if(withShadow) global.shadow.write ## that else that val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public) regFileWrite.valid := output(REGFILE_WRITE_VALID) && arbitration.isFiring - regFileWrite.address := output(INSTRUCTION)(rdRange).asUInt + regFileWrite.address := U(shadowPrefix(output(INSTRUCTION)(rdRange))) regFileWrite.data := output(REGFILE_WRITE_DATA) //CPU will initialise constant register zero in the first cycle diff --git a/src/main/scala/vexriscv/plugin/ShiftPlugins.scala b/src/main/scala/vexriscv/plugin/ShiftPlugins.scala index 563ba27..086528d 100644 --- a/src/main/scala/vexriscv/plugin/ShiftPlugins.scala +++ b/src/main/scala/vexriscv/plugin/ShiftPlugins.scala @@ -26,7 +26,7 @@ class FullBarrelShifterPlugin(earlyInjection : Boolean = false) extends Plugin[V REGFILE_WRITE_VALID -> True, BYPASSABLE_EXECUTE_STAGE -> Bool(earlyInjection), BYPASSABLE_MEMORY_STAGE -> True, - RS1_USE -> True + RS1_USE -> True ) val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)]( @@ -35,8 +35,8 @@ class FullBarrelShifterPlugin(earlyInjection : Boolean = false) extends Plugin[V REGFILE_WRITE_VALID -> True, BYPASSABLE_EXECUTE_STAGE -> Bool(earlyInjection), BYPASSABLE_MEMORY_STAGE -> True, - RS1_USE -> True, - RS2_USE -> True + RS1_USE -> True, + RS2_USE -> True ) val decoderService = pipeline.service(classOf[DecoderService])