-
Notifications
You must be signed in to change notification settings - Fork 428
Feature ap draw #3285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Feature ap draw #3285
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,10 @@ | |
#include "ap_netlist_fwd.h" | ||
#include "atom_netlist.h" | ||
#include "device_grid.h" | ||
#include "draw.h" | ||
#ifndef NO_GRAPHICS | ||
#include "draw_global.h" | ||
#endif | ||
#include "flat_placement_bins.h" | ||
#include "flat_placement_density_manager.h" | ||
#include "globals.h" | ||
|
@@ -352,6 +356,10 @@ PartialPlacement SimPLGlobalPlacer::place() { | |
PartialPlacement best_p_placement(ap_netlist_); | ||
double best_ub_hpwl = std::numeric_limits<double>::max(); | ||
|
||
#ifndef NO_GRAPHICS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See my comments above. I would like to keep these ifdefs and the draw state out of this class. |
||
get_draw_state_vars()->set_ap_partial_placement_ref(p_placement); | ||
update_screen(ScreenUpdatePriority::MAJOR, "AP starts", ANALYTICAL_PLACEMENT, nullptr); | ||
#endif | ||
// Run the global placer. | ||
for (size_t i = 0; i < max_num_iterations_; i++) { | ||
float iter_start_time = runtime_timer.elapsed_sec(); | ||
|
@@ -361,12 +369,22 @@ PartialPlacement SimPLGlobalPlacer::place() { | |
solver_->solve(i, p_placement); | ||
float solver_end_time = runtime_timer.elapsed_sec(); | ||
double lb_hpwl = p_placement.get_hpwl(ap_netlist_); | ||
#ifndef NO_GRAPHICS | ||
// Per iteration analytical solve display | ||
std::string iter_msg = vtr::string_fmt("AP Iteration %zu after analytical solve", i); | ||
update_screen(ScreenUpdatePriority::MAJOR, iter_msg.c_str(), ANALYTICAL_PLACEMENT, nullptr); | ||
#endif | ||
|
||
// Run the legalizer. | ||
float legalizer_start_time = runtime_timer.elapsed_sec(); | ||
partial_legalizer_->legalize(p_placement); | ||
float legalizer_end_time = runtime_timer.elapsed_sec(); | ||
double ub_hpwl = p_placement.get_hpwl(ap_netlist_); | ||
#ifndef NO_GRAPHICS | ||
// Per iteration legalized display | ||
iter_msg = vtr::string_fmt("AP Iteration %zu after partial legalization", i); | ||
update_screen(ScreenUpdatePriority::MAJOR, iter_msg.c_str(), ANALYTICAL_PLACEMENT, nullptr); | ||
#endif | ||
|
||
// Perform a timing update | ||
float timing_update_start_time = runtime_timer.elapsed_sec(); | ||
|
@@ -422,6 +440,8 @@ PartialPlacement SimPLGlobalPlacer::place() { | |
|
||
if (hpwl_relative_gap < target_hpwl_relative_gap_) | ||
break; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why add these extra lines? |
||
|
||
} | ||
|
||
// Update the setup slacks. This is performed down here (as well as being | ||
|
@@ -450,6 +470,13 @@ PartialPlacement SimPLGlobalPlacer::place() { | |
*density_manager_, | ||
pre_cluster_timing_manager_); | ||
|
||
|
||
#ifndef NO_GRAPHICS | ||
// Final display of the last iteration's placement | ||
get_draw_state_vars()->set_ap_partial_placement_ref(p_placement); | ||
update_screen(ScreenUpdatePriority::MAJOR, "Global Placement Complete", ANALYTICAL_PLACEMENT, nullptr); | ||
get_draw_state_vars()->clear_ap_partial_placement_ref(); | ||
#endif | ||
// Return the placement from the final iteration. | ||
return best_p_placement; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,10 +16,12 @@ | |
#include <cstring> | ||
#include <cmath> | ||
#include "draw.h" | ||
#include "draw_types.h" | ||
#include "timing_info.h" | ||
#include "physical_types.h" | ||
|
||
#include "move_utils.h" | ||
#include "vpr_types.h" | ||
|
||
#ifndef NO_GRAPHICS | ||
|
||
|
@@ -174,63 +176,65 @@ static void draw_main_canvas(ezgl::renderer* g) { | |
t_draw_state* draw_state = get_draw_state_vars(); | ||
|
||
g->set_font_size(14); | ||
if (draw_state->pic_on_screen != ANALYTICAL_PLACEMENT) { | ||
draw_block_pin_util(); | ||
drawplace(g); | ||
draw_internal_draw_subblk(g); | ||
|
||
draw_block_pin_util(); | ||
drawplace(g); | ||
draw_internal_draw_subblk(g); | ||
if (draw_state->pic_on_screen == ROUTING) { // ROUTING on screen | ||
|
||
if (draw_state->pic_on_screen == ROUTING) { // ROUTING on screen | ||
draw_rr(g); | ||
|
||
draw_rr(g); | ||
if (draw_state->show_nets && draw_state->draw_nets == DRAW_ROUTED_NETS) { | ||
draw_route(ALL_NETS, g); | ||
|
||
if (draw_state->show_nets && draw_state->draw_nets == DRAW_ROUTED_NETS) { | ||
draw_route(ALL_NETS, g); | ||
|
||
if (draw_state->highlight_fan_in_fan_out) { | ||
draw_route(HIGHLIGHTED, g); | ||
if (draw_state->highlight_fan_in_fan_out) { | ||
draw_route(HIGHLIGHTED, g); | ||
} | ||
} | ||
} | ||
|
||
draw_congestion(g); | ||
draw_congestion(g); | ||
|
||
draw_routing_costs(g); | ||
draw_routing_costs(g); | ||
|
||
draw_router_expansion_costs(g); | ||
draw_router_expansion_costs(g); | ||
|
||
draw_routing_util(g); | ||
draw_routing_util(g); | ||
|
||
draw_routing_bb(g); | ||
} | ||
draw_routing_bb(g); | ||
} | ||
|
||
draw_placement_macros(g); | ||
draw_placement_macros(g); | ||
|
||
#ifndef NO_SERVER | ||
if (g_vpr_ctx.server().gate_io.is_running()) { | ||
const ServerContext& server_ctx = g_vpr_ctx.server(); // shortcut | ||
draw_crit_path_elements(server_ctx.crit_paths, server_ctx.crit_path_element_indexes, server_ctx.draw_crit_path_contour, g); | ||
} else { | ||
draw_crit_path(g); | ||
} | ||
if (g_vpr_ctx.server().gate_io.is_running()) { | ||
const ServerContext& server_ctx = g_vpr_ctx.server(); // shortcut | ||
draw_crit_path_elements(server_ctx.crit_paths, server_ctx.crit_path_element_indexes, server_ctx.draw_crit_path_contour, g); | ||
} else { | ||
draw_crit_path(g); | ||
} | ||
#else | ||
draw_crit_path(g); | ||
draw_crit_path(g); | ||
#endif /* NO_SERVER */ | ||
|
||
draw_logical_connections(g); | ||
draw_logical_connections(g); | ||
|
||
draw_selected_pb_flylines(g); | ||
draw_selected_pb_flylines(g); | ||
|
||
draw_noc(g); | ||
draw_noc(g); | ||
|
||
if (draw_state->draw_partitions) { | ||
highlight_all_regions(g); | ||
draw_constrained_atoms(g); | ||
} | ||
if (draw_state->draw_partitions) { | ||
highlight_all_regions(g); | ||
draw_constrained_atoms(g); | ||
} | ||
|
||
if (draw_state->color_map) { | ||
draw_color_map_legend(*draw_state->color_map, g); | ||
draw_state->color_map.reset(); //Free color map in preparation for next redraw | ||
if (draw_state->color_map) { | ||
draw_color_map_legend(*draw_state->color_map, g); | ||
draw_state->color_map.reset(); //Free color map in preparation for next redraw | ||
} | ||
} else { | ||
draw_analytical_place(g); | ||
} | ||
|
||
if (draw_state->auto_proceed) { | ||
//Automatically exit the event loop, so user's don't need to manually click proceed | ||
|
||
|
@@ -286,7 +290,7 @@ void update_screen(ScreenUpdatePriority priority, const char* msg, enum pic_type | |
* value controls whether or not the Proceed button must be clicked to * | ||
* continue. Saves the pic_on_screen_val to allow pan and zoom redraws. */ | ||
t_draw_state* draw_state = get_draw_state_vars(); | ||
|
||
strcpy(draw_state->default_message, msg); | ||
|
||
if (!draw_state->show_graphics) | ||
|
@@ -302,16 +306,30 @@ void update_screen(ScreenUpdatePriority priority, const char* msg, enum pic_type | |
|
||
state_change = true; | ||
|
||
if (draw_state->show_graphics) { | ||
if (pic_on_screen_val == ANALYTICAL_PLACEMENT) { | ||
set_initial_world_ap(); | ||
} else { | ||
set_initial_world(); | ||
} | ||
} | ||
|
||
if (draw_state->pic_on_screen == NO_PICTURE) { | ||
// Only add the canvas the first time we open graphics | ||
application.add_canvas("MainCanvas", draw_main_canvas, | ||
initial_world); | ||
application.add_canvas("MainCanvas", draw_main_canvas, initial_world); | ||
} else { | ||
// TODO: will this ever be null? | ||
auto canvas = application.get_canvas(application.get_main_canvas_id()); | ||
if (canvas != nullptr) { | ||
canvas->get_camera().set_world(initial_world); | ||
} | ||
} | ||
|
||
draw_state->setup_timing_info = setup_timing_info; | ||
draw_state->pic_on_screen = pic_on_screen_val; | ||
} | ||
|
||
// What is this? Always true! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would mark this as a FIXME, or raise an issue so we can resolve. A comment like this will get missed. |
||
bool should_pause = int(priority) >= draw_state->gr_automode; | ||
|
||
//If there was a state change, we must call ezgl::application::run() to update the buttons. | ||
|
@@ -481,7 +499,18 @@ void init_draw_coords(float clb_width, const BlkLocRegistry& blk_loc_registry) { | |
//Margin beyond edge of the drawn device to extend the visible world | ||
//Setting this to > 0.0 means 'Zoom Fit' leave some fraction of white | ||
//space around the device edges | ||
#else | ||
(void)clb_width; | ||
(void)blk_loc_registry; | ||
#endif /* NO_GRAPHICS */ | ||
} | ||
|
||
#ifndef NO_GRAPHICS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would be careful with this ifdef. You are not defining these functions when graphics is disabled. However, they are still available in the header file... I would put the ifdef inside of the method and have the method do nothing when graphics is not enabled. |
||
|
||
void set_initial_world() { | ||
constexpr float VISIBLE_MARGIN = 0.01; | ||
t_draw_coords* draw_coords = get_draw_coords_vars(); | ||
const DeviceContext& device_ctx = g_vpr_ctx.device(); | ||
|
||
float draw_width = draw_coords->tile_x[device_ctx.grid.width() - 1] | ||
+ draw_coords->get_tile_width(); | ||
|
@@ -491,14 +520,24 @@ void init_draw_coords(float clb_width, const BlkLocRegistry& blk_loc_registry) { | |
initial_world = ezgl::rectangle( | ||
{-VISIBLE_MARGIN * draw_width, -VISIBLE_MARGIN * draw_height}, | ||
{(1. + VISIBLE_MARGIN) * draw_width, (1. + VISIBLE_MARGIN) | ||
* draw_height}); | ||
#else | ||
(void)clb_width; | ||
(void)blk_loc_registry; | ||
#endif /* NO_GRAPHICS */ | ||
* draw_height}); | ||
} | ||
|
||
#ifndef NO_GRAPHICS | ||
void set_initial_world_ap() { | ||
constexpr float VISIBLE_MARGIN = 0.01f; | ||
const DeviceContext& device_ctx = g_vpr_ctx.device(); | ||
|
||
const size_t grid_w = device_ctx.grid.width(); | ||
const size_t grid_h = device_ctx.grid.height(); | ||
|
||
|
||
float draw_width = static_cast<float>(grid_w); | ||
float draw_height = static_cast<float>(grid_h); | ||
|
||
initial_world = ezgl::rectangle( | ||
{-VISIBLE_MARGIN * draw_width, -VISIBLE_MARGIN * draw_height}, | ||
{(1.f + VISIBLE_MARGIN) * draw_width, (1.f + VISIBLE_MARGIN) * draw_height}); | ||
} | ||
|
||
int get_track_num(int inode, const vtr::OffsetMatrix<int>& chanx_track, const vtr::OffsetMatrix<int>& chany_track) { | ||
/* Returns the track number of this routing resource node. */ | ||
|
@@ -624,6 +663,11 @@ void act_on_mouse_press(ezgl::application* app, GdkEventButton* event, double x, | |
* fanins and fanouts are highlighted when you click on a block * | ||
* attached to them. */ | ||
|
||
if (get_draw_state_vars()->pic_on_screen == ANALYTICAL_PLACEMENT) { | ||
// No selection in analytical placement mode yet | ||
return; | ||
} | ||
|
||
/* Control + mouse click to select multiple nets. */ | ||
if (!(event->state & GDK_CONTROL_MASK)) | ||
deselect_all(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,9 @@ void update_screen(ScreenUpdatePriority priority, const char* msg, enum pic_type | |
*/ | ||
void init_draw_coords(float clb_width, const BlkLocRegistry& blk_loc_registry); | ||
|
||
void set_initial_world_ap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These new methods need comments. Also see my prior comments on their definitions. |
||
void set_initial_world(); | ||
|
||
/* Sets the static show_graphics and gr_automode variables to the * | ||
* desired values. They control if graphics are enabled and, if so, * | ||
* how often the user is prompted for input. */ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,8 @@ | |
* Blocks are drawn in layer order (so that semi-transparent blocks/grids render well)*/ | ||
void drawplace(ezgl::renderer* g); | ||
|
||
void draw_analytical_place(ezgl::renderer* g); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs comment. |
||
|
||
/** This routine draws the nets on the placement. The nets have not | ||
* yet been routed, so we just draw a chain showing a possible path | ||
* for each net. This gives some idea of future congestion. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to keep the drawing code pretty isolated from the AP code as much as possible. In the future, we may decide to make another global placer as well, and I would like to avoid duplicate code.
I suggest that you create a new class in the
analytical_place
directory for drawing. Something like APDrawManager or something. This class would then have methods for drawing the pre and post legalized placements. This would remove the global accesses from this method. The global placer can then take this as an argument, which it can use to draw whenever it needs.