Files
gps/targets/fpga/genesys2/Makefile
T
onur 1dbd1b5151 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.
2026-08-13 01:28:46 +03:00

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)"