OpenCores
URL https://opencores.org/ocsvn/radiohdl/radiohdl/trunk

Subversion Repositories radiohdl

[/] [radiohdl/] [trunk/] [core/] [hdl_libraries_wizard.py] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 danv
###############################################################################
2
#
3
# Copyright (C) 2014
4
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
5
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
#
20
###############################################################################
21
 
22
"""HDL configuration for building simulation and synthesis targets.
23
 
24
   There should be one hdl_buildset_<buildset>.cfg file per buildset somewhere in the
25
   toolRootDir and at least one hdllib.cfg file somewhere in the libRootDir.
26
   Every HDL library that is in the libRootDir can be found if it has a hdllib.cfg file.
27
   Together the hdl_buildset_<buildset>.cfg and hdllib.cfg files contain all the keys and
28
   values that are sufficient to be able to build the targets for the HDL
29
   library. The possible targets are:
30
 
31
   - compile to created the library binaries for simulation
32
   - synthesize to created an image that can be loaded ion the FPGA
33
   - verify VHDL test benches in simulation
34
   - verify Python test cases via the MM control interface in simulation
35
   - validate Python test cases on hardware via the MM control interface
36
 
37
   The contents of the cfg files consist of a series of key - value pairs
38
   that are read into a dictionary as defined in hdl_configfile.py. Whether
39
   the key is a valid key depends on the application that interprets the
40
   dictionary.
41
 
42
   The methods can have the library dictionary or the library name as
43
   argument. The default arguments are the self.libs.dicts and the
44
   corresponding self.lib_names. The argument can be a list or a single value.
45
   Similar the return can be a list or a single value, because a list of one
46
   element is unlistified.
47
 
48
"""
49
 
50
import sys
51
import fnmatch
52
from os import listdir, walk, getenv
53
from os.path import expandvars, isabs, join, isfile
54
import shutil
55
from distutils.dir_util import copy_tree
56
from argparse import ArgumentParser
57
import collections
58
import common_radiohdl as cm
59
from configfile import ConfigFile
60
from hdl_configfile import HdlBuildset
61
from hdl_configtree import HdlLibTree
62
 
63
__all__ = ['HdlLibrariesWizard']
64
 
65
 
66
class HdlLibrariesWizard:
67
 
68
    def __init__(self, toolRootDir, toolFileName, libFileName='hdllib.cfg', libFileSections=None):
69
        """Get tool dictionary info from toolRootDir and all HDL library dictionary info for it
70
 
71
           - self.tool.dicts = single dictionary that contains the tool info (only one tool dict in dicts list)
72
           - self.libs.dicts = list of dictionaries that contains the info of the HDL libraries.
73
 
74
           The libRootDir parameter is defined in the hdl_buildset_<buildset>.cfg file and is the root directory from where the hdllib.cfg
75
           files are searched for.
76
 
77
           - self.lib_names = the library names of self.libs.dicts
78
 
79
           In parallel to the self.libs.dicts list of dictionaries a list of self.lib_names is created to be able to identify
80
           a HDL library dict also by its library name. Iherefore it is important that the indexing of parallel lists remains
81
           intact at all times.
82
 
83
           - self.technologyNames = the technologyNames parameter is defined in the hdl_buildset_<buildset>.cfg file. All generic HDL
84
             libraries and these technology specific libraries are kept. If self.technologyNames is:
85
             []                              : Keep all HDL libraries that were found.
86
             ['ip_stratixiv', 'ip_arria10']  : The HDL libraries with a hdl_lib_technology that is not '' or does not match one of the technologies
87
                                               in technologyNames are removed from the list of HDL library dictionaries.
88
 
89
           - self.removed_libs = contains the HDL library dicts that have been removed from self.libs.dicts, because they are for
90
                                  a technology that is not within technologyNames.
91
 
92
           Keep lists of all unavailable library names that were found at the hdl_lib_uses_synth, hdl_lib_uses_ip, hdl_lib_uses_sim and
93
           hdl_lib_include_ip keys in the self.libs.dicts:
94
 
95
           - self.unavailable_use_libs = self.unavailable_use_synth_libs + self.unavailable_use_ip_libs + self.unavailable_use_sim_libs
96
           - self.unavailable_include_ip_libs
97
 
98
           Unavailable used libraries can be missing for a valid reason when they are not required (e.g. IP for another technology). Being able to
99
           ignore missing libraries does require that the entities from these libraries are instantiated as components in the VHDL. The difference
100
           between a removed library and an unavailable library is that for a removed library the HDL config information is still known, whereas
101
           for an unavailable library it is not. Therefore the library clause names for referred but unavailable HDL libraries are disclosed at the
102
           'hdl_lib_disclose_library_clause_names' keys of the libraries that use them and kept in a dictionary:
103
 
104
           - self.disclosed_library_clause_names
105
 
106
        """
107
        print("HdlLibrariesWizard(toolRootDir=%s, toolFileName=%s, libFileName=%s, libFileSections=%s)"
108
              % (toolRootDir, toolFileName, libFileName, libFileSections))
109
        self.toolRootDir = toolRootDir  # TODO almost obsolete
110
 
111
        # read the buildset file. This file contains major information about paths, technologies, and so on
112
        full_buildsetfile_name = "%s/%s" % (toolRootDir, toolFileName)
113
        buildset_info = HdlBuildset(full_buildsetfile_name)
114
        buildset_info.resolve_key_references()
115
        self.buildset = buildset_info.content
116
 
117
        # HDL library config files
118
        self.libRootDirs = [expandvars(rootdir) for rootdir in self.buildset['lib_root_dirs'].replace("\t", " ").split(" ")
119
                            if rootdir != '']
120
        self.libs = HdlLibTree(rootdirs=self.libRootDirs,
121
                               filename=libFileName,
122
                               sections=libFileSections)   # library dict files
123
        if len(self.libs.configfiles) == 0:
124
            sys.exit('Error : No HDL library config files found')
125
        print("Found %d hdllib files:" % len(self.libs.configfiles))
126
 
127
        # Substitute key words occurring in hdllib.cfg files with their value.
128
        self.substitute_key_words()
129
 
130
        self.familyNames = self.buildset['family_names'].split()
131
        print("### self.familyNames = ", self.familyNames)
132
 
133
        # Keep the generic HDL libraries and remove those that do not match the specified IP technologies
134
        self.technologyNames = self.buildset['technology_names'].split()
135
        print("### self.technologyNames = ", self.technologyNames)
136
        self.removed_libs = {}
137
 
138
        buildset_files = []
139
        for root, dirs, files in walk(join(getenv("RADIOHDL_GEAR"), 'config')):
140
            for name in files:
141
                if fnmatch.fnmatch(name, 'hdl_buildset_*.cfg'):
142
                    buildset_files.append(join(root, name))
143
        all_buildset_names = [bs[bs.rfind('_')+1:bs.rfind('.')] for bs in buildset_files]
144
        # print(all_buildset_names)
145
 
146
        for cfglib_name in list(self.libs.configfiles.keys()):
147
            techname = self.libs.configfiles[cfglib_name]['hdl_lib_technology']
148
            if (techname != '' and techname not in self.technologyNames):
149
                # keep the removed libs we need the content of those libs later.
150
                self.removed_libs[cfglib_name] = self.libs.configfiles[cfglib_name]
151
            else:
152
                # accept only projects for active buildset_name
153
                # this method asume the hdl_lib_name is starting with the buildset_name and ending with 
154
                # the project name seperated by a '_'
155
                # for example unb2b_<project_name>
156
                for buildset_name in sorted(all_buildset_names)[::-1]:
157
                    if buildset_name == self.buildset['buildset_name']:
158
                        continue
159
                    if buildset_name+'_' in self.libs.configfiles[cfglib_name]['hdl_lib_name']:
160
                        # keep the removed libs we need the content of those libs later.
161
                        self.removed_libs[cfglib_name] = self.libs.configfiles[cfglib_name]
162
 
163
        self.libs.remove_files_from_tree(list(self.removed_libs.keys()))
164
        print(len(self.removed_libs), "REMOVED LIBS:", sorted(self.removed_libs))
165
 
166
        # Keep list of used HDL library names
167
        self.lib_names = list(self.libs.configfiles.keys())
168
        print(len(self.lib_names), "KEPT LIBS:", sorted(self.lib_names))
169
 
170
        # No need to check for duplicates since HdlLibTree did that already.
171
 
172
        # create dictionary of library names with library clause names that are disclosed at the 'hdl_lib_disclose_library_clause_names' keys.
173
        self.disclosed_library_clause_names = {}
174
        for lib in list(self.libs.configfiles.values()):
175
            if lib.get_value('hdl_lib_disclose_library_clause_names'):
176
                key_values = lib.get_value('hdl_lib_disclose_library_clause_names').split()
177
                lib_name = key_values[0::2]
178
                lib_clause_name = key_values[1::2]
179
                lib_pairs = list(zip(lib_name, lib_clause_name))
180
                # No need to check for duplicate lib_names, because a dictionary cannot have duplicate keys
181
                for lp in lib_pairs:
182
                    self.disclosed_library_clause_names[lp[0]] = lp[1]
183
        # Check whether the used libraries from the self.libs.dicts keys indeed exist, otherwise remove them from the dictionary key
184
        # string and add the used library name to the list of unavailable used library names and check that the library use clause
185
        # name was disclosed at the 'hdl_lib_disclose_library_clause_names' key. In this way other methods do not have to check a
186
        # used library does indeed exist.
187
        self.unavailable_use_synth_libs = []
188
        self.unavailable_use_ip_libs = []
189
        self.unavailable_use_sim_libs = []
190
        self.unavailable_include_ip_libs = []
191
        for lib in list(self.libs.configfiles.values()):
192
            use_synth_libs = []
193
            use_ip_libs = []
194
            use_sim_libs = []
195
            include_ip_libs = []
196
            if lib.get_value('hdl_lib_uses_synth'):
197
                use_synth_libs = lib.get_value('hdl_lib_uses_synth').split()
198
            if lib.get_value('hdl_lib_uses_ip'):
199
                use_ip_libs += lib.get_value('hdl_lib_uses_ip').split()
200
            if lib.get_value('hdl_lib_uses_sim'):
201
                use_sim_libs += lib.get_value('hdl_lib_uses_sim').split()
202
            if lib.get_value('hdl_lib_include_ip'):
203
                include_ip_libs = lib.get_value('hdl_lib_include_ip').split()
204
            for use_name in use_synth_libs:
205
                if (use_name not in self.lib_names) and (use_name not in self.removed_libs):
206
                    lib['hdl_lib_uses_synth'] = cm.remove_from_list_string(lib['hdl_lib_uses_synth'], use_name)
207
                    self.unavailable_use_synth_libs.append(use_name)
208
                    if use_name not in list(self.disclosed_library_clause_names.keys()):
209
                        sys.exit("Error : Unavailable library %s at 'hdl_lib_uses_synth' key is not disclosed at 'hdl_lib_disclose_library_clause_names' key in library %s" % (use_name, lib_name))
210
            for use_name in use_ip_libs:
211
                if (use_name not in self.lib_names) and (use_name not in self.removed_libs):
212
                    lib['hdl_lib_uses_ip'] = cm.remove_from_list_string(lib['hdl_lib_uses_ip'], use_name)
213
                    self.unavailable_use_ip_libs.append(use_name)
214
                    if use_name not in list(self.disclosed_library_clause_names.keys()):
215
                        sys.exit("Error : Unavailable library %s at 'hdl_lib_uses_ip' key is not disclosed at 'hdl_lib_disclose_library_clause_names' key in library %s" % (use_name, lib_name))
216
            for use_name in use_sim_libs:
217
                if (use_name not in self.lib_names) and (use_name not in self.removed_libs):
218
                    lib['hdl_lib_uses_sim'] = cm.remove_from_list_string(lib['hdl_lib_uses_sim'], use_name)
219
                    self.unavailable_use_sim_libs.append(use_name)
220
                    if use_name not in list(self.disclosed_library_clause_names.keys()):
221
                        sys.exit("Error : Unavailable library %s at 'hdl_lib_uses_sim' key is not disclosed at 'hdl_lib_disclose_library_clause_names' key in library %s" % (use_name, lib_name))
222
            for use_name in include_ip_libs:
223
                if (use_name not in self.lib_names) and (use_name not in self.removed_libs):
224
                    lib['hdl_lib_include_ip'] = cm.remove_from_list_string(lib['hdl_lib_include_ip'], use_name)
225
                    self.unavailable_include_ip_libs.append(use_name)
226
                    if use_name not in list(self.disclosed_library_clause_names.keys()):
227
                        sys.exit("Error : Unavailable library %s at 'hdl_lib_include_ip' key in library %s is not disclosed at any 'hdl_lib_disclose_library_clause_names' key" % (use_name, lib_name))
228
        # remove all duplicates from the list
229
        self.unavailable_use_synth_libs  = cm.unique(self.unavailable_use_synth_libs)
230
        self.unavailable_use_ip_libs     = cm.unique(self.unavailable_use_ip_libs)
231
        self.unavailable_use_sim_libs    = cm.unique(self.unavailable_use_sim_libs)
232
        self.unavailable_include_ip_libs = cm.unique(self.unavailable_include_ip_libs)   # list of include_ip_use_libs
233
        self.unavailable_use_libs        = self.unavailable_use_synth_libs + self.unavailable_use_ip_libs + self.unavailable_use_sim_libs
234
        self.unavailable_use_libs        = cm.unique(self.unavailable_use_libs)          # aggregate list of use_*_libs
235
 
236
    # The Key value pairs defined in hdltool<buildset>.cfg can be used in hdllib.cfg files. See hdllib.cfg of technology library
237
    def substitute_key_words(self):
238
        for lib in list(self.libs.configfiles.values()):
239
            for lib_key, lib_value in list(lib.content.items()):
240
                for tool_key, tool_value in list(self.buildset.items()):
241
                    tool_key_string = '<%s>' % tool_key
242
                    if tool_key_string in lib_value:
243
                        lib[lib_key] = lib_value.replace(tool_key_string, tool_value)
244
 
245
    def check_library_names(self, check_lib_names, lib_names=None):
246
        """Check that HDL library names exists within the list of library names, if not then exit with Error message.
247
           The list of library names can be specified via the argument lib_names, or it defaults to the list of
248
           self.lib_names of HDL libraries that were found in the toolRootDir for the libFileName of this object.
249
        """
250
        if lib_names is None:
251
            lib_names = self.lib_names
252
        for check_lib_name in cm.listify(check_lib_names):
253
            if check_lib_name not in cm.listify(lib_names):
254
                sys.exit('Error : Unknown HDL library name %s found with %s' % (check_lib_name, cm.method_name()))
255
 
256
    def get_used_libs(self, build_type, lib_dict, arg_include_ip_libs=[]):
257
        """Get the list of used HDL libraries from the lib_dict that this library directly depends on, so only at this HDL library hierachy level.
258
 
259
           Which libraries are actually used depends on the build_type. The build_type can be:
260
            ''      uses all libraries from 'hdl_lib_uses_synth', 'hdl_lib_uses_ip' and 'hdl_lib_uses_sim' in the lib_dict
261
            'sim'   uses all libraries from 'hdl_lib_uses_synth', 'hdl_lib_uses_ip' and 'hdl_lib_uses_sim' in the lib_dict
262
            'synth' uses all libraries from 'hdl_lib_uses_synth' in the lib_dict and from 'hdl_lib_uses_ip' it only uses the IP
263
                    libraries that are mentioned in the local 'hdl_lib_include_ip' key or in the global arg_include_ip_libs
264
 
265
           The 'hdl_lib_uses_*' keys all appear locally in the same hdllib.cfg file. The 'hdl_lib_include_ip' key appears at this level or at
266
           a higher level (design) library hdllib.cfg file to select which of all available 'hdl_lib_uses_ip' IP libraries will actually be
267
           used in the design. The 'hdl_lib_include_ip' cannot appear in a lower level hdllib.cfg, because a lower level HDL library cannot
268
           depend on a higher level HDL library. Therefore the IP libraries that need to be included from 'hdl_lib_uses_ip' will be known in
269
           include_ip_libs.
270
        """
271
        # Get local library dependencies
272
        use_synth_libs = []
273
        use_ip_libs = []
274
        use_sim_libs = []
275
        include_ip_libs = []
276
        if 'hdl_lib_uses_synth' in lib_dict.content:
277
            use_synth_libs = lib_dict['hdl_lib_uses_synth'].split()
278
        if 'hdl_lib_uses_ip' in lib_dict.content:
279
            use_ip_libs += lib_dict['hdl_lib_uses_ip'].split()
280
        if 'hdl_lib_uses_sim' in lib_dict.content:
281
            use_sim_libs += lib_dict['hdl_lib_uses_sim'].split()
282
        if 'hdl_lib_include_ip' in lib_dict.content:
283
            include_ip_libs = lib_dict['hdl_lib_include_ip'].split()
284
 
285
        # Append include_ip_libs from this level to the global list of arg_include_ip_libs
286
        include_ip_libs = list(arg_include_ip_libs) + include_ip_libs
287
 
288
        # Get the actually use_libs for lib_dict
289
        use_libs = use_synth_libs + use_ip_libs + use_sim_libs  # default include all IP, so ignore include_ip_libs
290
        if build_type == 'sim':
291
            use_libs = use_synth_libs + use_ip_libs + use_sim_libs    # for simulation included all IP, so ignore include_ip_libs
292
        if build_type == 'synth':
293
            use_libs = use_synth_libs
294
            # For synthesis only keep the local use_ip_libs if it is mentioned in the global include_ip_libs. Vice versa also only
295
            # include the global include_ip_libs if they appear in a local use_ip_libs, to avoid that an IP library that is mentioned
296
            # in the global include_ip_libs gets included while it is not instantiated anywhere in the design.
297
            for ip_lib in use_ip_libs:
298
                if ip_lib in include_ip_libs:
299
                    use_libs += [ip_lib]
300
 
301
        # Remove any duplicate library names from the lists
302
        use_libs = cm.unique(use_libs)
303
        include_ip_libs = cm.unique(include_ip_libs)
304
 
305
        # Remove libraries that are in the removed technologies (use list() to take copy)
306
        for use_name in list(use_libs):
307
            if use_name in self.removed_libs:
308
                use_libs.remove(use_name)
309
        for use_name in list(include_ip_libs):
310
            if use_name in self.removed_libs:
311
                include_ip_libs.remove(use_name)
312
 
313
        return use_libs, include_ip_libs
314
 
315
    def derive_all_use_libs(self, build_type, lib_name, arg_include_ip_libs=[]):
316
        """Recursively derive a complete list of all HDL libraries that the specified HDL lib_name library depends on, so from this
317
           HDL library down the entire hierachy.
318
 
319
           The hdl_lib_uses_* key only needs to contain all libraries that are declared at the VHDL LIBRARY clauses of the
320
           source files in this VHDL library. This derive_all_use_libs() will recursively find all deeper level VHDL libraries as well.
321
 
322
           The arg_include_ip_libs selects the IP library to keep from 'hdl_lib_uses_ip'. The include_ip_libs is passed on
323
           through the recursion hierarchy via arg_include_ip_libs to ensure that the from the top level library down all
324
           multiple choice IP libraries in 'hdl_lib_uses_ip' that need to be included are indeed included. The multiple choice IP
325
           libraries in 'hdl_lib_uses_ip' that are not in include_ip_libs are excluded.
326
 
327
           Note:
328
           . Only the generic HDL libraries and the technology specific libraries that match self.technologyNames are used,
329
             because the other technology libraries have been removed from self.libs.dicts already at __init__() and from the
330
             library dependency lists in get_used_libs()
331
           . If Python breaks because recursion limit is reached, then two hdllib.cfg probably mutually use eachother which is
332
             not allowed.
333
        """
334
        # use list() to take local copy, to avoid next that default empty list argument arg_include_ip_libs=[] gets disturbed
335
        include_ip_libs = list(arg_include_ip_libs)
336
        if lib_name in self.lib_names:
337
            all_use_libs = [lib_name]
338
            lib_dict = self.libs.configfiles[lib_name]
339
            use_libs, include_ip_libs = self.get_used_libs(build_type, lib_dict, include_ip_libs)
340
 
341
            for use_lib in use_libs:
342
                if use_lib not in all_use_libs:
343
                    all_use_libs.append(use_lib)
344
                    # use recursion to include all used libs
345
                    all_use_libs += self.derive_all_use_libs(build_type, use_lib, include_ip_libs)
346
            # remove all duplicates from the list
347
            return cm.unique(all_use_libs)
348
        else:
349
            sys.exit('Error : Unknown HDL library name %s in %s()' % (lib_name, cm.method_name()))
350
 
351
    def derive_lib_order(self, build_type, lib_name, lib_names=None):
352
        """Derive the dependency order for all HDL libraries in lib_names that HDL library lib_name depends on.
353
        """
354
        if lib_names is None:
355
            # At first entry derive the list of all HDL libraries that lib_name depends on
356
            lib_names = self.derive_all_use_libs(build_type, lib_name)
357
 
358
        # Derive the order of all HDL libraries that lib_name depends on, start with the order of lib_names
359
        lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=lib_names)
360
        # use list() to take local copy to avoid modifying list order of self.lib_names which matches self.libs.dicts list order
361
        lib_order = list(lib_names)
362
        for lib_dict in lib_dicts:
363
            lib_name = lib_dict['hdl_lib_name']
364
            use_libs, _ = self.get_used_libs('', lib_dict, [])
365
            for use_lib in use_libs:
366
                if use_lib in lib_names:
367
                    if lib_order.index(use_lib) > lib_order.index(lib_name):
368
                        lib_order.remove(use_lib)
369
                        lib_order.insert(lib_order.index(lib_name), use_lib)  # move used lib to just before this lib
370
        # use recursion to keep on reordering the lib_order until it is stable
371
        if lib_names != lib_order:
372
            lib_order = self.derive_lib_order(build_type, lib_name, lib_order)
373
        return lib_order
374
 
375
    def get_lib_dicts_from_lib_names(self, lib_names=None):
376
        """Get list the HDL libraries lib_dicts from list of HDL libraries lib_names and preseve the library order.
377
        """
378
        if lib_names is None:
379
            lib_names = self.lib_names
380
 
381
        # Cannot use:
382
        # lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=lib_names)
383
        # because then the order of self.libs.dicts is used
384
        lib_dicts = []
385
        for lib_name in cm.listify(lib_names):
386
            lib_dicts.append(self.libs.configfiles[lib_name])
387
        return lib_dicts
388
 
389
    def get_lib_names_from_lib_dicts(self, lib_dicts=None):
390
        """Get list the HDL libraries lib_names from list of HDL libraries lib_dicts and preseve the library order.
391
        """
392
        lib_names = self.libs.get_key_values('hdl_lib_name', lib_dicts)
393
        return lib_names
394
 
395
    def get_tool_build_dir(self, build_type):
396
        """Get the central tool build directory.
397
 
398
        The build_type can be:
399
            'sim'   uses the 'sim_tool_name'   key in the self.buildset
400
            'synth' uses the 'synth_tool_name' key in the self.buildset
401
            When another name is used that name is used directly as toolname in the construction of the path.
402
 
403
        The function returns a tuple with the following four components:
404
            - the absolute path to the central main build directory
405
            - the buildset_name key value as subdirectory
406
            - the toolname as subdirectory (derived from *_tool_name or the given value of 'build_type')
407
            - project_deeper_subdir. See explanation below.
408
 
409
        The project file will be located in the build dir or at some levels deeper in the build dir.
410
        These optional extra subdirectory levels allow for relative file reference from project file
411
        location. This is useful to be able to keep memory initialisation files in the library build
412
        directory that are referred to using some fixed ../../ path in the HDL code.
413
            - project_deeper_subdir = '' when project_dir_depth_<build_type> = 0 or not in buildset
414
            - project_deeper_subdir = 'p/' when project_dir_depth_<build_type> = 1
415
            - project_deeper_subdir = 'p/p/' when project_dir_depth_<build_type> = 2,
416
            - project_deeper_subdir = 'p/p/p/' when project_dir_depth_<build_type> = 3, etc
417
        """
418
        # Determine build_maindir
419
        build_maindir = expandvars('${RADIOHDL_BUILD_DIR}')
420
        if not isabs(build_maindir):
421
            sys.exit('Error : The build_dir value must be an absolute path')
422
 
423
        # Determine build_buildset_dir
424
        build_buildset_dir = self.buildset['buildset_name']
425
 
426
        # Determine build_tooldir
427
        tool_name_key = build_type + '_tool_name'
428
        if tool_name_key in self.buildset:
429
            build_tooldir = self.buildset[tool_name_key]
430
        else:
431
            build_tooldir = build_type
432
 
433
        # Determine project_deeper_subdir
434
        project_dir_depth_key = 'project_dir_depth_' + build_type
435
        if project_dir_depth_key not in self.buildset:
436
            project_deeper_subdir = ''
437
        else:
438
            project_deeper_subdir = 'p/' * int(self.buildset[project_dir_depth_key])
439
 
440
        return build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir
441
 
442
    def get_lib_build_dirs(self, build_type, lib_dicts=None):
443
        """Get the subdirectories within the central tool build directory for all HDL libraries in the specified list of lib_dicts.
444
 
445
        The build_type can be:
446
            'sim'   uses the 'sim_tool_name'   key in the self.buildset
447
            'synth' uses the 'synth_tool_name' key in the self.buildset
448
 
449
        The build dir key value must be an absolute directory path. The lib build dir consists of
450
            - the absolute path to the central main build directory
451
            - the buildset_name key value as subdirectory
452
            - the tool_name_key value as subdirectory
453
            - the library name as library subdirectory
454
            - zero or more extra subdirectory levels to allow for relative file reference from project file location
455
        """
456
        if lib_dicts is None:
457
            lib_dicts = list(self.libs.configfiles.values())
458
        build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type)
459
        build_dirs = []
460
        for lib_dict in cm.listify(lib_dicts):
461
            lib_name = lib_dict['hdl_lib_name']
462
            build_dirs.append(join(build_maindir, build_buildset_dir, build_tooldir, lib_name, project_deeper_subdir))  # central build main directory with subdirectory per library
463
        return cm.unlistify(build_dirs)
464
 
465
    def create_lib_order_files(self, build_type, lib_names=None):
466
        """Create the compile order file '<lib_name>_lib_order.txt' for all HDL libraries in the specified list of lib_names.
467
 
468
           The file is stored in the sim build directory of the HDL library.
469
           The file is read by commands.do in Modelsim to avoid having to derive the library compile order in TCL.
470
        """
471
        if lib_names is None:
472
            lib_names = self.lib_names
473
 
474
        lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names)
475
        for lib_dict in lib_dicts:
476
            lib_name = lib_dict['hdl_lib_name']
477
            lib_order = self.derive_lib_order(build_type, lib_name)
478
            file_name = lib_name + '_lib_order.txt'
479
            file_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict)
480
            cm.mkdir(file_path)
481
            filePathName = join(file_path, file_name)
482
            with open(filePathName, 'w') as fp:
483
                for lib in lib_order:
484
                    fp.write('%s ' % lib)
485
        print("Created {} lib-order files".format(len(lib_dicts)))
486
 
487
    # Methods to create sub directories at various levels in the build directory as defined in HDL tool config file
488
    def create_sub_directory_in_build_main_dir(self, build_type, subdir_name):
489
        """Create <subdir_name>/ in the central <build_main>/ directory
490
        """
491
        build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type)
492
        subdir_path = join(build_maindir, subdir_name)
493
        cm.mkdir(subdir_path)
494
 
495
    def create_sub_directory_in_build_buildset_dir(self, build_type, subdir_name):
496
        """Create <subdir_name>/ in the central <build_main>/<build_buildset_dir>/ directory.
497
        """
498
        build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type)
499
        subdir_path = join(build_maindir, build_buildset_dir, subdir_name)
500
        cm.mkdir(subdir_path)
501
 
502
    def create_sub_directory_in_build_tool_dir(self, build_type, subdir_name):
503
        """Create <subdir_name>/ in the central <build_main>/<build_buildset_dir>/<build_tooldir>/ directory.
504
        """
505
        build_maindir, build_buildset_dir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir(build_type)
506
        subdir_path = join(build_maindir, build_buildset_dir, build_tooldir, subdir_name)
507
        cm.mkdir(subdir_path)
508
 
509
    def create_sub_directory_in_build_lib_dir(self, build_type, subdir_name, lib_names=None):
510
        """Create <subdir_name>/ in project local build directory <lib_name>/ for all HDL libraries in the specified list of lib_names.
511
        """
512
        if lib_names is None:
513
            lib_names = self.lib_names
514
        lib_dicts = self.libs.get_configfiles('hdl_lib_name', values=lib_names)
515
        for lib_dict in lib_dicts:
516
            lib_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict)
517
            subdir_path = join(lib_path, subdir_name)
518
            cm.mkdir(subdir_path)
519
        print("Created {} subdirectories".format(len(lib_dicts)))
520
 
521
    def copy_files(self, build_type, lib_names=None):
522
        """
523
        Copy all source directories and source files listed at the <tool_name>_copy_files key.
524
        The build_type selects the <tool_name>_copy_files key using the <build_type>_tool_name key value
525
        from the hdl_buildset_<buildset>.cfg.
526
        The <tool_name>_copy_files key expects a source and a destination pair per listed directory or file:
527
        - The sources need to be specified with absolute path or relative to the HDL library source directory
528
          where the hdllib.cfg is stored
529
        - The destinations need to be specified with absolute path or relative to HDL library build directory
530
          where the project file (e.g. mpf, qpf) gets stored
531
 
532
        Arguments:
533
        - lib_names  : zero or more HDL libraries
534
        """
535
        if lib_names is None:
536
            lib_names = self.lib_names
537
 
538
        lib_dicts          = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names)
539
        tool_name_key      = build_type + '_tool_name'
540
        tool_name_value    = self.buildset[tool_name_key]
541
        tool_name_copy_key = tool_name_value + '_copy_files'
542
        lib_count          = 0
543
        dir_count          = 0
544
        file_count         = 0
545
        for lib_dict in lib_dicts:
546
            if tool_name_copy_key in lib_dict.content:
547
                lib_count += 1
548
                lib_path       = lib_dict.location
549
                build_dir_path = self.get_lib_build_dirs(build_type, lib_dicts=lib_dict)
550
                cm.mkdir(build_dir_path)
551
                key_values     = lib_dict[tool_name_copy_key].split()
552
                sources        = key_values[0::2]
553
                destinations   = key_values[1::2]
554
                file_io = list(zip(sources, destinations))
555
                for fpn_io in file_io:
556 7 danv
                    try:
557
                        sourcePathName  = cm.expand_file_path_name(fpn_io[0], lib_path)
558
                        destinationPath = cm.expand_file_path_name(fpn_io[1], build_dir_path)
559
                        # print("Copy '{}'' to '{}'".format(sourcePathName, destinationPath))
560
                        if isfile(sourcePathName):
561
                            shutil.copy(sourcePathName, destinationPath)     # copy file
562
                            file_count += 1
563
                        else:
564
                            copy_tree(sourcePathName, destinationPath)       # copy directory tree (will create new destinationPath directory)
565
                            dir_count += 1
566
                    except:
567
                        print("Could not copy source {} to desination {}".format(sourcePathName,destinationPath))
568 4 danv
        print("Copied {} files and {} directories for {} libraries".format(file_count, dir_count, lib_count))
569
 
570
 
571
if __name__ == '__main__':
572
    # Parse command line arguments
573
    buildsetSelect = sorted([cfgfile[13:-4] for cfgfile in listdir(expandvars('$RADIOHDL_CONFIG'))
574
                             if cfgfile.startswith("hdl_buildset_") and cfgfile.endswith(".cfg")])
575
    argparser = ArgumentParser(description='Hdl_config shows several selections of all of your hdllib.cfg files.')
576
    argparser.add_argument('buildset', help='choose buildset %s' % (buildsetSelect))
577
    argparser.add_argument('--toplib', default=None, required=False, help='top library to show more information about.')
578
    args = argparser.parse_args()
579
 
580
    # check arguments
581
    if args.buildset not in buildsetSelect:
582
        print('buildset %s is not supported' % args.buildset)
583
        print("Supported buildset are:", buildsetSelect)
584
        sys.exit(1)
585
    args.buildsetFile = 'hdl_buildset_' + args.buildset + '.cfg'
586
 
587
    # Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
588
    hdl = HdlLibrariesWizard(toolRootDir=expandvars('${RADIOHDL_CONFIG}'),
589
                             toolFileName=args.buildsetFile,
590
                             libFileName='hdllib.cfg')
591
 
592
    print('#')
593
    print('# HdlLibrariesWizard:')
594
    print('#')
595
    for libname in list(hdl.libs.configfiles.keys()):
596
        print("\n", libname)
597
        libinfo = hdl.libs.configfiles[libname]
598
        for k, v in libinfo.content.items():
599
            print(k, '=', v)
600
    print('')
601
 
602
    print('')
603
    print('Library paths :')
604
    for libname in list(hdl.libs.configfiles.keys()):
605
        print('    ', hdl.libs.configfiles[libname].location)
606
 
607
    print('')
608
    print('Library file names :"')
609
    for libname in list(hdl.libs.configfiles.keys()):
610
        print('    ', libname)
611
 
612
    print('')
613
    print('Library section headers :')
614
    for libname, libinfo in hdl.libs.configfiles.items():
615
        print('    %-52s : %s' % (libname, libinfo['section_headers']))
616
 
617
    print('')
618
    print('Build directories for simulation:')
619
    for build_dir in hdl.get_lib_build_dirs('sim'):
620
        print('    ', build_dir)
621
 
622
    print('')
623
    print('Build directories for synthesis:')
624
    for build_dir in hdl.get_lib_build_dirs('synth'):
625
        print('    ', build_dir)
626
 
627
    print('')
628
    print('Removed library names = \n', list(hdl.removed_libs.keys()))
629
 
630
    print('')
631
    print("Unavailable library names in any 'hdl_lib_uses_synth' key = \n", hdl.unavailable_use_synth_libs)
632
    print("Unavailable library names in any 'hdl_lib_uses_ip' key = \n", hdl.unavailable_use_ip_libs)
633
    print("Unavailable library names in any 'hdl_lib_uses_sim' key = \n", hdl.unavailable_use_sim_libs)
634
    print("Unavailable library names in any 'hdl_lib_uses_*' key = \n", hdl.unavailable_use_libs)
635
    print('')
636
    print("Unavailable library names in any 'hdl_lib_include_ip' key = \n", hdl.unavailable_include_ip_libs)
637
 
638
    print('')
639
    print("Used library clause names that are explicitly disclosed at the 'hdl_lib_disclose_library_clause_names' keys:")
640
    for key in list(hdl.disclosed_library_clause_names.keys()):
641
        print('    %-52s : %s' % (key, hdl.disclosed_library_clause_names[key]))
642
 
643
    if args.toplib:
644
        for build_type in ['sim', 'synth']:
645
            print('')
646
            print('derive_all_use_libs for %s of %s = \n'
647
                  % (build_type, args.toplib), hdl.derive_all_use_libs(build_type, args.toplib))
648
            print('')
649
            print('derive_lib_order for %s of %s = \n'
650
                  % (build_type, args.toplib), hdl.derive_lib_order(build_type, args.toplib))
651
 
652
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.