From 5e0db1ad3a70f516ccb397207fc39ea52bfee3a7 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 24 Feb 2025 13:29:14 +0100 Subject: [PATCH] nxpython support in gantry --- scripts/gantry.py | 28 +++++++++++++- scripts/install_gantry.sh | 3 ++ scripts/nxp_script.py | 81 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 scripts/nxp_script.py diff --git a/scripts/gantry.py b/scripts/gantry.py index 514eca8..c57a2fd 100644 --- a/scripts/gantry.py +++ b/scripts/gantry.py @@ -2,6 +2,10 @@ import typer import elab as elaborate import build_env from typing_extensions import Annotated +import subprocess +import os + +gantry_install_path = "/home/thesis2/exjobb-public/scripts" app = typer.Typer() @@ -40,7 +44,29 @@ def run( print(f"Running (and synthesizing if needed) {topdef} with arch {arch} in library {library}. VHDL {std}") return elaborate.runDesign(topdef, arch, library, std) -@hardware.command() +@hardware.command(help="Synthesizes the provided top level design using NXPython. Make sure you run this with NXPython.") +def synth( + topdef: Annotated[str, typer.Argument(help="Top Definition entity to synthesize")] = "", + library: Annotated[str, typer.Option("--library", "-l", help="Library to compile from, defaults to \"work\"")] = "work" + ): + proc = subprocess.run(["nxpython", f"{gantry_install_path}/nxp_script.py", "synthDesign", library, topdef]) + +@hardware.command(help="Places the provided top level design using NXPython. Make sure you run this with NXPython.") +def place( + topdef: Annotated[str, typer.Argument(help="Top Definition entity to synthesize")] = "", + library: Annotated[str, typer.Option("--library", "-l", help="Library to compile from, defaults to \"work\"")] = "work" + ): + proc = subprocess.run(["nxpython", f"{gantry_install_path}/nxp_script.py", "placeDesign", library, topdef]) + + +@hardware.command(help="Routes the provided top level design using NXPython. Make sure you run this with NXPython.") +def route( + topdef: Annotated[str, typer.Argument(help="Top Definition entity to synthesize")] = "", + library: Annotated[str, typer.Option("--library", "-l", help="Library to compile from, defaults to \"work\"")] = "work" + ): + proc = subprocess.run(["nxpython", f"{gantry_install_path}/nxp_script.py", "routeDesign", library, topdef]) + +@hardware.command(help="") def build(): print("Build!") diff --git a/scripts/install_gantry.sh b/scripts/install_gantry.sh index 673ba6c..f886ba3 100755 --- a/scripts/install_gantry.sh +++ b/scripts/install_gantry.sh @@ -1,6 +1,9 @@ #!/bin/bash PWD=$(pwd) +ESCAPED_PWD=$(printf '%s\n' "$PWD" | sed -e 's/[\/&]/\\&/g') +echo $ESCAPED_PWD +sed -i "0,/gantry_install_path =\"\"/s/gantry_install_path = \"\"/gantry_install_path = \"$ESCAPED_PWD\"/" gantry.py printf "#!/bin/bash \n$PWD/bin/python3 $PWD/gantry.py \$@" > "$PWD/gantry" chmod +x "$PWD/gantry" diff --git a/scripts/nxp_script.py b/scripts/nxp_script.py new file mode 100644 index 0000000..fc310b7 --- /dev/null +++ b/scripts/nxp_script.py @@ -0,0 +1,81 @@ +import os +import subprocess +import build_env +import sys +import traceback +from nxpython import * + +artifact_path = "" + +# Evaluate whether we want the user to provide a selection of files +def makeProject(library: str, project_name: str, path): + # Create an Impulse project and add all VHDL files to it + print(path) + #Createproject enters the implicitly created directory + print(f"Creating project \'{project_name}\'\n") + getProject().setTopCellName(library, project_name) + getProject().setVariantName("NG-MEDIUM", "LGA-625") + getProject().addParameters({}) + print(path) + listed = list(os.listdir(path)) + files = list(filter(lambda x: ".vhdl" in x or ".vhd" in x or ".v\0" in x, listed)) # Find VHDL and Verilog files + files = list(map(lambda x: os.path.join(path, x), files)) + print(f"Adding the following files to project: {files}\n") + getProject().addFiles(files) + print("Saving project") + getProject().save(os.path.join(artifact_path, project_name + ".nym")) + return 0 + +# Do we want the user to specify how far they want to progress wach step? What does the number mean? +def synthDesign(library: str, project_name: str, path): + # Synthesize the design of the project of the provided `project_name` + print("Starting synthesis\n") + try: + nymFile = os.path.join(artifact_path, project_name + ".nym") + os.lstat(nymFile) + getProject().loadNative(nymFile) + except: + print("No existing project found, creating new project\n") + makeProject(library, project_name, path) + getProject().loadNative(os.path.join(artifact_path, project_name + ".nym")) + getProject().progress("Synthesize", 3) + getProject().save(os.path.join(artifact_path, project_name + "-synth.nym")) + return 0 + +def placeDesign(library: str, project_name: str, path): + # Place the given design. Will use a previously synthesized project if available, otherwise one will be created. + print("Starting place\n") + try: + nymFile = os.path.join(artifact_path, project_name + "-synth.nym") + os.lstat(nymFile) + getProject().load(nymFile) + except: + print("No existing synthesis found, entering synthesis stage\n") + synthDesign(library, project_name, path) + getProject().load(os.path.join(artifact_path, project_name + "-synth.nym")) + getProject().progress("Place", 5) + getProject().save(os.path.join(artifact_path, project_name + "-place.nym")) + +def routeDesign(library: str, project_name: str, path): + # Route the given design. Will use a previously placed project if available, otherwise one will be created. + print("Starting route\n") + try: + nymFile = os.path.join(artifact_path, project_name + "-place.nym") + os.lstat(nymFile) + getProject().load(nymFile) + except: + print("No existing place found, entering place stage\n") + placeDesign(library, project_name, path) + getProject().load(os.path.join(artifact_path, project_name + "-place.nym")) + getProject().progress("Route", 3) + getProject().save(os.path.join(artifact_path, project_name + "-route.nym")) + + +if __name__ == "__main__": + path = os.getcwd() + artifact_path = os.path.join(path, "syn") + print(f"Calling {sys.argv[1]}() with arguments {sys.argv[2]}, {sys.argv[3]}") + createProject(artifact_path) + globals()[sys.argv[1]](sys.argv[2], sys.argv[3], path) + getProject().createAnalyzer() + getProject().getAnalyzer().launch(conditions="worstcase", maximumSlack=0, searchPathsLimit=10, synthesisMode=False)