timing: Fix handling of clock inputs

Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
David Shah 2018-11-03 14:09:27 +00:00
parent fad69d4930
commit e633aa09cc
2 changed files with 19 additions and 12 deletions

View File

@ -160,8 +160,15 @@ struct Timing
topographical_order.emplace_back(o->net); topographical_order.emplace_back(o->net);
TimingData td; TimingData td;
td.false_startpoint = (portClass == TMG_GEN_CLOCK || portClass == TMG_IGNORE); td.false_startpoint = (portClass == TMG_GEN_CLOCK || portClass == TMG_IGNORE);
td.max_arrival = 0;
net_data[o->net][ClockEvent{async_clock, RISING_EDGE}] = td; 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 // 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 // the current output port, increment fanin counter
for (auto i : input_ports) { for (auto i : input_ports) {
@ -254,7 +261,8 @@ struct Timing
auto net_delay = net_delays ? ctx->getNetinfoRouteDelay(net, usr) : delay_t(); auto net_delay = net_delays ? ctx->getNetinfoRouteDelay(net, usr) : delay_t();
auto usr_arrival = net_arrival + net_delay; 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 // Skip
} else { } else {
auto budget_override = ctx->getBudgetOverride(net, usr, net_delay); auto budget_override = ctx->getBudgetOverride(net, usr, net_delay);
@ -347,7 +355,7 @@ struct Timing
TimingClockingInfo clkInfo = ctx->getPortClockingInfo(usr.cell, usr.port, i); TimingClockingInfo clkInfo = ctx->getPortClockingInfo(usr.cell, usr.port, i);
const NetInfo *clknet = get_net_or_empty(usr.cell, clkInfo.clock_port); const NetInfo *clknet = get_net_or_empty(usr.cell, clkInfo.clock_port);
IdString clksig = clknet ? clknet->name : async_clock; 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 { } else {
process_endpoint(async_clock, RISING_EDGE, 0); process_endpoint(async_clock, RISING_EDGE, 0);
@ -405,7 +413,8 @@ struct Timing
continue; continue;
// And find the fanin net with the latest arrival time // 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; const auto net_arrival = net_data.at(port.second.net).at(crit_pair.first.start).max_arrival;
if (net_arrival > max_arrival) { if (net_arrival > max_arrival) {
max_arrival = net_arrival; max_arrival = net_arrival;
@ -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); ctx->getCellDelay(sink_cell, last_port, driver.port, comb_delay);
} }
total += comb_delay.maxDelay(); total += comb_delay.maxDelay();
log_info("%4.1f %4.1f Source %s.%s\n", ctx->getDelayNS(comb_delay.maxDelay()), log_info("%4.1f %4.1f Source %s.%s\n", ctx->getDelayNS(comb_delay.maxDelay()), ctx->getDelayNS(total),
ctx->getDelayNS(total), driver_cell->name.c_str(ctx), driver.port.c_str(ctx)); driver_cell->name.c_str(ctx), driver.port.c_str(ctx));
auto net_delay = ctx->getNetinfoRouteDelay(net, *sink); auto net_delay = ctx->getNetinfoRouteDelay(net, *sink);
total += net_delay; total += net_delay;
auto driver_loc = ctx->getBelLocation(driver_cell->bel); auto driver_loc = ctx->getBelLocation(driver_cell->bel);
auto sink_loc = ctx->getBelLocation(sink_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), 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), ctx->getDelayNS(total), net->name.c_str(ctx), ctx->getDelayNS(sink->budget), driver_loc.x,
driver_loc.x, driver_loc.y, sink_loc.x, sink_loc.y); 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)); log_info(" Sink %s.%s\n", sink_cell->name.c_str(ctx), sink->port.c_str(ctx));
last_port = sink->port; last_port = sink->port;
} }
}; };
for (auto &clock : clock_reports) { 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); print_path_report(clock.second.first, crit_path);
} }
for (auto &xclock : xclock_paths) { for (auto &xclock : xclock_paths) {
log_break(); log_break();
std::string start = format_event(xclock.start); std::string start = format_event(xclock.start);

View File

@ -894,7 +894,7 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
else else
return TMG_REGISTER_INPUT; return TMG_REGISTER_INPUT;
} else if (cell->type == id_ICESTORM_DSP || cell->type == id_ICESTORM_SPRAM) { } 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; return TMG_CLOCK_INPUT;
else { else {
clockInfoCount = 1; clockInfoCount = 1;
@ -960,7 +960,7 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
info.hold.delay = 0; info.hold.delay = 0;
} }
} else if (cell->type == id_ICESTORM_DSP || cell->type == id_ICESTORM_SPRAM) { } 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; info.edge = RISING_EDGE;
if (cell->ports.at(port).type == PORT_OUT) { if (cell->ports.at(port).type == PORT_OUT) {
bool has_clktoq = getCellDelay(cell, info.clock_port, port, info.clockToQ); bool has_clktoq = getCellDelay(cell, info.clock_port, port, info.clockToQ);