| #pragma once |
| #include "tatum/graph_visitors/CommonAnalysisOps.hpp" |
| #include "tatum/delay_calc/DelayCalculator.hpp" |
| |
| namespace tatum { namespace detail { |
| |
| /** \class SetupAnalysisOps |
| * |
| * The operations for CommonAnalysisVisitor to perform setup analysis. |
| * The setup analysis operations define that maximum edge delays are used, and that the |
| * maixmum arrival time (and minimum required times) are propagated through the timing graph. |
| * |
| * \see HoldAnalysisOps |
| * \see CommonAnalysisVisitor |
| */ |
| class SetupAnalysisOps : public CommonAnalysisOps { |
| public: |
| SetupAnalysisOps(size_t num_tags, size_t num_slacks) |
| : CommonAnalysisOps(num_tags, num_slacks) {} |
| |
| Time clock_constraint(const TimingConstraints& tc, const DomainId src_id, const DomainId sink_id) { |
| return tc.setup_constraint(src_id, sink_id, NodeId::INVALID()); |
| } |
| |
| Time clock_constraint(const TimingConstraints& tc, const DomainId src_id, const DomainId sink_id, const NodeId capture_node) { |
| return tc.setup_constraint(src_id, sink_id, capture_node); |
| } |
| |
| Time clock_uncertainty(const TimingConstraints& tc, const DomainId src_id, const DomainId sink_id) { |
| //Setup analysis, so early capture clock arrival is pessimistic |
| return -tc.setup_clock_uncertainty(src_id, sink_id); |
| } |
| |
| Time launch_source_latency(const TimingConstraints& tc, const DomainId domain) { |
| //For pessimistic setup analysis launch occurs late |
| return tc.source_latency(domain, ArrivalType::LATE); |
| } |
| |
| Time capture_source_latency(const TimingConstraints& tc, const DomainId domain) { |
| //For pessimistic setup analysis capture occurs early |
| return tc.source_latency(domain, ArrivalType::EARLY); |
| } |
| |
| Time input_constraint(const TimingConstraints& tc, const NodeId node, const DomainId domain) { |
| return tc.input_constraint(node, domain, DelayType::MAX); |
| } |
| |
| auto input_constraints(const TimingConstraints& tc, const NodeId node) { |
| return tc.input_constraints(node, DelayType::MAX); |
| } |
| |
| Time output_constraint(const TimingConstraints& tc, const NodeId node, const DomainId domain) { |
| return tc.output_constraint(node, domain, DelayType::MAX); |
| } |
| |
| auto output_constraints(const TimingConstraints& tc, const NodeId node) { |
| return tc.output_constraints(node, DelayType::MAX); |
| } |
| |
| TimingTag const_gen_tag() { return TimingTag::CONST_GEN_TAG_SETUP(); } |
| |
| void merge_req_tags(const NodeId node, const Time time, const NodeId origin, const TimingTag& ref_tag, bool arrival_must_be_valid=false) { |
| node_tags_[node].min(time, origin, ref_tag, arrival_must_be_valid); |
| } |
| |
| void merge_arr_tags(const NodeId node, const Time time, const NodeId origin, const TimingTag& ref_tag) { |
| node_tags_[node].max(time, origin, ref_tag); |
| } |
| |
| Time data_edge_delay(const DelayCalculator& dc, const TimingGraph& tg, const EdgeId edge_id) { |
| Time delay = dc.max_edge_delay(tg, edge_id); |
| |
| TATUM_ASSERT_MSG(delay.value() >= 0., "Data edge delay expected to be positive"); |
| |
| return delay; |
| } |
| |
| Time launch_clock_edge_delay(const DelayCalculator& dc, const TimingGraph& tg, const EdgeId edge_id) { |
| Time delay = dc.max_edge_delay(tg, edge_id); |
| |
| TATUM_ASSERT_MSG(delay.value() >= 0., "Launch clock edge delay expected to be positive"); |
| |
| return delay; |
| } |
| |
| Time capture_clock_edge_delay(const DelayCalculator& dc, const TimingGraph& tg, const EdgeId edge_id) { |
| NodeId src_node = tg.edge_src_node(edge_id); |
| NodeId sink_node = tg.edge_sink_node(edge_id); |
| |
| if(tg.node_type(src_node) == NodeType::CPIN && tg.node_type(sink_node) == NodeType::SINK) { |
| Time tsu = dc.setup_time(tg, edge_id); |
| TATUM_ASSERT_MSG(!std::isnan(tsu.value()), "Setup Time (Tsu) expected to be numeric value (not NaN)"); |
| |
| //The setup time is returned as a negative value, since it is placed on the clock path |
| //(instead of the data path). |
| return -tsu; |
| } else { |
| Time tcq = dc.max_edge_delay(tg, edge_id); |
| TATUM_ASSERT_MSG(tcq.value() >= 0., "Clock-to-q delay (Tcq) expected to be positive"); |
| |
| return tcq; |
| } |
| } |
| |
| Time calculate_slack(const Time required_time, const Time arrival_time) { |
| //Setup requires the arrival to occur *before* the required time, so |
| //slack is the amount of required time left after the arrival time; meaning |
| //we we subtract the arrival time from the required time to get the setup slack |
| return required_time - arrival_time; |
| } |
| |
| }; |
| |
| }} //namespace |
| |