From 6bde7a5522cc9d58aafe3aed09a8dc9aa88a0d67 Mon Sep 17 00:00:00 2001 From: SebastianLievano Date: Wed, 20 Jul 2022 10:20:40 -0400 Subject: [PATCH 1/8] Added auto-complete functionality/changed layout --- vpr/main.ui | 308 +++++++++++++++++++----------------- vpr/src/draw/draw.cpp | 19 ++- vpr/src/draw/search_bar.cpp | 245 +++++++++++++++++++++------- vpr/src/draw/search_bar.h | 22 ++- vpr/src/draw/ui_setup.cpp | 52 ++++++ 5 files changed, 435 insertions(+), 211 deletions(-) diff --git a/vpr/main.ui b/vpr/main.ui index 4bb2986dc23..0d68be28b7d 100644 --- a/vpr/main.ui +++ b/vpr/main.ui @@ -13,16 +13,6 @@ - - BlockNames - 0 - - - - 0 - - - False @@ -148,6 +138,16 @@ + + 5 + 0 + + + + 0 + + + test False @@ -239,6 +239,12 @@ + + + + + + False @@ -535,59 +541,6 @@ - - False - - - True - False - - - SearchType - True - False - 0 - - Block ID - Block Name - Net ID - Net Name - RR Node ID - - - - 0 - 0 - - - - - True - True - search - gtk-find - Search... - - - 1 - 0 - - - - - Search - True - True - True - - - 2 - 0 - - - - - True False @@ -601,52 +554,42 @@ True False - - - True - False - True - True - - - 0 - 1 - 4 - 3 - - + True True False + end - - Window + + Zoom Fit True True True 0 - 1 + 0 - - Zoom Fit + + Window True True True + start 0 - 0 + 1 4 - 1 + 0 + 2 @@ -657,7 +600,7 @@ 0 - 4 + 5 4 @@ -671,108 +614,160 @@ 4 - 4 + 5 - + True - True - False - True - SearchPopover - - - True - False - center - gtk-find - - + False + True + True 0 - 0 + 2 + 4 + 3 - + + SearchType True - True - False - True - BlockPopover - - - True - False - Block Settings - - + False + 0 + + Block ID + Block Name + Net ID + Net Name + RR Node ID + - 1 + 0 0 - + + Search True True - False True - NetPopover - - - True - False - Net Settings - - - 2 + 3 0 - + True True - False - True - RoutingPopover - - - True - False - Routing Options - - + search + True + gtk-find + Search... + Completion - 3 + 1 0 + 2 - + True - True - False - True - MiscPopover + False + True + + + True + True + False + True + BlockPopover + + + True + False + Block Settings + + + + + 0 + 0 + + - + True - False - Misc. + True + False + True + NetPopover + + + True + False + Net Settings + + + + 1 + 0 + + + + + True + True + False + True + RoutingPopover + + + True + False + Routing Options + + + + + 2 + 0 + + + + + True + True + False + True + MiscPopover + + + True + False + Misc. + + + + + 3 + 0 + - 4 - 0 + 0 + 1 + 4 @@ -781,6 +776,27 @@ + + + + + + + + False + + + True + False + + + + + + + + + diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp index daff060d12b..2437a9503f0 100644 --- a/vpr/src/draw/draw.cpp +++ b/vpr/src/draw/draw.cpp @@ -282,6 +282,7 @@ static void default_setup(ezgl::application* app) { basic_button_setup(app); net_button_setup(app); block_button_setup(app); + search_setup(app); } /* function below intializes the interface window with a set of buttons and links @@ -675,12 +676,26 @@ bool draw_if_net_highlighted(ClusterNetId inet) { } # if defined(X11) && !defined(__MINGW32__) -void act_on_key_press(ezgl::application* /*app*/, GdkEventKey* /*event*/, char* key_name) { +void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_name) { //VTR_LOG("Key press %c (%d)\n", key_pressed, keysym); std::string key(key_name); + std::cout << "Pressed key" << std::endl; + if(gtk_widget_is_focus(GTK_WIDGET(app->get_object("TextInput")))){ + if(key == "Return"){ + enable_autocomplete(app); + } + } } # else -void act_on_key_press(ezgl::application* /*app*/, GdkEventKey* /*event*/, char* /*key_name*/) { +void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_name) { + std::cout << "Pressed key" << std::endl; + std::string key(key_name); + GtkWidget* searchBar = GTK_WIDGET(app->get_object("TextInput")); + if(gtk_widget_is_focus(searchBar)){ + if(key == "Return"){ + enable_autocomplete(app); + } + } } # endif diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp index 02592fc8c1a..b9a080d44bf 100644 --- a/vpr/src/draw/search_bar.cpp +++ b/vpr/src/draw/search_bar.cpp @@ -1,5 +1,4 @@ #ifndef NO_GRAPHICS - # include # include @@ -52,6 +51,7 @@ extern std::string rr_highlight_message; void search_and_highlight(GtkWidget* /*widget*/, ezgl::application* app) { auto& device_ctx = g_vpr_ctx.device(); auto& cluster_ctx = g_vpr_ctx.clustering(); + auto& atom_ctx = g_vpr_ctx.atom(); // get ID from search bar GtkEntry* text_entry = (GtkEntry*)app->get_object("TextInput"); @@ -59,16 +59,7 @@ void search_and_highlight(GtkWidget* /*widget*/, ezgl::application* app) { std::string user_input = text; std::stringstream ss(user_input); - GObject* combo_box = (GObject*)app->get_object("SearchType"); - gchar* type = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo_box)); - //Checking that a type is selected - if (type && type[0] == '\0') { - warning_dialog_box("Please select a search type"); - app->refresh_drawing(); - return; - } - - std::string search_type(type); + auto search_type = get_search_type(app); // reset deselect_all(); @@ -99,14 +90,33 @@ void search_and_highlight(GtkWidget* /*widget*/, ezgl::application* app) { return; } - highlight_blocks((ClusterBlockId)block_id); + highlight_cluster_block((ClusterBlockId)block_id); } else if (search_type == "Block Name") { std::string block_name = ""; ss >> block_name; - highlight_blocks((std::string)block_name); + AtomBlockId atom_blk_id = AtomBlockId::INVALID(); + atom_blk_id = atom_ctx.nlist.find_block(block_name); + //If block is found, the CLB containing it is highlighted + if (atom_blk_id != AtomBlockId::INVALID()) { + ClusterBlockId block_id = atom_ctx.lookup.atom_clb(atom_blk_id); + //Highlighting atom block. IF function returns false, highlighting clb that contains + if (!highlight_atom_block(atom_blk_id, block_id, app)) { + highlight_cluster_block(block_id); + } + return; + } + //Continues if atom block not found (Checking if user searched a clb) + ClusterBlockId block_id = ClusterBlockId::INVALID(); + block_id = cluster_ctx.clb_nlist.find_block(block_name); + + if (block_id == ClusterBlockId::INVALID()) { + warning_dialog_box("Invalid Block Name"); + return; //name not exist + } + highlight_cluster_block(block_id); //found block } else if (search_type == "Net ID") { @@ -126,8 +136,15 @@ void search_and_highlight(GtkWidget* /*widget*/, ezgl::application* app) { else if (search_type == "Net Name") { std::string net_name = ""; ss >> net_name; + AtomNetId atom_net_id = AtomNetId::INVALID(); + atom_net_id = atom_ctx.nlist.find_net(net_name); - highlight_nets((std::string)net_name); + if (atom_net_id == AtomNetId::INVALID()) { + warning_dialog_box("Invalid Net Name"); + return; //name not exist + } + ClusterNetId clb_net_id = atom_ctx.lookup.clb_net(atom_net_id); + highlight_nets(clb_net_id); } else @@ -229,7 +246,12 @@ void auto_zoom_rr_node(int rr_node_id) { (application.get_canvas(application.get_main_canvas_id()))->get_camera().set_world(zoom_view); } -void highlight_blocks(ClusterBlockId clb_index) { +/** + * @brief Highlights the given cluster block + * + * @param clb_index Cluster Index to be highlighted + */ +void highlight_cluster_block(ClusterBlockId clb_index) { char msg[vtr::bufsize]; auto& cluster_ctx = g_vpr_ctx.clustering(); auto& place_ctx = g_vpr_ctx.placement(); @@ -257,45 +279,82 @@ void highlight_blocks(ClusterBlockId clb_index) { application.refresh_drawing(); } -void highlight_nets(ClusterNetId net_id) { - t_trace* tptr; - auto& route_ctx = g_vpr_ctx.routing(); +/** + * @brief Finds and highlights the atom block. Returns true if block shows, false if not + * + * @param atom_blk AtomBlockId being searched for + * @param cl_blk ClusterBlock containing atom_blk + * @param app ezgl:: application used + * @return true | If sub-block can be highlighted + * @return false | If sub-block not found (impossible in search case) or not shown at current zoom lvl + */ +bool highlight_atom_block(AtomBlockId atom_blk, ClusterBlockId cl_blk, ezgl::application* app) { + auto& atom_ctx = g_vpr_ctx.atom(); + auto& cl_ctx = g_vpr_ctx.clustering(); + t_pb* pb = cl_ctx.clb_nlist.block_pb(cl_blk); - t_draw_state* draw_state = get_draw_state_vars(); + //Getting the pb* for the atom block + auto atom_block_pb = find_atom_block_in_pb(atom_ctx.nlist.block_name(atom_blk), pb); + if (!atom_block_pb) return false; //If no block found, returning false - if (int(route_ctx.trace.size()) == 0) return; + //Ensuring that block is drawn at current zoom lvl, returning false if not + auto atom_block_depth = atom_block_pb->pb_graph_node->pb_type->depth; + t_draw_state* draw_state = get_draw_state_vars(); + int max_depth = draw_state->show_blk_internal; + if (atom_block_depth > max_depth) return false; - for (tptr = route_ctx.trace[net_id].head; tptr != nullptr; tptr = tptr->next) { - draw_state->net_color[net_id] = ezgl::MAGENTA; - } + //Highlighting block + get_selected_sub_block_info().set(atom_block_pb, cl_blk); + app->refresh_drawing(); + return true; } -void highlight_nets(std::string net_name) { - auto& cluster_ctx = g_vpr_ctx.clustering(); - - ClusterNetId net_id = ClusterNetId::INVALID(); - net_id = cluster_ctx.clb_nlist.find_net(net_name); - - if (net_id == ClusterNetId::INVALID()) { - warning_dialog_box("Invalid Net Name"); - return; //name not exist +/** + * @brief Recursively looks through pb graph to find block w. given name + * + * @param name name of block being searched for + * @param pb current node to be examined + * @return t_pb* t_pb ptr of block w. name "name" + */ +t_pb* find_atom_block_in_pb(std::string name, t_pb* pb) { + //Checking if block is one being searched for + std::string pbName(pb->name); + if (pbName == name) return pb; + //If block has no children, returning + if (pb->child_pbs == nullptr) return nullptr; + + int num_child_types = pb->get_num_child_types(); + //Iterating through all child types + for (int i = 0; i < num_child_types; ++i) { + if (pb->child_pbs[i] == nullptr) continue; + int num_children_of_type = pb->get_num_children_of_type(i); + //Iterating through all of pb's children of given type + for (int j = 0; j < num_children_of_type; ++j) { + t_pb* child_pb = &pb->child_pbs[i][j]; + //If child exists, recursively calling function on it + if (child_pb->name != nullptr) { + t_pb* subtree_result = find_atom_block_in_pb(name, child_pb); + //If a result is found, returning it to top of recursive calls + if (subtree_result != nullptr) { + return subtree_result; + } + } + } } - - highlight_nets(net_id); //found net + return nullptr; } -void highlight_blocks(std::string block_name) { - auto& cluster_ctx = g_vpr_ctx.clustering(); +void highlight_nets(ClusterNetId net_id) { + t_trace* tptr; + auto& route_ctx = g_vpr_ctx.routing(); - ClusterBlockId block_id = ClusterBlockId::INVALID(); - block_id = cluster_ctx.clb_nlist.find_block(block_name); + t_draw_state* draw_state = get_draw_state_vars(); - if (block_id == ClusterBlockId::INVALID()) { - warning_dialog_box("Invalid Block Name"); - return; //name not exist - } + if (int(route_ctx.trace.size()) == 0) return; - highlight_blocks(block_id); //found block + for (tptr = route_ctx.trace[net_id].head; tptr != nullptr; tptr = tptr->next) { + draw_state->net_color[net_id] = ezgl::MAGENTA; + } } void warning_dialog_box(const char* message) { @@ -339,34 +398,102 @@ void warning_dialog_box(const char* message) { void search_type_changed(GtkComboBox* self, ezgl::application* app) { auto type = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(self)); GtkEntry* searchBar = GTK_ENTRY(app->get_object("TextInput")); + GtkEntryCompletion* completion = GTK_ENTRY_COMPLETION(app->get_object("Completion")); + GtkTreeModel* netNames = GTK_TREE_MODEL(app->get_object("NetNames")); + GtkTreeModel* blockNames = GTK_TREE_MODEL(app->get_object("BlockNames")); //Ensuring a valid type was selected if (!type) return; if (type[0] == '\0') return; std::string searchType(type); - //Setting active completion model to blockCompleter if type selected is block Name + + /* + * If search type is name, connecting search bar to completion, + * and connecting completion to the appropriate model (blocks or nets) + * Additionally, visibility of key length setter is toggled by these changes + */ if (searchType == "Block Name") { - GtkEntryCompletion* blockCompleter = GTK_ENTRY_COMPLETION(app->get_object("BlockNameCompleter")); - gtk_entry_set_completion(searchBar, blockCompleter); - } else { //If not, setting to null + gtk_entry_completion_set_model(completion, blockNames); + } else if (searchType == "Net Name") { + gtk_entry_completion_set_model(completion, netNames); + } else { //setting to null if option does not require auto-complete + gtk_entry_completion_set_model(completion, NULL); gtk_entry_set_completion(searchBar, nullptr); } } /** - * @brief loads block names into gtk list store item used for completion + * @brief A new matching function used for the wildcard search options + * Will be slower * - * @param app ezgl application + * @param completer the GtkEntryCompletion being used + * @param key a normalized and case-folded key representing the text + * @param iter GtkTreeIter pointing at the current entry being compared + * @param user_data null + * @return gboolean */ -void load_block_names(ezgl::application* app) { - auto blockStorage = GTK_LIST_STORE(app->get_object("BlockNames")); - auto& cluster_ctx = g_vpr_ctx.clustering(); - GtkTreeIter iter; - //Getting and storing all block names - for (ClusterBlockId id : cluster_ctx.clb_nlist.blocks()) { - gtk_list_store_append(blockStorage, &iter); - gtk_list_store_set(blockStorage, &iter, - 0, (cluster_ctx.clb_nlist.block_name(id)).c_str(), -1); +gboolean customMatchingFunction( + GtkEntryCompletion* completer, + const gchar* key, + GtkTreeIter* iter, + gpointer /*user data*/ +) { + GtkTreeModel* model = gtk_entry_completion_get_model(completer); + const gchar* text; + gtk_tree_model_get(model, iter, 0, &text, -1); + //Removing case information + g_utf8_casefold(text, -1); + g_utf8_normalize(text, -1, G_NORMALIZE_DEFAULT); + std::string cppText(text); + //If substring not found, returning false; + return (cppText.find(key, 0) != std::string::npos); +} + +void enable_autocomplete(ezgl::application* app){ + std::cout << "enabling autocomplete" << std::endl; + GtkEntryCompletion* completion = GTK_ENTRY_COMPLETION(app->get_object("Completion")); + GtkEntry* searchBar = GTK_ENTRY(app->get_object("TextInput")); + std::string searchType = get_search_type(app); + if(gtk_entry_completion_get_model(completion) == NULL){ + std::cout << "NO MODEL SELECTED" << std::endl; + return; } + gtk_entry_set_completion(searchBar, completion); + gtk_entry_completion_set_minimum_key_length(completion, 1); + gtk_entry_completion_complete(completion); + std::string oldText(gtk_entry_get_text(searchBar)); + if(oldText.length() == 0) return; + + //gtk_entry_set_text(searchBar, ""); + + for(int i = 0; i < oldText.length(); ++i){ + gtk_widget_grab_focus(GTK_WIDGET(searchBar)); + GdkEvent new_event; + new_event.key.type = GDK_KEY_PRESS; + new_event.key.window = gtk_widget_get_parent_window(GTK_WIDGET(searchBar)); + new_event.key.send_event = TRUE; + new_event.key.time = GDK_CURRENT_TIME; + new_event.key.keyval = gdk_unicode_to_keyval((int)oldText[i]); + new_event.key.state = GDK_KEY_PRESS_MASK; + new_event.key.length = 0; + new_event.key.string = 0; + new_event.key.hardware_keycode = 0; + new_event.key.group = 0; + gdk_event_put(&new_event); + } +} + + +std::string get_search_type(ezgl::application* app){ + GObject* combo_box = (GObject*)app->get_object("SearchType"); + gchar* type = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo_box)); + //Checking that a type is selected + if (type && type[0] == '\0') { + warning_dialog_box("Please select a search type"); + app->refresh_drawing(); + return "Failed lol"; + } + std::string searchType(type); + return searchType; } -#endif /* NO_GRAPHICS */ +#endif /* NO_GRAPHICS */ \ No newline at end of file diff --git a/vpr/src/draw/search_bar.h b/vpr/src/draw/search_bar.h index 50588156a71..d10b66b3483 100644 --- a/vpr/src/draw/search_bar.h +++ b/vpr/src/draw/search_bar.h @@ -13,12 +13,17 @@ void search_and_highlight(GtkWidget* /*widget*/, ezgl::application* app); bool highlight_rr_nodes(int hit_node); void auto_zoom_rr_node(int rr_node_id); -void highlight_blocks(ClusterBlockId clb_index); +void highlight_cluster_block(ClusterBlockId clb_index); void highlight_nets(ClusterNetId net_id); void highlight_nets(std::string net_name); -void highlight_blocks(std::string block_name); -void load_block_names(ezgl::application* app); +void highlight_atom_block(AtomBlockId block_id); + +gboolean customMatchingFunction( + GtkEntryCompletion* completer, + const gchar* key, + GtkTreeIter* iter, + gpointer user_data); //Function to manage entry completions when search type is changed void search_type_changed(GtkComboBox* /*self*/, ezgl::application* app); @@ -26,6 +31,15 @@ void search_type_changed(GtkComboBox* /*self*/, ezgl::application* app); /*function below pops up a dialog box with no button, showing the input warning message*/ void warning_dialog_box(const char* message); +void key_length_val_changed(GtkSpinButton* self, ezgl::application* app); + +t_pb* find_atom_block_in_pb(std::string name, t_pb* pb); + +bool highlight_atom_block(AtomBlockId atom_blk, ClusterBlockId cl_blk, ezgl::application* app); + +void enable_autocomplete(ezgl::application* app); + +std::string get_search_type(ezgl::application* app); #endif /* NO_GRAPHICS */ -#endif /* SEARCH_BAR_H */ +#endif /* SEARCH_BAR_H */ \ No newline at end of file diff --git a/vpr/src/draw/ui_setup.cpp b/vpr/src/draw/ui_setup.cpp index d12bbacaeeb..6b7f7425ec9 100644 --- a/vpr/src/draw/ui_setup.cpp +++ b/vpr/src/draw/ui_setup.cpp @@ -138,6 +138,19 @@ void routing_button_setup(ezgl::application* app) { g_signal_connect(toggle_router_util, "changed", G_CALLBACK(toggle_router_util_cbk), app); } +/** + * @brief Loads required data for search autocomplete, sets up special completion fn + * + * @param app ezgl app + */ +void search_setup(ezgl::application* app){ + load_block_names(app); + load_net_names(app); + //Setting custom matching function for entry completion (searches whole string instead of start) + GtkEntryCompletion* wildcardComp = GTK_ENTRY_COMPLETION(app->get_object("Completion")); + gtk_entry_completion_set_match_func(wildcardComp, (GtkEntryCompletionMatchFunc)customMatchingFunction, NULL, NULL); +} + /** * @brief connects critical path button to its cbk fn * @@ -169,4 +182,43 @@ void hide_widget(std::string widgetName, ezgl::application* app) { gtk_widget_hide(widget); } +/** + * @brief loads block names into gtk list store item used for completion + * + * @param app ezgl application used for ui + */ +void load_block_names(ezgl::application* app) { + auto blockStorage = GTK_LIST_STORE(app->get_object("BlockNames")); + auto& cluster_ctx = g_vpr_ctx.clustering(); + auto& atom_ctx = g_vpr_ctx.atom(); + GtkTreeIter iter; + for (ClusterBlockId id : cluster_ctx.clb_nlist.blocks()) { + gtk_list_store_append(blockStorage, &iter); + gtk_list_store_set(blockStorage, &iter, + 0, (cluster_ctx.clb_nlist.block_name(id)).c_str(), -1); + } + for (AtomBlockId id : atom_ctx.nlist.blocks()) { + gtk_list_store_append(blockStorage, &iter); + gtk_list_store_set(blockStorage, &iter, + 0, (atom_ctx.nlist.block_name(id)).c_str(), -1); + } +} + +/** + * @brief loads net names into gtk list store item used for completion + * + * @param app ezgl application used for ui + */ +void load_net_names(ezgl::application* app) { + auto netStorage = GTK_LIST_STORE(app->get_object("NetNames")); + auto& atom_ctx = g_vpr_ctx.atom(); + GtkTreeIter iter; + //Loading net names + for (AtomNetId id : atom_ctx.nlist.nets()) { + gtk_list_store_append(netStorage, &iter); + gtk_list_store_set(netStorage, &iter, + 0, (atom_ctx.nlist.net_name(id)).c_str(), -1); + } +} + #endif /* NO_GRAPHICS */ From a513d467669302799978ca321efe8995e406a369 Mon Sep 17 00:00:00 2001 From: SebastianLievano Date: Wed, 20 Jul 2022 13:06:27 -0400 Subject: [PATCH 2/8] Changed auto-complete method to one fake event --- vpr/main.ui | 19 +++++++++++++++++++ vpr/src/draw/draw.cpp | 2 ++ vpr/src/draw/search_bar.cpp | 20 ++++++++++++-------- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/vpr/main.ui b/vpr/main.ui index 0d68be28b7d..777f1ceecc9 100644 --- a/vpr/main.ui +++ b/vpr/main.ui @@ -610,6 +610,7 @@ True True True + end right @@ -797,6 +798,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp index 2437a9503f0..14ce99c5bee 100644 --- a/vpr/src/draw/draw.cpp +++ b/vpr/src/draw/draw.cpp @@ -693,7 +693,9 @@ void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_ GtkWidget* searchBar = GTK_WIDGET(app->get_object("TextInput")); if(gtk_widget_is_focus(searchBar)){ if(key == "Return"){ + std::string oldText(gtk_entry_get_text(GTK_ENTRY(searchBar))); enable_autocomplete(app); + gtk_editable_set_position(GTK_EDITABLE(searchBar), oldText.length()); } } } diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp index b9a080d44bf..7dad14ed871 100644 --- a/vpr/src/draw/search_bar.cpp +++ b/vpr/src/draw/search_bar.cpp @@ -457,29 +457,33 @@ void enable_autocomplete(ezgl::application* app){ std::cout << "NO MODEL SELECTED" << std::endl; return; } + std::string oldText(gtk_entry_get_text(searchBar)); gtk_entry_set_completion(searchBar, completion); - gtk_entry_completion_set_minimum_key_length(completion, 1); + gtk_entry_completion_set_minimum_key_length(completion, std::max(0, (int)(oldText.length()-1))); gtk_entry_completion_complete(completion); - std::string oldText(gtk_entry_get_text(searchBar)); + if(oldText.length() == 0) return; - //gtk_entry_set_text(searchBar, ""); - - for(int i = 0; i < oldText.length(); ++i){ - gtk_widget_grab_focus(GTK_WIDGET(searchBar)); + + std::cout << "Added text" << std::endl; + gtk_widget_grab_focus(GTK_WIDGET(searchBar)); + std::string newText = (oldText.length() > 1)? oldText.substr(0, oldText.length()-1) : ""; + gtk_entry_set_text(searchBar, newText.c_str()); + // for(int i = 0; i < oldText.length(); ++i){ + GdkEvent new_event; new_event.key.type = GDK_KEY_PRESS; new_event.key.window = gtk_widget_get_parent_window(GTK_WIDGET(searchBar)); new_event.key.send_event = TRUE; new_event.key.time = GDK_CURRENT_TIME; - new_event.key.keyval = gdk_unicode_to_keyval((int)oldText[i]); + new_event.key.keyval = gdk_unicode_to_keyval((int)oldText[oldText.length()-1]); new_event.key.state = GDK_KEY_PRESS_MASK; new_event.key.length = 0; new_event.key.string = 0; new_event.key.hardware_keycode = 0; new_event.key.group = 0; gdk_event_put(&new_event); - } + //} } From eb7ba2b21526817c33209634d685b2d2a5fec1a2 Mon Sep 17 00:00:00 2001 From: SebastianLievano Date: Wed, 20 Jul 2022 13:06:50 -0400 Subject: [PATCH 3/8] Added new function defs --- vpr/src/draw/ui_setup.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vpr/src/draw/ui_setup.h b/vpr/src/draw/ui_setup.h index d37e816851c..69b8115e4f8 100644 --- a/vpr/src/draw/ui_setup.h +++ b/vpr/src/draw/ui_setup.h @@ -18,10 +18,13 @@ void basic_button_setup(ezgl::application* app); void net_button_setup(ezgl::application* app); void block_button_setup(ezgl::application* app); +void search_setup(ezgl::application* app); void routing_button_setup(ezgl::application* app); void crit_path_button_setup(ezgl::application* app); void hide_crit_path_button(ezgl::application* app); +void load_block_names(ezgl::application* app); +void load_net_names(ezgl::application* app); void hide_widget(std::string widgetName, ezgl::application* app); void show_widget(std::string widgetName, ezgl::application* app); From 89ddeaf533332329eee0d3ac739f10f9c7b4aa20 Mon Sep 17 00:00:00 2001 From: SebastianLievano Date: Wed, 20 Jul 2022 19:56:02 -0400 Subject: [PATCH 4/8] Finalized code, added NoC button --- vpr/main.ui | 33 ++++++- vpr/src/draw/buttons.cpp | 36 -------- vpr/src/draw/buttons.h | 2 - vpr/src/draw/draw.cpp | 10 +-- vpr/src/draw/draw_toggle_functions.cpp | 16 ++-- vpr/src/draw/draw_toggle_functions.h | 5 +- vpr/src/draw/search_bar.cpp | 116 ++++++++++++++++++------- 7 files changed, 131 insertions(+), 87 deletions(-) diff --git a/vpr/main.ui b/vpr/main.ui index 777f1ceecc9..d6b4b31e079 100644 --- a/vpr/main.ui +++ b/vpr/main.ui @@ -103,6 +103,35 @@ 5 + + + True + False + Toggle NoC Display + + + False + True + 6 + + + + + True + False + 0 + + None + NoC Links + NoC Link Usage + + + + False + True + 7 + + Block Outline @@ -116,7 +145,7 @@ False True - 6 + 8 @@ -132,7 +161,7 @@ False True - 7 + 9 diff --git a/vpr/src/draw/buttons.cpp b/vpr/src/draw/buttons.cpp index 6fc4beb6e14..ae48bdbc7b9 100644 --- a/vpr/src/draw/buttons.cpp +++ b/vpr/src/draw/buttons.cpp @@ -28,42 +28,6 @@ gint label_left_start_col = 0; gint box_left_start_col = 0; gint button_row = 2; // 2 is the row num of the window button in main.ui, add buttons starting from this row -void button_for_displaying_noc() { - GObject* main_window = application.get_object(application.get_main_window_id().c_str()); - GObject* main_window_grid = application.get_object("InnerGrid"); - t_draw_state* draw_state = get_draw_state_vars(); - - // if the user did not turn on the "noc" option then we don't give the option to display the noc to the user - if (!draw_state->show_noc_button) { - return; - } - - // if we are here then the user turned the "noc" option on, so create a button to allow the user to display the noc - - //combo box for toggle_noc_display - GtkWidget* toggle_noc_display_widget = gtk_combo_box_text_new(); - GtkWidget* toggle_noc_display_label = gtk_label_new("Toggle NoC Display:"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(toggle_noc_display_widget), "None"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(toggle_noc_display_widget), "NoC Links"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(toggle_noc_display_widget), "NoC Link Usage"); - - gtk_combo_box_set_active((GtkComboBox*)toggle_noc_display_widget, 0); // default set to None which has an index 0 - gtk_widget_set_name(toggle_noc_display_widget, "toggle_noc_display"); - - //attach to the grid - gtk_grid_attach((GtkGrid*)main_window_grid, toggle_noc_display_label, label_left_start_col, button_row++, box_width, box_height); - gtk_grid_attach((GtkGrid*)main_window_grid, toggle_noc_display_widget, box_left_start_col, button_row++, box_width, box_height); - - // show the newy added check box - gtk_widget_show_all((GtkWidget*)main_window); - - //connect signals - g_signal_connect_swapped(GTK_COMBO_BOX_TEXT(toggle_noc_display_widget), - "changed", - G_CALLBACK(toggle_noc_display), - toggle_noc_display_widget); -} - void delete_button(const char* button_name) { GObject* main_window_grid = application.get_object("InnerGrid"); GList* list_of_widgets = gtk_container_get_children(GTK_CONTAINER(main_window_grid)); diff --git a/vpr/src/draw/buttons.h b/vpr/src/draw/buttons.h index 5dcba6f11fc..853ad4cb50b 100644 --- a/vpr/src/draw/buttons.h +++ b/vpr/src/draw/buttons.h @@ -9,8 +9,6 @@ # include "ezgl/application.hpp" # include "ezgl/graphics.hpp" -void button_for_displaying_noc(); - void delete_button(const char* button_name); GtkWidget* find_button(const char* button_name); #endif /* NO_GRAPHICS */ diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp index 14ce99c5bee..c6ea9c876a4 100644 --- a/vpr/src/draw/draw.cpp +++ b/vpr/src/draw/draw.cpp @@ -302,7 +302,6 @@ static void initial_setup_NO_PICTURE_to_PLACEMENT(ezgl::application* app, //Hiding unused functionality hide_widget("RoutingMenuButton", app); hide_crit_path_button(app); - button_for_displaying_noc(); } /* function below intializes the interface window with a set of buttons and links @@ -357,7 +356,6 @@ static void initial_setup_NO_PICTURE_to_ROUTING(ezgl::application* app, default_setup(app); routing_button_setup(app); hide_crit_path_button(app); - button_for_displaying_noc(); } /* function below intializes the interface window with a set of buttons and links @@ -680,8 +678,8 @@ void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_ //VTR_LOG("Key press %c (%d)\n", key_pressed, keysym); std::string key(key_name); std::cout << "Pressed key" << std::endl; - if(gtk_widget_is_focus(GTK_WIDGET(app->get_object("TextInput")))){ - if(key == "Return"){ + if (gtk_widget_is_focus(GTK_WIDGET(app->get_object("TextInput")))) { + if (key == "Return") { enable_autocomplete(app); } } @@ -691,8 +689,8 @@ void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_ std::cout << "Pressed key" << std::endl; std::string key(key_name); GtkWidget* searchBar = GTK_WIDGET(app->get_object("TextInput")); - if(gtk_widget_is_focus(searchBar)){ - if(key == "Return"){ + if (gtk_widget_is_focus(searchBar)) { + if (key == "Return") { std::string oldText(gtk_entry_get_text(GTK_ENTRY(searchBar))); enable_autocomplete(app); gtk_editable_set_position(GTK_EDITABLE(searchBar), oldText.length()); diff --git a/vpr/src/draw/draw_toggle_functions.cpp b/vpr/src/draw/draw_toggle_functions.cpp index eb06fb0f000..a8f6f4bf189 100644 --- a/vpr/src/draw/draw_toggle_functions.cpp +++ b/vpr/src/draw/draw_toggle_functions.cpp @@ -406,15 +406,19 @@ void toggle_expansion_cost_cbk(GtkComboBoxText* self, ezgl::application* app) { app->refresh_drawing(); } -void toggle_noc_display(GtkWidget* /*widget*/, gint /*response_id*/, gpointer /*data*/) { +/** + * @brief cbk fn to toggle Network-On-Chip (Noc) visibility + * alters draw_state->draw_noc to reflect new state + * + * @param self ptr to combo box + * @param app ezgl application + */ +void toggle_noc_cbk(GtkComboBoxText* self, ezgl::application* app) { /* this is the callback function for runtime created toggle_noc_display button * which is written in button.cpp */ t_draw_state* draw_state = get_draw_state_vars(); - std::string button_name = "toggle_noc_display"; - auto toggle_crit_path = find_button(button_name.c_str()); - gchar* combo_box_content = gtk_combo_box_text_get_active_text( - GTK_COMBO_BOX_TEXT(toggle_crit_path)); + gchar* combo_box_content = gtk_combo_box_text_get_active_text(self); if (strcmp(combo_box_content, "None") == 0) { draw_state->draw_noc = DRAW_NO_NOC; } else if (strcmp(combo_box_content, "NoC Links") == 0) @@ -423,7 +427,7 @@ void toggle_noc_display(GtkWidget* /*widget*/, gint /*response_id*/, gpointer /* draw_state->draw_noc = DRAW_NOC_LINK_USAGE; g_free(combo_box_content); - application.refresh_drawing(); + app->refresh_drawing(); } /** diff --git a/vpr/src/draw/draw_toggle_functions.h b/vpr/src/draw/draw_toggle_functions.h index c0c433843f7..7461e309cf2 100644 --- a/vpr/src/draw/draw_toggle_functions.h +++ b/vpr/src/draw/draw_toggle_functions.h @@ -107,11 +107,10 @@ void toggle_crit_path_cbk(GtkComboBoxText* self, ezgl::application* app); * Draws different router expansion costs based on user input. Changes value of draw_state->show_router_expansion_cost. */ void toggle_expansion_cost_cbk(GtkComboBoxText* self, ezgl::application* app); -/* Callback function for runtime created toggle_noc_display - * in button.cpp. +/* Callback function for main.ui created ToggleNocBox in ui_setup.cpp * Controls if the NoC on chip should be visualized and whether the link usage * in the NoC should be visualized. Changes value of draw_state->draw_noc */ -void toggle_noc_display(GtkWidget* widget, gint /*response_id*/, gpointer /*data*/); +void toggle_noc_cbk(GtkComboBoxText* self, ezgl::application* app); /* Callback function for main.ui created netMaxFanout widget in button.cpp. * Sets draw_state->draw_net_max_fanout to its corresponding value in the UI. */ diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp index 7dad14ed871..2a52d74a646 100644 --- a/vpr/src/draw/search_bar.cpp +++ b/vpr/src/draw/search_bar.cpp @@ -1,3 +1,18 @@ +/** + * @file search_bar.cpp + * @author Sebastian Lievano + * @brief Contains search/auto-complete related functions + * @version 0.1 + * @date 2022-07-20 + * + * This file essentially follows the whole search process, from searching, finding the match, + * and finally highlighting the searched for item. Additionally, auto-complete related stuff is found + * here. + * + * @copyright Copyright (c) 2022 + * + */ + #ifndef NO_GRAPHICS # include # include @@ -94,20 +109,25 @@ void search_and_highlight(GtkWidget* /*widget*/, ezgl::application* app) { } else if (search_type == "Block Name") { + /* If the block exists in atom netlist, proceeding with highlighting process. + * if highlight atom block fn returns false, that means that the block can't be highlighted + * We've already confirmed the block exists in the netlist, so that means that at this zoom lvl, + * the subblock is not shown. Therefore highlight the clb mapping. + * + * If the block does not exist in the atom netlist, we will check the CLB netlist to see if + * they searched for a cluster block*/ std::string block_name = ""; ss >> block_name; - AtomBlockId atom_blk_id = AtomBlockId::INVALID(); - atom_blk_id = atom_ctx.nlist.find_block(block_name); - //If block is found, the CLB containing it is highlighted + AtomBlockId atom_blk_id = atom_ctx.nlist.find_block(block_name); if (atom_blk_id != AtomBlockId::INVALID()) { ClusterBlockId block_id = atom_ctx.lookup.atom_clb(atom_blk_id); - //Highlighting atom block. IF function returns false, highlighting clb that contains if (!highlight_atom_block(atom_blk_id, block_id, app)) { highlight_cluster_block(block_id); } return; } + //Continues if atom block not found (Checking if user searched a clb) ClusterBlockId block_id = ClusterBlockId::INVALID(); block_id = cluster_ctx.clb_nlist.find_block(block_name); @@ -134,10 +154,11 @@ void search_and_highlight(GtkWidget* /*widget*/, ezgl::application* app) { } else if (search_type == "Net Name") { + //in this case, all nets (clb and non-clb) are contained in the atom netlist + //So we only need to search this one std::string net_name = ""; ss >> net_name; - AtomNetId atom_net_id = AtomNetId::INVALID(); - atom_net_id = atom_ctx.nlist.find_net(net_name); + AtomNetId atom_net_id = atom_ctx.nlist.find_net(net_name); if (atom_net_id == AtomNetId::INVALID()) { warning_dialog_box("Invalid Net Name"); @@ -314,7 +335,7 @@ bool highlight_atom_block(AtomBlockId atom_blk, ClusterBlockId cl_blk, ezgl::app * * @param name name of block being searched for * @param pb current node to be examined - * @return t_pb* t_pb ptr of block w. name "name" + * @return t_pb* t_pb ptr of block w. name "name". Returns nullptr if nothing found */ t_pb* find_atom_block_in_pb(std::string name, t_pb* pb) { //Checking if block is one being searched for @@ -350,6 +371,7 @@ void highlight_nets(ClusterNetId net_id) { t_draw_state* draw_state = get_draw_state_vars(); + //If routing does not exist return if (int(route_ctx.trace.size()) == 0) return; for (tptr = route_ctx.trace[net_id].head; tptr != nullptr; tptr = tptr->next) { @@ -422,8 +444,8 @@ void search_type_changed(GtkComboBox* self, ezgl::application* app) { } /** - * @brief A new matching function used for the wildcard search options - * Will be slower + * @brief A non-default matching function. As opposed to simply searching for a prefix(default), + * searches string for presence of a substring. Ignores cases. * * @param completer the GtkEntryCompletion being used * @param key a normalized and case-folded key representing the text @@ -448,46 +470,76 @@ gboolean customMatchingFunction( return (cppText.find(key, 0) != std::string::npos); } -void enable_autocomplete(ezgl::application* app){ +/** + * @brief Creates a GdkEvent that simulates user pressing key "key" + * + * @param key character value + * @param window GdkWindow + * @return GdkEvent Keypress event + */ +GdkEvent simulate_keypress(char key, GdkWindow* window) { + int charVal = (int)key; + //Creating event and adding properties + GdkEvent new_event; + new_event.key.type = GDK_KEY_PRESS; + new_event.key.window = window; + new_event.key.send_event = TRUE; + new_event.key.time = GDK_CURRENT_TIME; + new_event.key.keyval = gdk_unicode_to_keyval(charVal); + new_event.key.state = GDK_KEY_PRESS_MASK; + new_event.key.length = 0; + new_event.key.string = 0; + new_event.key.hardware_keycode = 0; + new_event.key.group = 0; + return new_event; +} + +/** + * @brief Turns on autocomplete + * + * This function enables the auto-complete fuctionality for the search bar. + * Normally, this is pretty simple, but the idea is to have auto-complete appear as soon + * as the user hits the "Enter" key. To accomplish this, a fake Gdk event is created + * to simulate the user hitting a key. + * + * @param app ezgl app + */ +void enable_autocomplete(ezgl::application* app) { std::cout << "enabling autocomplete" << std::endl; GtkEntryCompletion* completion = GTK_ENTRY_COMPLETION(app->get_object("Completion")); GtkEntry* searchBar = GTK_ENTRY(app->get_object("TextInput")); + std::string searchType = get_search_type(app); - if(gtk_entry_completion_get_model(completion) == NULL){ + //Checking to make sure that we are on a mode that uses auto-complete + if (gtk_entry_completion_get_model(completion) == NULL) { std::cout << "NO MODEL SELECTED" << std::endl; return; } + + //Getting input text std::string oldText(gtk_entry_get_text(searchBar)); + + //Turning on completion gtk_entry_set_completion(searchBar, completion); - gtk_entry_completion_set_minimum_key_length(completion, std::max(0, (int)(oldText.length()-1))); gtk_entry_completion_complete(completion); - if(oldText.length() == 0) return; + //Setting min key length to either 0 or 1 less than key length (max option) + gtk_entry_completion_set_minimum_key_length(completion, std::max(0, (int)(oldText.length() - 1))); + //If string len is 0, reutrning + if (oldText.length() == 0) return; - std::cout << "Added text" << std::endl; gtk_widget_grab_focus(GTK_WIDGET(searchBar)); - std::string newText = (oldText.length() > 1)? oldText.substr(0, oldText.length()-1) : ""; + std::string newText = (oldText.length() > 1) ? oldText.substr(0, oldText.length() - 1) : ""; gtk_entry_set_text(searchBar, newText.c_str()); - // for(int i = 0; i < oldText.length(); ++i){ - - GdkEvent new_event; - new_event.key.type = GDK_KEY_PRESS; - new_event.key.window = gtk_widget_get_parent_window(GTK_WIDGET(searchBar)); - new_event.key.send_event = TRUE; - new_event.key.time = GDK_CURRENT_TIME; - new_event.key.keyval = gdk_unicode_to_keyval((int)oldText[oldText.length()-1]); - new_event.key.state = GDK_KEY_PRESS_MASK; - new_event.key.length = 0; - new_event.key.string = 0; - new_event.key.hardware_keycode = 0; - new_event.key.group = 0; - gdk_event_put(&new_event); - //} -} + //Creating a false event to insert the last character into the string + auto window = gtk_widget_get_parent_window(GTK_WIDGET(searchBar)); + GdkEvent new_event = simulate_keypress(oldText.back(), window); + gdk_event_put(&new_event); +} -std::string get_search_type(ezgl::application* app){ +std::string get_search_type(ezgl::application* app) { GObject* combo_box = (GObject*)app->get_object("SearchType"); gchar* type = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo_box)); //Checking that a type is selected From d39bc212c2b01e992e77feb50bb1570734a81927 Mon Sep 17 00:00:00 2001 From: SebastianLievano Date: Thu, 21 Jul 2022 01:06:22 -0400 Subject: [PATCH 5/8] Removed extra cout's --- vpr/src/draw/draw.cpp | 2 -- vpr/src/draw/search_bar.cpp | 1 - vpr/src/draw/ui_setup.cpp | 13 +++++++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp index c6ea9c876a4..566c94262c2 100644 --- a/vpr/src/draw/draw.cpp +++ b/vpr/src/draw/draw.cpp @@ -677,7 +677,6 @@ bool draw_if_net_highlighted(ClusterNetId inet) { void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_name) { //VTR_LOG("Key press %c (%d)\n", key_pressed, keysym); std::string key(key_name); - std::cout << "Pressed key" << std::endl; if (gtk_widget_is_focus(GTK_WIDGET(app->get_object("TextInput")))) { if (key == "Return") { enable_autocomplete(app); @@ -686,7 +685,6 @@ void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_ } # else void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_name) { - std::cout << "Pressed key" << std::endl; std::string key(key_name); GtkWidget* searchBar = GTK_WIDGET(app->get_object("TextInput")); if (gtk_widget_is_focus(searchBar)) { diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp index 2a52d74a646..038b46baaf4 100644 --- a/vpr/src/draw/search_bar.cpp +++ b/vpr/src/draw/search_bar.cpp @@ -505,7 +505,6 @@ GdkEvent simulate_keypress(char key, GdkWindow* window) { * @param app ezgl app */ void enable_autocomplete(ezgl::application* app) { - std::cout << "enabling autocomplete" << std::endl; GtkEntryCompletion* completion = GTK_ENTRY_COMPLETION(app->get_object("Completion")); GtkEntry* searchBar = GTK_ENTRY(app->get_object("TextInput")); diff --git a/vpr/src/draw/ui_setup.cpp b/vpr/src/draw/ui_setup.cpp index 6b7f7425ec9..97511de9958 100644 --- a/vpr/src/draw/ui_setup.cpp +++ b/vpr/src/draw/ui_setup.cpp @@ -80,7 +80,7 @@ void net_button_setup(ezgl::application* app) { * @brief sets up block related buttons, connects their signals * * Connects signals and sets init. values for blk internals spin button, - * blk pin util combo box, and placement macros combo box created in + * blk pin util combo box,placement macros combo box, and noc combo bx created in * main.ui. Found in Block Settings dropdown * @param app */ @@ -100,6 +100,15 @@ void block_button_setup(ezgl::application* app) { //Toggle Placement Macros GtkComboBoxText* placement_macros = GTK_COMBO_BOX_TEXT(app->get_object("TogglePlacementMacros")); g_signal_connect(placement_macros, "changed", G_CALLBACK(placement_macros_cbk), app); + + //Toggle NoC Display (based on startup cmd --noc on) + if (!draw_state->show_noc_button) { + hide_widget("NocLabel", app); + hide_widget("ToggleNocBox", app); + } else { + GtkComboBoxText* toggleNocBox = GTK_COMBO_BOX_TEXT(app->get_object("ToggleNocBox")); + g_signal_connect(toggleNocBox, "changed", G_CALLBACK(toggle_noc_cbk), app); + } } /** @@ -143,7 +152,7 @@ void routing_button_setup(ezgl::application* app) { * * @param app ezgl app */ -void search_setup(ezgl::application* app){ +void search_setup(ezgl::application* app) { load_block_names(app); load_net_names(app); //Setting custom matching function for entry completion (searches whole string instead of start) From d987df500707e2956802e51d095a38edf79c5703 Mon Sep 17 00:00:00 2001 From: SebastianLievano Date: Thu, 21 Jul 2022 14:46:33 -0400 Subject: [PATCH 6/8] Added missing function declaration/comments --- vpr/src/draw/search_bar.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vpr/src/draw/search_bar.h b/vpr/src/draw/search_bar.h index d10b66b3483..1854ee79f11 100644 --- a/vpr/src/draw/search_bar.h +++ b/vpr/src/draw/search_bar.h @@ -31,14 +31,19 @@ void search_type_changed(GtkComboBox* /*self*/, ezgl::application* app); /*function below pops up a dialog box with no button, showing the input warning message*/ void warning_dialog_box(const char* message); -void key_length_val_changed(GtkSpinButton* self, ezgl::application* app); - +//Returns pb ptr of given atom block name t_pb* find_atom_block_in_pb(std::string name, t_pb* pb); +//Highlights atom block in cluster block bool highlight_atom_block(AtomBlockId atom_blk, ClusterBlockId cl_blk, ezgl::application* app); +//Turns on autocomplete/suggestions void enable_autocomplete(ezgl::application* app); +//Simulates key press event +GdkEvent simulate_keypress(char key, GdkWindow* window); + +//Returns current search type std::string get_search_type(ezgl::application* app); #endif /* NO_GRAPHICS */ From 031ae9a5b7cc15d379b49e618e39ddab1f9b0d8e Mon Sep 17 00:00:00 2001 From: SebastianLievano Date: Wed, 27 Jul 2022 23:54:52 -0400 Subject: [PATCH 7/8] Made PR fixes. Added performance info for search. --- vpr/src/draw/draw.cpp | 20 +++----- vpr/src/draw/draw_toggle_functions.cpp | 3 +- vpr/src/draw/search_bar.cpp | 64 ++++++++++++++++++-------- vpr/src/draw/search_bar.h | 2 +- vpr/src/draw/ui_setup.cpp | 9 +++- 5 files changed, 61 insertions(+), 37 deletions(-) diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp index 566c94262c2..998fa2d4885 100644 --- a/vpr/src/draw/draw.cpp +++ b/vpr/src/draw/draw.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "vtr_assert.h" #include "vtr_ndoffsetmatrix.h" @@ -669,21 +670,15 @@ bool draw_if_net_highlighted(ClusterNetId inet) { if (draw_state->net_color[inet] != DEFAULT_RR_NODE_COLOR) { return true; } - return false; } -# if defined(X11) && !defined(__MINGW32__) -void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_name) { - //VTR_LOG("Key press %c (%d)\n", key_pressed, keysym); - std::string key(key_name); - if (gtk_widget_is_focus(GTK_WIDGET(app->get_object("TextInput")))) { - if (key == "Return") { - enable_autocomplete(app); - } - } -} -# else +/** + * @brief cbk function for key press + * + * At the moment, only does something if user is currently typing in searchBar and + * hits enter, at which point it runs autocomplete + */ void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_name) { std::string key(key_name); GtkWidget* searchBar = GTK_WIDGET(app->get_object("TextInput")); @@ -695,7 +690,6 @@ void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_ } } } -# endif void act_on_mouse_press(ezgl::application* app, GdkEventButton* event, double x, double y) { // std::cout << "User clicked the "; diff --git a/vpr/src/draw/draw_toggle_functions.cpp b/vpr/src/draw/draw_toggle_functions.cpp index a8f6f4bf189..a7e95ffde0e 100644 --- a/vpr/src/draw/draw_toggle_functions.cpp +++ b/vpr/src/draw/draw_toggle_functions.cpp @@ -409,13 +409,12 @@ void toggle_expansion_cost_cbk(GtkComboBoxText* self, ezgl::application* app) { /** * @brief cbk fn to toggle Network-On-Chip (Noc) visibility * alters draw_state->draw_noc to reflect new state + * Reacts to main.ui created combo box, setup in ui_setup.cpp * * @param self ptr to combo box * @param app ezgl application */ void toggle_noc_cbk(GtkComboBoxText* self, ezgl::application* app) { - /* this is the callback function for runtime created toggle_noc_display button - * which is written in button.cpp */ t_draw_state* draw_state = get_draw_state_vars(); gchar* combo_box_content = gtk_combo_box_text_get_active_text(self); diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp index 038b46baaf4..2ed71ab620c 100644 --- a/vpr/src/draw/search_bar.cpp +++ b/vpr/src/draw/search_bar.cpp @@ -75,6 +75,8 @@ void search_and_highlight(GtkWidget* /*widget*/, ezgl::application* app) { std::stringstream ss(user_input); auto search_type = get_search_type(app); + if (search_type == "") + return; // reset deselect_all(); @@ -121,22 +123,22 @@ void search_and_highlight(GtkWidget* /*widget*/, ezgl::application* app) { AtomBlockId atom_blk_id = atom_ctx.nlist.find_block(block_name); if (atom_blk_id != AtomBlockId::INVALID()) { - ClusterBlockId block_id = atom_ctx.lookup.atom_clb(atom_blk_id); - if (!highlight_atom_block(atom_blk_id, block_id, app)) { - highlight_cluster_block(block_id); + ClusterBlockId cluster_block_id = atom_ctx.lookup.atom_clb(atom_blk_id); + if (!highlight_atom_block(atom_blk_id, cluster_block_id, app)) { + highlight_cluster_block(cluster_block_id); } return; } //Continues if atom block not found (Checking if user searched a clb) - ClusterBlockId block_id = ClusterBlockId::INVALID(); - block_id = cluster_ctx.clb_nlist.find_block(block_name); + ClusterBlockId cluster_block_id = ClusterBlockId::INVALID(); + cluster_block_id = cluster_ctx.clb_nlist.find_block(block_name); - if (block_id == ClusterBlockId::INVALID()) { + if (cluster_block_id == ClusterBlockId::INVALID()) { warning_dialog_box("Invalid Block Name"); return; //name not exist } - highlight_cluster_block(block_id); //found block + highlight_cluster_block(cluster_block_id); //found block } else if (search_type == "Net ID") { @@ -340,10 +342,11 @@ bool highlight_atom_block(AtomBlockId atom_blk, ClusterBlockId cl_blk, ezgl::app t_pb* find_atom_block_in_pb(std::string name, t_pb* pb) { //Checking if block is one being searched for std::string pbName(pb->name); - if (pbName == name) return pb; + if (pbName == name) + return pb; //If block has no children, returning - if (pb->child_pbs == nullptr) return nullptr; - + if (pb->child_pbs == nullptr) + return nullptr; int num_child_types = pb->get_num_child_types(); //Iterating through all child types for (int i = 0; i < num_child_types; ++i) { @@ -373,10 +376,7 @@ void highlight_nets(ClusterNetId net_id) { //If routing does not exist return if (int(route_ctx.trace.size()) == 0) return; - - for (tptr = route_ctx.trace[net_id].head; tptr != nullptr; tptr = tptr->next) { - draw_state->net_color[net_id] = ezgl::MAGENTA; - } + draw_state->net_color[net_id] = ezgl::MAGENTA; } void warning_dialog_box(const char* message) { @@ -445,13 +445,14 @@ void search_type_changed(GtkComboBox* self, ezgl::application* app) { /** * @brief A non-default matching function. As opposed to simply searching for a prefix(default), - * searches string for presence of a substring. Ignores cases. + * searches string for presence of a substring. Case-insensitive * * @param completer the GtkEntryCompletion being used * @param key a normalized and case-folded key representing the text * @param iter GtkTreeIter pointing at the current entry being compared * @param user_data null - * @return gboolean + * @return true | if the string pointed to by iter contains key (case-insensitive) + * @return false | if the string pointed to does not contain key */ gboolean customMatchingFunction( GtkEntryCompletion* completer, @@ -471,7 +472,8 @@ gboolean customMatchingFunction( } /** - * @brief Creates a GdkEvent that simulates user pressing key "key" + * @brief Creates a GdkEvent that simulates user pressing key "key". + * Currently used to fool GtkEntryCompletion into showing options w/o receiving a new input * * @param key character value * @param window GdkWindow @@ -502,6 +504,27 @@ GdkEvent simulate_keypress(char key, GdkWindow* window) { * as the user hits the "Enter" key. To accomplish this, a fake Gdk event is created * to simulate the user hitting a key. * + * This was done for usability reasons; if this is not done, user will need to input another key before seeing + * autocomplete results. Considering the enter is supposed to be a search, we want to search for the users + * key, not the key + another char + * + * PERFORMANCE DATA + * Correlation between key length and time is shaky; there might be some correlation to + * how many strings are similar to it. All tests are performed with the key "1" - pretty common + * Tests are searched three times then average + * MODEL 1: EARCH + TSENG.BLIF + * NETS 1483 + * NET SRCH. 19392 + * BLOCKS 1835 + * BLOCK SRCH. 21840 + * For second model (much larger, much longer CPU times) observed large dropoff in times from one char to two chars (about 2 times faster) but after stayed consistent + * Maybe when I ahve more time, will make a cute graph or something, no time right now + * MODEL 2: Strativix arch + MES_NOC (TITAN) + * NETS 577696 + * NET SRCH. 4.93438e+06 + * BLOCKS 572148 + * BLOCKS SRCH. 4.8654e+06 + * Obviously much slower w. more nets/blocks. However, it only performs a single search, pretty bearable considering its searching in strings * @param app ezgl app */ void enable_autocomplete(ezgl::application* app) { @@ -509,6 +532,8 @@ void enable_autocomplete(ezgl::application* app) { GtkEntry* searchBar = GTK_ENTRY(app->get_object("TextInput")); std::string searchType = get_search_type(app); + if (searchType == "") + return; //Checking to make sure that we are on a mode that uses auto-complete if (gtk_entry_completion_get_model(completion) == NULL) { std::cout << "NO MODEL SELECTED" << std::endl; @@ -538,14 +563,15 @@ void enable_autocomplete(ezgl::application* app) { gdk_event_put(&new_event); } +//Returns current search type. Returns empty string if fails std::string get_search_type(ezgl::application* app) { GObject* combo_box = (GObject*)app->get_object("SearchType"); gchar* type = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo_box)); //Checking that a type is selected - if (type && type[0] == '\0') { + if (!type || (type && type[0] == '\0')) { warning_dialog_box("Please select a search type"); app->refresh_drawing(); - return "Failed lol"; + return ""; } std::string searchType(type); return searchType; diff --git a/vpr/src/draw/search_bar.h b/vpr/src/draw/search_bar.h index 1854ee79f11..92f51470601 100644 --- a/vpr/src/draw/search_bar.h +++ b/vpr/src/draw/search_bar.h @@ -40,7 +40,7 @@ bool highlight_atom_block(AtomBlockId atom_blk, ClusterBlockId cl_blk, ezgl::app //Turns on autocomplete/suggestions void enable_autocomplete(ezgl::application* app); -//Simulates key press event +//Simulates key press event GdkEvent simulate_keypress(char key, GdkWindow* window); //Returns current search type diff --git a/vpr/src/draw/ui_setup.cpp b/vpr/src/draw/ui_setup.cpp index 97511de9958..54b8c6d8404 100644 --- a/vpr/src/draw/ui_setup.cpp +++ b/vpr/src/draw/ui_setup.cpp @@ -192,7 +192,7 @@ void hide_widget(std::string widgetName, ezgl::application* app) { } /** - * @brief loads block names into gtk list store item used for completion + * @brief loads atom and cluster lvl names into gtk list store item used for completion * * @param app ezgl application used for ui */ @@ -201,20 +201,23 @@ void load_block_names(ezgl::application* app) { auto& cluster_ctx = g_vpr_ctx.clustering(); auto& atom_ctx = g_vpr_ctx.atom(); GtkTreeIter iter; + int i = 0; for (ClusterBlockId id : cluster_ctx.clb_nlist.blocks()) { gtk_list_store_append(blockStorage, &iter); gtk_list_store_set(blockStorage, &iter, 0, (cluster_ctx.clb_nlist.block_name(id)).c_str(), -1); + i++; } for (AtomBlockId id : atom_ctx.nlist.blocks()) { gtk_list_store_append(blockStorage, &iter); gtk_list_store_set(blockStorage, &iter, 0, (atom_ctx.nlist.block_name(id)).c_str(), -1); + i++; } } /** - * @brief loads net names into gtk list store item used for completion + * @brief loads atom net names into gtk list store item used for completion * * @param app ezgl application used for ui */ @@ -223,10 +226,12 @@ void load_net_names(ezgl::application* app) { auto& atom_ctx = g_vpr_ctx.atom(); GtkTreeIter iter; //Loading net names + int i = 0; for (AtomNetId id : atom_ctx.nlist.nets()) { gtk_list_store_append(netStorage, &iter); gtk_list_store_set(netStorage, &iter, 0, (atom_ctx.nlist.net_name(id)).c_str(), -1); + i++; } } From a5d0c244fbd45ecb7d36c3bba3ee95674e42eb31 Mon Sep 17 00:00:00 2001 From: SebastianLievano Date: Tue, 2 Aug 2022 16:25:10 -0400 Subject: [PATCH 8/8] new draw struct mem to track completion/toggle off --- vpr/src/draw/draw.cpp | 11 +++++++++-- vpr/src/draw/draw_types.h | 1 + vpr/src/draw/search_bar.cpp | 6 ++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp index 998fa2d4885..f05c48ca990 100644 --- a/vpr/src/draw/draw.cpp +++ b/vpr/src/draw/draw.cpp @@ -682,13 +682,20 @@ bool draw_if_net_highlighted(ClusterNetId inet) { void act_on_key_press(ezgl::application* app, GdkEventKey* /*event*/, char* key_name) { std::string key(key_name); GtkWidget* searchBar = GTK_WIDGET(app->get_object("TextInput")); + std::string text(gtk_entry_get_text(GTK_ENTRY(searchBar))); + t_draw_state* draw_state = get_draw_state_vars(); if (gtk_widget_is_focus(searchBar)) { if (key == "Return") { - std::string oldText(gtk_entry_get_text(GTK_ENTRY(searchBar))); enable_autocomplete(app); - gtk_editable_set_position(GTK_EDITABLE(searchBar), oldText.length()); + gtk_editable_set_position(GTK_EDITABLE(searchBar), text.length()); + return; } } + if (draw_state->justEnabled) { + draw_state->justEnabled = false; + } else { + gtk_entry_set_completion(GTK_ENTRY(searchBar), nullptr); + } } void act_on_mouse_press(ezgl::application* app, GdkEventButton* event, double x, double y) { diff --git a/vpr/src/draw/draw_types.h b/vpr/src/draw/draw_types.h index db989a59777..9fd29f29ff2 100644 --- a/vpr/src/draw/draw_types.h +++ b/vpr/src/draw/draw_types.h @@ -217,6 +217,7 @@ struct t_draw_state { bool show_noc_button = false; e_draw_noc draw_noc = DRAW_NO_NOC; std::shared_ptr noc_usage_color_map = nullptr; // color map used to display noc link bandwidth usage + bool justEnabled = false; //Whether auto-complete was just enabled std::vector list_of_breakpoints; diff --git a/vpr/src/draw/search_bar.cpp b/vpr/src/draw/search_bar.cpp index 2ed71ab620c..fcc6771c9e9 100644 --- a/vpr/src/draw/search_bar.cpp +++ b/vpr/src/draw/search_bar.cpp @@ -369,7 +369,6 @@ t_pb* find_atom_block_in_pb(std::string name, t_pb* pb) { } void highlight_nets(ClusterNetId net_id) { - t_trace* tptr; auto& route_ctx = g_vpr_ctx.routing(); t_draw_state* draw_state = get_draw_state_vars(); @@ -524,12 +523,13 @@ GdkEvent simulate_keypress(char key, GdkWindow* window) { * NET SRCH. 4.93438e+06 * BLOCKS 572148 * BLOCKS SRCH. 4.8654e+06 - * Obviously much slower w. more nets/blocks. However, it only performs a single search, pretty bearable considering its searching in strings + * Obviously much slower w. more nets/blocks. However, it only performs a single search after each enter key press, pretty bearable considering its searching in strings * @param app ezgl app */ void enable_autocomplete(ezgl::application* app) { GtkEntryCompletion* completion = GTK_ENTRY_COMPLETION(app->get_object("Completion")); GtkEntry* searchBar = GTK_ENTRY(app->get_object("TextInput")); + auto draw_state = get_draw_state_vars(); std::string searchType = get_search_type(app); if (searchType == "") @@ -550,6 +550,8 @@ void enable_autocomplete(ezgl::application* app) { //Setting min key length to either 0 or 1 less than key length (max option) gtk_entry_completion_set_minimum_key_length(completion, std::max(0, (int)(oldText.length() - 1))); + draw_state->justEnabled = true; + //If string len is 0, reutrning if (oldText.length() == 0) return;