fpga: tools: error out on unconstrained paths for diamond builds

This commit is contained in:
Max Köhler 2025-06-25 12:21:32 +02:00 committed by Wade Fife
parent f3fa2e73c2
commit e329fd0474
2 changed files with 68 additions and 0 deletions

View File

@ -31,6 +31,13 @@ BUILD_DIAMOND_DESIGN = \
export LC_ALL=en_US.UTF-8; \
cp $(TOOLS_DIR)/scripts/dmd_design_build.tcl $(4)/build.tcl; \
cd $(4); \
echo "BUILDER: Checking variables..."; \
python3 $(TOOLS_DIR)/scripts/diamond_check_variables.py $(1).lpf; \
if [ $$? -ne 0 ]; \
then \
echo "BUILDER: Diamond variable check failed."; \
exit 1; \
fi; \
echo "BUILDER: Implementating design..."; \
$(DIAMOND_EXE) build.tcl > $(1)_log.txt ; \
if [ $$? -ne 0 ]; \
@ -45,6 +52,18 @@ BUILD_DIAMOND_DESIGN = \
echo "BUILDER: Timing failed. See $(1)_impl1.twr for details."; \
exit 1; \
fi; \
grep "unconstrained" impl1/$(1)_impl1.twr | grep -v "0 unconstrained" > /dev/null 2>&1; \
if [ $$? -eq 0 ]; \
then \
echo "BUILDER: Unconstrained paths found. See $(1)_impl1.twr for details."; \
exit 1; \
fi; \
grep "Semantic error" impl1/$(1)_impl1.mrp > /dev/null 2>&1; \
if [ $$? -eq 0 ]; \
then \
echo "BUILDER: Semantic error found. See $(1)_impl1.mrp for details."; \
exit 1; \
fi; \
echo "BUILDER: Generating bitfile..."; \
ddtcmd -oft -svfsingle -if $(5)/$(1)_$(5).jed \
-dev $(2) -op "FLASH Erase,Program,Verify" -revd \

View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
#
# Copyright 2025 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
# Checks whether all variables in a Diamond lpf file are defined before usage.
# This check is not done in Diamond, so there is no error or warning message for us to
# check for.
#
import argparse
import re
def parse_arguments():
parser = argparse.ArgumentParser(description="Check variables in a Diamond lpf file")
parser.add_argument("filename", type=str, help="The lpf file to check")
parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose output")
return parser.parse_args()
args = parse_arguments()
defined_variables = set()
pattern = re.compile(r"(@define\s+)?\$(\w+)")
# search the file line by line
with open(args.filename, "r") as f:
for line_number, line in enumerate(f, start=1):
position = 0
match = True
while match:
match = pattern.search(line, position)
if match:
# If group 1 is present we have a define and add the variable to the set
if match.group(1):
defined_variables.add(match.group(2))
if args.verbose:
print(f"Line {line_number},{position}: Define variable {match.group(2)}")
# Otherwise it is a usage and we check if the variable is defined
else:
if args.verbose:
print(f"Line {line_number},{position}: Use of variable {match.group(2)}")
if match.group(2) not in defined_variables:
raise Exception(
f"Error: Variable {match.group(2)} is used before being defined"
)
position = match.end(2)