Do NaN synthesis pattern matching via attributes
authorCassie Jones <code@witchoflight.com>
Fri, 6 Mar 2020 17:29:46 +0000 (18:29 +0100)
committerCassie Jones <code@witchoflight.com>
Fri, 6 Mar 2020 17:29:46 +0000 (18:29 +0100)
The previous implementation of NaN synthesis used matching on cell
types, which wouldn't scale with adding support for larger cell types.
Using attributes allows for simply adding the appropriate width
attributes and figuring things out from there.

dff_nan.pmg
erase_b2f.pmg
example/example.ys
nangate.cc
share_nan.pmg
techlib.sv

index ac4cb8bc1d7edefff855941a99518742038f126d..340e0f05dda49863f1d6bd2925838eaa6ad8abcf 100644 (file)
@@ -4,13 +4,13 @@ match dff
 endmatch
 
 match input
-    select input->type == \fp3_to_bit
+    select input->attributes.count(\nan_f2b)
     index <SigSpec> port(input, \Y) === port(dff, \D)
     optional
 endmatch
 
 match output
-    select output->type == \bit_to_fp3
+    select output->attributes.count(\nan_b2f)
     index <SigSpec> port(output, \A) === port(dff, \Q)
     optional
 endmatch
index 2a9aceecc16a00a78b834383a8b9f9039b2f9eba..eb1aa11c3271e1df57cac270984607f5dd13f614 100644 (file)
@@ -1,8 +1,9 @@
 match base
-    select base->type == \fp3_to_bit
+    select base->attributes.count(\nan_f2b)
 endmatch
 
 match target
-    select target->type == \bit_to_fp3
+    select target->attributes.count(\nan_b2f)
     index <SigSpec> port(target, \A) === port(base, \Y)
+    index <Const> target->attributes[\nan_b2f] === base->attributes[\nan_f2b]
 endmatch
index 3de18f0795f30357dca5081ed2e66df94b790314..262cb4ff234ed9f4eb82cb69c475bff4e5f7e937 100644 (file)
@@ -1,4 +1,5 @@
 plugin -i nangate.so
 read_verilog -sv example/example.sv
 synth_nan -top hello
-synth_ice40 -noflatten -top hello
+show hello
+# synth_ice40 -noflatten -top hello
index 726b798651737195aaa0fb13f94e8696ac0689f9..a64d4f0dd1106da6122c979b3e01eff23d5f74e3 100644 (file)
@@ -23,8 +23,12 @@ struct NandToNaNWorker
                 f2b_count += 1;
                 RTLIL::Cell *b2fA = module->addCell(NEW_ID, "\\bit_to_fp3");
                 RTLIL::Cell *b2fB = module->addCell(NEW_ID, "\\bit_to_fp3");
-                RTLIL::Cell *nan  = module->addCell(NEW_ID, "\\nan");
+                RTLIL::Cell *nan  = module->addCell(NEW_ID, "\\nan_fp3");
                 RTLIL::Cell *f2b  = module->addCell(NEW_ID, "\\fp3_to_bit");
+                b2fA->attributes[ID(nan_b2f)] = 3;
+                b2fB->attributes[ID(nan_b2f)] = 3;
+                nan->attributes[ID(nan_cell)] = 3;
+                f2b->attributes[ID(nan_f2b)] = 3;
                 b2fA->setPort("\\A", cell->getPort("\\A"));
                 b2fA->setPort("\\Y", module->addWire(NEW_ID, 3));
                 b2fB->setPort("\\A", cell->getPort("\\B"));
@@ -41,8 +45,11 @@ struct NandToNaNWorker
                 not_count += 1;
                 f2b_count += 1;
                 RTLIL::Cell *b2f = module->addCell(NEW_ID, "\\bit_to_fp3");
-                RTLIL::Cell *nan = module->addCell(NEW_ID, "\\nan");
+                RTLIL::Cell *nan = module->addCell(NEW_ID, "\\nan_fp3");
                 RTLIL::Cell *f2b = module->addCell(NEW_ID, "\\fp3_to_bit");
+                b2f->attributes[ID(nan_b2f)] = 3;
+                nan->attributes[ID(nan_cell)] = 3;
+                f2b->attributes[ID(nan_f2b)] = 3;
                 b2f->setPort("\\A", cell->getPort("\\A"));
                 b2f->setPort("\\Y", module->addWire(NEW_ID, 3));
                 f2b->setPort("\\A", module->addWire(NEW_ID, 3));
@@ -71,7 +78,7 @@ struct NandToNaNPass : public Pass {
             NandToNaNWorker worker(design, module);
             log("Replaced %d NAND gates and %d NOT gates.\n",
                 worker.nand_count, worker.not_count);
-            log("Inserted:\n        nan: %5d\n bit_to_fp3: %5d\n fp3_to_bit: %5d\n",
+            log("Inserted:\n    nan_fp3: %5d\n bit_to_fp3: %5d\n fp3_to_bit: %5d\n",
                 worker.nand_count + worker.not_count,
                 worker.b2f_count, worker.f2b_count);
         }
@@ -90,9 +97,11 @@ struct DffToFp3Pass : public Pass {
             pm.run([&]() { dffs.insert(pm.st.dff); });
             for (auto &dff : dffs) {
                 RTLIL::Cell *f2b = module->addCell(NEW_ID, "\\fp3_to_bit");
+                f2b->attributes[ID(nan_f2b)] = 3;
                 f2b->setPort("\\A", module->addWire(NEW_ID, 3));
                 f2b->setPort("\\Y", dff->getPort("\\Q"));
                 RTLIL::Cell *b2f = module->addCell(NEW_ID, "\\bit_to_fp3");
+                b2f->attributes[ID(nan_b2f)] = 3;
                 b2f->setPort("\\A", dff->getPort("\\D"));
                 b2f->setPort("\\Y", module->addWire(NEW_ID, 3));
                 for (int i = 0; i < 3; i++) {
index 571f3b8a6797ce7f6c4076ed2e3f0219ca070d76..fa778ff91c83eb618b4fd19cb7a8120fbc2d6d1e 100644 (file)
@@ -1,9 +1,9 @@
 match cvt_a
-    select cvt_a->type.in(\fp3_to_bit, \bit_to_fp3)
+    select cvt_a->attributes.count(\nan_b2f) || cvt_a->attributes.count(\nan_f2b)
 endmatch
 
 match cvt_b
-    select cvt_b->type.in(\fp3_to_bit, \bit_to_fp3)
+    select cvt_b->attributes.count(\nan_b2f) || cvt_b->attributes.count(\nan_f2b)
     index <IdString> cvt_b->type === cvt_a->type
     index <SigSpec> port(cvt_b, \A) === port(cvt_a, \A)
 endmatch
index bdcd6a1ced037ccab904333fcc252fc3175d5f09..4f4717a68e218fa0f052d241ff8d6b6984a1e742 100644 (file)
 
 // A NaN gate! Computes `Inf - max(x+y, -Inf)`.
 // See http://tom7.org/nand/
-module nan(
+module nan_fp3(
     input      [2:0] A,
-    input      [2:0] B, output reg [2:0] Y
+    input      [2:0] B,
+    output reg [2:0] Y
 );
 
 always begin