1 |
4 |
danv |
#! /usr/bin/env python3
|
2 |
|
|
###############################################################################
|
3 |
|
|
#
|
4 |
|
|
# Copyright (C) 2014
|
5 |
|
|
# ASTRON (Netherlands Institute for Radio Astronomy)
|
6 |
|
|
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
|
7 |
|
|
#
|
8 |
|
|
# This program is free software: you can redistribute it and/or modify
|
9 |
|
|
# it under the terms of the GNU General Public License as published by
|
10 |
|
|
# the Free Software Foundation, either version 3 of the License, or
|
11 |
|
|
# (at your option) any later version.
|
12 |
|
|
#
|
13 |
|
|
# This program is distributed in the hope that it will be useful,
|
14 |
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
|
|
# GNU General Public License for more details.
|
17 |
|
|
#
|
18 |
|
|
# You should have received a copy of the GNU General Public License
|
19 |
|
|
# along with this program. If not, see .
|
20 |
|
|
#
|
21 |
|
|
###############################################################################
|
22 |
|
|
|
23 |
|
|
"""HDL configuration for building Modelsim simulation targets.
|
24 |
|
|
|
25 |
|
|
Usage:
|
26 |
|
|
> python ${RADIOHDL_GEAR}/oneclick/base/modelsim_config.py -t unb1
|
27 |
|
|
"""
|
28 |
|
|
|
29 |
|
|
import sys
|
30 |
|
|
import os.path
|
31 |
|
|
from os import listdir
|
32 |
|
|
from argparse import ArgumentParser
|
33 |
|
|
import common_radiohdl as cm
|
34 |
|
|
import hdl_libraries_wizard
|
35 |
|
|
from configfile import ConfigFile
|
36 |
|
|
|
37 |
|
|
|
38 |
|
|
class ModelsimConfig(hdl_libraries_wizard.HdlLibrariesWizard):
|
39 |
|
|
|
40 |
|
|
def __init__(self, toolRootDir, buildsetFile, libFileName):
|
41 |
|
|
"""Get Modelsim tool info from toolRootDir and all HDL library info from libRootDir.
|
42 |
|
|
|
43 |
|
|
This class uses the default keys and the keys from the libFileSections in the libFileName config file.
|
44 |
|
|
|
45 |
|
|
Arguments:
|
46 |
|
|
- toolRootDir : Root directory from where the hdl_buildset_.cfg file is searched for.
|
47 |
|
|
- buildsetFile : Default HDL tools configuration file name
|
48 |
|
|
- libFileName : Default HDL library configuration file name
|
49 |
|
|
|
50 |
|
|
The libRootDir is defined in the hdl_buildset_.cfg file and is the root directory from where the hdllib.cfg
|
51 |
|
|
files are searched for.
|
52 |
|
|
|
53 |
|
|
Files:
|
54 |
|
|
- hdl_buildset_.cfg : HDL tool configuration dictionary file. One central file per buildset.
|
55 |
|
|
|
56 |
|
|
- hdllib.cfg : HDL library configuration dictionary file. One file for each HDL library.
|
57 |
|
|
|
58 |
|
|
- modelsim_project_files.txt
|
59 |
|
|
The modelsim_project_files.txt file is a dictionary file with the list the Modelsim project files for all HDL
|
60 |
|
|
libraries that were found in the libRootDir. The keys are the library names and the values are the paths to the
|
61 |
|
|
corresponding modelsim project files. The modelsim_project_files.txt file is created by
|
62 |
|
|
create_modelsim_project_files_file() and is read by the TCL commands.do file in Modelsim. Creating the file in
|
63 |
|
|
Python and then reading this in TCL makes the commands.do much simpler.
|
64 |
|
|
|
65 |
|
|
- .mpf : Modelsim project file for a certain HDL library based on the hdllib.cfg. The file is created by
|
66 |
|
|
create_modelsim_project_file().
|
67 |
|
|
|
68 |
|
|
- _lib_order.txt
|
69 |
|
|
The _lib_order.txt file contains the library compile order for a certain HDL library. The files are
|
70 |
|
|
created by create_lib_order_files() in the same build directory as where the Modelsim project file is stored.
|
71 |
|
|
The _lib_order.txt files are read by the TCL commands.do file in Modelsim. Creating the files in Python
|
72 |
|
|
and then reading them in TCL makes the commands.do much simpler.
|
73 |
|
|
"""
|
74 |
|
|
libFileSections = ['modelsim_project_file']
|
75 |
|
|
hdl_libraries_wizard.HdlLibrariesWizard.__init__(self, toolRootDir, buildsetFile, libFileName, libFileSections)
|
76 |
|
|
|
77 |
|
|
def read_compile_order_from_mpf(self, mpfPathName):
|
78 |
|
|
"""Utility to read the compile order of the project files from an existing .mpf."""
|
79 |
|
|
# read .mpf to find all project files
|
80 |
|
|
project_file_indices = []
|
81 |
|
|
project_file_names = []
|
82 |
|
|
with open(mpfPathName, 'r') as fp:
|
83 |
|
|
for line in fp:
|
84 |
|
|
words = line.split()
|
85 |
|
|
if words:
|
86 |
|
|
key = words[0]
|
87 |
|
|
if key.find('Project_File_') >= 0 and key.find('Project_File_P_') == -1:
|
88 |
|
|
project_file_indices.append(key[len('Project_File_'):])
|
89 |
|
|
project_file_names.append(words[2])
|
90 |
|
|
# read .mpf again to find compile order for the project files
|
91 |
|
|
compile_order = list(range(len(project_file_names)))
|
92 |
|
|
with open(mpfPathName, 'r') as fp:
|
93 |
|
|
for line in fp:
|
94 |
|
|
words = line.split()
|
95 |
|
|
if words:
|
96 |
|
|
key = words[0]
|
97 |
|
|
if key.find('Project_File_P_') >= 0:
|
98 |
|
|
project_file_index = project_file_indices.index(key[len('Project_File_P_'):])
|
99 |
|
|
project_file_name = project_file_names[project_file_index]
|
100 |
|
|
k = words.index('compile_order')
|
101 |
|
|
k = int(words[k + 1])
|
102 |
|
|
compile_order[k] = project_file_name
|
103 |
|
|
return compile_order
|
104 |
|
|
|
105 |
|
|
def read_hdl_libraries_technology_file(self, technologyName, filePath=None):
|
106 |
|
|
"""Read the list of technology HDL libraries from a file.
|
107 |
|
|
|
108 |
|
|
Arguments:
|
109 |
|
|
- technologyName : refers to the hdl_libraries_.txt file
|
110 |
|
|
- filePath : path to hdl_libraries_.txt, when None then the file is
|
111 |
|
|
read in the default toolRootDir
|
112 |
|
|
"""
|
113 |
|
|
fileName = 'hdl_libraries_ip_' + technologyName + '.txt' # use fixed file name format
|
114 |
|
|
if filePath is None:
|
115 |
|
|
toolDir = os.path.expandvars('$RADIOHDL_BUILD_DIR')
|
116 |
|
|
toolSubDir = self.buildset['buildset_name']
|
117 |
|
|
fileNamePath = os.path.join(toolDir, toolSubDir, fileName) # default file path
|
118 |
|
|
else:
|
119 |
|
|
fileNamePath = os.path.join(filePath, fileName) # specified file path
|
120 |
|
|
tech_dict = ConfigFile(fileNamePath).content
|
121 |
|
|
return tech_dict
|
122 |
|
|
|
123 |
|
|
def create_modelsim_lib_compile_ip_files(self, lib_names=None):
|
124 |
|
|
"""
|
125 |
|
|
Create the '_lib_compile_ip.txt' file for all HDL libraries in the specified list of lib_names.
|
126 |
|
|
The file is stored in the sim build directory of the HDL library.
|
127 |
|
|
The file is read by commands.do in Modelsim to know which IP needs to be compiled before the library is compiled.
|
128 |
|
|
"""
|
129 |
|
|
if lib_names is None:
|
130 |
|
|
lib_names = self.lib_names
|
131 |
|
|
|
132 |
|
|
count = 0
|
133 |
|
|
lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names)
|
134 |
|
|
for lib_dict in lib_dicts:
|
135 |
|
|
if 'modelsim_compile_ip_files' in lib_dict.content:
|
136 |
|
|
count += 1
|
137 |
|
|
compile_ip_files = lib_dict['modelsim_compile_ip_files'].split()
|
138 |
|
|
lib_name = lib_dict['hdl_lib_name']
|
139 |
|
|
file_name = lib_name + '_lib_compile_ip.txt'
|
140 |
|
|
file_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict)
|
141 |
|
|
cm.mkdir(file_path)
|
142 |
|
|
filePathName = os.path.join(file_path, file_name)
|
143 |
|
|
with open(filePathName, 'w') as fp:
|
144 |
|
|
for fpn in compile_ip_files:
|
145 |
|
|
# Write the expanded file path name for _lib_compile_ip.txt so that it can be executed directly from its location in SVN using the Modelsim "do"-command in the commands.do.
|
146 |
|
|
# An alternative would be to write the basename, so only _lib_compile_ip.txt, but that would require copying the basename file to the mpf build directory
|
147 |
|
|
efpn = os.path.expandvars(fpn)
|
148 |
|
|
fp.write('%s ' % efpn)
|
149 |
|
|
print("Created {} compile-ip files".format(count))
|
150 |
|
|
|
151 |
|
|
def simulation_configuration(self, list_mode=False):
|
152 |
|
|
"""Prepare settings for simulation configuration.
|
153 |
|
|
The output format is string or list, dependent on list_mode.
|
154 |
|
|
Return tuple of project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization.
|
155 |
|
|
"""
|
156 |
|
|
# project_sim_p_defaults
|
157 |
|
|
project_sim_p_defaults = 'Generics {} timing default -std_output {} -nopsl 0 +notimingchecks 0 selected_du {} -hazards 0 -sdf {} ok 1 -0in 0 -nosva 0 +pulse_r {} -absentisempty 0 -multisource_delay {} +pulse_e {} vopt_env 1 -coverage 0 -sdfnoerror 0 +plusarg {} -vital2.2b 0 -t default -memprof 0 is_vopt_flow 0 -noglitch 0 -nofileshare 0 -wlf {} -assertdebug 0 +no_pulse_msg 0 -0in_options {} -assertfile {} -sdfnowarn 0 -Lf {} -std_input {}'
|
158 |
|
|
|
159 |
|
|
# project_sim_p_search_libraries
|
160 |
|
|
if list_mode:
|
161 |
|
|
project_sim_p_search_libraries = self.buildset['modelsim_search_libraries'].split()
|
162 |
|
|
else:
|
163 |
|
|
project_sim_p_search_libraries = '-L {}'
|
164 |
|
|
if 'modelsim_search_libraries' in self.buildset:
|
165 |
|
|
project_sim_p_search_libraries = '-L {'
|
166 |
|
|
for sl in self.buildset['modelsim_search_libraries'].split():
|
167 |
|
|
project_sim_p_search_libraries += sl
|
168 |
|
|
project_sim_p_search_libraries += ' '
|
169 |
|
|
project_sim_p_search_libraries += '}'
|
170 |
|
|
|
171 |
|
|
# project_sim_p_otherargs
|
172 |
|
|
# Note:
|
173 |
|
|
# E.g. the vsim-8684 load warning does not occur when the simulation is loaded via double click, but it
|
174 |
|
|
# does occur when the simulation is relaoded via the command line, because in the command line history
|
175 |
|
|
# the +nowarn8684 is then for some reason not preserved by Modelsim.
|
176 |
|
|
otherargs = ''
|
177 |
|
|
otherargs = '+nowarn8684 +nowarn8683 -quiet'
|
178 |
|
|
otherargs = '+nowarn8684 +nowarn8683'
|
179 |
|
|
otherargs = '+nowarn8684 +nowarn8683 +nowarnTFMPC +nowarnPCDPC' # nowarn on verilog IP connection mismatch warnings
|
180 |
|
|
if list_mode:
|
181 |
|
|
project_sim_p_otherargs = otherargs.split()
|
182 |
|
|
else:
|
183 |
|
|
project_sim_p_otherargs = 'OtherArgs {' + otherargs + '}'
|
184 |
|
|
|
185 |
|
|
# project_sim_p_optimization
|
186 |
|
|
project_sim_p_optimization = 'is_vopt_opt_used 2' # = when 'Enable optimization' is not selected in GUI
|
187 |
|
|
project_sim_p_optimization = 'is_vopt_opt_used 1 voptargs {OtherVoptArgs {} timing default VoptOutFile {} -vopt_keep_delta 0 -0in 0 -fvopt {} VoptOptimize:method 1 -vopt_00 2 +vopt_notimingcheck 0 -Lfvopt {} VoptOptimize:list .vopt_opt.nb.canvas.notebook.cs.page1.cs.g.spec.listbox -Lvopt {} +vopt_acc {} VoptOptimize .vopt_opt.nb.canvas.notebook.cs.page1.cs -vopt_hazards 0 VoptOptimize:Buttons .vopt_opt.nb.canvas.notebook.cs.page1.cs.g.spec.bf 0InOptionsWgt .vopt_opt.nb.canvas.notebook.cs.page3.cs.zf.ze -0in_options {}}' # = when 'Enable optimization' is selected in GUI for full visibility
|
188 |
|
|
|
189 |
|
|
return project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization
|
190 |
|
|
|
191 |
|
|
def create_modelsim_project_file(self, lib_names=None):
|
192 |
|
|
"""
|
193 |
|
|
Create the Modelsim project file for all technology libraries and RTL HDL libraries.
|
194 |
|
|
|
195 |
|
|
Arguments:
|
196 |
|
|
- lib_names : one or more HDL libraries
|
197 |
|
|
|
198 |
|
|
Library mapping:
|
199 |
|
|
- Technology libraries that are available, but not used are mapped to work.
|
200 |
|
|
- Unavailable libraries are also mapped to work. The default library clause name is
|
201 |
|
|
with postfix '_lib'. This is a best effort guess, because it is impossible to know the library clause name
|
202 |
|
|
for an unavailable library. If the best effort guess is not suitable, then the workaround is to create a
|
203 |
|
|
place holder directory with hdllib.cfg that defines the actual library clause name as it appears in the
|
204 |
|
|
VHDL for the unavailable HDL library. unavailable library names occur when e.g. a technology IP library
|
205 |
|
|
is not available in the toolRootDir because it is not needed, or it may indicate a spelling error.
|
206 |
|
|
"""
|
207 |
|
|
if lib_names is None:
|
208 |
|
|
lib_names = self.lib_names
|
209 |
|
|
|
210 |
|
|
lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names)
|
211 |
|
|
print("SELF.BUILDSET=", self.buildset)
|
212 |
|
|
for lib_dict in lib_dicts:
|
213 |
|
|
# Open mpf
|
214 |
|
|
lib_name = lib_dict['hdl_lib_name']
|
215 |
|
|
mpf_name = lib_name + '.mpf'
|
216 |
|
|
mpf_path = self.get_lib_build_dirs('sim', lib_dicts=lib_dict)
|
217 |
|
|
cm.mkdir(mpf_path)
|
218 |
|
|
mpfPathName = os.path.join(mpf_path, mpf_name)
|
219 |
|
|
with open(mpfPathName, 'w') as fp:
|
220 |
|
|
# Write [Library] section for all used libraries
|
221 |
|
|
fp.write('[Library]\n')
|
222 |
|
|
|
223 |
|
|
# . map used vendor technology libs to their target directory
|
224 |
|
|
# for technologyName in self.technologyNames:
|
225 |
|
|
# tech_dict = self.read_hdl_libraries_technology_file(technologyName)
|
226 |
|
|
# for lib_clause, lib_work in tech_dict.items():
|
227 |
|
|
# fp.write('%s = %s\n' % (lib_clause, lib_work))
|
228 |
|
|
|
229 |
|
|
for familyName in self.familyNames:
|
230 |
|
|
tech_dict = self.read_hdl_libraries_technology_file(familyName)
|
231 |
|
|
for lib_clause, lib_work in tech_dict.items():
|
232 |
|
|
fp.write('%s = %s\n' % (lib_clause, lib_work))
|
233 |
|
|
|
234 |
|
|
# . not used vendor technology libs are not compiled but are mapped to work to avoid compile error when mentioned in the LIBRARY clause
|
235 |
|
|
for removed_lib in sorted(self.removed_libs):
|
236 |
|
|
fp.write('%s = work\n' % self.removed_libs[removed_lib]['hdl_library_clause_name'])
|
237 |
|
|
|
238 |
|
|
# . unavailable used libs are not compiled but are mapped to work to avoid compile error when mentioned in the LIBRARY clause
|
239 |
|
|
for unavailable_use_name in sorted(self.unavailable_use_libs):
|
240 |
|
|
# if the unavailable library is not in the dictionary of disclosed unavailable library clause names, then assume that the library clause
|
241 |
|
|
# name has the default postfix '_lib'.
|
242 |
|
|
if unavailable_use_name in self.disclosed_library_clause_names:
|
243 |
|
|
fp.write('%s = work\n' % self.disclosed_library_clause_names[unavailable_use_name])
|
244 |
|
|
else:
|
245 |
|
|
fp.write('%s_lib = work\n' % unavailable_use_name)
|
246 |
|
|
|
247 |
|
|
# . all used libs for this lib_name
|
248 |
|
|
use_lib_names = self.derive_all_use_libs('sim', lib_name)
|
249 |
|
|
use_lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=use_lib_names)
|
250 |
|
|
use_lib_build_sim_dirs = self.get_lib_build_dirs('sim', lib_dicts=use_lib_dicts)
|
251 |
|
|
use_lib_clause_names = self.libs.get_key_values('hdl_library_clause_name', use_lib_dicts)
|
252 |
|
|
for lib_clause, lib_dir in zip(use_lib_clause_names, cm.listify(use_lib_build_sim_dirs)):
|
253 |
|
|
lib_work = os.path.join(lib_dir, 'work')
|
254 |
|
|
fp.write('%s = %s\n' % (lib_clause, lib_work))
|
255 |
|
|
|
256 |
|
|
# . work
|
257 |
|
|
fp.write('work = work\n')
|
258 |
|
|
|
259 |
|
|
# . others modelsim default libs
|
260 |
|
|
model_tech_dir = os.path.expandvars(self.buildset['modelsim_dir'])
|
261 |
|
|
fp.write('others = %s\n' % os.path.join(model_tech_dir, 'modelsim.ini'))
|
262 |
|
|
|
263 |
|
|
# Write [Project] section for all used libraries
|
264 |
|
|
fp.write('[Project]\n')
|
265 |
|
|
fp.write('Project_Version = 6\n') # must be >= 6 to fit all
|
266 |
|
|
fp.write('Project_DefaultLib = work\n')
|
267 |
|
|
fp.write('Project_SortMethod = unused\n')
|
268 |
|
|
|
269 |
|
|
# - project files
|
270 |
|
|
synth_files = lib_dict['synth_files'].split()
|
271 |
|
|
test_bench_files = lib_dict['test_bench_files'].split()
|
272 |
|
|
project_files = synth_files + test_bench_files
|
273 |
|
|
if 'modelsim_compile_ip_files' in lib_dict.content:
|
274 |
|
|
compile_ip_files = lib_dict['modelsim_compile_ip_files'].split()
|
275 |
|
|
project_files += compile_ip_files
|
276 |
|
|
fp.write('Project_Files_Count = %d\n' % len(project_files))
|
277 |
|
|
for i, fn in enumerate(project_files):
|
278 |
|
|
filePathName = cm.expand_file_path_name(fn, lib_dict.location)
|
279 |
|
|
fp.write('Project_File_%d = %s\n' % (i, filePathName))
|
280 |
|
|
|
281 |
|
|
project_file_p_defaults_hdl = 'vhdl_novitalcheck 0 group_id 0 cover_nofec 0 vhdl_nodebug 0 vhdl_1164 1 vhdl_noload 0 vhdl_synth 0 vhdl_enable0In 0 vlog_1995compat 0 last_compile 0 vhdl_disableopt 0 cover_excludedefault 0 vhdl_vital 0 vhdl_warn1 1 vhdl_warn2 1 vhdl_explicit 1 vhdl_showsource 0 cover_covercells 0 vhdl_0InOptions {} vhdl_warn3 1 vlog_vopt {} cover_optlevel 3 voptflow 1 vhdl_options {} vhdl_warn4 1 toggle - ood 0 vhdl_warn5 1 cover_noshort 0 compile_to work cover_nosub 0 dont_compile 0 vhdl_use93 2002 cover_stmt 1'
|
282 |
|
|
project_file_p_defaults_vhdl = 'file_type vhdl'
|
283 |
|
|
project_file_p_defaults_verilog = 'file_type verilog'
|
284 |
|
|
project_file_p_defaults_tcl = 'last_compile 0 compile_order -1 file_type tcl group_id 0 dont_compile 1 ood 1'
|
285 |
|
|
|
286 |
|
|
project_folders = []
|
287 |
|
|
offset = 0
|
288 |
|
|
|
289 |
|
|
nof_synth_files = len(synth_files)
|
290 |
|
|
if nof_synth_files > 0:
|
291 |
|
|
project_folders.append('synth_files')
|
292 |
|
|
for i in range(nof_synth_files):
|
293 |
|
|
|
294 |
|
|
# Add file type specific settings
|
295 |
|
|
file_ext = synth_files[i].split('.')[-1]
|
296 |
|
|
if file_ext == 'vhd' or file_ext == 'vhdl':
|
297 |
|
|
project_file_p_defaults_file_specific = project_file_p_defaults_vhdl
|
298 |
|
|
elif file_ext == 'v':
|
299 |
|
|
project_file_p_defaults_file_specific = project_file_p_defaults_verilog
|
300 |
|
|
else:
|
301 |
|
|
print('\nERROR - Undefined file extension in synth_files:', lib_name, synth_files[i])
|
302 |
|
|
sys.exit()
|
303 |
|
|
|
304 |
|
|
fp.write('Project_File_P_%d = folder %s compile_order %d %s\n' % (
|
305 |
|
|
offset+i, project_folders[-1], offset+i, project_file_p_defaults_hdl+' '+project_file_p_defaults_file_specific))
|
306 |
|
|
offset = nof_synth_files
|
307 |
|
|
|
308 |
|
|
nof_test_bench_files = len(test_bench_files)
|
309 |
|
|
if nof_test_bench_files > 0:
|
310 |
|
|
project_folders.append('test_bench_files')
|
311 |
|
|
for i in range(nof_test_bench_files):
|
312 |
|
|
|
313 |
|
|
# Add file type specific settings
|
314 |
|
|
file_ext = test_bench_files[i].split('.')[-1]
|
315 |
|
|
if file_ext == 'vhd' or file_ext == 'vho' or file_ext == 'vhdl':
|
316 |
|
|
project_file_p_defaults_file_specific = project_file_p_defaults_vhdl
|
317 |
|
|
elif file_ext == 'v':
|
318 |
|
|
project_file_p_defaults_file_specific = project_file_p_defaults_verilog
|
319 |
|
|
else:
|
320 |
|
|
print('\nERROR - Undefined file extension in test_bench_files:', lib_name, test_bench_files[i])
|
321 |
|
|
sys.exit()
|
322 |
|
|
|
323 |
|
|
fp.write('Project_File_P_%d = folder %s compile_order %d %s\n' % (
|
324 |
|
|
offset+i, project_folders[-1], offset+i, project_file_p_defaults_hdl+' '+project_file_p_defaults_file_specific))
|
325 |
|
|
offset += nof_test_bench_files
|
326 |
|
|
|
327 |
|
|
if 'modelsim_compile_ip_files' in lib_dict.content:
|
328 |
|
|
nof_compile_ip_files = len(compile_ip_files)
|
329 |
|
|
if nof_compile_ip_files > 0:
|
330 |
|
|
project_folders.append('compile_ip_files')
|
331 |
|
|
for i in range(nof_compile_ip_files):
|
332 |
|
|
fp.write('Project_File_P_%d = folder %s compile_order %d %s\n' % (
|
333 |
|
|
offset + i, project_folders[-1], offset + i, project_file_p_defaults_tcl))
|
334 |
|
|
offset += nof_compile_ip_files
|
335 |
|
|
|
336 |
|
|
# - project folders
|
337 |
|
|
fp.write('Project_Folder_Count = %d\n' % len(project_folders))
|
338 |
|
|
for i, fd in enumerate(project_folders):
|
339 |
|
|
fp.write('Project_Folder_%d = %s\n' % (i, fd))
|
340 |
|
|
fp.write('Project_Folder_P_%d = folder {Top Level}\n' % i)
|
341 |
|
|
|
342 |
|
|
# - simulation configurations
|
343 |
|
|
fp.write('Project_Sim_Count = %d\n' % len(test_bench_files))
|
344 |
|
|
project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization = self.simulation_configuration()
|
345 |
|
|
for i, fn in enumerate(test_bench_files):
|
346 |
|
|
fName = os.path.basename(fn)
|
347 |
|
|
tbName = os.path.splitext(fName)[0]
|
348 |
|
|
fp.write('Project_Sim_%d = %s\n' % (i, tbName))
|
349 |
|
|
for i, fn in enumerate(test_bench_files):
|
350 |
|
|
fName = os.path.basename(fn)
|
351 |
|
|
tbName = os.path.splitext(fName)[0]
|
352 |
|
|
fp.write('Project_Sim_P_%d = folder {Top Level} additional_dus work.%s %s %s %s %s\n' % (
|
353 |
|
|
i, tbName, project_sim_p_defaults, project_sim_p_search_libraries, project_sim_p_otherargs, project_sim_p_optimization))
|
354 |
|
|
|
355 |
|
|
# Write [vsim] section
|
356 |
|
|
fp.write('[vsim]\n')
|
357 |
|
|
fp.write('RunLength = 0 ps\n')
|
358 |
|
|
fp.write('resolution = 1fs\n')
|
359 |
|
|
fp.write('IterationLimit = 5000\n') # According to 'verror 3601' the default is 5000, typically 100 is enough, but e.g. the ip_stratixiv_phy_xaui_0 requires more.
|
360 |
|
|
fp.write('DefaultRadix = decimal\n')
|
361 |
|
|
print("Created {} project files".format(len(lib_dicts)))
|
362 |
|
|
|
363 |
|
|
def create_modelsim_project_files_file(self, lib_names=None):
|
364 |
|
|
"""Create file with list of the Modelsim project files for all HDL libraries.
|
365 |
|
|
|
366 |
|
|
Arguments:
|
367 |
|
|
- lib_names : one or more HDL libraries
|
368 |
|
|
"""
|
369 |
|
|
fileName = 'modelsim_project_files.txt' # use fixed file name
|
370 |
|
|
build_maindir, build_buildsetdir, build_tooldir, project_deeper_subdir = self.get_tool_build_dir('sim')
|
371 |
|
|
fileNamePath = os.path.join(build_maindir, build_buildsetdir, build_tooldir, fileName) # and use too build dir for file path
|
372 |
|
|
if lib_names is None:
|
373 |
|
|
lib_names = self.lib_names
|
374 |
|
|
with open(fileNamePath, 'w') as fp:
|
375 |
|
|
lib_dicts = self.libs.get_configfiles(key='hdl_lib_name', values=lib_names)
|
376 |
|
|
mpf_paths = self.get_lib_build_dirs('sim', lib_dicts=lib_dicts)
|
377 |
|
|
for lib_name, mpf_path in zip(cm.listify(lib_names), cm.listify(mpf_paths)):
|
378 |
|
|
fp.write('%s = %s\n' % (lib_name, mpf_path))
|
379 |
|
|
print("Created project file {}".format(fileNamePath))
|
380 |
|
|
|
381 |
|
|
|
382 |
|
|
if __name__ == '__main__':
|
383 |
|
|
# Mode
|
384 |
|
|
# 0 = Create Modelsim mpf files for all hdllib.cfg
|
385 |
|
|
# 1 = Read compile order from mpf for a single and write itinto the hdllib.cfg.
|
386 |
|
|
# This is useful to avoid having to manually edit the compile order for an existing $UNB .mpf into the hdllib.cfg.
|
387 |
|
|
# The compile order is important for the synth_files that need to be in hierarchical order. The test_bench_files are typically
|
388 |
|
|
# independent so these may be put in alphabetical order. The compile order is read from the .mpf and saved in the
|
389 |
|
|
# hdllib.cfg. The hdllib.cfg still does need some manual editing to set the proper key and paths.
|
390 |
|
|
mode = 0
|
391 |
|
|
|
392 |
|
|
buildsetSelect = sorted([cfgfile[13:-4] for cfgfile in listdir(os.path.expandvars('$RADIOHDL_CONFIG'))
|
393 |
|
|
if cfgfile.startswith("hdl_buildset_") and cfgfile.endswith(".cfg")])
|
394 |
|
|
# Parse command line arguments
|
395 |
|
|
argparser = ArgumentParser(description='Modelsim creates/updates all your modelsim environment(s).')
|
396 |
|
|
argparser.add_argument('buildset', help='choose buildset %s' % (buildsetSelect))
|
397 |
|
|
argparser.add_argument('-v', '--verbosity', required=False, type=int, default=0, help='verbosity >= 0 for more info')
|
398 |
|
|
args = argparser.parse_args()
|
399 |
|
|
|
400 |
|
|
# check arguments
|
401 |
|
|
if args.buildset not in buildsetSelect:
|
402 |
|
|
print('buildset %s is not supported' % args.buildset)
|
403 |
|
|
print("Supported buildset are:", buildsetSelect)
|
404 |
|
|
sys.exit(1)
|
405 |
|
|
args.buildsetFile = 'hdl_buildset_' + args.buildset + '.cfg'
|
406 |
|
|
|
407 |
|
|
# Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
|
408 |
|
|
msim = ModelsimConfig(toolRootDir=os.path.expandvars('$RADIOHDL_CONFIG'),
|
409 |
|
|
buildsetFile=args.buildsetFile,
|
410 |
|
|
libFileName='hdllib.cfg')
|
411 |
|
|
|
412 |
|
|
if mode == 0:
|
413 |
|
|
# Read the dictionary info from all HDL tool and library configuration files in the current directory and the sub directories
|
414 |
|
|
if args.verbosity >= 2:
|
415 |
|
|
print('#')
|
416 |
|
|
print('# ModelsimConfig:')
|
417 |
|
|
print('#')
|
418 |
|
|
print('')
|
419 |
|
|
print('HDL library paths that are found in %s:' % msim.libRootDirs)
|
420 |
|
|
for lib in sorted(msim.libs.configfiles.values()):
|
421 |
|
|
print(' ', lib.location)
|
422 |
|
|
|
423 |
|
|
if args.verbosity >= 2:
|
424 |
|
|
print('')
|
425 |
|
|
print('Build directories for simulation:')
|
426 |
|
|
for sim_dir in msim.get_lib_build_dirs('sim'):
|
427 |
|
|
print(' ', sim_dir)
|
428 |
|
|
|
429 |
|
|
print('')
|
430 |
|
|
print('Create library compile order files for simulation...')
|
431 |
|
|
msim.create_lib_order_files('sim')
|
432 |
|
|
# sys.exit(0)
|
433 |
|
|
|
434 |
|
|
print('')
|
435 |
|
|
print('Create library compile ip files...')
|
436 |
|
|
msim.create_modelsim_lib_compile_ip_files()
|
437 |
|
|
|
438 |
|
|
print('')
|
439 |
|
|
print('Create modelsim projects list file...')
|
440 |
|
|
msim.create_modelsim_project_files_file()
|
441 |
|
|
|
442 |
|
|
print('')
|
443 |
|
|
print('Create sub directory in project dir for all HDL libraries that are found in %s...' % msim.libRootDirs)
|
444 |
|
|
msim.create_sub_directory_in_build_lib_dir('sim', 'mmfiles') # should match c_mmf_local_dir_path in mm_file_pkg.vhd
|
445 |
|
|
|
446 |
|
|
print('')
|
447 |
|
|
print('Copy directories and files from HDL library source tree to project dir for all HDL libraries that are found in %s...' % msim.libRootDirs)
|
448 |
|
|
msim.copy_files('sim')
|
449 |
|
|
|
450 |
|
|
print('')
|
451 |
|
|
print('Create Modelsim Project Files for technology %s and all HDL libraries in %s...' % (msim.technologyNames, msim.libRootDirs))
|
452 |
|
|
msim.create_modelsim_project_file()
|
453 |
|
|
# sys.exit(0)
|
454 |
|
|
|
455 |
|
|
if mode == 1:
|
456 |
|
|
# for lib_name in ['ado','ap','bf','bist','blp','bp','cdo','cim','cir','cp','cr','dc','eth','fmf','i2c','lvds','pfs','pft2','rcuh','ri','rsp','rsr','rsu','sens','serdes','si','st','tbbi','tdsh']:
|
457 |
|
|
for lib_name in ['tst']:
|
458 |
|
|
# Read compile order from existing .mpf
|
459 |
|
|
# First manually create rudimentary hdllib.cfg file for the library with lib name and clause filled in. Then run this script to get
|
460 |
|
|
# the ordered list of src and tb files. Then manualy edit the hdllib.cfg to put the files at the synth or sim key.
|
461 |
|
|
# mpfPathName = os.path.expandvars('$UNB/Firmware/designs/%s/build/synth/quartus/sopc_%s_sim/%s.mpf' % (lib_name, lib_name, lib_name))
|
462 |
|
|
# mpfPathName = os.path.expandvars('$UNB/Firmware/modules/Lofar/%s/build/sim/modelsim/%s.mpf' % (lib_name, lib_name))
|
463 |
|
|
# mpfPathName = os.path.expandvars('$UNB/Firmware/modules/%s/build/sim/modelsim/%s.mpf' % (lib_name, lib_name))
|
464 |
|
|
mpfPathName = os.path.expandvars('$RSP/%s/build/sim/modelsim/%s.mpf' % (lib_name, lib_name))
|
465 |
|
|
compile_order = msim.read_compile_order_from_mpf(mpfPathName)
|
466 |
|
|
# Append the compile_order list to the lib_name dictionary hdllib.cfg file
|
467 |
|
|
lib_dict = msim.libs.get_configfiles(key='hdl_lib_name', values=lib_name)
|
468 |
|
|
lib_path = msim.libs.get_filePath(lib_dict)
|
469 |
|
|
filePathName = os.path.join(lib_path, 'hdllib.cfg')
|
470 |
|
|
print('')
|
471 |
|
|
print('Save modelsim compile order for', lib_name, 'in HDL library config file', filePathName)
|
472 |
|
|
msim.libs.append_key_to_dict_file(filePathName, 'files', compile_order)
|