diff options
-rw-r--r-- | CMakeLists.txt | 10 | ||||
-rw-r--r-- | common/timing.cc | 32 | ||||
-rw-r--r-- | common/timing_opt.cc | 5 | ||||
-rw-r--r-- | ecp5/bitstream.cc | 3 | ||||
-rw-r--r-- | ecp5/globals.cc | 13 | ||||
-rw-r--r-- | ecp5/lpf.cc | 3 | ||||
-rw-r--r-- | ecp5/main.cc | 10 | ||||
-rw-r--r-- | ecp5/pack.cc | 12 | ||||
-rw-r--r-- | generic/main.cc | 2 | ||||
-rw-r--r-- | ice40/main.cc | 8 |
10 files changed, 64 insertions, 34 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fa8f511..21133e3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,9 +36,11 @@ set(link_param "") if (STATIC_BUILD) set(Boost_USE_STATIC_LIBS ON) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows" AND MSVC) - set(CMAKE_CXX_FLAGS_RELEASE "/MT") - set(CMAKE_CXX_FLAGS_DEBUG "/MTd") + elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + if (MSVC) + set(CMAKE_CXX_FLAGS_RELEASE "/MT") + set(CMAKE_CXX_FLAGS_DEBUG "/MTd") + endif() if (BUILD_PYTHON) add_definitions(-DBOOST_PYTHON_STATIC_LIB) endif() @@ -309,7 +311,7 @@ foreach (family ${ARCH}) if (STATIC_BUILD) target_link_libraries(${target} LINK_PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES} ${EXPAT_LIBRARIES}) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows" AND MSVC) + elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") else() target_link_libraries(${target} LINK_PUBLIC -lutil) endif() diff --git a/common/timing.cc b/common/timing.cc index ae9a95fe..40cbb36e 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -123,9 +123,9 @@ struct Timing { const auto clk_period = ctx->getDelayFromNS(1.0e9 / ctx->setting<float>("target_freq")).maxDelay(); - // First, compute the topographical order of nets to walk through the circuit, assuming it is a _acyclic_ graph + // First, compute the topological order of nets to walk through the circuit, assuming it is a _acyclic_ graph // TODO(eddieh): Handle the case where it is cyclic, e.g. combinatorial loops - std::vector<NetInfo *> topographical_order; + std::vector<NetInfo *> topological_order; std::unordered_map<const NetInfo *, std::unordered_map<ClockEvent, TimingData>> net_data; // In lieu of deleting edges from the graph, simply count the number of fanins to each output port std::unordered_map<const PortInfo *, unsigned> port_fanin; @@ -150,7 +150,7 @@ struct Timing // If output port is influenced by a clock (e.g. FF output) then add it to the ordering as a timing // start-point if (portClass == TMG_REGISTER_OUTPUT) { - topographical_order.emplace_back(o->net); + topological_order.emplace_back(o->net); for (int i = 0; i < clocks; i++) { TimingClockingInfo clkInfo = ctx->getPortClockingInfo(cell.second.get(), o->name, i); const NetInfo *clknet = get_net_or_empty(cell.second.get(), clkInfo.clock_port); @@ -161,7 +161,7 @@ struct Timing } else { if (portClass == TMG_STARTPOINT || portClass == TMG_GEN_CLOCK || portClass == TMG_IGNORE) { - topographical_order.emplace_back(o->net); + topological_order.emplace_back(o->net); TimingData td; td.false_startpoint = (portClass == TMG_GEN_CLOCK || portClass == TMG_IGNORE); td.max_arrival = 0; @@ -185,7 +185,7 @@ struct Timing } // If there is no fanin, add the port as a false startpoint if (!port_fanin.count(o) && !net_data.count(o->net)) { - topographical_order.emplace_back(o->net); + topological_order.emplace_back(o->net); TimingData td; td.false_startpoint = true; td.max_arrival = 0; @@ -200,12 +200,12 @@ struct Timing for (auto &p : ctx->ports) { if (p.second.type != PORT_IN || p.second.net == nullptr) continue; - topographical_order.emplace_back(p.second.net); + topological_order.emplace_back(p.second.net); } } - std::deque<NetInfo *> queue(topographical_order.begin(), topographical_order.end()); - // Now walk the design, from the start points identified previously, building up a topographical order + std::deque<NetInfo *> queue(topological_order.begin(), topological_order.end()); + // Now walk the design, from the start points identified previously, building up a topological order while (!queue.empty()) { const auto net = queue.front(); queue.pop_front(); @@ -229,12 +229,12 @@ struct Timing bool is_path = ctx->getCellDelay(usr.cell, usr.port, port.first, comb_delay); if (!is_path) continue; - // Decrement the fanin count, and only add to topographical order if all its fanins have already + // Decrement the fanin count, and only add to topological order if all its fanins have already // been visited auto it = port_fanin.find(&port.second); NPNR_ASSERT(it != port_fanin.end()); if (--it->second == 0) { - topographical_order.emplace_back(port.second.net); + topological_order.emplace_back(port.second.net); queue.emplace_back(port.second.net); port_fanin.erase(it); } @@ -266,8 +266,8 @@ struct Timing "timing ports, etc.\n"); } - // Go forwards topographically to find the maximum arrival time and max path length for each net - for (auto net : topographical_order) { + // Go forwards topologically to find the maximum arrival time and max path length for each net + for (auto net : topological_order) { if (!net_data.count(net)) continue; auto &nd_map = net_data.at(net); @@ -314,9 +314,9 @@ struct Timing std::unordered_map<ClockPair, std::pair<delay_t, NetInfo *>> crit_nets; - // Now go backwards topographically to determine the minimum path slack, and to distribute all path slack evenly + // Now go backwards topologically to determine the minimum path slack, and to distribute all path slack evenly // between all nets on the path - for (auto net : boost::adaptors::reverse(topographical_order)) { + for (auto net : boost::adaptors::reverse(topological_order)) { if (!net_data.count(net)) continue; auto &nd_map = net_data.at(net); @@ -482,8 +482,8 @@ struct Timing if (net_crit) { NPNR_ASSERT(crit_path); - // Go through in reverse topographical order to set required times - for (auto net : boost::adaptors::reverse(topographical_order)) { + // Go through in reverse topological order to set required times + for (auto net : boost::adaptors::reverse(topological_order)) { if (!net_data.count(net)) continue; auto &nd_map = net_data.at(net); diff --git a/common/timing_opt.cc b/common/timing_opt.cc index 898222ab..309eedf2 100644 --- a/common/timing_opt.cc +++ b/common/timing_opt.cc @@ -39,9 +39,8 @@ namespace std { template <> struct hash<std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString>> { - std::size_t - operator()(const std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString> &idp) const - noexcept + std::size_t operator()( + const std::pair<NEXTPNR_NAMESPACE_PREFIX IdString, NEXTPNR_NAMESPACE_PREFIX IdString> &idp) const noexcept { std::size_t seed = 0; boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(idp.first)); diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index 542ee6ca..d6b1c701 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -932,7 +932,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex else log_error("cannot set DRIVE on differential IO at location %s\n", pio.c_str()); cc.tiles[pio_tile].add_enum(pio + ".DRIVE", str_or_default(ci->attrs, ctx->id("DRIVE"), "12")); - cc.tiles[pio_tile].add_enum(other + ".DRIVE", str_or_default(ci->attrs, ctx->id("DRIVE"), "12")); + cc.tiles[pio_tile].add_enum(other + ".DRIVE", + str_or_default(ci->attrs, ctx->id("DRIVE"), "12")); } } else { if (!drive_3v3_warning_done) diff --git a/ecp5/globals.cc b/ecp5/globals.cc index 65b1710f..550af615 100644 --- a/ecp5/globals.cc +++ b/ecp5/globals.cc @@ -63,11 +63,20 @@ class Ecp5GlobalRouter return false; } + bool is_logic_port(const PortRef &user) + { + if (user.cell->type == id_TRELLIS_SLICE && user.port != id_CLK && user.port != id_WCK) + return true; + return false; + } + std::vector<NetInfo *> get_clocks() { std::unordered_map<IdString, int> clockCount; for (auto &net : ctx->nets) { NetInfo *ni = net.second.get(); + if (ni->name == ctx->id("$PACKER_GND_NET") || ni->name == ctx->id("$PACKER_VCC_NET")) + continue; clockCount[ni->name] = 0; for (const auto &user : ni->users) { if (is_clock_port(user)) { @@ -160,6 +169,8 @@ class Ecp5GlobalRouter if (ctx->checkWireAvail(next)) { for (auto pip : ctx->getPipsUphill(next)) { WireId src = ctx->getPipSrcWire(pip); + if (backtrace.count(src)) + continue; backtrace[src] = pip; upstream.push(src); } @@ -412,6 +423,8 @@ class Ecp5GlobalRouter keep_users.push_back(user); } else if (net->driver.cell->type == id_EXTREFB && user.cell->type == id_DCUA) { keep_users.push_back(user); + } else if (is_logic_port(user)) { + keep_users.push_back(user); } else { glbnet->users.push_back(user); user.cell->ports.at(user.port).net = glbnet.get(); diff --git a/ecp5/lpf.cc b/ecp5/lpf.cc index e626cc54..e740b737 100644 --- a/ecp5/lpf.cc +++ b/ecp5/lpf.cc @@ -48,6 +48,9 @@ bool Arch::applyLPF(std::string filename, std::istream &in) size_t cstart = line.find('#'); if (cstart != std::string::npos) line = line.substr(0, cstart); + cstart = line.find("//"); + if (cstart != std::string::npos) + line = line.substr(0, cstart); if (isempty(line)) continue; linebuf += line; diff --git a/ecp5/main.cc b/ecp5/main.cc index a24011db..f1cb9760 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -174,12 +174,12 @@ std::unique_ptr<Context> ECP5CommandHandler::createContext(std::unordered_map<st if (values.find("arch.name") != values.end()) { std::string arch_name = values["arch.name"].as_string(); if (arch_name != "ecp5") - log_error("Unsuported architecture '%s'.\n", arch_name.c_str()); + log_error("Unsupported architecture '%s'.\n", arch_name.c_str()); } if (values.find("arch.type") != values.end()) { std::string arch_type = values["arch.type"].as_string(); if (chipArgs.type != ArchArgs::NONE) - log_error("Overriding architecture is unsuported.\n"); + log_error("Overriding architecture is unsupported.\n"); if (arch_type == "lfe5u_12f") chipArgs.type = ArchArgs::LFE5U_12F; @@ -203,11 +203,11 @@ std::unique_ptr<Context> ECP5CommandHandler::createContext(std::unordered_map<st chipArgs.type = ArchArgs::LFE5UM5G_85F; if (chipArgs.type == ArchArgs::NONE) - log_error("Unsuported FPGA type '%s'.\n", arch_type.c_str()); + log_error("Unsupported FPGA type '%s'.\n", arch_type.c_str()); } if (values.find("arch.package") != values.end()) { if (vm.count("package")) - log_error("Overriding architecture is unsuported.\n"); + log_error("Overriding architecture is unsupported.\n"); chipArgs.package = values["arch.package"].as_string(); } if (values.find("arch.speed") != values.end()) { @@ -219,7 +219,7 @@ std::unique_ptr<Context> ECP5CommandHandler::createContext(std::unordered_map<st else if (arch_speed == "8") chipArgs.speed = ArchArgs::SPEED_8; else - log_error("Unsuported speed '%s'.\n", arch_speed.c_str()); + log_error("Unsupported speed '%s'.\n", arch_speed.c_str()); } if (chipArgs.type == ArchArgs::NONE) chipArgs.type = ArchArgs::LFE5U_45F; diff --git a/ecp5/pack.cc b/ecp5/pack.cc index 55b2c791..fb8a95e9 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -1617,6 +1617,18 @@ class Ecp5Packer for (auto pin : ctx->getBelPins(exemplar_bel)) if (ctx->getBelPinType(exemplar_bel, pin) == PORT_IN) autocreate_empty_port(ci, pin); + // Disconnect these ports if connected to constant to prevent routing failure + for (auto ndport : {id_D_TXBIT_CLKP_FROM_ND, id_D_TXBIT_CLKN_FROM_ND, id_D_SYNC_ND, + id_D_TXPLL_LOL_FROM_ND, id_CH0_HDINN, id_CH0_HDINP, id_CH1_HDINN, id_CH1_HDINP}) { + const NetInfo *net = get_net_or_empty(ci, ndport); + if (net == nullptr || net->driver.cell == nullptr) + continue; + IdString ct = net->driver.cell->type; + if (ct == ctx->id("GND") || ct == ctx->id("VCC")) { + disconnect_port(ctx, ci, ndport); + ci->ports.erase(ndport); + } + } } } for (auto cell : sorted(ctx->cells)) { diff --git a/generic/main.cc b/generic/main.cc index bb780996..784178c6 100644 --- a/generic/main.cc +++ b/generic/main.cc @@ -58,7 +58,7 @@ std::unique_ptr<Context> GenericCommandHandler::createContext(std::unordered_map if (values.find("arch.name") != values.end()) { std::string arch_name = values["arch.name"].as_string(); if (arch_name != "generic") - log_error("Unsuported architecture '%s'.\n", arch_name.c_str()); + log_error("Unsupported architecture '%s'.\n", arch_name.c_str()); } auto ctx = std::unique_ptr<Context>(new Context(chipArgs)); if (vm.count("no-iobs")) diff --git a/ice40/main.cc b/ice40/main.cc index 3b512a5a..07c91399 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -163,12 +163,12 @@ std::unique_ptr<Context> Ice40CommandHandler::createContext(std::unordered_map<s if (values.find("arch.name") != values.end()) { std::string arch_name = values["arch.name"].as_string(); if (arch_name != "ice40") - log_error("Unsuported architecture '%s'.\n", arch_name.c_str()); + log_error("Unsupported architecture '%s'.\n", arch_name.c_str()); } if (values.find("arch.type") != values.end()) { std::string arch_type = values["arch.type"].as_string(); if (chipArgs.type != ArchArgs::NONE) - log_error("Overriding architecture is unsuported.\n"); + log_error("Overriding architecture is unsupported.\n"); if (arch_type == "lp384") { chipArgs.type = ArchArgs::LP384; @@ -192,11 +192,11 @@ std::unique_ptr<Context> Ice40CommandHandler::createContext(std::unordered_map<s chipArgs.type = ArchArgs::U4K; } if (chipArgs.type == ArchArgs::NONE) - log_error("Unsuported FPGA type '%s'.\n", arch_type.c_str()); + log_error("Unsupported FPGA type '%s'.\n", arch_type.c_str()); } if (values.find("arch.package") != values.end()) { if (vm.count("package")) - log_error("Overriding architecture is unsuported.\n"); + log_error("Overriding architecture is unsupported.\n"); chipArgs.package = values["arch.package"].as_string(); } |