coriolis/cumulus/src/designflow/yosys.py

119 lines
4.4 KiB
Python
Raw Normal View History

import os.path
from pathlib import Path
from pyosys import libyosys as yosys
from doit.exceptions import TaskFailed
from .task import FlowTask
class BadLiberty ( Exception ): pass
class Yosys ( FlowTask ):
_liberty = None
@staticmethod
def setLiberty ( liberty ):
if isinstance(liberty,Path): pass
elif isinstance(liberty,str): liberty = Path( liberty )
else:
raise BadLiberty( '[ERROR] Yosys.setLiberty(): Should be <str> or <Path> ({})' \
.format( liberty ))
if not liberty.is_file():
raise BadLiberty( '[ERROR] Yosys.setLiberty(): File not found "{}"' \
.format( liberty ))
Yosys._liberty = liberty
@staticmethod
def mkRule ( rule, depends, top=None, blackboxes=[], flattens=[] ):
return Yosys( rule, depends, top, blackboxes, flattens )
def __init__ ( self, rule, depends, top, blackboxes, flattens ):
super().__init__( rule, [], depends )
self.success = True
self.blackboxes = blackboxes
self.flattens = flattens
self.depends += blackboxes
if top is not None:
self.top = top
else:
if self.main.find('.') == -1:
self.top = self.main
else:
self.top = '.'.join( self.main.split('.')[0:-1] )
self.targets = [ self.top + '.blif' ]
self.addClean( self.targets )
def __repr__ ( self ):
return '<yosys {} top={} blackboxes=[{}] flattens=[{}]>' \
.format( self.main, self.top, ','.join(self.blackboxes), ','.join(self.flattens) )
@property
def liberty ( self ):
return Yosys._liberty
@property
def main ( self ):
return self.file_depend( 0 )
def _run_pass ( self, command ):
if self.success is not True: return
yosys.run_pass( command, self.tool )
def _loadDesign ( self, design ):
Comprehensive reorganisation of the Python part of Coriolis. * Move all Python stuff under a common Python namespace "coriolis". * Instead of having a series subtrees for each tool, integrate everything in one common tree. So now, all components can be located either with an absolute path from "coriolis" or, inside cross-reference themselves through relatives imports. * As a consequence, we only need to add ".../site-packages/coriolis/" to the PYTHONPATH, and not a whole bunch of subdirectories. And nothing, if installed in-system. * The tree of free technologies configuration files is also moved below "coriolis/technos" instead of "/etc". * Supressed "cumulus" level for the plugins. * All python modules are rewritten using relative imports except for the configuration files that uses absolute import as they can be cloned outside of the tree to serve as templates. * Change: In boostrap/FindPythonSitePackages, include "/coriolis" in Python_CORIOLISARCH and Python_CORIOLISLIB. Provide a Python_SITELIB *without* "/coriolis" appended. * Change: In cumulus/plugins/__init__.loadPlugins(), must prefix modules read in the plugins directory by "coriolis.plugins.". No longer need to add their path to sys.path. * Change: In crlcore/python/technos/nodeX/*/devices.py, the scripts of the layouts generators must be prefixed by "coriolis.oroshi.". * Change: In CRL::System CTOR, no longer add the pathes of the various plugins to sys.path. Only "site-packages/coriolis/". * New: In Utilities::Path::toPyModePath(), new method to convert a filesystem path into a python module path. Examples: "coriolis/plugins/block" --> "coriolis.plugins.block". "coriolis/plugins/rsave.py" --> "coriolis.plugins.rsave". * Change: In katanaEngine::_runKatanaEngine(), rename the hook script initHook.py. No longer need to modify sys.path. * Change: In BoraEngine::_runBoraEngine(), rename the hook script initHook.py. No longer need to modify sys.path. * Change: In UnicornGui::_runUnicornInit(), rename the hook script initHook.py. No longer need to modify sys.path. * Change: In cumulus.plugins.chip.constants, put the constants outside __init__.py to avoid a loop at initialization.
2023-02-27 15:14:32 -06:00
from ..helpers.io import ErrorMessage
if self.success is not True: return
if not os.path.isfile(design):
e = ErrorMessage( 1, 'Yosys._loadDesign(): Can\'t find design file "{}".'.format( design ))
self.success = TaskFailed( e )
return
if design.endswith('.v' ): self._run_pass( 'read_verilog {}'.format( design ))
elif design.endswith('.il'): self._run_pass( 'read_ilang {}'.format( design ))
else:
e = ErrorMessage( 1, 'Yosys._loadDesign(): Unsupported input format for "{}".'.format( design ))
self.success = TaskFailed( e )
return
def _loadBlackboxes ( self ):
if self.success is not True: return
for blackbox in self.blackboxes:
self._loadDesign( blackbox )
def _doFlattens ( self ):
if self.success is not True: return
flattens = ' '.join( self.flattens )
self._run_pass( 'flatten {}\n'.format( flattens ))
self._run_pass( 'hierarchy -top {}\n'.format( self.top ))
def doTask ( self ):
Comprehensive reorganisation of the Python part of Coriolis. * Move all Python stuff under a common Python namespace "coriolis". * Instead of having a series subtrees for each tool, integrate everything in one common tree. So now, all components can be located either with an absolute path from "coriolis" or, inside cross-reference themselves through relatives imports. * As a consequence, we only need to add ".../site-packages/coriolis/" to the PYTHONPATH, and not a whole bunch of subdirectories. And nothing, if installed in-system. * The tree of free technologies configuration files is also moved below "coriolis/technos" instead of "/etc". * Supressed "cumulus" level for the plugins. * All python modules are rewritten using relative imports except for the configuration files that uses absolute import as they can be cloned outside of the tree to serve as templates. * Change: In boostrap/FindPythonSitePackages, include "/coriolis" in Python_CORIOLISARCH and Python_CORIOLISLIB. Provide a Python_SITELIB *without* "/coriolis" appended. * Change: In cumulus/plugins/__init__.loadPlugins(), must prefix modules read in the plugins directory by "coriolis.plugins.". No longer need to add their path to sys.path. * Change: In crlcore/python/technos/nodeX/*/devices.py, the scripts of the layouts generators must be prefixed by "coriolis.oroshi.". * Change: In CRL::System CTOR, no longer add the pathes of the various plugins to sys.path. Only "site-packages/coriolis/". * New: In Utilities::Path::toPyModePath(), new method to convert a filesystem path into a python module path. Examples: "coriolis/plugins/block" --> "coriolis.plugins.block". "coriolis/plugins/rsave.py" --> "coriolis.plugins.rsave". * Change: In katanaEngine::_runKatanaEngine(), rename the hook script initHook.py. No longer need to modify sys.path. * Change: In BoraEngine::_runBoraEngine(), rename the hook script initHook.py. No longer need to modify sys.path. * Change: In UnicornGui::_runUnicornInit(), rename the hook script initHook.py. No longer need to modify sys.path. * Change: In cumulus.plugins.chip.constants, put the constants outside __init__.py to avoid a loop at initialization.
2023-02-27 15:14:32 -06:00
from ..helpers.io import ErrorMessage
if self.liberty is None:
e = ErrorMessage( 1, [ 'Yosys.doTask(): "liberty" has not been set' ] )
return TaskFailed( e )
if not self.liberty.is_file():
e = ErrorMessage( 1, [ 'Yosys.doTask(): File not found "{}"'
, '"{}"'.format( self.liberty.as_posix() ) ] )
return TaskFailed( e )
#print( 'Yosys.doTask() on "{}"'.format( self.design ))
self.tool = yosys.Design()
self._loadBlackboxes()
self._loadDesign( self.main )
self._run_pass( 'hierarchy -check -top {}'.format( self.top ))
self._run_pass( 'synth -top {}'.format( self.top ))
self._doFlattens()
self._run_pass( 'memory' )
self._run_pass( 'dfflibmap -liberty {}'.format( self.liberty.as_posix() ))
self._run_pass( 'abc -liberty {}'.format( self.liberty.as_posix() ))
self._run_pass( 'clean' )
self._run_pass( 'write_blif {}'.format( self.targets[0] ))
return self.success
def create_doit_tasks ( self ):
return { 'basename' : self.basename
, 'actions' : [ self.doTask ]
, 'doc' : 'Run {}.'.format( self )
, 'file_dep' : self.file_dep
, 'targets' : self.targets
}