diff options
author | Clifford Wolf <clifford@clifford.at> | 2015-02-25 23:01:54 +0100 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2015-02-25 23:01:54 +0100 |
commit | 27a918eadf11cfe6cfe0eead022c8ff3336a855e (patch) | |
tree | 2e203f109da77bb50c88bb0cd4bcb52cc4d424ba | |
parent | 331f8b8d0ba2c11aac89f15622b23a0284c538d7 (diff) | |
parent | 3fe18c26cd020b31012e465c5a8b1db0abe64182 (diff) | |
download | yosys-27a918eadf11cfe6cfe0eead022c8ff3336a855e.tar.gz yosys-27a918eadf11cfe6cfe0eead022c8ff3336a855e.tar.bz2 yosys-27a918eadf11cfe6cfe0eead022c8ff3336a855e.zip |
Merge branch 'master' of github.com:cliffordwolf/yosys
-rw-r--r-- | README | 3 | ||||
-rw-r--r-- | passes/techmap/techmap.cc | 65 |
2 files changed, 54 insertions, 14 deletions
@@ -288,6 +288,9 @@ Verilog Attributes and non-standard features Setting the "keep" attribute on a module has the same effect as setting it on all instances of the module. +- The "keep_hierarchy" attribute on cells and modules keeps the "flatten" + command from flattening the indicated cells and modules. + - The "init" attribute on wires is set by the frontend when a register is initialized "FPGA-style" with 'reg foo = val'. It can be used during synthesis to add the necessary reset logic. diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 87e736bda..ab748ed74 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -68,6 +68,10 @@ struct TechmapWorker std::set<RTLIL::Module*, RTLIL::IdString::compare_ptr_by_name<RTLIL::Module>> module_queue; dict<Module*, SigMap> sigmaps; + pool<IdString> flatten_do_list; + pool<IdString> flatten_done_list; + pool<Cell*> flatten_keep_list; + struct TechmapWireData { RTLIL::Wire *wire; RTLIL::SigSpec value; @@ -323,6 +327,22 @@ struct TechmapWorker continue; } + if (flatten_mode) { + bool keepit = cell->get_bool_attribute("\\keep_hierarchy"); + for (auto &tpl_name : celltypeMap.at(cell_type)) + if (map->modules_[tpl_name]->get_bool_attribute("\\keep_hierarchy")) + keepit = true; + if (keepit) { + if (!flatten_keep_list[cell]) { + log("Keeping %s.%s (found keep_hierarchy property).\n", log_id(module), log_id(cell)); + flatten_keep_list.insert(cell); + } + if (!flatten_done_list[cell->type]) + flatten_do_list.insert(cell->type); + continue; + } + } + for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = sigmap(conn.second); @@ -1059,6 +1079,9 @@ struct FlattenPass : public Pass { log("pass is very simmilar to the 'techmap' pass. The only difference is that this\n"); log("pass is using the current design as mapping library.\n"); log("\n"); + log("Cells and/or modules with the 'keep_hiearchy' attribute set will not be\n"); + log("flattened by this command.\n"); + log("\n"); } virtual void execute(std::vector<std::string> args, RTLIL::Design *design) { @@ -1071,8 +1094,8 @@ struct FlattenPass : public Pass { worker.flatten_mode = true; std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap; - for (auto &it : design->modules_) - celltypeMap[it.first].insert(it.first); + for (auto module : design->modules()) + celltypeMap[module->name].insert(module->name); RTLIL::Module *top_mod = NULL; if (design->full_selection()) @@ -1080,26 +1103,40 @@ struct FlattenPass : public Pass { if (mod->get_bool_attribute("\\top")) top_mod = mod; - bool did_something = true; std::set<RTLIL::Cell*> handled_cells; - while (did_something) { - did_something = false; - if (top_mod != NULL) { - if (worker.techmap_module(design, top_mod, design, handled_cells, celltypeMap, false)) - did_something = true; - } else { - for (auto mod : vector<Module*>(design->modules())) - if (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false)) - did_something = true; + if (top_mod != NULL) { + worker.flatten_do_list.insert(top_mod->name); + while (!worker.flatten_do_list.empty()) { + auto mod = design->module(*worker.flatten_do_list.begin()); + while (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false)) { } + worker.flatten_done_list.insert(mod->name); + worker.flatten_do_list.erase(mod->name); } + } else { + for (auto mod : vector<Module*>(design->modules())) + while (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false)) { } } log("No more expansions possible.\n"); - if (top_mod != NULL) { + if (top_mod != NULL) + { + pool<RTLIL::IdString> used_modules, new_used_modules; + new_used_modules.insert(top_mod->name); + while (!new_used_modules.empty()) { + pool<RTLIL::IdString> queue; + queue.swap(new_used_modules); + for (auto modname : queue) + used_modules.insert(modname); + for (auto modname : queue) + for (auto cell : design->module(modname)->cells()) + if (design->module(cell->type) && !used_modules[cell->type]) + new_used_modules.insert(cell->type); + } + dict<RTLIL::IdString, RTLIL::Module*> new_modules; for (auto mod : vector<Module*>(design->modules())) - if (mod == top_mod || mod->get_bool_attribute("\\blackbox")) { + if (used_modules[mod->name] || mod->get_bool_attribute("\\blackbox")) { new_modules[mod->name] = mod; } else { log("Deleting now unused module %s.\n", log_id(mod)); |