Add support for big endian byte ordering

This commit is contained in:
Marcus Comstedt 2020-08-30 15:17:09 +02:00
parent 2942d0652a
commit c489143442
4 changed files with 81 additions and 58 deletions

View File

@ -52,8 +52,8 @@ case class MuraxConfig(coreFrequency : HertzNumber,
object MuraxConfig{ object MuraxConfig{
def default : MuraxConfig = default(false) def default : MuraxConfig = default(false, false)
def default(withXip : Boolean) = MuraxConfig( def default(withXip : Boolean = false, bigEndian : Boolean = false) = MuraxConfig(
coreFrequency = 12 MHz, coreFrequency = 12 MHz,
onChipRamSize = 8 kB, onChipRamSize = 8 kB,
onChipRamHexFile = null, onChipRamHexFile = null,
@ -75,12 +75,14 @@ object MuraxConfig{
cmdForkPersistence = withXip, //Required by the Xip controller cmdForkPersistence = withXip, //Required by the Xip controller
prediction = NONE, prediction = NONE,
catchAccessFault = false, catchAccessFault = false,
compressedGen = false compressedGen = false,
bigEndian = bigEndian
), ),
new DBusSimplePlugin( new DBusSimplePlugin(
catchAddressMisaligned = false, catchAddressMisaligned = false,
catchAccessFault = false, catchAccessFault = false,
earlyInjection = false earlyInjection = false,
bigEndian = bigEndian
), ),
new CsrPlugin(CsrPluginConfig.smallest(mtvecInit = if(withXip) 0xE0040020l else 0x80000020l)), new CsrPlugin(CsrPluginConfig.smallest(mtvecInit = if(withXip) 0xE0040020l else 0x80000020l)),
new DecoderSimplePlugin( new DecoderSimplePlugin(
@ -214,9 +216,11 @@ case class Murax(config : MuraxConfig) extends Component{
dataWidth = 32 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 //Arbiter of the cpu dBus/iBus to drive the mainBus
//Priority to dBus, !! cmd transactions can change on the fly !! //Priority to dBus, !! cmd transactions can change on the fly !!
val mainBusArbiter = new MuraxMasterArbiter(pipelinedMemoryBusConfig) val mainBusArbiter = new MuraxMasterArbiter(pipelinedMemoryBusConfig, bigEndianDBus)
//Instanciate the CPU //Instanciate the CPU
val cpu = new VexRiscv( val cpu = new VexRiscv(
@ -258,7 +262,8 @@ case class Murax(config : MuraxConfig) extends Component{
val ram = new MuraxPipelinedMemoryBusRam( val ram = new MuraxPipelinedMemoryBusRam(
onChipRamSize = onChipRamSize, onChipRamSize = onChipRamSize,
onChipRamHexFile = onChipRamHexFile, onChipRamHexFile = onChipRamHexFile,
pipelinedMemoryBusConfig = pipelinedMemoryBusConfig pipelinedMemoryBusConfig = pipelinedMemoryBusConfig,
bigEndian = bigEndianDBus
) )
mainBusMapping += ram.io.bus -> (0x80000000l, onChipRamSize) mainBusMapping += ram.io.bus -> (0x80000000l, onChipRamSize)

View File

@ -10,10 +10,10 @@ import spinal.lib._
import spinal.lib.bus.simple._ import spinal.lib.bus.simple._
import vexriscv.plugin.{DBusSimpleBus, IBusSimpleBus} 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 io = new Bundle{
val iBus = slave(IBusSimpleBus(null)) val iBus = slave(IBusSimpleBus(null))
val dBus = slave(DBusSimpleBus()) val dBus = slave(DBusSimpleBus(bigEndian))
val masterBus = master(PipelinedMemoryBus(pipelinedMemoryBusConfig)) 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.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.address := io.dBus.cmd.valid ? io.dBus.cmd.address | io.iBus.cmd.pc
io.masterBus.cmd.data := io.dBus.cmd.data io.masterBus.cmd.data := io.dBus.cmd.data
io.masterBus.cmd.mask := io.dBus.cmd.size.mux( io.masterBus.cmd.mask := io.dBus.genMask(io.dBus.cmd)
0 -> B"0001",
1 -> B"0011",
default -> B"1111"
) |<< io.dBus.cmd.address(1 downto 0)
io.iBus.cmd.ready := io.masterBus.cmd.ready && !io.dBus.cmd.valid io.iBus.cmd.ready := io.masterBus.cmd.ready && !io.dBus.cmd.valid
io.dBus.cmd.ready := io.masterBus.cmd.ready 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 io = new Bundle{
val bus = slave(PipelinedMemoryBus(pipelinedMemoryBusConfig)) val bus = slave(PipelinedMemoryBus(pipelinedMemoryBusConfig))
} }
@ -71,6 +67,14 @@ case class MuraxPipelinedMemoryBusRam(onChipRamSize : BigInt, onChipRamHexFile :
if(onChipRamHexFile != null){ if(onChipRamHexFile != null){
HexTools.initRam(ram, onChipRamHexFile, 0x80000000l) 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)
} }
} }

View File

@ -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 cmd = Stream(DBusSimpleCmd())
val rsp = DBusSimpleRsp() val rsp = DBusSimpleRsp()
@ -100,12 +100,27 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
} }
def cmdS2mPipe() : DBusSimpleBus = { def cmdS2mPipe() : DBusSimpleBus = {
val s = DBusSimpleBus() val s = DBusSimpleBus(bigEndian)
s.cmd << this.cmd.s2mPipe() s.cmd << this.cmd.s2mPipe()
this.rsp := s.rsp this.rsp := s.rsp
s 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 = { def toAxi4Shared(stageCmd : Boolean = false, pendingWritesMax : Int = 7): Axi4Shared = {
val axi = Axi4Shared(DBusSimpleBus.getAxi4Config()) val axi = Axi4Shared(DBusSimpleBus.getAxi4Config())
@ -130,11 +145,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
axi.writeData.arbitrationFrom(dataStage) axi.writeData.arbitrationFrom(dataStage)
axi.writeData.last := True axi.writeData.last := True
axi.writeData.data := dataStage.data axi.writeData.data := dataStage.data
axi.writeData.strb := (dataStage.size.mux( axi.writeData.strb := genMask(dataStage).resized
U(0) -> B"0001",
U(1) -> B"0011",
default -> B"1111"
) << dataStage.address(1 downto 0)).resized
rsp.ready := axi.r.valid rsp.ready := axi.r.valid
@ -158,11 +169,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
mm.write := cmdStage.valid && cmdStage.wr mm.write := cmdStage.valid && cmdStage.wr
mm.address := (cmdStage.address >> 2) @@ U"00" mm.address := (cmdStage.address >> 2) @@ U"00"
mm.writeData := cmdStage.data(31 downto 0) mm.writeData := cmdStage.data(31 downto 0)
mm.byteEnable := (cmdStage.size.mux ( mm.byteEnable := genMask(cmdStage).resized
U(0) -> B"0001",
U(1) -> B"0011",
default -> B"1111"
) << cmdStage.address(1 downto 0)).resized
cmdStage.ready := mm.waitRequestn cmdStage.ready := mm.waitRequestn
@ -181,11 +188,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
bus.ADR := cmdStage.address >> 2 bus.ADR := cmdStage.address >> 2
bus.CTI :=B"000" bus.CTI :=B"000"
bus.BTE := "00" bus.BTE := "00"
bus.SEL := (cmdStage.size.mux ( bus.SEL := genMask(cmdStage).resized
U(0) -> B"0001",
U(1) -> B"0011",
default -> B"1111"
) << cmdStage.address(1 downto 0)).resized
when(!cmdStage.wr) { when(!cmdStage.wr) {
bus.SEL := "1111" bus.SEL := "1111"
} }
@ -209,11 +212,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
bus.cmd.write := cmd.wr bus.cmd.write := cmd.wr
bus.cmd.address := cmd.address.resized bus.cmd.address := cmd.address.resized
bus.cmd.data := cmd.data bus.cmd.data := cmd.data
bus.cmd.mask := cmd.size.mux( bus.cmd.mask := genMask(cmd)
0 -> B"0001",
1 -> B"0011",
default -> B"1111"
) |<< cmd.address(1 downto 0)
cmd.ready := bus.cmd.ready cmd.ready := bus.cmd.ready
rsp.ready := bus.rsp.valid rsp.ready := bus.rsp.valid
@ -265,11 +264,7 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{
1 -> U"01", 1 -> U"01",
default -> U"11" default -> U"11"
) )
bus.cmd.mask := cmd.size.mux( bus.cmd.mask := genMask(cmd)
0 -> B"0001",
1 -> B"0011",
default -> B"1111"
) |<< cmd.address(1 downto 0)
cmd.ready := bus.cmd.ready cmd.ready := bus.cmd.ready
@ -289,6 +284,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
emitCmdInMemoryStage : Boolean = false, emitCmdInMemoryStage : Boolean = false,
onlyLoadWords : Boolean = false, onlyLoadWords : Boolean = false,
withLrSc : Boolean = false, withLrSc : Boolean = false,
val bigEndian : Boolean = false,
memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] with DBusAccessService { memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] with DBusAccessService {
var dBus : DBusSimpleBus = null var dBus : DBusSimpleBus = null
@ -393,7 +389,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
import pipeline._ import pipeline._
import pipeline.config._ import pipeline.config._
dBus = master(DBusSimpleBus()).setName("dBus") dBus = master(DBusSimpleBus(bigEndian)).setName("dBus")
decode plug new Area { decode plug new Area {
@ -436,11 +432,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
insert(MEMORY_ADDRESS_LOW) := dBus.cmd.address(1 downto 0) insert(MEMORY_ADDRESS_LOW) := dBus.cmd.address(1 downto 0)
//formal //formal
val formalMask = dBus.cmd.size.mux( val formalMask = dBus.genMask(dBus.cmd)
U(0) -> B"0001",
U(1) -> B"0011",
default -> B"1111"
) |<< dBus.cmd.address(1 downto 0)
insert(FORMAL_MEM_ADDR) := dBus.cmd.address & U"xFFFFFFFC" 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_WMASK) := (dBus.cmd.valid && dBus.cmd.wr) ? formalMask | B"0000"
@ -541,13 +533,28 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
val rspShifted = MEMORY_READ_DATA() val rspShifted = MEMORY_READ_DATA()
rspShifted := input(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)){ switch(input(MEMORY_ADDRESS_LOW)){
is(1){rspShifted(7 downto 0) := input(MEMORY_READ_DATA)(15 downto 8)} 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(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)} is(3){rspShifted(7 downto 0) := input(MEMORY_READ_DATA)(31 downto 24)}
} }
val rspFormated = input(INSTRUCTION)(13 downto 12).mux( 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)), 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)), 1 -> B((31 downto 16) -> (rspShifted(15) && ! input(INSTRUCTION)(14)),(15 downto 0) -> rspShifted(15 downto 0)),
default -> rspShifted //W default -> rspShifted //W

View File

@ -234,7 +234,8 @@ class IBusSimplePlugin( resetVector : BigInt,
val singleInstructionPipeline : Boolean = false, val singleInstructionPipeline : Boolean = false,
val memoryTranslatorPortConfig : Any = null, val memoryTranslatorPortConfig : Any = null,
relaxPredictorAddress : Boolean = true, relaxPredictorAddress : Boolean = true,
predictionBuffer : Boolean = true predictionBuffer : Boolean = true,
bigEndian : Boolean = false
) extends IBusFetcherImpl( ) extends IBusFetcherImpl(
resetVector = resetVector, resetVector = resetVector,
keepPcPlus4 = keepPcPlus4, keepPcPlus4 = keepPcPlus4,
@ -371,6 +372,12 @@ class IBusSimplePlugin( resetVector : BigInt,
fetchRsp.pc := stages.last.output.payload fetchRsp.pc := stages.last.output.payload
fetchRsp.rsp := rspBuffer.output.payload fetchRsp.rsp := rspBuffer.output.payload
fetchRsp.rsp.error.clearWhen(!rspBuffer.output.valid) //Avoid interference with instruction injection from the debug plugin 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 join = Stream(FetchRsp())
val exceptionDetected = False val exceptionDetected = False