aboutsummaryrefslogtreecommitdiff
path: root/VexRiscv/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala
diff options
context:
space:
mode:
authorFriedrich Beckmann <friedrich.beckmann@hs-augsburg.de>2022-07-25 17:55:39 +0200
committerFriedrich Beckmann <friedrich.beckmann@hs-augsburg.de>2022-07-25 17:55:39 +0200
commit3fff6023602822531efdae30bc8ebf862967f1ef (patch)
tree16028102b8d850f8ab3115d28a8539ca6bc5f51d /VexRiscv/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala
Initial Commit
Diffstat (limited to 'VexRiscv/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala')
-rw-r--r--VexRiscv/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala614
1 files changed, 614 insertions, 0 deletions
diff --git a/VexRiscv/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/VexRiscv/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala
new file mode 100644
index 0000000..372cfcc
--- /dev/null
+++ b/VexRiscv/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala
@@ -0,0 +1,614 @@
+package vexriscv.plugin
+
+import vexriscv._
+import spinal.core._
+import spinal.lib._
+import spinal.lib.bus.amba3.ahblite.{AhbLite3Config, AhbLite3Master}
+import spinal.lib.bus.amba4.axi._
+import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
+import spinal.lib.bus.bmb.{Bmb, BmbParameter}
+import spinal.lib.bus.wishbone.{Wishbone, WishboneConfig}
+import spinal.lib.bus.simple._
+import vexriscv.ip.DataCacheMemCmd
+
+import scala.collection.mutable.ArrayBuffer
+
+
+case class DBusSimpleCmd() extends Bundle{
+ val wr = Bool
+ val address = UInt(32 bits)
+ val data = Bits(32 bit)
+ val size = UInt(2 bit)
+}
+
+case class DBusSimpleRsp() extends Bundle with IMasterSlave{
+ val ready = Bool
+ val error = Bool
+ val data = Bits(32 bit)
+
+ override def asMaster(): Unit = {
+ out(ready,error,data)
+ }
+}
+
+
+object DBusSimpleBus{
+ def getAxi4Config() = Axi4Config(
+ addressWidth = 32,
+ dataWidth = 32,
+ useId = false,
+ useRegion = false,
+ useBurst = false,
+ useLock = false,
+ useQos = false,
+ useLen = false,
+ useResp = true
+ )
+
+ def getAvalonConfig() = AvalonMMConfig.pipelined(
+ addressWidth = 32,
+ dataWidth = 32).copy(
+ useByteEnable = true,
+ useResponse = true,
+ maximumPendingReadTransactions = 1
+ )
+
+ def getWishboneConfig() = WishboneConfig(
+ addressWidth = 30,
+ dataWidth = 32,
+ selWidth = 4,
+ useSTALL = false,
+ useLOCK = false,
+ useERR = true,
+ useRTY = false,
+ tgaWidth = 0,
+ tgcWidth = 0,
+ tgdWidth = 0,
+ useBTE = true,
+ useCTI = true
+ )
+
+ def getPipelinedMemoryBusConfig() = PipelinedMemoryBusConfig(
+ addressWidth = 32,
+ dataWidth = 32
+ )
+
+ def getAhbLite3Config() = AhbLite3Config(
+ addressWidth = 32,
+ dataWidth = 32
+ )
+ def getBmbParameter() = BmbParameter(
+ addressWidth = 32,
+ dataWidth = 32,
+ lengthWidth = 2,
+ sourceWidth = 0,
+ contextWidth = 1,
+ alignment = BmbParameter.BurstAlignement.LENGTH
+ )
+}
+
+case class DBusSimpleBus(bigEndian : Boolean = false) extends Bundle with IMasterSlave{
+ val cmd = Stream(DBusSimpleCmd())
+ val rsp = DBusSimpleRsp()
+
+ override def asMaster(): Unit = {
+ master(cmd)
+ slave(rsp)
+ }
+
+ def cmdS2mPipe() : DBusSimpleBus = {
+ val s = DBusSimpleBus(bigEndian)
+ s.cmd << this.cmd.s2mPipe()
+ this.rsp := s.rsp
+ s
+ }
+
+ def genMask(cmd : DBusSimpleCmd) = {
+ if(bigEndian)
+ cmd.size.mux(
+ U(0) -> B"1000",
+ U(1) -> B"1100",
+ default -> B"1111"
+ ) |>> cmd.address(1 downto 0)
+ else
+ cmd.size.mux(
+ U(0) -> B"0001",
+ U(1) -> B"0011",
+ default -> B"1111"
+ ) |<< cmd.address(1 downto 0)
+ }
+
+ def toAxi4Shared(stageCmd : Boolean = false, pendingWritesMax : Int = 7): Axi4Shared = {
+ val axi = Axi4Shared(DBusSimpleBus.getAxi4Config())
+
+ val cmdPreFork = if (stageCmd) cmd.stage.stage().s2mPipe() else cmd
+
+ val pendingWrites = CounterUpDown(
+ stateCount = pendingWritesMax + 1,
+ incWhen = cmdPreFork.fire && cmdPreFork.wr,
+ decWhen = axi.writeRsp.fire
+ )
+
+ val hazard = (pendingWrites =/= 0 && cmdPreFork.valid && !cmdPreFork.wr) || pendingWrites === pendingWritesMax
+ val (cmdFork, dataFork) = StreamFork2(cmdPreFork.haltWhen(hazard))
+ axi.sharedCmd.arbitrationFrom(cmdFork)
+ axi.sharedCmd.write := cmdFork.wr
+ axi.sharedCmd.prot := "010"
+ axi.sharedCmd.cache := "1111"
+ axi.sharedCmd.size := cmdFork.size.resized
+ axi.sharedCmd.addr := cmdFork.address
+
+ val dataStage = dataFork.throwWhen(!dataFork.wr)
+ axi.writeData.arbitrationFrom(dataStage)
+ axi.writeData.last := True
+ axi.writeData.data := dataStage.data
+ axi.writeData.strb := genMask(dataStage).resized
+
+
+ rsp.ready := axi.r.valid
+ rsp.error := !axi.r.isOKAY()
+ rsp.data := axi.r.data
+
+ axi.r.ready := True
+ axi.b.ready := True
+ axi
+ }
+
+ def toAxi4(stageCmd : Boolean = true) = this.toAxi4Shared(stageCmd).toAxi4()
+
+
+
+ def toAvalon(stageCmd : Boolean = true): AvalonMM = {
+ val avalonConfig = DBusSimpleBus.getAvalonConfig()
+ val mm = AvalonMM(avalonConfig)
+ val cmdStage = if(stageCmd) cmd.stage else cmd
+ mm.read := cmdStage.valid && !cmdStage.wr
+ mm.write := cmdStage.valid && cmdStage.wr
+ mm.address := (cmdStage.address >> 2) @@ U"00"
+ mm.writeData := cmdStage.data(31 downto 0)
+ mm.byteEnable := genMask(cmdStage).resized
+
+
+ cmdStage.ready := mm.waitRequestn
+ rsp.ready :=mm.readDataValid
+ rsp.error := mm.response =/= AvalonMM.Response.OKAY
+ rsp.data := mm.readData
+
+ mm
+ }
+
+ def toWishbone(): Wishbone = {
+ val wishboneConfig = DBusSimpleBus.getWishboneConfig()
+ val bus = Wishbone(wishboneConfig)
+ val cmdStage = cmd.halfPipe()
+
+ bus.ADR := cmdStage.address >> 2
+ bus.CTI :=B"000"
+ bus.BTE := "00"
+ bus.SEL := genMask(cmdStage).resized
+ when(!cmdStage.wr) {
+ bus.SEL := "1111"
+ }
+ bus.WE := cmdStage.wr
+ bus.DAT_MOSI := cmdStage.data
+
+ cmdStage.ready := cmdStage.valid && bus.ACK
+ bus.CYC := cmdStage.valid
+ bus.STB := cmdStage.valid
+
+ rsp.ready := cmdStage.valid && !bus.WE && bus.ACK
+ rsp.data := bus.DAT_MISO
+ rsp.error := False //TODO
+ bus
+ }
+
+ def toPipelinedMemoryBus() : PipelinedMemoryBus = {
+ val pipelinedMemoryBusConfig = DBusSimpleBus.getPipelinedMemoryBusConfig()
+ val bus = PipelinedMemoryBus(pipelinedMemoryBusConfig)
+ bus.cmd.valid := cmd.valid
+ bus.cmd.write := cmd.wr
+ bus.cmd.address := cmd.address.resized
+ bus.cmd.data := cmd.data
+ bus.cmd.mask := genMask(cmd)
+ cmd.ready := bus.cmd.ready
+
+ rsp.ready := bus.rsp.valid
+ rsp.data := bus.rsp.data
+
+ bus
+ }
+
+ def toAhbLite3Master(avoidWriteToReadHazard : Boolean): AhbLite3Master = {
+ val bus = AhbLite3Master(DBusSimpleBus.getAhbLite3Config())
+ bus.HADDR := this.cmd.address
+ bus.HWRITE := this.cmd.wr
+ bus.HSIZE := B(this.cmd.size, 3 bits)
+ bus.HBURST := 0
+ bus.HPROT := "1111"
+ bus.HTRANS := this.cmd.valid ## B"0"
+ bus.HMASTLOCK := False
+ bus.HWDATA := RegNextWhen(this.cmd.data, bus.HREADY)
+ this.cmd.ready := bus.HREADY
+
+ val pending = RegInit(False) clearWhen(bus.HREADY) setWhen(this.cmd.fire && !this.cmd.wr)
+ this.rsp.ready := bus.HREADY && pending
+ this.rsp.data := bus.HRDATA
+ this.rsp.error := bus.HRESP
+
+ if(avoidWriteToReadHazard) {
+ val writeDataPhase = RegNextWhen(bus.HTRANS === 2 && bus.HWRITE, bus.HREADY) init (False)
+ val potentialHazard = this.cmd.valid && !this.cmd.wr && writeDataPhase
+ when(potentialHazard) {
+ bus.HTRANS := 0
+ this.cmd.ready := False
+ }
+ }
+ bus
+ }
+
+ def toBmb() : Bmb = {
+ val pipelinedMemoryBusConfig = DBusSimpleBus.getBmbParameter()
+ val bus = Bmb(pipelinedMemoryBusConfig)
+
+ bus.cmd.valid := cmd.valid
+ bus.cmd.last := True
+ bus.cmd.context(0) := cmd.wr
+ bus.cmd.opcode := (cmd.wr ? B(Bmb.Cmd.Opcode.WRITE) | B(Bmb.Cmd.Opcode.READ))
+ bus.cmd.address := cmd.address.resized
+ bus.cmd.data := cmd.data
+ bus.cmd.length := cmd.size.mux(
+ 0 -> U"00",
+ 1 -> U"01",
+ default -> U"11"
+ )
+ bus.cmd.mask := genMask(cmd)
+
+ cmd.ready := bus.cmd.ready
+
+ rsp.ready := bus.rsp.valid && !bus.rsp.context(0)
+ rsp.data := bus.rsp.data
+ rsp.error := bus.rsp.isError
+ bus.rsp.ready := True
+
+ bus
+ }
+}
+
+
+class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
+ catchAccessFault : Boolean = false,
+ earlyInjection : Boolean = false, /*, idempotentRegions : (UInt) => Bool = (x) => False*/
+ emitCmdInMemoryStage : Boolean = false,
+ onlyLoadWords : Boolean = false,
+ withLrSc : Boolean = false,
+ val bigEndian : Boolean = false,
+ memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] with DBusAccessService {
+
+ var dBus : DBusSimpleBus = null
+ assert(!(emitCmdInMemoryStage && earlyInjection))
+ object MEMORY_ENABLE extends Stageable(Bool)
+ object MEMORY_READ_DATA extends Stageable(Bits(32 bits))
+ object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
+ object ALIGNEMENT_FAULT extends Stageable(Bool)
+ object MMU_FAULT extends Stageable(Bool)
+ object MEMORY_ATOMIC extends Stageable(Bool)
+ object ATOMIC_HIT extends Stageable(Bool)
+ object MEMORY_STORE extends Stageable(Bool)
+
+ var memoryExceptionPort : Flow[ExceptionCause] = null
+ var rspStage : Stage = null
+ var mmuBus : MemoryTranslatorBus = null
+ var redoBranch : Flow[UInt] = null
+ val catchSomething = catchAccessFault || catchAddressMisaligned || memoryTranslatorPortConfig != null
+
+ @dontName var dBusAccess : DBusAccess = null
+ override def newDBusAccess(): DBusAccess = {
+ assert(dBusAccess == null)
+ dBusAccess = DBusAccess()
+ dBusAccess
+ }
+
+ override def setup(pipeline: VexRiscv): Unit = {
+ import Riscv._
+ import pipeline.config._
+ import pipeline._
+
+ val decoderService = pipeline.service(classOf[DecoderService])
+
+ val stdActions = List[(Stageable[_ <: BaseType],Any)](
+ SRC1_CTRL -> Src1CtrlEnum.RS,
+ SRC_USE_SUB_LESS -> False,
+ MEMORY_ENABLE -> True,
+ RS1_USE -> True
+ ) ++ (if(catchAccessFault || catchAddressMisaligned) List(IntAluPlugin.ALU_CTRL -> IntAluPlugin.AluCtrlEnum.ADD_SUB) else Nil) //Used for access fault bad address in memory stage
+
+ val loadActions = stdActions ++ List(
+ SRC2_CTRL -> Src2CtrlEnum.IMI,
+ REGFILE_WRITE_VALID -> True,
+ BYPASSABLE_EXECUTE_STAGE -> False,
+ BYPASSABLE_MEMORY_STAGE -> Bool(earlyInjection),
+ MEMORY_STORE -> False,
+ HAS_SIDE_EFFECT -> True
+ )
+
+ val storeActions = stdActions ++ List(
+ SRC2_CTRL -> Src2CtrlEnum.IMS,
+ RS2_USE -> True,
+ MEMORY_STORE -> True,
+ HAS_SIDE_EFFECT -> True
+ )
+
+ decoderService.addDefault(MEMORY_ENABLE, False)
+ decoderService.add(
+ (if(onlyLoadWords) List(LW) else List(LB, LH, LW, LBU, LHU, LWU)).map(_ -> loadActions) ++
+ List(SB, SH, SW).map(_ -> storeActions)
+ )
+
+
+ if(withLrSc){
+ List(LB, LH, LW, LBU, LHU, LWU, SB, SH, SW).foreach(e =>
+ decoderService.add(e, Seq(MEMORY_ATOMIC -> False))
+ )
+ decoderService.add(
+ key = LR,
+ values = loadActions.filter(_._1 != SRC2_CTRL) ++ Seq(
+ SRC_ADD_ZERO -> True,
+ MEMORY_ATOMIC -> True
+ )
+ )
+
+ decoderService.add(
+ key = SC,
+ values = storeActions.filter(_._1 != SRC2_CTRL) ++ Seq(
+ SRC_ADD_ZERO -> True,
+ REGFILE_WRITE_VALID -> True,
+ BYPASSABLE_EXECUTE_STAGE -> False,
+ BYPASSABLE_MEMORY_STAGE -> False,
+ MEMORY_ATOMIC -> True
+ )
+ )
+ }
+
+ decoderService.add(FENCE, Nil)
+
+ rspStage = if(stages.last == execute) execute else (if(emitCmdInMemoryStage) writeBack else memory)
+ if(catchSomething) {
+ val exceptionService = pipeline.service(classOf[ExceptionService])
+ memoryExceptionPort = exceptionService.newExceptionPort(rspStage)
+ }
+
+ if(memoryTranslatorPortConfig != null) {
+ mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA, memoryTranslatorPortConfig)
+ redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.memory != null) pipeline.memory else pipeline.execute)
+ }
+ }
+
+ override def build(pipeline: VexRiscv): Unit = {
+ import pipeline._
+ import pipeline.config._
+
+ object MMU_RSP extends Stageable(MemoryTranslatorRsp(mmuBus.p))
+
+ dBus = master(DBusSimpleBus(bigEndian)).setName("dBus")
+
+
+ decode plug new Area {
+ import decode._
+
+ if(mmuBus != null) when(mmuBus.busy && arbitration.isValid && input(MEMORY_ENABLE)) {
+ arbitration.haltItself := True
+ }
+ }
+
+ //Emit dBus.cmd request
+ val cmdSent = if(rspStage == execute) RegInit(False) setWhen(dBus.cmd.fire) clearWhen(!execute.arbitration.isStuck) else False
+ val cmdStage = if(emitCmdInMemoryStage) memory else execute
+ cmdStage plug new Area{
+ import cmdStage._
+ val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
+
+
+ if (catchAddressMisaligned)
+ insert(ALIGNEMENT_FAULT) := (dBus.cmd.size === 2 && dBus.cmd.address(1 downto 0) =/= 0) || (dBus.cmd.size === 1 && dBus.cmd.address(0 downto 0) =/= 0)
+ else
+ insert(ALIGNEMENT_FAULT) := False
+
+
+ val skipCmd = False
+ skipCmd setWhen(input(ALIGNEMENT_FAULT))
+
+ dBus.cmd.valid := arbitration.isValid && input(MEMORY_ENABLE) && !arbitration.isStuckByOthers && !arbitration.isFlushed && !skipCmd && !cmdSent
+ dBus.cmd.wr := input(MEMORY_STORE)
+ dBus.cmd.size := input(INSTRUCTION)(13 downto 12).asUInt
+ dBus.cmd.payload.data := dBus.cmd.size.mux (
+ U(0) -> input(RS2)(7 downto 0) ## input(RS2)(7 downto 0) ## input(RS2)(7 downto 0) ## input(RS2)(7 downto 0),
+ 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 && !skipCmd && !cmdSent){
+ arbitration.haltItself := True
+ }
+
+ insert(MEMORY_ADDRESS_LOW) := dBus.cmd.address(1 downto 0)
+
+ //formal
+ val formalMask = dBus.genMask(dBus.cmd)
+
+ insert(FORMAL_MEM_ADDR) := dBus.cmd.address & U"xFFFFFFFC"
+ insert(FORMAL_MEM_WMASK) := (dBus.cmd.valid && dBus.cmd.wr) ? formalMask | B"0000"
+ insert(FORMAL_MEM_RMASK) := (dBus.cmd.valid && !dBus.cmd.wr) ? formalMask | B"0000"
+ insert(FORMAL_MEM_WDATA) := dBus.cmd.payload.data
+
+ val mmu = (mmuBus != null) generate new Area {
+ mmuBus.cmd.last.isValid := arbitration.isValid && input(MEMORY_ENABLE)
+ mmuBus.cmd.last.isStuck := arbitration.isStuck
+ mmuBus.cmd.last.virtualAddress := input(SRC_ADD).asUInt
+ mmuBus.cmd.last.bypassTranslation := False
+ mmuBus.end := !arbitration.isStuck || arbitration.isRemoved
+ dBus.cmd.address := mmuBus.rsp.physicalAddress
+
+ //do not emit memory request if MMU refilling
+ insert(MMU_FAULT) := input(MMU_RSP).exception || (!input(MMU_RSP).allowWrite && input(MEMORY_STORE)) || (!input(MMU_RSP).allowRead && !input(MEMORY_STORE))
+ skipCmd.setWhen(input(MMU_FAULT) || input(MMU_RSP).refilling)
+
+ insert(MMU_RSP) := mmuBus.rsp
+ }
+
+ val mmuLess = (mmuBus == null) generate new Area{
+ dBus.cmd.address := input(SRC_ADD).asUInt
+ }
+
+
+ val atomic = withLrSc generate new Area{
+ val reserved = RegInit(False)
+ insert(ATOMIC_HIT) := reserved
+ when(arbitration.isFiring && input(MEMORY_ENABLE) && (if(mmuBus != null) !input(MMU_FAULT) else True) && !skipCmd){
+ reserved setWhen(input(MEMORY_ATOMIC))
+ reserved clearWhen(input(MEMORY_STORE))
+ }
+ when(input(MEMORY_STORE) && input(MEMORY_ATOMIC) && !input(ATOMIC_HIT)){
+ skipCmd := True
+ }
+ }
+ }
+
+ //Collect dBus.rsp read responses
+ rspStage plug new Area {
+ val s = rspStage; import s._
+
+
+ insert(MEMORY_READ_DATA) := dBus.rsp.data
+
+ arbitration.haltItself setWhen(arbitration.isValid && input(MEMORY_ENABLE) && !input(MEMORY_STORE) && (!dBus.rsp.ready || (if(rspStage == execute) !cmdSent else False)))
+
+ if(catchSomething) {
+ memoryExceptionPort.valid := False
+ memoryExceptionPort.code.assignDontCare()
+ memoryExceptionPort.badAddr := input(REGFILE_WRITE_DATA).asUInt
+
+ if(catchAccessFault) when(dBus.rsp.ready && dBus.rsp.error && !input(MEMORY_STORE)) {
+ memoryExceptionPort.valid := True
+ memoryExceptionPort.code := 5
+ }
+
+ if(catchAddressMisaligned) when(input(ALIGNEMENT_FAULT)){
+ memoryExceptionPort.code := (input(MEMORY_STORE) ? U(6) | U(4)).resized
+ memoryExceptionPort.valid := True
+ }
+
+ if(memoryTranslatorPortConfig != null) {
+ redoBranch.valid := False
+ redoBranch.payload := input(PC)
+
+ when(input(MMU_RSP).refilling){
+ redoBranch.valid := True
+ memoryExceptionPort.valid := False
+ } elsewhen(input(MMU_FAULT)) {
+ memoryExceptionPort.valid := True
+ memoryExceptionPort.code := (input(MEMORY_STORE) ? U(15) | U(13)).resized
+ }
+
+ arbitration.flushIt setWhen(redoBranch.valid)
+ arbitration.flushNext setWhen(redoBranch.valid)
+ }
+
+ when(!(arbitration.isValid && input(MEMORY_ENABLE) && (Bool(cmdStage != rspStage) || !arbitration.isStuckByOthers))){
+ if(catchSomething) memoryExceptionPort.valid := False
+ if(memoryTranslatorPortConfig != null) redoBranch.valid := False
+ }
+
+ }
+ }
+
+ //Reformat read responses, REGFILE_WRITE_DATA overriding
+ val injectionStage = if(earlyInjection) memory else stages.last
+ injectionStage plug new Area {
+ import injectionStage._
+
+
+ val rspShifted = MEMORY_READ_DATA()
+ rspShifted := input(MEMORY_READ_DATA)
+ if(bigEndian)
+ switch(input(MEMORY_ADDRESS_LOW)){
+ is(1){rspShifted(31 downto 24) := input(MEMORY_READ_DATA)(23 downto 16)}
+ is(2){rspShifted(31 downto 16) := input(MEMORY_READ_DATA)(15 downto 0)}
+ is(3){rspShifted(31 downto 24) := input(MEMORY_READ_DATA)(7 downto 0)}
+ }
+ else
+ switch(input(MEMORY_ADDRESS_LOW)){
+ is(1){rspShifted(7 downto 0) := input(MEMORY_READ_DATA)(15 downto 8)}
+ is(2){rspShifted(15 downto 0) := input(MEMORY_READ_DATA)(31 downto 16)}
+ is(3){rspShifted(7 downto 0) := input(MEMORY_READ_DATA)(31 downto 24)}
+ }
+
+ val rspFormated =
+ if(bigEndian)
+ input(INSTRUCTION)(13 downto 12).mux(
+ 0 -> B((31 downto 8) -> (rspShifted(31) && !input(INSTRUCTION)(14)),(7 downto 0) -> rspShifted(31 downto 24)),
+ 1 -> B((31 downto 16) -> (rspShifted(31) && ! input(INSTRUCTION)(14)),(15 downto 0) -> rspShifted(31 downto 16)),
+ default -> rspShifted //W
+ )
+ else
+ input(INSTRUCTION)(13 downto 12).mux(
+ 0 -> B((31 downto 8) -> (rspShifted(7) && !input(INSTRUCTION)(14)),(7 downto 0) -> rspShifted(7 downto 0)),
+ 1 -> B((31 downto 16) -> (rspShifted(15) && ! input(INSTRUCTION)(14)),(15 downto 0) -> rspShifted(15 downto 0)),
+ default -> rspShifted //W
+ )
+
+ when(arbitration.isValid && input(MEMORY_ENABLE)) {
+ output(REGFILE_WRITE_DATA) := (if(!onlyLoadWords) rspFormated else input(MEMORY_READ_DATA))
+ if(withLrSc){
+ when(input(MEMORY_ATOMIC) && input(MEMORY_STORE)){
+ output(REGFILE_WRITE_DATA) := (!input(ATOMIC_HIT)).asBits.resized
+ }
+ }
+ }
+
+// if(!earlyInjection && !emitCmdInMemoryStage && config.withWriteBackStage)
+// assert(!(arbitration.isValid && input(MEMORY_ENABLE) && !input(MEMORY_STORE) && arbitration.isStuck),"DBusSimplePlugin doesn't allow writeback stage stall when read happend")
+
+ //formal
+ insert(FORMAL_MEM_RDATA) := input(MEMORY_READ_DATA)
+ }
+
+ //Share access to the dBus (used by self refilled MMU)
+ val dBusSharing = (dBusAccess != null) generate new Area{
+ val state = Reg(UInt(2 bits)) init(0)
+ dBusAccess.cmd.ready := False
+ dBusAccess.rsp.valid := False
+ dBusAccess.rsp.data := dBus.rsp.data
+ dBusAccess.rsp.error := dBus.rsp.error
+ dBusAccess.rsp.redo := False
+
+ switch(state){
+ is(0){
+ when(dBusAccess.cmd.valid){
+ decode.arbitration.haltItself := True
+ when(!stages.dropWhile(_ != execute).map(_.arbitration.isValid).orR){
+ state := 1
+ }
+ }
+ }
+ is(1){
+ decode.arbitration.haltItself := True
+ dBus.cmd.valid := True
+ dBus.cmd.address := dBusAccess.cmd.address
+ dBus.cmd.wr := dBusAccess.cmd.write
+ dBus.cmd.data := dBusAccess.cmd.data
+ dBus.cmd.size := dBusAccess.cmd.size
+ when(dBus.cmd.ready){
+ state := (dBusAccess.cmd.write ? U(0) | U(2))
+ dBusAccess.cmd.ready := True
+ }
+ }
+ is(2){
+ decode.arbitration.haltItself := True
+ when(dBus.rsp.ready){
+ dBusAccess.rsp.valid := True
+ state := 0
+ }
+ }
+ }
+ }
+ }
+}