mirror of https://github.com/YosysHQ/yosys.git
Added "abc -luts" option, Improved Xilinx logic mapping
This commit is contained in:
parent
9251553592
commit
17372d8abd
|
@ -592,7 +592,7 @@ struct abc_output_filter
|
||||||
};
|
};
|
||||||
|
|
||||||
void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
|
void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
|
||||||
std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, int lut_mode2, bool dff_mode, std::string clk_str,
|
std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
|
||||||
bool keepff, std::string delay_target, bool fast_mode, const std::vector<RTLIL::Cell*> &cells, bool show_tempdir)
|
bool keepff, std::string delay_target, bool fast_mode, const std::vector<RTLIL::Cell*> &cells, bool show_tempdir)
|
||||||
{
|
{
|
||||||
module = current_module;
|
module = current_module;
|
||||||
|
@ -626,7 +626,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
if (!constr_file.empty())
|
if (!constr_file.empty())
|
||||||
abc_script += stringf("read_constr -v %s; ", constr_file.c_str());
|
abc_script += stringf("read_constr -v %s; ", constr_file.c_str());
|
||||||
} else
|
} else
|
||||||
if (lut_mode)
|
if (!lut_costs.empty())
|
||||||
abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
|
abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
|
||||||
else
|
else
|
||||||
abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str());
|
abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str());
|
||||||
|
@ -642,7 +642,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
abc_script += script_file[i];
|
abc_script += script_file[i];
|
||||||
} else
|
} else
|
||||||
abc_script += stringf("source %s", script_file.c_str());
|
abc_script += stringf("source %s", script_file.c_str());
|
||||||
} else if (lut_mode)
|
} else if (!lut_costs.empty())
|
||||||
abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
|
abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
|
||||||
else if (!liberty_file.empty())
|
else if (!liberty_file.empty())
|
||||||
abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR);
|
abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR);
|
||||||
|
@ -868,15 +868,13 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_"));
|
fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_"));
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
if (lut_mode) {
|
if (!lut_costs.empty()) {
|
||||||
buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str());
|
buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str());
|
||||||
f = fopen(buffer.c_str(), "wt");
|
f = fopen(buffer.c_str(), "wt");
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
|
log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
|
||||||
for (int i = 0; i < lut_mode; i++)
|
for (int i = 0; i < GetSize(lut_costs); i++)
|
||||||
fprintf(f, "%d 1.00 1.00\n", i+1);
|
fprintf(f, "%d %d.00 1.00\n", i+1, lut_costs.at(i));
|
||||||
for (int i = lut_mode; i < lut_mode2; i++)
|
|
||||||
fprintf(f, "%d %d.00 1.00\n", i+1, 2 << (i - lut_mode));
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,7 +892,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
|
||||||
if (ifs.fail())
|
if (ifs.fail())
|
||||||
log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
|
log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
|
||||||
|
|
||||||
bool builtin_lib = liberty_file.empty() && script_file.empty() && !lut_mode;
|
bool builtin_lib = liberty_file.empty() && script_file.empty() && lut_costs.empty();
|
||||||
RTLIL::Design *mapped_design = new RTLIL::Design;
|
RTLIL::Design *mapped_design = new RTLIL::Design;
|
||||||
parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_");
|
parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_");
|
||||||
|
|
||||||
|
@ -1238,6 +1236,10 @@ struct AbcPass : public Pass {
|
||||||
log(" the area cost doubles with each additional input bit. the delay cost\n");
|
log(" the area cost doubles with each additional input bit. the delay cost\n");
|
||||||
log(" is still constant for all lut widths.\n");
|
log(" is still constant for all lut widths.\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
|
log(" -luts <cost1>,<cost2>,<cost3>,<sizeN>:<cost4-N>,..\n");
|
||||||
|
log(" generate netlist using luts. Use the specified costs for luts with 1,\n");
|
||||||
|
log(" 2, 3, .. inputs.\n");
|
||||||
|
log("\n");
|
||||||
// log(" -mux4, -mux8, -mux16\n");
|
// log(" -mux4, -mux8, -mux16\n");
|
||||||
// log(" try to extract 4-input, 8-input, and/or 16-input muxes\n");
|
// log(" try to extract 4-input, 8-input, and/or 16-input muxes\n");
|
||||||
// log(" (ignored when used with -liberty or -lut)\n");
|
// log(" (ignored when used with -liberty or -lut)\n");
|
||||||
|
@ -1291,7 +1293,7 @@ struct AbcPass : public Pass {
|
||||||
std::string script_file, liberty_file, constr_file, clk_str, delay_target;
|
std::string script_file, liberty_file, constr_file, clk_str, delay_target;
|
||||||
bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
|
bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
|
||||||
bool show_tempdir = false;
|
bool show_tempdir = false;
|
||||||
int lut_mode = 0, lut_mode2 = 0;
|
vector<int> lut_costs;
|
||||||
markgroups = false;
|
markgroups = false;
|
||||||
|
|
||||||
map_mux4 = false;
|
map_mux4 = false;
|
||||||
|
@ -1341,6 +1343,7 @@ struct AbcPass : public Pass {
|
||||||
if (arg == "-lut" && argidx+1 < args.size()) {
|
if (arg == "-lut" && argidx+1 < args.size()) {
|
||||||
string arg = args[++argidx];
|
string arg = args[++argidx];
|
||||||
size_t pos = arg.find_first_of(':');
|
size_t pos = arg.find_first_of(':');
|
||||||
|
int lut_mode = 0, lut_mode2 = 0;
|
||||||
if (pos != string::npos) {
|
if (pos != string::npos) {
|
||||||
lut_mode = atoi(arg.substr(0, pos).c_str());
|
lut_mode = atoi(arg.substr(0, pos).c_str());
|
||||||
lut_mode2 = atoi(arg.substr(pos+1).c_str());
|
lut_mode2 = atoi(arg.substr(pos+1).c_str());
|
||||||
|
@ -1348,6 +1351,27 @@ struct AbcPass : public Pass {
|
||||||
lut_mode = atoi(arg.c_str());
|
lut_mode = atoi(arg.c_str());
|
||||||
lut_mode2 = lut_mode;
|
lut_mode2 = lut_mode;
|
||||||
}
|
}
|
||||||
|
lut_costs.clear();
|
||||||
|
for (int i = 0; i < lut_mode; i++)
|
||||||
|
lut_costs.push_back(1);
|
||||||
|
for (int i = lut_mode; i < lut_mode2; i++)
|
||||||
|
lut_costs.push_back(2 << (i - lut_mode));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (arg == "-luts" && argidx+1 < args.size()) {
|
||||||
|
lut_costs.clear();
|
||||||
|
for (auto &tok : split_tokens(args[++argidx], ",")) {
|
||||||
|
auto parts = split_tokens(tok, ":");
|
||||||
|
if (GetSize(parts) == 0 && !lut_costs.empty())
|
||||||
|
lut_costs.push_back(lut_costs.back());
|
||||||
|
else if (GetSize(parts) == 1)
|
||||||
|
lut_costs.push_back(atoi(parts.at(0).c_str()));
|
||||||
|
else if (GetSize(parts) == 2)
|
||||||
|
while (GetSize(lut_costs) < atoi(parts.at(0).c_str()))
|
||||||
|
lut_costs.push_back(atoi(parts.at(1).c_str()));
|
||||||
|
else
|
||||||
|
log_cmd_error("Invalid -luts syntax.\n");
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (arg == "-mux4") {
|
if (arg == "-mux4") {
|
||||||
|
@ -1414,7 +1438,7 @@ struct AbcPass : public Pass {
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
if (lut_mode != 0 && !liberty_file.empty())
|
if (!lut_costs.empty() && !liberty_file.empty())
|
||||||
log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n");
|
log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n");
|
||||||
if (!constr_file.empty() && liberty_file.empty())
|
if (!constr_file.empty() && liberty_file.empty())
|
||||||
log_cmd_error("Got -constr but no -liberty!\n");
|
log_cmd_error("Got -constr but no -liberty!\n");
|
||||||
|
@ -1423,7 +1447,7 @@ struct AbcPass : public Pass {
|
||||||
if (mod->processes.size() > 0)
|
if (mod->processes.size() > 0)
|
||||||
log("Skipping module %s as it contains processes.\n", log_id(mod));
|
log("Skipping module %s as it contains processes.\n", log_id(mod));
|
||||||
else if (!dff_mode || !clk_str.empty())
|
else if (!dff_mode || !clk_str.empty())
|
||||||
abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, lut_mode2, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir);
|
abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff, delay_target, fast_mode, mod->selected_cells(), show_tempdir);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assign_map.set(mod);
|
assign_map.set(mod);
|
||||||
|
@ -1567,7 +1591,7 @@ struct AbcPass : public Pass {
|
||||||
clk_sig = assign_map(std::get<1>(it.first));
|
clk_sig = assign_map(std::get<1>(it.first));
|
||||||
en_polarity = std::get<2>(it.first);
|
en_polarity = std::get<2>(it.first);
|
||||||
en_sig = assign_map(std::get<3>(it.first));
|
en_sig = assign_map(std::get<3>(it.first));
|
||||||
abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, lut_mode2,
|
abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs,
|
||||||
!clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second, show_tempdir);
|
!clk_sig.empty(), "$", keepff, delay_target, fast_mode, it.second, show_tempdir);
|
||||||
assign_map.set(mod);
|
assign_map.set(mod);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ struct SynthXilinxPass : public Pass {
|
||||||
log(" opt -fast\n");
|
log(" opt -fast\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" map_luts:\n");
|
log(" map_luts:\n");
|
||||||
log(" abc -lut 5:8 [-dff]\n");
|
log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n");
|
||||||
log(" clean\n");
|
log(" clean\n");
|
||||||
log("\n");
|
log("\n");
|
||||||
log(" map_cells:\n");
|
log(" map_cells:\n");
|
||||||
|
@ -204,7 +204,7 @@ struct SynthXilinxPass : public Pass {
|
||||||
|
|
||||||
if (check_label(active, run_from, run_to, "map_luts"))
|
if (check_label(active, run_from, run_to, "map_luts"))
|
||||||
{
|
{
|
||||||
Pass::call(design, "abc -lut 6:8" + string(retime ? " -dff" : ""));
|
Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
|
||||||
Pass::call(design, "clean");
|
Pass::call(design, "clean");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue