mirror of https://github.com/YosysHQ/yosys.git
abstract: -value MVP, use buffer-normalized mode
This commit is contained in:
parent
4637fa74e3
commit
6027030215
|
@ -57,70 +57,70 @@ bool abstract_state(Module* mod, Cell* cell, Wire* enable, bool enable_pol) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool abstract_value(Module* mod, Wire* wire, Wire* enable, bool enable_pol) {
|
struct AbstractPortCtx {
|
||||||
// (void)mod->addMux(NEW_ID,
|
|
||||||
// mux_a,
|
|
||||||
// mux_b,
|
|
||||||
// enable,
|
|
||||||
// abstracted);
|
|
||||||
// cell->setPort(ID::D, SigSpec(abstracted));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AbstractInitCtx {
|
|
||||||
Module* mod;
|
Module* mod;
|
||||||
SigMap sigmap;
|
SigMap sigmap;
|
||||||
pool<SigBit> init_bits;
|
pool<std::pair<Cell*, IdString>> outs;
|
||||||
};
|
};
|
||||||
|
|
||||||
void collect_init_bits_cells(AbstractInitCtx& ctx) {
|
void collect_selected_ports(AbstractPortCtx& ctx) {
|
||||||
// TODO Should this discriminate between FFs and other cells?
|
for (Cell* cell : ctx.mod->cells()) {
|
||||||
for (auto cell : ctx.mod->selected_cells()) {
|
for (auto& conn : cell->connections()) {
|
||||||
// Add all sigbits on all cell outputs to init_bits
|
// we bufnorm
|
||||||
for (auto &conn : cell->connections()) {
|
log_assert(conn.second.is_wire() || conn.second.is_fully_const());
|
||||||
if (cell->output(conn.first)) {
|
if (conn.second.is_wire() && cell->output(conn.first))
|
||||||
for (auto bit : conn.second) {
|
if (ctx.mod->selected(cell) || ctx.mod->selected(conn.second.as_wire()))
|
||||||
log_debug("init: cell %s output %s\n", cell->name.c_str(), log_signal(bit));
|
ctx.outs.insert(std::make_pair(cell, conn.first));
|
||||||
ctx.init_bits.insert(ctx.sigmap(bit));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_init_bits_wires(AbstractInitCtx& ctx) {
|
unsigned int abstract_value(Module* mod, Wire* enable, bool enable_pol) {
|
||||||
for (auto wire : ctx.mod->selected_wires()) {
|
AbstractPortCtx ctx {mod, SigMap(mod), {}};
|
||||||
auto canonical = ctx.sigmap(wire);
|
collect_selected_ports(ctx);
|
||||||
// Find canonical drivers of all the wire bits and add them to init_bits
|
unsigned int changed = 0;
|
||||||
for (auto bit : canonical.bits()) {
|
for (auto [cell, port] : ctx.outs) {
|
||||||
log_debug("init: wire %s bit %s\n", wire->name.c_str(), log_signal(bit));
|
SigSpec sig = cell->getPort(port);
|
||||||
ctx.init_bits.insert(ctx.sigmap(bit));
|
log_assert(sig.is_wire());
|
||||||
|
Wire* original = mod->addWire(NEW_ID, sig.size());
|
||||||
|
cell->setPort(port, original);
|
||||||
|
auto anyseq = mod->Anyseq(NEW_ID, sig.size());
|
||||||
|
// This code differs from abstract_state
|
||||||
|
// in that we reuse the original signal as the mux output,
|
||||||
|
// not input
|
||||||
|
SigSpec mux_a, mux_b;
|
||||||
|
if (enable_pol) {
|
||||||
|
mux_a = original;
|
||||||
|
mux_b = anyseq;
|
||||||
|
} else {
|
||||||
|
mux_a = anyseq;
|
||||||
|
mux_b = original;
|
||||||
}
|
}
|
||||||
|
(void)mod->addMux(NEW_ID,
|
||||||
|
mux_a,
|
||||||
|
mux_b,
|
||||||
|
enable,
|
||||||
|
sig);
|
||||||
|
changed++;
|
||||||
}
|
}
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int abstract_init(Module* mod) {
|
unsigned int abstract_init(Module* mod) {
|
||||||
AbstractInitCtx ctx {mod, SigMap(mod), pool<SigBit>()};
|
AbstractPortCtx ctx {mod, SigMap(mod), {}};
|
||||||
pool<SigBit> init_bits;
|
collect_selected_ports(ctx);
|
||||||
collect_init_bits_cells(ctx);
|
|
||||||
collect_init_bits_wires(ctx);
|
|
||||||
unsigned int changed = 0;
|
unsigned int changed = 0;
|
||||||
|
|
||||||
for (SigBit bit : ctx.init_bits) {
|
for (auto [cell, port] : ctx.outs) {
|
||||||
next_sigbit:
|
SigSpec sig = cell->getPort(port);
|
||||||
if (!bit.is_wire() || !bit.wire->has_attribute(ID::init))
|
log_assert(sig.is_wire());
|
||||||
|
if (!sig.as_wire()->has_attribute(ID::init))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Const init = bit.wire->attributes.at(ID::init);
|
Const init = sig.as_wire()->attributes.at(ID::init);
|
||||||
std::vector<RTLIL::State>& bits = init.bits();
|
sig.as_wire()->attributes.erase(ID::init);
|
||||||
bits[bit.offset] = RTLIL::State::Sx;
|
changed += sig.size();
|
||||||
changed++;
|
|
||||||
|
|
||||||
for (auto bit : bits)
|
|
||||||
if (bit != RTLIL::State::Sx)
|
|
||||||
goto next_sigbit;
|
|
||||||
// All bits are Sx, erase init attribute entirely
|
|
||||||
bit.wire->attributes.erase(ID::init);
|
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
@ -174,6 +174,7 @@ struct AbstractPass : public Pass {
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
|
design->bufNormalize(true);
|
||||||
unsigned int changed = 0;
|
unsigned int changed = 0;
|
||||||
if ((mode == State) || (mode == Value)) {
|
if ((mode == State) || (mode == Value)) {
|
||||||
if (!enable_name.length())
|
if (!enable_name.length())
|
||||||
|
@ -191,14 +192,13 @@ struct AbstractPass : public Pass {
|
||||||
if (ct.cell_types.count(cell->type))
|
if (ct.cell_types.count(cell->type))
|
||||||
changed += abstract_state(mod, cell, enable_wire, enable_pol);
|
changed += abstract_state(mod, cell, enable_wire, enable_pol);
|
||||||
} else {
|
} else {
|
||||||
// Value
|
changed += abstract_value(mod, enable_wire, enable_pol);
|
||||||
for (auto wire : mod->selected_wires()) {
|
|
||||||
changed += abstract_value(mod, wire, enable_wire, enable_pol);
|
|
||||||
}
|
|
||||||
log_cmd_error("Unsupported (TODO)\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log("Abstracted %d cells.\n", changed);
|
if (mode == State)
|
||||||
|
log("Abstracted %d cells.\n", changed);
|
||||||
|
else
|
||||||
|
log("Abstracted %d values.\n", changed);
|
||||||
} else if (mode == Initial) {
|
} else if (mode == Initial) {
|
||||||
for (auto mod : design->selected_modules()) {
|
for (auto mod : design->selected_modules()) {
|
||||||
changed += abstract_init(mod);
|
changed += abstract_init(mod);
|
||||||
|
@ -207,6 +207,7 @@ struct AbstractPass : public Pass {
|
||||||
} else {
|
} else {
|
||||||
log_cmd_error("No mode selected, see help message\n");
|
log_cmd_error("No mode selected, see help message\n");
|
||||||
}
|
}
|
||||||
|
design->bufNormalize(false);
|
||||||
}
|
}
|
||||||
} AbstractPass;
|
} AbstractPass;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
read_verilog <<EOT
|
read_verilog <<EOT
|
||||||
|
|
||||||
module half_clock (CLK, Q);
|
module half_clock (CLK, Q, magic);
|
||||||
input CLK;
|
input CLK;
|
||||||
output reg Q;
|
output reg Q;
|
||||||
reg magic;
|
input magic;
|
||||||
always @(posedge CLK)
|
always @(posedge CLK)
|
||||||
Q <= ~Q;
|
Q <= ~Q;
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -12,16 +12,16 @@ EOT
|
||||||
proc
|
proc
|
||||||
# show -prefix before_base
|
# show -prefix before_base
|
||||||
abstract -state -enablen magic
|
abstract -state -enablen magic
|
||||||
check
|
check -assert
|
||||||
# show -prefix after_base
|
# show -prefix after_base
|
||||||
|
|
||||||
design -reset
|
design -reset
|
||||||
read_verilog <<EOT
|
read_verilog <<EOT
|
||||||
module half_clock_en (CLK, E, Q);
|
module half_clock_en (CLK, E, Q, magic);
|
||||||
input CLK;
|
input CLK;
|
||||||
input E;
|
input E;
|
||||||
output reg Q;
|
output reg Q;
|
||||||
reg magic;
|
input magic;
|
||||||
always @(posedge CLK)
|
always @(posedge CLK)
|
||||||
if (E)
|
if (E)
|
||||||
Q <= ~Q;
|
Q <= ~Q;
|
||||||
|
@ -33,7 +33,7 @@ opt_expr
|
||||||
opt_dff
|
opt_dff
|
||||||
# show -prefix before_en
|
# show -prefix before_en
|
||||||
abstract -state -enablen magic
|
abstract -state -enablen magic
|
||||||
check
|
check -assert
|
||||||
# show -prefix after_en
|
# show -prefix after_en
|
||||||
|
|
||||||
design -reset
|
design -reset
|
||||||
|
@ -50,9 +50,35 @@ proc
|
||||||
opt_expr
|
opt_expr
|
||||||
opt_dff
|
opt_dff
|
||||||
dump
|
dump
|
||||||
|
select -none
|
||||||
abstract -init
|
abstract -init
|
||||||
check
|
select -clear
|
||||||
|
check -assert
|
||||||
|
# dump
|
||||||
|
|
||||||
|
design -reset
|
||||||
|
read_verilog <<EOT
|
||||||
|
module main (input [3:0] baz);
|
||||||
|
reg foo;
|
||||||
|
reg bar;
|
||||||
|
assign foo = bar;
|
||||||
|
assign bar = baz[0];
|
||||||
|
reg aaa = 1'b1;
|
||||||
|
always @(posedge bar)
|
||||||
|
aaa <= ~aaa;
|
||||||
|
endmodule
|
||||||
|
EOT
|
||||||
|
|
||||||
|
proc -noopt
|
||||||
|
# show -prefix before_init
|
||||||
dump
|
dump
|
||||||
|
select -none
|
||||||
|
abstract -init
|
||||||
|
select -clear
|
||||||
|
# show -prefix after_init
|
||||||
|
dump
|
||||||
|
check -assert
|
||||||
|
# dump
|
||||||
|
|
||||||
|
|
||||||
design -reset
|
design -reset
|
||||||
|
@ -85,6 +111,38 @@ opt_expr
|
||||||
opt_dff
|
opt_dff
|
||||||
# show -prefix before_a
|
# show -prefix before_a
|
||||||
abstract -state -enablen magic
|
abstract -state -enablen magic
|
||||||
check
|
check -assert
|
||||||
# show -prefix after_a
|
# show -prefix after_a
|
||||||
# opt_clean
|
# opt_clean
|
||||||
|
|
||||||
|
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
|
||||||
|
# show -prefix before_value
|
||||||
|
abstract -value -enablen magic
|
||||||
|
check -assert
|
||||||
|
clean
|
||||||
|
# show -prefix after_value
|
||||||
|
# dump
|
||||||
|
|
Loading…
Reference in New Issue