Added library support for nxp_script

This commit is contained in:
Adam 2025-03-28 17:07:38 +01:00
parent 7b5ab586cb
commit 4ea39b4333
3 changed files with 94 additions and 31 deletions

View File

@ -1,14 +1,22 @@
import typer
import os
<<<<<<< HEAD
from re import split
from project_man import findProjectFile, getLibraryInProject, initProjectFile, addLibraryInProject, removeLibraryInProject, getLibrariesPresent
=======
from project_man import findProjectRoot, getProjectDict, getLibrariesInProject, findProjectFile, getLibraryInProject, getSourceFilesWithLib, initProjectFile, addLibraryInProject, removeLibraryInProject, getLibrariesPresent
>>>>>>> 8bf7864 (Added library support for nxp_script)
import elab as elaborate
import build_env
from typing import List, Optional
from typing_extensions import Annotated
import subprocess
<<<<<<< HEAD
gantry_install_path = "/home/thesis1/repos/gantry/src"
=======
gantry_install_path = "/home/thesis2/gantry/src"
>>>>>>> 8bf7864 (Added library support for nxp_script)
app = typer.Typer()
@ -145,22 +153,42 @@ def run(
@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 todefaults to \"\"")] = ""
arch: Annotated[str, typer.Argument(help="Architecture to synthesize within the top definition provided")] = "",
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile to")] = "",
includes: Annotated[Optional[List[str]], typer.Option("--include", "-i", help="Which libraries to include in compile")] = None,
):
proc = subprocess.run(["source_and_run.sh", f"{gantry_install_path}/nxp_script.py", "synthDesign", library, topdef])
library = autoDetectLibrary(library)
print(f"Synthesizing {topdef} with arch {arch} in library {library}.")
if includes is not None:
print(f"Including libraries: {includes}")
else:
_, includes = getSourceFilesWithLib() # TODO: Error handling
_, proj_root = findProjectRoot()
proc = subprocess.run(["source_and_run.sh", # Source NXPython
f"{gantry_install_path}/nxp_script.py", # Run script
"synthDesign", # Function call
library, # Function arguments
topdef,
proj_root] +
includes
)
@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 to. If current directory contains libraries, it will be automatically detected")] = ""
topdef: Annotated[str, typer.Argument(help="Top Definition entity to place")] = "",
arch: Annotated[str, typer.Argument(help="Architecture to place within the top definition provided")] = "",
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile to. If current directory contains libraries, it will be automatically detected")] = "",
includes: Annotated[Optional[List[str]], typer.Option("--include", "-i", help="Which libraries to include in compile")] = None,
):
proc = subprocess.run(["source_and_run.sh", 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 to. If current directory contains libraries, it will be automatically detected")] = ""
topdef: Annotated[str, typer.Argument(help="Top Definition entity to route")] = "",
arch: Annotated[str, typer.Argument(help="Architecture to route within the top definition provided")] = "",
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile to. If current directory contains libraries, it will be automatically detected")] = "",
includes: Annotated[Optional[List[str]], typer.Option("--include", "-i", help="Which libraries to include in compile")] = None,
):
proc = subprocess.run(["source_and_run.sh", f"{gantry_install_path}/nxp_script.py", "routeDesign", library, topdef])

View File

@ -1,72 +1,79 @@
import os
import subprocess
import build_env
import sys
import traceback
from nxpython import *
artifact_path = ""
def getNXFormatedIncludes(path, libs) -> "tuple[bool, list[tuple[str, str]]]":
printRemark("These libraries exst in the project: " + str(libs))
includes = []
for lib in libs:
listed = list(os.listdir(os.path.join(path, lib)))
files = list(filter(lambda x: ".vhdl" in x or ".vhd" in x or ".v\0" in x, listed)) # Find VHDL and Verilog files
lib_name = str.split(lib, "/")[-1]
includes = includes + list(map(lambda x: (lib_name, os.path.join(lib, x)), files))
return (True, includes)
# Evaluate whether we want the user to provide a selection of files
def makeProject(library: str, project_name: str, path):
def makeProject(library: str, project_name: str, includes: "list[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")
# Createproject enters the implicitly created directory
printRemark(f"Creating project \'{project_name}\'\n")
printRemark(f"Setting topcell name to {project_name} in library {library}")
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")
for lib, file in includes:
printRemark(f"Adding file {os.path.join(path, file)} from lib {lib}")
getProject().addFile(lib, os.path.join(path, file))
printRemark("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):
def synthDesign(library: str, project_name: str, includes: "list[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)
printRemark("No existing project found, creating new project\n")
makeProject(library, project_name, includes, path)
getProject().loadNative(os.path.join(artifact_path, project_name + ".nym"))
printRemark("Starting synthesis\n")
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):
def placeDesign(library: str, project_name: str, includes: "list[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)
printRemark("No existing synthesis found, entering synthesis stage\n")
synthDesign(library, project_name, includes, path)
getProject().load(os.path.join(artifact_path, project_name + "-synth.nym"))
printRemark("Starting place\n")
getProject().progress("Place", 5)
getProject().save(os.path.join(artifact_path, project_name + "-place.nym"))
def routeDesign(library: str, project_name: str, path):
def routeDesign(library: str, project_name: str, includes: "list[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)
printRemark("No existing place found, entering place stage\n")
placeDesign(library, project_name, includes, path)
getProject().load(os.path.join(artifact_path, project_name + "-place.nym"))
printRemark("Starting route\n")
getProject().progress("Route", 3)
getProject().save(os.path.join(artifact_path, project_name + "-route.nym"))
@ -76,6 +83,11 @@ if __name__ == "__main__":
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)
nx_includes = []
for i in range(5, len(sys.argv[5:]), 2):
nx_includes.append((sys.argv[i], sys.argv[i + 1]))
printRemark("\nNX_INCLUDES ARE: " + str(nx_includes) + "\n")
# <Function Name>(Library, Topdef, Includes, Working_dir)
globals()[sys.argv[1]](sys.argv[2], sys.argv[3], nx_includes, path)
getProject().createAnalyzer()
getProject().getAnalyzer().launch(conditions="worstcase", maximumSlack=0, searchPathsLimit=10, synthesisMode=False)

View File

@ -127,6 +127,7 @@ def getLibraryInProject(lib: str, cwd=os.getcwd()) -> "tuple[bool, dict[str, Any
libs[lib]["path"] = os.path.relpath(absPath, cwd)
return (True, libs)
return (False, {})
def getLibrariesInProject(cwd=os.getcwd()) -> "tuple[bool, dict[str, Any]]":
(exists, projectDict) = getProjectDict()
if not exists:
@ -152,6 +153,28 @@ def getLibrariesPresent(cwd=os.getcwd()) -> "tuple[bool, dict[str, Any]]":
libsInCwd[lib] = libs[lib]
return (True, libsInCwd)
# TODO: Make this function recursively look in folders in the library directory
# Returns a list in the format [<lib>, <file_path>, <lib>, <file_path>...]
# This is used for sending the files to NXPython
def getSourceFilesWithLib() -> "tuple[bool, list[str]]":
exists, proj_dict = getProjectDict()
if not exists:
return (False, [])
if "libraries" not in proj_dict.keys():
## Successful read, no libs found -> empty return
return (True, [])
_, proj_root = findProjectRoot()
result = []
cwd = os.getcwd()
for lib in proj_dict["libraries"].keys():
listed = list(os.listdir(os.path.join(proj_root, lib)))
files = list(filter(lambda x: ".vhdl" in x or ".vhd" in x or ".v\0" in x, listed)) # Find VHDL and Verilog files
for file in files:
result.append(lib)
rel_file_path = os.path.relpath(os.path.join(proj_root, lib, file), cwd)
result.append(rel_file_path)
return (True, result)
def createProjectFileTemplate(projectName: str) -> str:
return f"""
title = "{projectName}"