3030# ============================================================================
3131#
3232from pathlib import Path
33+ from typing import Iterable
3334
34- from lxml import etree
35+ from xml . dom import minidom , Node
3536from pyVHDLModel import VHDLVersion
3637from 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
120171class XDCConstraintFile (ConstraintFile , SDCContent ):
0 commit comments