diff --git a/passes/silimate/Makefile.inc b/passes/silimate/Makefile.inc index eadfd1375..32604027b 100644 --- a/passes/silimate/Makefile.inc +++ b/passes/silimate/Makefile.inc @@ -1,6 +1,7 @@ OBJS += passes/silimate/activity.o OBJS += passes/silimate/annotate_cell_fanout.o +OBJS += passes/silimate/annotate_ff_width.o OBJS += passes/silimate/breakreduce.o OBJS += passes/silimate/breaksop.o OBJS += passes/silimate/bus_rebuild.o diff --git a/passes/silimate/annotate_ff_width.cc b/passes/silimate/annotate_ff_width.cc new file mode 100644 index 000000000..1782fa5ad --- /dev/null +++ b/passes/silimate/annotate_ff_width.cc @@ -0,0 +1,63 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2026 Stan Lee + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct AnnotateFfWidthPass : public Pass { + AnnotateFfWidthPass() : Pass("annotate_ff_width", "annotate every flip-flop with its bit-width") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" annotate_ff_width [selection]\n"); + log("\n"); + log("Annotate every flip-flop with its width."); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) override + { + log_header(design, "Executing ANNOTATE_FF_WIDTH pass.\n"); + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + break; + extra_args(args, argidx, design); + + // Loop through all flip-flops and annotate with their width + int annotated = 0; + for (auto module : design->selected_modules()) { + for (auto cell : module->selected_cells()) { + if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + continue; + int width; + if (cell->hasParam(ID::WIDTH)) + width = cell->getParam(ID::WIDTH).as_int(); + else if (cell->hasPort(ID::Q)) + width = GetSize(cell->getPort(ID::Q)); + else + width = 1; + cell->set_string_attribute(ID(ff_width), std::to_string(width)); + annotated++; + } + } + log("Annotated %d flip-flops.\n", annotated); + } +} AnnotateFfWidthPass; +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/clockgate.cc b/passes/techmap/clockgate.cc index 1e0858224..54fbbb247 100644 --- a/passes/techmap/clockgate.cc +++ b/passes/techmap/clockgate.cc @@ -255,6 +255,8 @@ struct ClockgatePass : public Pass { log(" Intended for DFT scan-enable pins.\n"); log(" -min_net_size \n"); log(" Only transform sets of at least eligible FFs.\n"); + log(" -min_ff_size \n"); + log(" Only transform FFs whose original (pre-split) register width, or 'ff_width' attribute\n"); log(" -min_disabled_threshold \n"); log(" Only transform sets of FFs where the total sum of disabled FFs is greater than .\n"); log(" -max_src \n"); @@ -323,6 +325,8 @@ struct ClockgatePass : public Pass { std::vector liberty_files; std::vector dont_use_cells; int min_net_size = 0; + int min_ff_size = 0; + bool use_ff_size_threshold = false; double min_disabled_threshold = -1; bool use_disabled_threshold = false; int max_src = -1; @@ -357,6 +361,11 @@ struct ClockgatePass : public Pass { min_net_size = atoi(args[++argidx].c_str()); continue; } + if (args[argidx] == "-min_ff_size" && argidx+1 < args.size()) { + min_ff_size = atoi(args[++argidx].c_str()); + use_ff_size_threshold = true; + continue; + } if (args[argidx] == "-min_disabled_threshold" && argidx+1 < args.size()) { min_disabled_threshold = atof(args[++argidx].c_str()); use_disabled_threshold = true; @@ -411,6 +420,13 @@ struct ClockgatePass : public Pass { if (!ff.sig_clk[0].is_wire() || !ff.sig_ce[0].is_wire()) continue; + if (use_ff_size_threshold) { + std::string attr = cell->get_string_attribute(ID(ff_width)); + int orig_w = attr.empty() ? ff.width : atoi(attr.c_str()); + if (orig_w < min_ff_size) + continue; + } + ce_ffs.insert(cell); ClkNetInfo info = clk_info_from_ff(ff); @@ -441,9 +457,13 @@ struct ClockgatePass : public Pass { auto& gclk = clk_net.second; // Check if the clock net qualifies for clock gating. - bool qualifies = use_disabled_threshold - ? (gclk.en_disabled_sum >= min_disabled_threshold) - : (gclk.net_size >= min_net_size); + bool qualifies; + if (use_ff_size_threshold) + qualifies = (gclk.net_size >= 1); + else if (use_disabled_threshold) + qualifies = (gclk.en_disabled_sum >= min_disabled_threshold); + else + qualifies = (gclk.net_size >= min_net_size); if (!qualifies) continue; @@ -563,7 +583,11 @@ struct ClockgatePass : public Pass { clk_nets.clear(); } - log("Converted %d FFs using %s.\n", gated_flop_count, use_disabled_threshold ? "disabled threshold" : "net size"); + const char *mode = use_ff_size_threshold ? "FF width threshold" + : use_disabled_threshold ? "disabled threshold" + : "net size"; + + log("Converted %d FFs using %s.\n", gated_flop_count, mode); } } ClockgatePass;