diff --git a/common/base_arch.h b/common/base_arch.h index e9cc8cf0..fbafee99 100644 --- a/common/base_arch.h +++ b/common/base_arch.h @@ -75,7 +75,7 @@ typename std::enable_if::value, Tret>::type return_if_mat } template -typename std::enable_if::value, Tret>::type return_if_match(Tret r) +typename std::enable_if::value, Tc>::type return_if_match(Tret r) { NPNR_ASSERT_FALSE("default implementations of cell type and bel bucket range functions only available when the " "respective range types are 'const std::vector&'"); diff --git a/mistral/arch.cc b/mistral/arch.cc index fd2f345d..aa149a3c 100644 --- a/mistral/arch.cc +++ b/mistral/arch.cc @@ -21,6 +21,13 @@ #include "log.h" #include "nextpnr.h" +#include "placer1.h" +#include "placer_heap.h" +#include "router1.h" +#include "router2.h" +#include "timing.h" +#include "util.h" + #include "cyclonev.h" NEXTPNR_NAMESPACE_BEGIN @@ -244,10 +251,6 @@ BelBucketId Arch::getBelBucketForCellType(IdString cell_type) const return cell_type; } -bool Arch::pack() { return true; } -bool Arch::place() { return true; } -bool Arch::route() { return true; } - BelId Arch::add_bel(int x, int y, IdString name, IdString type) { auto &bels = bels_by_tile.at(pos2idx(x, y)); @@ -321,6 +324,68 @@ void Arch::assign_default_pinmap(CellInfo *cell) } } +void Arch::assignArchInfo() +{ + for (auto cell : sorted(cells)) { + CellInfo *ci = cell.second; + if (is_comb_cell(ci->type)) + assign_comb_info(ci); + else if (ci->type == id_MISTRAL_FF) + assign_ff_info(ci); + assign_default_pinmap(ci); + } +} + +bool Arch::place() +{ + std::string placer = str_or_default(settings, id("placer"), defaultPlacer); + + if (placer == "heap") { + PlacerHeapCfg cfg(getCtx()); + cfg.ioBufTypes.insert(id_MISTRAL_IO); + cfg.ioBufTypes.insert(id_MISTRAL_IB); + cfg.ioBufTypes.insert(id_MISTRAL_OB); + cfg.cellGroups.emplace_back(); + cfg.cellGroups.back().insert({id_MISTRAL_COMB}); + cfg.cellGroups.back().insert({id_MISTRAL_FF}); + + cfg.beta = 0.5; // TODO: find a good value of beta for sensible ALM spreading + cfg.criticalityExponent = 7; + if (!placer_heap(getCtx(), cfg)) + return false; + } else if (placer == "sa") { + if (!placer1(getCtx(), Placer1Cfg(getCtx()))) + return false; + } else { + log_error("Mistral architecture does not support placer '%s'\n", placer.c_str()); + } + + getCtx()->attrs[getCtx()->id("step")] = std::string("place"); + archInfoToAttributes(); + return true; +} + +bool Arch::route() +{ + assign_budget(getCtx(), true); + + lab_pre_route(); + + std::string router = str_or_default(settings, id("router"), defaultRouter); + bool result; + if (router == "router1") { + result = router1(getCtx(), Router1Cfg(getCtx())); + } else if (router == "router2") { + router2(getCtx(), Router2Cfg(getCtx())); + result = true; + } else { + log_error("Mistral architecture does not support router '%s'\n", router.c_str()); + } + getCtx()->attrs[getCtx()->id("step")] = std::string("route"); + archInfoToAttributes(); + return result; +} + #ifdef WITH_HEAP const std::string Arch::defaultPlacer = "heap"; #else diff --git a/mistral/arch.h b/mistral/arch.h index ff006881..dd684dfe 100644 --- a/mistral/arch.h +++ b/mistral/arch.h @@ -214,6 +214,7 @@ struct ArchRanges : BaseArchRanges using AllBelsRangeT = const std::vector &; using TileBelsRangeT = std::vector; using BelPinsRangeT = std::vector; + using CellBelPinRangeT = const std::vector &; // Wires using AllWiresRangeT = AllWireRange; using DownhillPipRangeT = UpDownhillPipRange; @@ -315,11 +316,17 @@ struct Arch : BaseArch // ------------------------------------------------- + const std::vector &getBelPinsForCellPin(const CellInfo *cell_info, IdString pin) const override + { + return cell_info->pin_data.at(pin).bel_pins; + } + bool isValidBelForCellType(IdString cell_type, BelId bel) const override; BelBucketId getBelBucketForCellType(IdString cell_type) const override; // ------------------------------------------------- + void assignArchInfo() override; bool pack() override; bool place() override; bool route() override; @@ -350,6 +357,10 @@ struct Arch : BaseArch void assign_comb_info(CellInfo *cell) const; // lab.cc void assign_ff_info(CellInfo *cell) const; // lab.cc + void lab_pre_route(); // lab.cc + void assign_control_sets(uint32_t lab); // lab.cc + void reassign_alm_inputs(uint32_t lab, uint8_t alm); // lab.cc + // ------------------------------------------------- bool is_io_cell(IdString cell_type) const; // io.cc diff --git a/mistral/lab.cc b/mistral/lab.cc index 1f117106..f01c6e95 100644 --- a/mistral/lab.cc +++ b/mistral/lab.cc @@ -388,6 +388,33 @@ bool Arch::is_lab_ctrlset_legal(uint32_t lab) const return true; } +void Arch::lab_pre_route() +{ + for (uint32_t lab = 0; lab < labs.size(); lab++) { + assign_control_sets(lab); + for (uint8_t alm = 0; alm < 10; alm++) { + reassign_alm_inputs(lab, alm); + } + } +} + +void Arch::assign_control_sets(uint32_t lab) +{ + // TODO: set up reservations for checkPipAvailForNet for control set signals + // This will be needed because clock and CE are routed together and must be kept together, there isn't free choice + // e.g. CLK0 & ENA0 must be use for one control set, and CLK1 & ENA1 for another, they can't be mixed and matched +} + +void Arch::reassign_alm_inputs(uint32_t lab, uint8_t alm) +{ + // TODO: based on the usage of LUTs inside the ALM, set up cell-bel pin map for the combinational cells in the ALM + // so that each physical bel pin is only used for one net; and the logical functions can be implemented correctly. + // This function should also insert route-through LUTs to legalise flipflop inputs as needed. + // TODO: in the future, as well as the reassignment here we will also have pseudo PIPs in front of the ALM so that + // the router can permute LUTs for routeability; too. Here we will need to lock out some of those PIPs depending on + // the usage of the ALM, as not all inputs are always interchangeable. +} + // This default cell-bel pin mapping is used to provide estimates during placement only. It will have errors and // overlaps and a correct mapping will be resolved twixt placement and routing const std::unordered_map Arch::comb_pinmap = { diff --git a/mistral/pack.cc b/mistral/pack.cc new file mode 100644 index 00000000..78a000d9 --- /dev/null +++ b/mistral/pack.cc @@ -0,0 +1,35 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2021 gatecat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "log.h" +#include "nextpnr.h" +#include "util.h" + +NEXTPNR_NAMESPACE_BEGIN + +bool Arch::pack() +{ + // TODO: + // - Insert constant driver LUTs + // - Fold constants and inverters into cell pins + // - Constrain IO + return true; +} + +NEXTPNR_NAMESPACE_END \ No newline at end of file