From 77aa2031e7e93b3d91b7594ad21d84e946b7cb04 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 24 Apr 2016 00:48:06 +0200 Subject: [PATCH 1/4] Converted "prep" to ScriptPass --- techlibs/common/prep.cc | 117 +++++++++++++++++---------------------- techlibs/common/synth.cc | 2 +- 2 files changed, 53 insertions(+), 66 deletions(-) diff --git a/techlibs/common/prep.cc b/techlibs/common/prep.cc index 255306488..9f1b7763c 100644 --- a/techlibs/common/prep.cc +++ b/techlibs/common/prep.cc @@ -25,22 +25,11 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -bool check_label(bool &active, std::string run_from, std::string run_to, std::string label) +struct PrepPass : public ScriptPass { - if (!run_from.empty() && run_from == run_to) { - active = (label == run_from); - } else { - if (label == run_from) - active = true; - if (label == run_to) - active = false; - } - return active; -} + PrepPass() : ScriptPass("prep", "generic synthesis script") { } -struct PrepPass : public Pass { - PrepPass() : Pass("prep", "generic synthesis script") { } - virtual void help() + virtual void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -63,31 +52,21 @@ struct PrepPass : public Pass { log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); - log("\n"); - log(" begin:\n"); - log(" hierarchy -check [-top ]\n"); - log("\n"); - log(" prep:\n"); - log(" proc\n"); - log(" opt_expr -keepdc\n"); - log(" opt_clean\n"); - log(" check\n"); - log(" opt -keepdc\n"); - log(" wreduce\n"); - log(" memory_dff [-nordff]\n"); - log(" opt_clean\n"); - log(" memory_collect\n"); - log(" opt -keepdc -fast\n"); - log("\n"); - log(" check:\n"); - log(" stat\n"); - log(" check\n"); + help_script(); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + + string top_module, fsm_opts, memory_opts; + + virtual void clear_flags() YS_OVERRIDE { - std::string top_module, memory_opts; - std::string run_from, run_to; + top_module.clear(); + memory_opts.clear(); + } + + virtual void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + string run_from, run_to; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) @@ -118,41 +97,49 @@ struct PrepPass : public Pass { if (!design->full_selection()) log_cmd_error("This comannd only operates on fully selected designs!\n"); - bool active = run_from.empty(); - log_header(design, "Executing PREP pass.\n"); log_push(); - if (check_label(active, run_from, run_to, "begin")) - { - if (top_module.empty()) - Pass::call(design, stringf("hierarchy -check")); - else - Pass::call(design, stringf("hierarchy -check -top %s", top_module.c_str())); - } - - if (check_label(active, run_from, run_to, "coarse")) - { - Pass::call(design, "proc"); - Pass::call(design, "opt_expr -keepdc"); - Pass::call(design, "opt_clean"); - Pass::call(design, "check"); - Pass::call(design, "opt -keepdc"); - Pass::call(design, "wreduce"); - Pass::call(design, "memory_dff" + memory_opts); - Pass::call(design, "opt_clean"); - Pass::call(design, "memory_collect"); - Pass::call(design, "opt -keepdc -fast"); - } - - if (check_label(active, run_from, run_to, "check")) - { - Pass::call(design, "stat"); - Pass::call(design, "check"); - } + run_script(design, run_from, run_to); log_pop(); } + + virtual void script() YS_OVERRIDE + { + + if (check_label("begin")) + { + if (help_mode) { + run("hierarchy -check [-top ]"); + } else { + if (top_module.empty()) + run("hierarchy -check"); + else + run(stringf("hierarchy -check -top %s", top_module.c_str())); + } + } + + if (check_label("coarse")) + { + run("proc"); + run("opt_expr -keepdc"); + run("opt_clean"); + run("check"); + run("opt -keepdc"); + run("wreduce"); + run("memory_dff" + (help_mode ? " [-nordff]" : memory_opts)); + run("opt_clean"); + run("memory_collect"); + run("opt -keepdc -fast"); + } + + if (check_label("check")) + { + run("stat"); + run("check"); + } + } } PrepPass; PRIVATE_NAMESPACE_END diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index acfe888d9..949678f36 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -68,7 +68,7 @@ struct SynthPass : public ScriptPass log("\n"); } - std::string top_module, fsm_opts, memory_opts; + string top_module, fsm_opts, memory_opts; bool noalumacc, nofsm, noabc; virtual void clear_flags() YS_OVERRIDE From 09ffebb9959510cacdc04c926800223235f50313 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 24 Apr 2016 00:48:33 +0200 Subject: [PATCH 2/4] Added "prep -flatten" and "synth -flatten" --- techlibs/common/prep.cc | 21 ++++++++++++++++++--- techlibs/common/synth.cc | 22 ++++++++++++++++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/techlibs/common/prep.cc b/techlibs/common/prep.cc index 9f1b7763c..cdd908e04 100644 --- a/techlibs/common/prep.cc +++ b/techlibs/common/prep.cc @@ -42,6 +42,10 @@ struct PrepPass : public ScriptPass log(" -top \n"); log(" use the specified module as top module (default='top')\n"); log("\n"); + log(" -flatten\n"); + log(" flatten the design before synthesis. this will pass '-auto-top' to\n"); + log(" 'hierarchy' if no top module is specified.\n"); + log("\n"); log(" -nordff\n"); log(" passed to 'memory_dff'. prohibits merging of FFs into memory read ports\n"); log("\n"); @@ -57,11 +61,13 @@ struct PrepPass : public ScriptPass } string top_module, fsm_opts, memory_opts; + bool flatten; virtual void clear_flags() YS_OVERRIDE { top_module.clear(); memory_opts.clear(); + flatten = false; } virtual void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -86,6 +92,10 @@ struct PrepPass : public ScriptPass } continue; } + if (args[argidx] == "-flatten") { + flatten = true; + continue; + } if (args[argidx] == "-nordff") { memory_opts += " -nordff"; continue; @@ -113,9 +123,12 @@ struct PrepPass : public ScriptPass if (help_mode) { run("hierarchy -check [-top ]"); } else { - if (top_module.empty()) - run("hierarchy -check"); - else + if (top_module.empty()) { + if (flatten) + run("hierarchy -check -auto-top"); + else + run("hierarchy -check"); + } else run(stringf("hierarchy -check -top %s", top_module.c_str())); } } @@ -123,6 +136,8 @@ struct PrepPass : public ScriptPass if (check_label("coarse")) { run("proc"); + if (help_mode || flatten) + run("flatten", "(if -flatten)"); run("opt_expr -keepdc"); run("opt_clean"); run("check"); diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 949678f36..859a6606f 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -41,6 +41,10 @@ struct SynthPass : public ScriptPass log(" -top \n"); log(" use the specified module as top module (default='top')\n"); log("\n"); + log(" -flatten\n"); + log(" flatten the design before synthesis. this will pass '-auto-top' to\n"); + log(" 'hierarchy' if no top module is specified.\n"); + log("\n"); log(" -encfile \n"); log(" passed to 'fsm_recode' via 'fsm'\n"); log("\n"); @@ -69,7 +73,7 @@ struct SynthPass : public ScriptPass } string top_module, fsm_opts, memory_opts; - bool noalumacc, nofsm, noabc; + bool flatten, noalumacc, nofsm, noabc; virtual void clear_flags() YS_OVERRIDE { @@ -77,6 +81,7 @@ struct SynthPass : public ScriptPass fsm_opts.clear(); memory_opts.clear(); + flatten = false; noalumacc = false; nofsm = false; noabc = false; @@ -109,6 +114,10 @@ struct SynthPass : public ScriptPass } continue; } + if (args[argidx] == "-flatten") { + flatten = true; + continue; + } if (args[argidx] == "-nofsm") { nofsm = true; continue; @@ -147,9 +156,12 @@ struct SynthPass : public ScriptPass if (help_mode) { run("hierarchy -check [-top ]"); } else { - if (top_module.empty()) - run(stringf("hierarchy -check")); - else + if (top_module.empty()) { + if (flatten) + run("hierarchy -check -auto-top"); + else + run("hierarchy -check"); + } else run(stringf("hierarchy -check -top %s", top_module.c_str())); } } @@ -157,6 +169,8 @@ struct SynthPass : public ScriptPass if (check_label("coarse")) { run("proc"); + if (help_mode || flatten) + run("flatten", "(if -flatten)"); run("opt_expr"); run("opt_clean"); run("check"); From 9aa4b3309c35d842e2b1a04172745a5e34a3c445 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 24 Apr 2016 17:12:34 +0200 Subject: [PATCH 3/4] Added "yosys -D ALL" --- kernel/driver.cc | 23 +++++++++++++++++------ kernel/log.cc | 4 ++++ kernel/log.h | 1 + 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 0844eaa2e..45cdd461d 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -216,6 +216,7 @@ int main(int argc, char **argv) printf(" -D [:]\n"); printf(" dump the design when printing the specified log header to a file.\n"); printf(" yosys_dump_.il is used as filename if none is specified.\n"); + printf(" Use 'ALL' as to dump at every header.\n"); printf("\n"); printf(" -V\n"); printf(" print version information and exit\n"); @@ -322,13 +323,23 @@ int main(int argc, char **argv) case 'D': { auto args = split_tokens(optarg, ":"); - if (GetSize(args) == 1) - args.push_back("yosys_dump_" + args[0] + ".il"); - if (GetSize(args) != 2) { - fprintf(stderr, "Invalid number of tokens in -D.\n"); - exit(1); + if (!args.empty() && args[0] == "ALL") { + if (GetSize(args) != 1) { + fprintf(stderr, "Invalid number of tokens in -D ALL.\n"); + exit(1); + } + log_hdump_all = true; + } else { + if (!args.empty() && !args[0].empty() && args[0].back() == '.') + args[0].pop_back(); + if (GetSize(args) == 1) + args.push_back("yosys_dump_" + args[0] + ".il"); + if (GetSize(args) != 2) { + fprintf(stderr, "Invalid number of tokens in -D.\n"); + exit(1); + } + log_hdump[args[0]].insert(args[1]); } - log_hdump[args[0]].insert(args[1]); } break; default: diff --git a/kernel/log.cc b/kernel/log.cc index f2b343dff..fe84184a5 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -41,6 +41,7 @@ YOSYS_NAMESPACE_BEGIN std::vector log_files; std::vector log_streams; std::map> log_hdump; +bool log_hdump_all = false; FILE *log_errfile = NULL; SHA1 *log_hasher = NULL; @@ -159,6 +160,9 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap) logv(format, ap); log_flush(); + if (log_hdump_all) + log_hdump[header_id].insert("yosys_dump_" + header_id + ".il"); + if (log_hdump.count(header_id) && design != nullptr) for (auto &filename : log_hdump.at(header_id)) { log("Dumping current design to '%s'.\n", filename.c_str()); diff --git a/kernel/log.h b/kernel/log.h index 6090f8273..c265bae42 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -48,6 +48,7 @@ struct log_cmd_error_exception { }; extern std::vector log_files; extern std::vector log_streams; extern std::map> log_hdump; +extern bool log_hdump_all; extern FILE *log_errfile; extern SHA1 *log_hasher; From b1d6f05fa2156017f50383d01d49342c8ec5e209 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 24 Apr 2016 19:29:56 +0200 Subject: [PATCH 4/4] Fixed performance bug in proc_dlatch --- passes/proc/proc_dlatch.cc | 63 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc index c339ac682..92bf8906d 100644 --- a/passes/proc/proc_dlatch.cc +++ b/passes/proc/proc_dlatch.cc @@ -33,6 +33,7 @@ struct proc_dlatch_db_t Module *module; SigMap sigmap; + dict> mux_srcbits; dict> mux_drivers; dict sigusers; @@ -40,10 +41,24 @@ struct proc_dlatch_db_t { for (auto cell : module->cells()) { - if (cell->type.in("$mux", "$pmux")) { + if (cell->type.in("$mux", "$pmux")) + { auto sig_y = sigmap(cell->getPort("\\Y")); for (int i = 0; i < GetSize(sig_y); i++) mux_drivers[sig_y[i]] = pair(cell, i); + + pool mux_srcbits_pool; + for (auto bit : sigmap(cell->getPort("\\A"))) + mux_srcbits_pool.insert(bit); + for (auto bit : sigmap(cell->getPort("\\B"))) + mux_srcbits_pool.insert(bit); + + vector mux_srcbits_vec; + for (auto bit : mux_srcbits_pool) + if (bit.wire != nullptr) + mux_srcbits_vec.push_back(bit); + + mux_srcbits[cell].swap(mux_srcbits_vec); } for (auto &conn : cell->connections()) @@ -58,6 +73,42 @@ struct proc_dlatch_db_t sigusers[bit]++; } + bool quickcheck(const SigSpec &haystack, const SigSpec &needle) + { + pool haystack_bits = sigmap(haystack).to_sigbit_pool(); + pool needle_bits = sigmap(needle).to_sigbit_pool(); + + pool cells_queue, cells_visited; + pool bits_queue, bits_visited; + + bits_queue = haystack_bits; + while (!bits_queue.empty()) + { + for (auto &bit : bits_queue) { + auto it = mux_drivers.find(bit); + if (it != mux_drivers.end()) + if (!cells_visited.count(it->second.first)) + cells_queue.insert(it->second.first); + bits_visited.insert(bit); + } + + bits_queue.clear(); + + for (auto c : cells_queue) { + for (auto bit : mux_srcbits[c]) { + if (needle_bits.count(bit)) + return true; + if (!bits_visited.count(bit)) + bits_queue.insert(bit); + } + } + + cells_queue.clear(); + } + + return false; + } + struct rule_node_t { // a node is true if "signal" equals "match" and [any @@ -218,9 +269,17 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc) continue; } - for (auto ss : sr->actions) { + for (auto ss : sr->actions) + { db.sigmap.apply(ss.first); db.sigmap.apply(ss.second); + + if (!db.quickcheck(ss.second, ss.first)) { + nolatches_bits.first.append(ss.first); + nolatches_bits.second.append(ss.second); + continue; + } + for (int i = 0; i < GetSize(ss.first); i++) latches_out_in[ss.first[i]] = ss.second[i]; }