aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-10-24 18:10:19 +0100
committerDavid Shah <dave@ds0.me>2018-11-12 14:03:58 +0000
commit83b1c436303ad152cf78a517979d8ab7e24eadf6 (patch)
treee3c2756501304eaaf390557ec07b1f57127696c1
parent7bd542ecbeb5d2ea0cf3b381b56bfc4ff18498fb (diff)
downloadnextpnr-83b1c436303ad152cf78a517979d8ab7e24eadf6.tar.gz
nextpnr-83b1c436303ad152cf78a517979d8ab7e24eadf6.tar.bz2
nextpnr-83b1c436303ad152cf78a517979d8ab7e24eadf6.zip
timing: Working on a timing constraint API
Signed-off-by: David Shah <davey1576@gmail.com>
-rw-r--r--common/nextpnr.h103
-rw-r--r--common/timing.cc3
2 files changed, 105 insertions, 1 deletions
diff --git a/common/nextpnr.h b/common/nextpnr.h
index 59ae0323..909d49a1 100644
--- a/common/nextpnr.h
+++ b/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); }
};
+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
diff --git a/common/timing.cc b/common/timing.cc
index 2769cd65..196168ab 100644
--- a/common/timing.cc
+++ b/common/timing.cc
@@ -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) {