diff --git a/src/elab.py b/src/elab.py index d5be319..1e7cec6 100644 --- a/src/elab.py +++ b/src/elab.py @@ -1,8 +1,66 @@ import os import subprocess import build_env +from re import split, sub from typing import List -from project_man import getLibrariesPresent, getLibrariesInProject +from project_man import getLibrariesPresent, getLibrariesInProject, getLibraryInProject + +## returns list of dicts containing {lib: ..., file: ...} in correct compile order +def getNeededDependencies(topDef: str, arch: str, lib: str, std: str, includes: List[str]): + incs = generateIncludesForGHDL(includes) + disableWarnings = [ + "-Wno-library", "-Wno-deprecated-option", "-Wno-unexpected-option", + "-Wno-binding", "-Wno-port", "-Wno-pragma", "-Wno-specs", "-Wno-runtime-error", + "-Wno-missing-wait", "-Wno-shared", "-Wno-hide", "-Wno-nowrite", + "-Wno-logic-loop", "-Wno-pure", "-Wno-analyze-assert", "-Wno-attribute", + "-Wno-useless", "-Wno-open-assoc", "-Wno-conformance", "-Wno-unkept-attribute", + "-Wno-unhandled-attribute", "-Wno-elaboration" + ] + command = [ + "ghdl", "--elab-order", "--workdir=work", f"--work={lib}", f"--std={std}" + ] + incs + disableWarnings + [ + "--libraries", f"{topDef}", f"{arch}" + ] + res = subprocess.run(command,capture_output=True) + if res.returncode != 0: + print(res.stdout, res.stderr) + res = split("\r\n", res.stdout.decode()) + res = res[0:-1] + res = list(map(lambda x: {"lib": split(" ",x)[0], "file": split(" ", x)[1]}, res)) + res = list(filter(lambda x: x["lib"] != lib, res)) + outputDict = {} + for x in res: + if x["lib"] not in outputDict.keys(): + outputDict[x["lib"]] = [] + ## For some reason, GHDL doesn't play nice with relative include paths, so + ## many unnecessary "cd thing/.." occurs in a row. This regex fixes that. + fixed = sub(r"\w*/../","", x["file"]) + outputDict[x["lib"]].append(fixed) + + print(outputDict) + return outputDict + +## anylyzes the needed dependecies such that elaboration using libraries is nice :) +def analyzeNeededDependencies(topDef: str, arch: str, lib: str, std: str, includes: List[str]): + deps = getNeededDependencies(topDef, arch, lib, std, includes) + incs = generateIncludesForGHDL(includes) + print(incs) + [exists, libDict] = getLibrariesInProject() + if not exists: + print("project doesn't exist") + return + for currLib in deps.keys(): + currLibPath = libDict[currLib]["path"] + filesNames = list(map(lambda x: split("/",x)[-1],deps[currLib])) + vhdlFiles = list(map(lambda x: os.path.join(currLibPath, x),deps[currLib])) + if len(vhdlFiles) == 0: + continue + print(f"Analyzing dependecies in {currLib}: {filesNames}") + command = [ + "ghdl", "-a", f"--workdir={os.path.join(currLibPath, 'work')}", f"--work={currLib}", f"--std={std}" + ] + incs + vhdlFiles + subprocess.run(command) + def generateIncludesForGHDL(includes: List[str]): cmd = [] @@ -20,9 +78,12 @@ def generateIncludesForGHDL(includes: List[str]): def elabDesign(topDef: str, arch: str, lib: str, std: str, includes: List[str]): if not build_env.ghdlEnvExists(std, lib): print("No GHDL environment present. Add all needed files before elaborating") + analyzeNeededDependencies(topDef, arch, lib, std, includes) incs = generateIncludesForGHDL(includes) command = [ - "ghdl", "-m", "--workdir=work", f"--work={lib}", f"--std={std}"] + incs + ["-o", f"work/{topDef}-{arch}", f"work.{topDef}", f"{arch}"] + "ghdl", "-m", "--workdir=work", f"--work={lib}", f"--std={std}" + ] + incs + [ + "-o", f"work/{topDef}-{arch}", f"work.{topDef}", f"{arch}"] subprocess.run(command) def runDesign(topDef: str, arch: str, lib: str, std: str, includes): @@ -32,11 +93,13 @@ def runDesign(topDef: str, arch: str, lib: str, std: str, includes): wavePath = os.path.join(os.getcwd(), "wave") incs = generateIncludesForGHDL(includes) command = [ ## may add -v for verbose - "ghdl", "--elab-run", f"--workdir=work", f"--work={lib}", f"--std={std}"] + incs + ["-o", f"work/{topDef}-{arch}", f"{topDef}", f"{arch}", - f"--wave=wave/{topDef}-{arch}.ghw" ##, "--read-wave-opt=