From: whitequark Date: Tue, 19 May 2020 23:33:14 +0000 (+0000) Subject: back.rtlil: handle signed and large Instance parameters correctly. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=afdbe742c5712e8a136a94ad363a2fdbea9a7e28;p=nmigen.git back.rtlil: handle signed and large Instance parameters correctly. Fixes #388. --- diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index 48fa125..3838101 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -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): if isinstance(value, str): return "\"{}\"".format(value.translate(_escape_map)) 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): value_twos_compl = value.value & ((1 << value.width) - 1) return "{}'{:0{}b}".format(value.width, value_twos_compl, value.width) @@ -149,6 +166,9 @@ class _ModuleBuilder(_Namer, _BufferedBuilder, _AttrBuilder): if isinstance(value, float): self._append(" parameter real \\{} \"{!r}\"\n", param, value) + elif signed(value): + self._append(" parameter signed \\{} {}\n", + param, const(value)) else: self._append(" parameter \\{} {}\n", param, const(value))