srcfile.py 10.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
# -*- coding: utf-8 -*-
#
# Copyright (c) 2013, 2014 CERN
# Author: Pawel Szostek (pawel.szostek@cern.ch)
# Multi-tool support by Javier D. Garcia-Lasheras (javier@garcialasheras.com)
#
# 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/>.
#

"""Module providing the source file class and a set of classes
representing the different possible files and file extensions"""

from __future__ import print_function
from __future__ import absolute_import
import os
import logging

from .util import path as path_mod
from .dep_file import DepFile, File
import six


class SourceFile(DepFile):

    """This is a class acting as a base for the different
    HDL sources files, i.e. those that can be parsed"""

    cur_index = 0

    def __init__(self, path, module, library):
        assert isinstance(path, six.string_types)
45
        self.is_include = False
46 47 48 49 50 51 52 53 54 55 56
        self.library = library
        if not library:
            self.library = "work"
        DepFile.__init__(self,
                         file_path=path,
                         module=module)

    def __hash__(self):
        return hash(self.path + self.library)


57 58
# SOURCE FILES

59 60 61 62
class VHDLFile(SourceFile):

    """This is the class providing the generic VHDL file"""

63
    def __init__(self, path, module, library=None):
64
        SourceFile.__init__(self, path=path, module=module, library=library)
65 66
        from hdlmake.vhdl_parser import VHDLParser
        self.parser = VHDLParser(self)
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

    def _check_encryption(self):
        """Check if the VHDL is encrypted (in Xilinx toolchain)"""
        file_aux = open(self.path, "rb")
        text = file_aux.read(3)
        file_aux.close()
        if text == b'Xlx':
            return True
        else:
            return False


class VerilogFile(SourceFile):

    """This is the class providing the generic Verilog file"""

    def __init__(self, path, module, library=None,
84
                 include_dirs=None, is_include=False):
85
        SourceFile.__init__(self, path=path, module=module, library=library)
86
        from hdlmake.vlog_parser import VerilogParser
87 88 89 90
        self.include_dirs = []
        if include_dirs:
            self.include_dirs.extend(include_dirs)
        self.include_dirs.append(path_mod.relpath(self.dirname))
91 92 93
        self.parser = VerilogParser(self)
        for dir_aux in self.include_paths:
            self.parser.add_search_path(dir_aux)
94
        self.is_include = is_include
95 96 97 98 99 100 101


class SVFile(VerilogFile):
    """This is the class providing the generic SystemVerilog file"""
    pass


102
# TCL COMMAND FILE
103 104 105 106 107 108

class TCLFile(File):
    """This is the class providing the Tool Command Language file"""
    pass


109 110 111 112 113 114 115
# XILINX FILES

class UCFFile(File):
    """This is the class providing the User Constraint Guide file"""
    pass


116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
class XISEFile(File):
    """This is the class providing the new Xilinx ISE project file"""
    pass


class CDCFile(File):
    """This is the class providing the Xilinx ChipScope Definition
    and Connection file"""
    pass


class XMPFile(File):
    """Xilinx Embedded Micro Processor"""
    pass


class PPRFile(File):
    """Xilinx PlanAhead Project"""
    pass


class XPRFile(File):
    """Xilinx Vivado Project"""
    pass


class BDFile(File):
    """Xilinx Block Design"""
    pass


class XCOFile(File):
    """Xilinx Core Generator File"""
    pass


class NGCFile(File):
    """Xilinx Generated Netlist File"""
    pass


157 158 159 160 161
class XDCFile(File):
    """Xilinx Design Constraint File"""
    pass


162 163 164 165 166
class XCFFile(File):
    """Xilinx XST Constraint File"""
    pass


167 168 169 170 171 172 173 174 175 176
class COEFile(File):
    """Xilinx Coefficient File"""
    pass


class MIFFile(File):
    """Xilinx Memory Initialization File"""
    pass


177 178 179 180 181
class RAMFile(File):
    """Xilinx RAM  File"""
    pass


182 183 184 185 186
class VHOFile(File):
    """Xilinx VHDL Template File"""
    pass


187 188 189 190 191
class BMMFile(File):
    """Xilinx Block Memory Map File"""
    pass


192 193 194 195 196
class VEOFile(File):
    """Xilinx Verilog Template File"""
    pass


197 198 199 200 201
class XCIFile(File):
    """Xilinx Core IP File"""
    pass


202 203 204 205 206 207 208 209 210 211
XILINX_FILE_DICT = {
    'xise': XISEFile,
    'ise': XISEFile,
    'ngc': NGCFile,
    'ucf': UCFFile,
    'cdc': CDCFile,
    'xmp': XMPFile,
    'ppr': PPRFile,
    'xpr': XPRFile,
    'bd': BDFile,
212 213
    'xco': XCOFile,
    'xdc': XDCFile,
214
    'xcf': XCFFile,
215 216
    'coe': COEFile,
    'mif': MIFFile,
217
    'ram': RAMFile,
218 219
    'vho': VHOFile,
    'veo': VEOFile,
220
    'bmm': BMMFile,
221
    'xci': XCIFile}
222 223 224 225 226 227 228 229 230 231 232


# SYNOPSYS FILES

class SDCFile(File):
    """Synopsys Design Constraints"""
    pass


# LATTICE FILES

233 234 235 236 237 238 239 240 241
class LDFFile(File):
    """Lattice Diamond Project File"""
    pass


class LPFFile(File):
    """Lattice Preference/Constraint File"""
    pass

242 243 244
class PCFFile(File):
    """Icestorm Physical constraints File"""
    pass
245 246 247 248 249 250

class EDFFile(File):
    """EDIF Netlist Files"""
    pass


251 252 253 254 255 256
LATTICE_FILE_DICT = {
    'ldf': LDFFile,
    'lpf': LPFFile,
    'edf': EDFFile,
    'edif': EDFFile,
    'edi': EDFFile,
257 258
    'edn': EDFFile,
    'pcf': PCFFile}
259 260 261 262


# MICROSEMI/ACTEL FILES

263 264 265 266 267
class PDCFile(File):
    """Physical Design Constraints"""
    pass


268 269 270 271 272 273
MICROSEMI_FILE_DICT = {
    'pdc': PDCFile}


# OHR FILES

274 275 276 277 278
class WBGenFile(File):
    """Wishbone generator file"""
    pass


279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
# INTEL/ALTERA FILES

class QIPFile(File):
    """This is the class providing the Altera Quartus IP file"""
    pass


class QSYSFile(File):
    """Qsys - Altera's System Integration Tool"""
    pass


class DPFFile(File):
    """This is the class providing Altera Quartus Design Protocol File"""
    pass


296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
class QSFFile(File):
    """Quartus Settings File"""
    pass


class BSFFile(File):
    """Quartus Block Symbol File"""
    pass


class BDFFile(File):
    """Quartus Block Design File"""
    pass


class TDFFile(File):
    """Quartus Text Design File"""
    pass


class GDFFile(File):
    """Quartus Graphic Design File"""
    pass


321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
class SignalTapFile(File):
    """This is the class providing the Altera Signal Tap Language file"""
    pass


ALTERA_FILE_DICT = {
    'stp': SignalTapFile,
    'qip': QIPFile,
    'qsys': QSYSFile,
    'dpf': DPFFile,
    'qsf': QSFFile,
    'bsf': BSFFile,
    'bdf': BDFFile,
    'tdf': TDFFile,
    'gdf': GDFFile}


338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
class SourceFileSet(set):

    """Class providing a extension of the 'set' object that includes
    methods that allow for an easier management of a collection of HDL
    source files"""

    def __init__(self):
        super(SourceFileSet, self).__init__()
        self = []

    def __str__(self):
        return str([str(f) for f in self])

    def add(self, files):
        """Add a set of files to the source fileset instance"""
        if isinstance(files, str):
            raise RuntimeError("Expected object, not a string")
        elif files is None:
            logging.debug("Got None as a file.\n Ommiting")
        else:
            try:
                for file_aux in files:
                    super(SourceFileSet, self).add(file_aux)
            except TypeError:  # single file, not a list
                super(SourceFileSet, self).add(files)

    def filter(self, filetype):
        """Method that filters and returns all of the HDL source files
        contained in the instance SourceFileSet matching the provided type"""
        out = SourceFileSet()
        for file_aux in self:
            if isinstance(file_aux, filetype):
                out.add(file_aux)
        return out

    def inversed_filter(self, filetype):
        """Method that filters and returns all of the HDL source files
        contained in the instance SourceFileSet NOT matching the provided
        type"""
        out = SourceFileSet()
        for file_aux in self:
            if not isinstance(file_aux, filetype):
                out.add(file_aux)
        return out

    def get_libs(self):
        """Method that returns a set containing all of the libraries that are
        provided by any of the source files in the SourceFileSet"""
        ret = set()
        for file_aux in self:
            try:
                ret.add(file_aux.library)
            except TypeError:
                pass
        return ret


def create_source_file(path, module, library=None,
396
                       include_dirs=None, is_include=False):
397 398 399 400 401 402 403 404 405 406 407 408 409 410
    """Function that analyzes the given arguments and returns a new HDL source
    file of the appropriated type"""
    if path is None or path == "":
        raise RuntimeError("Expected a file path, got: " + str(path))
    if not os.path.isabs(path):
        path = os.path.abspath(path)
    tmp = path.rsplit('.')
    extension = tmp[len(tmp) - 1]
    logging.debug("add file " + path)

    new_file = None
    if extension in ['vhd', 'vhdl', 'vho']:
        new_file = VHDLFile(path=path,
                            module=module,
411
                            library=library)
412 413 414 415
    elif extension in ['v', 'vh', 'vo', 'vm']:
        new_file = VerilogFile(path=path,
                               module=module,
                               library=library,
416 417
                               include_dirs=include_dirs,
                               is_include=is_include)
418 419 420 421
    elif extension == 'sv' or extension == 'svh':
        new_file = SVFile(path=path,
                          module=module,
                          library=library,
422 423
                          include_dirs=include_dirs,
                          is_include=is_include)
424 425 426 427 428 429
    elif extension == 'wb':
        new_file = WBGenFile(path=path, module=module)
    elif extension == 'tcl':
        new_file = TCLFile(path=path, module=module)
    elif extension == 'sdc':
        new_file = SDCFile(path=path, module=module)
430 431 432 433 434 435 436 437
    elif extension in XILINX_FILE_DICT:
        new_file = XILINX_FILE_DICT[extension](path=path, module=module)
    elif extension in ALTERA_FILE_DICT:
        new_file = ALTERA_FILE_DICT[extension](path=path, module=module)
    elif extension in LATTICE_FILE_DICT:
        new_file = LATTICE_FILE_DICT[extension](path=path, module=module)
    elif extension in MICROSEMI_FILE_DICT:
        new_file = MICROSEMI_FILE_DICT[extension](path=path, module=module)
438 439 440
    else:
        logging.error("Cannot create source file %s, "
                      "unknown file extension %s", path, extension)
441
        quit(1)
442
    return new_file