Source code for hdlConvertorAst.to.verilog.expr

from hdlConvertorAst.hdlAst import HdlOpType, HdlValueId, HdlValueInt, HdlAll, \
    HdlOp, HdlTypeAuto
from hdlConvertorAst.py_ver_compatibility import is_str
from hdlConvertorAst.to.common import ToHdlCommon, ASSOCIATIVITY, \
    ASSIGN_OPERATORS_SYMBOLS_C
from hdlConvertorAst.to.hdlUtils import iter_with_last
from hdlConvertorAst.to.verilog.utils import collect_array_dims, get_wire_t_params

L = ASSOCIATIVITY.L_TO_R
R = ASSOCIATIVITY.R_TO_L

ASSIGN_OPERATORS = [
    HdlOpType.ASSIGN,
    HdlOpType.PLUS_ASSIGN,
    HdlOpType.MINUS_ASSIGN,
    HdlOpType.MUL_ASSIGN,
    HdlOpType.DIV_ASSIGN,
    HdlOpType.MOD_ASSIGN,
    HdlOpType.AND_ASSIGN,
    HdlOpType.OR_ASSIGN,
    HdlOpType.XOR_ASSIGN,
    HdlOpType.SHIFT_LEFT_ASSIGN,
    HdlOpType.SHIFT_RIGHT_ASSIGN,
    HdlOpType.ARITH_SHIFT_LEFT_ASSIGN,
    HdlOpType.ARITH_SHIFT_RIGHT_ASSIGN,
]

SIGNED = HdlValueId("signed")


[docs]def pop_signed_flag(o): """ :type op: HdlOp pop signed/unsigned flag from type expr """ base_expr = o is_signed = None if o.fn == HdlOpType.PARAMETRIZATION and len(o.ops) == 2: op1 = o.ops[1] if isinstance(op1, HdlOp) and\ op1.fn == HdlOpType.MAP_ASSOCIATION and\ op1.ops[0] == SIGNED: base_expr = o.ops[0] is_signed = bool(int(op1.ops[1])) return base_expr, is_signed
[docs]class ToVerilog2005Expr(ToHdlCommon): GENERIC_BIN_OPS = { HdlOpType.APOSTROPHE: "'", HdlOpType.AND: " & ", HdlOpType.AND_LOG: " && ", HdlOpType.OR: " | ", HdlOpType.OR_LOG: " || ", HdlOpType.NAND: " ~& ", HdlOpType.NOR: " ~| ", HdlOpType.XOR: " ^ ", HdlOpType.XNOR: " ~^ ", HdlOpType.DIV: " / ", HdlOpType.POW: " ** ", HdlOpType.MOD: " % ", HdlOpType.EQ: ' == ', HdlOpType.NE: " != ", HdlOpType.IS: ' === ', HdlOpType.IS_NOT: " !== ", HdlOpType.EQ_MATCH:" ==? ", HdlOpType.NE_MATCH:" !=? ", HdlOpType.SLL: " << ", HdlOpType.SRL: " >> ", HdlOpType.SLA: " <<< ", HdlOpType.SRA: " >>> ", HdlOpType.DOWNTO: ":", HdlOpType.TO: ":", HdlOpType.PART_SELECT_POST: " +: ", HdlOpType.PART_SELECT_PRE: " -: ", HdlOpType.MAP_ASSOCIATION: ":", HdlOpType.ARITH_SHIFT_LEFT_ASSIGN: ' <<<= ', HdlOpType.ARITH_SHIFT_RIGHT_ASSIGN: ' >>>= ', HdlOpType.DOUBLE_COLON: "::", } GENERIC_BIN_OPS.update(ToHdlCommon.GENERIC_BIN_OPS) GENERIC_BIN_OPS.update(ASSIGN_OPERATORS_SYMBOLS_C) OP_PRECEDENCE = { HdlOpType.APOSTROPHE: (1, L), HdlOpType.DOT: (1, L), HdlOpType.INDEX: (1, L), HdlOpType.CALL: (2, L), HdlOpType.TYPE_OF: (2, L), HdlOpType.PARAMETRIZATION: (2, L), HdlOpType.POW: (5, L), HdlOpType.CONCAT: (6, L), HdlOpType.REPL_CONCAT: (7, L), HdlOpType.DIV: (8, L), HdlOpType.MUL: (8, L), HdlOpType.MOD: (8, L), HdlOpType.ADD: (9, L), HdlOpType.SUB: (9, L), HdlOpType.SLL: (10, L), HdlOpType.SRL: (10, L), HdlOpType.SLA: (10, L), HdlOpType.SRA: (10, L), HdlOpType.GT: (11, L), HdlOpType.LT: (11, L), HdlOpType.GE: (11, L), HdlOpType.LE: (11, L), HdlOpType.EQ: (12, L), HdlOpType.NE: (12, L), HdlOpType.IS: (12, L), HdlOpType.IS_NOT: (12, L), HdlOpType.EQ_MATCH: (12, L), HdlOpType.NE_MATCH: (12, L), HdlOpType.AND: (13, L), HdlOpType.XOR: (13, L), HdlOpType.OR: (13, L), HdlOpType.NAND: (13, L), HdlOpType.XNOR: (13, L), HdlOpType.AND_LOG: (14, L), HdlOpType.OR_LOG: (14, L), HdlOpType.TERNARY: (15, R), HdlOpType.RISING: (16, R), HdlOpType.FALLING: (16, R), HdlOpType.DOWNTO: (17, L), HdlOpType.TO: (17, L), HdlOpType.PART_SELECT_PRE: (17, L), HdlOpType.PART_SELECT_POST: (17, L), HdlOpType.MAP_ASSOCIATION: (17, L), } OP_PRECEDENCE.update({k: (3, R) for k in [ HdlOpType.MINUS_UNARY, HdlOpType.PLUS_UNARY, HdlOpType.INCR_PRE, HdlOpType.INCR_POST, HdlOpType.DECR_PRE, HdlOpType.DECR_POST, HdlOpType.NEG, HdlOpType.NEG_LOG, HdlOpType.OR_UNARY, HdlOpType.AND_UNARY, HdlOpType.NAND_UNARY, HdlOpType.NOR_UNARY, HdlOpType.XOR_UNARY, HdlOpType.XNOR_UNARY ]}) OP_PRECEDENCE.update({k: (18, ASSOCIATIVITY.NONE) for k in ASSIGN_OPERATORS}) GENERIC_UNARY_OPS = { HdlOpType.NEG_LOG: "!", HdlOpType.NEG: "~", HdlOpType.MINUS_UNARY: "-", HdlOpType.PLUS_UNARY: "+", HdlOpType.OR_UNARY: "|", HdlOpType.AND_UNARY: "&", HdlOpType.NAND_UNARY: "~&", HdlOpType.NOR_UNARY: "~|", HdlOpType.XOR_UNARY: "^", HdlOpType.XNOR_UNARY: "~^", HdlOpType.RISING: "posedge ", HdlOpType.FALLING: "negedge ", HdlOpType.INCR_PRE: "++", HdlOpType.DECR_PRE: "--", } GENERIC_UNARY_OPS_POSTFIX = { HdlOpType.INCR_POST: "++", HdlOpType.DECR_POST: "--", }
[docs] def visit_HdlValueInt(self, o): """ :type o: HdlValueInt """ w = self.out.write if o.bits is None: w(str(o.val)) else: if o.base is None: f = "{0}'h{1:x}" else: b = o.base if b == 2: base_char = 'b' elif b == 8: base_char = 'O' elif b == 10: base_char = 'd' elif b == 16: base_char = 'h' else: raise NotImplementedError(b) f = "{0}'" + base_char + "{1}" w(f.format(o.bits, o.val))
[docs] def visit_iHdlExpr(self, o): """ :type o: iHdlExpr :return: True, the flag used to mark that the ; should be added if this is a statement """ w = self.out.write if isinstance(o, HdlValueId): w(o.val) elif is_str(o): w('"%s"' % o.replace("\n", "\\\n")) elif isinstance(o, HdlValueInt): self.visit_HdlValueInt(o) elif isinstance(o, HdlOp): _o, is_signed = pop_signed_flag(o) if o is not _o: self.visit_iHdlExpr(_o) else: self.visit_HdlOp(_o) if is_signed is True: w(" signed") elif is_signed is False: w(" unsigned") elif o is HdlAll: w("*") elif o is HdlTypeAuto: pass elif o is None: w("null") elif isinstance(o, float): w(str(o)) elif isinstance(o, list): w("'{") for last, e in iter_with_last(o): self.visit_iHdlExpr(e) if not last: w(", ") w("}") else: raise NotImplementedError(o.__class__, o) return True
[docs] def _visit_operand(self, operand, i, parent, expr_requires_parenthesis, cancel_parenthesis): if isinstance(operand, HdlOp) and \ (operand.fn in self.GENERIC_UNARY_OPS or operand.fn in self.GENERIC_UNARY_OPS_POSTFIX) and \ (parent.fn in self.GENERIC_UNARY_OPS or parent.fn in self.GENERIC_UNARY_OPS_POSTFIX): # unary operator in unary operator expr_requires_parenthesis = True return super(ToVerilog2005Expr, self)._visit_operand(operand, i, parent, expr_requires_parenthesis, cancel_parenthesis)
[docs] def visit_HdlOp(self, o): """ :type o: HdlOp """ w = self.out.write op = o.fn if op == HdlOpType.CONCAT: w = self.out.write w("{") for is_last, (o_i, _o) in iter_with_last(enumerate(o.ops)): self._visit_operand(_o, o_i, o, False, True) if not is_last: w(", ") w("}") return elif op == HdlOpType.REPL_CONCAT: w = self.out.write w("{") self._visit_operand(o.ops[0], 0, o, True, False) w("{") for is_last, (o_i, _o) in iter_with_last(enumerate(o.ops[1:])): self._visit_operand(_o, o_i, o, False, True) if not is_last: w(", ") w("}}") return elif op == HdlOpType.TERNARY: cond, v0, v1 = o.ops self._visit_operand(cond, 0, o, True, False) w(" ? ") self._visit_operand(v0, 1, o, False, False) w(" : ") self._visit_operand(v1, 2, o, False, False) return elif op == HdlOpType.TYPE_OF: w("type(") self._visit_operand(o.ops[0], 0, o, False, True) w(")") return else: super(ToVerilog2005Expr, self).visit_HdlOp(o) return True
[docs] def visit_type_first_part(self, t): """ :type t: iHdlExpr :return: True if the type has also the array dimension part """ w = self.out.write t, array_dims = collect_array_dims(t) wire_params = get_wire_t_params(t) if wire_params is None: if t != HdlTypeAuto: if isinstance(t, HdlOp) and t.fn == HdlOpType.TYPE_OF: w("var ") self.visit_iHdlExpr(t) elif self._type_requires_nettype: w("wire") else: base_t, width, is_signed, _ = wire_params space_required = False if base_t is not HdlTypeAuto and base_t: if not (not self._type_requires_nettype and base_t in (HdlValueId("wire"), HdlValueId("reg"))): w(base_t.val) space_required = True elif self._type_requires_nettype: w("wire") space_required = True if is_signed is None: pass else: if space_required: w(" ") if is_signed: w("signed") else: w("unsigned") if width is not None: # 1D vector w("[") self.visit_iHdlExpr(width) w("]") return len(array_dims) > 0
[docs] def visit_type_array_part(self, t): """ :type t: iHdlExpr """ w = self.out.write _, array_dim = collect_array_dims(t) for ad in array_dim: w("[") if ad is not None: self.visit_iHdlExpr(ad) w("]")