timing: Add hold time to bound of critical path report
This commit is contained in:
parent
4b63b1115e
commit
2d542eb63a
@ -203,6 +203,32 @@ 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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string tmgPortClass_to_str(TimingPortClass tmg_class)
|
||||||
|
{
|
||||||
|
switch (tmg_class) {
|
||||||
|
case TMG_CLOCK_INPUT:
|
||||||
|
return "TMG_CLOCK_INPUT";
|
||||||
|
case TMG_GEN_CLOCK:
|
||||||
|
return "TMG_GEN_CLOCK";
|
||||||
|
case TMG_REGISTER_INPUT:
|
||||||
|
return "TMG_REGISTER_INPUT";
|
||||||
|
case TMG_REGISTER_OUTPUT:
|
||||||
|
return "TMG_REGISTER_OUTPUT";
|
||||||
|
case TMG_COMB_INPUT:
|
||||||
|
return "TMG_COMB_INPUT";
|
||||||
|
case TMG_COMB_OUTPUT:
|
||||||
|
return "TMG_COMB_OUTPUT";
|
||||||
|
case TMG_STARTPOINT:
|
||||||
|
return "TMG_STARTPOINT";
|
||||||
|
case TMG_ENDPOINT:
|
||||||
|
return "TMG_ENDPOINT";
|
||||||
|
case TMG_IGNORE:
|
||||||
|
return "TMG_IGNORE";
|
||||||
|
default:
|
||||||
|
return "TMG_BOOM";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum ClockEdge
|
enum ClockEdge
|
||||||
{
|
{
|
||||||
RISING_EDGE,
|
RISING_EDGE,
|
||||||
|
@ -826,16 +826,31 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set hold time
|
||||||
|
auto cell = cell_info(endpoint);
|
||||||
|
auto &port = port_info(endpoint);
|
||||||
|
int port_clocks;
|
||||||
|
auto portClass = ctx->getPortTimingClass(cell, port.name, port_clocks);
|
||||||
|
if (portClass == TMG_REGISTER_INPUT) {
|
||||||
|
for (int i = 0; i < port_clocks; i++) {
|
||||||
|
auto info = ctx->getPortClockingInfo(cell, port.name, i);
|
||||||
|
if (!cell->ports.count(info.clock_port) || cell->ports.at(info.clock_port).net == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
report.bound.min_delay = info.hold.min_delay;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pool<std::pair<IdString, IdString>> visited;
|
pool<std::pair<IdString, IdString>> visited;
|
||||||
std::vector<PortRef> crit_path_rev;
|
std::vector<PortRef> crit_path_rev;
|
||||||
auto cursor = endpoint;
|
auto cursor = endpoint;
|
||||||
|
|
||||||
while (cursor != CellPortKey()) {
|
while (cursor != CellPortKey()) {
|
||||||
auto cell = cell_info(cursor);
|
|
||||||
auto &port = port_info(cursor);
|
|
||||||
|
|
||||||
int port_clocks;
|
int port_clocks;
|
||||||
auto portClass = ctx->getPortTimingClass(cell, port.name, port_clocks);
|
auto portClass = ctx->getPortTimingClass(cell, port.name, port_clocks);
|
||||||
|
printf("%s.%s %s\n", cell->name.c_str(ctx), port.name.c_str(ctx), tmgPortClass_to_str(portClass));
|
||||||
|
|
||||||
// combinational loop
|
// combinational loop
|
||||||
if (!visited.insert(std::make_pair(cell->name, port.name)).second)
|
if (!visited.insert(std::make_pair(cell->name, port.name)).second)
|
||||||
@ -848,6 +863,8 @@ CriticalPath TimingAnalyser::build_critical_path_report(domain_id_t domain_pair,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
cursor = ports.at(cursor).arrival.at(dp.key.launch).bwd_max;
|
cursor = ports.at(cursor).arrival.at(dp.key.launch).bwd_max;
|
||||||
|
auto cell = cell_info(cursor);
|
||||||
|
auto &port = port_info(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto crit_path = boost::adaptors::reverse(crit_path_rev);
|
auto crit_path = boost::adaptors::reverse(crit_path_rev);
|
||||||
|
Loading…
Reference in New Issue
Block a user