timing: Working on a timing constraint API

Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
David Shah 2018-10-24 18:10:19 +01:00 committed by David Shah
parent 7bd542ecbe
commit 83b1c43630
2 changed files with 105 additions and 1 deletions

View File

@ -194,6 +194,14 @@ struct Loc
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
namespace std {
@ -208,6 +216,15 @@ template <> struct hash<NEXTPNR_NAMESPACE_PREFIX Loc>
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
#include "archdefs.h"
@ -266,6 +283,8 @@ struct PipMap
PlaceStrength strength = STRENGTH_NONE;
};
struct ClockConstraint;
struct NetInfo : ArchNetInfo
{
IdString name;
@ -278,6 +297,8 @@ struct NetInfo : ArchNetInfo
// wire -> uphill_pip
std::unordered_map<WireId, PipMap> wires;
ClockConstraint *clkconstr = nullptr;
Region *region = nullptr;
};
@ -293,6 +314,7 @@ struct PortInfo
IdString name;
NetInfo *net;
PortType type;
TimingConstrObjectId tmg_id;
};
struct CellInfo : ArchCellInfo
@ -320,6 +342,7 @@ struct CellInfo : ArchCellInfo
// parent.[xyz] := 0 when (constr_parent == nullptr)
Region *region = nullptr;
TimingConstrObjectId tmg_id;
};
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
};
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
{
uint64_t rngstate;
@ -431,6 +508,11 @@ struct BaseCtx
idstring_idx_to_str = new std::vector<const std::string *>;
IdString::initialize_add(this, "", 0);
IdString::initialize_arch(this);
TimingConstraintObject wildcard;
wildcard.id.index = 0;
wildcard.type = TimingConstraintObject::ANYTHING;
constraintObjects.push_back(wildcard);
}
~BaseCtx()
@ -514,6 +596,27 @@ struct BaseCtx
void refreshUiPip(PipId pip) { pipUiReload.insert(pip); }
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

View File

@ -215,7 +215,8 @@ struct Timing
for (auto net : boost::adaptors::reverse(topographical_order)) {
auto &nd = net_data.at(net);
// 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;
auto &net_min_remaining_budget = nd.min_remaining_budget;
for (auto &usr : net->users) {