Merge pull request #962 from YosysHQ/eddie/refactor_synth_xilinx

Refactor synth_xilinx to auto-generate doc
This commit is contained in:
Clifford Wolf 2019-04-30 18:07:19 +02:00 committed by GitHub
commit 5bc4de077a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 107 additions and 162 deletions

View File

@ -225,11 +225,13 @@ struct SynthIce40Pass : public ScriptPass
run("proc"); run("proc");
} }
if (flatten && check_label("flatten", "(unless -noflatten)")) if (check_label("flatten", "(unless -noflatten)"))
{ {
run("flatten"); if (flatten) {
run("tribuf -logic"); run("flatten");
run("deminout"); run("tribuf -logic");
run("deminout");
}
} }
if (check_label("coarse")) if (check_label("coarse"))

View File

@ -25,18 +25,9 @@
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN PRIVATE_NAMESPACE_BEGIN
bool check_label(bool &active, std::string run_from, std::string run_to, std::string label) struct SynthXilinxPass : public ScriptPass
{ {
if (label == run_from) SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
active = true;
if (label == run_to)
active = false;
return active;
}
struct SynthXilinxPass : public Pass
{
SynthXilinxPass() : Pass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
void help() YS_OVERRIDE void help() YS_OVERRIDE
{ {
@ -85,79 +76,30 @@ struct SynthXilinxPass : public Pass
log("\n"); log("\n");
log("\n"); log("\n");
log("The following commands are executed by this synthesis command:\n"); log("The following commands are executed by this synthesis command:\n");
log("\n"); help_script();
log(" begin:\n");
log(" read_verilog -lib +/xilinx/cells_sim.v\n");
log(" read_verilog -lib +/xilinx/cells_xtra.v\n");
log(" read_verilog -lib +/xilinx/brams_bb.v\n");
log(" hierarchy -check -top <top>\n");
log("\n");
log(" flatten: (only if -flatten)\n");
log(" proc\n");
log(" flatten\n");
log("\n");
log(" coarse:\n");
log(" synth -run coarse\n");
log("\n");
log(" bram: (only executed when '-nobram' is not given)\n");
log(" memory_bram -rules +/xilinx/brams.txt\n");
log(" techmap -map +/xilinx/brams_map.v\n");
log("\n");
log(" dram: (only executed when '-nodram' is not given)\n");
log(" memory_bram -rules +/xilinx/drams.txt\n");
log(" techmap -map +/xilinx/drams_map.v\n");
log("\n");
log(" fine:\n");
log(" opt -fast\n");
log(" memory_map\n");
log(" dffsr2dff\n");
log(" dff2dffe\n");
log(" techmap -map +/xilinx/arith_map.v\n");
log(" opt -fast\n");
log("\n");
log(" map_cells:\n");
log(" simplemap t:$dff t:$dffe (without '-nosrl' only)\n");
log(" pmux2shiftx (without '-nosrl' only)\n");
log(" opt_expr -mux_undef (without '-nosrl' only)\n");
log(" shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n");
log(" techmap -map +/xilinx/cells_map.v\n");
log(" clean\n");
log("\n");
log(" map_luts:\n");
log(" opt -full\n");
log(" techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v\n");
log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n");
log(" clean\n");
log(" shregmap -minlen 3 -init -params -enpol any_or_none (without '-nosrl' only)\n");
log(" techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT \\\n");
log(" -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n");
log(" clean\n");
log("\n");
log(" check:\n");
log(" hierarchy -check\n");
log(" stat\n");
log(" check -noinit\n");
log("\n");
log(" edif: (only if -edif)\n");
log(" write_edif <file-name>\n");
log("\n");
log(" blif: (only if -blif)\n");
log(" write_blif <file-name>\n");
log("\n"); log("\n");
} }
std::string top_opt, edif_file, blif_file;
bool flatten, retime, vpr, nobram, nodram, nosrl;
void clear_flags() YS_OVERRIDE
{
top_opt = "-auto-top";
edif_file.clear();
blif_file.clear();
flatten = false;
retime = false;
vpr = false;
nobram = false;
nodram = false;
nosrl = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{ {
std::string top_opt = "-auto-top";
std::string edif_file;
std::string blif_file;
std::string run_from, run_to; std::string run_from, run_to;
bool flatten = false; clear_flags();
bool retime = false;
bool vpr = false;
bool nobram = false;
bool nodram = false;
bool nosrl = false;
size_t argidx; size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) for (argidx = 1; argidx < args.size(); argidx++)
@ -213,127 +155,128 @@ struct SynthXilinxPass : public Pass
if (!design->full_selection()) if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n"); log_cmd_error("This command only operates on fully selected designs!\n");
bool active = run_from.empty();
log_header(design, "Executing SYNTH_XILINX pass.\n"); log_header(design, "Executing SYNTH_XILINX pass.\n");
log_push(); log_push();
if (check_label(active, run_from, run_to, "begin")) run_script(design, run_from, run_to);
{
if (vpr) {
Pass::call(design, "read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
} else {
Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v");
}
Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v"); log_pop();
}
if (!nobram) { void script() YS_OVERRIDE
Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); {
} if (check_label("begin")) {
if (vpr)
run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v");
else
run("read_verilog -lib +/xilinx/cells_sim.v");
Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str())); run("read_verilog -lib +/xilinx/cells_xtra.v");
if (!nobram || help_mode)
run("read_verilog -lib +/xilinx/brams_bb.v", "(skip if '-nobram')");
run(stringf("hierarchy -check %s", top_opt.c_str()));
} }
if (flatten && check_label(active, run_from, run_to, "flatten")) if (check_label("flatten", "(with '-flatten' only)")) {
{ if (flatten || help_mode) {
Pass::call(design, "proc"); run("proc");
Pass::call(design, "flatten"); run("flatten");
}
if (check_label(active, run_from, run_to, "coarse"))
{
Pass::call(design, "synth -run coarse");
}
if (check_label(active, run_from, run_to, "bram"))
{
if (!nobram) {
Pass::call(design, "memory_bram -rules +/xilinx/brams.txt");
Pass::call(design, "techmap -map +/xilinx/brams_map.v");
} }
} }
if (check_label(active, run_from, run_to, "dram")) if (check_label("coarse")) {
{ run("synth -run coarse");
if (!nodram) { }
Pass::call(design, "memory_bram -rules +/xilinx/drams.txt");
Pass::call(design, "techmap -map +/xilinx/drams_map.v"); if (check_label("bram", "(skip if '-nobram')")) {
if (!nobram || help_mode) {
run("memory_bram -rules +/xilinx/brams.txt");
run("techmap -map +/xilinx/brams_map.v");
} }
} }
if (check_label(active, run_from, run_to, "fine")) if (check_label("dram", "(skip if '-nodram')")) {
{ if (!nodram || help_mode) {
Pass::call(design, "opt -fast"); run("memory_bram -rules +/xilinx/drams.txt");
Pass::call(design, "memory_map"); run("techmap -map +/xilinx/drams_map.v");
Pass::call(design, "dffsr2dff");
Pass::call(design, "dff2dffe");
if (vpr) {
Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY");
} else {
Pass::call(design, "techmap -map +/xilinx/arith_map.v");
} }
Pass::call(design, "opt -fast");
} }
if (check_label(active, run_from, run_to, "map_cells")) if (check_label("fine")) {
run("opt -fast");
run("memory_map");
run("dffsr2dff");
run("dff2dffe");
if (!vpr || help_mode)
run("techmap -map +/xilinx/arith_map.v");
else
run("techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY");
run("hierarchy -check");
run("opt -fast");
}
if (check_label("map_cells"))
{ {
if (!nosrl) { if (!nosrl || help_mode) {
// shregmap operates on bit-level flops, not word-level, // shregmap operates on bit-level flops, not word-level,
// so break those down here // so break those down here
Pass::call(design, "simplemap t:$dff t:$dffe"); run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')");
// shregmap -tech xilinx can cope with $shiftx and $mux // shregmap -tech xilinx can cope with $shiftx and $mux
// cells for identifiying variable-length shift registers, // cells for identifiying variable-length shift registers,
// so attempt to convert $pmux-es to the former // so attempt to convert $pmux-es to the former
Pass::call(design, "pmux2shiftx"); run("pmux2shiftx", "(skip if '-nosrl')");
// pmux2shiftx can leave behind a $pmux with a single entry // pmux2shiftx can leave behind a $pmux with a single entry
// -- need this to clean that up before shregmap // -- need this to clean that up before shregmap
Pass::call(design, "opt_expr -mux_undef"); run("opt_expr -mux_undef", "(skip if '-nosrl')");
// shregmap with '-tech xilinx' infers variable length shift regs // shregmap with '-tech xilinx' infers variable length shift regs
Pass::call(design, "shregmap -tech xilinx -minlen 3"); run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')");
} }
Pass::call(design, "techmap -map +/xilinx/cells_map.v"); run("techmap -map +/xilinx/cells_map.v");
Pass::call(design, "clean"); run("clean");
} }
if (check_label(active, run_from, run_to, "map_luts")) if (check_label("map_luts"))
{ {
Pass::call(design, "opt -full"); run("opt -full");
Pass::call(design, "techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v"); run("techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v");
Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); if (help_mode)
Pass::call(design, "clean"); run("abc -luts 2:2,3,6:5,10,20 [-dff]");
else
run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
run("clean");
// This shregmap call infers fixed length shift registers after abc // This shregmap call infers fixed length shift registers after abc
// has performed any necessary retiming // has performed any necessary retiming
if (!nosrl) if (!nosrl || help_mode)
Pass::call(design, "shregmap -minlen 3 -init -params -enpol any_or_none"); run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')");
Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); "-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
Pass::call(design, "clean"); run("clean");
} }
if (check_label(active, run_from, run_to, "check")) if (check_label("check"))
{ {
Pass::call(design, "hierarchy -check"); run("hierarchy -check");
Pass::call(design, "stat"); run("stat");
Pass::call(design, "check -noinit"); run("check -noinit");
} }
if (check_label(active, run_from, run_to, "edif")) if (check_label("edif"))
{ {
if (!edif_file.empty()) if (!edif_file.empty() || help_mode)
Pass::call(design, stringf("write_edif -pvector bra %s", edif_file.c_str())); run(stringf("write_edif -pvector bra %s", edif_file.c_str()));
}
if (check_label(active, run_from, run_to, "blif"))
{
if (!blif_file.empty())
Pass::call(design, stringf("write_blif %s", edif_file.c_str()));
} }
log_pop(); if (check_label("blif"))
{
if (!blif_file.empty() || help_mode)
run(stringf("write_blif %s", edif_file.c_str()));
}
} }
} SynthXilinxPass; } SynthXilinxPass;