diff options
Diffstat (limited to 'common/basectx.h')
-rw-r--r-- | common/basectx.h | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/common/basectx.h b/common/basectx.h new file mode 100644 index 00000000..fccd12af --- /dev/null +++ b/common/basectx.h @@ -0,0 +1,238 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com> + * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com> + * + * 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 BASECTX_H +#define BASECTX_H + +#include <mutex> +#include <unordered_map> +#include <vector> +#ifndef NPNR_DISABLE_THREADS +#include <boost/thread.hpp> +#endif + +#include "idstring.h" +#include "nextpnr_namespaces.h" +#include "nextpnr_types.h" +#include "property.h" +#include "str_ring_buffer.h" + +NEXTPNR_NAMESPACE_BEGIN + +struct Context; + +struct BaseCtx +{ +#ifndef NPNR_DISABLE_THREADS + // Lock to perform mutating actions on the Context. + std::mutex mutex; + boost::thread::id mutex_owner; + + // Lock to be taken by UI when wanting to access context - the yield() + // method will lock/unlock it when its' released the main mutex to make + // sure the UI is not starved. + std::mutex ui_mutex; +#endif + + // ID String database. + 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; + + // Placed nets and cells. + std::unordered_map<IdString, std::unique_ptr<NetInfo>> nets; + std::unordered_map<IdString, std::unique_ptr<CellInfo>> cells; + + // Hierarchical (non-leaf) cells by full path + std::unordered_map<IdString, HierarchicalCell> hierarchy; + // This is the root of the above structure + IdString top_module; + + // Aliases for nets, which may have more than one name due to assignments and hierarchy + std::unordered_map<IdString, IdString> net_aliases; + + // Top-level ports + std::unordered_map<IdString, PortInfo> ports; + std::unordered_map<IdString, CellInfo *> port_cells; + + // Floorplanning regions + std::unordered_map<IdString, std::unique_ptr<Region>> region; + + // Context meta data + std::unordered_map<IdString, Property> attrs; + + Context *as_ctx = nullptr; + + // Has the frontend loaded a design? + bool design_loaded; + + BaseCtx() + { + idstring_str_to_idx = new std::unordered_map<std::string, int>; + idstring_idx_to_str = new std::vector<const std::string *>; + IdString::initialize_add(this, "", 0); + IdString::initialize_arch(this); + + design_loaded = false; + } + + virtual ~BaseCtx() + { + delete idstring_str_to_idx; + delete idstring_idx_to_str; + } + + // Must be called before performing any mutating changes on the Ctx/Arch. + void lock(void) + { +#ifndef NPNR_DISABLE_THREADS + mutex.lock(); + mutex_owner = boost::this_thread::get_id(); +#endif + } + + void unlock(void) + { +#ifndef NPNR_DISABLE_THREADS + NPNR_ASSERT(boost::this_thread::get_id() == mutex_owner); + mutex.unlock(); +#endif + } + + // Must be called by the UI before rendering data. This lock will be + // prioritized when processing code calls yield(). + void lock_ui(void) + { +#ifndef NPNR_DISABLE_THREADS + ui_mutex.lock(); + mutex.lock(); +#endif + } + + void unlock_ui(void) + { +#ifndef NPNR_DISABLE_THREADS + mutex.unlock(); + ui_mutex.unlock(); +#endif + } + + // Yield to UI by unlocking the main mutex, flashing the UI mutex and + // relocking the main mutex. Call this when you're performing a + // long-standing action while holding a lock to let the UI show + // visualization updates. + // Must be called with the main lock taken. + void yield(void) + { +#ifndef NPNR_DISABLE_THREADS + unlock(); + ui_mutex.lock(); + ui_mutex.unlock(); + lock(); +#endif + } + + IdString id(const std::string &s) const { return IdString(this, s); } + + IdString id(const char *s) const { return IdString(this, s); } + + Context *getCtx() { return as_ctx; } + + const Context *getCtx() const { return as_ctx; } + + const char *nameOf(IdString name) const { return name.c_str(this); } + + template <typename T> const char *nameOf(const T *obj) const + { + if (obj == nullptr) + return ""; + return obj->name.c_str(this); + } + + const char *nameOfBel(BelId bel) const; + const char *nameOfWire(WireId wire) const; + 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; + bool frameUiReload = false; + std::unordered_set<BelId> belUiReload; + std::unordered_set<WireId> wireUiReload; + std::unordered_set<PipId> pipUiReload; + std::unordered_set<GroupId> groupUiReload; + + void refreshUi() { allUiReload = true; } + + void refreshUiFrame() { frameUiReload = true; } + + void refreshUiBel(BelId bel) { belUiReload.insert(bel); } + + void refreshUiWire(WireId wire) { wireUiReload.insert(wire); } + + void refreshUiPip(PipId pip) { pipUiReload.insert(pip); } + + void refreshUiGroup(GroupId group) { groupUiReload.insert(group); } + + // -------------------------------------------------------------- + + NetInfo *getNetByAlias(IdString alias) const + { + return nets.count(alias) ? nets.at(alias).get() : nets.at(net_aliases.at(alias)).get(); + } + + // Intended to simplify Python API + void addClock(IdString net, float freq); + void createRectangularRegion(IdString name, int x0, int y0, int x1, int y1); + void addBelToRegion(IdString name, BelId bel); + void constrainCellToRegion(IdString cell, IdString region_name); + + // Helper functions for Python bindings + NetInfo *createNet(IdString name); + void connectPort(IdString net, IdString cell, IdString port); + void disconnectPort(IdString cell, IdString port); + void ripupNet(IdString name); + void lockNetRouting(IdString name); + + CellInfo *createCell(IdString name, IdString type); + void copyBelPorts(IdString cell, BelId bel); + + // Workaround for lack of wrappable constructors + DecalXY constructDecalXY(DecalId decal, float x, float y); + + void archInfoToAttributes(); + void attributesToArchInfo(); +}; + +NEXTPNR_NAMESPACE_END + +#endif /* BASECTX_H */ |