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("]")