From ff1d1072a7dd600dc31191554b023d808f94ae8f Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Wed, 19 Sep 2018 00:09:14 +0200 Subject: [PATCH] XIP is physicaly working on murax --- .../iCE40-hx8k_breakout_board_xip/toplevel.v | 10 +- src/main/c/murax/xipBootloader/.gitignore | 6 ++ src/main/c/murax/xipBootloader/crt.S | 54 +++++++++++ src/main/c/murax/xipBootloader/demo.S | 24 +++++ src/main/c/murax/xipBootloader/makefile | 23 +++++ src/main/c/murax/xipBootloader/mapping.ld | 96 +++++++++++++++++++ src/main/scala/vexriscv/demo/Murax.scala | 29 +++--- .../scala/vexriscv/demo/MuraxUtiles.scala | 23 +++++ src/test/scala/vexriscv/MuraxSim.scala | 2 +- 9 files changed, 249 insertions(+), 18 deletions(-) create mode 100644 src/main/c/murax/xipBootloader/.gitignore create mode 100644 src/main/c/murax/xipBootloader/crt.S create mode 100644 src/main/c/murax/xipBootloader/demo.S create mode 100644 src/main/c/murax/xipBootloader/makefile create mode 100644 src/main/c/murax/xipBootloader/mapping.ld diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/toplevel.v b/scripts/Murax/iCE40-hx8k_breakout_board_xip/toplevel.v index db884cc..5034de8 100644 --- a/scripts/Murax/iCE40-hx8k_breakout_board_xip/toplevel.v +++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/toplevel.v @@ -9,8 +9,8 @@ module toplevel( output io_B12, input io_B10, - input io_P12, - output io_P11, + output io_P12, + input io_P11, output io_R11, output io_R12, @@ -46,9 +46,9 @@ module toplevel( wire [1:0] io_xpi_data_1_write; wire [0:0] io_xpi_ss; - assign io_P11 = io_xpi_data_0_write[0]; - assign io_xpi_data_1_read[0] = io_P12; - assign io_xpi_data_1_read[1] = io_P12; + assign io_P12 = io_xpi_data_0_write[0]; + assign io_xpi_data_1_read[0] = io_P11; + assign io_xpi_data_1_read[1] = io_P11; assign io_R11 = io_xpi_sclk_write[0]; assign io_R12 = io_xpi_ss[0]; diff --git a/src/main/c/murax/xipBootloader/.gitignore b/src/main/c/murax/xipBootloader/.gitignore new file mode 100644 index 0000000..ca41ed2 --- /dev/null +++ b/src/main/c/murax/xipBootloader/.gitignore @@ -0,0 +1,6 @@ +*.bin +*.elf +*.map +*.d +*.asm +*.o \ No newline at end of file diff --git a/src/main/c/murax/xipBootloader/crt.S b/src/main/c/murax/xipBootloader/crt.S new file mode 100644 index 0000000..178f788 --- /dev/null +++ b/src/main/c/murax/xipBootloader/crt.S @@ -0,0 +1,54 @@ +#define CTRL_BASE 0xF001F000 +#define XIP_BASE 0xE0040000 +#define CTRL_DATA 0x00 +#define CTRL_STATUS 0x04 +#define CTRL_MODE 0x08 +#define CTRL_RATE 0x20 +#define CTRL_SS_SETUP 0x24 +#define CTRL_SS_HOLD 0x28 +#define CTRL_SS_DISABLE 0x2C + +#define CTRL_XIP_CONFIG 0x40 +#define CTRL_XIP_MODE 0x44 + +.global crtStart +.global main + +#define CTRL x31 + +crtStart: + li x31, CTRL_BASE + sw x0, CTRL_MODE(CTRL) + li t0, 2 + sw t0, CTRL_RATE(CTRL) + li t0, 4 + sw t0, CTRL_SS_SETUP(CTRL) + sw t0, CTRL_SS_HOLD(CTRL) + sw t0, CTRL_SS_DISABLE(CTRL) + + + li a0, 0x880 + call spiWrite + li a0, 0x181 + call spiWrite + li a0, 0x183 + call spiWrite + li a0, 0x800 + call spiWrite + + + li t0, 0x00FF010B + sw t0, CTRL_XIP_MODE(CTRL) + li t0, 0x1 + sw t0, CTRL_XIP_CONFIG(CTRL) + li t0, XIP_BASE + jr t0 + + +spiWrite: + sw a0,CTRL_DATA(CTRL) +spiWrite_wait: + lw t0,CTRL_STATUS(CTRL) + srli t0,t0,0x10 + beqz t0,spiWrite_wait + ret diff --git a/src/main/c/murax/xipBootloader/demo.S b/src/main/c/murax/xipBootloader/demo.S new file mode 100644 index 0000000..34d02b1 --- /dev/null +++ b/src/main/c/murax/xipBootloader/demo.S @@ -0,0 +1,24 @@ +#define GPIO_BASE 0xF0000000 +#define GPIO_OUTPUT 4 +#define GPIO_OUTPUT_ENABLE 8 + + +.global crtStart + +crtStart: + + + li x31, GPIO_BASE + li t0, 0x000000FF + sw t0, GPIO_OUTPUT_ENABLE(x31) + + li t0,0 +redo: + sw t0, GPIO_OUTPUT(x31) + li t1,10000 + addi t0,t0,1 +loop: + addi t1,t1,-1 + bnez t1, loop + j redo + diff --git a/src/main/c/murax/xipBootloader/makefile b/src/main/c/murax/xipBootloader/makefile new file mode 100644 index 0000000..56b8ab8 --- /dev/null +++ b/src/main/c/murax/xipBootloader/makefile @@ -0,0 +1,23 @@ +CFLAGS= -march=rv32i -mabi=ilp32 -g -O3 -MD +LFLAGS= -nostdlib -mcmodel=medany -nostartfiles -ffreestanding -fPIC -fPIE + + +all: crt.S demo.S + riscv64-unknown-elf-gcc -c $(CFLAGS) -o crt.o crt.S + riscv64-unknown-elf-gcc $(CFLAGS) -o crt.elf crt.o $(LFLAGS) -Wl,-Bstatic,-T,mapping.ld,-Map,crt.map,--print-memory-usage + riscv64-unknown-elf-objdump -S -d crt.elf > crt.asm + riscv64-unknown-elf-objcopy -O binary crt.elf crt.bin + + riscv64-unknown-elf-gcc -c $(CFLAGS) -o demo.o demo.S + riscv64-unknown-elf-gcc $(CFLAGS) -o demo.elf demo.o $(LFLAGS) -Wl,-Bstatic,-T,mapping.ld,-Map,demo.map,--print-memory-usage + riscv64-unknown-elf-objdump -S -d demo.elf > demo.asm + riscv64-unknown-elf-objcopy -O binary demo.elf demo.bin + + + +clean: + rm -f *.o + rm -f *.bin + rm -f *.elf + rm -f *.asm + rm -f *.map \ No newline at end of file diff --git a/src/main/c/murax/xipBootloader/mapping.ld b/src/main/c/murax/xipBootloader/mapping.ld new file mode 100644 index 0000000..cc1b070 --- /dev/null +++ b/src/main/c/murax/xipBootloader/mapping.ld @@ -0,0 +1,96 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. +*/ +OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv") +OUTPUT_ARCH(riscv) +ENTRY(crtStart) + +MEMORY { + mem : ORIGIN = 0x80000000, LENGTH = 0x00000400 +} + +_stack_size = DEFINED(_stack_size) ? _stack_size : 0; + +SECTIONS { + + .vector : { + *crt.o(.text); + } > mem + + .memory : { + *(.text); + end = .; + } > mem + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } > mem + + .ctors : + { + . = ALIGN(4); + _ctors_start = .; + KEEP(*(.init_array*)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + . = ALIGN(4); + _ctors_end = .; + } > mem + + .data : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + } > mem + + .bss (NOLOAD) : { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _bss_start = .; + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _bss_end = .; + } > mem + + .noinit (NOLOAD) : { + . = ALIGN(4); + *(.noinit .noinit.*) + . = ALIGN(4); + } > mem + + ._stack (NOLOAD): + { + . = ALIGN(16); + PROVIDE (_stack_end = .); + . = . + _stack_size; + . = ALIGN(16); + PROVIDE (_stack_start = .); + } > mem + +} + diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala index df82e83..2716e04 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -44,18 +44,13 @@ case class MuraxConfig(coreFrequency : HertzNumber, require(pipelineApbBridge || pipelineMainBus, "At least pipelineMainBus or pipelineApbBridge should be enable to avoid wipe transactions") val genXpi = xipConfig != null - def addXip(): MuraxConfig = copy(xipConfig = SpiDdrMasterCtrl.MemoryMappingParameters( - SpiDdrMasterCtrl.Parameters(8, 12, SpiDdrParameter(2, 1)).addAllMods(), - cmdFifoDepth = 32, - rspFifoDepth = 32, - xip = SpiDdrMasterCtrl.XipBusParameters(addressWidth = 24, dataWidth = 32) - )) } object MuraxConfig{ - def default = MuraxConfig( + def default : MuraxConfig = default(false) + def default(withXip : Boolean) = MuraxConfig( coreFrequency = 12 MHz, onChipRamSize = 8 kB, onChipRamHexFile = null, @@ -63,10 +58,15 @@ object MuraxConfig{ pipelineMainBus = false, pipelineApbBridge = true, gpioWidth = 32, - xipConfig = null, + xipConfig = ifGen(withXip) (SpiDdrMasterCtrl.MemoryMappingParameters( + SpiDdrMasterCtrl.Parameters(8, 12, SpiDdrParameter(2, 1)).addAllMods(), + cmdFifoDepth = 32, + rspFifoDepth = 32, + xip = SpiDdrMasterCtrl.XipBusParameters(addressWidth = 24, dataWidth = 32) + )), cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel new IBusSimplePlugin( - resetVector = 0x80000000l, + resetVector = if(withXip) 0xF001E000l else 0x80000000l, relaxedPcCalculation = true, prediction = NONE, catchAccessFault = false, @@ -224,7 +224,9 @@ case class Murax(config : MuraxConfig) extends Component{ val timerInterrupt = False val externalInterrupt = False for(plugin <- cpu.plugins) plugin match{ - case plugin : IBusSimplePlugin => mainBusArbiter.io.iBus <> plugin.iBus + case plugin : IBusSimplePlugin => + mainBusArbiter.io.iBus.cmd <> plugin.iBus.cmd.halfPipe() //TODO !! + mainBusArbiter.io.iBus.rsp <> plugin.iBus.rsp case plugin : DBusSimplePlugin => { if(!pipelineDBus) mainBusArbiter.io.dBus <> plugin.dBus @@ -289,7 +291,7 @@ case class Murax(config : MuraxConfig) extends Component{ apbMapping += ctrl.io.apb -> (0x1F000, 4 kB) val accessBus = new SimpleBus(SimpleBusConfig(24,32)) - mainBusMapping += accessBus -> (0x90000000l, 16 MB) + mainBusMapping += accessBus -> (0xE0000000l, 16 MB) ctrl.io.xip.cmd.valid <> (accessBus.cmd.valid && !accessBus.cmd.wr) ctrl.io.xip.cmd.ready <> accessBus.cmd.ready @@ -297,6 +299,9 @@ case class Murax(config : MuraxConfig) extends Component{ ctrl.io.xip.rsp.valid <> accessBus.rsp.valid ctrl.io.xip.rsp.payload <> accessBus.rsp.data + + val bootloader = Apb3Rom("src/main/c/murax/xipBootloader/crt.bin") + apbMapping += bootloader.io.apb -> (0x1E000, 4 kB) }) @@ -327,7 +332,7 @@ object Murax{ object MuraxWithXip{ def main(args: Array[String]) { - SpinalVerilog(Murax(MuraxConfig.default.addXip())) + SpinalVerilog(Murax(MuraxConfig.default(withXip = true))) } } diff --git a/src/main/scala/vexriscv/demo/MuraxUtiles.scala b/src/main/scala/vexriscv/demo/MuraxUtiles.scala index 8d60db5..44ca954 100644 --- a/src/main/scala/vexriscv/demo/MuraxUtiles.scala +++ b/src/main/scala/vexriscv/demo/MuraxUtiles.scala @@ -1,5 +1,7 @@ package vexriscv.demo +import java.nio.{ByteBuffer, ByteOrder} + import spinal.core._ import spinal.lib.bus.amba3.apb.{Apb3, Apb3Config, Apb3SlaveFactory} import spinal.lib.bus.misc.SizeMapping @@ -96,6 +98,27 @@ class MuraxSimpleBusRam(onChipRamSize : BigInt, onChipRamHexFile : String, simpl } + +case class Apb3Rom(onChipRamBinFile : String) extends Component{ + import java.nio.file.{Files, Paths} + val byteArray = Files.readAllBytes(Paths.get(onChipRamBinFile)) + val wordCount = (byteArray.length+3)/4 + val buffer = ByteBuffer.wrap(Files.readAllBytes(Paths.get(onChipRamBinFile))).order(ByteOrder.LITTLE_ENDIAN); + val wordArray = (0 until wordCount).map(i => { + val v = buffer.getInt + if(v < 0) BigInt(v.toLong & 0xFFFFFFFFl) else BigInt(v) + }) + + val io = new Bundle{ + val apb = slave(Apb3(log2Up(wordCount*4),32)) + } + + val rom = Mem(Bits(32 bits), wordCount) initBigInt(wordArray) +// io.apb.PRDATA := rom.readSync(io.apb.PADDR >> 2) + io.apb.PRDATA := rom.readAsync(RegNext(io.apb.PADDR >> 2)) + io.apb.PREADY := True +} + class MuraxSimpleBusToApbBridge(apb3Config: Apb3Config, pipelineBridge : Boolean, simpleBusConfig : SimpleBusConfig) extends Component{ assert(apb3Config.dataWidth == simpleBusConfig.dataWidth) diff --git a/src/test/scala/vexriscv/MuraxSim.scala b/src/test/scala/vexriscv/MuraxSim.scala index 4d65b63..a6cee0a 100644 --- a/src/test/scala/vexriscv/MuraxSim.scala +++ b/src/test/scala/vexriscv/MuraxSim.scala @@ -20,7 +20,7 @@ import scala.collection.mutable object MuraxSim { def main(args: Array[String]): Unit = { // def config = MuraxConfig.default.copy(onChipRamSize = 256 kB) - def config = MuraxConfig.default.copy(onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex").addXip() + def config = MuraxConfig.default(withXip = true).copy(onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex") val simSlowDown = true SimConfig.allOptimisation.withWave.compile(new Murax(config)).doSimUntilVoid{dut => val mainClkPeriod = (1e12/dut.config.coreFrequency.toDouble).toLong