Newer
Older
#
# Copyright (c) 2011 Pawel Szostek (pawel.szostek@cern.ch)
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
#
class File(object):
def __init__(self, path):
self.path = path
@property
def name(self):
return os.path.basename(self.path)
@property
def purename(self):
return os.path.splitext(self.name)[0]
@property
def dirname(self):
return os.path.dirname(self.path)
def rel_path(self, dir=None):
import path
if dir == None:
dir = os.getcwd()
return path.relpath(self.path, dir)
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):
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, vcom_opt = None):
if not vcom_opt:
self.vcom_opt = ""
else:
self.vcom_opt = vcom_opt
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_requires = list(self.__search_use_clauses())
self.dep_provides = list(self.__search_packages())
p.vprint(self.path + " provides " + str(self.dep_provides))
p.vprint(self.path + " requires " + str(self.dep_requires))
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.
"""
if global_mod.top_module.action == "simulation":
try:
std_libs = flow.ModelsiminiReader().get_libraries()
except RuntimeError:
std_libs = flow.MODELSIM_STANDARD_LIBS
elif global_mod.top_module.action == "synthesis":
if global_mod.top_module.target == "xilinx":
std_libs = flow.ISE_STANDARD_LIBS
elif global_mod.top_module.target == "altera":
std_libs = flow.MODELSIM_STANDARD_LIBS
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:
#identifiers and keywords are case-insensitive in VHDL
line_lower = line.lower()
m = re.match(use_pattern, line_lower)
if m != None:
use_lines.append(m.group(1))
for line in use_lines:
m = re.match(lib_pattern, line)
if m != None:
if (m.group(1)).lower() in std_libs:
continue
if self.library != "work":
#if a file is put in a library, `work' points this library
new = (self.library.lower(), m.group(2).lower())
else:
new = (m.group(1).lower(), m.group(2).lower())
#dont add if the tuple is already in the list
if new in self.dep_provides:
continue
ret.add(new)
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]*.*$")
#identifiers and keywords are case-insensitive in VHDL
m = re.match(package_pattern, line)
if m != None:
ret.add((self.library.lower(), m.group(1).lower()))
def __init__(self, path, library = None, vlog_opt = None, include_dirs = None):
if not library:
library = "work"
SourceFile.__init__(self, path, library);
self.__create_deps();
if not vlog_opt:
self.vlog_opt = ""
else:
self.vlog_opt = vlog_opt
self.include_dirs = []
if include_dirs:
self.include_dirs.extend(include_dirs)
self.include_dirs.append(path_mod.relpath(self.dirname))
def __create_deps(self):
self.dep_requires = self.__search_includes()
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]+\"([^ \"]+)\".*$")
ret = []
for line in text:
#in Verilog and SV identifiers are case-sensitive
m = re.match(include_pattern, line)
if m != None:
ret.append(m.group(1))
f.close()
return ret
class SVFile(VerilogFile):
def __init__(self, path, library = None, vlog_opt = None, include_dirs = None):
VerilogFile.__init__(self, path, library, vlog_opt, include_dirs)
class TCLFile(File):
def __init__(self, path):
File.__init__(self, path)
class XISEFile(File):
def __init__(self, path):
File.__init__(self, path)
class CDCFile(File):
def __init__(self, path):
File.__init__(self, path)
class SignalTapFile(File):
def __init__(self, path):
File.__init__(self, path)
class SDCFile(File):
def __init__(self, path):
File.__init__(self, path)
class DPFFile(File):
def __init__(self, path):
File.__init__(self, path)
SourceFile.__init__(self, path);
class SourceFileSet(list):
def __str__(self):
return str([str(f) for f in self.files])
if isinstance(files, str):
raise RuntimeError("Expected object, not a string")
elif files == None:
p.vprint("Got None as a file.\n Ommiting")
else:
try:
for f in files:
if f not in self:
self.append(f)
except: #single file, not a list
if files not in self:
self.append(files)
out = SourceFileSet()
for f in self:
try:
ret.add(file.library)
except:
pass
return ret
class SourceFileFactory:
def new (self, path, library=None, vcom_opt=None, vlog_opt=None, include_dirs=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]
if extension == 'vhd' or extension == 'vhdl' or extension == 'vho':
nf = VHDLFile(path, library, vcom_opt)
elif extension == 'v' or extension == 'vh' or extension == 'vo':
nf = VerilogFile(path, library, vlog_opt, include_dirs)
elif extension == 'sv' or extension == 'svh':
nf = SVFile(path, library, vlog_opt, include_dirs)
nf = UCFFile(path)
elif extension == 'cdc':
nf = CDCFile(path)
elif extension == 'wb':
nf = WBGenFile(path);
elif extension == 'tcl':
nf = TCLFile(path)
elif extension == 'xise' or extension == 'ise':
elif extension == 'stp':
nf = SignalTapFile(path)
elif extension == 'sdc':
nf = SDCFile(path)
elif extension == 'dpf':
nf = DPFFile(path)