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_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