From 242535255103ad9f6ad163876394035cf12a11ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Wed, 16 Oct 2024 11:44:18 +0200 Subject: [PATCH 1/8] keep_hierarchy: Redo hierarchy traversal for `-min_cost` --- passes/hierarchy/keep_hierarchy.cc | 67 +++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/passes/hierarchy/keep_hierarchy.cc b/passes/hierarchy/keep_hierarchy.cc index 6b947e673..2a38751c8 100644 --- a/passes/hierarchy/keep_hierarchy.cc +++ b/passes/hierarchy/keep_hierarchy.cc @@ -23,13 +23,61 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +struct ThresholdHiearchyKeeping { + Design *design; + CellCosts costs; + dict done; + pool in_progress; + uint64_t threshold; + + ThresholdHiearchyKeeping(Design *design, uint64_t threshold) + : design(design), costs(design), threshold(threshold) {} + + uint64_t visit(RTLIL::Module *module) { + if (module->has_attribute(ID(gate_cost_equivalent))) + return module->attributes[ID(gate_cost_equivalent)].as_int(); + + if (done.count(module)) + return done.at(module); + + if (in_progress.count(module)) + log_error("Circular hierarchy\n"); + in_progress.insert(module); + + uint64_t size = 0; + module->has_processes_warn(); + + for (auto cell : module->cells()) { + if (!cell->type.isPublic()) { + size += costs.get(cell); + } else { + RTLIL::Module *submodule = design->module(cell->type); + if (!submodule) + log_error("Hierarchy contains unknown module '%s' (instanced as %s in %s)\n", + log_id(cell->type), log_id(cell), log_id(module)); + size += visit(submodule); + } + } + + if (size > threshold) { + log("Marking %s (module too big: %llu > %llu).\n", log_id(module), size, threshold); + module->set_bool_attribute(ID::keep_hierarchy); + size = 0; + } + + in_progress.erase(module); + done[module] = size; + return size; + } +}; + struct KeepHierarchyPass : public Pass { KeepHierarchyPass() : Pass("keep_hierarchy", "add the keep_hierarchy attribute") {} void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" keep_hierarchy [options]\n"); + log(" keep_hierarchy [options] [selection]\n"); log("\n"); log("Add the keep_hierarchy attribute.\n"); log("\n"); @@ -54,16 +102,15 @@ struct KeepHierarchyPass : public Pass { } extra_args(args, argidx, design); - CellCosts costs(design); + if (min_cost) { + RTLIL::Module *top = design->top_module(); + if (!top) + log_cmd_error("'-min_cost' mode requires a single top module in the design\n"); - for (auto module : design->selected_modules()) { - if (min_cost) { - unsigned int cost = costs.get(module); - if (cost > min_cost) { - log("Marking %s (module too big: %d > %d).\n", log_id(module), cost, min_cost); - module->set_bool_attribute(ID::keep_hierarchy); - } - } else { + ThresholdHiearchyKeeping worker(design, min_cost); + worker.visit(top); + } else { + for (auto module : design->selected_modules()) { log("Marking %s.\n", log_id(module)); module->set_bool_attribute(ID::keep_hierarchy); } From cf79630be0c43af93e5ae6d7ae8382b27fcd81d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Sat, 19 Oct 2024 01:18:30 +0200 Subject: [PATCH 2/8] keep_hierarchy: Require size information on blackboxes --- passes/hierarchy/keep_hierarchy.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/hierarchy/keep_hierarchy.cc b/passes/hierarchy/keep_hierarchy.cc index 2a38751c8..04c8cfdc2 100644 --- a/passes/hierarchy/keep_hierarchy.cc +++ b/passes/hierarchy/keep_hierarchy.cc @@ -37,6 +37,9 @@ struct ThresholdHiearchyKeeping { if (module->has_attribute(ID(gate_cost_equivalent))) return module->attributes[ID(gate_cost_equivalent)].as_int(); + if (module->get_blackbox_attribute()) + log_error("Missing cost information on instanced blackbox %s\n", log_id(module)); + if (done.count(module)) return done.at(module); From c8fffce2b51fa221b42f1c663162041df4bc5399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 5 Nov 2024 09:00:46 +0100 Subject: [PATCH 3/8] keep_hierarchy: Update messages --- passes/hierarchy/keep_hierarchy.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/passes/hierarchy/keep_hierarchy.cc b/passes/hierarchy/keep_hierarchy.cc index 04c8cfdc2..7253004e4 100644 --- a/passes/hierarchy/keep_hierarchy.cc +++ b/passes/hierarchy/keep_hierarchy.cc @@ -63,7 +63,7 @@ struct ThresholdHiearchyKeeping { } if (size > threshold) { - log("Marking %s (module too big: %llu > %llu).\n", log_id(module), size, threshold); + log("Keeping %s (estimated size above threshold: %llu > %llu).\n", log_id(module), size, threshold); module->set_bool_attribute(ID::keep_hierarchy); size = 0; } @@ -75,7 +75,7 @@ struct ThresholdHiearchyKeeping { }; struct KeepHierarchyPass : public Pass { - KeepHierarchyPass() : Pass("keep_hierarchy", "add the keep_hierarchy attribute") {} + KeepHierarchyPass() : Pass("keep_hierarchy", "selectively add the keep_hierarchy attribute") {} void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -85,9 +85,15 @@ struct KeepHierarchyPass : public Pass { log("Add the keep_hierarchy attribute.\n"); log("\n"); log(" -min_cost \n"); - log(" only add the attribute to modules estimated to have more\n"); - log(" than gates after simple techmapping. Intended\n"); - log(" for tuning trade-offs between quality and yosys runtime.\n"); + log(" only add the attribute to modules estimated to have more than \n"); + log(" gates after simple techmapping. Intended for tuning trade-offs between\n"); + log(" quality and yosys runtime.\n"); + log("\n"); + log(" When evaluating a module's cost, gates which are within a submodule\n"); + log(" which is marked with the keep_hierarchy attribute are not counted\n"); + log(" towards the upper module's cost. This applies to both when the attribute\n"); + log(" was added by this command or was pre-existing.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) override { From 426ef53c205a0c5de14dbcb821363ac3e04d5ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 5 Nov 2024 09:14:15 +0100 Subject: [PATCH 4/8] Document `gate_cost_equivalent` --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 3845d2502..3bcd59ec8 100644 --- a/README.md +++ b/README.md @@ -575,6 +575,9 @@ Non-standard or SystemVerilog features for formal verification ``@(posedge )`` or ``@(negedge )`` when ```` is marked with the ``(* gclk *)`` Verilog attribute. +- The `gate_cost_equivalent` attribute on a module can be used to specify + the estimated cost of a module as an equivalent number of basic gate + instances. Supported features from SystemVerilog ===================================== From 69a36aec3b90d0a5b0513900b4852dae27e280f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 5 Nov 2024 09:28:45 +0100 Subject: [PATCH 5/8] Add keep_hierarchy test --- tests/various/keep_hierarchy.ys | 53 +++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/various/keep_hierarchy.ys diff --git a/tests/various/keep_hierarchy.ys b/tests/various/keep_hierarchy.ys new file mode 100644 index 000000000..3f509dc64 --- /dev/null +++ b/tests/various/keep_hierarchy.ys @@ -0,0 +1,53 @@ +read_verilog < Date: Tue, 3 Dec 2024 11:09:15 +0100 Subject: [PATCH 6/8] Update `gate_cost_equivalent` help --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3bcd59ec8..19041673a 100644 --- a/README.md +++ b/README.md @@ -354,6 +354,11 @@ Verilog Attributes and non-standard features - The ``keep_hierarchy`` attribute on cells and modules keeps the ``flatten`` command from flattening the indicated cells and modules. +- The `gate_cost_equivalent` attribute on a module can be used to specify + the estimated cost of the module as a number of basic gate instances. See + the help message of command `keep_hierarchy` which interprets this + attribute. + - The ``init`` attribute on wires is set by the frontend when a register is initialized "FPGA-style" with ``reg foo = val``. It can be used during synthesis to add the necessary reset logic. @@ -575,10 +580,6 @@ Non-standard or SystemVerilog features for formal verification ``@(posedge )`` or ``@(negedge )`` when ```` is marked with the ``(* gclk *)`` Verilog attribute. -- The `gate_cost_equivalent` attribute on a module can be used to specify - the estimated cost of a module as an equivalent number of basic gate - instances. - Supported features from SystemVerilog ===================================== From c33f7b92f73af3d4d7cdfed6e6dc287d38ddb267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 3 Dec 2024 11:11:02 +0100 Subject: [PATCH 7/8] Fix typo --- passes/hierarchy/keep_hierarchy.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/hierarchy/keep_hierarchy.cc b/passes/hierarchy/keep_hierarchy.cc index 7253004e4..61c66551b 100644 --- a/passes/hierarchy/keep_hierarchy.cc +++ b/passes/hierarchy/keep_hierarchy.cc @@ -23,14 +23,14 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -struct ThresholdHiearchyKeeping { +struct ThresholdHierarchyKeeping { Design *design; CellCosts costs; dict done; pool in_progress; uint64_t threshold; - ThresholdHiearchyKeeping(Design *design, uint64_t threshold) + ThresholdHierarchyKeeping(Design *design, uint64_t threshold) : design(design), costs(design), threshold(threshold) {} uint64_t visit(RTLIL::Module *module) { @@ -116,7 +116,7 @@ struct KeepHierarchyPass : public Pass { if (!top) log_cmd_error("'-min_cost' mode requires a single top module in the design\n"); - ThresholdHiearchyKeeping worker(design, min_cost); + ThresholdHierarchyKeeping worker(design, min_cost); worker.visit(top); } else { for (auto module : design->selected_modules()) { From 6ad4918121f5e71b1e79f7289a9812a630bf0db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 3 Dec 2024 11:11:59 +0100 Subject: [PATCH 8/8] Account for pre-existing `keep_hierarchy` in cost sum --- passes/hierarchy/keep_hierarchy.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/passes/hierarchy/keep_hierarchy.cc b/passes/hierarchy/keep_hierarchy.cc index 61c66551b..bfae9fa38 100644 --- a/passes/hierarchy/keep_hierarchy.cc +++ b/passes/hierarchy/keep_hierarchy.cc @@ -37,6 +37,9 @@ struct ThresholdHierarchyKeeping { if (module->has_attribute(ID(gate_cost_equivalent))) return module->attributes[ID(gate_cost_equivalent)].as_int(); + if (module->has_attribute(ID(keep_hierarchy))) + return 0; + if (module->get_blackbox_attribute()) log_error("Missing cost information on instanced blackbox %s\n", log_id(module));