From 929c817384a310801eceb2e35ea8f48c79a1c3eb Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Wed, 19 Feb 2025 09:43:53 -0800 Subject: [PATCH 1/5] splitnets new options --- tests/various/test_splitnets.tcl | 63 ++++++++++++++++++++++++++++++++ tests/various/test_splitnets.v | 13 +++++++ tests/various/test_splitnets.ys | 1 + 3 files changed, 77 insertions(+) create mode 100644 tests/various/test_splitnets.tcl create mode 100644 tests/various/test_splitnets.v create mode 100644 tests/various/test_splitnets.ys diff --git a/tests/various/test_splitnets.tcl b/tests/various/test_splitnets.tcl new file mode 100644 index 000000000..9cb2b4305 --- /dev/null +++ b/tests/various/test_splitnets.tcl @@ -0,0 +1,63 @@ +yosys -import + +proc read_stats { file } { + set fid [open $file] + set result [read $fid] + close $fid + set ports 0 + set nets 0 + foreach line [split $result "\n"] { + if [regexp {Number of wires:[ \t]+([0-9]+)} $line tmp n] { + set nets [expr $nets + $n] + } + if [regexp {Number of ports:[ \t]+([0-9]+)} $line tmp n] { + set ports [expr $ports + $n] + } + } + return [list $nets $ports] +} + +proc assert_count { type actual expected } { + if {$actual != $expected} { + puts "Error, $type count: $actual vs $expected expected" + exit 1 + } +} + +read_verilog test_splitnets.v +hierarchy -auto-top +procs +design -save "pre" + +splitnets -ports_only -top_only +write_verilog -noexpr "ports_only_in_top.v" +tee -o "ports_only_in_top.txt" stat +foreach {nets ports} [read_stats "ports_only_in_top.txt"] {} +assert_count "nets" $nets 26 +assert_count "ports" $ports 16 + +design -load "pre" +splitnets -ports_only +write_verilog -noexpr "ports_only_in_all.v" +tee -o "ports_only_in_all.txt" stat +foreach {nets ports} [read_stats "ports_only_in_all.txt"] {} +assert_count "nets" $nets 30 +assert_count "ports" $ports 20 + +design -load "pre" +splitnets -ports -top_only +write_verilog -noexpr "ports_nets_in_top.v" +tee -o "ports_nets_in_top.txt" stat +foreach {nets ports} [read_stats "ports_nets_in_top.txt"] {} +assert_count "nets" $nets 30 +assert_count "ports" $ports 16 + +design -load "pre" +splitnets -ports +write_verilog -noexpr "ports_nets_in_all.v" +tee -o "ports_nets_in_all.txt" stat +foreach {nets ports} [read_stats "ports_nets_in_all.txt"] {} +assert_count "nets" $nets 40 +assert_count "ports" $ports 20 + +exit 0 diff --git a/tests/various/test_splitnets.v b/tests/various/test_splitnets.v new file mode 100644 index 000000000..2833ce147 --- /dev/null +++ b/tests/various/test_splitnets.v @@ -0,0 +1,13 @@ +module bottom(input clk, input wire [1:0] i, output reg [1:0] q); + reg [1:0] q1; + always @(posedge clk) begin + q1 <= i; + q <= q1; + end +endmodule + +module top(input clk, input wire [1:0] i, output reg [1:0] q); + reg [1:0] q1; + bottom u1 (.clk(clk), .i(i), .q(q1)); + not u2 (q, q1); +endmodule diff --git a/tests/various/test_splitnets.ys b/tests/various/test_splitnets.ys new file mode 100644 index 000000000..2af787d4f --- /dev/null +++ b/tests/various/test_splitnets.ys @@ -0,0 +1 @@ +tcl test_splitnets.tcl From f65808aaf4a188042db4652130df46a04440191f Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Wed, 19 Feb 2025 09:44:10 -0800 Subject: [PATCH 2/5] splitnets new options --- passes/cmds/splitnets.cc | 42 ++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index bd8b9ceac..09ca92b83 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -112,6 +112,12 @@ struct SplitnetsPass : public Pass { log(" -ports\n"); log(" also split module ports. per default only internal signals are split.\n"); log("\n"); + log(" -ports_only\n"); + log(" Split module ports, but not the internal signals.\n"); + log("\n"); + log(" -top_only\n"); + log(" Split module ports/nets, only at the top level.\n"); + log("\n"); log(" -driver\n"); log(" don't blindly split nets in individual bits. instead look at the driver\n"); log(" and split nets so that no driver drives only part of a net.\n"); @@ -121,6 +127,8 @@ struct SplitnetsPass : public Pass { { bool flag_ports = false; bool flag_driver = false; + bool flag_ports_only = false; + bool flag_top_only = false; std::string format = "[]:"; log_header(design, "Executing SPLITNETS pass (splitting up multi-bit signals).\n"); @@ -136,6 +144,14 @@ struct SplitnetsPass : public Pass { flag_ports = true; continue; } + if (args[argidx] == "-ports_only") { + flag_ports_only = true; + continue; + } + if (args[argidx] == "-top_only") { + flag_top_only = true; + continue; + } if (args[argidx] == "-driver") { flag_driver = true; continue; @@ -151,11 +167,12 @@ struct SplitnetsPass : public Pass { { if (module->has_processes_warn()) continue; - + if (flag_top_only && (design->top_module() != module)) { + continue; + } SplitnetsWorker worker; - if (flag_ports) - { + if (flag_ports || flag_ports_only) { int normalized_port_factor = 0; for (auto wire : module->wires()) @@ -186,7 +203,8 @@ struct SplitnetsPass : public Pass { for (auto &chunk : sig.chunks()) { if (chunk.wire == NULL) continue; - if (chunk.wire->port_id == 0 || flag_ports) { + if (flag_ports_only && (chunk.wire->port_id != 0) || + ((!flag_ports_only) && (chunk.wire->port_id == 0 || flag_ports))) { if (chunk.offset != 0) split_wires_at[chunk.wire].insert(chunk.offset); if (chunk.offset + chunk.width < chunk.wire->width) @@ -203,11 +221,12 @@ struct SplitnetsPass : public Pass { } worker.append_wire(module, it.first, cursor, it.first->width - cursor, format); } - } - else - { + } else { for (auto wire : module->wires()) { - if (wire->width > 1 && (wire->port_id == 0 || flag_ports) && design->selected(module, wire)) + if (flag_ports_only) { + if (wire->width > 1 && (wire->port_id != 0) && design->selected(module, wire)) + worker.splitmap[wire] = std::vector(); + } else if (wire->width > 1 && (wire->port_id == 0 || flag_ports) && design->selected(module, wire)) worker.splitmap[wire] = std::vector(); } @@ -218,9 +237,8 @@ struct SplitnetsPass : public Pass { module->rewrite_sigspecs(worker); - if (flag_ports) - { - for (auto wire : module->wires()) + if (flag_ports || flag_ports_only) { + for (auto wire : module->wires()) { if (wire->port_id == 0) continue; @@ -243,7 +261,7 @@ struct SplitnetsPass : public Pass { delete_wires.insert(it.first); module->remove(delete_wires); - if (flag_ports) + if (flag_ports || flag_ports_only) module->fixup_ports(); } From 5b641d0a24a9ad2bc262d46169959cde128263a6 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 19 Feb 2025 10:06:39 -0800 Subject: [PATCH 3/5] Update splitnets.cc --- passes/cmds/splitnets.cc | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index 09ca92b83..104e24062 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -113,10 +113,10 @@ struct SplitnetsPass : public Pass { log(" also split module ports. per default only internal signals are split.\n"); log("\n"); log(" -ports_only\n"); - log(" Split module ports, but not the internal signals.\n"); + log(" split module ports, but not the internal signals.\n"); log("\n"); log(" -top_only\n"); - log(" Split module ports/nets, only at the top level.\n"); + log(" split module ports/nets, only at the first level of hierarchy.\n"); log("\n"); log(" -driver\n"); log(" don't blindly split nets in individual bits. instead look at the driver\n"); @@ -167,12 +167,13 @@ struct SplitnetsPass : public Pass { { if (module->has_processes_warn()) continue; - if (flag_top_only && (design->top_module() != module)) { + if (flag_top_only && (design->top_module() != module)) continue; - } + SplitnetsWorker worker; - if (flag_ports || flag_ports_only) { + if (flag_ports || flag_ports_only) + { int normalized_port_factor = 0; for (auto wire : module->wires()) @@ -203,8 +204,8 @@ struct SplitnetsPass : public Pass { for (auto &chunk : sig.chunks()) { if (chunk.wire == NULL) continue; - if (flag_ports_only && (chunk.wire->port_id != 0) || - ((!flag_ports_only) && (chunk.wire->port_id == 0 || flag_ports))) { + if (flag_ports_only && (chunk.wire->port_id != 0) || !flag_ports_only && (chunk.wire->port_id == 0 || flag_ports)) + { if (chunk.offset != 0) split_wires_at[chunk.wire].insert(chunk.offset); if (chunk.offset + chunk.width < chunk.wire->width) @@ -221,12 +222,14 @@ struct SplitnetsPass : public Pass { } worker.append_wire(module, it.first, cursor, it.first->width - cursor, format); } - } else { + } + else + { for (auto wire : module->wires()) { - if (flag_ports_only) { + if (flag_ports_only) if (wire->width > 1 && (wire->port_id != 0) && design->selected(module, wire)) worker.splitmap[wire] = std::vector(); - } else if (wire->width > 1 && (wire->port_id == 0 || flag_ports) && design->selected(module, wire)) + else if (wire->width > 1 && (wire->port_id == 0 || flag_ports) && design->selected(module, wire)) worker.splitmap[wire] = std::vector(); } @@ -237,7 +240,8 @@ struct SplitnetsPass : public Pass { module->rewrite_sigspecs(worker); - if (flag_ports || flag_ports_only) { + if (flag_ports || flag_ports_only) + { for (auto wire : module->wires()) { if (wire->port_id == 0) From 4de90307a9d7b3bffa866718703aeb517467a06b Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 19 Feb 2025 10:07:10 -0800 Subject: [PATCH 4/5] Update splitnets.cc --- passes/cmds/splitnets.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index 104e24062..15079f163 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -116,7 +116,7 @@ struct SplitnetsPass : public Pass { log(" split module ports, but not the internal signals.\n"); log("\n"); log(" -top_only\n"); - log(" split module ports/nets, only at the first level of hierarchy.\n"); + log(" split module ports/nets, only at the top level of hierarchy.\n"); log("\n"); log(" -driver\n"); log(" don't blindly split nets in individual bits. instead look at the driver\n"); From 707731147cc8726b5db2c19fabe3691b749ee8f8 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 19 Feb 2025 10:10:54 -0800 Subject: [PATCH 5/5] Update splitnets.cc --- passes/cmds/splitnets.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index 15079f163..388f125d8 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -204,8 +204,8 @@ struct SplitnetsPass : public Pass { for (auto &chunk : sig.chunks()) { if (chunk.wire == NULL) continue; - if (flag_ports_only && (chunk.wire->port_id != 0) || !flag_ports_only && (chunk.wire->port_id == 0 || flag_ports)) - { + if ((flag_ports_only && (chunk.wire->port_id != 0) || + (!flag_ports_only && (chunk.wire->port_id == 0 || flag_ports))) { if (chunk.offset != 0) split_wires_at[chunk.wire].insert(chunk.offset); if (chunk.offset + chunk.width < chunk.wire->width) @@ -242,7 +242,7 @@ struct SplitnetsPass : public Pass { if (flag_ports || flag_ports_only) { - for (auto wire : module->wires()) + for (auto wire : module->wires()) { if (wire->port_id == 0) continue;