diff options
Diffstat (limited to 'techlibs/coolrunner2')
-rw-r--r-- | techlibs/coolrunner2/Makefile.inc | 1 | ||||
-rw-r--r-- | techlibs/coolrunner2/coolrunner2_sop.cc | 64 | ||||
-rw-r--r-- | techlibs/coolrunner2/synth_coolrunner2.cc | 33 | ||||
-rw-r--r-- | techlibs/coolrunner2/tff_extract.v | 41 |
4 files changed, 123 insertions, 16 deletions
diff --git a/techlibs/coolrunner2/Makefile.inc b/techlibs/coolrunner2/Makefile.inc index 96bbb0f47..d62c9960c 100644 --- a/techlibs/coolrunner2/Makefile.inc +++ b/techlibs/coolrunner2/Makefile.inc @@ -4,4 +4,5 @@ OBJS += techlibs/coolrunner2/coolrunner2_sop.o $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_latch.v)) $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/cells_sim.v)) +$(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/tff_extract.v)) $(eval $(call add_share_file,share/coolrunner2,techlibs/coolrunner2/xc2_dff.lib)) diff --git a/techlibs/coolrunner2/coolrunner2_sop.cc b/techlibs/coolrunner2/coolrunner2_sop.cc index b57214ccb..de0cbb29d 100644 --- a/techlibs/coolrunner2/coolrunner2_sop.cc +++ b/techlibs/coolrunner2/coolrunner2_sop.cc @@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN struct Coolrunner2SopPass : public Pass { Coolrunner2SopPass() : Pass("coolrunner2_sop", "break $sop cells into ANDTERM/ORTERM cells") { } - virtual void help() + void help() YS_OVERRIDE { log("\n"); log(" coolrunner2_sop [options] [selection]\n"); @@ -33,7 +33,7 @@ struct Coolrunner2SopPass : public Pass { log("Break $sop cells into ANDTERM/ORTERM cells.\n"); log("\n"); } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing COOLRUNNER2_SOP pass (break $sop cells into ANDTERM/ORTERM cells).\n"); extra_args(args, 1, design); @@ -60,10 +60,8 @@ struct Coolrunner2SopPass : public Pass { dict<SigBit, pool<tuple<Cell*, std::string>>> special_pterms_inv; for (auto cell : module->selected_cells()) { - if (cell->type == "\\FDCP" || cell->type == "\\FDCP_N" || cell->type == "\\FDDCP" || - cell->type == "\\FTCP" || cell->type == "\\FTCP_N" || cell->type == "\\FTDCP" || - cell->type == "\\FDCPE" || cell->type == "\\FDCPE_N" || cell->type == "\\FDDCPE" || - cell->type == "\\LDCP" || cell->type == "\\LDCP_N") + if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\FTCP", "\\FTCP_N", "\\FTDCP", + "\\FDCPE", "\\FDCPE_N", "\\FDDCPE", "\\LDCP", "\\LDCP_N")) { if (cell->hasPort("\\PRE")) special_pterms_no_inv[sigmap(cell->getPort("\\PRE")[0])].insert( @@ -250,6 +248,60 @@ struct Coolrunner2SopPass : public Pass { } } + // In some cases we can get a FF feeding straight into an FF. This is not possible, so we need to insert + // some AND/XOR cells in the middle to make it actually work. + + // Find all the FF outputs + pool<SigBit> sig_fed_by_ff; + for (auto cell : module->selected_cells()) + { + if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N", + "\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE")) + { + auto output = sigmap(cell->getPort("\\Q")[0]); + sig_fed_by_ff.insert(output); + } + } + + // Look at all the FF inputs + for (auto cell : module->selected_cells()) + { + if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N", + "\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE")) + { + SigBit input; + if (cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP")) + input = sigmap(cell->getPort("\\T")[0]); + else + input = sigmap(cell->getPort("\\D")[0]); + + if (sig_fed_by_ff[input]) + { + printf("Buffering input to \"%s\"\n", cell->name.c_str()); + + auto and_to_xor_wire = module->addWire(NEW_ID); + auto xor_to_ff_wire = module->addWire(NEW_ID); + + auto and_cell = module->addCell(NEW_ID, "\\ANDTERM"); + and_cell->setParam("\\TRUE_INP", 1); + and_cell->setParam("\\COMP_INP", 0); + and_cell->setPort("\\OUT", and_to_xor_wire); + and_cell->setPort("\\IN", input); + and_cell->setPort("\\IN_B", SigSpec()); + + auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR"); + xor_cell->setParam("\\INVERT_OUT", false); + xor_cell->setPort("\\IN_PTC", and_to_xor_wire); + xor_cell->setPort("\\OUT", xor_to_ff_wire); + + if (cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP")) + cell->setPort("\\T", xor_to_ff_wire); + else + cell->setPort("\\D", xor_to_ff_wire); + } + } + } + // Actually do the removal now that we aren't iterating for (auto cell : cells_to_remove) { diff --git a/techlibs/coolrunner2/synth_coolrunner2.cc b/techlibs/coolrunner2/synth_coolrunner2.cc index 562cce460..388e2b792 100644 --- a/techlibs/coolrunner2/synth_coolrunner2.cc +++ b/techlibs/coolrunner2/synth_coolrunner2.cc @@ -29,7 +29,7 @@ struct SynthCoolrunner2Pass : public ScriptPass { SynthCoolrunner2Pass() : ScriptPass("synth_coolrunner2", "synthesis for Xilinx Coolrunner-II CPLDs") { } - virtual void help() YS_OVERRIDE + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -55,7 +55,7 @@ struct SynthCoolrunner2Pass : public ScriptPass log(" do not flatten design before synthesis\n"); log("\n"); log(" -retime\n"); - log(" run 'abc' with -dff option\n"); + log(" run 'abc' with '-dff -D 1' options\n"); log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); @@ -66,7 +66,7 @@ struct SynthCoolrunner2Pass : public ScriptPass string top_opt, json_file; bool flatten, retime; - virtual void clear_flags() YS_OVERRIDE + void clear_flags() YS_OVERRIDE { top_opt = "-auto-top"; json_file = ""; @@ -74,7 +74,7 @@ struct SynthCoolrunner2Pass : public ScriptPass retime = false; } - virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { string run_from, run_to; clear_flags(); @@ -111,7 +111,7 @@ struct SynthCoolrunner2Pass : public ScriptPass extra_args(args, argidx, design); if (!design->full_selection()) - log_cmd_error("This comannd only operates on fully selected designs!\n"); + log_cmd_error("This command only operates on fully selected designs!\n"); log_header(design, "Executing SYNTH_COOLRUNNER2 pass.\n"); log_push(); @@ -121,7 +121,7 @@ struct SynthCoolrunner2Pass : public ScriptPass log_pop(); } - virtual void script() YS_OVERRIDE + void script() YS_OVERRIDE { if (check_label("begin")) { @@ -129,7 +129,7 @@ struct SynthCoolrunner2Pass : public ScriptPass run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str())); } - if (check_label("flatten", "(unless -noflatten)") && flatten) + if (flatten && check_label("flatten", "(unless -noflatten)")) { run("proc"); run("flatten"); @@ -149,9 +149,19 @@ struct SynthCoolrunner2Pass : public ScriptPass run("dfflibmap -prepare -liberty +/coolrunner2/xc2_dff.lib"); } + if (check_label("map_tff")) + { + // This is quite hacky. By telling abc that it can only use AND and XOR gates, abc will try and use XOR + // gates "whenever possible." This will hopefully cause toggle flip-flop structures to turn into an XOR + // connected to a D flip-flop. We then match on these and convert them into XC2 TFF cells. + run("abc -g AND,XOR"); + run("clean"); + run("extract -map +/coolrunner2/tff_extract.v"); + } + if (check_label("map_pla")) { - run("abc -sop -I 40 -P 56"); + run("abc -sop -I 40 -P 56" + string(retime ? " -dff -D 1" : "")); run("clean"); } @@ -160,10 +170,15 @@ struct SynthCoolrunner2Pass : public ScriptPass run("dfflibmap -liberty +/coolrunner2/xc2_dff.lib"); run("dffinit -ff FDCP Q INIT"); run("dffinit -ff FDCP_N Q INIT"); + run("dffinit -ff FTCP Q INIT"); + run("dffinit -ff FTCP_N Q INIT"); run("dffinit -ff LDCP Q INIT"); run("dffinit -ff LDCP_N Q INIT"); run("coolrunner2_sop"); run("iopadmap -bits -inpad IBUF O:I -outpad IOBUFE I:IO -inoutpad IOBUFE O:IO -toutpad IOBUFE E:I:IO -tinoutpad IOBUFE E:O:I:IO"); + run("attrmvcp -attr src -attr LOC t:IOBUFE n:*"); + run("attrmvcp -attr src -attr LOC -driven t:IBUF n:*"); + run("splitnets"); run("clean"); } @@ -179,8 +194,6 @@ struct SynthCoolrunner2Pass : public ScriptPass if (!json_file.empty() || help_mode) run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str())); } - - log_pop(); } } SynthCoolrunner2Pass; diff --git a/techlibs/coolrunner2/tff_extract.v b/techlibs/coolrunner2/tff_extract.v new file mode 100644 index 000000000..b4237dd18 --- /dev/null +++ b/techlibs/coolrunner2/tff_extract.v @@ -0,0 +1,41 @@ +module FTCP (C, PRE, CLR, T, Q); + input C, PRE, CLR, T; + output wire Q; + + wire xorout; + + $_XOR_ xorgate ( + .A(T), + .B(Q), + .Y(xorout), + ); + + $_DFFSR_PPP_ dff ( + .C(C), + .D(xorout), + .Q(Q), + .S(PRE), + .R(CLR), + ); +endmodule + +module FTCP_N (C, PRE, CLR, T, Q); + input C, PRE, CLR, T; + output wire Q; + + wire xorout; + + $_XOR_ xorgate ( + .A(T), + .B(Q), + .Y(xorout), + ); + + $_DFFSR_NPP_ dff ( + .C(C), + .D(xorout), + .Q(Q), + .S(PRE), + .R(CLR), + ); +endmodule |