From: Clifford Wolf Date: Fri, 19 Dec 2014 23:44:03 +0000 (+0100) Subject: Added DFFE support to "abc" pass X-Git-Tag: yosys-0.5~242 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f7b323196fbd1c2f35ab034b33f9617f7428cf31;p=yosys.git Added DFFE support to "abc" pass --- diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc index 9d6d94579..b1a96dda4 100644 --- a/passes/abc/abc.cc +++ b/passes/abc/abc.cc @@ -95,8 +95,8 @@ RTLIL::Module *module; std::vector signal_list; std::map signal_map; -bool clk_polarity; -RTLIL::SigSpec clk_sig; +bool clk_polarity, en_polarity; +RTLIL::SigSpec clk_sig, en_sig; 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) { @@ -147,7 +147,24 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) return; if (clk_sig != assign_map(cell->getPort("\\C"))) return; + goto matching_dff; + } + if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_") + { + if (clk_polarity != (cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_")) + return; + if (en_polarity != (cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_")) + return; + if (clk_sig != assign_map(cell->getPort("\\C"))) + return; + if (en_sig != assign_map(cell->getPort("\\E"))) + return; + goto matching_dff; + } + + if (0) { + matching_dff: RTLIL::SigSpec sig_d = cell->getPort("\\D"); RTLIL::SigSpec sig_q = cell->getPort("\\Q"); @@ -556,6 +573,9 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin clk_polarity = true; clk_sig = RTLIL::SigSpec(); + en_polarity = true; + en_sig = RTLIL::SigSpec(); + std::string tempdir_name = "/tmp/yosys-abc-XXXXXX"; if (!cleanup) tempdir_name[0] = tempdir_name[4] = '_'; @@ -607,6 +627,17 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin fclose(f); if (clk_str.empty()) { + if (clk_str.find(',') != std::string::npos) { + int pos = clk_str.find(','); + std::string en_str = clk_str.substr(pos+1); + clk_str = clk_str.substr(0, pos); + if (en_str[0] == '!') { + en_polarity = false; + en_str = en_str.substr(1); + } + if (module->wires_.count(RTLIL::escape_id(en_str)) != 0) + en_sig = assign_map(RTLIL::SigSpec(module->wires_.at(RTLIL::escape_id(en_str)), 0)); + } if (clk_str[0] == '!') { clk_polarity = false; clk_str = clk_str.substr(1); @@ -618,19 +649,34 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (dff_mode && clk_sig.size() == 0) { int best_dff_counter = 0; - std::map, int> dff_counters; + typedef std::tuple clkdomain_t; + std::map dff_counters; for (auto &it : module->cells_) { RTLIL::Cell *cell = it.second; - if (cell->type != "$_DFF_N_" && cell->type != "$_DFF_P_") + clkdomain_t key; + + if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_") + { + key = clkdomain_t(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C")), true, RTLIL::SigSpec()); + } + else + if (cell->type == "$_DFFE_NN_" || cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_") + { + bool this_clk_pol = cell->type == "$_DFFE_PN_" || cell->type == "$_DFFE_PP_"; + bool this_en_pol = cell->type == "$_DFFE_NP_" || cell->type == "$_DFFE_PP_"; + key = clkdomain_t(this_clk_pol, assign_map(cell->getPort("\\C")), this_en_pol, assign_map(cell->getPort("\\E"))); + } + else continue; - std::pair key(cell->type == "$_DFF_P_", assign_map(cell->getPort("\\C"))); if (++dff_counters[key] > best_dff_counter) { best_dff_counter = dff_counters[key]; - clk_polarity = key.first; - clk_sig = key.second; + clk_polarity = std::get<0>(key); + clk_sig = std::get<1>(key); + en_polarity = std::get<2>(key); + en_sig = std::get<3>(key); } } } @@ -638,13 +684,20 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin if (dff_mode || !clk_str.empty()) { if (clk_sig.size() == 0) log("No (matching) clock domain found. Not extracting any FF cells.\n"); - else - log("Found (matching) %s clock domain: %s\n", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); + else { + log("Found (matching) %s clock domain: %s", clk_polarity ? "posedge" : "negedge", log_signal(clk_sig)); + if (en_sig.size() != 0) + log(", enabled by %s%s", en_polarity ? "" : "!", log_signal(en_sig)); + log("\n"); + } } if (clk_sig.size() != 0) mark_port(clk_sig); + if (en_sig.size() != 0) + mark_port(en_sig); + std::vector cells; cells.reserve(module->cells_.size()); for (auto &it : module->cells_) @@ -899,7 +952,14 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } if (c->type == "\\DFF") { log_assert(clk_sig.size() == 1); - RTLIL::Cell *cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + RTLIL::Cell *cell; + if (en_sig.size() == 0) { + cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + } else { + 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("\\E", en_sig); + } cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)])); cell->setPort("\\C", clk_sig); @@ -924,7 +984,14 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin } if (c->type == "\\_dff_") { log_assert(clk_sig.size() == 1); - RTLIL::Cell *cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + RTLIL::Cell *cell; + if (en_sig.size() == 0) { + cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_"); + } else { + 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("\\E", en_sig); + } cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)])); cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)])); cell->setPort("\\C", clk_sig);