Merge tdk_new and Ti375 Efinity support
Keep the current GPS software and Genesys2/VCU118 flows while integrating Ti375C529 Efinity, flash, programming, and debug support. Add board-specific SPI NOR profiles and persistent GPS flash layouts across all three boards.
This commit is contained in:
@@ -72,7 +72,10 @@ GPS_DEBUG_LEVEL ?= 1
|
||||
GPS_ESKF_ENABLE ?= 1
|
||||
GPS_EPHEMERIS_FLASH_ENABLE ?= 1
|
||||
GPS_EPHEMERIS_FLASH_SEED_INITIAL ?= 1
|
||||
GPS_EPHEMERIS_FLASH_BASE ?= 0x01fe0000
|
||||
GPS_NAV_CONTEXT_ENABLE ?= 1
|
||||
GPS_NAV_CONTEXT_FLASH_BASE ?= 0x01fc0000
|
||||
BSP_SPI_FLASH_PROFILE ?= 1
|
||||
IMU_SENSOR ?= auto
|
||||
|
||||
FLASH_MCS ?= $(OUT_DIR)/flash/genesys2_rocket.mcs
|
||||
@@ -180,7 +183,10 @@ help:
|
||||
' GPS_ESKF_ENABLE=$(GPS_ESKF_ENABLE)' \
|
||||
' GPS_EPHEMERIS_FLASH_ENABLE=$(GPS_EPHEMERIS_FLASH_ENABLE)' \
|
||||
' GPS_EPHEMERIS_FLASH_SEED_INITIAL=$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)' \
|
||||
' GPS_EPHEMERIS_FLASH_BASE=$(GPS_EPHEMERIS_FLASH_BASE)' \
|
||||
' GPS_NAV_CONTEXT_ENABLE=$(GPS_NAV_CONTEXT_ENABLE)' \
|
||||
' GPS_NAV_CONTEXT_FLASH_BASE=$(GPS_NAV_CONTEXT_FLASH_BASE)' \
|
||||
' BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)' \
|
||||
' IMU_SENSOR=$(IMU_SENSOR)' \
|
||||
' UART_PORT=$(UART_PORT)' \
|
||||
' ETH_RF_IFACE=$(ETH_RF_IFACE)' \
|
||||
@@ -222,17 +228,20 @@ fpga-config:
|
||||
' GPS_ESKF_ENABLE=$(GPS_ESKF_ENABLE)' \
|
||||
' GPS_EPHEMERIS_FLASH_ENABLE=$(GPS_EPHEMERIS_FLASH_ENABLE)' \
|
||||
' GPS_EPHEMERIS_FLASH_SEED_INITIAL=$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)' \
|
||||
' GPS_EPHEMERIS_FLASH_BASE=$(GPS_EPHEMERIS_FLASH_BASE)' \
|
||||
' GPS_NAV_CONTEXT_ENABLE=$(GPS_NAV_CONTEXT_ENABLE)' \
|
||||
' GPS_NAV_CONTEXT_FLASH_BASE=$(GPS_NAV_CONTEXT_FLASH_BASE)' \
|
||||
' BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)' \
|
||||
' IMU_SENSOR=$(IMU_SENSOR)' \
|
||||
' ETH_RF_IFACE=$(ETH_RF_IFACE)' \
|
||||
' ETH_RF_INPUT=$(ETH_RF_INPUT)' \
|
||||
' ETH_RF_SAMPLE_FORMAT=$(ETH_RF_SAMPLE_FORMAT)'
|
||||
|
||||
software:
|
||||
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" IMU_SENSOR="$(IMU_SENSOR)" bootloader flash-image
|
||||
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" IMU_SENSOR="$(IMU_SENSOR)" bootloader flash-image
|
||||
|
||||
$(APP_ELF): FORCE
|
||||
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" IMU_SENSOR="$(IMU_SENSOR)" app
|
||||
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" IMU_SENSOR="$(IMU_SENSOR)" app
|
||||
|
||||
chisel: software
|
||||
@cd "$(REPO_DIR)"
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#-----------------------------------------------------------
|
||||
# Vivado v2025.2 (64-bit)
|
||||
# SW Build 6299465 on Fri Nov 14 12:34:56 MST 2025
|
||||
# IP Build 6300035 on Fri Nov 14 10:48:45 MST 2025
|
||||
# SharedData Build 6298862 on Thu Nov 13 04:50:51 MST 2025
|
||||
# Start of session at: Tue Jul 7 01:14:33 2026
|
||||
# Process ID : 505349
|
||||
# Current directory : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream
|
||||
# Command line : vivado
|
||||
# Log file : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream/vivado.log
|
||||
# Journal file : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream/vivado.jou
|
||||
# Running On : onur
|
||||
# Platform : Ubuntu
|
||||
# Operating System : Ubuntu 22.04.5 LTS
|
||||
# Processor Detail : AMD Ryzen 7 7800X3D 8-Core Processor
|
||||
# CPU Frequency : 4199.900 MHz
|
||||
# CPU Physical cores : 12
|
||||
# CPU Logical cores : 12
|
||||
# Host memory : 22112 MB
|
||||
# Swap memory : 2147 MB
|
||||
# Total Virtual : 24260 MB
|
||||
# Available Virtual : 20472 MB
|
||||
#-----------------------------------------------------------
|
||||
start_gui
|
||||
@@ -1,118 +0,0 @@
|
||||
#-----------------------------------------------------------
|
||||
# Vivado v2025.2 (64-bit)
|
||||
# SW Build 6299465 on Fri Nov 14 12:34:56 MST 2025
|
||||
# IP Build 6300035 on Fri Nov 14 10:48:45 MST 2025
|
||||
# SharedData Build 6298862 on Thu Nov 13 04:50:51 MST 2025
|
||||
# Start of session at: Tue Jul 7 01:14:33 2026
|
||||
# Process ID : 505349
|
||||
# Current directory : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream
|
||||
# Command line : vivado
|
||||
# Log file : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream/vivado.log
|
||||
# Journal file : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream/vivado.jou
|
||||
# Running On : onur
|
||||
# Platform : Ubuntu
|
||||
# Operating System : Ubuntu 22.04.5 LTS
|
||||
# Processor Detail : AMD Ryzen 7 7800X3D 8-Core Processor
|
||||
# CPU Frequency : 4199.900 MHz
|
||||
# CPU Physical cores : 12
|
||||
# CPU Logical cores : 12
|
||||
# Host memory : 22112 MB
|
||||
# Swap memory : 2147 MB
|
||||
# Total Virtual : 24260 MB
|
||||
# Available Virtual : 20472 MB
|
||||
#-----------------------------------------------------------
|
||||
start_gui
|
||||
Sourcing tcl script '/home/onur/.Xilinx/Vivado/Vivado_init.tcl'
|
||||
Configured Digilent board repo: /home/onur/.local/share/digilent-vivado-boards/new/board_files
|
||||
WARNING: [Board 49-26] cannot add Board Part digilentinc.com:gzu_3eg:part0:1.0 available at /home/onur/.local/share/digilent-vivado-boards/new/board_files/genesys-zu-3eg/B.0/board.xml as part xczu3eg-sfvc784-1-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part digilentinc.com:gzu_3eg:part0:1.1 available at /home/onur/.local/share/digilent-vivado-boards/new/board_files/genesys-zu-3eg/D.0/board.xml as part xczu3eg-sfvc784-1-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part digilentinc.com:gzu_5ev:part0:1.1 available at /home/onur/.local/share/digilent-vivado-boards/new/board_files/genesys-zu-5ev/C.0/board.xml as part xczu5ev-sfvc784-1-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:emb-plus-vpr-4616:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/emb-plus-vpr-4616/1.0/board.xml as part xcve2302-sfva784-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:emb-plus-vpr-4616:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/emb-plus-vpr-4616/1.1/board.xml as part xcve2302-sfva784-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k24c:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k24c/1.0/board.xml as part xck24-ubva530-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k24c:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k24c/1.1/board.xml as part xck24-ubva530-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k24i:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k24i/1.0/board.xml as part xck24-ubva530-2lvi-i specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26c:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26c/1.2/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26c:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26c/1.3/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26c:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26c/1.4/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26i:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26i/1.2/board.xml as part xck26-sfvc784-2lvi-i specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26i:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26i/1.3/board.xml as part xck26-sfvc784-2lvi-i specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26i:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26i/1.4/board.xml as part xck26-sfvc784-2lvi-i specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kcu105:part0:1.6 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kcu105/1.6/board.xml as part xcku040-ffva1156-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kcu105:part0:1.7 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kcu105/1.7/board.xml as part xcku040-ffva1156-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kcu116:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kcu116/1.4/board.xml as part xcku5p-ffvb676-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kcu116:part0:1.5 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kcu116/1.5/board.xml as part xcku5p-ffvb676-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kcu1500:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kcu1500/1.2/board.xml as part xcku115-flvb2104-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kd240_som:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kd240_som/1.0/board.xml as part xck24-ubva530-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kd240_som:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kd240_som/1.1/board.xml as part xck24-ubva530-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kr260_som:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kr260_som/1.0/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kr260_som:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kr260_som/1.1/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kv260_som:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kv260_som/1.2/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kv260_som:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kv260_som/1.3/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kv260_som:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kv260_som/1.4/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:scu35:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/scu35/1.0/board.xml as part xcsu35p-sbvb625-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:v80:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/v80/1.0/board.xml as part xcv80-lsva4737-2mhp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:2.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/2.2/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:3.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/3.0/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:3.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/3.1/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:3.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/3.2/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:3.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/3.3/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:3.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/3.4/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190_newl:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190_newl/production/1.0/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190_newl:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190_newl/production/1.1/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190_newl:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190_newl/production/1.2/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190_newl:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190_newl/production/1.3/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu108:part0:1.6 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu108/1.6/board.xml as part xcvu095-ffva2104-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu108:part0:1.7 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu108/1.7/board.xml as part xcvu095-ffva2104-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu110:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu110/1.4/board.xml as part xcvu190-flgc2104-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu118:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu118/2.0/board.xml as part xcvu9p-flga2104-2l-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu118:part0:2.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu118/2.3/board.xml as part xcvu9p-flga2104-2l-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu118:part0:2.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu118/2.4/board.xml as part xcvu9p-flga2104-2l-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu128:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu128/production/1.0/board.xml as part xcvu37p-fsvh2892-2l-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu129:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu129/production/1.0/board.xml as part xcvu29p-fsga2577-2l-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu1525:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu1525/1.3/board.xml as part xcvu9p-fsgd2104-2l-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek280:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek280/production/1.0/board.xml as part xcve2802-vsvh1760-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek280:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek280/production/1.1/board.xml as part xcve2802-vsvh1760-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek280:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek280/production/1.2/board.xml as part xcve2802-vsvh1760-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek385:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek385/1.0/board.xml as part xc2ve3858-ssva2112-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek385:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek385/1.1/board.xml as part xc2ve3858-ssva2112-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek385_1:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek385_2/1.0/board.xml as part xc2ve3858-ssva2112-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vermeo_t1_mpsoc:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vermeo_t1_mpsoc/1.0/board.xml as part xczu19eg-ffvd1760-2l-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vermeo_t1_rfsoc:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vermeo_t1_rfsoc/1.0/board.xml as part xczu21dr-ffvd1156-2l-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vhk158:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vhk158/production/1.0/board.xml as part xcvh1582-vsva3697-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vhk158:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vhk158/production/1.1/board.xml as part xcvh1582-vsva3697-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vhk158:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vhk158/production/1.2/board.xml as part xcvh1582-vsva3697-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180:part0:2.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180/production/2.2/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180:part0:3.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180/production/3.0/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180:part0:3.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180/production/3.1/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180:part0:3.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180/production/3.2/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180:part0:3.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180/production/3.3/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180_newl:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180_newl/production/1.0/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180_newl:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180_newl/production/1.1/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk120:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk120/production/1.0/board.xml as part xcvp1202-vsva2785-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk120:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk120/production/1.1/board.xml as part xcvp1202-vsva2785-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk120:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk120/production/1.2/board.xml as part xcvp1202-vsva2785-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk180:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk180/production/1.0/board.xml as part xcvp1802-lsvc4072-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk180:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk180/production/1.1/board.xml as part xcvp1802-lsvc4072-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk180:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk180/production/1.2/board.xml as part xcvp1802-lsvc4072-2mp-e-s specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vrk160:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vrk160/1.0/board.xml as part xcvr1602-vsva2488-2mp-e-s-es1 specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vrk160:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vrk160/1.1/board.xml as part xcvr1602-vsva2488-2mp-e-s-es1 specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu102:part0:3.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu102/3.3/board.xml as part xczu9eg-ffvb1156-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu102:part0:3.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu102/3.4/board.xml as part xczu9eg-ffvb1156-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu104:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu104/1.1/board.xml as part xczu7ev-ffvc1156-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu106:part0:2.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu106/2.4/board.xml as part xczu7ev-ffvc1156-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu106:part0:2.5 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu106/2.5/board.xml as part xczu7ev-ffvc1156-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu106:part0:2.6 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu106/2.6/board.xml as part xczu7ev-ffvc1156-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu111:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu111/1.2/board.xml as part xczu28dr-ffvg1517-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu111:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu111/1.3/board.xml as part xczu28dr-ffvg1517-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu111:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu111/1.4/board.xml as part xczu28dr-ffvg1517-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu1275:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu1275/1.0/board.xml as part xczu29dr-ffvf1760-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu1285:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu1285/1.0/board.xml as part xczu39dr-ffvf1760-2-i specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu208:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu208/production/2.0/board.xml as part xczu48dr-fsvg1517-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu208ld:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu208ld/production/2.0/board.xml as part xczu58dr-fsvg1517-2-i specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu216:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu216/production/2.0/board.xml as part xczu49dr-ffvf1760-2-e specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu216ld:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu216ld/production/2.0/board.xml as part xczu59dr-ffvf1760-2-i specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu670:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu670/2.0/board.xml as part xczu67dr-fsve1156-2-i specified in board_part file is either invalid or not available
|
||||
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu670ld:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu670ld/1.0/board.xml as part xczu57dr-fsve1156-2-i specified in board_part file is either invalid or not available
|
||||
exit
|
||||
INFO: [Common 17-206] Exiting Vivado at Tue Jul 7 01:14:42 2026...
|
||||
@@ -0,0 +1,12 @@
|
||||
/out/
|
||||
/flow/efinity/ti375c529_rocket.isf
|
||||
/flow/efinity/ti375c529_rocket.peri.xml
|
||||
/flow/efinity/ti375c529_rocket.pt.sdc
|
||||
/flow/efinity/ti375c529_rocket.pt.rpt
|
||||
/flow/efinity/ti375c529_rocket.pinout.*
|
||||
/flow/efinity/ti375c529_rocket.interface.csv
|
||||
/flow/efinity/ti375c529_rocket_template.v
|
||||
/flow/efinity/outflow/
|
||||
/flow/efinity/work_pnr/
|
||||
/flow/efinity/work_syn/
|
||||
/flow/efinity/RUNPNR_*
|
||||
@@ -0,0 +1,438 @@
|
||||
SHELL := /bin/bash
|
||||
.SHELLFLAGS := -euo pipefail -c
|
||||
.ONESHELL:
|
||||
|
||||
FPGA_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
REPO_DIR := $(abspath $(FPGA_DIR)/../../..)
|
||||
SOC_SW_DIR := $(REPO_DIR)/soc/software
|
||||
SOC_OUT_DIR := $(REPO_DIR)/soc/out
|
||||
HW_DIR := $(REPO_DIR)/hardware
|
||||
HW_GENERATED_DIR := $(HW_DIR)/generated
|
||||
GPS_SYSTEM_DIR ?= $(HW_DIR)/external/gps/rtl
|
||||
FLOW_DIR := $(FPGA_DIR)/flow/efinity
|
||||
DEBUG_DIR := $(FPGA_DIR)/flow/debug
|
||||
TOOL_SCRIPT_DIR := $(FPGA_DIR)/tools
|
||||
OUT_DIR := $(FPGA_DIR)/out
|
||||
LOG_DIR := $(OUT_DIR)/logs
|
||||
|
||||
include $(REPO_DIR)/tools/project.mk
|
||||
|
||||
BOARD ?= ti375c529
|
||||
DEVICE ?= Ti375C529
|
||||
TIMING_MODEL ?= C4
|
||||
SOC_CLK_HZ ?= 100000000
|
||||
GPS_ACQ_CLK_HZ ?= 100000000
|
||||
GPS_TRCK_CLK_HZ ?= 125000000
|
||||
GPS_RF_CLK_HZ ?= 16367981
|
||||
RF_INPUT_MODE ?= pmod
|
||||
UART_PORT ?= /dev/ttyUSB2
|
||||
UART_BAUD ?= 460800
|
||||
OPENOCD ?= $(shell command -v openocd)
|
||||
OPENOCD_ADAPTER_SPEED ?= 1000
|
||||
GDB_HOST ?= localhost
|
||||
GDB_PORT ?= 3333
|
||||
GDB ?= $(firstword $(wildcard /tools/toolchain/bin/riscv64-unknown-elf-gdb) $(CROSS)gdb)
|
||||
# Leave empty for Efinity's board-profile auto-detection. Boards without an
|
||||
# FTDI serial number require a bus/device-qualified URL, which changes after
|
||||
# re-enumeration; users with multiple boards can override this explicitly.
|
||||
FTDI_URL ?=
|
||||
BSP_UART_CLOCK_HZ ?= $(SOC_CLK_HZ)
|
||||
BSP_UART_BAUDRATE ?= $(UART_BAUD)
|
||||
BSP_CLINT_TIMEBASE_HZ ?= 1000000
|
||||
DTIM_BASE ?= 0x80000000
|
||||
DTIM_SIZE ?= 0x00100000
|
||||
# The compressed Ti375 configuration currently occupies about 5.2 MB.
|
||||
# Keep the application on a 64-KiB boundary with ample growth margin.
|
||||
APP_FLASH_OFFSET ?= 0x00800000
|
||||
FLASH_SIZE ?= 0x04000000
|
||||
GPS_DEBUG ?= 1
|
||||
GPS_DEBUG_LEVEL ?= 4
|
||||
GPS_ESKF_ENABLE ?= 1
|
||||
GPS_EPHEMERIS_FLASH_ENABLE ?= 1
|
||||
GPS_EPHEMERIS_FLASH_SEED_INITIAL ?= 1
|
||||
GPS_EPHEMERIS_FLASH_BASE ?= 0x03fe0000
|
||||
GPS_NAV_CONTEXT_ENABLE ?= 1
|
||||
GPS_NAV_CONTEXT_FLASH_BASE ?= 0x03fc0000
|
||||
BSP_SPI_FLASH_PROFILE ?= 3
|
||||
IMU_SENSOR ?= auto
|
||||
app ?=
|
||||
ifneq ($(strip $(app)),)
|
||||
APP ?= $(app)
|
||||
else
|
||||
APP ?= hello_uart
|
||||
endif
|
||||
|
||||
FIRRTL_DIR ?= $(HW_GENERATED_DIR)/ti375c529-soc
|
||||
VERILOG_DIR ?= $(HW_GENERATED_DIR)/ti375c529-soc-verilog
|
||||
WRAPPER := $(OUT_DIR)/build/generated/ti375c529_rocket_top.sv
|
||||
GPS_EFINITY_DIR := $(OUT_DIR)/build/generated/gps_efinity
|
||||
SOURCE_LIST := $(OUT_DIR)/build/efinity_sources.f
|
||||
PROJECT_XML := $(FLOW_DIR)/ti375c529_rocket.xml
|
||||
INTERFACE_SOURCE := $(HW_DIR)/fpga/ti375c529/constraints/ti375c529_rocket.isf
|
||||
INTERFACE_SCRIPT := $(FLOW_DIR)/ti375c529_rocket.isf
|
||||
BIT_FILE ?= $(OUT_DIR)/bitstream/ti375c529_rocket.bit
|
||||
CONFIG_HEX ?= $(OUT_DIR)/bitstream/ti375c529_rocket.hex
|
||||
APP_ELF ?= $(SOC_OUT_DIR)/software/$(APP)/$(APP).elf
|
||||
APP_FLASH_IMAGE ?= $(SOC_OUT_DIR)/flash/$(APP).flash.bin
|
||||
FLASH_DIR := $(OUT_DIR)/flash
|
||||
FLASH_REGION_DIR := $(FLASH_DIR)/regions
|
||||
APP_HEX ?= $(FLASH_REGION_DIR)/app.hex
|
||||
FLASH_HEX ?= $(FLASH_DIR)/ti375c529_rocket.hex
|
||||
FLASH_MANIFEST ?= $(FLASH_DIR)/ti375c529_rocket.json
|
||||
FLASH_LOADER ?= $(EFINITY_HOME)/pgm/fli/titanium/u006A0A79.bit
|
||||
FLASH_VERIFY ?= onchipx2
|
||||
OPENOCD_CFG ?= $(DEBUG_DIR)/openocd_ti375c529_bscan.cfg
|
||||
GDB_LOAD_SCRIPT ?= $(DEBUG_DIR)/gdb_load_and_run.gdb
|
||||
GDB_ATTACH_SCRIPT ?= $(DEBUG_DIR)/gdb_attach.gdb
|
||||
|
||||
.PHONY: help all fpga-config detect software chisel rtl soc interface map bitstream \
|
||||
program-fpga debug-openocd debug-load debug-gdb uart-listen \
|
||||
flash-image flash-regions program-flash program-flash-elf \
|
||||
program-flash-bitstream program-flash-regions program-flash-all \
|
||||
program-flash-combined program-flash-loader program-app program-bitstream \
|
||||
clean clean-sw clean-fpga FORCE
|
||||
|
||||
help:
|
||||
@printf '%s\n' \
|
||||
'Ti375C529 Efinity targets:' \
|
||||
' make detect Scan USB and read the Ti375 JTAG IDCODE' \
|
||||
' make software Build the Rocket boot ROM and selected RV64 app' \
|
||||
' make chisel Emit Rocket FIRRTL with the existing FPGA config' \
|
||||
' make rtl Emit split SystemVerilog, Efinix shell, and file list' \
|
||||
' make interface Generate Efinity pin/PLL/JTAG interface data' \
|
||||
' make map Run Efinity synthesis only' \
|
||||
' make bitstream Run the complete Efinity flow' \
|
||||
' make program-fpga Load BIT_FILE into Ti375 SRAM over JTAG' \
|
||||
' make flash-image Generate combined Lower-flash Efinity HEX' \
|
||||
' make program-flash Program only the application flash region' \
|
||||
' make program-flash-bitstream' \
|
||||
' Program only the configuration region' \
|
||||
' make program-flash-combined' \
|
||||
' Program configuration + application HEX' \
|
||||
' make debug-openocd Start Rocket DMI/GDB server through JTAG_USER1' \
|
||||
' make debug-load Load APP ELF into DTIM through GDB' \
|
||||
' make uart-listen Listen to FTDI UART interface 2' \
|
||||
' make fpga-config Print resolved tools, clocks, files, and USB config'
|
||||
|
||||
all: bitstream
|
||||
|
||||
fpga-config:
|
||||
@printf '%s\n' \
|
||||
'Ti375C529 FPGA config:' \
|
||||
' EFINITY_HOME=$(EFINITY_HOME)' \
|
||||
' EFX_RUN=$(EFX_RUN)' \
|
||||
' EFX_PGM=$(EFX_PGM)' \
|
||||
' OPENOCD=$(OPENOCD)' \
|
||||
' GDB=$(GDB)' \
|
||||
' DEVICE=$(DEVICE)' \
|
||||
' TIMING_MODEL=$(TIMING_MODEL)' \
|
||||
' SOC_CLK_HZ=$(SOC_CLK_HZ)' \
|
||||
' GPS_ACQ_CLK_HZ=$(GPS_ACQ_CLK_HZ)' \
|
||||
' GPS_TRCK_CLK_HZ=$(GPS_TRCK_CLK_HZ)' \
|
||||
' GPS_RF_CLK_HZ=$(GPS_RF_CLK_HZ)' \
|
||||
' RF_INPUT_MODE=$(RF_INPUT_MODE)' \
|
||||
' BIT_FILE=$(BIT_FILE)' \
|
||||
' CONFIG_HEX=$(CONFIG_HEX)' \
|
||||
' FLASH_HEX=$(FLASH_HEX)' \
|
||||
' APP_FLASH_OFFSET=$(APP_FLASH_OFFSET)' \
|
||||
' GPS_EPHEMERIS_FLASH_ENABLE=$(GPS_EPHEMERIS_FLASH_ENABLE)' \
|
||||
' GPS_EPHEMERIS_FLASH_SEED_INITIAL=$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)' \
|
||||
' GPS_EPHEMERIS_FLASH_BASE=$(GPS_EPHEMERIS_FLASH_BASE)' \
|
||||
' GPS_NAV_CONTEXT_ENABLE=$(GPS_NAV_CONTEXT_ENABLE)' \
|
||||
' GPS_NAV_CONTEXT_FLASH_BASE=$(GPS_NAV_CONTEXT_FLASH_BASE)' \
|
||||
' BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)' \
|
||||
' FLASH_LOADER=$(FLASH_LOADER)' \
|
||||
' FTDI_URL=$(FTDI_URL)' \
|
||||
' UART_PORT=$(UART_PORT)' \
|
||||
' UART_BAUD=$(UART_BAUD)'
|
||||
|
||||
detect:
|
||||
@set +u
|
||||
source "$(EFINITY_SETUP)" >/dev/null 2>&1
|
||||
set -u
|
||||
"$(EFX_PGM)" --scan_usb
|
||||
|
||||
software:
|
||||
@$(MAKE) -C "$(SOC_SW_DIR)" \
|
||||
TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" \
|
||||
APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" \
|
||||
BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" \
|
||||
BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" \
|
||||
GPS_SYSTEM_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" \
|
||||
BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" \
|
||||
BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" \
|
||||
GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" \
|
||||
GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" \
|
||||
GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" \
|
||||
GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" \
|
||||
GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" \
|
||||
GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" \
|
||||
GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" \
|
||||
BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" \
|
||||
IMU_SENSOR="$(IMU_SENSOR)" \
|
||||
bootloader flash-image
|
||||
|
||||
$(APP_ELF): FORCE
|
||||
@$(MAKE) -C "$(SOC_SW_DIR)" \
|
||||
TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" \
|
||||
BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" \
|
||||
BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" \
|
||||
GPS_SYSTEM_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" \
|
||||
BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" \
|
||||
BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" \
|
||||
GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" \
|
||||
GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" \
|
||||
GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" \
|
||||
GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" \
|
||||
GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" \
|
||||
GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" \
|
||||
GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" \
|
||||
BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" \
|
||||
IMU_SENSOR="$(IMU_SENSOR)" app
|
||||
|
||||
chisel: software
|
||||
@cd "$(REPO_DIR)"
|
||||
"$(MILL)" -i 'rocketchip[6.7.0].assembly'
|
||||
rm -rf "$(FIRRTL_DIR)"
|
||||
mkdir -p "$(FIRRTL_DIR)"
|
||||
"$(JAVA_HOME)/bin/java" \
|
||||
-DROCKET_DTIM_BASE="$(DTIM_BASE)" \
|
||||
-DROCKET_DTIM_SIZE="$(DTIM_SIZE)" \
|
||||
-DROCKET_SOC_CLOCK_HZ="$(SOC_CLK_HZ)" \
|
||||
-jar out/rocketchip/6.7.0/assembly.dest/out.jar \
|
||||
--dir "$(FIRRTL_DIR)" \
|
||||
--top freechips.rocketchip.fpga.VCU118RocketSystem \
|
||||
--config freechips.rocketchip.fpga.VCU118RocketConfig
|
||||
|
||||
rtl: chisel
|
||||
@cd "$(REPO_DIR)"
|
||||
rm -rf "$(VERILOG_DIR)"
|
||||
mkdir -p "$(VERILOG_DIR)" "$(dir $(WRAPPER))"
|
||||
$(FIRTOOL_ENV) "$(FIRTOOL)" \
|
||||
"$(FIRRTL_DIR)/VCU118RocketSystem.fir" \
|
||||
--split-verilog -o "$(VERILOG_DIR)" \
|
||||
--preserve-aggregate=none \
|
||||
--disable-annotation-unknown \
|
||||
--disable-all-randomization \
|
||||
--strip-debug-info
|
||||
find "$(VERILOG_DIR)" -maxdepth 1 -type f \( -name '*.sv' -o -name '*.v' \) \
|
||||
-printf './%f\n' | sort > "$(VERILOG_DIR)/filelist.f"
|
||||
perl -0pi -e 's/^([ \t]*)if \([^\n]*\)\n[ \t]*assert__[^\n]*:\s*assert\([^\n]*\);\n//mg; s/^[ \t]*assert__[^\n]*:\s*assert\([^\n]*\);\n//mg' "$(VERILOG_DIR)"/*.sv
|
||||
python3 "$(TOOL_SCRIPT_DIR)/prepare_efinity_rtl.py" \
|
||||
--verilog-dir "$(VERILOG_DIR)" \
|
||||
--gps-source-dir "$(GPS_SYSTEM_DIR)" \
|
||||
--gps-output-dir "$(GPS_EFINITY_DIR)"
|
||||
python3 "$(TOOL_SCRIPT_DIR)/gen_ti375c529_wrapper.py" \
|
||||
--rocket-top "$(VERILOG_DIR)/VCU118RocketSystem.sv" \
|
||||
--out "$(WRAPPER)"
|
||||
: > "$(SOURCE_LIST)"
|
||||
while IFS= read -r rel; do
|
||||
rel="$${rel#./}"
|
||||
printf '%s\n' "$(VERILOG_DIR)/$$rel" >> "$(SOURCE_LIST)"
|
||||
done < "$(VERILOG_DIR)/filelist.f"
|
||||
printf '%s\n' "$(HW_DIR)/upstream/rocket-chip/src/main/resources/vsrc/plusarg_reader.v" >> "$(SOURCE_LIST)"
|
||||
while IFS= read -r rel; do
|
||||
[[ -z "$$rel" || "$$rel" == \#* ]] && continue
|
||||
case "$$rel" in
|
||||
trck_src/xil_fifo.sv|trck_src/pulp_fifo/top.sv) continue ;;
|
||||
acq_src/acq_nco_carr.sv)
|
||||
printf '%s\n' "$(GPS_EFINITY_DIR)/acq_nco_carr.sv" >> "$(SOURCE_LIST)"
|
||||
continue ;;
|
||||
acq_src/twiddle_ram.sv)
|
||||
printf '%s\n' "$(GPS_EFINITY_DIR)/twiddle_ram.sv" >> "$(SOURCE_LIST)"
|
||||
continue ;;
|
||||
trck_src/NCO_carr.sv)
|
||||
printf '%s\n' "$(GPS_EFINITY_DIR)/NCO_carr.sv" >> "$(SOURCE_LIST)"
|
||||
continue ;;
|
||||
esac
|
||||
printf '%s\n' "$(GPS_SYSTEM_DIR)/$$rel" >> "$(SOURCE_LIST)"
|
||||
done < "$(GPS_SYSTEM_DIR)/filelist.f"
|
||||
printf '%s\n' "$(HW_DIR)/ip/max2771_spi/rtl/max2771_spi_engine.sv" >> "$(SOURCE_LIST)"
|
||||
# Efinix JTAG_USER1 has the same two-bit TDO lead-in as the Kintex-7
|
||||
# BSCANE2 path, so use the Genesys2-aligned Rocket DMI tunnel.
|
||||
printf '%s\n' "$(HW_DIR)/fpga/genesys2/rtl/rocket_bscan_dmi_tunnel.sv" >> "$(SOURCE_LIST)"
|
||||
$(MAKE) -C "$(FPGA_DIR)" "$(INTERFACE_SCRIPT)"
|
||||
|
||||
soc: rtl
|
||||
|
||||
$(INTERFACE_SCRIPT): $(INTERFACE_SOURCE)
|
||||
cp "$<" "$@"
|
||||
|
||||
interface: $(INTERFACE_SCRIPT)
|
||||
@mkdir -p "$(LOG_DIR)"
|
||||
cd "$(FLOW_DIR)"
|
||||
# Efinity prefers a matching generated .peri.xml over the source .isf.
|
||||
# Remove it so pin/PLL changes in the checked-in interface script are applied.
|
||||
rm -f "$(FLOW_DIR)/ti375c529_rocket.peri.xml"
|
||||
set +u
|
||||
source "$(EFINITY_SETUP)" >/dev/null 2>&1
|
||||
set -u
|
||||
python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow interface --un_flow \
|
||||
--pt_opts "peri_scripts=$(INTERFACE_SCRIPT)" 2>&1 | tee "$(LOG_DIR)/interface.log"
|
||||
|
||||
map: rtl interface
|
||||
@mkdir -p "$(LOG_DIR)"
|
||||
cd "$(FLOW_DIR)"
|
||||
set +u
|
||||
source "$(EFINITY_SETUP)" >/dev/null 2>&1
|
||||
set -u
|
||||
python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow map 2>&1 | tee "$(LOG_DIR)/map.log"
|
||||
|
||||
bitstream: rtl interface
|
||||
@mkdir -p "$(LOG_DIR)" "$(dir $(BIT_FILE))"
|
||||
cd "$(FLOW_DIR)"
|
||||
set +u
|
||||
source "$(EFINITY_SETUP)" >/dev/null 2>&1
|
||||
set -u
|
||||
: > "$(LOG_DIR)/full.log"
|
||||
python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow map 2>&1 | tee -a "$(LOG_DIR)/full.log"
|
||||
python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow pnr --work_dir work_pnr 2>&1 | tee -a "$(LOG_DIR)/full.log"
|
||||
python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow pgm --work_dir work_pnr 2>&1 | tee -a "$(LOG_DIR)/full.log"
|
||||
generated_bit="$$(find "$(FLOW_DIR)/outflow" "$(OUT_DIR)" -type f -name 'ti375c529_rocket.bit' 2>/dev/null | head -n 1)"
|
||||
if [[ -z "$$generated_bit" ]]; then
|
||||
echo "Efinity completed without a discoverable ti375c529_rocket.bit" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$$generated_bit" != "$(BIT_FILE)" ]]; then
|
||||
cp "$$generated_bit" "$(BIT_FILE)"
|
||||
fi
|
||||
generated_hex="$$(find "$(FLOW_DIR)/outflow" "$(OUT_DIR)" -type f -name 'ti375c529_rocket.hex' ! -path '$(FLASH_DIR)/*' 2>/dev/null | head -n 1)"
|
||||
if [[ -z "$$generated_hex" ]]; then
|
||||
echo "Efinity completed without a discoverable ti375c529_rocket.hex" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$$generated_hex" != "$(CONFIG_HEX)" ]]; then
|
||||
cp "$$generated_hex" "$(CONFIG_HEX)"
|
||||
fi
|
||||
printf 'Bitstream: %s\nConfiguration HEX: %s\n' "$(BIT_FILE)" "$(CONFIG_HEX)"
|
||||
|
||||
program-fpga:
|
||||
@if [[ ! -f "$(BIT_FILE)" ]]; then
|
||||
echo "Missing bitstream: $(BIT_FILE)" >&2
|
||||
echo "Run: make -C $(FPGA_DIR) bitstream" >&2
|
||||
exit 1
|
||||
fi
|
||||
set +u
|
||||
source "$(EFINITY_SETUP)" >/dev/null 2>&1
|
||||
set -u
|
||||
ftdi_args=()
|
||||
if [[ -n "$(FTDI_URL)" ]]; then
|
||||
ftdi_args+=(--url "$(FTDI_URL)")
|
||||
fi
|
||||
"$(EFX_PGM)" --mode jtag "$${ftdi_args[@]}" "$(BIT_FILE)"
|
||||
|
||||
debug-openocd:
|
||||
@"$(OPENOCD)" \
|
||||
-c "set ADAPTER_SPEED $(OPENOCD_ADAPTER_SPEED)" \
|
||||
-c "gdb_port $(GDB_PORT)" \
|
||||
-f "$(OPENOCD_CFG)"
|
||||
|
||||
debug-load: $(APP_ELF)
|
||||
@"$(GDB)" -q "$(APP_ELF)" \
|
||||
-ex "set confirm off" \
|
||||
-ex "set pagination off" \
|
||||
-ex "target extended-remote $(GDB_HOST):$(GDB_PORT)" \
|
||||
-x "$(GDB_LOAD_SCRIPT)"
|
||||
|
||||
debug-gdb: $(APP_ELF)
|
||||
@"$(GDB)" -q "$(APP_ELF)" \
|
||||
-ex "set confirm off" \
|
||||
-ex "set pagination off" \
|
||||
-ex "target extended-remote $(GDB_HOST):$(GDB_PORT)" \
|
||||
-x "$(GDB_ATTACH_SCRIPT)"
|
||||
|
||||
uart-listen:
|
||||
@stty -F "$(UART_PORT)" "$(UART_BAUD)" cs8 -cstopb -parenb -ixon -ixoff raw
|
||||
@cat "$(UART_PORT)"
|
||||
|
||||
flash-image: flash-regions
|
||||
|
||||
flash-regions: software
|
||||
@if [[ ! -f "$(CONFIG_HEX)" ]]; then
|
||||
echo "Missing Efinity configuration HEX: $(CONFIG_HEX)" >&2
|
||||
echo "Run: make -C $(FPGA_DIR) bitstream" >&2
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "$(FLASH_DIR)" "$(FLASH_REGION_DIR)"
|
||||
python3 "$(TOOL_SCRIPT_DIR)/make_flash_hex.py" \
|
||||
--config-hex "$(CONFIG_HEX)" \
|
||||
--app-bin "$(APP_FLASH_IMAGE)" \
|
||||
--app-offset "$(APP_FLASH_OFFSET)" \
|
||||
--flash-size "$(FLASH_SIZE)" \
|
||||
--nav-context-offset "$(GPS_NAV_CONTEXT_FLASH_BASE)" \
|
||||
--ephemeris-offset "$(GPS_EPHEMERIS_FLASH_BASE)" \
|
||||
--combined-hex "$(FLASH_HEX)" \
|
||||
--app-hex "$(APP_HEX)" \
|
||||
--manifest "$(FLASH_MANIFEST)"
|
||||
|
||||
program-flash-loader:
|
||||
@if [[ ! -f "$(FLASH_LOADER)" ]]; then
|
||||
echo "Missing Ti375 JTAG-to-SPI loader: $(FLASH_LOADER)" >&2
|
||||
exit 1
|
||||
fi
|
||||
set +u
|
||||
source "$(EFINITY_SETUP)" >/dev/null 2>&1
|
||||
set -u
|
||||
ftdi_args=()
|
||||
if [[ -n "$(FTDI_URL)" ]]; then
|
||||
ftdi_args+=(--url "$(FTDI_URL)")
|
||||
fi
|
||||
"$(EFX_PGM)" --mode jtag "$${ftdi_args[@]}" "$(FLASH_LOADER)"
|
||||
|
||||
program-flash program-flash-elf program-app: flash-regions
|
||||
@$(MAKE) -C "$(FPGA_DIR)" program-flash-loader
|
||||
set +u
|
||||
source "$(EFINITY_SETUP)" >/dev/null 2>&1
|
||||
set -u
|
||||
ftdi_args=()
|
||||
if [[ -n "$(FTDI_URL)" ]]; then
|
||||
ftdi_args+=(--url "$(FTDI_URL)")
|
||||
fi
|
||||
"$(EFX_PGM)" --mode jtag_bridge --jtag_bridge_mode all \
|
||||
--verify_method "$(FLASH_VERIFY)" --address "$(APP_FLASH_OFFSET)" \
|
||||
"$${ftdi_args[@]}" "$(APP_HEX)"
|
||||
|
||||
program-flash-bitstream program-bitstream:
|
||||
@if [[ ! -f "$(CONFIG_HEX)" ]]; then
|
||||
echo "Missing Efinity configuration HEX: $(CONFIG_HEX)" >&2
|
||||
echo "Run: make -C $(FPGA_DIR) bitstream" >&2
|
||||
exit 1
|
||||
fi
|
||||
$(MAKE) -C "$(FPGA_DIR)" program-flash-loader
|
||||
set +u
|
||||
source "$(EFINITY_SETUP)" >/dev/null 2>&1
|
||||
set -u
|
||||
ftdi_args=()
|
||||
if [[ -n "$(FTDI_URL)" ]]; then
|
||||
ftdi_args+=(--url "$(FTDI_URL)")
|
||||
fi
|
||||
"$(EFX_PGM)" --mode jtag_bridge --jtag_bridge_mode all \
|
||||
--verify_method "$(FLASH_VERIFY)" --address 0 \
|
||||
"$${ftdi_args[@]}" "$(CONFIG_HEX)"
|
||||
|
||||
program-flash-regions program-flash-all program-flash-combined: flash-image
|
||||
@$(MAKE) -C "$(FPGA_DIR)" program-flash-loader
|
||||
set +u
|
||||
source "$(EFINITY_SETUP)" >/dev/null 2>&1
|
||||
set -u
|
||||
ftdi_args=()
|
||||
if [[ -n "$(FTDI_URL)" ]]; then
|
||||
ftdi_args+=(--url "$(FTDI_URL)")
|
||||
fi
|
||||
"$(EFX_PGM)" --mode jtag_bridge --jtag_bridge_mode all \
|
||||
--verify_method "$(FLASH_VERIFY)" --address 0 \
|
||||
"$${ftdi_args[@]}" "$(FLASH_HEX)"
|
||||
|
||||
clean-sw:
|
||||
@$(MAKE) -C "$(SOC_SW_DIR)" clean
|
||||
|
||||
clean-fpga:
|
||||
rm -rf "$(OUT_DIR)" "$(FIRRTL_DIR)" "$(VERILOG_DIR)"
|
||||
rm -f "$(INTERFACE_SCRIPT)" \
|
||||
"$(FLOW_DIR)/ti375c529_rocket.peri.xml" \
|
||||
"$(FLOW_DIR)/ti375c529_rocket.pt.sdc" \
|
||||
"$(FLOW_DIR)/ti375c529_rocket.pt.rpt"
|
||||
|
||||
clean: clean-fpga
|
||||
|
||||
FORCE:
|
||||
@@ -0,0 +1,175 @@
|
||||
# Ti375C529 Rocket FPGA flow
|
||||
|
||||
This target keeps the project's RV64 Rocket/GPS subsystem in FPGA fabric and
|
||||
replaces only the Xilinx board shell and build flow with Efinix equivalents.
|
||||
It does not use the Ti375 hardened RV32 subsystem.
|
||||
|
||||
Detailed porting, synthesis, clocking, JTAG, and verification notes are in
|
||||
[`flow/efinity/README.md`](flow/efinity/README.md).
|
||||
|
||||
## Build and program
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-config
|
||||
make FPGA_BOARD=ti375c529 fpga-rtl
|
||||
make FPGA_BOARD=ti375c529 fpga-bitstream
|
||||
make FPGA_BOARD=ti375c529 fpga-program
|
||||
```
|
||||
|
||||
The Makefile auto-discovers Efinity under `/tools/efinix/efinity`. Override
|
||||
`EFINITY_HOME` when another installation is required.
|
||||
|
||||
Programming auto-selects the connected Ti375 development kit. If more than
|
||||
one compatible FTDI device is attached, run `make FPGA_BOARD=ti375c529
|
||||
fpga-detect` to list the bus-qualified URLs and pass the selected one as
|
||||
`FTDI_URL=...`.
|
||||
|
||||
Volatile JTAG programming and GDB loading into Rocket DTIM remain available.
|
||||
Persistent boot uses the board's Lower 512-Mbit SPI flash with this map:
|
||||
|
||||
| Region | Flash offset | Contents |
|
||||
|---|---:|---|
|
||||
| FPGA configuration | `0x00000000` | Efinity active-mode configuration HEX |
|
||||
| Rocket application | `0x00800000` | Boot header and ELF-derived payload |
|
||||
| Navigation context | `0x03FC0000` | Two 64-KiB journal sectors |
|
||||
| Ephemeris cache | `0x03FE0000` | Two 64-KiB journal sectors |
|
||||
|
||||
The application starts at 8 MiB because the compressed Ti375 configuration is
|
||||
currently about 5.19 MB; the previous 4 MiB trial offset would overlap it.
|
||||
Generate or program the Efinity raw HEX images with:
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-mcs APP=hello_uart
|
||||
make FPGA_BOARD=ti375c529 fpga-flash-app APP=hello_uart
|
||||
make FPGA_BOARD=ti375c529 fpga-flash-bitstream
|
||||
make FPGA_BOARD=ti375c529 fpga-flash-mcs APP=hello_uart
|
||||
```
|
||||
|
||||
`fpga-mcs` is the repository-wide compatibility target name. For this Efinix
|
||||
board it produces `.hex`, not Xilinx `.mcs`. `fpga-flash-app` changes only the
|
||||
application region; `fpga-flash-mcs` erases/programs configuration plus the
|
||||
application through Efinity's pre-built JTAG-to-SPI bridge and verifies the
|
||||
readback. Cold boot from this layout was verified by a complete board power
|
||||
cycle: Ti375 configured from flash and Rocket loaded and completed
|
||||
`hello_uart` from the application region without a JTAG/GDB load.
|
||||
|
||||
## Debug and load
|
||||
|
||||
Use the host OpenOCD build, not the OpenOCD shipped with Efinity. The build
|
||||
must include `riscv set_bscan_tunnel_ir`; Ti375 uses a 5-bit outer TAP and
|
||||
selects `JTAG_USER1` with instruction `0x08`.
|
||||
OpenOCD 0.12 can be given that upstream-compatible command with
|
||||
`flow/debug/openocd-0.12-ti375-bscan.patch`.
|
||||
|
||||
Apply it from a clean OpenOCD 0.12 source tree before configuring and building
|
||||
the host tool:
|
||||
|
||||
```bash
|
||||
git apply --check /path/to/gps/targets/fpga/ti375c529/flow/debug/openocd-0.12-ti375-bscan.patch
|
||||
git apply /path/to/gps/targets/fpga/ti375c529/flow/debug/openocd-0.12-ti375-bscan.patch
|
||||
```
|
||||
|
||||
Place the resulting `openocd` in `PATH`, or pass its absolute path with
|
||||
`OPENOCD=/path/to/openocd`.
|
||||
|
||||
In one terminal:
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-debug-openocd
|
||||
```
|
||||
|
||||
In a second terminal:
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-debug-load APP=hello_uart
|
||||
make FPGA_BOARD=ti375c529 fpga-uart
|
||||
```
|
||||
|
||||
The target deliberately selects `/tools/toolchain/bin/riscv64-unknown-elf-gdb`
|
||||
when it exists. The medany compiler toolchain is still used to build software,
|
||||
but it is not expected to contain GDB.
|
||||
|
||||
Efinity 2025.2 leaves Rocket's block-local packed store-data array undriven
|
||||
(`VDB-1002`). `tools/prepare_efinity_rtl.py` rewrites that generated RTL
|
||||
expression as an equivalent explicit `case`. Without the rewrite, DMI itself
|
||||
works, but GPR/CSR values stored into Debug Module data registers read as zero;
|
||||
OpenOCD consequently reports a misleading `misa=0`.
|
||||
|
||||
The patch is deliberately post-generation: Chisel and `firtool` first emit the
|
||||
Ti375 SystemVerilog tree, then `prepare_efinity_rtl.py` modifies only the
|
||||
generated Ti375 `Rocket.sv` before Efinity synthesis. It does not edit Rocket's
|
||||
native/upstream Chisel sources.
|
||||
|
||||
Two equivalent four-entry packed temporaries in the generated pbus/cbus
|
||||
`TLAtomicAutomata` modules are rewritten for the same reason, preserving the
|
||||
four atomic-operation mappings while removing their `VDB-1002` risk.
|
||||
|
||||
The same script generates Ti375-only copies of the acquisition carrier NCO,
|
||||
tracking carrier NCO, and FFT twiddle ROM under
|
||||
`out/build/generated/gps_efinity/`. This avoids Efinity 2025.2
|
||||
whole-array/`initial`/`$sin` elaboration failures without editing the shared GPS
|
||||
RTL. Only the Ti375 source list selects these copies; Genesys2 and VCU118 still
|
||||
use the originals. Detailed source paths, warning interpretation, and Questa
|
||||
RTL/post-map equivalence results are in the Efinity flow notes.
|
||||
|
||||
The affected generated source is
|
||||
`hardware/generated/ti375c529-soc-verilog/Rocket.sv`; Efinity records the
|
||||
original diagnostic in
|
||||
`targets/fpga/ti375c529/flow/efinity/outflow/ti375c529_rocket.warn.log`.
|
||||
The checked-in repair is
|
||||
`targets/fpga/ti375c529/tools/prepare_efinity_rtl.py` and runs after every
|
||||
`firtool` invocation, before Efinity synthesis.
|
||||
|
||||
## Board connections
|
||||
|
||||
PMOD0/J13 carries the GPS RF sampler:
|
||||
|
||||
| Signal | PMOD pin | FPGA resource | Package pin |
|
||||
|---|---:|---|---|
|
||||
| `rf_clk` | 10 | GPIOR_95_CLK12 | A12 |
|
||||
| `rf_data[0]` | 2 | GPIOR_89 | G16 |
|
||||
| `rf_data[1]` | 3 | GPIOR_90 | F16 |
|
||||
| `rf_data[2]` | 4 | GPIOR_91 | F17 |
|
||||
| `rf_data[3]` | 7 | GPIOR_92 | G17 |
|
||||
| `max2771_spi_sclk` | 1 | GPIOR_88_PLLIN1 | G15 |
|
||||
| `max2771_spi_csn` | 8 | GPIOR_93_PLLIN1 | A11 |
|
||||
| `max2771_spi_sdata` | 9 | GPIOR_94 | A13 |
|
||||
|
||||
`rf_clk` must be wired to J13 pin 10. Pin 10 is the PMOD0 header's dedicated
|
||||
3.3 V global-clock input. J13 pin 1 is used as the MAX2771 serial clock output;
|
||||
using it as the raw AFE clock would make Efinity promote normal GPIO routing
|
||||
into a GBUF and issue an extra-clock-insertion-delay warning.
|
||||
|
||||
As on Genesys2 and VCU118, the AX2771 clock is both the raw AFE sample clock
|
||||
and the source of the GPS processing-clock chain. Two Titanium PLLs generate
|
||||
an intermediate 55.5556 MHz clock, then 100 MHz acquisition and 125 MHz
|
||||
tracking clocks. The Rocket fabric uses the independent on-board 100 MHz
|
||||
oscillator.
|
||||
|
||||
PMOD1/J14 carries the sensor SPI, interrupt, and PPS:
|
||||
|
||||
| Signal | PMOD pin | FPGA resource | Package pin |
|
||||
|---|---:|---|---|
|
||||
| `pmod_spi_csn` | 1 | GPIOR_96_CLK13 | B12 |
|
||||
| `pmod_spi_dq[0]` | 2 | GPIOR_97 | C14 |
|
||||
| `pmod_spi_dq[1]` | 3 | GPIOR_98 | C13 |
|
||||
| `pmod_spi_sck` | 4 | GPIOR_99 | C12 |
|
||||
| `pmod_spi_dq[2]` | 7 | GPIOR_100 | D12 |
|
||||
| `pmod_spi_dq[3]` | 8 | GPIOR_101_PLLIN1 | F12 |
|
||||
| `pmod_irq` | 9 | GPIOR_102 | D13 |
|
||||
| `gps_pps` | 10 | GPIOR_103 | E13 |
|
||||
|
||||
The FTDI UART is `/dev/ttyUSB2` on the current Linux enumeration. SW3 is the
|
||||
active-low Rocket reset. JTAG uses Efinix `JTAG_USER1` and the existing Rocket
|
||||
DMI tunnel protocol.
|
||||
|
||||
The Lower flash user-mode connection is internal to the development kit:
|
||||
|
||||
| Signal | FPGA resource | Package pin |
|
||||
|---|---|---|
|
||||
| `flash_csn` | GPIOB_N_38 / SSL_N | A7 |
|
||||
| `flash_sck` | GPIOB_P_39 / CCK | G6 |
|
||||
| `flash_dq[0]` | GPIOB_N_40 / CDI0 | H4 |
|
||||
| `flash_dq[1]` | GPIOB_P_40 / CDI1 | H5 |
|
||||
| `flash_dq[2]` | GPIOB_N_39 / CDI2 | G5 |
|
||||
| `flash_dq[3]` | GPIOB_P_38 / CDI3 | B7 |
|
||||
@@ -0,0 +1,12 @@
|
||||
Board name: Efinix Titanium Ti375 C529 Development Kit
|
||||
Official link: https://www.efinixinc.com/products-devkits-titaniumti375c529.html
|
||||
|
||||
FPGA device: Ti375C529
|
||||
Efinity family: Titanium
|
||||
Efinity timing model: C4
|
||||
|
||||
Initial soft-Rocket flow clocks:
|
||||
SoC/fabric: 100 MHz from the on-board 100 MHz oscillator
|
||||
GPS RF: external AX2771 PMOD0/J13 clock, nominally 16.367981 MHz
|
||||
GPS acquisition: 100 MHz, PLL-derived from the GPS RF clock
|
||||
GPS tracking: 125 MHz, PLL-derived from the GPS RF clock
|
||||
@@ -0,0 +1 @@
|
||||
monitor halt
|
||||
@@ -0,0 +1,13 @@
|
||||
monitor halt
|
||||
monitor reset halt
|
||||
set $mie = 0
|
||||
set $mstatus = 0x6000
|
||||
set {unsigned long long}0x02004000 = 0xffffffffffffffff
|
||||
load
|
||||
set $mie = 0
|
||||
set $mstatus = 0x6000
|
||||
set $sp = (unsigned long)&_stack_top
|
||||
set $pc = _start
|
||||
monitor resume
|
||||
disconnect
|
||||
quit
|
||||
@@ -0,0 +1,62 @@
|
||||
--- a/src/target/riscv/riscv.c
|
||||
+++ b/src/target/riscv/riscv.c
|
||||
@@ -127,6 +127,7 @@
|
||||
|
||||
static bscan_tunnel_type_t bscan_tunnel_type;
|
||||
int bscan_tunnel_ir_width; /* if zero, then tunneling is not present/active */
|
||||
+static int bscan_tunnel_ir_id; /* outer TAP IR used to access the tunnel */
|
||||
|
||||
static const uint8_t bscan_zero[4] = {0};
|
||||
static const uint8_t bscan_one[4] = {1};
|
||||
@@ -451,8 +452,12 @@
|
||||
select_idcode.num_bits = target->tap->ir_length;
|
||||
|
||||
if (bscan_tunnel_ir_width != 0) {
|
||||
- assert(target->tap->ir_length >= 6);
|
||||
- uint32_t ir_user4_raw = 0x23 << (target->tap->ir_length - 6);
|
||||
+ uint32_t ir_user4_raw = bscan_tunnel_ir_id;
|
||||
+ /* Preserve the legacy Xilinx USER4 default when no IR was supplied. */
|
||||
+ if (ir_user4_raw == 0) {
|
||||
+ assert(target->tap->ir_length >= 6);
|
||||
+ ir_user4_raw = 0x23 << (target->tap->ir_length - 6);
|
||||
+ }
|
||||
h_u32_to_le(ir_user4, ir_user4_raw);
|
||||
select_user4.num_bits = target->tap->ir_length;
|
||||
bscan_tunneled_ir_width[0] = bscan_tunnel_ir_width;
|
||||
@@ -2859,6 +2864,21 @@
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
+COMMAND_HANDLER(riscv_set_bscan_tunnel_ir)
|
||||
+{
|
||||
+ int ir_id = 0;
|
||||
+
|
||||
+ if (CMD_ARGC > 1)
|
||||
+ return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
+
|
||||
+ if (CMD_ARGC == 1)
|
||||
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], ir_id);
|
||||
+
|
||||
+ LOG_INFO("Bscan tunnel IR 0x%x selected", ir_id);
|
||||
+ bscan_tunnel_ir_id = ir_id;
|
||||
+ return ERROR_OK;
|
||||
+}
|
||||
+
|
||||
COMMAND_HANDLER(riscv_set_enable_virt2phys)
|
||||
{
|
||||
if (CMD_ARGC != 1) {
|
||||
@@ -3072,6 +3092,14 @@
|
||||
"1: DATA_REGISTER}"
|
||||
},
|
||||
{
|
||||
+ .name = "set_bscan_tunnel_ir",
|
||||
+ .handler = riscv_set_bscan_tunnel_ir,
|
||||
+ .mode = COMMAND_ANY,
|
||||
+ .usage = "[value]",
|
||||
+ .help = "Specify the outer JTAG TAP IR used to access the BSCAN tunnel. "
|
||||
+ "The default remains the Xilinx FPGA USER4 instruction."
|
||||
+ },
|
||||
+ {
|
||||
.name = "set_enable_virt2phys",
|
||||
.handler = riscv_set_enable_virt2phys,
|
||||
.mode = COMMAND_ANY,
|
||||
@@ -0,0 +1,32 @@
|
||||
# Rocket debug through the Ti375 hard TAP, JTAG_USER1, and the project's DMI tunnel.
|
||||
|
||||
adapter driver ftdi
|
||||
ftdi vid_pid 0x0403 0x6011
|
||||
ftdi channel 1
|
||||
ftdi layout_init 0x08 0x0b
|
||||
|
||||
if {![info exists ADAPTER_SPEED]} {
|
||||
set ADAPTER_SPEED 1000
|
||||
}
|
||||
adapter speed $ADAPTER_SPEED
|
||||
|
||||
jtag newtap ti375 fpga -expected-id 0x006A0A79 -irlen 5 -ircapture 0x5 -irmask 0xF
|
||||
target create rocket.cpu riscv -chain-position ti375.fpga -coreid 0
|
||||
|
||||
# The outer Ti375 USER1 instruction is 0x08. The inner tunnel implements the
|
||||
# same 5-bit Rocket DTM IR and framing used by the Xilinx targets.
|
||||
riscv set_ir dtmcs 0x10
|
||||
riscv set_ir dmi 0x11
|
||||
riscv use_bscan_tunnel 5 0
|
||||
# Ti375 requires an OpenOCD build with the upstream configurable outer BSCAN
|
||||
# instruction support. Keep the catch only so older builds produce a readable
|
||||
# diagnostic before their legacy Xilinx-specific BSCAN path rejects this TAP.
|
||||
if {[catch {riscv set_bscan_tunnel_ir 8}]} {
|
||||
echo "OpenOCD lacks 'riscv set_bscan_tunnel_ir'; Ti375 requires that command"
|
||||
}
|
||||
|
||||
riscv set_reset_timeout_sec 10
|
||||
riscv set_command_timeout_sec 10
|
||||
|
||||
init
|
||||
halt
|
||||
@@ -0,0 +1,328 @@
|
||||
# Ti375C529 Efinity flow notes
|
||||
|
||||
This directory contains the Efinity project for the Ti375C529 development kit.
|
||||
The port keeps the same RV64 Rocket/GPS subsystem used by the Genesys2 and
|
||||
VCU118 targets. Only the FPGA shell, clocks, pin constraints, programming flow,
|
||||
and JTAG transport are vendor-specific. The hardened RV32 subsystem in the
|
||||
Ti375 device is not used.
|
||||
|
||||
## What was added
|
||||
|
||||
- Added `ti375c529` to the root FPGA board selection and build targets.
|
||||
- Added Efinity 2025.2 discovery through `EFINITY_HOME`; the current installation
|
||||
is `/tools/efinix/efinity/2025.2`.
|
||||
- Added a generated Ti375 wrapper around `VCU118RocketSystem` so the existing
|
||||
Rocket, DTIM, UART, GPS acquisition, tracking, PPS, and SPI logic is reused.
|
||||
- Added the Efinity XML project, interface script, SDC constraints, PLLs, pin
|
||||
assignments, and JTAG programming target.
|
||||
- Added FTDI UART operation at 460800 baud. On the current host it enumerates as
|
||||
`/dev/ttyUSB2`.
|
||||
- Added host OpenOCD/GDB debug through the Ti375 hard TAP and `JTAG_USER1`.
|
||||
- Added Efinity-specific generated-RTL rewrites for Rocket's store-data path and
|
||||
the GPS acquisition/tracking lookup tables that Efinity 2025.2 mis-elaborates.
|
||||
|
||||
## Clock structure
|
||||
|
||||
The Rocket fabric and GPS processing clocks have separate sources:
|
||||
|
||||
- The on-board 100 MHz oscillator drives the fabric PLL and the 100 MHz Rocket
|
||||
system clock.
|
||||
- AX2771 `rf_clk` enters through the dedicated global-clock input at J13 pin 10
|
||||
/ package pin A12 (`GPIOR_95_CLK12`). It is the raw AFE sample clock and feeds
|
||||
the GPS PLL chain. J13 pins 1, 8, and 9 carry the MAX2771 control bus; pin 1
|
||||
/ G15 is a PLL input, not a dedicated fabric GCLK input.
|
||||
- The GPS PLL chain generates 100 MHz acquisition and 125 MHz tracking clocks.
|
||||
- Acquisition and tracking reset release is gated by the relevant PLL lock
|
||||
signals.
|
||||
|
||||
The four AX2771 data bits use J13 pins 2, 3, 4, and 7, corresponding to package
|
||||
pins G16, F16, F17, and G17. The AX2771 clock must be jumpered to J13 pin 10.
|
||||
|
||||
## Efinity synthesis adaptation
|
||||
|
||||
This adaptation does **not** modify Rocket's native/upstream Chisel sources or
|
||||
the shared GPS SystemVerilog. The normal Chisel and `firtool` stages run first
|
||||
and emit SystemVerilog into `hardware/generated/ti375c529-soc-verilog/`.
|
||||
Immediately afterward,
|
||||
`targets/fpga/ti375c529/tools/prepare_efinity_rtl.py` patches the generated
|
||||
Ti375 `Rocket.sv` and writes Efinity-only GPS replacements under
|
||||
`targets/fpga/ti375c529/out/build/generated/gps_efinity/`. The Ti375 source-list
|
||||
recipe substitutes those generated copies for exactly these three shared GPS
|
||||
files:
|
||||
|
||||
- `acq_src/acq_nco_carr.sv`
|
||||
- `trck_src/NCO_carr.sv`
|
||||
- `acq_src/twiddle_ram.sv`
|
||||
|
||||
All other GPS RTL remains shared. Efinity consumes the replacements; Genesys2
|
||||
and VCU118 continue to consume the original GPS files. Deleting either
|
||||
generated directory and running `make FPGA_BOARD=ti375c529 fpga-rtl` repeats
|
||||
the same deterministic generation and substitution.
|
||||
|
||||
### Rocket store-data path
|
||||
|
||||
The CIRCT-generated `Rocket.sv` contains this block-local packed temporary for
|
||||
store-data byte-lane replication:
|
||||
|
||||
```systemverilog
|
||||
automatic logic [3:0][63:0] _GEN_24 = ...;
|
||||
mem_reg_rs2 <= _GEN_24[ex_reg_mem_size];
|
||||
```
|
||||
|
||||
Vivado synthesizes this construct correctly. Efinity 2025.2 reports `_GEN_24`
|
||||
as `VDB-1002: net does not have a driver`, leaving Rocket store data at zero.
|
||||
This initially looked like a Debug Module failure because abstract GPR/CSR
|
||||
reads execute a hart instruction that stores the result into Debug Module data
|
||||
registers. DMI was working, but OpenOCD received zeros and reported the
|
||||
misleading result `misa=0`.
|
||||
|
||||
`../../tools/prepare_efinity_rtl.py` replaces only that generated expression
|
||||
with an equivalent explicit `case` for byte, half-word, word, and double-word
|
||||
stores. The script runs automatically after `firtool`; generated RTL is not
|
||||
edited by hand. After the rewrite, the Rocket `VDB-1002` warning disappears
|
||||
from the current synthesis run. `ti375c529_rocket.warn.log` is reused by
|
||||
Efinity and can contain entries from older runs, so the generated source and
|
||||
the final warning block should be checked together.
|
||||
|
||||
The same Efinity limitation also affected the four-entry packed atomic-operation
|
||||
LUT emitted into generated `TLAtomicAutomata_pbus.sv` and
|
||||
`TLAtomicAutomata_cbus.sv`. Those `_GEN_4`/`_GEN_13` temporaries select the
|
||||
TileLink atomic ALU operation; they are unrelated to GPS acquisition but could
|
||||
break software atomics. The post-generation script rewrites both to an
|
||||
equivalent four-way `case`. Questa confirmed all four index mappings, and their
|
||||
`VDB-1002` diagnostics disappear from the current single-run `map.out`.
|
||||
|
||||
The exact paths are:
|
||||
|
||||
- Generated failing/fixed source:
|
||||
`hardware/generated/ti375c529-soc-verilog/Rocket.sv`
|
||||
- Generated TileLink atomic sources:
|
||||
`hardware/generated/ti375c529-soc-verilog/TLAtomicAutomata_pbus.sv` and
|
||||
`hardware/generated/ti375c529-soc-verilog/TLAtomicAutomata_cbus.sv`
|
||||
- Efinity synthesis warning log:
|
||||
`targets/fpga/ti375c529/flow/efinity/outflow/ti375c529_rocket.warn.log`
|
||||
- Deterministic repair:
|
||||
`targets/fpga/ti375c529/tools/prepare_efinity_rtl.py`
|
||||
- Invocation point:
|
||||
`targets/fpga/ti375c529/Makefile`, in the `rtl` recipe immediately after
|
||||
`firtool`
|
||||
|
||||
### GPS lookup-table paths
|
||||
|
||||
The original acquisition carrier NCO is
|
||||
`hardware/external/gps/rtl/acq_src/acq_nco_carr.sv`. It initializes the
|
||||
frequency and pull-in arrays with whole-package-array assignments and builds
|
||||
its sine table in an `initial` loop using `$sin`. Efinity 2025.2 reports the
|
||||
loop variable as never assigned and the three arrays as undriven. Stand-alone
|
||||
post-map comparison confirmed that this is functional, not cosmetic: the
|
||||
unpatched Efinity netlist produced incorrect sine/cosine samples in all 18,040
|
||||
tested production-parameter cycles.
|
||||
|
||||
The generated Ti375 copy replaces the frequency, pull-in, sine, and cosine
|
||||
reads with constant functions generated from `definitions.sv`. Questa compared
|
||||
41 frequency bins, 11 pull-in bins, and 40 cycles per combination: all 18,040
|
||||
RTL samples and all 18,040 Efinity post-map samples matched the original RTL.
|
||||
The current full-project synthesis no longer reports the acquisition arrays or
|
||||
its `$sin` loop as undriven.
|
||||
|
||||
The separate tracking carrier NCO is
|
||||
`hardware/external/gps/rtl/trck_src/NCO_carr.sv`. Its
|
||||
`sinwav_lut = TRCK_SINWAV_LUT` package-array initializer triggers the same
|
||||
Efinity `VDB-1002` behavior. The Ti375 copy uses an exact 128-entry constant
|
||||
function generated from `TRCK_SINWAV_LUT`. Questa matched every table entry at
|
||||
RTL and then matched 5,000 Efinity post-map cycles while visiting all 128
|
||||
addresses.
|
||||
|
||||
The acquisition FFT twiddle source is
|
||||
`hardware/external/gps/rtl/acq_src/twiddle_ram.sv`. Its whole-array
|
||||
`COS_ROM_ARRAY` and `SIN_ROM_ARRAY` assignments are converted only for Ti375 to
|
||||
two generated, exactly 15-bit-wide `$readmemb` files. Efinity infers 30
|
||||
`EFX_RAM10` blocks with embedded INIT data. Efinity still emits its generic
|
||||
`sin_rom/cos_rom does not have a driver` elaboration warning for this recognized
|
||||
ROM form, but this one is demonstrably benign: Questa matched all 8,192 RTL
|
||||
addresses and all 8,192 addresses in the Efinity post-map RAM netlist. Check
|
||||
the current `ti375c529_rocket.map.out` for a single run; the `.warn.log` and
|
||||
`.info.log` files retain records from older builds and can otherwise make fixed
|
||||
source paths look current.
|
||||
|
||||
## JTAG and OpenOCD
|
||||
|
||||
Ti375 and the Xilinx boards expose the same inner Rocket DTM protocol, but the
|
||||
outer FPGA TAP is different:
|
||||
|
||||
| Item | Xilinx flow | Ti375 flow |
|
||||
|---|---|---|
|
||||
| Outer TAP IR width | Xilinx-specific | 5 bits |
|
||||
| User instruction | legacy USER4 handling | `JTAG_USER1 = 0x08` |
|
||||
| Inner DTM IR width | 5 bits | 5 bits |
|
||||
| DTMCS / DMI IR | `0x10` / `0x11` | `0x10` / `0x11` |
|
||||
|
||||
The host OpenOCD must therefore implement:
|
||||
|
||||
```text
|
||||
riscv set_bscan_tunnel_ir 8
|
||||
```
|
||||
|
||||
A fixed OpenOCD pathname is **not** required. The target Makefile evaluates
|
||||
`command -v openocd`, so the first compatible patched host binary in `PATH` is
|
||||
used. Another compatible build can be selected without changing files:
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-debug-openocd OPENOCD=/path/to/openocd
|
||||
```
|
||||
|
||||
The original `/usr/local/bin/openocd` 0.12 build assumes the Xilinx USER4
|
||||
instruction and asserts that the outer TAP IR is at least six bits. It cannot
|
||||
drive the Ti375 5-bit TAP unchanged. `../debug/openocd-0.12-ti375-bscan.patch`
|
||||
adds the configurable outer instruction to OpenOCD 0.12. The OpenOCD shipped
|
||||
with Efinity is not required by this flow.
|
||||
|
||||
Apply the patch from a clean OpenOCD 0.12 source tree before configuring and
|
||||
building the host tool:
|
||||
|
||||
```bash
|
||||
git apply --check /path/to/gps/targets/fpga/ti375c529/flow/debug/openocd-0.12-ti375-bscan.patch
|
||||
git apply /path/to/gps/targets/fpga/ti375c529/flow/debug/openocd-0.12-ti375-bscan.patch
|
||||
```
|
||||
|
||||
The selected paths can be checked with:
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-config
|
||||
command -v openocd
|
||||
strings "$(command -v openocd)" | grep set_bscan_tunnel_ir
|
||||
```
|
||||
|
||||
The line `Disabling abstract command reads/writes from CSRs` is informational,
|
||||
not a failure. OpenOCD falls back to Rocket's Program Buffer for CSR access.
|
||||
|
||||
## GDB selection
|
||||
|
||||
Software is still compiled with the medany toolchain. That toolchain does not
|
||||
contain GDB, so the debug target deliberately selects:
|
||||
|
||||
```text
|
||||
/tools/toolchain/bin/riscv64-unknown-elf-gdb
|
||||
```
|
||||
|
||||
This can also be overridden with `GDB=/path/to/riscv64-unknown-elf-gdb`.
|
||||
|
||||
## Build, program, and debug
|
||||
|
||||
From the repository root:
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-config
|
||||
make FPGA_BOARD=ti375c529 fpga-rtl
|
||||
make FPGA_BOARD=ti375c529 fpga-bitstream
|
||||
make FPGA_BOARD=ti375c529 fpga-program
|
||||
```
|
||||
|
||||
Start the host OpenOCD server in one terminal:
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-debug-openocd
|
||||
```
|
||||
|
||||
Load and run an application, then monitor UART, from another terminal:
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-debug-load APP=hello_uart
|
||||
make FPGA_BOARD=ti375c529 fpga-uart
|
||||
```
|
||||
|
||||
## Persistent Lower-flash boot
|
||||
|
||||
The kit has Lower and Upper 512-Mbit SPI NOR devices. This port intentionally
|
||||
uses one MCS-like combined layout in the Lower ISSI IS25WP512 because Efinity's
|
||||
command-line `jtag_bridge` mode directly addresses that flash:
|
||||
|
||||
| Offset | Image |
|
||||
|---:|---|
|
||||
| `0x00000000` | Compressed, active-x1 FPGA configuration |
|
||||
| `0x00800000` | Rocket boot header followed by the application payload |
|
||||
| `0x03FC0000` | Persistent navigation context (two 64-KiB sectors) |
|
||||
| `0x03FE0000` | Persistent ephemeris cache (two 64-KiB sectors) |
|
||||
|
||||
The application offset is 64-KiB-sector aligned and leaves roughly 3.2 MB
|
||||
between the current 5,190,596-byte configuration and the firmware region.
|
||||
`spi_low_power_mode=off` is embedded in the configuration so the Lower flash
|
||||
stays available when Rocket enters user mode.
|
||||
|
||||
Rocket's existing MMIO SPI controller is connected to the configuration pins
|
||||
after configuration completes:
|
||||
|
||||
```text
|
||||
spi_sck/spi_csn/spi_dq_* -> A7/G6/H4/H5/G5/B7 -> Lower flash U47
|
||||
```
|
||||
|
||||
Generate the configuration, per-application, and combined raw Efinity HEX
|
||||
files:
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-bitstream
|
||||
make FPGA_BOARD=ti375c529 fpga-mcs APP=hello_uart
|
||||
```
|
||||
|
||||
Outputs are:
|
||||
|
||||
- `out/bitstream/ti375c529_rocket.hex`: configuration region
|
||||
- `out/flash/regions/app.hex`: application region
|
||||
- `out/flash/ti375c529_rocket.hex`: combined image
|
||||
- `out/flash/ti375c529_rocket.json`: offsets, sizes, and SHA-256 manifest
|
||||
|
||||
Program only the application, only the configuration, or the combined image:
|
||||
|
||||
```bash
|
||||
make FPGA_BOARD=ti375c529 fpga-flash-app APP=hello_uart
|
||||
make FPGA_BOARD=ti375c529 fpga-flash-bitstream
|
||||
make FPGA_BOARD=ti375c529 fpga-flash-mcs APP=hello_uart
|
||||
```
|
||||
|
||||
The Makefile first loads Efinity's device-matched bridge
|
||||
`/tools/efinix/efinity/2025.2/pgm/fli/titanium/u006A0A79.bit`, then uses
|
||||
`jtag_bridge` programming with on-chip verification. A fixed Efinity install
|
||||
path is not required; `FLASH_LOADER` is derived from `EFINITY_HOME` and can be
|
||||
overridden.
|
||||
|
||||
After bridge programming, the FPGA still contains the bridge design. Power
|
||||
cycle the kit for a true active-flash boot, or use `fpga-program` to load the
|
||||
normal design immediately and test the BootROM/application flash path.
|
||||
|
||||
## On-board verification
|
||||
|
||||
The completed flow was checked on the connected Ti375C529 kit with AX2771
|
||||
attached:
|
||||
|
||||
- Efinity interface, map, PNR, and programming-image stages passed.
|
||||
- Final patched timing passed with WNS `+0.101 ns` and WHS `+0.021 ns`.
|
||||
- The Ti375 JTAG IDCODE was read as `0x006a0a79`.
|
||||
- OpenOCD found one RV64 hart and read `misa=0x800000000080112d`.
|
||||
- A raw Program Buffer GPR/store test returned `0x5a` through DMI.
|
||||
- `/tools/toolchain/bin/riscv64-unknown-elf-gdb` loaded 40,880 bytes into DTIM.
|
||||
- `hello_uart` printed the expected Rocket/DTIM/UART messages at 460800 baud.
|
||||
- The persistent image passed with setup slack `+0.094 ns` and hold slack
|
||||
`+0.021 ns`.
|
||||
- The Lower flash was detected as ISSI IS25WP512, JEDEC `0x9d701a`.
|
||||
- The combined 8,429,552-byte HEX completed erase, write, readback, and verify.
|
||||
- BootROM read the payload at `0x00800040`, verified CRC `0xed3bbdf5`, copied
|
||||
40,880 bytes into DTIM, and ran `hello_uart` without GDB.
|
||||
- A full board power cycle then configured Ti375 from Lower flash. Host OpenOCD
|
||||
found the RV64 hart through `JTAG_USER1`; its PC was at
|
||||
`0x8000017e <_exit>` after `hello_uart` returned, and GDB `compare-sections`
|
||||
matched the complete ELF `.text` range in DTIM. This confirms cold boot of
|
||||
both hardware and software without a volatile JTAG/GDB load.
|
||||
|
||||
## Relevant files
|
||||
|
||||
- `ti375c529_rocket.xml`: Efinity project definition.
|
||||
- `ti375c529_rocket.isf`: generated/copy of the checked-in interface script.
|
||||
- `../../../../../hardware/fpga/ti375c529/constraints/`: source interface and SDC
|
||||
constraints.
|
||||
- `../../tools/gen_ti375c529_wrapper.py`: Efinix board-shell generator.
|
||||
- `../../tools/prepare_efinity_rtl.py`: deterministic Rocket and GPS
|
||||
Efinity-only RTL generation/rewrite.
|
||||
- `../../tools/make_flash_hex.py`: validated Efinity raw-HEX image builder.
|
||||
- `../debug/openocd_ti375c529_bscan.cfg`: Ti375 hard-TAP/OpenOCD configuration.
|
||||
- `../debug/openocd-0.12-ti375-bscan.patch`: host OpenOCD 0.12 compatibility
|
||||
patch.
|
||||
@@ -0,0 +1,71 @@
|
||||
<efx:project xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="ti375c529_rocket" description="RV64 Rocket and GPS on the Ti375C529 development kit" sw_version="2025.2.288.2.10" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd" last_run_state="pass" last_run_flow="bitstream" last_change="1785370142" config_result_in_sync="sync" design_ood="sync" place_ood="sync" route_ood="sync">
|
||||
<efx:device_info>
|
||||
<efx:family name="Titanium" />
|
||||
<efx:device name="Ti375C529" />
|
||||
<efx:timing_model name="C4" />
|
||||
</efx:device_info>
|
||||
<efx:design_info def_veri_version="verilog_2k" def_vhdl_version="vhdl_2008" unified_flow="true">
|
||||
<efx:top_module name="ti375c529_rocket_top" />
|
||||
<efx:design_file name="../../out/build/generated/ti375c529_rocket_top.sv" version="default" library="default" />
|
||||
<efx:design_file name="../../out/build/efinity_sources.f" version="na" library="default" />
|
||||
<efx:top_vhdl_arch name="" />
|
||||
</efx:design_info>
|
||||
<efx:constraint_info>
|
||||
<efx:sdc_file name="../../../../../hardware/fpga/ti375c529/constraints/ti375c529_rocket.sdc" />
|
||||
<efx:sdc_file name="outflow/ti375c529_rocket.pt.sdc" />
|
||||
<efx:sdc_file name="../../../../../hardware/fpga/ti375c529/constraints/ti375c529_rocket_clock_groups.sdc" />
|
||||
<efx:inter_file name="" />
|
||||
</efx:constraint_info>
|
||||
<efx:isf_info>
|
||||
<efx:isf_file name="ti375c529_rocket.isf" />
|
||||
</efx:isf_info>
|
||||
<efx:sim_info />
|
||||
<efx:misc_info />
|
||||
<efx:ooc_info />
|
||||
<efx:ip_info />
|
||||
<efx:synthesis tool_name="efx_map">
|
||||
<efx:param name="work_dir" value="../../out/build/work_syn" value_type="e_string" />
|
||||
<efx:param name="write_efx_verilog" value="on" value_type="e_bool" />
|
||||
<efx:param name="blackbox-error" value="1" value_type="e_option" />
|
||||
<efx:param name="hdl-compile-unit" value="1" value_type="e_option" />
|
||||
<efx:param name="infer-clk-enable" value="3" value_type="e_option" />
|
||||
<efx:param name="infer-sync-set-reset" value="1" value_type="e_option" />
|
||||
<efx:param name="mode" value="speed" value_type="e_option" />
|
||||
<efx:param name="retiming" value="1" value_type="e_option" />
|
||||
<efx:param name="seq_opt" value="1" value_type="e_option" />
|
||||
<efx:param name="use-logic-for-small-mem" value="64" value_type="e_integer" />
|
||||
<efx:param name="use-logic-for-small-rom" value="64" value_type="e_integer" />
|
||||
<efx:param name="max_threads" value="-1" value_type="e_integer" />
|
||||
<efx:param name="include" value="../../../../../hardware/external/gps/rtl/trck_src/pulp_fifo" value_type="e_string" />
|
||||
<efx:param name="include" value="../../out/build/generated/gps_efinity" value_type="e_string" />
|
||||
</efx:synthesis>
|
||||
<efx:place_and_route tool_name="efx_pnr">
|
||||
<efx:param name="work_dir" value="work_pnr" value_type="e_string" />
|
||||
<efx:param name="seed" value="2" value_type="e_integer" />
|
||||
<efx:param name="placer_effort_level" value="2" value_type="e_option" />
|
||||
<efx:param name="max_threads" value="-1" value_type="e_integer" />
|
||||
<efx:param name="beneficial_skew" value="on" value_type="e_option" />
|
||||
<efx:param name="print_critical_path" value="10" value_type="e_integer" />
|
||||
</efx:place_and_route>
|
||||
<efx:bitstream_generation tool_name="efx_pgm">
|
||||
<efx:param name="mode" value="active" value_type="e_option" />
|
||||
<efx:param name="width" value="1" value_type="e_option" />
|
||||
<efx:param name="enable_roms" value="smart" value_type="e_option" />
|
||||
<efx:param name="bitstream_compression" value="on" value_type="e_bool" />
|
||||
<efx:param name="spi_low_power_mode" value="off" value_type="e_bool" />
|
||||
<efx:param name="release_tri_then_reset" value="on" value_type="e_bool" />
|
||||
<efx:param name="generate_bit" value="on" value_type="e_bool" />
|
||||
<efx:param name="generate_hex" value="on" value_type="e_bool" />
|
||||
<efx:param name="jtag_usercode" value="0x52564B54" value_type="e_string" />
|
||||
</efx:bitstream_generation>
|
||||
<efx:debugger>
|
||||
<efx:param name="work_dir" value="../../out/build/work_dbg" value_type="e_string" />
|
||||
<efx:param name="auto_instantiation" value="off" value_type="e_bool" />
|
||||
<efx:param name="profile" value="NONE" value_type="e_string" />
|
||||
</efx:debugger>
|
||||
<efx:security>
|
||||
<efx:param name="enable_bitstream_encrypt" value="off" value_type="e_bool" />
|
||||
<efx:param name="enable_bitstream_auth" value="off" value_type="e_bool" />
|
||||
<efx:param name="randomize_iv_value" value="on" value_type="e_bool" />
|
||||
</efx:security>
|
||||
</efx:project>
|
||||
@@ -0,0 +1,276 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate the Efinix Ti375 board shell around the shared Rocket subsystem."""
|
||||
|
||||
import argparse
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def width_bits(width):
|
||||
if not width:
|
||||
return 1
|
||||
match = re.fullmatch(r"\[(\d+):(\d+)\]", width.strip())
|
||||
if not match:
|
||||
raise ValueError(f"unsupported width: {width}")
|
||||
return abs(int(match.group(1)) - int(match.group(2))) + 1
|
||||
|
||||
|
||||
def parse_ports(verilog_path):
|
||||
text = Path(verilog_path).read_text()
|
||||
module_name = Path(verilog_path).stem
|
||||
start = text.index(f"module {module_name}(")
|
||||
end = text.index(");", start)
|
||||
header = re.sub(r"//.*", "", text[start:end])
|
||||
pieces = re.split(r"\b(input|output)\b", header)[1:]
|
||||
ports = []
|
||||
for direction, body in zip(pieces[0::2], pieces[1::2]):
|
||||
body = body.replace("\n", " ")
|
||||
body = re.split(r"\b(input|output)\b", body)[0]
|
||||
default_width = ""
|
||||
width_match = re.match(r"\s*(\[[^\]]+\])\s*(.*)", body)
|
||||
if width_match:
|
||||
default_width = width_match.group(1)
|
||||
rest = width_match.group(2)
|
||||
else:
|
||||
rest = body
|
||||
for item in rest.split(","):
|
||||
item = item.strip()
|
||||
if not item:
|
||||
continue
|
||||
item_match = re.match(r"(\[[^\]]+\])\s*(\w+)$", item)
|
||||
if item_match:
|
||||
width, name = item_match.groups()
|
||||
else:
|
||||
width = default_width
|
||||
name = item.split()[-1]
|
||||
if re.fullmatch(r"\w+", name):
|
||||
ports.append((direction, width, name))
|
||||
return ports
|
||||
|
||||
|
||||
def const_for(width):
|
||||
bits = width_bits(width)
|
||||
return "1'b0" if bits == 1 else f"{bits}'d0"
|
||||
|
||||
|
||||
def is_clock(name):
|
||||
return name.endswith("_clock") or name == "debug_clock"
|
||||
|
||||
|
||||
def is_reset(name):
|
||||
return name.endswith("_reset") or name == "debug_reset"
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--rocket-top", required=True)
|
||||
parser.add_argument("--out", required=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
ports = parse_ports(args.rocket_top)
|
||||
port_by_name = {name: (direction, width) for direction, width, name in ports}
|
||||
|
||||
required = {
|
||||
"uart_rxd", "uart_txd",
|
||||
"spi_sck", "spi_csn", "spi_dq_i", "spi_dq_o", "spi_dq_oe",
|
||||
"pmod_spi_sck", "pmod_spi_csn",
|
||||
"pmod_spi_dq_i", "pmod_spi_dq_o", "pmod_spi_dq_oe",
|
||||
"max2771_spi_sclk", "max2771_spi_csn",
|
||||
"max2771_spi_sdata_i", "max2771_spi_sdata_o",
|
||||
"max2771_spi_sdata_oe",
|
||||
"pmod_irq", "gps_acq_clk", "gps_trck_clk",
|
||||
"gps_rf_clk", "gps_rf_data", "gps_pps",
|
||||
}
|
||||
missing = sorted(required - port_by_name.keys())
|
||||
if missing:
|
||||
raise RuntimeError(f"Rocket top is missing required Ti375 ports: {', '.join(missing)}")
|
||||
|
||||
passthrough = {
|
||||
"pmod_spi_sck", "pmod_spi_csn",
|
||||
"max2771_spi_sclk", "max2771_spi_csn",
|
||||
"pmod_irq", "gps_pps",
|
||||
}
|
||||
|
||||
def decl(width, name):
|
||||
return f" wire {width + ' ' if width else ''}{name};"
|
||||
|
||||
assigns = []
|
||||
for direction, width, name in ports:
|
||||
if direction != "input" or name in passthrough:
|
||||
continue
|
||||
if name.startswith("debug_clockeddmi_dmi_req"):
|
||||
continue
|
||||
if name in {
|
||||
"debug_clockeddmi_dmi_resp_ready",
|
||||
"debug_clockeddmi_dmiClock",
|
||||
"debug_clockeddmi_dmiReset",
|
||||
}:
|
||||
continue
|
||||
if name == "resetctrl_hartIsInReset_0":
|
||||
value = "soc_reset"
|
||||
elif name == "debug_reset":
|
||||
value = "fabric_reset"
|
||||
elif is_reset(name):
|
||||
value = "soc_reset"
|
||||
elif name == "gps_acq_clk":
|
||||
value = "gps_acq_clk_gen"
|
||||
elif name == "gps_trck_clk":
|
||||
value = "gps_trck_clk_gen"
|
||||
elif name in {"gps_rf_clk", "gps_afe_clk"}:
|
||||
value = "rf_clk"
|
||||
elif name == "gps_rf_data":
|
||||
value = "rf_data"
|
||||
elif is_clock(name):
|
||||
value = "fabric_clk"
|
||||
elif name == "debug_dmactiveAck":
|
||||
value = "debug_dmactive"
|
||||
elif name == "uart_rxd":
|
||||
value = "uart_rx"
|
||||
elif name == "spi_dq_i":
|
||||
value = "flash_dq_IN"
|
||||
elif name == "pmod_spi_dq_i":
|
||||
value = "pmod_spi_dq_IN"
|
||||
elif name == "max2771_spi_sdata_i":
|
||||
value = "max2771_spi_sdata_IN"
|
||||
elif name == "interrupts":
|
||||
value = "2'b00"
|
||||
else:
|
||||
value = const_for(width)
|
||||
assigns.append(f" assign {name} = {value};")
|
||||
|
||||
port_map = ",\n".join(f" .{name}({name})" for _, _, name in ports)
|
||||
internal_decls = "\n".join(
|
||||
decl(width, name) for _, width, name in ports if name not in passthrough
|
||||
)
|
||||
|
||||
content = f"""`timescale 1ns/1ps
|
||||
|
||||
module ti375c529_rocket_top (
|
||||
(* syn_peri_port = 0 *) input wire fabric_clk,
|
||||
(* syn_peri_port = 0 *) input wire fabric_pll_locked,
|
||||
(* syn_peri_port = 0 *) input wire board_clk_100,
|
||||
(* syn_peri_port = 0 *) input wire gps_ref_clk_gen,
|
||||
(* syn_peri_port = 0 *) input wire gps_acq_clk_gen,
|
||||
(* syn_peri_port = 0 *) input wire gps_trck_clk_gen,
|
||||
(* syn_peri_port = 0 *) input wire gps_domain_feedback,
|
||||
(* syn_peri_port = 0 *) input wire gps_ref_pll_locked,
|
||||
(* syn_peri_port = 0 *) input wire gps_domain_pll_locked,
|
||||
(* syn_peri_port = 0 *) input wire reset_n,
|
||||
(* syn_peri_port = 0 *) input wire uart_rx,
|
||||
(* syn_peri_port = 0 *) output wire uart_tx,
|
||||
(* syn_peri_port = 0 *) output wire flash_sck,
|
||||
(* syn_peri_port = 0 *) output wire flash_csn,
|
||||
(* syn_peri_port = 0 *) input wire [3:0] flash_dq_IN,
|
||||
(* syn_peri_port = 0 *) output wire [3:0] flash_dq_OUT,
|
||||
(* syn_peri_port = 0 *) output wire [3:0] flash_dq_OE,
|
||||
(* syn_peri_port = 0 *) input wire rf_clk,
|
||||
(* syn_peri_port = 0 *) input wire [3:0] rf_data,
|
||||
(* syn_peri_port = 0 *) output wire pmod_spi_sck,
|
||||
(* syn_peri_port = 0 *) output wire pmod_spi_csn,
|
||||
(* syn_peri_port = 0 *) input wire [3:0] pmod_spi_dq_IN,
|
||||
(* syn_peri_port = 0 *) output wire [3:0] pmod_spi_dq_OUT,
|
||||
(* syn_peri_port = 0 *) output wire [3:0] pmod_spi_dq_OE,
|
||||
(* syn_peri_port = 0 *) input wire pmod_irq,
|
||||
(* syn_peri_port = 0 *) output wire max2771_spi_sclk,
|
||||
(* syn_peri_port = 0 *) output wire max2771_spi_csn,
|
||||
(* syn_peri_port = 0 *) input wire max2771_spi_sdata_IN,
|
||||
(* syn_peri_port = 0 *) output wire max2771_spi_sdata_OUT,
|
||||
(* syn_peri_port = 0 *) output wire max2771_spi_sdata_OE,
|
||||
(* syn_peri_port = 0 *) output wire gps_pps,
|
||||
(* syn_peri_port = 0 *) input wire jtag_CAPTURE,
|
||||
(* syn_peri_port = 0 *) input wire jtag_DRCK,
|
||||
(* syn_peri_port = 0 *) input wire jtag_RESET,
|
||||
(* syn_peri_port = 0 *) input wire jtag_RUNTEST,
|
||||
(* syn_peri_port = 0 *) input wire jtag_SEL,
|
||||
(* syn_peri_port = 0 *) input wire jtag_SHIFT,
|
||||
(* syn_peri_port = 0 *) input wire jtag_TCK,
|
||||
(* syn_peri_port = 0 *) input wire jtag_TDI,
|
||||
(* syn_peri_port = 0 *) input wire jtag_TMS,
|
||||
(* syn_peri_port = 0 *) input wire jtag_UPDATE,
|
||||
(* syn_peri_port = 0 *) output wire jtag_TDO,
|
||||
(* syn_peri_port = 0 *) output wire [4:0] led
|
||||
);
|
||||
wire gps_clock_locked = gps_ref_pll_locked & gps_domain_pll_locked;
|
||||
wire pll_ready_async = fabric_pll_locked & gps_clock_locked & reset_n;
|
||||
(* async_reg = "true" *) reg [2:0] pll_ready_sync = 3'b000;
|
||||
reg [15:0] reset_shift = 16'hffff;
|
||||
|
||||
always @(posedge fabric_clk) begin
|
||||
pll_ready_sync <= {{pll_ready_sync[1:0], pll_ready_async}};
|
||||
if (!pll_ready_sync[2])
|
||||
reset_shift <= 16'hffff;
|
||||
else
|
||||
reset_shift <= {{reset_shift[14:0], 1'b0}};
|
||||
end
|
||||
|
||||
wire fabric_reset = reset_shift[15];
|
||||
reg [31:0] heartbeat = 32'd0;
|
||||
always @(posedge fabric_clk) begin
|
||||
if (fabric_reset)
|
||||
heartbeat <= 32'd0;
|
||||
else
|
||||
heartbeat <= heartbeat + 32'd1;
|
||||
end
|
||||
|
||||
{internal_decls}
|
||||
|
||||
wire soc_reset = fabric_reset | debug_ndreset;
|
||||
|
||||
rocket_bscan_dmi_tunnel u_rocket_dmi_tunnel (
|
||||
.tck(jtag_TCK),
|
||||
.reset(fabric_reset | jtag_RESET),
|
||||
.bscan_capture(jtag_CAPTURE),
|
||||
.bscan_sel(jtag_SEL),
|
||||
.bscan_shift(jtag_SHIFT),
|
||||
.bscan_tdi(jtag_TDI),
|
||||
.bscan_update(jtag_UPDATE),
|
||||
.bscan_tdo(jtag_TDO),
|
||||
.dmi_clock(debug_clockeddmi_dmiClock),
|
||||
.dmi_reset(debug_clockeddmi_dmiReset),
|
||||
.dmi_req_ready(debug_clockeddmi_dmi_req_ready),
|
||||
.dmi_req_valid(debug_clockeddmi_dmi_req_valid),
|
||||
.dmi_req_addr(debug_clockeddmi_dmi_req_bits_addr),
|
||||
.dmi_req_data(debug_clockeddmi_dmi_req_bits_data),
|
||||
.dmi_req_op(debug_clockeddmi_dmi_req_bits_op),
|
||||
.dmi_resp_ready(debug_clockeddmi_dmi_resp_ready),
|
||||
.dmi_resp_valid(debug_clockeddmi_dmi_resp_valid),
|
||||
.dmi_resp_data(debug_clockeddmi_dmi_resp_bits_data),
|
||||
.dmi_resp_resp(debug_clockeddmi_dmi_resp_bits_resp)
|
||||
);
|
||||
|
||||
assign pmod_spi_dq_OUT = pmod_spi_dq_o;
|
||||
assign pmod_spi_dq_OE = pmod_spi_dq_oe;
|
||||
assign max2771_spi_sdata_OUT = max2771_spi_sdata_o;
|
||||
assign max2771_spi_sdata_OE = max2771_spi_sdata_oe;
|
||||
assign flash_sck = spi_sck;
|
||||
assign flash_csn = spi_csn;
|
||||
assign flash_dq_OUT = spi_dq_o;
|
||||
assign flash_dq_OE = spi_dq_oe;
|
||||
assign uart_tx = uart_txd;
|
||||
|
||||
// The kit LEDs are active-low. Show heartbeat, PLL locks, reset release,
|
||||
// and debug-module activity from LED13 down to LED9.
|
||||
assign led = ~{{heartbeat[25], gps_clock_locked, fabric_pll_locked,
|
||||
~fabric_reset, debug_dmactive}};
|
||||
|
||||
{chr(10).join(assigns)}
|
||||
|
||||
(* syn_preserve = 1 *)
|
||||
{Path(args.rocket_top).stem} u_rocket (
|
||||
{port_map}
|
||||
);
|
||||
|
||||
// These hard-TAP outputs are intentionally unused by the DMI framing logic.
|
||||
wire _unused_hard_signals = jtag_DRCK ^ jtag_RUNTEST ^ jtag_TMS ^
|
||||
board_clk_100 ^ gps_ref_clk_gen ^
|
||||
gps_domain_feedback;
|
||||
endmodule
|
||||
"""
|
||||
|
||||
output = Path(args.out)
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
output.write_text(content)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build Efinity raw-HEX images for Ti375C529 persistent Rocket boot."""
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
HEX_BYTE = re.compile(r"[0-9a-fA-F]{2}")
|
||||
|
||||
|
||||
def parse_int(value):
|
||||
return int(value, 0)
|
||||
|
||||
|
||||
def read_raw_hex(path):
|
||||
data = bytearray()
|
||||
with path.open() as source:
|
||||
for line_number, line in enumerate(source, 1):
|
||||
value = line.strip()
|
||||
if not HEX_BYTE.fullmatch(value):
|
||||
raise SystemExit(
|
||||
f"{path}:{line_number}: expected one hexadecimal byte per line"
|
||||
)
|
||||
data.append(int(value, 16))
|
||||
return bytes(data)
|
||||
|
||||
|
||||
def write_raw_hex(path, chunks):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with path.open("w") as output:
|
||||
for chunk in chunks:
|
||||
for value in chunk:
|
||||
output.write(f"{value:02X}\n")
|
||||
|
||||
|
||||
def sha256(data):
|
||||
return hashlib.sha256(data).hexdigest()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Combine an Efinity configuration HEX and Rocket app image"
|
||||
)
|
||||
parser.add_argument("--config-hex", type=Path, required=True)
|
||||
parser.add_argument("--app-bin", type=Path, required=True)
|
||||
parser.add_argument("--app-offset", type=parse_int, required=True)
|
||||
parser.add_argument("--flash-size", type=parse_int, default=0x04000000)
|
||||
parser.add_argument("--nav-context-offset", type=parse_int, required=True)
|
||||
parser.add_argument("--ephemeris-offset", type=parse_int, required=True)
|
||||
parser.add_argument("--combined-hex", type=Path, required=True)
|
||||
parser.add_argument("--app-hex", type=Path, required=True)
|
||||
parser.add_argument("--manifest", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
config = read_raw_hex(args.config_hex)
|
||||
app = args.app_bin.read_bytes()
|
||||
app_end = args.app_offset + len(app)
|
||||
|
||||
if args.app_offset & 0xFFFF:
|
||||
raise SystemExit("application offset must be aligned to a 64-KiB sector")
|
||||
if len(config) > args.app_offset:
|
||||
raise SystemExit(
|
||||
f"configuration image (0x{len(config):x} bytes) overlaps application "
|
||||
f"at 0x{args.app_offset:x}"
|
||||
)
|
||||
if app_end > args.flash_size:
|
||||
raise SystemExit(
|
||||
f"application ends at 0x{app_end:x}, beyond flash size 0x{args.flash_size:x}"
|
||||
)
|
||||
reserved_size = 2 * 0x10000
|
||||
if args.nav_context_offset + reserved_size > args.ephemeris_offset:
|
||||
raise SystemExit("navigation context overlaps ephemeris flash region")
|
||||
if args.ephemeris_offset + reserved_size > args.flash_size:
|
||||
raise SystemExit("ephemeris flash region exceeds device capacity")
|
||||
if app_end > args.nav_context_offset:
|
||||
raise SystemExit(
|
||||
f"application ends at 0x{app_end:x}, overlapping persistent data at "
|
||||
f"0x{args.nav_context_offset:x}"
|
||||
)
|
||||
|
||||
padding_size = args.app_offset - len(config)
|
||||
write_raw_hex(args.app_hex, (app,))
|
||||
write_raw_hex(args.combined_hex, (config, bytes([0xFF]) * padding_size, app))
|
||||
|
||||
manifest = {
|
||||
"format": "Efinity raw HEX (one byte per line)",
|
||||
"flash": "Ti375C529 lower SPI NOR (U47)",
|
||||
"flash_size": f"0x{args.flash_size:08x}",
|
||||
"configuration": {
|
||||
"source": str(args.config_hex),
|
||||
"offset": "0x00000000",
|
||||
"size": len(config),
|
||||
"sha256": sha256(config),
|
||||
},
|
||||
"application": {
|
||||
"source": str(args.app_bin),
|
||||
"offset": f"0x{args.app_offset:08x}",
|
||||
"size": len(app),
|
||||
"sha256": sha256(app),
|
||||
},
|
||||
"navigation_context": {
|
||||
"offset": f"0x{args.nav_context_offset:08x}",
|
||||
"size": reserved_size,
|
||||
},
|
||||
"ephemeris_cache": {
|
||||
"offset": f"0x{args.ephemeris_offset:08x}",
|
||||
"size": reserved_size,
|
||||
},
|
||||
"combined": {
|
||||
"image": str(args.combined_hex),
|
||||
"programmed_length": app_end,
|
||||
},
|
||||
}
|
||||
args.manifest.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.manifest.write_text(json.dumps(manifest, indent=2) + "\n")
|
||||
|
||||
print(f"configuration: 0x00000000..0x{len(config) - 1:08x}")
|
||||
print(f"application: 0x{args.app_offset:08x}..0x{app_end - 1:08x}")
|
||||
print(f"combined HEX: {args.combined_hex}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,316 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Apply small, deterministic Efinity synthesis adaptations to generated RTL."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import math
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROCKET_STORE_DATA = """ else begin
|
||||
automatic logic [3:0][63:0] _GEN_24 =
|
||||
{{ex_rs_1}, {{2{ex_rs_1[31:0]}}}, {{4{ex_rs_1[15:0]}}}, {{8{ex_rs_1[7:0]}}}};
|
||||
mem_reg_rs2 <= _GEN_24[ex_reg_mem_size];
|
||||
end"""
|
||||
|
||||
EFINITY_STORE_DATA = """ else begin
|
||||
// Efinity 2025.2 leaves the block-local packed automatic array above
|
||||
// undriven (VDB-1002). Spell out the byte-lane replication instead.
|
||||
case (ex_reg_mem_size)
|
||||
2'h0: mem_reg_rs2 <= {8{ex_rs_1[7:0]}};
|
||||
2'h1: mem_reg_rs2 <= {4{ex_rs_1[15:0]}};
|
||||
2'h2: mem_reg_rs2 <= {2{ex_rs_1[31:0]}};
|
||||
default: mem_reg_rs2 <= ex_rs_1;
|
||||
endcase
|
||||
end"""
|
||||
|
||||
ATOMIC_LUT_DECLARATION = re.compile(
|
||||
r"^(?P<indent>\s*)automatic logic \[3:0\]\[3:0\] (?P<name>_GEN_[0-9]+) "
|
||||
r"= '\{4'hC, 4'h8, 4'hE, 4'h6\};$",
|
||||
re.MULTILINE,
|
||||
)
|
||||
|
||||
NCO_ROM_START = '(*rom_style = "distributed" *) logic [PH_ACC_WL-1 : 0] freq_word_arr'
|
||||
NCO_ROM_END = "logic [PH_ACC_WL-1 : 0] sin_phase, cos_phase;"
|
||||
|
||||
|
||||
def parse_integer_parameter(text: str, name: str) -> int:
|
||||
match = re.search(rf"\bparameter\s+{re.escape(name)}\s*=\s*([0-9]+)\s*;", text)
|
||||
if match is None:
|
||||
raise RuntimeError(f"could not find integer parameter {name}")
|
||||
return int(match.group(1))
|
||||
|
||||
|
||||
def parse_sv_integer(token: str) -> tuple[int, int | None]:
|
||||
token = token.strip().replace("_", "")
|
||||
match = re.fullmatch(r"(-)?([0-9]+)'([dDhHbB])([0-9a-fA-F]+)", token)
|
||||
if match is not None:
|
||||
sign, width_text, radix_text, digits = match.groups()
|
||||
radix = {"d": 10, "h": 16, "b": 2}[radix_text.lower()]
|
||||
value = int(digits, radix)
|
||||
if sign:
|
||||
value = -value
|
||||
return value, int(width_text)
|
||||
if re.fullmatch(r"-?[0-9]+", token):
|
||||
return int(token), None
|
||||
raise RuntimeError(f"unsupported SystemVerilog integer literal: {token!r}")
|
||||
|
||||
|
||||
def parse_array_parameter(text: str, name: str) -> list[tuple[int, int | None]]:
|
||||
match = re.search(
|
||||
rf"\bparameter\s+\[[^\]]+\]\s+{re.escape(name)}\s*\[[^\]]+\]\s*=\s*\{{(.*?)\}}\s*;",
|
||||
text,
|
||||
re.DOTALL,
|
||||
)
|
||||
if match is None:
|
||||
raise RuntimeError(f"could not find array parameter {name}")
|
||||
return [parse_sv_integer(token) for token in match.group(1).split(",") if token.strip()]
|
||||
|
||||
|
||||
def sv_case_function(
|
||||
name: str,
|
||||
input_width: str,
|
||||
output_width: str,
|
||||
values: list[int],
|
||||
literal_width: int,
|
||||
) -> str:
|
||||
lines = [
|
||||
f"function automatic logic [{output_width}-1 : 0] {name};",
|
||||
f" input logic [{input_width}-1 : 0] index;",
|
||||
" begin",
|
||||
" case (index)",
|
||||
]
|
||||
for index, value in enumerate(values):
|
||||
literal = f"-{literal_width}'sd{-value}" if value < 0 else f"{literal_width}'d{value}"
|
||||
lines.append(f" {index}: {name} = {literal};")
|
||||
lines.extend(
|
||||
[
|
||||
f" default: {name} = '0;",
|
||||
" endcase",
|
||||
" end",
|
||||
"endfunction",
|
||||
]
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def round_sv_real(value: float) -> int:
|
||||
"""Match real-to-integral assignment rounding used by SystemVerilog."""
|
||||
return math.floor(value + 0.5) if value >= 0 else math.ceil(value - 0.5)
|
||||
|
||||
|
||||
def build_nco_rom_functions(definitions: str) -> str:
|
||||
phase_width = parse_integer_parameter(definitions, "ACQ_NCO_PH_ACC_WL")
|
||||
sine_integer_bits = parse_integer_parameter(definitions, "ACQ_SIN_IL")
|
||||
sine_fraction_bits = parse_integer_parameter(definitions, "ACQ_SIN_FL")
|
||||
lut_address_width = parse_integer_parameter(definitions, "ACQ_SIN_LUT_DEPTH_WL")
|
||||
freq_values = [value for value, _ in parse_array_parameter(definitions, "FREQ_WORD_ARRAY")]
|
||||
pullin_values = [value for value, _ in parse_array_parameter(definitions, "PULLIN_FREQ_WORD_ARRAY")]
|
||||
sine_width = sine_integer_bits + sine_fraction_bits
|
||||
sine_values = [
|
||||
round_sv_real(
|
||||
math.sin(2.0 * math.pi * index / (1 << lut_address_width))
|
||||
* (1 << sine_fraction_bits)
|
||||
)
|
||||
for index in range(1 << lut_address_width)
|
||||
]
|
||||
return "\n\n".join(
|
||||
[
|
||||
"// Efinity 2025.2 mis-elaborates the original initial/$sin ROMs.\n"
|
||||
"// These constant functions are generated from definitions.sv for Ti375 only.",
|
||||
sv_case_function(
|
||||
"efinity_freq_word", "FREQ_BIN_WL", "PH_ACC_WL", freq_values, phase_width
|
||||
),
|
||||
sv_case_function(
|
||||
"efinity_pullin_word", "NUM_PULLIN_WL", "PH_ACC_WL", pullin_values, phase_width
|
||||
),
|
||||
sv_case_function(
|
||||
"efinity_sine", "LUT_DEPTH_WL", "ACQ_SIN_IL + ACQ_SIN_FL", sine_values, sine_width
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def rewrite_acquisition_nco(source: Path, destination: Path, definitions: str) -> None:
|
||||
text = source.read_text(encoding="utf-8")
|
||||
start = text.find(NCO_ROM_START)
|
||||
end = text.find(NCO_ROM_END, start)
|
||||
if start < 0 or end < 0:
|
||||
raise RuntimeError(f"could not locate acquisition NCO ROM block in {source}")
|
||||
text = text[:start] + build_nco_rom_functions(definitions) + "\n\n" + text[end:]
|
||||
old_sum = (
|
||||
"freq_word_arr[freq_bin_idx_i] + "
|
||||
"pullin_freq_word_arr[pullin_freq_bin_idx_i]"
|
||||
)
|
||||
new_sum = (
|
||||
"efinity_freq_word(freq_bin_idx_i) + "
|
||||
"efinity_pullin_word(pullin_freq_bin_idx_i)"
|
||||
)
|
||||
if text.count(old_sum) != 2:
|
||||
raise RuntimeError(f"expected two NCO phase increments in {source}")
|
||||
text = text.replace(old_sum, new_sum)
|
||||
if text.count("sinwav_lut[truncated_sin_phase]") != 1:
|
||||
raise RuntimeError(f"expected one sine ROM read in {source}")
|
||||
if text.count("sinwav_lut[truncated_cos_phase]") != 1:
|
||||
raise RuntimeError(f"expected one cosine ROM read in {source}")
|
||||
text = text.replace("sinwav_lut[truncated_sin_phase]", "efinity_sine(truncated_sin_phase)")
|
||||
text = text.replace("sinwav_lut[truncated_cos_phase]", "efinity_sine(truncated_cos_phase)")
|
||||
destination.write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def rewrite_tracking_nco(source: Path, destination: Path, definitions: str) -> None:
|
||||
text = source.read_text(encoding="utf-8")
|
||||
declaration = (
|
||||
'(*rom_style = "distributed" *) logic [SIN_IL-1 : -SIN_FL] '
|
||||
"sinwav_lut [0 : 2**LUT_DEPTH_WL-1];"
|
||||
)
|
||||
values = [value for value, _ in parse_array_parameter(definitions, "TRCK_SINWAV_LUT")]
|
||||
expected_entries = parse_integer_parameter(definitions, "NUM_TRCK_SINWAV_LUT")
|
||||
if len(values) != expected_entries:
|
||||
raise RuntimeError(
|
||||
f"expected {expected_entries} tracking sine entries, got {len(values)}"
|
||||
)
|
||||
function = (
|
||||
"// Efinity 2025.2 leaves the original package-array initialized ROM undriven.\n"
|
||||
"// This Ti375-only constant function preserves the exact definitions.sv values.\n"
|
||||
+ sv_case_function(
|
||||
"efinity_tracking_sine",
|
||||
"LUT_DEPTH_WL",
|
||||
"SIN_IL + SIN_FL",
|
||||
values,
|
||||
parse_integer_parameter(definitions, "TRCK_CARR_NCO_SIN_WL"),
|
||||
)
|
||||
)
|
||||
if text.count(declaration) != 1:
|
||||
raise RuntimeError(f"expected one tracking sine ROM declaration in {source}")
|
||||
text = text.replace(declaration, function)
|
||||
initializer = """initial begin
|
||||
sinwav_lut = TRCK_SINWAV_LUT;
|
||||
end
|
||||
|
||||
"""
|
||||
if text.count(initializer) != 1:
|
||||
raise RuntimeError(f"expected one tracking sine ROM initializer in {source}")
|
||||
text = text.replace(initializer, "")
|
||||
if text.count("sinwav_lut[accum_truncated_sin]") != 1:
|
||||
raise RuntimeError(f"expected one tracking sine ROM read in {source}")
|
||||
if text.count("sinwav_lut[accum_truncated_cos]") != 1:
|
||||
raise RuntimeError(f"expected one tracking cosine ROM read in {source}")
|
||||
text = text.replace(
|
||||
"sinwav_lut[accum_truncated_sin]", "efinity_tracking_sine(accum_truncated_sin)"
|
||||
)
|
||||
text = text.replace(
|
||||
"sinwav_lut[accum_truncated_cos]", "efinity_tracking_sine(accum_truncated_cos)"
|
||||
)
|
||||
destination.write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def write_mem_file(path: Path, entries: list[tuple[int, int | None]], width: int) -> None:
|
||||
mask = (1 << width) - 1
|
||||
path.write_text(
|
||||
# Binary keeps each row exactly TWIDDLE_WIDTH bits. A hexadecimal row
|
||||
# would round 15 bits up to four digits and Efinity warns about a
|
||||
# spurious 16-to-15-bit truncation even though the value is correct.
|
||||
"".join(f"{value & mask:0{width}b}\n" for value, _ in entries),
|
||||
encoding="ascii",
|
||||
)
|
||||
|
||||
|
||||
def rewrite_twiddle_rom(source: Path, destination: Path) -> None:
|
||||
text = source.read_text(encoding="utf-8")
|
||||
old = """initial begin
|
||||
cos_rom = COS_ROM_ARRAY;
|
||||
sin_rom = SIN_ROM_ARRAY;
|
||||
end"""
|
||||
new = """initial begin
|
||||
// Generated Ti375 files are resolved through Efinity's memory-init include path.
|
||||
$readmemb("ti375_twiddle_cos_15.mem", cos_rom);
|
||||
$readmemb("ti375_twiddle_sin_15.mem", sin_rom);
|
||||
end"""
|
||||
if text.count(old) != 1:
|
||||
raise RuntimeError(f"expected one twiddle ROM initializer in {source}")
|
||||
destination.write_text(text.replace(old, new), encoding="utf-8")
|
||||
|
||||
|
||||
def prepare_gps_rtl(source_dir: Path, output_dir: Path) -> None:
|
||||
definitions_path = source_dir / "common" / "definitions.sv"
|
||||
definitions = definitions_path.read_text(encoding="utf-8")
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
rewrite_acquisition_nco(
|
||||
source_dir / "acq_src" / "acq_nco_carr.sv",
|
||||
output_dir / "acq_nco_carr.sv",
|
||||
definitions,
|
||||
)
|
||||
rewrite_tracking_nco(
|
||||
source_dir / "trck_src" / "NCO_carr.sv",
|
||||
output_dir / "NCO_carr.sv",
|
||||
definitions,
|
||||
)
|
||||
rewrite_twiddle_rom(
|
||||
source_dir / "acq_src" / "twiddle_ram.sv",
|
||||
output_dir / "twiddle_ram.sv",
|
||||
)
|
||||
cos_entries = parse_array_parameter(definitions, "COS_ROM_ARRAY")
|
||||
sin_entries = parse_array_parameter(definitions, "SIN_ROM_ARRAY")
|
||||
expected_entries = parse_integer_parameter(definitions, "NUM_TWIDDLE_ROM_IDX")
|
||||
if len(cos_entries) != expected_entries or len(sin_entries) != expected_entries:
|
||||
raise RuntimeError(
|
||||
f"expected {expected_entries} twiddle entries, got "
|
||||
f"cos={len(cos_entries)} sin={len(sin_entries)}"
|
||||
)
|
||||
write_mem_file(output_dir / "ti375_twiddle_cos_15.mem", cos_entries, 15)
|
||||
write_mem_file(output_dir / "ti375_twiddle_sin_15.mem", sin_entries, 15)
|
||||
|
||||
|
||||
def rewrite_rocket_store_data(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
if EFINITY_STORE_DATA in text:
|
||||
return
|
||||
if text.count(ROCKET_STORE_DATA) != 1:
|
||||
raise RuntimeError(f"expected one Rocket store-data array in {path}")
|
||||
path.write_text(text.replace(ROCKET_STORE_DATA, EFINITY_STORE_DATA), encoding="utf-8")
|
||||
|
||||
|
||||
def rewrite_tilelink_atomic_lut(path: Path) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
if "// Avoid Efinity VDB-1002 on the block-local packed LUT." in text:
|
||||
return
|
||||
match = ATOMIC_LUT_DECLARATION.search(text)
|
||||
if match is None:
|
||||
raise RuntimeError(f"expected one TileLink atomic packed LUT in {path}")
|
||||
if ATOMIC_LUT_DECLARATION.search(text, match.end()) is not None:
|
||||
raise RuntimeError(f"expected only one TileLink atomic packed LUT in {path}")
|
||||
indent = match.group("indent")
|
||||
temporary = match.group("name")
|
||||
old_read = f"{indent}cam_a_0_lut <= {temporary}[auto_in_a_bits_param[1:0]];"
|
||||
new_read = f"""{indent}// Avoid Efinity VDB-1002 on the block-local packed LUT.
|
||||
{indent}case (auto_in_a_bits_param[1:0])
|
||||
{indent} 2'h0: cam_a_0_lut <= 4'h6;
|
||||
{indent} 2'h1: cam_a_0_lut <= 4'hE;
|
||||
{indent} 2'h2: cam_a_0_lut <= 4'h8;
|
||||
{indent} default: cam_a_0_lut <= 4'hC;
|
||||
{indent}endcase"""
|
||||
if text.count(old_read) != 1:
|
||||
raise RuntimeError(f"expected one TileLink atomic packed LUT read in {path}")
|
||||
text = text[: match.start()] + text[match.end() + 1 :]
|
||||
text = text.replace(old_read, new_read)
|
||||
path.write_text(text, encoding="utf-8")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--verilog-dir", type=Path, required=True)
|
||||
parser.add_argument("--gps-source-dir", type=Path, required=True)
|
||||
parser.add_argument("--gps-output-dir", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
rewrite_rocket_store_data(args.verilog_dir / "Rocket.sv")
|
||||
rewrite_tilelink_atomic_lut(args.verilog_dir / "TLAtomicAutomata_pbus.sv")
|
||||
rewrite_tilelink_atomic_lut(args.verilog_dir / "TLAtomicAutomata_cbus.sv")
|
||||
prepare_gps_rtl(args.gps_source_dir, args.gps_output_dir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -69,6 +69,12 @@ FLASH_FORCE ?= 0
|
||||
GPS_DEBUG ?= 1
|
||||
GPS_DEBUG_LEVEL ?= 4
|
||||
GPS_ESKF_ENABLE ?= 1
|
||||
GPS_EPHEMERIS_FLASH_ENABLE ?= 1
|
||||
GPS_EPHEMERIS_FLASH_SEED_INITIAL ?= 1
|
||||
GPS_EPHEMERIS_FLASH_BASE ?= 0x07fe0000
|
||||
GPS_NAV_CONTEXT_ENABLE ?= 1
|
||||
GPS_NAV_CONTEXT_FLASH_BASE ?= 0x07fc0000
|
||||
BSP_SPI_FLASH_PROFILE ?= 2
|
||||
IMU_SENSOR ?= auto
|
||||
|
||||
FLASH_MCS ?= $(OUT_DIR)/flash/vcu118_rocket.mcs
|
||||
@@ -213,13 +219,19 @@ fpga-config:
|
||||
' UART_PORT=$(UART_PORT)' \
|
||||
' UART_BAUD=$(UART_BAUD)' \
|
||||
' GPS_ESKF_ENABLE=$(GPS_ESKF_ENABLE)' \
|
||||
' GPS_EPHEMERIS_FLASH_ENABLE=$(GPS_EPHEMERIS_FLASH_ENABLE)' \
|
||||
' GPS_EPHEMERIS_FLASH_SEED_INITIAL=$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)' \
|
||||
' GPS_EPHEMERIS_FLASH_BASE=$(GPS_EPHEMERIS_FLASH_BASE)' \
|
||||
' GPS_NAV_CONTEXT_ENABLE=$(GPS_NAV_CONTEXT_ENABLE)' \
|
||||
' GPS_NAV_CONTEXT_FLASH_BASE=$(GPS_NAV_CONTEXT_FLASH_BASE)' \
|
||||
' BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)' \
|
||||
' IMU_SENSOR=$(IMU_SENSOR)'
|
||||
|
||||
software:
|
||||
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" IMU_SENSOR="$(IMU_SENSOR)" bootloader flash-image
|
||||
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" IMU_SENSOR="$(IMU_SENSOR)" bootloader flash-image
|
||||
|
||||
$(APP_ELF): FORCE
|
||||
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" IMU_SENSOR="$(IMU_SENSOR)" app
|
||||
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" IMU_SENSOR="$(IMU_SENSOR)" app
|
||||
|
||||
chisel: software
|
||||
@cd "$(REPO_DIR)"
|
||||
|
||||
Reference in New Issue
Block a user