This commit is contained in:
Andrew Zonenberg 2016-04-24 22:11:56 -07:00
commit d57c85111f
6 changed files with 169 additions and 78 deletions

View File

@ -216,6 +216,7 @@ int main(int argc, char **argv)
printf(" -D <header_id>[:<filename>]\n"); printf(" -D <header_id>[:<filename>]\n");
printf(" dump the design when printing the specified log header to a file.\n"); printf(" dump the design when printing the specified log header to a file.\n");
printf(" yosys_dump_<header_id>.il is used as filename if none is specified.\n"); printf(" yosys_dump_<header_id>.il is used as filename if none is specified.\n");
printf(" Use 'ALL' as <header_id> to dump at every header.\n");
printf("\n"); printf("\n");
printf(" -V\n"); printf(" -V\n");
printf(" print version information and exit\n"); printf(" print version information and exit\n");
@ -322,6 +323,15 @@ int main(int argc, char **argv)
case 'D': case 'D':
{ {
auto args = split_tokens(optarg, ":"); auto args = split_tokens(optarg, ":");
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) if (GetSize(args) == 1)
args.push_back("yosys_dump_" + args[0] + ".il"); args.push_back("yosys_dump_" + args[0] + ".il");
if (GetSize(args) != 2) { if (GetSize(args) != 2) {
@ -330,6 +340,7 @@ int main(int argc, char **argv)
} }
log_hdump[args[0]].insert(args[1]); log_hdump[args[0]].insert(args[1]);
} }
}
break; break;
default: default:
fprintf(stderr, "Run '%s -h' for help.\n", argv[0]); fprintf(stderr, "Run '%s -h' for help.\n", argv[0]);

View File

@ -41,6 +41,7 @@ YOSYS_NAMESPACE_BEGIN
std::vector<FILE*> log_files; std::vector<FILE*> log_files;
std::vector<std::ostream*> log_streams; std::vector<std::ostream*> log_streams;
std::map<std::string, std::set<std::string>> log_hdump; std::map<std::string, std::set<std::string>> log_hdump;
bool log_hdump_all = false;
FILE *log_errfile = NULL; FILE *log_errfile = NULL;
SHA1 *log_hasher = NULL; SHA1 *log_hasher = NULL;
@ -159,6 +160,9 @@ void logv_header(RTLIL::Design *design, const char *format, va_list ap)
logv(format, ap); logv(format, ap);
log_flush(); log_flush();
if (log_hdump_all)
log_hdump[header_id].insert("yosys_dump_" + header_id + ".il");
if (log_hdump.count(header_id) && design != nullptr) if (log_hdump.count(header_id) && design != nullptr)
for (auto &filename : log_hdump.at(header_id)) { for (auto &filename : log_hdump.at(header_id)) {
log("Dumping current design to '%s'.\n", filename.c_str()); log("Dumping current design to '%s'.\n", filename.c_str());

View File

@ -48,6 +48,7 @@ struct log_cmd_error_exception { };
extern std::vector<FILE*> log_files; extern std::vector<FILE*> log_files;
extern std::vector<std::ostream*> log_streams; extern std::vector<std::ostream*> log_streams;
extern std::map<std::string, std::set<std::string>> log_hdump; extern std::map<std::string, std::set<std::string>> log_hdump;
extern bool log_hdump_all;
extern FILE *log_errfile; extern FILE *log_errfile;
extern SHA1 *log_hasher; extern SHA1 *log_hasher;

View File

@ -33,6 +33,7 @@ struct proc_dlatch_db_t
Module *module; Module *module;
SigMap sigmap; SigMap sigmap;
dict<Cell*, vector<SigBit>> mux_srcbits;
dict<SigBit, pair<Cell*, int>> mux_drivers; dict<SigBit, pair<Cell*, int>> mux_drivers;
dict<SigBit, int> sigusers; dict<SigBit, int> sigusers;
@ -40,10 +41,24 @@ struct proc_dlatch_db_t
{ {
for (auto cell : module->cells()) for (auto cell : module->cells())
{ {
if (cell->type.in("$mux", "$pmux")) { if (cell->type.in("$mux", "$pmux"))
{
auto sig_y = sigmap(cell->getPort("\\Y")); auto sig_y = sigmap(cell->getPort("\\Y"));
for (int i = 0; i < GetSize(sig_y); i++) for (int i = 0; i < GetSize(sig_y); i++)
mux_drivers[sig_y[i]] = pair<Cell*, int>(cell, i); mux_drivers[sig_y[i]] = pair<Cell*, int>(cell, i);
pool<SigBit> 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<SigBit> 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()) for (auto &conn : cell->connections())
@ -58,6 +73,42 @@ struct proc_dlatch_db_t
sigusers[bit]++; sigusers[bit]++;
} }
bool quickcheck(const SigSpec &haystack, const SigSpec &needle)
{
pool<SigBit> haystack_bits = sigmap(haystack).to_sigbit_pool();
pool<SigBit> needle_bits = sigmap(needle).to_sigbit_pool();
pool<Cell*> cells_queue, cells_visited;
pool<SigBit> 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 struct rule_node_t
{ {
// a node is true if "signal" equals "match" and [any // 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; continue;
} }
for (auto ss : sr->actions) { for (auto ss : sr->actions)
{
db.sigmap.apply(ss.first); db.sigmap.apply(ss.first);
db.sigmap.apply(ss.second); 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++) for (int i = 0; i < GetSize(ss.first); i++)
latches_out_in[ss.first[i]] = ss.second[i]; latches_out_in[ss.first[i]] = ss.second[i];
} }

View File

@ -25,22 +25,11 @@
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN 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) { PrepPass() : ScriptPass("prep", "generic synthesis script") { }
active = (label == run_from);
} else {
if (label == run_from)
active = true;
if (label == run_to)
active = false;
}
return active;
}
struct PrepPass : public Pass { virtual void help() YS_OVERRIDE
PrepPass() : Pass("prep", "generic synthesis script") { }
virtual void help()
{ {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n"); log("\n");
@ -53,6 +42,10 @@ struct PrepPass : public Pass {
log(" -top <module>\n"); log(" -top <module>\n");
log(" use the specified module as top module (default='top')\n"); log(" use the specified module as top module (default='top')\n");
log("\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(" -nordff\n");
log(" passed to 'memory_dff'. prohibits merging of FFs into memory read ports\n"); log(" passed to 'memory_dff'. prohibits merging of FFs into memory read ports\n");
log("\n"); log("\n");
@ -63,31 +56,23 @@ struct PrepPass : public Pass {
log("\n"); log("\n");
log("\n"); log("\n");
log("The following commands are executed by this synthesis command:\n"); log("The following commands are executed by this synthesis command:\n");
log("\n"); help_script();
log(" begin:\n");
log(" hierarchy -check [-top <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");
log("\n"); log("\n");
} }
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
string top_module, fsm_opts, memory_opts;
bool flatten;
virtual void clear_flags() YS_OVERRIDE
{ {
std::string top_module, memory_opts; top_module.clear();
std::string run_from, run_to; memory_opts.clear();
flatten = false;
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
string run_from, run_to;
size_t argidx; size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) for (argidx = 1; argidx < args.size(); argidx++)
@ -107,6 +92,10 @@ struct PrepPass : public Pass {
} }
continue; continue;
} }
if (args[argidx] == "-flatten") {
flatten = true;
continue;
}
if (args[argidx] == "-nordff") { if (args[argidx] == "-nordff") {
memory_opts += " -nordff"; memory_opts += " -nordff";
continue; continue;
@ -118,41 +107,54 @@ struct PrepPass : public Pass {
if (!design->full_selection()) if (!design->full_selection())
log_cmd_error("This comannd only operates on fully selected designs!\n"); 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_header(design, "Executing PREP pass.\n");
log_push(); log_push();
if (check_label(active, run_from, run_to, "begin")) run_script(design, run_from, run_to);
{
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");
}
log_pop(); log_pop();
} }
virtual void script() YS_OVERRIDE
{
if (check_label("begin"))
{
if (help_mode) {
run("hierarchy -check [-top <top>]");
} 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()));
}
}
if (check_label("coarse"))
{
run("proc");
if (help_mode || flatten)
run("flatten", "(if -flatten)");
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; } PrepPass;
PRIVATE_NAMESPACE_END PRIVATE_NAMESPACE_END

View File

@ -41,6 +41,10 @@ struct SynthPass : public ScriptPass
log(" -top <module>\n"); log(" -top <module>\n");
log(" use the specified module as top module (default='top')\n"); log(" use the specified module as top module (default='top')\n");
log("\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 <file>\n"); log(" -encfile <file>\n");
log(" passed to 'fsm_recode' via 'fsm'\n"); log(" passed to 'fsm_recode' via 'fsm'\n");
log("\n"); log("\n");
@ -68,8 +72,8 @@ struct SynthPass : public ScriptPass
log("\n"); log("\n");
} }
std::string top_module, fsm_opts, memory_opts; string top_module, fsm_opts, memory_opts;
bool noalumacc, nofsm, noabc; bool flatten, noalumacc, nofsm, noabc;
virtual void clear_flags() YS_OVERRIDE virtual void clear_flags() YS_OVERRIDE
{ {
@ -77,6 +81,7 @@ struct SynthPass : public ScriptPass
fsm_opts.clear(); fsm_opts.clear();
memory_opts.clear(); memory_opts.clear();
flatten = false;
noalumacc = false; noalumacc = false;
nofsm = false; nofsm = false;
noabc = false; noabc = false;
@ -109,6 +114,10 @@ struct SynthPass : public ScriptPass
} }
continue; continue;
} }
if (args[argidx] == "-flatten") {
flatten = true;
continue;
}
if (args[argidx] == "-nofsm") { if (args[argidx] == "-nofsm") {
nofsm = true; nofsm = true;
continue; continue;
@ -147,9 +156,12 @@ struct SynthPass : public ScriptPass
if (help_mode) { if (help_mode) {
run("hierarchy -check [-top <top>]"); run("hierarchy -check [-top <top>]");
} else { } else {
if (top_module.empty()) if (top_module.empty()) {
run(stringf("hierarchy -check")); if (flatten)
run("hierarchy -check -auto-top");
else else
run("hierarchy -check");
} else
run(stringf("hierarchy -check -top %s", top_module.c_str())); run(stringf("hierarchy -check -top %s", top_module.c_str()));
} }
} }
@ -157,6 +169,8 @@ struct SynthPass : public ScriptPass
if (check_label("coarse")) if (check_label("coarse"))
{ {
run("proc"); run("proc");
if (help_mode || flatten)
run("flatten", "(if -flatten)");
run("opt_expr"); run("opt_expr");
run("opt_clean"); run("opt_clean");
run("check"); run("check");