fhdl/verilog: Create _print_operator/_print_slice, move code outside _print_expression and cleanup/simplify.
This commit is contained in:
parent
cdfb8d141a
commit
2c98ad94b5
|
@ -100,6 +100,73 @@ def _print_constant(node):
|
||||||
value = abs(node.value),
|
value = abs(node.value),
|
||||||
), node.signed
|
), node.signed
|
||||||
|
|
||||||
|
# Print Operator -----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(UNARY, BINARY, TERNARY) = (1, 2, 3)
|
||||||
|
|
||||||
|
def _print_operator(ns, node):
|
||||||
|
operator = node.op
|
||||||
|
operands = node.operands
|
||||||
|
arity = len(operands)
|
||||||
|
assert arity in [UNARY, BINARY, TERNARY]
|
||||||
|
|
||||||
|
def to_signed(r):
|
||||||
|
return f"$signed({{1'd0 {r}}}))"
|
||||||
|
|
||||||
|
# Unary Operator.
|
||||||
|
if arity == UNARY:
|
||||||
|
r1, s1 = _print_expression(ns, operands[0])
|
||||||
|
# Negation Operator.
|
||||||
|
if operator == "-":
|
||||||
|
# Negate and convert to signed if not already.
|
||||||
|
r = "-" + (r1 if s1 else to_signed(r1))
|
||||||
|
s = True
|
||||||
|
# Other Operators.
|
||||||
|
else:
|
||||||
|
r = operator + r1
|
||||||
|
s = s1
|
||||||
|
|
||||||
|
# Binary Operator.
|
||||||
|
if arity == BINARY:
|
||||||
|
r1, s1 = _print_expression(ns, operands[0])
|
||||||
|
r2, s2 = _print_expression(ns, operands[1])
|
||||||
|
# Convert all expressions to signed when at least one is signed.
|
||||||
|
if operator not in ["<<<", ">>>"]:
|
||||||
|
if s2 and not s1:
|
||||||
|
r1 = to_signed(r1)
|
||||||
|
if s1 and not s2:
|
||||||
|
r2 = to_signed(r2)
|
||||||
|
r = f"{r1} {operator} {r2}"
|
||||||
|
s = s1 or s2
|
||||||
|
|
||||||
|
# Ternary Operator.
|
||||||
|
if arity == TERNARY:
|
||||||
|
assert operator == "m"
|
||||||
|
r1, s1 = _print_expression(ns, operands[0])
|
||||||
|
r2, s2 = _print_expression(ns, operands[1])
|
||||||
|
r3, s3 = _print_expression(ns, operands[2])
|
||||||
|
# Convert all expressions to signed when at least one is signed.
|
||||||
|
if s2 and not s3:
|
||||||
|
r3 = to_signed(r3)
|
||||||
|
if s3 and not s2:
|
||||||
|
r2 = to_signed(r2)
|
||||||
|
r = f"{r1} ? {r2} : {r3}"
|
||||||
|
s = s2 or s3
|
||||||
|
|
||||||
|
return f"({r})", s
|
||||||
|
|
||||||
|
# Print Slice --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _print_slice(ns, node):
|
||||||
|
assert (node.stop - node.start) >= 1
|
||||||
|
if (isinstance(node.value, Signal) and len(node.value) == 1):
|
||||||
|
assert node.start == 0
|
||||||
|
sr = "" # Avoid slicing 1-bit Signals.
|
||||||
|
else:
|
||||||
|
sr = f"[{node.stop-1}:{node.start}]" if (node.stop - node.start) > 1 else f"[{node.start}]"
|
||||||
|
r, s = _print_expression(ns, node.value)
|
||||||
|
return r + sr, s
|
||||||
|
|
||||||
# Print Expression ---------------------------------------------------------------------------------
|
# Print Expression ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
def _print_expression(ns, node):
|
def _print_expression(ns, node):
|
||||||
|
@ -113,55 +180,11 @@ def _print_expression(ns, node):
|
||||||
|
|
||||||
# Operator.
|
# Operator.
|
||||||
elif isinstance(node, _Operator):
|
elif isinstance(node, _Operator):
|
||||||
arity = len(node.operands)
|
return _print_operator(ns, node)
|
||||||
r1, s1 = _print_expression(ns, node.operands[0])
|
|
||||||
if arity == 1:
|
|
||||||
if node.op == "-":
|
|
||||||
if s1:
|
|
||||||
r = node.op + r1
|
|
||||||
else:
|
|
||||||
r = "-$signed({1'd0, " + r1 + "})"
|
|
||||||
s = True
|
|
||||||
else:
|
|
||||||
r = node.op + r1
|
|
||||||
s = s1
|
|
||||||
elif arity == 2:
|
|
||||||
r2, s2 = _print_expression(ns, node.operands[1])
|
|
||||||
if node.op not in ["<<<", ">>>"]:
|
|
||||||
if s2 and not s1:
|
|
||||||
r1 = "$signed({1'd0, " + r1 + "})"
|
|
||||||
if s1 and not s2:
|
|
||||||
r2 = "$signed({1'd0, " + r2 + "})"
|
|
||||||
r = r1 + " " + node.op + " " + r2
|
|
||||||
s = s1 or s2
|
|
||||||
elif arity == 3:
|
|
||||||
assert node.op == "m"
|
|
||||||
r2, s2 = _print_expression(ns, node.operands[1])
|
|
||||||
r3, s3 = _print_expression(ns, node.operands[2])
|
|
||||||
if s2 and not s3:
|
|
||||||
r3 = "$signed({1'd0, " + r3 + "})"
|
|
||||||
if s3 and not s2:
|
|
||||||
r2 = "$signed({1'd0, " + r2 + "})"
|
|
||||||
r = r1 + " ? " + r2 + " : " + r3
|
|
||||||
s = s2 or s3
|
|
||||||
else:
|
|
||||||
raise TypeError
|
|
||||||
return "(" + r + ")", s
|
|
||||||
|
|
||||||
# Slice.
|
# Slice.
|
||||||
elif isinstance(node, _Slice):
|
elif isinstance(node, _Slice):
|
||||||
# Verilog does not like us slicing non-array signals...
|
return _print_slice(ns, node)
|
||||||
if (isinstance(node.value, Signal) and
|
|
||||||
len(node.value) == 1 and
|
|
||||||
node.start == 0 and node.stop == 1):
|
|
||||||
return _print_expression(ns, node.value)
|
|
||||||
|
|
||||||
if node.start + 1 == node.stop:
|
|
||||||
sr = "[" + str(node.start) + "]"
|
|
||||||
else:
|
|
||||||
sr = "[" + str(node.stop-1) + ":" + str(node.start) + "]"
|
|
||||||
r, s = _print_expression(ns, node.value)
|
|
||||||
return r + sr, s
|
|
||||||
|
|
||||||
# Cat.
|
# Cat.
|
||||||
elif isinstance(node, Cat):
|
elif isinstance(node, Cat):
|
||||||
|
|
Loading…
Reference in New Issue