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),
|
||||
), 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 ---------------------------------------------------------------------------------
|
||||
|
||||
def _print_expression(ns, node):
|
||||
|
@ -113,55 +180,11 @@ def _print_expression(ns, node):
|
|||
|
||||
# Operator.
|
||||
elif isinstance(node, _Operator):
|
||||
arity = len(node.operands)
|
||||
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
|
||||
return _print_operator(ns, node)
|
||||
|
||||
# Slice.
|
||||
elif isinstance(node, _Slice):
|
||||
# Verilog does not like us slicing non-array signals...
|
||||
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
|
||||
return _print_slice(ns, node)
|
||||
|
||||
# Cat.
|
||||
elif isinstance(node, Cat):
|
||||
|
|
Loading…
Reference in New Issue