Skip to content

Commit cd2edd1

Browse files
authored
Parse with DOM and set Attributes to File/FileSet
2 parents 53bd8e1 + 0948f02 commit cd2edd1

File tree

6 files changed

+186
-50
lines changed

6 files changed

+186
-50
lines changed

pyEDAA/ProjectModel/Xilinx/Vivado.py

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,46 @@
3030
# ============================================================================
3131
#
3232
from pathlib import Path
33+
from typing import Iterable
3334

34-
from lxml import etree
35+
from xml.dom import minidom, Node
3536
from pyVHDLModel import VHDLVersion
3637
from pydecor import export
3738

38-
from pyEDAA.ProjectModel import ConstraintFile, ProjectFile, XMLFile, XMLContent, SDCContent, Project, FileSet, \
39-
VHDLSourceFile, File, VerilogSourceFile
39+
from pyEDAA.ProjectModel import ProjectFile, XMLFile, XMLContent, SDCContent, Project, FileSet, File, Attribute
40+
from pyEDAA.ProjectModel import File as Model_File
41+
from pyEDAA.ProjectModel import ConstraintFile as Model_ConstraintFile
42+
from pyEDAA.ProjectModel import VerilogSourceFile as Model_VerilogSourceFile
43+
from pyEDAA.ProjectModel import VHDLSourceFile as Model_VHDLSourceFile
44+
45+
46+
@export
47+
class UsedInAttribute(Attribute):
48+
KEY = "UsedIn"
49+
VALUE_TYPE = Iterable[str]
50+
51+
def __init__(self):
52+
super().__init__()
53+
54+
55+
@export
56+
class File(Model_File):
57+
pass
58+
59+
60+
@export
61+
class ConstraintFile(Model_ConstraintFile):
62+
pass
63+
64+
65+
@export
66+
class VerilogSourceFile(Model_VerilogSourceFile):
67+
pass
68+
69+
70+
@export
71+
class VHDLSourceFile(Model_VHDLSourceFile):
72+
pass
4073

4174

4275
@export
@@ -54,33 +87,33 @@ def Parse(self):
5487
raise Exception(f"Vivado project file '{self._path!s}' not found.") from FileNotFoundError(f"File '{self._path!s}' not found.")
5588

5689
try:
57-
with self._path.open(encoding="utf-8") as fileHandle:
58-
content = fileHandle.read()
59-
content = bytes(bytearray(content, encoding="utf-8"))
60-
except OSError as ex:
90+
root = minidom.parse(str(self._path)).documentElement
91+
except Exception as ex:
6192
raise Exception(f"Couldn't open '{self._path!s}'.") from ex
6293

63-
XMLParser = etree.XMLParser(remove_blank_text=True, encoding="utf-8")
64-
root = etree.XML(content, XMLParser)
65-
6694
self._xprProject = Project(self._path.stem, rootDirectory=self._path.parent)
6795
self._ParseRootElement(root)
6896

6997
def _ParseRootElement(self, root):
70-
filesetsNode = root.find("FileSets")
71-
for filesetNode in filesetsNode:
72-
self._ParseFileSet(filesetNode)
98+
for rootNode in root.childNodes:
99+
if rootNode.nodeName == "FileSets":
100+
for fileSetsNode in rootNode.childNodes:
101+
if fileSetsNode.nodeType == Node.ELEMENT_NODE and fileSetsNode.tagName == "FileSet":
102+
self._ParseFileSet(fileSetsNode)
73103

74104
def _ParseFileSet(self, filesetNode):
75-
filesetName = filesetNode.get("Name")
105+
filesetName = filesetNode.getAttribute("Name")
76106
fileset = FileSet(filesetName, design=self._xprProject.DefaultDesign)
77107

78-
for fileNode in filesetNode:
79-
if fileNode.tag == "File":
80-
self._ParseFile(fileNode, fileset)
108+
for fileNode in filesetNode.childNodes:
109+
if fileNode.nodeType == Node.ELEMENT_NODE:
110+
if fileNode.tagName == "File":
111+
self._ParseFile(fileNode, fileset)
112+
elif fileNode.nodeType == Node.ELEMENT_NODE and fileNode.tagName == "Config":
113+
self._ParseFileSetConfig(fileNode, fileset)
81114

82115
def _ParseFile(self, fileNode, fileset):
83-
croppedPath = fileNode.get("Path").replace("$PPRDIR/", "")
116+
croppedPath = fileNode.getAttribute("Path").replace("$PPRDIR/", "")
84117
filePath = Path(croppedPath)
85118
if filePath.suffix in (".vhd", ".vhdl"):
86119
self._ParseVHDLFile(fileNode, filePath, fileset)
@@ -96,12 +129,24 @@ def _ParseFile(self, fileNode, fileset):
96129
def _ParseVHDLFile(self, fileNode, path, fileset):
97130
vhdlFile = VHDLSourceFile(path)
98131
fileset.AddFile(vhdlFile)
132+
usedInAttr = []
99133

100-
if fileNode[0].tag == "FileInfo":
101-
if fileNode[0].get("SFType") == "VHDL2008":
102-
vhdlFile.VHDLVersion = VHDLVersion.VHDL2008
103-
else:
104-
vhdlFile.VHDLVersion = VHDLVersion.VHDL93
134+
for childNode in fileNode.childNodes:
135+
if childNode.nodeType == Node.ELEMENT_NODE and childNode.tagName == "FileInfo":
136+
if childNode.getAttribute("SFType") == "VHDL2008":
137+
vhdlFile.VHDLVersion = VHDLVersion.VHDL2008
138+
else:
139+
vhdlFile.VHDLVersion = VHDLVersion.VHDL93
140+
141+
for fileAttribute in childNode.childNodes:
142+
if fileAttribute.nodeType == Node.ELEMENT_NODE and fileAttribute.tagName == "Attr":
143+
if fileAttribute.getAttribute("Name") == "Library":
144+
libraryName = fileAttribute.getAttribute("Val")
145+
vhdlFile.VHDLLibrary = fileset.GetOrCreateVHDLLibrary(libraryName)
146+
elif fileAttribute.getAttribute("Val") == "UsedIn":
147+
usedInAttr.append(fileAttribute.getAttribute("Val"))
148+
149+
vhdlFile[UsedInAttribute] = usedInAttr
105150

106151
def _ParseDefaultFile(self, _, path, fileset):
107152
File(path, fileSet=fileset)
@@ -115,6 +160,12 @@ def _ParseVerilogFile(self, _, path, fileset):
115160
def _ParseXCIFile(self, _, path, fileset):
116161
IPCoreInstantiationFile(path, fileSet=fileset)
117162

163+
def _ParseFileSetConfig(self, fileNode, fileset):
164+
for option in fileNode.childNodes:
165+
if option.nodeType == Node.ELEMENT_NODE and option.tagName == "Option":
166+
if option.getAttribute("Name") == "TopModule":
167+
fileset.TopLevel = option.getAttribute("Val")
168+
118169

119170
@export
120171
class XDCConstraintFile(ConstraintFile, SDCContent):

0 commit comments

Comments
 (0)