#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/ffinit.h"
+#include "kernel/ff.h"
#include "kernel/cost.h"
#include "kernel/log.h"
#include <stdlib.h>
enum class gate_type_t {
G_NONE,
G_FF,
+ G_FF0,
+ G_FF1,
G_BUF,
G_NOT,
G_AND,
std::map<RTLIL::SigBit, int> signal_map;
FfInitVals initvals;
pool<std::string> enabled_gates;
-bool recover_init, cmos_cost;
+bool cmos_cost;
+bool had_init;
-bool clk_polarity, en_polarity;
-RTLIL::SigSpec clk_sig, en_sig;
+bool clk_polarity, en_polarity, arst_polarity, srst_polarity;
+RTLIL::SigSpec clk_sig, en_sig, arst_sig, srst_sig;
dict<int, std::string> pi_map, po_map;
int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1)
void extract_cell(RTLIL::Cell *cell, bool keepff)
{
- if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
- {
- if (clk_polarity != (cell->type == ID($_DFF_P_)))
+ if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
+ FfData ff(&initvals, cell);
+ gate_type_t type = G(FF);
+ if (!ff.has_clk)
return;
- if (clk_sig != assign_map(cell->getPort(ID::C)))
+ if (ff.has_gclk)
return;
- if (GetSize(en_sig) != 0)
+ if (ff.has_aload)
return;
- goto matching_dff;
- }
-
- if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
- {
- if (clk_polarity != cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_)))
+ if (ff.has_sr)
return;
- if (en_polarity != cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_)))
+ if (!ff.is_fine)
return;
- if (clk_sig != assign_map(cell->getPort(ID::C)))
+ if (clk_polarity != ff.pol_clk)
return;
- if (en_sig != assign_map(cell->getPort(ID::E)))
+ if (clk_sig != assign_map(ff.sig_clk))
return;
- goto matching_dff;
- }
-
- if (0) {
- matching_dff:
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
+ if (ff.has_ce) {
+ if (en_polarity != ff.pol_ce)
+ return;
+ if (en_sig != assign_map(ff.sig_ce))
+ return;
+ } else {
+ if (GetSize(en_sig) != 0)
+ return;
+ }
+ if (ff.val_init == State::S1) {
+ type = G(FF1);
+ had_init = true;
+ } else if (ff.val_init == State::S0) {
+ type = G(FF0);
+ had_init = true;
+ }
+ if (ff.has_arst) {
+ if (arst_polarity != ff.pol_arst)
+ return;
+ if (arst_sig != assign_map(ff.sig_arst))
+ return;
+ if (ff.val_arst == State::S1) {
+ if (type == G(FF0))
+ return;
+ type = G(FF1);
+ } else if (ff.val_arst == State::S0) {
+ if (type == G(FF1))
+ return;
+ type = G(FF0);
+ }
+ } else {
+ if (GetSize(arst_sig) != 0)
+ return;
+ }
+ if (ff.has_srst) {
+ if (srst_polarity != ff.pol_srst)
+ return;
+ if (srst_sig != assign_map(ff.sig_srst))
+ return;
+ if (ff.val_srst == State::S1) {
+ if (type == G(FF0))
+ return;
+ type = G(FF1);
+ } else if (ff.val_srst == State::S0) {
+ if (type == G(FF1))
+ return;
+ type = G(FF0);
+ }
+ } else {
+ if (GetSize(srst_sig) != 0)
+ return;
+ }
if (keepff)
- for (auto &c : sig_q.chunks())
+ for (auto &c : ff.sig_q.chunks())
if (c.wire != nullptr)
c.wire->attributes[ID::keep] = 1;
- assign_map.apply(sig_d);
- assign_map.apply(sig_q);
-
- map_signal(sig_q, G(FF), map_signal(sig_d));
+ map_signal(ff.sig_q, type, map_signal(ff.sig_d));
- module->remove(cell);
+ ff.remove();
return;
}
// dot_f = fopen("test.dot", "w");
for (auto &g : signal_list) {
- if (g.type == G(NONE) || g.type == G(FF)) {
+ if (g.type == G(NONE) || g.type == G(FF) || g.type == G(FF0) || g.type == G(FF1)) {
workpool.insert(g.id);
} else {
if (g.in1 >= 0) {
signal_list.clear();
pi_map.clear();
po_map.clear();
- recover_init = false;
if (clk_str != "$")
{
en_polarity = true;
en_sig = RTLIL::SigSpec();
+
+ arst_polarity = true;
+ arst_sig = RTLIL::SigSpec();
+
+ srst_polarity = true;
+ srst_sig = RTLIL::SigSpec();
}
if (!clk_str.empty() && clk_str != "$")
{
+ std::string en_str;
+ std::string arst_str;
+ std::string srst_str;
if (clk_str.find(',') != std::string::npos) {
int pos = clk_str.find(',');
- std::string en_str = clk_str.substr(pos+1);
+ en_str = clk_str.substr(pos+1);
clk_str = clk_str.substr(0, pos);
+ }
+ if (en_str.find(',') != std::string::npos) {
+ int pos = en_str.find(',');
+ arst_str = en_str.substr(pos+1);
+ arst_str = en_str.substr(0, pos);
+ }
+ if (arst_str.find(',') != std::string::npos) {
+ int pos = arst_str.find(',');
+ srst_str = arst_str.substr(pos+1);
+ srst_str = arst_str.substr(0, pos);
+ }
+ if (clk_str[0] == '!') {
+ clk_polarity = false;
+ clk_str = clk_str.substr(1);
+ }
+ if (module->wire(RTLIL::escape_id(clk_str)) != nullptr)
+ clk_sig = assign_map(module->wire(RTLIL::escape_id(clk_str)));
+ if (en_str != "") {
if (en_str[0] == '!') {
en_polarity = false;
en_str = en_str.substr(1);
if (module->wire(RTLIL::escape_id(en_str)) != nullptr)
en_sig = assign_map(module->wire(RTLIL::escape_id(en_str)));
}
- if (clk_str[0] == '!') {
- clk_polarity = false;
- clk_str = clk_str.substr(1);
+ if (arst_str != "") {
+ if (arst_str[0] == '!') {
+ arst_polarity = false;
+ arst_str = arst_str.substr(1);
+ }
+ if (module->wire(RTLIL::escape_id(arst_str)) != nullptr)
+ arst_sig = assign_map(module->wire(RTLIL::escape_id(arst_str)));
+ }
+ if (srst_str != "") {
+ if (srst_str[0] == '!') {
+ srst_polarity = false;
+ srst_str = srst_str.substr(1);
+ }
+ if (module->wire(RTLIL::escape_id(srst_str)) != nullptr)
+ srst_sig = assign_map(module->wire(RTLIL::escape_id(srst_str)));
}
- if (module->wire(RTLIL::escape_id(clk_str)) != nullptr)
- clk_sig = assign_map(module->wire(RTLIL::escape_id(clk_str)));
}
if (dff_mode && clk_sig.empty())
log("Found%s %s clock domain: %s", clk_str.empty() ? "" : " matching", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig));
if (en_sig.size() != 0)
log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig));
+ if (arst_sig.size() != 0)
+ log(", asynchronously reset by %s%s", arst_polarity ? "" : "!", log_signal(arst_sig));
+ if (srst_sig.size() != 0)
+ log(", synchronously reset by %s%s", srst_polarity ? "" : "!", log_signal(srst_sig));
log("\n");
}
}
+ had_init = false;
for (auto c : cells)
extract_cell(c, keepff);
if (en_sig.size() != 0)
mark_port(en_sig);
+ if (arst_sig.size() != 0)
+ mark_port(arst_sig);
+
+ if (srst_sig.size() != 0)
+ mark_port(srst_sig);
+
handle_loops();
buffer = stringf("%s/input.blif", tempdir_name.c_str());
fprintf(f, "00-- 1\n");
fprintf(f, "--00 1\n");
} else if (si.type == G(FF)) {
- if (si.init == State::S0 || si.init == State::S1) {
- fprintf(f, ".latch ys__n%d ys__n%d %d\n", si.in1, si.id, si.init == State::S1 ? 1 : 0);
- recover_init = true;
- } else
- fprintf(f, ".latch ys__n%d ys__n%d 2\n", si.in1, si.id);
+ fprintf(f, ".latch ys__n%d ys__n%d 2\n", si.in1, si.id);
+ } else if (si.type == G(FF0)) {
+ fprintf(f, ".latch ys__n%d ys__n%d 0\n", si.in1, si.id);
+ } else if (si.type == G(FF1)) {
+ fprintf(f, ".latch ys__n%d ys__n%d 1\n", si.in1, si.id);
} else if (si.type != G(NONE))
log_abort();
if (si.type != G(NONE))
design->select(module, wire);
}
+ SigMap mapped_sigmap(mapped_mod);
+ FfInitVals mapped_initvals(&mapped_sigmap, mapped_mod);
+
std::map<std::string, int> cell_stats;
for (auto c : mapped_mod->cells())
{
}
if (c->type == ID(DFF)) {
log_assert(clk_sig.size() == 1);
- RTLIL::Cell *cell;
- if (en_sig.size() == 0) {
- cell = module->addCell(remap_name(c->name), clk_polarity ? ID($_DFF_P_) : ID($_DFF_N_));
- } else {
+ FfData ff(module, &initvals, remap_name(c->name));
+ ff.width = 1;
+ ff.is_fine = true;
+ ff.has_clk = true;
+ ff.pol_clk = clk_polarity;
+ ff.sig_clk = clk_sig;
+ if (en_sig.size() != 0) {
log_assert(en_sig.size() == 1);
- cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
- cell->setPort(ID::E, en_sig);
+ ff.has_ce = true;
+ ff.pol_ce = en_polarity;
+ ff.sig_ce = en_sig;
}
- if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx;
- for (auto name : {ID::D, ID::Q}) {
- RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name);
- cell->setPort(name, module->wire(remapped_name));
+ RTLIL::Const init = mapped_initvals(c->getPort(ID::Q));
+ if (had_init)
+ ff.val_init = init;
+ else
+ ff.val_init = State::Sx;
+ if (arst_sig.size() != 0) {
+ log_assert(arst_sig.size() == 1);
+ ff.has_arst = true;
+ ff.pol_arst = arst_polarity;
+ ff.sig_arst = arst_sig;
+ ff.val_arst = init;
}
- cell->setPort(ID::C, clk_sig);
+ if (srst_sig.size() != 0) {
+ log_assert(srst_sig.size() == 1);
+ ff.has_srst = true;
+ ff.pol_srst = srst_polarity;
+ ff.sig_srst = srst_sig;
+ ff.val_srst = init;
+ }
+ ff.sig_d = module->wire(remap_name(c->getPort(ID::D).as_wire()->name));
+ ff.sig_q = module->wire(remap_name(c->getPort(ID::Q).as_wire()->name));
+ RTLIL::Cell *cell = ff.emit();
+ if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx;
design->select(module, cell);
continue;
}
if (c->type == ID(_dff_)) {
log_assert(clk_sig.size() == 1);
- RTLIL::Cell *cell;
- if (en_sig.size() == 0) {
- cell = module->addCell(remap_name(c->name), clk_polarity ? ID($_DFF_P_) : ID($_DFF_N_));
- } else {
+ FfData ff(module, &initvals, remap_name(c->name));
+ ff.width = 1;
+ ff.is_fine = true;
+ ff.has_clk = true;
+ ff.pol_clk = clk_polarity;
+ ff.sig_clk = clk_sig;
+ if (en_sig.size() != 0) {
log_assert(en_sig.size() == 1);
- cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
- cell->setPort(ID::E, en_sig);
+ ff.pol_ce = en_polarity;
+ ff.sig_ce = en_sig;
}
- if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx;
- for (auto name : {ID::D, ID::Q}) {
- RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name);
- cell->setPort(name, module->wire(remapped_name));
+ RTLIL::Const init = mapped_initvals(c->getPort(ID::Q));
+ if (had_init)
+ ff.val_init = init;
+ else
+ ff.val_init = State::Sx;
+ if (arst_sig.size() != 0) {
+ log_assert(arst_sig.size() == 1);
+ ff.pol_arst = arst_polarity;
+ ff.sig_arst = arst_sig;
+ ff.val_arst = init;
+ }
+ if (srst_sig.size() != 0) {
+ log_assert(srst_sig.size() == 1);
+ ff.pol_srst = srst_polarity;
+ ff.sig_srst = srst_sig;
+ ff.val_srst = init;
}
- cell->setPort(ID::C, clk_sig);
+ ff.sig_d = module->wire(remap_name(c->getPort(ID::D).as_wire()->name));
+ ff.sig_q = module->wire(remap_name(c->getPort(ID::Q).as_wire()->name));
+ RTLIL::Cell *cell = ff.emit();
+ if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx;
design->select(module, cell);
continue;
}
module->connect(conn);
}
- if (recover_init)
- for (auto wire : mapped_mod->wires()) {
- if (wire->attributes.count(ID::init)) {
- Wire *w = module->wire(remap_name(wire->name));
- log_assert(w->attributes.count(ID::init) == 0);
- w->attributes[ID::init] = wire->attributes.at(ID::init);
- }
- }
-
for (auto &it : cell_stats)
log("ABC RESULTS: %15s cells: %8d\n", it.first.c_str(), it.second);
int in_wires = 0, out_wires = 0;
std::set<RTLIL::Cell*> expand_queue_up, next_expand_queue_up;
std::set<RTLIL::Cell*> expand_queue_down, next_expand_queue_down;
- typedef tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t;
+ typedef tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec, bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t;
std::map<clkdomain_t, std::vector<RTLIL::Cell*>> assigned_cells;
std::map<RTLIL::Cell*, clkdomain_t> assigned_cells_reverse;
}
}
- if (cell->type.in(ID($_DFF_N_), ID($_DFF_P_)))
- {
- key = clkdomain_t(cell->type == ID($_DFF_P_), assign_map(cell->getPort(ID::C)), true, RTLIL::SigSpec());
- }
- else
- if (cell->type.in(ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_)))
- {
- bool this_clk_pol = cell->type.in(ID($_DFFE_PN_), ID($_DFFE_PP_));
- bool this_en_pol = cell->type.in(ID($_DFFE_NP_), ID($_DFFE_PP_));
- key = clkdomain_t(this_clk_pol, assign_map(cell->getPort(ID::C)), this_en_pol, assign_map(cell->getPort(ID::E)));
- }
- else
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
+ continue;
+
+ FfData ff(&initvals, cell);
+ if (!ff.has_clk)
+ continue;
+ if (ff.has_gclk)
+ continue;
+ if (ff.has_aload)
+ continue;
+ if (ff.has_sr)
+ continue;
+ if (!ff.is_fine)
continue;
+ key = clkdomain_t(
+ ff.pol_clk,
+ ff.sig_clk,
+ ff.has_ce ? ff.pol_ce : true,
+ ff.has_ce ? assign_map(ff.sig_ce) : RTLIL::SigSpec(),
+ ff.has_arst ? ff.pol_arst : true,
+ ff.has_arst ? assign_map(ff.sig_arst) : RTLIL::SigSpec(),
+ ff.has_srst ? ff.pol_srst : true,
+ ff.has_srst ? assign_map(ff.sig_srst) : RTLIL::SigSpec()
+ );
unassigned_cells.erase(cell);
expand_queue.insert(cell);
expand_queue.swap(next_expand_queue);
}
- clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec());
+ clkdomain_t key(true, RTLIL::SigSpec(), true, RTLIL::SigSpec(), true, RTLIL::SigSpec(), true, RTLIL::SigSpec());
for (auto cell : unassigned_cells) {
assigned_cells[key].push_back(cell);
assigned_cells_reverse[cell] = key;
log_header(design, "Summary of detected clock domains:\n");
for (auto &it : assigned_cells)
- log(" %d cells in clk=%s%s, en=%s%s\n", GetSize(it.second),
+ log(" %d cells in clk=%s%s, en=%s%s, arst=%s%s, srst=%s%s\n", GetSize(it.second),
std::get<0>(it.first) ? "" : "!", log_signal(std::get<1>(it.first)),
- std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first)));
+ std::get<2>(it.first) ? "" : "!", log_signal(std::get<3>(it.first)),
+ std::get<4>(it.first) ? "" : "!", log_signal(std::get<5>(it.first)),
+ std::get<6>(it.first) ? "" : "!", log_signal(std::get<7>(it.first)));
for (auto &it : assigned_cells) {
clk_polarity = std::get<0>(it.first);
clk_sig = assign_map(std::get<1>(it.first));
en_polarity = std::get<2>(it.first);
en_sig = assign_map(std::get<3>(it.first));
+ arst_polarity = std::get<4>(it.first);
+ arst_sig = assign_map(std::get<5>(it.first));
+ srst_polarity = std::get<6>(it.first);
+ srst_sig = assign_map(std::get<7>(it.first));
abc_module(design, mod, script_file, exe_file, liberty_files, genlib_files, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode, abc_dress);
assign_map.set(mod);