Skip to content

Commit

Permalink
abstract: -state allow partial abstraction, don't use buffer-normaliz…
Browse files Browse the repository at this point in the history
…ed mode
  • Loading branch information
widlarizer committed Feb 7, 2025
1 parent eb8982a commit 9af21e6
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 49 deletions.
137 changes: 88 additions & 49 deletions passes/cmds/abstract.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,97 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

bool abstract_state(Module* mod, Cell* cell, Wire* enable, bool enable_pol) {
FfData ff(nullptr, cell);
if (ff.has_sr)
log_cmd_error("SR not supported\n");

// Normalize to simpler FF
ff.unmap_ce();
ff.unmap_srst();
if (ff.has_arst)
ff.arst_to_aload();
struct EnableLogic {
Wire* wire;
bool pol;
};

bool abstract_state_port(FfData& ff, SigSpec& port_sig, std::set<int> offsets, EnableLogic enable) {
// Construct abstract value
auto anyseq = mod->Anyseq(NEW_ID, ff.width);

if (ff.has_aload) {
// ad := enable ? anyseq : ad
Wire* abstracted_ad = mod->addWire(NEW_ID, ff.sig_ad.size());
SigSpec mux_a, mux_b;
if (enable_pol) {
mux_a = ff.sig_ad;
mux_b = anyseq;
} else {
mux_a = anyseq;
mux_b = ff.sig_ad;
auto anyseq = ff.module->Anyseq(NEW_ID, offsets.size());
Wire* abstracted = ff.module->addWire(NEW_ID, offsets.size());
SigSpec mux_input;
int abstracted_idx = 0;
for (int d_idx = 0; d_idx < ff.width; d_idx++) {
if (offsets.count(d_idx)) {
log_debug("bit %d: abstracted\n", d_idx);
mux_input.append(port_sig[d_idx]);
port_sig[d_idx].wire = abstracted;
port_sig[d_idx].offset = abstracted_idx;
log_assert(abstracted_idx < abstracted->width);
abstracted_idx++;
}
(void)mod->addMux(NEW_ID,
mux_a,
mux_b,
enable,
abstracted_ad);
ff.sig_ad = abstracted_ad;
}
// d := enable ? anyseq : d
Wire* abstracted_d = mod->addWire(NEW_ID, ff.sig_d.size());
SigSpec mux_a, mux_b;
if (enable_pol) {
mux_a = ff.sig_d;
if (enable.pol) {
mux_a = mux_input;
mux_b = anyseq;
} else {
mux_a = anyseq;
mux_b = ff.sig_d;
mux_b = mux_input;
}
(void)mod->addMux(NEW_ID,
Cell* mux = ff.module->addMux(NEW_ID,

Check warning on line 37 in passes/cmds/abstract.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, clang-10)

unused variable 'mux' [-Wunused-variable]

Check warning on line 37 in passes/cmds/abstract.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, gcc-10)

unused variable ‘mux’ [-Wunused-variable]

Check warning on line 37 in passes/cmds/abstract.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, clang-19)

unused variable 'mux' [-Wunused-variable]

Check warning on line 37 in passes/cmds/abstract.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, gcc-13)

unused variable ‘mux’ [-Wunused-variable]

Check warning on line 37 in passes/cmds/abstract.cc

View workflow job for this annotation

GitHub Actions / test-compile (macos-13, clang)

unused variable 'mux' [-Wunused-variable]
mux_a,
mux_b,
enable,
abstracted_d);
ff.sig_d = abstracted_d;
enable.wire,
abstracted);
// log_cell(mux);
(void)ff.emit();
return true;
}

unsigned int abstract_state(Module* mod, EnableLogic enable) {
CellTypes ct;
ct.setup_internals_ff();
SigMap sigmap(mod);
pool<SigBit> selected_representatives;

// Collect reps for all wire bits of selected wires
for (auto wire : mod->selected_wires())
for (auto bit : sigmap(wire))
selected_representatives.insert(bit);

// Collect reps for all output wire bits of selected cells
for (auto cell : mod->selected_cells())
for (auto conn : cell->connections())
if (cell->output(conn.first))
for (auto bit : conn.second.bits())
selected_representatives.insert(sigmap(bit));

unsigned int changed = 0;
std::vector<FfData> ffs;
// Abstract flop inputs if they're driving a selected output rep
for (auto cell : mod->cells()) {
if (!ct.cell_types.count(cell->type))
continue;
FfData ff(nullptr, cell);
if (ff.has_sr)
log_cmd_error("SR not supported\n");
ffs.push_back(ff);
}
for (auto ff : ffs) {
// A bit inefficient
std::set<int> offsets_to_abstract;
for (auto bit : ff.sig_q)
if (selected_representatives.count(sigmap(bit)))
offsets_to_abstract.insert(bit.offset);

if (offsets_to_abstract.empty())
continue;

// Normalize to simpler FF
ff.unmap_ce();
ff.unmap_srst();
if (ff.has_arst)
ff.arst_to_aload();

if (ff.has_aload)
changed += abstract_state_port(ff, ff.sig_ad, offsets_to_abstract, enable);
changed += abstract_state_port(ff, ff.sig_d, offsets_to_abstract, enable);
}
return changed;
}

struct AbstractPortCtx {
Module* mod;
SigMap sigmap;
Expand All @@ -75,7 +114,7 @@ void collect_selected_ports(AbstractPortCtx& ctx) {
}
}

unsigned int abstract_value(Module* mod, Wire* enable, bool enable_pol) {
unsigned int abstract_value(Module* mod, EnableLogic enable) {
AbstractPortCtx ctx {mod, SigMap(mod), {}};
collect_selected_ports(ctx);
unsigned int changed = 0;
Expand All @@ -89,7 +128,7 @@ unsigned int abstract_value(Module* mod, Wire* enable, bool enable_pol) {
// in that we reuse the original signal as the mux output,
// not input
SigSpec mux_a, mux_b;
if (enable_pol) {
if (enable.pol) {

Check warning on line 131 in passes/cmds/abstract.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, gcc-10)

‘enable_pol’ may be used uninitialized in this function [-Wmaybe-uninitialized]

Check warning on line 131 in passes/cmds/abstract.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, gcc-13)

‘enable_pol’ may be used uninitialized [-Wmaybe-uninitialized]
mux_a = original;
mux_b = anyseq;
} else {
Expand All @@ -99,7 +138,7 @@ unsigned int abstract_value(Module* mod, Wire* enable, bool enable_pol) {
(void)mod->addMux(NEW_ID,
mux_a,
mux_b,
enable,
enable.wire,
sig);
changed++;
}
Expand Down Expand Up @@ -174,25 +213,24 @@ struct AbstractPass : public Pass {
}
extra_args(args, argidx, design);

design->bufNormalize(true);
if (mode != State)

Check warning on line 216 in passes/cmds/abstract.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, gcc-13)

‘mode’ may be used uninitialized [-Wmaybe-uninitialized]
design->bufNormalize(true);

unsigned int changed = 0;
if ((mode == State) || (mode == Value)) {

Check warning on line 220 in passes/cmds/abstract.cc

View workflow job for this annotation

GitHub Actions / test-compile (ubuntu-latest, gcc-10)

‘mode’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if (!enable_name.length())
log_cmd_error("Unspecified enable wire\n");
CellTypes ct;
if (mode == State)
ct.setup_internals_ff();
for (auto mod : design->selected_modules()) {
log_debug("module %s\n", mod->name.c_str());
Wire *enable_wire = mod->wire("\\" + enable_name);
if (!enable_wire)
log_cmd_error("Enable wire %s not found in module %s\n", enable_name.c_str(), mod->name.c_str());
if (mode == State) {
for (auto cell : mod->selected_cells())
if (ct.cell_types.count(cell->type))
changed += abstract_state(mod, cell, enable_wire, enable_pol);
// for (auto cell : mod->selected_cells())
// if (ct.cell_types.count(cell->type))
changed += abstract_state(mod, {enable_wire, enable_pol});
} else {
changed += abstract_value(mod, enable_wire, enable_pol);
changed += abstract_value(mod, {enable_wire, enable_pol});
}
}
if (mode == State)
Expand All @@ -207,7 +245,8 @@ struct AbstractPass : public Pass {
} else {
log_cmd_error("No mode selected, see help message\n");
}
design->bufNormalize(false);
if (mode != State)
design->bufNormalize(false);
}
} AbstractPass;

Expand Down
21 changes: 21 additions & 0 deletions tests/various/abstract.ys
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,27 @@ abstract -state -enablen magic
check -assert
# show -prefix after_base

design -reset
read_verilog <<EOT

module fff (CLK, DDD, QQQ, Q, magic);
input CLK;
input [2:0] DDD;
output reg [2:0] QQQ;
output reg Q;
input magic;
always @(posedge CLK)
QQQ <= DDD;
assign Q = QQQ[0];
endmodule

EOT
proc
# show -prefix before_wide
abstract -state -enablen magic w:Q
# show -prefix after_wide
check -assert

design -reset
read_verilog <<EOT
module half_clock_en (CLK, E, Q, magic);
Expand Down

0 comments on commit 9af21e6

Please sign in to comment.