timing: Working on a timing constraint API
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
7bd542ecbe
commit
83b1c43630
103
common/nextpnr.h
103
common/nextpnr.h
@ -194,6 +194,14 @@ struct Loc
|
|||||||
bool operator!=(const Loc &other) const { return (x != other.x) || (y != other.y) || (z == other.z); }
|
bool operator!=(const Loc &other) const { return (x != other.x) || (y != other.y) || (z == other.z); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TimingConstrObjectId
|
||||||
|
{
|
||||||
|
int32_t index = -1;
|
||||||
|
|
||||||
|
bool operator==(const TimingConstrObjectId &other) const { return index == other.index; }
|
||||||
|
bool operator!=(const TimingConstrObjectId &other) const { return index != other.index; }
|
||||||
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
@ -208,6 +216,15 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX Loc>
|
|||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct hash<NEXTPNR_NAMESPACE_PREFIX TimingConstrObjectId>
|
||||||
|
{
|
||||||
|
std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX TimingConstrObjectId &obj) const noexcept
|
||||||
|
{
|
||||||
|
return hash<int>()(obj.index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#include "archdefs.h"
|
#include "archdefs.h"
|
||||||
@ -266,6 +283,8 @@ struct PipMap
|
|||||||
PlaceStrength strength = STRENGTH_NONE;
|
PlaceStrength strength = STRENGTH_NONE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ClockConstraint;
|
||||||
|
|
||||||
struct NetInfo : ArchNetInfo
|
struct NetInfo : ArchNetInfo
|
||||||
{
|
{
|
||||||
IdString name;
|
IdString name;
|
||||||
@ -278,6 +297,8 @@ struct NetInfo : ArchNetInfo
|
|||||||
// wire -> uphill_pip
|
// wire -> uphill_pip
|
||||||
std::unordered_map<WireId, PipMap> wires;
|
std::unordered_map<WireId, PipMap> wires;
|
||||||
|
|
||||||
|
ClockConstraint *clkconstr = nullptr;
|
||||||
|
|
||||||
Region *region = nullptr;
|
Region *region = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -293,6 +314,7 @@ struct PortInfo
|
|||||||
IdString name;
|
IdString name;
|
||||||
NetInfo *net;
|
NetInfo *net;
|
||||||
PortType type;
|
PortType type;
|
||||||
|
TimingConstrObjectId tmg_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CellInfo : ArchCellInfo
|
struct CellInfo : ArchCellInfo
|
||||||
@ -320,6 +342,7 @@ struct CellInfo : ArchCellInfo
|
|||||||
// parent.[xyz] := 0 when (constr_parent == nullptr)
|
// parent.[xyz] := 0 when (constr_parent == nullptr)
|
||||||
|
|
||||||
Region *region = nullptr;
|
Region *region = nullptr;
|
||||||
|
TimingConstrObjectId tmg_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TimingPortClass
|
enum TimingPortClass
|
||||||
@ -335,6 +358,60 @@ enum TimingPortClass
|
|||||||
TMG_IGNORE, // Asynchronous to all clocks, "don't care", and should be ignored (false path) for analysis
|
TMG_IGNORE, // Asynchronous to all clocks, "don't care", and should be ignored (false path) for analysis
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TimingClockingInfo
|
||||||
|
{
|
||||||
|
IdString clock_port; // Port name of clock domain
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RISING,
|
||||||
|
FALLING
|
||||||
|
} edge;
|
||||||
|
DelayInfo setup, hold; // Input timing checks
|
||||||
|
DelayInfo clockToQ; // Output clock-to-Q time
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClockConstraint
|
||||||
|
{
|
||||||
|
DelayInfo high;
|
||||||
|
DelayInfo low;
|
||||||
|
DelayInfo period;
|
||||||
|
|
||||||
|
TimingConstrObjectId domain_tmg_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimingConstraintObject
|
||||||
|
{
|
||||||
|
TimingConstrObjectId id;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ANYTHING,
|
||||||
|
CLOCK_DOMAIN,
|
||||||
|
NET,
|
||||||
|
CELL,
|
||||||
|
CELL_PORT
|
||||||
|
} type;
|
||||||
|
IdString entity; // Name of clock net; net or cell
|
||||||
|
IdString port; // Name of port on a cell
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimingConstraint
|
||||||
|
{
|
||||||
|
IdString name;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FALSE_PATH,
|
||||||
|
MIN_DELAY,
|
||||||
|
MAX_DELAY,
|
||||||
|
MULTICYCLE,
|
||||||
|
} type;
|
||||||
|
|
||||||
|
delay_t value;
|
||||||
|
|
||||||
|
std::unordered_set<TimingConstrObjectId> from;
|
||||||
|
std::unordered_set<TimingConstrObjectId> to;
|
||||||
|
};
|
||||||
|
|
||||||
struct DeterministicRNG
|
struct DeterministicRNG
|
||||||
{
|
{
|
||||||
uint64_t rngstate;
|
uint64_t rngstate;
|
||||||
@ -431,6 +508,11 @@ struct BaseCtx
|
|||||||
idstring_idx_to_str = new std::vector<const std::string *>;
|
idstring_idx_to_str = new std::vector<const std::string *>;
|
||||||
IdString::initialize_add(this, "", 0);
|
IdString::initialize_add(this, "", 0);
|
||||||
IdString::initialize_arch(this);
|
IdString::initialize_arch(this);
|
||||||
|
|
||||||
|
TimingConstraintObject wildcard;
|
||||||
|
wildcard.id.index = 0;
|
||||||
|
wildcard.type = TimingConstraintObject::ANYTHING;
|
||||||
|
constraintObjects.push_back(wildcard);
|
||||||
}
|
}
|
||||||
|
|
||||||
~BaseCtx()
|
~BaseCtx()
|
||||||
@ -514,6 +596,27 @@ struct BaseCtx
|
|||||||
void refreshUiPip(PipId pip) { pipUiReload.insert(pip); }
|
void refreshUiPip(PipId pip) { pipUiReload.insert(pip); }
|
||||||
|
|
||||||
void refreshUiGroup(GroupId group) { groupUiReload.insert(group); }
|
void refreshUiGroup(GroupId group) { groupUiReload.insert(group); }
|
||||||
|
|
||||||
|
// --------------------------------------------------------------
|
||||||
|
|
||||||
|
// Timing Constraint API
|
||||||
|
|
||||||
|
// constraint name -> constraint
|
||||||
|
std::unordered_map<IdString, std::unique_ptr<TimingConstraint>> constraints;
|
||||||
|
// object ID -> object
|
||||||
|
std::vector<TimingConstraintObject> constraintObjects;
|
||||||
|
// object ID -> constraint
|
||||||
|
std::unordered_multimap<TimingConstrObjectId, TimingConstraint *> constrsFrom;
|
||||||
|
std::unordered_multimap<TimingConstrObjectId, TimingConstraint *> constrsTo;
|
||||||
|
|
||||||
|
TimingConstrObjectId timingWildcardObject();
|
||||||
|
TimingConstrObjectId timingClockDomainObject(NetInfo *clockDomain);
|
||||||
|
TimingConstrObjectId timingNetObject(NetInfo *net);
|
||||||
|
TimingConstrObjectId timingCellObject(CellInfo *cell);
|
||||||
|
TimingConstrObjectId timingPortObject(CellInfo *cell, IdString port);
|
||||||
|
|
||||||
|
void addConstraint(std::unique_ptr<TimingConstraint> constr);
|
||||||
|
void removeConstraint(IdString constrName);
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -215,7 +215,8 @@ struct Timing
|
|||||||
for (auto net : boost::adaptors::reverse(topographical_order)) {
|
for (auto net : boost::adaptors::reverse(topographical_order)) {
|
||||||
auto &nd = net_data.at(net);
|
auto &nd = net_data.at(net);
|
||||||
// Ignore false startpoints
|
// Ignore false startpoints
|
||||||
if (nd.false_startpoint) continue;
|
if (nd.false_startpoint)
|
||||||
|
continue;
|
||||||
const delay_t net_length_plus_one = nd.max_path_length + 1;
|
const delay_t net_length_plus_one = nd.max_path_length + 1;
|
||||||
auto &net_min_remaining_budget = nd.min_remaining_budget;
|
auto &net_min_remaining_budget = nd.min_remaining_budget;
|
||||||
for (auto &usr : net->users) {
|
for (auto &usr : net->users) {
|
||||||
|
Loading…
Reference in New Issue
Block a user