diff options
Diffstat (limited to 'passes')
-rw-r--r-- | passes/equiv/equiv_simple.cc | 4 | ||||
-rw-r--r-- | passes/fsm/fsm_expand.cc | 30 | ||||
-rw-r--r-- | passes/hierarchy/hierarchy.cc | 6 | ||||
-rw-r--r-- | passes/opt/opt_clean.cc | 2 | ||||
-rw-r--r-- | passes/opt/opt_expr.cc | 120 | ||||
-rw-r--r-- | passes/opt/opt_rmdff.cc | 26 | ||||
-rw-r--r-- | passes/techmap/abc.cc | 6 |
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" |