aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2018-11-03 14:09:27 +0000
committerDavid Shah <dave@ds0.me>2018-11-12 14:03:58 +0000
commite633aa09ccd89040d450b7cb4b7864c4fd8c0468 (patch)
treef7d2a04e90cf25a0f836d72485114f8e76f056b6
parentfad69d49309ec979f0251a3213f212968629a8ed (diff)
downloadnextpnr-e633aa09ccd89040d450b7cb4b7864c4fd8c0468.tar.gz
nextpnr-e633aa09ccd89040d450b7cb4b7864c4fd8c0468.tar.bz2
nextpnr-e633aa09ccd89040d450b7cb4b7864c4fd8c0468.zip
timing: Fix handling of clock inputs
Signed-off-by: David Shah <dave@ds0.me>
-rw-r--r--common/timing.cc27
-rw-r--r--ice40/arch.cc4
2 files changed, 19 insertions, 12 deletions
diff --git a/common/timing.cc b/common/timing.cc
index 8ecea38e..10b321f7 100644
--- a/common/timing.cc
+++ b/common/timing.cc
@@ -160,8 +160,15 @@ struct Timing
topographical_order.emplace_back(o->net);
TimingData td;
td.false_startpoint = (portClass == TMG_GEN_CLOCK || portClass == TMG_IGNORE);
+ td.max_arrival = 0;
net_data[o->net][ClockEvent{async_clock, RISING_EDGE}] = td;
}
+
+ // Don't analyse paths from a clock input to other pins - they will be considered by the
+ // special-case handling register input/output class ports
+ if (portClass == TMG_CLOCK_INPUT)
+ continue;
+
// Otherwise, for all driven input ports on this cell, if a timing arc exists between the input and
// the current output port, increment fanin counter
for (auto i : input_ports) {
@@ -254,7 +261,8 @@ struct Timing
auto net_delay = net_delays ? ctx->getNetinfoRouteDelay(net, usr) : delay_t();
auto usr_arrival = net_arrival + net_delay;
- if (portClass == TMG_REGISTER_INPUT || portClass == TMG_ENDPOINT || portClass == TMG_IGNORE) {
+ if (portClass == TMG_REGISTER_INPUT || portClass == TMG_ENDPOINT || portClass == TMG_IGNORE ||
+ portClass == TMG_CLOCK_INPUT) {
// Skip
} else {
auto budget_override = ctx->getBudgetOverride(net, usr, net_delay);
@@ -347,7 +355,7 @@ struct Timing
TimingClockingInfo clkInfo = ctx->getPortClockingInfo(usr.cell, usr.port, i);
const NetInfo *clknet = get_net_or_empty(usr.cell, clkInfo.clock_port);
IdString clksig = clknet ? clknet->name : async_clock;
- process_endpoint(clksig, clknet ? RISING_EDGE : clkInfo.edge, clkInfo.setup.maxDelay());
+ process_endpoint(clksig, clknet ? clkInfo.edge : RISING_EDGE, clkInfo.setup.maxDelay());
}
} else {
process_endpoint(async_clock, RISING_EDGE, 0);
@@ -405,7 +413,8 @@ struct Timing
continue;
// And find the fanin net with the latest arrival time
- if (net_data.count(port.second.net) && net_data.at(port.second.net).count(crit_pair.first.start)) {
+ if (net_data.count(port.second.net) &&
+ net_data.at(port.second.net).count(crit_pair.first.start)) {
const auto net_arrival = net_data.at(port.second.net).at(crit_pair.first.start).max_arrival;
if (net_arrival > max_arrival) {
max_arrival = net_arrival;
@@ -554,7 +563,7 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
}
if (print_path) {
- auto print_path_report = [ctx] (ClockPair &clocks, PortRefVector &crit_path) {
+ auto print_path_report = [ctx](ClockPair &clocks, PortRefVector &crit_path) {
delay_t total = 0;
auto &front = crit_path.front();
auto &front_port = front->cell->ports.at(front->port);
@@ -587,19 +596,18 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
ctx->getCellDelay(sink_cell, last_port, driver.port, comb_delay);
}
total += comb_delay.maxDelay();
- log_info("%4.1f %4.1f Source %s.%s\n", ctx->getDelayNS(comb_delay.maxDelay()),
- ctx->getDelayNS(total), driver_cell->name.c_str(ctx), driver.port.c_str(ctx));
+ log_info("%4.1f %4.1f Source %s.%s\n", ctx->getDelayNS(comb_delay.maxDelay()), ctx->getDelayNS(total),
+ driver_cell->name.c_str(ctx), driver.port.c_str(ctx));
auto net_delay = ctx->getNetinfoRouteDelay(net, *sink);
total += net_delay;
auto driver_loc = ctx->getBelLocation(driver_cell->bel);
auto sink_loc = ctx->getBelLocation(sink_cell->bel);
log_info("%4.1f %4.1f Net %s budget %f ns (%d,%d) -> (%d,%d)\n", ctx->getDelayNS(net_delay),
- ctx->getDelayNS(total), net->name.c_str(ctx), ctx->getDelayNS(sink->budget),
- driver_loc.x, driver_loc.y, sink_loc.x, sink_loc.y);
+ ctx->getDelayNS(total), net->name.c_str(ctx), ctx->getDelayNS(sink->budget), driver_loc.x,
+ driver_loc.y, sink_loc.x, sink_loc.y);
log_info(" Sink %s.%s\n", sink_cell->name.c_str(ctx), sink->port.c_str(ctx));
last_port = sink->port;
}
-
};
for (auto &clock : clock_reports) {
@@ -610,7 +618,6 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p
print_path_report(clock.second.first, crit_path);
}
-
for (auto &xclock : xclock_paths) {
log_break();
std::string start = format_event(xclock.start);
diff --git a/ice40/arch.cc b/ice40/arch.cc
index c14fecc4..2d910d6f 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -894,7 +894,7 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
else
return TMG_REGISTER_INPUT;
} else if (cell->type == id_ICESTORM_DSP || cell->type == id_ICESTORM_SPRAM) {
- if (port == id_CLK)
+ if (port == id_CLK || port == id_CLOCK)
return TMG_CLOCK_INPUT;
else {
clockInfoCount = 1;
@@ -960,7 +960,7 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
info.hold.delay = 0;
}
} else if (cell->type == id_ICESTORM_DSP || cell->type == id_ICESTORM_SPRAM) {
- info.clock_port = id_CLK;
+ info.clock_port = cell->type == id_ICESTORM_SPRAM ? id_CLOCK : id_CLK;
info.edge = RISING_EDGE;
if (cell->ports.at(port).type == PORT_OUT) {
bool has_clktoq = getCellDelay(cell, info.clock_port, port, info.clockToQ);