From 584a69302a1e0c62f894dc303645e2c5de184df2 Mon Sep 17 00:00:00 2001 From: onur cayan Date: Thu, 13 Aug 2026 01:47:09 +0300 Subject: [PATCH] fix(efinity): fail early when toolchain is missing --- README.md | 9 +- targets/fpga/ti375c529/Makefile | 89 +++++++++++++++---- targets/fpga/ti375c529/README.md | 15 +++- targets/fpga/ti375c529/flow/efinity/README.md | 6 +- tools/project.mk | 16 +++- 5 files changed, 104 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index a1f5b02..9b1a537 100644 --- a/README.md +++ b/README.md @@ -560,9 +560,12 @@ interface: SPIx4 ### Ti375C529 Efinity build ve flash -Efinity varsayilan olarak `/tools/efinix/efinity` altinda aranir. Farkli bir -kurulum `EFINITY_HOME=/path/to/efinity` ile secilebilir. Build, SRAM'e gecici -programlama ve kart tespiti kokten su sekilde yapilir: +Efinity `/tools/efinix/efinity`, `/opt`, kullanici dizini ve +`tools/local/efinity` altinda aranir. Farkli bir kurulum +`EFINITY_HOME=/path/to/efinity/2025.2` ile secilebilir. `fpga-bitstream`, uzun +RTL elaborasyonundan once kurulumdaki `bin/setup.sh` ve `scripts/efx_run.py` +dosyalarini kontrol eder. Build, SRAM'e gecici programlama ve kart tespiti +kokten su sekilde yapilir: ```sh make FPGA_BOARD=ti375c529 fpga-config diff --git a/targets/fpga/ti375c529/Makefile b/targets/fpga/ti375c529/Makefile index 9b4ba14..2f508eb 100644 --- a/targets/fpga/ti375c529/Makefile +++ b/targets/fpga/ti375c529/Makefile @@ -1,6 +1,7 @@ SHELL := /bin/bash .SHELLFLAGS := -euo pipefail -c .ONESHELL: +.NOTPARALLEL: detect interface map bitstream program-fpga program-flash-loader FPGA_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) REPO_DIR := $(abspath $(FPGA_DIR)/../../..) @@ -85,7 +86,8 @@ 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 \ +.PHONY: help all fpga-config efinity-build-check efinity-program-check \ + 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 \ @@ -116,12 +118,34 @@ help: all: bitstream +efinity-build-check: + @if [[ -z "$(strip $(EFINITY_HOME))" ]]; then + echo "Efinity installation not found." >&2 + echo "Install Efinity 2025.2, then set EFINITY_HOME=/path/to/efinity/2025.2." >&2 + echo "Searched /tools/efinix/efinity, /opt, \$$HOME, and tools/local/efinity." >&2 + exit 1 + fi + for required in "$(EFINITY_SETUP)" "$(EFX_RUN)"; do + if [[ ! -r "$$required" ]]; then + echo "Incomplete Efinity installation: missing $$required" >&2 + echo "Set EFINITY_HOME to the directory containing bin/setup.sh." >&2 + exit 1 + fi + done + +efinity-program-check: efinity-build-check + @if [[ ! -x "$(EFX_PGM)" ]]; then + echo "Incomplete Efinity installation: missing $(EFX_PGM)" >&2 + exit 1 + fi + fpga-config: @printf '%s\n' \ 'Ti375C529 FPGA config:' \ - ' EFINITY_HOME=$(EFINITY_HOME)' \ - ' EFX_RUN=$(EFX_RUN)' \ - ' EFX_PGM=$(EFX_PGM)' \ + ' EFINITY_HOME=$(if $(strip $(EFINITY_HOME)),$(EFINITY_HOME),NOT FOUND)' \ + ' EFINITY_SETUP=$(if $(strip $(EFINITY_SETUP)),$(EFINITY_SETUP),NOT FOUND)' \ + ' EFX_RUN=$(if $(strip $(EFX_RUN)),$(EFX_RUN),NOT FOUND)' \ + ' EFX_PGM=$(if $(strip $(EFX_PGM)),$(EFX_PGM),NOT FOUND)' \ ' OPENOCD=$(OPENOCD)' \ ' GDB=$(GDB)' \ ' DEVICE=$(DEVICE)' \ @@ -146,9 +170,12 @@ fpga-config: ' UART_PORT=$(UART_PORT)' \ ' UART_BAUD=$(UART_BAUD)' -detect: +detect: efinity-program-check @set +u - source "$(EFINITY_SETUP)" >/dev/null 2>&1 + if ! source "$(EFINITY_SETUP)" >/dev/null; then + echo "Failed to initialize Efinity from $(EFINITY_SETUP)" >&2 + exit 1 + fi set -u "$(EFX_PGM)" --scan_usb @@ -258,31 +285,40 @@ soc: rtl $(INTERFACE_SCRIPT): $(INTERFACE_SOURCE) cp "$<" "$@" -interface: $(INTERFACE_SCRIPT) +interface: efinity-build-check $(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 + if ! source "$(EFINITY_SETUP)" >/dev/null; then + echo "Failed to initialize Efinity from $(EFINITY_SETUP)" >&2 + exit 1 + fi 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 +map: efinity-build-check rtl interface @mkdir -p "$(LOG_DIR)" cd "$(FLOW_DIR)" set +u - source "$(EFINITY_SETUP)" >/dev/null 2>&1 + if ! source "$(EFINITY_SETUP)" >/dev/null; then + echo "Failed to initialize Efinity from $(EFINITY_SETUP)" >&2 + exit 1 + fi set -u python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow map 2>&1 | tee "$(LOG_DIR)/map.log" -bitstream: rtl interface +bitstream: efinity-build-check rtl interface @mkdir -p "$(LOG_DIR)" "$(dir $(BIT_FILE))" cd "$(FLOW_DIR)" set +u - source "$(EFINITY_SETUP)" >/dev/null 2>&1 + if ! source "$(EFINITY_SETUP)" >/dev/null; then + echo "Failed to initialize Efinity from $(EFINITY_SETUP)" >&2 + exit 1 + fi set -u : > "$(LOG_DIR)/full.log" python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow map 2>&1 | tee -a "$(LOG_DIR)/full.log" @@ -306,14 +342,17 @@ bitstream: rtl interface fi printf 'Bitstream: %s\nConfiguration HEX: %s\n' "$(BIT_FILE)" "$(CONFIG_HEX)" -program-fpga: +program-fpga: efinity-program-check @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 + if ! source "$(EFINITY_SETUP)" >/dev/null; then + echo "Failed to initialize Efinity from $(EFINITY_SETUP)" >&2 + exit 1 + fi set -u ftdi_args=() if [[ -n "$(FTDI_URL)" ]]; then @@ -365,13 +404,16 @@ flash-regions: software --app-hex "$(APP_HEX)" \ --manifest "$(FLASH_MANIFEST)" -program-flash-loader: +program-flash-loader: efinity-program-check @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 + if ! source "$(EFINITY_SETUP)" >/dev/null; then + echo "Failed to initialize Efinity from $(EFINITY_SETUP)" >&2 + exit 1 + fi set -u ftdi_args=() if [[ -n "$(FTDI_URL)" ]]; then @@ -382,7 +424,10 @@ program-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 + if ! source "$(EFINITY_SETUP)" >/dev/null; then + echo "Failed to initialize Efinity from $(EFINITY_SETUP)" >&2 + exit 1 + fi set -u ftdi_args=() if [[ -n "$(FTDI_URL)" ]]; then @@ -400,7 +445,10 @@ program-flash-bitstream program-bitstream: fi $(MAKE) -C "$(FPGA_DIR)" program-flash-loader set +u - source "$(EFINITY_SETUP)" >/dev/null 2>&1 + if ! source "$(EFINITY_SETUP)" >/dev/null; then + echo "Failed to initialize Efinity from $(EFINITY_SETUP)" >&2 + exit 1 + fi set -u ftdi_args=() if [[ -n "$(FTDI_URL)" ]]; then @@ -413,7 +461,10 @@ program-flash-bitstream program-bitstream: 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 + if ! source "$(EFINITY_SETUP)" >/dev/null; then + echo "Failed to initialize Efinity from $(EFINITY_SETUP)" >&2 + exit 1 + fi set -u ftdi_args=() if [[ -n "$(FTDI_URL)" ]]; then diff --git a/targets/fpga/ti375c529/README.md b/targets/fpga/ti375c529/README.md index f367e0f..5cb3789 100644 --- a/targets/fpga/ti375c529/README.md +++ b/targets/fpga/ti375c529/README.md @@ -16,8 +16,19 @@ 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. +The Makefile auto-discovers versioned Efinity installations under +`/tools/efinix/efinity`, `/opt`, the current user's home directory, and +`tools/local/efinity`. Override discovery when required: + +```bash +make FPGA_BOARD=ti375c529 fpga-bitstream \ + EFINITY_HOME=/path/to/efinity/2025.2 +``` + +`fpga-rtl` does not require Efinity. The `interface`, `bitstream`, and +programming targets require a complete Efinity installation containing +`bin/setup.sh` and `scripts/efx_run.py`; they now stop before hardware +elaboration with a direct diagnostic when it is absent. Programming auto-selects the connected Ti375 development kit. If more than one compatible FTDI device is attached, run `make FPGA_BOARD=ti375c529 diff --git a/targets/fpga/ti375c529/flow/efinity/README.md b/targets/fpga/ti375c529/flow/efinity/README.md index 9ecd46e..e2f95a2 100644 --- a/targets/fpga/ti375c529/flow/efinity/README.md +++ b/targets/fpga/ti375c529/flow/efinity/README.md @@ -9,8 +9,8 @@ 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 Efinity 2025.2 discovery through `EFINITY_HOME`. Common `/tools`, + `/opt`, user-local, and repository-local installation paths are searched. - 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 @@ -280,7 +280,7 @@ 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 +`$(EFINITY_HOME)/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. diff --git a/tools/project.mk b/tools/project.mk index 27cb321..99c9c54 100644 --- a/tools/project.mk +++ b/tools/project.mk @@ -16,10 +16,18 @@ FIRTOOL ?= $(firstword $(wildcard $(SOC_TOOLS_ROOT)/circt-current/bin/firtool) $ Z3_LIB_DIR ?= $(firstword $(wildcard $(SOC_TOOLS_ROOT)/z3-current/bin) $(wildcard $(PROJECT_TOOLS_DIR)/z3/*/bin)) CIRCT_LIB_DIR ?= $(patsubst %/bin/firtool,%/lib,$(FIRTOOL)) VIVADO ?= $(lastword $(sort $(wildcard /tools/Xilinx/*/Vivado/bin/vivado) $(shell command -v vivado 2>/dev/null))) -EFINITY_HOME ?= $(lastword $(sort $(wildcard /tools/efinix/efinity/*))) -EFINITY_SETUP ?= $(EFINITY_HOME)/bin/setup.sh -EFX_RUN ?= $(EFINITY_HOME)/scripts/efx_run.py -EFX_PGM ?= $(EFINITY_HOME)/pgm/bin/ftdi_pgm.sh +_EFINITY_SETUP_CANDIDATES := $(sort \ + $(wildcard /tools/efinix/efinity/*/bin/setup.sh) \ + $(wildcard /opt/efinix/efinity/*/bin/setup.sh) \ + $(wildcard /opt/efinity/bin/setup.sh) \ + $(wildcard /opt/efinity/*/bin/setup.sh) \ + $(wildcard $(HOME)/efinix/efinity/*/bin/setup.sh) \ + $(wildcard $(HOME)/Efinity/*/bin/setup.sh) \ + $(wildcard $(PROJECT_TOOLS_DIR)/efinity/*/bin/setup.sh)) +EFINITY_HOME ?= $(patsubst %/bin/setup.sh,%,$(lastword $(_EFINITY_SETUP_CANDIDATES))) +EFINITY_SETUP ?= $(if $(strip $(EFINITY_HOME)),$(EFINITY_HOME)/bin/setup.sh) +EFX_RUN ?= $(if $(strip $(EFINITY_HOME)),$(EFINITY_HOME)/scripts/efx_run.py) +EFX_PGM ?= $(if $(strip $(EFINITY_HOME)),$(EFINITY_HOME)/pgm/bin/ftdi_pgm.sh) # RISCV_TOOLCHAIN may point either to the toolchain root or its bin directory. # TOOLCHAIN keeps compatibility with the existing software Makefiles.