Source code for hwt.serializer.simModel.serializer

from copy import copy
from typing import Optional, List

from hdlConvertorAst.hdlAst._expr import HdlValueId, HdlValueInt, HdlOp, \
    HdlOpType
from hdlConvertorAst.hdlAst._statements import HdlStmIf, HdlStmAssign, \
    HdlStmProcess, HdlStmBlock
from hdlConvertorAst.hdlAst._structural import HdlModuleDec, HdlModuleDef
from hdlConvertorAst.to.basic_hdl_sim_model.keywords import SIMMODEL_KEYWORDS
from hdlConvertorAst.translate.verilog_to_basic_hdl_sim_model.utils import hdl_getattr, \
    hdl_map_asoc, hdl_call
from hdlConvertorAst.translate.common.name_scope import LanguageKeyword, NameScope
from hwt.hdl.operator import Operator
from hwt.hdl.operatorDefs import AllOps
from hwt.hdl.portItem import HdlPortItem
from hwt.hdl.statements.assignmentContainer import HdlAssignmentContainer
from hwt.hdl.statements.codeBlockContainer import HdlStmCodeBlockContainer
from hwt.hdl.statements.ifContainter import IfContainer
from hwt.hdl.statements.switchContainer import SwitchContainer
from hwt.serializer.generic.constant_cache import ConstantCache
from hwt.serializer.generic.to_hdl_ast import ToHdlAst
from hwt.serializer.simModel.tmpVarConstructorConstOnly import TmpVarConstructorConstOnly
from hwt.serializer.simModel.types import ToHdlAstSimModel_types
from hwt.serializer.simModel.value import ToHdlAstSimModel_value
from hwt.synthesizer.rtlLevel.mainBases import RtlSignalBase
from hwtSimApi.basic_hdl_simulator.sim_utils import sim_eval_cond


[docs]class ToHdlAstSimModel(ToHdlAstSimModel_value, ToHdlAstSimModel_types, ToHdlAst): """ Serializer which converts :class:`hwt.synthesizer.unit.Unit` instances to simulator code """ _keywords_dict = {kw: LanguageKeyword() for kw in SIMMODEL_KEYWORDS} SIM_EVAL_COND = HdlValueId("sim_eval_cond", obj=sim_eval_cond) C = HdlValueId("c", obj=LanguageKeyword()) CVLD = HdlValueId("cVld", obj=LanguageKeyword()) TMP_VAR_CONSTRUCTOR = TmpVarConstructorConstOnly
[docs] def __init__(self, name_scope: Optional[NameScope]=None): super(ToHdlAstSimModel, self).__init__(name_scope) self.currentUnit = None self.stm_outputs = {}
[docs] def as_hdl_HdlModuleDec(self, o: HdlModuleDec): # convert types, exprs # delete params because they should not be used in expressions and thus # are useless new_o = copy(o) new_o.params = [] new_o.ports = [self.as_hdl_HdlPortItem(p) for p in o.ports] return new_o
[docs] def as_hdl_PortConnection(self, o: HdlPortItem): assert isinstance(o, HdlPortItem), o intern, outer = o.getInternSig(), o.getOuterSig() assert not intern.hidden, intern assert not outer.hidden, outer intern_hdl = HdlValueId(intern.name, obj=intern) outer_hdl = HdlValueId(outer.name, obj=outer) pm = hdl_map_asoc(intern_hdl, outer_hdl) return pm
[docs] def as_hdl_HdlAssignmentContainer(self, a: HdlAssignmentContainer): dst, dst_indexes, src = self._as_hdl_HdlAssignmentContainer_auto_conversions(a) ev = HdlValueInt(int(a._event_dependent_from_branch == 0), None, None) if dst_indexes is not None: src = (src, dst_indexes, ev) else: src = (src, ev) hdl_dst = hdl_getattr(hdl_getattr(self.SELF_IO, dst.name), "val_next") hdl_a = HdlStmAssign(src, hdl_dst) hdl_a.is_blocking = dst.virtual_only return hdl_a
[docs] def as_hdl_IfContainer_out_invalidate_section(self, outputs: List[RtlSignalBase], parent: IfContainer): outputInvalidateStms = [] for o in outputs: # [TODO] look up indexes indexes = None v = o._dtype.from_py(None) oa = HdlAssignmentContainer(v, o, indexes, virtual_only=True, parentStm=parent, event_dependent_from_branch=parent._event_dependent_from_branch) outputInvalidateStms.append(self.as_hdl_HdlAssignmentContainer(oa)) if len(outputInvalidateStms) == 1: return outputInvalidateStms[0] else: b = HdlStmBlock() b.body = outputInvalidateStms return b
[docs] def as_hdl_IfContainer_cond_eval(self, cond): """ constructs condition evaluation statement c, cVld = sim_eval_cond(cond) """ c, cVld = self.C, self.CVLD cond = self.as_hdl_cond(cond, True) cond_eval = hdl_call(self.SIM_EVAL_COND, [cond]) cond_eval = HdlStmAssign(cond_eval, (c, cVld)) cond_eval.is_blocking = True return c, cVld, cond_eval
[docs] def as_hdl_IfContainer(self, ifc: IfContainer) -> HdlStmIf: """ .. code-block:: python if cond: ... else: ... will become .. code-block:: python c, cVld = sim_eval_cond(cond) if not cVld: # ivalidate outputs elif c: ... # original if true branch else: ... # original if else brach """ invalidate_block = self.as_hdl_IfContainer_out_invalidate_section( ifc._outputs, ifc) c, cVld, cond_eval = self.as_hdl_IfContainer_cond_eval(ifc.cond) _if = HdlStmIf() res = HdlStmBlock() res.body = [cond_eval, _if] _if.cond = HdlOp(HdlOpType.NEG_LOG, [cVld, ]) _if.if_true = invalidate_block if_true = self.as_hdl_statements(ifc.ifTrue) _if.elifs.append((c, if_true)) elifs = iter(ifc.elIfs) for eif_c, eif_stms in elifs: c, cVld, cond_eval = self.as_hdl_IfContainer_cond_eval(eif_c) newIf = HdlStmIf() newIf.cond = HdlOp(HdlOpType.NEG_LOG, [cVld, ]) newIf.if_true = invalidate_block if_true = self.as_hdl_statements(eif_stms) newIf.elifs.append((c, if_true)) _if.if_false = HdlStmBlock() _if.if_false.body = [cond_eval, newIf] _if = newIf _if.if_false = self.as_hdl_statements(ifc.ifFalse) return res
[docs] def as_hdl_SwitchContainer(self, sw: SwitchContainer) -> HdlStmIf: "switch -> if" switchOn = sw.switchOn def mkCond(c): return switchOn._eq(c) elIfs = [] for key, statements in sw.cases[1:]: elIfs.append((mkCond(key), statements)) ifFalse = sw.default topCond = mkCond(sw.cases[0][0]) topIf = IfContainer(topCond, ifTrue=sw.cases[0][1], ifFalse=ifFalse, elIfs=elIfs) topIf._sensitivity = sw._sensitivity topIf._inputs = sw._inputs topIf._outputs = sw._outputs return self.as_hdl_IfContainer(topIf)
[docs] def sensitivityListItem(self, item, anyEventDependent): if isinstance(item, Operator): op = item.operator if op == AllOps.RISING_EDGE: sens = HdlOpType.RISING elif op == AllOps.FALLING_EDGE: sens = HdlOpType.FALLING else: raise TypeError("This is not an event sensitivity", op) return HdlOp(sens, [HdlValueId(item.operands[0].name)]) else: return HdlValueId(item.name)
[docs] def has_to_be_process(self, proc): return True
[docs] def can_pop_process_wrap(self, statements, hasToBeVhdlProcess): return False
[docs] def as_hdl_HdlStmCodeBlockContainer(self, proc: HdlStmCodeBlockContainer) -> HdlStmProcess: p = ToHdlAst.as_hdl_HdlStmCodeBlockContainer(self, proc) self.stm_outputs[p] = sorted( [HdlValueId(i.name, obj=i) for i in proc._outputs] ) return p
[docs] def as_hdl_extraVarsInit(self, extraVars): return []
[docs] def _as_hdl_HdlModuleDef_body(self, *args) -> HdlModuleDef: orig_const_cache = self.constCache try: self.constCache = ConstantCache(self, self.tmpVars) return ToHdlAst._as_hdl_HdlModuleDef_body(self, *args) finally: self.constCache = orig_const_cache