mirror of https://github.com/YosysHQ/yosys.git
abstract: -state allow partial abstraction, don't use buffer-normalized mode
This commit is contained in:
parent
6027030215
commit
387d0de383
|
@ -5,10 +5,82 @@
|
|||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
bool abstract_state(Module* mod, Cell* cell, Wire* enable, bool enable_pol) {
|
||||
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 = 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++;
|
||||
}
|
||||
}
|
||||
SigSpec mux_a, mux_b;
|
||||
if (enable.pol) {
|
||||
mux_a = mux_input;
|
||||
mux_b = anyseq;
|
||||
} else {
|
||||
mux_a = anyseq;
|
||||
mux_b = mux_input;
|
||||
}
|
||||
(void)ff.module->addMux(NEW_ID,
|
||||
mux_a,
|
||||
mux_b,
|
||||
enable.wire,
|
||||
abstracted);
|
||||
(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();
|
||||
|
@ -16,45 +88,11 @@ bool abstract_state(Module* mod, Cell* cell, Wire* enable, bool enable_pol) {
|
|||
if (ff.has_arst)
|
||||
ff.arst_to_aload();
|
||||
|
||||
// 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;
|
||||
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);
|
||||
}
|
||||
(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;
|
||||
mux_b = anyseq;
|
||||
} else {
|
||||
mux_a = anyseq;
|
||||
mux_b = ff.sig_d;
|
||||
}
|
||||
(void)mod->addMux(NEW_ID,
|
||||
mux_a,
|
||||
mux_b,
|
||||
enable,
|
||||
abstracted_d);
|
||||
ff.sig_d = abstracted_d;
|
||||
(void)ff.emit();
|
||||
return true;
|
||||
return changed;
|
||||
}
|
||||
|
||||
struct AbstractPortCtx {
|
||||
|
@ -75,7 +113,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;
|
||||
|
@ -89,7 +127,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) {
|
||||
mux_a = original;
|
||||
mux_b = anyseq;
|
||||
} else {
|
||||
|
@ -99,7 +137,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++;
|
||||
}
|
||||
|
@ -174,25 +212,24 @@ struct AbstractPass : public Pass {
|
|||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
if (mode != State)
|
||||
design->bufNormalize(true);
|
||||
|
||||
unsigned int changed = 0;
|
||||
if ((mode == State) || (mode == Value)) {
|
||||
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)
|
||||
|
@ -207,6 +244,7 @@ struct AbstractPass : public Pass {
|
|||
} else {
|
||||
log_cmd_error("No mode selected, see help message\n");
|
||||
}
|
||||
if (mode != State)
|
||||
design->bufNormalize(false);
|
||||
}
|
||||
} AbstractPass;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue