| #ifndef DEDUP_CHIPDB_H | |
| #define DEDUP_CHIPDB_H | |
| #include "RoutingGraph.hpp" | |
| #include <map> | |
| #include <unordered_map> | |
| #include <boost/functional/hash.hpp> | |
| #include <cstdint> | |
| #include <memory> | |
| using namespace std; | |
| namespace Trellis { | |
| namespace DDChipDb { | |
| /* | |
| A deduplicated chip database is a database with the following properties, intended to be used in place-and-route flows. | |
| - All coordinates are relative | |
| - All wire, bel and arc IDs are sequential starting from zero at a location | |
| - Locations with identical wire, bel and arc data once converted to relative coordinates are only stored once | |
| - The database is fully linked: wires contain arcs and bel pins up and downhill, arcs store their up and down wires, | |
| etc | |
| */ | |
| struct RelId | |
| { | |
| Location rel; | |
| int32_t id = -1; | |
| }; | |
| inline bool operator<(RelId a, RelId b) | |
| { | |
| return (a.rel < b.rel) || (a.rel == b.rel && a.id < b.id); | |
| } | |
| inline bool operator==(RelId a, RelId b) | |
| { | |
| return (a.rel == b.rel) && (a.id == b.id); | |
| } | |
| inline bool operator!=(RelId a, RelId b) | |
| { | |
| return (a.rel != b.rel) || (a.id != b.id); | |
| } | |
| struct BelPort | |
| { | |
| RelId bel; | |
| ident_t pin = -1; | |
| }; | |
| inline bool operator==(const BelPort &a, const BelPort &b) | |
| { | |
| return a.bel == b.bel && a.pin == b.pin; | |
| } | |
| struct BelWire | |
| { | |
| RelId wire; | |
| ident_t pin = -1; | |
| PortDirection dir; | |
| }; | |
| inline bool operator==(const BelWire &a, const BelWire &b) | |
| { | |
| return a.wire == b.wire && a.pin == b.pin && a.dir == b.dir; | |
| } | |
| enum ArcClass : int8_t | |
| { | |
| ARC_STANDARD = 0, | |
| ARC_FIXED = 1 | |
| }; | |
| struct DdArcData | |
| { | |
| RelId srcWire; | |
| RelId sinkWire; | |
| ArcClass cls; | |
| int32_t delay; | |
| ident_t tiletype; | |
| }; | |
| 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; | |
| } | |
| struct WireData | |
| { | |
| ident_t name; | |
| set<RelId> arcsDownhill, arcsUphill; | |
| vector<BelPort> belPins; | |
| }; | |
| inline bool operator==(const WireData &a, const WireData &b) | |
| { | |
| return a.name == b.name && a.arcsDownhill.size() == b.arcsDownhill.size() && | |
| equal(a.arcsDownhill.begin(), a.arcsDownhill.end(), b.arcsDownhill.begin()) | |
| && a.arcsUphill.size() == b.arcsUphill.size() | |
| && equal(a.arcsUphill.begin(), a.arcsUphill.end(), b.arcsUphill.begin()) | |
| && a.belPins.size() == b.belPins.size() | |
| && equal(a.belPins.begin(), a.belPins.end(), b.belPins.begin()); | |
| } | |
| struct BelData | |
| { | |
| ident_t name, type; | |
| int z; | |
| vector<BelWire> wires; | |
| }; | |
| inline bool operator==(const BelData &a, const BelData &b) | |
| { | |
| return a.name == b.name && a.type == b.type && a.z == b.z && a.wires.size() == b.wires.size() | |
| && equal(a.wires.begin(), a.wires.end(), b.wires.begin()); | |
| } | |
| typedef pair<uint64_t, uint64_t> checksum_t; | |
| struct LocationData | |
| { | |
| vector<WireData> wires; | |
| vector<DdArcData> arcs; | |
| vector<BelData> bels; | |
| checksum_t checksum() const; | |
| }; | |
| inline bool operator==(const LocationData &a, const LocationData &b) | |
| { | |
| return a.wires.size() == b.wires.size() && equal(a.wires.begin(), a.wires.end(), b.wires.begin()) && | |
| a.arcs.size() == b.arcs.size() && equal(a.arcs.begin(), a.arcs.end(), b.arcs.begin()) | |
| && a.bels.size() == b.bels.size() && equal(a.bels.begin(), a.bels.end(), b.bels.begin()); | |
| } | |
| } | |
| } | |
| namespace std { | |
| template<> | |
| struct hash<Trellis::DDChipDb::RelId> | |
| { | |
| std::size_t operator()(const Trellis::DDChipDb::RelId &rid) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| boost::hash_combine(seed, hash<Trellis::Location>()(rid.rel)); | |
| boost::hash_combine(seed, hash<int32_t>()(rid.id)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<set<Trellis::DDChipDb::RelId>> | |
| { | |
| std::size_t operator()(const set<Trellis::DDChipDb::RelId> &rids) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| for (const auto &rid : rids) | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::RelId>()(rid)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<vector<Trellis::DDChipDb::RelId>> | |
| { | |
| std::size_t operator()(const vector<Trellis::DDChipDb::RelId> &rids) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| for (const auto &rid : rids) | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::RelId>()(rid)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<Trellis::DDChipDb::BelPort> | |
| { | |
| std::size_t operator()(const Trellis::DDChipDb::BelPort &port) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::RelId>()(port.bel)); | |
| boost::hash_combine(seed, hash<Trellis::ident_t>()(port.pin)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<Trellis::DDChipDb::BelWire> | |
| { | |
| std::size_t operator()(const Trellis::DDChipDb::BelWire &port) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::RelId>()(port.wire)); | |
| boost::hash_combine(seed, hash<Trellis::ident_t>()(port.pin)); | |
| boost::hash_combine(seed, hash<Trellis::ident_t>()(port.dir)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<vector<Trellis::DDChipDb::BelPort>> | |
| { | |
| std::size_t operator()(const vector<Trellis::DDChipDb::BelPort> &bps) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| for (const auto &bp : bps) | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::BelPort>()(bp)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<vector<Trellis::DDChipDb::BelWire>> | |
| { | |
| std::size_t operator()(const vector<Trellis::DDChipDb::BelWire> &bps) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| for (const auto &bp : bps) | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::BelWire>()(bp)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<Trellis::DDChipDb::DdArcData> | |
| { | |
| std::size_t operator()(const Trellis::DDChipDb::DdArcData &arc) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::RelId>()(arc.srcWire)); | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::RelId>()(arc.sinkWire)); | |
| boost::hash_combine(seed, hash<int8_t>()(arc.cls)); | |
| boost::hash_combine(seed, hash<int32_t>()(arc.delay)); | |
| boost::hash_combine(seed, hash<Trellis::ident_t>()(arc.tiletype)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<Trellis::DDChipDb::WireData> | |
| { | |
| std::size_t operator()(const Trellis::DDChipDb::WireData &wire) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| boost::hash_combine(seed, hash<Trellis::ident_t>()(wire.name)); | |
| boost::hash_combine(seed, hash<set<Trellis::DDChipDb::RelId>>()(wire.arcsDownhill)); | |
| boost::hash_combine(seed, hash<set<Trellis::DDChipDb::RelId>>()(wire.arcsUphill)); | |
| boost::hash_combine(seed, hash<vector<Trellis::DDChipDb::BelPort>>()(wire.belPins)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<Trellis::DDChipDb::BelData> | |
| { | |
| std::size_t operator()(const Trellis::DDChipDb::BelData &bel) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| boost::hash_combine(seed, hash<Trellis::ident_t>()(bel.name)); | |
| boost::hash_combine(seed, hash<Trellis::ident_t>()(bel.type)); | |
| boost::hash_combine(seed, hash<vector<Trellis::DDChipDb::BelWire>>()(bel.wires)); | |
| boost::hash_combine(seed, hash<int>()(bel.z)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<vector<Trellis::DDChipDb::BelData>> | |
| { | |
| std::size_t operator()(const vector<Trellis::DDChipDb::BelData> &vec) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| for (const auto &item : vec) | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::BelData>()(item)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<vector<Trellis::DDChipDb::DdArcData>> | |
| { | |
| std::size_t operator()(const vector<Trellis::DDChipDb::DdArcData> &vec) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| for (const auto &item : vec) | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::DdArcData>()(item)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<vector<Trellis::DDChipDb::WireData>> | |
| { | |
| std::size_t operator()(const vector<Trellis::DDChipDb::WireData> &vec) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| for (const auto &item : vec) | |
| boost::hash_combine(seed, hash<Trellis::DDChipDb::WireData>()(item)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<Trellis::DDChipDb::checksum_t> | |
| { | |
| std::size_t operator()(const Trellis::DDChipDb::checksum_t &cs) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| boost::hash_combine(seed, hash<uint64_t>()(cs.first)); | |
| boost::hash_combine(seed, hash<uint64_t>()(cs.second)); | |
| return seed; | |
| } | |
| }; | |
| template<> | |
| struct hash<Trellis::DDChipDb::LocationData> | |
| { | |
| std::size_t operator()(const Trellis::DDChipDb::LocationData &ld) const noexcept | |
| { | |
| std::size_t seed = 0; | |
| boost::hash_combine(seed, hash<vector<Trellis::DDChipDb::WireData>>()(ld.wires)); | |
| boost::hash_combine(seed, hash<vector<Trellis::DDChipDb::DdArcData>>()(ld.arcs)); | |
| boost::hash_combine(seed, hash<vector<Trellis::DDChipDb::BelData>>()(ld.bels)); | |
| return seed; | |
| } | |
| }; | |
| } | |
| namespace Trellis { | |
| class Chip; | |
| namespace DDChipDb { | |
| struct DedupChipdb : public IdStore | |
| { | |
| DedupChipdb(); | |
| DedupChipdb(const IdStore &base); | |
| map<checksum_t, LocationData> locationTypes; | |
| map<Location, checksum_t> typeAtLocation; | |
| LocationData get_cs_data(checksum_t id); | |
| }; | |
| shared_ptr<DedupChipdb> make_dedup_chipdb(Chip &chip); | |
| } | |
| } | |
| #endif |