/*********************************** Top-level Summary *************************************
 * This is VPR's main graphics application program. The program interacts with graphics.c,
 * which provides an API for displaying graphics on both X11 and Win32. The most important
 * subroutine in this file is drawscreen(), which is a callback function that X11 or Win32
 * will call whenever the screen needs to be updated. Then, drawscreen() will decide what
 * drawing subroutines to call depending on whether PLACEMENT or ROUTING is shown on screen
 * and whether any of the menu buttons has been triggered. As a note, looks into draw_global.c
 * for understanding the data structures associated with drawing.
 *
 * Authors: Vaughn Betz, Long Yu (Mike) Wang
 * Last updated: August 2013
 */

#include <cstdio>
#include <cfloat>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <sstream>
#include <array>
using namespace std;

#include "vtr_assert.h"
#include "vtr_ndoffsetmatrix.h"
#include "vtr_memory.h"
#include "vtr_log.h"
#include "vtr_color_map.h"

#include "vpr_utils.h"
#include "vpr_error.h"

#include "globals.h"
#include "graphics.h"
#include "draw.h"
#include "read_xml_arch_file.h"
#include "draw_global.h"
#include "intra_logic_block.h"
#include "atom_netlist.h"
#include "tatum/report/TimingPathCollector.hpp"
#include "hsl.h"
#include "route_export.h"

#ifdef WIN32 /* For runtime tracking in WIN32. The clock() function defined in time.h will *
              * track CPU runtime.														   */
#    include <time.h>
#else /* For X11. The clock() function in time.h will not output correct time difference   *
       * for X11, because the graphics is processed by the Xserver rather than local CPU,  *
       * which means tracking CPU time will not be the same as the actual wall clock time. *
       * Thus, so use gettimeofday() in sys/time.h to track actual calendar time.          */
#    include <sys/time.h>
#endif

//To process key presses we need the X11 keysym definitions,
//which are unavailable when building with MINGW
#if defined(X11) && !defined(__MINGW32__)
#    include <X11/keysym.h>
#endif

#include "rr_graph.h"
#include "route_util.h"
#include "place_macro.h"

/****************************** Define Macros *******************************/

#define DEFAULT_RR_NODE_COLOR BLACK
//#define TIME_DRAWSCREEN /* Enable if want to track runtime for drawscreen() */

//The arrow head position for turning/straight-thru connections in a switch box
constexpr float SB_EDGE_TURN_ARROW_POSITION = 0.2;
constexpr float SB_EDGE_STRAIGHT_ARROW_POSITION = 0.95;

constexpr float EMPTY_BLOCK_LIGHTEN_FACTOR = 0.10;

//Kelly's maximum contrast colors are selected to be easily distinguishable as described in:
//  Kenneth Kelly, "Twenty-Two Colors of Maximum Contrast", Color Eng. 3(6), 1943
//We use these to highlight a relatively small number of things (e.g. stages in a critical path,
//a subset of selected net) where it is important for them to be visually distinct.
const std::vector<t_color> kelly_max_contrast_colors = {
    //t_color(242, 243, 244), //white: skip white since it doesn't contrast well with VPR's light background
    t_color(34, 34, 34),    //black
    t_color(243, 195, 0),   //yellow
    t_color(135, 86, 146),  //purple
    t_color(243, 132, 0),   //orange
    t_color(161, 202, 241), //light blue
    t_color(190, 0, 50),    //red
    t_color(194, 178, 128), //buf
    t_color(132, 132, 130), //gray
    t_color(0, 136, 86),    //green
    t_color(230, 143, 172), //purplish pink
    t_color(0, 103, 165),   //blue
    t_color(249, 147, 121), //yellowish pink
    t_color(96, 78, 151),   //violet
    t_color(246, 166, 0),   //orange yellow
    t_color(179, 68, 108),  //purplish red
    t_color(220, 211, 0),   //greenish yellow
    t_color(136, 45, 23),   //redish brown
    t_color(141, 182, 0),   //yellow green
    t_color(101, 69, 34),   //yellowish brown
    t_color(226, 88, 34),   //reddish orange
    t_color(43, 61, 38)     //olive green
};

//The colours used to draw block types
const std::vector<color_types> block_type_colors = {
    //This first set of colours is somewhat curated to yield
    //a nice colour pallette
    BISQUE, //EMPTY type is usually the type with index 0, so this colour
            //usually unused
    LIGHTGREY,
    LIGHTSKYBLUE,
    THISTLE,
    KHAKI,
    CORAL,
    TURQUOISE,
    MEDIUMPURPLE,
    DARKSLATEBLUE,
    DARKKHAKI,
    LIGHTMEDIUMBLUE,
    SADDLEBROWN,
    FIREBRICK,
    LIMEGREEN,
    PLUM,

    //However, if we have lots of block types we just assign arbitrary HTML
    //colours. Note that these are shuffled (instead of in alphabetical order)
    //since some colours which are alphabetically close are also close in
    //shade (making them difficult to distinguish)
    DARKGREEN,
    PALEVIOLETRED,
    BLUE,
    FORESTGREEN,
    WHEAT,
    GOLD,
    MOCCASIN,
    MEDIUMORCHID,
    SKYBLUE,
    WHITESMOKE,
    LIME,
    MEDIUMSLATEBLUE,
    TOMATO,
    CYAN,
    OLIVE,
    LIGHTGRAY,
    STEELBLUE,
    LIGHTCORAL,
    IVORY,
    MEDIUMVIOLETRED,
    SNOW,
    DARKGRAY,
    GREY,
    GRAY,
    YELLOW,
    REBECCAPURPLE,
    DARKCYAN,
    MIDNIGHTBLUE,
    ROSYBROWN,
    CORNSILK,
    NAVAJOWHITE,
    BLANCHEDALMOND,
    ORCHID,
    LIGHTGOLDENRODYELLOW,
    MAROON,
    GREENYELLOW,
    SILVER,
    PALEGOLDENROD,
    LAWNGREEN,
    DIMGREY,
    DARKVIOLET,
    DARKTURQUOISE,
    INDIGO,
    DARKORANGE,
    PAPAYAWHIP,
    MINTCREAM,
    GREEN,
    DARKMAGENTA,
    MAGENTA,
    LIGHTSLATEGRAY,
    CHARTREUSE,
    GHOSTWHITE,
    LIGHTCYAN,
    SIENNA,
    GOLDENROD,
    DARKSLATEGRAY,
    OLDLACE,
    SEASHELL,
    SPRINGGREEN,
    MEDIUMTURQUOISE,
    LEMONCHIFFON,
    MISTYROSE,
    OLIVEDRAB,
    LIGHTBLUE,
    CHOCOLATE,
    SEAGREEN,
    DEEPPINK,
    LIGHTSEAGREEN,
    FLORALWHITE,
    CADETBLUE,
    AZURE,
    BURLYWOOD,
    AQUAMARINE,
    BROWN,
    POWDERBLUE,
    HOTPINK,
    MEDIUMBLUE,
    BLUEVIOLET,
    GREY75,
    PURPLE,
    TEAL,
    ANTIQUEWHITE,
    DEEPSKYBLUE,
    SLATEGRAY,
    SALMON,
    SLATEBLUE,
    DARKORCHID,
    LIGHTPINK,
    DARKBLUE,
    PEACHPUFF,
    PALEGREEN,
    DARKSALMON,
    DARKOLIVEGREEN,
    DARKSEAGREEN,
    VIOLET,
    RED,
    DARKSLATEGREY,
    PALETURQUOISE,
    DARKRED,
    SLATEGREY,
    HONEYDEW,
    AQUA,
    LIGHTSTEELBLUE,
    DODGERBLUE,
    MEDIUMSPRINGGREEN,
    NAVY,
    GAINSBORO,
    LIGHTYELLOW,
    CRIMSON,
    FUCHSIA,
    DARKGOLDENROD,
    SANDYBROWN,
    BEIGE,
    LINEN,
    ORANGERED,
    ROYALBLUE,
    LAVENDER,
    TAN,
    YELLOWGREEN,
    CORNFLOWERBLUE,
    LAVENDERBLUSH,
    MEDIUMSEAGREEN,
    PINK,
    GREY55,
    PERU,
    LIGHTGREEN,
    LIGHTSALMON,
    INDIANRED,
    DIMGRAY,
    LIGHTSLATEGREY,
    MEDIUMAQUAMARINE,
    DARKGREY,
    ORANGE,
    ALICEBLUE,
};

//FIXME: ugly hack
extern t_pl_macro* pl_macros;
extern int num_pl_macros;

/************************** File Scope Variables ****************************/

std::string rr_highlight_message;

/********************** Subroutines local to this module ********************/

static void toggle_nets(void (*drawscreen)());
static void toggle_rr(void (*drawscreen)());
static void toggle_congestion(void (*drawscreen)());
static void toggle_routing_congestion_cost(void (*drawscreen)());
static void toggle_routing_bounding_box(void (*drawscreen_ptr)());
static void toggle_routing_util(void (*drawscreen_ptr)());
static void toggle_crit_path(void (*drawscreen_ptr)());
static void toggle_block_pin_util(void (*drawscreen_ptr)());
static void toggle_router_rr_costs(void (*drawscreen_ptr)());
static void toggle_placement_macros(void (*drawscreen_ptr)());

static void drawscreen();
static void redraw_screen();
static void drawplace();
static void drawnets();
static void drawroute(enum e_draw_net_type draw_net_type);
static void draw_congestion();
static void draw_routing_costs();
static void draw_routing_bb();
static void draw_routing_util();
static void draw_crit_path();
static void draw_placement_macros();

static void highlight_blocks(float x, float y, t_event_buttonPressed button_info);
static void act_on_mouse_over(float x, float y);
static void deselect_all();

static void act_on_key_press(char key_pressed, int keysym);

static void draw_routed_net(ClusterNetId net);
void draw_partial_route(const std::vector<int>& rr_nodes_to_draw);
static void draw_rr();
static void draw_rr_edges(int from_node);
static void draw_rr_pin(int inode, const t_color& color);
static void draw_rr_chan(int inode, const t_color color);
static void draw_rr_src_sink(int inode, t_color color);
static t_bound_box draw_get_rr_chan_bbox(int inode);
static void draw_pin_to_chan_edge(int pin_node, int chan_node);
static void draw_x(float x, float y, float size);
static void draw_pin_to_pin(int opin, int ipin);
static void draw_rr_switch(float from_x, float from_y, float to_x, float to_y, bool buffered, bool switch_configurable);
static void draw_chany_to_chany_edge(int from_node, int to_node, int to_track, short switch_type);
static void draw_chanx_to_chanx_edge(int from_node, int to_node, int to_track, short switch_type);
static void draw_chanx_to_chany_edge(int chanx_node, int chanx_track, int chany_node, int chany_track, enum e_edge_dir edge_dir, short switch_type);
static int get_track_num(int inode, const vtr::OffsetMatrix<int>& chanx_track, const vtr::OffsetMatrix<int>& chany_track);
static bool draw_if_net_highlighted(ClusterNetId inet);
static void draw_highlight_fan_in_fan_out(const std::set<int>& nodes);
static void highlight_nets(char* message, int hit_node);
static int draw_check_rr_node_hit(float click_x, float click_y);
static std::set<int> draw_expand_non_configurable_rr_nodes(int hit_node);
static void draw_expand_non_configurable_rr_nodes_recurr(int from_node, std::set<int>& expanded_nodes);
static bool highlight_rr_nodes(float x, float y);
static void draw_highlight_blocks_color(t_type_ptr type, ClusterBlockId blk_id);
static void draw_reset_blk_colors();
static void draw_reset_blk_color(ClusterBlockId blk_id);

static inline bool LOD_screen_area_test_square(float width, float screen_area_threshold);
static inline bool default_triangle_LOD_screen_area_test();
static inline bool triangle_LOD_screen_area_test(float arrow_size);

static inline void draw_mux_with_size(t_point origin, e_side orientation, float height, int size);
static inline t_bound_box draw_mux(t_point origin, e_side orientation, float height);
static inline t_bound_box draw_mux(t_point origin, e_side orientation, float height, float width, float height_scale);

static void draw_flyline_timing_edge(t_point start, t_point end, float incr_delay);
static void draw_routed_timing_edge(tatum::NodeId start_tnode, tatum::NodeId end_tnode, float incr_delay, t_color color);
static void draw_routed_timing_edge_connection(tatum::NodeId src_tnode, tatum::NodeId sink_tnode, t_color color);
static std::vector<int> trace_routed_connection_rr_nodes(const ClusterNetId net_id, const int driver_pin, const int sink_pin);
static bool trace_routed_connection_rr_nodes_recurr(const t_rt_node* rt_node, int sink_rr_node, std::vector<int>& rr_nodes_on_path);
static int find_edge(int prev_inode, int inode);

t_color to_t_color(vtr::Color<float> color);
static void draw_color_map_legend(const vtr::ColorMap& cmap);

t_color get_block_type_color(t_type_ptr type);
t_color lighten_color(t_color color, float amount);

static void draw_block_pin_util();

static float get_router_rr_cost(const t_rr_node_route_inf node_inf, e_draw_router_rr_cost draw_router_rr_cost);
static void draw_router_rr_costs();

static void draw_rr_costs(const std::vector<float>& rr_costs, bool lowest_cost_first = true);

/********************** Subroutine definitions ******************************/

void init_graphics_state(bool show_graphics_val, int gr_automode_val, enum e_route_type route_type) {
    /* Call accessor functions to retrieve global variables. */
    t_draw_state* draw_state = get_draw_state_vars();

    /* 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.                         */

    draw_state->show_graphics = show_graphics_val;
    draw_state->gr_automode = gr_automode_val;
    draw_state->draw_route_type = route_type;
}

void update_screen(ScreenUpdatePriority priority, const char* msg, enum pic_type pic_on_screen_val, std::shared_ptr<SetupTimingInfo> setup_timing_info) {
    /* Updates the screen if the user has requested graphics.  The priority  *
     * 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();

    if (!draw_state->show_graphics) /* Graphics turned off */
        return;

    /* If it's the type of picture displayed has changed, set up the proper  *
     * buttons.                                                              */
    if (draw_state->pic_on_screen != pic_on_screen_val) { //State changed
        if (pic_on_screen_val == PLACEMENT && draw_state->pic_on_screen == NO_PICTURE) {
            //Placement first to open
            create_button("Window", "Toggle Nets", toggle_nets);
            create_button("Toggle Nets", "Blk Internal", toggle_blk_internal);
            create_button("Blk Internal", "Blk Pin Util", toggle_block_pin_util);
            create_button("Blk Pin Util", "Place Macros", toggle_placement_macros);
            if (setup_timing_info) {
                create_button("Place Macros", "Crit. Path", toggle_crit_path);
            }
        } else if (pic_on_screen_val == ROUTING && draw_state->pic_on_screen == PLACEMENT) {
            //Routing, opening after placement
            create_button("Blk Internal", "Toggle RR", toggle_rr);
            create_button("Toggle RR", "Congestion", toggle_congestion);
            create_button("Congestion", "Cong. Cost", toggle_routing_congestion_cost);
            create_button("Cong. Cost", "Route BB", toggle_routing_bounding_box);
            create_button("Route BB", "Routing Util", toggle_routing_util);
            create_button("Routing Util", "Router Cost", toggle_router_rr_costs);
        } else if (pic_on_screen_val == PLACEMENT && draw_state->pic_on_screen == ROUTING) {
            //Placement, opening after routing

            //Clean-up routing specific-buttons
            destroy_button("Toggle RR");
            destroy_button("Congestion");
            destroy_button("Cong. Cost");
            destroy_button("Route BB");
            destroy_button("Route Util");
            destroy_button("Router Cost");
        } else if (pic_on_screen_val == ROUTING
                   && draw_state->pic_on_screen == NO_PICTURE) {
            //Routing opening first
            create_button("Window", "Toggle Nets", toggle_nets);
            create_button("Toggle Nets", "Blk Internal", toggle_blk_internal);
            create_button("Blk Internal", "Blk Pin Util", toggle_block_pin_util);
            create_button("Blk Pin Util", "Place Macros", toggle_placement_macros);
            create_button("Place Macros", "Toggle RR", toggle_rr);
            create_button("Toggle RR", "Congestion", toggle_congestion);
            create_button("Congestion", "Cong. Cost", toggle_routing_congestion_cost);
            create_button("Cong. Cost", "Route BB", toggle_routing_bounding_box);
            create_button("Route BB", "Routing Util", toggle_routing_util);
            create_button("Routing Util", "Router Cost", toggle_router_rr_costs);
            if (setup_timing_info) {
                create_button("Cong. Cost", "Crit. Path", toggle_crit_path);
            }
        }
    }
    /* Save the main message. */

    vtr::strncpy(draw_state->default_message, msg, vtr::bufsize);

    draw_state->setup_timing_info = setup_timing_info;

    draw_state->pic_on_screen = pic_on_screen_val;
    update_message(msg);
    drawscreen();

    //Has the user asked us to pause at the next screen updated?
    bool forced_pause = g_vpr_ctx.forced_pause();

    if (int(priority) >= draw_state->gr_automode || forced_pause) {
        if (forced_pause) {
            VTR_LOG("Starting interactive graphics (due to user interrupt)\n");
            g_vpr_ctx.set_forced_pause(false); //Reset pause flag
        }
        set_mouse_move_input(true); //Enable act_on_mouse_over callback
        set_keypress_input(true);   //Enable act_on_mouse_over callback
        event_loop(highlight_blocks, act_on_mouse_over, act_on_key_press, drawscreen);
    } else {
        flushinput();
    }
}

static void drawscreen() {
#ifdef TIME_DRAWSCREEN
    /* This can be used to test how long it takes for the redrawing routing to finish   *
     * updating the screen for a given input which would cause the screen to be redrawn.*/

#    ifdef WIN32
    clock_t drawscreen_begin, drawscreen_end;
    drawscreen_begin = clock();

#    else /* For X11. The clock() function in time.h does not output correct time difference *
           * in Linux, so use gettimeofday() in sys/time.h for accurate runtime tracking. */
    struct timeval begin;
    gettimeofday(&begin, NULL); /* get start time */

    unsigned long begin_time;
    begin_time = begin.tv_sec * 1000000 + begin.tv_usec;
#    endif
#endif

    /* This is the screen redrawing routine that event_loop assumes exists.  *
     * It erases whatever is on screen, then calls redraw_screen to redraw   *
     * it.                                                                   */

    set_drawing_buffer(OFF_SCREEN);

    clearscreen();
    redraw_screen();

    copy_off_screen_buffer_to_screen();

#ifdef TIME_DRAWSCREEN

#    ifdef WIN32
    drawscreen_end = clock();

    VTR_LOG("Drawscreen took %f seconds.\n", (float)(drawscreen_end - drawscreen_begin) / CLOCKS_PER_SEC);

#    else  /* X11 */
    struct timeval end;
    gettimeofday(&end, NULL); /* get end time */

    unsigned long end_time;
    end_time = end.tv_sec * 1000000 + end.tv_usec;

    unsigned long time_diff_microsec;
    time_diff_microsec = end_time - begin_time;

    VTR_LOG("Drawscreen took %ld microseconds\n", time_diff_microsec);
#    endif /* WIN32 */
#endif     /* TIME_DRAWSCREEN */
}

static void redraw_screen() {
    /* The screen redrawing routine called by drawscreen and           *
     * highlight_blocks.  Call this routine instead of drawscreen if   *
     * you know you don't need to erase the current graphics, and want *
     * to avoid a screen "flash".                                      */

    t_draw_state* draw_state = get_draw_state_vars();

    setfontsize(14);

    draw_block_pin_util();

    drawplace();

    draw_internal_draw_subblk();

    if (draw_state->pic_on_screen == PLACEMENT) {
        switch (draw_state->show_nets) {
            case DRAW_NETS:
                drawnets();
                break;
            case DRAW_LOGICAL_CONNECTIONS:
                break;
            default:
                break;
        }

    } else { /* ROUTING on screen */

        switch (draw_state->show_nets) {
            case DRAW_NETS:
                drawroute(ALL_NETS);
                break;
            case DRAW_LOGICAL_CONNECTIONS:
            // fall through
            default:
                draw_rr();
                break;
        }

        draw_congestion();

        draw_routing_costs();

        draw_router_rr_costs();

        draw_routing_util();

        draw_routing_bb();
    }

    draw_placement_macros();

    draw_crit_path();

    draw_logical_connections();

    if (draw_state->color_map) {
        draw_color_map_legend(*draw_state->color_map);
        draw_state->color_map.reset(); //Free color map in preparation for next redraw
    }
}

static void toggle_nets(void (*drawscreen_ptr)()) {
    /* Enables/disables drawing of nets when a the user clicks on a button.    *
     * Also disables drawing of routing resources.  See graphics.c for details *
     * of how buttons work.                                                    */
    t_draw_state* draw_state = get_draw_state_vars();

    enum e_draw_nets new_state;

    switch (draw_state->show_nets) {
        case DRAW_NO_NETS:
            new_state = DRAW_NETS;
            break;
        case DRAW_NETS:
            new_state = DRAW_LOGICAL_CONNECTIONS;
            break;
        default:
        case DRAW_LOGICAL_CONNECTIONS:
            new_state = DRAW_NO_NETS;
            break;
    }

    draw_state->reset_nets_congestion_and_rr();
    draw_state->show_nets = new_state;

    update_message(draw_state->default_message);
    drawscreen_ptr();
}

static void toggle_rr(void (*drawscreen_ptr)()) {
    /* Cycles through the options for viewing the routing resources available   *
     * in an FPGA.  If a routing isn't on screen, the routing graph hasn't been *
     * built, and this routine doesn't switch the view. Otherwise, this routine *
     * switches to the routing resource view.  Clicking on the toggle cycles    *
     * through the options:  DRAW_NO_RR, DRAW_ALL_RR, DRAW_ALL_BUT_BUFFERS_RR,  *
     * DRAW_NODES_AND_SBOX_RR, and DRAW_NODES_RR.                               */

    t_draw_state* draw_state = get_draw_state_vars();

    enum e_draw_rr_toggle new_state = (enum e_draw_rr_toggle)(((int)draw_state->draw_rr_toggle + 1)
                                                              % ((int)DRAW_RR_TOGGLE_MAX));
    draw_state->reset_nets_congestion_and_rr();
    draw_state->draw_rr_toggle = new_state;

    update_message(draw_state->default_message);
    drawscreen_ptr();
}

static void toggle_congestion(void (*drawscreen_ptr)()) {
    /* Turns the congestion display on and off.   */
    t_draw_state* draw_state = get_draw_state_vars();

    e_draw_congestion new_state = (enum e_draw_congestion)(((int)draw_state->show_congestion + 1)
                                                           % ((int)DRAW_CONGEST_MAX));
    draw_state->reset_nets_congestion_and_rr();
    draw_state->show_congestion = new_state;

    if (draw_state->show_congestion == DRAW_NO_CONGEST) {
        update_message(draw_state->default_message);
    }

    drawscreen_ptr();
}

static void toggle_routing_congestion_cost(void (*drawscreen_ptr)()) {
    //Turns routing congestion costs on and off
    t_draw_state* draw_state = get_draw_state_vars();
    e_draw_routing_costs new_state = (enum e_draw_routing_costs)(((int)draw_state->show_routing_costs + 1)
                                                                 % ((int)DRAW_ROUTING_COST_MAX));

    draw_state->reset_nets_congestion_and_rr();
    draw_state->show_routing_costs = new_state;

    if (draw_state->show_routing_costs == DRAW_NO_ROUTING_COSTS) {
        update_message(draw_state->default_message);
    }
    drawscreen_ptr();
}

static void toggle_routing_bounding_box(void (*drawscreen_ptr)()) {
    t_draw_state* draw_state = get_draw_state_vars();

    auto& route_ctx = g_vpr_ctx.routing();

    if (route_ctx.route_bb.size() == 0) {
        return; //Nothing to draw
    } else if ((size_t)draw_state->show_routing_bb == route_ctx.route_bb.size()) {
        draw_state->show_routing_bb = OPEN; //Done going through all BB
    } else if (draw_state->show_routing_bb == OPEN) {
        draw_state->show_routing_bb = 0; //Start at first BB
    } else {
        ++draw_state->show_routing_bb; //Next net BB
    }

    if (draw_state->show_routing_bb == OPEN) {
        update_message(draw_state->default_message);
    }
    drawscreen_ptr();
}

static void toggle_routing_util(void (*drawscreen_ptr)()) {
    t_draw_state* draw_state = get_draw_state_vars();

    e_draw_routing_util new_state = (enum e_draw_routing_util)(((int)draw_state->show_routing_util + 1)
                                                               % ((int)DRAW_ROUTING_UTIL_MAX));
    draw_state->show_routing_util = new_state;

    if (draw_state->show_routing_util == DRAW_NO_ROUTING_UTIL) {
        update_message(draw_state->default_message);
    }
    drawscreen_ptr();
}

void toggle_blk_internal(void (*drawscreen_ptr)()) {
    t_draw_state* draw_state;

    /* Call accessor function to retrieve global variables. */
    draw_state = get_draw_state_vars();

    /* Increment the depth of sub-blocks to be shown */
    draw_state->show_blk_internal++;
    /* If depth exceeds maximum sub-block level in pb_graph, then
     * disable internals drawing
     */
    if (draw_state->show_blk_internal > draw_state->max_sub_blk_lvl)
        draw_state->show_blk_internal = 0;

    drawscreen_ptr();
}

static void toggle_block_pin_util(void (*drawscreen_ptr)()) {
    t_draw_state* draw_state = get_draw_state_vars();

    e_draw_block_pin_util new_state = (enum e_draw_block_pin_util)(((int)draw_state->show_blk_pin_util + 1)
                                                                   % ((int)DRAW_PIN_UTIL_MAX));

    draw_state->show_blk_pin_util = new_state;

    if (new_state == DRAW_NO_BLOCK_PIN_UTIL) {
        draw_reset_blk_colors();
        update_message(draw_state->default_message);
    }
    drawscreen_ptr();
}

static void toggle_placement_macros(void (*drawscreen_ptr)()) {
    t_draw_state* draw_state = get_draw_state_vars();

    e_draw_placement_macros new_state = (enum e_draw_placement_macros)(((int)draw_state->show_placement_macros + 1)
                                                                       % ((int)DRAW_PLACEMENT_MACROS_MAX));

    draw_state->show_placement_macros = new_state;

    drawscreen_ptr();
}

static void toggle_crit_path(void (*drawscreen_ptr)()) {
    t_draw_state* draw_state = get_draw_state_vars();

    if (draw_state->pic_on_screen == PLACEMENT) {
        switch (draw_state->show_crit_path) {
            case DRAW_NO_CRIT_PATH:
                draw_state->show_crit_path = DRAW_CRIT_PATH_FLYLINES;
                break;
            case DRAW_CRIT_PATH_FLYLINES:
                draw_state->show_crit_path = DRAW_CRIT_PATH_FLYLINES_DELAYS;
                break;
            default:
                draw_state->show_crit_path = DRAW_NO_CRIT_PATH;
                break;
        };
    } else {
        VTR_ASSERT(draw_state->pic_on_screen == ROUTING);

        switch (draw_state->show_crit_path) {
            case DRAW_NO_CRIT_PATH:
                draw_state->show_crit_path = DRAW_CRIT_PATH_FLYLINES;
                break;
            case DRAW_CRIT_PATH_FLYLINES:
                draw_state->show_crit_path = DRAW_CRIT_PATH_FLYLINES_DELAYS;
                break;
            case DRAW_CRIT_PATH_FLYLINES_DELAYS:
                draw_state->show_crit_path = DRAW_CRIT_PATH_ROUTING;
                break;
            case DRAW_CRIT_PATH_ROUTING:
                draw_state->show_crit_path = DRAW_CRIT_PATH_ROUTING_DELAYS;
                break;
            default:
                draw_state->show_crit_path = DRAW_NO_CRIT_PATH;
                break;
        };
    }

    drawscreen_ptr();
}

static void toggle_router_rr_costs(void (*drawscreen_ptr)()) {
    t_draw_state* draw_state = get_draw_state_vars();

    e_draw_router_rr_cost new_state = (enum e_draw_router_rr_cost)(((int)draw_state->show_router_rr_cost + 1)
                                                                   % ((int)DRAW_ROUTER_RR_COST_MAX));
    draw_state->show_router_rr_cost = new_state;

    if (draw_state->show_router_rr_cost == DRAW_NO_ROUTER_RR_COST) {
        update_message(draw_state->default_message);
    }
    drawscreen_ptr();
}

void alloc_draw_structs(const t_arch* arch) {
    /* Call accessor functions to retrieve global variables. */
    t_draw_coords* draw_coords = get_draw_coords_vars();
    t_draw_state* draw_state = get_draw_state_vars();
    auto& device_ctx = g_vpr_ctx.device();
    auto& cluster_ctx = g_vpr_ctx.clustering();

    /* Allocate the structures needed to draw the placement and routing.  Set *
     * up the default colors for blocks and nets.                             */

    draw_coords->tile_x = (float*)vtr::malloc(device_ctx.grid.width() * sizeof(float));
    draw_coords->tile_y = (float*)vtr::malloc(device_ctx.grid.height() * sizeof(float));

    /* For sub-block drawings inside clbs */
    draw_internal_alloc_blk();

    draw_state->net_color.resize(cluster_ctx.clb_nlist.nets().size());

    draw_state->block_color.resize(cluster_ctx.clb_nlist.blocks().size());

    /* Space is allocated for draw_rr_node but not initialized because we do *
     * not yet know information about the routing resources.				  */
    draw_state->draw_rr_node = (t_draw_rr_node*)vtr::malloc(
        device_ctx.rr_nodes.size() * sizeof(t_draw_rr_node));

    draw_state->arch_info = arch;

    deselect_all(); /* Set initial colors */
}

void free_draw_structs() {
    /* Free everything allocated by alloc_draw_structs. Called after close_graphics() *
     * in vpr_api.c.
     *
     * For safety, set all the array pointers to NULL in case any data
     * structure gets freed twice.													 */
    t_draw_state* draw_state = get_draw_state_vars();
    t_draw_coords* draw_coords = get_draw_coords_vars();

    if (draw_coords != nullptr) {
        free(draw_coords->tile_x);
        draw_coords->tile_x = nullptr;
        free(draw_coords->tile_y);
        draw_coords->tile_y = nullptr;
    }

    if (draw_state != nullptr) {
        free(draw_state->draw_rr_node);
        draw_state->draw_rr_node = nullptr;
    }
}

void init_draw_coords(float width_val) {
    /* Load the arrays containing the left and bottom coordinates of the clbs   *
     * forming the FPGA.  tile_width_val sets the width and height of a drawn    *
     * clb.                                                                     */
    t_draw_state* draw_state = get_draw_state_vars();
    t_draw_coords* draw_coords = get_draw_coords_vars();
    auto& device_ctx = g_vpr_ctx.device();

    if (!draw_state->show_graphics)
        return; /* Graphics disabled */

    /* Each time routing is on screen, need to reallocate the color of each *
     * rr_node, as the number of rr_nodes may change.						*/
    if (device_ctx.rr_nodes.size() != 0) {
        draw_state->draw_rr_node = (t_draw_rr_node*)vtr::realloc(draw_state->draw_rr_node,
                                                                 (device_ctx.rr_nodes.size()) * sizeof(t_draw_rr_node));
        for (size_t i = 0; i < device_ctx.rr_nodes.size(); i++) {
            draw_state->draw_rr_node[i].color = DEFAULT_RR_NODE_COLOR;
            draw_state->draw_rr_node[i].node_highlighted = false;
        }
    }

    draw_coords->tile_width = width_val;
    draw_coords->pin_size = 0.3;
    for (int i = 0; i < device_ctx.num_block_types; ++i) {
        if (device_ctx.block_types[i].num_pins > 0) {
            draw_coords->pin_size = min(draw_coords->pin_size,
                                        (draw_coords->get_tile_width() / (4.0F * device_ctx.block_types[i].num_pins)));
        }
    }

    size_t j = 0;
    for (size_t i = 0; i < (device_ctx.grid.width() - 1); i++) {
        draw_coords->tile_x[i] = (i * draw_coords->get_tile_width()) + j;
        j += device_ctx.chan_width.y_list[i] + 1; /* N wires need N+1 units of space */
    }
    draw_coords->tile_x[device_ctx.grid.width() - 1] = ((device_ctx.grid.width() - 1) * draw_coords->get_tile_width()) + j;

    j = 0;
    for (size_t i = 0; i < (device_ctx.grid.height() - 1); ++i) {
        draw_coords->tile_y[i] = (i * draw_coords->get_tile_width()) + j;
        j += device_ctx.chan_width.x_list[i] + 1;
    }
    draw_coords->tile_y[device_ctx.grid.height() - 1] = ((device_ctx.grid.height() - 1) * draw_coords->get_tile_width()) + j;

    /* Load coordinates of sub-blocks inside the clbs */
    draw_internal_init_blk();

    //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
    constexpr float VISIBLE_MARGIN = 0.01;

    float draw_width = draw_coords->tile_x[device_ctx.grid.width() - 1] + draw_coords->get_tile_width();
    float draw_height = draw_coords->tile_y[device_ctx.grid.height() - 1] + draw_coords->get_tile_width();

    set_visible_world(
        -VISIBLE_MARGIN * draw_width,
        -VISIBLE_MARGIN * draw_height,
        (1. + VISIBLE_MARGIN) * draw_width,
        (1. + VISIBLE_MARGIN) * draw_height);
}

/* Draws the blocks placed on the proper clbs.  Occupied blocks are darker colours *
 * while empty ones are lighter colours and have a dashed border.      */
static void drawplace() {
    t_draw_state* draw_state = get_draw_state_vars();
    t_draw_coords* draw_coords = get_draw_coords_vars();
    auto& device_ctx = g_vpr_ctx.device();
    auto& place_ctx = g_vpr_ctx.placement();

    ClusterBlockId bnum;
    int num_sub_tiles;

    setlinewidth(0);

    for (size_t i = 0; i < device_ctx.grid.width(); i++) {
        for (size_t j = 0; j < device_ctx.grid.height(); j++) {
            /* Only the first block of a group should control drawing */
            if (device_ctx.grid[i][j].width_offset > 0 || device_ctx.grid[i][j].height_offset > 0)
                continue;

            num_sub_tiles = device_ctx.grid[i][j].type->capacity;
            /* Don't draw if tile capacity is zero. eg. corners. */
            if (num_sub_tiles == 0) {
                continue;
            }

            for (int k = 0; k < num_sub_tiles; ++k) {
                /* Look at the tile at start of large block */
                bnum = place_ctx.grid_blocks[i][j].blocks[k];

                /* Fill background for the clb. Do not fill if "show_blk_internal"
                 * is toggled.
                 */
                if (bnum == INVALID_BLOCK_ID) continue;

                //Determine the block color
                t_color block_color;
                if (bnum != EMPTY_BLOCK_ID) {
                    block_color = draw_state->block_color[bnum];
                } else {
                    block_color = get_block_type_color(device_ctx.grid[i][j].type);
                    block_color = lighten_color(block_color, EMPTY_BLOCK_LIGHTEN_FACTOR);
                }
                setcolor(block_color);

                /* Get coords of current sub_tile */
                t_bound_box abs_clb_bbox = draw_coords->get_absolute_clb_bbox(i, j, k);

                fillrect(abs_clb_bbox);

                setcolor(BLACK);

                setlinestyle((EMPTY_BLOCK_ID == bnum) ? DASHED : SOLID);
                drawrect(abs_clb_bbox);

                /* Draw text if the space has parts of the netlist */
                if (bnum != EMPTY_BLOCK_ID && bnum != INVALID_BLOCK_ID) {
                    auto& cluster_ctx = g_vpr_ctx.clustering();
                    std::string name = cluster_ctx.clb_nlist.block_name(bnum) + vtr::string_fmt(" (#%zu)", size_t(bnum));
                    drawtext_in(abs_clb_bbox, name.c_str());
                }

                /* Draw text for block type so that user knows what block */
                if (device_ctx.grid[i][j].width_offset == 0 && device_ctx.grid[i][j].height_offset == 0) {
                    std::string block_type_loc = device_ctx.grid[i][j].type->name;
                    block_type_loc += vtr::string_fmt(" (%d,%d)", i, j);
                    drawtext(abs_clb_bbox.get_center() - t_point(0, abs_clb_bbox.get_height() / 4),
                             block_type_loc.c_str(), abs_clb_bbox);
                }
            }
        }
    }
}

static void drawnets() {
    t_draw_state* draw_state = get_draw_state_vars();
    t_draw_coords* draw_coords = get_draw_coords_vars();
    /* 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.        */

    ClusterBlockId b1, b2;
    auto& cluster_ctx = g_vpr_ctx.clustering();

    setlinestyle(SOLID);
    setlinewidth(0);

    /* Draw the net as a star from the source to each sink. Draw from centers of *
     * blocks (or sub blocks in the case of IOs).                                */

    for (auto net_id : cluster_ctx.clb_nlist.nets()) {
        if (cluster_ctx.clb_nlist.net_is_ignored(net_id))
            continue; /* Don't draw */

        setcolor(draw_state->net_color[net_id]);
        b1 = cluster_ctx.clb_nlist.net_driver_block(net_id);
        t_point driver_center = draw_coords->get_absolute_clb_bbox(b1, cluster_ctx.clb_nlist.block_type(b1)).get_center();

        for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
            b2 = cluster_ctx.clb_nlist.pin_block(pin_id);
            t_point sink_center = draw_coords->get_absolute_clb_bbox(b2, cluster_ctx.clb_nlist.block_type(b2)).get_center();
            drawline(driver_center, sink_center);

            /* Uncomment to draw a chain instead of a star. */
            /* driver_center = sink_center;  */
        }
    }
}

static void draw_congestion() {
    /* Draws all the overused routing resources (i.e. congestion) in RED.   */
    t_draw_state* draw_state = get_draw_state_vars();

    if (draw_state->show_congestion == DRAW_NO_CONGEST) {
        return;
    }

    auto& device_ctx = g_vpr_ctx.device();
    auto& route_ctx = g_vpr_ctx.routing();

    //Record min/max congestion
    float min_congestion_ratio = 1.;
    float max_congestion_ratio = min_congestion_ratio;
    std::vector<int> congested_rr_nodes = collect_congested_rr_nodes();
    for (int inode : congested_rr_nodes) {
        short occ = route_ctx.rr_node_route_inf[inode].occ();
        short capacity = device_ctx.rr_nodes[inode].capacity();

        float congestion_ratio = float(occ) / capacity;

        max_congestion_ratio = std::max(max_congestion_ratio, congestion_ratio);
    }

    char msg[vtr::bufsize];
    if (draw_state->show_congestion == DRAW_CONGESTED) {
        sprintf(msg, "RR Node Overuse ratio range (%.2f, %.2f]", min_congestion_ratio, max_congestion_ratio);
    } else {
        VTR_ASSERT(draw_state->show_congestion == DRAW_CONGESTED_WITH_NETS);
        sprintf(msg, "RR Node Overuse ratio range (%.2f, %.2f] (and congested nets)", min_congestion_ratio, max_congestion_ratio);
    }
    update_message(msg);

    std::unique_ptr<vtr::ColorMap> cmap = std::make_unique<vtr::PlasmaColorMap>(min_congestion_ratio, max_congestion_ratio);

    //Sort the nodes in ascending order of value for drawing, this ensures high
    //valued nodes are not overdrawn by lower value ones (e.g. when zoomed-out far)
    auto cmp_ascending_acc_cost = [&](int lhs_node, int rhs_node) {
        short lhs_occ = route_ctx.rr_node_route_inf[lhs_node].occ();
        short lhs_capacity = device_ctx.rr_nodes[lhs_node].capacity();

        short rhs_occ = route_ctx.rr_node_route_inf[rhs_node].occ();
        short rhs_capacity = device_ctx.rr_nodes[rhs_node].capacity();

        float lhs_cong_ratio = float(lhs_occ) / lhs_capacity;
        float rhs_cong_ratio = float(rhs_occ) / rhs_capacity;

        return lhs_cong_ratio < rhs_cong_ratio;
    };
    std::sort(congested_rr_nodes.begin(), congested_rr_nodes.end(), cmp_ascending_acc_cost);

    if (draw_state->show_congestion == DRAW_CONGESTED_WITH_NETS) {
        auto rr_node_nets = collect_rr_node_nets();

        for (int inode : congested_rr_nodes) {
            for (ClusterNetId net : rr_node_nets[inode]) {
                t_color color = kelly_max_contrast_colors[size_t(net) % kelly_max_contrast_colors.size()];
                draw_state->net_color[net] = color;
            }
        }
        setlinewidth(0);
        drawroute(HIGHLIGHTED);

        //Reset colors
        for (int inode : congested_rr_nodes) {
            for (ClusterNetId net : rr_node_nets[inode]) {
                draw_state->net_color[net] = DEFAULT_RR_NODE_COLOR;
            }
        }
    } else {
        setlinewidth(2);
    }

    //Draw each congested node
    for (int inode : congested_rr_nodes) {
        short occ = route_ctx.rr_node_route_inf[inode].occ();
        short capacity = device_ctx.rr_nodes[inode].capacity();

        float congestion_ratio = float(occ) / capacity;

        bool node_congested = (occ > capacity);
        VTR_ASSERT(node_congested);

        t_color color = to_t_color(cmap->color(congestion_ratio));

        switch (device_ctx.rr_nodes[inode].type()) {
            case CHANX: //fallthrough
            case CHANY:
                draw_rr_chan(inode, color);
                break;

            case IPIN: //fallthrough
            case OPIN:
                draw_rr_pin(inode, color);
                break;
            default:
                break;
        }
    }

    draw_state->color_map = std::move(cmap);
}

static void draw_routing_costs() {
    /* Draws routing costs */

    t_draw_state* draw_state = get_draw_state_vars();

    if (draw_state->show_routing_costs == DRAW_NO_ROUTING_COSTS) {
        return;
    }

    auto& device_ctx = g_vpr_ctx.device();
    auto& route_ctx = g_vpr_ctx.routing();

    setlinewidth(2);

    VTR_ASSERT(!route_ctx.rr_node_route_inf.empty());

    float min_cost = std::numeric_limits<float>::infinity();
    float max_cost = -min_cost;
    std::vector<float> rr_node_costs(device_ctx.rr_nodes.size(), 0.);
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
        float cost = 0.;
        if (draw_state->show_routing_costs == DRAW_TOTAL_ROUTING_COSTS
            || draw_state->show_routing_costs == DRAW_LOG_TOTAL_ROUTING_COSTS) {
            int cost_index = device_ctx.rr_nodes[inode].cost_index();
            cost = device_ctx.rr_indexed_data[cost_index].base_cost
                   + route_ctx.rr_node_route_inf[inode].acc_cost
                   + route_ctx.rr_node_route_inf[inode].pres_cost;

        } else if (draw_state->show_routing_costs == DRAW_BASE_ROUTING_COSTS) {
            int cost_index = device_ctx.rr_nodes[inode].cost_index();
            cost = device_ctx.rr_indexed_data[cost_index].base_cost;

        } else if (draw_state->show_routing_costs == DRAW_ACC_ROUTING_COSTS
                   || draw_state->show_routing_costs == DRAW_LOG_ACC_ROUTING_COSTS) {
            cost = route_ctx.rr_node_route_inf[inode].acc_cost;

        } else {
            VTR_ASSERT(draw_state->show_routing_costs == DRAW_PRES_ROUTING_COSTS
                       || draw_state->show_routing_costs == DRAW_LOG_PRES_ROUTING_COSTS);
            cost = route_ctx.rr_node_route_inf[inode].pres_cost;
        }

        if (draw_state->show_routing_costs == DRAW_LOG_TOTAL_ROUTING_COSTS
            || draw_state->show_routing_costs == DRAW_LOG_ACC_ROUTING_COSTS
            || draw_state->show_routing_costs == DRAW_LOG_PRES_ROUTING_COSTS) {
            cost = std::log(cost);
        }
        rr_node_costs[inode] = cost;
        min_cost = std::min(min_cost, cost);
        max_cost = std::max(max_cost, cost);
    }

    //Hide min value, draw_rr_costs() ignores NaN's
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
        if (rr_node_costs[inode] == min_cost) {
            rr_node_costs[inode] = NAN;
        }
    }

    char msg[vtr::bufsize];
    if (draw_state->show_routing_costs == DRAW_TOTAL_ROUTING_COSTS) {
        sprintf(msg, "Total Congestion Cost Range [%g, %g]", min_cost, max_cost);
    } else if (draw_state->show_routing_costs == DRAW_LOG_TOTAL_ROUTING_COSTS) {
        sprintf(msg, "Log Total Congestion Cost Range [%g, %g]", min_cost, max_cost);
    } else if (draw_state->show_routing_costs == DRAW_BASE_ROUTING_COSTS) {
        sprintf(msg, "Base Congestion Cost Range [%g, %g]", min_cost, max_cost);
    } else if (draw_state->show_routing_costs == DRAW_ACC_ROUTING_COSTS) {
        sprintf(msg, "Accumulated (Historical) Congestion Cost Range [%g, %g]", min_cost, max_cost);
    } else if (draw_state->show_routing_costs == DRAW_LOG_ACC_ROUTING_COSTS) {
        sprintf(msg, "Log Accumulated (Historical) Congestion Cost Range [%g, %g]", min_cost, max_cost);
    } else if (draw_state->show_routing_costs == DRAW_PRES_ROUTING_COSTS) {
        sprintf(msg, "Present Congestion Cost Range [%g, %g]", min_cost, max_cost);
    } else if (draw_state->show_routing_costs == DRAW_LOG_PRES_ROUTING_COSTS) {
        sprintf(msg, "Log Present Congestion Cost Range [%g, %g]", min_cost, max_cost);
    } else {
        sprintf(msg, "Cost Range [%g, %g]", min_cost, max_cost);
    }
    update_message(msg);

    draw_rr_costs(rr_node_costs, true);
}

static void draw_routing_bb() {
    t_draw_state* draw_state = get_draw_state_vars();

    if (draw_state->show_routing_bb == OPEN) {
        return;
    }

    auto& route_ctx = g_vpr_ctx.routing();
    auto& cluster_ctx = g_vpr_ctx.clustering();

    VTR_ASSERT(draw_state->show_routing_bb != OPEN);
    VTR_ASSERT(draw_state->show_routing_bb < (int)route_ctx.route_bb.size());

    t_draw_coords* draw_coords = get_draw_coords_vars();

    auto net_id = ClusterNetId(draw_state->show_routing_bb);
    const t_bb* bb = &route_ctx.route_bb[net_id];

    //The router considers an RR node to be 'within' the the bounding box if it
    //is *loosely* greater (i.e. greater than or equal) the left/bottom edges, and
    //it is *loosely* less (i.e. less than or equal) the right/top edges.
    //
    //In the graphics we represent this by drawing the BB so that legal RR node start/end points
    //are contained within the drawn box. Since VPR associates each x/y channel location to
    //the right/top of the tile with the same x/y cordinates, this means we draw the box so that:
    //  * The left edge is to the left of the channel at bb xmin (including the channel at xmin)
    //  * The bottom edge is to the below of the channel at bb ymin (including the channel at ymin)
    //  * The right edge is to the right of the channel at bb xmax (including the channel at xmax)
    //  * The top edge is to the right of the channel at bb ymax (including the channel at ymax)
    //Since tile_x/tile_y correspond to the drawing coordinates the block at grid x/y's bottom-left corner
    //this means we need to shift the top/right drawn co-ordinate one tile + channel width right/up so
    //the drawn box contains the top/right channels
    int draw_xlow = draw_coords->tile_x[bb->xmin];
    int draw_ylow = draw_coords->tile_y[bb->ymin];
    int draw_xhigh = draw_coords->tile_x[bb->xmax] + 2 * draw_coords->get_tile_width();
    int draw_yhigh = draw_coords->tile_y[bb->ymax] + 2 * draw_coords->get_tile_height();

    setcolor(RED);
    drawrect(draw_xlow, draw_ylow, draw_xhigh, draw_yhigh);

    t_color fill = SKYBLUE;
    fill.alpha *= 0.3;
    setcolor(fill);
    fillrect(draw_xlow, draw_ylow, draw_xhigh, draw_yhigh);

    draw_routed_net(net_id);

    std::string msg;
    ;
    msg += "Showing BB";
    msg += " (" + std::to_string(bb->xmin) + ", " + std::to_string(bb->ymin) + ", " + std::to_string(bb->xmax) + ", " + std::to_string(bb->ymax) + ")";
    msg += " and routing for net '" + cluster_ctx.clb_nlist.net_name(net_id) + "'";
    msg += " (#" + std::to_string(size_t(net_id)) + ")";
    update_message(msg.c_str());
}

void draw_rr() {
    /* Draws the routing resources that exist in the FPGA, if the user wants *
     * them drawn.                                                           */
    t_draw_state* draw_state = get_draw_state_vars();
    auto& device_ctx = g_vpr_ctx.device();

    if (draw_state->draw_rr_toggle == DRAW_NO_RR || draw_state->draw_rr_toggle == DRAW_MOUSE_OVER_RR) {
        setlinewidth(3);
        drawroute(HIGHLIGHTED);
        setlinewidth(0);
        return;
    }

    setlinestyle(SOLID);

    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
        if (!draw_state->draw_rr_node[inode].node_highlighted) {
            /* If not highlighted node, assign color based on type. */
            switch (device_ctx.rr_nodes[inode].type()) {
                case CHANX:
                case CHANY:
                    draw_state->draw_rr_node[inode].color = DEFAULT_RR_NODE_COLOR;
                    break;
                case OPIN:
                    draw_state->draw_rr_node[inode].color = PINK;
                    break;
                case IPIN:
                    draw_state->draw_rr_node[inode].color = LIGHTSKYBLUE;
                    break;
                default:
                    break;
            }
        }

        /* Now call drawing routines to draw the node. */
        switch (device_ctx.rr_nodes[inode].type()) {
            case SOURCE:
            case SINK:
                break; /* Don't draw. */

            case CHANX:
                draw_rr_chan(inode, draw_state->draw_rr_node[inode].color);
                draw_rr_edges(inode);
                break;

            case CHANY:
                draw_rr_chan(inode, draw_state->draw_rr_node[inode].color);
                draw_rr_edges(inode);
                break;

            case IPIN:
                draw_rr_pin(inode, draw_state->draw_rr_node[inode].color);
                break;

            case OPIN:
                draw_rr_pin(inode, draw_state->draw_rr_node[inode].color);
                draw_rr_edges(inode);
                break;

            default:
                vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                          "in draw_rr: Unexpected rr_node type: %d.\n", device_ctx.rr_nodes[inode].type());
        }
    }

    drawroute(HIGHLIGHTED);
}

static void draw_rr_chan(int inode, const t_color color) {
    auto& device_ctx = g_vpr_ctx.device();

    t_rr_type type = device_ctx.rr_nodes[inode].type();

    VTR_ASSERT(type == CHANX || type == CHANY);

    t_bound_box bound_box = draw_get_rr_chan_bbox(inode);
    e_direction dir = device_ctx.rr_nodes[inode].direction();

    //We assume increasing direction, and swap if needed
    t_point start = bound_box.bottom_left();
    t_point end = bound_box.top_right();
    if (dir == DEC_DIRECTION) {
        std::swap(start, end);
    }

    setcolor(color);
    if (color != DEFAULT_RR_NODE_COLOR) {
        // If wire is highlighted, then draw with thicker linewidth.
        setlinewidth(3);
    }

    drawline(start, end);

    if (color != DEFAULT_RR_NODE_COLOR) {
        // Revert width change
        setlinewidth(0);
    }

    // draw the arrows and small lines iff zoomed in really far.
    if (default_triangle_LOD_screen_area_test() == false) {
        return;
    }

    e_side mux_dir = TOP;
    int coord_min = -1;
    int coord_max = -1;
    if (type == CHANX) {
        coord_min = device_ctx.rr_nodes[inode].xlow();
        coord_max = device_ctx.rr_nodes[inode].xhigh();
        if (dir == INC_DIRECTION) {
            mux_dir = RIGHT;
        } else {
            mux_dir = LEFT;
        }
    } else {
        VTR_ASSERT(type == CHANY);
        coord_min = device_ctx.rr_nodes[inode].ylow();
        coord_max = device_ctx.rr_nodes[inode].yhigh();
        if (dir == INC_DIRECTION) {
            mux_dir = TOP;
        } else {
            mux_dir = BOTTOM;
        }
    }

    //Draw direction indicators at the boundary of each switch block, and label them
    //with the corresponding switch point (see build_switchblocks.c for a description of switch points)
    t_draw_coords* draw_coords = get_draw_coords_vars();
    float arrow_offset = DEFAULT_ARROW_SIZE / 2;
    t_color arrow_color = LIGHTGREY;
    t_color text_color = BLACK;
    for (int k = coord_min; k <= coord_max; ++k) {
        int switchpoint_min = -1;
        int switchpoint_max = -1;
        if (dir == INC_DIRECTION) {
            switchpoint_min = k - coord_min;
            switchpoint_max = switchpoint_min + 1;
        } else {
            switchpoint_min = (coord_max + 1) - k;
            switchpoint_max = switchpoint_min - 1;
        }

        t_point arrow_loc_min;
        t_point arrow_loc_max;
        if (type == CHANX) {
            float sb_xmin = draw_coords->tile_x[k];
            arrow_loc_min = t_point(sb_xmin + arrow_offset, start.y);

            float sb_xmax = draw_coords->tile_x[k] + draw_coords->get_tile_width();
            arrow_loc_max = t_point(sb_xmax - arrow_offset, start.y);

        } else {
            float sb_ymin = draw_coords->tile_y[k];
            arrow_loc_min = t_point(start.x, sb_ymin + arrow_offset);

            float sb_ymax = draw_coords->tile_y[k] + draw_coords->get_tile_height();
            arrow_loc_max = t_point(start.x, sb_ymax - arrow_offset);
        }

        if (switchpoint_min == 0) {
            if (dir != BI_DIRECTION) {
                //Draw a mux at the start of each wire, labelled with it's size (#inputs)
                draw_mux_with_size(start, mux_dir, WIRE_DRAWING_WIDTH, device_ctx.rr_nodes[inode].fan_in());
            }
        } else {
            //Draw arrows and label with switch point
            if (k == coord_min) {
                std::swap(arrow_color, text_color);
            }

            setcolor(arrow_color);
            draw_triangle_along_line(arrow_loc_min, start, end);

            setcolor(text_color);
            t_bound_box bbox(t_point(arrow_loc_min.x - DEFAULT_ARROW_SIZE / 2, arrow_loc_min.y - DEFAULT_ARROW_SIZE / 4),
                             t_point(arrow_loc_min.x + DEFAULT_ARROW_SIZE / 2, arrow_loc_min.y + DEFAULT_ARROW_SIZE / 4));
            drawtext_in(bbox, std::to_string(switchpoint_min));

            if (k == coord_min) {
                //Revert
                std::swap(arrow_color, text_color);
            }
        }

        if (switchpoint_max == 0) {
            if (dir != BI_DIRECTION) {
                //Draw a mux at the start of each wire, labelled with it's size (#inputs)
                draw_mux_with_size(start, mux_dir, WIRE_DRAWING_WIDTH, device_ctx.rr_nodes[inode].fan_in());
            }
        } else {
            //Draw arrows and label with switch point
            if (k == coord_max) {
                std::swap(arrow_color, text_color);
            }

            setcolor(arrow_color);
            draw_triangle_along_line(arrow_loc_max, start, end);

            setcolor(text_color);
            t_bound_box bbox(t_point(arrow_loc_max.x - DEFAULT_ARROW_SIZE / 2, arrow_loc_max.y - DEFAULT_ARROW_SIZE / 4),
                             t_point(arrow_loc_max.x + DEFAULT_ARROW_SIZE / 2, arrow_loc_max.y + DEFAULT_ARROW_SIZE / 4));
            drawtext_in(bbox, std::to_string(switchpoint_max));

            if (k == coord_max) {
                //Revert
                std::swap(arrow_color, text_color);
            }
        }
    }
    setcolor(color); //Ensure color is still set correctly if we drew any arrows/text
}

static void draw_rr_edges(int inode) {
    /* Draws all the edges that the user wants shown between inode and what it *
     * connects to.  inode is assumed to be a CHANX, CHANY, or IPIN.           */
    t_draw_state* draw_state = get_draw_state_vars();
    auto& device_ctx = g_vpr_ctx.device();

    t_rr_type from_type, to_type;
    int to_node, from_ptc_num, to_ptc_num;
    short switch_type;

    from_type = device_ctx.rr_nodes[inode].type();

    if ((draw_state->draw_rr_toggle == DRAW_NODES_RR)
        || (draw_state->draw_rr_toggle == DRAW_NODES_AND_SBOX_RR && from_type == OPIN)) {
        return; /* Nothing to draw. */
    }

    from_ptc_num = device_ctx.rr_nodes[inode].ptc_num();

    for (int iedge = 0, l = device_ctx.rr_nodes[inode].num_edges(); iedge < l; iedge++) {
        to_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge);
        to_type = device_ctx.rr_nodes[to_node].type();
        to_ptc_num = device_ctx.rr_nodes[to_node].ptc_num();
        bool edge_configurable = device_ctx.rr_nodes[inode].edge_is_configurable(iedge);

        switch (from_type) {
            case OPIN:
                switch (to_type) {
                    case CHANX:
                    case CHANY:
                        if (draw_state->draw_rr_node[inode].color == MAGENTA) {
                            // If OPIN was clicked on, set color to fan-out
                            setcolor(draw_state->draw_rr_node[to_node].color);
                        } else if (draw_state->draw_rr_node[to_node].color == MAGENTA) {
                            // If CHANX or CHANY got clicked, set color to fan-in
                            setcolor(draw_state->draw_rr_node[inode].color);
                        } else {
                            setcolor(PINK);
                        }
                        draw_pin_to_chan_edge(inode, to_node);
                        break;
                    case IPIN:
                        if (draw_state->draw_rr_node[inode].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[to_node].color);
                        } else if (draw_state->draw_rr_node[to_node].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[inode].color);
                        } else {
                            setcolor(MEDIUMPURPLE);
                        }
                        draw_pin_to_pin(inode, to_node);
                        break;
                    default:
                        vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                                  "in draw_rr_edges: node %d (type: %d) connects to node %d (type: %d).\n",
                                  inode, from_type, to_node, to_type);
                        break;
                }
                break;

            case CHANX: /* from_type */
                switch (to_type) {
                    case IPIN:
                        if (draw_state->draw_rr_toggle == DRAW_NODES_AND_SBOX_RR) {
                            break;
                        }

                        if (draw_state->draw_rr_node[to_node].node_highlighted && draw_state->draw_rr_node[inode].color == DEFAULT_RR_NODE_COLOR) {
                            // If the IPIN is clicked on, draw connection to all the CHANX
                            // wire segments fanning into the pin. If a CHANX wire is clicked
                            // on, draw only the connection between that wire and the IPIN, with
                            // the pin fanning out from the wire.
                            break;
                        }

                        if (draw_state->draw_rr_node[inode].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[to_node].color);
                        } else if (draw_state->draw_rr_node[to_node].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[inode].color);
                        } else {
                            setcolor(LIGHTSKYBLUE);
                        }
                        draw_pin_to_chan_edge(to_node, inode);
                        break;

                    case CHANX:
                        if (draw_state->draw_rr_node[inode].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[to_node].color);
                        } else if (draw_state->draw_rr_node[to_node].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[inode].color);
                        } else if (!edge_configurable) {
                            setcolor(DARKGREY);
                        } else {
                            setcolor(DARKGREEN);
                        }
                        switch_type = device_ctx.rr_nodes[inode].edge_switch(iedge);
                        draw_chanx_to_chanx_edge(inode, to_node,
                                                 to_ptc_num, switch_type);
                        break;

                    case CHANY:
                        if (draw_state->draw_rr_node[inode].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[to_node].color);
                        } else if (draw_state->draw_rr_node[to_node].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[inode].color);
                        } else if (!edge_configurable) {
                            setcolor(DARKGREY);
                        } else {
                            setcolor(DARKGREEN);
                        }
                        switch_type = device_ctx.rr_nodes[inode].edge_switch(iedge);
                        draw_chanx_to_chany_edge(inode, from_ptc_num, to_node,
                                                 to_ptc_num, FROM_X_TO_Y, switch_type);
                        break;

                    default:
                        vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                                  "in draw_rr_edges: node %d (type: %d) connects to node %d (type: %d).\n",
                                  inode, from_type, to_node, to_type);
                        break;
                }
                break;

            case CHANY: /* from_type */
                switch (to_type) {
                    case IPIN:
                        if (draw_state->draw_rr_toggle == DRAW_NODES_AND_SBOX_RR) {
                            break;
                        }

                        if (draw_state->draw_rr_node[to_node].node_highlighted && draw_state->draw_rr_node[inode].color == DEFAULT_RR_NODE_COLOR) {
                            // If the IPIN is clicked on, draw connection to all the CHANY
                            // wire segments fanning into the pin. If a CHANY wire is clicked
                            // on, draw only the connection between that wire and the IPIN, with
                            // the pin fanning out from the wire.
                            break;
                        }

                        if (draw_state->draw_rr_node[inode].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[to_node].color);
                        } else if (draw_state->draw_rr_node[to_node].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[inode].color);
                        } else {
                            setcolor(LIGHTSKYBLUE);
                        }
                        draw_pin_to_chan_edge(to_node, inode);
                        break;

                    case CHANX:
                        if (draw_state->draw_rr_node[inode].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[to_node].color);
                        } else if (draw_state->draw_rr_node[to_node].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[inode].color);
                        } else if (!edge_configurable) {
                            setcolor(DARKGREY);
                        } else {
                            setcolor(DARKGREEN);
                        }
                        switch_type = device_ctx.rr_nodes[inode].edge_switch(iedge);
                        draw_chanx_to_chany_edge(to_node, to_ptc_num, inode,
                                                 from_ptc_num, FROM_Y_TO_X, switch_type);
                        break;

                    case CHANY:
                        if (draw_state->draw_rr_node[inode].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[to_node].color);
                        } else if (draw_state->draw_rr_node[to_node].color == MAGENTA) {
                            setcolor(draw_state->draw_rr_node[inode].color);
                        } else if (!edge_configurable) {
                            setcolor(DARKGREY);
                        } else {
                            setcolor(DARKGREEN);
                        }
                        switch_type = device_ctx.rr_nodes[inode].edge_switch(iedge);
                        draw_chany_to_chany_edge(inode, to_node,
                                                 to_ptc_num, switch_type);
                        break;

                    default:
                        vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                                  "in draw_rr_edges: node %d (type: %d) connects to node %d (type: %d).\n",
                                  inode, from_type, to_node, to_type);
                        break;
                }
                break;

            default: /* from_type */
                vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                          "draw_rr_edges called with node %d of type %d.\n",
                          inode, from_type);
                break;
        }
    } /* End of for each edge loop */
}

static void draw_x(float x, float y, float size) {
    /* Draws an X centered at (x,y).  The width and height of the X are each    *
     * 2 * size.                                                                */

    drawline(x - size, y + size, x + size, y - size);
    drawline(x - size, y - size, x + size, y + size);
}

static void draw_chanx_to_chany_edge(int chanx_node, int chanx_track, int chany_node, int chany_track, enum e_edge_dir edge_dir, short switch_type) {
    t_draw_state* draw_state = get_draw_state_vars();
    t_draw_coords* draw_coords = get_draw_coords_vars();
    auto& device_ctx = g_vpr_ctx.device();

    /* Draws an edge (SBOX connection) between an x-directed channel and a    *
     * y-directed channel.                                                    */

    float x1, y1, x2, y2;
    t_bound_box chanx_bbox, chany_bbox;
    int chanx_xlow, chany_x, chany_ylow, chanx_y;

    /* Get the coordinates of the CHANX and CHANY segments. */
    chanx_bbox = draw_get_rr_chan_bbox(chanx_node);
    chany_bbox = draw_get_rr_chan_bbox(chany_node);

    /* (x1,y1): point on CHANX segment, (x2,y2): point on CHANY segment. */

    y1 = chanx_bbox.bottom();
    x2 = chany_bbox.left();

    chanx_xlow = device_ctx.rr_nodes[chanx_node].xlow();
    chanx_y = device_ctx.rr_nodes[chanx_node].ylow();
    chany_x = device_ctx.rr_nodes[chany_node].xlow();
    chany_ylow = device_ctx.rr_nodes[chany_node].ylow();

    if (chanx_xlow <= chany_x) { /* Can draw connection going right */
        /* Connection not at end of the CHANX segment. */
        x1 = draw_coords->tile_x[chany_x] + draw_coords->get_tile_width();

        if (device_ctx.rr_nodes[chanx_node].direction() != BI_DIRECTION) {
            if (edge_dir == FROM_X_TO_Y) {
                if ((chanx_track % 2) == 1) { /* If dec wire, then going left */
                    x1 = draw_coords->tile_x[chany_x + 1];
                }
            }
        }

    } else { /* Must draw connection going left. */
        x1 = chanx_bbox.left();
    }

    if (chany_ylow <= chanx_y) { /* Can draw connection going up. */
        /* Connection not at end of the CHANY segment. */
        y2 = draw_coords->tile_y[chanx_y] + draw_coords->get_tile_width();

        if (device_ctx.rr_nodes[chany_node].direction() != BI_DIRECTION) {
            if (edge_dir == FROM_Y_TO_X) {
                if ((chany_track % 2) == 1) { /* If dec wire, then going down */
                    y2 = draw_coords->tile_y[chanx_y + 1];
                }
            }
        }

    } else { /* Must draw connection going down. */
        y2 = chany_bbox.bottom();
    }

    drawline(x1, y1, x2, y2);

    if (draw_state->draw_rr_toggle == DRAW_ALL_RR || draw_state->draw_rr_node[chanx_node].node_highlighted) {
        if (edge_dir == FROM_X_TO_Y) {
            draw_rr_switch(x1, y1, x2, y2, device_ctx.rr_switch_inf[switch_type].buffered(), device_ctx.rr_switch_inf[switch_type].configurable());
        } else {
            draw_rr_switch(x2, y2, x1, y1, device_ctx.rr_switch_inf[switch_type].buffered(), device_ctx.rr_switch_inf[switch_type].configurable());
        }
    }
}

static void draw_chanx_to_chanx_edge(int from_node, int to_node, int to_track, short switch_type) {
    /* Draws a connection between two x-channel segments.  Passing in the track *
     * numbers allows this routine to be used for both rr_graph and routing     *
     * drawing.                                                                 */

    t_draw_state* draw_state = get_draw_state_vars();
    t_draw_coords* draw_coords = get_draw_coords_vars();
    auto& device_ctx = g_vpr_ctx.device();

    float x1, x2, y1, y2;
    t_bound_box from_chan, to_chan;
    int from_xlow, to_xlow, from_xhigh, to_xhigh;

    // Get the coordinates of the channel wires.
    from_chan = draw_get_rr_chan_bbox(from_node);
    to_chan = draw_get_rr_chan_bbox(to_node);

    /* (x1, y1) point on from_node, (x2, y2) point on to_node. */

    y1 = from_chan.bottom();
    y2 = to_chan.bottom();

    from_xlow = device_ctx.rr_nodes[from_node].xlow();
    from_xhigh = device_ctx.rr_nodes[from_node].xhigh();
    to_xlow = device_ctx.rr_nodes[to_node].xlow();
    to_xhigh = device_ctx.rr_nodes[to_node].xhigh();

    if (to_xhigh < from_xlow) { /* From right to left */
        /* UDSD Note by WMF: could never happen for INC wires, unless U-turn. For DEC
         * wires this handles well */
        x1 = from_chan.left();
        x2 = to_chan.right();
    } else if (to_xlow > from_xhigh) { /* From left to right */
        /* UDSD Note by WMF: could never happen for DEC wires, unless U-turn. For INC
         * wires this handles well */
        x1 = from_chan.right();
        x2 = to_chan.left();
    }

    /* Segments overlap in the channel.  Figure out best way to draw.  Have to  *
     * make sure the drawing is symmetric in the from rr and to rr so the edges *
     * will be drawn on top of each other for bidirectional connections.        */

    else {
        if (device_ctx.rr_nodes[to_node].direction() != BI_DIRECTION) {
            /* must connect to to_node's wire beginning at x2 */
            if (to_track % 2 == 0) { /* INC wire starts at leftmost edge */
                VTR_ASSERT(from_xlow < to_xlow);
                x2 = to_chan.left();
                /* since no U-turns from_track must be INC as well */
                x1 = draw_coords->tile_x[to_xlow - 1] + draw_coords->get_tile_width();
            } else { /* DEC wire starts at rightmost edge */
                VTR_ASSERT(from_xhigh > to_xhigh);
                x2 = to_chan.right();
                x1 = draw_coords->tile_x[to_xhigh + 1];
            }
        } else {
            if (to_xlow < from_xlow) { /* Draw from left edge of one to other */
                x1 = from_chan.left();
                x2 = draw_coords->tile_x[from_xlow - 1] + draw_coords->get_tile_width();
            } else if (from_xlow < to_xlow) {
                x1 = draw_coords->tile_x[to_xlow - 1] + draw_coords->get_tile_width();
                x2 = to_chan.left();
            }                                 /* The following then is executed when from_xlow == to_xlow */
            else if (to_xhigh > from_xhigh) { /* Draw from right edge of one to other */
                x1 = from_chan.right();
                x2 = draw_coords->tile_x[from_xhigh + 1];
            } else if (from_xhigh > to_xhigh) {
                x1 = draw_coords->tile_x[to_xhigh + 1];
                x2 = to_chan.right();
            } else { /* Complete overlap: start and end both align. Draw outside the sbox */
                x1 = from_chan.left();
                x2 = from_chan.left() + draw_coords->get_tile_width();
            }
        }
    }

    drawline(x1, y1, x2, y2);

    if (draw_state->draw_rr_toggle == DRAW_ALL_RR || draw_state->draw_rr_node[from_node].node_highlighted) {
        draw_rr_switch(x1, y1, x2, y2, device_ctx.rr_switch_inf[switch_type].buffered(), device_ctx.rr_switch_inf[switch_type].configurable());
    }
}

static void draw_chany_to_chany_edge(int from_node, int to_node, int to_track, short switch_type) {
    t_draw_state* draw_state = get_draw_state_vars();
    t_draw_coords* draw_coords = get_draw_coords_vars();
    auto& device_ctx = g_vpr_ctx.device();

    /* Draws a connection between two y-channel segments.  Passing in the track *
     * numbers allows this routine to be used for both rr_graph and routing     *
     * drawing.                                                                 */

    float x1, x2, y1, y2;
    t_bound_box from_chan, to_chan;
    int from_ylow, to_ylow, from_yhigh, to_yhigh; //, from_x, to_x;

    // Get the coordinates of the channel wires.
    from_chan = draw_get_rr_chan_bbox(from_node);
    to_chan = draw_get_rr_chan_bbox(to_node);

    // from_x = device_ctx.rr_nodes[from_node].xlow();
    // to_x = device_ctx.rr_nodes[to_node].xlow();
    from_ylow = device_ctx.rr_nodes[from_node].ylow();
    from_yhigh = device_ctx.rr_nodes[from_node].yhigh();
    to_ylow = device_ctx.rr_nodes[to_node].ylow();
    to_yhigh = device_ctx.rr_nodes[to_node].yhigh();

    /* (x1, y1) point on from_node, (x2, y2) point on to_node. */

    x1 = from_chan.left();
    x2 = to_chan.left();

    if (to_yhigh < from_ylow) { /* From upper to lower */
        y1 = from_chan.bottom();
        y2 = to_chan.top();
    } else if (to_ylow > from_yhigh) { /* From lower to upper */
        y1 = from_chan.top();
        y2 = to_chan.bottom();
    }

    /* Segments overlap in the channel.  Figure out best way to draw.  Have to  *
     * make sure the drawing is symmetric in the from rr and to rr so the edges *
     * will be drawn on top of each other for bidirectional connections.        */

    /* UDSD Modification by WMF Begin */
    else {
        if (device_ctx.rr_nodes[to_node].direction() != BI_DIRECTION) {
            if (to_track % 2 == 0) { /* INC wire starts at bottom edge */

                y2 = to_chan.bottom();
                /* since no U-turns from_track must be INC as well */
                y1 = draw_coords->tile_y[to_ylow - 1] + draw_coords->get_tile_width();
            } else { /* DEC wire starts at top edge */

                y2 = to_chan.top();
                y1 = draw_coords->tile_y[to_yhigh + 1];
            }
        } else {
            if (to_ylow < from_ylow) { /* Draw from bottom edge of one to other. */
                y1 = from_chan.bottom();
                y2 = draw_coords->tile_y[from_ylow - 1] + draw_coords->get_tile_width();
            } else if (from_ylow < to_ylow) {
                y1 = draw_coords->tile_y[to_ylow - 1] + draw_coords->get_tile_width();
                y2 = to_chan.bottom();
            } else if (to_yhigh > from_yhigh) { /* Draw from top edge of one to other. */
                y1 = from_chan.top();
                y2 = draw_coords->tile_y[from_yhigh + 1];
            } else if (from_yhigh > to_yhigh) {
                y1 = draw_coords->tile_y[to_yhigh + 1];
                y2 = to_chan.top();
            } else { /* Complete overlap: start and end both align. Draw outside the sbox */
                y1 = from_chan.bottom();
                y2 = from_chan.bottom() + draw_coords->get_tile_width();
            }
        }
    }

    /* UDSD Modification by WMF End */
    drawline(x1, y1, x2, y2);

    if (draw_state->draw_rr_toggle == DRAW_ALL_RR || draw_state->draw_rr_node[from_node].node_highlighted) {
        draw_rr_switch(x1, y1, x2, y2, device_ctx.rr_switch_inf[switch_type].buffered(), device_ctx.rr_switch_inf[switch_type].configurable());
    }
}

/* This function computes and returns the boundary coordinates of a channel
 * wire segment. This can be used for drawing a wire or determining if a
 * wire has been clicked on by the user.
 * TODO: Fix this for global routing, currently for detailed only.
 */
static t_bound_box draw_get_rr_chan_bbox(int inode) {
    t_bound_box bound_box;

    t_draw_coords* draw_coords = get_draw_coords_vars();
    auto& device_ctx = g_vpr_ctx.device();

    switch (device_ctx.rr_nodes[inode].type()) {
        case CHANX:
            bound_box.left() = draw_coords->tile_x[device_ctx.rr_nodes[inode].xlow()];
            bound_box.right() = draw_coords->tile_x[device_ctx.rr_nodes[inode].xhigh()]
                                + draw_coords->get_tile_width();
            bound_box.bottom() = draw_coords->tile_y[device_ctx.rr_nodes[inode].ylow()]
                                 + draw_coords->get_tile_width()
                                 + (1. + device_ctx.rr_nodes[inode].ptc_num());
            bound_box.top() = draw_coords->tile_y[device_ctx.rr_nodes[inode].ylow()]
                              + draw_coords->get_tile_width()
                              + (1. + device_ctx.rr_nodes[inode].ptc_num());
            break;
        case CHANY:
            bound_box.left() = draw_coords->tile_x[device_ctx.rr_nodes[inode].xlow()]
                               + draw_coords->get_tile_width()
                               + (1. + device_ctx.rr_nodes[inode].ptc_num());
            bound_box.right() = draw_coords->tile_x[device_ctx.rr_nodes[inode].xlow()]
                                + draw_coords->get_tile_width()
                                + (1. + device_ctx.rr_nodes[inode].ptc_num());
            bound_box.bottom() = draw_coords->tile_y[device_ctx.rr_nodes[inode].ylow()];
            bound_box.top() = draw_coords->tile_y[device_ctx.rr_nodes[inode].yhigh()]
                              + draw_coords->get_tile_width();
            break;
        default:
            // a problem. leave at default value (ie. zeros)
            break;
    }

    return bound_box;
}

static void draw_rr_switch(float from_x, float from_y, float to_x, float to_y, bool buffered, bool configurable) {
    /* Draws a buffer (triangle) or pass transistor (circle) on the edge        *
     * connecting from to to, depending on the status of buffered.  The drawing *
     * is closest to the from_node, since it reflects the switch type of from.  */

    if (!buffered) {
        if (configurable) { /* Draw a circle for a pass transistor */
            float xcen = from_x + (to_x - from_x) / 10.;
            float ycen = from_y + (to_y - from_y) / 10.;
            const float switch_rad = 0.15;
            drawarc(xcen, ycen, switch_rad, 0., 360.);
        } else {
            //Pass, nothing to draw
        }
    } else { /* Buffer */
        if (from_x == to_x || from_y == to_y) {
            //Straight connection
            draw_triangle_along_line(t_point(from_x, from_y), t_point(to_x, to_y), SB_EDGE_STRAIGHT_ARROW_POSITION);
        } else {
            //Turn connection
            draw_triangle_along_line(t_point(from_x, from_y), t_point(to_x, to_y), SB_EDGE_TURN_ARROW_POSITION);
        }
    }
}

static void draw_rr_pin(int inode, const t_color& color) {
    /* Draws an IPIN or OPIN rr_node.  Note that the pin can appear on more    *
     * than one side of a clb.  Also note that this routine can change the     *
     * current color to BLACK.                                                 */

    t_draw_coords* draw_coords = get_draw_coords_vars();

    //exit early unless zoomed in really far.
    if (LOD_screen_area_test_square(draw_coords->pin_size, MIN_VISIBLE_AREA) == false) {
        return;
    }

    float xcen, ycen;
    char str[vtr::bufsize];
    auto& device_ctx = g_vpr_ctx.device();

    int ipin = device_ctx.rr_nodes[inode].ptc_num();

    setcolor(color);

    /* TODO: This is where we can hide fringe physical pins and also identify globals (hide, color, show) */
    draw_get_rr_pin_coords(inode, &xcen, &ycen);
    fillrect(xcen - draw_coords->pin_size, ycen - draw_coords->pin_size,
             xcen + draw_coords->pin_size, ycen + draw_coords->pin_size);
    sprintf(str, "%d", ipin);
    setcolor(BLACK);
    drawtext(xcen, ycen, str, 2 * draw_coords->pin_size, 2 * draw_coords->pin_size);
    setcolor(color);
}

/* Returns the coordinates at which the center of this pin should be drawn. *
 * inode gives the node number, and iside gives the side of the clb or pad  *
 * the physical pin is on.                                                  */
void draw_get_rr_pin_coords(int inode, float* xcen, float* ycen) {
    auto& device_ctx = g_vpr_ctx.device();
    draw_get_rr_pin_coords(&device_ctx.rr_nodes[inode], xcen, ycen);
}

void draw_get_rr_pin_coords(const t_rr_node* node, float* xcen, float* ycen) {
    t_draw_coords* draw_coords = get_draw_coords_vars();

    int i, j, k, ipin, pins_per_sub_tile;
    float offset, xc, yc, step;
    t_type_ptr type;
    auto& device_ctx = g_vpr_ctx.device();

    i = node->xlow();
    j = node->ylow();

    xc = draw_coords->tile_x[i];
    yc = draw_coords->tile_y[j];

    ipin = node->ptc_num();
    type = device_ctx.grid[i][j].type;
    pins_per_sub_tile = type->num_pins / type->capacity;
    k = ipin / pins_per_sub_tile;

    /* Since pins numbers go across all sub_tiles in a block in order
     * we can treat as a block box for this step */

    /* For each sub_tile we need and extra padding space */
    step = (float)(draw_coords->get_tile_width()) / (float)(type->num_pins + type->capacity);
    offset = (ipin + k + 1) * step;

    switch (node->side()) {
        case LEFT:
            yc += offset;
            break;

        case RIGHT:
            xc += draw_coords->get_tile_width();
            yc += offset;
            break;

        case BOTTOM:
            xc += offset;
            break;

        case TOP:
            xc += offset;
            yc += draw_coords->get_tile_width();
            break;

        default:
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                      "in draw_get_rr_pin_coords: Unexpected side %s.\n", node->side_string());
            break;
    }

    *xcen = xc;
    *ycen = yc;
}

static void draw_rr_src_sink(int inode, t_color color) {
    t_draw_coords* draw_coords = get_draw_coords_vars();

    auto& device_ctx = g_vpr_ctx.device();

    int xlow = device_ctx.rr_nodes[inode].xlow();
    int ylow = device_ctx.rr_nodes[inode].ylow();
    int xhigh = device_ctx.rr_nodes[inode].xhigh();
    int yhigh = device_ctx.rr_nodes[inode].yhigh();

    setcolor(color);

    fillrect(draw_coords->get_tile_width() * xlow, draw_coords->get_tile_height() * ylow,
             draw_coords->get_tile_width() * xhigh, draw_coords->get_tile_height() * yhigh);
}

/* Draws the nets in the positions fixed by the router.  If draw_net_type is *
 * ALL_NETS, draw all the nets.  If it is HIGHLIGHTED, draw only the nets    *
 * that are not coloured black (useful for drawing over the rr_graph).       */
static void drawroute(enum e_draw_net_type draw_net_type) {
    /* Next free track in each channel segment if routing is GLOBAL */

    auto& cluster_ctx = g_vpr_ctx.clustering();

    t_draw_state* draw_state = get_draw_state_vars();

    setlinestyle(SOLID);

    /* Now draw each net, one by one.      */

    for (auto net_id : cluster_ctx.clb_nlist.nets()) {
        if (draw_net_type == HIGHLIGHTED && draw_state->net_color[net_id] == BLACK)
            continue;

        draw_routed_net(net_id);
    } /* End for (each net) */
}

static void draw_routed_net(ClusterNetId net_id) {
    auto& route_ctx = g_vpr_ctx.routing();
    auto& cluster_ctx = g_vpr_ctx.clustering();

    t_draw_state* draw_state = get_draw_state_vars();

    if (cluster_ctx.clb_nlist.net_is_ignored(net_id)) /* Don't draw. */
        return;

    if (route_ctx.trace[net_id].head == nullptr) /* No routing.  Skip.  (Allows me to draw */
        return;                                  /* partially complete routes).            */

    t_trace* tptr = route_ctx.trace[net_id].head; /* SOURCE to start */
    int inode = tptr->index;

    std::vector<int> rr_nodes_to_draw;
    rr_nodes_to_draw.push_back(inode);
    for (;;) {
        tptr = tptr->next;
        inode = tptr->index;

        if (draw_if_net_highlighted(net_id)) {
            /* If a net has been highlighted, highlight the whole net in *
             * the same color.											 */
            draw_state->draw_rr_node[inode].color = draw_state->net_color[net_id];
            draw_state->draw_rr_node[inode].node_highlighted = true;
        } else {
            /* If not highlighted, draw the node in default color. */
            draw_state->draw_rr_node[inode].color = DEFAULT_RR_NODE_COLOR;
        }

        rr_nodes_to_draw.push_back(inode);

        if (tptr->iswitch == OPEN) { //End of branch
            draw_partial_route(rr_nodes_to_draw);
            rr_nodes_to_draw.clear();

            /* Skip the next segment */
            tptr = tptr->next;
            if (tptr == nullptr)
                break;
            inode = tptr->index;
            rr_nodes_to_draw.push_back(inode);
        }

    } /* End loop over traceback. */

    draw_partial_route(rr_nodes_to_draw);
}

//Draws the set of rr_nodes specified, using the colors set in draw_state
void draw_partial_route(const std::vector<int>& rr_nodes_to_draw) {
    t_draw_state* draw_state = get_draw_state_vars();
    auto& device_ctx = g_vpr_ctx.device();

    static vtr::OffsetMatrix<int> chanx_track; /* [1..device_ctx.grid.width() - 2][0..device_ctx.grid.height() - 2] */
    static vtr::OffsetMatrix<int> chany_track; /* [0..device_ctx.grid.width() - 2][1..device_ctx.grid.height() - 2] */
    if (draw_state->draw_route_type == GLOBAL) {
        /* Allocate some temporary storage if it's not already available. */
        size_t width = device_ctx.grid.width();
        size_t height = device_ctx.grid.height();
        if (chanx_track.empty()) {
            chanx_track = vtr::OffsetMatrix<int>({{{1, width - 1}, {0, height - 1}}});
        }

        if (chany_track.empty()) {
            chany_track = vtr::OffsetMatrix<int>({{{0, width - 1}, {1, height - 1}}});
        }

        for (size_t i = 1; i < width - 1; i++)
            for (size_t j = 0; j < height - 1; j++)
                chanx_track[i][j] = (-1);

        for (size_t i = 0; i < width - 1; i++)
            for (size_t j = 1; j < height - 1; j++)
                chany_track[i][j] = (-1);
    }

    for (size_t i = 1; i < rr_nodes_to_draw.size(); ++i) {
        int inode = rr_nodes_to_draw[i];
        auto rr_type = device_ctx.rr_nodes[inode].type();

        int prev_node = rr_nodes_to_draw[i - 1];
        auto prev_type = device_ctx.rr_nodes[prev_node].type();

        int iedge = find_edge(prev_node, inode);
        auto switch_type = device_ctx.rr_nodes[prev_node].edge_switch(iedge);

        switch (rr_type) {
            case OPIN: {
                draw_rr_pin(inode, draw_state->draw_rr_node[inode].color);
                break;
            }
            case IPIN: {
                draw_rr_pin(inode, draw_state->draw_rr_node[inode].color);
                if (device_ctx.rr_nodes[prev_node].type() == OPIN) {
                    draw_pin_to_pin(prev_node, inode);
                } else {
                    draw_pin_to_chan_edge(inode, prev_node);
                }
                break;
            }
            case CHANX: {
                if (draw_state->draw_route_type == GLOBAL)
                    chanx_track[device_ctx.rr_nodes[inode].xlow()][device_ctx.rr_nodes[inode].ylow()]++;

                int itrack = get_track_num(inode, chanx_track, chany_track);
                draw_rr_chan(inode, draw_state->draw_rr_node[inode].color);

                switch (prev_type) {
                    case CHANX: {
                        draw_chanx_to_chanx_edge(prev_node, inode,
                                                 itrack, switch_type);
                        break;
                    }
                    case CHANY: {
                        int prev_track = get_track_num(prev_node, chanx_track,
                                                       chany_track);
                        draw_chanx_to_chany_edge(inode, itrack, prev_node,
                                                 prev_track, FROM_Y_TO_X, switch_type);
                        break;
                    }
                    case OPIN: {
                        draw_pin_to_chan_edge(prev_node, inode);
                        break;
                    }
                    default: {
                        vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                                  "Unexpected connection from an rr_node of type %d to one of type %d.\n",
                                  prev_type, rr_type);
                    }
                }

                break;
            }
            case CHANY: {
                if (draw_state->draw_route_type == GLOBAL)
                    chany_track[device_ctx.rr_nodes[inode].xlow()][device_ctx.rr_nodes[inode].ylow()]++;

                int itrack = get_track_num(inode, chanx_track, chany_track);
                draw_rr_chan(inode, draw_state->draw_rr_node[inode].color);

                switch (prev_type) {
                    case CHANX: {
                        int prev_track = get_track_num(prev_node, chanx_track,
                                                       chany_track);
                        draw_chanx_to_chany_edge(prev_node, prev_track, inode,
                                                 itrack, FROM_X_TO_Y, switch_type);
                        break;
                    }
                    case CHANY: {
                        draw_chany_to_chany_edge(prev_node, inode,
                                                 itrack, switch_type);
                        break;
                    }
                    case OPIN: {
                        draw_pin_to_chan_edge(prev_node, inode);

                        break;
                    }
                    default: {
                        vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                                  "Unexpected connection from an rr_node of type %d to one of type %d.\n",
                                  prev_type, rr_type);
                    }
                }

                break;
            }
            default: {
                break;
            }
        }
    }
}

static 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.   */

    int i, j;
    t_rr_type rr_type;
    auto& device_ctx = g_vpr_ctx.device();

    if (get_draw_state_vars()->draw_route_type == DETAILED)
        return (device_ctx.rr_nodes[inode].ptc_num());

    /* GLOBAL route stuff below. */

    rr_type = device_ctx.rr_nodes[inode].type();
    i = device_ctx.rr_nodes[inode].xlow(); /* NB: Global rr graphs must have only unit */
    j = device_ctx.rr_nodes[inode].ylow(); /* length channel segments.                 */

    switch (rr_type) {
        case CHANX:
            return (chanx_track[i][j]);

        case CHANY:
            return (chany_track[i][j]);

        default:
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                      "in get_track_num: Unexpected node type %d for node %d.\n", rr_type, inode);
            return OPEN;
    }
}

/* This helper function determines whether a net has been highlighted. The highlighting
 * could be caused by the user clicking on a routing resource, toggled, or
 * fan-in/fan-out of a highlighted node.
 */
static bool draw_if_net_highlighted(ClusterNetId inet) {
    t_draw_state* draw_state = get_draw_state_vars();

    if (draw_state->net_color[inet] != DEFAULT_RR_NODE_COLOR) {
        return true;
    }

    return false;
}

/* If an rr_node has been clicked on, it will be highlighted in MAGENTA.
 * If so, and toggle nets is selected, highlight the whole net in that colour.
 */
static void highlight_nets(char* message, int hit_node) {
    t_trace* tptr;
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& route_ctx = g_vpr_ctx.routing();

    t_draw_state* draw_state = get_draw_state_vars();

    for (auto net_id : cluster_ctx.clb_nlist.nets()) {
        for (tptr = route_ctx.trace[net_id].head; tptr != nullptr; tptr = tptr->next) {
            if (draw_state->draw_rr_node[tptr->index].color == MAGENTA) {
                draw_state->net_color[net_id] = draw_state->draw_rr_node[tptr->index].color;
                if (tptr->index == hit_node) {
                    std::string orig_msg(message);
                    sprintf(message, "%s  ||  Net: %zu (%s)", orig_msg.c_str(), size_t(net_id),
                            cluster_ctx.clb_nlist.net_name(net_id).c_str());
                }
            } else if (draw_state->draw_rr_node[tptr->index].color == WHITE) {
                // If node is de-selected.
                draw_state->net_color[net_id] = BLACK;
                break;
            }
        }
    }
    update_message(message);
}

/* If an rr_node has been clicked on, it will be either highlighted in MAGENTA,
 * or de-highlighted in WHITE. If highlighted, and toggle_rr is selected, highlight
 * fan_in into the node in blue and fan_out from the node in red. If de-highlighted,
 * de-highlight its fan_in and fan_out.
 */
static void draw_highlight_fan_in_fan_out(const std::set<int>& nodes) {
    t_draw_state* draw_state = get_draw_state_vars();
    auto& device_ctx = g_vpr_ctx.device();

    for (auto node : nodes) {
        /* Highlight the fanout nodes in red. */
        for (int iedge = 0, l = device_ctx.rr_nodes[node].num_edges(); iedge < l; iedge++) {
            int fanout_node = device_ctx.rr_nodes[node].edge_sink_node(iedge);

            if (draw_state->draw_rr_node[node].color == MAGENTA && draw_state->draw_rr_node[fanout_node].color != MAGENTA) {
                // If node is highlighted, highlight its fanout
                draw_state->draw_rr_node[fanout_node].color = DRIVES_IT_COLOR;
                draw_state->draw_rr_node[fanout_node].node_highlighted = true;
            } else if (draw_state->draw_rr_node[node].color == WHITE) {
                // If node is de-highlighted, de-highlight its fanout
                draw_state->draw_rr_node[fanout_node].color = DEFAULT_RR_NODE_COLOR;
                draw_state->draw_rr_node[fanout_node].node_highlighted = false;
            }
        }

        /* Highlight the nodes that can fanin to this node in blue. */
        for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
            for (int iedge = 0, l = device_ctx.rr_nodes[inode].num_edges(); iedge < l; iedge++) {
                int fanout_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge);
                if (fanout_node == node) {
                    if (draw_state->draw_rr_node[node].color == MAGENTA && draw_state->draw_rr_node[inode].color != MAGENTA) {
                        // If node is highlighted, highlight its fanin
                        draw_state->draw_rr_node[inode].color = BLUE;
                        draw_state->draw_rr_node[inode].node_highlighted = true;
                    } else if (draw_state->draw_rr_node[node].color == WHITE) {
                        // If node is de-highlighted, de-highlight its fanin
                        draw_state->draw_rr_node[inode].color = DEFAULT_RR_NODE_COLOR;
                        draw_state->draw_rr_node[inode].node_highlighted = false;
                    }
                }
            }
        }
    }
}

/* This is a helper function for highlight_rr_nodes(). It determines whether
 * a routing resource has been clicked on by computing a bounding box for that
 *  and checking if the mouse click hit inside its bounding box.
 *
 *  It returns the hit RR node's ID (or OPEN if no hit)
 */
static int draw_check_rr_node_hit(float click_x, float click_y) {
    int hit_node = OPEN;
    t_bound_box bound_box;

    t_draw_coords* draw_coords = get_draw_coords_vars();
    auto& device_ctx = g_vpr_ctx.device();

    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
        switch (device_ctx.rr_nodes[inode].type()) {
            case IPIN:
            case OPIN: {
                int i = device_ctx.rr_nodes[inode].xlow();
                int j = device_ctx.rr_nodes[inode].ylow();
                t_type_ptr type = device_ctx.grid[i][j].type;
                int width_offset = device_ctx.grid[i][j].width_offset;
                int height_offset = device_ctx.grid[i][j].height_offset;
                int ipin = device_ctx.rr_nodes[inode].ptc_num();
                float xcen, ycen;

                int iside;
                for (iside = 0; iside < 4; iside++) {
                    // If pin exists on this side of the block, then get pin coordinates
                    if (type->pinloc[width_offset][height_offset][iside][ipin]) {
                        draw_get_rr_pin_coords(inode, &xcen, &ycen);

                        // Now check if we clicked on this pin
                        if (click_x >= xcen - draw_coords->pin_size && click_x <= xcen + draw_coords->pin_size && click_y >= ycen - draw_coords->pin_size && click_y <= ycen + draw_coords->pin_size) {
                            hit_node = inode;
                            return hit_node;
                        }
                    }
                }
                break;
            }
            case CHANX:
            case CHANY: {
                bound_box = draw_get_rr_chan_bbox(inode);

                // Check if we clicked on this wire, with 30%
                // tolerance outside its boundary
                const float tolerance = 0.3;
                if (click_x >= bound_box.left() - tolerance && click_x <= bound_box.right() + tolerance && click_y >= bound_box.bottom() - tolerance && click_y <= bound_box.top() + tolerance) {
                    hit_node = inode;
                    return hit_node;
                }
                break;
            }
            default:
                break;
        }
    }
    return hit_node;
}

static std::set<int> draw_expand_non_configurable_rr_nodes(int from_node) {
    std::set<int> expanded_nodes;
    draw_expand_non_configurable_rr_nodes_recurr(from_node, expanded_nodes);
    return expanded_nodes;
}

static void draw_expand_non_configurable_rr_nodes_recurr(int from_node, std::set<int>& expanded_nodes) {
    auto& device_ctx = g_vpr_ctx.device();

    expanded_nodes.insert(from_node);

    for (int iedge = 0; iedge < device_ctx.rr_nodes[from_node].num_edges(); ++iedge) {
        bool edge_configurable = device_ctx.rr_nodes[from_node].edge_is_configurable(iedge);
        int to_node = device_ctx.rr_nodes[from_node].edge_sink_node(iedge);

        if (!edge_configurable && !expanded_nodes.count(to_node)) {
            draw_expand_non_configurable_rr_nodes_recurr(to_node, expanded_nodes);
        }
    }
}

/* This routine is called when the routing resource graph is shown, and someone
 * clicks outside a block. That click might represent a click on a wire -- we call
 * this routine to determine which wire (if any) was clicked on.  If a wire was
 * clicked upon, we highlight it in Magenta, and its fanout in red.
 */
static bool highlight_rr_nodes(float x, float y) {
    t_draw_state* draw_state = get_draw_state_vars();

    char message[250] = "";

    if (draw_state->draw_rr_toggle == DRAW_NO_RR && !draw_state->show_nets) {
        update_message(draw_state->default_message);
        drawscreen();
        return false; //No rr shown
    }

    // Check which rr_node (if any) was clicked on.
    int hit_node = draw_check_rr_node_hit(x, y);

    if (hit_node != OPEN) {
        auto nodes = draw_expand_non_configurable_rr_nodes(hit_node);
        for (auto node : nodes) {
            if (draw_state->draw_rr_node[node].color != MAGENTA) {
                /* If the node hasn't been clicked on before, highlight it
                 * in magenta.
                 */
                draw_state->draw_rr_node[node].color = MAGENTA;
                draw_state->draw_rr_node[node].node_highlighted = true;

            } else {
                //Using white color to represent de-highlighting (or
                //de-selecting) of node.
                draw_state->draw_rr_node[node].color = WHITE;
                draw_state->draw_rr_node[node].node_highlighted = false;
            }

            //Print info about all nodes to terminal
            VTR_LOG("%s\n", describe_rr_node(node).c_str());
        }

        //Show info about *only* hit node to graphics
        std::string info = describe_rr_node(hit_node);

        sprintf(message, "Selected %s", info.c_str());
        rr_highlight_message = message;

        if (draw_state->draw_rr_toggle != DRAW_NO_RR) {
            // If rr_graph is shown, highlight the fan-in/fan-outs for
            // this node.
            draw_highlight_fan_in_fan_out(nodes);
        }
    } else {
        update_message(draw_state->default_message);
        rr_highlight_message = "";
        drawscreen();
        return false; //No hit
    }

    if (draw_state->show_nets) {
        highlight_nets(message, hit_node);
    } else
        update_message(message);

    drawscreen();
    return true; //Hit
}

static void highlight_blocks(float abs_x, float abs_y, t_event_buttonPressed button_info) {
    /* This routine is called when the user clicks in the graphics area. *
     * It determines if a clb was clicked on.  If one was, it is         *
     * highlighted in green, it's fanin nets and clbs are highlighted in *
     * blue and it's fanout is highlighted in red.  If no clb was        *
     * clicked on (user clicked on white space) any old highlighting is  *
     * removed.  Note that even though global nets are not drawn, their  *
     * fanins and fanouts are highlighted when you click on a block      *
     * attached to them.                                                 */

    t_draw_coords* draw_coords = get_draw_coords_vars();

    char msg[vtr::bufsize];
    ClusterBlockId clb_index = EMPTY_BLOCK_ID;
    auto& device_ctx = g_vpr_ctx.device();
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& place_ctx = g_vpr_ctx.placement();

    /* Control + mouse click to select multiple nets. */
    if (!button_info.ctrl_pressed)
        deselect_all();

    //Check if we hit an rr node
    // Note that we check this before checking for a block, since pins and routing may appear overtop of a multi-width/height block
    if (highlight_rr_nodes(abs_x, abs_y)) {
        return; //Selected an rr node
    }

    /// determine block ///
    t_bound_box clb_bbox(0, 0, 0, 0);

    // iterate over grid x
    for (size_t i = 0; i < device_ctx.grid.width(); ++i) {
        if (draw_coords->tile_x[i] > abs_x) {
            break; // we've gone to far in the x direction
        }
        // iterate over grid y
        for (size_t j = 0; j < device_ctx.grid.height(); ++j) {
            if (draw_coords->tile_y[j] > abs_y) {
                break; // we've gone to far in the y direction
            }
            // iterate over sub_blocks
            const t_grid_tile* grid_tile = &device_ctx.grid[i][j];
            for (int k = 0; k < grid_tile->type->capacity; ++k) {
                clb_index = place_ctx.grid_blocks[i][j].blocks[k];
                if (clb_index != EMPTY_BLOCK_ID) {
                    clb_bbox = draw_coords->get_absolute_clb_bbox(clb_index, cluster_ctx.clb_nlist.block_type(clb_index));
                    if (clb_bbox.intersects(abs_x, abs_y)) {
                        break;
                    } else {
                        clb_index = EMPTY_BLOCK_ID;
                    }
                }
            }
            if (clb_index != EMPTY_BLOCK_ID) {
                break; // we've found something
            }
        }
        if (clb_index != EMPTY_BLOCK_ID) {
            break; // we've found something
        }
    }

    if (clb_index == EMPTY_BLOCK_ID) {
        //Nothing found
        return;
    }

    VTR_ASSERT(clb_index != EMPTY_BLOCK_ID);

    // note: this will clear the selected sub-block if show_blk_internal is 0,
    // or if it doesn't find anything
    t_point point_in_clb = t_point(abs_x, abs_y) - clb_bbox.bottom_left();
    highlight_sub_block(point_in_clb, clb_index, cluster_ctx.clb_nlist.block_pb(clb_index));

    if (get_selected_sub_block_info().has_selection()) {
        t_pb* selected_subblock = get_selected_sub_block_info().get_selected_pb();
        sprintf(msg, "sub-block %s (a \"%s\") selected",
                selected_subblock->name, selected_subblock->pb_graph_node->pb_type->name);
    } else {
        /* Highlight block and fan-in/fan-outs. */
        draw_highlight_blocks_color(cluster_ctx.clb_nlist.block_type(clb_index), clb_index);
        sprintf(msg, "Block #%zu (%s) at (%d, %d) selected.", size_t(clb_index), cluster_ctx.clb_nlist.block_name(clb_index).c_str(), place_ctx.block_locs[clb_index].loc.x, place_ctx.block_locs[clb_index].loc.y);
    }

    update_message(msg);

    drawscreen(); /* Need to erase screen. */
}

static void act_on_mouse_over(float mouse_x, float mouse_y) {
    t_draw_state* draw_state = get_draw_state_vars();

    if (draw_state->draw_rr_toggle != DRAW_NO_RR) {
        int hit_node = draw_check_rr_node_hit(mouse_x, mouse_y);

        if (hit_node != OPEN) {
            //Update message

            std::string info = describe_rr_node(hit_node);
            std::string msg = vtr::string_fmt("Moused over %s", info.c_str());
            update_message(msg.c_str());
        } else {
            //No rr node moused over, reset message
            if (!rr_highlight_message.empty()) {
                update_message(rr_highlight_message.c_str());
            } else {
                update_message(draw_state->default_message);
            }
        }
    }
}

#if defined(X11) && !defined(__MINGW32__)
static void act_on_key_press(char /*key_pressed*/, int keysym) {
    //VTR_LOG("Key press %c (%d)\n", key_pressed, keysym);
    switch (keysym) {
        case XK_Shift_L: {
            float zoom_factor = get_zoom_factor();
            zoom_factor += (zoom_factor - 1.);
            zoom_factor = std::min(8.f, zoom_factor); //Clip maximum zoom factor
            VTR_LOG("Increasing graphics zoom factor to %f\n", zoom_factor);
            set_zoom_factor(zoom_factor);
            break;
        }
        case XK_Control_L: {
            float zoom_factor = get_zoom_factor();
            zoom_factor -= (zoom_factor - 1.) / 2;
            zoom_factor = std::max(1.0001f, zoom_factor); //Clip minimum zoom factor
            VTR_LOG("Decreasing graphics zoom factor to %f\n", zoom_factor);
            set_zoom_factor(zoom_factor);
            break;
        }
        default:
            break; //Unrecognized
    }
}
#else
static void act_on_key_press(char /*key_pressed*/, int /*keysym*/) {
    //Nothing to do
}
#endif

static void draw_highlight_blocks_color(t_type_ptr type, ClusterBlockId blk_id) {
    int k, iclass;
    ClusterBlockId fanblk;

    t_draw_state* draw_state = get_draw_state_vars();
    auto& cluster_ctx = g_vpr_ctx.clustering();

    for (k = 0; k < type->num_pins; k++) { /* Each pin on a CLB */
        ClusterNetId net_id = cluster_ctx.clb_nlist.block_net(blk_id, k);

        if (net_id == ClusterNetId::INVALID())
            continue;

        iclass = type->pin_class[k];

        if (type->class_inf[iclass].type == DRIVER) { /* Fanout */
            if (draw_state->block_color[blk_id] == SELECTED_COLOR) {
                /* If block already highlighted, de-highlight the fanout. (the deselect case)*/
                draw_state->net_color[net_id] = BLACK;
                for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
                    fanblk = cluster_ctx.clb_nlist.pin_block(pin_id);
                    draw_reset_blk_color(fanblk);
                }
            } else {
                /* Highlight the fanout */
                draw_state->net_color[net_id] = DRIVES_IT_COLOR;
                for (auto pin_id : cluster_ctx.clb_nlist.net_sinks(net_id)) {
                    fanblk = cluster_ctx.clb_nlist.pin_block(pin_id);
                    draw_state->block_color[fanblk] = DRIVES_IT_COLOR;
                }
            }
        } else { /* This net is fanin to the block. */
            if (draw_state->block_color[blk_id] == SELECTED_COLOR) {
                /* If block already highlighted, de-highlight the fanin. (the deselect case)*/
                draw_state->net_color[net_id] = BLACK;
                fanblk = cluster_ctx.clb_nlist.net_driver_block(net_id); /* DRIVER to net */
                draw_reset_blk_color(fanblk);
            } else {
                /* Highlight the fanin */
                draw_state->net_color[net_id] = DRIVEN_BY_IT_COLOR;
                fanblk = cluster_ctx.clb_nlist.net_driver_block(net_id); /* DRIVER to net */
                draw_state->block_color[fanblk] = DRIVEN_BY_IT_COLOR;
            }
        }
    }

    if (draw_state->block_color[blk_id] == SELECTED_COLOR) {
        /* If block already highlighted, de-highlight the selected block. */
        draw_reset_blk_color(blk_id);
    } else {
        /* Highlight the selected block. */
        draw_state->block_color[blk_id] = SELECTED_COLOR;
    }
}

static void deselect_all() {
    // Sets the color of all clbs, nets and rr_nodes to the default.
    // as well as clearing the highlighed sub-block

    t_draw_state* draw_state = get_draw_state_vars();
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& device_ctx = g_vpr_ctx.device();

    /* Create some colour highlighting */
    for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
        draw_reset_blk_color(blk_id);
    }

    for (auto net_id : cluster_ctx.clb_nlist.nets())
        draw_state->net_color[net_id] = BLACK;

    for (size_t i = 0; i < device_ctx.rr_nodes.size(); i++) {
        draw_state->draw_rr_node[i].color = DEFAULT_RR_NODE_COLOR;
        draw_state->draw_rr_node[i].node_highlighted = false;
    }

    get_selected_sub_block_info().clear();
}

static void draw_reset_blk_color(ClusterBlockId blk_id) {
    t_draw_state* draw_state = get_draw_state_vars();
    auto& cluster_ctx = g_vpr_ctx.clustering();

    draw_state->block_color[blk_id] = get_block_type_color(cluster_ctx.clb_nlist.block_type(blk_id));
}

/**
 * Draws a small triange, at a position along a line from 'start' to 'end'.
 *
 * 'relative_position' [0., 1] defines the triangles position relative to 'start'.
 *
 * A 'relative_position' of 0. draws the triangle centered at 'start'.
 * A 'relative_position' of 1. draws the triangle centered at 'end'.
 * Fractional values draw the triangle along the line
 */
void draw_triangle_along_line(t_point start, t_point end, float relative_position, float arrow_size) {
    VTR_ASSERT(relative_position >= 0. && relative_position <= 1.);
    float xdelta = end.x - start.x;
    float ydelta = end.y - start.y;

    float xtri = start.x + xdelta * relative_position;
    float ytri = start.y + ydelta * relative_position;

    draw_triangle_along_line(xtri, ytri, start.x, end.x, start.y, end.y, arrow_size);
}

/* Draws a trangle with it's center at loc, and of length & width
 * arrow_size, rotated such that it points in the direction
 * of the directed line segment start -> end.
 */
void draw_triangle_along_line(t_point loc, t_point start, t_point end, float arrow_size) {
    draw_triangle_along_line(loc.x, loc.y, start.x, end.x, start.y, end.y, arrow_size);
}

/**
 * Draws a trangle with it's center at (xend, yend), and of length & width
 * arrow_size, rotated such that it points in the direction
 * of the directed line segment (x1, y1) -> (x2, y2).
 *
 * Note that the parameters are in a strange order
 */
void draw_triangle_along_line(float xend, float yend, float x1, float x2, float y1, float y2, float arrow_size) {
    float switch_rad = arrow_size / 2;
    float xdelta, ydelta;
    float magnitude;
    float xunit, yunit;
    float xbaseline, ybaseline;
    t_point poly[3];

    xdelta = x2 - x1;
    ydelta = y2 - y1;
    magnitude = sqrt(xdelta * xdelta + ydelta * ydelta);

    xunit = xdelta / magnitude;
    yunit = ydelta / magnitude;

    poly[0].x = xend + xunit * switch_rad;
    poly[0].y = yend + yunit * switch_rad;
    xbaseline = xend - xunit * switch_rad;
    ybaseline = yend - yunit * switch_rad;
    poly[1].x = xbaseline + yunit * switch_rad;
    poly[1].y = ybaseline - xunit * switch_rad;
    poly[2].x = xbaseline - yunit * switch_rad;
    poly[2].y = ybaseline + xunit * switch_rad;

    fillpoly(poly, 3);
}

static inline bool LOD_screen_area_test_square(float width, float screen_area_threshold) {
    //Since world coordinates get clipped when converted to screen (at high zoom levels),
    //we can not pick an arbitrary world root coordinate for the rectange we want to test,
    //as clipping could cause it's area to go to zero when we convert from world to screen
    //coordinates.
    //
    //Instead we specify an on-screen location for the rectangle we plan to test
    t_point lower_left = scrn_to_world(t_point(0., 0.)); //Pick one corner of the screen

    //Offset by the width
    t_point upper_right = lower_left;
    upper_right.offset(width, width);

    t_bound_box world_rect = t_bound_box(lower_left, upper_right);

    return LOD_screen_area_test(world_rect, screen_area_threshold);
}

static inline bool default_triangle_LOD_screen_area_test() {
    return triangle_LOD_screen_area_test(DEFAULT_ARROW_SIZE);
}

static inline bool triangle_LOD_screen_area_test(float arrow_size) {
    return LOD_screen_area_test_square(arrow_size * 0.66, MIN_VISIBLE_AREA);
}

static void draw_pin_to_chan_edge(int pin_node, int chan_node) {
    /* This routine draws an edge from the pin_node to the chan_node (CHANX or   *
     * CHANY).  The connection is made to the nearest end of the track instead   *
     * of perpundicular to the track to symbolize a single-drive connection.     */

    /* TODO: Fix this for global routing, currently for detailed only */

    t_draw_coords* draw_coords = get_draw_coords_vars();
    auto& device_ctx = g_vpr_ctx.device();

    const t_rr_node& pin_rr = device_ctx.rr_nodes[pin_node];
    const t_rr_node& chan_rr = device_ctx.rr_nodes[chan_node];

    const t_grid_tile& grid_tile = device_ctx.grid[pin_rr.xlow()][pin_rr.ylow()];
    t_type_ptr grid_type = grid_tile.type;

    VTR_ASSERT_MSG(grid_type->pinloc[grid_tile.width_offset][grid_tile.height_offset][pin_rr.side()][pin_rr.pin_num()],
                   "Pin coordinates should match block type pin locations");

    float draw_pin_offset;
    if (pin_rr.side() == TOP || pin_rr.side() == RIGHT) {
        draw_pin_offset = draw_coords->pin_size;
    } else {
        VTR_ASSERT(pin_rr.side() == BOTTOM || pin_rr.side() == LEFT);
        draw_pin_offset = -draw_coords->pin_size;
    }

    float x1 = 0, y1 = 0;
    draw_get_rr_pin_coords(pin_node, &x1, &y1);

    t_bound_box chan_bbox = draw_get_rr_chan_bbox(chan_node);

    float x2 = 0, y2 = 0;
    switch (chan_rr.type()) {
        case CHANX: {
            y1 += draw_pin_offset;
            y2 = chan_bbox.bottom();
            x2 = x1;
            if (is_opin(pin_rr.pin_num(), grid_type)) {
                if (chan_rr.direction() == INC_DIRECTION) {
                    x2 = chan_bbox.left();
                } else if (chan_rr.direction() == DEC_DIRECTION) {
                    x2 = chan_bbox.right();
                }
            }
            break;
        }
        case CHANY: {
            x1 += draw_pin_offset;
            x2 = chan_bbox.left();
            y2 = y1;
            if (is_opin(pin_rr.pin_num(), grid_type)) {
                if (chan_rr.direction() == INC_DIRECTION) {
                    y2 = chan_bbox.bottom();
                } else if (chan_rr.direction() == DEC_DIRECTION) {
                    y2 = chan_bbox.top();
                }
            }
            break;
        }
        default: {
            vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
                      "in draw_pin_to_chan_edge: Invalid channel node %d.\n", chan_node);
        }
    }

    drawline(x1, y1, x2, y2);

    //don't draw the ex, or triangle unless zoomed in really far
    if (chan_rr.direction() == BI_DIRECTION || !is_opin(pin_rr.pin_num(), grid_type)) {
        if (LOD_screen_area_test_square(draw_coords->pin_size * 1.3, MIN_VISIBLE_AREA) == true) {
            draw_x(x2, y2, 0.7 * draw_coords->pin_size);
        }
    } else {
        if (default_triangle_LOD_screen_area_test() == true) {
            float xend = x2 + (x1 - x2) / 10.;
            float yend = y2 + (y1 - y2) / 10.;
            draw_triangle_along_line(xend, yend, x1, x2, y1, y2);
        }
    }
}

static void draw_pin_to_pin(int opin_node, int ipin_node) {
    /* This routine draws an edge from the opin rr node to the ipin rr node */
    auto& device_ctx = g_vpr_ctx.device();
    VTR_ASSERT(device_ctx.rr_nodes[opin_node].type() == OPIN);
    VTR_ASSERT(device_ctx.rr_nodes[ipin_node].type() == IPIN);

    float x1 = 0, y1 = 0;
    draw_get_rr_pin_coords(opin_node, &x1, &y1);

    float x2 = 0, y2 = 0;
    draw_get_rr_pin_coords(ipin_node, &x2, &y2);

    drawline(x1, y1, x2, y2);

    if (default_triangle_LOD_screen_area_test() == true) {
        float xend = x2 + (x1 - x2) / 10.;
        float yend = y2 + (y1 - y2) / 10.;
        draw_triangle_along_line(xend, yend, x1, x2, y1, y2);
    }
}

static inline void draw_mux_with_size(t_point origin, e_side orientation, float height, int size) {
    setcolor(YELLOW);
    auto bounds = draw_mux(origin, orientation, height);

    setcolor(BLACK);
    drawtext_in(bounds, std::to_string(size));
}

//Draws a mux
static inline t_bound_box draw_mux(t_point origin, e_side orientation, float height) {
    return draw_mux(origin, orientation, height, 0.4 * height, 0.6);
}

//Draws a mux, height/width define the bounding box, scale [0.,1.] controls the slope of the muxes sides
static inline t_bound_box draw_mux(t_point origin, e_side orientation, float height, float width, float scale) {
    std::array<t_point, 4> mux_polygon;

    switch (orientation) {
        case TOP:
            //Clock-wise from bottom left
            mux_polygon[0] = t_point(origin.x - height / 2, origin.y - width / 2);
            mux_polygon[1] = t_point(origin.x - (scale * height) / 2, origin.y + width / 2);
            mux_polygon[2] = t_point(origin.x + (scale * height) / 2, origin.y + width / 2);
            mux_polygon[3] = t_point(origin.x + height / 2, origin.y - width / 2);
            break;
        case BOTTOM:
            //Clock-wise from bottom left
            mux_polygon[0] = t_point(origin.x - (scale * height) / 2, origin.y - width / 2);
            mux_polygon[1] = t_point(origin.x - height / 2, origin.y + width / 2);
            mux_polygon[2] = t_point(origin.x + height / 2, origin.y + width / 2);
            mux_polygon[3] = t_point(origin.x + (scale * height) / 2, origin.y - width / 2);
            break;
        case LEFT:
            //Clock-wise from bottom left
            mux_polygon[0] = t_point(origin.x - width / 2, origin.y - (scale * height) / 2);
            mux_polygon[1] = t_point(origin.x - width / 2, origin.y + (scale * height) / 2);
            mux_polygon[2] = t_point(origin.x + width / 2, origin.y + height / 2);
            mux_polygon[3] = t_point(origin.x + width / 2, origin.y - height / 2);
            break;
        case RIGHT:
            //Clock-wise from bottom left
            mux_polygon[0] = t_point(origin.x - width / 2, origin.y - height / 2);
            mux_polygon[1] = t_point(origin.x - width / 2, origin.y + height / 2);
            mux_polygon[2] = t_point(origin.x + width / 2, origin.y + (scale * height) / 2);
            mux_polygon[3] = t_point(origin.x + width / 2, origin.y - (scale * height) / 2);
            break;

        default:
            VTR_ASSERT_MSG(false, "Unrecognized orientation");
    }

    fillpoly(mux_polygon.data(), mux_polygon.size());

    t_point min = mux_polygon[0];
    t_point max = mux_polygon[0];
    for (const auto& point : mux_polygon) {
        min.x = std::min(min.x, point.x);
        min.y = std::min(min.y, point.y);
        max.x = std::max(max.x, point.x);
        max.y = std::max(max.y, point.y);
    }

    return t_bound_box(min, max);
}

t_point tnode_draw_coord(tatum::NodeId node) {
    auto& atom_ctx = g_vpr_ctx.atom();

    AtomPinId pin = atom_ctx.lookup.tnode_atom_pin(node);
    return atom_pin_draw_coord(pin);
}

t_point atom_pin_draw_coord(AtomPinId pin) {
    auto& atom_ctx = g_vpr_ctx.atom();

    AtomBlockId blk = atom_ctx.nlist.pin_block(pin);
    ClusterBlockId clb_index = atom_ctx.lookup.atom_clb(blk);
    const t_pb_graph_node* pg_gnode = atom_ctx.lookup.atom_pb_graph_node(blk);

    t_draw_coords* draw_coords = get_draw_coords_vars();
    t_bound_box pb_bbox = draw_coords->get_absolute_pb_bbox(clb_index, pg_gnode);

    //We place each atom pin inside it's pb bounding box
    //and distribute the pins along it's vertical centre line
    const float FRACTION_USABLE_WIDTH = 0.8;
    float width = pb_bbox.get_width();
    float usable_width = width * FRACTION_USABLE_WIDTH;
    float x_offset = pb_bbox.left() + width * (1 - FRACTION_USABLE_WIDTH) / 2;

    int pin_index, pin_total;
    find_pin_index_at_model_scope(pin, blk, &pin_index, &pin_total);

    const t_point point = {
        x_offset + usable_width * pin_index / ((float)pin_total),
        pb_bbox.get_ycenter()};

    return point;
}

static void draw_crit_path() {
    tatum::TimingPathCollector path_collector;

    t_draw_state* draw_state = get_draw_state_vars();
    auto& timing_ctx = g_vpr_ctx.timing();

    if (draw_state->show_crit_path == DRAW_NO_CRIT_PATH) {
        return;
    }

    if (!draw_state->setup_timing_info) {
        return; //No timing to draw
    }

    //Get the worst timing path
    auto paths = path_collector.collect_worst_setup_timing_paths(*timing_ctx.graph, *(draw_state->setup_timing_info->setup_analyzer()), 1);
    tatum::TimingPath path = paths[0];

    //Walk through the timing path drawing each edge
    tatum::NodeId prev_node;
    float prev_arr_time = std::numeric_limits<float>::quiet_NaN();
    int i = 0;
    for (tatum::TimingPathElem elem : path.data_arrival_path().elements()) {
        tatum::NodeId node = elem.node();
        float arr_time = elem.tag().time();

        if (prev_node) {
            //We draw each 'edge' in a different color, this allows users to identify the stages and
            //any routing which corresponds to the edge
            //
            //We pick colors from the kelly max-contrast list, for long paths there may be repeats
            t_color color = kelly_max_contrast_colors[i++ % kelly_max_contrast_colors.size()];

            float delay = arr_time - prev_arr_time;
            if (draw_state->show_crit_path == DRAW_CRIT_PATH_FLYLINES || draw_state->show_crit_path == DRAW_CRIT_PATH_FLYLINES_DELAYS) {
                setcolor(color);
                setlinestyle(SOLID);
                draw_flyline_timing_edge(tnode_draw_coord(prev_node), tnode_draw_coord(node), delay);
            } else {
                VTR_ASSERT(draw_state->show_crit_path != DRAW_NO_CRIT_PATH);

                //Draw the routed version of the timing edge
                draw_routed_timing_edge(prev_node, node, delay, color);
            }
        }
        prev_node = node;
        prev_arr_time = arr_time;
    }
}

static void draw_flyline_timing_edge(t_point start, t_point end, float incr_delay) {
    drawline(start, end);
    draw_triangle_along_line(start, end, 0.95, 40 * DEFAULT_ARROW_SIZE);
    draw_triangle_along_line(start, end, 0.05, 40 * DEFAULT_ARROW_SIZE);

    bool draw_delays = (get_draw_state_vars()->show_crit_path == DRAW_CRIT_PATH_FLYLINES_DELAYS
                        || get_draw_state_vars()->show_crit_path == DRAW_CRIT_PATH_ROUTING_DELAYS);
    if (draw_delays) {
        //Determine the strict bounding box based on the lines start/end
        float min_x = std::min(start.x, end.x);
        float max_x = std::max(start.x, end.x);
        float min_y = std::min(start.y, end.y);
        float max_y = std::max(start.y, end.y);

        //If we have a nearly horizontal/vertical line the bbox is too
        //small to draw the text, so widen it by a tile (i.e. CLB) width
        float tile_width = get_draw_coords_vars()->get_tile_width();
        if (max_x - min_x < tile_width) {
            max_x += tile_width / 2;
            min_x -= tile_width / 2;
        }
        if (max_y - min_y < tile_width) {
            max_y += tile_width / 2;
            min_y -= tile_width / 2;
        }

        //TODO: draw the delays nicer
        //   * rotate to match edge
        //   * offset from line
        //   * track visible in window
        t_bound_box text_bbox(min_x, min_y, max_x, max_y);

        std::stringstream ss;
        ss.precision(3);
        ss << 1e9 * incr_delay; //In nanoseconds
        std::string incr_delay_str = ss.str();

        drawtext_in(text_bbox, incr_delay_str.c_str());
    }
}

static void draw_routed_timing_edge(tatum::NodeId start_tnode, tatum::NodeId end_tnode, float incr_delay, t_color color) {
    draw_routed_timing_edge_connection(start_tnode, end_tnode, color);

    setlinestyle(DASHED);
    setlinewidth(3);
    setcolor(color);

    draw_flyline_timing_edge(tnode_draw_coord(start_tnode), tnode_draw_coord(end_tnode), incr_delay);

    setlinewidth(0);
    setlinestyle(SOLID);
}

//Collect all the drawing locations associated with the timing edge between start and end
static void draw_routed_timing_edge_connection(tatum::NodeId src_tnode, tatum::NodeId sink_tnode, t_color color) {
    auto& atom_ctx = g_vpr_ctx.atom();
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& timing_ctx = g_vpr_ctx.timing();

    AtomPinId atom_src_pin = atom_ctx.lookup.tnode_atom_pin(src_tnode);
    AtomPinId atom_sink_pin = atom_ctx.lookup.tnode_atom_pin(sink_tnode);

    std::vector<t_point> points;
    points.push_back(atom_pin_draw_coord(atom_src_pin));

    tatum::EdgeId tedge = timing_ctx.graph->find_edge(src_tnode, sink_tnode);
    tatum::EdgeType edge_type = timing_ctx.graph->edge_type(tedge);

    ClusterNetId net_id = ClusterNetId::INVALID();

    //We currently only trace interconnect edges in detail, and treat all others
    //as flylines
    if (edge_type == tatum::EdgeType::INTERCONNECT) {
        //All atom pins are implemented inside CLBs, so next hop is to the top-level CLB pins

        //TODO: most of this code is highly similar to code in PostClusterDelayCalculator, refactor
        //      into a common method for walking the clustered netlist, this would also (potentially)
        //      allow us to grab the component delays
        AtomBlockId atom_src_block = atom_ctx.nlist.pin_block(atom_src_pin);
        AtomBlockId atom_sink_block = atom_ctx.nlist.pin_block(atom_sink_pin);

        ClusterBlockId clb_src_block = atom_ctx.lookup.atom_clb(atom_src_block);
        VTR_ASSERT(clb_src_block != ClusterBlockId::INVALID());
        ClusterBlockId clb_sink_block = atom_ctx.lookup.atom_clb(atom_sink_block);
        VTR_ASSERT(clb_sink_block != ClusterBlockId::INVALID());

        const t_pb_graph_pin* sink_gpin = atom_ctx.lookup.atom_pin_pb_graph_pin(atom_sink_pin);
        VTR_ASSERT(sink_gpin);

        int sink_pb_route_id = sink_gpin->pin_count_in_cluster;

        int sink_block_pin_index = -1;
        int sink_net_pin_index = -1;

        std::tie(net_id, sink_block_pin_index, sink_net_pin_index) = find_pb_route_clb_input_net_pin(clb_sink_block, sink_pb_route_id);
        if (net_id != ClusterNetId::INVALID() && sink_block_pin_index != -1 && sink_net_pin_index != -1) {
            //Connection leaves the CLB
            //Now that we have the CLB source and sink pins, we need to grab all the points on the routing connecting the pins
            VTR_ASSERT(cluster_ctx.clb_nlist.net_driver_block(net_id) == clb_src_block);

            auto routed_rr_nodes = trace_routed_connection_rr_nodes(net_id, 0, sink_net_pin_index);

            //Mark all the nodes highlighted
            t_draw_state* draw_state = get_draw_state_vars();
            for (int inode : routed_rr_nodes) {
                draw_state->draw_rr_node[inode].color = color;
            }

            draw_partial_route(routed_rr_nodes);
        } else {
            //Connection entirely within the CLB, we don't draw the internal routing so treat it as a fly-line
            VTR_ASSERT(clb_src_block == clb_sink_block);
        }
    }

    points.push_back(atom_pin_draw_coord(atom_sink_pin));
}

//Returns the set of rr nodes which connect driver to sink
static std::vector<int> trace_routed_connection_rr_nodes(const ClusterNetId net_id, const int driver_pin, const int sink_pin) {
    auto& route_ctx = g_vpr_ctx.routing();

    bool allocated_route_tree_structs = alloc_route_tree_timing_structs(true); //Needed for traceback_to_route_tree

    //Conver the traceback into an easily search-able
    t_rt_node* rt_root = traceback_to_route_tree(net_id);

    VTR_ASSERT(rt_root && rt_root->inode == route_ctx.net_rr_terminals[net_id][driver_pin]);

    int sink_rr_node = route_ctx.net_rr_terminals[net_id][sink_pin];

    std::vector<int> rr_nodes_on_path;

    //Collect the rr nodes
    trace_routed_connection_rr_nodes_recurr(rt_root, sink_rr_node, rr_nodes_on_path);

    //Traced from sink to source, but we want to draw from source to sink
    std::reverse(rr_nodes_on_path.begin(), rr_nodes_on_path.end());

    if (allocated_route_tree_structs) {
        clear_rr_node_to_rt_node(); //Clean-up
        free_route_tree_timing_structs();
        //See discussion in route_tree_timing.cpp on clear_rr_node_to_rt_node usage.
    }
    return rr_nodes_on_path;
}

//Helper function for trace_routed_connection_rr_nodes
//Adds the rr nodes linking rt_node to sink_rr_node to rr_nodes_on_path
//Returns true if rt_node is on the path
bool trace_routed_connection_rr_nodes_recurr(const t_rt_node* rt_node, int sink_rr_node, std::vector<int>& rr_nodes_on_path) {
    //DFS from the current rt_node to the sink_rr_node, when the sink is found trace back the used rr nodes

    if (rt_node->inode == sink_rr_node) {
        rr_nodes_on_path.push_back(sink_rr_node);
        return true;
    }

    for (t_linked_rt_edge* edge = rt_node->u.child_list; edge != nullptr; edge = edge->next) {
        t_rt_node* child_rt_node = edge->child;
        VTR_ASSERT(child_rt_node);

        bool on_path_to_sink = trace_routed_connection_rr_nodes_recurr(child_rt_node, sink_rr_node, rr_nodes_on_path);

        if (on_path_to_sink) {
            rr_nodes_on_path.push_back(rt_node->inode);
            return true;
        }
    }

    return false; //Not on path to sink
}

//Find the edge between two rr nodes
static int find_edge(int prev_inode, int inode) {
    auto& device_ctx = g_vpr_ctx.device();
    for (int iedge = 0; iedge < device_ctx.rr_nodes[prev_inode].num_edges(); ++iedge) {
        if (device_ctx.rr_nodes[prev_inode].edge_sink_node(iedge) == inode) {
            return iedge;
        }
    }
    VTR_ASSERT(false);
    return OPEN;
}

t_color to_t_color(vtr::Color<float> color) {
    return t_color(color.r * 255, color.g * 255, color.b * 255);
}

static void draw_color_map_legend(const vtr::ColorMap& cmap) {
    constexpr float LEGEND_WIDTH_FAC = 0.075;
    constexpr float LEGEND_VERT_OFFSET_FAC = 0.05;
    constexpr float TEXT_OFFSET = 10;
    constexpr size_t NUM_COLOR_POINTS = 1000;

    set_coordinate_system(GL_SCREEN);
    t_bound_box visible_screen = get_visible_screen();

    float screen_width = visible_screen.get_width();
    float vert_offset = visible_screen.get_height() * LEGEND_VERT_OFFSET_FAC;
    float legend_width = std::min<int>(LEGEND_WIDTH_FAC * screen_width, 100);

    t_bound_box legend(visible_screen.left(), visible_screen.bottom() + vert_offset, visible_screen.left() + legend_width, visible_screen.top() - vert_offset);

    float range = cmap.max() - cmap.min();
    float height_incr = legend.get_height() / float(NUM_COLOR_POINTS);
    for (size_t i = 0; i < NUM_COLOR_POINTS; ++i) {
        float val = cmap.min() + (float(i) / NUM_COLOR_POINTS) * range;
        t_color color = to_t_color(cmap.color(val));

        t_bound_box cbox = {legend.left(), legend.bottom() + i * height_incr,
                            legend.right(), legend.bottom() + (i + 1) * height_incr};
        setcolor(color);
        fillrect(cbox);
    }

    setcolor(BLACK);

    //Min mark
    std::string str = vtr::string_fmt("%.3g", cmap.min());
    drawtext(legend.get_xcenter(), legend.bottom() + TEXT_OFFSET, str.c_str());

    //Mid marker
    str = vtr::string_fmt("%.3g", cmap.min() + (cmap.range() / 2.));
    drawtext(legend.get_xcenter(), legend.get_ycenter(), str.c_str());

    //Max marker
    str = vtr::string_fmt("%.3g", cmap.max());
    drawtext(legend.get_xcenter(), legend.top() - TEXT_OFFSET, str.c_str());

    setcolor(BLACK);
    drawrect(legend);

    set_coordinate_system(GL_WORLD);
}

t_color get_block_type_color(t_type_ptr type) {
    //Wrap around if there are too many blocks
    // This ensures we support an arbitrary number of types,
    // although the colours may repeat
    t_color color = block_type_colors[type->index % block_type_colors.size()];

    return color;
}

//Lightens a color's luminance [0, 1] by an aboslute 'amount'
t_color lighten_color(t_color color, float amount) {
    constexpr double MAX_LUMINANCE = 0.95; //Clip luminance so it doesn't go full white
    auto hsl = color2hsl(color);

    hsl.l = std::max(0., std::min(MAX_LUMINANCE, hsl.l + amount));

    return hsl2color(hsl);
}

static void draw_block_pin_util() {
    t_draw_state* draw_state = get_draw_state_vars();
    if (draw_state->show_blk_pin_util == DRAW_NO_BLOCK_PIN_UTIL) {
        return;
    }

    auto& device_ctx = g_vpr_ctx.device();
    auto& cluster_ctx = g_vpr_ctx.clustering();

    std::map<t_type_ptr, size_t> total_input_pins;
    std::map<t_type_ptr, size_t> total_output_pins;
    for (int itype = 0; itype < device_ctx.num_block_types; ++itype) {
        t_type_ptr type = &device_ctx.block_types[itype];
        if (is_empty_type(type)) continue;

        t_pb_type* pb_type = type->pb_type;

        total_input_pins[type] = pb_type->num_input_pins + pb_type->num_clock_pins;
        total_output_pins[type] = pb_type->num_output_pins;
    }

    auto blks = cluster_ctx.clb_nlist.blocks();
    vtr::vector<ClusterBlockId, float> pin_util(blks.size());
    for (auto blk : blks) {
        auto type = cluster_ctx.clb_nlist.block_type(blk);

        if (draw_state->show_blk_pin_util == DRAW_BLOCK_PIN_UTIL_TOTAL) {
            pin_util[blk] = cluster_ctx.clb_nlist.block_pins(blk).size() / float(total_input_pins[type] + total_output_pins[type]);
        } else if (draw_state->show_blk_pin_util == DRAW_BLOCK_PIN_UTIL_INPUTS) {
            pin_util[blk] = (cluster_ctx.clb_nlist.block_input_pins(blk).size() + cluster_ctx.clb_nlist.block_clock_pins(blk).size()) / float(total_input_pins[type]);
        } else if (draw_state->show_blk_pin_util == DRAW_BLOCK_PIN_UTIL_OUTPUTS) {
            pin_util[blk] = (cluster_ctx.clb_nlist.block_output_pins(blk).size()) / float(total_output_pins[type]);
        } else {
            VTR_ASSERT(false);
        }
    }

    std::unique_ptr<vtr::ColorMap> cmap = std::make_unique<vtr::PlasmaColorMap>(0., 1.);

    for (auto blk : blks) {
        t_color color = to_t_color(cmap->color(pin_util[blk]));
        draw_state->block_color[blk] = color;
    }

    draw_state->color_map = std::move(cmap);

    if (draw_state->show_blk_pin_util == DRAW_BLOCK_PIN_UTIL_TOTAL) {
        update_message("Block Total Pin Utilization");
    } else if (draw_state->show_blk_pin_util == DRAW_BLOCK_PIN_UTIL_INPUTS) {
        update_message("Block Input Pin Utilization");

    } else if (draw_state->show_blk_pin_util == DRAW_BLOCK_PIN_UTIL_OUTPUTS) {
        update_message("Block Output Pin Utilization");
    } else {
        VTR_ASSERT(false);
    }
}

static void draw_reset_blk_colors() {
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto blks = cluster_ctx.clb_nlist.blocks();
    for (auto blk : blks) {
        draw_reset_blk_color(blk);
    }
}

static void draw_routing_util() {
    t_draw_state* draw_state = get_draw_state_vars();
    if (draw_state->show_routing_util == DRAW_NO_ROUTING_UTIL) {
        return;
    }

    t_draw_coords* draw_coords = get_draw_coords_vars();
    auto& device_ctx = g_vpr_ctx.device();

    auto chanx_usage = calculate_routing_usage(CHANX);
    auto chany_usage = calculate_routing_usage(CHANY);

    auto chanx_avail = calculate_routing_avail(CHANX);
    auto chany_avail = calculate_routing_avail(CHANY);

    float min_util = 0.;
    float max_util = -std::numeric_limits<float>::infinity();
    for (size_t x = 0; x < device_ctx.grid.width() - 1; ++x) {
        for (size_t y = 0; y < device_ctx.grid.height() - 1; ++y) {
            max_util = std::max(max_util, routing_util(chanx_usage[x][y], chanx_avail[x][y]));
            max_util = std::max(max_util, routing_util(chany_usage[x][y], chany_avail[x][y]));
        }
    }
    max_util = std::max(max_util, 1.f);

    std::unique_ptr<vtr::ColorMap> cmap = std::make_unique<vtr::PlasmaColorMap>(min_util, max_util);

    float tile_width = draw_coords->get_tile_width();
    float tile_height = draw_coords->get_tile_height();

    float ALPHA = 0.95;
    if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_OVER_BLOCKS) {
        ALPHA = 1.;
    }

    for (size_t x = 0; x < device_ctx.grid.width() - 1; ++x) {
        for (size_t y = 0; y < device_ctx.grid.height() - 1; ++y) {
            float sb_util = 0;
            float chanx_util = 0;
            float chany_util = 0;
            int chan_count = 0;
            if (x > 0) {
                chanx_util = routing_util(chanx_usage[x][y], chanx_avail[x][y]);
                t_color chanx_color = to_t_color(cmap->color(chanx_util));
                chanx_color.alpha *= ALPHA;
                setcolor(chanx_color);
                t_bound_box bb(draw_coords->tile_x[x], draw_coords->tile_y[y] + 1 * tile_height,
                               draw_coords->tile_x[x] + 1 * tile_width, draw_coords->tile_y[y + 1]);
                fillrect(bb);

                setcolor(BLACK);
                if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_VALUE) {
                    drawtext_in(bb, vtr::string_fmt("%.2f", chanx_util).c_str());
                } else if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_FORMULA) {
                    drawtext_in(bb, vtr::string_fmt("%.2f = %.0f / %.0f", chanx_util, chanx_usage[x][y], chanx_avail[x][y]).c_str());
                }

                sb_util += chanx_util;
                ++chan_count;
            }

            if (y > 0) {
                chany_util = routing_util(chany_usage[x][y], chany_avail[x][y]);
                t_color chany_color = to_t_color(cmap->color(chany_util));
                chany_color.alpha *= ALPHA;
                setcolor(chany_color);
                t_bound_box bb(draw_coords->tile_x[x] + 1 * tile_width, draw_coords->tile_y[y],
                               draw_coords->tile_x[x + 1], draw_coords->tile_y[y] + 1 * tile_height);
                fillrect(bb);

                setcolor(BLACK);
                if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_VALUE) {
                    drawtext_in(bb, vtr::string_fmt("%.2f", chany_util).c_str());
                } else if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_FORMULA) {
                    drawtext_in(bb, vtr::string_fmt("%.2f = %.0f / %.0f", chany_util, chany_usage[x][y], chany_avail[x][y]).c_str());
                }

                sb_util += chany_util;
                ++chan_count;
            }

            //For now SB util is just average of surrounding channels
            //TODO: calculate actual usage
            sb_util += routing_util(chanx_usage[x + 1][y], chanx_avail[x + 1][y]);
            chan_count += 1;
            sb_util += routing_util(chany_usage[x][y + 1], chany_avail[x][y + 1]);
            chan_count += 1;

            VTR_ASSERT(chan_count > 0);
            sb_util /= chan_count;
            t_color sb_color = to_t_color(cmap->color(sb_util));
            sb_color.alpha *= ALPHA;
            setcolor(sb_color);
            t_bound_box bb(draw_coords->tile_x[x] + 1 * tile_width, draw_coords->tile_y[y] + 1 * tile_height,
                           draw_coords->tile_x[x + 1], draw_coords->tile_y[y + 1]);
            fillrect(bb);

            //Draw over blocks
            if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_OVER_BLOCKS) {
                if (x < device_ctx.grid.width() - 2 && y < device_ctx.grid.height() - 2) {
                    t_bound_box bb2(draw_coords->tile_x[x + 1], draw_coords->tile_y[y + 1],
                                    draw_coords->tile_x[x + 1] + 1 * tile_width, draw_coords->tile_y[y + 1] + 1 * tile_width);
                    fillrect(bb2);
                }
            }

            setcolor(BLACK);
            if (draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_VALUE
                || draw_state->show_routing_util == DRAW_ROUTING_UTIL_WITH_FORMULA) {
                drawtext_in(bb, vtr::string_fmt("%.2f", sb_util).c_str());
            }
        }
    }

    draw_state->color_map = std::move(cmap);
}

static float get_router_rr_cost(const t_rr_node_route_inf node_inf, e_draw_router_rr_cost draw_router_rr_cost) {
    if (draw_router_rr_cost == DRAW_ROUTER_RR_COST_TOTAL) {
        return node_inf.path_cost;
    } else if (draw_router_rr_cost == DRAW_ROUTER_RR_COST_KNOWN) {
        return node_inf.backward_path_cost;
    } else if (draw_router_rr_cost == DRAW_ROUTER_RR_COST_EXPECTED) {
        return node_inf.path_cost - node_inf.backward_path_cost;
    }

    VPR_THROW(VPR_ERROR_DRAW, "Invalid Router RR cost drawing type");
}

static void draw_router_rr_costs() {
    t_draw_state* draw_state = get_draw_state_vars();
    if (draw_state->show_router_rr_cost == DRAW_NO_ROUTER_RR_COST) {
        return;
    }

    auto& device_ctx = g_vpr_ctx.device();
    auto& routing_ctx = g_vpr_ctx.routing();

    std::vector<float> rr_costs(device_ctx.rr_nodes.size());

    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
        float cost = get_router_rr_cost(routing_ctx.rr_node_route_inf[inode], draw_state->show_router_rr_cost);
        rr_costs[inode] = cost;
    }

    bool all_nan = true;
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); ++inode) {
        if (std::isinf(rr_costs[inode])) {
            rr_costs[inode] = NAN;
        } else {
            all_nan = false;
        }
    }

    if (!all_nan) {
        draw_rr_costs(rr_costs, false);
    }

    if (draw_state->show_router_rr_cost == DRAW_ROUTER_RR_COST_TOTAL) {
        update_message("Routing Expected Total Cost (known + estimate)");
    } else if (draw_state->show_router_rr_cost == DRAW_ROUTER_RR_COST_KNOWN) {
        update_message("Routing Known Cost (from source to node)");
    } else {
        update_message("Routing Expected Cost (from node to target)");
        VTR_ASSERT(draw_state->show_router_rr_cost == DRAW_ROUTER_RR_COST_EXPECTED);
    }
}

static void draw_rr_costs(const std::vector<float>& rr_costs, bool lowest_cost_first) {
    t_draw_state* draw_state = get_draw_state_vars();

    /* Draws routing costs */

    auto& device_ctx = g_vpr_ctx.device();

    setlinewidth(2);

    VTR_ASSERT(rr_costs.size() == device_ctx.rr_nodes.size());

    float min_cost = std::numeric_limits<float>::infinity();
    float max_cost = -min_cost;
    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
        if (std::isnan(rr_costs[inode])) continue;

        min_cost = std::min(min_cost, rr_costs[inode]);
        max_cost = std::max(max_cost, rr_costs[inode]);
    }
    if (min_cost == std::numeric_limits<float>::infinity()) min_cost = 0;
    if (max_cost == -std::numeric_limits<float>::infinity()) max_cost = 0;
    std::unique_ptr<vtr::ColorMap> cmap = std::make_unique<vtr::PlasmaColorMap>(min_cost, max_cost);

    //Draw the nodes in ascending order of value, this ensures high valued nodes
    //are not overdrawn by lower value ones (e.g. when zoomed-out far)
    std::vector<int> nodes(device_ctx.rr_nodes.size());
    std::iota(nodes.begin(), nodes.end(), 0);
    auto cmp_ascending_cost = [&](int lhs_node, int rhs_node) {
        if (lowest_cost_first) {
            return rr_costs[lhs_node] > rr_costs[rhs_node];
        }
        return rr_costs[lhs_node] < rr_costs[rhs_node];
    };
    std::sort(nodes.begin(), nodes.end(), cmp_ascending_cost);

    for (int inode : nodes) {
        float cost = rr_costs[inode];
        if (std::isnan(cost)) continue;

        t_color color = to_t_color(cmap->color(cost));

        switch (device_ctx.rr_nodes[inode].type()) {
            case CHANX: //fallthrough
            case CHANY:
                draw_rr_chan(inode, color);
                draw_rr_edges(inode);
                break;

            case IPIN: //fallthrough
                draw_rr_pin(inode, color);
                break;
            case OPIN:
                draw_rr_pin(inode, color);
                draw_rr_edges(inode);
                break;
            case SOURCE:
            case SINK:
                color.alpha *= 0.8;
                draw_rr_src_sink(inode, color);
                break;
            default:
                break;
        }
    }

    draw_state->color_map = std::move(cmap);
}

static void draw_placement_macros() {
    t_draw_state* draw_state = get_draw_state_vars();

    if (draw_state->show_placement_macros == DRAW_NO_PLACEMENT_MACROS) {
        return;
    }

    t_draw_coords* draw_coords = get_draw_coords_vars();

    auto& place_ctx = g_vpr_ctx.placement();
    auto& cluster_ctx = g_vpr_ctx.clustering();
    for (size_t imacro = 0; imacro < place_ctx.pl_macros.size(); ++imacro) {
        const t_pl_macro* pl_macro = &place_ctx.pl_macros[imacro];

        //TODO: for now we just draw the bounding box of the macro, which is incorrect for non-rectangular macros...
        int xlow = std::numeric_limits<int>::max();
        int ylow = std::numeric_limits<int>::max();
        int xhigh = std::numeric_limits<int>::min();
        int yhigh = std::numeric_limits<int>::min();

        int x_root = OPEN;
        int y_root = OPEN;
        for (size_t imember = 0; imember < pl_macro->members.size(); ++imember) {
            const t_pl_macro_member* member = &pl_macro->members[imember];

            ClusterBlockId blk = member->blk_index;

            if (imember == 0) {
                x_root = place_ctx.block_locs[blk].loc.x;
                y_root = place_ctx.block_locs[blk].loc.y;
            }

            int x = x_root + member->offset.x;
            int y = y_root + member->offset.y;

            xlow = std::min(xlow, x);
            ylow = std::min(ylow, y);
            xhigh = std::max(xhigh, x + cluster_ctx.clb_nlist.block_type(blk)->width);
            yhigh = std::max(yhigh, y + cluster_ctx.clb_nlist.block_type(blk)->height);
        }

        int draw_xlow = draw_coords->tile_x[xlow];
        int draw_ylow = draw_coords->tile_y[ylow];
        int draw_xhigh = draw_coords->tile_x[xhigh];
        int draw_yhigh = draw_coords->tile_y[yhigh];

        setcolor(RED);
        drawrect(draw_xlow, draw_ylow, draw_xhigh, draw_yhigh);

        t_color fill = SKYBLUE;
        fill.alpha *= 0.3;
        setcolor(fill);
        fillrect(draw_xlow, draw_ylow, draw_xhigh, draw_yhigh);
    }
}
