mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-04 13:21:23 +00:00
fixup! abstract: -state MVP
This commit is contained in:
parent
083759676a
commit
6e99dbd351
2 changed files with 142 additions and 32 deletions
|
@ -6,35 +6,79 @@ USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
bool abstract_state(Module* mod, Cell* cell, Wire* enable, bool enable_pol) {
|
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();
|
||||||
|
|
||||||
|
// Construct abstract value
|
||||||
|
auto anyseq = mod->Anyseq(NEW_ID, ff.width);
|
||||||
|
|
||||||
|
if (ff.has_aload) {
|
||||||
|
// aload := enable ? anyseq : aload
|
||||||
|
// ff.pol_aload = enable_pol;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
(void)mod->addMux(NEW_ID,
|
||||||
|
mux_a,
|
||||||
|
mux_b,
|
||||||
|
enable,
|
||||||
|
abstracted_ad);
|
||||||
|
ff.sig_ad = abstracted_ad;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool abstract_value(Module* mod, Wire* wire, Wire* enable, bool enable_pol) {
|
||||||
|
// (void)mod->addMux(NEW_ID,
|
||||||
|
// mux_a,
|
||||||
|
// mux_b,
|
||||||
|
// enable,
|
||||||
|
// abstracted);
|
||||||
|
// cell->setPort(ID::D, SigSpec(abstracted));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool abstract_init(Module* mod, Cell* cell) {
|
||||||
CellTypes ct;
|
CellTypes ct;
|
||||||
ct.setup_internals_ff();
|
ct.setup_internals_ff();
|
||||||
if (!ct.cell_types.count(cell->type))
|
if (!ct.cell_types.count(cell->type))
|
||||||
return false;
|
return false;
|
||||||
FfData ff(nullptr, cell);
|
// TODO figure out memory cells?
|
||||||
// Doesn't matter if there was an enable signal already
|
|
||||||
// we discard it and mux with symbolic value
|
|
||||||
ff.has_ce = false;
|
|
||||||
Wire* inp = cell->getPort(ID::D).as_wire();
|
|
||||||
cell = ff.emit();
|
|
||||||
|
|
||||||
Wire* abstracted = mod->addWire(NEW_ID, inp->width);
|
cell->unsetParam(ID::init);
|
||||||
SigSpec mux_a, mux_b;
|
|
||||||
if (enable_pol) {
|
|
||||||
mux_a = inp;
|
|
||||||
mux_b = mod->Anyseq(NEW_ID, inp->width);
|
|
||||||
} else {
|
|
||||||
mux_a = mod->Anyseq(NEW_ID, inp->width);
|
|
||||||
mux_b = inp;
|
|
||||||
}
|
|
||||||
(void)mod->addMux(NEW_ID,
|
|
||||||
mux_a,
|
|
||||||
mux_b,
|
|
||||||
enable,
|
|
||||||
abstracted);
|
|
||||||
cell->setPort(ID::D, SigSpec(abstracted));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct AbstractPass : public Pass {
|
struct AbstractPass : public Pass {
|
||||||
AbstractPass() : Pass("abstract", "extract clock gating out of flip flops") { }
|
AbstractPass() : Pass("abstract", "extract clock gating out of flip flops") { }
|
||||||
void help() override {
|
void help() override {
|
||||||
|
@ -84,31 +128,41 @@ struct AbstractPass : public Pass {
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
unsigned int changed_cells = 0;
|
unsigned int changed = 0;
|
||||||
if ((mode == State) || (mode == Value)) {
|
if ((mode == State) || (mode == Value)) {
|
||||||
if (!enable_name.length())
|
if (!enable_name.length())
|
||||||
log_cmd_error("Unspecified enable wire\n");
|
log_cmd_error("Unspecified enable wire\n");
|
||||||
|
CellTypes ct;
|
||||||
|
if (mode == State)
|
||||||
|
ct.setup_internals_ff();
|
||||||
for (auto mod : design->selected_modules()) {
|
for (auto mod : design->selected_modules()) {
|
||||||
log("module %s\n", mod->name.c_str());
|
log_debug("module %s\n", mod->name.c_str());
|
||||||
Wire *enable_wire = mod->wire("\\" + enable_name);
|
Wire *enable_wire = mod->wire("\\" + enable_name);
|
||||||
if (!enable_wire)
|
if (!enable_wire)
|
||||||
log_cmd_error("Enable wire %s not found in module %s\n", enable_name.c_str(), mod->name.c_str());
|
log_cmd_error("Enable wire %s not found in module %s\n", enable_name.c_str(), mod->name.c_str());
|
||||||
if (mode == State) {
|
if (mode == State) {
|
||||||
for (auto cell : mod->selected_cells()) {
|
for (auto cell : mod->selected_cells())
|
||||||
log("cell %s\n", cell->name.c_str());
|
if (ct.cell_types.count(cell->type))
|
||||||
changed_cells += abstract_state(mod, cell, enable_wire, enable_pol);
|
changed += abstract_state(mod, cell, enable_wire, enable_pol);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Value
|
// Value
|
||||||
|
for (auto wire : mod->selected_wires()) {
|
||||||
|
changed += abstract_value(mod, wire, enable_wire, enable_pol);
|
||||||
|
}
|
||||||
log_cmd_error("Unsupported (TODO)\n");
|
log_cmd_error("Unsupported (TODO)\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log("Abstracted %d cells.\n", changed);
|
||||||
} else if (mode == Initial) {
|
} else if (mode == Initial) {
|
||||||
log_cmd_error("Unsupported\n");
|
for (auto mod : design->selected_modules()) {
|
||||||
|
for (auto cell : mod->selected_cells()) {
|
||||||
|
changed += abstract_init(mod, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log("Abstracted %d wires.\n", changed);
|
||||||
} else {
|
} else {
|
||||||
log_cmd_error("No mode selected, see help message\n");
|
log_cmd_error("No mode selected, see help message\n");
|
||||||
}
|
}
|
||||||
log("Abstracted %d cell(s).\n", changed_cells);
|
|
||||||
}
|
}
|
||||||
} AbstractPass;
|
} AbstractPass;
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,14 @@ endmodule
|
||||||
EOT
|
EOT
|
||||||
proc
|
proc
|
||||||
# dump
|
# dump
|
||||||
|
# show -prefix before_base
|
||||||
abstract -state -enablen magic
|
abstract -state -enablen magic
|
||||||
check
|
check
|
||||||
|
# show -prefix after_base
|
||||||
# dump
|
# dump
|
||||||
|
|
||||||
design -reset
|
design -reset
|
||||||
|
|
||||||
read_verilog <<EOT
|
read_verilog <<EOT
|
||||||
|
|
||||||
module half_clock_en (CLK, E, Q);
|
module half_clock_en (CLK, E, Q);
|
||||||
input CLK;
|
input CLK;
|
||||||
input E;
|
input E;
|
||||||
|
@ -28,14 +28,70 @@ module half_clock_en (CLK, E, Q);
|
||||||
if (E)
|
if (E)
|
||||||
Q <= ~Q;
|
Q <= ~Q;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
proc
|
proc
|
||||||
opt_expr
|
opt_expr
|
||||||
opt_dff
|
opt_dff
|
||||||
# show
|
# show
|
||||||
# dump
|
# dump
|
||||||
|
# show -prefix before_en
|
||||||
abstract -state -enablen magic
|
abstract -state -enablen magic
|
||||||
check
|
check
|
||||||
|
# show -prefix after_en
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog <<EOT
|
||||||
|
module half_clock (CLK, Q);
|
||||||
|
input CLK;
|
||||||
|
output reg Q = 1'b1;
|
||||||
|
always @(posedge CLK)
|
||||||
|
Q <= ~Q;
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
|
||||||
|
proc
|
||||||
|
opt_expr
|
||||||
|
opt_dff
|
||||||
|
dump
|
||||||
|
abstract -init
|
||||||
|
check
|
||||||
|
dump
|
||||||
|
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog <<EOT
|
||||||
|
module this_adff (CLK, ARST, D, Q, magic);
|
||||||
|
|
||||||
|
parameter WIDTH = 2;
|
||||||
|
parameter CLK_POLARITY = 1'b1;
|
||||||
|
parameter ARST_POLARITY = 1'b1;
|
||||||
|
parameter ARST_VALUE = 0;
|
||||||
|
|
||||||
|
input CLK, ARST, magic;
|
||||||
|
input [WIDTH-1:0] D;
|
||||||
|
output reg [WIDTH-1:0] Q;
|
||||||
|
wire pos_clk = CLK == CLK_POLARITY;
|
||||||
|
wire pos_arst = ARST == ARST_POLARITY;
|
||||||
|
|
||||||
|
always @(posedge pos_clk, posedge pos_arst) begin
|
||||||
|
if (pos_arst)
|
||||||
|
Q <= ARST_VALUE;
|
||||||
|
else
|
||||||
|
Q <= D;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
|
||||||
|
proc
|
||||||
|
opt_expr
|
||||||
|
opt_dff
|
||||||
|
# show
|
||||||
|
# dump
|
||||||
|
show -prefix before_a
|
||||||
|
abstract -state -enablen magic
|
||||||
|
check
|
||||||
|
show -prefix after_a
|
||||||
# opt_clean
|
# opt_clean
|
||||||
# show
|
# show
|
Loading…
Add table
Add a link
Reference in a new issue