aboutsummaryrefslogtreecommitdiffstats
path: root/passes
diff options
context:
space:
mode:
Diffstat (limited to 'passes')
-rw-r--r--passes/equiv/equiv_simple.cc4
-rw-r--r--passes/fsm/fsm_expand.cc30
-rw-r--r--passes/hierarchy/hierarchy.cc6
-rw-r--r--passes/opt/opt_clean.cc2
-rw-r--r--passes/opt/opt_expr.cc120
-rw-r--r--passes/opt/opt_rmdff.cc26
-rw-r--r--passes/techmap/abc.cc6
7 files changed, 176 insertions, 18 deletions
diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc
index 49963ed68..270200c34 100644
--- a/passes/equiv/equiv_simple.cc
+++ b/passes/equiv/equiv_simple.cc
@@ -59,7 +59,7 @@ struct EquivSimpleWorker
for (auto &conn : cell->connections())
if (yosys_celltypes.cell_input(cell->type, conn.first))
for (auto bit : sigmap(conn.second)) {
- if (cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_")) {
+ if (cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_", "$ff", "$_FF_")) {
if (!conn.first.in("\\CLK", "\\C"))
next_seed.insert(bit);
} else
@@ -329,7 +329,7 @@ struct EquivSimplePass : public Pass {
unproven_cells_counter, GetSize(unproven_equiv_cells), log_id(module));
for (auto cell : module->cells()) {
- if (!ct.cell_known(cell->type) && !cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_"))
+ if (!ct.cell_known(cell->type) && !cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_", "$ff", "$_FF_"))
continue;
for (auto &conn : cell->connections())
if (yosys_celltypes.cell_output(cell->type, conn.first))
diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc
index e7b9dcf90..2c344a1c1 100644
--- a/passes/fsm/fsm_expand.cc
+++ b/passes/fsm/fsm_expand.cc
@@ -54,13 +54,27 @@ struct FsmExpand
if (cell->getPort("\\A").size() < 2)
return true;
+ int in_bits = 0;
RTLIL::SigSpec new_signals;
- if (cell->hasPort("\\A"))
+
+ if (cell->hasPort("\\A")) {
+ in_bits += GetSize(cell->getPort("\\A"));
new_signals.append(assign_map(cell->getPort("\\A")));
- if (cell->hasPort("\\B"))
+ }
+
+ if (cell->hasPort("\\B")) {
+ in_bits += GetSize(cell->getPort("\\B"));
new_signals.append(assign_map(cell->getPort("\\B")));
- if (cell->hasPort("\\S"))
+ }
+
+ if (cell->hasPort("\\S")) {
+ in_bits += GetSize(cell->getPort("\\S"));
new_signals.append(assign_map(cell->getPort("\\S")));
+ }
+
+ if (in_bits > 8)
+ return false;
+
if (cell->hasPort("\\Y"))
new_signals.append(assign_map(cell->getPort("\\Y")));
@@ -173,6 +187,16 @@ struct FsmExpand
new_ctrl_out.append(output_sig);
fsm_cell->setPort("\\CTRL_OUT", new_ctrl_out);
+ if (GetSize(input_sig) > 10)
+ log_warning("Cell %s.%s (%s) has %d input bits, merging into FSM %s.%s might be problematic.\n",
+ log_id(cell->module), log_id(cell), log_id(cell->type),
+ GetSize(input_sig), log_id(fsm_cell->module), log_id(fsm_cell));
+
+ if (GetSize(fsm_data.transition_table) > 10000)
+ log_warning("Transition table for FSM %s.%s already has %d rows, merging more cells "
+ "into this FSM might be problematic.\n", log_id(fsm_cell->module), log_id(fsm_cell),
+ GetSize(fsm_data.transition_table));
+
std::vector<FsmData::transition_t> new_transition_table;
for (auto &tr : fsm_data.transition_table) {
for (int i = 0; i < (1 << input_sig.size()); i++) {
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index 337af7fd7..4786aacaf 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -175,16 +175,12 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
{
filename = dir + "/" + RTLIL::unescape_id(cell->type) + ".v";
if (check_file_exists(filename)) {
- std::vector<std::string> args;
- args.push_back(filename);
Frontend::frontend_call(design, NULL, filename, "verilog");
goto loaded_module;
}
filename = dir + "/" + RTLIL::unescape_id(cell->type) + ".il";
if (check_file_exists(filename)) {
- std::vector<std::string> args;
- args.push_back(filename);
Frontend::frontend_call(design, NULL, filename, "ilang");
goto loaded_module;
}
@@ -317,7 +313,7 @@ bool set_keep_assert(std::map<RTLIL::Module*, bool> &cache, RTLIL::Module *mod)
if (cache.count(mod) == 0)
for (auto c : mod->cells()) {
RTLIL::Module *m = mod->design->module(c->type);
- if ((m != nullptr && set_keep_assert(cache, m)) || c->type.in("$assert", "$assume"))
+ if ((m != nullptr && set_keep_assert(cache, m)) || c->type.in("$assert", "$assume", "$cover"))
return cache[mod] = true;
}
return cache[mod];
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index 6600ffa25..65944caec 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -64,7 +64,7 @@ struct keep_cache_t
bool query(Cell *cell)
{
- if (cell->type.in("$memwr", "$meminit", "$assert", "$assume"))
+ if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$cover"))
return true;
if (cell->has_keep_attr())
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index b62eae285..b3f2e87ed 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -259,6 +259,29 @@ bool is_one_or_minus_one(const Const &value, bool is_signed, bool &is_negative)
return last_bit_one;
}
+// if the signal has only one bit set, return the index of that bit.
+// otherwise return -1
+int get_onehot_bit_index(RTLIL::SigSpec signal)
+{
+ int bit_index = -1;
+
+ for (int i = 0; i < GetSize(signal); i++)
+ {
+ if (signal[i] == RTLIL::State::S0)
+ continue;
+
+ if (signal[i] != RTLIL::State::S1)
+ return -1;
+
+ if (bit_index != -1)
+ return -1;
+
+ bit_index = i;
+ }
+
+ return bit_index;
+}
+
void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool consume_x, bool mux_undef, bool mux_bool, bool do_fine, bool keepdc, bool clkinv)
{
if (!design->selected(module))
@@ -1167,6 +1190,103 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
}
}
+ // replace a<0 or a>=0 with the top bit of a
+ if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le"))
+ {
+ //used to decide whether the signal needs to be negated
+ bool is_lt = false;
+
+ //references the variable signal in the comparison
+ RTLIL::SigSpec sigVar;
+
+ //references the constant signal in the comparison
+ RTLIL::SigSpec sigConst;
+
+ // note that this signal must be constant for the optimization
+ // to take place, but it is not checked beforehand.
+ // If new passes are added, this signal must be checked for const-ness
+
+ //width of the variable port
+ int width;
+
+ bool var_signed;
+
+ if (cell->type == "$lt" || cell->type == "$ge") {
+ is_lt = cell->type == "$lt" ? 1 : 0;
+ sigVar = cell->getPort("\\A");
+ sigConst = cell->getPort("\\B");
+ width = cell->parameters["\\A_WIDTH"].as_int();
+ var_signed = cell->parameters["\\A_SIGNED"].as_bool();
+ } else
+ if (cell->type == "$gt" || cell->type == "$le") {
+ is_lt = cell->type == "$gt" ? 1 : 0;
+ sigVar = cell->getPort("\\B");
+ sigConst = cell->getPort("\\A");
+ width = cell->parameters["\\B_WIDTH"].as_int();
+ var_signed = cell->parameters["\\B_SIGNED"].as_bool();
+ }
+
+ // replace a(signed) < 0 with the high bit of a
+ if (sigConst.is_fully_const() && sigConst.is_fully_zero() && var_signed == true)
+ {
+ RTLIL::SigSpec a_prime(RTLIL::State::S0, cell->parameters["\\Y_WIDTH"].as_int());
+ a_prime[0] = sigVar[width - 1];
+ if (is_lt) {
+ log("Replacing %s cell `%s' (implementing X<0) with X[%d]: %s\n",
+ log_id(cell->type), log_id(cell), width-1, log_signal(a_prime));
+ module->connect(cell->getPort("\\Y"), a_prime);
+ module->remove(cell);
+ } else {
+ log("Replacing %s cell `%s' (implementing X>=0) with ~X[%d]: %s\n",
+ log_id(cell->type), log_id(cell), width-1, log_signal(a_prime));
+ module->addNot(NEW_ID, a_prime, cell->getPort("\\Y"));
+ module->remove(cell);
+ }
+ did_something = true;
+ goto next_cell;
+ } else
+ if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false)
+ {
+ if (sigConst.is_fully_zero()) {
+ RTLIL::SigSpec a_prime(RTLIL::State::S0, 1);
+ if (is_lt) {
+ log("Replacing %s cell `%s' (implementing unsigned X<0) with constant false.\n",
+ log_id(cell->type), log_id(cell));
+ a_prime[0] = RTLIL::State::S0;
+ } else {
+ log("Replacing %s cell `%s' (implementing unsigned X>=0) with constant true.\n",
+ log_id(cell->type), log_id(cell));
+ a_prime[0] = RTLIL::State::S1;
+ }
+ module->connect(cell->getPort("\\Y"), a_prime);
+ module->remove(cell);
+ did_something = true;
+ goto next_cell;
+ }
+
+ int const_bit_set = get_onehot_bit_index(sigConst);
+ if (const_bit_set >= 0) {
+ int bit_set = const_bit_set;
+ RTLIL::SigSpec a_prime(RTLIL::State::S0, width - bit_set);
+ for (int i = bit_set; i < width; i++) {
+ a_prime[i - bit_set] = sigVar[i];
+ }
+ if (is_lt) {
+ log("Replacing %s cell `%s' (implementing unsigned X<%s) with !X[%d:%d]: %s.\n",
+ log_id(cell->type), log_id(cell), log_signal(sigConst), width - 1, bit_set, log_signal(a_prime));
+ module->addLogicNot(NEW_ID, a_prime, cell->getPort("\\Y"));
+ } else {
+ log("Replacing %s cell `%s' (implementing unsigned X>=%s) with |X[%d:%d]: %s.\n",
+ log_id(cell->type), log_id(cell), log_signal(sigConst), width - 1, bit_set, log_signal(a_prime));
+ module->addReduceOr(NEW_ID, a_prime, cell->getPort("\\Y"));
+ }
+ module->remove(cell);
+ did_something = true;
+ goto next_cell;
+ }
+ }
+ }
+
next_cell:;
#undef ACTION_DO
#undef ACTION_DO_Y
diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc
index 922f086f1..00094738c 100644
--- a/passes/opt/opt_rmdff.cc
+++ b/passes/opt/opt_rmdff.cc
@@ -41,9 +41,27 @@ void remove_init_attr(SigSpec sig)
bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
{
- SigSpec sig_e = dlatch->getPort("\\EN");
+ SigSpec sig_e;
+ State on_state, off_state;
+
+ if (dlatch->type == "$dlatch") {
+ sig_e = assign_map(dlatch->getPort("\\EN"));
+ on_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S1 : State::S0;
+ off_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S0 : State::S1;
+ } else
+ if (dlatch->type == "$_DLATCH_P_") {
+ sig_e = assign_map(dlatch->getPort("\\E"));
+ on_state = State::S1;
+ off_state = State::S0;
+ } else
+ if (dlatch->type == "$_DLATCH_N_") {
+ sig_e = assign_map(dlatch->getPort("\\E"));
+ on_state = State::S0;
+ off_state = State::S1;
+ } else
+ log_abort();
- if (sig_e == State::S0)
+ if (sig_e == off_state)
{
RTLIL::Const val_init;
for (auto bit : dff_init_map(dlatch->getPort("\\Q")))
@@ -52,7 +70,7 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch)
goto delete_dlatch;
}
- if (sig_e == State::S1)
+ if (sig_e == on_state)
{
mod->connect(dlatch->getPort("\\Q"), dlatch->getPort("\\D"));
goto delete_dlatch;
@@ -268,7 +286,7 @@ struct OptRmdffPass : public Pass {
"$ff", "$dff", "$adff"))
dff_list.push_back(cell->name);
- if (cell->type == "$dlatch")
+ if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_"))
dlatch_list.push_back(cell->name);
}
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 9b829f435..a1cea3aaf 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -29,11 +29,11 @@
// Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558-562, doi:10.1145/368996.369025
// http://en.wikipedia.org/wiki/Topological_sorting
-#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; dch -f; map {D}"
-#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; dch -f; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
+#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
+#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
-#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; dch -f; map"
+#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}"
#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"