Source code for hwt.serializer.verilog.ops

from builtins import isinstance
from typing import Union

from hdlConvertorAst.hdlAst import HdlValueInt
from hdlConvertorAst.hdlAst._expr import HdlValueId, HdlOpType, HdlOp
from hdlConvertorAst.translate.common.name_scope import LanguageKeyword
from hdlConvertorAst.translate.verilog_to_basic_hdl_sim_model.utils import hdl_call
from hwt.hdl.operator import Operator
from hwt.hdl.operatorDefs import AllOps
from hwt.hdl.types.bits import Bits
from hwt.hdl.types.defs import BIT, INT
from hwt.hdl.value import HValue
from hwt.serializer.exceptions import UnsupportedEventOpErr
from hwt.serializer.generic.ops import HWT_TO_HDLCONVEROTR_OPS
from hwt.synthesizer.rtlLevel.rtlSignal import RtlSignal


zero, one = BIT.from_py(0), BIT.from_py(1)


[docs]class ToHdlAstVerilog_ops(): SIGNED = HdlValueId("$signed", obj=LanguageKeyword()) UNSIGNED = HdlValueId("$unsigned", obj=LanguageKeyword()) op_transl_dict = { **HWT_TO_HDLCONVEROTR_OPS, AllOps.INDEX: HdlOpType.INDEX, }
[docs] def _operandIsAnotherOperand(self, operand): if isinstance(operand, RtlSignal) and operand.hidden\ and isinstance(operand.origin, Operator): return True
[docs] def as_hdl_operand(self, operand: Union[RtlSignal, HValue], i: int, operator: Operator): # [TODO] if operand is concatenation and parent operator # is not concatenation operand should be extracted # as tmp variable # * maybe flatten the concatenations if operator.operator != AllOps.CONCAT\ and self._operandIsAnotherOperand(operand)\ and operand.origin.operator == AllOps.CONCAT: _, tmpVar = self.tmpVars.create_var_cached("tmp_concat_", operand._dtype, def_val=operand) # HdlAssignmentContainer(tmpVar, operand, virtual_only=True) operand = tmpVar elif operator.operator == AllOps.INDEX and i == 0 and self._operandIsAnotherOperand(operand): _, tmpVar = self.tmpVars.create_var_cached("tmp_index_", operand._dtype, def_val=operand) operand = tmpVar oper = operator.operator width = None if not isinstance(operand, RtlSignal) and operand._dtype == INT and\ oper not in [AllOps.BitsAsUnsigned, AllOps.BitsAsVec, AllOps.BitsAsSigned, AllOps.INDEX] and\ operator.result is not None and\ not operator.result._dtype == INT: # have to lock the width for o in operator.operands: try: bl = o._dtype.bit_length except AttributeError: bl = None if bl is not None: width = bl() break assert width is not None, (operator, operand) hdl_op = self.as_hdl_Value(operand) if width is not None: if isinstance(hdl_op, HdlValueInt): assert isinstance(width, int), width hdl_op.bits = width else: return HdlOp(HdlOpType.APOSTROPHE, [self.as_hdl_int(width), hdl_op]) return hdl_op
[docs] def as_hdl_Operator(self, op: Operator): ops = op.operands o = op.operator if o == AllOps.TERNARY: if ops[1] == one and ops[2] == zero: # ignore redundant x ? 1 : 0 return self.as_hdl_cond(ops[0], True) else: op0 = self.as_hdl_cond(ops[0], True) op1 = self.as_hdl_operand(ops[1], 1, op) op2 = self.as_hdl_operand(ops[2], 2, op) return HdlOp(HdlOpType.TERNARY, [op0, op1, op2]) elif o == AllOps.RISING_EDGE or o == AllOps.FALLING_EDGE: raise UnsupportedEventOpErr() elif o in [AllOps.BitsAsUnsigned, AllOps.BitsAsVec, AllOps.BitsAsSigned]: op0, = ops do_cast = bool(op0._dtype.signed) != bool(op.result._dtype.signed) op_hdl = self.as_hdl_operand(op0, 0, op) if do_cast: if bool(op0._dtype.signed): cast = self.SIGNED else: cast = self.UNSIGNED return hdl_call(cast, [op_hdl, ]) else: return op_hdl else: op0_t = ops[0]._dtype if o == AllOps.INDEX and isinstance(op0_t, Bits) and op0_t.bit_length() == 1 and not op0_t.force_vector: assert int(ops[1]) == 0, ops # drop whole index operator return self.as_hdl_operand(ops[0], 0, op) else: _o = self.op_transl_dict[o] return HdlOp(_o, [self.as_hdl_operand(o2, i, op) for i, o2 in enumerate(ops)])