nextpnr/common/nextpnr_types.h

342 lines
9.1 KiB
C++

/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2018 Serge Bazanski <q3k@q3k.org>
*
* 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.
*
*/
// Types defined in this header use one or more user defined types (e.g. BelId).
// If a new common type is desired that doesn't depend on a user defined type,
// either put it in it's own header, or in nextpnr_base_types.h.
#ifndef NEXTPNR_TYPES_H
#define NEXTPNR_TYPES_H
#include <unordered_map>
#include <unordered_set>
#include "archdefs.h"
#include "hashlib.h"
#include "nextpnr_base_types.h"
#include "nextpnr_namespaces.h"
#include "property.h"
NEXTPNR_NAMESPACE_BEGIN
struct DecalXY
{
DecalId decal;
float x = 0, y = 0;
bool operator==(const DecalXY &other) const { return (decal == other.decal && x == other.x && y == other.y); }
};
struct BelPin
{
BelId bel;
IdString pin;
};
struct Region
{
IdString name;
bool constr_bels = false;
bool constr_wires = false;
bool constr_pips = false;
pool<BelId> bels;
pool<WireId> wires;
pool<Loc> piplocs;
};
struct PipMap
{
PipId pip = PipId();
PlaceStrength strength = STRENGTH_NONE;
};
struct CellInfo;
struct PortRef
{
CellInfo *cell = nullptr;
IdString port;
delay_t budget = 0;
};
// minimum and maximum delay
struct DelayPair
{
DelayPair(){};
explicit DelayPair(delay_t delay) : min_delay(delay), max_delay(delay){};
DelayPair(delay_t min_delay, delay_t max_delay) : min_delay(min_delay), max_delay(max_delay){};
delay_t minDelay() const { return min_delay; };
delay_t maxDelay() const { return max_delay; };
delay_t min_delay, max_delay;
DelayPair operator+(const DelayPair &other) const
{
return {min_delay + other.min_delay, max_delay + other.max_delay};
}
DelayPair operator-(const DelayPair &other) const
{
return {min_delay - other.min_delay, max_delay - other.max_delay};
}
};
// four-quadrant, min and max rise and fall delay
struct DelayQuad
{
DelayPair rise, fall;
DelayQuad(){};
explicit DelayQuad(delay_t delay) : rise(delay), fall(delay){};
DelayQuad(delay_t min_delay, delay_t max_delay) : rise(min_delay, max_delay), fall(min_delay, max_delay){};
DelayQuad(DelayPair rise, DelayPair fall) : rise(rise), fall(fall){};
DelayQuad(delay_t min_rise, delay_t max_rise, delay_t min_fall, delay_t max_fall)
: rise(min_rise, max_rise), fall(min_fall, max_fall){};
delay_t minRiseDelay() const { return rise.minDelay(); };
delay_t maxRiseDelay() const { return rise.maxDelay(); };
delay_t minFallDelay() const { return fall.minDelay(); };
delay_t maxFallDelay() const { return fall.maxDelay(); };
delay_t minDelay() const { return std::min<delay_t>(rise.minDelay(), fall.minDelay()); };
delay_t maxDelay() const { return std::max<delay_t>(rise.maxDelay(), fall.maxDelay()); };
DelayPair delayPair() const { return DelayPair(minDelay(), maxDelay()); };
DelayQuad operator+(const DelayQuad &other) const { return {rise + other.rise, fall + other.fall}; }
DelayQuad operator-(const DelayQuad &other) const { return {rise - other.rise, fall - other.fall}; }
};
struct ClockConstraint;
struct NetInfo : ArchNetInfo
{
explicit NetInfo(IdString name) : name(name){};
IdString name, hierpath;
int32_t udata = 0;
PortRef driver;
std::vector<PortRef> users;
dict<IdString, Property> attrs;
// wire -> uphill_pip
dict<WireId, PipMap> wires;
std::vector<IdString> aliases; // entries in net_aliases that point to this net
std::unique_ptr<ClockConstraint> clkconstr;
Region *region = nullptr;
};
enum PortType
{
PORT_IN = 0,
PORT_OUT = 1,
PORT_INOUT = 2
};
struct PortInfo
{
IdString name;
NetInfo *net;
PortType type;
};
struct Context;
struct CellInfo : ArchCellInfo
{
CellInfo(Context *ctx, IdString name, IdString type) : ctx(ctx), name(name), type(type){};
Context *ctx = nullptr;
IdString name, type, hierpath;
int32_t udata;
dict<IdString, PortInfo> ports;
dict<IdString, Property> attrs, params;
BelId bel;
PlaceStrength belStrength = STRENGTH_NONE;
// cell is part of a cluster if != ClusterId
ClusterId cluster;
Region *region = nullptr;
void addInput(IdString name);
void addOutput(IdString name);
void addInout(IdString name);
void setParam(IdString name, Property value);
void unsetParam(IdString name);
void setAttr(IdString name, Property value);
void unsetAttr(IdString name);
// check whether a bel complies with the cell's region constraint
bool testRegion(BelId bel) const;
};
enum TimingPortClass
{
TMG_CLOCK_INPUT, // Clock input to a sequential cell
TMG_GEN_CLOCK, // Generated clock output (PLL, DCC, etc)
TMG_REGISTER_INPUT, // Input to a register, with an associated clock (may also have comb. fanout too)
TMG_REGISTER_OUTPUT, // Output from a register
TMG_COMB_INPUT, // Combinational input, no paths end here
TMG_COMB_OUTPUT, // Combinational output, no paths start here
TMG_STARTPOINT, // Unclocked primary startpoint, such as an IO cell output
TMG_ENDPOINT, // Unclocked primary endpoint, such as an IO cell input
TMG_IGNORE, // Asynchronous to all clocks, "don't care", and should be ignored (false path) for analysis
};
enum ClockEdge
{
RISING_EDGE,
FALLING_EDGE
};
struct TimingClockingInfo
{
IdString clock_port; // Port name of clock domain
ClockEdge edge;
DelayPair setup, hold; // Input timing checks
DelayQuad clockToQ; // Output clock-to-Q time
};
struct ClockConstraint
{
DelayPair high;
DelayPair low;
DelayPair period;
};
struct ClockFmax
{
float achieved;
float constraint;
};
struct ClockEvent
{
IdString clock;
ClockEdge edge;
bool operator==(const ClockEvent &other) const { return clock == other.clock && edge == other.edge; }
unsigned int hash() const { return mkhash(clock.hash(), int(edge)); }
};
struct ClockPair
{
ClockEvent start, end;
bool operator==(const ClockPair &other) const { return start == other.start && end == other.end; }
unsigned int hash() const { return mkhash(start.hash(), end.hash()); }
};
struct CriticalPath
{
struct Segment
{
// Segment type
enum class Type
{
CLK_TO_Q, // Clock-to-Q delay
SOURCE, // Delayless source
LOGIC, // Combinational logic delay
ROUTING, // Routing delay
SETUP // Setup time in sink
};
// Type
Type type;
// Net name (routing only)
IdString net;
// From cell.port
std::pair<IdString, IdString> from;
// To cell.port
std::pair<IdString, IdString> to;
// Segment delay
delay_t delay;
// Segment budget (routing only)
delay_t budget;
};
// Clock pair
ClockPair clock_pair;
// Total path delay
delay_t delay;
// Period (max allowed delay)
delay_t period;
// Individual path segments
std::vector<Segment> segments;
};
// Holds timing information of a single source to sink path of a net
struct NetSinkTiming
{
// Clock event pair
ClockPair clock_pair;
// Cell and port (the sink)
std::pair<IdString, IdString> cell_port;
// Delay
delay_t delay;
// Delay budget
delay_t budget;
};
struct TimingResult
{
// Achieved and target Fmax for all clock domains
dict<IdString, ClockFmax> clock_fmax;
// Single domain critical paths
dict<IdString, CriticalPath> clock_paths;
// Cross-domain critical paths
std::vector<CriticalPath> xclock_paths;
// Detailed net timing data
dict<IdString, std::vector<NetSinkTiming>> detailed_net_timings;
};
// Represents the contents of a non-leaf cell in a design
// with hierarchy
struct HierarchicalPort
{
IdString name;
PortType dir;
std::vector<IdString> nets;
int offset;
bool upto;
};
struct HierarchicalCell
{
IdString name, type, parent, fullpath;
// Name inside cell instance -> global name
dict<IdString, IdString> leaf_cells, nets;
// Global name -> name inside cell instance
dict<IdString, IdString> leaf_cells_by_gname, nets_by_gname;
// Cell port to net
dict<IdString, HierarchicalPort> ports;
// Name inside cell instance -> global name
dict<IdString, IdString> hier_cells;
};
NEXTPNR_NAMESPACE_END
#endif /* NEXTPNR_TYPES_H */