back.rtlil: fix incorrect escaping of signed parameters.
authorwhitequark <whitequark@whitequark.org>
Tue, 28 Apr 2020 02:16:12 +0000 (02:16 +0000)
committerwhitequark <whitequark@whitequark.org>
Tue, 28 Apr 2020 02:18:45 +0000 (02:18 +0000)
Also, improve escaping code in general.

nmigen/back/rtlil.py

index 3f9936e7882400d37c3bb8ecff43e4d384d12f17..48fa125cb59ef54c0591300c1b60676d79d78462 100644 (file)
@@ -14,6 +14,27 @@ class ImplementationLimit(Exception):
     pass
 
 
+_escape_map = str.maketrans({
+    "\"": "\\\"",
+    "\\": "\\\\",
+    "\t": "\\t",
+    "\r": "\\r",
+    "\n": "\\n",
+})
+
+
+def const(value):
+    if isinstance(value, str):
+        return "\"{}\"".format(value.translate(_escape_map))
+    elif isinstance(value, int):
+        return "{:d}".format(value)
+    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)
+    else:
+        assert False, "Invalid constant {!r}".format(value)
+
+
 class _Namer:
     def __init__(self):
         super().__init__()
@@ -58,21 +79,9 @@ class _ProxiedBuilder:
 
 
 class _AttrBuilder:
-    _escape_map = str.maketrans({
-        "\"": "\\\"",
-        "\\": "\\\\",
-        "\t": "\\t",
-        "\r": "\\r",
-        "\n": "\\n",
-    })
-
     def _attribute(self, name, value, *, indent=0):
-        if isinstance(value, str):
-            self._append("{}attribute \\{} \"{}\"\n",
-                         "  " * indent, name, value.translate(self._escape_map))
-        else:
-            self._append("{}attribute \\{} {}\n",
-                         "  " * indent, name, int(value))
+        self._append("{}attribute \\{} {}\n",
+                     "  " * indent, name, const(value))
 
     def _attributes(self, attrs, *, src=None, **kwargs):
         for name, value in attrs.items():
@@ -137,20 +146,12 @@ class _ModuleBuilder(_Namer, _BufferedBuilder, _AttrBuilder):
         name = self._make_name(name, local=False)
         self._append("  cell {} {}\n", kind, name)
         for param, value in params.items():
-            if isinstance(value, str):
-                self._append("    parameter \\{} \"{}\"\n",
-                             param, value.translate(self._escape_map))
-            elif isinstance(value, int):
-                self._append("    parameter \\{} {}'{:b}\n",
-                             param, bits_for(value), value)
-            elif isinstance(value, float):
+            if isinstance(value, float):
                 self._append("    parameter real \\{} \"{!r}\"\n",
                              param, value)
-            elif isinstance(value, ast.Const):
-                self._append("    parameter \\{} {}'{:b}\n",
-                             param, len(value), value.value)
             else:
-                assert False, "Bad parameter {!r}".format(value)
+                self._append("    parameter \\{} {}\n",
+                             param, const(value))
         for port, wire in ports.items():
             self._append("    connect {} {}\n", port, wire)
         self._append("  end\n")
@@ -433,11 +434,7 @@ class _RHSValueCompiler(_ValueCompiler):
         return super().on_value(self.s.expand(value))
 
     def on_Const(self, value):
-        if isinstance(value.value, str):
-            return "{}'{}".format(value.width, value.value)
-        else:
-            value_twos_compl = value.value & ((1 << value.width) - 1)
-            return "{}'{:0{}b}".format(value.width, value_twos_compl, value.width)
+        return const(value)
 
     def on_AnyConst(self, value):
         if value in self.s.anys: