diff --git a/vpr/main.ui b/vpr/main.ui
index 4bb2986dc23..d6b4b31e079 100644
--- a/vpr/main.ui
+++ b/vpr/main.ui
@@ -13,16 +13,6 @@
-
False
@@ -113,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
@@ -126,7 +145,7 @@
False
True
- 6
+ 8
@@ -142,12 +161,22 @@
False
True
- 7
+ 9
+
+ 5
+ 0
+
+
+
+ 0
+
+
+
test
False
@@ -239,6 +268,12 @@
+
+
+
+
+
+
False
@@ -535,59 +570,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 +583,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 +629,7 @@
0
- 4
+ 5
4
@@ -667,112 +639,165 @@
True
True
True
+ end
right
4
- 4
+ 5
-
-
-
-
-
@@ -781,6 +806,45 @@
+
+
+
+
+
+
+
+ False
+
+
+ True
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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 daff060d12b..f05c48ca990 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"
@@ -282,6 +283,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
@@ -301,7 +303,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
@@ -356,7 +357,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
@@ -670,19 +670,33 @@ 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);
+/**
+ * @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"));
+ 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") {
+ enable_autocomplete(app);
+ 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);
+ }
}
-# else
-void act_on_key_press(ezgl::application* /*app*/, GdkEventKey* /*event*/, char* /*key_name*/) {
-}
-# 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 eb06fb0f000..a7e95ffde0e 100644
--- a/vpr/src/draw/draw_toggle_functions.cpp
+++ b/vpr/src/draw/draw_toggle_functions.cpp
@@ -406,15 +406,18 @@ void toggle_expansion_cost_cbk(GtkComboBoxText* self, ezgl::application* app) {
app->refresh_drawing();
}
-void toggle_noc_display(GtkWidget* /*widget*/, gint /*response_id*/, gpointer /*data*/) {
- /* this is the callback function for runtime created toggle_noc_display button
- * which is written in button.cpp */
+/**
+ * @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) {
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 +426,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/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 02592fc8c1a..fcc6771c9e9 100644
--- a/vpr/src/draw/search_bar.cpp
+++ b/vpr/src/draw/search_bar.cpp
@@ -1,5 +1,19 @@
-#ifndef NO_GRAPHICS
+/**
+ * @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
@@ -52,6 +66,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 +74,9 @@ 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();
+ auto search_type = get_search_type(app);
+ if (search_type == "")
return;
- }
-
- std::string search_type(type);
// reset
deselect_all();
@@ -99,14 +107,38 @@ 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") {
+ /* 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;
- highlight_blocks((std::string)block_name);
+ AtomBlockId atom_blk_id = atom_ctx.nlist.find_block(block_name);
+ if (atom_blk_id != AtomBlockId::INVALID()) {
+ 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 cluster_block_id = ClusterBlockId::INVALID();
+ cluster_block_id = cluster_ctx.clb_nlist.find_block(block_name);
+
+ if (cluster_block_id == ClusterBlockId::INVALID()) {
+ warning_dialog_box("Invalid Block Name");
+ return; //name not exist
+ }
+ highlight_cluster_block(cluster_block_id); //found block
}
else if (search_type == "Net ID") {
@@ -124,10 +156,18 @@ 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 = 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 +269,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 +302,80 @@ 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". 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
+ 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();
-
- ClusterBlockId block_id = ClusterBlockId::INVALID();
- block_id = cluster_ctx.clb_nlist.find_block(block_name);
+void highlight_nets(ClusterNetId net_id) {
+ auto& route_ctx = g_vpr_ctx.routing();
- if (block_id == ClusterBlockId::INVALID()) {
- warning_dialog_box("Invalid Block Name");
- return; //name not exist
- }
+ t_draw_state* draw_state = get_draw_state_vars();
- highlight_blocks(block_id); //found block
+ //If routing does not exist return
+ if (int(route_ctx.trace.size()) == 0) return;
+ draw_state->net_color[net_id] = ezgl::MAGENTA;
}
void warning_dialog_box(const char* message) {
@@ -339,34 +419,164 @@ 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 non-default matching function. As opposed to simply searching for a prefix(default),
+ * searches string for presence of a substring. Case-insensitive
*
- * @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 true | if the string pointed to by iter contains key (case-insensitive)
+ * @return false | if the string pointed to does not contain key
*/
-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);
+}
+
+/**
+ * @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
+ * @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.
+ *
+ * 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 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 == "")
+ 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;
+ return;
}
+
+ //Getting input text
+ std::string oldText(gtk_entry_get_text(searchBar));
+
+ //Turning on completion
+ gtk_entry_set_completion(searchBar, completion);
+ gtk_entry_completion_complete(completion);
+
+ //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;
+
+ 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());
+
+ //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);
+}
+
+//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 && type[0] == '\0')) {
+ warning_dialog_box("Please select a search type");
+ app->refresh_drawing();
+ return "";
+ }
+ 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..92f51470601 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,20 @@ 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);
+//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 */
-#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..54b8c6d8404 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);
+ }
}
/**
@@ -138,6 +147,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 +191,48 @@ void hide_widget(std::string widgetName, ezgl::application* app) {
gtk_widget_hide(widget);
}
+/**
+ * @brief loads atom and cluster lvl 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;
+ 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 atom 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
+ 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++;
+ }
+}
+
#endif /* NO_GRAPHICS */
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);