// OpenSTA, Static Timing Analyzer // Copyright (c) 2019, Parallax Software, Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #ifndef STA_GRAPH_H #define STA_GRAPH_H #include "DisallowCopyAssign.hh" #include "Iterator.hh" #include "Map.hh" #include "Vector.hh" #include "Pool.hh" #include "StaState.hh" #include "LibertyClass.hh" #include "NetworkClass.hh" #include "Delay.hh" #include "GraphClass.hh" namespace sta { class MinMax; class Sdc; class PathVertexRep; enum VertexColor { vertex_color_white, vertex_color_gray, vertex_color_black }; typedef Pool DelayPool; typedef Pool VertexPool; typedef Pool EdgePool; typedef Map PinVertexMap; typedef Iterator VertexEdgeIterator; typedef Map WidthCheckAnnotations; typedef Map PeriodCheckAnnotations; typedef Vector DelayPoolSeq; // The graph acts as a BUILDER for the graph vertices and edges. class Graph : public StaState { public: // slew_tr_count is // 0 no slews // 1 one slew for rise/fall // 2 rise/fall slews // ap_count is the dcalc analysis point count. Graph(StaState *sta, int slew_tr_count, bool have_arc_delays, DcalcAPIndex ap_count); void makeGraph(); virtual ~Graph(); // Number of arc delays and slews from sdf or delay calculation. virtual void setDelayCount(DcalcAPIndex ap_count); // Vertex functions. // Bidirect pins have two vertices. virtual Vertex *vertex(VertexIndex vertex_index) const; VertexIndex index(const Vertex *vertex) const; void makePinVertices(Pin *pin); void makePinVertices(Pin *pin, Vertex *&vertex, Vertex *&bidir_drvr_vertex); // Both vertices for bidirects. void pinVertices(const Pin *pin, // Return values. Vertex *&vertex, Vertex *&bidirect_drvr_vertex) const; // Driver vertex for bidirects. Vertex *pinDrvrVertex(const Pin *pin) const; // Load vertex for bidirects. Vertex *pinLoadVertex(const Pin *pin) const; virtual void deleteVertex(Vertex *vertex); bool hasFaninOne(Vertex *vertex) const; VertexIndex vertexCount() { return vertex_count_; } // Slews are reported slews in seconds. // Reported slew are the same as those in the liberty tables. // reported_slews = measured_slews / slew_derate_from_library // Measured slews are between slew_lower_threshold and slew_upper_threshold. virtual const Slew &slew(const Vertex *vertex, const TransRiseFall *tr, DcalcAPIndex ap_index); virtual void setSlew(Vertex *vertex, const TransRiseFall *tr, DcalcAPIndex ap_index, const Slew &slew); // Edge functions. virtual Edge *edge(EdgeIndex edge_index) const; EdgeIndex index(const Edge *edge) const; virtual Edge *makeEdge(Vertex *from, Vertex *to, TimingArcSet *arc_set); virtual void makeWireEdge(Pin *from_pin, Pin *to_pin); void makePinInstanceEdges(Pin *pin); void makeInstanceEdges(const Instance *inst); void makeWireEdgesToPin(Pin *to_pin); void makeWireEdgesThruPin(Pin *hpin); virtual void makeWireEdgesFromPin(Pin *drvr_pin); virtual void deleteEdge(Edge *edge); virtual ArcDelay arcDelay(const Edge *edge, const TimingArc *arc, DcalcAPIndex ap_index) const; virtual void setArcDelay(Edge *edge, const TimingArc *arc, DcalcAPIndex ap_index, ArcDelay delay); // Alias for arcDelays using library wire arcs. virtual const ArcDelay &wireArcDelay(const Edge *edge, const TransRiseFall *tr, DcalcAPIndex ap_index); virtual void setWireArcDelay(Edge *edge, const TransRiseFall *tr, DcalcAPIndex ap_index, const ArcDelay &delay); // Is timing arc delay annotated. bool arcDelayAnnotated(Edge *edge, TimingArc *arc, DcalcAPIndex ap_index) const; void setArcDelayAnnotated(Edge *edge, TimingArc *arc, DcalcAPIndex ap_index, bool annotated); bool wireDelayAnnotated(Edge *edge, const TransRiseFall *tr, DcalcAPIndex ap_index) const; void setWireDelayAnnotated(Edge *edge, const TransRiseFall *tr, DcalcAPIndex ap_index, bool annotated); // True if any edge arc is annotated. bool delayAnnotated(Edge *edge); EdgeIndex edgeCount() { return edge_count_; } virtual ArcIndex arcCount() { return arc_count_; } // Sdf width check annotation. void widthCheckAnnotation(const Pin *pin, const TransRiseFall *tr, DcalcAPIndex ap_index, // Return values. float &width, bool &exists); void setWidthCheckAnnotation(const Pin *pin, const TransRiseFall *tr, DcalcAPIndex ap_index, float width); // Sdf period check annotation. void periodCheckAnnotation(const Pin *pin, DcalcAPIndex ap_index, // Return values. float &period, bool &exists); void setPeriodCheckAnnotation(const Pin *pin, DcalcAPIndex ap_index, float period); // Remove all delay and slew annotations. void removeDelaySlewAnnotations(); VertexSet *regClkVertices() { return ®_clk_vertices_; } protected: void makeVerticesAndEdges(); void vertexAndEdgeCounts(// Return values. VertexIndex &vertex_count, EdgeIndex &edge_count, ArcIndex &arc_count); virtual void vertexAndEdgeCounts(const Instance *inst, PinSet &visited_drvrs, // Return values. VertexIndex &vertex_count, EdgeIndex &edge_count, ArcIndex &arc_count); virtual void drvrPinEdgeCounts(Pin *pin, PinSet &visited_drvrs, // Return values. EdgeIndex &edge_count, ArcIndex &arc_count); Vertex *makeVertex(Pin *pin, bool is_bidirect_drvr, bool is_reg_clk); virtual void makeEdgeArcDelays(Edge *edge); void makePinVertices(const Instance *inst); void makeWireEdgesFromPin(Pin *drvr_pin, PinSet &visited_drvrs); void makeWireEdges(); virtual void makeInstDrvrWireEdges(Instance *inst, PinSet &visited_drvrs); virtual void makePortInstanceEdges(const Instance *inst, LibertyCell *cell, LibertyPort *from_to_port); void removeWidthCheckAnnotations(); void removePeriodCheckAnnotations(); void makeSlewPools(VertexIndex vertex_count, DcalcAPIndex count); void deleteSlewPools(); void makeVertexSlews(); void deleteVertexSlews(Vertex *vertex); void makeArcDelayPools(ArcIndex arc_count, DcalcAPIndex ap_count); void deleteArcDelayPools(); virtual void deleteEdgeArcDelays(Edge *edge); void deleteInEdge(Vertex *vertex, Edge *edge); void deleteOutEdge(Vertex *vertex, Edge *edge); void removeDelays(); float *makeFloats(ObjectIndex count); void deleteFloats(float *floats, ObjectIndex count); void removeDelayAnnotated(Edge *edge); VertexPool *vertices_; EdgePool *edges_; // Bidirect pins are split into two vertices: // load/sink (top level output, instance pin input) vertex in pin_vertex_map // driver/source (top level input, instance pin output) vertex // in pin_bidirect_drvr_vertex_map PinVertexMap pin_bidirect_drvr_vertex_map_; VertexIndex vertex_count_; EdgeIndex edge_count_; ArcIndex arc_count_; Vector arc_delay_annotated_; int slew_tr_count_; bool have_arc_delays_; DcalcAPIndex ap_count_; DelayPoolSeq slew_pools_; // [ap_index][tr_index][vertex_index] VertexIndex slew_count_; DelayPoolSeq arc_delays_; // [ap_index][edge_arc_index] Pool *float_pool_; // Sdf width check annotations. WidthCheckAnnotations *width_check_annotations_; // Sdf period check annotations. PeriodCheckAnnotations *period_check_annotations_; // Register/latch clock vertices to search from. VertexSet reg_clk_vertices_; friend class Vertex; friend class VertexIterator; friend class VertexInEdgeIterator; friend class VertexOutEdgeIterator; friend class MakeEdgesThruHierPin; private: DISALLOW_COPY_AND_ASSIGN(Graph); }; // Each Vertex corresponds to one network pin. class Vertex { public: Vertex(); Pin *pin() const { return pin_; } // Pin path with load/driver suffix for bidirects. const char *name(const Network *network) const; bool isBidirectDriver() const { return is_bidirect_drvr_; } Level level() const { return level_; } void setLevel(Level level); bool isRoot() const{ return level_ == 0; } VertexColor color() const { return (VertexColor) color_; } void setColor(VertexColor color); Arrival *arrivals() const { return arrivals_; } void setArrivals(Arrival *arrivals); PathVertexRep *prevPaths() const { return prev_paths_; } void setPrevPaths(PathVertexRep *prev_paths); // Requireds optionally follow arrivals in the same array. bool hasRequireds() const { return has_requireds_; } void setHasRequireds(bool has_req); TagGroupIndex tagGroupIndex() const; void setTagGroupIndex(TagGroupIndex tag_index); // Slew is annotated by sdc set_annotated_transition cmd. bool slewAnnotated(const TransRiseFall *tr, DcalcAPIndex ap_index) const; // True if any rise/fall analysis pt slew is annotated. bool slewAnnotated() const; void setSlewAnnotated(bool annotated, const TransRiseFall *tr, DcalcAPIndex ap_index); void removeSlewAnnotated(); // Constant zero/one from simulation. bool isConstant() const; LogicValue simValue() const; void setSimValue(LogicValue value); bool isDisabledConstraint() const { return is_disabled_constraint_; } void setIsDisabledConstraint(bool disabled); // True when vertex has timing check edges that constrain it. bool hasChecks() const { return has_checks_; } void setHasChecks(bool has_checks); bool isCheckClk() const { return is_check_clk_; } void setIsCheckClk(bool is_check_clk); bool isGatedClkEnable() const { return is_gated_clk_enable_; } void setIsGatedClkEnable(bool enable); bool hasDownstreamClkPin() const { return has_downstream_clk_pin_; } void setHasDownstreamClkPin(bool has_clk_pin); // Vertices are constrained if they have one or more of the // following timing constraints: // output delay constraints // data check constraints // path delay constraints bool isConstrained() const { return is_constrained_; } void setIsConstrained(bool constrained); bool bfsInQueue(BfsIndex index) const; void setBfsInQueue(BfsIndex index, bool value); bool isRegClk() const { return is_reg_clk_; } static int transitionCount() { return 2; } // rise/fall protected: void init(Pin *pin, bool is_bidirect_drvr, bool is_reg_clk); Pin *pin_; Arrival *arrivals_; PathVertexRep *prev_paths_; EdgeIndex in_edges_; // Edges to this vertex. EdgeIndex out_edges_; // Edges from this vertex. unsigned int tag_group_index_:tag_group_index_bits; bool has_requireds_:1; unsigned int slew_annotated_:4; // Bidirect pins have two vertices. // This flag distinguishes the driver and load vertices. bool is_bidirect_drvr_:1; bool is_reg_clk_:1; unsigned int sim_value_:3; // LogicValue bool is_disabled_constraint_:1; bool is_gated_clk_enable_:1; // Constrained by timing check edge. bool has_checks_:1; // Is the clock for a timing check. bool is_check_clk_:1; bool is_constrained_:1; bool has_downstream_clk_pin_:1; // Levelization search state. unsigned int color_:2; unsigned int level_:16; // Each bit corresponds to a different BFS queue. unsigned int bfs_in_queue_:bfs_index_bits; private: DISALLOW_COPY_AND_ASSIGN(Vertex); friend class Graph; friend class Edge; friend class VertexInEdgeIterator; friend class VertexOutEdgeIterator; }; // There is one Edge between each pair of pins that has a timing // path between them. class Edge { public: Edge(); Vertex *to(const Graph *graph) const { return graph->vertex(to_); } Vertex *from(const Graph *graph) const { return graph->vertex(from_); } TimingRole *role() const; bool isWire() const; TimingSense sense() const; TimingArcSet *timingArcSet() const { return arc_set_; } void setTimingArcSet(TimingArcSet *set); ArcIndex arcDelays() const { return arc_delays_; } void setArcDelays(ArcIndex arc_delays); bool delayAnnotationIsIncremental() const; void setDelayAnnotationIsIncremental(bool is_incr); // Edge is disabled by set_disable_timing constraint. bool isDisabledConstraint() const; void setIsDisabledConstraint(bool disabled); // Timing sense for the to_pin function after simplifying the // function based constants on the instance pins. TimingSense simTimingSense() const; void setSimTimingSense(TimingSense sense); // Edge is disabled by constants in condition (when) function. bool isDisabledCond() const { return is_disabled_cond_; } void setIsDisabledCond(bool disabled); // Edge is disabled to break combinational loops. bool isDisabledLoop() const { return is_disabled_loop_; } void setIsDisabledLoop(bool disabled); // Edge is disabled to prevent converging clocks from merging (Xilinx). bool isBidirectInstPath() const { return is_bidirect_inst_path_; } void setIsBidirectInstPath(bool is_bidir); bool isBidirectNetPath() const { return is_bidirect_net_path_; } void setIsBidirectNetPath(bool is_bidir); protected: void init(VertexIndex from, VertexIndex to, TimingArcSet *arc_set); TimingArcSet *arc_set_; VertexIndex from_; VertexIndex to_; VertexIndex vertex_in_link_; // Vertex in edges list. VertexIndex vertex_out_next_; // Vertex out edges doubly linked list. VertexIndex vertex_out_prev_; ArcIndex arc_delays_; unsigned int delay_annotation_is_incremental_:1; unsigned int is_bidirect_inst_path_:1; unsigned int is_bidirect_net_path_:1; // Timing sense from function and constants on edge instance. unsigned int sim_timing_sense_:timing_sense_bit_count; unsigned int is_disabled_constraint_:1; unsigned int is_disabled_cond_:1; unsigned int is_disabled_loop_:1; private: DISALLOW_COPY_AND_ASSIGN(Edge); friend class Graph; friend class GraphDelays1; friend class GraphSlewsDelays1; friend class GraphSlewsDelays2; friend class Vertex; friend class VertexInEdgeIterator; friend class VertexOutEdgeIterator; }; // Iterate over all graph vertices. class VertexIterator : public Iterator { public: explicit VertexIterator(Graph *graph); virtual bool hasNext() { return vertex_ || bidir_vertex_; } virtual Vertex *next(); private: DISALLOW_COPY_AND_ASSIGN(VertexIterator); bool findNextPin(); void findNext(); Graph *graph_; Network *network_; Instance *top_inst_; LeafInstanceIterator *inst_iter_; InstancePinIterator *pin_iter_; Vertex *vertex_; Vertex *bidir_vertex_; }; class VertexInEdgeIterator : public VertexEdgeIterator { public: VertexInEdgeIterator(Vertex *vertex, const Graph *graph); VertexInEdgeIterator(VertexIndex vertex_index, const Graph *graph); bool hasNext() { return (next_ != NULL); } Edge *next(); private: DISALLOW_COPY_AND_ASSIGN(VertexInEdgeIterator); Edge *next_; const Graph *graph_; }; class VertexOutEdgeIterator : public VertexEdgeIterator { public: VertexOutEdgeIterator(Vertex *vertex, const Graph *graph); bool hasNext() { return (next_ != NULL); } Edge *next(); private: DISALLOW_COPY_AND_ASSIGN(VertexOutEdgeIterator); Edge *next_; const Graph *graph_; }; // Iterate over the edges through a hierarchical pin. class EdgesThruHierPinIterator : public Iterator { public: EdgesThruHierPinIterator(const Pin *hpin, Network *network, Graph *graph); virtual bool hasNext() { return edge_iter_.hasNext(); } virtual Edge *next() { return edge_iter_.next(); } private: DISALLOW_COPY_AND_ASSIGN(EdgesThruHierPinIterator); EdgeSet edges_; EdgeSet::Iterator edge_iter_; }; } // namespace #endif