fixed automatic analysis when elaborating
This commit is contained in:
parent
b9f4929726
commit
7b5ab586cb
@ -3,7 +3,7 @@ from re import split
|
||||
import subprocess
|
||||
from typing import List
|
||||
|
||||
from project_man import addLibraryInProject, removeLibraryInProject
|
||||
from project_man import addLibraryInProject, getLibraryInProject, removeLibraryInProject
|
||||
|
||||
def getCfFileId(std: str):
|
||||
return "08" if std == "08" else "93" ## Weird behaviour from GHDL, but all vhdl versions besides 08 have [...]93.cf
|
||||
@ -48,21 +48,19 @@ def addVHDLFiles(fileNames: List[str], std: str, lib: str):
|
||||
print("no files to add.")
|
||||
return 0
|
||||
print(f"adding {vhdlFiles} to library {lib}")
|
||||
command = ["ghdl", "-i", "--workdir=work", f"--work={lib}", f"--std={std}"] + vhdlFiles
|
||||
command = ["ghdl", "-i", "-C", "--workdir=work", f"--work={lib}", f"--std={std}"] + vhdlFiles
|
||||
subprocess.run(command)
|
||||
return 0
|
||||
|
||||
def removeVHDLFiles(fileNames: List[str], std: str, lib: str):
|
||||
if not ghdlEnvExists(std=std, lib=lib):
|
||||
return -1
|
||||
cfFileId = getCfFileId(std)
|
||||
cfFileName = list(filter(lambda x: ".cf" in x and lib in x and cfFileId in x, os.listdir("work")))[0]
|
||||
cfFilePath = os.path.join("work",cfFileName)
|
||||
cfFilePath = getCfFilePath(std, lib)
|
||||
currentlyAdded = getCurrentlyAddedFiles(cfFilePath)
|
||||
|
||||
for fileName in fileNames:
|
||||
if fileName not in currentlyAdded:
|
||||
print(f"file {fileName} is not present in {cfFileName}.")
|
||||
print(f"file {fileName} is not present in {cfFilePath}.")
|
||||
return 0
|
||||
currentlyAdded.remove(fileName)
|
||||
removeCurrentlyAddedFile(fileName, cfFilePath)
|
||||
@ -72,11 +70,24 @@ def removeVHDLFiles(fileNames: List[str], std: str, lib: str):
|
||||
os.remove(cfFilePath)
|
||||
|
||||
|
||||
def getCfFilePath(std: str, lib: str):
|
||||
(exists, libDict) = getLibraryInProject(lib)
|
||||
if not exists:
|
||||
cfFileId = getCfFileId(std)
|
||||
cfFileName = list(filter(lambda x: ".cf" in x and lib in x and cfFileId in x, os.listdir("work")))[0]
|
||||
return os.path.join("work",cfFileName)
|
||||
|
||||
workDir = os.path.join(libDict[lib]["path"], "work")
|
||||
cfFileId = getCfFileId(std)
|
||||
cfFileName = list(filter(lambda x: ".cf" in x and lib in x and cfFileId in x, os.listdir(workDir)))[0]
|
||||
return os.path.join(workDir,cfFileName)
|
||||
|
||||
|
||||
def getCurrentlyAddedFiles(cfFilePath:str):
|
||||
f = open(cfFilePath,"r")
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
fileLines = filter(lambda x: "file" in x, lines)
|
||||
fileLines = filter(lambda x: "file" in split(" ", x)[0], lines)
|
||||
files = map(lambda x: split("\" \"",x)[1], fileLines)
|
||||
return list(files)
|
||||
|
||||
|
||||
92
src/elab.py
92
src/elab.py
@ -1,6 +1,7 @@
|
||||
import os
|
||||
import subprocess
|
||||
import build_env
|
||||
import pprint
|
||||
from re import split, sub
|
||||
from typing import List
|
||||
from project_man import getLibrariesPresent, getLibrariesInProject, getLibraryInProject
|
||||
@ -17,54 +18,81 @@ def getNeededDependencies(topDef: str, arch: str, lib: str, std: str, includes:
|
||||
"-Wno-unhandled-attribute", "-Wno-elaboration"
|
||||
]
|
||||
command = [
|
||||
"ghdl", "--elab-order", "--workdir=work", f"--work={lib}", f"--std={std}"
|
||||
"ghdl","--gen-depends", "-C", "-fsynopsys", "--ieee=standard", "-fexplicit", "--workdir=work", f"--work={lib}", f"--std={std}", "-frelaxed-rules"
|
||||
] + incs + disableWarnings + [
|
||||
"--libraries", f"{topDef}", f"{arch}"
|
||||
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)
|
||||
res = split("#", res.stdout.decode())
|
||||
res = split("\r\n", res[-1])[1:-1]
|
||||
res = list(filter(lambda x: x[0] != '/', res))
|
||||
res = list(map(lambda x: split(":", x)[0], res))
|
||||
res = list(map(lambda x: split("/", x[0:-2]), res))
|
||||
res = list(map(lambda x: {"libPath":"/".join(x[0:-2]), "fileName":x[-1]}, res))
|
||||
|
||||
print(res)
|
||||
return res
|
||||
|
||||
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]):
|
||||
print(f"Analyzing dependecies to {topDef} {arch}")
|
||||
deps = getNeededDependencies(topDef, arch, lib, std, includes)
|
||||
incs = generateIncludesForGHDL(includes)
|
||||
print(incs)
|
||||
[exists, libDict] = getLibrariesInProject()
|
||||
pprint.pp(deps)
|
||||
pprint.pp(libDict)
|
||||
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]))
|
||||
|
||||
succesful = 0
|
||||
total = 0
|
||||
for dep in deps:
|
||||
currLibPath = dep["libPath"]
|
||||
currFile = dep["fileName"]
|
||||
currLib = ""
|
||||
currStd = ""
|
||||
for lib in libDict.keys():
|
||||
if libDict[lib]["path"] == currLibPath:
|
||||
currLib = lib
|
||||
currStd = libDict[lib]["vhdl-version"]
|
||||
if currLib == "":
|
||||
print(f"no lib inferred for {currLibPath}")
|
||||
continue
|
||||
##filesNames = list(map(lambda x: split("/",x)[-1],deps[currLib]))
|
||||
##vhdlFiles = list(map(lambda x: os.path.join(currLibPath, x),deps[currLib]))
|
||||
##vhdlFiles = list(filter(lambda x: ".vhd" in x, os.listdir(currLibPath)))
|
||||
##vhdlFiles = list(map(lambda x: os.path.join(currLibPath, x), vhdlFiles))
|
||||
incs = generateIncludesForGHDL(includes, currLibPath)
|
||||
vhdlFiles = build_env.getCurrentlyAddedFiles(build_env.getCfFilePath(currStd, currLib))
|
||||
if len(vhdlFiles) == 0:
|
||||
continue
|
||||
print(f"Analyzing dependecies in {currLib}: {filesNames}")
|
||||
currFileName = ""
|
||||
for vhdlFile in vhdlFiles:
|
||||
test = split("/",vhdlFile)[-1]
|
||||
test = split(".vhd", test)[0]
|
||||
if test == currFile:
|
||||
currFileName = vhdlFile
|
||||
if currFileName == "":
|
||||
print(f"no file name found for {currFile}")
|
||||
return
|
||||
total = total + 1
|
||||
command = [
|
||||
"ghdl", "-a", f"--workdir={os.path.join(currLibPath, 'work')}", f"--work={currLib}", f"--std={std}"
|
||||
] + incs + vhdlFiles
|
||||
subprocess.run(command)
|
||||
"ghdl", "-a", "-C", "-fsynopsys", "--ieee=standard", "-fexplicit" ,"--workdir=work", f"--work={currLib}", f"--std={std}", "-frelaxed-rules"
|
||||
] + incs + [currFileName]
|
||||
res = subprocess.run(command, cwd=currLibPath)
|
||||
if res.returncode == 0:
|
||||
succesful = succesful + 1
|
||||
print(f"Successfully analyzed {currLib} - {currFileName}")
|
||||
else:
|
||||
print(f"Failed analysis {currLib} - {currFileName}")
|
||||
print(f"Successfully analyzed {succesful}/{total} VHDL sources")
|
||||
|
||||
|
||||
def generateIncludesForGHDL(includes: List[str]):
|
||||
def generateIncludesForGHDL(includes: List[str], cwd=os.getcwd()):
|
||||
cmd = []
|
||||
[exists, projectLibs] = getLibrariesInProject()
|
||||
[exists, projectLibs] = getLibrariesInProject(cwd=cwd)
|
||||
if not exists:
|
||||
return []
|
||||
for lib in projectLibs.keys():
|
||||
@ -80,10 +108,12 @@ def elabDesign(topDef: str, arch: str, lib: str, std: str, includes: List[str]):
|
||||
print("No GHDL environment present. Add all needed files before elaborating")
|
||||
analyzeNeededDependencies(topDef, arch, lib, std, includes)
|
||||
incs = generateIncludesForGHDL(includes)
|
||||
print("Dependecy analysis complete, continuing to elaboration")
|
||||
command = [
|
||||
"ghdl", "-m", "--workdir=work", f"--work={lib}", f"--std={std}"
|
||||
"ghdl", "-m", "-C","-fsynopsys", "--ieee=standard", "-fexplicit" , "--workdir=work", f"--work={lib}", f"--std={std}"
|
||||
] + incs + [
|
||||
"-o", f"work/{topDef}-{arch}", f"work.{topDef}", f"{arch}"]
|
||||
print(" ".join(command))
|
||||
subprocess.run(command)
|
||||
|
||||
def runDesign(topDef: str, arch: str, lib: str, std: str, includes):
|
||||
@ -93,7 +123,7 @@ 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}"
|
||||
"ghdl", "--elab-run", "-C", 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=<See"
|
||||
]
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import typer
|
||||
import os
|
||||
from re import split
|
||||
from project_man import findProjectFile, getLibraryInProject, initProjectFile, addLibraryInProject, removeLibraryInProject, getLibrariesPresent
|
||||
import elab as elaborate
|
||||
import build_env
|
||||
@ -7,7 +8,7 @@ from typing import List, Optional
|
||||
from typing_extensions import Annotated
|
||||
import subprocess
|
||||
|
||||
gantry_install_path = "/home/thesis1/exjobb-public/scripts"
|
||||
gantry_install_path = "/home/thesis1/repos/gantry/src"
|
||||
|
||||
app = typer.Typer()
|
||||
|
||||
@ -25,7 +26,9 @@ def autoDetectLibrary(lib: str) -> str:
|
||||
if not exists:
|
||||
print("No libs found.")
|
||||
return "work"
|
||||
if len(presentLibs.keys()) == 1:
|
||||
if len(presentLibs.keys()) == 0:
|
||||
return split("/",os.getcwd())[-1]
|
||||
elif len(presentLibs.keys()) == 1:
|
||||
return presentLibs.popitem()[0]
|
||||
else:
|
||||
libs = list(map(lambda x: x[0], presentLibs.items()))
|
||||
@ -48,7 +51,7 @@ def autoDetectStd(library: str, std: str) -> str:
|
||||
if std == "" or std not in complete_vhdl_ver():
|
||||
(exists, libDict) = getLibraryInProject(library)
|
||||
if not exists:
|
||||
return "93"
|
||||
return "93c"
|
||||
else:
|
||||
return libDict["vhdl-version"]
|
||||
else:
|
||||
@ -69,7 +72,7 @@ def create(
|
||||
def addLib(
|
||||
libname: Annotated[str, typer.Argument(help="Name of the library. This is what is used for imports in VHDL.")],
|
||||
libpath: Annotated[str, typer.Argument(help="Relative path to the library. This tells simulators where to import form.")],
|
||||
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93"
|
||||
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 94c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93c"
|
||||
):
|
||||
print(f"Adding library {libname} to gantry.toml")
|
||||
addLibraryInProject(libname, libpath, std)
|
||||
@ -84,7 +87,7 @@ def removeLib(
|
||||
@software.command(help="Adds files to a library. Automatically updates gantry project file and creates GHDL project files")
|
||||
def add(
|
||||
filenames: Annotated[List[str], typer.Argument(help="Which files to add to the library. May be more than one.")],
|
||||
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93",
|
||||
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93c",
|
||||
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile to.")] = ""
|
||||
):
|
||||
library = autoDetectLibrary(library)
|
||||
@ -97,7 +100,7 @@ def add(
|
||||
@software.command(help="Removes files from a library. Automatically updates gantry project file and creates GHDL project files")
|
||||
def remove(
|
||||
filenames: Annotated[List[str], typer.Argument(help="Which files to add to the library. May be more than one.")],
|
||||
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93",
|
||||
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93c",
|
||||
library: Annotated[str, typer.Option("--library", "-l", help="Library to compile to.")] = ""
|
||||
):
|
||||
library = autoDetectLibrary(library)
|
||||
@ -111,7 +114,7 @@ def elab(
|
||||
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,
|
||||
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93"
|
||||
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93c"
|
||||
):
|
||||
library = autoDetectLibrary(library)
|
||||
std = autoDetectStd(library, std)
|
||||
@ -128,7 +131,7 @@ def run(
|
||||
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,
|
||||
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93"
|
||||
std: Annotated[str, typer.Option(help="Which VHDL standard to use. 87, 93, 93c, 00, 02 or 08", autocompletion=complete_vhdl_ver)] = "93c"
|
||||
):
|
||||
library = autoDetectLibrary(library)
|
||||
std = autoDetectStd(library, std)
|
||||
|
||||
@ -112,7 +112,7 @@ def addLibraryInProject(lib: str, relPath: str, std: str) -> "tuple[bool, str]":
|
||||
return (wentWell, "")
|
||||
return (False, "Library with this name is already declared")
|
||||
|
||||
def getLibraryInProject(lib: str) -> "tuple[bool, dict[str, Any]]":
|
||||
def getLibraryInProject(lib: str, cwd=os.getcwd()) -> "tuple[bool, dict[str, Any]]":
|
||||
(exists, projectDict) = getProjectDict()
|
||||
if not exists:
|
||||
return (False, {})
|
||||
@ -122,9 +122,12 @@ def getLibraryInProject(lib: str) -> "tuple[bool, dict[str, Any]]":
|
||||
return (False, {})
|
||||
(_, projectRoot) = findProjectRoot()
|
||||
if lib in projectDict["libraries"].keys():
|
||||
return (True, projectDict["libraries"][lib])
|
||||
libs[lib] = projectDict["libraries"][lib]
|
||||
absPath = os.path.join(projectRoot, libs[lib]["path"])
|
||||
libs[lib]["path"] = os.path.relpath(absPath, cwd)
|
||||
return (True, libs)
|
||||
return (False, {})
|
||||
def getLibrariesInProject() -> "tuple[bool, dict[str, Any]]":
|
||||
def getLibrariesInProject(cwd=os.getcwd()) -> "tuple[bool, dict[str, Any]]":
|
||||
(exists, projectDict) = getProjectDict()
|
||||
if not exists:
|
||||
return (False, {})
|
||||
@ -136,11 +139,10 @@ def getLibrariesInProject() -> "tuple[bool, dict[str, Any]]":
|
||||
for lib in projectDict["libraries"].keys():
|
||||
libs[lib] = projectDict["libraries"][lib]
|
||||
absPath = os.path.join(projectRoot, libs[lib]["path"])
|
||||
libs[lib]["path"] = os.path.relpath(absPath, os.getcwd())
|
||||
libs[lib]["path"] = os.path.relpath(absPath, cwd)
|
||||
return (True, libs)
|
||||
|
||||
def getLibrariesPresent() -> "tuple[bool, dict[str, Any]]":
|
||||
cwd = os.getcwd()
|
||||
def getLibrariesPresent(cwd=os.getcwd()) -> "tuple[bool, dict[str, Any]]":
|
||||
(exists, libs) = getLibrariesInProject()
|
||||
if not exists:
|
||||
return (False, {})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user