1 |
4 |
danv |
#!/usr/bin/env python3
|
2 |
|
|
###############################################################################
|
3 |
|
|
#
|
4 |
|
|
# Copyright (C) 2014-2018
|
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 |
|
|
# $Id$
|
22 |
|
|
#
|
23 |
|
|
###############################################################################
|
24 |
|
|
|
25 |
|
|
import sys
|
26 |
|
|
import os
|
27 |
|
|
from os.path import expandvars, dirname, basename
|
28 |
|
|
from subprocess import call, STDOUT
|
29 |
|
|
from common_radiohdl import listify, mkdir
|
30 |
|
|
from argparse import ArgumentParser
|
31 |
|
|
from hdl_configfile import HdlBuildset, HdlTool
|
32 |
|
|
from hdl_configtree import HdlLibTree
|
33 |
|
|
|
34 |
|
|
|
35 |
|
|
def run_qmegawiz(buildset, outputdir, hdllib, vhdl_files, options):
|
36 |
|
|
"""
|
37 |
|
|
Run qmegawiz for the configuration in the given hdllib.
|
38 |
|
|
The script takes care that the exit code of qmegawiz is returned to the caller.
|
39 |
|
|
"""
|
40 |
|
|
extra_options = hdllib.get_value("qmegawiz_extra_options", False)
|
41 |
|
|
if not extra_options:
|
42 |
|
|
extra_options = ""
|
43 |
|
|
|
44 |
|
|
error_code = 0
|
45 |
|
|
for vhdl_file in vhdl_files:
|
46 |
|
|
script = '. ${RADIOHDL_GEAR}/quartus/set_quartus %s\n' % buildset
|
47 |
|
|
script += 'cd %s\n' % outputdir
|
48 |
|
|
script += 'cp %s/%s .\n' % (hdllib.location, vhdl_file)
|
49 |
|
|
script += 'set -o pipefail\n'
|
50 |
|
|
# echo line without 'Info:' to make sure grep it's exit code is 0
|
51 |
|
|
script += '(echo " " ; qmegawiz %s %s %s 2>&1) | grep -iv Info:\n' \
|
52 |
|
|
% (options, extra_options, vhdl_file)
|
53 |
|
|
script += 'exit_code=$?\n'
|
54 |
|
|
script += 'rm %s\n' % vhdl_file
|
55 |
|
|
script += 'exit $exit_code\n'
|
56 |
|
|
# execute script
|
57 |
|
|
print("compiling {} ... ".format(vhdl_file))
|
58 |
7 |
danv |
return_code = call(script, stdout=None, stderr=STDOUT, shell=True, exectuable="/bin/bash")
|
59 |
4 |
danv |
# qmegawiz is very sloppy with it's exitcodes. We assume 0 is OK although this not always the case. :-(
|
60 |
|
|
if return_code == 0:
|
61 |
|
|
print("*** Generation (probably) OK\n")
|
62 |
|
|
else:
|
63 |
|
|
print("*** Error during generation, exitcode={}\n".format(return_code))
|
64 |
|
|
error_code |= return_code
|
65 |
|
|
return error_code
|
66 |
|
|
|
67 |
|
|
|
68 |
|
|
def run_qsys(buildset, outputdir, hdllib, vhdl_files, options):
|
69 |
|
|
"""
|
70 |
|
|
Run qsys for the configuration in the given hdllib.
|
71 |
|
|
The script takes care that the exit code of qsys is returned to the caller.
|
72 |
|
|
"""
|
73 |
|
|
extra_options = hdllib.get_value("qsys-generate_extra_options", False)
|
74 |
|
|
if not extra_options:
|
75 |
|
|
extra_options = ""
|
76 |
|
|
|
77 |
|
|
error_code = 0
|
78 |
|
|
for vhdl_file in vhdl_files:
|
79 |
|
|
script = '. ${RADIOHDL_GEAR}/quartus/set_quartus %s\n' % buildset
|
80 |
|
|
script += 'cd %s\n' % outputdir
|
81 |
|
|
script += 'cp %s/%s .\n' % (hdllib.location, vhdl_file)
|
82 |
|
|
#script += 'cd %s\n' % hdllib.location
|
83 |
|
|
script += 'set -o pipefail\n'
|
84 |
|
|
# echo line without 'Info:' to make sure grep it's exit code is 0
|
85 |
|
|
script += '(echo " " ; qsys-generate %s %s %s --search-path=%s --output-directory=%s 2>&1) | grep -iv Info:\n' \
|
86 |
|
|
% (vhdl_file, options, extra_options, "outputdir,$", outputdir)
|
87 |
|
|
script += 'exit_code=$?\n'
|
88 |
|
|
script += 'rm %s\n' % vhdl_file
|
89 |
|
|
script += 'exit $exit_code\n'
|
90 |
|
|
# execute script
|
91 |
|
|
print("compiling {} ... , output-dir = {}".format(vhdl_file, outputdir))
|
92 |
7 |
danv |
return_code = call(script, stdout=None, stderr=STDOUT, shell=True, executable="/bin/bash")
|
93 |
4 |
danv |
if return_code == 0:
|
94 |
|
|
print("*** Generation OK\n")
|
95 |
|
|
else:
|
96 |
|
|
print("*** Error during generation, exitcode={}\n".format(return_code))
|
97 |
|
|
error_code |= return_code
|
98 |
|
|
return error_code
|
99 |
|
|
|
100 |
|
|
|
101 |
|
|
def run_quartus_sh(buildset, outputdir, hdllib, tcl_files, options):
|
102 |
|
|
"""
|
103 |
|
|
Run quartus_sh for the configuration in the given hdllib.
|
104 |
|
|
The script takes care that the exit code of quartus_sh is returned to the caller.
|
105 |
|
|
"""
|
106 |
|
|
extra_options = hdllib.get_value("quartus_sh_extra_options", False)
|
107 |
|
|
if not extra_options:
|
108 |
|
|
extra_options = ""
|
109 |
|
|
|
110 |
|
|
error_code = 0
|
111 |
|
|
for tcl_file in tcl_files:
|
112 |
|
|
script = '. ${RADIOHDL_GEAR}/quartus/set_quartus %s\n' % buildset
|
113 |
|
|
script += 'cd %s/%s\n' % (outputdir, hdllib.quartus_sh_ip_srcdir)
|
114 |
|
|
script += 'set -o pipefail\n'
|
115 |
|
|
# echo line without 'Info:' to make sure grep it's exit code is 0
|
116 |
|
|
script += '(echo " " ; quartus_sh %s %s -t %s 2>&1) | grep -iv Info:\n' \
|
117 |
|
|
% (options, extra_options, tcl_file)
|
118 |
|
|
script += 'exit_code=$?\n'
|
119 |
|
|
script += 'exit $exit_code\n'
|
120 |
|
|
# execute script
|
121 |
|
|
print("compiling {} ... ".format(tcl_file))
|
122 |
7 |
danv |
return_code = call(script, stdout=None, stderr=STDOUT, shell=True, executable="/bin/bash")
|
123 |
4 |
danv |
if return_code == 0:
|
124 |
|
|
print("*** Generation OK\n")
|
125 |
|
|
else:
|
126 |
|
|
print("*** Error during generation, exitcode={}\n".format(return_code))
|
127 |
|
|
error_code |= return_code
|
128 |
|
|
return error_code
|
129 |
|
|
|
130 |
|
|
|
131 |
|
|
def expand_all_vars(dir_name):
|
132 |
|
|
_dirname = dir_name
|
133 |
|
|
while '$' in _dirname:
|
134 |
|
|
# print(_dirname)
|
135 |
|
|
_dirname = expandvars(_dirname)
|
136 |
|
|
return _dirname
|
137 |
|
|
|
138 |
|
|
|
139 |
|
|
if __name__ == '__main__':
|
140 |
|
|
# setup parser and parse the arguments.
|
141 |
|
|
argparser = ArgumentParser(description='Generate the IP libraries for all technologies of the given buildset')
|
142 |
|
|
argparser.add_argument('buildset', help="Filename like 'hdl_buildset_.cfg'")
|
143 |
|
|
args = argparser.parse_args()
|
144 |
|
|
|
145 |
|
|
# resolve full name of buildsetfile and force it to be explicit absolute or relative.
|
146 |
|
|
full_buildsetfile_name = os.path.join(os.getenv('RADIOHDL_CONFIG'), 'hdl_buildset_{}.cfg'.format(args.buildset))
|
147 |
|
|
print('full_buildsetfile_name={}'.format(full_buildsetfile_name))
|
148 |
|
|
if full_buildsetfile_name[0] != '/':
|
149 |
|
|
full_buildsetfile_name = "./" + full_buildsetfile_name
|
150 |
|
|
# read the file
|
151 |
|
|
buildset_info = HdlBuildset(full_buildsetfile_name)
|
152 |
|
|
buildset_info.resolve_key_references()
|
153 |
|
|
|
154 |
|
|
# read in all hdllib configfiles
|
155 |
|
|
root_dirs = [expand_all_vars(rootdir) for rootdir in buildset_info.lib_root_dirs.replace("\t", " ").split(" ")
|
156 |
|
|
if rootdir != '']
|
157 |
|
|
lib_tree = HdlLibTree(rootdirs=root_dirs, filename="hdllib.cfg", sections="generate_ip_libs")
|
158 |
|
|
|
159 |
|
|
# read in the tool environment settings
|
160 |
|
|
tool_config_file = os.path.join(os.getenv('RADIOHDL_CONFIG'), 'hdl_tool_{}.cfg'.format(buildset_info.synth_tool_name))
|
161 |
|
|
print('tool_config_file={}'.format(tool_config_file))
|
162 |
|
|
tool_info = HdlTool(tool_config_file)
|
163 |
|
|
tool_info.resolve_key_references()
|
164 |
|
|
ip_tools = [tool for tool in tool_info.ip_tools.replace("\t", " ").split(" ")
|
165 |
|
|
if tool != '']
|
166 |
|
|
|
167 |
|
|
files_with_errors = []
|
168 |
|
|
for technology in listify(buildset_info.technology_names):
|
169 |
|
|
print()
|
170 |
|
|
print("Generating IP libraries for technology:", technology)
|
171 |
|
|
# for all tools supported by quartus
|
172 |
|
|
for ip_tool in ip_tools:
|
173 |
|
|
tool_options = tool_info['{}_default_options'.format(ip_tool)]
|
174 |
|
|
ip_tool_key = "{}_ip_files".format(ip_tool)
|
175 |
|
|
# for all hdllib.cfg files found
|
176 |
|
|
for ip_lib_name in sorted(lib_tree.configfiles.keys())[::-1]: # TODO reverse order issue!
|
177 |
|
|
ip_lib_info = lib_tree.configfiles[ip_lib_name]
|
178 |
|
|
# if technology matches and there are files defined for the current tool
|
179 |
|
|
if ip_lib_info.hdl_lib_technology == technology and ip_tool_key in ip_lib_info.content:
|
180 |
|
|
# we have a match do the compilation
|
181 |
|
|
print("==> Processing {} with {}".format(ip_lib_info.ID, ip_tool))
|
182 |
|
|
outputdir = os.path.join(os.getenv('RADIOHDL_BUILD_DIR'), '{}/{}/'.format(args.buildset, ip_tool))
|
183 |
|
|
mkdir(outputdir)
|
184 |
|
|
vhdl_files = [name for name in ip_lib_info[ip_tool_key].replace("\t", " ").split(" ")
|
185 |
|
|
if name != '']
|
186 |
|
|
if ip_tool == 'qmegawiz':
|
187 |
|
|
err_code = run_qmegawiz(args.buildset, outputdir, ip_lib_info, vhdl_files, tool_options)
|
188 |
|
|
elif ip_tool == 'qsys-generate':
|
189 |
|
|
err_code = run_qsys(args.buildset, outputdir, ip_lib_info, vhdl_files, tool_options)
|
190 |
|
|
|
191 |
|
|
elif ip_tool == 'quartus_sh':
|
192 |
|
|
err_code = run_quartus_sh(args.buildset, outputdir, ip_lib_info, vhdl_files, tool_options)
|
193 |
|
|
else:
|
194 |
|
|
raise NameError("Hdllib file in %s contains a unknown tool (%s) for generating IP." %
|
195 |
|
|
(ip_lib_info.ID, ip_tool))
|
196 |
|
|
if err_code:
|
197 |
|
|
files_with_errors.append(ip_lib_info.ID)
|
198 |
|
|
|
199 |
|
|
if files_with_errors:
|
200 |
|
|
print("##### The following files had compile errors:")
|
201 |
|
|
print(" ", files_with_errors)
|
202 |
|
|
else:
|
203 |
|
|
print("+++++ No errors during compilation! +++++\n")
|