21 #include "../timing/library.h"
22 #include "../timing/graph.h"
23 #include "../netlist/netlist.h"
24 #include "../interconnection/rc_tree.h"
26 #include <lemon/connectivity.h>
28 #include <boost/units/limits.hpp>
29 #include <boost/units/cmath.hpp>
33 #include "design_constraints.h"
35 #include "graph_nodes_timing.h"
36 #include "graph_arcs_timing.h"
39 #include <lemon/path.h>
41 #ifndef OPHIDIAN_TIMING_GENERIC_STA_H
42 #define OPHIDIAN_TIMING_GENERIC_STA_H
48 using TimingType = boost::units::quantity< boost::units::si::time >;
50 TimingType operator()(
const TimingType &a,
const TimingType &b)
const {
51 return std::min(a, b);
53 TimingType inverted(
const TimingType &a,
const TimingType &b)
const {
54 return std::max(a, b);
56 static double slack_signal() {
59 static TimingType best() {
60 return std::numeric_limits<TimingType >::infinity();
62 static TimingType worst() {
63 return -std::numeric_limits<TimingType >::infinity();
69 using TimingType = boost::units::quantity< boost::units::si::time >;
71 TimingType operator()(
const TimingType &a,
const TimingType &b)
const {
72 return std::max(a, b);
74 TimingType inverted(
const TimingType &a,
const TimingType &b)
const {
75 return std::min(a, b);
77 static double slack_signal() {
80 static TimingType best() {
81 return -std::numeric_limits<TimingType >::infinity();
83 static TimingType worst() {
84 return std::numeric_limits<TimingType >::infinity();
109 std::vector<lemon::ListDigraph::Node> sorted;
110 std::vector< std::vector<lemon::ListDigraph::Node> > levels;
111 std::vector<lemon::ListDigraph::Node> sorted_drivers;
122 boost::units::quantity< boost::units::si::time > clock_period;
124 void compute_tests();
129 template <
class WireDelayModel,
class MergeStrategy>
132 using SlewType = boost::units::quantity< boost::units::si::time >;
133 using CapacitanceType = boost::units::quantity< boost::units::si::capacitance >;
140 MergeStrategy m_merge;
142 SlewType compute_slew(lemon::ListDigraph::Node node, CapacitanceType load)
const {
143 SlewType worst_slew = MergeStrategy::best();
144 if(lemon::countInArcs(m_topology->g.G(), node) == 0)
145 return m_timing.nodes.slew(node);
146 switch(m_topology->g.node_edge(node))
149 for(lemon::ListDigraph::InArcIt it(m_topology->g.G(), node); it != lemon::INVALID; ++it)
151 auto tarc = m_topology->g.edge_entity(it) ;
152 worst_slew = m_merge(worst_slew, m_timing.lib.timing_arc_rise_slew(tarc).compute(load, m_timing.nodes.slew(m_topology->g.edge_source(it))));
156 for(lemon::ListDigraph::InArcIt it(m_topology->g.G(), node); it != lemon::INVALID; ++it)
158 auto tarc = m_topology->g.edge_entity(it) ;
159 worst_slew = m_merge(worst_slew, m_timing.lib.timing_arc_fall_slew(tarc).compute(load, m_timing.nodes.slew(m_topology->g.edge_source(it))));
169 m_topology(&topology),
181 m_topology = &topology;
189 using namespace boost::units;
190 using namespace boost::units::si;
192 m_timing.nodes.arrival( m_topology->g.rise_node(m_topology->netlist.pin_by_name(dc.clock.port_name)), 0.0*seconds );
193 m_timing.nodes.arrival( m_topology->g.fall_node(m_topology->netlist.pin_by_name(dc.clock.port_name)), 0.0*seconds );
195 for(
auto & i : dc.input_delays)
197 auto pin = m_topology->netlist.
pin_by_name(i.port_name);
198 m_timing.nodes.arrival( m_topology->g.rise_node(pin), quantity<si::time>(i.delay*pico*seconds) );
199 m_timing.nodes.arrival( m_topology->g.fall_node(pin), quantity<si::time>(i.delay*pico*seconds) );
202 for(
auto & i : dc.input_drivers)
204 auto pin = m_topology->netlist.pin_by_name(i.port_name);
205 m_timing.nodes.slew( m_topology->g.rise_node(pin), quantity<si::time>(i.slew_rise*pico*seconds) );
206 m_timing.nodes.slew( m_topology->g.fall_node(pin), quantity<si::time>(i.slew_fall*pico*seconds) );
210 for(lemon::ListDigraph::NodeIt node(m_topology->g.G()); node != lemon::INVALID; ++node)
212 if(m_timing.lib.pin_clock_input(m_topology->netlist.pin_std_cell(m_topology->g.pin(node))))
213 m_timing.nodes.required( node, MergeStrategy::worst() );
214 else if(lemon::countOutArcs(m_topology->g.G(), node) == 0 )
215 m_timing.nodes.required( node, m_merge(quantity<si::time>(0.0*seconds), quantity<si::time>(dc.clock.period * pico* seconds)) );
221 SlewType rise_arrival(
const entity_system::entity pin)
const
223 return m_timing.nodes.arrival(m_topology->g.rise_node(pin));
225 SlewType fall_arrival(
const entity_system::entity pin)
const
227 return m_timing.nodes.arrival(m_topology->g.fall_node(pin));
230 SlewType rise_slew(
const entity_system::entity pin)
const
232 return m_timing.nodes.slew(m_topology->g.rise_node(pin));
234 SlewType fall_slew(
const entity_system::entity pin)
const
236 return m_timing.nodes.slew(m_topology->g.fall_node(pin));
239 SlewType rise_slack(
const entity_system::entity pin)
const
241 auto node = m_topology->g.rise_node(pin);
242 return MergeStrategy::slack_signal()*(m_timing.nodes.required(node)-m_timing.nodes.arrival(node));
244 SlewType fall_slack(
const entity_system::entity pin)
const
246 auto node = m_topology->g.fall_node(pin);
247 return MergeStrategy::slack_signal()*(m_timing.nodes.required(node)-m_timing.nodes.arrival(node));
252 for(
auto & level : m_topology->levels)
255 for(i = 0; i < level.size(); ++i)
257 auto node = level[i];
258 if(lemon::countInArcs(m_topology->g.G(), node) != 0)
260 auto pin = m_topology->g.pin(node);
261 auto net = m_topology->netlist.pin_net(pin);
262 auto & tree = m_rc_trees[m_topology->netlist.net_system().lookup(net)];
264 std::vector< SlewType > slews(tree.node_count());
265 std::vector< SlewType > delays(tree.node_count());
266 std::vector< CapacitanceType > ceffs(tree.node_count());
267 WireDelayModel calculator;
268 calculator.delay_map(delays);
269 calculator.slew_map(slews);
270 calculator.ceff_map(ceffs);
271 std::function<SlewType(CapacitanceType)> s_calculator = std::bind(&generic_sta::compute_slew,
this, node, std::placeholders::_1);
273 CapacitanceType load = calculator.simulate(s_calculator, tree);
275 m_timing.nodes.load(node, load);
276 m_timing.nodes.slew(node, slews[0]);
278 SlewType worst_arrival = MergeStrategy::best();
279 switch(m_topology->g.node_edge(node))
282 for(lemon::ListDigraph::InArcIt it(m_topology->g.G(), node); it != lemon::INVALID; ++it)
284 auto tarc = m_topology->g.edge_entity(it) ;
285 auto edge_source = m_topology->g.edge_source(it);
286 auto arc_delay = m_timing.lib.timing_arc_rise_delay(tarc).compute(load, m_timing.nodes.slew(edge_source));
287 auto arc_slew = m_timing.lib.timing_arc_rise_slew(tarc).compute(load, m_timing.nodes.slew(edge_source));
288 m_timing.arcs.delay(it, arc_delay);
289 m_timing.arcs.slew(it, arc_slew);
290 worst_arrival = m_merge(worst_arrival, m_timing.nodes.arrival(edge_source) + arc_delay);
294 for(lemon::ListDigraph::InArcIt it(m_topology->g.G(), node); it != lemon::INVALID; ++it)
296 auto tarc = m_topology->g.edge_entity(it) ;
297 auto edge_source = m_topology->g.edge_source(it);
298 auto arc_delay = m_timing.lib.timing_arc_fall_delay(tarc).compute(load, m_timing.nodes.slew(edge_source));
299 auto arc_slew = m_timing.lib.timing_arc_fall_slew(tarc).compute(load, m_timing.nodes.slew(edge_source));
300 m_timing.arcs.delay(it, arc_delay);
301 m_timing.arcs.slew(it, arc_slew);
302 worst_arrival = m_merge(worst_arrival, m_timing.nodes.arrival(edge_source) + arc_delay);
306 m_timing.nodes.arrival(node, worst_arrival);
307 for(lemon::ListDigraph::OutArcIt arc(m_topology->g.G(), node); arc != lemon::INVALID; ++arc)
309 auto arc_target = m_topology->g.edge_target(arc);
310 auto target_pin = m_topology->g.pin(arc_target);
311 auto target_capacitor = tree.tap(m_topology->netlist.pin_name(target_pin));
312 m_timing.arcs.slew(arc, slews[target_capacitor]);
313 m_timing.arcs.delay(arc, delays[target_capacitor]);
314 m_timing.nodes.slew(arc_target, m_timing.arcs.slew(arc));
315 m_timing.nodes.arrival(arc_target, m_timing.nodes.arrival(node) + m_timing.arcs.delay(arc));
325 for(
auto node_it = m_topology->sorted.rbegin(); node_it != m_topology->sorted.rend(); ++node_it)
327 auto node = *node_it;
328 if(lemon::countOutArcs(m_topology->g.G(), node) > 0)
330 SlewType required = MergeStrategy::worst();
331 for(lemon::ListDigraph::OutArcIt arc(m_topology->g.G(), node); arc != lemon::INVALID; ++arc)
332 required = m_merge.inverted(required, m_timing.nodes.required(m_topology->g.edge_target(arc))-m_timing.arcs.delay(arc));
333 m_timing.nodes.required(node, required);
339 lemon::Path<lemon::ListDigraph> critical_path()
const {
340 lemon::Path<lemon::ListDigraph> cp;
341 SlewType worst_slack = std::numeric_limits<SlewType>::infinity();
342 lemon::ListDigraph::Node worst_PO;
343 for(
auto node_it = m_topology->sorted.rbegin(); node_it != m_topology->sorted.rend(); ++node_it)
345 auto node = *node_it;
346 if(lemon::countOutArcs(m_topology->g.G(), node) == 0)
348 SlewType current_PO_slack = MergeStrategy::slack_signal()*(m_timing.nodes.required(node)-m_timing.nodes.arrival(node));
349 if(current_PO_slack < worst_slack)
351 worst_slack = current_PO_slack;
356 lemon::ListDigraph::Node current_node = worst_PO;
357 lemon::ListDigraph::Node next_node = current_node;
358 while(next_node != lemon::INVALID)
360 current_node = next_node;
361 next_node = lemon::INVALID;
362 lemon::ListDigraph::Arc worst_arc = lemon::INVALID;
363 SlewType worst_slack_input = std::numeric_limits<SlewType>::infinity();
364 for(lemon::ListDigraph::InArcIt in(m_topology->g.G(), current_node); in != lemon::INVALID; ++in)
366 auto source = m_topology->g.G().source(in);
367 SlewType slack = MergeStrategy::slack_signal()*(m_timing.nodes.required(source)-m_timing.nodes.arrival(source));
368 if(slack < worst_slack_input)
370 worst_slack_input = slack;
375 if(worst_arc != lemon::INVALID)
376 cp.addFront(worst_arc);
388 #endif // OPHIDIAN_TIMING_GENERIC_STA_H
Definition: generic_sta.h:68
Definition: generic_sta.h:47
Definition: generic_sta.h:117
Definition: design_constraints.h:63
Definition: graph_nodes_timing.h:31
Definition: generic_sta.h:89
Netlist class.
Definition: netlist.h:41
Definition: generic_sta.h:106
Definition: graph_arcs_timing.h:30
Definition: generic_sta.h:130
entity_system::entity pin_by_name(std::string name) const
Finds pin.
Definition: netlist.h:276