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

View File

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

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 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,13 +533,28 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
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 = 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)),
1 -> B((31 downto 16) -> (rspShifted(15) && ! input(INSTRUCTION)(14)),(15 downto 0) -> rspShifted(15 downto 0)),
default -> rspShifted //W

View File

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