From fc5e6bec9ab8bf2c25b2b943de4013daf727dfb8 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 12 Nov 2018 13:42:25 +0000 Subject: timing: Add support for clock constraints Signed-off-by: David Shah --- common/nextpnr.cc | 9 +++++++++ common/nextpnr.h | 5 ++++- common/timing.cc | 25 ++++++++++++++++++++++--- ecp5/arch_pybindings.cc | 4 ++++ ice40/arch_pybindings.cc | 4 ++++ ice40/pack.cc | 8 ++++++++ 6 files changed, 51 insertions(+), 4 deletions(-) diff --git a/common/nextpnr.cc b/common/nextpnr.cc index 3621217b..8e8a8d19 100644 --- a/common/nextpnr.cc +++ b/common/nextpnr.cc @@ -381,4 +381,13 @@ void Context::check() const } } +void BaseCtx::addClock(IdString net, float freq) +{ + std::unique_ptr cc(new ClockConstraint()); + cc->period = getCtx()->getDelayFromNS(1000 / freq); + cc->high = getCtx()->getDelayFromNS(500 / freq); + cc->low = getCtx()->getDelayFromNS(500 / freq); + nets.at(net)->clkconstr = std::move(cc); +} + NEXTPNR_NAMESPACE_END diff --git a/common/nextpnr.h b/common/nextpnr.h index 216e1532..70af6c71 100644 --- a/common/nextpnr.h +++ b/common/nextpnr.h @@ -297,7 +297,7 @@ struct NetInfo : ArchNetInfo // wire -> uphill_pip std::unordered_map wires; - ClockConstraint *clkconstr = nullptr; + std::unique_ptr clkconstr; TimingConstrObjectId tmg_id; @@ -627,6 +627,9 @@ struct BaseCtx void addConstraint(std::unique_ptr constr); void removeConstraint(IdString constrName); + + // Intended to simplify Python API + void addClock(IdString net, float freq); }; NEXTPNR_NAMESPACE_END diff --git a/common/timing.cc b/common/timing.cc index 8351b1f3..fec74312 100644 --- a/common/timing.cc +++ b/common/timing.cc @@ -315,13 +315,26 @@ struct Timing const auto endpoint_arrival = net_arrival + net_delay + setup; auto path_budget = clk_period - endpoint_arrival; delay_t period; - + // Set default period if (edge == startdomain.first.edge) { period = clk_period; } else { period = clk_period / 2; } - + if (clksig != async_clock) { + if (ctx->nets.at(clksig)->clkconstr) { + if (edge == startdomain.first.edge) { + // same edge + period = ctx->nets.at(clksig)->clkconstr->period.minDelay(); + } else if (edge == RISING_EDGE) { + // falling -> rising + period = ctx->nets.at(clksig)->clkconstr->low.minDelay(); + } else if (edge == FALLING_EDGE) { + // rising -> falling + period = ctx->nets.at(clksig)->clkconstr->high.minDelay(); + } + } + } if (update) { auto budget_share = budget_override ? 0 : path_budget / net_length_plus_one; usr.budget = std::min(usr.budget, net_delay + budget_share); @@ -637,7 +650,13 @@ void timing_analysis(Context *ctx, bool print_histogram, bool print_fmax, bool p if (print_fmax) { log_break(); for (auto &clock : clock_reports) { - log_info("Max frequency for clock '%s': %.02f MHz\n", clock.first.c_str(ctx), clock_fmax[clock.first]); + if (ctx->nets.at(clock.first)->clkconstr) { + float target = 1000 / ctx->getDelayNS(ctx->nets.at(clock.first)->clkconstr->period.minDelay()); + log_info("Max frequency for clock '%s': %.02f MHz (%s at %.02f MHz)\n", clock.first.c_str(ctx), + clock_fmax[clock.first], (target < clock_fmax[clock.first]) ? "PASS" : "FAIL", target); + } else { + log_info("Max frequency for clock '%s': %.02f MHz\n", clock.first.c_str(ctx), clock_fmax[clock.first]); + } } log_break(); diff --git a/ecp5/arch_pybindings.cc b/ecp5/arch_pybindings.cc index 9312b4ad..5e73a673 100644 --- a/ecp5/arch_pybindings.cc +++ b/ecp5/arch_pybindings.cc @@ -130,6 +130,10 @@ void arch_wrap_python() "cells"); readonly_wrapper>::def_wrap(ctx_cls, "nets"); + + fn_wrapper_2a_v, + pass_through>::def_wrap(ctx_cls, "addClock"); + WRAP_RANGE(Bel, conv_to_str); WRAP_RANGE(Wire, conv_to_str); WRAP_RANGE(AllPip, conv_to_str); diff --git a/ice40/arch_pybindings.cc b/ice40/arch_pybindings.cc index f1639ba6..3fafb1f6 100644 --- a/ice40/arch_pybindings.cc +++ b/ice40/arch_pybindings.cc @@ -140,6 +140,10 @@ void arch_wrap_python() "cells"); readonly_wrapper>::def_wrap(ctx_cls, "nets"); + + fn_wrapper_2a_v, + pass_through>::def_wrap(ctx_cls, "addClock"); + WRAP_RANGE(Bel, conv_to_str); WRAP_RANGE(Wire, conv_to_str); WRAP_RANGE(AllPip, conv_to_str); diff --git a/ice40/pack.cc b/ice40/pack.cc index b9360b74..7a27d505 100644 --- a/ice40/pack.cc +++ b/ice40/pack.cc @@ -490,6 +490,14 @@ static void insert_global(Context *ctx, NetInfo *net, bool is_reset, bool is_cen } } net->users = keep_users; + + if (net->clkconstr) { + glbnet->clkconstr = std::unique_ptr(new ClockConstraint()); + glbnet->clkconstr->low = net->clkconstr->low; + glbnet->clkconstr->high = net->clkconstr->high; + glbnet->clkconstr->period = net->clkconstr->period; + } + ctx->nets[glbnet->name] = std::move(glbnet); ctx->cells[gb->name] = std::move(gb); } -- cgit v1.2.3