/*
 Jason Luu 2008
 Print complex block information to a file
 */

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
using namespace std;

#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_digest.h"
#include "vtr_memory.h"

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

#include "pugixml.hpp"

#include "globals.h"
#include "atom_netlist.h"
#include "pack_types.h"
#include "cluster_router.h"
#include "output_clustering.h"
#include "read_xml_arch_file.h"
#include "vpr_utils.h"

#define LINELENGTH 1024
#define TAB_LENGTH 4

/****************** Static variables local to this module ************************/

static t_pb_graph_pin ***pb_graph_pin_lookup_from_index_by_type = nullptr; /* [0..device_ctx.num_block_types-1][0..num_pb_graph_pins-1] lookup pointer to pb_graph_pin from pb_graph_pin index */


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

/* Prints out one cluster (clb).  Both the external pins and the *
* internal connections are printed out.                         */
static void print_stats() {
	int ipin, itype;
	int total_nets_absorbed;
    std::unordered_map<AtomNetId,bool> nets_absorbed;

	int *num_clb_types, *num_clb_inputs_used, *num_clb_outputs_used;

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

	num_clb_types = num_clb_inputs_used = num_clb_outputs_used = nullptr;

	num_clb_types = (int*) vtr::calloc(device_ctx.num_block_types, sizeof(int));
	num_clb_inputs_used = (int*) vtr::calloc(device_ctx.num_block_types, sizeof(int));
	num_clb_outputs_used = (int*) vtr::calloc(device_ctx.num_block_types, sizeof(int));

    for(auto net_id : atom_ctx.nlist.nets()) {
		nets_absorbed[net_id] = true;
	}

	/* Counters used only for statistics purposes. */

	for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
		for (ipin = 0; ipin < cluster_ctx.clb_nlist.block_type(blk_id)->num_pins; ipin++) {
			if (cluster_ctx.clb_nlist.block_pb(blk_id)->pb_route == nullptr) {
				ClusterNetId clb_net_id = cluster_ctx.clb_nlist.block_net(blk_id, ipin);
				if (clb_net_id != ClusterNetId::INVALID()) {
                    auto net_id = atom_ctx.lookup.atom_net(clb_net_id);
                    VTR_ASSERT(net_id);
					nets_absorbed[net_id] = false;
					if (cluster_ctx.clb_nlist.block_type(blk_id)->class_inf[cluster_ctx.clb_nlist.block_type(blk_id)->pin_class[ipin]].type == RECEIVER) {
						num_clb_inputs_used[cluster_ctx.clb_nlist.block_type(blk_id)->index]++;
					}
					else if (cluster_ctx.clb_nlist.block_type(blk_id)->class_inf[cluster_ctx.clb_nlist.block_type(blk_id)->pin_class[ipin]].type == DRIVER) {
						num_clb_outputs_used[cluster_ctx.clb_nlist.block_type(blk_id)->index]++;
					}
				}
			}
			else {
				int pb_graph_pin_id = get_pb_graph_node_pin_from_block_pin(blk_id, ipin)->pin_count_in_cluster;
				auto atom_net_id = cluster_ctx.clb_nlist.block_pb(blk_id)->pb_route[pb_graph_pin_id].atom_net_id;
				if (atom_net_id) {
					nets_absorbed[atom_net_id] = false;
					if (cluster_ctx.clb_nlist.block_type(blk_id)->class_inf[cluster_ctx.clb_nlist.block_type(blk_id)->pin_class[ipin]].type
						== RECEIVER) {
						num_clb_inputs_used[cluster_ctx.clb_nlist.block_type(blk_id)->index]++;
					}
					else if (cluster_ctx.clb_nlist.block_type(blk_id)->class_inf[cluster_ctx.clb_nlist.block_type(blk_id)->pin_class[ipin]].type
						== DRIVER) {
						num_clb_outputs_used[cluster_ctx.clb_nlist.block_type(blk_id)->index]++;
					}
				}
			}
		}
		num_clb_types[cluster_ctx.clb_nlist.block_type(blk_id)->index]++;
	}

	for (itype = 0; itype < device_ctx.num_block_types; itype++) {
		if (num_clb_types[itype] == 0) {
			VTR_LOG("\t%s: # blocks: %d, average # input + clock pins used: %g, average # output pins used: %g\n",
					device_ctx.block_types[itype].name, num_clb_types[itype], 0.0, 0.0);
		} else {
			VTR_LOG("\t%s: # blocks: %d, average # input + clock pins used: %g, average # output pins used: %g\n",
					device_ctx.block_types[itype].name, num_clb_types[itype],
					(float) num_clb_inputs_used[itype] / (float) num_clb_types[itype],
					(float) num_clb_outputs_used[itype] / (float) num_clb_types[itype]);
		}
	}

	total_nets_absorbed = 0;
    for(auto net_id : atom_ctx.nlist.nets()) {
		if (nets_absorbed[net_id] == true) {
			total_nets_absorbed++;
		}
	}
	VTR_LOG("Absorbed logical nets %d out of %d nets, %d nets not absorbed.\n",
			total_nets_absorbed, (int)atom_ctx.nlist.nets().size(), (int)atom_ctx.nlist.nets().size() - total_nets_absorbed);
	free(num_clb_types);
	free(num_clb_inputs_used);
	free(num_clb_outputs_used);
	/* TODO: print more stats */
}

static const char * clustering_xml_net_text(AtomNetId net_id) {
	/* This routine prints out the atom_ctx.nlist net name (or open).
     * net_num is the index of the atom_ctx.nlist net to be printed
	 */

	if (!net_id) {
		return "open";
	} else {
        auto& atom_ctx = g_vpr_ctx.atom();
		return atom_ctx.nlist.net_name(net_id).c_str();
	}
}

static std::string clustering_xml_interconnect_text(t_type_ptr type, int inode, t_pb_route *pb_route) {
	if (!pb_route[inode].atom_net_id) {
		return "open";
	}

	int prev_node = pb_route[inode].driver_pb_pin_id;
	int prev_edge;
	if (prev_node == OPEN) {
		/* No previous driver implies that this is either a top-level input pin or a primitive output pin */
		t_pb_graph_pin *cur_pin = pb_graph_pin_lookup_from_index_by_type[type->index][inode];
		VTR_ASSERT(cur_pin->parent_node->pb_type->parent_mode == nullptr ||
				(cur_pin->parent_node->pb_type->num_modes == 0 && cur_pin->port->type == OUT_PORT)
				);
		return clustering_xml_net_text(pb_route[inode].atom_net_id);
	} else {
		t_pb_graph_pin *cur_pin = pb_graph_pin_lookup_from_index_by_type[type->index][inode];
		t_pb_graph_pin *prev_pin = pb_graph_pin_lookup_from_index_by_type[type->index][prev_node];

		for(prev_edge = 0; prev_edge < prev_pin->num_output_edges; prev_edge++) {
			VTR_ASSERT(prev_pin->output_edges[prev_edge]->num_output_pins == 1);
			if(prev_pin->output_edges[prev_edge]->output_pins[0]->pin_count_in_cluster == inode) {
				break;
			}
		}
		VTR_ASSERT(prev_edge < prev_pin->num_output_edges);

		char *name = prev_pin->output_edges[prev_edge]->interconnect->name;
		if (prev_pin->port->parent_pb_type->depth
				>= cur_pin->port->parent_pb_type->depth) {
			/* Connections from siblings or children should have an explicit index, connections from parent does not need an explicit index */
			return vtr::string_fmt("%s[%d].%s[%d]->%s",
					prev_pin->parent_node->pb_type->name,
					prev_pin->parent_node->placement_index,
					prev_pin->port->name,
					prev_pin->pin_number, name);
		} else {
			return vtr::string_fmt("%s.%s[%d]->%s",
					prev_pin->parent_node->pb_type->name,
					prev_pin->port->name,
					prev_pin->pin_number, name);
		}
	}
}

/* outputs a block that is open or unused.
 * In some cases, a block is unused for logic but is used for routing. When that happens, the block
 * cannot simply be marked open as that would lose the routing information. Instead, a block must be
 * output that reflects the routing resources used. This function handles both cases.
 */
static void clustering_xml_open_block(pugi::xml_node parent_node, t_type_ptr type, t_pb_graph_node * pb_graph_node,
		int pb_index, bool is_used, t_pb_route *pb_route) {
	int i, j, k, m;
	const t_pb_type * pb_type, *child_pb_type;
	t_mode * mode = nullptr;
	int prev_edge, prev_node;
	int mode_of_edge, port_index, node_index;

	mode_of_edge = UNDEFINED;

	pb_type = pb_graph_node->pb_type;

	pugi::xml_node block_node = parent_node.append_child("block");
	block_node.append_attribute("name") = "open";
	block_node.append_attribute("instance") = vtr::string_fmt("%s[%d]", pb_graph_node->pb_type->name, pb_index).c_str();

	if (is_used) {
		/* Determine mode if applicable */
		port_index = 0;
		for (i = 0; i < pb_type->num_ports; i++) {
			if (pb_type->ports[i].type == OUT_PORT) {
				VTR_ASSERT(!pb_type->ports[i].is_clock);
				for (j = 0; j < pb_type->ports[i].num_pins; j++) {
					node_index = pb_graph_node->output_pins[port_index][j].pin_count_in_cluster;
					if (pb_type->num_modes > 0 && pb_route[node_index].atom_net_id) {
						prev_node = pb_route[node_index].driver_pb_pin_id;
						t_pb_graph_pin *prev_pin = pb_graph_pin_lookup_from_index_by_type[type->index][prev_node];
						for(prev_edge = 0; prev_edge < prev_pin->num_output_edges; prev_edge++) {
							VTR_ASSERT(prev_pin->output_edges[prev_edge]->num_output_pins == 1);
							if(prev_pin->output_edges[prev_edge]->output_pins[0]->pin_count_in_cluster == node_index) {
								break;
							}
						}
						VTR_ASSERT(prev_edge < prev_pin->num_output_edges);
						mode_of_edge = prev_pin->output_edges[prev_edge]->interconnect->parent_mode_index;
						VTR_ASSERT(mode == nullptr || &pb_type->modes[mode_of_edge] == mode);
						VTR_ASSERT(mode_of_edge == 0); /* for now, unused blocks must always default to use mode 0 */
						mode = &pb_type->modes[mode_of_edge];
					}
				}
				port_index++;
			}
		}

		VTR_ASSERT(mode != nullptr && mode_of_edge != UNDEFINED);

		block_node.append_attribute("mode") = mode->name;
		block_node.append_attribute("pb_type_num_modes") = pb_type->num_modes;


		pugi::xml_node inputs_node = block_node.append_child("inputs");

		port_index = 0;
		for (i = 0; i < pb_type->num_ports; i++) {
			if (!pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT) {
				pugi::xml_node port_node = inputs_node.append_child("port");
				port_node.append_attribute("name") = pb_graph_node->pb_type->ports[i].name;

				std::vector<std::string> pins;
				for (j = 0; j < pb_type->ports[i].num_pins; j++) {
					node_index = pb_graph_node->input_pins[port_index][j].pin_count_in_cluster;

					if (pb_type->parent_mode == nullptr) {
						pins.push_back(clustering_xml_net_text(pb_route[node_index].atom_net_id));
					} else {
						pins.push_back(clustering_xml_interconnect_text(type, node_index, pb_route));
					}
				}
				port_node.text().set(vtr::join(pins.begin(), pins.end(), " ").c_str());
				port_index++;
			}
		}

		pugi::xml_node outputs_node = block_node.append_child("outputs");

		port_index = 0;
		for (i = 0; i < pb_type->num_ports; i++) {
			if (pb_type->ports[i].type == OUT_PORT) {
				VTR_ASSERT(!pb_type->ports[i].is_clock);

				pugi::xml_node port_node = outputs_node.append_child("port");
				port_node.append_attribute("name") = pb_graph_node->pb_type->ports[i].name;
				std::vector<std::string> pins;
				for (j = 0; j < pb_type->ports[i].num_pins; j++) {
					node_index =
							pb_graph_node->output_pins[port_index][j].pin_count_in_cluster;
					pins.push_back(clustering_xml_interconnect_text(type, node_index, pb_route));
				}
				port_node.text().set(vtr::join(pins.begin(), pins.end(), " ").c_str());
				port_index++;
			}
		}

		pugi::xml_node clock_node = block_node.append_child("clocks");

		port_index = 0;
		for (i = 0; i < pb_type->num_ports; i++) {
			if (pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT) {
				pugi::xml_node port_node = clock_node.append_child("port");
				port_node.append_attribute("name") = pb_graph_node->pb_type->ports[i].name;

				std::vector<std::string> pins;
				for (j = 0; j < pb_type->ports[i].num_pins; j++) {
					node_index = pb_graph_node->clock_pins[port_index][j].pin_count_in_cluster;
					if (pb_type->parent_mode == nullptr) {
						pins.push_back(clustering_xml_net_text(pb_route[node_index].atom_net_id));
					} else {
						pins.push_back(clustering_xml_interconnect_text(type, node_index, pb_route));
					}
				}
				port_node.text().set(vtr::join(pins.begin(), pins.end(), " ").c_str());
				port_index++;
			}
		}

		if (pb_type->num_modes > 0) {
			for (i = 0; i < mode->num_pb_type_children; i++) {
				child_pb_type = &mode->pb_type_children[i];
				for (j = 0; j < mode->pb_type_children[i].num_pb; j++) {
					port_index = 0;
					is_used = false;
					for (k = 0; k < child_pb_type->num_ports && !is_used; k++) {
						if (child_pb_type->ports[k].type == OUT_PORT) {
							for (m = 0; m < child_pb_type->ports[k].num_pins;
									m++) {
								node_index =
										pb_graph_node->child_pb_graph_nodes[mode_of_edge][i][j].output_pins[port_index][m].pin_count_in_cluster;
								if (pb_route[node_index].atom_net_id) {
									is_used = true;
									break;
								}
							}
							port_index++;
						}
					}
					clustering_xml_open_block(block_node, type,
							&pb_graph_node->child_pb_graph_nodes[mode_of_edge][i][j],
							j, is_used, pb_route);
				}
			}
		}
	}
}

/* outputs a block that is used (i.e. has configuration) and all of its child blocks */
static void clustering_xml_block(pugi::xml_node parent_node, t_type_ptr type, t_pb * pb, int pb_index, t_pb_route *pb_route) {
	int i, j, k, m;
	const t_pb_type *pb_type, *child_pb_type;
	t_pb_graph_node *pb_graph_node;
	t_mode *mode;
	int port_index, node_index;
	bool is_used;

	pb_type = pb->pb_graph_node->pb_type;
	pb_graph_node = pb->pb_graph_node;
	mode = &pb_type->modes[pb->mode];

	pugi::xml_node block_node = parent_node.append_child("block");
	block_node.append_attribute("name") = pb->name;
	block_node.append_attribute("instance") = vtr::string_fmt("%s[%d]", pb_type->name, pb_index).c_str();

	if (pb_type->num_modes > 0) {
		block_node.append_attribute("mode") = mode->name;
	} else {
		const auto& atom_ctx = g_vpr_ctx.atom();
		AtomBlockId atom_blk = atom_ctx.nlist.find_block(pb->name);
		VTR_ASSERT(atom_blk);

		pugi::xml_node attrs_node = block_node.append_child("attributes");
		for (const auto& attr : atom_ctx.nlist.block_attrs(atom_blk)) {
			pugi::xml_node attr_node = attrs_node.append_child("attribute");
			attr_node.append_attribute("name") = attr.first.c_str();
			attr_node.text().set(attr.second.c_str());
		}

		pugi::xml_node params_node = block_node.append_child("parameters");
		for (const auto& param : atom_ctx.nlist.block_params(atom_blk)) {
			pugi::xml_node param_node = params_node.append_child("parameter");
			param_node.append_attribute("name") = param.first.c_str();
			param_node.text().set(param.second.c_str());
		}
	}

	pugi::xml_node inputs_node = block_node.append_child("inputs");

	port_index = 0;
	for (i = 0; i < pb_type->num_ports; i++) {
		if (!pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT) {
			pugi::xml_node port_node = inputs_node.append_child("port");
			port_node.append_attribute("name") = pb_graph_node->pb_type->ports[i].name;

			std::vector<std::string> pins;
			for (j = 0; j < pb_type->ports[i].num_pins; j++) {
				node_index = pb->pb_graph_node->input_pins[port_index][j].pin_count_in_cluster;

				if (pb_type->parent_mode == nullptr) {
					pins.push_back(clustering_xml_net_text(pb_route[node_index].atom_net_id));
				} else {
					pins.push_back(clustering_xml_interconnect_text(type, node_index, pb_route));
				}
			}
			port_node.text().set(vtr::join(pins.begin(), pins.end(), " ").c_str());

            //The cluster router may have rotated equivalent pins (e.g. LUT inputs),
            //record the resulting rotation here so it can be unambigously mapped
            //back to the atom netlist
            if(pb_type->ports[i].equivalent != PortEquivalence::NONE && pb_type->parent_mode != nullptr && pb_type->num_modes == 0) {
                //This is a primitive with equivalent inputs

                auto& atom_ctx = g_vpr_ctx.atom();
                AtomBlockId atom_blk = atom_ctx.nlist.find_block(pb->name);
                VTR_ASSERT(atom_blk);

                AtomPortId atom_port = atom_ctx.nlist.find_atom_port(atom_blk, pb_type->ports[i].model_port);

                if(atom_port) { //Port exists (some LUTs may have no input and hence no port in the atom netlist)

					pugi::xml_node port_rotation_node = inputs_node.append_child("port_rotation_map");
					port_rotation_node.append_attribute("name") = pb_graph_node->pb_type->ports[i].name;

                    std::set<AtomPinId> recorded_pins;
					std::vector<std::string> pin_map_list;

                    for (j = 0; j < pb_type->ports[i].num_pins; j++) {
                        node_index = pb->pb_graph_node->input_pins[port_index][j].pin_count_in_cluster;
                        AtomNetId atom_net = pb_route[node_index].atom_net_id;

                        if(atom_net) {
                            //This physical pin is in use, find the original pin in the atom netlist
                            AtomPinId orig_pin;
                            for(AtomPinId atom_pin : atom_ctx.nlist.port_pins(atom_port)) {
                                if(recorded_pins.count(atom_pin)) continue; //Don't add pins twice

                                AtomNetId atom_pin_net = atom_ctx.nlist.pin_net(atom_pin);

                                if(atom_pin_net == atom_net) {
                                    recorded_pins.insert(atom_pin);
                                    orig_pin = atom_pin;
                                    break;
                                }
                            }

                            VTR_ASSERT(orig_pin);
                            //The physical pin j, maps to a pin in the atom netlist
							pin_map_list.push_back(vtr::string_fmt("%d", atom_ctx.nlist.pin_port_bit(orig_pin)));
                        } else {
                            //The physical pin is disconnected
							pin_map_list.push_back("open");
                        }
                    }
					port_rotation_node.text().set(vtr::join(pin_map_list.begin(), pin_map_list.end(), " ").c_str());
                }
            }

			port_index++;
		}
	}


	pugi::xml_node outputs_node = block_node.append_child("outputs");

	port_index = 0;
	for (i = 0; i < pb_type->num_ports; i++) {
		if (pb_type->ports[i].type == OUT_PORT) {
			VTR_ASSERT(!pb_type->ports[i].is_clock);

			pugi::xml_node port_node = outputs_node.append_child("port");
			port_node.append_attribute("name") = pb_graph_node->pb_type->ports[i].name;
			std::vector<std::string> pins;
			for (j = 0; j < pb_type->ports[i].num_pins; j++) {
				node_index =
						pb->pb_graph_node->output_pins[port_index][j].pin_count_in_cluster;
				pins.push_back(clustering_xml_interconnect_text(type, node_index, pb_route));
			}
			port_node.text().set(vtr::join(pins.begin(), pins.end(), " ").c_str());
			port_index++;
		}
	}


	pugi::xml_node clock_node = block_node.append_child("clocks");

	port_index = 0;
	for (i = 0; i < pb_type->num_ports; i++) {
		if (pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT) {
			pugi::xml_node port_node = clock_node.append_child("port");
			port_node.append_attribute("name") = pb_graph_node->pb_type->ports[i].name;

			std::vector<std::string> pins;
			for (j = 0; j < pb_type->ports[i].num_pins; j++) {
				node_index = pb->pb_graph_node->clock_pins[port_index][j].pin_count_in_cluster;
				if (pb_type->parent_mode == nullptr) {
					pins.push_back(clustering_xml_net_text(pb_route[node_index].atom_net_id));
				} else {
					pins.push_back(clustering_xml_interconnect_text(type, node_index, pb_route));
				}
			}
			port_node.text().set(vtr::join(pins.begin(), pins.end(), " ").c_str());
			port_index++;
		}
	}

	if (pb_type->num_modes > 0) {
		for (i = 0; i < mode->num_pb_type_children; i++) {
			for (j = 0; j < mode->pb_type_children[i].num_pb; j++) {
				/* If child pb is not used but routing is used, I must print things differently */
				if ((pb->child_pbs[i] != nullptr) && (pb->child_pbs[i][j].name != nullptr)) {
					clustering_xml_block(block_node, type, &pb->child_pbs[i][j], j, pb_route);
				} else {
					is_used = false;
					child_pb_type = &mode->pb_type_children[i];
					port_index = 0;

					for (k = 0; k < child_pb_type->num_ports && !is_used; k++) {
						if (child_pb_type->ports[k].type == OUT_PORT) {
							for (m = 0; m < child_pb_type->ports[k].num_pins; m++) {
								node_index = pb_graph_node->child_pb_graph_nodes[pb->mode][i][j].output_pins[port_index][m].pin_count_in_cluster;
								if (pb_route[node_index].atom_net_id) {
									is_used = true;
									break;
								}
							}
							port_index++;
						}
					}
					clustering_xml_open_block(block_node, type,
							&pb_graph_node->child_pb_graph_nodes[pb->mode][i][j],
							j, is_used, pb_route);
				}
			}
		}
	}
}

/* This routine dumps out the output netlist in a format suitable for  *
* input to vpr. This routine also dumps out the internal structure of *
* the cluster, in essentially a graph based format.                   */
void output_clustering(const vtr::vector_map<ClusterBlockId, std::vector<t_intra_lb_net>*> &intra_lb_routing, bool global_clocks,
		const std::unordered_set<AtomNetId>& is_clock, const std::string& architecture_id, const char *out_fname, bool skip_clustering) {
    auto& device_ctx = g_vpr_ctx.device();
    auto& atom_ctx = g_vpr_ctx.atom();
	auto& cluster_ctx = g_vpr_ctx.mutable_clustering();

	if(!intra_lb_routing.empty()) {
		VTR_ASSERT(intra_lb_routing.size() == cluster_ctx.clb_nlist.blocks().size());
		for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
			cluster_ctx.clb_nlist.block_pb(blk_id)->pb_route = alloc_and_load_pb_route(intra_lb_routing[blk_id], cluster_ctx.clb_nlist.block_pb(blk_id)->pb_graph_node);
		}
	}

	pb_graph_pin_lookup_from_index_by_type = new t_pb_graph_pin **[device_ctx.num_block_types];
	for(int itype = 0; itype < device_ctx.num_block_types; itype++) {
		pb_graph_pin_lookup_from_index_by_type[itype] = alloc_and_load_pb_graph_pin_lookup_from_index(&device_ctx.block_types[itype]);
	}

	pugi::xml_document out_xml;

	pugi::xml_node block_node = out_xml.append_child("block");
	block_node.append_attribute("name") = out_fname;
	block_node.append_attribute("instance") = "FPGA_packed_netlist[0]";
	block_node.append_attribute("architecture_id") = architecture_id.c_str();
	block_node.append_attribute("atom_netlist_id") = atom_ctx.nlist.netlist_id().c_str();

	std::vector<std::string> inputs;
	std::vector<std::string> outputs;

    for(auto blk_id : atom_ctx.nlist.blocks()) {
        auto type = atom_ctx.nlist.block_type(blk_id);
		switch (type) {
        case AtomBlockType::INPAD:
			if (skip_clustering) {
				VTR_ASSERT(0);
			}
			inputs.push_back(atom_ctx.nlist.block_name(blk_id));
			break;

        case AtomBlockType::OUTPAD:
			if (skip_clustering) {
				VTR_ASSERT(0);
			}
			outputs.push_back(atom_ctx.nlist.block_name(blk_id));
			break;

        case AtomBlockType::BLOCK:
			if (skip_clustering) {
				VTR_ASSERT(0);
			}
			break;

		default:
			VTR_LOG_ERROR(
					"in output_netlist: Unexpected type %d for atom block %s.\n",
					type, atom_ctx.nlist.block_name(blk_id).c_str());
		}
	}

	block_node.append_child("inputs").text().set(vtr::join(inputs.begin(), inputs.end(), " ").c_str());
	block_node.append_child("outputs").text().set(vtr::join(outputs.begin(), outputs.end(), " ").c_str());

	if (global_clocks) {
		std::vector<std::string> clocks;
        for(auto net_id : atom_ctx.nlist.nets()) {
            if(is_clock.count(net_id)) {
				clocks.push_back(atom_ctx.nlist.net_name(net_id));
			}
		}

		block_node.append_child("clocks").text().set(vtr::join(clocks.begin(), clocks.end(), " ").c_str());
	}

	if (skip_clustering == false) {
		for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
			/* TODO: Must do check that total CLB pins match top-level pb pins, perhaps check this earlier? */
			clustering_xml_block(block_node, cluster_ctx.clb_nlist.block_type(blk_id), cluster_ctx.clb_nlist.block_pb(blk_id), size_t(blk_id), cluster_ctx.clb_nlist.block_pb(blk_id)->pb_route);
		}
	}

	out_xml.save_file(out_fname);

	print_stats();

	if(!intra_lb_routing.empty()) {
		for (auto blk_id : cluster_ctx.clb_nlist.blocks()) {
			free_pb_route(cluster_ctx.clb_nlist.block_pb(blk_id)->pb_route);
			cluster_ctx.clb_nlist.block_pb(blk_id)->pb_route = nullptr;
		}
	}

	for(int itype = 0; itype < device_ctx.num_block_types; itype++) {
		free_pb_graph_pin_lookup_from_index (pb_graph_pin_lookup_from_index_by_type[itype]);
	}
	delete[] pb_graph_pin_lookup_from_index_by_type;
}
