mirror of https://github.com/YosysHQ/yosys.git
abstract: -state MVP
This commit is contained in:
parent
f445479374
commit
e4ca7b8846
|
@ -53,3 +53,4 @@ OBJS += passes/cmds/example_dt.o
|
|||
OBJS += passes/cmds/portarcs.o
|
||||
OBJS += passes/cmds/wrapcell.o
|
||||
OBJS += passes/cmds/setenv.o
|
||||
OBJS += passes/cmds/abstract.o
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
#include "kernel/yosys.h"
|
||||
#include "kernel/celltypes.h"
|
||||
#include "kernel/ff.h"
|
||||
|
||||
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();
|
||||
|
||||
// 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;
|
||||
}
|
||||
(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;
|
||||
}
|
||||
|
||||
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;
|
||||
ct.setup_internals_ff();
|
||||
if (!ct.cell_types.count(cell->type))
|
||||
return false;
|
||||
// TODO figure out memory cells?
|
||||
|
||||
cell->unsetParam(ID::init);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
struct AbstractPass : public Pass {
|
||||
AbstractPass() : Pass("abstract", "extract clock gating out of flip flops") { }
|
||||
void help() override {
|
||||
// TODO
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) override {
|
||||
log_header(design, "Executing ABSTRACT pass.\n");
|
||||
|
||||
size_t argidx;
|
||||
enum Mode {
|
||||
None,
|
||||
State,
|
||||
Initial,
|
||||
Value,
|
||||
};
|
||||
Mode mode;
|
||||
std::string enable_name;
|
||||
bool enable_pol; // true is high
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
std::string arg = args[argidx];
|
||||
if (arg == "-state") {
|
||||
mode = State;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-init") {
|
||||
mode = Initial;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-value") {
|
||||
mode = Value;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-enable") {
|
||||
enable_name = args[++argidx];
|
||||
enable_pol = true;
|
||||
continue;
|
||||
}
|
||||
if (arg == "-enablen") {
|
||||
enable_name = args[++argidx];
|
||||
enable_pol = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
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);
|
||||
} else {
|
||||
// Value
|
||||
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);
|
||||
} else if (mode == Initial) {
|
||||
for (auto mod : design->selected_modules()) {
|
||||
for (auto cell : mod->selected_cells()) {
|
||||
changed += abstract_init(mod, cell);
|
||||
}
|
||||
}
|
||||
log("Abstracted %d wires.\n", changed);
|
||||
} else {
|
||||
log_cmd_error("No mode selected, see help message\n");
|
||||
}
|
||||
}
|
||||
} AbstractPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
|
@ -0,0 +1,97 @@
|
|||
read_verilog <<EOT
|
||||
|
||||
module half_clock (CLK, Q);
|
||||
input CLK;
|
||||
output reg Q;
|
||||
reg magic;
|
||||
always @(posedge CLK)
|
||||
Q <= ~Q;
|
||||
endmodule
|
||||
|
||||
EOT
|
||||
proc
|
||||
# dump
|
||||
# show -prefix before_base
|
||||
abstract -state -enablen magic
|
||||
check
|
||||
# show -prefix after_base
|
||||
# dump
|
||||
|
||||
design -reset
|
||||
read_verilog <<EOT
|
||||
module half_clock_en (CLK, E, Q);
|
||||
input CLK;
|
||||
input E;
|
||||
output reg Q;
|
||||
reg magic;
|
||||
always @(posedge CLK)
|
||||
if (E)
|
||||
Q <= ~Q;
|
||||
endmodule
|
||||
EOT
|
||||
|
||||
proc
|
||||
opt_expr
|
||||
opt_dff
|
||||
# show
|
||||
# dump
|
||||
# show -prefix before_en
|
||||
abstract -state -enablen magic
|
||||
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
|
||||
# show
|
Loading…
Reference in New Issue