diff options
author | Clifford Wolf <clifford@clifford.at> | 2018-11-09 12:57:14 +0100 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2018-11-09 12:57:14 +0100 |
commit | 66dd17664c08aca17b53d2853558121aa9e702e4 (patch) | |
tree | b6bc5dd919e5f525ec7328861b81f616673a1ea6 /ecp5/arch.cc | |
parent | e91241f10d68fcaaf0a81fa77e9a91666120ccee (diff) | |
parent | 15d9b3d3cc05656e58d01ba2f97ec92b6daaee1c (diff) | |
download | nextpnr-66dd17664c08aca17b53d2853558121aa9e702e4.tar.gz nextpnr-66dd17664c08aca17b53d2853558121aa9e702e4.tar.bz2 nextpnr-66dd17664c08aca17b53d2853558121aa9e702e4.zip |
Merge branch 'master' of github.com:YosysHQ/nextpnr into router_improve
Diffstat (limited to 'ecp5/arch.cc')
-rw-r--r-- | ecp5/arch.cc | 108 |
1 files changed, 102 insertions, 6 deletions
diff --git a/ecp5/arch.cc b/ecp5/arch.cc index 82ebfba1..4a0b31b5 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -19,13 +19,16 @@ */ #include <algorithm> +#include <boost/range/adaptor/reversed.hpp> #include <cmath> #include <cstring> #include "gfx.h" +#include "globals.h" #include "log.h" #include "nextpnr.h" #include "placer1.h" #include "router1.h" +#include "timing.h" #include "util.h" NEXTPNR_NAMESPACE_BEGIN @@ -74,11 +77,13 @@ Arch::Arch(ArchArgs args) : args(args) log_error("Unsupported ECP5 chip type.\n"); } #else - if (args.type == ArchArgs::LFE5U_25F) { + if (args.type == ArchArgs::LFE5U_25F || args.type == ArchArgs::LFE5UM_25F || args.type == ArchArgs::LFE5UM5G_25F) { chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_25k)); - } else if (args.type == ArchArgs::LFE5U_45F) { + } else if (args.type == ArchArgs::LFE5U_45F || args.type == ArchArgs::LFE5UM_45F || + args.type == ArchArgs::LFE5UM5G_45F) { chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_45k)); - } else if (args.type == ArchArgs::LFE5U_85F) { + } else if (args.type == ArchArgs::LFE5U_85F || args.type == ArchArgs::LFE5UM_85F || + args.type == ArchArgs::LFE5UM5G_85F) { chip_info = get_chip_info(reinterpret_cast<const RelPtr<ChipInfoPOD> *>(chipdb_blob_85k)); } else { log_error("Unsupported ECP5 chip type.\n"); @@ -108,6 +113,18 @@ std::string Arch::getChipName() const return "LFE5U-45F"; } else if (args.type == ArchArgs::LFE5U_85F) { return "LFE5U-85F"; + } else if (args.type == ArchArgs::LFE5UM_25F) { + return "LFE5UM-25F"; + } else if (args.type == ArchArgs::LFE5UM_45F) { + return "LFE5UM-45F"; + } else if (args.type == ArchArgs::LFE5UM_85F) { + return "LFE5UM-85F"; + } else if (args.type == ArchArgs::LFE5UM5G_25F) { + return "LFE5UM5G-25F"; + } else if (args.type == ArchArgs::LFE5UM5G_45F) { + return "LFE5UM5G-45F"; + } else if (args.type == ArchArgs::LFE5UM5G_85F) { + return "LFE5UM5G-85F"; } else { log_error("Unknown chip\n"); } @@ -123,6 +140,18 @@ IdString Arch::archArgsToId(ArchArgs args) const return id("lfe5u_45f"); if (args.type == ArchArgs::LFE5U_85F) return id("lfe5u_85f"); + if (args.type == ArchArgs::LFE5UM_25F) + return id("lfe5um_25f"); + if (args.type == ArchArgs::LFE5UM_45F) + return id("lfe5um_45f"); + if (args.type == ArchArgs::LFE5UM_85F) + return id("lfe5um_85f"); + if (args.type == ArchArgs::LFE5UM5G_25F) + return id("lfe5um5g_25f"); + if (args.type == ArchArgs::LFE5UM5G_45F) + return id("lfe5um5g_45f"); + if (args.type == ArchArgs::LFE5UM5G_85F) + return id("lfe5um5g_85f"); return IdString(); } @@ -389,7 +418,12 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); } -bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); } +bool Arch::route() +{ + route_ecp5_globals(getCtx()); + assign_budget(getCtx(), true); + return router1(getCtx(), Router1Cfg(getCtx())); +} // ----------------------------------------------------------------------- @@ -504,12 +538,12 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort delay.delay = 193; return true; } - +#if 0 // FIXME if (fromPort == id_WCK && (toPort == id_F0 || toPort == id_F1)) { delay.delay = 717; return true; } - +#endif if ((fromPort == id_A0 && toPort == id_WADO3) || (fromPort == id_A1 && toPort == id_WDO1) || (fromPort == id_B0 && toPort == id_WADO1) || (fromPort == id_B1 && toPort == id_WDO3) || (fromPort == id_C0 && toPort == id_WADO2) || (fromPort == id_C1 && toPort == id_WDO0) || @@ -518,6 +552,25 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort return true; } return false; + } else if (cell->type == id_DCCA) { + if (fromPort == id_CLKI && toPort == id_CLKO) { + delay.delay = 0; + return true; + } + return false; + } else if (cell->type == id_DP16KD) { + if (fromPort == id_CLKA) { + if (toPort.str(this).substr(0, 3) == "DOA") { + delay.delay = 4260; + return true; + } + } else if (fromPort == id_CLKB) { + if (toPort.str(this).substr(0, 3) == "DOB") { + delay.delay = 4280; + return true; + } + } + return false; } else { return false; } @@ -525,6 +578,8 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, IdString &clockPort) const { + auto disconnected = [cell](IdString p) { return !cell->ports.count(p) || cell->ports.at(p).net == nullptr; }; + if (cell->type == id_TRELLIS_SLICE) { int sd0 = int_or_default(cell->params, id("REG0_SD"), 0), sd1 = int_or_default(cell->params, id("REG1_SD"), 0); if (port == id_CLK || port == id_WCK) @@ -532,6 +587,13 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, Id if (port == id_A0 || port == id_A1 || port == id_B0 || port == id_B1 || port == id_C0 || port == id_C1 || port == id_D0 || port == id_D1 || port == id_FCI || port == id_FXA || port == id_FXB) return TMG_COMB_INPUT; + if (port == id_F0 && disconnected(id_A0) && disconnected(id_B0) && disconnected(id_C0) && disconnected(id_D0) && + disconnected(id_FCI)) + return TMG_IGNORE; // LUT with no inputs is a constant + if (port == id_F1 && disconnected(id_A1) && disconnected(id_B1) && disconnected(id_C1) && disconnected(id_D1) && + disconnected(id_FCI)) + return TMG_IGNORE; // LUT with no inputs is a constant + if (port == id_F0 || port == id_F1 || port == id_FCO || port == id_OFX0 || port == id_OFX1) return TMG_COMB_OUTPUT; if (port == id_DI0 || port == id_DI1 || port == id_CE || port == id_LSR || (sd0 == 1 && port == id_M0) || @@ -563,6 +625,34 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, Id if (port == id_O) return TMG_STARTPOINT; return TMG_IGNORE; + } else if (cell->type == id_DCCA) { + if (port == id_CLKI) + return TMG_COMB_INPUT; + if (port == id_CLKO) + return TMG_COMB_OUTPUT; + return TMG_IGNORE; + } else if (cell->type == id_DP16KD) { + if (port == id_CLKA || port == id_CLKB) + return TMG_CLOCK_INPUT; + std::string port_name = port.str(this); + for (auto c : boost::adaptors::reverse(port_name)) { + if (std::isdigit(c)) + continue; + if (c == 'A') + clockPort = id_CLKA; + else if (c == 'B') + clockPort = id_CLKB; + else + NPNR_ASSERT_FALSE_STR("bad ram port"); + return (cell->ports.at(port).type == PORT_OUT) ? TMG_REGISTER_OUTPUT : TMG_REGISTER_INPUT; + } + NPNR_ASSERT_FALSE_STR("no timing type for RAM port '" + port.str(this) + "'"); + } else if (cell->type == id_MULT18X18D) { + return TMG_IGNORE; // FIXME + } else if (cell->type == id_ALU54B) { + return TMG_IGNORE; // FIXME + } else if (cell->type == id_EHXPLLL) { + return TMG_IGNORE; } else { NPNR_ASSERT_FALSE_STR("no timing data for cell type '" + cell->type.str(this) + "'"); } @@ -579,4 +669,10 @@ std::vector<std::pair<std::string, std::string>> Arch::getTilesAtLocation(int ro return ret; } +GlobalInfoPOD Arch::globalInfoAtLoc(Location loc) +{ + int locidx = loc.y * chip_info->width + loc.x; + return chip_info->location_glbinfo[locidx]; +} + NEXTPNR_NAMESPACE_END |