#include "vtr_log.h"
#include "vtr_memory.h"

#include "vpr_types.h"
#include "vpr_error.h"

#include "globals.h"
#include "rr_graph.h"
#include "check_rr_graph.h"

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

static bool rr_node_is_global_clb_ipin(int inode);

static void check_unbuffered_edges(int from_node);

static bool has_adjacent_channel(const t_rr_node& node, const DeviceGrid& grid);

static void check_rr_edge(int from_node, int from_edge, int to_node);

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

void check_rr_graph(const t_graph_type graph_type,
                    const DeviceGrid& grid,
                    const std::vector<t_physical_tile_type>& types) {
    e_route_type route_type = DETAILED;
    if (graph_type == GRAPH_GLOBAL) {
        route_type = GLOBAL;
    }

    auto& device_ctx = g_vpr_ctx.device();

    auto total_edges_to_node = std::vector<int>(device_ctx.rr_nodes.size());
    auto switch_types_from_current_to_node = std::vector<unsigned char>(device_ctx.rr_nodes.size());
    const int num_rr_switches = device_ctx.rr_switch_inf.size();

    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
        device_ctx.rr_nodes[inode].validate();

        /* Ignore any uninitialized rr_graph nodes */
        if ((device_ctx.rr_nodes[inode].type() == SOURCE)
            && (device_ctx.rr_nodes[inode].xlow() == 0) && (device_ctx.rr_nodes[inode].ylow() == 0)
            && (device_ctx.rr_nodes[inode].xhigh() == 0) && (device_ctx.rr_nodes[inode].yhigh() == 0)) {
            continue;
        }

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

        check_rr_node(inode, route_type, device_ctx);

        /* Check all the connectivity (edges, etc.) information.                    */

        std::map<int, std::vector<int>> edges_from_current_to_node;
        for (int iedge = 0; iedge < num_edges; iedge++) {
            int to_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge);

            if (to_node < 0 || to_node >= (int)device_ctx.rr_nodes.size()) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_graph: node %d has an edge %d.\n"
                                "\tEdge is out of range.\n",
                                inode, to_node);
            }

            check_rr_edge(inode, iedge, to_node);

            edges_from_current_to_node[to_node].push_back(iedge);
            total_edges_to_node[to_node]++;

            auto switch_type = device_ctx.rr_nodes[inode].edge_switch(iedge);

            if (switch_type < 0 || switch_type >= num_rr_switches) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_graph: node %d has a switch type %d.\n"
                                "\tSwitch type is out of range.\n",
                                inode, switch_type);
            }
        } /* End for all edges of node. */

        //Check that multiple edges between the same from/to nodes make sense
        for (int iedge = 0; iedge < num_edges; iedge++) {
            int to_node = device_ctx.rr_nodes[inode].edge_sink_node(iedge);

            if (edges_from_current_to_node[to_node].size() == 1) continue; //Single edges are always OK

            VTR_ASSERT_MSG(edges_from_current_to_node[to_node].size() > 1, "Expect multiple edges");

            t_rr_type to_rr_type = device_ctx.rr_nodes[to_node].type();

            //Only expect chan <-> chan connections to have multiple edges
            if ((to_rr_type != CHANX && to_rr_type != CHANY)
                || (rr_type != CHANX && rr_type != CHANY)) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_graph: node %d (%s) connects to node %d (%s) %zu times - multi-connections only expected for CHAN->CHAN.\n",
                          inode, rr_node_typename[rr_type], to_node, rr_node_typename[to_rr_type], edges_from_current_to_node[to_node].size());
            }

            //Between two wire segments
            VTR_ASSERT_MSG(to_rr_type == CHANX || to_rr_type == CHANY, "Expect channel type");
            VTR_ASSERT_MSG(rr_type == CHANX || rr_type == CHANY, "Expect channel type");

            //While multiple connections between the same wires can be electrically legal,
            //they are redundant if they are of the same switch type.
            //
            //Identify any such edges with identical switches
            std::map<short, int> switch_counts;
            for (auto edge : edges_from_current_to_node[to_node]) {
                auto edge_switch = device_ctx.rr_nodes[inode].edge_switch(edge);

                switch_counts[edge_switch]++;
            }

            //Tell the user about any redundant edges
            for (auto kv : switch_counts) {
                if (kv.second <= 1) continue;

                auto switch_type = device_ctx.rr_switch_inf[kv.first].type();

                VPR_ERROR(VPR_ERROR_ROUTE, "in check_rr_graph: node %d has %d redundant connections to node %d of switch type %d (%s)",
                          inode, kv.second, to_node, kv.first, SWITCH_TYPE_STRINGS[size_t(switch_type)]);
            }
        }

        /* Slow test could leave commented out most of the time. */
        check_unbuffered_edges(inode);

        //Check that all config/non-config edges are appropriately organized
        for (auto edge : device_ctx.rr_nodes[inode].configurable_edges()) {
            if (!device_ctx.rr_nodes[inode].edge_is_configurable(edge)) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "in check_rr_graph: node %d edge %d is non-configurable, but in configurable edges",
                                inode, edge);
            }
        }

        for (auto edge : device_ctx.rr_nodes[inode].non_configurable_edges()) {
            if (device_ctx.rr_nodes[inode].edge_is_configurable(edge)) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "in check_rr_graph: node %d edge %d is configurable, but in non-configurable edges",
                                inode, edge);
            }
        }

    } /* End for all rr_nodes */

    /* I built a list of how many edges went to everything in the code above -- *
     * now I check that everything is reachable.                                */
    bool is_fringe_warning_sent = false;

    for (size_t inode = 0; inode < device_ctx.rr_nodes.size(); inode++) {
        t_rr_type rr_type = device_ctx.rr_nodes[inode].type();

        if (rr_type != SOURCE) {
            if (total_edges_to_node[inode] < 1 && !rr_node_is_global_clb_ipin(inode)) {
                /* A global CLB input pin will not have any edges, and neither will  *
                 * a SOURCE or the start of a carry-chain.  Anything else is an error.
                 * For simplicity, carry-chain input pin are entirely ignored in this test
                 */
                bool is_chain = false;
                if (rr_type == IPIN) {
                    t_physical_tile_type_ptr type = device_ctx.grid[device_ctx.rr_nodes[inode].xlow()][device_ctx.rr_nodes[inode].ylow()].type;
                    for (const t_fc_specification& fc_spec : types[type->index].fc_specs) {
                        if (fc_spec.fc_value == 0 && fc_spec.seg_index == 0) {
                            is_chain = true;
                        }
                    }
                }

                const auto& node = device_ctx.rr_nodes[inode];

                bool is_fringe = ((device_ctx.rr_nodes[inode].xlow() == 1)
                                  || (device_ctx.rr_nodes[inode].ylow() == 1)
                                  || (device_ctx.rr_nodes[inode].xhigh() == int(grid.width()) - 2)
                                  || (device_ctx.rr_nodes[inode].yhigh() == int(grid.height()) - 2));
                bool is_wire = (device_ctx.rr_nodes[inode].type() == CHANX
                                || device_ctx.rr_nodes[inode].type() == CHANY);

                if (!is_chain && !is_fringe && !is_wire) {
                    if (node.type() == IPIN || node.type() == OPIN) {
                        if (has_adjacent_channel(node, device_ctx.grid)) {
                            auto block_type = device_ctx.grid[node.xlow()][node.ylow()].type;
                            VTR_LOG_ERROR("in check_rr_graph: node %d (%s) at (%d,%d) block=%s side=%s has no fanin.\n",
                                          inode, node.type_string(), node.xlow(), node.ylow(), block_type->name, node.side_string());
                        }
                    } else {
                        VTR_LOG_ERROR("in check_rr_graph: node %d (%s) has no fanin.\n",
                                      inode, device_ctx.rr_nodes[inode].type_string());
                    }
                } else if (!is_chain && !is_fringe_warning_sent) {
                    VTR_LOG_WARN(
                        "in check_rr_graph: fringe node %d %s at (%d,%d) has no fanin.\n"
                        "\t This is possible on a fringe node based on low Fc_out, N, and certain lengths.\n",
                        inode, device_ctx.rr_nodes[inode].type_string(), device_ctx.rr_nodes[inode].xlow(), device_ctx.rr_nodes[inode].ylow());
                    is_fringe_warning_sent = true;
                }
            }
        } else { /* SOURCE.  No fanin for now; change if feedthroughs allowed. */
            if (total_edges_to_node[inode] != 0) {
                VTR_LOG_ERROR("in check_rr_graph: SOURCE node %d has a fanin of %d, expected 0.\n",
                              inode, total_edges_to_node[inode]);
            }
        }
    }
}

static bool rr_node_is_global_clb_ipin(int inode) {
    /* Returns true if inode refers to a global CLB input pin node.   */

    int ipin;
    t_physical_tile_type_ptr type;

    auto& device_ctx = g_vpr_ctx.device();

    type = device_ctx.grid[device_ctx.rr_nodes[inode].xlow()][device_ctx.rr_nodes[inode].ylow()].type;

    if (device_ctx.rr_nodes[inode].type() != IPIN)
        return (false);

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

    return type->is_ignored_pin[ipin];
}

void check_rr_node(int inode, enum e_route_type route_type, const DeviceContext& device_ctx) {
    /* This routine checks that the rr_node is inside the grid and has a valid
     * pin number, etc.
     */

    int xlow, ylow, xhigh, yhigh, ptc_num, capacity;
    t_rr_type rr_type;
    t_physical_tile_type_ptr type;
    int nodes_per_chan, tracks_per_node, num_edges, cost_index;
    float C, R;

    rr_type = device_ctx.rr_nodes[inode].type();
    xlow = device_ctx.rr_nodes[inode].xlow();
    xhigh = device_ctx.rr_nodes[inode].xhigh();
    ylow = device_ctx.rr_nodes[inode].ylow();
    yhigh = device_ctx.rr_nodes[inode].yhigh();
    ptc_num = device_ctx.rr_nodes[inode].ptc_num();
    capacity = device_ctx.rr_nodes[inode].capacity();
    cost_index = device_ctx.rr_nodes[inode].cost_index();
    type = nullptr;

    const auto& grid = device_ctx.grid;
    if (xlow > xhigh || ylow > yhigh) {
        VPR_ERROR(VPR_ERROR_ROUTE,
                  "in check_rr_node: rr endpoints are (%d,%d) and (%d,%d).\n", xlow, ylow, xhigh, yhigh);
    }

    if (xlow < 0 || xhigh > int(grid.width()) - 1 || ylow < 0 || yhigh > int(grid.height()) - 1) {
        VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                        "in check_rr_node: rr endpoints (%d,%d) and (%d,%d) are out of range.\n", xlow, ylow, xhigh, yhigh);
    }

    if (ptc_num < 0) {
        VPR_ERROR(VPR_ERROR_ROUTE,
                  "in check_rr_node: inode %d (type %d) had a ptc_num of %d.\n", inode, rr_type, ptc_num);
    }

    if (cost_index < 0 || cost_index >= (int)device_ctx.rr_indexed_data.size()) {
        VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                        "in check_rr_node: node %d cost index (%d) is out of range.\n", inode, cost_index);
    }

    /* Check that the segment is within the array and such. */
    type = device_ctx.grid[xlow][ylow].type;

    switch (rr_type) {
        case SOURCE:
        case SINK:
            if (type == nullptr) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_node: node %d (type %d) is at an illegal clb location (%d, %d).\n", inode, rr_type, xlow, ylow);
            }
            if (xlow != (xhigh - type->width + 1) || ylow != (yhigh - type->height + 1)) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_node: node %d (type %d) has endpoints (%d,%d) and (%d,%d)\n", inode, rr_type, xlow, ylow, xhigh, yhigh);
            }
            break;
        case IPIN:
        case OPIN:
            if (type == nullptr) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_node: node %d (type %d) is at an illegal clb location (%d, %d).\n", inode, rr_type, xlow, ylow);
            }
            if (xlow != xhigh || ylow != yhigh) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_node: node %d (type %d) has endpoints (%d,%d) and (%d,%d)\n", inode, rr_type, xlow, ylow, xhigh, yhigh);
            }
            break;

        case CHANX:
            if (xlow < 1 || xhigh > int(grid.width()) - 2 || yhigh > int(grid.height()) - 2 || yhigh != ylow) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_node: CHANX out of range for endpoints (%d,%d) and (%d,%d)\n", xlow, ylow, xhigh, yhigh);
            }
            if (route_type == GLOBAL && xlow != xhigh) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_node: node %d spans multiple channel segments (not allowed for global routing).\n", inode);
            }
            break;

        case CHANY:
            if (xhigh > int(grid.width()) - 2 || ylow < 1 || yhigh > int(grid.height()) - 2 || xlow != xhigh) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "Error in check_rr_node: CHANY out of range for endpoints (%d,%d) and (%d,%d)\n", xlow, ylow, xhigh, yhigh);
            }
            if (route_type == GLOBAL && ylow != yhigh) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_node: node %d spans multiple channel segments (not allowed for global routing).\n", inode);
            }
            break;

        default:
            VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                            "in check_rr_node: Unexpected segment type: %d\n", rr_type);
    }

    /* Check that it's capacities and such make sense. */

    switch (rr_type) {
        case SOURCE:
            if (ptc_num >= type->num_class
                || type->class_inf[ptc_num].type != DRIVER) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_node: inode %d (type %d) had a ptc_num of %d.\n", inode, rr_type, ptc_num);
            }
            if (type->class_inf[ptc_num].num_pins != capacity) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_node: inode %d (type %d) had a capacity of %d.\n", inode, rr_type, capacity);
            }
            break;

        case SINK:
            if (ptc_num >= type->num_class
                || type->class_inf[ptc_num].type != RECEIVER) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_node: inode %d (type %d) had a ptc_num of %d.\n", inode, rr_type, ptc_num);
            }
            if (type->class_inf[ptc_num].num_pins != capacity) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_node: inode %d (type %d) has a capacity of %d.\n", inode, rr_type, capacity);
            }
            break;

        case OPIN:
            if (ptc_num >= type->num_pins
                || type->class_inf[type->pin_class[ptc_num]].type != DRIVER) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_node: inode %d (type %d) had a ptc_num of %d.\n", inode, rr_type, ptc_num);
            }
            if (capacity != 1) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_node: inode %d (type %d) has a capacity of %d.\n", inode, rr_type, capacity);
            }
            break;

        case IPIN:
            if (ptc_num >= type->num_pins
                || type->class_inf[type->pin_class[ptc_num]].type != RECEIVER) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_node: inode %d (type %d) had a ptc_num of %d.\n", inode, rr_type, ptc_num);
            }
            if (capacity != 1) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_node: inode %d (type %d) has a capacity of %d.\n", inode, rr_type, capacity);
            }
            break;

        case CHANX:
            if (route_type == DETAILED) {
                nodes_per_chan = device_ctx.chan_width.max;
                tracks_per_node = 1;
            } else {
                nodes_per_chan = 1;
                tracks_per_node = device_ctx.chan_width.x_list[ylow];
            }

            if (ptc_num >= nodes_per_chan) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_node: inode %d (type %d) has a ptc_num of %d.\n", inode, rr_type, ptc_num);
            }

            if (capacity != tracks_per_node) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_node: inode %d (type %d) has a capacity of %d.\n", inode, rr_type, capacity);
            }
            break;

        case CHANY:
            if (route_type == DETAILED) {
                nodes_per_chan = device_ctx.chan_width.max;
                tracks_per_node = 1;
            } else {
                nodes_per_chan = 1;
                tracks_per_node = device_ctx.chan_width.y_list[xlow];
            }

            if (ptc_num >= nodes_per_chan) {
                VPR_ERROR(VPR_ERROR_ROUTE,
                          "in check_rr_node: inode %d (type %d) has a ptc_num of %d.\n", inode, rr_type, ptc_num);
            }

            if (capacity != tracks_per_node) {
                VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                                "in check_rr_node: inode %d (type %d) has a capacity of %d.\n", inode, rr_type, capacity);
            }
            break;

        default:
            VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                            "in check_rr_node: Unexpected segment type: %d\n", rr_type);
    }

    /* Check that the number of (out) edges is reasonable. */
    num_edges = device_ctx.rr_nodes[inode].num_edges();

    if (rr_type != SINK && rr_type != IPIN) {
        if (num_edges <= 0) {
            /* Just a warning, since a very poorly routable rr-graph could have nodes with no edges.  *
             * If such a node was ever used in a final routing (not just in an rr_graph), other       *
             * error checks in check_routing will catch it.                                           */

            //Don't worry about disconnect PINs which have no adjacent channels (i.e. on the device perimeter)
            bool check_for_out_edges = true;
            if (rr_type == IPIN || rr_type == OPIN) {
                if (!has_adjacent_channel(device_ctx.rr_nodes[inode], device_ctx.grid)) {
                    check_for_out_edges = false;
                }
            }

            if (check_for_out_edges) {
                std::string info = describe_rr_node(inode);
                VTR_LOG_WARN("in check_rr_node: %s has no out-going edges.\n", info.c_str());
            }
        }
    } else if (rr_type == SINK) { /* SINK -- remove this check if feedthroughs allowed */
        if (num_edges != 0) {
            VPR_FATAL_ERROR(VPR_ERROR_ROUTE,
                            "in check_rr_node: node %d is a sink, but has %d edges.\n", inode, num_edges);
        }
    }

    /* Check that the capacitance and resistance are reasonable. */
    C = device_ctx.rr_nodes[inode].C();
    R = device_ctx.rr_nodes[inode].R();

    if (rr_type == CHANX || rr_type == CHANY) {
        if (C < 0. || R < 0.) {
            VPR_ERROR(VPR_ERROR_ROUTE,
                      "in check_rr_node: node %d of type %d has R = %g and C = %g.\n", inode, rr_type, R, C);
        }
    } else {
        if (C != 0. || R != 0.) {
            VPR_ERROR(VPR_ERROR_ROUTE,
                      "in check_rr_node: node %d of type %d has R = %g and C = %g.\n", inode, rr_type, R, C);
        }
    }
}

static void check_unbuffered_edges(int from_node) {
    /* This routine checks that all pass transistors in the routing truly are  *
     * bidirectional.  It may be a slow check, so don't use it all the time.   */

    int from_edge, to_node, to_edge, from_num_edges, to_num_edges;
    t_rr_type from_rr_type, to_rr_type;
    short from_switch_type;
    bool trans_matched;

    auto& device_ctx = g_vpr_ctx.device();

    from_rr_type = device_ctx.rr_nodes[from_node].type();
    if (from_rr_type != CHANX && from_rr_type != CHANY)
        return;

    from_num_edges = device_ctx.rr_nodes[from_node].num_edges();

    for (from_edge = 0; from_edge < from_num_edges; from_edge++) {
        to_node = device_ctx.rr_nodes[from_node].edge_sink_node(from_edge);
        to_rr_type = device_ctx.rr_nodes[to_node].type();

        if (to_rr_type != CHANX && to_rr_type != CHANY)
            continue;

        from_switch_type = device_ctx.rr_nodes[from_node].edge_switch(from_edge);

        if (device_ctx.rr_switch_inf[from_switch_type].buffered())
            continue;

        /* We know that we have a pass transistor from from_node to to_node. Now *
         * check that there is a corresponding edge from to_node back to         *
         * from_node.                                                            */

        to_num_edges = device_ctx.rr_nodes[to_node].num_edges();
        trans_matched = false;

        for (to_edge = 0; to_edge < to_num_edges; to_edge++) {
            if (device_ctx.rr_nodes[to_node].edge_sink_node(to_edge) == from_node
                && device_ctx.rr_nodes[to_node].edge_switch(to_edge) == from_switch_type) {
                trans_matched = true;
                break;
            }
        }

        if (trans_matched == false) {
            VPR_ERROR(VPR_ERROR_ROUTE,
                      "in check_unbuffered_edges:\n"
                      "connection from node %d to node %d uses an unbuffered switch (switch type %d '%s')\n"
                      "but there is no corresponding unbuffered switch edge in the other direction.\n",
                      from_node, to_node, from_switch_type, device_ctx.rr_switch_inf[from_switch_type].name);
        }

    } /* End for all from_node edges */
}

static bool has_adjacent_channel(const t_rr_node& node, const DeviceGrid& grid) {
    VTR_ASSERT(node.type() == IPIN || node.type() == OPIN);

    if ((node.xlow() == 0 && node.side() != RIGHT)                          //left device edge connects only along block's right side
        || (node.ylow() == int(grid.height() - 1) && node.side() != BOTTOM) //top device edge connects only along block's bottom side
        || (node.xlow() == int(grid.width() - 1) && node.side() != LEFT)    //right deivce edge connects only along block's left side
        || (node.ylow() == 0 && node.side() != TOP)                         //bottom deivce edge connects only along block's top side
    ) {
        return false;
    }
    return true; //All other blocks will be surrounded on all sides by channels
}

static void check_rr_edge(int from_node, int iedge, int to_node) {
    auto& device_ctx = g_vpr_ctx.device();

    //Check that to to_node's fan-in is correct, given the switch type
    int iswitch = device_ctx.rr_nodes[from_node].edge_switch(iedge);
    auto switch_type = device_ctx.rr_switch_inf[iswitch].type();

    int to_fanin = device_ctx.rr_nodes[to_node].fan_in();
    switch (switch_type) {
        case SwitchType::BUFFER:
            //Buffer switches are non-configurable, and uni-directional -- they must have only one driver
            if (to_fanin != 1) {
                std::string msg = "Non-configurable BUFFER type switch must have only one driver. ";
                msg += vtr::string_fmt(" Actual fan-in was %d (expected 1).\n", to_fanin);
                msg += "  Possible cause is complex block output pins connecting to:\n";
                msg += "    " + describe_rr_node(to_node);

                VPR_FATAL_ERROR(VPR_ERROR_ROUTE, msg.c_str());
            }
        case SwitchType::TRISTATE:  //Fallthrough
        case SwitchType::MUX:       //Fallthrough
        case SwitchType::PASS_GATE: //Fallthrough
        case SwitchType::SHORT:     //Fallthrough
            break;                  //pass
        default:
            VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Invalid switch type %d", switch_type);
    }
}
