YosysHQ / yosys

Yosys Open SYnthesis Suite
https://yosyshq.net/yosys/
ISC License
3.32k stars 859 forks source link

CXXRTL: blackbox output ports cannot generate clock events #4230

Open jfng opened 4 months ago

jfng commented 4 months ago

Version

Yosys 0.38+92 (git sha1 84116c9a3, gcc 13.2.1 -fPIC -Os)

On which OS did this happen?

Linux

Reproduction Steps

Unzip repro.zip, run make, ./main and inspect the VCD.

top.v:

module top();
    wire clk;
    reg r;

    foo foo (.clk(clk));

    always @(posedge clk) begin
        r <= ~r;
    end
endmodule

foo.v:

(* cxxrtl_blackbox *)
module foo(...);
    (* cxxrtl_comb *) output clk;
endmodule

foo.cc:

struct foo : public bb_p_foo {
    bool eval(performer *performer) override {
        p_clk.next.set<bool>(!p_clk.curr.get<bool>());
        return true;
    }
};

Expected Behavior

r should toggle on each clk cycle.

expected

Actual Behavior

r stays low.

actual

jfng commented 4 months ago

The expected behavior can be obtained by applying this patch, which reverts 93288b8ea:

diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc
index c60b43d3f..e81ea1a85 100644
--- a/backends/cxxrtl/cxxrtl_backend.cc
+++ b/backends/cxxrtl/cxxrtl_backend.cc
@@ -1409,7 +1409,7 @@ struct CxxrtlWorker {
                clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
                if (clk_bit.wire) {
                    f << indent << "if (" << (cell->getParam(ID::CLK_POLARITY).as_bool() ? "posedge_" : "negedge_")
-                               << mangle(clk_bit) << ") {\n";
+                               << mangle(clk_bit) << "()) {\n";
                } else {
                    f << indent << "if (false) {\n";
                }
@@ -1716,16 +1716,16 @@ struct CxxrtlWorker {
            switch (sync->type) {
                case RTLIL::STp:
                    log_assert(sync_bit.wire != nullptr);
-                   events.insert("posedge_" + mangle(sync_bit));
+                   events.insert("posedge_" + mangle(sync_bit) + "()");
                    break;
                case RTLIL::STn:
                    log_assert(sync_bit.wire != nullptr);
-                   events.insert("negedge_" + mangle(sync_bit));
+                   events.insert("negedge_" + mangle(sync_bit) + "()");
                    break;
                case RTLIL::STe:
                    log_assert(sync_bit.wire != nullptr);
-                   events.insert("posedge_" + mangle(sync_bit));
-                   events.insert("negedge_" + mangle(sync_bit));
+                   events.insert("posedge_" + mangle(sync_bit) + "()");
+                   events.insert("negedge_" + mangle(sync_bit) + "()");
                    break;

                case RTLIL::STa:
@@ -1829,7 +1829,7 @@ struct CxxrtlWorker {
            clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
            if (clk_bit.wire) {
                f << indent << "if (" << (port.clk_polarity ? "posedge_" : "negedge_")
-                       << mangle(clk_bit) << ") {\n";
+                       << mangle(clk_bit) << "()) {\n";
            } else {
                f << indent << "if (false) {\n";
            }
@@ -1975,7 +1975,7 @@ struct CxxrtlWorker {
                clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
                if (clk_bit.wire) {
                    f << indent << "if (" << (port.clk_polarity ? "posedge_" : "negedge_")
-                               << mangle(clk_bit) << ") {\n";
+                               << mangle(clk_bit) << "()) {\n";
                } else {
                    f << indent << "if (false) {\n";
                }
@@ -2159,22 +2159,6 @@ struct CxxrtlWorker {
        inc_indent();
            f << indent << "bool converged = " << (eval_converges.at(module) ? "true" : "false") << ";\n";
            if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) {
-               for (auto wire : module->wires()) {
-                   if (edge_wires[wire]) {
-                       for (auto edge_type : edge_types) {
-                           if (edge_type.first.wire == wire) {
-                               if (edge_type.second != RTLIL::STn) {
-                                   f << indent << "bool posedge_" << mangle(edge_type.first) << " = ";
-                                   f << "this->posedge_" << mangle(edge_type.first) << "();\n";
-                               }
-                               if (edge_type.second != RTLIL::STp) {
-                                   f << indent << "bool negedge_" << mangle(edge_type.first) << " = ";
-                                   f << "this->negedge_" << mangle(edge_type.first) << "();\n";
-                               }
-                           }
-                       }
-                   }
-               }
                for (auto wire : module->wires())
                    dump_wire(wire, /*is_local=*/true);
                for (auto node : schedule[module]) {
whitequark commented 4 months ago

Considering that I'd like to deprecate and remove the entire current CXXRTL black-box system I'm not motivated to spend a lot of time on this issue.