nextpnr/generic/viaduct_api.h
gatecat 9b51c6e337 clangformat
Signed-off-by: gatecat <gatecat@ds0.me>
2024-09-30 14:51:33 +02:00

116 lines
4.8 KiB
C++

/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2021 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 VIADUCT_API_H
#define VIADUCT_API_H
#include "nextpnr_namespaces.h"
#include "nextpnr_types.h"
NEXTPNR_NAMESPACE_BEGIN
/*
Viaduct -- a series of small arches
Viaduct is a framework that provides an 'inbetween' step between nextpnr-generic
using Python bindings and a full-custom arch.
It allows an arch to programmatically build a set of bels (placement locations)
and a routing graph in-memory at startup; and then hook into nextpnr's flow
and validity checking rules at runtime with custom C++ code.
To create a Viaduct 'uarch', the following are required:
- an implementation of ViaductAPI. At a minimum; you will need to use ctx->addBel, ctx->addWire and ctx->addPip to
create the graph of placement and routing resources in-memory. Also implement any placement validity checking required -
like rules for how LUTs and FFs can be placed together in a SLICE.
- an instance of a struct deriving from ViaductArch - this is how the uarch is discovered. Override create(args) to
create an instance of your ViaductAPI implementation.
- these should be within C++ files in a new subfolder of 'viaduct'. Add the name of this subfolder to the list of
VIADUCT_UARCHES in family.cmake if building in-tree.
For an example of how these pieces fit together; see 'viaduct/example' which implements a small synthetic architecture
using this framework.
*/
struct Context;
struct ViaductAPI
{
virtual void init(Context *ctx);
Context *ctx;
bool with_gui = false;
// --- Bel functions ---
// Called when a bel is placed/unplaced (with cell=nullptr for a unbind)
virtual void notifyBelChange(BelId bel, CellInfo *cell) {}
// This only needs to return false if a bel is disabled for a microarch-specific reason and not just because it's
// bound (which the base generic will deal with)
virtual bool checkBelAvail(BelId bel) const { return true; }
// Mirror the ArchAPI functions - see archapi.md
virtual std::vector<IdString> getCellTypes() const;
virtual BelBucketId getBelBucketForBel(BelId bel) const;
virtual BelBucketId getBelBucketForCellType(IdString cell_type) const;
virtual bool isValidBelForCellType(IdString cell_type, BelId bel) const;
virtual bool isBelLocationValid(BelId bel, bool explain_invalid = false) const { return true; }
// --- Wire and pip functions ---
// Called when a wire/pip is placed/unplaced (with net=nullptr for a unbind)
virtual void notifyWireChange(WireId wire, NetInfo *net) {}
virtual void notifyPipChange(PipId pip, NetInfo *net) {}
// These only need to return false if a wire/pip is disabled for a microarch-specific reason and not just because
// it's bound (which the base arch will deal with)
virtual bool checkWireAvail(WireId wire) const { return true; }
virtual bool checkPipAvail(PipId pip) const { return true; }
virtual bool checkPipAvailForNet(PipId pip, const NetInfo *net) const { return checkPipAvail(pip); };
// --- Route lookahead ---
virtual delay_t estimateDelay(WireId src, WireId dst) const;
virtual delay_t predictDelay(BelId src_bel, IdString src_pin, BelId dst_bel, IdString dst_pin) const;
virtual BoundingBox getRouteBoundingBox(WireId src, WireId dst) const;
// --- Flow hooks ---
virtual void pack() {}; // replaces the pack function
// Called before and after main placement and routing
virtual void prePlace() {};
virtual void postPlace() {};
virtual void preRoute() {};
virtual void postRoute() {};
virtual ~ViaductAPI() {};
};
struct ViaductArch
{
static ViaductArch *list_head;
ViaductArch *list_next = nullptr;
std::string name;
ViaductArch(const std::string &name);
~ViaductArch() {};
virtual std::unique_ptr<ViaductAPI> create(const dict<std::string, std::string> &args) = 0;
static std::string list();
static std::unique_ptr<ViaductAPI> create(const std::string &name, const dict<std::string, std::string> &args);
};
NEXTPNR_NAMESPACE_END
#endif