mirror of https://github.com/YosysHQ/yosys.git
This commit is contained in:
commit
d57c85111f
|
@ -216,6 +216,7 @@ int main(int argc, char **argv)
|
|||
printf(" -D <header_id>[:<filename>]\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(" Use 'ALL' as <header_id> 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:
|
||||
|
|
|
@ -41,6 +41,7 @@ YOSYS_NAMESPACE_BEGIN
|
|||
std::vector<FILE*> log_files;
|
||||
std::vector<std::ostream*> log_streams;
|
||||
std::map<std::string, std::set<std::string>> 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());
|
||||
|
|
|
@ -48,6 +48,7 @@ struct log_cmd_error_exception { };
|
|||
extern std::vector<FILE*> log_files;
|
||||
extern std::vector<std::ostream*> log_streams;
|
||||
extern std::map<std::string, std::set<std::string>> log_hdump;
|
||||
extern bool log_hdump_all;
|
||||
extern FILE *log_errfile;
|
||||
extern SHA1 *log_hasher;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ struct proc_dlatch_db_t
|
|||
Module *module;
|
||||
SigMap sigmap;
|
||||
|
||||
dict<Cell*, vector<SigBit>> mux_srcbits;
|
||||
dict<SigBit, pair<Cell*, int>> mux_drivers;
|
||||
dict<SigBit, int> 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*, 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())
|
||||
|
@ -58,6 +73,42 @@ struct proc_dlatch_db_t
|
|||
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
|
||||
{
|
||||
// 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];
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
@ -53,6 +42,10 @@ struct PrepPass : public Pass {
|
|||
log(" -top <module>\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");
|
||||
|
@ -63,31 +56,23 @@ 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 <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<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;
|
||||
std::string run_from, run_to;
|
||||
top_module.clear();
|
||||
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;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
|
@ -107,6 +92,10 @@ struct PrepPass : public Pass {
|
|||
}
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-flatten") {
|
||||
flatten = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nordff") {
|
||||
memory_opts += " -nordff";
|
||||
continue;
|
||||
|
@ -118,41 +107,54 @@ 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 <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;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
|
|
|
@ -41,6 +41,10 @@ struct SynthPass : public ScriptPass
|
|||
log(" -top <module>\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 <file>\n");
|
||||
log(" passed to 'fsm_recode' via 'fsm'\n");
|
||||
log("\n");
|
||||
|
@ -68,8 +72,8 @@ struct SynthPass : public ScriptPass
|
|||
log("\n");
|
||||
}
|
||||
|
||||
std::string top_module, fsm_opts, memory_opts;
|
||||
bool noalumacc, nofsm, noabc;
|
||||
string top_module, fsm_opts, memory_opts;
|
||||
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 <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");
|
||||
|
|
Loading…
Reference in New Issue