back.rtlil: handle signed and large Instance parameters correctly.

Fixes #388.
This commit is contained in:
whitequark 2020-05-19 23:33:14 +00:00
parent 393c27ac8e
commit fbf9e1f339

View file

@ -23,11 +23,28 @@ _escape_map = str.maketrans({
}) })
def signed(value):
if isinstance(value, str):
return False
elif isinstance(value, int):
return value < 0
elif isinstance(value, ast.Const):
return value.signed
else:
assert False, "Invalid constant {!r}".format(value)
def const(value): def const(value):
if isinstance(value, str): if isinstance(value, str):
return "\"{}\"".format(value.translate(_escape_map)) return "\"{}\"".format(value.translate(_escape_map))
elif isinstance(value, int): elif isinstance(value, int):
return "{:d}".format(value) if value in range(0, 2**31-1):
return "{:d}".format(value)
else:
# This code path is only used for Instances, where Verilog-like behavior is desirable.
# Verilog ensures that integers with unspecified width are 32 bits wide or more.
width = max(32, bits_for(value))
return const(ast.Const(value, width))
elif isinstance(value, ast.Const): elif isinstance(value, ast.Const):
value_twos_compl = value.value & ((1 << value.width) - 1) value_twos_compl = value.value & ((1 << value.width) - 1)
return "{}'{:0{}b}".format(value.width, value_twos_compl, value.width) return "{}'{:0{}b}".format(value.width, value_twos_compl, value.width)
@ -149,6 +166,9 @@ class _ModuleBuilder(_Namer, _BufferedBuilder, _AttrBuilder):
if isinstance(value, float): if isinstance(value, float):
self._append(" parameter real \\{} \"{!r}\"\n", self._append(" parameter real \\{} \"{!r}\"\n",
param, value) param, value)
elif signed(value):
self._append(" parameter signed \\{} {}\n",
param, const(value))
else: else:
self._append(" parameter \\{} {}\n", self._append(" parameter \\{} {}\n",
param, const(value)) param, const(value))