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(" -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]);
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Reference in New Issue