aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2022-02-26 15:11:33 +0000
committergatecat <gatecat@ds0.me>2022-02-26 15:11:33 +0000
commit434a9737bb459189b463c8768454ea6c0e151406 (patch)
tree9930d7e5787d0eb757f29db66f2efc2575456eca /common
parent0b4f1e2b51990a512edd2129145b3ff463dcdd21 (diff)
downloadnextpnr-434a9737bb459189b463c8768454ea6c0e151406.tar.gz
nextpnr-434a9737bb459189b463c8768454ea6c0e151406.tar.bz2
nextpnr-434a9737bb459189b463c8768454ea6c0e151406.zip
Add indexed_store container type
Signed-off-by: gatecat <gatecat@ds0.me>
Diffstat (limited to 'common')
-rw-r--r--common/indexed_store.h266
-rw-r--r--common/nextpnr_types.h1
2 files changed, 267 insertions, 0 deletions
diff --git a/common/indexed_store.h b/common/indexed_store.h
new file mode 100644
index 00000000..5579b039
--- /dev/null
+++ b/common/indexed_store.h
@@ -0,0 +1,266 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2021-22 gatecat <gatecat@ds0.me>
+ *
+ * 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.
+ *
+ */
+
+#ifndef INDEXED_STORE_H
+#define INDEXED_STORE_H
+
+#include <algorithm>
+#include <limits>
+#include <vector>
+
+#include "nextpnr_assertions.h"
+#include "nextpnr_namespaces.h"
+
+NEXTPNR_NAMESPACE_BEGIN
+
+template <typename T> struct store_index
+{
+ int32_t m_index = -1;
+ store_index() = default;
+ explicit store_index(int32_t index) : m_index(index){};
+ int32_t idx() const { return m_index; }
+ void set(int32_t index) { m_index = index; }
+ bool empty() const { return m_index == -1; }
+ bool operator==(const store_index<T> &other) const { return m_index == other.m_index; }
+ bool operator!=(const store_index<T> &other) const { return m_index != other.m_index; }
+ bool operator<(const store_index<T> &other) const { return m_index < other.m_index; }
+ unsigned int hash() const { return m_index; }
+
+ operator bool() const { return !empty(); }
+ bool operator!() const { return empty(); }
+};
+
+// "Slotted" indexed object store
+template <typename T> class indexed_store
+{
+ private:
+ // This should move to using std::optional at some point
+ class slot
+ {
+ private:
+ alignas(T) unsigned char storage[sizeof(T)];
+ int32_t next_free;
+ bool active;
+ inline T &obj() { return reinterpret_cast<T &>(storage); }
+ inline const T &obj() const { return reinterpret_cast<const T &>(storage); }
+ friend class indexed_store<T>;
+
+ public:
+ slot() : active(false), next_free(std::numeric_limits<int32_t>::max()){};
+ slot(slot &&other) : active(other.active), next_free(other.next_free)
+ {
+ if (active)
+ ::new (static_cast<void *>(&storage)) T(std::move(other.obj()));
+ };
+
+ template <class... Args> void create(Args &&...args)
+ {
+ NPNR_ASSERT(!active);
+ active = true;
+ ::new (static_cast<void *>(&storage)) T(std::forward<Args &&>(args)...);
+ }
+ bool empty() const { return !active; }
+ T &get()
+ {
+ NPNR_ASSERT(active);
+ return reinterpret_cast<T &>(storage);
+ }
+ const T &get() const
+ {
+ NPNR_ASSERT(active);
+ return reinterpret_cast<const T &>(storage);
+ }
+ void free(int32_t first_free)
+ {
+ NPNR_ASSERT(active);
+ obj().~T();
+ active = false;
+ next_free = first_free;
+ }
+ ~slot()
+ {
+ if (active)
+ obj().~T();
+ }
+ };
+
+ std::vector<slot> slots;
+ int32_t first_free = 0;
+ int32_t active_count = 0;
+
+ public:
+ // Create a new entry and return its index
+ template <class... Args> store_index<T> add(Args &&...args)
+ {
+ ++active_count;
+ if (first_free == int32_t(slots.size())) {
+ slots.emplace_back();
+ slots.back().create(std::forward<Args &&>(args)...);
+ ++first_free;
+ return store_index<T>(int32_t(slots.size()) - 1);
+ } else {
+ int32_t idx = first_free;
+ auto &slot = slots.at(idx);
+ first_free = slot.next_free;
+ slot.create(std::forward<Args &&>(args)...);
+ return store_index<T>(idx);
+ }
+ }
+
+ // Remove an entry at an index
+ void remove(store_index<T> idx)
+ {
+ --active_count;
+ slots.at(idx.m_index).free(first_free);
+ first_free = idx.m_index;
+ }
+
+ // Number of live entries
+ int32_t entries() const { return active_count; }
+
+ // Reserve a certain amount of space
+ void reserve(int32_t size) { slots.reser
module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
	parameter CLKPOL2 = 1;
	parameter CLKPOL3 = 1;
	parameter [36863:0] INIT = 36864'bx;

	input CLK2;
	input CLK3;

	input [8:0] A1ADDR;
	output [71:0] A1DATA;
	input A1EN;

	input [8:0] B1ADDR;
	input [71:0] B1DATA;
	input [7:0] B1EN;

	wire [15:0] A1ADDR_16 = {A1ADDR, 6'b0};
	wire [15:0] B1ADDR_16 = {B1ADDR, 6'b0};
div>
#include "archdefs.h"
#include "hashlib.h"
+#include "indexed_store.h"
#include "nextpnr_base_types.h"
#include "nextpnr_namespaces.h"
#include "property.h"