aboutsummaryrefslogtreecommitdiffstats
path: root/common/nextpnr.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/nextpnr.h')
-rw-r--r--common/nextpnr.h155
1 files changed, 155 insertions, 0 deletions
diff --git a/common/nextpnr.h b/common/nextpnr.h
index b4f68f93..78bbf66e 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -145,6 +145,152 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX IdString>
NEXTPNR_NAMESPACE_BEGIN
+// An small size optimised array that is statically allocated when the size is N or less; heap allocated otherwise
+template <typename T, size_t N> class SSOArray
+{
+ private:
+ union
+ {
+ T data_static[N];
+ T *data_heap;
+ };
+ size_t m_size;
+ inline bool is_heap() const { return (m_size > N); }
+ void alloc()
+ {
+ if (is_heap()) {
+ data_heap = new T[m_size];
+ }
+ }
+
+ public:
+ T *data() { return is_heap() ? data_heap : data_static; }
+ const T *data() const { return is_heap() ? data_heap : data_static; }
+ size_t size() const { return m_size; }
+
+ T *begin() { return data(); }
+ T *end() { return data() + m_size; }
+ const T *begin() const { return data(); }
+ const T *end() const { return data() + m_size; }
+
+ SSOArray() : m_size(0){};
+
+ SSOArray(size_t size, const T &init = T()) : m_size(size)
+ {
+ alloc();
+ std::fill(begin(), end(), init);
+ }
+
+ SSOArray(const SSOArray &other) : m_size(other.size())
+ {
+ alloc();
+ std::copy(other.begin(), other.end(), begin());
+ }
+
+ template <typename Tother> SSOArray(const Tother &other) : m_size(other.size())
+ {
+ alloc();
+ std::copy(other.begin(), other.end(), begin());
+ }
+
+ ~SSOArray()
+ {
+ if (is_heap()) {
+ delete[] data_heap;
+ }
+ }
+
+ bool operator==(const SSOArray &other) const
+ {
+ if (size() != other.size())
+ return false;
+ return std::equal(begin(), end(), other.begin());
+ }
+ bool operator!=(const SSOArray &other) const
+ {
+ if (size() != other.size())
+ return true;
+ return !std::equal(begin(), end(), other.begin());
+ }
+ T &operator[](size_t idx)
+ {
+ NPNR_ASSERT(idx < m_size);
+ return data()[idx];
+ }
+ const T &operator[](size_t idx) const
+ {
+ NPNR_ASSERT(idx < m_size);
+ return data()[idx];
+ }
+};
+
+struct IdStringList
+{
+ SSOArray<IdString, 4> ids;
+
+ IdStringList(){};
+ IdStringList(size_t n) : ids(n, IdString()){};
+ IdStringList(IdString id) : ids(1, id){};
+ template <typename Tlist> IdStringList(const Tlist &list) : ids(list){};
+
+ static IdStringList parse(Context *ctx, const std::string &str);
+ void build_str(const Context *ctx, std::string &str) const;
+ std::string str(const Context *ctx) const;
+
+ size_t size() const { return ids.size(); }
+ const IdString *begin() const { return ids.begin(); }
+ const IdString *end() const { return ids.end(); }
+ const IdString &operator[](size_t idx) const { return ids[idx]; }
+ bool operator==(const IdStringList &other) const { return ids == other.ids; }
+ bool operator!=(const IdStringList &other) const { return ids != other.ids; }
+ bool operator<(const IdStringList &other) const
+ {
+ if (size() > other.size())
+ return false;
+ if (size() < other.size())
+ return true;
+ for (size_t i = 0; i < size(); i++) {
+ IdString a = ids[i], b = other[i];
+ if (a.index < b.index)
+ return true;
+ if (a.index > b.index)
+ return false;
+ }
+ return false;
+ }
+};
+
+NEXTPNR_NAMESPACE_END
+
+namespace std {
+template <> struct hash<NEXTPNR_NAMESPACE_PREFIX IdStringList>
+{
+ std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX IdStringList &obj) const noexcept
+ {
+ std::size_t seed = 0;
+ boost::hash_combine(seed, hash<size_t>()(obj.size()));
+ for (auto &id : obj)
+ boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(id));
+ return seed;
+ }
+};
+} // namespace std
+
+NEXTPNR_NAMESPACE_BEGIN
+
+// A ring buffer of strings, so we can return a simple const char * pointer for %s formatting - inspired by how logging
+// in Yosys works Let's just hope noone tries to log more than 100 things in one call....
+class StrRingBuffer
+{
+ private:
+ static const size_t N = 100;
+ std::array<std::string, N> buffer;
+ size_t index = 0;
+
+ public:
+ std::string &next();
+};
+
struct GraphicElement
{
enum type_t
@@ -667,6 +813,9 @@ struct BaseCtx
mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
mutable std::vector<const std::string *> *idstring_idx_to_str;
+ // Temporary string backing store for logging
+ mutable StrRingBuffer log_strs;
+
// Project settings and config switches
std::unordered_map<IdString, Property> settings;
@@ -782,6 +931,12 @@ struct BaseCtx
const char *nameOfPip(PipId pip) const;
const char *nameOfGroup(GroupId group) const;
+ // Wrappers of arch functions that take a string and handle IdStringList parsing
+ BelId getBelByNameStr(const std::string &str);
+ WireId getWireByNameStr(const std::string &str);
+ PipId getPipByNameStr(const std::string &str);
+ GroupId getGroupByNameStr(const std::string &str);
+
// --------------------------------------------------------------
bool allUiReload = true;