back.rtlil: handle signed and large Instance parameters correctly.
authorwhitequark <whitequark@whitequark.org>
Tue, 19 May 2020 23:33:14 +0000 (23:33 +0000)
committerwhitequark <whitequark@whitequark.org>
Tue, 19 May 2020 23:33:14 +0000 (23:33 +0000)
Fixes #388.

nmigen/back/rtlil.py

index 48fa125cb59ef54c0591300c1b60676d79d78462..3838101384f3f175db0c696b1860fc8136721863 100644 (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):
     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))