1dbd1b5151
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.
647 lines
22 KiB
Makefile
647 lines
22 KiB
Makefile
SHELL := /bin/bash
|
|
.SHELLFLAGS := -euo pipefail -c
|
|
.ONESHELL:
|
|
|
|
FPGA_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
|
REPO_DIR := $(abspath $(FPGA_DIR)/../../..)
|
|
FPGA_SCRIPT_DIR := $(FPGA_DIR)/flow/vivado/scripts
|
|
TOOL_SCRIPT_DIR := $(FPGA_DIR)/tools
|
|
SOC_DIR := $(REPO_DIR)/soc
|
|
SOC_SW_DIR := $(SOC_DIR)/software
|
|
SOC_OUT_DIR := $(SOC_DIR)/out
|
|
HW_DIR := $(REPO_DIR)/hardware
|
|
HW_GENERATED_DIR := $(HW_DIR)/generated
|
|
GPS_SYSTEM_DIR ?= $(HW_DIR)/external/gps/rtl
|
|
OUT_DIR := $(FPGA_DIR)/out
|
|
LOG_DIR := $(OUT_DIR)/logs
|
|
|
|
include $(REPO_DIR)/tools/project.mk
|
|
|
|
VIVADO ?= /tools/Xilinx/2025.2/Vivado/bin/vivado
|
|
OPENOCD ?= openocd
|
|
GDB ?= $(CROSS)gdb
|
|
GDB_HOST ?= localhost
|
|
GDB_PORT ?= 3333
|
|
OPENOCD_ADAPTER_SPEED ?= 1000
|
|
UART_PORT ?= auto
|
|
UART_BAUD ?= 460800
|
|
BOARD ?= genesys2
|
|
PART_NAME ?= xc7k325tffg900-2
|
|
BOARD_PART ?= digilentinc.com:genesys2:part0:1.1
|
|
SOC_CLK_HZ ?= 50000000
|
|
GPS_ACQ_CLK_HZ ?= 80000000
|
|
GPS_TRCK_CLK_HZ ?= 125000000
|
|
GPS_RF_CLK_HZ ?= 16367981
|
|
# GPS RF source for the generated FPGA top.
|
|
# pmod : external 4-bit RF data + RF clock from the 3.3 V PMOD header
|
|
# generated : old lab fallback, internal RF clock and zero RF data
|
|
# ethernet : raw-Ethernet RF streamer through the Genesys2 RGMII PHY
|
|
RF_INPUT_MODE ?= pmod
|
|
BSP_UART_CLOCK_HZ ?= $(SOC_CLK_HZ)
|
|
BSP_UART_BAUDRATE ?= $(UART_BAUD)
|
|
BSP_CLINT_TIMEBASE_HZ ?= 500000
|
|
# DTIM is Rocket's scratchpad RAM; hardware generator and software must agree.
|
|
DTIM_BASE ?= 0x80000000
|
|
DTIM_SIZE ?= 0x00100000
|
|
MAKE_BIN ?= make
|
|
ETH_RF_TOOL_DIR ?= $(REPO_DIR)/targets/fpga/vcu118/flow/ethernet_rf
|
|
ETH_RF_IFACE ?= enx14ebb6850432
|
|
ETH_RF_INPUT ?= $(OUT_DIR)/rf/gps_rf_input.bin
|
|
ETH_RF_SAMPLE_FORMAT ?= real4-signmag
|
|
ifneq ($(strip $(SAMPLE_FORMAT)),)
|
|
ETH_RF_SAMPLE_FORMAT := $(SAMPLE_FORMAT)
|
|
endif
|
|
ETH_RF_CHUNK_SAMPLES ?= 17800
|
|
ETH_RF_MTU ?= 9000
|
|
ETH_RF_PRELOAD_SAMPLES ?= 131072
|
|
ETH_RF_MAX_SAMPLES ?= 0
|
|
ETH_RF_MAX_BYTES ?= 0
|
|
ETH_RF_SENDER ?= $(OUT_DIR)/tools/send_gps_rf
|
|
|
|
BITSTREAM_OFFSET ?= 0x00000000
|
|
APP_FLASH_OFFSET ?= 0x01800000
|
|
FLASH_SIZE_MB ?= 32
|
|
FLASH_INTERFACE ?= SPIx4
|
|
CFGMEM_PART ?= s25fl256sxxxxxx0-spi-x1_x2_x4
|
|
FLASH_VERIFY ?= 0
|
|
FLASH_ERASE ?= 1
|
|
FLASH_REGIONS ?= auto
|
|
FLASH_FORCE ?= 0
|
|
GPS_DEBUG ?= 1
|
|
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
|
|
FLASH_BIN ?= $(OUT_DIR)/flash/genesys2_rocket.bin
|
|
BIT_FILE ?= $(OUT_DIR)/bitstream/genesys2_rocket.bit
|
|
DEBUG_DIR := $(FPGA_DIR)/flow/debug
|
|
OPENOCD_CFG ?= $(DEBUG_DIR)/openocd_genesys2_bscan.cfg
|
|
GDB_LOAD_SCRIPT ?= $(DEBUG_DIR)/gdb_load_and_run.gdb
|
|
GDB_ATTACH_SCRIPT ?= $(DEBUG_DIR)/gdb_attach.gdb
|
|
app ?=
|
|
ifneq ($(strip $(app)),)
|
|
APP ?= $(app)
|
|
else
|
|
APP ?= hello_uart
|
|
endif
|
|
|
|
FLASH_REGION_DIR ?= $(OUT_DIR)/flash/regions
|
|
FLASH_STATE ?= $(OUT_DIR)/flash/programmed_regions.tsv
|
|
BITSTREAM_MCS ?= $(FLASH_REGION_DIR)/bitstream.mcs
|
|
APP_MCS ?= $(FLASH_REGION_DIR)/app.mcs
|
|
APP_BUILD_DIR ?= $(SOC_OUT_DIR)/software/$(APP)
|
|
BOOTLOADER_BUILD_DIR ?= $(SOC_OUT_DIR)/software/bootloader
|
|
APP_ELF ?= $(APP_BUILD_DIR)/$(APP).elf
|
|
APP_FLASH_IMAGE ?= $(SOC_OUT_DIR)/flash/$(APP).flash.bin
|
|
FIRRTL_DIR ?= $(HW_GENERATED_DIR)/genesys2-soc
|
|
VERILOG_DIR ?= $(HW_GENERATED_DIR)/genesys2-soc-verilog
|
|
|
|
SOFTWARE_TARGETS := software
|
|
BUILD_TARGETS := chisel rtl soc bitstream fpga-config
|
|
FLASH_IMAGE_TARGETS := flash-image flash-regions
|
|
PROGRAM_TARGETS := \
|
|
program-fpga \
|
|
program-flash \
|
|
program-flash-elf \
|
|
program-flash-bitstream \
|
|
program-flash-regions \
|
|
program-flash-all \
|
|
program-flash-combined
|
|
DEBUG_TARGETS := debug-openocd debug-load debug-gdb uart-listen eth-rf-host eth-rf-caps eth-rf-send eth-rf-stop eth-rf-send-python
|
|
ALIASES := program-app program-bitstream
|
|
CLEAN_TARGETS := clean-sw clean-fpga clean-flash prune clean
|
|
|
|
.PHONY: help all \
|
|
$(SOFTWARE_TARGETS) \
|
|
$(BUILD_TARGETS) \
|
|
$(FLASH_IMAGE_TARGETS) \
|
|
$(PROGRAM_TARGETS) \
|
|
$(DEBUG_TARGETS) \
|
|
$(ALIASES) \
|
|
$(CLEAN_TARGETS) \
|
|
FORCE
|
|
|
|
help:
|
|
@printf '%s\n' \
|
|
'Genesys2 FPGA targets:' \
|
|
' make software Build bootloader, hello app, and SPI flash app image' \
|
|
' make chisel Build Scala/Chisel generator and emit FIRRTL' \
|
|
' make rtl Convert FIRRTL to split SystemVerilog and wrapper' \
|
|
' make bitstream Run Vivado non-project synth/place/route/bitgen' \
|
|
' make flash-image Generate one combined MCS/BIN image' \
|
|
' make flash-regions Generate sparse per-region MCS images' \
|
|
' make program-fpga Program FPGA SRAM with BIT_FILE' \
|
|
' make program-flash Program changed app flash region only' \
|
|
' make program-flash-bitstream' \
|
|
' Program changed bitstream flash region only' \
|
|
' make program-flash-all' \
|
|
' Program changed bitstream and app regions separately' \
|
|
' make program-flash-combined' \
|
|
' Legacy one-MCS programming path' \
|
|
' make debug-openocd Open OpenOCD BSCAN/GDB server for programmed FPGA' \
|
|
' make debug-load Load APP ELF over GDB and run from DTIM' \
|
|
' make debug-gdb Attach interactive GDB to OpenOCD' \
|
|
' make uart-listen Listen to board UART' \
|
|
' make eth-rf-caps Allow non-sudo Ethernet RF sender execution via file capabilities' \
|
|
' make eth-rf-send Stream GPS RF binary to FPGA over raw Ethernet using C host app' \
|
|
' Requires RF_INPUT_MODE=ethernet bitstream' \
|
|
' make eth-rf-stop Stop FPGA Ethernet RF playback' \
|
|
' make eth-rf-send-python' \
|
|
' Stream GPS RF binary using Python fallback' \
|
|
' make fpga-config Show board clocks, RF, flash, UART, and Vivado config' \
|
|
'' \
|
|
'Config env:' \
|
|
' BOARD=$(BOARD)' \
|
|
' PART_NAME=$(PART_NAME)' \
|
|
' BOARD_PART=$(BOARD_PART)' \
|
|
' 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) # pmod, generated, or ethernet' \
|
|
' GPS_SYSTEM_DIR=$(GPS_SYSTEM_DIR)' \
|
|
' BSP_UART_CLOCK_HZ=$(BSP_UART_CLOCK_HZ)' \
|
|
' BSP_UART_BAUDRATE=$(BSP_UART_BAUDRATE)' \
|
|
' BSP_CLINT_TIMEBASE_HZ=$(BSP_CLINT_TIMEBASE_HZ)' \
|
|
' DTIM_BASE=$(DTIM_BASE)' \
|
|
' DTIM_SIZE=$(DTIM_SIZE)' \
|
|
' BITSTREAM_OFFSET=$(BITSTREAM_OFFSET)' \
|
|
' APP_FLASH_OFFSET=$(APP_FLASH_OFFSET)' \
|
|
' FLASH_SIZE_MB=$(FLASH_SIZE_MB)' \
|
|
' CFGMEM_PART=$(CFGMEM_PART)' \
|
|
' FLASH_REGIONS=$(FLASH_REGIONS) # auto, all, app, bitstream, or comma list' \
|
|
' FLASH_FORCE=$(FLASH_FORCE) # 1 forces unchanged regions too' \
|
|
' APP=$(APP)' \
|
|
' APP_ELF=$(APP_ELF)' \
|
|
' 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)' \
|
|
' ETH_RF_INPUT=$(ETH_RF_INPUT)' \
|
|
' ETH_RF_CHUNK_SAMPLES=$(ETH_RF_CHUNK_SAMPLES)' \
|
|
' ETH_RF_MTU=$(ETH_RF_MTU)' \
|
|
' ETH_RF_PRELOAD_SAMPLES=$(ETH_RF_PRELOAD_SAMPLES)' \
|
|
' ETH_RF_MAX_SAMPLES=$(ETH_RF_MAX_SAMPLES)' \
|
|
' GDB_PORT=$(GDB_PORT)' \
|
|
' OPENOCD_ADAPTER_SPEED=$(OPENOCD_ADAPTER_SPEED)'
|
|
|
|
all: bitstream
|
|
|
|
fpga-config:
|
|
@printf '%s\n' \
|
|
'FPGA config:' \
|
|
' BOARD=$(BOARD)' \
|
|
' PART_NAME=$(PART_NAME)' \
|
|
' BOARD_PART=$(BOARD_PART)' \
|
|
' 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)' \
|
|
' GPS_SYSTEM_DIR=$(GPS_SYSTEM_DIR)' \
|
|
' BSP_UART_CLOCK_HZ=$(BSP_UART_CLOCK_HZ)' \
|
|
' BSP_UART_BAUDRATE=$(BSP_UART_BAUDRATE)' \
|
|
' BSP_CLINT_TIMEBASE_HZ=$(BSP_CLINT_TIMEBASE_HZ)' \
|
|
' DTIM_BASE=$(DTIM_BASE)' \
|
|
' DTIM_SIZE=$(DTIM_SIZE)' \
|
|
' BIT_FILE=$(BIT_FILE)' \
|
|
' BITSTREAM_OFFSET=$(BITSTREAM_OFFSET)' \
|
|
' APP_FLASH_OFFSET=$(APP_FLASH_OFFSET)' \
|
|
' FLASH_SIZE_MB=$(FLASH_SIZE_MB)' \
|
|
' FLASH_INTERFACE=$(FLASH_INTERFACE)' \
|
|
' CFGMEM_PART=$(CFGMEM_PART)' \
|
|
' 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)' \
|
|
' 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_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_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)"
|
|
"$(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)" "$(OUT_DIR)/build/generated"
|
|
$(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)/gen_genesys2_wrapper.py" \
|
|
--rocket-top "$(VERILOG_DIR)/VCU118RocketSystem.sv" \
|
|
--out "$(OUT_DIR)/build/generated/genesys2_rocket_top.sv" \
|
|
--rf-input-mode "$(RF_INPUT_MODE)"
|
|
|
|
soc: rtl
|
|
|
|
bitstream: rtl
|
|
@mkdir -p "$(LOG_DIR)"
|
|
cd "$(LOG_DIR)"
|
|
GPS_SYSTEM_DIR="$(GPS_SYSTEM_DIR)" \
|
|
RF_INPUT_MODE="$(RF_INPUT_MODE)" "$(VIVADO)" -mode batch \
|
|
-log "$(LOG_DIR)/build_bitstream.log" \
|
|
-journal "$(LOG_DIR)/build_bitstream.jou" \
|
|
-source "$(FPGA_SCRIPT_DIR)/build.tcl"
|
|
|
|
flash-image: software
|
|
@if [[ ! -f "$(BIT_FILE)" ]]; then
|
|
echo "Missing bitstream: $(BIT_FILE)" >&2
|
|
echo "Run: make -C $(FPGA_DIR) bitstream" >&2
|
|
exit 1
|
|
fi
|
|
mkdir -p "$(LOG_DIR)"
|
|
cd "$(LOG_DIR)"
|
|
BIT_FILE="$(BIT_FILE)" \
|
|
APP_FLASH_IMAGE="$(APP_FLASH_IMAGE)" \
|
|
FLASH_MCS="$(FLASH_MCS)" \
|
|
FLASH_BIN="$(FLASH_BIN)" \
|
|
FLASH_SIZE_MB="$(FLASH_SIZE_MB)" \
|
|
FLASH_INTERFACE="$(FLASH_INTERFACE)" \
|
|
BITSTREAM_OFFSET="$(BITSTREAM_OFFSET)" \
|
|
APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" \
|
|
"$(VIVADO)" -mode batch \
|
|
-log "$(LOG_DIR)/write_flash.log" \
|
|
-journal "$(LOG_DIR)/write_flash.jou" \
|
|
-source "$(FPGA_SCRIPT_DIR)/write_flash.tcl"
|
|
|
|
flash-regions:
|
|
@selected="$(FLASH_REGIONS)"
|
|
selected="$${selected,,}"
|
|
selected="$${selected//,/ }"
|
|
if [[ "$$selected" == "auto" ]]; then
|
|
selected="bitstream app"
|
|
fi
|
|
need_app=0
|
|
need_bitstream=0
|
|
region_names=()
|
|
for region in $$selected; do
|
|
case "$$region" in
|
|
all)
|
|
need_app=1
|
|
need_bitstream=1
|
|
region_names+=(bitstream app)
|
|
;;
|
|
app|application|software|hello)
|
|
need_app=1
|
|
region_names+=(app)
|
|
;;
|
|
bit|bitstream)
|
|
need_bitstream=1
|
|
region_names+=(bitstream)
|
|
;;
|
|
none|"")
|
|
;;
|
|
*)
|
|
echo "Unknown FLASH_REGIONS entry: $$region" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
if [[ "$$need_app" == "1" ]]; then
|
|
$(MAKE_BIN) -C "$(FPGA_DIR)" software
|
|
fi
|
|
if [[ "$$need_bitstream" == "1" && ! -f "$(BIT_FILE)" ]]; then
|
|
echo "Missing bitstream: $(BIT_FILE)" >&2
|
|
echo "Run: make -C $(FPGA_DIR) bitstream" >&2
|
|
exit 1
|
|
fi
|
|
if [[ "$${#region_names[@]}" -eq 0 ]]; then
|
|
echo "No flash regions selected."
|
|
exit 0
|
|
fi
|
|
joined="$$(IFS=';'; echo "$${region_names[*]}")"
|
|
mkdir -p "$(LOG_DIR)"
|
|
cd "$(LOG_DIR)"
|
|
BIT_FILE="$(BIT_FILE)" \
|
|
APP_FLASH_IMAGE="$(APP_FLASH_IMAGE)" \
|
|
BITSTREAM_MCS="$(BITSTREAM_MCS)" \
|
|
APP_MCS="$(APP_MCS)" \
|
|
FLASH_SIZE_MB="$(FLASH_SIZE_MB)" \
|
|
FLASH_INTERFACE="$(FLASH_INTERFACE)" \
|
|
BITSTREAM_OFFSET="$(BITSTREAM_OFFSET)" \
|
|
APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" \
|
|
FLASH_REGION_NAMES="$$joined" \
|
|
"$(VIVADO)" -mode batch \
|
|
-log "$(LOG_DIR)/write_flash_regions.log" \
|
|
-journal "$(LOG_DIR)/write_flash_regions.jou" \
|
|
-source "$(FPGA_SCRIPT_DIR)/write_flash_regions.tcl"
|
|
|
|
program-fpga:
|
|
@mkdir -p "$(LOG_DIR)"
|
|
cd "$(LOG_DIR)"
|
|
BIT_FILE="$(BIT_FILE)" \
|
|
"$(VIVADO)" -mode batch \
|
|
-log "$(LOG_DIR)/program_fpga.log" \
|
|
-journal "$(LOG_DIR)/program_fpga.jou" \
|
|
-source "$(FPGA_SCRIPT_DIR)/program_fpga.tcl"
|
|
|
|
program-flash program-flash-elf program-app:
|
|
@$(MAKE_BIN) -C "$(FPGA_DIR)" program-flash-regions FLASH_REGIONS=app
|
|
|
|
program-flash-bitstream program-bitstream:
|
|
@$(MAKE_BIN) -C "$(FPGA_DIR)" program-flash-regions FLASH_REGIONS=bitstream
|
|
|
|
program-flash-all:
|
|
@$(MAKE_BIN) -C "$(FPGA_DIR)" program-flash-regions FLASH_REGIONS=all
|
|
|
|
program-flash-regions:
|
|
@selected="$(FLASH_REGIONS)"
|
|
selected="$${selected,,}"
|
|
selected="$${selected//,/ }"
|
|
if [[ "$$selected" == "auto" ]]; then
|
|
selected="bitstream app"
|
|
fi
|
|
need_app=0
|
|
need_bitstream=0
|
|
for region in $$selected; do
|
|
case "$$region" in
|
|
all)
|
|
need_app=1
|
|
need_bitstream=1
|
|
;;
|
|
app|application|software|hello)
|
|
need_app=1
|
|
;;
|
|
bit|bitstream)
|
|
need_bitstream=1
|
|
;;
|
|
none|"")
|
|
;;
|
|
*)
|
|
echo "Unknown FLASH_REGIONS entry: $$region" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
if [[ "$$need_app" == "1" ]]; then
|
|
$(MAKE_BIN) -C "$(FPGA_DIR)" software
|
|
fi
|
|
if [[ "$$need_bitstream" == "1" && ! -f "$(BIT_FILE)" ]]; then
|
|
echo "Missing bitstream: $(BIT_FILE)" >&2
|
|
echo "Run: make -C $(FPGA_DIR) bitstream" >&2
|
|
exit 1
|
|
fi
|
|
state_line() {
|
|
local name="$$1"
|
|
local offset="$$2"
|
|
local source_file="$$3"
|
|
local mcs_file="$$4"
|
|
local size hash
|
|
size="$$(stat -c '%s' "$$source_file")"
|
|
hash="$$(sha256sum "$$source_file" | awk '{print $$1}')"
|
|
printf '%s\t%s\t%s\t%s\t%s\t%s\n' "$$name" "$$offset" "$$size" "$$hash" "$$source_file" "$$mcs_file"
|
|
}
|
|
plan_names=()
|
|
plan_mcs=()
|
|
plan_state=()
|
|
region_planned() {
|
|
local name="$$1"
|
|
local planned
|
|
for planned in "$${plan_names[@]}"; do
|
|
[[ "$$planned" == "$$name" ]] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
add_region() {
|
|
local name="$$1"
|
|
local offset="$$2"
|
|
local source_file="$$3"
|
|
local mcs_file="$$4"
|
|
local line
|
|
region_planned "$$name" && return
|
|
if [[ ! -f "$$source_file" ]]; then
|
|
echo "Missing flash source for $$name: $$source_file" >&2
|
|
exit 1
|
|
fi
|
|
line="$$(state_line "$$name" "$$offset" "$$source_file" "$$mcs_file")"
|
|
if [[ "$(FLASH_FORCE)" != "1" && -f "$(FLASH_STATE)" ]] && grep -Fqx "$$line" "$(FLASH_STATE)"; then
|
|
echo "Skipping unchanged flash region: $$name"
|
|
return
|
|
fi
|
|
plan_names+=("$$name")
|
|
plan_mcs+=("$$mcs_file")
|
|
plan_state+=("$$line")
|
|
}
|
|
for region in $$selected; do
|
|
case "$$region" in
|
|
all)
|
|
add_region bitstream "$(BITSTREAM_OFFSET)" "$(BIT_FILE)" "$(BITSTREAM_MCS)"
|
|
add_region app "$(APP_FLASH_OFFSET)" "$(APP_FLASH_IMAGE)" "$(APP_MCS)"
|
|
;;
|
|
app|application|software|hello)
|
|
add_region app "$(APP_FLASH_OFFSET)" "$(APP_FLASH_IMAGE)" "$(APP_MCS)"
|
|
;;
|
|
bit|bitstream)
|
|
add_region bitstream "$(BITSTREAM_OFFSET)" "$(BIT_FILE)" "$(BITSTREAM_MCS)"
|
|
;;
|
|
none|"")
|
|
;;
|
|
esac
|
|
done
|
|
if [[ "$${#plan_names[@]}" -eq 0 ]]; then
|
|
echo "No changed flash regions to program."
|
|
exit 0
|
|
fi
|
|
region_names="$$(IFS=';'; echo "$${plan_names[*]}")"
|
|
region_files="$$(IFS=';'; echo "$${plan_mcs[*]}")"
|
|
mkdir -p "$(LOG_DIR)"
|
|
cd "$(LOG_DIR)"
|
|
BIT_FILE="$(BIT_FILE)" \
|
|
APP_FLASH_IMAGE="$(APP_FLASH_IMAGE)" \
|
|
BITSTREAM_MCS="$(BITSTREAM_MCS)" \
|
|
APP_MCS="$(APP_MCS)" \
|
|
FLASH_SIZE_MB="$(FLASH_SIZE_MB)" \
|
|
FLASH_INTERFACE="$(FLASH_INTERFACE)" \
|
|
BITSTREAM_OFFSET="$(BITSTREAM_OFFSET)" \
|
|
APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" \
|
|
FLASH_REGION_NAMES="$$region_names" \
|
|
"$(VIVADO)" -mode batch \
|
|
-log "$(LOG_DIR)/write_flash_regions.log" \
|
|
-journal "$(LOG_DIR)/write_flash_regions.jou" \
|
|
-source "$(FPGA_SCRIPT_DIR)/write_flash_regions.tcl"
|
|
FLASH_REGION_NAMES="$$region_names" \
|
|
FLASH_REGION_FILES="$$region_files" \
|
|
FLASH_MCS="$(FLASH_MCS)" \
|
|
CFGMEM_PART="$(CFGMEM_PART)" \
|
|
FLASH_VERIFY="$(FLASH_VERIFY)" \
|
|
FLASH_ERASE="$(FLASH_ERASE)" \
|
|
"$(VIVADO)" -mode batch \
|
|
-log "$(LOG_DIR)/program_flash.log" \
|
|
-journal "$(LOG_DIR)/program_flash.jou" \
|
|
-source "$(FPGA_SCRIPT_DIR)/program_flash.tcl"
|
|
grep -q "Programmed flash" "$(LOG_DIR)/program_flash.log"
|
|
mkdir -p "$$(dirname "$(FLASH_STATE)")"
|
|
tmp="$(FLASH_STATE).tmp.$$$$"
|
|
if [[ -f "$(FLASH_STATE)" ]]; then
|
|
cp "$(FLASH_STATE)" "$$tmp"
|
|
else
|
|
: > "$$tmp"
|
|
fi
|
|
for line in "$${plan_state[@]}"; do
|
|
name="$${line%%$$'\t'*}"
|
|
next="$$tmp.next"
|
|
awk -F '\t' -v name="$$name" '$$1 != name' "$$tmp" > "$$next"
|
|
mv "$$next" "$$tmp"
|
|
printf '%s\n' "$$line" >> "$$tmp"
|
|
done
|
|
mv "$$tmp" "$(FLASH_STATE)"
|
|
echo "Updated flash program state: $(FLASH_STATE)"
|
|
|
|
program-flash-combined: flash-image
|
|
@mkdir -p "$(LOG_DIR)"
|
|
cd "$(LOG_DIR)"
|
|
FLASH_REGION_NAMES="combined" \
|
|
FLASH_REGION_FILES="$(FLASH_MCS)" \
|
|
FLASH_MCS="$(FLASH_MCS)" \
|
|
CFGMEM_PART="$(CFGMEM_PART)" \
|
|
FLASH_VERIFY="$(FLASH_VERIFY)" \
|
|
FLASH_ERASE="$(FLASH_ERASE)" \
|
|
"$(VIVADO)" -mode batch \
|
|
-log "$(LOG_DIR)/program_flash_combined.log" \
|
|
-journal "$(LOG_DIR)/program_flash_combined.jou" \
|
|
-source "$(FPGA_SCRIPT_DIR)/program_flash.tcl"
|
|
|
|
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:
|
|
@port="$(UART_PORT)"
|
|
if [[ "$$port" == "auto" ]]; then
|
|
for candidate in \
|
|
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_*-if00-port0 \
|
|
/dev/serial/by-id/usb-Digilent_Digilent_Adept_USB_Device_*-if01-port0 \
|
|
/dev/serial/by-id/usb-Digilent_Digilent_Adept_USB_Device_*-if00-port0 \
|
|
/dev/ttyUSB2 \
|
|
/dev/ttyUSB1 \
|
|
/dev/ttyUSB0; do
|
|
if [[ -e "$$candidate" ]]; then
|
|
port="$$candidate"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
if [[ "$$port" == "auto" || ! -e "$$port" ]]; then
|
|
echo "No UART device found. Set UART_PORT=/dev/ttyUSBx or UART_PORT=/dev/serial/by-id/..." >&2
|
|
exit 1
|
|
fi
|
|
echo "Listening on $$port @ $(UART_BAUD)"
|
|
stty -F "$$port" "$(UART_BAUD)" cs8 -cstopb -parenb -ixon -ixoff raw
|
|
cat "$$port"
|
|
|
|
eth-rf-host: $(ETH_RF_SENDER)
|
|
|
|
$(ETH_RF_SENDER): $(ETH_RF_TOOL_DIR)/send_gps_rf.c
|
|
@mkdir -p "$$(dirname "$@")"
|
|
gcc -O3 -std=c11 -Wall -Wextra -o "$@" "$<"
|
|
|
|
eth-rf-caps: $(ETH_RF_SENDER)
|
|
@sudo setcap cap_net_raw,cap_net_admin+ep "$(ETH_RF_SENDER)"
|
|
@getcap "$(ETH_RF_SENDER)"
|
|
|
|
eth-rf-send: $(ETH_RF_SENDER)
|
|
@"$(ETH_RF_SENDER)" \
|
|
--iface "$(ETH_RF_IFACE)" \
|
|
--input "$(ETH_RF_INPUT)" \
|
|
--sample-format "$(ETH_RF_SAMPLE_FORMAT)" \
|
|
--chunk-samples "$(ETH_RF_CHUNK_SAMPLES)" \
|
|
--mtu "$(ETH_RF_MTU)" \
|
|
--preload-samples "$(ETH_RF_PRELOAD_SAMPLES)" \
|
|
--max-samples "$(ETH_RF_MAX_SAMPLES)" \
|
|
--max-bytes "$(ETH_RF_MAX_BYTES)"
|
|
|
|
eth-rf-stop: $(ETH_RF_SENDER)
|
|
@"$(ETH_RF_SENDER)" \
|
|
--iface "$(ETH_RF_IFACE)" \
|
|
--mtu "$(ETH_RF_MTU)" \
|
|
--stop-only
|
|
|
|
eth-rf-send-python:
|
|
@python3 "$(ETH_RF_TOOL_DIR)/send_gps_rf.py" \
|
|
--iface "$(ETH_RF_IFACE)" \
|
|
--input "$(ETH_RF_INPUT)" \
|
|
--sample-format "$(ETH_RF_SAMPLE_FORMAT)" \
|
|
--chunk-samples "$(ETH_RF_CHUNK_SAMPLES)" \
|
|
--mtu "$(ETH_RF_MTU)" \
|
|
--preload-samples "$(ETH_RF_PRELOAD_SAMPLES)" \
|
|
--max-samples "$(ETH_RF_MAX_SAMPLES)" \
|
|
--max-bytes "$(ETH_RF_MAX_BYTES)"
|
|
|
|
clean-sw:
|
|
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" clean
|
|
|
|
clean-fpga:
|
|
@rm -rf "$(OUT_DIR)/build" "$(OUT_DIR)/bitstream" "$(OUT_DIR)/reports" "$(OUT_DIR)/logs"
|
|
|
|
clean-flash:
|
|
@rm -rf "$(OUT_DIR)/flash"
|
|
|
|
prune:
|
|
@rm -rf "$(OUT_DIR)/logs" "$(OUT_DIR)/reports" "$(OUT_DIR)/build/checkpoints"
|
|
rm -f "$(OUT_DIR)/flash/genesys2_rocket.mcs" "$(OUT_DIR)/flash/genesys2_rocket.bin" "$(OUT_DIR)/flash/genesys2_rocket.prm"
|
|
rm -f "$(OUT_DIR)/flash/regions/bitstream.mcs" "$(OUT_DIR)/flash/regions/bitstream.prm"
|
|
find "$(OUT_DIR)" -type d -empty -delete 2>/dev/null || true
|
|
|
|
clean: clean-sw
|
|
@rm -rf "$(OUT_DIR)" "$(FIRRTL_DIR)" "$(VERILOG_DIR)"
|