mirror of https://github.com/YosysHQ/yosys.git
abc9 -keepff -> -dff; refactor dff operations
This commit is contained in:
parent
0e95756e96
commit
8e507bd807
|
@ -82,7 +82,7 @@ struct XAigerWriter
|
||||||
dict<SigBit, SigBit> not_map, alias_map;
|
dict<SigBit, SigBit> not_map, alias_map;
|
||||||
dict<SigBit, pair<SigBit, SigBit>> and_map;
|
dict<SigBit, pair<SigBit, SigBit>> and_map;
|
||||||
vector<SigBit> ci_bits, co_bits;
|
vector<SigBit> ci_bits, co_bits;
|
||||||
dict<SigBit, std::tuple<SigBit,int,int>> ff_bits;
|
dict<SigBit, Cell*> ff_bits;
|
||||||
dict<SigBit, float> arrival_times;
|
dict<SigBit, float> arrival_times;
|
||||||
|
|
||||||
vector<pair<int, int>> aig_gates;
|
vector<pair<int, int>> aig_gates;
|
||||||
|
@ -204,7 +204,6 @@ struct XAigerWriter
|
||||||
dict<SigBit, pool<IdString>> bit_drivers, bit_users;
|
dict<SigBit, pool<IdString>> bit_drivers, bit_users;
|
||||||
TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
|
TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
|
||||||
bool abc9_box_seen = false;
|
bool abc9_box_seen = false;
|
||||||
std::vector<Cell*> flop_boxes;
|
|
||||||
|
|
||||||
for (auto cell : module->selected_cells()) {
|
for (auto cell : module->selected_cells()) {
|
||||||
if (cell->type == "$_NOT_")
|
if (cell->type == "$_NOT_")
|
||||||
|
@ -236,14 +235,17 @@ struct XAigerWriter
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type == "$__ABC9_FF_")
|
if (cell->type == "$__ABC9_FF_" &&
|
||||||
|
// The presence of an abc9_mergeability attribute indicates
|
||||||
|
// that we do want to pass this flop to ABC
|
||||||
|
cell->attributes.count("\\abc9_mergeability"))
|
||||||
{
|
{
|
||||||
SigBit D = sigmap(cell->getPort("\\D").as_bit());
|
SigBit D = sigmap(cell->getPort("\\D").as_bit());
|
||||||
SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
|
SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
|
||||||
unused_bits.erase(D);
|
unused_bits.erase(D);
|
||||||
undriven_bits.erase(Q);
|
undriven_bits.erase(Q);
|
||||||
alias_map[Q] = D;
|
alias_map[Q] = D;
|
||||||
auto r = ff_bits.insert(std::make_pair(D, std::make_tuple(Q, 0, 2)));
|
auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell));
|
||||||
log_assert(r.second);
|
log_assert(r.second);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -252,14 +254,25 @@ struct XAigerWriter
|
||||||
if (inst_module) {
|
if (inst_module) {
|
||||||
bool abc9_box = inst_module->attributes.count("\\abc9_box_id");
|
bool abc9_box = inst_module->attributes.count("\\abc9_box_id");
|
||||||
bool abc9_flop = inst_module->get_bool_attribute("\\abc9_flop");
|
bool abc9_flop = inst_module->get_bool_attribute("\\abc9_flop");
|
||||||
// The lack of an abc9_mergeability attribute indicates that
|
if (abc9_box && cell->get_bool_attribute("\\abc9_keep"))
|
||||||
// we do want to keep this flop, so do not treat it as a box
|
|
||||||
if (abc9_flop && !cell->attributes.count("\\abc9_mergeability"))
|
|
||||||
abc9_box = false;
|
abc9_box = false;
|
||||||
|
|
||||||
for (const auto &conn : cell->connections()) {
|
for (const auto &conn : cell->connections()) {
|
||||||
auto port_wire = inst_module->wire(conn.first);
|
auto port_wire = inst_module->wire(conn.first);
|
||||||
|
|
||||||
|
if (abc9_box) {
|
||||||
|
// Ignore inout for the sake of topographical ordering
|
||||||
|
if (port_wire->port_input && !port_wire->port_output)
|
||||||
|
for (auto bit : sigmap(conn.second))
|
||||||
|
bit_users[bit].insert(cell->name);
|
||||||
|
if (port_wire->port_output)
|
||||||
|
for (auto bit : sigmap(conn.second))
|
||||||
|
bit_drivers[bit].insert(cell->name);
|
||||||
|
|
||||||
|
if (!abc9_flop)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (port_wire->port_output) {
|
if (port_wire->port_output) {
|
||||||
int arrival = 0;
|
int arrival = 0;
|
||||||
auto it = port_wire->attributes.find("\\abc9_arrival");
|
auto it = port_wire->attributes.find("\\abc9_arrival");
|
||||||
|
@ -272,25 +285,11 @@ struct XAigerWriter
|
||||||
for (auto bit : sigmap(conn.second))
|
for (auto bit : sigmap(conn.second))
|
||||||
arrival_times[bit] = arrival;
|
arrival_times[bit] = arrival;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abc9_box) {
|
|
||||||
// Ignore inout for the sake of topographical ordering
|
|
||||||
if (port_wire->port_input && !port_wire->port_output)
|
|
||||||
for (auto bit : sigmap(conn.second))
|
|
||||||
bit_users[bit].insert(cell->name);
|
|
||||||
if (port_wire->port_output)
|
|
||||||
for (auto bit : sigmap(conn.second))
|
|
||||||
bit_drivers[bit].insert(cell->name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abc9_box) {
|
if (abc9_box) {
|
||||||
abc9_box_seen = true;
|
abc9_box_seen = true;
|
||||||
|
|
||||||
toposort.node(cell->name);
|
toposort.node(cell->name);
|
||||||
|
|
||||||
if (abc9_flop)
|
|
||||||
flop_boxes.push_back(cell);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -321,61 +320,6 @@ struct XAigerWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abc9_box_seen) {
|
if (abc9_box_seen) {
|
||||||
dict<IdString, std::pair<IdString,int>> flop_q;
|
|
||||||
for (auto cell : flop_boxes) {
|
|
||||||
auto r = flop_q.insert(std::make_pair(cell->type, std::make_pair(IdString(), 0)));
|
|
||||||
SigBit d;
|
|
||||||
if (r.second) {
|
|
||||||
for (const auto &conn : cell->connections()) {
|
|
||||||
if (!conn.second.is_bit())
|
|
||||||
continue;
|
|
||||||
d = conn.second;
|
|
||||||
if (!ff_bits.count(d))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
r.first->second.first = conn.first;
|
|
||||||
Module *inst_module = module->design->module(cell->type);
|
|
||||||
Wire *wire = inst_module->wire(conn.first);
|
|
||||||
log_assert(wire);
|
|
||||||
auto jt = wire->attributes.find("\\abc9_arrival");
|
|
||||||
if (jt != wire->attributes.end()) {
|
|
||||||
if (jt->second.flags != 0)
|
|
||||||
log_error("Attribute 'abc9_arrival' on port '%s' of module '%s' is not an integer.\n", log_id(wire), log_id(cell->type));
|
|
||||||
r.first->second.second = jt->second.as_int();
|
|
||||||
}
|
|
||||||
log_assert(d == sigmap(d));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
d = cell->getPort(r.first->second.first);
|
|
||||||
|
|
||||||
auto &rhs = ff_bits.at(d);
|
|
||||||
|
|
||||||
auto it = cell->attributes.find(ID(abc9_mergeability));
|
|
||||||
log_assert(it != cell->attributes.end());
|
|
||||||
std::get<1>(rhs) = it->second.as_int();
|
|
||||||
cell->attributes.erase(it);
|
|
||||||
|
|
||||||
it = cell->attributes.find(ID(abc9_init));
|
|
||||||
log_assert(it != cell->attributes.end());
|
|
||||||
log_assert(GetSize(it->second) == 1);
|
|
||||||
if (it->second[0] == State::S1)
|
|
||||||
std::get<2>(rhs) = 1;
|
|
||||||
else if (it->second[0] == State::S0)
|
|
||||||
std::get<2>(rhs) = 0;
|
|
||||||
else {
|
|
||||||
log_assert(it->second[0] == State::Sx);
|
|
||||||
std::get<2>(rhs) = 0;
|
|
||||||
}
|
|
||||||
cell->attributes.erase(it);
|
|
||||||
|
|
||||||
const SigBit &q = std::get<0>(rhs);
|
|
||||||
auto arrival = r.first->second.second;
|
|
||||||
if (arrival)
|
|
||||||
arrival_times[q] = arrival;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &it : bit_users)
|
for (auto &it : bit_users)
|
||||||
if (bit_drivers.count(it.first))
|
if (bit_drivers.count(it.first))
|
||||||
for (auto driver_cell : bit_drivers.at(it.first))
|
for (auto driver_cell : bit_drivers.at(it.first))
|
||||||
|
@ -501,11 +445,11 @@ struct XAigerWriter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect <cell>.$abc9_currQ (inserted by abc9_map.v) as an input to the flop box
|
// Connect <cell>.abc9_ff.Q (inserted by abc9_map.v) as the last input to the flop box
|
||||||
if (box_module->get_bool_attribute("\\abc9_flop")) {
|
if (box_module->get_bool_attribute("\\abc9_flop")) {
|
||||||
SigSpec rhs = module->wire(stringf("%s.$abc9_currQ", cell->name.c_str()));
|
SigSpec rhs = module->wire(stringf("%s.abc9_ff.Q", cell->name.c_str()));
|
||||||
if (rhs.empty())
|
if (rhs.empty())
|
||||||
log_error("'%s.$abc9_currQ' is not a wire present in module '%s'.\n", log_id(cell), log_id(module));
|
log_error("'%s.abc9_ff.Q' is not a wire present in module '%s'.\n", log_id(cell), log_id(module));
|
||||||
|
|
||||||
for (auto b : rhs) {
|
for (auto b : rhs) {
|
||||||
SigBit I = sigmap(b);
|
SigBit I = sigmap(b);
|
||||||
|
@ -553,7 +497,8 @@ struct XAigerWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &i : ff_bits) {
|
for (const auto &i : ff_bits) {
|
||||||
const SigBit &q = std::get<0>(i.second);
|
const Cell *cell = i.second;
|
||||||
|
const SigBit &q = sigmap(cell->getPort("\\Q"));
|
||||||
aig_m++, aig_i++;
|
aig_m++, aig_i++;
|
||||||
log_assert(!aig_map.count(q));
|
log_assert(!aig_map.count(q));
|
||||||
aig_map[q] = 2*aig_m;
|
aig_map[q] = 2*aig_m;
|
||||||
|
@ -742,7 +687,7 @@ struct XAigerWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
// For flops only, create an extra 1-bit input that drives a new wire
|
// For flops only, create an extra 1-bit input that drives a new wire
|
||||||
// called "<cell>.$abc9_currQ" that is used below
|
// called "<cell>.abc9_ff.Q" that is used below
|
||||||
if (box_module->get_bool_attribute("\\abc9_flop")) {
|
if (box_module->get_bool_attribute("\\abc9_flop")) {
|
||||||
log_assert(holes_cell);
|
log_assert(holes_cell);
|
||||||
|
|
||||||
|
@ -754,7 +699,8 @@ struct XAigerWriter
|
||||||
holes_wire->port_id = port_id++;
|
holes_wire->port_id = port_id++;
|
||||||
holes_module->ports.push_back(holes_wire->name);
|
holes_module->ports.push_back(holes_wire->name);
|
||||||
}
|
}
|
||||||
Wire *w = holes_module->addWire(stringf("%s.$abc9_currQ", cell->name.c_str()));
|
Wire *w = holes_module->addWire(stringf("%s.abc9_ff.Q", cell->name.c_str()));
|
||||||
|
log_assert(w);
|
||||||
holes_module->connect(w, holes_wire);
|
holes_module->connect(w, holes_wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,13 +720,25 @@ struct XAigerWriter
|
||||||
write_s_buffer(ff_bits.size());
|
write_s_buffer(ff_bits.size());
|
||||||
|
|
||||||
for (const auto &i : ff_bits) {
|
for (const auto &i : ff_bits) {
|
||||||
const SigBit &q = std::get<0>(i.second);
|
const SigBit &d = i.first;
|
||||||
int mergeability = std::get<1>(i.second);
|
const Cell *cell = i.second;
|
||||||
|
|
||||||
|
int mergeability = cell->attributes.at(ID(abc9_mergeability)).as_int();
|
||||||
log_assert(mergeability > 0);
|
log_assert(mergeability > 0);
|
||||||
write_r_buffer(mergeability);
|
write_r_buffer(mergeability);
|
||||||
int init = std::get<2>(i.second);
|
|
||||||
write_s_buffer(init);
|
Const init = cell->attributes.at(ID(abc9_init));
|
||||||
write_i_buffer(arrival_times.at(q, 0));
|
log_assert(GetSize(init) == 1);
|
||||||
|
if (init == State::S1)
|
||||||
|
write_s_buffer(1);
|
||||||
|
else if (init == State::S0)
|
||||||
|
write_s_buffer(0);
|
||||||
|
else {
|
||||||
|
log_assert(init == State::Sx);
|
||||||
|
write_s_buffer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_i_buffer(arrival_times.at(d, 0));
|
||||||
//write_o_buffer(0);
|
//write_o_buffer(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,9 +791,9 @@ struct XAigerWriter
|
||||||
log_assert(pos != std::string::npos);
|
log_assert(pos != std::string::npos);
|
||||||
IdString driver = Q.wire->name.substr(0, pos);
|
IdString driver = Q.wire->name.substr(0, pos);
|
||||||
// And drive the signal that was previously driven by "DFF.Q" (typically
|
// And drive the signal that was previously driven by "DFF.Q" (typically
|
||||||
// used to implement clock-enable functionality) with the "<cell>.$abc9_currQ"
|
// used to implement clock-enable functionality) with the "<cell>.abc9_ff.Q"
|
||||||
// wire (which itself is driven an input port) we inserted above
|
// wire (which itself is driven an input port) we inserted above
|
||||||
Wire *currQ = holes_module->wire(stringf("%s.$abc9_currQ", driver.c_str()));
|
Wire *currQ = holes_module->wire(stringf("%s.abc9_ff.Q", driver.c_str()));
|
||||||
log_assert(currQ);
|
log_assert(currQ);
|
||||||
holes_module->connect(Q, currQ);
|
holes_module->connect(Q, currQ);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -249,7 +249,7 @@ struct abc9_output_filter
|
||||||
};
|
};
|
||||||
|
|
||||||
void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file,
|
void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file,
|
||||||
bool cleanup, vector<int> lut_costs, bool keepff, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
|
bool cleanup, vector<int> lut_costs, bool dff, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
|
||||||
bool show_tempdir, std::string box_file, std::string lut_file,
|
bool show_tempdir, std::string box_file, std::string lut_file,
|
||||||
std::string wire_delay, bool nomfs
|
std::string wire_delay, bool nomfs
|
||||||
)
|
)
|
||||||
|
@ -347,7 +347,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
|
||||||
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
|
buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
|
||||||
log_assert(!design->module(ID($__abc9__)));
|
log_assert(!design->module(ID($__abc9__)));
|
||||||
{
|
{
|
||||||
AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
|
AigerReader reader(design, ifs, ID($__abc9__), "" /* clk_name */, /*buffer.c_str()*/ "" /* map_filename */, true /* wideports */);
|
||||||
reader.parse_xaiger();
|
reader.parse_xaiger();
|
||||||
}
|
}
|
||||||
ifs.close();
|
ifs.close();
|
||||||
|
@ -430,7 +430,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
|
||||||
if (jt == abc9_box.end())
|
if (jt == abc9_box.end())
|
||||||
jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first;
|
jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first;
|
||||||
if (jt->second) {
|
if (jt->second) {
|
||||||
if (!keepff || !box_module->get_bool_attribute("\\abc9_flop"))
|
if (box_module->get_bool_attribute("\\abc9_flop")) {
|
||||||
|
if (dff)
|
||||||
|
boxes.emplace_back(cell);
|
||||||
|
else
|
||||||
|
box_module->set_bool_attribute("\\abc9_keep", false);
|
||||||
|
}
|
||||||
|
else
|
||||||
boxes.emplace_back(cell);
|
boxes.emplace_back(cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -795,9 +801,9 @@ struct Abc9Pass : public Pass {
|
||||||
log(" generate netlist using luts. Use the specified costs for luts with 1,\n");
|
log(" generate netlist using luts. Use the specified costs for luts with 1,\n");
|
||||||
log(" 2, 3, .. inputs.\n");
|
log(" 2, 3, .. inputs.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -keepff\n");
|
log(" -dff\n");
|
||||||
log(" do not represent (* abc9_flop *) modules as boxes (and thus do not perform\n");
|
log(" also pass $_ABC9_FF_ cells through ABC. modules with many clock domains\n");
|
||||||
log(" any form of sequential synthesis).\n");
|
log(" are marked as such and automatically partitioned by ABC.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -nocleanup\n");
|
log(" -nocleanup\n");
|
||||||
log(" when this option is used, the temporary files created by this pass\n");
|
log(" when this option is used, the temporary files created by this pass\n");
|
||||||
|
@ -837,7 +843,7 @@ struct Abc9Pass : public Pass {
|
||||||
#endif
|
#endif
|
||||||
std::string script_file, clk_str, box_file, lut_file;
|
std::string script_file, clk_str, box_file, lut_file;
|
||||||
std::string delay_target, lutin_shared = "-S 1", wire_delay;
|
std::string delay_target, lutin_shared = "-S 1", wire_delay;
|
||||||
bool fast_mode = false, keepff = false, cleanup = true;
|
bool fast_mode = false, dff = false, cleanup = true;
|
||||||
bool show_tempdir = false;
|
bool show_tempdir = false;
|
||||||
bool nomfs = false;
|
bool nomfs = false;
|
||||||
vector<int> lut_costs;
|
vector<int> lut_costs;
|
||||||
|
@ -928,8 +934,8 @@ struct Abc9Pass : public Pass {
|
||||||
fast_mode = true;
|
fast_mode = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-keepff") {
|
if (arg == "-dff") {
|
||||||
keepff = true;
|
dff = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-nocleanup") {
|
if (arg == "-nocleanup") {
|
||||||
|
@ -985,16 +991,14 @@ struct Abc9Pass : public Pass {
|
||||||
typedef SigSpec clkdomain_t;
|
typedef SigSpec clkdomain_t;
|
||||||
dict<clkdomain_t, int> clk_to_mergeability;
|
dict<clkdomain_t, int> clk_to_mergeability;
|
||||||
|
|
||||||
|
if (dff)
|
||||||
if (!keepff)
|
|
||||||
for (auto cell : module->selected_cells()) {
|
for (auto cell : module->selected_cells()) {
|
||||||
auto inst_module = design->module(cell->type);
|
if (cell->type != "$__ABC9_FF_")
|
||||||
if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop"))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str()));
|
Wire *abc9_clock_wire = module->wire(stringf("%s.clock", cell->name.c_str()));
|
||||||
if (abc9_clock_wire == NULL)
|
if (abc9_clock_wire == NULL)
|
||||||
log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
|
log_error("'%s.clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
|
||||||
SigSpec abc9_clock = assign_map(abc9_clock_wire);
|
SigSpec abc9_clock = assign_map(abc9_clock_wire);
|
||||||
|
|
||||||
clkdomain_t key(abc9_clock);
|
clkdomain_t key(abc9_clock);
|
||||||
|
@ -1003,19 +1007,26 @@ struct Abc9Pass : public Pass {
|
||||||
auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second));
|
auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second));
|
||||||
log_assert(r2.second);
|
log_assert(r2.second);
|
||||||
|
|
||||||
Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str()));
|
Wire *abc9_init_wire = module->wire(stringf("%s.init", cell->name.c_str()));
|
||||||
if (abc9_init_wire == NULL)
|
if (abc9_init_wire == NULL)
|
||||||
log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
|
log_error("'%s.init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
|
||||||
log_assert(GetSize(abc9_init_wire) == 1);
|
log_assert(GetSize(abc9_init_wire) == 1);
|
||||||
SigSpec abc9_init = assign_map(abc9_init_wire);
|
SigSpec abc9_init = assign_map(abc9_init_wire);
|
||||||
if (!abc9_init.is_fully_const())
|
if (!abc9_init.is_fully_const())
|
||||||
log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
|
log_error("'%s.init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
|
||||||
r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const()));
|
r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const()));
|
||||||
log_assert(r2.second);
|
log_assert(r2.second);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
for (auto cell : module->selected_cells()) {
|
||||||
|
auto inst_module = design->module(cell->type);
|
||||||
|
if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop"))
|
||||||
|
continue;
|
||||||
|
cell->set_bool_attribute("\\abc9_keep");
|
||||||
|
}
|
||||||
|
|
||||||
design->selected_active_module = module->name.str();
|
design->selected_active_module = module->name.str();
|
||||||
abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, keepff,
|
abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, dff,
|
||||||
delay_target, lutin_shared, fast_mode, show_tempdir,
|
delay_target, lutin_shared, fast_mode, show_tempdir,
|
||||||
box_file, lut_file, wire_delay, nomfs);
|
box_file, lut_file, wire_delay, nomfs);
|
||||||
design->selected_active_module.clear();
|
design->selected_active_module.clear();
|
||||||
|
|
|
@ -51,29 +51,29 @@
|
||||||
// || ||
|
// || ||
|
||||||
// || /\/\/\/\ ||
|
// || /\/\/\/\ ||
|
||||||
// D -->>-----< > ||
|
// D -->>-----< > ||
|
||||||
// R -->>-----< Comb. > || +----------+
|
// R -->>-----< Comb. > || +-----------+
|
||||||
// CE -->>-----< logic >--->>-- $Q --|$__ABC_FF_|--+-->> Q
|
// CE -->>-----< logic >--->>-- $Q --|$__ABC9_FF_|--+-->> Q
|
||||||
// $abc9_currQ +-->>-----< > || +----------+ |
|
// abc9_ff.Q +-->>-----< > || +-----------+ |
|
||||||
// | || \/\/\/\/ || |
|
// | || \/\/\/\/ || |
|
||||||
// | || || |
|
// | || || |
|
||||||
// | ++==================++ |
|
// | ++==================++ |
|
||||||
// | |
|
// | |
|
||||||
// +----------------------------------------------+
|
// +-----------------------------------------------+
|
||||||
//
|
//
|
||||||
// The purpose of the following FD* rules are to wrap the flop with:
|
// The purpose of the following FD* rules are to wrap the flop with:
|
||||||
// (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9
|
// (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9
|
||||||
// the connectivity of its basic D-Q flop
|
// the connectivity of its basic D-Q flop
|
||||||
// (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to
|
// (b) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to
|
||||||
// capture asynchronous behaviour
|
// capture asynchronous behaviour
|
||||||
// (c) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock
|
// (c) a special _TECHMAP_REPLACE_.abc9_ff.clock wire to capture its clock
|
||||||
// domain and polarity (used when partitioning the module so that `abc9' only
|
// domain and polarity (used when partitioning the module so that `abc9' only
|
||||||
// performs sequential synthesis (with reachability analysis) correctly on
|
// performs sequential synthesis (with reachability analysis) correctly on
|
||||||
// one domain at a time) and also used to infer the optional delay target
|
// one domain at a time) and also used to infer the optional delay target
|
||||||
// from the (* abc9_clock_period = %d *) attribute attached to any wire
|
// from the (* abc9_clock_period = %d *) attribute attached to any wire
|
||||||
// within
|
// within
|
||||||
// (d) a special _TECHMAP_REPLACE_.$abc9_init wire to encode the flop's initial
|
// (d) a special _TECHMAP_REPLACE_.abc9_ff.init wire to encode the flop's initial
|
||||||
// state
|
// state
|
||||||
// (e) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback
|
// (e) a special _TECHMAP_REPLACE_.abc9_ff.Q wire that will be used for feedback
|
||||||
// into the (combinatorial) FD* cell to facilitate clock-enable behaviour
|
// into the (combinatorial) FD* cell to facilitate clock-enable behaviour
|
||||||
//
|
//
|
||||||
// In order to perform sequential synthesis, `abc9' also requires that
|
// In order to perform sequential synthesis, `abc9' also requires that
|
||||||
|
@ -108,12 +108,12 @@ module FDRE (output Q, input C, CE, D, R);
|
||||||
);
|
);
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
$__ABC9_FF_ abc_dff (.D($Q), .Q(QQ));
|
$__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ));
|
||||||
|
|
||||||
// Special signals
|
// Special signals
|
||||||
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
|
wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED};
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
|
wire [0:0] abc9_ff.init = 1'b0;
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
|
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ;
|
||||||
endmodule
|
endmodule
|
||||||
module FDRE_1 (output Q, input C, CE, D, R);
|
module FDRE_1 (output Q, input C, CE, D, R);
|
||||||
parameter [0:0] INIT = 1'b0;
|
parameter [0:0] INIT = 1'b0;
|
||||||
|
@ -135,12 +135,12 @@ module FDRE_1 (output Q, input C, CE, D, R);
|
||||||
);
|
);
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
$__ABC9_FF_ abc_dff (.D($Q), .Q(QQ));
|
$__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ));
|
||||||
|
|
||||||
// Special signals
|
// Special signals
|
||||||
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
|
wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */};
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
|
wire [0:0] abc9_ff.init = 1'b0;
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
|
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module FDSE (output Q, input C, CE, D, S);
|
module FDSE (output Q, input C, CE, D, S);
|
||||||
|
@ -171,12 +171,12 @@ module FDSE (output Q, input C, CE, D, S);
|
||||||
.D(D), .Q($Q), .C(C), .CE(CE), .S(S)
|
.D(D), .Q($Q), .C(C), .CE(CE), .S(S)
|
||||||
);
|
);
|
||||||
end endgenerate
|
end endgenerate
|
||||||
$__ABC9_FF_ abc_dff (.D($Q), .Q(QQ));
|
$__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ));
|
||||||
|
|
||||||
// Special signals
|
// Special signals
|
||||||
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
|
wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED};
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
|
wire [0:0] abc9_ff.init = 1'b0;
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
|
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ;
|
||||||
endmodule
|
endmodule
|
||||||
module FDSE_1 (output Q, input C, CE, D, S);
|
module FDSE_1 (output Q, input C, CE, D, S);
|
||||||
parameter [0:0] INIT = 1'b1;
|
parameter [0:0] INIT = 1'b1;
|
||||||
|
@ -197,12 +197,12 @@ module FDSE_1 (output Q, input C, CE, D, S);
|
||||||
.D(D), .Q($Q), .C(C), .CE(CE), .S(S)
|
.D(D), .Q($Q), .C(C), .CE(CE), .S(S)
|
||||||
);
|
);
|
||||||
end endgenerate
|
end endgenerate
|
||||||
$__ABC9_FF_ abc_dff (.D($Q), .Q(QQ));
|
$__ABC9_FF_ abc9_ff (.D($Q), .Q(QQ));
|
||||||
|
|
||||||
// Special signals
|
// Special signals
|
||||||
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
|
wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */};
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
|
wire [0:0] abc9_ff.init = 1'b0;
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
|
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = QQ;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module FDCE (output Q, input C, CE, D, CLR);
|
module FDCE (output Q, input C, CE, D, CLR);
|
||||||
|
@ -210,7 +210,7 @@ module FDCE (output Q, input C, CE, D, CLR);
|
||||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||||
parameter [0:0] IS_CLR_INVERTED = 1'b0;
|
parameter [0:0] IS_CLR_INVERTED = 1'b0;
|
||||||
wire QQ, $Q, $abc9_currQ;
|
wire QQ, $Q, $QQ;
|
||||||
generate if (INIT == 1'b1) begin
|
generate if (INIT == 1'b1) begin
|
||||||
assign Q = ~QQ;
|
assign Q = ~QQ;
|
||||||
FDPE #(
|
FDPE #(
|
||||||
|
@ -227,7 +227,7 @@ module FDCE (output Q, input C, CE, D, CLR);
|
||||||
// $__ABC9_ASYNC1 below
|
// $__ABC9_ASYNC1 below
|
||||||
);
|
);
|
||||||
// Since this is an async flop, async behaviour is dealt with here
|
// Since this is an async flop, async behaviour is dealt with here
|
||||||
$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ));
|
$__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ));
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
assign Q = QQ;
|
assign Q = QQ;
|
||||||
|
@ -245,18 +245,18 @@ module FDCE (output Q, input C, CE, D, CLR);
|
||||||
// $__ABC9_ASYNC0 below
|
// $__ABC9_ASYNC0 below
|
||||||
);
|
);
|
||||||
// Since this is an async flop, async behaviour is dealt with here
|
// Since this is an async flop, async behaviour is dealt with here
|
||||||
$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ));
|
$__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ));
|
||||||
end endgenerate
|
end endgenerate
|
||||||
$__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ));
|
$__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ));
|
||||||
|
|
||||||
// Special signals
|
// Special signals
|
||||||
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
|
wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED};
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
|
wire [0:0] abc9_ff.init = 1'b0;
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
|
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ;
|
||||||
endmodule
|
endmodule
|
||||||
module FDCE_1 (output Q, input C, CE, D, CLR);
|
module FDCE_1 (output Q, input C, CE, D, CLR);
|
||||||
parameter [0:0] INIT = 1'b0;
|
parameter [0:0] INIT = 1'b0;
|
||||||
wire QQ, $Q, $abc9_currQ;
|
wire QQ, $Q, $QQ;
|
||||||
generate if (INIT == 1'b1) begin
|
generate if (INIT == 1'b1) begin
|
||||||
assign Q = ~QQ;
|
assign Q = ~QQ;
|
||||||
FDPE_1 #(
|
FDPE_1 #(
|
||||||
|
@ -269,7 +269,7 @@ module FDCE_1 (output Q, input C, CE, D, CLR);
|
||||||
// behaviour is captured by
|
// behaviour is captured by
|
||||||
// $__ABC9_ASYNC1 below
|
// $__ABC9_ASYNC1 below
|
||||||
);
|
);
|
||||||
$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ));
|
$__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR), .Y(QQ));
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
assign Q = QQ;
|
assign Q = QQ;
|
||||||
|
@ -283,14 +283,14 @@ module FDCE_1 (output Q, input C, CE, D, CLR);
|
||||||
// behaviour is captured by
|
// behaviour is captured by
|
||||||
// $__ABC9_ASYNC0 below
|
// $__ABC9_ASYNC0 below
|
||||||
);
|
);
|
||||||
$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ));
|
$__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR), .Y(QQ));
|
||||||
end endgenerate
|
end endgenerate
|
||||||
$__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ));
|
$__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ));
|
||||||
|
|
||||||
// Special signals
|
// Special signals
|
||||||
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
|
wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */};
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
|
wire [0:0] abc9_ff.init = 1'b0;
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
|
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module FDPE (output Q, input C, CE, D, PRE);
|
module FDPE (output Q, input C, CE, D, PRE);
|
||||||
|
@ -298,7 +298,7 @@ module FDPE (output Q, input C, CE, D, PRE);
|
||||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||||
parameter [0:0] IS_PRE_INVERTED = 1'b0;
|
parameter [0:0] IS_PRE_INVERTED = 1'b0;
|
||||||
wire QQ, $Q, $abc9_currQ;
|
wire QQ, $Q, $QQ;
|
||||||
generate if (INIT == 1'b1) begin
|
generate if (INIT == 1'b1) begin
|
||||||
assign Q = ~QQ;
|
assign Q = ~QQ;
|
||||||
FDCE #(
|
FDCE #(
|
||||||
|
@ -314,7 +314,7 @@ module FDPE (output Q, input C, CE, D, PRE);
|
||||||
// behaviour is captured by
|
// behaviour is captured by
|
||||||
// $__ABC9_ASYNC0 below
|
// $__ABC9_ASYNC0 below
|
||||||
);
|
);
|
||||||
$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ));
|
$__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ));
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
assign Q = QQ;
|
assign Q = QQ;
|
||||||
|
@ -331,18 +331,18 @@ module FDPE (output Q, input C, CE, D, PRE);
|
||||||
// behaviour is captured by
|
// behaviour is captured by
|
||||||
// $__ABC9_ASYNC1 below
|
// $__ABC9_ASYNC1 below
|
||||||
);
|
);
|
||||||
$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ));
|
$__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ));
|
||||||
end endgenerate
|
end endgenerate
|
||||||
$__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ));
|
$__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ));
|
||||||
|
|
||||||
// Special signals
|
// Special signals
|
||||||
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
|
wire [1:0] abc9_ff.clock = {C, IS_C_INVERTED};
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
|
wire [0:0] abc9_ff.init = 1'b0;
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
|
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ;
|
||||||
endmodule
|
endmodule
|
||||||
module FDPE_1 (output Q, input C, CE, D, PRE);
|
module FDPE_1 (output Q, input C, CE, D, PRE);
|
||||||
parameter [0:0] INIT = 1'b1;
|
parameter [0:0] INIT = 1'b1;
|
||||||
wire QQ, $Q, $abc9_currQ;
|
wire QQ, $Q, $QQ;
|
||||||
generate if (INIT == 1'b1) begin
|
generate if (INIT == 1'b1) begin
|
||||||
assign Q = ~QQ;
|
assign Q = ~QQ;
|
||||||
FDCE_1 #(
|
FDCE_1 #(
|
||||||
|
@ -355,7 +355,7 @@ module FDPE_1 (output Q, input C, CE, D, PRE);
|
||||||
// behaviour is captured by
|
// behaviour is captured by
|
||||||
// $__ABC9_ASYNC0 below
|
// $__ABC9_ASYNC0 below
|
||||||
);
|
);
|
||||||
$__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ));
|
$__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE), .Y(QQ));
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
assign Q = QQ;
|
assign Q = QQ;
|
||||||
|
@ -369,14 +369,14 @@ module FDPE_1 (output Q, input C, CE, D, PRE);
|
||||||
// behaviour is captured by
|
// behaviour is captured by
|
||||||
// $__ABC9_ASYNC1 below
|
// $__ABC9_ASYNC1 below
|
||||||
);
|
);
|
||||||
$__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ));
|
$__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE), .Y(QQ));
|
||||||
end endgenerate
|
end endgenerate
|
||||||
$__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ));
|
$__ABC9_FF_ abc9_ff (.D($Q), .Q($QQ));
|
||||||
|
|
||||||
// Special signals
|
// Special signals
|
||||||
wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
|
wire [1:0] abc9_ff.clock = {C, 1'b1 /* IS_C_INVERTED */};
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
|
wire [0:0] abc9_ff.init = 1'b0;
|
||||||
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
|
wire [0:0] _TECHMAP_REPLACE_.abc9_ff.Q = $QQ;
|
||||||
endmodule
|
endmodule
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
log(" flatten design before synthesis\n");
|
log(" flatten design before synthesis\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -dff\n");
|
log(" -dff\n");
|
||||||
log(" enable sequential synthesis with 'abc9'\n");
|
log(" run 'abc9' with -dff option\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" -retime\n");
|
log(" -retime\n");
|
||||||
log(" run 'abc' with -dff option\n");
|
log(" run 'abc' with -dff option\n");
|
||||||
|
@ -559,8 +559,8 @@ struct SynthXilinxPass : public ScriptPass
|
||||||
abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut";
|
abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut";
|
||||||
else
|
else
|
||||||
abc9_opts += " -lut +/xilinx/abc9_xc7.lut";
|
abc9_opts += " -lut +/xilinx/abc9_xc7.lut";
|
||||||
if (!dff_mode)
|
if (dff_mode)
|
||||||
abc9_opts += " -keepff";
|
abc9_opts += " -dff";
|
||||||
run("abc9" + abc9_opts);
|
run("abc9" + abc9_opts);
|
||||||
run("techmap -map +/xilinx/abc9_unmap.v");
|
run("techmap -map +/xilinx/abc9_unmap.v");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue