Source code for hdlConvertorAst.to.vhdl.expr

from hdlConvertorAst.hdlAst._expr import HdlOpType, HdlValueId, HdlValueInt, \
    HdlAll, HdlOp, HdlOthers
from hdlConvertorAst.py_ver_compatibility import is_str
from hdlConvertorAst.to.common import ToHdlCommon, ASSOCIATIVITY
from hdlConvertorAst.to.hdlUtils import iter_with_last, Indent
from copy import copy

L = ASSOCIATIVITY.L_TO_R
R = ASSOCIATIVITY.R_TO_L


# https://www.csee.umbc.edu/portal/help/VHDL/operator.html
[docs]class ToVhdl2008Expr(ToHdlCommon): GENERIC_UNARY_OPS = copy(ToHdlCommon.GENERIC_UNARY_OPS) GENERIC_UNARY_OPS.update({ HdlOpType.NEG: "NOT ", HdlOpType.NEG_LOG: "NOT ", HdlOpType.RANGE: "RANGE ", # used in HdlPhysicalDef }) BITWISE_BIN_OPS = { HdlOpType.AND, HdlOpType.AND_LOG, HdlOpType.OR, HdlOpType.OR_LOG, HdlOpType.XOR, HdlOpType.NAND, HdlOpType.NOR, HdlOpType.XNOR } GENERIC_BIN_OPS = { HdlOpType.AND: " AND ", HdlOpType.AND_LOG: " AND ", HdlOpType.OR: " OR ", HdlOpType.OR_LOG: " OR ", HdlOpType.DIV: " / ", HdlOpType.MOD: " MOD ", HdlOpType.REM: " REM ", HdlOpType.POW: " ** ", HdlOpType.NAND: " NAND ", HdlOpType.NOR: " NOR ", HdlOpType.XOR: " XOR ", HdlOpType.XNOR: " XNOR ", HdlOpType.EQ: ' = ', HdlOpType.NE: " /= ", HdlOpType.EQ_MATCH: ' ?= ', HdlOpType.NE_MATCH: ' ?/= ', HdlOpType.LT_MATCH: ' ?< ', HdlOpType.LE_MATCH: ' ?<= ', HdlOpType.GT_MATCH: ' ?> ', HdlOpType.GE_MATCH: ' ?>= ', HdlOpType.TO: " TO ", HdlOpType.DOWNTO: " DOWNTO ", HdlOpType.ARROW: " => ", HdlOpType.MAP_ASSOCIATION: " => ", HdlOpType.RANGE: " RANGE ", HdlOpType.CONCAT: " & ", HdlOpType.ROL: " ROL ", HdlOpType.ROR: " ROR ", HdlOpType.SLA: " SLA ", HdlOpType.SRA: " SRA ", HdlOpType.SLL: " SLL ", HdlOpType.SRL: " SRL ", HdlOpType.UNIT_SPEC: " ", } EQ_NEQ_OPS = ( HdlOpType.EQ, HdlOpType.NE ) GENERIC_BIN_OPS.update(ToHdlCommon.GENERIC_BIN_OPS) NUM_BASES = { 2: "", 8: "O", 16: "X", 256: "", # 'X' literals } OP_PRECEDENCE = { HdlOpType.UNIT_SPEC: (0, L), HdlOpType.DOT: (1, L), HdlOpType.CALL: (1, L), HdlOpType.INDEX: (1, L), HdlOpType.RISING: (1, L), HdlOpType.FALLING: (1, L), HdlOpType.APOSTROPHE: (1, L), HdlOpType.POW: (2, R), HdlOpType.ABS: (2, L), HdlOpType.NEG: (2, R), HdlOpType.NEG_LOG: (2, R), HdlOpType.MUL: (3, L), HdlOpType.DIV: (3, L), HdlOpType.MOD: (3, L), HdlOpType.REM: (3, L), HdlOpType.PLUS_UNARY: (4, R), HdlOpType.MINUS_UNARY: (4, R), HdlOpType.CONCAT: (5, L), HdlOpType.ADD: (5, L), HdlOpType.SUB: (5, L), HdlOpType.SLL: (6, L), HdlOpType.SRL: (6, L), HdlOpType.SLA: (6, L), HdlOpType.SRA: (6, L), HdlOpType.ROL: (6, L), HdlOpType.ROR: (6, L), HdlOpType.EQ: (7, L), HdlOpType.NE: (7, L), HdlOpType.GT: (7, L), HdlOpType.LT: (7, L), HdlOpType.GE: (7, L), HdlOpType.LE: (7, L), HdlOpType.EQ_MATCH: (7, L), HdlOpType.NE_MATCH: (7, L), HdlOpType.LT_MATCH: (7, L), HdlOpType.LE_MATCH: (7, L), HdlOpType.GT_MATCH: (7, L), HdlOpType.GE_MATCH: (7, L), HdlOpType.AND: (8, L), HdlOpType.OR: (8, L), HdlOpType.NAND: (8, ASSOCIATIVITY.NONE), HdlOpType.NOR: (8, ASSOCIATIVITY.NONE), HdlOpType.XOR: (8, L), HdlOpType.XNOR: (8, ASSOCIATIVITY.NONE), HdlOpType.DOWNTO: (9, L), HdlOpType.TO: (9, L), HdlOpType.TERNARY: (9, R), HdlOpType.RANGE: (10, L), HdlOpType.ARROW: (11, L), HdlOpType.MAP_ASSOCIATION: (11, L), }
[docs] def visit_HdlValueInt(self, o): w = self.out.write v = o.val bits = o.bits if is_str(v): v = v.upper() if o.base == 256: w("'%s'" % v) else: w('%s"%s"' % (self.NUM_BASES[o.base], v)) return if bits is None: if o.base is not None: b = self.NUM_BASES[o.base] if o.base == 256: w("'%d'" % v) elif o.base == 16: w('%s"%X"' % (b, v)) elif o.base == 8: w('%s"%o"' % (b, v)) elif o.base == 2: w('{0}"{1:b}"'.format(b, v)) else: raise NotImplementedError(o.base) else: w(str(v)) return elif bits % 8 == 0: f = 'X"{0:0%dx}"' % (bits / 8) else: f = '"{0:0%db}"' % (bits) w(f.format(v))
[docs] def _visit_operand_parentheses_extra_check(self, op_my, precedence_my, asoc_my, op_parent, precedence_parent, asoc_parent, left, right): if super(ToVhdl2008Expr, self)._visit_operand_parentheses_extra_check( op_my, precedence_my, asoc_my, op_parent, precedence_parent, asoc_parent, left, right): return True elif op_my in self.BITWISE_BIN_OPS and\ op_parent in self.BITWISE_BIN_OPS and\ op_my != op_parent: return True else: return False
[docs] def _visit_operand(self, operand, i, parent, expr_requires_parenthesis, cancel_parenthesis): if parent.fn in self.EQ_NEQ_OPS and isinstance(operand, HdlOp) and operand.fn in self.EQ_NEQ_OPS: # handle the case (a = b) = (c = d) where to boolean conversion is applied during a = b evaluation expr_requires_parenthesis = True return ToHdlCommon._visit_operand(self, operand, i, parent, expr_requires_parenthesis, cancel_parenthesis)
[docs] def visit_HdlOp(self, o): """ :type o: HdlOp """ fn = o.ops[0] if fn == HdlValueId("assert"): self.visit_assert(o.ops[1:]) return elif fn == HdlValueId("report"): self.visit_report(o.ops[1:]) return w = self.out.write op = o.fn if op == HdlOpType.RISING: w("RISING_EDGE(") self.visit_iHdlExpr(o.ops[0]) w(")") elif op == HdlOpType.FALLING: w("FALLING_EDGE(") self.visit_iHdlExpr(o.ops[0]) w(")") elif op == HdlOpType.INDEX or op == HdlOpType.CALL: self._visit_operand(o.ops[0], 0, o, False, False) w("(") for isLast, (o_i, _o) in iter_with_last(enumerate(o.ops[1:])): self._visit_operand(_o, o_i + 1, o, False, True) if not isLast: w(", ") w(")") elif op == HdlOpType.TERNARY: has_3_ops = len(o.ops) == 3 if has_3_ops: cond, o0, o1 = o.ops else: cond, o0 = o.ops self._visit_operand(o0, 1, o, True, False) w(" WHEN ") self._visit_operand(cond, 0, o, True, False) if has_3_ops: if isinstance(o1, HdlOp) and o1.fn == HdlOpType.TERNARY: w(" ELSE\n") self.visit_iHdlExpr(o1) # must not have parenthesis else: w(" ELSE ") self._visit_operand(o1, 2, o, False, False) elif op == HdlOpType.APOSTROPHE: self._visit_operand(o.ops[0], 0, o, True, False) w("'") args = o.ops[1] if isinstance(args, list): self.visit_iHdlExpr(args) elif isinstance(args, HdlValueId): # normal attribute self.visit_iHdlExpr(args) else: w("(") self._visit_operand(args, 0, o, False, True) w(")") elif op == HdlOpType.ABS: w("ABS(") self.visit_iHdlExpr(o.ops[0]) w(")") elif op == HdlOpType.DEFINE_RESOLVER: assert self.in_typedef self.visit_iHdlExpr(o.ops[0]) w(" ") self.visit_iHdlExpr(o.ops[1]) else: return ToHdlCommon.visit_HdlOp(self, o)
[docs] def visit_str(self, o): """ :type o: str """ w = self.out.write if o == "": w('""') else: ESCAPES = { '\n': 'LF\n', '\c': 'CR' } CONC = self.GENERIC_BIN_OPS[HdlOpType.CONCAT] first = True in_string_lit = False for c in o: esc = ESCAPES.get(c, None) if esc is None: if not in_string_lit: if not first: # first character after escape sequence w(CONC) w('"') # string start " in_string_lit = True # character inside "" w(c) else: if not first: if in_string_lit: w('"') # string end " # escape sequence behind string w(CONC) in_string_lit = False # escape name w(esc) first = False if in_string_lit: w('"') # string end "
[docs] def visit_iHdlExpr(self, expr): w = self.out.write if expr is HdlAll: w("ALL") elif expr is HdlOthers: w("OTHERS") elif expr is None: if self.in_typedef: w("<>") else: w("OPEN") elif is_str(expr): self.visit_str(expr) elif isinstance(expr, list): with_nl = len(expr) > 3 if with_nl: w("(\n") else: w("(") with Indent(self.out): for is_last, elem in iter_with_last(expr): self.visit_iHdlExpr(elem) if not is_last: if with_nl: w(",\n") else: w(", ") w(")") else: ToHdlCommon.visit_iHdlExpr(self, expr)