From 7239331d5463321d4864164f320beef67310f1e5 Mon Sep 17 00:00:00 2001 From: gatecat Date: Mon, 13 Dec 2021 15:57:28 +0000 Subject: [PATCH] libtrellis: LUT permutation support for ECP5 Signed-off-by: gatecat --- libtrellis/include/Chip.hpp | 4 ++-- libtrellis/include/DedupChipdb.hpp | 6 ++++-- libtrellis/include/RoutingGraph.hpp | 1 + libtrellis/src/Chip.cpp | 32 +++++++++++++++++++++++++---- libtrellis/src/DedupChipdb.cpp | 5 +++-- libtrellis/src/PyTrellis.cpp | 6 ++++-- 6 files changed, 42 insertions(+), 12 deletions(-) diff --git a/libtrellis/include/Chip.hpp b/libtrellis/include/Chip.hpp index c5295ce0..3d0b7490 100644 --- a/libtrellis/include/Chip.hpp +++ b/libtrellis/include/Chip.hpp @@ -177,7 +177,7 @@ class Chip int get_max_col() const; // Build the routing graph for the chip - shared_ptr get_routing_graph(); + shared_ptr get_routing_graph(bool include_lutperm_pips = false); vector>>> tiles_at_location; @@ -191,7 +191,7 @@ class Chip private: // Factory functions - shared_ptr get_routing_graph_ecp5(); + shared_ptr get_routing_graph_ecp5(bool include_lutperm_pips = false); shared_ptr get_routing_graph_machxo2(); }; diff --git a/libtrellis/include/DedupChipdb.hpp b/libtrellis/include/DedupChipdb.hpp index fc6468f1..3c3d0df5 100644 --- a/libtrellis/include/DedupChipdb.hpp +++ b/libtrellis/include/DedupChipdb.hpp @@ -81,12 +81,13 @@ struct DdArcData ArcClass cls; int32_t delay; ident_t tiletype; + int16_t lutperm_flags; }; inline bool operator==(const DdArcData &a, const DdArcData &b) { return a.srcWire == b.srcWire && a.sinkWire == b.sinkWire && a.cls == b.cls && a.delay == b.delay && - a.tiletype == b.tiletype; + a.tiletype == b.tiletype && a.lutperm_flags == b.lutperm_flags; } struct WireData @@ -241,6 +242,7 @@ struct hash boost::hash_combine(seed, hash()(arc.cls)); boost::hash_combine(seed, hash()(arc.delay)); boost::hash_combine(seed, hash()(arc.tiletype)); + boost::hash_combine(seed, hash()(arc.lutperm_flags)); return seed; } }; @@ -355,7 +357,7 @@ struct DedupChipdb : public IdStore LocationData get_cs_data(checksum_t id); }; -shared_ptr make_dedup_chipdb(Chip &chip); +shared_ptr make_dedup_chipdb(Chip &chip, bool include_lutperm_pips = false); /* An optimized chip database is a database with the following properties, intended to be used in place-and-route flows. diff --git a/libtrellis/include/RoutingGraph.hpp b/libtrellis/include/RoutingGraph.hpp index bacc6a19..f0509e8a 100644 --- a/libtrellis/include/RoutingGraph.hpp +++ b/libtrellis/include/RoutingGraph.hpp @@ -64,6 +64,7 @@ struct RoutingArc RoutingId source; RoutingId sink; bool configurable = false; + uint16_t lutperm_flags = 0; mutable int cdb_id = 0; }; diff --git a/libtrellis/src/Chip.cpp b/libtrellis/src/Chip.cpp index e8049698..99bc26d0 100644 --- a/libtrellis/src/Chip.cpp +++ b/libtrellis/src/Chip.cpp @@ -113,17 +113,17 @@ ChipDelta operator-(const Chip &a, const Chip &b) return delta; } -shared_ptr Chip::get_routing_graph() +shared_ptr Chip::get_routing_graph(bool include_lutperm_pips) { if(info.family == "ECP5") { - return get_routing_graph_ecp5(); + return get_routing_graph_ecp5(include_lutperm_pips); } else if(info.family == "MachXO2") { return get_routing_graph_machxo2(); } else throw runtime_error("Unknown chip family: " + info.family); } -shared_ptr Chip::get_routing_graph_ecp5() +shared_ptr Chip::get_routing_graph_ecp5(bool include_lutperm_pips) { shared_ptr rg(new RoutingGraph(*this)); //cout << "Building routing graph" << endl; @@ -136,8 +136,32 @@ shared_ptr Chip::get_routing_graph_ecp5() tie(y, x) = tile->info.get_row_col(); // SLICE Bels if (tile->info.type == "PLC2") { - for (int z = 0; z < 4; z++) + for (int z = 0; z < 4; z++) { Ecp5Bels::add_lc(*rg, x, y, z); + if (include_lutperm_pips) { + // Add permutation pseudo-pips as a crossbar in front of each LUT's inputs + Location loc(x, y); + const string abcd = "ABCD"; + for (int k = (z*2); k < ((z+1)*2); k++) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (i == j) + continue; + string input = fmt(abcd[j] << k); + string output = fmt(abcd[i] << k << "_SLICE"); + RoutingArc rarc; + rarc.id = rg->ident(fmt(input << "->" << output)); + rarc.source = RoutingId{loc, rg->ident(input)}; + rarc.sink = RoutingId{loc, rg->ident(output)}; + rarc.tiletype = rg->ident(tile->info.type); + rarc.configurable = false; + rarc.lutperm_flags = (0x4000 | (k << 4) | ((i & 0x3) << 2) |(j & 0x3)); + rg->add_arc(loc, rarc); + } + } + } + } + } } // PIO Bels if (tile->info.type.find("PICL0") != string::npos || tile->info.type.find("PICR0") != string::npos) diff --git a/libtrellis/src/DedupChipdb.cpp b/libtrellis/src/DedupChipdb.cpp index 828f63a6..2b53de49 100644 --- a/libtrellis/src/DedupChipdb.cpp +++ b/libtrellis/src/DedupChipdb.cpp @@ -32,9 +32,9 @@ DedupChipdb::DedupChipdb() DedupChipdb::DedupChipdb(const IdStore &base) : IdStore(base) {} -shared_ptr make_dedup_chipdb(Chip &chip) +shared_ptr make_dedup_chipdb(Chip &chip, bool include_lutperm_pips) { - shared_ptr graph = chip.get_routing_graph(); + shared_ptr graph = chip.get_routing_graph(include_lutperm_pips); for (auto &loc : graph->tiles) { const auto &td = loc.second; // Index bels, wires and arcs @@ -87,6 +87,7 @@ shared_ptr make_dedup_chipdb(Chip &chip) ad.delay = 1; ad.sinkWire = RelId{Location(ra.sink.loc.x - x, ra.sink.loc.y - y), graph->tiles.at(ra.sink.loc).wires.at(ra.sink.id).cdb_id}; ad.srcWire = RelId{Location(ra.source.loc.x - x, ra.source.loc.y - y), graph->tiles.at(ra.source.loc).wires.at(ra.source.id).cdb_id}; + ad.lutperm_flags = ra.lutperm_flags; ld.arcs.push_back(ad); } diff --git a/libtrellis/src/PyTrellis.cpp b/libtrellis/src/PyTrellis.cpp index 674f3fa8..5a05f4eb 100644 --- a/libtrellis/src/PyTrellis.cpp +++ b/libtrellis/src/PyTrellis.cpp @@ -503,7 +503,8 @@ PYBIND11_MODULE (pytrellis, m) .def_readwrite("sinkWire", &DdArcData::sinkWire) .def_readwrite("cls", &DdArcData::cls) .def_readwrite("delay", &DdArcData::delay) - .def_readwrite("tiletype", &DdArcData::tiletype); + .def_readwrite("tiletype", &DdArcData::tiletype) + .def_readwrite("lutperm_flags", &DdArcData::lutperm_flags); class_(m, "WireData") .def_readwrite("name", &WireData::name) @@ -546,7 +547,8 @@ PYBIND11_MODULE (pytrellis, m) .def("ident", &DedupChipdb::ident) .def("to_str", &DedupChipdb::to_str); - m.def("make_dedup_chipdb", make_dedup_chipdb); + m.def("make_dedup_chipdb", make_dedup_chipdb, + py::arg("chip"), py::arg("include_lutperm_pips")=false); class_>(m, "OptimizedChipdb") .def_readwrite("tiles", &OptimizedChipdb::tiles)