def toSimModel(unit, targetPlatform=DummyPlatform(), dumpModelIn=None): """ Create a simulation model for unit :param unit: interface level unit which you wont prepare for simulation :param targetPlatform: target platform for this synthes :param dumpModelIn: folder to where put sim model files (otherwise sim model will be constructed only in memory) """ sim_code = toRtl(unit, targetPlatform=targetPlatform, saveTo=dumpModelIn, serializer=SimModelSerializer) if dumpModelIn is not None: d = os.path.join(os.getcwd(), dumpModelIn) dInPath = d in sys.path if not dInPath: sys.path.insert(0, d) if unit._name in sys.modules: del sys.modules[unit._name] simModule = importlib.import_module(unit._name) if not dInPath: sys.path.remove(d) else: simModule = ModuleType('simModule') # python supports only ~100 opened brackets # it exceded it throws MemoryError: s_push: parser stack overflow exec(sim_code, simModule.__dict__) return simModule.__dict__[unit._name]
def compileSim(cls, unit, build_dir: Optional[str]=DEFAULT_BUILD_DIR, unique_name: Optional[str]=None, onAfterToRtl=None, target_platform=DummyPlatform()): """ Create simulation model and connect it with interfaces of original unit and decorate it with agents :param unit: interface level unit which you wont prepare for simulation :param target_platform: target platform for this synthesis :param build_dir: folder to where to put sim model files, if None temporary folder is used and then deleted (or simulator will be constructed in memory if possible) :param unique_name: name which is used as name of the module for simulation (if is None it is automatically generated) :param onAfterToRtl: callback fn(unit) which will be called after unit will be synthesised to RTL and before Unit instance signals are replaced with simulator specific ones """ if unique_name is None: unique_name = cls.get_unique_name(unit) cls.rtl_simulator_cls = toBasicSimulatorSimModel(# toVerilatorSimModel( unit, unique_name=unique_name, build_dir=build_dir, target_platform=target_platform, do_compile=cls.RECOMPILE) if onAfterToRtl: onAfterToRtl(unit) cls.u = unit
def test_indexOps(self): c, interf = IndexOps() _, arch = list(c.synthesize("indexOps", interf, DummyPlatform())) s = VhdlSerializer.Architecture(arch, VhdlSerializer.getBaseContext()) self.assertNotIn("sig_", s)
def build(cls, unit: Unit, unique_name: str, build_dir: Optional[str], target_platform=DummyPlatform(), do_compile=True) -> "BasicRtlSimulatorVcd": """ Create a pycocotb.basic_hdl_simulator based simulation model for specified unit and load it to python :param unit: interface level unit which you wont prepare for simulation :param unique_name: unique name for build directory and python module with simulator :param target_platform: target platform for this synthesis :param build_dir: directory to store sim model build files, if None sim model will be constructed only in memory """ if unique_name is None: unique_name = unit._getDefaultName() _filter = SerializerFilterDoNotExclude() if build_dir is None or not do_compile: buff = StringIO() store_man = SaveToStream(SimModelSerializer, buff, _filter=_filter) else: if not os.path.isabs(build_dir): build_dir = os.path.join(os.getcwd(), build_dir) build_private_dir = os.path.join(build_dir, unique_name) store_man = SaveToFilesFlat(SimModelSerializer, build_private_dir, _filter=_filter) store_man.module_path_prefix = unique_name to_rtl(unit, name=unique_name, target_platform=target_platform, store_manager=store_man) if build_dir is not None: d = build_dir dInPath = d in sys.path if not dInPath: sys.path.insert(0, d) if unique_name in sys.modules: del sys.modules[unique_name] simModule = importlib.import_module( unique_name + "." + unique_name, package='simModule_' + unique_name) if not dInPath: sys.path.pop(0) else: simModule = ModuleType('simModule_' + unique_name) # python supports only ~100 opened brackets # if exceeded it throws MemoryError: s_push: parser stack overflow exec(buff.getvalue(), simModule.__dict__) model_cls = simModule.__dict__[unit._name] # can not use just function as it would get bounded to class return cls(model_cls, unit)
def synthesised(u: Unit, targetPlatform=DummyPlatform()): assert not u._wasSynthetised() if not hasattr(u, "_interfaces"): u._loadDeclarations() for _ in u._toRtl(targetPlatform): pass return u
def to_rtl_str(unit_or_cls: Unit, serializer_cls=Vhdl2008Serializer, name: str = None, target_platform=DummyPlatform()): buff = StringIO() store_manager = SaveToStream(serializer_cls, buff) to_rtl(unit_or_cls, store_manager, name, target_platform) return buff.getvalue()
def serializeAsIpcore(unit, folderName=".", name=None, serializer: GenericSerializer=VhdlSerializer, targetPlatform=DummyPlatform()): from hwt.serializer.ip_packager import IpPackager p = IpPackager(unit, name=name, serializer=serializer, targetPlatform=targetPlatform) p.createPackage(folderName) return p
def netlistToVhdlStr(name, netlist, interfaces): for s in interfaces: s._interface = True ctx = VhdlSerializer.getBaseContext() return "\n".join([ VhdlSerializer.asHdl(o, ctx) for o in netlist.synthesize(name, interfaces, DummyPlatform()) ])
def build(cls, unit: Unit, unique_name: str, build_dir: Optional[str], target_platform=DummyPlatform(), do_compile=True): """ Create a verilator based simulation model for specified unit and load it to Python :param unit: interface level unit which you wont prepare for simulation :param unique_name: unique name for build directory and python module with simulator :param target_platform: target platform for this synthesis :param build_dir: directory to store sim model build files, if None temporary folder is used and then deleted :param do_compile: if false reuse existing build if exists [TODO] """ if build_dir is None: build_dir = os.path.join("tmp", unique_name) build_private_dir = os.path.join(os.getcwd(), build_dir, unique_name) store_man = SaveToFilesFlat(VerilogSerializer, build_private_dir, _filter=SerializerFilterDoNotExclude()) to_rtl(unit, name=unique_name, target_platform=target_platform, store_manager=store_man) sim_verilog = store_man.files accessible_signals = collect_signals(unit) used_names = {x[0] for x in accessible_signals} assert len(used_names) == len(accessible_signals), \ "All signal has to have unique names" if do_compile: verilatorCompile(sim_verilog, build_dir) sim_so = generatePythonModuleWrapper(unit._name, unique_name, build_dir, accessible_signals) else: sim_so = None file_pattern = './**/{0}.*.so'.format(unique_name) for filename in iglob(file_pattern, recursive=True): assert sim_so is None, ("Can not resolve simulation library", sim_so, filename) sim_so = filename # load compiled library into python sim_module = loadPythonCExtensionFromFile(sim_so, unique_name) sim_cls = getattr(sim_module, unique_name) return sim_cls
def synthesised(u: Unit, target_platform=DummyPlatform()): """ Elaborate design without producing any HDL """ sm = StoreManager(DummySerializerConfig, _filter=SerializerFilterDoNotExclude()) if not hasattr(u, "_interfaces"): u._loadDeclarations() for _ in u._to_rtl(target_platform, sm): pass return u
def serializeAsIpcore(unit, folderName=".", name=None, serializer_cls=Vhdl2008Serializer, target_platform=DummyPlatform()): """ Create an IPCore package """ from hwt.serializer.ip_packager import IpPackager p = IpPackager(unit, name=name, serializer_cls=serializer_cls, target_platform=target_platform) p.createPackage(folderName) return p
def toBasicSimulatorSimModel(unit: Unit, unique_name: str, build_dir: Optional[str], target_platform=DummyPlatform(), do_compile=True): """ Create a pycocotb.basic_hdl_simulator based simulation model for specified unit and load it to python :param unit: interface level unit which you wont prepare for simulation :param unique_name: unique name for build directory and python module with simulator :param target_platform: target platform for this synthesis :param build_dir: directory to store sim model build files, if None sim model will be constructed only in memory """ if unique_name is None: unique_name = unit._getDefaultName() if build_dir is not None: build_private_dir = os.path.join(os.getcwd(), build_dir, unique_name) else: build_private_dir = None sim_code = toRtl(unit, name=unique_name, targetPlatform=target_platform, saveTo=build_private_dir, serializer=SimModelSerializer) if build_dir is not None: d = os.path.join(os.getcwd(), build_dir) dInPath = d in sys.path if not dInPath: sys.path.insert(0, d) if unique_name in sys.modules: del sys.modules[unique_name] simModule = importlib.import_module(unique_name + "." + unique_name, package='simModule_' + unique_name) if not dInPath: sys.path.pop(0) else: simModule = ModuleType('simModule_' + unique_name) # python supports only ~100 opened brackets # if exceded it throws MemoryError: s_push: parser stack overflow exec(sim_code, simModule.__dict__) model_cls = simModule.__dict__[unit._name] # can not use just function as it would get bounded to class return BasicSimConstructor(model_cls, unit)
def to_rtl(unit_or_cls: Unit, store_manager: StoreManager, name: str = None, target_platform=DummyPlatform()): """ Convert unit to RTL using specified serializer :param unitOrCls: unit instance or class, which should be converted :param name: name override of top unit (if is None name is derived form class name) :param target_platform: meta-informations about target platform, distributed on every unit under _target_platform attribute before Unit._impl() is called """ if isinstance(unit_or_cls, Unit): u = unit_or_cls else: u = unit_or_cls() u._target_platform = target_platform u._store_manager = store_manager u._loadDeclarations() if name is not None: assert isinstance(name, str) u._hdl_module_name = u._name = name # serialize all unit instances to HDL code constraints = HdlConstraintList() for _, obj in u._to_rtl(target_platform, store_manager): # collect constraints directly in current component constraints.extend(obj._constraints) if obj._shared_component_with: # if the instance is shared with something else make # the paths in constraints relative to a component path_old = _get_absolute_path(obj._shared_component_with[0]) path_new = _get_absolute_path(obj) for c in _Unit_constraints_copy_recursively( obj, path_old, path_new): constraints.append(c) if constraints: # serialize all constraints in design store_manager.write(constraints) return store_manager
def toVerilatorSimModel(unit: Unit, unique_name: str, build_dir: Optional[str], target_platform=DummyPlatform(), do_compile=True): """ Create a verilator based simulation model for specified unit and load it to Python :param unit: interface level unit which you wont prepare for simulation :param unique_name: unique name for build directory and python module with simulator :param target_platform: target platform for this synthesis :param build_dir: directory to store sim model build files, if None temporary folder is used and then deleted :param do_compile: if false reuse existing build if exists [TODO] """ if build_dir is None: build_dir = "tmp/%s" % unique_name # with tempdir(suffix=unique_name) as build_dir: sim_verilog = toRtl(unit, targetPlatform=target_platform, saveTo=build_dir, serializer=VerilogForVerilatorSerializer) accessible_signals = collect_signals(unit) used_names = {x[0] for x in accessible_signals} assert len(used_names) == len(accessible_signals), \ "All signal has to have unique names" if do_compile: verilatorCompile(sim_verilog, build_dir) sim_so = generatePythonModuleWrapper(unit._name, unique_name, build_dir, accessible_signals) else: sim_so = None file_pattern = './**/{0}.*.so'.format(unique_name) for filename in iglob(file_pattern, recursive=True): assert sim_so is None, ("Can not resolve simulation library", sim_so, filename) sim_so = filename # load compiled library into python sim_module = loadPythonCExtensionFromFile(sim_so, unique_name) sim_cls = getattr(sim_module, unique_name) return sim_cls
def netlistToVhdlStr(name: str, netlist: RtlNetlist, interfaces: Dict[RtlSignal, DIRECTION]): name_scope = NameScope(None, name, True) buff = StringIO() store_manager = SaveToStream(Vhdl2008Serializer, buff) netlist.create_HdlModuleDec(name, store_manager, {}) netlist.interfaces = interfaces for s, d in interfaces.items(): s._interface = True pi = portItemfromSignal(s, netlist, d) # port of current top component s.name = name_scope.checked_name(s.name, s) pi.connectInternSig(s) netlist.ent.ports.append(pi) netlist.ent.ports.sort(key=lambda x: x.name) netlist.create_HdlModuleDef(DummyPlatform(), store_manager) store_manager.write(netlist.arch) return buff.getvalue()
def compileSimAndStart( self, unit: Unit, build_dir: Optional[str]=DEFAULT_BUILD_DIR, unique_name: Optional[str]=None, onAfterToRtl=None, target_platform=DummyPlatform()): """ Use this method if you did not used compileSim() or SingleUnitSimTestCase to setup the simulator and DUT """ if unique_name is None: unique_name = "%s__%s" % (self.getTestName(), unit._getDefaultName()) self.compileSim(unit, build_dir, unique_name, onAfterToRtl, target_platform) self.u = unit SimTestCase.setUp(self) return self.u
def prepareUnit(self, unit, modelCls=None, dumpModelIn=None, onAfterToRtl=None, targetPlatform=DummyPlatform()): """ Create simulation model and connect it with interfaces of original unit and decorate it with agents and collect all simulation processes :param unit: interface level unit which you wont prepare for simulation :param modelCls: class of rtl simulation model to run simulation on, if is None rtl sim model will be generated from unit :param dumpModelIn: folder to where put sim model files (if is None sim model will be constructed only in memory) :param onAfterToRtl: callback fn(unit) which will be called unit after it will be synthesised to rtl """ self.u, self.model, self.procs = simPrepare( unit, modelCls=modelCls, targetPlatform=targetPlatform, dumpModelIn=dumpModelIn, onAfterToRtl=onAfterToRtl)
def __init__(self, topUnit: Unit, name: str=None, extra_files: List[str]=[], serializer_cls=Vhdl2008Serializer, target_platform=DummyPlatform()): """ :param topObj: :class:`hwt.synthesizer.unit.Unit` instance of top component :param name: optional name of top :param extra_files: list of extra HDL/constrain file names for files which should be distributed in this IP-core (\*.v - verilog, \*.sv,\*.svh -system verilog, \*.vhd - vhdl, \*.xdc - XDC) :param serializer: serializer which specifies target HDL language :param target_platform: specifies properties of target platform, like available resources, vendor, etc. """ if not name: name = topUnit._getDefaultName() super(IpPackager, self).__init__( topUnit, name, extra_files) self.serializer = serializer_cls self.target_platform = target_platform
def __init__(self, topUnit: Unit, name: str=None, extraVhdlFiles: List[str]=[], extraVerilogFiles: List[str]=[], serializer=VhdlSerializer, targetPlatform=DummyPlatform()): """ :param topObj: Unit instance of top component :param name: optional name of top :param extraVhdlFiles: list of extra vhdl file names for files which should be distributed in this IP-core :param extraVerilogFiles: same as extraVhdlFiles just for Verilog :param serializer: serializer which specifies target HDL language :param targetPlatform: specifies properties of target platform, like available resources, vendor, etc. """ assert not topUnit._wasSynthetised() if not name: name = topUnit._getDefaultName() super(IpPackager, self).__init__( topUnit, name, extraVhdlFiles, extraVerilogFiles) self.serializer = serializer self.targetPlatform = targetPlatform
def simPrepare(unit: Unit, modelCls: Optional[SimModel] = None, targetPlatform=DummyPlatform(), dumpModelIn: str = None, onAfterToRtl=None): """ Create simulation model and connect it with interfaces of original unit and decorate it with agents :param unit: interface level unit which you wont prepare for simulation :param modelCls: class of rtl simulation model to run simulation on, if is None rtl sim model will be generated from unit :param targetPlatform: target platform for this synthes :param dumpModelIn: folder to where put sim model files (if is None sim model will be constructed only in memory) :param onAfterToRtl: callback fn(unit, modelCls) which will be called after unit will be synthesised to rtl :return: tuple (fully loaded unit with connected sim model, connected simulation model, simulation processes of agents ) """ if modelCls is None: modelCls = toSimModel(unit, targetPlatform=targetPlatform, dumpModelIn=dumpModelIn) else: # to instantiate hierarchy of unit toSimModel(unit) if onAfterToRtl: onAfterToRtl(unit, modelCls) reconnectUnitSignalsToModel(unit, modelCls) model = modelCls() procs = autoAddAgents(unit) return unit, model, procs
def __init__(self, topUnit: Unit, name: str = None, extraVhdlFiles: List[str] = [], extraVerilogFiles: List[str] = [], serializer=VhdlSerializer, targetPlatform=DummyPlatform()): assert not topUnit._wasSynthetised() self.topUnit = topUnit self.serializer = serializer self.targetPlatform = targetPlatform if name: self.name = name else: self.name = self.topUnit._getDefaultName() self.hdlFiles = UniqList() for f in extraVhdlFiles: self.hdlFiles.append(f) for f in extraVerilogFiles: self.hdlFiles.append(f)
def toRtl(unitOrCls: Unit, name: str=None, serializer: GenericSerializer=VhdlSerializer, targetPlatform=DummyPlatform(), saveTo: str=None): """ Convert unit to RTL using specified serializer :param unitOrCls: unit instance or class, which should be converted :param name: name override of top unit (if is None name is derived form class name) :param serializer: serializer which should be used for to RTL conversion :param targetPlatform: metainformatins about target platform, distributed on every unit under _targetPlatform attribute before Unit._impl() is called :param saveTo: directory where files should be stored If None RTL is returned as string. :raturn: if saveTo returns RTL string else returns list of file names which were created """ if not isinstance(unitOrCls, Unit): u = unitOrCls() else: u = unitOrCls u._loadDeclarations() if name is not None: assert isinstance(name, str) u._name = name globScope = serializer.getBaseNameScope() mouduleScopes = {} # unitCls : unitobj serializedClasses = {} # (unitCls, paramsValues) : unitObj # where paramsValues are dict name:value serializedConfiguredUnits = {} doSerialize = True createFiles = saveTo is not None if createFiles: os.makedirs(saveTo, exist_ok=True) files = UniqList() else: codeBuff = [] for obj in u._toRtl(targetPlatform): doSerialize = serializer.serializationDecision( obj, serializedClasses, serializedConfiguredUnits) if doSerialize: if isinstance(obj, Entity): s = globScope.fork(1) s.setLevel(2) ctx = serializer.getBaseContext() ctx.scope = s mouduleScopes[obj] = ctx ctx.currentUnit = obj.origin sc = serializer.Entity(obj, ctx) if createFiles: fName = obj.name + serializer.fileExtension fileMode = 'w' elif isinstance(obj, Architecture): try: ctx = mouduleScopes[obj.entity] except KeyError: raise SerializerException( "Entity should be serialized" " before architecture of %s" % (obj.getEntityName())) sc = serializer.Architecture(obj, ctx) if createFiles: fName = obj.getEntityName() + serializer.fileExtension fileMode = 'a' else: if hasattr(obj, "_hdlSources"): for fn in obj._hdlSources: if isinstance(fn, str): shutil.copy2(fn, saveTo) files.append(fn) continue else: sc = serializer.asHdl(obj) if sc: if createFiles: fp = os.path.join(saveTo, fName) files.append(fp) with open(fp, fileMode) as f: if fileMode == 'a': f.write("\n") f.write( serializer.formatter(sc) ) else: codeBuff.append(sc) elif not createFiles: try: name = '"%s"' % obj.name except AttributeError: name = "" codeBuff.append(serializer.comment( "Object of class %s, %s was not serialized as specified" % ( obj.__class__.__name__, name))) if createFiles: return files else: return serializer.formatter( "\n".join(codeBuff) )
from hwt.synthesizer.dummyPlatform import DummyPlatform from hwtGraph.elk.fromHwt.extractSplits import extractSplits from hwtGraph.elk.fromHwt.flattenTrees import flattenTrees from hwtGraph.elk.fromHwt.mergeSplitsOnInterfaces import mergeSplitsOnInterfaces from hwtGraph.elk.fromHwt.netlistPreprocessors import unhideResultsOfIndexingAndConcatOnPublicSignals from hwtGraph.elk.fromHwt.reduceUselessAssignments import reduceUselessAssignments from hwtGraph.elk.fromHwt.resolveSharedConnections import resolveSharedConnections from hwtGraph.elk.fromHwt.sortStatementPorts import sortStatementPorts from hwtGraph.elk.fromHwt.propagatePresets import propagatePresets DEFAULT_PLATFORM = DummyPlatform() DEFAULT_PLATFORM.beforeHdlArchGeneration.extend([ unhideResultsOfIndexingAndConcatOnPublicSignals, propagatePresets, ]) DEFAULT_LAYOUT_OPTIMIZATIONS = [ # optimizations reduceUselessAssignments, extractSplits, lambda root: flattenTrees( root, lambda node: node.cls == "Operator" and node.name == "CONCAT", True), mergeSplitsOnInterfaces, resolveSharedConnections, # prettyfications sortStatementPorts, ]