From c489143442d9ccc23790153cca6ad33c2736114a Mon Sep 17 00:00:00 2001 From: Marcus Comstedt Date: Sun, 30 Aug 2020 15:17:09 +0200 Subject: [PATCH] Add support for big endian byte ordering --- src/main/scala/vexriscv/demo/Murax.scala | 17 ++-- .../scala/vexriscv/demo/MuraxUtiles.scala | 20 ++-- .../vexriscv/plugin/DBusSimplePlugin.scala | 93 ++++++++++--------- .../vexriscv/plugin/IBusSimplePlugin.scala | 9 +- 4 files changed, 81 insertions(+), 58 deletions(-) diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala index 6d98907..a0590ad 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -52,8 +52,8 @@ case class MuraxConfig(coreFrequency : HertzNumber, object MuraxConfig{ - def default : MuraxConfig = default(false) - def default(withXip : Boolean) = MuraxConfig( + def default : MuraxConfig = default(false, false) + def default(withXip : Boolean = false, bigEndian : Boolean = false) = MuraxConfig( coreFrequency = 12 MHz, onChipRamSize = 8 kB, onChipRamHexFile = null, @@ -75,12 +75,14 @@ object MuraxConfig{ cmdForkPersistence = withXip, //Required by the Xip controller prediction = NONE, catchAccessFault = false, - compressedGen = false + compressedGen = false, + bigEndian = bigEndian ), new DBusSimplePlugin( catchAddressMisaligned = false, catchAccessFault = false, - earlyInjection = false + earlyInjection = false, + bigEndian = bigEndian ), new CsrPlugin(CsrPluginConfig.smallest(mtvecInit = if(withXip) 0xE0040020l else 0x80000020l)), new DecoderSimplePlugin( @@ -214,9 +216,11 @@ case class Murax(config : MuraxConfig) extends Component{ dataWidth = 32 ) + val bigEndianDBus = config.cpuPlugins.exists(_ match{ case plugin : DBusSimplePlugin => plugin.bigEndian case _ => false}) + //Arbiter of the cpu dBus/iBus to drive the mainBus //Priority to dBus, !! cmd transactions can change on the fly !! - val mainBusArbiter = new MuraxMasterArbiter(pipelinedMemoryBusConfig) + val mainBusArbiter = new MuraxMasterArbiter(pipelinedMemoryBusConfig, bigEndianDBus) //Instanciate the CPU val cpu = new VexRiscv( @@ -258,7 +262,8 @@ case class Murax(config : MuraxConfig) extends Component{ val ram = new MuraxPipelinedMemoryBusRam( onChipRamSize = onChipRamSize, onChipRamHexFile = onChipRamHexFile, - pipelinedMemoryBusConfig = pipelinedMemoryBusConfig + pipelinedMemoryBusConfig = pipelinedMemoryBusConfig, + bigEndian = bigEndianDBus ) mainBusMapping += ram.io.bus -> (0x80000000l, onChipRamSize) diff --git a/src/main/scala/vexriscv/demo/MuraxUtiles.scala b/src/main/scala/vexriscv/demo/MuraxUtiles.scala index 1c45bc3..1e22157 100644 --- a/src/main/scala/vexriscv/demo/MuraxUtiles.scala +++ b/src/main/scala/vexriscv/demo/MuraxUtiles.scala @@ -10,10 +10,10 @@ import spinal.lib._ import spinal.lib.bus.simple._ import vexriscv.plugin.{DBusSimpleBus, IBusSimpleBus} -class MuraxMasterArbiter(pipelinedMemoryBusConfig : PipelinedMemoryBusConfig) extends Component{ +class MuraxMasterArbiter(pipelinedMemoryBusConfig : PipelinedMemoryBusConfig, bigEndian : Boolean = false) extends Component{ val io = new Bundle{ val iBus = slave(IBusSimpleBus(null)) - val dBus = slave(DBusSimpleBus()) + val dBus = slave(DBusSimpleBus(bigEndian)) val masterBus = master(PipelinedMemoryBus(pipelinedMemoryBusConfig)) } @@ -21,11 +21,7 @@ class MuraxMasterArbiter(pipelinedMemoryBusConfig : PipelinedMemoryBusConfig) ex io.masterBus.cmd.write := io.dBus.cmd.valid && io.dBus.cmd.wr io.masterBus.cmd.address := io.dBus.cmd.valid ? io.dBus.cmd.address | io.iBus.cmd.pc io.masterBus.cmd.data := io.dBus.cmd.data - io.masterBus.cmd.mask := io.dBus.cmd.size.mux( - 0 -> B"0001", - 1 -> B"0011", - default -> B"1111" - ) |<< io.dBus.cmd.address(1 downto 0) + io.masterBus.cmd.mask := io.dBus.genMask(io.dBus.cmd) io.iBus.cmd.ready := io.masterBus.cmd.ready && !io.dBus.cmd.valid io.dBus.cmd.ready := io.masterBus.cmd.ready @@ -53,7 +49,7 @@ class MuraxMasterArbiter(pipelinedMemoryBusConfig : PipelinedMemoryBusConfig) ex } -case class MuraxPipelinedMemoryBusRam(onChipRamSize : BigInt, onChipRamHexFile : String, pipelinedMemoryBusConfig : PipelinedMemoryBusConfig) extends Component{ +case class MuraxPipelinedMemoryBusRam(onChipRamSize : BigInt, onChipRamHexFile : String, pipelinedMemoryBusConfig : PipelinedMemoryBusConfig, bigEndian : Boolean = false) extends Component{ val io = new Bundle{ val bus = slave(PipelinedMemoryBus(pipelinedMemoryBusConfig)) } @@ -71,6 +67,14 @@ case class MuraxPipelinedMemoryBusRam(onChipRamSize : BigInt, onChipRamHexFile : if(onChipRamHexFile != null){ HexTools.initRam(ram, onChipRamHexFile, 0x80000000l) + if(bigEndian) + // HexTools.initRam (incorrectly) assumes little endian byte ordering + for((word, wordIndex) <- ram.initialContent.zipWithIndex) + ram.initialContent(wordIndex) = + ((word & 0xffl) << 24) | + ((word & 0xff00l) << 8) | + ((word & 0xff0000l) >> 8) | + ((word & 0xff000000l) >> 24) } } diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala index e08b640..c9fe212 100644 --- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala @@ -90,7 +90,7 @@ object DBusSimpleBus{ ) } -case class DBusSimpleBus() extends Bundle with IMasterSlave{ +case class DBusSimpleBus(bigEndian : Boolean = false) extends Bundle with IMasterSlave{ val cmd = Stream(DBusSimpleCmd()) val rsp = DBusSimpleRsp() @@ -100,12 +100,27 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{ } def cmdS2mPipe() : DBusSimpleBus = { - val s = 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()) @@ -130,11 +145,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{ axi.writeData.arbitrationFrom(dataStage) axi.writeData.last := True axi.writeData.data := dataStage.data - axi.writeData.strb := (dataStage.size.mux( - U(0) -> B"0001", - U(1) -> B"0011", - default -> B"1111" - ) << dataStage.address(1 downto 0)).resized + axi.writeData.strb := genMask(dataStage).resized rsp.ready := axi.r.valid @@ -158,11 +169,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{ mm.write := cmdStage.valid && cmdStage.wr mm.address := (cmdStage.address >> 2) @@ U"00" mm.writeData := cmdStage.data(31 downto 0) - mm.byteEnable := (cmdStage.size.mux ( - U(0) -> B"0001", - U(1) -> B"0011", - default -> B"1111" - ) << cmdStage.address(1 downto 0)).resized + mm.byteEnable := genMask(cmdStage).resized cmdStage.ready := mm.waitRequestn @@ -181,11 +188,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{ bus.ADR := cmdStage.address >> 2 bus.CTI :=B"000" bus.BTE := "00" - bus.SEL := (cmdStage.size.mux ( - U(0) -> B"0001", - U(1) -> B"0011", - default -> B"1111" - ) << cmdStage.address(1 downto 0)).resized + bus.SEL := genMask(cmdStage).resized when(!cmdStage.wr) { bus.SEL := "1111" } @@ -209,11 +212,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{ bus.cmd.write := 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) + bus.cmd.mask := genMask(cmd) cmd.ready := bus.cmd.ready rsp.ready := bus.rsp.valid @@ -265,11 +264,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{ 1 -> U"01", default -> U"11" ) - bus.cmd.mask := cmd.size.mux( - 0 -> B"0001", - 1 -> B"0011", - default -> B"1111" - ) |<< cmd.address(1 downto 0) + bus.cmd.mask := genMask(cmd) cmd.ready := bus.cmd.ready @@ -289,6 +284,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = 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 @@ -393,7 +389,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, import pipeline._ import pipeline.config._ - dBus = master(DBusSimpleBus()).setName("dBus") + dBus = master(DBusSimpleBus(bigEndian)).setName("dBus") decode plug new Area { @@ -436,11 +432,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, insert(MEMORY_ADDRESS_LOW) := dBus.cmd.address(1 downto 0) //formal - val formalMask = dBus.cmd.size.mux( - U(0) -> B"0001", - U(1) -> B"0011", - default -> B"1111" - ) |<< dBus.cmd.address(1 downto 0) + 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" @@ -541,17 +533,32 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, val rspShifted = MEMORY_READ_DATA() rspShifted := input(MEMORY_READ_DATA) - 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)} - } + 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 = 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 - ) + 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)) diff --git a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala index b8bc978..22c3606 100644 --- a/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/IBusSimplePlugin.scala @@ -234,7 +234,8 @@ class IBusSimplePlugin( resetVector : BigInt, val singleInstructionPipeline : Boolean = false, val memoryTranslatorPortConfig : Any = null, relaxPredictorAddress : Boolean = true, - predictionBuffer : Boolean = true + predictionBuffer : Boolean = true, + bigEndian : Boolean = false ) extends IBusFetcherImpl( resetVector = resetVector, keepPcPlus4 = keepPcPlus4, @@ -371,6 +372,12 @@ class IBusSimplePlugin( resetVector : BigInt, fetchRsp.pc := stages.last.output.payload fetchRsp.rsp := rspBuffer.output.payload fetchRsp.rsp.error.clearWhen(!rspBuffer.output.valid) //Avoid interference with instruction injection from the debug plugin + if(bigEndian){ + // inst(15 downto 0) should contain lower addressed parcel, + // and inst(31 downto 16) the higher addressed parcel + fetchRsp.rsp.inst.allowOverride + fetchRsp.rsp.inst := rspBuffer.output.payload.inst.rotateLeft(16) + } val join = Stream(FetchRsp()) val exceptionDetected = False