timing: Add clock skew to arrival and required time
This commit is contained in:
parent
60ee682d58
commit
fc3b2de8da
@ -116,10 +116,10 @@ delay_t Context::predictArcDelay(const NetInfo *net_info, const PortRef &sink) c
|
|||||||
|
|
||||||
delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &user_info) const
|
delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &user_info) const
|
||||||
{
|
{
|
||||||
#ifdef ARCH_ECP5
|
// #ifdef ARCH_ECP5
|
||||||
if (net_info->is_global)
|
// if (net_info->is_global)
|
||||||
return 0;
|
// return 0;
|
||||||
#endif
|
// #endif
|
||||||
|
|
||||||
if (net_info->wires.empty())
|
if (net_info->wires.empty())
|
||||||
return predictArcDelay(net_info, user_info);
|
return predictArcDelay(net_info, user_info);
|
||||||
@ -417,7 +417,7 @@ void Context::check() const
|
|||||||
namespace {
|
namespace {
|
||||||
struct FixupHierarchyWorker
|
struct FixupHierarchyWorker
|
||||||
{
|
{
|
||||||
FixupHierarchyWorker(Context *ctx) : ctx(ctx){};
|
FixupHierarchyWorker(Context *ctx) : ctx(ctx) {};
|
||||||
Context *ctx;
|
Context *ctx;
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
|
@ -174,10 +174,20 @@ void TimingAnalyser::get_route_delays()
|
|||||||
NetInfo *ni = net.second.get();
|
NetInfo *ni = net.second.get();
|
||||||
if (ni->driver.cell == nullptr || ni->driver.cell->bel == BelId())
|
if (ni->driver.cell == nullptr || ni->driver.cell->bel == BelId())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (clock_skew) {
|
||||||
|
printf("net %s has driver %s.%s\n", ni->name.c_str(ctx), ni->driver.cell->name.c_str(ctx),
|
||||||
|
ni->driver.port.c_str(ctx));
|
||||||
|
}
|
||||||
for (auto &usr : ni->users) {
|
for (auto &usr : ni->users) {
|
||||||
if (usr.cell->bel == BelId())
|
if (usr.cell->bel == BelId())
|
||||||
continue;
|
continue;
|
||||||
ports.at(CellPortKey(usr)).route_delay = DelayPair(ctx->getNetinfoRouteDelay(ni, usr));
|
ports.at(CellPortKey(usr)).route_delay = DelayPair(ctx->getNetinfoRouteDelay(ni, usr));
|
||||||
|
|
||||||
|
if (clock_skew) {
|
||||||
|
printf("\tuser %s.%s, delay: %f\n", usr.cell->name.c_str(ctx), usr.port.c_str(ctx),
|
||||||
|
ctx->getDelayNS(ctx->getNetinfoRouteDelay(ni, usr)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -567,12 +577,15 @@ void TimingAnalyser::walk_forward()
|
|||||||
auto &pd = ports.at(sp.first);
|
auto &pd = ports.at(sp.first);
|
||||||
DelayPair init_arrival(0);
|
DelayPair init_arrival(0);
|
||||||
CellPortKey clock_key;
|
CellPortKey clock_key;
|
||||||
// TODO: clock routing delay, if analysis of that is enabled
|
|
||||||
if (sp.second != IdString()) {
|
if (sp.second != IdString()) {
|
||||||
// clocked startpoints have a clock-to-out time
|
// clocked startpoints have a clock-to-out time
|
||||||
for (auto &fanin : pd.cell_arcs) {
|
for (auto &fanin : pd.cell_arcs) {
|
||||||
if (fanin.type == CellArc::CLK_TO_Q && fanin.other_port == sp.second) {
|
if (fanin.type == CellArc::CLK_TO_Q && fanin.other_port == sp.second) {
|
||||||
init_arrival = init_arrival + fanin.value.delayPair();
|
init_arrival += fanin.value.delayPair();
|
||||||
|
if (clock_skew) {
|
||||||
|
auto clock_delay = ports.at(CellPortKey(sp.first.cell, fanin.other_port)).route_delay;
|
||||||
|
init_arrival += clock_delay;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -619,20 +632,28 @@ void TimingAnalyser::walk_backward()
|
|||||||
auto &dom = domains.at(dom_id);
|
auto &dom = domains.at(dom_id);
|
||||||
for (auto &ep : dom.endpoints) {
|
for (auto &ep : dom.endpoints) {
|
||||||
auto &pd = ports.at(ep.first);
|
auto &pd = ports.at(ep.first);
|
||||||
DelayPair init_setuphold(0);
|
DelayPair init_required(0);
|
||||||
CellPortKey clock_key;
|
CellPortKey clock_key;
|
||||||
// TODO: clock routing delay, if analysis of that is enabled
|
// TODO: clock routing delay, if analysis of that is enabled
|
||||||
if (ep.second != IdString()) {
|
if (ep.second != IdString()) {
|
||||||
// Add setup/hold time, if this endpoint is clocked
|
// Add setup/hold time, if this endpoint is clocked
|
||||||
for (auto &fanin : pd.cell_arcs) {
|
for (auto &fanin : pd.cell_arcs) {
|
||||||
if (fanin.type == CellArc::SETUP && fanin.other_port == ep.second)
|
printf("walk bwd %s.%s, fanin: %s, arctype: %s\n", ep.first.cell.c_str(ctx),
|
||||||
init_setuphold.min_delay -= fanin.value.maxDelay();
|
ep.first.port.c_str(ctx), fanin.other_port.c_str(ctx), arcType_to_str(fanin.type).c_str());
|
||||||
|
|
||||||
|
if (fanin.type == CellArc::SETUP && fanin.other_port == ep.second) {
|
||||||
|
if (clock_skew) {
|
||||||
|
auto clock_delay = ports.at(CellPortKey(ep.first.cell, fanin.other_port)).route_delay;
|
||||||
|
init_required += clock_delay;
|
||||||
|
}
|
||||||
|
init_required.min_delay -= fanin.value.maxDelay();
|
||||||
|
}
|
||||||
if (fanin.type == CellArc::HOLD && fanin.other_port == ep.second)
|
if (fanin.type == CellArc::HOLD && fanin.other_port == ep.second)
|
||||||
init_setuphold.max_delay -= fanin.value.maxDelay();
|
init_required.max_delay -= fanin.value.maxDelay();
|
||||||
}
|
}
|
||||||
clock_key = CellPortKey(ep.first.cell, ep.second);
|
clock_key = CellPortKey(ep.first.cell, ep.second);
|
||||||
}
|
}
|
||||||
set_required_time(ep.first, dom_id, init_setuphold, 1, clock_key);
|
set_required_time(ep.first, dom_id, init_required, 1, clock_key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Walk backwards in topological order
|
// Walk backwards in topological order
|
||||||
@ -1211,6 +1232,8 @@ void timing_analysis(Context *ctx, bool print_slack_histogram, bool print_fmax,
|
|||||||
bool update_results)
|
bool update_results)
|
||||||
{
|
{
|
||||||
TimingAnalyser tmg(ctx);
|
TimingAnalyser tmg(ctx);
|
||||||
|
tmg.setup_only = false;
|
||||||
|
tmg.clock_skew = true;
|
||||||
tmg.setup(ctx->detailed_timing_report, print_slack_histogram, print_path || print_fmax);
|
tmg.setup(ctx->detailed_timing_report, print_slack_histogram, print_path || print_fmax);
|
||||||
|
|
||||||
auto &result = tmg.get_timing_result();
|
auto &result = tmg.get_timing_result();
|
||||||
|
@ -98,6 +98,10 @@ struct TimingAnalyser
|
|||||||
|
|
||||||
TimingResult &get_timing_result() { return result; }
|
TimingResult &get_timing_result() { return result; }
|
||||||
|
|
||||||
|
// Enable analysis of clock skew between FFs.
|
||||||
|
// Only do this after legal placement
|
||||||
|
bool clock_skew = false;
|
||||||
|
|
||||||
bool setup_only = false;
|
bool setup_only = false;
|
||||||
bool have_loops = false;
|
bool have_loops = false;
|
||||||
bool updated_domains = false;
|
bool updated_domains = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user