blob: 88688c98b204f7f99a486d5c789cb1b85eef70e6 [file] [log] [blame]
#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