cxxrtl: add an unsupported knob for manipulating clock trees.
authorwhitequark <whitequark@whitequark.org>
Wed, 22 Apr 2020 01:15:27 +0000 (01:15 +0000)
committerwhitequark <whitequark@whitequark.org>
Wed, 22 Apr 2020 01:15:27 +0000 (01:15 +0000)
This is quite possibly the worst way to implement this, but it does
work for a subset of well-behaved designs, and can be used to measure
how much performance is lost simulating the inactive edge of a clock.

It should be replaced with a clock tree analyzer generating safe
code once it is clear how should such a thing look like.

backends/cxxrtl/cxxrtl.cc

index 3cdc5ab6b8c0db8274ef1d82da93a057cd52cdd8..bb473cefb3430ee5a789abd2b7424fe11ffdc57c 100644 (file)
@@ -1202,6 +1202,24 @@ struct CxxrtlWorker {
                                        f << indent << mangle(cell) << access << mangle_wire_name(conn.first) << " = ";
                                        dump_sigspec_rhs(conn.second);
                                        f << ";\n";
+                                       if (getenv("CXXRTL_VOID_MY_WARRANTY")) {
+                                               // Until we have proper clock tree detection, this really awful hack that opportunistically
+                                               // propagates prev_* values for clocks can be used to estimate how much faster a design could
+                                               // be if only one clock edge was simulated by replacing:
+                                               //   top.p_clk = value<1>{0u}; top.step();
+                                               //   top.p_clk = value<1>{1u}; top.step();
+                                               // with:
+                                               //   top.prev_p_clk = value<1>{0u}; top.p_clk = value<1>{1u}; top.step();
+                                               // Don't rely on this; it will be removed without warning.
+                                               RTLIL::Module *cell_module = cell->module->design->module(cell->type);
+                                               if (cell_module != nullptr && cell_module->wire(conn.first) && conn.second.is_wire()) {
+                                                       RTLIL::Wire *cell_module_wire = cell_module->wire(conn.first);
+                                                       if (edge_wires[conn.second.as_wire()] && edge_wires[cell_module_wire]) {
+                                                               f << indent << mangle(cell) << access << "prev_" << mangle(cell_module_wire) << " = ";
+                                                               f << "prev_" << mangle(conn.second.as_wire()) << ";\n";
+                                                       }
+                                               }
+                                       }
                                } else if (cell->input(conn.first)) {
                                        f << indent << mangle(cell) << access << mangle_wire_name(conn.first) << ".next = ";
                                        dump_sigspec_rhs(conn.second);