From e5560cb8a923c8b4e53207ff9b78f50d7803f225 Mon Sep 17 00:00:00 2001 From: abhinavputhran Date: Fri, 6 Mar 2026 16:27:03 -0500 Subject: [PATCH 1/2] async2sync: inherit src attributes on new_q and new_d wires. Fixes #5674 --- passes/sat/async2sync.cc | 10 ++++++++++ tests/sat/async2sync.ys | 11 +++++++++++ 2 files changed, 21 insertions(+) create mode 100644 tests/sat/async2sync.ys diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc index eb3b154b2..de231b16d 100644 --- a/passes/sat/async2sync.cc +++ b/passes/sat/async2sync.cc @@ -153,7 +153,10 @@ struct Async2syncPass : public Pass { initvals.remove_init(ff.sig_q); Wire *new_d = module->addWire(NEW_ID, ff.width); + new_d->set_src_attribute(cell->get_src_attribute()); + Wire *new_q = module->addWire(NEW_ID, ff.width); + new_q->set_src_attribute(cell->get_src_attribute()); SigSpec sig_set = ff.sig_set; SigSpec sig_clr = ff.sig_clr; @@ -199,7 +202,10 @@ struct Async2syncPass : public Pass { initvals.remove_init(ff.sig_q); Wire *new_d = module->addWire(NEW_ID, ff.width); + new_d->set_src_attribute(cell->get_src_attribute()); + Wire *new_q = module->addWire(NEW_ID, ff.width); + new_q->set_src_attribute(cell->get_src_attribute()); if (ff.pol_aload) { if (!ff.is_fine) { @@ -232,6 +238,7 @@ struct Async2syncPass : public Pass { initvals.remove_init(ff.sig_q); Wire *new_q = module->addWire(NEW_ID, ff.width); + new_q->set_src_attribute(cell->get_src_attribute()); if (ff.pol_arst) { if (!ff.is_fine) @@ -266,10 +273,13 @@ struct Async2syncPass : public Pass { initvals.remove_init(ff.sig_q); Wire *new_q = module->addWire(NEW_ID, ff.width); + new_q->set_src_attribute(cell->get_src_attribute()); + Wire *new_d; if (ff.has_aload) { new_d = module->addWire(NEW_ID, ff.width); + new_d->set_src_attribute(cell->get_src_attribute()); if (ff.pol_aload) { if (!ff.is_fine) module->addMux(NEW_ID, new_q, ff.sig_ad, ff.sig_aload, new_d); diff --git a/tests/sat/async2sync.ys b/tests/sat/async2sync.ys new file mode 100644 index 000000000..0bfbe83ea --- /dev/null +++ b/tests/sat/async2sync.ys @@ -0,0 +1,11 @@ +read_verilog << EOT +module top(input clk, arst, d, output reg q); + always @(posedge clk or posedge arst) + if (arst) q <= 0; + else q <= d; +endmodule +EOT +proc +async2sync +dump w:\$auto\$async2sync* + From 3d6d9c5d4f6fff1d6c132857aadeb0f5a387a2ea Mon Sep 17 00:00:00 2001 From: abhinavputhran Date: Sun, 8 Mar 2026 22:34:28 -0400 Subject: [PATCH 2/2] tests for has_arst, has_sr, has_aload, latch with has_aload true paths. confirmed the tests fail without fix --- tests/sat/async2sync.ys | 47 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/tests/sat/async2sync.ys b/tests/sat/async2sync.ys index 0bfbe83ea..5cfa3d8e8 100644 --- a/tests/sat/async2sync.ys +++ b/tests/sat/async2sync.ys @@ -1,3 +1,4 @@ +# has_arst path read_verilog << EOT module top(input clk, arst, d, output reg q); always @(posedge clk or posedge arst) @@ -7,5 +8,49 @@ endmodule EOT proc async2sync -dump w:\$auto\$async2sync* +select -assert-count 1 w:$auto$async2sync* a:src=* %i +design -reset +# has_sr path +read_verilog << EOT +module sr(input clk, set, clr, d, output reg q); + always @(posedge clk or posedge set or posedge clr) + if (clr) q <= 0; + else if (set) q <= 1; + else q <= d; +endmodule +EOT +proc +async2sync +select -assert-count 2 w:$auto$async2sync* a:src=* %i +design -reset + +# has_aload path +read_verilog << EOT +module aload(input clk, aload, d, ad, output reg q); + always @(posedge clk or posedge aload) + if (aload) q <= ad; + else q <= d; +endmodule +EOT +proc +async2sync +select -assert-count 2 w:$auto$async2sync* a:src=* %i +design -reset + +# latch path +read_verilog << EOT +module latch(input en, arst, d, output reg q); + always @(*) + if (arst) q <= 0; + else if (en) q <= d; +endmodule +EOT +proc +async2sync +# latch with async reset path creates 2 wires (new_q + new_d from has_arst handling) +select -assert-count 2 w:$auto$async2sync* a:src=* %i +design -reset +# a latch where has_aload is false (no async load) cannot be tested here +# because proc optimizes it away into muxes before async2sync runs, +# leaving no latch cell for async2sync to process.