Merge pull request #170 from Silimate/ffnormpol

ffnormpol pass
This commit is contained in:
Akash Levy 2026-05-27 01:05:05 -07:00 committed by GitHub
commit 7ea578a212
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 252 additions and 0 deletions

View File

@ -11,6 +11,7 @@ OBJS += passes/silimate/obs_clean.o
OBJS += passes/silimate/segv.o
OBJS += passes/silimate/reg_rename.o
OBJS += passes/silimate/infer_ce.o
OBJS += passes/silimate/ffnormpol.o
OBJS += passes/silimate/report_fanout.o
OBJS += passes/silimate/splitfanout.o
OBJS += passes/silimate/splitlarge.o

View File

@ -0,0 +1,135 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2026 Silimate Inc.
*
* 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"
#include "kernel/sigtools.h"
#include "kernel/ff.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct FfNormPolPass : public Pass {
FfNormPolPass() : Pass("ffnormpol", "normalize FF/latch control polarities to positive") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" ffnormpol [selection]\n");
log("\n");
log("This pass normalizes built-in FF and latch control polarities to\n");
log("positive polarity. Negative-edge clocks and active-low enables,\n");
log("resets, sets, clears, and latch enables are rewritten by inserting\n");
log("inverters on the corresponding control signals and re-emitting the\n");
log("cell with positive polarity.\n");
log("\n");
log("Both coarse-grain cells with polarity parameters and fine-grain cells\n");
log("with polarity encoded in the cell type are handled through FfData.\n");
log("\n");
}
struct Worker {
Module *module;
SigMap sigmap;
FfInitVals initvals;
dict<SigSpec, SigSpec> inverted_signals;
int normalized_cells = 0;
int normalized_controls = 0;
Worker(Module *module) : module(module), sigmap(module), initvals(&sigmap, module) { }
SigSpec invert(SigSpec sig, const char *suffix, const std::string &src)
{
sig = sigmap(sig);
if (inverted_signals.count(sig))
return inverted_signals.at(sig);
SigSpec inv = module->Not(NEW_ID_SUFFIX(suffix), sig, false, src);
inverted_signals[sig] = inv;
return inv;
}
bool normalize(FfData &ff, SigSpec &sig, bool &pol, const char *suffix)
{
if (pol)
return false;
sig = invert(sig, suffix, ff.attributes[ID::src].decode_string());
pol = true;
normalized_controls++;
return true;
}
void run()
{
std::vector<Cell *> cells;
for (auto cell : module->selected_cells())
if (cell->is_builtin_ff())
cells.push_back(cell);
for (auto cell : cells) {
FfData ff(&initvals, cell);
bool changed = false;
if (ff.has_clk)
changed |= normalize(ff, ff.sig_clk, ff.pol_clk, "ffnormpol_clk");
if (ff.has_ce)
changed |= normalize(ff, ff.sig_ce, ff.pol_ce, "ffnormpol_ce");
if (ff.has_aload)
changed |= normalize(ff, ff.sig_aload, ff.pol_aload, "ffnormpol_aload");
if (ff.has_arst)
changed |= normalize(ff, ff.sig_arst, ff.pol_arst, "ffnormpol_arst");
if (ff.has_srst)
changed |= normalize(ff, ff.sig_srst, ff.pol_srst, "ffnormpol_srst");
if (ff.has_sr) {
changed |= normalize(ff, ff.sig_clr, ff.pol_clr, "ffnormpol_clr");
changed |= normalize(ff, ff.sig_set, ff.pol_set, "ffnormpol_set");
}
if (changed) {
ff.emit();
normalized_cells++;
}
}
}
};
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing FFNORMPOL pass (normalize FF/latch control polarities).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
break;
extra_args(args, argidx, design);
int total_cells = 0;
int total_controls = 0;
for (auto module : design->selected_modules()) {
Worker worker(module);
worker.run();
total_cells += worker.normalized_cells;
total_controls += worker.normalized_controls;
}
log("Normalized %d controls on %d FF/latch cells.\n", total_controls, total_cells);
}
} FfNormPolPass;
PRIVATE_NAMESPACE_END

116
tests/silimate/ffnormpol.ys Normal file
View File

@ -0,0 +1,116 @@
log -header "Normalize coarse and fine FF/latch polarities"
log -push
design -reset
read_rtlil <<EOT
module \top
wire input 1 \clk
wire input 2 \en
wire input 3 \arst
wire input 4 \srst
wire input 5 \aload
wire width 2 input 6 \set
wire width 2 input 7 \clr
wire width 2 input 8 \d
wire width 2 input 9 \ad
wire width 2 output 10 \q_dffe
wire width 2 output 11 \q_adffe
wire width 2 output 12 \q_sdffce
wire width 2 output 13 \q_aldffe
wire width 2 output 14 \q_dlatchsr
wire width 2 output 15 \q_sr
wire output 16 \q_fine
cell $dffe \dffe_neg
parameter \CLK_POLARITY 1'0
parameter \EN_POLARITY 1'0
parameter \WIDTH 2
connect \CLK \clk
connect \EN \en
connect \D \d
connect \Q \q_dffe
end
cell $adffe \adffe_neg
parameter \CLK_POLARITY 1'0
parameter \EN_POLARITY 1'0
parameter \ARST_POLARITY 1'0
parameter \ARST_VALUE 2'01
parameter \WIDTH 2
connect \CLK \clk
connect \EN \en
connect \ARST \arst
connect \D \d
connect \Q \q_adffe
end
cell $sdffce \sdffce_neg
parameter \CLK_POLARITY 1'0
parameter \EN_POLARITY 1'0
parameter \SRST_POLARITY 1'0
parameter \SRST_VALUE 2'10
parameter \WIDTH 2
connect \CLK \clk
connect \EN \en
connect \SRST \srst
connect \D \d
connect \Q \q_sdffce
end
cell $aldffe \aldffe_neg
parameter \CLK_POLARITY 1'0
parameter \EN_POLARITY 1'0
parameter \ALOAD_POLARITY 1'0
parameter \WIDTH 2
connect \CLK \clk
connect \EN \en
connect \ALOAD \aload
connect \D \d
connect \AD \ad
connect \Q \q_aldffe
end
cell $dlatchsr \dlatchsr_neg
parameter \EN_POLARITY 1'0
parameter \SET_POLARITY 1'0
parameter \CLR_POLARITY 1'0
parameter \WIDTH 2
connect \EN \aload
connect \SET \set
connect \CLR \clr
connect \D \d
connect \Q \q_dlatchsr
end
cell $sr \sr_neg
parameter \SET_POLARITY 1'0
parameter \CLR_POLARITY 1'0
parameter \WIDTH 2
connect \SET \set
connect \CLR \clr
connect \Q \q_sr
end
cell $_DFFE_NN_ \fine_dffe_neg
connect \C \clk
connect \E \en
connect \D \d [0]
connect \Q \q_fine
end
end
EOT
ffnormpol
check -assert
select -assert-count 0 r:CLK_POLARITY=0
select -assert-count 0 r:EN_POLARITY=0
select -assert-count 0 r:ARST_POLARITY=0
select -assert-count 0 r:SRST_POLARITY=0
select -assert-count 0 r:ALOAD_POLARITY=0
select -assert-count 0 r:SET_POLARITY=0
select -assert-count 0 r:CLR_POLARITY=0
select -assert-count 1 t:$_DFFE_PP_
select -assert-count 7 t:$not
design -reset
log -pop