From 28a11976daa0376db37766f807f5b234cc508dfb Mon Sep 17 00:00:00 2001 From: Mateusz Holenko Date: Wed, 10 Jul 2019 10:38:38 +0200 Subject: [PATCH 01/29] Allow to set custom RAM base address for emulator This is needed when loading the emulator to RAM with an offset. --- src/main/c/common/ram.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/c/common/ram.ld b/src/main/c/common/ram.ld index 19dc3d9..2ebf858 100755 --- a/src/main/c/common/ram.ld +++ b/src/main/c/common/ram.ld @@ -4,7 +4,7 @@ ENTRY( _start ) MEMORY { - ram : ORIGIN = 0x80000000, LENGTH = 64k + ram : ORIGIN = DEFINED(__ram_origin) ? __ram_origin : 0x80000000, LENGTH = 64k } From 423355ecbff46ef0dddc5e7a48ae10af2a2d1bea Mon Sep 17 00:00:00 2001 From: Mateusz Holenko Date: Wed, 10 Jul 2019 10:38:58 +0200 Subject: [PATCH 02/29] Allow to set custom DTB/OS_CALL addresses Setting those from command line during compilation allows to create a custom setup without the need of modifying the sources. --- src/main/c/emulator/src/config.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/c/emulator/src/config.h b/src/main/c/emulator/src/config.h index 191ae9f..6e251ad 100644 --- a/src/main/c/emulator/src/config.h +++ b/src/main/c/emulator/src/config.h @@ -3,7 +3,13 @@ //#define QEMU #define SIM + +#ifndef OS_CALL #define OS_CALL 0xC0000000 +#endif + +#ifndef DTB #define DTB 0xC3000000 +#endif #endif From 39c3f408e58bd0eb6b62638071f8de3e2659465b Mon Sep 17 00:00:00 2001 From: Mateusz Holenko Date: Wed, 10 Jul 2019 10:39:47 +0200 Subject: [PATCH 03/29] Create makefile targets Allow to change build target without modifiying the sources. In order to keep compatibilty `sim` target is built by default. --- src/main/c/emulator/makefile | 6 ++++++ src/main/c/emulator/src/config.h | 3 --- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/c/emulator/makefile b/src/main/c/emulator/makefile index e861785..d9d9098 100755 --- a/src/main/c/emulator/makefile +++ b/src/main/c/emulator/makefile @@ -12,6 +12,12 @@ SRCS = $(wildcard src/*.c) \ LDSCRIPT = ${STANDALONE}/common/ram.ld +sim: CFLAGS += -DSIM +sim: all + +qemu: CFLAGS += -DQEMU +qemu: all + include ${STANDALONE}/common/riscv64-unknown-elf.mk include ${STANDALONE}/common/standalone.mk diff --git a/src/main/c/emulator/src/config.h b/src/main/c/emulator/src/config.h index 6e251ad..afce2d5 100644 --- a/src/main/c/emulator/src/config.h +++ b/src/main/c/emulator/src/config.h @@ -1,9 +1,6 @@ #ifndef CONFIG_H #define CONFIG_H -//#define QEMU -#define SIM - #ifndef OS_CALL #define OS_CALL 0xC0000000 #endif From 6a2584b840a172f39b6c7882276a25a76874047c Mon Sep 17 00:00:00 2001 From: Mateusz Holenko Date: Wed, 10 Jul 2019 10:39:26 +0200 Subject: [PATCH 04/29] Add `litex` target Use configuration from the `csr.h` file generated dynamically when building a LiteX platform. --- src/main/c/emulator/makefile | 5 +++ src/main/c/emulator/src/hal.c | 71 ++++++++++++++++++++++++++++++++++ src/main/c/emulator/src/main.c | 2 +- 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/main/c/emulator/makefile b/src/main/c/emulator/makefile index d9d9098..7534d08 100755 --- a/src/main/c/emulator/makefile +++ b/src/main/c/emulator/makefile @@ -18,6 +18,11 @@ sim: all qemu: CFLAGS += -DQEMU qemu: all +litex: CFLAGS += -DLITEX -I${LITEX_BASE}/software/include +litex: | check_litex_base all +check_litex_base: + @[ "${LITEX_BASE}" ] || ( echo ">> LITEX_BASE is not set"; exit 1 ) + include ${STANDALONE}/common/riscv64-unknown-elf.mk include ${STANDALONE}/common/standalone.mk diff --git a/src/main/c/emulator/src/hal.c b/src/main/c/emulator/src/hal.c index 52bb0e4..a9189f2 100644 --- a/src/main/c/emulator/src/hal.c +++ b/src/main/c/emulator/src/hal.c @@ -144,5 +144,76 @@ void halInit(){ #endif +#ifdef LITEX + +// this is copied from LiteX +#define CSR_ACCESSORS_DEFINED +static inline void csr_writeb(uint8_t value, unsigned long addr) +{ + *((volatile uint8_t *)addr) = value; +} + +static inline uint8_t csr_readb(unsigned long addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline void csr_writew(uint16_t value, unsigned long addr) +{ + *((volatile uint16_t *)addr) = value; +} + +static inline uint16_t csr_readw(unsigned long addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline void csr_writel(uint32_t value, unsigned long addr) +{ + *((volatile uint32_t *)addr) = value; +} + +static inline uint32_t csr_readl(unsigned long addr) +{ + return *(volatile uint32_t *)addr; +} + +// this is a file generated by LiteX +#include + +#if !defined(CSR_UART_BASE) || !defined(CSR_CPU_BASE) + #error LiteX configuration with uart and cpu_timer is required. +#endif + +void stopSim(){ + while(1); +} + +void putC(char ch){ + uart_rxtx_write(ch); +} + +int32_t getC(){ + return uart_rxempty_read() + ? -1 + : uart_rxtx_read(); +} + +uint32_t rdtime(){ + return (uint32_t)cpu_timer_time_read(); +} + +uint32_t rdtimeh(){ + return (uint32_t)(cpu_timer_time_read() >> 32); +} + +void setMachineTimerCmp(uint32_t low, uint32_t high){ + cpu_timer_time_cmp_write((((unsigned long long int)high) << 32) | low); +} + +void halInit(){ +} + +#endif diff --git a/src/main/c/emulator/src/main.c b/src/main/c/emulator/src/main.c index 2102818..dc12fb8 100755 --- a/src/main/c/emulator/src/main.c +++ b/src/main/c/emulator/src/main.c @@ -161,7 +161,7 @@ void trap(){ #ifdef SIM uint32_t instruction = csr_read(mbadaddr); #endif -#ifdef QEMU +#if defined(QEMU) || defined(LITEX) uint32_t instruction = 0; uint32_t i; if (mepc & 2) { From 5085877eed6f965476f832d60c9c55080d8a7f63 Mon Sep 17 00:00:00 2001 From: Mateusz Holenko Date: Wed, 24 Jul 2019 14:55:47 +0200 Subject: [PATCH 05/29] Fix handling LiteX uart and timer. --- src/main/c/emulator/src/hal.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/c/emulator/src/hal.c b/src/main/c/emulator/src/hal.c index a9189f2..5a151bb 100644 --- a/src/main/c/emulator/src/hal.c +++ b/src/main/c/emulator/src/hal.c @@ -190,28 +190,44 @@ void stopSim(){ } void putC(char ch){ + // protect against writing to a full tx fifo + while(uart_txfull_read()); uart_rxtx_write(ch); } int32_t getC(){ - return uart_rxempty_read() - ? -1 - : uart_rxtx_read(); + if(uart_rxempty_read()) + { + return -1; + } + + // this is required to refresh rexempty status + uart_ev_pending_write(1 << 1); + return uart_rxtx_read(); } uint32_t rdtime(){ - return (uint32_t)cpu_timer_time_read(); + cpu_timer_latch_write(0); + uint32_t result = (uint32_t)cpu_timer_time_read(); + cpu_timer_latch_write(1); + return result; } uint32_t rdtimeh(){ - return (uint32_t)(cpu_timer_time_read() >> 32); + cpu_timer_latch_write(0); + uint32_t result = (uint32_t)(cpu_timer_time_read() >> 32); + cpu_timer_latch_write(1); + return result; } void setMachineTimerCmp(uint32_t low, uint32_t high){ + cpu_timer_latch_write(0); cpu_timer_time_cmp_write((((unsigned long long int)high) << 32) | low); + cpu_timer_latch_write(1); } void halInit(){ + cpu_timer_latch_write(1); } #endif From 955e70206c646fc1a19f4605dd3363aa8eeee17e Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Fri, 26 Apr 2019 18:01:35 +0800 Subject: [PATCH 06/29] MmuPlugin: fix generation without writeBack stage If there is no writeBack stage, the elaboration step would hit a NullPointerException when trying to insert into the writeBack stage. Instead, pull from the most recent stage, which is where MMU access should reside. Signed-off-by: Sean Cross --- src/main/scala/vexriscv/plugin/MmuPlugin.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/MmuPlugin.scala b/src/main/scala/vexriscv/plugin/MmuPlugin.scala index ebf46c4..9dedde5 100644 --- a/src/main/scala/vexriscv/plugin/MmuPlugin.scala +++ b/src/main/scala/vexriscv/plugin/MmuPlugin.scala @@ -250,8 +250,9 @@ class MmuPlugin(ioRange : UInt => Bool, } } - writeBack plug new Area{ - import writeBack._ + val fenceStage = stages.last + fenceStage plug new Area{ + import fenceStage._ when(arbitration.isValid && input(IS_SFENCE_VMA)){ // || csrService.isWriting(CSR.SATP) for(port <- core.ports; line <- port.cache) line.valid := False //Assume that the instruction already fetched into the pipeline are ok } From b0199297fdc1d58793fa18fd0f81af03c6a8252d Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Fri, 26 Apr 2019 18:02:43 +0800 Subject: [PATCH 07/29] caches: work without writeBack stage In the case of an MMU miss, the data caches will create a retry branch port. These currently implicitly go into the memory/writeBack stage, however not all CPUs have this stage. Place the retry branch port into the correct stage. Signed-off-by: Sean Cross --- src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala | 2 +- src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 78af84f..b8f2ba1 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -143,7 +143,7 @@ class DBusCachedPlugin(config : DataCacheConfig, decoderService.add(FENCE, Nil) mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig) - redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.writeBack) + redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.writeBack != null) pipeline.writeBack else pipeline.execute) if(catchSomething) exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.writeBack) diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala index aba2e88..8d23548 100644 --- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala @@ -309,7 +309,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, if(memoryTranslatorPortConfig != null) { mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA, memoryTranslatorPortConfig) - redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.memory) + redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.memory != null) pipeline.memory else pipeline.execute) } } From fe385da850d7bcff8f6a416fe44cd21a7ac82a45 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 16 Sep 2019 14:22:33 +0200 Subject: [PATCH 08/29] Fix Artix7 FMax, my apologies for that, was due to a bad scripting using Kintex 7 instead --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e595cbe..2af47aa 100644 --- a/README.md +++ b/README.md @@ -66,51 +66,51 @@ The CPU configurations used below can be found in the `src/scala/vexriscv/demo` ``` VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass, no interrupt) -> - Artix 7 -> 324 Mhz 496 LUT 505 FF + Artix 7 -> 233 Mhz 494 LUT 505 FF Cyclone V -> 193 Mhz 347 ALMs Cyclone IV -> 179 Mhz 730 LUT 494 FF iCE40 -> 92 Mhz 1130 LC VexRiscv smallest (RV32I, 0.52 DMIPS/Mhz, no datapath bypass) -> - Artix 7 -> 328 Mhz 539 LUT 562 FF + Artix 7 -> 232 Mhz 538 LUT 562 FF Cyclone V -> 189 Mhz 387 ALMs Cyclone IV -> 175 Mhz 829 LUT 550 FF iCE40 -> 85 Mhz 1292 LC VexRiscv small and productive (RV32I, 0.82 DMIPS/Mhz) -> - Artix 7 -> 324 Mhz 701 LUT 531 FF + Artix 7 -> 226 Mhz 689 LUT 531 FF Cyclone V -> 145 Mhz 499 ALMs Cyclone IV -> 150 Mhz 1,111 LUT 525 FF iCE40 -> 63 Mhz 1596 LC VexRiscv small and productive with I$ (RV32I, 0.70 DMIPS/Mhz, 4KB-I$) -> - Artix 7 -> 336 Mhz 764 LUT 562 FF + Artix 7 -> 230 Mhz 734 LUT 564 FF Cyclone V -> 145 Mhz 511 ALMs Cyclone IV -> 144 Mhz 1,145 LUT 531 FF iCE40 -> 66 Mhz 1680 LC VexRiscv full no cache (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz, single cycle barrel shifter, debug module, catch exceptions, static branch) -> - Artix 7 -> 326 Mhz 1544 LUT 977 FF + Artix 7 -> 219 Mhz 1537 LUT 977 FF Cyclone V -> 139 Mhz 958 ALMs - Cyclone IV -> 135 Mhz 2,011 LUT 968 FF + Cyclone IV -> 135 Mhz 2,011 LUT 968 FF VexRiscv full (RV32IM, 1.21 DMIPS/Mhz 2.30 Coremark/Mhz with cache trashing, 4KB-I$,4KB-D$, single cycle barrel shifter, debug module, catch exceptions, static branch) -> - Artix 7 -> 279 Mhz 1686 LUT 1172 FF + Artix 7 -> 193 Mhz 1706 LUT 1172 FF Cyclone V -> 144 Mhz 1,128 ALMs Cyclone IV -> 133 Mhz 2,298 LUT 1,096 FF VexRiscv full max dmips/mhz -> (RV32IM, 1.44 DMIPS/Mhz 2.70 Coremark/Mhz,, 16KB-I$,16KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch prediction in the fetch stage, branch and shift operations done in the Execute stage) -> - Artix 7 -> 193 Mhz 1758 LUT 1094 FF + Artix 7 -> 140 Mhz 1767 LUT 1128 FF Cyclone V -> 90 Mhz 1,089 ALMs Cyclone IV -> 79 Mhz 2,336 LUT 1,048 FF VexRiscv full with MMU (RV32IM, 1.24 DMIPS/Mhz 2.35 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, debug module, catch exceptions, dynamic branch, MMU) -> - Artix 7 -> 239 Mhz 2029 LUT 1585 FF + Artix 7 -> 161 Mhz 1985 LUT 1585 FF Cyclone V -> 124 Mhz 1,319 ALMs Cyclone IV -> 122 Mhz 2,710 LUT 1,501 FF VexRiscv linux balanced (RV32IMA, 1.21 DMIPS/Mhz 2.27 Coremark/Mhz, with cache trashing, 4KB-I$, 4KB-D$, single cycle barrel shifter, catch exceptions, static branch, MMU, Supervisor, Compatible with mainstream linux) -> - Artix 7 -> 249 Mhz 2549 LUT 2014 FF + Artix 7 -> 170 Mhz 2530 LUT 2013 FF Cyclone V -> 125 Mhz 1,618 ALMs Cyclone IV -> 116 Mhz 3,314 LUT 2,016 FF @@ -296,7 +296,7 @@ You can find some FPGA projects which instantiate the Briey SoC here (DE1-SoC, D Here are some measurements of Briey SoC timings and area : ``` - Artix 7 -> 275 Mhz 3072 LUT 3291 FF + Artix 7 -> 186 Mhz 3138 LUT 3328 FF Cyclone V -> 139 Mhz 2,175 ALMs Cyclone IV -> 129 Mhz 4,337 LUT 3,170 FF ``` @@ -351,13 +351,13 @@ Here are some timing and area measurements of the Murax SoC: ``` Murax interlocked stages (0.45 DMIPS/Mhz, 8 bits GPIO) -> - Artix 7 -> 313 Mhz 1039 LUT 1200 FF + Artix 7 -> 215 Mhz 1044 LUT 1202 FF Cyclone V -> 173 Mhz 737 ALMs Cyclone IV -> 144 Mhz 1,484 LUT 1,206 FF iCE40 -> 64 Mhz 2422 LC (nextpnr) MuraxFast bypassed stages (0.65 DMIPS/Mhz, 8 bits GPIO) -> - Artix 7 -> 323 Mhz 1241 LUT 1301 FF + Artix 7 -> 229 Mhz 1269 LUT 1302 FF Cyclone V -> 159 Mhz 864 ALMs Cyclone IV -> 137 Mhz 1,688 LUT 1,241 FF iCE40 -> 66 Mhz 2799 LC (nextpnr) From 0b79c637b672af5e0ff77b4dd7fe04859b34f419 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Fri, 20 Sep 2019 08:35:23 +0800 Subject: [PATCH 09/29] mulsimpleplugin: fix build for short pipelines Signed-off-by: Sean Cross --- src/main/scala/vexriscv/plugin/MulSimplePlugin.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/MulSimplePlugin.scala b/src/main/scala/vexriscv/plugin/MulSimplePlugin.scala index 41ed391..1be6da7 100644 --- a/src/main/scala/vexriscv/plugin/MulSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulSimplePlugin.scala @@ -66,14 +66,16 @@ class MulSimplePlugin extends Plugin[VexRiscv]{ insert(MUL_OPB) := ((bSigned ? b.msb | False) ## b).asSInt } - memory plug new Area { - import memory._ + val injectionStage = if(pipeline.memory != null) pipeline.memory else pipeline.execute + injectionStage plug new Area { + import injectionStage._ insert(MUL) := (input(MUL_OPA) * input(MUL_OPB))(63 downto 0).asBits } - writeBack plug new Area { - import writeBack._ + val memStage = stages.last + memStage plug new Area { + import memStage._ when(arbitration.isValid && input(IS_MUL)){ switch(input(INSTRUCTION)(13 downto 12)){ From fdc95debef1e898e419d435cc73448073f86a547 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Fri, 20 Sep 2019 08:35:49 +0800 Subject: [PATCH 10/29] dbuscached: fix build for short pipelines Signed-off-by: Sean Cross --- .../vexriscv/plugin/DBusCachedPlugin.scala | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 10e4550..8b1ceb4 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -226,8 +226,10 @@ class DBusCachedPlugin(val config : DataCacheConfig, if(relaxedMemoryTranslationRegister) insert(MEMORY_VIRTUAL_ADDRESS) := cache.io.cpu.execute.address } - memory plug new Area{ - import memory._ + val flushStage = if(memory != null) memory else execute + flushStage plug new Area { + import flushStage._ + cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE) cache.io.cpu.memory.isStuck := arbitration.isStuck cache.io.cpu.memory.isRemoved := arbitration.removeIt @@ -237,8 +239,9 @@ class DBusCachedPlugin(val config : DataCacheConfig, cache.io.cpu.memory.mmuBus.rsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite) } - writeBack plug new Area{ - import writeBack._ + val fenceStage = stages.last + fenceStage plug new Area{ + import fenceStage._ cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE) cache.io.cpu.writeBack.isStuck := arbitration.isStuck cache.io.cpu.writeBack.isUser := (if(privilegeService != null) privilegeService.isUser() else False) @@ -323,10 +326,10 @@ class DBusCachedPlugin(val config : DataCacheConfig, execute.insert(IS_DBUS_SHARING) := dBusAccess.cmd.fire - mmuBus.cmd.bypassTranslation setWhen(memory.input(IS_DBUS_SHARING)) - cache.io.cpu.memory.isValid setWhen(memory.input(IS_DBUS_SHARING)) - cache.io.cpu.writeBack.isValid setWhen(writeBack.input(IS_DBUS_SHARING)) - dBusAccess.rsp.valid := writeBack.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt) + mmuBus.cmd.bypassTranslation setWhen(flushStage.input(IS_DBUS_SHARING)) + cache.io.cpu.memory.isValid setWhen(flushStage.input(IS_DBUS_SHARING)) + cache.io.cpu.writeBack.isValid setWhen(fenceStage.input(IS_DBUS_SHARING)) + dBusAccess.rsp.valid := fenceStage.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt) dBusAccess.rsp.data := cache.io.cpu.writeBack.data dBusAccess.rsp.error := cache.io.cpu.writeBack.unalignedAccess || cache.io.cpu.writeBack.accessError dBusAccess.rsp.redo := cache.io.cpu.redo @@ -334,10 +337,10 @@ class DBusCachedPlugin(val config : DataCacheConfig, when(forceDatapath){ execute.output(REGFILE_WRITE_DATA) := dBusAccess.cmd.address.asBits } - memory.input(IS_DBUS_SHARING) init(False) - writeBack.input(IS_DBUS_SHARING) init(False) + flushStage.input(IS_DBUS_SHARING) init(False) + fenceStage.input(IS_DBUS_SHARING) init(False) when(dBusAccess.rsp.valid){ - writeBack.input(IS_DBUS_SHARING).getDrivingReg := False + fenceStage.input(IS_DBUS_SHARING).getDrivingReg := False } } } From b8b053e706a66d4baf936d42104db43eab4fbf21 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Fri, 20 Sep 2019 08:36:01 +0800 Subject: [PATCH 11/29] muldiviterative: fix build for short pipelines Signed-off-by: Sean Cross --- src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala index f366854..11af4ab 100644 --- a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala @@ -69,8 +69,9 @@ class MulDivIterativePlugin(genMul : Boolean = true, import pipeline.config._ if(!genMul && !genDiv) return - memory plug new Area { - import memory._ + val flushStage = if(memory != null) memory else execute + flushStage plug new Area { + import flushStage._ //Shared ressources val rs1 = Reg(UInt(33 bits)) From e8236dfebed0a55a955f87223cf1ffffabee009d Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sat, 21 Sep 2019 12:49:46 +0200 Subject: [PATCH 12/29] Add MulSimplePlugin regressions --- .../scala/vexriscv/TestIndividualFeatures.scala | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index 33e4aa6..7c11b14 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -99,6 +99,22 @@ class MulDivDimension extends VexRiscvDimension("MulDiv") { val noWriteBack = universes.contains(VexRiscvUniverse.NO_WRITEBACK) var l = List[VexRiscvPosition]() + + + + new VexRiscvPosition("MulDivFpgaSimple") { + override def testParam = "MUL=yes DIV=yes" + override def applyOn(config: VexRiscvConfig): Unit = { + config.plugins += new MulSimplePlugin + config.plugins += new MulDivIterativePlugin( + genMul = false, + genDiv = true, + mulUnrollFactor = 32, + divUnrollFactor = 1 + ) + } + } :: l + if(!noMemory) { l = new VexRiscvPosition("MulDivAsic") { override def testParam = "MUL=yes DIV=yes" From e1795e59d5660f627bfde5d13a1622866de8495f Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sat, 21 Sep 2019 13:00:54 +0200 Subject: [PATCH 13/29] Enable RF bypass on MUL DIV with pipeline wihout writeback/memory stages --- src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala | 2 +- src/main/scala/vexriscv/plugin/MulSimplePlugin.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala index 11af4ab..1bd8fb4 100644 --- a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala @@ -31,7 +31,7 @@ class MulDivIterativePlugin(genMul : Boolean = true, SRC1_CTRL -> Src1CtrlEnum.RS, SRC2_CTRL -> Src2CtrlEnum.RS, REGFILE_WRITE_VALID -> True, - BYPASSABLE_EXECUTE_STAGE -> False, + BYPASSABLE_EXECUTE_STAGE -> Bool(pipeline.stages.last == pipeline.execute), BYPASSABLE_MEMORY_STAGE -> True, RS1_USE -> True, RS2_USE -> True diff --git a/src/main/scala/vexriscv/plugin/MulSimplePlugin.scala b/src/main/scala/vexriscv/plugin/MulSimplePlugin.scala index 1be6da7..3b407e1 100644 --- a/src/main/scala/vexriscv/plugin/MulSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulSimplePlugin.scala @@ -19,8 +19,8 @@ class MulSimplePlugin extends Plugin[VexRiscv]{ SRC1_CTRL -> Src1CtrlEnum.RS, SRC2_CTRL -> Src2CtrlEnum.RS, REGFILE_WRITE_VALID -> True, - BYPASSABLE_EXECUTE_STAGE -> False, - BYPASSABLE_MEMORY_STAGE -> False, + BYPASSABLE_EXECUTE_STAGE -> Bool(pipeline.stages.last == pipeline.execute), + BYPASSABLE_MEMORY_STAGE -> Bool(pipeline.stages.last == pipeline.memory), RS1_USE -> True, RS2_USE -> True, IS_MUL -> True From ace963b542b773584f45158339b3e48e355bee7a Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sat, 21 Sep 2019 14:13:28 +0200 Subject: [PATCH 14/29] Hazard on memory stage do not need to know if that's bypassable if the memory stage is the last one --- src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala b/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala index f674ae8..1ed1d83 100644 --- a/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala @@ -95,7 +95,7 @@ class HazardSimplePlugin(bypassExecute : Boolean = false, } if(withWriteBackStage) trackHazardWithStage(writeBack,bypassWriteBack,null) - if(withMemoryStage) trackHazardWithStage(memory ,bypassMemory ,BYPASSABLE_MEMORY_STAGE) + if(withMemoryStage) trackHazardWithStage(memory ,bypassMemory, if(stages.last == memory) null else BYPASSABLE_MEMORY_STAGE) if(readStage != execute) trackHazardWithStage(execute ,bypassExecute , if(stages.last == execute) null else BYPASSABLE_EXECUTE_STAGE) From bf82829e9edeb68545036bfbd8667bb8280bd465 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 23 Sep 2019 15:20:20 +0200 Subject: [PATCH 15/29] Data cache can now be used without writeback stage --- src/main/scala/vexriscv/ip/DataCache.scala | 19 +++++++---- .../vexriscv/plugin/DBusCachedPlugin.scala | 34 ++++++++++--------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index f692680..17c4bf6 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -24,8 +24,9 @@ case class DataCacheConfig(cacheSize : Int, earlyDataMux : Boolean = false, tagSizeShift : Int = 0, //Used to force infering ram withLrSc : Boolean = false, - withAmo : Boolean = false){ - + withAmo : Boolean = false, + mergeExecuteMemory : Boolean = false){ + assert(!(mergeExecuteMemory && (earlyDataMux || earlyWaysHits))) assert(!(earlyDataMux && !earlyWaysHits)) def burstSize = bytePerLine*8/memDataWidth val burstLength = bytePerLine/(memDataWidth/8) @@ -446,7 +447,7 @@ class DataCache(p : DataCacheConfig) extends Component{ } val stageA = new Area{ - def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.memory.isStuck) + def stagePipe[T <: Data](that : T) = if(mergeExecuteMemory) CombInit(that) else RegNextWhen(that, !io.cpu.memory.isStuck) val request = stagePipe(io.cpu.execute.args) val mask = stagePipe(stage0.mask) io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid @@ -457,16 +458,22 @@ class DataCache(p : DataCacheConfig) extends Component{ val wayHits = earlyWaysHits generate ways.map(way => (io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagsReadRsp.address && way.tagsReadRsp.valid)) val dataMux = earlyDataMux generate MuxOH(wayHits, ways.map(_.dataReadRsp)) - val colisions = stagePipe(stage0.colisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto wordRange.low), mask) //Assume the writeback stage will never be unstall memory acces while memory stage is stalled + val colisions = if(mergeExecuteMemory){ + stagePipe(stage0.colisions) + } else { + //Assume the writeback stage will never be unstall memory acces while memory stage is stalled + stagePipe(stage0.colisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto wordRange.low), mask) + } } val stageB = new Area { def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.writeBack.isStuck) + def ramPipe[T <: Data](that : T) = if(mergeExecuteMemory) CombInit(that) else RegNextWhen(that, !io.cpu.writeBack.isStuck) val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck) val mmuRspFreeze = False val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck && !mmuRspFreeze) - val tagsReadRsp = ways.map(w => stagePipe(w.tagsReadRsp)) - val dataReadRsp = !earlyDataMux generate ways.map(w => stagePipe(w.dataReadRsp)) + val tagsReadRsp = ways.map(w => ramPipe(w.tagsReadRsp)) + val dataReadRsp = !earlyDataMux generate ways.map(w => ramPipe(w.dataReadRsp)) val waysHits = if(earlyWaysHits) stagePipe(B(stageA.wayHits)) else B(tagsReadRsp.map(tag => mmuRsp.physicalAddress(tagRange) === tag.address && tag.valid).asBits()) val waysHit = waysHits.orR val dataMux = if(earlyDataMux) stagePipe(stageA.dataMux) else MuxOH(waysHits, dataReadRsp) diff --git a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala index 8b1ceb4..9102a72 100644 --- a/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusCachedPlugin.scala @@ -148,7 +148,7 @@ class DBusCachedPlugin(val config : DataCacheConfig, redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.writeBack != null) pipeline.writeBack else pipeline.execute) if(catchSomething) - exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.writeBack) + exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(if(pipeline.writeBack == null) pipeline.memory else pipeline.writeBack) if(pipeline.serviceExist(classOf[PrivilegeService])) privilegeService = pipeline.service(classOf[PrivilegeService]) @@ -162,7 +162,9 @@ class DBusCachedPlugin(val config : DataCacheConfig, dBus = master(DataCacheMemBus(this.config)).setName("dBus") - val cache = new DataCache(this.config) + val cache = new DataCache(this.config.copy( + mergeExecuteMemory = writeBack == null + )) //Interconnect the plugin dBus with the cache dBus with some optional pipelining def optionPipe[T](cond : Boolean, on : T)(f : T => T) : T = if(cond) f(on) else on @@ -226,22 +228,22 @@ class DBusCachedPlugin(val config : DataCacheConfig, if(relaxedMemoryTranslationRegister) insert(MEMORY_VIRTUAL_ADDRESS) := cache.io.cpu.execute.address } - val flushStage = if(memory != null) memory else execute - flushStage plug new Area { - import flushStage._ + val mmuAndBufferStage = if(writeBack != null) memory else execute + mmuAndBufferStage plug new Area { + import mmuAndBufferStage._ cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE) cache.io.cpu.memory.isStuck := arbitration.isStuck cache.io.cpu.memory.isRemoved := arbitration.removeIt - cache.io.cpu.memory.address := (if(relaxedMemoryTranslationRegister) input(MEMORY_VIRTUAL_ADDRESS) else U(input(REGFILE_WRITE_DATA))) + cache.io.cpu.memory.address := (if(relaxedMemoryTranslationRegister) input(MEMORY_VIRTUAL_ADDRESS) else if(mmuAndBufferStage == execute) cache.io.cpu.execute.address else U(input(REGFILE_WRITE_DATA))) cache.io.cpu.memory.mmuBus <> mmuBus cache.io.cpu.memory.mmuBus.rsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite) } - val fenceStage = stages.last - fenceStage plug new Area{ - import fenceStage._ + val managementStage = stages.last + managementStage plug new Area{ + import managementStage._ cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE) cache.io.cpu.writeBack.isStuck := arbitration.isStuck cache.io.cpu.writeBack.isUser := (if(privilegeService != null) privilegeService.isUser() else False) @@ -326,10 +328,10 @@ class DBusCachedPlugin(val config : DataCacheConfig, execute.insert(IS_DBUS_SHARING) := dBusAccess.cmd.fire - mmuBus.cmd.bypassTranslation setWhen(flushStage.input(IS_DBUS_SHARING)) - cache.io.cpu.memory.isValid setWhen(flushStage.input(IS_DBUS_SHARING)) - cache.io.cpu.writeBack.isValid setWhen(fenceStage.input(IS_DBUS_SHARING)) - dBusAccess.rsp.valid := fenceStage.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt) + mmuBus.cmd.bypassTranslation setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING)) + if(mmuAndBufferStage != execute) (cache.io.cpu.memory.isValid setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING))) + cache.io.cpu.writeBack.isValid setWhen(managementStage.input(IS_DBUS_SHARING)) + dBusAccess.rsp.valid := managementStage.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt) dBusAccess.rsp.data := cache.io.cpu.writeBack.data dBusAccess.rsp.error := cache.io.cpu.writeBack.unalignedAccess || cache.io.cpu.writeBack.accessError dBusAccess.rsp.redo := cache.io.cpu.redo @@ -337,10 +339,10 @@ class DBusCachedPlugin(val config : DataCacheConfig, when(forceDatapath){ execute.output(REGFILE_WRITE_DATA) := dBusAccess.cmd.address.asBits } - flushStage.input(IS_DBUS_SHARING) init(False) - fenceStage.input(IS_DBUS_SHARING) init(False) + if(mmuAndBufferStage != execute) mmuAndBufferStage.input(IS_DBUS_SHARING) init(False) + managementStage.input(IS_DBUS_SHARING) init(False) when(dBusAccess.rsp.valid){ - fenceStage.input(IS_DBUS_SHARING).getDrivingReg := False + managementStage.input(IS_DBUS_SHARING).getDrivingReg := False } } } From 49944643d222fc72b800bb2fa1880f6ef91618c6 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 23 Sep 2019 15:20:51 +0200 Subject: [PATCH 16/29] Add regression for data cache without writeback stage, seem to pass tests, including linux ones --- .../vexriscv/TestIndividualFeatures.scala | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index 7c11b14..efa975c 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -392,7 +392,7 @@ class DBusDimension extends VexRiscvDimension("DBus") { - if(r.nextDouble() < 0.4 || noMemory || noWriteBack){ + if(r.nextDouble() < 0.4 || noMemory){ val withLrSc = catchAll val earlyInjection = r.nextBoolean() && !universes.contains(VexRiscvUniverse.NO_WRITEBACK) new VexRiscvPosition("Simple" + (if(earlyInjection) "Early" else "Late")) { @@ -412,7 +412,8 @@ class DBusDimension extends VexRiscvDimension("DBus") { var wayCount = 0 val withLrSc = catchAll val withAmo = catchAll && r.nextBoolean() - val dBusRspSlavePipe, relaxedMemoryTranslationRegister, earlyWaysHits = r.nextBoolean() + val dBusRspSlavePipe, relaxedMemoryTranslationRegister = r.nextBoolean() + val earlyWaysHits = r.nextBoolean() && !noWriteBack val dBusCmdMasterPipe, dBusCmdSlavePipe = false //As it create test bench issues do{ @@ -616,11 +617,11 @@ class TestIndividualFeatures extends FunSuite { val testId : Option[mutable.HashSet[Int]] = None val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong - +// // val testId = Some(mutable.HashSet(3,4,9,11,13,16,18,19,20,21)) -// val testId = Some(mutable.HashSet(24, 43, 49)) -// val testId = Some(mutable.HashSet(11)) -// val seed = -8309068850561113754l +// val testId = Some(mutable.HashSet(22)) +// val testId = Some(mutable.HashSet(22, 33 , 38, 47, 48)) +// val seed = 5426556825163943143l val rand = new Random(seed) @@ -638,11 +639,16 @@ class TestIndividualFeatures extends FunSuite { universe += VexRiscvUniverse.MMU universe += VexRiscvUniverse.FORCE_MULDIV universe += VexRiscvUniverse.SUPERVISOR + if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEMW_RATE", "0.6").toDouble < rand.nextDouble()){ + universe += VexRiscvUniverse.NO_WRITEBACK + } } else { if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_MACHINE_OS_RATE", "0.5").toDouble > rand.nextDouble()) { universe += VexRiscvUniverse.CATCH_ALL + if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEMW_RATE", "0.6").toDouble < rand.nextDouble()){ + universe += VexRiscvUniverse.NO_WRITEBACK + } } - var tmp = rand.nextDouble() if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEMW_RATE", "0.6").toDouble > rand.nextDouble()){ }else if(sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEM_RATE", "0.5").toDouble > rand.nextDouble()){ universe += VexRiscvUniverse.NO_WRITEBACK From 2d56c6738c8712621999e3c7fd75a8deb566aa91 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Sun, 20 Oct 2019 22:07:43 +0200 Subject: [PATCH 17/29] Multiplication Plugin using 16-bit DSPs --- .../scala/vexriscv/plugin/Mul16Plugin.scala | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/main/scala/vexriscv/plugin/Mul16Plugin.scala diff --git a/src/main/scala/vexriscv/plugin/Mul16Plugin.scala b/src/main/scala/vexriscv/plugin/Mul16Plugin.scala new file mode 100644 index 0000000..f2a63c3 --- /dev/null +++ b/src/main/scala/vexriscv/plugin/Mul16Plugin.scala @@ -0,0 +1,119 @@ +package vexriscv.plugin + +import vexriscv._ +import vexriscv.plugin._ +import spinal.core._ + +/** + * A multiplication plugin using only 16-bit multiplications + */ +class Mul16Plugin extends Plugin[VexRiscv]{ + + object MUL_LL extends Stageable(UInt(32 bits)) + object MUL_LH extends Stageable(UInt(32 bits)) + object MUL_HL extends Stageable(UInt(32 bits)) + object MUL_HH extends Stageable(UInt(32 bits)) + + object MUL extends Stageable(Bits(64 bits)) + + object IS_MUL extends Stageable(Bool) + + override def setup(pipeline: VexRiscv): Unit = { + import Riscv._ + import pipeline.config._ + + + val actions = List[(Stageable[_ <: BaseType],Any)]( + SRC1_CTRL -> Src1CtrlEnum.RS, + SRC2_CTRL -> Src2CtrlEnum.RS, + REGFILE_WRITE_VALID -> True, + BYPASSABLE_EXECUTE_STAGE -> False, + BYPASSABLE_MEMORY_STAGE -> False, + RS1_USE -> True, + RS2_USE -> True, + IS_MUL -> True + ) + + val decoderService = pipeline.service(classOf[DecoderService]) + decoderService.addDefault(IS_MUL, False) + decoderService.add(List( + MULX -> actions + )) + + } + + override def build(pipeline: VexRiscv): Unit = { + import pipeline._ + import pipeline.config._ + + // Prepare signed inputs for the multiplier in the next stage. + // This will map them best to an FPGA DSP. + execute plug new Area { + import execute._ + val a,b = Bits(32 bit) + + a := input(SRC1) + b := input(SRC2) + + val aLow = a(15 downto 0).asUInt + val bLow = b(15 downto 0).asUInt + val aHigh = a(31 downto 16).asUInt + val bHigh = b(31 downto 16).asUInt + + insert(MUL_LL) := aLow * bLow + insert(MUL_LH) := aLow * bHigh + insert(MUL_HL) := aHigh * bLow + insert(MUL_HH) := aHigh * bHigh + } + + memory plug new Area { + import memory._ + + val ll = UInt(32 bits) + val lh = UInt(33 bits) + val hl = UInt(32 bits) + val hh = UInt(32 bits) + + ll := input(MUL_LL) + lh := input(MUL_LH).resized + hl := input(MUL_HL) + hh := input(MUL_HH) + + val hllh = lh + hl + insert(MUL) := ((hh ## ll(31 downto 16)).asUInt + hllh) ## ll(15 downto 0) + } + + writeBack plug new Area { + import writeBack._ + val aSigned,bSigned = Bool + switch(input(INSTRUCTION)(13 downto 12)) { + is(B"01") { + aSigned := True + bSigned := True + } + is(B"10") { + aSigned := True + bSigned := False + } + default { + aSigned := False + bSigned := False + } + } + + val a = (aSigned && input(SRC1).msb) ? input(SRC2).asUInt | U(0) + val b = (bSigned && input(SRC2).msb) ? input(SRC1).asUInt | U(0) + + when(arbitration.isValid && input(IS_MUL)){ + switch(input(INSTRUCTION)(13 downto 12)){ + is(B"00"){ + output(REGFILE_WRITE_DATA) := input(MUL)(31 downto 0) + } + is(B"01",B"10",B"11"){ + output(REGFILE_WRITE_DATA) := (((input(MUL)(63 downto 32)).asUInt + ~a) + (~b + 2)).asBits + } + } + } + } + } +} From 8091a872f3b4d2e01135c8f1e5e4f471b8ddaa41 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 21 Oct 2019 12:53:03 +0200 Subject: [PATCH 18/29] Fix muldiv plugin for CPU configs without memory/writeback stages --- .../plugin/MulDivIterativePlugin.scala | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala index 1bd8fb4..a97a0ac 100644 --- a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala @@ -78,13 +78,19 @@ class MulDivIterativePlugin(genMul : Boolean = true, val rs2 = Reg(UInt(32 bits)) val accumulator = Reg(UInt(65 bits)) + //FrontendOK is only used for CPU configs without memory/writeback stages, were it is required to wait one extra cycle + // to let's the frontend process rs1 rs2 registers + val frontendOk = if(flushStage != execute) True else RegInit(False) setWhen(arbitration.isValid && ((if(genDiv) input(IS_DIV) else False) || (if(genMul) input(IS_MUL) else False))) clearWhen(arbitration.isMoving) val mul = ifGen(genMul) (if(customMul != null) customMul(rs1,rs2,memory,pipeline) else new Area{ assert(isPow2(mulUnrollFactor)) val counter = Counter(32 / mulUnrollFactor + 1) val done = counter.willOverflowIfInc when(arbitration.isValid && input(IS_MUL)){ - when(!done){ + when(!frontendOk || !done){ + arbitration.haltItself := True + } + when(frontendOk && !done){ arbitration.haltItself := True counter.increment() rs2 := rs2 |>> mulUnrollFactor @@ -113,8 +119,10 @@ class MulDivIterativePlugin(genMul : Boolean = true, val done = Reg(Bool) setWhen(counter === counter.end-1) clearWhen(!arbitration.isStuck) val result = Reg(Bits(32 bits)) when(arbitration.isValid && input(IS_DIV)){ - when(!done){ + when(!frontendOk || !done){ arbitration.haltItself := True + } + when(frontendOk && !done){ counter.increment() def stages(inNumerator: UInt, inRemainder: UInt, stage: Int): Unit = stage match { @@ -140,16 +148,11 @@ class MulDivIterativePlugin(genMul : Boolean = true, } output(REGFILE_WRITE_DATA) := result -// when(input(INSTRUCTION)(13 downto 12) === "00" && counter === 0 && rs2 =/= 0 && rs1 < 16 && rs2 < 16 && !input(RS1).msb && !input(RS2).msb) { -// output(REGFILE_WRITE_DATA) := B(rs1(3 downto 0) / rs2(3 downto 0)).resized -// counter.willIncrement := False -// arbitration.haltItself := False -// } } }) //Execute stage logic to drive memory stage's input regs - when(!arbitration.isStuck){ + when(if(flushStage != execute) !arbitration.isStuck else !frontendOk){ accumulator := 0 def twoComplement(that : Bits, enable: Bool): UInt = (Mux(enable, ~that, that).asUInt + enable.asUInt) val rs2NeedRevert = execute.input(RS2).msb && execute.input(IS_RS2_SIGNED) From 67028cdb48ce9087aa6c5168d8b0c10584a3ce04 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Mon, 21 Oct 2019 12:53:53 +0200 Subject: [PATCH 19/29] Add Mul16Plugin to regression tests Fix missing MulSimplePlugin in regressions tests --- .../vexriscv/TestIndividualFeatures.scala | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index efa975c..005f335 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -102,7 +102,7 @@ class MulDivDimension extends VexRiscvDimension("MulDiv") { - new VexRiscvPosition("MulDivFpgaSimple") { + l = new VexRiscvPosition("MulDivFpgaSimple") { override def testParam = "MUL=yes DIV=yes" override def applyOn(config: VexRiscvConfig): Unit = { config.plugins += new MulSimplePlugin @@ -115,6 +115,19 @@ class MulDivDimension extends VexRiscvDimension("MulDiv") { } } :: l + if(!noMemory && !noWriteBack) l = new VexRiscvPosition("MulDivFpga16BitsDsp") { + override def testParam = "MUL=yes DIV=yes" + override def applyOn(config: VexRiscvConfig): Unit = { + config.plugins += new Mul16Plugin + config.plugins += new MulDivIterativePlugin( + genMul = false, + genDiv = true, + mulUnrollFactor = 32, + divUnrollFactor = 1 + ) + } + } :: l + if(!noMemory) { l = new VexRiscvPosition("MulDivAsic") { override def testParam = "MUL=yes DIV=yes" @@ -619,9 +632,9 @@ class TestIndividualFeatures extends FunSuite { val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong // // val testId = Some(mutable.HashSet(3,4,9,11,13,16,18,19,20,21)) -// val testId = Some(mutable.HashSet(22)) -// val testId = Some(mutable.HashSet(22, 33 , 38, 47, 48)) -// val seed = 5426556825163943143l +// val testId = Some(mutable.HashSet(11)) +// val testId = Some(mutable.HashSet(4, 11)) +// val seed = 6592877339343561798l val rand = new Random(seed) From bb9261773b26513e3e983e6951500307b3f8fe62 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Wed, 23 Oct 2019 00:02:08 +0200 Subject: [PATCH 20/29] Fix MulDiveIterative plugin when RSx have hazard in the execute stage --- src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala index a97a0ac..6820f8e 100644 --- a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala @@ -80,7 +80,7 @@ class MulDivIterativePlugin(genMul : Boolean = true, //FrontendOK is only used for CPU configs without memory/writeback stages, were it is required to wait one extra cycle // to let's the frontend process rs1 rs2 registers - val frontendOk = if(flushStage != execute) True else RegInit(False) setWhen(arbitration.isValid && ((if(genDiv) input(IS_DIV) else False) || (if(genMul) input(IS_MUL) else False))) clearWhen(arbitration.isMoving) + val frontendOk = if(flushStage != execute) True else RegInit(False) setWhen(arbitration.isValid && !pipeline.service(classOf[HazardService]).hazardOnExecuteRS && ((if(genDiv) input(IS_DIV) else False) || (if(genMul) input(IS_MUL) else False))) clearWhen(arbitration.isMoving) val mul = ifGen(genMul) (if(customMul != null) customMul(rs1,rs2,memory,pipeline) else new Area{ assert(isPow2(mulUnrollFactor)) From 8839f8a8e9c443e59c04291a00b1ee5c3cec6d62 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Sun, 3 Nov 2019 16:43:29 +0100 Subject: [PATCH 21/29] Fix DBus AXI bridges from writePending counter deadlock --- src/main/scala/vexriscv/ip/DataCache.scala | 9 +++++---- .../scala/vexriscv/plugin/DBusSimplePlugin.scala | 12 +++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index 17c4bf6..838489d 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -185,16 +185,17 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave slave(rsp) } - def toAxi4Shared(stageCmd : Boolean = false): Axi4Shared = { + def toAxi4Shared(stageCmd : Boolean = false, pendingWritesMax : Int = 7): Axi4Shared = { val axi = Axi4Shared(p.getAxi4SharedConfig()) - val pendingWritesMax = 7 + + val cmdPreFork = if (stageCmd) cmd.stage.stage().s2mPipe() else cmd + val pendingWrites = CounterUpDown( stateCount = pendingWritesMax + 1, - incWhen = axi.sharedCmd.fire && axi.sharedCmd.write, + incWhen = cmdPreFork.fire && cmdPreFork.wr, decWhen = axi.writeRsp.fire ) - val cmdPreFork = if (stageCmd) cmd.stage.stage().s2mPipe() else cmd val hazard = (pendingWrites =/= 0 && !cmdPreFork.wr) || pendingWrites === pendingWritesMax val (cmdFork, dataFork) = StreamFork2(cmdPreFork.haltWhen(hazard)) val cmdStage = cmdFork.throwWhen(RegNextWhen(!cmdFork.last,cmdFork.fire).init(False)) diff --git a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala index fe5ac77..e08b640 100644 --- a/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DBusSimplePlugin.scala @@ -106,17 +106,19 @@ case class DBusSimpleBus() extends Bundle with IMasterSlave{ s } - def toAxi4Shared(stageCmd : Boolean = false): Axi4Shared = { + def toAxi4Shared(stageCmd : Boolean = false, pendingWritesMax : Int = 7): Axi4Shared = { val axi = Axi4Shared(DBusSimpleBus.getAxi4Config()) - val pendingWritesMax = 7 + + val cmdPreFork = if (stageCmd) cmd.stage.stage().s2mPipe() else cmd + val pendingWrites = CounterUpDown( stateCount = pendingWritesMax + 1, - incWhen = axi.sharedCmd.fire && axi.sharedCmd.write, + incWhen = cmdPreFork.fire && cmdPreFork.wr, decWhen = axi.writeRsp.fire ) - val cmdPreFork = if (stageCmd) cmd.stage.stage().s2mPipe() else cmd - val (cmdFork, dataFork) = StreamFork2(cmdPreFork.haltWhen((pendingWrites =/= 0 && cmdPreFork.valid && !cmdPreFork.wr) || pendingWrites === pendingWritesMax)) + val hazard = (pendingWrites =/= 0 && cmdPreFork.valid && !cmdPreFork.wr) || pendingWrites === pendingWritesMax + val (cmdFork, dataFork) = StreamFork2(cmdPreFork.haltWhen(hazard)) axi.sharedCmd.arbitrationFrom(cmdFork) axi.sharedCmd.write := cmdFork.wr axi.sharedCmd.prot := "010" From f6e707a6394be16a78efe6608019c9596bedd189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Piku=C5=82a?= Date: Thu, 7 Nov 2019 14:47:36 +0100 Subject: [PATCH 22/29] Update index links in README Eclipse links in index were incorrect. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2af47aa..d0deb16 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ - [Regression tests](#regression-tests) - [Interactive debug of the simulated CPU via GDB OpenOCD and Verilator](#interactive-debug-of-the-simulated-cpu-via-gdb-openocd-and-verilator) - [Using Eclipse to run the software and debug it](#using-Eclipse-to-run-the-software-and-debug-it) - * [By using Zylin plugin](#by-using-zylin-plugin) - * [By using FreedomStudio](#by-using-freedomstudio) + * [By using gnu-mcu-eclipse](#by-using-gnu-mcu-eclipse) + * [By using Zylin plugin (old)](#by-using-zylin-plugin-old) - [Briey SoC](#briey-soc) - [Murax SoC](#murax-soc) - [Running Linux](#running-linux) From 061ebd1b2cc78e4ae6df070a2a75be14f636c3a8 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Sun, 12 Jan 2020 13:27:45 +0100 Subject: [PATCH 23/29] Fix murax xip bootloader --- src/main/c/murax/xipBootloader/crt.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/c/murax/xipBootloader/crt.S b/src/main/c/murax/xipBootloader/crt.S index 178f788..8da77ab 100644 --- a/src/main/c/murax/xipBootloader/crt.S +++ b/src/main/c/murax/xipBootloader/crt.S @@ -49,6 +49,6 @@ spiWrite: sw a0,CTRL_DATA(CTRL) spiWrite_wait: lw t0,CTRL_STATUS(CTRL) - srli t0,t0,0x10 + slli t0,t0,0x10 beqz t0,spiWrite_wait ret From b866dcb07f3aca8fc86187b0ae3adb9df081537c Mon Sep 17 00:00:00 2001 From: sebastien-riou Date: Sun, 12 Jan 2020 16:08:14 +0100 Subject: [PATCH 24/29] XIP on Murax improvements --- .../iCE40-hx8k_breakout_board_xip/Makefile | 22 +-- .../iCE40-hx8k_breakout_board_xip/README.md | 135 ++++++++++++++++-- src/main/c/murax/xipBootloader/crt.S | 14 +- src/main/c/murax/xipBootloader/crt.bin | Bin 120 -> 176 bytes src/main/c/murax/xipBootloader/demo.S | 11 +- src/main/c/murax/xipBootloader/demo.bin | Bin 48 -> 0 bytes src/main/c/murax/xipBootloader/makefile | 22 ++- src/main/c/murax/xipBootloader/mapping_rom.ld | 96 +++++++++++++ src/main/c/murax/xipBootloader/mapping_xip.ld | 96 +++++++++++++ src/main/scala/vexriscv/demo/Murax.scala | 42 +----- 10 files changed, 373 insertions(+), 65 deletions(-) delete mode 100755 src/main/c/murax/xipBootloader/demo.bin create mode 100644 src/main/c/murax/xipBootloader/mapping_rom.ld create mode 100644 src/main/c/murax/xipBootloader/mapping_xip.ld diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile b/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile index 88aa1a2..8feef20 100644 --- a/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile +++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/Makefile @@ -1,19 +1,21 @@ +VBASE = ../../.. +VNAME = Murax_iCE40_hx8k_breakout_board_xip +VERILOG = ${VBASE}/${VNAME}.v -VERILOG = ../../../Murax_iCE40_hx8k_breakout_board_xip.v +all: prog -generate : - #(cd ../../..; sbt "runMain vexriscv.demo.Murax_iCE40_hx8k_breakout_board_xip") +${VERILOG} : + (cd ${VBASE}; sbt "runMain vexriscv.demo.${VNAME}") -../../../Murax_iCE40_hx8k_breakout_board_xip.v : - #(cd ../../..; sbt "runMain vexriscv.demo.Murax_iCE40_hx8k_breakout_board_xip") +generate : ${VERILOG} -../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin: +${VERILOG}*.bin: -bin/Murax_iCE40_hx8k_breakout_board_xip.blif : ${VERILOG} ../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin +bin/Murax_iCE40_hx8k_breakout_board_xip.blif : ${VERILOG} ${VERILOG}*.bin mkdir -p bin rm -f Murax_iCE40_hx8k_breakout_board_xip.v*.bin - cp ../../../Murax_iCE40_hx8k_breakout_board_xip.v*.bin . | true + cp ${VERILOG}*.bin . | true yosys -v3 -p "synth_ice40 -top Murax_iCE40_hx8k_breakout_board_xip -blif bin/Murax_iCE40_hx8k_breakout_board_xip.blif" ${VERILOG} bin/Murax_iCE40_hx8k_breakout_board_xip.asc : Murax_iCE40_hx8k_breakout_board_xip.pcf bin/Murax_iCE40_hx8k_breakout_board_xip.blif @@ -28,11 +30,15 @@ time: bin/Murax_iCE40_hx8k_breakout_board_xip.bin icetime -tmd hx8k bin/Murax_iCE40_hx8k_breakout_board_xip.asc prog : bin/Murax_iCE40_hx8k_breakout_board_xip.bin + lsusb -d 0403:6010 iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin sudo-prog : bin/Murax_iCE40_hx8k_breakout_board_xip.bin + sudo lsusb -d 0403:6010 sudo iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin clean : rm -rf bin rm -f Murax_iCE40_hx8k_breakout_board_xip.v*.bin + rm -f ${VERILOG}*.bin + rm -f ${VERILOG} diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md b/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md index 1e50a02..06e9439 100644 --- a/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md +++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md @@ -59,12 +59,29 @@ The process should take around 30 seconds on a reasonable fast computer. ## Programming +Make sure the FPGA board is the only USB peripheral with ID 0403:6010 + +For example, this is bad: +``` +user@lafite:~$ lsusb -d 0403:6010 +Bus 001 Device 088: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC +Bus 001 Device 090: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC +``` +This is good: +``` +user@lafite:~$ lsusb -d 0403:6010 +Bus 001 Device 088: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC +``` + + After building you should be able to run `make prog`. You may need to run `make sudo-prog` if root is needed to access your USB devices. You should get output like the following; ``` -iceprog -S bin/toplevel.bin +lsusb -d 0403:6010 +Bus 001 Device 088: ID 0403:6010 Future Technology Devices International, Ltd FT2232C Dual USB-UART/FIFO IC +iceprog -S bin/Murax_iCE40_hx8k_breakout_board_xip.bin init.. cdone: high reset.. @@ -74,13 +91,115 @@ cdone: high Bye. ``` -After programming the LEDs at the top of the board should start flashing in an -interesting pattern. +WARNING: having this output does NOT guarantee you actually programmed anything in the FPGA! -## Connect +After programming nothing visual will happen, except the LEDs being off. +The bootloader is waiting for a valid content in the flash. "valid content" is +identified by a magic word at 0xE0040000: it shall be 0x12340fb7, which is the +value for the instruction "li x31, 0x12340000". -After programming you should be able to connect to the serial port and have the -output echoed back to you. +## Programming flash image -On Linux you can do this using a command like `screen /dev/ttyUSB1`. Then as -you type you should get back the same characters. +### Connect JTAG + +We will use vexrisc JTAG to program the flash, so you need openocd and a +suitable JTAG dongle. + +Pin-out: +``` +TCK: H16 aka J2.25 +TDO: G16 aka J2.26 +TDI: G15 aka J2.27 +TMS: F15 aka J2.28 +``` +In addition you need to connect the ground and VTarget aka VIO: J2.2 on the +board. + +### Start GDB server / OpenOCD +Make sure to use https://github.com/SpinalHDL/openocd_riscv +Make sure to select the configuration file which match your JTAG dongle. + +An example with the dongle "ft2232h_breakout": +``` +src/openocd -f tcl/interface/ftdi/ft2232h_breakout.cfg -c "set MURAX_CPU0_YAML ../VexRiscv/cpu0.yaml" -f tcl/target/murax_xip.cfg +``` + +You should get an output like below: +``` +Open On-Chip Debugger 0.10.0+dev-01214-g0ace94f (2019-10-02-18:23) +Licensed under GNU GPL v2 +For bug reports, read + http://openocd.org/doc/doxygen/bugs.html +../VexRiscv/cpu0.yaml +adapter speed: 100 kHz +adapter_nsrst_delay: 260 +Info : auto-selecting first available session transport "jtag". To override use 'transport select '. +jtag_ntrst_delay: 250 +Info : set servers polling period to 50ms +Error: libusb_get_string_descriptor_ascii() failed with LIBUSB_ERROR_INVALID_PARAM +Info : clock speed 100 kHz +Info : JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (), part: 0x0001, ver: 0x1) +Info : Listening on port 3333 for gdb connections +requesting target halt and executing a soft reset +Info : Listening on port 6666 for tcl connections +Info : Listening on port 4444 for telnet connections +``` + +### Loading the flash with telnet + +First we connect and stop execution on the device: +``` +user@lafite:~/Downloads/vexrisc_full/VexRiscv/src/main/c/murax/xipBootloader$ telnet 127.0.0.1 4444 +Trying 127.0.0.1... +Connected to 127.0.0.1. +Escape character is '^]'. +Open On-Chip Debugger +> reset +JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (), part: 0x0001, ver: 0x1) +> +``` + +Now we can safely connect the J7 jumper on the board to be able to access the flash. +After that, we can load the program in flash: +``` +> flash erase_sector 0 4 4 +erased sectors 4 through 4 on flash bank 0 in 0.872235s +> flash write_bank 0 /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin 0x40000 +wrote 48 bytes from file /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin to flash bank 0 at offset 0x00040000 in 0.285539s (0.164 KiB/s) +> flash verify_bank 0 /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin 0x40000 +read 48 bytes from file /home/user/dev/vexrisc_fork/VexRiscv/src/main/c/murax/xipBootloader/demo_xip.bin and flash bank 0 at offset 0x00040000 in 0.192036s (0.244 KiB/s) +contents match +> reset +JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (), part: 0x0001, ver: 0x1) +> resume +> exit +Connection closed by foreign host. +``` + +From now the device runs the code from flash, LEDs shall display a dot moving from D9 to D2. + +### Loading flash using GDB / eclipse +- ``` +src/openocd -f tcl/interface/ftdi/ft2232h_breakout.cfg -c "set MURAX_CPU0_YAML ../VexRiscv/cpu0.yaml" -f tcl/target/murax_xip.cfg +``` +- Make sure J7 is connected. +- Connect to GDB / eclipse as usual. + +From there code loading, step, break points works as usual (including software break points in flash). + +## Update hardware/bootloader + +- Stop any OpenOCD connection +- Remove J7, then: +- ``` +make clean prog +``` +- Remember to check a single FTDI device is listed in the output. If not: + - Disconnect the other devices + - ``` + make prog + ``` +- Connect J7, flash software shall start executing. + +## Flash software +Refer to "Loading the flash with telnet" or "Loading flash using GDB / eclipse". diff --git a/src/main/c/murax/xipBootloader/crt.S b/src/main/c/murax/xipBootloader/crt.S index 178f788..8668c8a 100644 --- a/src/main/c/murax/xipBootloader/crt.S +++ b/src/main/c/murax/xipBootloader/crt.S @@ -42,13 +42,25 @@ crtStart: li t0, 0x1 sw t0, CTRL_XIP_CONFIG(CTRL) li t0, XIP_BASE + lw t1, (t0) + li t2, 0x12340fb7 + xor t1,t1,t2 + bnez t1,retry jr t0 +retry: + li a0, 0x800 + call spiWrite + li t1,100000 +loop: + addi t1,t1,-1 + bnez t1, loop + j crtStart spiWrite: sw a0,CTRL_DATA(CTRL) spiWrite_wait: lw t0,CTRL_STATUS(CTRL) - srli t0,t0,0x10 + slli t0,t0,0x10 beqz t0,spiWrite_wait ret diff --git a/src/main/c/murax/xipBootloader/crt.bin b/src/main/c/murax/xipBootloader/crt.bin index d64a1cb00efe30e57fa9ae8eb357f1590f780573..bf751967431a1eb58a39071360f4fe56c3dfae48 100755 GIT binary patch delta 141 zcmb=}z&Jsxo`GGMRY2lBLj#*Is{xQ^U^5qGU=U_yZFtY%z`C93Kf~mvO#;e`;#np$ z2{0%xh-cZ(#PWc7F%!dfVH2Ur&Becsor@WgMVJ}V8<-dndK(zcn;98|nVGYMnLq!3 jEXVvW|HJ)n$_v&rG%xaJm^_Jz@o^8+zjXEn1~32sem5w1 delta 84 zcmdnMSTRA%?*OwftANCN1_vN*0HhBvnTs+o2(z*_yk}rw+RpT!VRF+Z0p&&UER&f8 l7?c;pvutN#d63?~1Z1ygXkO&cF!>S_E<%Gcy-XZW030pZ`CWWB!-_Vg5e`AOHYn Cd=EPS diff --git a/src/main/c/murax/xipBootloader/makefile b/src/main/c/murax/xipBootloader/makefile index 56b8ab8..4421131 100644 --- a/src/main/c/murax/xipBootloader/makefile +++ b/src/main/c/murax/xipBootloader/makefile @@ -4,20 +4,34 @@ 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-gcc $(CFLAGS) -o crt.elf crt.o $(LFLAGS) -Wl,-Bstatic,-T,mapping_rom.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 $(CFLAGS) -o crt_ram.elf crt.o $(LFLAGS) -Wl,-Bstatic,-T,mapping.ld,-Map,crt_ram.map,--print-memory-usage + riscv64-unknown-elf-objdump -S -d crt_ram.elf > crt_ram.asm + riscv64-unknown-elf-objcopy -O binary crt_ram.elf crt_ram.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 + riscv64-unknown-elf-gcc $(CFLAGS) -o demo_rom.elf demo.o $(LFLAGS) -Wl,-Bstatic,-T,mapping_rom.ld,-Map,demo_rom.map,--print-memory-usage + riscv64-unknown-elf-objdump -S -d demo_rom.elf > demo_rom.asm + riscv64-unknown-elf-objcopy -O binary demo_rom.elf demo_rom.bin + riscv64-unknown-elf-gcc $(CFLAGS) -o demo_xip.elf demo.o $(LFLAGS) -Wl,-Bstatic,-T,mapping_xip.ld,-Map,demo_xip.map,--print-memory-usage + riscv64-unknown-elf-objdump -S -d demo_xip.elf > demo_xip.asm + riscv64-unknown-elf-objcopy -O binary demo_xip.elf demo_xip.bin -clean: +clean-for-commit: rm -f *.o - rm -f *.bin rm -f *.elf rm -f *.asm - rm -f *.map \ No newline at end of file + rm -f *.map + rm -f *.d + rm demo_rom.bin demo.bin crt_ram.bin + +clean: clean-tmp + rm -f *.bin diff --git a/src/main/c/murax/xipBootloader/mapping_rom.ld b/src/main/c/murax/xipBootloader/mapping_rom.ld new file mode 100644 index 0000000..aaa0c3c --- /dev/null +++ b/src/main/c/murax/xipBootloader/mapping_rom.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 + rom : ORIGIN = 0xF001E000, LENGTH = 0x00000400 +} + +_stack_size = DEFINED(_stack_size) ? _stack_size : 0; + +SECTIONS { + + .vector : { + *crt.o(.text); + } > rom + + .memory : { + *(.text); + end = .; + } > rom + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } > rom + + .ctors : + { + . = ALIGN(4); + _ctors_start = .; + KEEP(*(.init_array*)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + . = ALIGN(4); + _ctors_end = .; + } > rom + + .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.*) + } > rom + + .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/c/murax/xipBootloader/mapping_xip.ld b/src/main/c/murax/xipBootloader/mapping_xip.ld new file mode 100644 index 0000000..ed56400 --- /dev/null +++ b/src/main/c/murax/xipBootloader/mapping_xip.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 + xip : ORIGIN = 0xE0040000, LENGTH = 0x00000400 +} + +_stack_size = DEFINED(_stack_size) ? _stack_size : 0; + +SECTIONS { + + .vector : { + *crt.o(.text); + } > xip + + .memory : { + *(.text); + end = .; + } > xip + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } > xip + + .ctors : + { + . = ALIGN(4); + _ctors_start = .; + KEEP(*(.init_array*)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + . = ALIGN(4); + _ctors_end = .; + } > xip + + .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.*) + } > xip + + .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 d78beeb..846fa04 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -385,7 +385,8 @@ object Murax_iCE40_hx8k_breakout_board_xip{ val led = out Bits(8 bits) } - val murax = Murax(MuraxConfig.default(withXip = true)) + //val murax = Murax(MuraxConfig.default(withXip = true)) + val murax = Murax(MuraxConfig.default(withXip = true).copy(onChipRamSize = 8 kB)) murax.io.asyncReset := False val mainClkBuffer = SB_GB() @@ -438,45 +439,6 @@ object Murax_iCE40_hx8k_breakout_board_xip{ def main(args: Array[String]) { SpinalVerilog(Murax_iCE40_hx8k_breakout_board_xip()) - /*SpinalVerilog{ - val c = Murax(MuraxConfig.default(withXip = true)) - - - - - c.rework { - c.resetCtrlClockDomain { - c.io.xip.setAsDirectionLess.allowDirectionLessIo.flattenForeach(_.unsetName()) - - out(RegNext(c.io.xip.ss)).setName("io_xip_ss") - - val sclk = SB_IO_SCLK() - sclk.PACKAGE_PIN := inout(Analog(Bool)).setName("io_xip_sclk") - sclk.CLOCK_ENABLE := True - - sclk.OUTPUT_CLK := ClockDomain.current.readClockWire - sclk.D_OUT_0 <> c.io.xip.sclk.write(0) - sclk.D_OUT_1 <> RegNext(c.io.xip.sclk.write(1)) - - for (i <- 0 until c.io.xip.p.dataWidth) { - val data = c.io.xip.data(i) - val bb = SB_IO_DATA() - bb.PACKAGE_PIN := inout(Analog(Bool)).setName(s"io_xip_data_$i" ) - bb.CLOCK_ENABLE := True - - bb.OUTPUT_CLK := ClockDomain.current.readClockWire - bb.OUTPUT_ENABLE <> data.writeEnable - bb.D_OUT_0 <> data.write(0) - bb.D_OUT_1 <> RegNext(data.write(1)) - - bb.INPUT_CLK := ClockDomain.current.readClockWire - data.read(0) := bb.D_IN_0 - data.read(1) := RegNext(bb.D_IN_1) - } - } - } - c - }*/ } } From bfb0b54f9b9893d96860b6e4169921391a7086da Mon Sep 17 00:00:00 2001 From: sebastien-riou Date: Sun, 12 Jan 2020 19:52:27 +0100 Subject: [PATCH 25/29] readme for XIP on Murax improved --- .../Murax/iCE40-hx8k_breakout_board_xip/README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md b/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md index 06e9439..f7a4dac 100644 --- a/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md +++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md @@ -9,6 +9,11 @@ This board can be purchased for ~$USD 49 directly from Lattice and is supported by the IceStorm [`iceprog`](https://github.com/cliffordwolf/icestorm/tree/master/iceprog) tool. +# Bootloader operations + +A bootloader is implemented in a ROM within the FPGA bitfile. It configure the SPI and attempt to read the first word in 'XIP' area of the flash (0xE0040000 in CPU address space, 0x40000 in flash). If this first word is the magic word +then the bootloader jump at 0xE0040000. +The magic word is 0x12340fb7, which is the value for the instruction "li x31, 0x12340000" or "lui t6,0x12340". # Using the example @@ -94,9 +99,7 @@ Bye. WARNING: having this output does NOT guarantee you actually programmed anything in the FPGA! After programming nothing visual will happen, except the LEDs being off. -The bootloader is waiting for a valid content in the flash. "valid content" is -identified by a magic word at 0xE0040000: it shall be 0x12340fb7, which is the -value for the instruction "li x31, 0x12340000". +The bootloader is waiting for a valid content in the flash (see Bootloader operations). ## Programming flash image @@ -179,7 +182,7 @@ Connection closed by foreign host. From now the device runs the code from flash, LEDs shall display a dot moving from D9 to D2. ### Loading flash using GDB / eclipse -- ``` +``` src/openocd -f tcl/interface/ftdi/ft2232h_breakout.cfg -c "set MURAX_CPU0_YAML ../VexRiscv/cpu0.yaml" -f tcl/target/murax_xip.cfg ``` - Make sure J7 is connected. @@ -191,12 +194,12 @@ From there code loading, step, break points works as usual (including software b - Stop any OpenOCD connection - Remove J7, then: -- ``` +``` make clean prog ``` - Remember to check a single FTDI device is listed in the output. If not: - Disconnect the other devices - - ``` + ``` make prog ``` - Connect J7, flash software shall start executing. From de9f704de262ad7900940271a46df4d824d14c06 Mon Sep 17 00:00:00 2001 From: sebastien-riou Date: Mon, 13 Jan 2020 21:58:08 +0100 Subject: [PATCH 26/29] better pin names in scala, bootloader without magic word --- .../Murax_iCE40_hx8k_breakout_board_xip.pcf | 22 ++++----- .../iCE40-hx8k_breakout_board_xip/README.md | 3 +- src/main/c/murax/xipBootloader/crt.S | 14 ++++-- src/main/c/murax/xipBootloader/crt.bin | Bin 176 -> 192 bytes src/main/scala/vexriscv/demo/Murax.scala | 45 ++++++++---------- 5 files changed, 44 insertions(+), 40 deletions(-) diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/Murax_iCE40_hx8k_breakout_board_xip.pcf b/scripts/Murax/iCE40-hx8k_breakout_board_xip/Murax_iCE40_hx8k_breakout_board_xip.pcf index 4962e25..510acf7 100644 --- a/scripts/Murax/iCE40-hx8k_breakout_board_xip/Murax_iCE40_hx8k_breakout_board_xip.pcf +++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/Murax_iCE40_hx8k_breakout_board_xip.pcf @@ -1,12 +1,12 @@ ## iCE40-hx8k breakout board -set_io io_J3 J3 -set_io io_H16 H16 -set_io io_G15 G15 -set_io io_G16 G16 -set_io io_F15 F15 -set_io io_B12 B12 -set_io io_B10 B10 +set_io io_mainClk J3 +set_io io_jtag_tck H16 +set_io io_jtag_tdi G15 +set_io io_jtag_tdo G16 +set_io io_jtag_tms F15 +set_io io_uart_txd B12 +set_io io_uart_rxd B10 set_io io_led[0] B5 set_io io_led[1] B4 set_io io_led[2] A2 @@ -17,7 +17,7 @@ set_io io_led[6] B3 set_io io_led[7] C3 #XIP -set_io io_P12 P12 -set_io io_P11 P11 -set_io io_R11 R11 -set_io io_R12 R12 \ No newline at end of file +set_io io_miso P12 +set_io io_mosi P11 +set_io io_sclk R11 +set_io io_spis R12 diff --git a/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md b/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md index f7a4dac..3ed77c5 100644 --- a/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md +++ b/scripts/Murax/iCE40-hx8k_breakout_board_xip/README.md @@ -11,9 +11,8 @@ by the IceStorm # Bootloader operations -A bootloader is implemented in a ROM within the FPGA bitfile. It configure the SPI and attempt to read the first word in 'XIP' area of the flash (0xE0040000 in CPU address space, 0x40000 in flash). If this first word is the magic word +A bootloader is implemented in a ROM within the FPGA bitfile. It configure the SPI and attempt to read the first word in 'XIP' area of the flash (0xE0040000 in CPU address space, 0x40000 in flash). If this first word is not 0xFFFFFFFF and the same value is read 3 times, then the bootloader jump at 0xE0040000. -The magic word is 0x12340fb7, which is the value for the instruction "li x31, 0x12340000" or "lui t6,0x12340". # Using the example diff --git a/src/main/c/murax/xipBootloader/crt.S b/src/main/c/murax/xipBootloader/crt.S index 8668c8a..5268767 100644 --- a/src/main/c/murax/xipBootloader/crt.S +++ b/src/main/c/murax/xipBootloader/crt.S @@ -43,9 +43,17 @@ crtStart: sw t0, CTRL_XIP_CONFIG(CTRL) li t0, XIP_BASE lw t1, (t0) - li t2, 0x12340fb7 - xor t1,t1,t2 - bnez t1,retry + li t2, 0xFFFFFFFF + xor t3,t1,t2 + beqz t3,retry + //if we are here we have read a value from flash which is not all ones + lw t2, (t0) + xor t3,t1,t2 + bnez t3,retry + lw t2, (t0) + xor t3,t1,t2 + bnez t3,retry + //if we are here we have read the same value 3 times, so flash seems good, lets's jump jr t0 retry: diff --git a/src/main/c/murax/xipBootloader/crt.bin b/src/main/c/murax/xipBootloader/crt.bin index bf751967431a1eb58a39071360f4fe56c3dfae48..3584ff4b9d823a2b06f626f59e6ea53c5f120f29 100755 GIT binary patch delta 102 zcmdnMcz|(&mYf5JFsp#Xdxit-!mI{B+JW6%lz~B*m9^nLLj&7H4;kgj%pd+6`xP@J vGw?ArFJ@u@v!(bL;A|1TiN(rd^S>%DSkKVB$e&^IBqqkkJxu@78yFY>TtOWE delta 86 zcmX@WxPftkmK+1SFsp#Xdxi!!VO9em&A?_Z%D^DZ%G&Ur!GU$6hYbIAVH2Ur&Becs mor@WgMVKeHD@)z~ro3Q1L-QhkhRKtd7$5gA{Y!6P00RKO;}`+} diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala index 846fa04..389b91f 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -368,58 +368,55 @@ object Murax_iCE40_hx8k_breakout_board_xip{ case class Murax_iCE40_hx8k_breakout_board_xip() extends Component{ val io = new Bundle { - val J3 = in Bool() - val H16 = in Bool() - val G15 = in Bool() - val G16 = out Bool() - val F15 = in Bool() - val B12 = out Bool() - val B10 = in Bool() + val mainClk = in Bool() + val jtag_tck = in Bool() + val jtag_tdi = in Bool() + val jtag_tdo = out Bool() + val jtag_tms = in Bool() + val uart_txd = out Bool() + val uart_rxd = in Bool() - - //p12 as mosi mean flash config - val P12 = inout(Analog(Bool)) - val P11 = inout(Analog(Bool)) - val R11 = out Bool() - val R12 = out Bool() + val mosi = inout(Analog(Bool)) + val miso = inout(Analog(Bool)) + val sclk = out Bool() + val spis = out Bool() val led = out Bits(8 bits) } - //val murax = Murax(MuraxConfig.default(withXip = true)) val murax = Murax(MuraxConfig.default(withXip = true).copy(onChipRamSize = 8 kB)) murax.io.asyncReset := False val mainClkBuffer = SB_GB() - mainClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.J3 + mainClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.mainClk mainClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.mainClk val jtagClkBuffer = SB_GB() - jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.H16 + jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.jtag_tck jtagClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.jtag.tck io.led <> murax.io.gpioA.write(7 downto 0) - murax.io.jtag.tdi <> io.G15 - murax.io.jtag.tdo <> io.G16 - murax.io.jtag.tms <> io.F15 + murax.io.jtag.tdi <> io.jtag_tdi + murax.io.jtag.tdo <> io.jtag_tdo + murax.io.jtag.tms <> io.jtag_tms murax.io.gpioA.read <> 0 - murax.io.uart.txd <> io.B12 - murax.io.uart.rxd <> io.B10 + murax.io.uart.txd <> io.uart_txd + murax.io.uart.rxd <> io.uart_rxd val xip = new ClockingArea(murax.systemClockDomain) { - RegNext(murax.io.xip.ss.asBool) <> io.R12 + RegNext(murax.io.xip.ss.asBool) <> io.spis val sclkIo = SB_IO_SCLK() - sclkIo.PACKAGE_PIN <> io.R11 + sclkIo.PACKAGE_PIN <> io.sclk sclkIo.CLOCK_ENABLE := True sclkIo.OUTPUT_CLK := ClockDomain.current.readClockWire sclkIo.D_OUT_0 <> murax.io.xip.sclk.write(0) sclkIo.D_OUT_1 <> RegNext(murax.io.xip.sclk.write(1)) - val datas = for ((data, pin) <- (murax.io.xip.data, List(io.P12, io.P11).reverse).zipped) yield new Area { + val datas = for ((data, pin) <- (murax.io.xip.data, List(io.mosi, io.miso)).zipped) yield new Area { val dataIo = SB_IO_DATA() dataIo.PACKAGE_PIN := pin dataIo.CLOCK_ENABLE := True From 97b2838d1884b48a2c8a9dbbb7a613c50374bfea Mon Sep 17 00:00:00 2001 From: sebastien-riou Date: Thu, 16 Jan 2020 21:58:55 +0100 Subject: [PATCH 27/29] Murax on Digilent Arty A7-35 --- scripts/Murax/arty_a7/README.md | 129 +++++++ scripts/Murax/arty_a7/arty_a7.xdc | 366 +++++++++++++++++++ scripts/Murax/arty_a7/arty_a7_org.xdc | 350 ++++++++++++++++++ scripts/Murax/arty_a7/make_mcs_file | 6 + scripts/Murax/arty_a7/make_mmi_files | 4 + scripts/Murax/arty_a7/make_vivado_project | 9 + scripts/Murax/arty_a7/makefile | 62 ++++ scripts/Murax/arty_a7/open_vivado_project | 4 + scripts/Murax/arty_a7/picocom_arty | 1 + scripts/Murax/arty_a7/toplevel.v | 66 ++++ scripts/Murax/arty_a7/write_flash | 3 + scripts/Murax/arty_a7/write_fpga | 3 + src/main/c/murax/hello_world/makefile | 134 +++++++ src/main/c/murax/hello_world/src/crt.S | 98 +++++ src/main/c/murax/hello_world/src/gpio.h | 15 + src/main/c/murax/hello_world/src/interrupt.h | 17 + src/main/c/murax/hello_world/src/linker.ld | 110 ++++++ src/main/c/murax/hello_world/src/main.c | 42 +++ src/main/c/murax/hello_world/src/murax.h | 17 + src/main/c/murax/hello_world/src/prescaler.h | 16 + src/main/c/murax/hello_world/src/timer.h | 20 + src/main/c/murax/hello_world/src/uart.h | 42 +++ src/main/scala/vexriscv/demo/Murax.scala | 7 + 23 files changed, 1521 insertions(+) create mode 100644 scripts/Murax/arty_a7/README.md create mode 100644 scripts/Murax/arty_a7/arty_a7.xdc create mode 100644 scripts/Murax/arty_a7/arty_a7_org.xdc create mode 100755 scripts/Murax/arty_a7/make_mcs_file create mode 100755 scripts/Murax/arty_a7/make_mmi_files create mode 100755 scripts/Murax/arty_a7/make_vivado_project create mode 100644 scripts/Murax/arty_a7/makefile create mode 100755 scripts/Murax/arty_a7/open_vivado_project create mode 100644 scripts/Murax/arty_a7/picocom_arty create mode 100644 scripts/Murax/arty_a7/toplevel.v create mode 100755 scripts/Murax/arty_a7/write_flash create mode 100755 scripts/Murax/arty_a7/write_fpga create mode 100644 src/main/c/murax/hello_world/makefile create mode 100644 src/main/c/murax/hello_world/src/crt.S create mode 100644 src/main/c/murax/hello_world/src/gpio.h create mode 100644 src/main/c/murax/hello_world/src/interrupt.h create mode 100644 src/main/c/murax/hello_world/src/linker.ld create mode 100644 src/main/c/murax/hello_world/src/main.c create mode 100644 src/main/c/murax/hello_world/src/murax.h create mode 100644 src/main/c/murax/hello_world/src/prescaler.h create mode 100644 src/main/c/murax/hello_world/src/timer.h create mode 100644 src/main/c/murax/hello_world/src/uart.h diff --git a/scripts/Murax/arty_a7/README.md b/scripts/Murax/arty_a7/README.md new file mode 100644 index 0000000..ad781f3 --- /dev/null +++ b/scripts/Murax/arty_a7/README.md @@ -0,0 +1,129 @@ +This example is for the Digilent ARTY A7 35T board. + +# Using the example + +## Before Starting + +You should make sure you have the following tools installed: + * vivado 2018.1 or later + * riscv toolchain (riscv64-unknown-elf) + * sbt + +## Board setup +Make sure you have a rev E board. If you have a later version check that the +flash part is S25FL128SAGMF100. + +Jumper settings for board rev E: + * Disconnect anything from the connectors (Pmod, Arduino) + * Jumpers: JP1 and JP2 on, others off. + +## Building + +You should be able to just type `make` and get output similar to this; +``` +... +Memory region Used Size Region Size %age Used + RAM: 896 B 2 KB 43.75% +... +--------------------------------------------------------------------------------- +Finished RTL Elaboration : Time (s): cpu = 00:00:08 ; elapsed = 00:00:09 . Memory (MB): peak = 1457.785 ; gain = 243.430 ; free physical = 17940 ; free virtual = 57159 +--------------------------------------------------------------------------------- +... +--------------------------------------------------------------------------------- +Finished Technology Mapping : Time (s): cpu = 00:02:42 ; elapsed = 00:02:58 . Memory (MB): peak = 1986.879 ; gain = 772.523 ; free physical = 17454 ; free virtual = 56670 +--------------------------------------------------------------------------------- +... +--------------------------------------------------------------------------------- +Finished Writing Synthesis Report : Time (s): cpu = 00:02:45 ; elapsed = 00:03:01 . Memory (MB): peak = 1986.879 ; gain = 772.523 ; free physical = 17457 ; free virtual = 56673 +--------------------------------------------------------------------------------- +... +Writing bitstream ./toplevel.bit... +... +mmi files generated +... +******************************************** + ./soc_latest_sw.bit correctly generated +******************************************** +... +******************************************** + ./soc_latest_sw.mcs correctly generated +******************************************** + +INFO: [Common 17-206] Exiting Vivado at Thu Nov 28 04:00:50 2019... +``` + +The process should take around 8 minutes on a reasonably fast computer. + +## Programming + +### Direct FPGA RAM programming + +Run `make prog` to program the bit file directly to FPGA RAM. + +You should get output like the following; +``` +... +****** Xilinx hw_server v2018.1 + **** Build date : Apr 4 2018-18:56:09 + ** Copyright 1986-2018 Xilinx, Inc. All Rights Reserved. + +INFO: [Labtoolstcl 44-466] Opening hw_target localhost:3121/xilinx_tcf/Digilent/210319AB569AA +INFO: [Labtools 27-1434] Device xc7a35t (JTAG device index = 0) is programmed with a design that has no supported debug core(s) in it. +WARNING: [Labtools 27-3361] The debug hub core was not detected. +Resolution: +1. Make sure the clock connected to the debug hub (dbg_hub) core is a free running clock and is active. +2. Make sure the BSCAN_SWITCH_USER_MASK device property in Vivado Hardware Manager reflects the user scan chain setting in the design and refresh the device. To determine the user scan chain setting in the design, open the implemented design and use 'get_property C_USER_SCAN_CHAIN [get_debug_cores dbg_hub]'. +For more details on setting the scan chain property, consult the Vivado Debug and Programming User Guide (UG908). +INFO: [Labtools 27-3164] End of startup status: HIGH +INFO: [Common 17-206] Exiting Vivado at Thu Nov 28 04:01:36 2019... +``` + +After programming the LED4~LED7 shall show some activity. + +### QSPI flash programming + +Run `make flash` to program the bit file to the QSPI flash. + +You should get output like the following; +``` +... +****** Xilinx hw_server v2018.1 + **** Build date : Apr 4 2018-18:56:09 + ** Copyright 1986-2018 Xilinx, Inc. All Rights Reserved. + + +INFO: [Labtoolstcl 44-466] Opening hw_target localhost:3121/xilinx_tcf/Digilent/210319AB569AA +INFO: [Labtools 27-1434] Device xc7a35t (JTAG device index = 0) is programmed with a design that has no supported debug core(s) in it. +... +INFO: [Labtools 27-3164] End of startup status: HIGH +Mfg ID : 1 Memory Type : 20 Memory Capacity : 18 Device ID 1 : 0 Device ID 2 : 0 +Performing Erase Operation... +Erase Operation successful. +Performing Program and Verify Operations... +Program/Verify Operation successful. +INFO: [Labtoolstcl 44-377] Flash programming completed successfully +program_hw_cfgmem: Time (s): cpu = 00:00:00.11 ; elapsed = 00:00:52 . Memory (MB): peak = 1792.711 ; gain = 8.000 ; free physical = 17712 ; free virtual = 56943 +INFO: [Labtoolstcl 44-464] Closing hw_target localhost:3121/xilinx_tcf/Digilent/210319AB569AA +... +INFO: [Common 17-206] Exiting Vivado at Thu Nov 28 04:06:28 2019... +``` + +After programming the flash you need to press the "PROG" button on the board. Then after a second or so the "DONE" LED shall be ON and LED4~LED7 shall show some activity. + + +## Connect + +After programming you should be able to connect to the serial port and have some output. + +On Linux you can do this using a command like `screen /dev/ttyUSB1`. Other good alternatives: + +* moserial (GUI) +* picocom (can be launched via the file "picocom_arty") + +Parameters: +* port is : /dev/ttyUSB1 +* flowcontrol : none +* baudrate is : 115200 +* parity is : none +* databits are : 8 +* stopbits are : 1 diff --git a/scripts/Murax/arty_a7/arty_a7.xdc b/scripts/Murax/arty_a7/arty_a7.xdc new file mode 100644 index 0000000..5ddd8fe --- /dev/null +++ b/scripts/Murax/arty_a7/arty_a7.xdc @@ -0,0 +1,366 @@ +set_property PACKAGE_PIN F4 [get_ports tck] +set_property IOSTANDARD LVCMOS33 [get_ports tck] + +set_property PACKAGE_PIN D2 [get_ports tms] +set_property IOSTANDARD LVCMOS33 [get_ports tms] + +set_property PACKAGE_PIN D4 [get_ports tdo] +set_property IOSTANDARD LVCMOS33 [get_ports tdo] +set_property PULLUP true [get_ports tdo] + +set_property PACKAGE_PIN E2 [get_ports tdi] +set_property IOSTANDARD LVCMOS33 [get_ports tdi] + +set_property PACKAGE_PIN D3 [get_ports trst] +set_property IOSTANDARD LVCMOS33 [get_ports trst] +set_property PULLUP true [get_ports trst] + + +## serial:0.tx +set_property PACKAGE_PIN D10 [get_ports serial_tx] +set_property IOSTANDARD LVCMOS33 [get_ports serial_tx] +## serial:0.rx +set_property PACKAGE_PIN A9 [get_ports serial_rx] +set_property IOSTANDARD LVCMOS33 [get_ports serial_rx] +## clk100:0 +set_property PACKAGE_PIN E3 [get_ports clk100] +set_property IOSTANDARD LVCMOS33 [get_ports clk100] +## cpu_reset:0 +set_property PACKAGE_PIN C2 [get_ports cpu_reset] +set_property IOSTANDARD LVCMOS33 [get_ports cpu_reset] +## eth_ref_clk:0 +#set_property LOC G18 [get_ports eth_ref_clk] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_ref_clk] +## user_led:0 +set_property PACKAGE_PIN H5 [get_ports user_led0] +set_property IOSTANDARD LVCMOS33 [get_ports user_led0] +## user_led:1 +set_property PACKAGE_PIN J5 [get_ports user_led1] +set_property IOSTANDARD LVCMOS33 [get_ports user_led1] +## user_led:2 +set_property PACKAGE_PIN T9 [get_ports user_led2] +set_property IOSTANDARD LVCMOS33 [get_ports user_led2] +## user_led:3 +set_property PACKAGE_PIN T10 [get_ports user_led3] +set_property IOSTANDARD LVCMOS33 [get_ports user_led3] +## user_sw:0 +set_property PACKAGE_PIN A8 [get_ports user_sw0] +set_property IOSTANDARD LVCMOS33 [get_ports user_sw0] +## user_sw:1 +set_property PACKAGE_PIN C11 [get_ports user_sw1] +set_property IOSTANDARD LVCMOS33 [get_ports user_sw1] +## user_sw:2 +set_property PACKAGE_PIN C10 [get_ports user_sw2] +set_property IOSTANDARD LVCMOS33 [get_ports user_sw2] +## user_sw:3 +set_property PACKAGE_PIN A10 [get_ports user_sw3] +set_property IOSTANDARD LVCMOS33 [get_ports user_sw3] +## user_btn:0 +set_property PACKAGE_PIN D9 [get_ports user_btn0] +set_property IOSTANDARD LVCMOS33 [get_ports user_btn0] +## user_btn:1 +set_property PACKAGE_PIN C9 [get_ports user_btn1] +set_property IOSTANDARD LVCMOS33 [get_ports user_btn1] +## user_btn:2 +set_property PACKAGE_PIN B9 [get_ports user_btn2] +set_property IOSTANDARD LVCMOS33 [get_ports user_btn2] +## user_btn:3 +set_property PACKAGE_PIN B8 [get_ports user_btn3] +set_property IOSTANDARD LVCMOS33 [get_ports user_btn3] +## spiflash_1x:0.cs_n +#set_property LOC L13 [get_ports spiflash_1x_cs_n] +#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_cs_n] +# ## spiflash_1x:0.mosi +#set_property LOC K17 [get_ports spiflash_1x_mosi] +#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_mosi] +# ## spiflash_1x:0.miso +#set_property LOC K18 [get_ports spiflash_1x_miso] +#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_miso] +# ## spiflash_1x:0.wp +#set_property LOC L14 [get_ports spiflash_1x_wp] +#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_wp] +# ## spiflash_1x:0.hold +#set_property LOC M14 [get_ports spiflash_1x_hold] +#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_hold] +# ## ddram:0.a +#set_property LOC R2 [get_ports ddram_a[0]] +#set_property SLEW FAST [get_ports ddram_a[0]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[0]] +# ## ddram:0.a +#set_property LOC M6 [get_ports ddram_a[1]] +#set_property SLEW FAST [get_ports ddram_a[1]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[1]] +# ## ddram:0.a +#set_property LOC N4 [get_ports ddram_a[2]] +#set_property SLEW FAST [get_ports ddram_a[2]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[2]] +# ## ddram:0.a +#set_property LOC T1 [get_ports ddram_a[3]] +#set_property SLEW FAST [get_ports ddram_a[3]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[3]] +# ## ddram:0.a +#set_property LOC N6 [get_ports ddram_a[4]] +#set_property SLEW FAST [get_ports ddram_a[4]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[4]] +# ## ddram:0.a +#set_property LOC R7 [get_ports ddram_a[5]] +#set_property SLEW FAST [get_ports ddram_a[5]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[5]] +# ## ddram:0.a +#set_property LOC V6 [get_ports ddram_a[6]] +#set_property SLEW FAST [get_ports ddram_a[6]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[6]] +# ## ddram:0.a +#set_property LOC U7 [get_ports ddram_a[7]] +#set_property SLEW FAST [get_ports ddram_a[7]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[7]] +# ## ddram:0.a +#set_property LOC R8 [get_ports ddram_a[8]] +#set_property SLEW FAST [get_ports ddram_a[8]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[8]] +# ## ddram:0.a +#set_property LOC V7 [get_ports ddram_a[9]] +#set_property SLEW FAST [get_ports ddram_a[9]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[9]] +# ## ddram:0.a +#set_property LOC R6 [get_ports ddram_a[10]] +#set_property SLEW FAST [get_ports ddram_a[10]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[10]] +# ## ddram:0.a +#set_property LOC U6 [get_ports ddram_a[11]] +#set_property SLEW FAST [get_ports ddram_a[11]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[11]] +# ## ddram:0.a +#set_property LOC T6 [get_ports ddram_a[12]] +#set_property SLEW FAST [get_ports ddram_a[12]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[12]] +# ## ddram:0.a +#set_property LOC T8 [get_ports ddram_a[13]] +#set_property SLEW FAST [get_ports ddram_a[13]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[13]] +# ## ddram:0.ba +#set_property LOC R1 [get_ports ddram_ba[0]] +#set_property SLEW FAST [get_ports ddram_ba[0]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[0]] +# ## ddram:0.ba +#set_property LOC P4 [get_ports ddram_ba[1]] +#set_property SLEW FAST [get_ports ddram_ba[1]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[1]] +# ## ddram:0.ba +#set_property LOC P2 [get_ports ddram_ba[2]] +#set_property SLEW FAST [get_ports ddram_ba[2]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[2]] +# ## ddram:0.ras_n +#set_property LOC P3 [get_ports ddram_ras_n] +#set_property SLEW FAST [get_ports ddram_ras_n] +#set_property IOSTANDARD SSTL15 [get_ports ddram_ras_n] +# ## ddram:0.cas_n +#set_property LOC M4 [get_ports ddram_cas_n] +#set_property SLEW FAST [get_ports ddram_cas_n] +#set_property IOSTANDARD SSTL15 [get_ports ddram_cas_n] +# ## ddram:0.we_n +#set_property LOC P5 [get_ports ddram_we_n] +#set_property SLEW FAST [get_ports ddram_we_n] +#set_property IOSTANDARD SSTL15 [get_ports ddram_we_n] +# ## ddram:0.cs_n +#set_property LOC U8 [get_ports ddram_cs_n] +#set_property SLEW FAST [get_ports ddram_cs_n] +#set_property IOSTANDARD SSTL15 [get_ports ddram_cs_n] +# ## ddram:0.dm +#set_property LOC L1 [get_ports ddram_dm[0]] +#set_property SLEW FAST [get_ports ddram_dm[0]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dm[0]] +# ## ddram:0.dm +#set_property LOC U1 [get_ports ddram_dm[1]] +#set_property SLEW FAST [get_ports ddram_dm[1]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dm[1]] +# ## ddram:0.dq +#set_property LOC K5 [get_ports ddram_dq[0]] +#set_property SLEW FAST [get_ports ddram_dq[0]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[0]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[0]] +# ## ddram:0.dq +#set_property LOC L3 [get_ports ddram_dq[1]] +#set_property SLEW FAST [get_ports ddram_dq[1]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[1]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[1]] +# ## ddram:0.dq +#set_property LOC K3 [get_ports ddram_dq[2]] +#set_property SLEW FAST [get_ports ddram_dq[2]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[2]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[2]] +# ## ddram:0.dq +#set_property LOC L6 [get_ports ddram_dq[3]] +#set_property SLEW FAST [get_ports ddram_dq[3]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[3]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[3]] +# ## ddram:0.dq +#set_property LOC M3 [get_ports ddram_dq[4]] +#set_property SLEW FAST [get_ports ddram_dq[4]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[4]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[4]] +# ## ddram:0.dq +#set_property LOC M1 [get_ports ddram_dq[5]] +#set_property SLEW FAST [get_ports ddram_dq[5]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[5]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[5]] +# ## ddram:0.dq +#set_property LOC L4 [get_ports ddram_dq[6]] +#set_property SLEW FAST [get_ports ddram_dq[6]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[6]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[6]] +# ## ddram:0.dq +#set_property LOC M2 [get_ports ddram_dq[7]] +#set_property SLEW FAST [get_ports ddram_dq[7]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[7]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[7]] +# ## ddram:0.dq +#set_property LOC V4 [get_ports ddram_dq[8]] +#set_property SLEW FAST [get_ports ddram_dq[8]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[8]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[8]] +# ## ddram:0.dq +#set_property LOC T5 [get_ports ddram_dq[9]] +#set_property SLEW FAST [get_ports ddram_dq[9]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[9]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[9]] +# ## ddram:0.dq +#set_property LOC U4 [get_ports ddram_dq[10]] +#set_property SLEW FAST [get_ports ddram_dq[10]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[10]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[10]] +# ## ddram:0.dq +#set_property LOC V5 [get_ports ddram_dq[11]] +#set_property SLEW FAST [get_ports ddram_dq[11]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[11]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[11]] +# ## ddram:0.dq +#set_property LOC V1 [get_ports ddram_dq[12]] +#set_property SLEW FAST [get_ports ddram_dq[12]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[12]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[12]] +# ## ddram:0.dq +#set_property LOC T3 [get_ports ddram_dq[13]] +#set_property SLEW FAST [get_ports ddram_dq[13]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[13]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[13]] +# ## ddram:0.dq +#set_property LOC U3 [get_ports ddram_dq[14]] +#set_property SLEW FAST [get_ports ddram_dq[14]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[14]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[14]] +# ## ddram:0.dq +#set_property LOC R3 [get_ports ddram_dq[15]] +#set_property SLEW FAST [get_ports ddram_dq[15]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[15]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[15]] +# ## ddram:0.dqs_p +#set_property LOC N2 [get_ports ddram_dqs_p[0]] +#set_property SLEW FAST [get_ports ddram_dqs_p[0]] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_p[0]] +# ## ddram:0.dqs_p +#set_property LOC U2 [get_ports ddram_dqs_p[1]] +#set_property SLEW FAST [get_ports ddram_dqs_p[1]] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_p[1]] +# ## ddram:0.dqs_n +#set_property LOC N1 [get_ports ddram_dqs_n[0]] +#set_property SLEW FAST [get_ports ddram_dqs_n[0]] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_n[0]] +# ## ddram:0.dqs_n +#set_property LOC V2 [get_ports ddram_dqs_n[1]] +#set_property SLEW FAST [get_ports ddram_dqs_n[1]] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_n[1]] +# ## ddram:0.clk_p +#set_property LOC U9 [get_ports ddram_clk_p] +#set_property SLEW FAST [get_ports ddram_clk_p] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_clk_p] +# ## ddram:0.clk_n +#set_property LOC V9 [get_ports ddram_clk_n] +#set_property SLEW FAST [get_ports ddram_clk_n] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_clk_n] +# ## ddram:0.cke +#set_property LOC N5 [get_ports ddram_cke] +#set_property SLEW FAST [get_ports ddram_cke] +#set_property IOSTANDARD SSTL15 [get_ports ddram_cke] +# ## ddram:0.odt +#set_property LOC R5 [get_ports ddram_odt] +#set_property SLEW FAST [get_ports ddram_odt] +#set_property IOSTANDARD SSTL15 [get_ports ddram_odt] +# ## ddram:0.reset_n +#set_property LOC K6 [get_ports ddram_reset_n] +#set_property SLEW FAST [get_ports ddram_reset_n] +#set_property IOSTANDARD SSTL15 [get_ports ddram_reset_n] +# ## eth_clocks:0.tx +#set_property LOC H16 [get_ports eth_clocks_tx] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_clocks_tx] +# ## eth_clocks:0.rx +#set_property LOC F15 [get_ports eth_clocks_rx] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_clocks_rx] +# ## eth:0.rst_n +#set_property LOC C16 [get_ports eth_rst_n] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rst_n] +# ## eth:0.mdio +#set_property LOC K13 [get_ports eth_mdio] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_mdio] +# ## eth:0.mdc +#set_property LOC F16 [get_ports eth_mdc] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_mdc] +# ## eth:0.rx_dv +#set_property LOC G16 [get_ports eth_rx_dv] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_dv] +# ## eth:0.rx_er +#set_property LOC C17 [get_ports eth_rx_er] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_er] +# ## eth:0.rx_data +#set_property LOC D18 [get_ports eth_rx_data[0]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[0]] +# ## eth:0.rx_data +#set_property LOC E17 [get_ports eth_rx_data[1]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[1]] +# ## eth:0.rx_data +#set_property LOC E18 [get_ports eth_rx_data[2]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[2]] +# ## eth:0.rx_data +#set_property LOC G17 [get_ports eth_rx_data[3]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[3]] +# ## eth:0.tx_en +#set_property LOC H15 [get_ports eth_tx_en] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_en] +# ## eth:0.tx_data +#set_property LOC H14 [get_ports eth_tx_data[0]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[0]] +# ## eth:0.tx_data +#set_property LOC J14 [get_ports eth_tx_data[1]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[1]] +# ## eth:0.tx_data +#set_property LOC J13 [get_ports eth_tx_data[2]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[2]] +# ## eth:0.tx_data +#set_property LOC H17 [get_ports eth_tx_data[3]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[3]] +# ## eth:0.col +#set_property LOC D17 [get_ports eth_col] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_col] +# ## eth:0.crs +#set_property LOC G14 [get_ports eth_crs] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_crs] + +set_property INTERNAL_VREF 0.75 [get_iobanks 34] + + +create_clock -period 10.000 -name clk100 [get_nets clk100] + +#create_clock -name eth_rx_clk -period 40.0 [get_nets eth_rx_clk] + +#create_clock -name eth_tx_clk -period 40.0 [get_nets eth_tx_clk] + +#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_rx_clk]] -asynchronous + +#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_tx_clk]] -asynchronous + +#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets eth_rx_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_tx_clk]] -asynchronous + + + + +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] diff --git a/scripts/Murax/arty_a7/arty_a7_org.xdc b/scripts/Murax/arty_a7/arty_a7_org.xdc new file mode 100644 index 0000000..75c81b1 --- /dev/null +++ b/scripts/Murax/arty_a7/arty_a7_org.xdc @@ -0,0 +1,350 @@ + ## serial:0.tx +set_property LOC D10 [get_ports serial_tx] +set_property IOSTANDARD LVCMOS33 [get_ports serial_tx] + ## serial:0.rx +set_property LOC A9 [get_ports serial_rx] +set_property IOSTANDARD LVCMOS33 [get_ports serial_rx] + ## clk100:0 +set_property LOC E3 [get_ports clk100] +set_property IOSTANDARD LVCMOS33 [get_ports clk100] + ## cpu_reset:0 +set_property LOC C2 [get_ports cpu_reset] +set_property IOSTANDARD LVCMOS33 [get_ports cpu_reset] + ## eth_ref_clk:0 +#set_property LOC G18 [get_ports eth_ref_clk] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_ref_clk] + ## user_led:0 +set_property LOC H5 [get_ports user_led0] +set_property IOSTANDARD LVCMOS33 [get_ports user_led0] + ## user_led:1 +set_property LOC J5 [get_ports user_led1] +set_property IOSTANDARD LVCMOS33 [get_ports user_led1] + ## user_led:2 +set_property LOC T9 [get_ports user_led2] +set_property IOSTANDARD LVCMOS33 [get_ports user_led2] + ## user_led:3 +set_property LOC T10 [get_ports user_led3] +set_property IOSTANDARD LVCMOS33 [get_ports user_led3] + ## user_sw:0 +set_property LOC A8 [get_ports user_sw0] +set_property IOSTANDARD LVCMOS33 [get_ports user_sw0] + ## user_sw:1 +set_property LOC C11 [get_ports user_sw1] +set_property IOSTANDARD LVCMOS33 [get_ports user_sw1] + ## user_sw:2 +set_property LOC C10 [get_ports user_sw2] +set_property IOSTANDARD LVCMOS33 [get_ports user_sw2] + ## user_sw:3 +set_property LOC A10 [get_ports user_sw3] +set_property IOSTANDARD LVCMOS33 [get_ports user_sw3] + ## user_btn:0 +set_property LOC D9 [get_ports user_btn0] +set_property IOSTANDARD LVCMOS33 [get_ports user_btn0] + ## user_btn:1 +set_property LOC C9 [get_ports user_btn1] +set_property IOSTANDARD LVCMOS33 [get_ports user_btn1] + ## user_btn:2 +set_property LOC B9 [get_ports user_btn2] +set_property IOSTANDARD LVCMOS33 [get_ports user_btn2] + ## user_btn:3 +set_property LOC B8 [get_ports user_btn3] +set_property IOSTANDARD LVCMOS33 [get_ports user_btn3] + ## spiflash_1x:0.cs_n +#set_property LOC L13 [get_ports spiflash_1x_cs_n] +#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_cs_n] +# ## spiflash_1x:0.mosi +#set_property LOC K17 [get_ports spiflash_1x_mosi] +#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_mosi] +# ## spiflash_1x:0.miso +#set_property LOC K18 [get_ports spiflash_1x_miso] +#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_miso] +# ## spiflash_1x:0.wp +#set_property LOC L14 [get_ports spiflash_1x_wp] +#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_wp] +# ## spiflash_1x:0.hold +#set_property LOC M14 [get_ports spiflash_1x_hold] +#set_property IOSTANDARD LVCMOS33 [get_ports spiflash_1x_hold] +# ## ddram:0.a +#set_property LOC R2 [get_ports ddram_a[0]] +#set_property SLEW FAST [get_ports ddram_a[0]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[0]] +# ## ddram:0.a +#set_property LOC M6 [get_ports ddram_a[1]] +#set_property SLEW FAST [get_ports ddram_a[1]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[1]] +# ## ddram:0.a +#set_property LOC N4 [get_ports ddram_a[2]] +#set_property SLEW FAST [get_ports ddram_a[2]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[2]] +# ## ddram:0.a +#set_property LOC T1 [get_ports ddram_a[3]] +#set_property SLEW FAST [get_ports ddram_a[3]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[3]] +# ## ddram:0.a +#set_property LOC N6 [get_ports ddram_a[4]] +#set_property SLEW FAST [get_ports ddram_a[4]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[4]] +# ## ddram:0.a +#set_property LOC R7 [get_ports ddram_a[5]] +#set_property SLEW FAST [get_ports ddram_a[5]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[5]] +# ## ddram:0.a +#set_property LOC V6 [get_ports ddram_a[6]] +#set_property SLEW FAST [get_ports ddram_a[6]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[6]] +# ## ddram:0.a +#set_property LOC U7 [get_ports ddram_a[7]] +#set_property SLEW FAST [get_ports ddram_a[7]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[7]] +# ## ddram:0.a +#set_property LOC R8 [get_ports ddram_a[8]] +#set_property SLEW FAST [get_ports ddram_a[8]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[8]] +# ## ddram:0.a +#set_property LOC V7 [get_ports ddram_a[9]] +#set_property SLEW FAST [get_ports ddram_a[9]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[9]] +# ## ddram:0.a +#set_property LOC R6 [get_ports ddram_a[10]] +#set_property SLEW FAST [get_ports ddram_a[10]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[10]] +# ## ddram:0.a +#set_property LOC U6 [get_ports ddram_a[11]] +#set_property SLEW FAST [get_ports ddram_a[11]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[11]] +# ## ddram:0.a +#set_property LOC T6 [get_ports ddram_a[12]] +#set_property SLEW FAST [get_ports ddram_a[12]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[12]] +# ## ddram:0.a +#set_property LOC T8 [get_ports ddram_a[13]] +#set_property SLEW FAST [get_ports ddram_a[13]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_a[13]] +# ## ddram:0.ba +#set_property LOC R1 [get_ports ddram_ba[0]] +#set_property SLEW FAST [get_ports ddram_ba[0]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[0]] +# ## ddram:0.ba +#set_property LOC P4 [get_ports ddram_ba[1]] +#set_property SLEW FAST [get_ports ddram_ba[1]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[1]] +# ## ddram:0.ba +#set_property LOC P2 [get_ports ddram_ba[2]] +#set_property SLEW FAST [get_ports ddram_ba[2]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_ba[2]] +# ## ddram:0.ras_n +#set_property LOC P3 [get_ports ddram_ras_n] +#set_property SLEW FAST [get_ports ddram_ras_n] +#set_property IOSTANDARD SSTL15 [get_ports ddram_ras_n] +# ## ddram:0.cas_n +#set_property LOC M4 [get_ports ddram_cas_n] +#set_property SLEW FAST [get_ports ddram_cas_n] +#set_property IOSTANDARD SSTL15 [get_ports ddram_cas_n] +# ## ddram:0.we_n +#set_property LOC P5 [get_ports ddram_we_n] +#set_property SLEW FAST [get_ports ddram_we_n] +#set_property IOSTANDARD SSTL15 [get_ports ddram_we_n] +# ## ddram:0.cs_n +#set_property LOC U8 [get_ports ddram_cs_n] +#set_property SLEW FAST [get_ports ddram_cs_n] +#set_property IOSTANDARD SSTL15 [get_ports ddram_cs_n] +# ## ddram:0.dm +#set_property LOC L1 [get_ports ddram_dm[0]] +#set_property SLEW FAST [get_ports ddram_dm[0]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dm[0]] +# ## ddram:0.dm +#set_property LOC U1 [get_ports ddram_dm[1]] +#set_property SLEW FAST [get_ports ddram_dm[1]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dm[1]] +# ## ddram:0.dq +#set_property LOC K5 [get_ports ddram_dq[0]] +#set_property SLEW FAST [get_ports ddram_dq[0]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[0]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[0]] +# ## ddram:0.dq +#set_property LOC L3 [get_ports ddram_dq[1]] +#set_property SLEW FAST [get_ports ddram_dq[1]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[1]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[1]] +# ## ddram:0.dq +#set_property LOC K3 [get_ports ddram_dq[2]] +#set_property SLEW FAST [get_ports ddram_dq[2]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[2]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[2]] +# ## ddram:0.dq +#set_property LOC L6 [get_ports ddram_dq[3]] +#set_property SLEW FAST [get_ports ddram_dq[3]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[3]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[3]] +# ## ddram:0.dq +#set_property LOC M3 [get_ports ddram_dq[4]] +#set_property SLEW FAST [get_ports ddram_dq[4]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[4]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[4]] +# ## ddram:0.dq +#set_property LOC M1 [get_ports ddram_dq[5]] +#set_property SLEW FAST [get_ports ddram_dq[5]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[5]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[5]] +# ## ddram:0.dq +#set_property LOC L4 [get_ports ddram_dq[6]] +#set_property SLEW FAST [get_ports ddram_dq[6]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[6]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[6]] +# ## ddram:0.dq +#set_property LOC M2 [get_ports ddram_dq[7]] +#set_property SLEW FAST [get_ports ddram_dq[7]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[7]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[7]] +# ## ddram:0.dq +#set_property LOC V4 [get_ports ddram_dq[8]] +#set_property SLEW FAST [get_ports ddram_dq[8]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[8]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[8]] +# ## ddram:0.dq +#set_property LOC T5 [get_ports ddram_dq[9]] +#set_property SLEW FAST [get_ports ddram_dq[9]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[9]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[9]] +# ## ddram:0.dq +#set_property LOC U4 [get_ports ddram_dq[10]] +#set_property SLEW FAST [get_ports ddram_dq[10]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[10]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[10]] +# ## ddram:0.dq +#set_property LOC V5 [get_ports ddram_dq[11]] +#set_property SLEW FAST [get_ports ddram_dq[11]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[11]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[11]] +# ## ddram:0.dq +#set_property LOC V1 [get_ports ddram_dq[12]] +#set_property SLEW FAST [get_ports ddram_dq[12]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[12]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[12]] +# ## ddram:0.dq +#set_property LOC T3 [get_ports ddram_dq[13]] +#set_property SLEW FAST [get_ports ddram_dq[13]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[13]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[13]] +# ## ddram:0.dq +#set_property LOC U3 [get_ports ddram_dq[14]] +#set_property SLEW FAST [get_ports ddram_dq[14]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[14]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[14]] +# ## ddram:0.dq +#set_property LOC R3 [get_ports ddram_dq[15]] +#set_property SLEW FAST [get_ports ddram_dq[15]] +#set_property IOSTANDARD SSTL15 [get_ports ddram_dq[15]] +#set_property IN_TERM UNTUNED_SPLIT_40 [get_ports ddram_dq[15]] +# ## ddram:0.dqs_p +#set_property LOC N2 [get_ports ddram_dqs_p[0]] +#set_property SLEW FAST [get_ports ddram_dqs_p[0]] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_p[0]] +# ## ddram:0.dqs_p +#set_property LOC U2 [get_ports ddram_dqs_p[1]] +#set_property SLEW FAST [get_ports ddram_dqs_p[1]] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_p[1]] +# ## ddram:0.dqs_n +#set_property LOC N1 [get_ports ddram_dqs_n[0]] +#set_property SLEW FAST [get_ports ddram_dqs_n[0]] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_n[0]] +# ## ddram:0.dqs_n +#set_property LOC V2 [get_ports ddram_dqs_n[1]] +#set_property SLEW FAST [get_ports ddram_dqs_n[1]] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_dqs_n[1]] +# ## ddram:0.clk_p +#set_property LOC U9 [get_ports ddram_clk_p] +#set_property SLEW FAST [get_ports ddram_clk_p] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_clk_p] +# ## ddram:0.clk_n +#set_property LOC V9 [get_ports ddram_clk_n] +#set_property SLEW FAST [get_ports ddram_clk_n] +#set_property IOSTANDARD DIFF_SSTL15 [get_ports ddram_clk_n] +# ## ddram:0.cke +#set_property LOC N5 [get_ports ddram_cke] +#set_property SLEW FAST [get_ports ddram_cke] +#set_property IOSTANDARD SSTL15 [get_ports ddram_cke] +# ## ddram:0.odt +#set_property LOC R5 [get_ports ddram_odt] +#set_property SLEW FAST [get_ports ddram_odt] +#set_property IOSTANDARD SSTL15 [get_ports ddram_odt] +# ## ddram:0.reset_n +#set_property LOC K6 [get_ports ddram_reset_n] +#set_property SLEW FAST [get_ports ddram_reset_n] +#set_property IOSTANDARD SSTL15 [get_ports ddram_reset_n] +# ## eth_clocks:0.tx +#set_property LOC H16 [get_ports eth_clocks_tx] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_clocks_tx] +# ## eth_clocks:0.rx +#set_property LOC F15 [get_ports eth_clocks_rx] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_clocks_rx] +# ## eth:0.rst_n +#set_property LOC C16 [get_ports eth_rst_n] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rst_n] +# ## eth:0.mdio +#set_property LOC K13 [get_ports eth_mdio] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_mdio] +# ## eth:0.mdc +#set_property LOC F16 [get_ports eth_mdc] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_mdc] +# ## eth:0.rx_dv +#set_property LOC G16 [get_ports eth_rx_dv] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_dv] +# ## eth:0.rx_er +#set_property LOC C17 [get_ports eth_rx_er] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_er] +# ## eth:0.rx_data +#set_property LOC D18 [get_ports eth_rx_data[0]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[0]] +# ## eth:0.rx_data +#set_property LOC E17 [get_ports eth_rx_data[1]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[1]] +# ## eth:0.rx_data +#set_property LOC E18 [get_ports eth_rx_data[2]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[2]] +# ## eth:0.rx_data +#set_property LOC G17 [get_ports eth_rx_data[3]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_rx_data[3]] +# ## eth:0.tx_en +#set_property LOC H15 [get_ports eth_tx_en] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_en] +# ## eth:0.tx_data +#set_property LOC H14 [get_ports eth_tx_data[0]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[0]] +# ## eth:0.tx_data +#set_property LOC J14 [get_ports eth_tx_data[1]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[1]] +# ## eth:0.tx_data +#set_property LOC J13 [get_ports eth_tx_data[2]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[2]] +# ## eth:0.tx_data +#set_property LOC H17 [get_ports eth_tx_data[3]] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_tx_data[3]] +# ## eth:0.col +#set_property LOC D17 [get_ports eth_col] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_col] +# ## eth:0.crs +#set_property LOC G14 [get_ports eth_crs] +#set_property IOSTANDARD LVCMOS33 [get_ports eth_crs] + +set_property INTERNAL_VREF 0.750 [get_iobanks 34] + +create_clock -name sys_clk -period 10.0 [get_nets sys_clk] + +create_clock -name clk100 -period 10.0 [get_nets clk100] + +#create_clock -name eth_rx_clk -period 40.0 [get_nets eth_rx_clk] + +#create_clock -name eth_tx_clk -period 40.0 [get_nets eth_tx_clk] + +#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_rx_clk]] -asynchronous + +#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_tx_clk]] -asynchronous + +#set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets eth_rx_clk]] -group [get_clocks -include_generated_clocks -of [get_nets eth_tx_clk]] -asynchronous + +set_false_path -quiet -to [get_nets -quiet -filter {mr_ff == TRUE}] + +set_false_path -quiet -to [get_pins -quiet -filter {REF_PIN_NAME == PRE} -of [get_cells -quiet -filter {ars_ff1 == TRUE || ars_ff2 == TRUE}]] + +set_max_delay 2 -quiet -from [get_pins -quiet -filter {REF_PIN_NAME == Q} -of [get_cells -quiet -filter {ars_ff1 == TRUE}]] -to [get_pins -quiet -filter {REF_PIN_NAME == D} -of [get_cells -quiet -filter {ars_ff2 == TRUE}]] diff --git a/scripts/Murax/arty_a7/make_mcs_file b/scripts/Murax/arty_a7/make_mcs_file new file mode 100755 index 0000000..40bcc5a --- /dev/null +++ b/scripts/Murax/arty_a7/make_mcs_file @@ -0,0 +1,6 @@ +#!/bin/sh +#Create mcs file for QSPI flash + +cd ./build + +vivado -mode batch -source ../make_mcs_file.tcl -notrace diff --git a/scripts/Murax/arty_a7/make_mmi_files b/scripts/Murax/arty_a7/make_mmi_files new file mode 100755 index 0000000..3919e16 --- /dev/null +++ b/scripts/Murax/arty_a7/make_mmi_files @@ -0,0 +1,4 @@ +#!/bin/sh + +cd ./build +vivado -mode batch -source ../make_mmi_files.tcl -notrace diff --git a/scripts/Murax/arty_a7/make_vivado_project b/scripts/Murax/arty_a7/make_vivado_project new file mode 100755 index 0000000..4a92510 --- /dev/null +++ b/scripts/Murax/arty_a7/make_vivado_project @@ -0,0 +1,9 @@ +#!/bin/sh + +#cannot rm build because it erase software images that the make file copy there +#rm -rf ./build + +mkdir ./build + +cd ./build +vivado -mode batch -source ../make_vivado_project.tcl -notrace diff --git a/scripts/Murax/arty_a7/makefile b/scripts/Murax/arty_a7/makefile new file mode 100644 index 0000000..b672652 --- /dev/null +++ b/scripts/Murax/arty_a7/makefile @@ -0,0 +1,62 @@ +ROOT=../../.. +SWBASE=$(ROOT)/src/main/c/murax +SOCSW=hello_world +SOCMEMSRC=$(SWBASE)/$(SOCSW)/build/$(SOCSW).v +SOCMEM=build/soc.mem + +TOP=Murax + +all : build/latest.bit + +../../../$(TOP).v : toplevel.v + (cd ../../..; sbt "runMain vexriscv.demo.Murax_arty") + +.PHONY: $(SOCMEMSRC) +$(SOCMEMSRC): + mkdir -p build + make -C $(SWBASE)/$(SOCSW) + +$(SOCMEM) : $(SOCMEMSRC) + cp -u $(SOCMEMSRC) $(SOCMEM) + +build/vivado_project/fpga.runs/impl_1/toplevel.bit : toplevel.v arty_a7.xdc ../../../$(TOP).v + mkdir -p build + ./make_vivado_project + cp build/vivado_project/fpga.runs/impl_1/toplevel.bit build/latest.bit + +build/soc.mmi: build/vivado_project/fpga.runs/impl_1/toplevel.bit + ./make_mmi_files + +build/latest_soc_sw.bit : $(SOCMEM) build/soc.mmi + rm -f updatemem.jou updatemem.log + updatemem -force --meminfo build/soc.mmi --data $(SOCMEM) --bit build/latest.bit --proc dummy --out build/latest_soc_sw.bit + cp build/latest_soc_sw.bit build/latest.bit + +build/latest.bit : build/latest_soc_sw.bit + +build/latest.mcs : build/latest.bit + ./make_mcs_file + +prog : build/latest.bit + ./write_fpga + +flash : build/latest.mcs + ./write_flash + +clean-soc-sw: + make -C $(SWBASE)/$(SOCSW) clean-all + +soc-sw: clean-soc-sw $(SOCMEM) + +.PHONY: clean +clean : + rm -rf build + mkdir build + rm -f updatemem.jou + rm -f updatemem.log + +clean-sw: clean-soc-sw + +clean-all : clean clean-sw + rm -f ../../../$(TOP).v + rm -f ../../../$(TOP).v_* diff --git a/scripts/Murax/arty_a7/open_vivado_project b/scripts/Murax/arty_a7/open_vivado_project new file mode 100755 index 0000000..24c54d1 --- /dev/null +++ b/scripts/Murax/arty_a7/open_vivado_project @@ -0,0 +1,4 @@ +#!/bin/sh + +cd ./build +vivado -mode batch -source ../open_vivado_project.tcl -notrace diff --git a/scripts/Murax/arty_a7/picocom_arty b/scripts/Murax/arty_a7/picocom_arty new file mode 100644 index 0000000..ff15a17 --- /dev/null +++ b/scripts/Murax/arty_a7/picocom_arty @@ -0,0 +1 @@ +picocom --baud 115200 --imap lfcrlf /dev/ttyUSB1 diff --git a/scripts/Murax/arty_a7/toplevel.v b/scripts/Murax/arty_a7/toplevel.v new file mode 100644 index 0000000..e127da6 --- /dev/null +++ b/scripts/Murax/arty_a7/toplevel.v @@ -0,0 +1,66 @@ +`timescale 1ns / 1ps + +module toplevel( + input wire clk100, + input wire cpu_reset,//active low + + input wire tck, + input wire tms, + input wire tdi, + input wire trst,//ignored + output reg tdo, + + input wire serial_rx, + output wire serial_tx, + + input wire user_sw0, + input wire user_sw1, + input wire user_sw2, + input wire user_sw3, + + input wire user_btn0, + input wire user_btn1, + input wire user_btn2, + input wire user_btn3, + + output wire user_led0, + output wire user_led1, + output wire user_led2, + output wire user_led3 + ); + + wire [31:0] io_gpioA_read; + wire [31:0] io_gpioA_write; + wire [31:0] io_gpioA_writeEnable; + + wire io_asyncReset = ~cpu_reset; + + assign {user_led3,user_led2,user_led1,user_led0} = io_gpioA_write[3 : 0]; + assign io_gpioA_read[3:0] = {user_sw3,user_sw2,user_sw1,user_sw0}; + assign io_gpioA_read[7:4] = {user_btn3,user_btn2,user_btn1,user_btn0}; + assign io_gpioA_read[11:8] = {tck,tms,tdi,trst}; + + reg tesic_tck,tesic_tms,tesic_tdi; + wire tesic_tdo; + reg soc_tck,soc_tms,soc_tdi; + wire soc_tdo; + + always @(*) begin + {soc_tck, soc_tms, soc_tdi } = {tck,tms,tdi}; + tdo = soc_tdo; + end + + Murax core ( + .io_asyncReset(io_asyncReset), + .io_mainClk (clk100 ), + .io_jtag_tck(soc_tck), + .io_jtag_tdi(soc_tdi), + .io_jtag_tdo(soc_tdo), + .io_jtag_tms(soc_tms), + .io_gpioA_read (io_gpioA_read), + .io_gpioA_write (io_gpioA_write), + .io_gpioA_writeEnable(io_gpioA_writeEnable), + .io_uart_txd(serial_tx), + .io_uart_rxd(serial_rx) + ); +endmodule diff --git a/scripts/Murax/arty_a7/write_flash b/scripts/Murax/arty_a7/write_flash new file mode 100755 index 0000000..05414c4 --- /dev/null +++ b/scripts/Murax/arty_a7/write_flash @@ -0,0 +1,3 @@ +#!/bin/sh +cd ./build +vivado -mode batch -source ../write_flash.tcl -notrace diff --git a/scripts/Murax/arty_a7/write_fpga b/scripts/Murax/arty_a7/write_fpga new file mode 100755 index 0000000..63a344e --- /dev/null +++ b/scripts/Murax/arty_a7/write_fpga @@ -0,0 +1,3 @@ +#!/bin/sh +cd ./build +vivado -mode batch -source ../write_fpga.tcl -notrace diff --git a/src/main/c/murax/hello_world/makefile b/src/main/c/murax/hello_world/makefile new file mode 100644 index 0000000..dc560c0 --- /dev/null +++ b/src/main/c/murax/hello_world/makefile @@ -0,0 +1,134 @@ +PROJ_NAME=hello_world +DEBUG=no +BENCH=no +MULDIV=no + +SRCS = $(wildcard src/*.c) \ + $(wildcard src/*.cpp) \ + $(wildcard src/*.S) + +OBJDIR = build + +INC = +LIBS = +LIBSINC = -L$(OBJDIR) +LDSCRIPT = ./src/linker.ld + +#include ../../../resources/gcc.mk +# Set it to yes if you are using the sifive precompiled GCC pack +SIFIVE_GCC_PACK ?= yes + +ifeq ($(SIFIVE_GCC_PACK),yes) + RISCV_NAME ?= riscv64-unknown-elf + RISCV_PATH ?= /opt/riscv/ +else + RISCV_NAME ?= riscv32-unknown-elf + ifeq ($(MULDIV),yes) + RISCV_PATH ?= /opt/riscv32im/ + else + RISCV_PATH ?= /opt/riscv32i/ + endif +endif + +MABI=ilp32 +MARCH := rv32i +ifeq ($(MULDIV),yes) + MARCH := $(MARCH)m +endif +ifeq ($(COMPRESSED),yes) + MARCH := $(MARCH)ac +endif + +CFLAGS += -march=$(MARCH) -mabi=$(MABI) -DNDEBUG +LDFLAGS += -march=$(MARCH) -mabi=$(MABI) + + + +#include ../../../resources/subproject.mk + + +ifeq ($(DEBUG),yes) + CFLAGS += -g3 -O0 +endif + +ifeq ($(DEBUG),no) + CFLAGS += -g -Os +endif + +ifeq ($(BENCH),yes) + CFLAGS += -fno-inline +endif + +ifeq ($(SIFIVE_GCC_PACK),yes) + RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/$(MARCH)/$(MABI)/ +else + RISCV_CLIB=$(RISCV_PATH)/$(RISCV_NAME)/lib/ +endif + + + + + +RISCV_OBJCOPY = $(RISCV_PATH)/bin/$(RISCV_NAME)-objcopy +RISCV_OBJDUMP = $(RISCV_PATH)/bin/$(RISCV_NAME)-objdump +RISCV_CC=$(RISCV_PATH)/bin/$(RISCV_NAME)-gcc + +CFLAGS += -MD -fstrict-volatile-bitfields -fno-strict-aliasing +LDFLAGS += -nostdlib -lgcc -mcmodel=medany -nostartfiles -ffreestanding -Wl,-Bstatic,-T,$(LDSCRIPT),-Map,$(OBJDIR)/$(PROJ_NAME).map,--print-memory-usage +#LDFLAGS += -lgcc -lc -lg -nostdlib -lgcc -msave-restore --strip-debug, + +OBJS := $(SRCS) +OBJS := $(OBJS:.c=.o) +OBJS := $(OBJS:.cpp=.o) +OBJS := $(OBJS:.S=.o) +OBJS := $(OBJS:..=miaou) +OBJS := $(addprefix $(OBJDIR)/,$(OBJS)) + + +all: $(OBJDIR)/$(PROJ_NAME).elf $(OBJDIR)/$(PROJ_NAME).hex $(OBJDIR)/$(PROJ_NAME).asm $(OBJDIR)/$(PROJ_NAME).v + +$(OBJDIR)/%.elf: $(OBJS) | $(OBJDIR) + $(RISCV_CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBSINC) $(LIBS) + +%.hex: %.elf + $(RISCV_OBJCOPY) -O ihex $^ $@ + +%.bin: %.elf + $(RISCV_OBJCOPY) -O binary $^ $@ + +%.v: %.elf + $(RISCV_OBJCOPY) -O verilog $^ $@ + +%.asm: %.elf + $(RISCV_OBJDUMP) -S -d $^ > $@ + +$(OBJDIR)/%.o: %.c + mkdir -p $(dir $@) + $(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^ + $(RISCV_CC) -S $(CFLAGS) $(INC) -o $@.disasm $^ + +$(OBJDIR)/%.o: %.cpp + mkdir -p $(dir $@) + $(RISCV_CC) -c $(CFLAGS) $(INC) -o $@ $^ + +$(OBJDIR)/%.o: %.S + mkdir -p $(dir $@) + $(RISCV_CC) -c $(CFLAGS) -o $@ $^ -D__ASSEMBLY__=1 + +$(OBJDIR): + mkdir -p $@ + +.PHONY: clean +clean: + rm -rf $(OBJDIR)/src + rm -f $(OBJDIR)/$(PROJ_NAME).elf + rm -f $(OBJDIR)/$(PROJ_NAME).hex + rm -f $(OBJDIR)/$(PROJ_NAME).map + rm -f $(OBJDIR)/$(PROJ_NAME).v + rm -f $(OBJDIR)/$(PROJ_NAME).asm + find $(OBJDIR) -type f -name '*.o' -print0 | xargs -0 -r rm + find $(OBJDIR) -type f -name '*.d' -print0 | xargs -0 -r rm + +clean-all : clean + +.SECONDARY: $(OBJS) diff --git a/src/main/c/murax/hello_world/src/crt.S b/src/main/c/murax/hello_world/src/crt.S new file mode 100644 index 0000000..62d67b9 --- /dev/null +++ b/src/main/c/murax/hello_world/src/crt.S @@ -0,0 +1,98 @@ +.global crtStart +.global main +.global irqCallback + + .section .start_jump,"ax",@progbits +crtStart: + //long jump to allow crtInit to be anywhere + //do it always in 12 bytes + lui x2, %hi(crtInit) + addi x2, x2, %lo(crtInit) + jalr x1,x2 + nop + +.section .text + +.global trap_entry +.align 5 +trap_entry: + sw x1, - 1*4(sp) + sw x5, - 2*4(sp) + sw x6, - 3*4(sp) + sw x7, - 4*4(sp) + sw x10, - 5*4(sp) + sw x11, - 6*4(sp) + sw x12, - 7*4(sp) + sw x13, - 8*4(sp) + sw x14, - 9*4(sp) + sw x15, -10*4(sp) + sw x16, -11*4(sp) + sw x17, -12*4(sp) + sw x28, -13*4(sp) + sw x29, -14*4(sp) + sw x30, -15*4(sp) + sw x31, -16*4(sp) + addi sp,sp,-16*4 + call irqCallback + lw x1 , 15*4(sp) + lw x5, 14*4(sp) + lw x6, 13*4(sp) + lw x7, 12*4(sp) + lw x10, 11*4(sp) + lw x11, 10*4(sp) + lw x12, 9*4(sp) + lw x13, 8*4(sp) + lw x14, 7*4(sp) + lw x15, 6*4(sp) + lw x16, 5*4(sp) + lw x17, 4*4(sp) + lw x28, 3*4(sp) + lw x29, 2*4(sp) + lw x30, 1*4(sp) + lw x31, 0*4(sp) + addi sp,sp,16*4 + mret + .text + + +crtInit: + .option push + .option norelax + la gp, __global_pointer$ + .option pop + la sp, _stack_start + +bss_init: + la a0, _bss_start + la a1, _bss_end +bss_loop: + beq a0,a1,bss_done + sw zero,0(a0) + add a0,a0,4 + j bss_loop +bss_done: + +ctors_init: + la a0, _ctors_start + addi sp,sp,-4 +ctors_loop: + la a1, _ctors_end + beq a0,a1,ctors_done + lw a3,0(a0) + add a0,a0,4 + sw a0,0(sp) + jalr a3 + lw a0,0(sp) + j ctors_loop +ctors_done: + addi sp,sp,4 + + + li a0, 0x880 //880 enable timer + external interrupts + csrw mie,a0 + li a0, 0x1808 //1808 enable interrupts + csrw mstatus,a0 + + call main +infinitLoop: + j infinitLoop diff --git a/src/main/c/murax/hello_world/src/gpio.h b/src/main/c/murax/hello_world/src/gpio.h new file mode 100644 index 0000000..34348fe --- /dev/null +++ b/src/main/c/murax/hello_world/src/gpio.h @@ -0,0 +1,15 @@ +#ifndef GPIO_H_ +#define GPIO_H_ + + +typedef struct +{ + volatile uint32_t INPUT; + volatile uint32_t OUTPUT; + volatile uint32_t OUTPUT_ENABLE; +} Gpio_Reg; + + +#endif /* GPIO_H_ */ + + diff --git a/src/main/c/murax/hello_world/src/interrupt.h b/src/main/c/murax/hello_world/src/interrupt.h new file mode 100644 index 0000000..23b7d27 --- /dev/null +++ b/src/main/c/murax/hello_world/src/interrupt.h @@ -0,0 +1,17 @@ +#ifndef INTERRUPTCTRL_H_ +#define INTERRUPTCTRL_H_ + +#include + +typedef struct +{ + volatile uint32_t PENDINGS; + volatile uint32_t MASKS; +} InterruptCtrl_Reg; + +static void interruptCtrl_init(InterruptCtrl_Reg* reg){ + reg->MASKS = 0; + reg->PENDINGS = 0xFFFFFFFF; +} + +#endif /* INTERRUPTCTRL_H_ */ diff --git a/src/main/c/murax/hello_world/src/linker.ld b/src/main/c/murax/hello_world/src/linker.ld new file mode 100644 index 0000000..57bc2f7 --- /dev/null +++ b/src/main/c/murax/hello_world/src/linker.ld @@ -0,0 +1,110 @@ +/* +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 { + RAM (rwx): ORIGIN = 0x80000000, LENGTH = 2k +} + +_stack_size = DEFINED(_stack_size) ? _stack_size : 256; +_heap_size = DEFINED(_heap_size) ? _heap_size : 0; + +SECTIONS { + + ._vector ORIGIN(RAM): { + *crt.o(.start_jump); + *crt.o(.text); + } > RAM + + ._user_heap (NOLOAD): + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + PROVIDE ( _heap_start = .); + . = . + _heap_size; + . = ALIGN(8); + PROVIDE ( _heap_end = .); + } > RAM + +._stack (NOLOAD): + { + . = ALIGN(16); + PROVIDE (_stack_end = .); + . = . + _stack_size; + . = ALIGN(16); + PROVIDE (_stack_start = .); + } > RAM + + .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.*) + } > RAM + + .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 = .; + } > RAM + + + .rodata : + { + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } > RAM + + .noinit (NOLOAD) : { + . = ALIGN(4); + *(.noinit .noinit.*) + . = ALIGN(4); + } > RAM + + .memory : { + *(.text); + end = .; + } > RAM + + .ctors : + { + . = ALIGN(4); + _ctors_start = .; + KEEP(*(.init_array*)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + . = ALIGN(4); + _ctors_end = .; + PROVIDE ( END_OF_SW_IMAGE = . ); + } > RAM + +} diff --git a/src/main/c/murax/hello_world/src/main.c b/src/main/c/murax/hello_world/src/main.c new file mode 100644 index 0000000..05f3227 --- /dev/null +++ b/src/main/c/murax/hello_world/src/main.c @@ -0,0 +1,42 @@ +//#include "stddefs.h" +#include + +#include "murax.h" + +void print(const char*str){ + while(*str){ + uart_write(UART,*str); + str++; + } +} +void println(const char*str){ + print(str); + uart_write(UART,'\n'); +} + +void delay(uint32_t loops){ + for(int i=0;iOUTPUT; + } +} + +void main() { + GPIO_A->OUTPUT_ENABLE = 0x0000000F; + GPIO_A->OUTPUT = 0x00000001; + println("hello world arty a7 v1"); + const int nleds = 4; + const int nloops = 2000000; + while(1){ + for(unsigned int i=0;iOUTPUT = 1<OUTPUT = (1<<(nleds-1))>>i; + delay(nloops); + } + } +} + +void irqCallback(){ +} diff --git a/src/main/c/murax/hello_world/src/murax.h b/src/main/c/murax/hello_world/src/murax.h new file mode 100644 index 0000000..fbfdf3e --- /dev/null +++ b/src/main/c/murax/hello_world/src/murax.h @@ -0,0 +1,17 @@ +#ifndef __MURAX_H__ +#define __MURAX_H__ + +#include "timer.h" +#include "prescaler.h" +#include "interrupt.h" +#include "gpio.h" +#include "uart.h" + +#define GPIO_A ((Gpio_Reg*)(0xF0000000)) +#define TIMER_PRESCALER ((Prescaler_Reg*)0xF0020000) +#define TIMER_INTERRUPT ((InterruptCtrl_Reg*)0xF0020010) +#define TIMER_A ((Timer_Reg*)0xF0020040) +#define TIMER_B ((Timer_Reg*)0xF0020050) +#define UART ((Uart_Reg*)(0xF0010000)) + +#endif /* __MURAX_H__ */ diff --git a/src/main/c/murax/hello_world/src/prescaler.h b/src/main/c/murax/hello_world/src/prescaler.h new file mode 100644 index 0000000..6bd9694 --- /dev/null +++ b/src/main/c/murax/hello_world/src/prescaler.h @@ -0,0 +1,16 @@ +#ifndef PRESCALERCTRL_H_ +#define PRESCALERCTRL_H_ + +#include + + +typedef struct +{ + volatile uint32_t LIMIT; +} Prescaler_Reg; + +static void prescaler_init(Prescaler_Reg* reg){ + +} + +#endif /* PRESCALERCTRL_H_ */ diff --git a/src/main/c/murax/hello_world/src/timer.h b/src/main/c/murax/hello_world/src/timer.h new file mode 100644 index 0000000..1577535 --- /dev/null +++ b/src/main/c/murax/hello_world/src/timer.h @@ -0,0 +1,20 @@ +#ifndef TIMERCTRL_H_ +#define TIMERCTRL_H_ + +#include + + +typedef struct +{ + volatile uint32_t CLEARS_TICKS; + volatile uint32_t LIMIT; + volatile uint32_t VALUE; +} Timer_Reg; + +static void timer_init(Timer_Reg *reg){ + reg->CLEARS_TICKS = 0; + reg->VALUE = 0; +} + + +#endif /* TIMERCTRL_H_ */ diff --git a/src/main/c/murax/hello_world/src/uart.h b/src/main/c/murax/hello_world/src/uart.h new file mode 100644 index 0000000..c3a30a5 --- /dev/null +++ b/src/main/c/murax/hello_world/src/uart.h @@ -0,0 +1,42 @@ +#ifndef UART_H_ +#define UART_H_ + + +typedef struct +{ + volatile uint32_t DATA; + volatile uint32_t STATUS; + volatile uint32_t CLOCK_DIVIDER; + volatile uint32_t FRAME_CONFIG; +} Uart_Reg; + +enum UartParity {NONE = 0,EVEN = 1,ODD = 2}; +enum UartStop {ONE = 0,TWO = 1}; + +typedef struct { + uint32_t dataLength; + enum UartParity parity; + enum UartStop stop; + uint32_t clockDivider; +} Uart_Config; + +static uint32_t uart_writeAvailability(Uart_Reg *reg){ + return (reg->STATUS >> 16) & 0xFF; +} +static uint32_t uart_readOccupancy(Uart_Reg *reg){ + return reg->STATUS >> 24; +} + +static void uart_write(Uart_Reg *reg, uint32_t data){ + while(uart_writeAvailability(reg) == 0); + reg->DATA = data; +} + +static void uart_applyConfig(Uart_Reg *reg, Uart_Config *config){ + reg->CLOCK_DIVIDER = config->clockDivider; + reg->FRAME_CONFIG = ((config->dataLength-1) << 0) | (config->parity << 8) | (config->stop << 16); +} + +#endif /* UART_H_ */ + + diff --git a/src/main/scala/vexriscv/demo/Murax.scala b/src/main/scala/vexriscv/demo/Murax.scala index 389b91f..dc2bc6f 100644 --- a/src/main/scala/vexriscv/demo/Murax.scala +++ b/src/main/scala/vexriscv/demo/Murax.scala @@ -477,3 +477,10 @@ object MuraxWithRamInit{ SpinalVerilog(Murax(MuraxConfig.default.copy(onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex"))) } } + +object Murax_arty{ + def main(args: Array[String]) { + val hex = "src/main/c/murax/hello_world/build/hello_world.hex" + SpinalVerilog(Murax(MuraxConfig.default(false).copy(coreFrequency = 100 MHz,onChipRamSize = 32 kB, onChipRamHexFile = hex))) + } +} From 2bcddd333d8150f948d61aa748bf3239d3600311 Mon Sep 17 00:00:00 2001 From: sebastien-riou Date: Fri, 17 Jan 2020 00:33:02 +0100 Subject: [PATCH 28/29] forced the commit of missing TCL files --- scripts/Murax/arty_a7/make_bit_file.tcl | 50 ++++++ scripts/Murax/arty_a7/make_mcs_file.tcl | 31 ++++ scripts/Murax/arty_a7/make_mmi_files.tcl | 6 + scripts/Murax/arty_a7/make_vivado_project.tcl | 46 ++++++ scripts/Murax/arty_a7/open_vivado_project.tcl | 4 + scripts/Murax/arty_a7/soc_mmi.tcl | 151 ++++++++++++++++++ scripts/Murax/arty_a7/vivado_params.tcl | 5 + scripts/Murax/arty_a7/write_flash.tcl | 26 +++ scripts/Murax/arty_a7/write_fpga.tcl | 10 ++ 9 files changed, 329 insertions(+) create mode 100644 scripts/Murax/arty_a7/make_bit_file.tcl create mode 100644 scripts/Murax/arty_a7/make_mcs_file.tcl create mode 100644 scripts/Murax/arty_a7/make_mmi_files.tcl create mode 100644 scripts/Murax/arty_a7/make_vivado_project.tcl create mode 100644 scripts/Murax/arty_a7/open_vivado_project.tcl create mode 100644 scripts/Murax/arty_a7/soc_mmi.tcl create mode 100644 scripts/Murax/arty_a7/vivado_params.tcl create mode 100644 scripts/Murax/arty_a7/write_flash.tcl create mode 100644 scripts/Murax/arty_a7/write_fpga.tcl diff --git a/scripts/Murax/arty_a7/make_bit_file.tcl b/scripts/Murax/arty_a7/make_bit_file.tcl new file mode 100644 index 0000000..a97b399 --- /dev/null +++ b/scripts/Murax/arty_a7/make_bit_file.tcl @@ -0,0 +1,50 @@ + +# Input files +set mmi_file "./soc.mmi" +set elf_file "./soc.elf" +set source_bit_file "./soc.bit" + +# Output files +set output_bit_file "./soc_latest_sw.bit" + +# Enable to turn on debug +set updatemem_debug 0 + +# Assemble bit file that can be downloaded to device directly +# Combine the original bit file, mmi file, and software elf to create the full bitstream + +# Delete target file +file delete -force $output_bit_file + +# Determine if the user has built the project and has the target source file +# If not, then use the reference bit file shipped with the project +if { ![file exists $source_bit_file] } { + puts "\n********************************************" + puts "INFO - File $source_bit_file doesn't exist as project has not been built" + puts " Using $reference_bit_file instead\n" + puts "********************************************/n" + set source_bit_file $reference_bit_file +} + +# Banner message to console as there is no output for a few seconds +puts " Running updatemem ..." + +if { $updatemem_debug } { + set error [catch {exec updatemem --debug --force --meminfo $mmi_file --data $elf_file --bit $source_bit_file --proc dummy --out $output_bit_file} result] +} else { + set error [catch {exec updatemem --force --meminfo $mmi_file --data $elf_file --bit $source_bit_file --proc dummy --out $output_bit_file} result] +} + +# Print the stdout from updatemem +puts $result + +# Updatemem returns 0 even when there is an error, so cannot trap on error. Having deleted output file to start, then +# detect if it now exists, else exit. +if { ![file exists $output_bit_file] } { + puts "ERROR - $output_bit_file not made" + return -1 +} else { + puts "\n********************************************" + puts " $output_bit_file correctly generated" + puts "********************************************\n" +} diff --git a/scripts/Murax/arty_a7/make_mcs_file.tcl b/scripts/Murax/arty_a7/make_mcs_file.tcl new file mode 100644 index 0000000..9863a2c --- /dev/null +++ b/scripts/Murax/arty_a7/make_mcs_file.tcl @@ -0,0 +1,31 @@ + +# Input file +set source_bit_file "./latest.bit" + +# Output file +set output_mcs_file "./latest.mcs" + +# Delete target file +file delete -force $output_mcs_file + +# Determine if the user has built the project and has the target source file +# If not, then use the reference bit file shipped with the project +if { ![file exists $source_bit_file] } { + puts "\n********************************************" + puts "INFO - File $source_bit_file doesn't exist as project has not been built\n" + puts "********************************************/n" + error +} + +# Create MCS file for base board QSPI flash memory +write_cfgmem -force -format MCS -size 16 -interface SPIx4 -loadbit " up 0 $source_bit_file" $output_mcs_file + +# Check MCS was correctly made +if { ![file exists $output_mcs_file] } { + puts "ERROR - $output_bit_file not made" + return -1 +} else { + puts "\n********************************************" + puts " $output_mcs_file correctly generated" + puts "********************************************\n" +} diff --git a/scripts/Murax/arty_a7/make_mmi_files.tcl b/scripts/Murax/arty_a7/make_mmi_files.tcl new file mode 100644 index 0000000..d9ecd48 --- /dev/null +++ b/scripts/Murax/arty_a7/make_mmi_files.tcl @@ -0,0 +1,6 @@ +source [file join [file dirname [file normalize [info script]]] vivado_params.tcl] + +open_project -read_only $outputdir/$projectName +open_run impl_1 +source $base/soc_mmi.tcl +puts "mmi files generated" diff --git a/scripts/Murax/arty_a7/make_vivado_project.tcl b/scripts/Murax/arty_a7/make_vivado_project.tcl new file mode 100644 index 0000000..b206ddb --- /dev/null +++ b/scripts/Murax/arty_a7/make_vivado_project.tcl @@ -0,0 +1,46 @@ +#Create output directory and clear contents +source [file join [file dirname [file normalize [info script]]] vivado_params.tcl] + +file mkdir $outputdir +set files [glob -nocomplain "$outputdir/*"] +if {[llength $files] != 0} { + puts "deleting contents of $outputdir" + file delete -force {*}[glob -directory $outputdir *]; # clear folder contents +} else { + puts "$outputdir is empty" +} + +#Create project +create_project -part $part $projectName $outputdir + +#add source files to Vivado project +#add_files -fileset sim_1 ./path/to/testbench.vhd +#add_files [glob ./path/to/sources/*.vhd] +#add_files -fileset constrs_1 ./path/to/constraint/constraint.xdc +#add_files [glob ./path/to/library/sources/*.vhd] +#set_property -library userDefined [glob ./path/to/library/sources/*.vhd] +add_files [glob $base/*.v] +add_files [glob $topv] +add_files -fileset constrs_1 $base/arty_a7.xdc + +#set top level module and update compile order +set_property top toplevel [current_fileset] +update_compile_order -fileset sources_1 +#update_compile_order -fileset sim_1 + +#launch synthesis +launch_runs synth_1 +wait_on_run synth_1 + +#Run implementation and generate bitstream +set_property STEPS.PHYS_OPT_DESIGN.IS_ENABLED true [get_runs impl_1] +launch_runs impl_1 -to_step write_bitstream +wait_on_run impl_1 +puts "Implementation done!" + +#reports generated by default +#open_run impl_1 +#report_timing_summary -check_timing_verbose -report_unconstrained -file report_timing_summary.rpt +#report_utilization -hierarchical -file report_utilization.rpt + +#TODO: add checks about timing, DRC, CDC such that the script give clear indication if design is OK or not diff --git a/scripts/Murax/arty_a7/open_vivado_project.tcl b/scripts/Murax/arty_a7/open_vivado_project.tcl new file mode 100644 index 0000000..4120019 --- /dev/null +++ b/scripts/Murax/arty_a7/open_vivado_project.tcl @@ -0,0 +1,4 @@ +source [file join [file dirname [file normalize [info script]]] vivado_params.tcl] + +open_project -read_only $outputdir/$projectName +start_gui diff --git a/scripts/Murax/arty_a7/soc_mmi.tcl b/scripts/Murax/arty_a7/soc_mmi.tcl new file mode 100644 index 0000000..33ea686 --- /dev/null +++ b/scripts/Murax/arty_a7/soc_mmi.tcl @@ -0,0 +1,151 @@ +#script to update the init values of RAM without re-synthesis + +if {![info exists mmi_file]} { + # Set MMI output file name + set mmi_file "soc.mmi" +} +if {![info exists part]} { + set part "xc7a35ticsg324-1L" +} + +# Function to swap bits +proc swap_bits { bit } { + + if { $bit > 23 } {return [expr {24 + (31 - $bit)}]} + if { $bit > 15 } {return [expr {16 + (23 - $bit)}]} + if { $bit > 7 } {return [expr {8 + (15 - $bit)}]} + return [expr {7 - $bit}] +} + +# If run from batch file, will need to open project, then open the run +# open_run impl_1 + +# Find all the RAMs, place in a list +set rams [get_cells -hier -regexp {.*core/system_ram/.*} -filter {REF_NAME =~ RAMB36E1}] + +puts "[llength $rams] RAMs in total" +foreach m $rams {puts $m} + +set mems [dict create] +foreach m $rams { + set numbers [regexp -all -inline -- {[0-9]+} $m] + dict set mems $numbers $m +} +set keys [dict keys $mems] +#set keys [lsort -integer $keys] +set rams [] +foreach key $keys { + set m [dict get $mems $key] + puts "$key -> $m" + lappend rams $m +} + +puts "after sort:" +foreach m $rams {puts $m} +puts $rams + +if { [llength $rams] == 0 } { + puts "Error - no memories found" + return -1 +} + +if { [expr {[llength $rams] % 4}] != 0 } { + puts "Error - Number of memories not divisible by 4" + return -1 +} + +set size_bytes [expr {4096*[llength $rams]}] +puts "Instruction memory size $size_bytes" + +# Currently only support memory sizes between 16kB, (one byte per mem), and 128kB, (one bit per mem) +if { ($size_bytes < (4*4096)) || ($size_bytes > (32*4096)) } { + puts "Error - Memory size of $size_bytes out of range" + puts " Script only supports memory sizes between 16kB and 128kB" + return -1 +} + +# Create and open target mmi file +set fp [open $mmi_file {WRONLY CREAT TRUNC}] +if { $fp == 0 } { + puts "Error - Unable to open $mmi_file for writing" + return -1 +} + +# Write the file header +puts $fp "" +puts $fp "" +puts $fp " " +puts $fp " " +puts $fp " " + +# Calculate the expected number of bits per memory +set mem_bits [expr {32/[llength $rams]}] + +puts "mem_bits = $mem_bits" + +set mem_info [dict create] + +set i 0 +foreach ram $rams { + # Get the RAM location + set loc_val [get_property LOC [get_cells $ram]] + regexp -- {(RAMB36_)([0-9XY]+)} $loc_val full ram_name loc_xy + + set memi [dict create ram $ram loc $loc_xy] + + set numbers [regexp -all -inline -- {[0-9]+} $ram] + if { [llength $numbers] == 2 } { + dict lappend mem_info [lindex $numbers 0] $memi + } else { + dict lappend mem_info [expr $i/4] $memi + } + incr i +} + +set sorted_mem_info [dict create] +foreach {idx mems} $mem_info { + foreach mem [lreverse $mems] { + dict lappend sorted_mem_info $idx $mem + } +} +foreach mems $sorted_mem_info { + foreach mem $mems { + puts $mem + } +} + +set lsb 0 +set memlen [ expr 4096*8 / $mem_bits ] +foreach {idx mems} $sorted_mem_info { + puts "idx=$idx" + foreach mem $mems { + puts "mem=$mem" + set ram [dict get $mem ram] + set loc [dict get $mem loc] + set msb [expr $lsb+$mem_bits-1] + set addr_start 0 + set addr_end [expr $memlen-1] + puts "ram=$ram loc=$loc lsb=$lsb msb=$msb addr_start=$addr_start addr_end=$addr_end" + puts $fp " " + puts $fp " " + puts $fp " " + puts $fp " " + puts $fp " " + puts $fp " " + + set lsb [expr ($msb+1)%32] + } +} + +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp " " +puts $fp "" + +close $fp diff --git a/scripts/Murax/arty_a7/vivado_params.tcl b/scripts/Murax/arty_a7/vivado_params.tcl new file mode 100644 index 0000000..343058d --- /dev/null +++ b/scripts/Murax/arty_a7/vivado_params.tcl @@ -0,0 +1,5 @@ +set outputdir ./vivado_project +set part "xc7a35ticsg324-1L" +set base ".." +set projectName "fpga" +set topv "$base/../../../Murax.v" diff --git a/scripts/Murax/arty_a7/write_flash.tcl b/scripts/Murax/arty_a7/write_flash.tcl new file mode 100644 index 0000000..845bff7 --- /dev/null +++ b/scripts/Murax/arty_a7/write_flash.tcl @@ -0,0 +1,26 @@ + +open_hw +connect_hw_server +open_hw_target +current_hw_device [get_hw_devices xc7a35t_0] +refresh_hw_device -update_hw_probes false [lindex [get_hw_devices xc7a35t_0] 0] + +create_hw_cfgmem -hw_device [lindex [get_hw_devices] 0] -mem_dev [lindex [get_cfgmem_parts {s25fl128sxxxxxx0-spi-x1_x2_x4}] 0] +set_property PROBES.FILE {} [get_hw_devices xc7a35t_0] +set_property FULL_PROBES.FILE {} [get_hw_devices xc7a35t_0] +refresh_hw_device [lindex [get_hw_devices xc7a35t_0] 0] +set_property PROGRAM.ADDRESS_RANGE {use_file} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.FILES [list "latest.mcs" ] [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.PRM_FILE {} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] +set_property PROGRAM.CHECKSUM 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] + +if {![string equal [get_property PROGRAM.HW_CFGMEM_TYPE [lindex [get_hw_devices xc7a35t_0] 0]] [get_property MEM_TYPE [get_property CFGMEM_PART [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]]]]] } { create_hw_bitstream -hw_device [lindex [get_hw_devices xc7a35t_0] 0] [get_property PROGRAM.HW_CFGMEM_BITFILE [ lindex [get_hw_devices xc7a35t_0] 0]]; program_hw_devices [lindex [get_hw_devices xc7a35t_0] 0]; }; +program_hw_cfgmem -hw_cfgmem [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a35t_0] 0]] + +close_hw_target +close_hw diff --git a/scripts/Murax/arty_a7/write_fpga.tcl b/scripts/Murax/arty_a7/write_fpga.tcl new file mode 100644 index 0000000..e3214f8 --- /dev/null +++ b/scripts/Murax/arty_a7/write_fpga.tcl @@ -0,0 +1,10 @@ +open_hw +connect_hw_server +open_hw_target +current_hw_device [get_hw_devices xc7a35t_0] +refresh_hw_device -update_hw_probes false [lindex [get_hw_devices xc7a35t_0] 0] +set_property PROBES.FILE {} [get_hw_devices xc7a35t_0] +set_property FULL_PROBES.FILE {} [get_hw_devices xc7a35t_0] +set_property PROGRAM.FILE {latest.bit} [get_hw_devices xc7a35t_0] +program_hw_devices [get_hw_devices xc7a35t_0] +disconnect_hw_server From 1fb1e358bbc90ea03d821e7f3c3b5ac397c9e6fa Mon Sep 17 00:00:00 2001 From: sebastien-riou Date: Fri, 17 Jan 2020 00:49:35 +0100 Subject: [PATCH 29/29] fix makefile clean target --- src/main/c/murax/xipBootloader/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/c/murax/xipBootloader/makefile b/src/main/c/murax/xipBootloader/makefile index 4421131..e08c17b 100644 --- a/src/main/c/murax/xipBootloader/makefile +++ b/src/main/c/murax/xipBootloader/makefile @@ -33,5 +33,5 @@ clean-for-commit: rm -f *.d rm demo_rom.bin demo.bin crt_ram.bin -clean: clean-tmp +clean: clean-for-commit rm -f *.bin