From 5643c1b8c5fbe1a31fcb4027ddbe096e74439cbf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Feb 2020 08:34:13 -0800 Subject: abc9_ops: -prep_lut and -write_lut to auto-generate LUT library --- passes/techmap/abc9.cc | 36 ++++++++++++++++++-- passes/techmap/abc9_ops.cc | 85 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 115 insertions(+), 6 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 5ae2fb22a..0e2ca80c7 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -145,6 +145,11 @@ struct Abc9Pass : public ScriptPass log(" generate netlist using luts. Use the specified costs for luts with 1,\n"); log(" 2, 3, .. inputs.\n"); log("\n"); + log(" -maxlut \n"); + log(" when auto-generating the lut library, discard all luts equal to or\n"); + log(" greater than this size (applicable when neither -lut nor -luts is\n"); + log(" specified).\n"); + log("\n"); log(" -dff\n"); log(" also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n"); log(" domains are marked as such and automatically partitioned by ABC.\n"); @@ -175,6 +180,8 @@ struct Abc9Pass : public ScriptPass std::stringstream exe_cmd; bool dff_mode, cleanup; + bool lut_mode; + int maxlut; std::string box_file; void clear_flags() YS_OVERRIDE @@ -183,6 +190,8 @@ struct Abc9Pass : public ScriptPass exe_cmd << "abc9_exe"; dff_mode = false; cleanup = true; + lut_mode = false; + maxlut = 0; box_file.clear(); } @@ -204,9 +213,11 @@ struct Abc9Pass : public ScriptPass for (argidx = 1; argidx < args.size(); argidx++) { std::string arg = args[argidx]; if ((arg == "-exe" || arg == "-script" || arg == "-D" || - /* arg == "-S" || */ arg == "-lut" || arg == "-luts" || + /*arg == "-S" ||*/ arg == "-lut" || arg == "-luts" || /*arg == "-box" ||*/ arg == "-W") && argidx+1 < args.size()) { + if (arg == "-lut" || arg == "-luts") + lut_mode = true; exe_cmd << " " << arg << " " << args[++argidx]; continue; } @@ -228,6 +239,10 @@ struct Abc9Pass : public ScriptPass box_file = args[++argidx]; continue; } + if (arg == "-maxlut" && argidx+1 < args.size()) { + maxlut = atoi(args[++argidx].c_str()); + continue; + } if (arg == "-run" && argidx+1 < args.size()) { size_t pos = args[argidx+1].find(':'); if (pos == std::string::npos) @@ -240,6 +255,9 @@ struct Abc9Pass : public ScriptPass } extra_args(args, argidx, design); + if (maxlut && lut_mode) + log_cmd_error("abc9 '-maxlut' option only applicable without '-lut' nor '-luts'.\n"); + log_assert(design); if (design->selected_modules().empty()) { log_warning("No modules selected for ABC9 techmapping.\n"); @@ -263,6 +281,10 @@ struct Abc9Pass : public ScriptPass run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)"); else run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""), "(option for -dff)"); + if (help_mode) + run("abc9_ops -prep_lut ", "(skip if -lut or -luts)"); + else if (!lut_mode) + run(stringf("abc9_ops -prep_lut %d", maxlut)); run("select -set abc9_holes A:abc9_holes"); run("flatten -wb @abc9_holes"); run("techmap @abc9_holes"); @@ -276,9 +298,10 @@ struct Abc9Pass : public ScriptPass if (check_label("map")) { if (help_mode) { run("foreach module in selection"); + run(" abc9_ops -write_lut /input.lut", "(skip if '-lut' or '-luts')"); run(" abc9_ops -write_box [|(null)] /input.box"); run(" write_xaiger -map /input.sym /input.xaig"); - run(" abc9_exe [options] -cwd -box /input.box"); + run(" abc9_exe [options] -cwd [-lut /input.lut] -box /input.box"); run(" read_aiger -xaiger -wideports -module_name $abc9 -map /input.sym /output.aig"); run(" abc9_ops -reintegrate"); } @@ -304,6 +327,8 @@ struct Abc9Pass : public ScriptPass tempdir_name[0] = tempdir_name[4] = '_'; tempdir_name = make_temp_dir(tempdir_name); + if (!lut_mode) + run(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str())); if (box_file.empty()) run(stringf("abc9_ops -write_box (null) %s/input.box", tempdir_name.c_str())); else @@ -319,7 +344,12 @@ struct Abc9Pass : public ScriptPass active_design->scratchpad_get_int("write_xaiger.num_inputs"), num_outputs); if (num_outputs) { - run(stringf("%s -cwd %s -box %s/input.box", exe_cmd.str().c_str(), tempdir_name.c_str(), tempdir_name.c_str())); + std::string abc9_exe_cmd; + abc9_exe_cmd += stringf("%s -cwd %s", exe_cmd.str().c_str(), tempdir_name.c_str()); + if (!lut_mode) + abc9_exe_cmd += stringf(" -lut %s/input.lut", tempdir_name.c_str()); + abc9_exe_cmd += stringf(" -box %s/input.box", tempdir_name.c_str()); + run(abc9_exe_cmd); run(stringf("read_aiger -xaiger -wideports -module_name %s$abc9 -map %s/input.sym %s/output.aig", log_id(mod), tempdir_name.c_str(), tempdir_name.c_str())); run("abc9_ops -reintegrate"); } diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 54605f90e..cf6d5eabb 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -562,6 +562,56 @@ void prep_delays(RTLIL::Design *design) design->scratchpad_set_string("abc9_ops.box.flops", ss.str()); } +void prep_lut(RTLIL::Design *design, int maxlut) +{ + std::stringstream ss; + std::vector> table; + for (auto module : design->modules()) { + auto it = module->attributes.find(ID(abc9_lut)); + if (it == module->attributes.end()) + continue; + SigBit o; + std::vector specify; + for (auto cell : module->cells()) { + if (cell->type != ID($specify2)) + continue; + log_assert(cell->getParam(ID(SRC_WIDTH)) == 1); + log_assert(cell->getParam(ID(DST_WIDTH)) == 1); + SigBit d = cell->getPort(ID(DST)); + if (o == SigBit()) + o = d; + else + log_assert(o == d); + int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); + int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); + specify.push_back(std::max(rise_max,fall_max)); + } + if (maxlut && GetSize(specify) > maxlut) + continue; + std::sort(specify.begin(), specify.end()); + ss.str(""); + ss << "# " << module->name.str() << std::endl; + ss << GetSize(specify) << " " << it->second.as_int(); + for (auto i : specify) + ss << " " << i; + ss << std::endl; + table.emplace_back(GetSize(specify), ss.str()); + } + // ABC expects ascending size + std::sort(table.begin(), table.end()); + ss.str(""); + for (auto &i : table) + ss << i.second; + design->scratchpad_set_string("abc9_ops.lut_library", ss.str()); +} + +void write_lut(RTLIL::Module *module, const std::string &dst) { + std::ofstream ofs(dst); + log_assert(ofs.is_open()); + ofs << module->design->scratchpad_get_string("abc9_ops.lut_library"); + ofs.close(); +} + void write_box(RTLIL::Module *module, const std::string &src, const std::string &dst) { std::ofstream ofs(dst); log_assert(ofs.is_open()); @@ -1002,6 +1052,12 @@ struct Abc9OpsPass : public Pass { log(" compute the clock domain and initial value of each flop in the design.\n"); log(" process the '$holes' module to support clock-enable functionality.\n"); log("\n"); + log(" -prep_lut \n"); + log(" pre-compute the lut library.\n"); + log("\n"); + log(" -write_lut \n"); + log(" TODO.\n"); + log("\n"); log(" -write_box (|(null)) \n"); log(" copy the existing box file from (skip if '(null)') and append any\n"); log(" new box definitions.\n"); @@ -1021,8 +1077,11 @@ struct Abc9OpsPass : public Pass { bool mark_scc_mode = false; bool prep_dff_mode = false; bool prep_xaiger_mode = false; + bool prep_lut_mode = false; bool reintegrate_mode = false; bool dff_mode = false; + std::string write_lut_dst; + int maxlut = 0; std::string write_box_src, write_box_dst; size_t argidx; @@ -1048,6 +1107,19 @@ struct Abc9OpsPass : public Pass { prep_delays_mode = true; continue; } + if (arg == "-prep_lut" && argidx+1 < args.size()) { + prep_lut_mode = true; + maxlut = atoi(args[++argidx].c_str()); + continue; + } + if (arg == "-write_lut" && argidx+1 < args.size()) { + write_lut_dst = args[++argidx]; + rewrite_filename(write_lut_dst); + continue; + } + if (arg == "-maxlut" && argidx+1 < args.size()) { + continue; + } if (arg == "-write_box" && argidx+2 < args.size()) { write_box_src = args[++argidx]; write_box_dst = args[++argidx]; @@ -1067,16 +1139,21 @@ struct Abc9OpsPass : public Pass { } extra_args(args, argidx, design); - if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || !write_box_src.empty() || reintegrate_mode)) - log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff}, -write_box, -reintegrate must be specified.\n"); + if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || prep_lut_mode || !write_lut_dst.empty() || !write_box_dst.empty() || reintegrate_mode)) + log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff,lut}, -write_{lut,box}, -reintegrate must be specified.\n"); if (dff_mode && !prep_xaiger_mode) log_cmd_error("'-dff' option is only relevant for -prep_xaiger.\n"); + if (maxlut && !write_lut_dst.empty()) + log_cmd_error("'-maxlut' option is only relevant for -prep_lut.\n"); + if (check_mode) check(design); if (prep_delays_mode) prep_delays(design); + if (prep_lut_mode) + prep_lut(design, maxlut); for (auto mod : design->selected_modules()) { if (mod->get_bool_attribute("\\abc9_holes")) @@ -1090,7 +1167,9 @@ struct Abc9OpsPass : public Pass { if (!design->selected_whole_module(mod)) log_error("Can't handle partially selected module %s!\n", log_id(mod)); - if (!write_box_src.empty()) + if (!write_lut_dst.empty()) + write_lut(mod, write_lut_dst); + if (!write_box_dst.empty()) write_box(mod, write_box_src, write_box_dst); if (mark_scc_mode) mark_scc(mod); -- cgit v1.2.3 From 74f49b1f55e08c9939c9e0c8a1a5c0405f0d28c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Feb 2020 08:54:13 -0800 Subject: abc9_ops: -prep_box, to be called once --- passes/techmap/abc9.cc | 13 +++---- passes/techmap/abc9_ops.cc | 86 ++++++++++++++++++++++------------------------ 2 files changed, 49 insertions(+), 50 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 0e2ca80c7..fc82f0e5f 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -192,7 +192,7 @@ struct Abc9Pass : public ScriptPass cleanup = true; lut_mode = false; maxlut = 0; - box_file.clear(); + box_file = "(null)"; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -285,6 +285,10 @@ struct Abc9Pass : public ScriptPass run("abc9_ops -prep_lut ", "(skip if -lut or -luts)"); else if (!lut_mode) run(stringf("abc9_ops -prep_lut %d", maxlut)); + if (help_mode) + run("abc9_ops -prep_box [<-box>|(null)]"); + else + run(stringf("abc9_ops -prep_box %s", box_file.c_str())); run("select -set abc9_holes A:abc9_holes"); run("flatten -wb @abc9_holes"); run("techmap @abc9_holes"); @@ -299,7 +303,7 @@ struct Abc9Pass : public ScriptPass if (help_mode) { run("foreach module in selection"); run(" abc9_ops -write_lut /input.lut", "(skip if '-lut' or '-luts')"); - run(" abc9_ops -write_box [|(null)] /input.box"); + run(" abc9_ops -write_box /input.box"); run(" write_xaiger -map /input.sym /input.xaig"); run(" abc9_exe [options] -cwd [-lut /input.lut] -box /input.box"); run(" read_aiger -xaiger -wideports -module_name $abc9 -map /input.sym /output.aig"); @@ -329,10 +333,7 @@ struct Abc9Pass : public ScriptPass if (!lut_mode) run(stringf("abc9_ops -write_lut %s/input.lut", tempdir_name.c_str())); - if (box_file.empty()) - run(stringf("abc9_ops -write_box (null) %s/input.box", tempdir_name.c_str())); - else - run(stringf("abc9_ops -write_box %s %s/input.box", box_file.c_str(), tempdir_name.c_str())); + run(stringf("abc9_ops -write_box %s/input.box", tempdir_name.c_str())); run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str())); int num_outputs = active_design->scratchpad_get_int("write_xaiger.num_outputs"); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index cf6d5eabb..d08c42e3b 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -464,7 +464,6 @@ void prep_delays(RTLIL::Design *design) cells.emplace_back(cell); } - delays.clear(); for (auto cell : cells) { RTLIL::Module* inst_module = module->design->module(cell->type); log_assert(inst_module); @@ -515,17 +514,6 @@ void prep_delays(RTLIL::Design *design) } } } - - std::stringstream ss; - bool first = true; - for (auto d : delays) { - if (first) - first = false; - else - ss << " "; - ss << d; - } - module->attributes[ID(abc9_delays)] = ss.str(); } int flops_id = ABC9_FLOPS_BASE_ID; @@ -559,7 +547,14 @@ void prep_delays(RTLIL::Design *design) // Last input is 'abc9_ff.Q' ss << " 0" << std::endl << std::endl; } - design->scratchpad_set_string("abc9_ops.box.flops", ss.str()); + design->scratchpad_set_string("abc9_ops.box_library.flops", ss.str()); + + ss.str(""); + for (const int d : delays) { + ss << "$__ABC9_DELAY@" << d << " " << ABC9_DELAY_BASE_ID + d << " 0 1 1" << std::endl; + ss << d << std::endl; + } + design->scratchpad_set_string("abc9_ops.box_library.delays", ss.str()); } void prep_lut(RTLIL::Design *design, int maxlut) @@ -612,33 +607,31 @@ void write_lut(RTLIL::Module *module, const std::string &dst) { ofs.close(); } -void write_box(RTLIL::Module *module, const std::string &src, const std::string &dst) { - std::ofstream ofs(dst); - log_assert(ofs.is_open()); +void prep_box(RTLIL::Design *design, const std::string &src) +{ + std::stringstream ss; // Since ABC can only accept one box file, we have to copy // over the existing box file if (src != "(null)") { std::ifstream ifs(src); - ofs << ifs.rdbuf() << std::endl; + log_assert(ifs.is_open()); + ss << ifs.rdbuf() << std::endl; ifs.close(); } - ofs << module->design->scratchpad_get_string("abc9_ops.box.flops"); - - auto it = module->attributes.find(ID(abc9_delays)); - if (it != module->attributes.end()) { - for (const auto &tok : split_tokens(it->second.decode_string())) { - int d = atoi(tok.c_str()); - ofs << "$__ABC9_DELAY@" << d << " " << ABC9_DELAY_BASE_ID + d << " 0 1 1" << std::endl; - ofs << d << std::endl; - } - module->attributes.erase(it); - } + ss << design->scratchpad_get_string("abc9_ops.box_library.flops", ss.str()); + ss << design->scratchpad_get_string("abc9_ops.box_library.delays", ss.str()); + design->scratchpad_set_string("abc9_ops.box_library", ss.str()); +} +void write_box(RTLIL::Module *module, const std::string &dst) { + std::ofstream ofs(dst); + log_assert(ofs.is_open()); + ofs << module->design->scratchpad_get_string("abc9_ops.box_library"); + // ABC expects at least one box if (ofs.tellp() == 0) ofs << "(dummy) 1 0 0 0"; - ofs.close(); } @@ -1056,11 +1049,14 @@ struct Abc9OpsPass : public Pass { log(" pre-compute the lut library.\n"); log("\n"); log(" -write_lut \n"); - log(" TODO.\n"); + log(" write the pre-computed lut library to .\n"); log("\n"); - log(" -write_box (|(null)) \n"); - log(" copy the existing box file from (skip if '(null)') and append any\n"); - log(" new box definitions.\n"); + log(" -prep_box \n"); + log(" pre-compute the box library. copy the existing box file from (skip\n"); + log(" if '(null)').\n"); + log("\n"); + log(" -write_box \n"); + log(" write the pre-computed box library to .\n"); log("\n"); log(" -reintegrate\n"); log(" for each selected module, re-intergrate the module '$abc9'\n"); @@ -1082,7 +1078,7 @@ struct Abc9OpsPass : public Pass { bool dff_mode = false; std::string write_lut_dst; int maxlut = 0; - std::string write_box_src, write_box_dst; + std::string prep_box_src, write_box_dst; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -1112,18 +1108,21 @@ struct Abc9OpsPass : public Pass { maxlut = atoi(args[++argidx].c_str()); continue; } + if (arg == "-maxlut" && argidx+1 < args.size()) { + continue; + } if (arg == "-write_lut" && argidx+1 < args.size()) { write_lut_dst = args[++argidx]; rewrite_filename(write_lut_dst); continue; } - if (arg == "-maxlut" && argidx+1 < args.size()) { + if (arg == "-prep_box" && argidx+1 < args.size()) { + prep_box_src = args[++argidx]; + rewrite_filename(prep_box_src); continue; } - if (arg == "-write_box" && argidx+2 < args.size()) { - write_box_src = args[++argidx]; + if (arg == "-write_box" && argidx+1 < args.size()) { write_box_dst = args[++argidx]; - rewrite_filename(write_box_src); rewrite_filename(write_box_dst); continue; } @@ -1139,21 +1138,20 @@ struct Abc9OpsPass : public Pass { } extra_args(args, argidx, design); - if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || prep_lut_mode || !write_lut_dst.empty() || !write_box_dst.empty() || reintegrate_mode)) - log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff,lut}, -write_{lut,box}, -reintegrate must be specified.\n"); + if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || prep_lut_mode || !prep_box_src.empty() || !write_lut_dst.empty() || !write_box_dst.empty() || reintegrate_mode)) + log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff,lut,box}, -write_{lut,box}, -reintegrate must be specified.\n"); if (dff_mode && !prep_xaiger_mode) log_cmd_error("'-dff' option is only relevant for -prep_xaiger.\n"); - if (maxlut && !write_lut_dst.empty()) - log_cmd_error("'-maxlut' option is only relevant for -prep_lut.\n"); - if (check_mode) check(design); if (prep_delays_mode) prep_delays(design); if (prep_lut_mode) prep_lut(design, maxlut); + if (!prep_box_src.empty()) + prep_box(design, prep_box_src); for (auto mod : design->selected_modules()) { if (mod->get_bool_attribute("\\abc9_holes")) @@ -1170,7 +1168,7 @@ struct Abc9OpsPass : public Pass { if (!write_lut_dst.empty()) write_lut(mod, write_lut_dst); if (!write_box_dst.empty()) - write_box(mod, write_box_src, write_box_dst); + write_box(mod, write_box_dst); if (mark_scc_mode) mark_scc(mod); if (prep_dff_mode) -- cgit v1.2.3 From 3d6603792dbd36ccb572403815b78121a7ad80e8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Feb 2020 09:18:08 -0800 Subject: abc9_ops: assert on $specify2 properties --- passes/techmap/abc9_ops.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index d08c42e3b..52beae421 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -572,7 +572,10 @@ void prep_lut(RTLIL::Design *design, int maxlut) continue; log_assert(cell->getParam(ID(SRC_WIDTH)) == 1); log_assert(cell->getParam(ID(DST_WIDTH)) == 1); + SigBit s = cell->getPort(ID(SRC)); SigBit d = cell->getPort(ID(DST)); + log_assert(s.wire->port_input); + log_assert(d.wire->port_output); if (o == SigBit()) o = d; else -- cgit v1.2.3 From 0e7c55e2a73f47d7f179d434ba79dd9e2bf9045b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Feb 2020 11:38:49 -0800 Subject: Auto-generate .box/.lut files from specify blocks --- passes/techmap/abc9_ops.cc | 157 +++++++++++++++++++++++++++++++++------------ 1 file changed, 117 insertions(+), 40 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 52beae421..bbbbc45d0 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -23,9 +23,6 @@ #include "kernel/utils.h" #include "kernel/celltypes.h" -#define ABC9_FLOPS_BASE_ID 8000 -#define ABC9_DELAY_BASE_ID 9000 - USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -269,7 +266,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) if (abc9_flop && !dff) continue; - if ((inst_module && inst_module->attributes.count("\\abc9_box_id")) || abc9_flop) { + if ((inst_module && inst_module->get_bool_attribute("\\abc9_box")) || abc9_flop) { auto r = box_ports.insert(cell->type); if (r.second) { // Make carry in the last PI, and carry out the last PO @@ -350,7 +347,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) log_assert(cell); RTLIL::Module* box_module = design->module(cell->type); - if (!box_module || (!box_module->attributes.count("\\abc9_box_id") && !box_module->get_bool_attribute("\\abc9_flop"))) + if (!box_module || (!box_module->get_bool_attribute("\\abc9_box") && !box_module->get_bool_attribute("\\abc9_flop"))) continue; cell->attributes["\\abc9_box_seq"] = box_count++; @@ -431,7 +428,6 @@ void prep_xaiger(RTLIL::Module *module, bool dff) void prep_delays(RTLIL::Design *design) { - std::set delays; pool flops; std::vector cells; dict>> requireds_cache; @@ -459,7 +455,7 @@ void prep_delays(RTLIL::Design *design) continue; // because all flop required times // will be captured in the flop box } - if (inst_module->attributes.count(ID(abc9_box_id))) + if (inst_module->attributes.count(ID(abc9_box))) continue; cells.emplace_back(cell); } @@ -481,13 +477,11 @@ void prep_delays(RTLIL::Design *design) continue; if (it->second.flags == 0) { int delay = it->second.as_int(); - delays.insert(delay); requireds.emplace_back(delay); } else for (const auto &tok : split_tokens(it->second.decode_string())) { int delay = atoi(tok.c_str()); - delays.insert(delay); requireds.push_back(delay); } } @@ -516,12 +510,13 @@ void prep_delays(RTLIL::Design *design) } } - int flops_id = ABC9_FLOPS_BASE_ID; + int abc9_box_id = design->scratchpad_get_int("abc9_ops.box_id"); std::stringstream ss; for (auto flop_module : flops) { int num_inputs = 0, num_outputs = 0; for (auto port_name : flop_module->ports) { auto wire = flop_module->wire(port_name); + log_assert(GetSize(wire) == 1); if (wire->port_input) num_inputs++; if (wire->port_output) num_outputs++; } @@ -529,11 +524,27 @@ void prep_delays(RTLIL::Design *design) auto r = flop_module->attributes.insert(ID(abc9_box_id)); if (r.second) - r.first->second = flops_id++; + r.first->second = ++abc9_box_id; ss << log_id(flop_module) << " " << r.first->second.as_int(); - ss << " 1 " << num_inputs+1 << " " << num_outputs << std::endl; + ss << " " << (flop_module->get_bool_attribute(ID::whitebox) ? "1" : "0"); + ss << " " << num_inputs+1 << " " << num_outputs << std::endl; + + ss << "#"; bool first = true; + for (auto port_name : flop_module->ports) { + auto wire = flop_module->wire(port_name); + if (!wire->port_input) + continue; + if (first) + first = false; + else + ss << " "; + ss << log_id(wire); + } + ss << " abc9_ff.Q" << std::endl; + + first = true; for (auto port_name : flop_module->ports) { auto wire = flop_module->wire(port_name); if (!wire->port_input) @@ -548,13 +559,7 @@ void prep_delays(RTLIL::Design *design) ss << " 0" << std::endl << std::endl; } design->scratchpad_set_string("abc9_ops.box_library.flops", ss.str()); - - ss.str(""); - for (const int d : delays) { - ss << "$__ABC9_DELAY@" << d << " " << ABC9_DELAY_BASE_ID + d << " 0 1 1" << std::endl; - ss << d << std::endl; - } - design->scratchpad_set_string("abc9_ops.box_library.delays", ss.str()); + design->scratchpad_set_int("abc9_ops.box_id", abc9_box_id); } void prep_lut(RTLIL::Design *design, int maxlut) @@ -610,22 +615,93 @@ void write_lut(RTLIL::Module *module, const std::string &dst) { ofs.close(); } -void prep_box(RTLIL::Design *design, const std::string &src) +void prep_box(RTLIL::Design *design) { std::stringstream ss; + ss << design->scratchpad_get_string("abc9_ops.box_library.flops", ss.str()); + + int abc9_box_id = design->scratchpad_get_int("abc9_ops.box_id"); + for (auto module : design->modules()) { + auto it = module->attributes.find(ID(abc9_box)); + if (it == module->attributes.end()) + continue; + module->attributes.erase(it); + log_assert(!module->attributes.count(ID(abc9_box_id))); + + dict, std::string> table; + std::vector inputs; + std::vector outputs; + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + if (wire->port_input) + for (int i = 0; i < GetSize(wire); i++) + inputs.emplace_back(wire, i); + if (wire->port_output) + for (int i = 0; i < GetSize(wire); i++) + outputs.emplace_back(wire, i); + } + for (auto cell : module->cells()) { + if (cell->type != ID($specify2)) + continue; + auto src = cell->getPort(ID(SRC)); + auto dst = cell->getPort(ID(DST)); + for (const auto &c : src.chunks()) + if (!c.wire->port_input) + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + for (const auto &c : dst.chunks()) + if (!c.wire->port_output) + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); + int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); + int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); + int max = std::max(rise_max,fall_max); + for (auto s : src) + for (auto d : dst) { + auto r = table.insert(std::make_pair(s,d)); + log_assert(r.second); + r.first->second = std::to_string(max); + } + } + auto r = module->attributes.insert(ID(abc9_box_id)); + log_assert(r.second); + r.first->second = ++abc9_box_id; + ss << log_id(module) << " " << abc9_box_id; + ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); + ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl; + bool first = true; + ss << "#"; + for (const auto &i : inputs) { + if (first) + first = false; + else + ss << " "; + if (GetSize(i.wire) == 1) + ss << log_id(i.wire); + else + ss << log_id(i.wire) << "[" << i.offset << "]"; + } + ss << std::endl; + for (const auto &o : outputs) { + first = true; + for (const auto &i : inputs) { + if (first) + first = false; + else + ss << " "; + ss << table.at(std::make_pair(i,o), "-"); + } + ss << " # "; + if (GetSize(o.wire) == 1) + ss << log_id(o.wire); + else + ss << log_id(o.wire) << "[" << o.offset << "]"; + ss << std::endl; - // Since ABC can only accept one box file, we have to copy - // over the existing box file - if (src != "(null)") { - std::ifstream ifs(src); - log_assert(ifs.is_open()); - ss << ifs.rdbuf() << std::endl; - ifs.close(); + } + ss << std::endl; } - ss << design->scratchpad_get_string("abc9_ops.box_library.flops", ss.str()); - ss << design->scratchpad_get_string("abc9_ops.box_library.delays", ss.str()); design->scratchpad_set_string("abc9_ops.box_library", ss.str()); + design->scratchpad_set_int("abc9_ops.box_id", abc9_box_id); } void write_box(RTLIL::Module *module, const std::string &dst) { @@ -1049,14 +1125,15 @@ struct Abc9OpsPass : public Pass { log(" process the '$holes' module to support clock-enable functionality.\n"); log("\n"); log(" -prep_lut \n"); - log(" pre-compute the lut library.\n"); + log(" pre-compute the lut library by analysing all modules marked with\n"); + log(" (* abc9_lut= *).\n"); log("\n"); log(" -write_lut \n"); log(" write the pre-computed lut library to .\n"); log("\n"); - log(" -prep_box \n"); - log(" pre-compute the box library. copy the existing box file from (skip\n"); - log(" if '(null)').\n"); + log(" -prep_box\n"); + log(" pre-compute the box library by analysing all modules marked with\n"); + log(" (* abc9_box *)\n"); log("\n"); log(" -write_box \n"); log(" write the pre-computed box library to .\n"); @@ -1077,11 +1154,12 @@ struct Abc9OpsPass : public Pass { bool prep_dff_mode = false; bool prep_xaiger_mode = false; bool prep_lut_mode = false; + bool prep_box_mode = false; bool reintegrate_mode = false; bool dff_mode = false; std::string write_lut_dst; int maxlut = 0; - std::string prep_box_src, write_box_dst; + std::string write_box_dst; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -1119,9 +1197,8 @@ struct Abc9OpsPass : public Pass { rewrite_filename(write_lut_dst); continue; } - if (arg == "-prep_box" && argidx+1 < args.size()) { - prep_box_src = args[++argidx]; - rewrite_filename(prep_box_src); + if (arg == "-prep_box") { + prep_box_mode = true; continue; } if (arg == "-write_box" && argidx+1 < args.size()) { @@ -1141,7 +1218,7 @@ struct Abc9OpsPass : public Pass { } extra_args(args, argidx, design); - if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || prep_lut_mode || !prep_box_src.empty() || !write_lut_dst.empty() || !write_box_dst.empty() || reintegrate_mode)) + if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || prep_lut_mode || prep_box_mode || !write_lut_dst.empty() || !write_box_dst.empty() || reintegrate_mode)) log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff,lut,box}, -write_{lut,box}, -reintegrate must be specified.\n"); if (dff_mode && !prep_xaiger_mode) @@ -1153,8 +1230,8 @@ struct Abc9OpsPass : public Pass { prep_delays(design); if (prep_lut_mode) prep_lut(design, maxlut); - if (!prep_box_src.empty()) - prep_box(design, prep_box_src); + if (prep_box_mode) + prep_box(design); for (auto mod : design->selected_modules()) { if (mod->get_bool_attribute("\\abc9_holes")) -- cgit v1.2.3 From 577545488a81e1f9b84b214d6d02187aac28af6c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 11 Feb 2020 14:22:43 -0800 Subject: xilinx: use specify blocks in place of abc9_{arrival,required} --- passes/techmap/abc9_ops.cc | 422 ++++++++++++++++++++++++++++----------------- 1 file changed, 264 insertions(+), 158 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index bbbbc45d0..9abe6af9f 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -70,54 +70,6 @@ void check(RTLIL::Design *design) carry_out = port_name; } } - - auto it = w->attributes.find("\\abc9_arrival"); - if (it != w->attributes.end()) { - int count = 0; - if (it->second.flags == 0) { - if (it->second.as_int() < 0) - log_error("%s.%s has negative arrival value %d!\n", log_id(m), log_id(port_name), - it->second.as_int()); - count++; - } - else - for (const auto &tok : split_tokens(it->second.decode_string())) { - if (tok.find_first_not_of("0123456789") != std::string::npos) - log_error("%s.%s has non-integer arrival value '%s'!\n", log_id(m), log_id(port_name), - tok.c_str()); - if (atoi(tok.c_str()) < 0) - log_error("%s.%s has negative arrival value %s!\n", log_id(m), log_id(port_name), - tok.c_str()); - count++; - } - if (count > 1 && count != GetSize(w)) - log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(m), log_id(port_name), - GetSize(w), log_signal(it->second), count); - } - - it = w->attributes.find("\\abc9_required"); - if (it != w->attributes.end()) { - int count = 0; - if (it->second.flags == 0) { - if (it->second.as_int() < 0) - log_error("%s.%s has negative required value %d!\n", log_id(m), log_id(port_name), - it->second.as_int()); - count++; - } - else - for (const auto &tok : split_tokens(it->second.decode_string())) { - if (tok.find_first_not_of("0123456789") != std::string::npos) - log_error("%s.%s has non-integer required value '%s'!\n", log_id(m), log_id(port_name), - tok.c_str()); - if (atoi(tok.c_str()) < 0) - log_error("%s.%s has negative required value %s!\n", log_id(m), log_id(port_name), - tok.c_str()); - count++; - } - if (count > 1 && count != GetSize(w)) - log_error("%s.%s is %d bits wide but abc9_required = %s has %d value(s)!\n", log_id(m), log_id(port_name), - GetSize(w), log_signal(it->second), count); - } } if (carry_in != IdString() && carry_out == IdString()) @@ -428,16 +380,15 @@ void prep_xaiger(RTLIL::Module *module, bool dff) void prep_delays(RTLIL::Design *design) { - pool flops; + // Derive and collect all blackbox modules, and collect all blackbox instantiations + pool derived; std::vector cells; - dict>> requireds_cache; for (auto module : design->selected_modules()) { if (module->processes.size() > 0) { log("Skipping module %s as it contains processes.\n", log_id(module)); continue; } - cells.clear(); for (auto cell : module->cells()) { if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_), ID($__ABC9_DELAY))) continue; @@ -447,119 +398,186 @@ void prep_delays(RTLIL::Design *design) continue; if (!inst_module->get_blackbox_attribute()) continue; - if (inst_module->get_bool_attribute(ID(abc9_flop))) { - IdString derived_type = inst_module->derive(design, cell->parameters); - inst_module = design->module(derived_type); - log_assert(inst_module); - flops.insert(inst_module); - continue; // because all flop required times - // will be captured in the flop box - } if (inst_module->attributes.count(ID(abc9_box))) continue; + IdString derived_type = inst_module->derive(design, cell->parameters); + inst_module = design->module(derived_type); + log_assert(inst_module); + derived.insert(inst_module); + cells.emplace_back(cell); } + } - for (auto cell : cells) { - RTLIL::Module* inst_module = module->design->module(cell->type); - log_assert(inst_module); - auto &cell_requireds = requireds_cache[cell->type]; - for (auto &conn : cell->connections_) { - auto port_wire = inst_module->wire(conn.first); - if (!port_wire->port_input) - continue; + // Transform all $specify3 and $specrule to abc9_{arrival,required} attributes + std::vector flops; + dict arrivals, requireds; + pool ports; + std::stringstream ss; + for (auto module : derived) { + if (module->get_bool_attribute(ID(abc9_flop))) + flops.push_back(module); - auto r = cell_requireds.insert(conn.first); - auto &requireds = r.first->second; - if (r.second) { - auto it = port_wire->attributes.find("\\abc9_required"); - if (it == port_wire->attributes.end()) - continue; - if (it->second.flags == 0) { - int delay = it->second.as_int(); - requireds.emplace_back(delay); - } - else - for (const auto &tok : split_tokens(it->second.decode_string())) { - int delay = atoi(tok.c_str()); - requireds.push_back(delay); - } + arrivals.clear(); + requireds.clear(); + for (auto cell : module->cells()) { + if (cell->type == ID($specify3)) { + auto src = cell->getPort(ID(SRC)); + auto dat = cell->getPort(ID(DAT)); + auto dst = cell->getPort(ID(DST)); + for (const auto &c : src.chunks()) + if (!c.wire->port_input) + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + for (const auto &c : dat.chunks()) + if (!c.wire->port_input) + log_error("Module '%s' contains specify cell '%s' where DAT '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dat)); + for (const auto &c : dst.chunks()) + if (!c.wire->port_output) + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); + if (!cell->getParam(ID(EDGE_EN)).as_bool()) + continue; + int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); + int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); + int max = std::max(rise_max,fall_max); + if (max < 0) { + log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); + continue; } - - if (requireds.empty()) + for (auto d : dst) + arrivals[d] = std::max(arrivals[d], max); + } + else if (cell->type == ID($specrule)) { + auto type = cell->getParam(ID(TYPE)).decode_string(); + if (type != "$setup" && type != "$setuphold") + continue; + auto src = cell->getPort(ID(SRC)); + auto dst = cell->getPort(ID(DST)); + for (const auto &c : src.chunks()) + if (!c.wire->port_input) + log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); + for (const auto &c : dst.chunks()) + if (!c.wire->port_input) + log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); + int setup = cell->getParam(ID(T_LIMIT)).as_int(); + if (setup < 0) { + log_warning("Module '%s' contains specify cell '%s' with T_LIMIT < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); continue; + } + for (const auto &s : src) + requireds[s] = std::max(requireds[s], setup); + } + } - SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); - auto it = requireds.begin(); - for (int i = 0; i < GetSize(conn.second); ++i) { -#ifndef NDEBUG - if (ys_debug(1)) { - static std::set> seen; - if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_required = %d\n", log_id(cell->type), log_id(conn.first), requireds[i]); - } -#endif - auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); - box->setPort(ID(I), conn.second[i]); - box->setPort(ID(O), O[i]); - box->setParam(ID(DELAY), *it); - if (requireds.size() > 1) - it++; - conn.second[i] = O[i]; + if (arrivals.empty() && requireds.empty()) + continue; + + ports.clear(); + for (const auto &i : arrivals) + ports.insert(i.first.wire); + for (auto wire : ports) { + log_assert(wire->port_output); + ss.str(""); + if (GetSize(wire) == 1) + wire->attributes[ID(abc9_arrival)] = arrivals.at(SigBit(wire,0)); + else { + bool first = true; + for (auto b : SigSpec(wire)) { + if (first) + first = false; + else + ss << " "; + auto it = arrivals.find(b); + if (it == arrivals.end()) + ss << "0"; + else + ss << it->second; } + wire->attributes[ID(abc9_arrival)] = ss.str(); } } - } - int abc9_box_id = design->scratchpad_get_int("abc9_ops.box_id"); - std::stringstream ss; - for (auto flop_module : flops) { - int num_inputs = 0, num_outputs = 0; - for (auto port_name : flop_module->ports) { - auto wire = flop_module->wire(port_name); - log_assert(GetSize(wire) == 1); - if (wire->port_input) num_inputs++; - if (wire->port_output) num_outputs++; + ports.clear(); + for (const auto &i : requireds) + ports.insert(i.first.wire); + for (auto wire : ports) { + log_assert(wire->port_input); + ss.str(""); + if (GetSize(wire) == 1) + wire->attributes[ID(abc9_required)] = requireds.at(SigBit(wire,0)); + else { + bool first = true; + for (auto b : SigSpec(wire)) { + if (first) + first = false; + else + ss << " "; + auto it = requireds.find(b); + if (it == requireds.end()) + ss << "0"; + else + ss << it->second; + } + wire->attributes[ID(abc9_required)] = ss.str(); + } } - log_assert(num_outputs == 1); + } - auto r = flop_module->attributes.insert(ID(abc9_box_id)); - if (r.second) - r.first->second = ++abc9_box_id; + // Insert $__ABC9_DELAY cells on all cells that instantiate blackboxes + // with (* abc9_required *) attributes + dict>> requireds_cache; + for (auto cell : cells) { + auto module = cell->module; + RTLIL::Module* inst_module = module->design->module(cell->type); + log_assert(inst_module); + IdString derived_type = inst_module->derive(design, cell->parameters); + inst_module = design->module(derived_type); + log_assert(inst_module); + + auto &cell_requireds = requireds_cache[cell->type]; + for (auto &conn : cell->connections_) { + auto port_wire = inst_module->wire(conn.first); + if (!port_wire->port_input) + continue; - ss << log_id(flop_module) << " " << r.first->second.as_int(); - ss << " " << (flop_module->get_bool_attribute(ID::whitebox) ? "1" : "0"); - ss << " " << num_inputs+1 << " " << num_outputs << std::endl; + auto r = cell_requireds.insert(conn.first); + auto &requireds = r.first->second; + if (r.second) { + auto it = port_wire->attributes.find("\\abc9_required"); + if (it == port_wire->attributes.end()) + continue; + if (it->second.flags == 0) { + int delay = it->second.as_int(); + requireds.emplace_back(delay); + } + else + for (const auto &tok : split_tokens(it->second.decode_string())) { + int delay = atoi(tok.c_str()); + requireds.push_back(delay); + } + } - ss << "#"; - bool first = true; - for (auto port_name : flop_module->ports) { - auto wire = flop_module->wire(port_name); - if (!wire->port_input) + if (requireds.empty()) continue; - if (first) - first = false; - else - ss << " "; - ss << log_id(wire); - } - ss << " abc9_ff.Q" << std::endl; - first = true; - for (auto port_name : flop_module->ports) { - auto wire = flop_module->wire(port_name); - if (!wire->port_input) - continue; - if (first) - first = false; - else - ss << " "; - ss << wire->attributes.at("\\abc9_required", 0).as_int(); + SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); + auto it = requireds.begin(); + for (int i = 0; i < GetSize(conn.second); ++i) { +#ifndef NDEBUG + if (ys_debug(1)) { + static std::set> seen; + if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_required = %d\n", log_id(cell->type), log_id(conn.first), requireds[i]); + } +#endif + auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); + box->setPort(ID(I), conn.second[i]); + box->setPort(ID(O), O[i]); + box->setParam(ID(DELAY), *it); + if (requireds.size() > 1) + it++; + conn.second[i] = O[i]; + } } - // Last input is 'abc9_ff.Q' - ss << " 0" << std::endl << std::endl; } - design->scratchpad_set_string("abc9_ops.box_library.flops", ss.str()); - design->scratchpad_set_int("abc9_ops.box_id", abc9_box_id); } void prep_lut(RTLIL::Design *design, int maxlut) @@ -587,7 +605,10 @@ void prep_lut(RTLIL::Design *design, int maxlut) log_assert(o == d); int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); - specify.push_back(std::max(rise_max,fall_max)); + int max = std::max(rise_max,fall_max); + if (max < 0) + log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell)); + specify.push_back(max); } if (maxlut && GetSize(specify) > maxlut) continue; @@ -618,10 +639,57 @@ void write_lut(RTLIL::Module *module, const std::string &dst) { void prep_box(RTLIL::Design *design) { std::stringstream ss; - ss << design->scratchpad_get_string("abc9_ops.box_library.flops", ss.str()); - - int abc9_box_id = design->scratchpad_get_int("abc9_ops.box_id"); + int abc9_box_id = 1; + dict> box_ports; for (auto module : design->modules()) { + if (module->get_bool_attribute(ID(abc9_flop))) { + int num_inputs = 0, num_outputs = 0; + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + log_assert(GetSize(wire) == 1); + if (wire->port_input) num_inputs++; + if (wire->port_output) num_outputs++; + } + log_assert(num_outputs == 1); + + auto r = module->attributes.insert(ID(abc9_box_id)); + if (r.second) + r.first->second = abc9_box_id++; + + ss << log_id(module) << " " << r.first->second.as_int(); + ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); + ss << " " << num_inputs+1 << " " << num_outputs << std::endl; + + ss << "#"; + bool first = true; + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + if (!wire->port_input) + continue; + if (first) + first = false; + else + ss << " "; + ss << log_id(wire); + } + ss << " abc9_ff.Q" << std::endl; + + first = true; + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + if (!wire->port_input) + continue; + if (first) + first = false; + else + ss << " "; + ss << wire->attributes.at("\\abc9_required", 0).as_int(); + } + // Last input is 'abc9_ff.Q' + ss << " 0" << std::endl << std::endl; + continue; + } + auto it = module->attributes.find(ID(abc9_box)); if (it == module->attributes.end()) continue; @@ -631,7 +699,33 @@ void prep_box(RTLIL::Design *design) dict, std::string> table; std::vector inputs; std::vector outputs; - for (auto port_name : module->ports) { + + auto r = box_ports.insert(module->name); + if (r.second) { + // Make carry in the last PI, and carry out the last PO + // since ABC requires it this way + IdString carry_in, carry_out; + for (const auto &port_name : module->ports) { + auto w = module->wire(port_name); + log_assert(w); + if (w->get_bool_attribute("\\abc9_carry")) { + log_assert(w->port_input != w->port_output); + if (w->port_input) + carry_in = port_name; + else if (w->port_output) + carry_out = port_name; + } + else + r.first->second.push_back(port_name); + } + + if (carry_in != IdString()) { + r.first->second.push_back(carry_in); + r.first->second.push_back(carry_out); + } + } + + for (auto port_name : r.first->second) { auto wire = module->wire(port_name); if (wire->port_input) for (int i = 0; i < GetSize(wire); i++) @@ -654,17 +748,29 @@ void prep_box(RTLIL::Design *design) int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); int max = std::max(rise_max,fall_max); - for (auto s : src) - for (auto d : dst) { - auto r = table.insert(std::make_pair(s,d)); + if (max < 0) + log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell)); + if (cell->getParam(ID(FULL)).as_bool()) { + for (auto s : src) + for (auto d : dst) { + auto r = table.insert(std::make_pair(s,d)); + log_assert(r.second); + r.first->second = std::to_string(max); + } + } + else { + log_assert(GetSize(src) == GetSize(dst)); + for (auto i = 0; i < GetSize(src); i++) { + auto r = table.insert(std::make_pair(src[i],dst[i])); log_assert(r.second); r.first->second = std::to_string(max); } + } } - auto r = module->attributes.insert(ID(abc9_box_id)); - log_assert(r.second); - r.first->second = ++abc9_box_id; + auto r2 = module->attributes.insert(ID(abc9_box_id)); + log_assert(r2.second); ss << log_id(module) << " " << abc9_box_id; + r2.first->second = abc9_box_id++; ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl; bool first = true; @@ -700,17 +806,17 @@ void prep_box(RTLIL::Design *design) ss << std::endl; } + // ABC expects at least one box + if (ss.tellp() == 0) + ss << "(dummy) 1 0 0 0"; + design->scratchpad_set_string("abc9_ops.box_library", ss.str()); - design->scratchpad_set_int("abc9_ops.box_id", abc9_box_id); } void write_box(RTLIL::Module *module, const std::string &dst) { std::ofstream ofs(dst); log_assert(ofs.is_open()); ofs << module->design->scratchpad_get_string("abc9_ops.box_library"); - // ABC expects at least one box - if (ofs.tellp() == 0) - ofs << "(dummy) 1 0 0 0"; ofs.close(); } -- cgit v1.2.3 From 12d70ca8fbad73f2615e711e786f8b90fa005bee Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 12 Feb 2020 15:25:30 -0800 Subject: xilinx: improve specify functionality --- passes/techmap/abc9_ops.cc | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 9abe6af9f..c48cd5c86 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -380,8 +380,10 @@ void prep_xaiger(RTLIL::Module *module, bool dff) void prep_delays(RTLIL::Design *design) { - // Derive and collect all blackbox modules, and collect all blackbox instantiations - pool derived; + // Derive and collect all Yosys blackbox modules that are not combinatorial abc9 boxes + // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations + pool blackboxes; + pool flops; std::vector cells; for (auto module : design->selected_modules()) { if (module->processes.size() > 0) { @@ -400,42 +402,38 @@ void prep_delays(RTLIL::Design *design) continue; if (inst_module->attributes.count(ID(abc9_box))) continue; - IdString derived_type = inst_module->derive(design, cell->parameters); - inst_module = design->module(derived_type); + IdString blackboxes_type = inst_module->derive(design, cell->parameters); + inst_module = design->module(blackboxes_type); log_assert(inst_module); - derived.insert(inst_module); + blackboxes.insert(inst_module); + + if (inst_module->get_bool_attribute(ID(abc9_flop))) { + flops.insert(inst_module); + continue; // do not add $__ABC9_DELAY boxes to flops + // as delays will be captured in the flop box + } cells.emplace_back(cell); } } // Transform all $specify3 and $specrule to abc9_{arrival,required} attributes - std::vector flops; dict arrivals, requireds; pool ports; std::stringstream ss; - for (auto module : derived) { - if (module->get_bool_attribute(ID(abc9_flop))) - flops.push_back(module); - + for (auto module : blackboxes) { arrivals.clear(); requireds.clear(); for (auto cell : module->cells()) { if (cell->type == ID($specify3)) { auto src = cell->getPort(ID(SRC)); - auto dat = cell->getPort(ID(DAT)); auto dst = cell->getPort(ID(DST)); for (const auto &c : src.chunks()) if (!c.wire->port_input) log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); - for (const auto &c : dat.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where DAT '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dat)); for (const auto &c : dst.chunks()) if (!c.wire->port_output) log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); - if (!cell->getParam(ID(EDGE_EN)).as_bool()) - continue; int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); int max = std::max(rise_max,fall_max); @@ -443,7 +441,7 @@ void prep_delays(RTLIL::Design *design) log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); continue; } - for (auto d : dst) + for (const auto &d : dst) arrivals[d] = std::max(arrivals[d], max); } else if (cell->type == ID($specrule)) { @@ -472,8 +470,10 @@ void prep_delays(RTLIL::Design *design) continue; ports.clear(); - for (const auto &i : arrivals) + for (const auto &i : arrivals) { + log_dump(i.first, i.first.wire->name); ports.insert(i.first.wire); + } for (auto wire : ports) { log_assert(wire->port_output); ss.str(""); @@ -1239,7 +1239,7 @@ struct Abc9OpsPass : public Pass { log("\n"); log(" -prep_box\n"); log(" pre-compute the box library by analysing all modules marked with\n"); - log(" (* abc9_box *)\n"); + log(" (* abc9_box *).\n"); log("\n"); log(" -write_box \n"); log(" write the pre-computed box library to .\n"); -- cgit v1.2.3 From 0ed550d83c6d4b4ff4301ee5316d5840fd36b72e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Feb 2020 09:48:48 -0800 Subject: abc9_ops: cope with T_LIMIT{,2}_{MIN,TYP,MAX} and auto-gen small LUTs --- passes/techmap/abc9_ops.cc | 51 ++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index c48cd5c86..c202d3d66 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -437,8 +437,10 @@ void prep_delays(RTLIL::Design *design) int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); int max = std::max(rise_max,fall_max); - if (max < 0) { + if (max < 0) log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); + if (max <= 0) { + log_debug("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); continue; } for (const auto &d : dst) @@ -456,9 +458,11 @@ void prep_delays(RTLIL::Design *design) for (const auto &c : dst.chunks()) if (!c.wire->port_input) log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); - int setup = cell->getParam(ID(T_LIMIT)).as_int(); - if (setup < 0) { - log_warning("Module '%s' contains specify cell '%s' with T_LIMIT < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); + int setup = cell->getParam(ID(T_LIMIT_MAX)).as_int(); + if (setup < 0) + log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); + if (setup <= 0) { + log_debug("Module '%s' contains specify cell '%s' with T_LIMIT_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); continue; } for (const auto &s : src) @@ -582,8 +586,7 @@ void prep_delays(RTLIL::Design *design) void prep_lut(RTLIL::Design *design, int maxlut) { - std::stringstream ss; - std::vector> table; + std::vector>> table; for (auto module : design->modules()) { auto it = module->attributes.find(ID(abc9_lut)); if (it == module->attributes.end()) @@ -603,6 +606,8 @@ void prep_lut(RTLIL::Design *design, int maxlut) o = d; else log_assert(o == d); + // TODO: Don't assume that each specify entry with the destination 'o' + // describes a unique LUT input int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); int max = std::max(rise_max,fall_max); @@ -612,20 +617,30 @@ void prep_lut(RTLIL::Design *design, int maxlut) } if (maxlut && GetSize(specify) > maxlut) continue; - std::sort(specify.begin(), specify.end()); - ss.str(""); - ss << "# " << module->name.str() << std::endl; - ss << GetSize(specify) << " " << it->second.as_int(); - for (auto i : specify) - ss << " " << i; - ss << std::endl; - table.emplace_back(GetSize(specify), ss.str()); + // ABC requires ascending LUT input delays + table.emplace_back(GetSize(specify), module->name, std::move(specify)); } - // ABC expects ascending size + // ABC requires ascending size std::sort(table.begin(), table.end()); - ss.str(""); - for (auto &i : table) - ss << i.second; + + std::stringstream ss; + const auto &first = table.front(); + // If the first entry does not start from a 1-input LUT, + // (as ABC requires) crop the first entry to do so + for (int i = 1; i < std::get<0>(first); i++) { + ss << "# $__ABC9_LUT" << i << std::endl; + ss << i; + for (int j = 0; j < i; j++) + ss << " " << std::get<2>(first)[j]; + ss << std::endl; + } + for (const auto &i : table) { + ss << "# " << log_id(std::get<1>(i)) << std::endl; + ss << GetSize(std::get<2>(i)); + for (const auto &j : std::get<2>(i)) + ss << " " << j; + ss << std::endl; + } design->scratchpad_set_string("abc9_ops.lut_library", ss.str()); } -- cgit v1.2.3 From 7317521c6fa897c90328ac127cb0cf98de0bb7dd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Feb 2020 09:54:40 -0800 Subject: abc9_ops: output LUT area --- passes/techmap/abc9_ops.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index c202d3d66..61a3880b7 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -586,7 +586,7 @@ void prep_delays(RTLIL::Design *design) void prep_lut(RTLIL::Design *design, int maxlut) { - std::vector>> table; + std::vector>> table; for (auto module : design->modules()) { auto it = module->attributes.find(ID(abc9_lut)); if (it == module->attributes.end()) @@ -618,7 +618,7 @@ void prep_lut(RTLIL::Design *design, int maxlut) if (maxlut && GetSize(specify) > maxlut) continue; // ABC requires ascending LUT input delays - table.emplace_back(GetSize(specify), module->name, std::move(specify)); + table.emplace_back(GetSize(specify), module->name, it->second.as_int(), std::move(specify)); } // ABC requires ascending size std::sort(table.begin(), table.end()); @@ -629,15 +629,15 @@ void prep_lut(RTLIL::Design *design, int maxlut) // (as ABC requires) crop the first entry to do so for (int i = 1; i < std::get<0>(first); i++) { ss << "# $__ABC9_LUT" << i << std::endl; - ss << i; + ss << i << " " << std::get<2>(first); for (int j = 0; j < i; j++) - ss << " " << std::get<2>(first)[j]; + ss << " " << std::get<3>(first)[j]; ss << std::endl; } for (const auto &i : table) { ss << "# " << log_id(std::get<1>(i)) << std::endl; - ss << GetSize(std::get<2>(i)); - for (const auto &j : std::get<2>(i)) + ss << std::get<0>(i) << " " << std::get<2>(i); + for (const auto &j : std::get<3>(i)) ss << " " << j; ss << std::endl; } -- cgit v1.2.3 From 7c92b6852f3bcc962e72bb787ac51e3f4324a4fb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Feb 2020 10:30:29 -0800 Subject: abc9_ops: sort LUT delays to be ascending --- passes/techmap/abc9_ops.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 61a3880b7..e1ab70f11 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -617,7 +617,8 @@ void prep_lut(RTLIL::Design *design, int maxlut) } if (maxlut && GetSize(specify) > maxlut) continue; - // ABC requires ascending LUT input delays + // ABC requires non-decreasing LUT input delays + std::sort(specify.begin(), specify.end()); table.emplace_back(GetSize(specify), module->name, it->second.as_int(), std::move(specify)); } // ABC requires ascending size @@ -777,6 +778,8 @@ void prep_box(RTLIL::Design *design) log_assert(GetSize(src) == GetSize(dst)); for (auto i = 0; i < GetSize(src); i++) { auto r = table.insert(std::make_pair(src[i],dst[i])); + if (!r.second) + log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(src[i]), log_signal(dst[i])); log_assert(r.second); r.first->second = std::to_string(max); } -- cgit v1.2.3 From e22fee6cdd905535c50c9b6d96a89e994944ea2c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 13 Feb 2020 11:15:59 -0800 Subject: abc9_ops: ignore (* abc9_flop *) if not '-dff' --- passes/techmap/abc9.cc | 8 +-- passes/techmap/abc9_ops.cc | 120 ++++++++++++++++++++++----------------------- 2 files changed, 64 insertions(+), 64 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index fc82f0e5f..5e650230d 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -192,7 +192,7 @@ struct Abc9Pass : public ScriptPass cleanup = true; lut_mode = false; maxlut = 0; - box_file = "(null)"; + box_file = ""; } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -286,9 +286,9 @@ struct Abc9Pass : public ScriptPass else if (!lut_mode) run(stringf("abc9_ops -prep_lut %d", maxlut)); if (help_mode) - run("abc9_ops -prep_box [<-box>|(null)]"); - else - run(stringf("abc9_ops -prep_box %s", box_file.c_str())); + run("abc9_ops -prep_box [-dff]", "(skip if -box)"); + else if (box_file.empty()) + run(stringf("abc9_ops -prep_box %s", dff_mode ? "-dff" : "")); run("select -set abc9_holes A:abc9_holes"); run("flatten -wb @abc9_holes"); run("techmap @abc9_holes"); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index e1ab70f11..f3d3381cd 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -378,7 +378,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) } } -void prep_delays(RTLIL::Design *design) +void prep_delays(RTLIL::Design *design, bool dff_mode) { // Derive and collect all Yosys blackbox modules that are not combinatorial abc9 boxes // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations @@ -407,7 +407,7 @@ void prep_delays(RTLIL::Design *design) log_assert(inst_module); blackboxes.insert(inst_module); - if (inst_module->get_bool_attribute(ID(abc9_flop))) { + if (dff_mode && inst_module->get_bool_attribute(ID(abc9_flop))) { flops.insert(inst_module); continue; // do not add $__ABC9_DELAY boxes to flops // as delays will be captured in the flop box @@ -474,10 +474,8 @@ void prep_delays(RTLIL::Design *design) continue; ports.clear(); - for (const auto &i : arrivals) { - log_dump(i.first, i.first.wire->name); + for (const auto &i : arrivals) ports.insert(i.first.wire); - } for (auto wire : ports) { log_assert(wire->port_output); ss.str(""); @@ -537,7 +535,7 @@ void prep_delays(RTLIL::Design *design) inst_module = design->module(derived_type); log_assert(inst_module); - auto &cell_requireds = requireds_cache[cell->type]; + auto &cell_requireds = requireds_cache[derived_type]; for (auto &conn : cell->connections_) { auto port_wire = inst_module->wire(conn.first); if (!port_wire->port_input) @@ -569,7 +567,7 @@ void prep_delays(RTLIL::Design *design) #ifndef NDEBUG if (ys_debug(1)) { static std::set> seen; - if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_required = %d\n", log_id(cell->type), log_id(conn.first), requireds[i]); + if (seen.emplace(derived_type, conn.first).second) log("%s.%s abc9_required = %d\n", log_id(cell->type), log_id(conn.first), requireds[i]); } #endif auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); @@ -652,64 +650,66 @@ void write_lut(RTLIL::Module *module, const std::string &dst) { ofs.close(); } -void prep_box(RTLIL::Design *design) +void prep_box(RTLIL::Design *design, bool dff_mode) { std::stringstream ss; int abc9_box_id = 1; dict> box_ports; for (auto module : design->modules()) { - if (module->get_bool_attribute(ID(abc9_flop))) { - int num_inputs = 0, num_outputs = 0; - for (auto port_name : module->ports) { - auto wire = module->wire(port_name); - log_assert(GetSize(wire) == 1); - if (wire->port_input) num_inputs++; - if (wire->port_output) num_outputs++; - } - log_assert(num_outputs == 1); + auto abc9_flop = module->get_bool_attribute(ID(abc9_flop)); + if (abc9_flop) { + if (dff_mode) { + int num_inputs = 0, num_outputs = 0; + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + log_assert(GetSize(wire) == 1); + if (wire->port_input) num_inputs++; + if (wire->port_output) num_outputs++; + } + log_assert(num_outputs == 1); - auto r = module->attributes.insert(ID(abc9_box_id)); - if (r.second) - r.first->second = abc9_box_id++; + auto r = module->attributes.insert(ID(abc9_box_id)); + if (r.second) + r.first->second = abc9_box_id++; - ss << log_id(module) << " " << r.first->second.as_int(); - ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); - ss << " " << num_inputs+1 << " " << num_outputs << std::endl; + ss << log_id(module) << " " << r.first->second.as_int(); + ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); + ss << " " << num_inputs+1 << " " << num_outputs << std::endl; - ss << "#"; - bool first = true; - for (auto port_name : module->ports) { - auto wire = module->wire(port_name); - if (!wire->port_input) - continue; - if (first) - first = false; - else - ss << " "; - ss << log_id(wire); - } - ss << " abc9_ff.Q" << std::endl; + ss << "#"; + bool first = true; + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + if (!wire->port_input) + continue; + if (first) + first = false; + else + ss << " "; + ss << log_id(wire); + } + ss << " abc9_ff.Q" << std::endl; - first = true; - for (auto port_name : module->ports) { - auto wire = module->wire(port_name); - if (!wire->port_input) - continue; - if (first) - first = false; - else - ss << " "; - ss << wire->attributes.at("\\abc9_required", 0).as_int(); + first = true; + for (auto port_name : module->ports) { + auto wire = module->wire(port_name); + if (!wire->port_input) + continue; + if (first) + first = false; + else + ss << " "; + ss << wire->attributes.at("\\abc9_required", 0).as_int(); + } + // Last input is 'abc9_ff.Q' + ss << " 0" << std::endl << std::endl; + continue; } - // Last input is 'abc9_ff.Q' - ss << " 0" << std::endl << std::endl; - continue; } - - auto it = module->attributes.find(ID(abc9_box)); - if (it == module->attributes.end()) - continue; - module->attributes.erase(it); + else { + if (!module->attributes.erase(ID(abc9_box))) + continue; + } log_assert(!module->attributes.count(ID(abc9_box_id))); dict, std::string> table; @@ -1241,8 +1241,8 @@ struct Abc9OpsPass : public Pass { log(" whiteboxes.\n"); log("\n"); log(" -dff\n"); - log(" consider flop cells (those instantiating modules marked with (* abc9_flop *)\n"); - log(" during -prep_xaiger.\n"); + log(" consider flop cells (those instantiating modules marked with (* abc9_flop *))\n"); + log(" during -prep_{delays,xaiger,box}.\n"); log("\n"); log(" -prep_dff\n"); log(" compute the clock domain and initial value of each flop in the design.\n"); @@ -1345,17 +1345,17 @@ struct Abc9OpsPass : public Pass { if (!(check_mode || mark_scc_mode || prep_delays_mode || prep_xaiger_mode || prep_dff_mode || prep_lut_mode || prep_box_mode || !write_lut_dst.empty() || !write_box_dst.empty() || reintegrate_mode)) log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff,lut,box}, -write_{lut,box}, -reintegrate must be specified.\n"); - if (dff_mode && !prep_xaiger_mode) - log_cmd_error("'-dff' option is only relevant for -prep_xaiger.\n"); + if (dff_mode && !prep_delays_mode && !prep_xaiger_mode && !prep_box_mode) + log_cmd_error("'-dff' option is only relevant for -prep_{delay,xaiger,box}.\n"); if (check_mode) check(design); if (prep_delays_mode) - prep_delays(design); + prep_delays(design, dff_mode); if (prep_lut_mode) prep_lut(design, maxlut); if (prep_box_mode) - prep_box(design); + prep_box(design, dff_mode); for (auto mod : design->selected_modules()) { if (mod->get_bool_attribute("\\abc9_holes")) -- cgit v1.2.3 From cda4acb544614711b2c187e93f515bfc43ca8da1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Feb 2020 11:11:34 -0800 Subject: abc9_ops: add and use new TimingInfo struct --- passes/techmap/abc9_ops.cc | 111 +++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 70 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index f3d3381cd..0a5d88a34 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -22,6 +22,7 @@ #include "kernel/sigtools.h" #include "kernel/utils.h" #include "kernel/celltypes.h" +#include "kernel/timinginfo.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -380,9 +381,8 @@ void prep_xaiger(RTLIL::Module *module, bool dff) void prep_delays(RTLIL::Design *design, bool dff_mode) { - // Derive and collect all Yosys blackbox modules that are not combinatorial abc9 boxes + // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations - pool blackboxes; pool flops; std::vector cells; for (auto module : design->selected_modules()) { @@ -405,7 +405,6 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) IdString blackboxes_type = inst_module->derive(design, cell->parameters); inst_module = design->module(blackboxes_type); log_assert(inst_module); - blackboxes.insert(inst_module); if (dff_mode && inst_module->get_bool_attribute(ID(abc9_flop))) { flops.insert(inst_module); @@ -417,70 +416,33 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) } } + const TimingInfo timing(design); + // Transform all $specify3 and $specrule to abc9_{arrival,required} attributes - dict arrivals, requireds; + // TODO: Deprecate pool ports; std::stringstream ss; - for (auto module : blackboxes) { - arrivals.clear(); - requireds.clear(); - for (auto cell : module->cells()) { - if (cell->type == ID($specify3)) { - auto src = cell->getPort(ID(SRC)); - auto dst = cell->getPort(ID(DST)); - for (const auto &c : src.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); - for (const auto &c : dst.chunks()) - if (!c.wire->port_output) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); - int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); - int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); - int max = std::max(rise_max,fall_max); - if (max < 0) - log_warning("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - if (max <= 0) { - log_debug("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - continue; - } - for (const auto &d : dst) - arrivals[d] = std::max(arrivals[d], max); - } - else if (cell->type == ID($specrule)) { - auto type = cell->getParam(ID(TYPE)).decode_string(); - if (type != "$setup" && type != "$setuphold") - continue; - auto src = cell->getPort(ID(SRC)); - auto dst = cell->getPort(ID(DST)); - for (const auto &c : src.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); - for (const auto &c : dst.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst)); - int setup = cell->getParam(ID(T_LIMIT_MAX)).as_int(); - if (setup < 0) - log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - if (setup <= 0) { - log_debug("Module '%s' contains specify cell '%s' with T_LIMIT_MAX <= 0 which is currently unsupported. Ignoring.\n", log_id(module), log_id(cell)); - continue; - } - for (const auto &s : src) - requireds[s] = std::max(requireds[s], setup); - } - } + for (auto module : design->modules()) { - if (arrivals.empty() && requireds.empty()) - continue; + auto it = timing.data.find(module->name); + if (it == timing.data.end()) + continue; + + const auto &t = it->second; + if (t.arrival.empty() && t.required.empty()) + continue; + + const auto &arrival = t.arrival; + const auto &required = t.required; ports.clear(); - for (const auto &i : arrivals) + for (const auto &i : arrival) ports.insert(i.first.wire); for (auto wire : ports) { log_assert(wire->port_output); ss.str(""); if (GetSize(wire) == 1) - wire->attributes[ID(abc9_arrival)] = arrivals.at(SigBit(wire,0)); + wire->attributes[ID(abc9_arrival)] = arrival.at(SigBit(wire,0)); else { bool first = true; for (auto b : SigSpec(wire)) { @@ -488,24 +450,20 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) first = false; else ss << " "; - auto it = arrivals.find(b); - if (it == arrivals.end()) - ss << "0"; - else - ss << it->second; + ss << arrival.at(b, 0); } wire->attributes[ID(abc9_arrival)] = ss.str(); } } ports.clear(); - for (const auto &i : requireds) + for (const auto &i : required) ports.insert(i.first.wire); for (auto wire : ports) { log_assert(wire->port_input); ss.str(""); if (GetSize(wire) == 1) - wire->attributes[ID(abc9_required)] = requireds.at(SigBit(wire,0)); + wire->attributes[ID(abc9_required)] = required.at(SigBit(wire,0)); else { bool first = true; for (auto b : SigSpec(wire)) { @@ -513,11 +471,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) first = false; else ss << " "; - auto it = requireds.find(b); - if (it == requireds.end()) - ss << "0"; - else - ss << it->second; + ss << required.at(b, 0); } wire->attributes[ID(abc9_required)] = ss.str(); } @@ -567,7 +521,8 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) #ifndef NDEBUG if (ys_debug(1)) { static std::set> seen; - if (seen.emplace(derived_type, conn.first).second) log("%s.%s abc9_required = %d\n", log_id(cell->type), log_id(conn.first), requireds[i]); + if (seen.emplace(derived_type, conn.first).second) log("%s.%s abc9_required = '%s'\n", log_id(cell->type), log_id(conn.first), + port_wire->attributes.at("\\abc9_required").decode_string().c_str()); } #endif auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); @@ -659,6 +614,7 @@ void prep_box(RTLIL::Design *design, bool dff_mode) auto abc9_flop = module->get_bool_attribute(ID(abc9_flop)); if (abc9_flop) { if (dff_mode) { + log_dump(module->name); int num_inputs = 0, num_outputs = 0; for (auto port_name : module->ports) { auto wire = module->wire(port_name); @@ -699,7 +655,22 @@ void prep_box(RTLIL::Design *design, bool dff_mode) first = false; else ss << " "; - ss << wire->attributes.at("\\abc9_required", 0).as_int(); + auto it = wire->attributes.find("\\abc9_required"); + if (it == wire->attributes.end()) + ss << 0; + else { + log_assert(it->second.flags == 0); + ss << it->second.as_int(); + +#ifndef NDEBUG + if (ys_debug(1)) { + static std::set> seen; + if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), + log_id(port_name), it->second.as_int()); + } +#endif + } + } // Last input is 'abc9_ff.Q' ss << " 0" << std::endl << std::endl; -- cgit v1.2.3 From 3ea5506f812879c0ecf66431efde002493e11bdf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Feb 2020 11:41:43 -0800 Subject: abc9_ops: use TimingInfo for -prep_{lut,box} too --- passes/techmap/abc9_ops.cc | 125 +++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 72 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 0a5d88a34..f55aeab85 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -424,8 +424,8 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) std::stringstream ss; for (auto module : design->modules()) { - auto it = timing.data.find(module->name); - if (it == timing.data.end()) + auto it = timing.find(module->name); + if (it == timing.end()) continue; const auto &t = it->second; @@ -539,35 +539,31 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) void prep_lut(RTLIL::Design *design, int maxlut) { + const TimingInfo timing(design); + std::vector>> table; for (auto module : design->modules()) { auto it = module->attributes.find(ID(abc9_lut)); if (it == module->attributes.end()) continue; + + auto jt = timing.find(module->name); + if (jt == timing.end()) + continue; + SigBit o; std::vector specify; - for (auto cell : module->cells()) { - if (cell->type != ID($specify2)) - continue; - log_assert(cell->getParam(ID(SRC_WIDTH)) == 1); - log_assert(cell->getParam(ID(DST_WIDTH)) == 1); - SigBit s = cell->getPort(ID(SRC)); - SigBit d = cell->getPort(ID(DST)); - log_assert(s.wire->port_input); - log_assert(d.wire->port_output); + auto &t = jt->second; + for (const auto &i : t.comb) { + auto &d = i.first.second; + log_dump(o, d); if (o == SigBit()) o = d; - else - log_assert(o == d); - // TODO: Don't assume that each specify entry with the destination 'o' - // describes a unique LUT input - int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); - int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); - int max = std::max(rise_max,fall_max); - if (max < 0) - log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell)); - specify.push_back(max); - } + else if (o != d) + log_error("(* abc9_lut *) module '%s' with has more than one output.\n", log_id(module)); + specify.push_back(i.second); + } + if (maxlut && GetSize(specify) > maxlut) continue; // ABC requires non-decreasing LUT input delays @@ -607,14 +603,27 @@ void write_lut(RTLIL::Module *module, const std::string &dst) { void prep_box(RTLIL::Design *design, bool dff_mode) { + const TimingInfo timing(design); + std::stringstream ss; int abc9_box_id = 1; + for (auto module : design->modules()) { + auto it = module->attributes.find(ID(abc9_box_id)); + if (it == module->attributes.end()) + continue; + abc9_box_id = std::max(abc9_box_id, it->second.as_int()); + } + dict> box_ports; for (auto module : design->modules()) { auto abc9_flop = module->get_bool_attribute(ID(abc9_flop)); if (abc9_flop) { + auto r = module->attributes.insert(ID(abc9_box_id)); + if (!r.second) + continue; + r.first->second = abc9_box_id++; + if (dff_mode) { - log_dump(module->name); int num_inputs = 0, num_outputs = 0; for (auto port_name : module->ports) { auto wire = module->wire(port_name); @@ -624,10 +633,6 @@ void prep_box(RTLIL::Design *design, bool dff_mode) } log_assert(num_outputs == 1); - auto r = module->attributes.insert(ID(abc9_box_id)); - if (r.second) - r.first->second = abc9_box_id++; - ss << log_id(module) << " " << r.first->second.as_int(); ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); ss << " " << num_inputs+1 << " " << num_outputs << std::endl; @@ -680,12 +685,12 @@ void prep_box(RTLIL::Design *design, bool dff_mode) else { if (!module->attributes.erase(ID(abc9_box))) continue; - } - log_assert(!module->attributes.count(ID(abc9_box_id))); - dict, std::string> table; - std::vector inputs; - std::vector outputs; + auto r = module->attributes.insert(ID(abc9_box_id)); + if (!r.second) + continue; + r.first->second = abc9_box_id++; + } auto r = box_ports.insert(module->name); if (r.second) { @@ -712,6 +717,8 @@ void prep_box(RTLIL::Design *design, bool dff_mode) } } + std::vector inputs; + std::vector outputs; for (auto port_name : r.first->second) { auto wire = module->wire(port_name); if (wire->port_input) @@ -721,47 +728,11 @@ void prep_box(RTLIL::Design *design, bool dff_mode) for (int i = 0; i < GetSize(wire); i++) outputs.emplace_back(wire, i); } - for (auto cell : module->cells()) { - if (cell->type != ID($specify2)) - continue; - auto src = cell->getPort(ID(SRC)); - auto dst = cell->getPort(ID(DST)); - for (const auto &c : src.chunks()) - if (!c.wire->port_input) - log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src)); - for (const auto &c : dst.chunks()) - if (!c.wire->port_output) - log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst)); - int rise_max = cell->getParam(ID(T_RISE_MAX)).as_int(); - int fall_max = cell->getParam(ID(T_FALL_MAX)).as_int(); - int max = std::max(rise_max,fall_max); - if (max < 0) - log_error("Module '%s' contains specify cell '%s' with T_{RISE,FALL}_MAX < 0.\n", log_id(module), log_id(cell)); - if (cell->getParam(ID(FULL)).as_bool()) { - for (auto s : src) - for (auto d : dst) { - auto r = table.insert(std::make_pair(s,d)); - log_assert(r.second); - r.first->second = std::to_string(max); - } - } - else { - log_assert(GetSize(src) == GetSize(dst)); - for (auto i = 0; i < GetSize(src); i++) { - auto r = table.insert(std::make_pair(src[i],dst[i])); - if (!r.second) - log_error("Module '%s' contains multiple specify cells for SRC '%s' and DST '%s'.\n", log_id(module), log_signal(src[i]), log_signal(dst[i])); - log_assert(r.second); - r.first->second = std::to_string(max); - } - } - } - auto r2 = module->attributes.insert(ID(abc9_box_id)); - log_assert(r2.second); - ss << log_id(module) << " " << abc9_box_id; - r2.first->second = abc9_box_id++; + + ss << log_id(module) << " " << module->attributes.at(ID(abc9_box_id)).as_int(); ss << " " << (module->get_bool_attribute(ID::whitebox) ? "1" : "0"); ss << " " << GetSize(inputs) << " " << GetSize(outputs) << std::endl; + bool first = true; ss << "#"; for (const auto &i : inputs) { @@ -775,6 +746,12 @@ void prep_box(RTLIL::Design *design, bool dff_mode) ss << log_id(i.wire) << "[" << i.offset << "]"; } ss << std::endl; + + auto it = timing.find(module->name); + if (it == timing.end()) + log_error("(* abc9_box *) module '%s' has no timing information.\n", log_id(module)); + + const auto &t = it->second.comb; for (const auto &o : outputs) { first = true; for (const auto &i : inputs) { @@ -782,7 +759,11 @@ void prep_box(RTLIL::Design *design, bool dff_mode) first = false; else ss << " "; - ss << table.at(std::make_pair(i,o), "-"); + auto jt = t.find(std::make_pair(i,o)); + if (jt == t.end()) + ss << "-"; + else + ss << jt->second; } ss << " # "; if (GetSize(o.wire) == 1) -- cgit v1.2.3 From a6fec9fe6052d2ec74fec4417be2fec45dea0df0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Feb 2020 12:01:03 -0800 Subject: abc9_ops: use TimingInfo for -prep_{lut,box} too --- passes/techmap/abc9_ops.cc | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index f55aeab85..80b19b471 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -381,6 +381,8 @@ void prep_xaiger(RTLIL::Module *module, bool dff) void prep_delays(RTLIL::Design *design, bool dff_mode) { + TimingInfo timing; + // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations pool flops; @@ -412,23 +414,19 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) // as delays will be captured in the flop box } + if (!timing.count(inst_module->name)) + timing.setup_module(inst_module); + cells.emplace_back(cell); } } - const TimingInfo timing(design); - // Transform all $specify3 and $specrule to abc9_{arrival,required} attributes // TODO: Deprecate pool ports; std::stringstream ss; - for (auto module : design->modules()) { - - auto it = timing.find(module->name); - if (it == timing.end()) - continue; - - const auto &t = it->second; + for (auto &i : timing.data) { + const auto &t = i.second; if (t.arrival.empty() && t.required.empty()) continue; @@ -539,7 +537,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) void prep_lut(RTLIL::Design *design, int maxlut) { - const TimingInfo timing(design); + TimingInfo timing; std::vector>> table; for (auto module : design->modules()) { @@ -547,16 +545,12 @@ void prep_lut(RTLIL::Design *design, int maxlut) if (it == module->attributes.end()) continue; - auto jt = timing.find(module->name); - if (jt == timing.end()) - continue; + auto &t = timing.setup_module(module); SigBit o; std::vector specify; - auto &t = jt->second; for (const auto &i : t.comb) { auto &d = i.first.second; - log_dump(o, d); if (o == SigBit()) o = d; else if (o != d) @@ -603,7 +597,7 @@ void write_lut(RTLIL::Module *module, const std::string &dst) { void prep_box(RTLIL::Design *design, bool dff_mode) { - const TimingInfo timing(design); + TimingInfo timing; std::stringstream ss; int abc9_box_id = 1; @@ -651,6 +645,7 @@ void prep_box(RTLIL::Design *design, bool dff_mode) } ss << " abc9_ff.Q" << std::endl; + auto &t = timing.setup_module(module).required; first = true; for (auto port_name : module->ports) { auto wire = module->wire(port_name); @@ -660,18 +655,18 @@ void prep_box(RTLIL::Design *design, bool dff_mode) first = false; else ss << " "; - auto it = wire->attributes.find("\\abc9_required"); - if (it == wire->attributes.end()) + auto it = t.find(wire); + if (it == t.end()) + // Assume that no setup time means zero ss << 0; else { - log_assert(it->second.flags == 0); - ss << it->second.as_int(); + ss << it->second; #ifndef NDEBUG if (ys_debug(1)) { static std::set> seen; if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), - log_id(port_name), it->second.as_int()); + log_id(port_name), it->second); } #endif } @@ -747,11 +742,10 @@ void prep_box(RTLIL::Design *design, bool dff_mode) } ss << std::endl; - auto it = timing.find(module->name); - if (it == timing.end()) + auto &t = timing.setup_module(module).comb; + if (t.empty()) log_error("(* abc9_box *) module '%s' has no timing information.\n", log_id(module)); - const auto &t = it->second.comb; for (const auto &o : outputs) { first = true; for (const auto &i : inputs) { -- cgit v1.2.3 From 1ef1ca812bd057fe0404893e357c10361225e393 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Feb 2020 12:54:47 -0800 Subject: Get rid of (* abc9_{arrival,required} *) entirely --- passes/techmap/abc9_ops.cc | 104 +++++++-------------------------------------- 1 file changed, 15 insertions(+), 89 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 80b19b471..dad39828a 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -293,6 +293,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) holes_module->set_bool_attribute("\\abc9_holes"); dict cell_cache; + TimingInfo timing; int port_id = 1, box_count = 0; for (auto cell_name : toposort.sorted) { @@ -404,8 +405,8 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) continue; if (inst_module->attributes.count(ID(abc9_box))) continue; - IdString blackboxes_type = inst_module->derive(design, cell->parameters); - inst_module = design->module(blackboxes_type); + IdString derived_type = inst_module->derive(design, cell->parameters); + inst_module = design->module(derived_type); log_assert(inst_module); if (dff_mode && inst_module->get_bool_attribute(ID(abc9_flop))) { @@ -414,71 +415,15 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) // as delays will be captured in the flop box } - if (!timing.count(inst_module->name)) + if (!timing.count(derived_type)) timing.setup_module(inst_module); cells.emplace_back(cell); } } - // Transform all $specify3 and $specrule to abc9_{arrival,required} attributes - // TODO: Deprecate - pool ports; - std::stringstream ss; - for (auto &i : timing.data) { - const auto &t = i.second; - if (t.arrival.empty() && t.required.empty()) - continue; - - const auto &arrival = t.arrival; - const auto &required = t.required; - - ports.clear(); - for (const auto &i : arrival) - ports.insert(i.first.wire); - for (auto wire : ports) { - log_assert(wire->port_output); - ss.str(""); - if (GetSize(wire) == 1) - wire->attributes[ID(abc9_arrival)] = arrival.at(SigBit(wire,0)); - else { - bool first = true; - for (auto b : SigSpec(wire)) { - if (first) - first = false; - else - ss << " "; - ss << arrival.at(b, 0); - } - wire->attributes[ID(abc9_arrival)] = ss.str(); - } - } - - ports.clear(); - for (const auto &i : required) - ports.insert(i.first.wire); - for (auto wire : ports) { - log_assert(wire->port_input); - ss.str(""); - if (GetSize(wire) == 1) - wire->attributes[ID(abc9_required)] = required.at(SigBit(wire,0)); - else { - bool first = true; - for (auto b : SigSpec(wire)) { - if (first) - first = false; - else - ss << " "; - ss << required.at(b, 0); - } - wire->attributes[ID(abc9_required)] = ss.str(); - } - } - } - // Insert $__ABC9_DELAY cells on all cells that instantiate blackboxes - // with (* abc9_required *) attributes - dict>> requireds_cache; + // with required times for (auto cell : cells) { auto module = cell->module; RTLIL::Module* inst_module = module->design->module(cell->type); @@ -487,48 +432,29 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) inst_module = design->module(derived_type); log_assert(inst_module); - auto &cell_requireds = requireds_cache[derived_type]; + auto &t = timing.at(derived_type).required; for (auto &conn : cell->connections_) { auto port_wire = inst_module->wire(conn.first); if (!port_wire->port_input) continue; - auto r = cell_requireds.insert(conn.first); - auto &requireds = r.first->second; - if (r.second) { - auto it = port_wire->attributes.find("\\abc9_required"); - if (it == port_wire->attributes.end()) + SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); + for (int i = 0; i < GetSize(conn.second); i++) { + auto d = t.at(SigBit(port_wire,i), 0); + if (d == 0) continue; - if (it->second.flags == 0) { - int delay = it->second.as_int(); - requireds.emplace_back(delay); - } - else - for (const auto &tok : split_tokens(it->second.decode_string())) { - int delay = atoi(tok.c_str()); - requireds.push_back(delay); - } - } - if (requireds.empty()) - continue; - - SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); - auto it = requireds.begin(); - for (int i = 0; i < GetSize(conn.second); ++i) { #ifndef NDEBUG if (ys_debug(1)) { - static std::set> seen; - if (seen.emplace(derived_type, conn.first).second) log("%s.%s abc9_required = '%s'\n", log_id(cell->type), log_id(conn.first), - port_wire->attributes.at("\\abc9_required").decode_string().c_str()); + static std::set> seen; + if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n", + log_id(cell->type), log_id(conn.first), i, d); } #endif auto box = module->addCell(NEW_ID, ID($__ABC9_DELAY)); box->setPort(ID(I), conn.second[i]); box->setPort(ID(O), O[i]); - box->setParam(ID(DELAY), *it); - if (requireds.size() > 1) - it++; + box->setParam(ID(DELAY), d); conn.second[i] = O[i]; } } @@ -1172,7 +1098,7 @@ struct Abc9OpsPass : public Pass { log("\n"); log(" -prep_delays\n"); log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n"); - log(" certain delays, e.g. (* abc9_required *) values.\n"); + log(" certain required times.\n"); log("\n"); log(" -mark_scc\n"); log(" for an arbitrarily chosen cell in each unique SCC of each selected module\n"); -- cgit v1.2.3 From 683c5ce9409b578df518df829b76777ab69cf87b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Feb 2020 13:26:00 -0800 Subject: abc9_ops: demote lack of box timing info to warning --- passes/techmap/abc9_ops.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index dad39828a..fc2f52157 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -669,8 +669,10 @@ void prep_box(RTLIL::Design *design, bool dff_mode) ss << std::endl; auto &t = timing.setup_module(module).comb; - if (t.empty()) - log_error("(* abc9_box *) module '%s' has no timing information.\n", log_id(module)); + if (t.empty()) { + log_warning("(* abc9_box *) module '%s' has no timing (and thus no connectivity) information.\n", log_id(module)); + continue; + } for (const auto &o : outputs) { first = true; -- cgit v1.2.3 From d6cff777513ff5b470bcd37588c123e118ad0cdb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 14 Feb 2020 13:53:28 -0800 Subject: abc9_ops: still emit delay table even box has no timing --- passes/techmap/abc9_ops.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index fc2f52157..8337b61b1 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -669,10 +669,8 @@ void prep_box(RTLIL::Design *design, bool dff_mode) ss << std::endl; auto &t = timing.setup_module(module).comb; - if (t.empty()) { + if (t.empty()) log_warning("(* abc9_box *) module '%s' has no timing (and thus no connectivity) information.\n", log_id(module)); - continue; - } for (const auto &o : outputs) { first = true; -- cgit v1.2.3 From 7c3b4b80ea62c53e3f4bd6d91dcf02ef09c40da7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Feb 2020 08:30:41 -0800 Subject: Fix spacing --- passes/techmap/abc9_ops.cc | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 8337b61b1..f7097fadb 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -266,8 +266,8 @@ void prep_xaiger(RTLIL::Module *module, bool dff) for (auto &it : bit_users) if (bit_drivers.count(it.first)) for (auto driver_cell : bit_drivers.at(it.first)) - for (auto user_cell : it.second) - toposort.edge(driver_cell, user_cell); + for (auto user_cell : it.second) + toposort.edge(driver_cell, user_cell); if (ys_debug(1)) toposort.analyze_loops = true; @@ -382,7 +382,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) void prep_delays(RTLIL::Design *design, bool dff_mode) { - TimingInfo timing; + TimingInfo timing; // Derive all Yosys blackbox modules that are not combinatorial abc9 boxes // (e.g. DSPs, RAMs, etc.) nor abc9 flops and collect all such instantiations @@ -412,7 +412,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) if (dff_mode && inst_module->get_bool_attribute(ID(abc9_flop))) { flops.insert(inst_module); continue; // do not add $__ABC9_DELAY boxes to flops - // as delays will be captured in the flop box + // as delays will be captured in the flop box } if (!timing.count(derived_type)) @@ -463,7 +463,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) void prep_lut(RTLIL::Design *design, int maxlut) { - TimingInfo timing; + TimingInfo timing; std::vector>> table; for (auto module : design->modules()) { @@ -482,7 +482,7 @@ void prep_lut(RTLIL::Design *design, int maxlut) else if (o != d) log_error("(* abc9_lut *) module '%s' with has more than one output.\n", log_id(module)); specify.push_back(i.second); - } + } if (maxlut && GetSize(specify) > maxlut) continue; @@ -523,7 +523,7 @@ void write_lut(RTLIL::Module *module, const std::string &dst) { void prep_box(RTLIL::Design *design, bool dff_mode) { - TimingInfo timing; + TimingInfo timing; std::stringstream ss; int abc9_box_id = 1; @@ -581,21 +581,21 @@ void prep_box(RTLIL::Design *design, bool dff_mode) first = false; else ss << " "; - auto it = t.find(wire); - if (it == t.end()) + auto it = t.find(wire); + if (it == t.end()) // Assume that no setup time means zero - ss << 0; - else { - ss << it->second; + ss << 0; + else { + ss << it->second; #ifndef NDEBUG - if (ys_debug(1)) { - static std::set> seen; - if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), - log_id(port_name), it->second); - } + if (ys_debug(1)) { + static std::set> seen; + if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module), + log_id(port_name), it->second); + } #endif - } + } } // Last input is 'abc9_ff.Q' -- cgit v1.2.3 From 9dcf204dece518a48192a90ea962a9d630283e11 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Feb 2020 08:41:48 -0800 Subject: TimingInfo: index by (port_name,offset) --- passes/techmap/abc9_ops.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index f7097fadb..e5de2bcc4 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -473,11 +473,11 @@ void prep_lut(RTLIL::Design *design, int maxlut) auto &t = timing.setup_module(module); - SigBit o; + TimingInfo::NameBit o; std::vector specify; for (const auto &i : t.comb) { auto &d = i.first.second; - if (o == SigBit()) + if (o == TimingInfo::NameBit()) o = d; else if (o != d) log_error("(* abc9_lut *) module '%s' with has more than one output.\n", log_id(module)); @@ -581,7 +581,8 @@ void prep_box(RTLIL::Design *design, bool dff_mode) first = false; else ss << " "; - auto it = t.find(wire); + log_assert(GetSize(wire) == 1); + auto it = t.find(SigBit(wire,0)); if (it == t.end()) // Assume that no setup time means zero ss << 0; -- cgit v1.2.3 From 6bb3d9f9c09993960a5a91fa51f163a7e67e2503 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Feb 2020 11:02:28 -0800 Subject: Make TimingInfo::TimingInfo(SigBit) constructor explicit --- passes/techmap/abc9_ops.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index e5de2bcc4..e46ad0a02 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -440,7 +440,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) SigSpec O = module->addWire(NEW_ID, GetSize(conn.second)); for (int i = 0; i < GetSize(conn.second); i++) { - auto d = t.at(SigBit(port_wire,i), 0); + auto d = t.at(TimingInfo::NameBit(conn.first,i), 0); if (d == 0) continue; @@ -582,7 +582,7 @@ void prep_box(RTLIL::Design *design, bool dff_mode) else ss << " "; log_assert(GetSize(wire) == 1); - auto it = t.find(SigBit(wire,0)); + auto it = t.find(TimingInfo::NameBit(port_name,0)); if (it == t.end()) // Assume that no setup time means zero ss << 0; @@ -680,7 +680,7 @@ void prep_box(RTLIL::Design *design, bool dff_mode) first = false; else ss << " "; - auto jt = t.find(std::make_pair(i,o)); + auto jt = t.find(std::make_pair(TimingInfo::NameBit(i),TimingInfo::NameBit(o))); if (jt == t.end()) ss << "-"; else -- cgit v1.2.3 From 88d5997c80e5c2bebb479f76b123899c6de48c57 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 18 Feb 2020 14:31:24 -0800 Subject: abc9_ops: suppress -prep_box warning for abc9_flop --- passes/techmap/abc9_ops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index e46ad0a02..cffcc189e 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -670,7 +670,7 @@ void prep_box(RTLIL::Design *design, bool dff_mode) ss << std::endl; auto &t = timing.setup_module(module).comb; - if (t.empty()) + if (!abc9_flop && t.empty()) log_warning("(* abc9_box *) module '%s' has no timing (and thus no connectivity) information.\n", log_id(module)); for (const auto &o : outputs) { -- cgit v1.2.3 From 78929e8c3d399d47a36bb974eed74e53a3840402 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 20 Feb 2020 07:52:08 -0800 Subject: Fixes for older compilers --- passes/techmap/abc9_ops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index cffcc189e..b0bd81698 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -680,7 +680,7 @@ void prep_box(RTLIL::Design *design, bool dff_mode) first = false; else ss << " "; - auto jt = t.find(std::make_pair(TimingInfo::NameBit(i),TimingInfo::NameBit(o))); + auto jt = t.find(TimingInfo::BitBit(i,o)); if (jt == t.end()) ss << "-"; else -- cgit v1.2.3