| /* Author: Long Yu Wang |
| * Date: August 2013 |
| * |
| * Author: Matthew J.P. Walker |
| * Date: May,June 2014 |
| */ |
| |
| #ifndef INTRA_LOGIC_BLOCK_H |
| #define INTRA_LOGIC_BLOCK_H |
| |
| #ifndef NO_GRAPHICS |
| |
| # include "vpr_types.h" |
| # include "draw_types.h" |
| # include "atom_netlist_fwd.h" |
| # include "route_tree_timing.h" |
| # include <unordered_set> |
| |
| # include "ezgl/point.hpp" |
| |
| # ifndef NO_GRAPHICS |
| # include "ezgl/graphics.hpp" |
| # include "ezgl/application.hpp" |
| # endif /* NO_GRAPHICS */ |
| |
| struct t_selected_sub_block_info { |
| struct clb_pin_tuple { |
| ClusterBlockId clb_index; |
| const t_pb_graph_node* pb_gnode; |
| |
| clb_pin_tuple(ClusterBlockId clb_index, const t_pb_graph_node* pb_gnode); |
| clb_pin_tuple(const AtomPinId atom_pin); |
| bool operator==(const clb_pin_tuple&) const; |
| }; |
| |
| struct gnode_clb_pair { |
| const t_pb_graph_node* pb_gnode = nullptr; |
| const ClusterBlockId clb_index; |
| gnode_clb_pair() = default; |
| gnode_clb_pair(const t_pb_graph_node* pb_gnode, const ClusterBlockId clb_index); |
| bool operator==(const gnode_clb_pair&) const; |
| }; |
| |
| struct sel_subblk_hasher { |
| inline std::size_t operator()(const gnode_clb_pair& v) const { |
| std::hash<const void*> ptr_hasher; |
| return ptr_hasher((const void*)v.pb_gnode) ^ ptr_hasher((const void*)&v.clb_index); |
| } |
| |
| inline std::size_t operator()(const std::pair<clb_pin_tuple, clb_pin_tuple>& v) const { |
| return (*this)(v.first) ^ (*this)(v.second); |
| } |
| |
| inline std::size_t operator()(const clb_pin_tuple& v) const { |
| std::hash<int> int_hasher; |
| std::hash<const void*> ptr_hasher; |
| return int_hasher(size_t(v.clb_index)) |
| ^ ptr_hasher((const void*)v.pb_gnode); |
| } |
| }; |
| |
| private: |
| t_pb* selected_pb; |
| ClusterBlockId containing_block_index; |
| t_pb_graph_node* selected_pb_gnode; |
| std::unordered_set<gnode_clb_pair, sel_subblk_hasher> sinks; |
| std::unordered_set<gnode_clb_pair, sel_subblk_hasher> sources; |
| std::unordered_set<gnode_clb_pair, sel_subblk_hasher> in_selected_subtree; |
| |
| public: |
| t_selected_sub_block_info(); |
| |
| void set(t_pb* new_selected_sub_block, const ClusterBlockId containing_block_index); |
| t_pb_graph_node* get_selected_pb_gnode() const; |
| ClusterBlockId get_containing_block() const; |
| |
| /* |
| * gets the t_pb that is currently selected. Please don't use this if |
| * you think you can get away with using is_selected(...) or get_selected_pb_gnode() and |
| * get_containing_block(). May disappear in future. |
| */ |
| t_pb* get_selected_pb() const; |
| |
| bool has_selection() const; |
| void clear(); |
| // pb related selection test functions |
| bool is_selected(const t_pb_graph_node* test, const ClusterBlockId clb_index) const; |
| bool is_sink_of_selected(const t_pb_graph_node* test, const ClusterBlockId clb_index) const; |
| bool is_source_of_selected(const t_pb_graph_node* test, const ClusterBlockId clb_index) const; |
| bool is_in_selected_subtree(const t_pb_graph_node* test, const ClusterBlockId clb_index) const; |
| }; |
| |
| /* Enable/disable clb internals drawing. Internals drawing is enabled with a click of the |
| * "Blk Internal" button. With each consecutive click of the button, a lower level in the |
| * pb_graph will be shown for every clb. When the number of clicks on the button exceeds |
| * the maximum level of sub-blocks that exists in the pb_graph, internals drawing |
| * will be disabled. |
| */ |
| # ifndef NO_GRAPHICS |
| void toggle_blk_internal(GtkWidget* /*widget*/, gint /*response_id*/, gpointer data); |
| |
| # endif /* NO_GRAPHICS */ |
| /* This function pre-allocates space to store bounding boxes for all sub-blocks. Each |
| * sub-block is identified by its descriptor_type and a unique pin ID in the type. |
| */ |
| void draw_internal_alloc_blk(); |
| |
| /* This function initializes bounding box values for all sub-blocks. It calls helper functions |
| * to traverse through the pb_graph for each descriptor_type and compute bounding box values. |
| */ |
| void draw_internal_init_blk(); |
| |
| /* Top-level drawing routine for internal sub-blocks. The function traverses through all |
| * grid tiles and calls helper function to draw inside each block. |
| */ |
| # ifndef NO_GRAPHICS |
| void draw_internal_draw_subblk(ezgl::renderer* g); |
| # endif /* NO_GRAPHICS */ |
| |
| /* Determines which part of a block to highlight, and stores it, |
| * so that the other subblock drawing functions will obey it. |
| * If the user missed all sub-parts, will return 1, else 0. |
| */ |
| int highlight_sub_block(const ezgl::point2d& point_in_clb, const ClusterBlockId clb_index, t_pb* pb); |
| |
| /* |
| * returns the struct with information about the sub-block selection |
| */ |
| t_selected_sub_block_info& get_selected_sub_block_info(); |
| |
| /* |
| * Draws lines from the proper logical sources, to the proper logical sinks. |
| * If the draw state says to show all logical connections, it will, |
| * and if there is a selected sub-block, it will highlight it's conections |
| */ |
| |
| void draw_logical_connections(ezgl::renderer* g); |
| |
| void find_pin_index_at_model_scope(const AtomPinId the_pin, const AtomBlockId lblk, int* pin_index, int* total_pins); |
| |
| #endif /* NO_GRAPHICS */ |
| |
| #endif /* INTRA_LOGIC_BLOCK_H */ |