def __GetModelSimVersion(self, binPath): if (self._host.Platform == "Windows"): vsimPath = binPath / "vsim.exe" else: vsimPath = binPath / "vsim" if not vsimPath.exists(): raise ConfigurationException("Executable '{0!s}' not found.".format(vsimPath)) \ from FileNotFoundError(str(vsimPath)) # get version and backend try: output = check_output([str(vsimPath), "-version"], universal_newlines=True) except OSError as ex: raise ConfigurationException( "Error while accessing '{0!s}'.".format(vsimPath)) from ex version = None versionRegExpStr = r"^.* vsim (.+?) " versionRegExp = re_compile(versionRegExpStr) for line in output.split('\n'): if version is None: match = versionRegExp.match(line) if match is not None: version = match.group(1) self._host.Config[self._section]['Version'] = version
def _DecodeAltera(self, deviceString): self.__vendor = Vendors.Altera deviceRegExpStr = r"(?P<gen>\d{1,2})" # generation deviceRegExpStr += r"(?P<fam>[acms])" # family deviceRegExpStr += r"(?P<st>(ls|e|g|x|t|gs|gx|gt|gz|sx|st)?)" # subtype deviceRegExp = re_compile(deviceRegExpStr) deviceRegExpMatch = deviceRegExp.match(deviceString[2:].lower()) if (deviceRegExpMatch is not None): self.__generation = int(deviceRegExpMatch.group('gen')) family = deviceRegExpMatch.group('fam') for fam in AlteraFamilies: if fam.Token == family: self.__family = fam break else: raise ConfigurationException("Unknown Altera device family.") subtype = deviceRegExpMatch.group('st') if (subtype != ""): d = {"g": "gx", "x": "sx", "t": "gt"} # re-name for Stratix 10 and Arria 10 if subtype in d: subtype = d[subtype] try: self.__subtype = AlteraSubTypes[subtype.upper()] except KeyError as ex: raise ConfigurationException("Unknown subtype '{0}'.".format(subtype)) from ex else: self.__subtype = AlteraSubTypes.NoSubType else: raise ConfigurationException("RegExp mismatch.")
def __WriteGitSection(self, binPath): if (self._host.Platform == "Windows"): gitPath = binPath / "git.exe" else: gitPath = binPath / "git" if not gitPath.exists(): raise ConfigurationException( "Executable '{0!s}' not found.".format( gitPath)) from FileNotFoundError(str(gitPath)) # get version and backend output = check_output([str(gitPath), "--version"], universal_newlines=True) version = None versionRegExpStr = r"^git version (\d+\.\d+\.\d+).*" versionRegExp = re_compile(versionRegExpStr) for line in output.split('\n'): if version is None: match = versionRegExp.match(line) if match is not None: version = match.group(1) if (version is None): raise ConfigurationException( "Version number not found in '{0!s} --version' output.".format( gitPath)) self._host.Config[self._section]['Version'] = version
def __CheckVivadoVersion(self, binPath, version): if (self._host.Platform == "Windows"): vivadoPath = binPath / "vivado.bat" else: vivadoPath = binPath / "vivado" if not vivadoPath.exists(): raise ConfigurationException("Executable '{0!s}' not found.".format(vivadoPath)) from FileNotFoundError(str(vivadoPath)) output = check_output([str(vivadoPath), "-version"], universal_newlines=True) if str(version) not in output: raise ConfigurationException("Vivado version mismatch. Expected version {0}.".format(version))
def __CheckISEVersion(self, binPath): # check for ISE 14.7 if (self._host.Platform == "Windows"): fusePath = binPath / "fuse.exe" else: fusePath = binPath / "fuse" if not fusePath.exists(): raise ConfigurationException("Executable '{0!s}' not found.".format(fusePath)) from FileNotFoundError(str(fusePath)) output = check_output([str(fusePath), "--version"], universal_newlines=True) if "P.20131013" not in output: raise ConfigurationException("ISE version mismatch. Expected version 14.7 (P.20131013).")
def __init__(self, host, boardName=None, device=None): # Board members if (boardName is None): boardName = "GENERIC" elif (boardName == ""): raise ValueError("Parameter 'board' is empty.") elif (not isinstance(boardName, str)): raise ValueError("Parameter 'board' is not of type str.") boardName = boardName.lower() if (boardName == "custom"): if (device is None): raise ValueError("Parameter 'device' is None.") elif isinstance(device, Device): self.__device = device else: self.__device = Device(device) else: boardSectionName = None for board in host.Config['BOARDS']: if (board.lower() == boardName): boardSectionName = host.Config['BOARDS'][board] # real board name boardName = boardSectionName.split('.')[1] break else: raise ConfigurationException("Unknown board '{0}'".format(boardName)) deviceName = host.Config[boardSectionName]['FPGA'] self.__device = Device(deviceName) self.__boardName = boardName
def __init__(self, deviceString): # Device members self.__vendor = Vendors.Unknown self.__family = GenericFamilies.Unknown self.__device = GenericDevices.Unknown self.__generation = 0 self.__subtype = GenericSubTypes.Unknown self.__number = 0 self.__speedGrade = 0 self.__package = Packages.Unknown self.__pinCount = 0 self.__deviceString = deviceString if (not isinstance(deviceString, str)): raise ValueError("Parameter 'deviceString' is not of type str.") if ((deviceString is None) or (deviceString == "")): raise ValueError("Parameter 'deviceString' is empty.") # vendor = GENERIC # ========================================================================== if (deviceString[0:2].lower() == "ge"): self._DecodeGeneric() # ge - Generic FPGA device elif (deviceString[0:2].lower() == "xc"): self._DecodeXilinx(deviceString) # xc - Xilinx devices (XC = Xilinx Commercial) elif (deviceString[0:2].lower() == "ep"): self._DecodeAltera(deviceString) # ep - Altera devices elif (deviceString[0:3].lower() == "ice"): self._DecodeLatticeICE(deviceString) # ice - Lattice iCE series elif (deviceString[0:3].lower() == "lcm"): self._DecodeLatticeLCM(deviceString) # lcm - Lattice MachXO series elif (deviceString[0:3].lower() == "lfe"): self._DecodeLatticeLFE(deviceString) # lfe - Lattice ECP series else: raise ConfigurationException("Unknown manufacturer code in device string '{0}'".format(deviceString))
def __UninstallGitHooks(self): self._host.LogNormal(" Uninstalling Git hooks...") pyIPCMIInstallationPath = Path( self._host.Config[self._host.LibraryKey]['InstallationDirectory']) hookRunnerPath = pyIPCMIInstallationPath / "tools/git/hooks/run-hook.sh" gitDirectoryPath = self.__GetGitDirectory() gitHookDirectoryPath = gitDirectoryPath / "hooks" for hookName in ["pre-commit"]: gitHookPath = gitHookDirectoryPath / hookName if gitHookPath.exists(): if (gitHookPath.is_symlink() and (gitHookPath.resolve() == hookRunnerPath)): self._host.LogNormal( " '{0}' hook is configured for pyIPCMI. Deleting.". format(hookName)) try: gitHookPath.unlink() except OSError as ex: raise ConfigurationException( "Cannot remove '{0!s}'.".format( gitHookPath)) from ex else: # TODO: check if file was copied -> Hash compare? self._host.LogWarning( " '{0}' hook is in use by another script. Skipping.". format(hookName))
def _LazyLoadable_Load(self): super()._LazyLoadable_Load() self._name = self._host.Config[self._configSection]['Name'] self._path = self._host.Directories.Root / self._host.Config[self._configSection]['Path'] solutionConfigPath = self._path / ".pyIPCMI" if (not self._path.is_absolute()): solutionConfigPath = self._host.Directories.Root / solutionConfigPath configFiles = [ solutionConfigPath / self.__SOLUTION_CONFIG_FILE__, solutionConfigPath / self.__SOLUTION_DEFAULT_FILE__ ] for configFile in configFiles: if (not configFile.exists()): raise ConfigurationException("Solution configuration file '{0!s}' not found.".format(configFile)) from FileNotFoundError(str(configFile)) self._host.Config.read(str(configFile)) # load projects for option in self._host.Config[self._configSection]: project = None if (self._host.Config[self._configSection][option] == "ISEProject"): project = ISEProject(self._host, option, self) elif (self._host.Config[self._configSection][option] == "VivadoProject"): project = VivadoProject(self._host, option, self) elif (self._host.Config[self._configSection][option] == "QuartusProject"): project = QuartusProject(self._host, option, self) elif (self._host.Config[self._configSection][option] == "LatticeProject"): project = LatticeProject(self._host, option, self) if (project is not None): self._projects[option.lower()] = project
def _DecodeLatticeLFE(self, deviceString): self.__vendor = Vendors.Lattice self.__family = LatticeFamilies.ECP self.__generation = int(deviceString[3:4]) if (self.__generation == 3): self._DecodeLatticeECP3(deviceString) elif (self.__generation == 5): self._DecodeLatticeECP5(deviceString) else: raise ConfigurationException("Unknown Lattice ECP generation.")
def __CheckActiveHDLVersion(self, binPath, version): """Compare the given Active-HDL version with the tool's version string.""" # TODO: use vsim abstraction? if (self._host.Platform == "Windows"): vsimPath = binPath / "vsim.exe" else: vsimPath = binPath / "vsim" if not vsimPath.exists(): raise ConfigurationException("Executable '{0!s}' not found.".format(vsimPath)) \ from FileNotFoundError(str(vsimPath)) output = check_output([str(vsimPath), "-version"], universal_newlines=True) if str(version) not in output: raise ConfigurationException( "Active-HDL version mismatch. Expected version {0}.".format( version))
def __CheckQuartusVersion(self, binPath, version): if (self._host.Platform == "Windows"): quartusPath = binPath / "quartus_sh.exe" else: quartusPath = binPath / "quartus_sh" if not quartusPath.exists(): raise ConfigurationException( "Executable '{0!s}' not found.".format( quartusPath)) from FileNotFoundError(str(quartusPath)) output = check_output([str(quartusPath), "-v"], universal_newlines=True, stderr=STDOUT) if "Version {0}".format(version) not in output: raise ConfigurationException( "Quartus version mismatch. Expected version {0}.".format( version))
def __InstallGitHooks(self): self._host.LogNormal(" Installing Git hooks...") pyIPCMIInstallationPath = Path( self._host.Config[self._host.LibraryKey]['InstallationDirectory']) hookRunnerPath = pyIPCMIInstallationPath / "tools/git/hooks/run-hook.sh" if (not hookRunnerPath.exists()): raise ConfigurationException( "Runner script '{0!s}' not found.".format( hookRunnerPath)) from FileNotFoundError( str(hookRunnerPath)) gitDirectoryPath = self.__GetGitDirectory() gitHookDirectoryPath = gitDirectoryPath / "hooks" for hookName in ["pre-commit"]: gitHookPath = gitHookDirectoryPath / hookName if gitHookPath.exists(): if (gitHookPath.is_symlink() and (gitHookPath.resolve() == hookRunnerPath)): self._host.LogNormal( " '{0}' hook is already configured for pyIPCMI.". format(hookName)) else: self._host.LogWarning( " '{0}' hook is already in use by another script.". format(hookName)) else: self._host.LogNormal( " Setting '{0}' hook for pyIPCMI...".format(hookName)) self._host.LogDebug("symlink '{0!s}' -> '{1!s}'.".format( gitHookPath, hookRunnerPath)) try: gitHookPath.symlink_to(hookRunnerPath) except OSError as ex: # if symlink fails, do a copy as backup solution if getattr(ex, 'winerror', None) == 1314: self._host.LogDebug("copy '{0!s}' to '{1!s}'.".format( hookRunnerPath, gitHookPath)) try: shutil_copy(str(hookRunnerPath), str(gitHookPath)) except OSError as ex2: raise ConfigurationException() from ex2
def RunPostConfigurationTasks(self): if (len(self._host.Config[self._section]) == 0): return # exit if not configured precompiledDirectory = self._host.Config['CONFIG.DirectoryNames'][ 'PrecompiledFiles'] vSimSimulatorFiles = self._host.Config['CONFIG.DirectoryNames'][ 'ModelSimFiles'] vsimPath = self._host.Directories.Root / precompiledDirectory / vSimSimulatorFiles modelsimIniPath = vsimPath / "modelsim.ini" if not vsimPath.exists(): self.LogVerbose("Creating directory for ModelSim files.") try: self.LogDebug("Creating directory '{0!s}'.".format(vsimPath)) vsimPath.mkdir(parents=True) except OSError as ex: raise ConfigurationException( "Error while creating '{0!s}'.".format(vsimPath)) from ex else: self.LogDebug("Directory for ModelSim files already exists.") if not modelsimIniPath.exists(): self.LogVerbose("Creating initial 'modelsim.ini' file.") self.LogDebug( "Writing initial 'modelsim.ini' file to '{0!s}'.".format( modelsimIniPath)) try: with modelsimIniPath.open('w') as fileHandle: fileContent = dedent("""\ [Library] others = $MODEL_TECH/../modelsim.ini """) fileHandle.write(fileContent) except OSError as ex: raise ConfigurationException( "Error while creating '{0!s}'.".format( modelsimIniPath)) from ex else: self.LogVerbose( "ModelSim configuration file '{0!s}' already exists.".format( modelsimIniPath))
def Path(self): cur = self result = [] while True: result.insert(0, cur) cur = cur.Parent if isinstance(cur, Library): break else: raise ConfigurationException("Hierarchy error. Expected Library.") return result
def __CheckDiamondVersion(self, binPath, version): if (self._host.Platform == "Windows"): tclShellPath = binPath / "pnmainc.exe" else: tclShellPath = binPath / "pnmainc" if not tclShellPath.exists(): raise ConfigurationException("Executable '{0!s}' not found.".format(tclShellPath)) from FileNotFoundError( str(tclShellPath)) try: output = check_output([str(tclShellPath), "???"], stderr=STDOUT, universal_newlines=True) except CalledProcessError as ex: output = ex.output for line in output.split('\n'): if str(version) in line: break else: raise ConfigurationException("Diamond version mismatch. Expected version {0}.".format(version)) self._host.Config[self._section]['Version'] = version
def QueryConfiguration(self, query): if (query == "ModelSim:InstallationDirectory"): result = self._GetModelSimInstallationDirectory() elif (query == "ModelSim:BinaryDirectory"): result = self._GetModelSimBinaryDirectory() elif (query == "Xilinx.ISE:SettingsFile"): result = self._GetXilinxISESettingsFile() elif (query == "Xilinx.Vivado:SettingsFile"): result = self._GetXilinxVivadoSettingsFile() else: parts = query.split(":") if (len(parts) == 2): sectionName = parts[0] optionName = parts[1] try: result = self.Config[sectionName][optionName] except KeyError as ex: raise ConfigurationException("Requested setting '{0}:{1}' not found.".format(sectionName, optionName)) from ex else: raise ConfigurationException("Syntax error in query string '{0}'".format(query)) if isinstance(result, Path): result = str(result) return result
def _ConfigureBinaryDirectory(self): """Updates section with value from _template and returns directory as Path object.""" binPath = super()._ConfigureBinaryDirectory() # unresolved = self._template[self._host.Platform][self._section]['BinaryDirectory2'] # self._host.Config[self._section]['BinaryDirectory2'] = unresolved # create entry defaultPath = Path(self._host.Config[self._section]['BinaryDirectory2']) # resolve entry binPath2 = defaultPath # may be more complex in the future if (not binPath2.exists()): raise ConfigurationException("{0!s} 2nd binary directory '{1!s}' does not exist.".format(self, binPath2)) \ from NotADirectoryError(str(binPath2)) return binPath
def _DecodeXilinx(self, deviceString): self.__vendor = Vendors.Xilinx self.__generation = int(deviceString[2:3]) familyToken = deviceString[3:4].lower() for fam in XilinxFamilies: if fam.Token == familyToken: self.__family = fam break else: raise ConfigurationException("Unknown Xilinx device family.") deviceRegExpStr = r"(?P<st1>[a-z]{0,2})" # device subtype - part 1 deviceRegExpStr += r"(?P<no>\d{1,4})" # device number deviceRegExpStr += r"(?P<st2>[aent]{0,2})" # device subtype - part 2 deviceRegExpStr += r"(?P<sg>[-1-5]{2})" # speed grade deviceRegExpStr += r"(?P<pack>[a-z]{1,3})" # package deviceRegExpStr += r"(?P<pins>\d{1,4})" # pin count deviceRegExp = re_compile(deviceRegExpStr) deviceRegExpMatch = deviceRegExp.match(deviceString[4:].lower()) if (deviceRegExpMatch is not None): subtype = deviceRegExpMatch.group('st1') + deviceRegExpMatch.group('st2') package = deviceRegExpMatch.group('pack') if (subtype != ""): try: self.__subtype = XilinxSubTypes[subtype.upper()] except KeyError as ex: raise ConfigurationException("Unknown subtype '{0}'.".format(subtype)) from ex else: self.__subtype = XilinxSubTypes.NoSubType self.__number = int(deviceRegExpMatch.group('no')) self.__speedGrade = int(deviceRegExpMatch.group('sg')) try: self.__package = Packages[package.upper()] except KeyError as ex: raise ConfigurationException("Unknown package '{0}'.".format(package)) from ex self.__pinCount = int(deviceRegExpMatch.group('pins')) else: raise ConfigurationException("RegExp mismatch.")
def _DecodeLatticeECP5(self, deviceString): self.__device = LatticeDevices.ECP5 familyToken = deviceString[4:6].lower() if (familyToken == "u-"): self.__subtype = LatticeSubTypes.U self.__number = int(deviceString[6:8]) self.__speedGrade = int(deviceString[10:11]) self.__package = Packages.CABGA self.__pinCount = 381 # TODO: implement other packages and pin counts elif (familyToken == "um"): self.__subtype = LatticeSubTypes.UM self.__number = int(deviceString[7:9]) self.__speedGrade = int(deviceString[11:12]) self.__package = Packages.CABGA self.__pinCount = 381 # TODO: implement other packages and pin counts else: raise ConfigurationException("Unknown Lattice ECP5 subtype.")
def __init__(self, host, fqn, libraryName=None, defaultType=EntityTypes.Source): self.__host = host self.__type = None self.__parts = [] if (fqn is None): raise ValueError("Parameter 'fqn' is None.") if (fqn == ""): raise ValueError("Parameter 'fqn' is empty.") if (libraryName is None): libraryName = self.__host.Root.DefaultLibraryName # extract EntityType splitList1 = fqn.split(":") if (len(splitList1) == 1): self.__type = defaultType entity = fqn elif (len(splitList1) == 2): self.__type = EntityTypes(splitList1[0]) entity = splitList1[1] else: raise ValueError("Argument 'fqn' has to many ':' signs.") # extract parts parts = entity.split(".") if (parts[0].lower() not in self.__host.Root): parts.insert(0, libraryName) # check and resolve parts cur = self.__host.Root self.__parts.append(cur) last = len(parts) - 1 for pos,part in enumerate(parts): if ((pos == last) and ("*" in part)): pe = StarWildCard(host, part, "----", cur) self.__parts.append(pe) elif ((pos == last) and ("?" in part)): pe = AskWildCard(host, part, "----", cur) self.__parts.append(pe) else: try: pe = cur[part] except KeyError: raise ConfigurationException("Entity '{GREEN}{good}{RED}.{bad}{NOCOLOR}' not found.".format(good=(".".join(parts[:pos])), bad=(".".join(parts[pos:])), **Init.Foreground)) self.__parts.append(pe) cur = pe
def __GetGitDirectory(self): try: gitRevParse = self._git.GetGitRevParse() gitRevParse.RevParseParameters[gitRevParse.SwitchGitDir] = True gitDirectory = gitRevParse.Execute() gitDirectoryPath = Path(gitDirectory) except CommonException as ex: raise ConfigurationException() from ex # WORKAROUND: GIT REV-PARSE # if the Git repository isn't a Git submodule AND the current working # directory is the Git top-level directory, then 'rev-parse' returns a # relative path, otherwise the path is already absolute. if (not gitDirectoryPath.is_absolute()): pyIPCMIInstallationPath = Path(self._host.Config[ self._host.LibraryKey]['InstallationDirectory']) gitDirectoryPath = pyIPCMIInstallationPath / gitDirectoryPath return gitDirectoryPath
def __InstallGitFilters(self): self._host.LogNormal(" Installing Git filters...") normalizeScript = "tools/git/filters/normalize.pl" pyIPCMIInstallationPath = Path( self._host.Config[self._host.LibraryKey]['InstallationDirectory']) normalizeScriptPath = pyIPCMIInstallationPath / normalizeScript if (not normalizeScriptPath.exists()): raise ConfigurationException( "Normalize script '{0!s}' not found.".format( normalizeScriptPath)) from FileNotFoundError( str(normalizeScriptPath)) try: commonCleanParameters = normalizeScript + " clean" commonSmudgeParameters = normalizeScript + " smudge" for fileFormat in [None, "rest", "vhdl"]: filterName = "normalize" cleanParameters = commonCleanParameters smudgeParameters = commonSmudgeParameters if (fileFormat is not None): filterName += "_" + fileFormat cleanParameters += " " + fileFormat smudgeParameters += " " + fileFormat git = self._git.GetGitConfig() git.ConfigParameters[git.ValueFilterClean] = filterName git.ConfigParameters[ git.ValueFilterParameters] = cleanParameters git.Execute() git = self._git.GetGitConfig() git.ConfigParameters[git.ValueFilterSmudge] = filterName git.ConfigParameters[ git.ValueFilterParameters] = smudgeParameters git.Execute() except CommonException: return False
def CreateFiles(self): solutionConfigPath = self._path / ".pyIPCMI" if (not self._path.is_absolute()): solutionConfigPath = self._host.Directories.Root / solutionConfigPath try: solutionConfigPath.mkdir(parents=True) except OSError as ex: raise ConfigurationException("Error while creating '{0!s}'.".format(solutionConfigPath)) from ex solutionConfigFile = solutionConfigPath / self.__SOLUTION_CONFIG_FILE__ with solutionConfigFile.open('w') as fileHandle: fileContent = dedent("""\ [SOLUTION.{slnID}] DefaultLibrary = """.format(slnID=self._id)) fileHandle.write(fileContent) solutionDefaultFile = solutionConfigPath / self.__SOLUTION_DEFAULT_FILE__ with solutionDefaultFile.open('w') as fileHandle: fileContent = dedent("""\ [SOLUTION.DEFAULTS] """) fileHandle.write(fileContent)
def __WriteGtkWaveSection(self, binPath): if (self._host.Platform == "Windows"): gtkwPath = binPath / "gtkwave.exe" else: gtkwPath = binPath / "gtkwave" if not gtkwPath.exists(): raise ConfigurationException( "Executable '{0!s}' not found.".format( gtkwPath)) from FileNotFoundError(str(gtkwPath)) # get version and backend output = check_output([str(gtkwPath), "--version"], universal_newlines=True) version = None versionRegExpStr = r"^GTKWave Analyzer v(.+?) " versionRegExp = re_compile(versionRegExpStr) for line in output.split('\n'): if version is None: match = versionRegExp.match(line) if match is not None: version = match.group(1) self._host.Config[self._section]['Version'] = version
def VivadoNetlist(self): if (len(self._vivadoNetlist) == 0): raise ConfigurationException("No Vivado netlist configured for '{0!s}'.".format(self)) return self._vivadoNetlist[0]
def CGNetlist(self): if (len(self._coreGenNetlist) == 0): raise ConfigurationException("No CoreGen netlist configured for '{0!s}'.".format(self)) return self._coreGenNetlist[0]
def XSTNetlist(self): if (len(self._xstNetlist) == 0): raise ConfigurationException("No XST netlist configured for '{0!s}'.".format(self)) return self._xstNetlist[0]
def QuartusNetlist(self): if (len(self._quartusNetlist) == 0): raise ConfigurationException("No Quartus-II netlist configured for '{0!s}'.".format(self)) return self._quartusNetlist[0]
def LatticeNetlist(self): if (len(self._latticeNetlist) == 0): raise ConfigurationException("No Lattice netlist configured for '{0!s}'.".format(self)) return self._latticeNetlist[0]