variables.py 11.7 KB
Newer Older
Pawel Szostek's avatar
Pawel Szostek committed
1
# -*- coding: utf-8 -*-
2
#
3
# Copyright (c) 2013, 2014 CERN
Pawel Szostek's avatar
Pawel Szostek committed
4
# Author: Pawel Szostek (pawel.szostek@cern.ch)
5
# Multi-tool support by Javier D. Garcia-Lasheras (javier@garcialasheras.com)
Paweł Szostek's avatar
Paweł Szostek committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#
# This file is part of Hdlmake.
#
# Hdlmake is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Hdlmake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Hdlmake.  If not, see <http://www.gnu.org/licenses/>.
#
22

23 24
"""Module providing the HDLMake Manifest and its associated parser"""

25
from __future__ import absolute_import
Pawel Szostek's avatar
Pawel Szostek committed
26
import os
27
import logging
28

29
from .configparser import ConfigParser
Pawel Szostek's avatar
Pawel Szostek committed
30

31

32
class ManifestParser(ConfigParser):
33

34 35
    """This is the class providing HDLMake Manifest parser capabilities"""

36
    def __init__(self):
37
        super(ManifestParser, self).__init__(
38
            description="Configuration options description")
39 40
        general_options = [
            {'name': 'top_module',
41
             'default': None,
42
             'help': "Top level HDL entity for synthesis and simulation",
43
             'type': ''},
44 45 46 47
            {'name': 'extra_modules',
             'default': None,
             'help': "Extra HDL entities that must be present in the design",
             'type': []},
48
            {'name': 'include_dirs',
49 50 51
             'default': None,
             'help': "Include dirs for Verilog sources",
             'type': []},
52
            {'name': 'action',
53 54 55 56
             'default': '',
             'help': "What is the action that should be taken if "
             "HDLMake is run in auto mode (simulation/synthesis)",
             'type': ''},
57 58 59 60
            {'name': 'language',
             'default': 'VHDL',
             'help': "Default language to be used by the tool ",
             'type': ''},
61
            {'name': 'library',
62 63 64
             'default': "work",
             'help': "Destination library for module's VHDL files",
             'type': ""},
65
            {'name': 'incl_makefiles',
66 67 68
             'default': [],
             'help': "List of .mk files appended to toplevel makefile",
             'type': []},
69
            {'name': 'files',
70 71 72
             'default': [],
             'help': "List of files from the current module",
             'type': ''},
73
            {'name': 'modules',
74 75 76
             'default': {},
             'help': "List of local modules",
             'type': {}}]
77
        self.add_option_list(general_options)
78
        self.add_delimiter()
79 80 81
        self.add_type('include_dirs', type_new="")
        self.add_type('incl_makefiles', type_new='')
        self.add_type('files', type_new=[])
82 83
        self.add_allowed_key('modules', key="svn")
        self.add_allowed_key('modules', key="git")
84
        self.add_allowed_key('modules', key="gitsm")
85 86 87
        self.add_allowed_key('modules', key="local")
        fetch_options = [
            {'name': 'fetchto',
88 89 90
             'default': None,
             'help': "Destination for fetched modules",
             'type': ''},
91
            {'name': 'fetch_pre_cmd',
92 93 94
             'default': '',
                        'help': "Command to be executed before fetch",
                        'type': ''},
95
            {'name': 'fetch_post_cmd',
96 97 98
             'default': '',
                        'help': "Command to be executed after fetch",
                        'type': ''}]
99
        self.add_option_list(fetch_options)
100
        self.add_delimiter()
101 102
        syn_options = [
            {'name': 'syn_tool',
103 104 105
             'default': None,
             'help': "Tool to be used in the synthesis",
             'type': ''},
106 107 108 109
            {'name': 'syn_path',
             'default': None,
             'help': "Execution path for the Tool to be used in synthesis",
             'type': ''},
110
            {'name': 'syn_device',
111 112 113
             'default': None,
             'help': "Target FPGA device",
             'type': ''},
114
            {'name': 'syn_family',
115 116 117
             'default': None,
             'help': "Target FPGA family",
             'type': ''},
118
            {'name': 'syn_grade',
119 120 121
             'default': None,
             'help': "Speed grade of target FPGA",
             'type': ''},
122
            {'name': 'syn_package',
123 124 125
             'default': None,
             'help': "Package variant of target FPGA",
             'type': ''},
126
            {'name': 'syn_top',
127 128 129
             'default': None,
             'help': "Top level module for synthesis",
             'type': ''},
130
            {'name': 'syn_project',
131 132 133
             'default': None,
             'help': "Project file (.xise, .ise, .qpf)",
             'type': ''},
134 135 136 137
            {'name': 'syn_properties',
             'default': None,
             'help': "Synthesis properties",
             'type': []},
138
            {'name': 'syn_pre_project_cmd',
139
             'default': '',
140 141 142 143 144
             'help': "Command to be executed before synthesis: project",
             'type': ''},
            {'name': 'syn_post_project_cmd',
             'default': '',
             'help': "Command to be executed after synthesis: project",
145
             'type': ''},
146
            {'name': 'syn_pre_synthesize_cmd',
147 148 149
             'default': '',
             'help': "Command to be executed before synthesis: synthesize",
             'type': ''},
150
            {'name': 'syn_post_synthesize_cmd',
151 152 153
             'default': '',
             'help': "Command to be executed after synthesis: synthesize",
             'type': ''},
154
            {'name': 'syn_pre_translate_cmd',
155 156 157
             'default': '',
             'help': "Command to be executed before synthesis: translate",
             'type': ''},
158
            {'name': 'syn_post_translate_cmd',
159 160 161
             'default': '',
             'help': "Command to be executed after synthesis: translate",
             'type': ''},
162
            {'name': 'syn_pre_map_cmd',
163 164 165
             'default': '',
             'help': "Command to be executed before synthesis: map",
             'type': ''},
166
            {'name': 'syn_post_map_cmd',
167 168 169
             'default': '',
             'help': "Command to be executed after synthesis: map",
             'type': ''},
170
            {'name': 'syn_pre_par_cmd',
171 172 173
             'default': '',
             'help': "Command to be executed before synthesis: par",
             'type': ''},
174
            {'name': 'syn_post_par_cmd',
175 176 177
             'default': '',
             'help': "Command to be executed after synthesis: par",
             'type': ''},
178
            {'name': 'syn_pre_bitstream_cmd',
179 180 181
             'default': '',
             'help': "Command to be executed before synthesis: bitstream",
             'type': ''},
182
            {'name': 'syn_post_bitstream_cmd',
183 184 185
             'default': '',
             'help': "Command to be executed after synthesis: bitstream",
             'type': ''}]
186
        self.add_option_list(syn_options)
187
        self.add_delimiter()
188 189
        quartus_options = [
            {'name': 'quartus_preflow',
190 191 192
             'default': None,
             'help': "Quartus pre-flow script file",
             'type': ''},
193
            {'name': 'quartus_postmodule',
194 195 196
             'default': None,
             'help': "Quartus post-module script file",
             'type': ''},
197
            {'name': 'quartus_postflow',
198 199 200
             'default': None,
             'help': "Quartus post-flow script file",
             'type': ''}]
201
        self.add_option_list(quartus_options)
202
        self.add_delimiter()
203 204
        sim_options = [
            {'name': 'sim_top',
205 206 207
             'default': None,
             'help': "Top level module for simulation",
             'type': ''},
208
            {'name': 'sim_tool',
209 210 211
             'default': None,
             'help': "Simulation tool to be used (e.g. isim, vsim, iverilog)",
             'type': ''},
212 213 214 215
            {'name': 'sim_path',
             'default': None,
             'help': "Execution path for the Tool to be used in simulation",
             'type': ''},
216
            {'name': 'sim_pre_cmd',
217 218 219
             'default': None,
             'help': "Command to be executed before simulation",
             'type': ''},
220
            {'name': 'sim_post_cmd',
221 222 223
             'default': None,
             'help': "Command to be executed after simulation",
             'type': ''}]
224
        self.add_option_list(sim_options)
225
        self.add_delimiter()
226
        modelsim_options = [
227 228 229 230
            {'name': 'modelsim_ini_path',
             'default': None,
             'help': "Directory containing a custom Modelsim .ini file",
             'type': ''},
231
            {'name': 'vsim_opt',
232 233 234
             'default': "",
             'help': "Additional options for vsim",
             'type': ''},
235
            {'name': 'vcom_opt',
236 237 238
             'default': "",
             'help': "Additional options for vcom",
             'type': ''},
239
            {'name': 'vlog_opt',
240 241 242
             'default': "",
             'help': "Additional options for vlog",
             'type': ''},
243
            {'name': 'vmap_opt',
244 245 246
             'default': "",
             'help': "Additional options for vmap",
             'type': ''}]
247
        self.add_option_list(modelsim_options)
248
        self.add_delimiter()
249 250 251 252 253
        self.add_option(
            'iverilog_opt',
            default="",
            help="Additional options for IVerilog",
            type='')
254
        self.add_delimiter()
255 256 257 258 259
        self.add_option(
            'ghdl_opt',
            default="",
            help="Additional options for GHDL",
            type='')
260
        self.add_delimiter()
261 262 263 264 265 266 267 268

    def add_option_list(self, option_list):
        """Add to the parser a list with the options and their keys"""
        for option in option_list:
            self.add_option(option["name"],
                            default=option["default"],
                            help=option["help"],
                            type=option["type"])
269

270
    def add_manifest(self, path):
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
        """Add to configuration the Manifest at directory (path) if exists"""
        def _search_for_manifest(path):
            """
            Look for manifest in the given folder and create a Manifest object
            """
            logging.debug("Looking for manifest in " + path)
            dir_files = os.listdir(path)
            if "manifest.py" in dir_files and "Manifest.py" in dir_files:
                logging.error(
                    "Both manifest.py and Manifest.py" +
                    "found in the module directory: %s",
                    path)
                quit()
            for filename in dir_files:
                if filename == "manifest.py" or filename == "Manifest.py":
                    if not os.path.isdir(filename):
                        logging.debug("Found manifest for module %s: %s",
                                      path, filename)
                        path_aux = os.path.join(path, filename)
290 291
                        if not isinstance(path_aux, str):
                            raise ValueError("Path must be an instance of str")
292 293 294
                        #if not path_mod.is_abs_path(path_aux):
                        #    raise ValueError(
                        #        "Manifest path must be absolute path")
295
                        return path_aux
296 297
            return None
        manifest = _search_for_manifest(path)
298
        if manifest is None:
299 300
            logging.error("No manifest found in path: %s", path)
            quit()
301
        else:
302 303
            logging.debug("Parse manifest in: %s", manifest)
            return self.add_config_file(manifest)
Pawel Szostek's avatar
Pawel Szostek committed
304

305
    def print_help(self):
306
        """Print the help for the Manifest parser object"""
307
        self.help()