XIP is physicaly working on murax
This commit is contained in:
parent
b51ac03a5e
commit
ff1d1072a7
|
@ -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];
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
*.bin
|
||||
*.elf
|
||||
*.map
|
||||
*.d
|
||||
*.asm
|
||||
*.o
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
@ -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)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue