Add SystemVerilog support to designflow.yosys. Merge with YosysNp.
* New: In designflow.yosys, add support to load SystemVerilog with the synlig plugin (CHIPS Alliance). Integrate back the "non-Python" version of the task. Now switch automatically between Python & Non-Python based on the availability of the plugin. Also select between "yosys" & "yowasp-yosys". * Change: In svase & sv2v, suppress the requirement of the *first* dependency file to be used as the default target. Now use the "top module" argument.
This commit is contained in:
parent
e0c159c07b
commit
4398770432
|
@ -18,7 +18,6 @@
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/designflow/sv2v.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/designflow/svase.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/designflow/yosys.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/designflow/yosysnp.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/designflow/blif2vst.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/designflow/pnr.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/designflow/klayout.py
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import os.path
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from pyosys import libyosys as yosys
|
||||
from doit.exceptions import TaskFailed
|
||||
from .task import FlowTask
|
||||
|
||||
|
@ -19,11 +18,12 @@ class Sv2v ( FlowTask ):
|
|||
FlagLog = 0x00000001
|
||||
|
||||
@staticmethod
|
||||
def mkRule ( rule, targets, depends, top=None, incdirs=[], libdirs=[], defines=[], flags=0 ):
|
||||
def mkRule ( rule, targets, depends, top, incdirs=[], libdirs=[], defines=[], flags=0 ):
|
||||
return Sv2v( rule, targets, depends, top, incdirs, libdirs, defines, flags )
|
||||
|
||||
def __init__ ( self, rule, targets, depends, top, incdirs, libdirs, defines, flags ):
|
||||
self.flags = flags
|
||||
self.top = top
|
||||
self.incdirs = incdirs
|
||||
self.libdirs = libdirs
|
||||
self.defines = defines
|
||||
|
@ -31,10 +31,6 @@ class Sv2v ( FlowTask ):
|
|||
self.success = True
|
||||
targets = FlowTask._normFileList( targets )
|
||||
depends = FlowTask._normFileList( depends )
|
||||
if top is not None:
|
||||
self.top = top
|
||||
else:
|
||||
self.top = depends[0].stem
|
||||
if targets == []:
|
||||
targets.append( self.top + '.v' )
|
||||
#if self.flags & Sv2v.FlagLog:
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import os.path
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from pyosys import libyosys as yosys
|
||||
from doit.exceptions import TaskFailed
|
||||
from .task import FlowTask
|
||||
|
||||
|
@ -19,11 +18,12 @@ class Svase ( FlowTask ):
|
|||
FlagLog = 0x00000001
|
||||
|
||||
@staticmethod
|
||||
def mkRule ( rule, targets, depends, top=None, incdirs=[], libdirs=[], defines=[], svargs=[], flags=0 ):
|
||||
def mkRule ( rule, targets, depends, top, incdirs=[], libdirs=[], defines=[], svargs=[], flags=0 ):
|
||||
return Svase( rule, targets, depends, top, incdirs, libdirs, defines, svargs, flags )
|
||||
|
||||
def __init__ ( self, rule, targets, depends, top, incdirs, libdirs, defines, svargs, flags ):
|
||||
self.flags = flags
|
||||
self.top = top
|
||||
self.svargs = svargs
|
||||
self.incdirs = incdirs
|
||||
self.libdirs = libdirs
|
||||
|
@ -32,10 +32,6 @@ class Svase ( FlowTask ):
|
|||
self.success = True
|
||||
targets = FlowTask._normFileList( targets )
|
||||
depends = FlowTask._normFileList( depends )
|
||||
if top is not None:
|
||||
self.top = top
|
||||
else:
|
||||
self.top = depends[0].stem
|
||||
if targets == []:
|
||||
targets.append( self.top + '.v' )
|
||||
#if self.flags & Svase.FlagLog:
|
||||
|
|
|
@ -1,16 +1,27 @@
|
|||
|
||||
import os.path
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from doit.exceptions import TaskFailed
|
||||
from .task import FlowTask
|
||||
|
||||
usePyYosys = True
|
||||
try:
|
||||
from pyosys import libyosys as yosys
|
||||
except:
|
||||
usePyYosys = False
|
||||
|
||||
|
||||
class BadLiberty ( Exception ): pass
|
||||
|
||||
|
||||
class Yosys ( FlowTask ):
|
||||
|
||||
_liberty = None
|
||||
FlagLog = 0x00000001
|
||||
FlagQuiet = 0x00000002
|
||||
FlagSystemVerilog = 0x00000004
|
||||
_liberty = None
|
||||
|
||||
@staticmethod
|
||||
def setLiberty ( liberty ):
|
||||
|
@ -25,20 +36,58 @@ class Yosys ( FlowTask ):
|
|||
Yosys._liberty = liberty
|
||||
|
||||
@staticmethod
|
||||
def mkRule ( rule, depends, top=None, blackboxes=[], flattens=[] ):
|
||||
return Yosys( rule, depends, top, blackboxes, flattens )
|
||||
def mkRule ( rule
|
||||
, depends
|
||||
, top =None
|
||||
, blackboxes=[]
|
||||
, flattens =[]
|
||||
, svOptions =None
|
||||
, svDefines =None
|
||||
, svIncdirs =None
|
||||
, svLibdirs =None
|
||||
, script =[]
|
||||
, flags =0 ):
|
||||
return Yosys( rule
|
||||
, depends
|
||||
, top
|
||||
, blackboxes
|
||||
, flattens
|
||||
, svOptions
|
||||
, svDefines
|
||||
, svIncdirs
|
||||
, svLibdirs
|
||||
, script
|
||||
, flags )
|
||||
|
||||
def __init__ ( self, rule, depends, top, blackboxes, flattens ):
|
||||
def __init__ ( self, rule
|
||||
, depends
|
||||
, top
|
||||
, blackboxes
|
||||
, flattens
|
||||
, svOptions
|
||||
, svDefines
|
||||
, svIncdirs
|
||||
, svLibdirs
|
||||
, script
|
||||
, flags ):
|
||||
super().__init__( rule, [], depends )
|
||||
self.success = True
|
||||
self.blackboxes = blackboxes
|
||||
self.flattens = flattens
|
||||
self.depends += blackboxes
|
||||
self.svOptions = svOptions
|
||||
self.svDefines = svDefines
|
||||
self.svIncdirs = svIncdirs
|
||||
self.svLibdirs = svLibdirs
|
||||
self.flags = flags
|
||||
self.script = script
|
||||
self.success = True
|
||||
if top is not None:
|
||||
self.top = top
|
||||
else:
|
||||
self.top = self.main.stem
|
||||
self.targets = [ Path( self.top + '.blif') ]
|
||||
if not usePyYosys:
|
||||
self.targets.append( Path( self.top + '.ys' ))
|
||||
self.addClean( self.targets )
|
||||
|
||||
def __repr__ ( self ):
|
||||
|
@ -53,11 +102,6 @@ class Yosys ( FlowTask ):
|
|||
def main ( self ):
|
||||
return self.file_depend( 0 )
|
||||
|
||||
def _run_pass ( self, command ):
|
||||
from pyosys import libyosys as yosys
|
||||
if self.success is not True: return
|
||||
yosys.run_pass( command, self.tool )
|
||||
|
||||
def _loadDesign ( self, design ):
|
||||
from ..helpers.io import ErrorMessage
|
||||
if self.success is not True: return
|
||||
|
@ -66,13 +110,45 @@ class Yosys ( FlowTask ):
|
|||
self.success = TaskFailed( e )
|
||||
return
|
||||
design = Path( design )
|
||||
if design.suffix == '.v' : self._run_pass( 'read_verilog -sv {}'.format( design.as_posix() ))
|
||||
elif design.suffix == '.il': self._run_pass( 'read_ilang {}'.format( design.as_posix() ))
|
||||
if design.suffix == '.v' : self.script.append( 'read_verilog -sv {}'.format( design.as_posix() ))
|
||||
elif design.suffix == '.il': self.script.append( 'read_ilang {}'.format( design.as_posix() ))
|
||||
else:
|
||||
e = ErrorMessage( 1, 'Yosys._loadDesign(): Unsupported input format for "{}".'.format( design ))
|
||||
self.success = TaskFailed( e )
|
||||
return
|
||||
|
||||
def _loadSVDesign ( self ):
|
||||
from ..helpers.io import ErrorMessage
|
||||
if self.success is not True: return
|
||||
self.script.append( 'plugin -i systemverilog' )
|
||||
svFileArgs = ''
|
||||
for svFile in self.depends:
|
||||
if not isinstance(svFile,Path):
|
||||
svFile = Path( svFile )
|
||||
if not svFile.is_file():
|
||||
print( '[WARNING] Can\'t find SV file "{}".'.format( svFile.as_posix() ))
|
||||
continue
|
||||
svFileArgs += ' {}'.format( svFile.as_posix() )
|
||||
defineArgs = ''
|
||||
for define in self.svDefines:
|
||||
defineArgs += ' -D{}'.format( define )
|
||||
includeArgs = ''
|
||||
for incdir in self.svIncdirs:
|
||||
includeArgs += ' -I{}'.format( incdir )
|
||||
libArgs = ''
|
||||
for libdir in self.svLibdirs:
|
||||
libArgs += ' -L {}'.format( libdir )
|
||||
options = ' '.join( self.svOptions )
|
||||
scriptArgs = { 'options' :options
|
||||
, 'defines' :defineArgs
|
||||
, 'includes' :includeArgs
|
||||
, 'libraries':libArgs
|
||||
, 'svFiles' :svFileArgs
|
||||
, 'top' : self.top }
|
||||
self.script.append( 'read_systemverilog {options} -top {top} {defines} {includes} {libraries} {svFiles}' \
|
||||
.format( **scriptArgs ))
|
||||
|
||||
|
||||
def _loadBlackboxes ( self ):
|
||||
if self.success is not True: return
|
||||
for blackbox in self.blackboxes:
|
||||
|
@ -81,11 +157,34 @@ class Yosys ( FlowTask ):
|
|||
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 ))
|
||||
self.script.append( 'flatten {}'.format( flattens ))
|
||||
self.script.append( 'hierarchy -top {}'.format( self.top ))
|
||||
|
||||
def _runScript ( self ):
|
||||
from ..helpers.io import ErrorMessage
|
||||
if usePyYosys:
|
||||
tool = yosys.Design()
|
||||
for command in self.script:
|
||||
yosys.run_pass( command, tool )
|
||||
|
||||
if shutil.which( 'yosys' ): command = [ 'yosys' ]
|
||||
elif shutil.which( 'yowasp-yosys' ): command = [ 'yowasp-yosys' ]
|
||||
else:
|
||||
e = ErrorMessage( 1, [ 'Yosys._runScript(): Neither "yosys" nor "yowasp-yosys" has been found' ] )
|
||||
self.success = TaskFailed( e )
|
||||
return
|
||||
ysFile = self.targets[-1].as_posix()
|
||||
with open( ysFile, 'w' ) as ysFd:
|
||||
ysFd.write( '\n'.join( self.script ).format( liberty =str(self.liberty)
|
||||
, cellname=self.main.stem
|
||||
, top =self.top ))
|
||||
if self.flags & Yosys.FlagQuiet: command += [ '-q' ]
|
||||
if self.flags & Yosys.FlagLog: command += [ '-l', self.log.as_posix() ]
|
||||
command += [ '-s', ysFile ]
|
||||
status = subprocess.call( command )
|
||||
self.success = (status == 0)
|
||||
|
||||
def doTask ( self ):
|
||||
from pyosys import libyosys as yosys
|
||||
from ..helpers.io import ErrorMessage
|
||||
if self.liberty is None:
|
||||
e = ErrorMessage( 1, [ 'Yosys.doTask(): "liberty" has not been set' ] )
|
||||
|
@ -95,17 +194,20 @@ class Yosys ( FlowTask ):
|
|||
, '"{}"'.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 ))
|
||||
if self.flags & Yosys.FlagSystemVerilog:
|
||||
self._loadSVDesign()
|
||||
else:
|
||||
self._loadDesign( self.main )
|
||||
self.script.append( 'hierarchy -check -top {}'.format( self.top ))
|
||||
self.script.append( '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] ))
|
||||
self.script.append( 'memory' )
|
||||
self.script.append( 'dfflibmap -liberty {}'.format( self.liberty.as_posix() ))
|
||||
self.script.append( 'abc -liberty {}'.format( self.liberty.as_posix() ))
|
||||
self.script.append( 'clean')
|
||||
self.script.append( 'write_blif {}'.format( self.targets[0] ))
|
||||
self._runScript()
|
||||
return self.success
|
||||
|
||||
def create_doit_tasks ( self ):
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import os.path
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from pyosys import libyosys as yosys
|
||||
from doit.exceptions import TaskFailed
|
||||
from .task import FlowTask
|
||||
|
||||
|
|
Loading…
Reference in New Issue