Skip to content
Snippets Groups Projects
srcfile.py 8.66 KiB
Newer Older
# -*- coding: utf-8 -*-
from dep_solver import IDependable 
import os
import msg as p
class File(object):
        def __init__(self, path):
                self.path = path
                self.name = os.path.basename(self.path)
                self.purename = os.path.splitext(self.name)[0]
                self.dirname = os.path.dirname(self.path)

        def __str__(self):
                return self.path

        def __eq__(self, other):
                _NOTFOUND = object()
                v1, v2 = [getattr(obj, "path", _NOTFOUND) for obj in [self, other]] 
                if v1 is _NOTFOUND or v2 is _NOTFOUND:
                    return False
                elif v1 != v2:
                    return False
                return True

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

        def __cmp__(self, other):
                if self.path < other.path:
                    return -1
                if self.path == other.path:
                    return 0
                if self.path > other.path:
                    return 1

        def __ne__(self, other):
                return not self.__eq__(other)

        def isdir(self):
                return os.path.isdir(self.path)

        def show(self):
                p.rawprint(self.path)

        def extension(self):
                tmp = self.path.rsplit('.')
                ext = tmp[len(tmp)-1]
                return ext

class SourceFile(IDependable, File):
        cur_index = 0
        def __init__(self, path, library = None):
                IDependable.__init__(self)
                File.__init__(self, path)
                if not library:
                        library = "work"

                self.library = library

        def gen_index(self):    
                self.__class__.cur_index = self.__class__.cur_index+1
                return self.__class__.cur_index


class VHDLFile(SourceFile):
        def __init__(self, path, library = None):
                SourceFile.__init__(self, path, library);
        def __check_encryption(self):
                f = open(self.path, "rb");
                s = f.read(3);
                f.close()
                if(s == b'Xlx'):
                        return True
                else:
                        return False
        def __create_deps(self):
                if self.__check_encryption():
                        self.dep_index = SourceFile.gen_index(self)
                        self.dep_fixed = True
                else:
                        self.dep_requires = self.__search_use_clauses()
                        self.dep_provides = self.__search_packages()
        def __search_use_clauses(self):
                """
                Reads a file and looks for 'use' clause. For every 'use' with
                non-standard library a tuple (lib, file) is returned in a list.

                """

                import re
                std_libs = ['ieee', 'altera_mf', 'cycloneiii', 'lpm', 'std', 'unisim', 'XilinxCoreLib', 'simprims']

                f = open(self.path, "r")
                try:
                        text = f.readlines()
                except UnicodeDecodeError:
                        return []

                use_pattern = re.compile("^[ \t]*use[ \t]+([^; ]+)[ \t]*;.*$")
                lib_pattern = re.compile("([^.]+)\.([^.]+)\.all")

                use_lines = []
                for line in text:
                        m = re.match(use_pattern, line)
                        if m != None:
                                use_lines.append(m.group(1))
                ret = []
                for line in use_lines:
                        m = re.match(lib_pattern, line)
                        if m != None:
                                if (m.group(1)).lower() in std_libs:
                                        continue
                                ret.append(m.group(1)+"::"+m.group(2))

                f.close()
                return ret
        def __search_packages(self):
                """
                Reads a file and looks for package clase. Returns list of packages' names
                from the file
                """

                import re
                f = open(self.path, "r")
                try:
                        text = f.readlines()
                except UnicodeDecodeError:
                        return []

                package_pattern = re.compile("^[ \t]*package[ \t]+([^ \t]+)[ \t]+is[ \t]*$")

                ret = []
                for line in text:
                        m = re.match(package_pattern, line)
                        if m != None:
                                ret.append(self.library+"::"+m.group(1))

                f.close()
                return ret
class VerilogFile(SourceFile):
        def __init__(self, path, library = None):
                if not library:
                        library = "work"
                SourceFile.__init__(self, path, library);
        def __create_deps(self):
                self.dep_requires = self.__search_includes()
                self.dep_provides = self.name 
        def __search_includes(self):
            import re
            f = open(self.path, "r")
            try:
                text = f.readlines()
            except UnicodeDecodeError:
                return []
            include_pattern = re.compile("^[ \t]*`include[ \t]+\"([^ \"]+)\"[ \t]*$")
            ret = []
            for line in text:
                    m = re.match(include_pattern, line)
                    if m != None:
                            ret.append(m.group(1))
            f.close()
            return ret

class UCFFile(SourceFile):
        def __init__(self, path):
                SourceFile.__init__(self, path);

class TCLFile(File):
        def __init__(self, path):
                File.__init__(self, path)
                
class XISEFile(File):
        def __init__(self, path):
                File.__init__(self, path)

class NGCFile(SourceFile):
        def __init__(self, path):
                SourceFile.__init__(self, path);

class WBGenFile(SourceFile):
        def __init__(self, path):
                SourceFile.__init__(self, path);

class SourceFileSet(object):
        def __init__(self):
                self.files = [];
        def __iter__(self):
                return self.files.__iter__()
        def __len__(self):
                return len(self.files)
        def __contains__(self,v):
                return v in self.files
        def __getitem__(self,v):
                return self.files[v]
        def __str__(self):
                return str([str(f) for f in self.files])

        def add(self, files):
                if isinstance(files, basestring):
                        raise RuntimeError("Expected object, not a string")
                elif files == None:
                        p.vprint("Got None as a file.\n Ommiting")
                                        if f not in self.files:
                                                self.files.append(f)
                        except: #single file, not a list
                                if files not in self.files:
                                        self.files.append(files)

        def filter(self, type):
                out = []
                for f in self.files:
                        if isinstance(f, type):
                                out.append(f)
                return out
        def get_libs(self):
                return set(file.library for file in self.files)


class SourceFileFactory:
        def new (self, path, library = None):
                if path == 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]
Paweł Szostek's avatar
Paweł Szostek committed
                p.vprint("SFF> " + path);
                nf = None
                if extension == 'vhd' or extension == 'vhdl':
                        nf = VHDLFile(path, library)
                elif extension == 'v' or extension == 'sv':
                        nf = VerilogFile(path, library);
                elif extension == 'ngc':
                        nf = NGCFile(path);
                elif extension == 'ucf':
                        nf = UCFFile(path);
                elif extension == 'wb':
                        nf = WBGenFile(path);
                elif extension == 'tcl':
                        nf = TCLFile(path)
                elif extension == 'xise':
                        nf = XISEFile(path)
                return nf