blob: b093af34f84b1ba9f16afd1467e28f9235c71840 [file] [log] [blame]
/* This file contains the functions to write the AtomNetlist into a hypergraph
* (format: http://glaros.dtc.umn.edu/gkhome/fetch/sw/hmetis/manual.pdf) for hMetis to partition.
*
* Brief summary of formatting
* ===========================
* Hypergraph H = (V, Eh) with V vertices and Eh hyperedges stored in plain text file.
* Contains |Eh|+1 lines if vertices weightless, and |Eh|+|V|+1 lines if weighted.
* Lines starting with ‘%’ are comments.
*
* First line contains 2 or 3 integers:
* (1) |Eh| = # of hyperedges
* (2) |V| = # of vertices
* (3) fmt = format (can be omitted, 1, 10, or 11, further explained below)
*
* The next |Eh| lines represent vertices contained in each hyper edge.
* Weights for hyperedge Eh_i are represented with an extra # at the end of each line.
*
* There are another |V| lines if vertices are weighted.
* Weights are a single #, for each vertex V_j.
*
* Example
* =======
* |Eh| = 4, |V| = 7, fmt = omitted
*
* Eh | V - Connected cliques
* ----------------------------
* 1 | 1, 2
* 2 | 1, 7, 5, 6
* 3 | 5, 6, 4
* 4 | 2, 3, 4
*
* This example translates to the following input hypergraph file:
* 4 7
* 1 2
* 1 7 5 6
* 5 6 4
* 2 3 4
*
* IMPORTANT NOTE
* ==============
* Hyperedges and vertices for input to hMetis start from 1 -> num_edges/vertices, not from 0
*
*/
#include <fstream>
#include <iostream>
#include <string>
#include "vpr_error.h"
#include "globals.h"
#include "hmetis_graph_writer.h"
using namespace std;
/* Local subroutines */
void write_unweighted_edges(fstream &fp);
void write_weighted_edges(fstream &fp);
void write_weighted_vertices(fstream &fp);
/* Main function in writing the hMetis hypergraph
* file_name: name of the file to write out to
*/
void write_hmetis_graph(std::string &file_name) {
fstream fp;
fp.open(file_name, fstream::out | fstream::trunc);
/* Prints out general info for easy error checking*/
if (!fp.is_open() || !fp.good()) {
vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
"couldn't open file \"%s\" for generating hypergraph file\n", file_name.c_str());
}
cout << "Writing hMetis hypergraph to " << file_name << endl;
auto& atom_ctx = g_vpr_ctx.atom();
/* Possible fmt values
* omitted - unweighted graph
* 1 - weighted Eh
* 10 - weighted V
* 11 - weighted Eh & V
*/
string fmt; //TODO: set fmt accordingly (may be passed in as an argument)
//First line - write # of hyperedges, then # of vertices, (optional) then fmt
fp << size_t(atom_ctx.nlist.nets().size()) << " " << size_t(atom_ctx.nlist.blocks().size()) << " " << fmt;
// Unweighted
if (fmt.empty()) {
write_unweighted_edges(fp);
}
// Weighted Eh
else if (fmt == "1") {
write_weighted_edges(fp);
}
// Weighted V
else if (fmt == "10") {
write_weighted_vertices(fp);
}
// Weighted Eh & V
else {
if (fmt != "11") {
vpr_throw(VPR_ERROR_OTHER, __FILE__, __LINE__,
"fmt %s is not (empty, 1, 10, 11)", fmt.c_str());
}
write_weighted_edges(fp);
write_weighted_vertices(fp);
}
fp.close();
cout << "Finished writing hMetis hypergraph to " << file_name << endl << endl;
}
/* Function to write if the hypergraph has unweighted edges
* The ith line written has the vertices connected by Eh_i
*/
void write_unweighted_edges(fstream &fp) {
auto& atom_ctx = g_vpr_ctx.atom();
// For each net, write the blocks connected to that net
for (auto net_id : atom_ctx.nlist.nets()) {
fp << endl;
for (auto pin_id : atom_ctx.nlist.net_pins(net_id)) {
//TODO: Put this into a map to check for duplicated blocks
//i.e. Net connects to more than one pin of the same block
fp << size_t(atom_ctx.nlist.pin_block(pin_id)) + 1 << " ";
}
}
}
/* Function to write if the hypergraph has weighted edges */
void write_weighted_edges(fstream &fp) {
auto& atom_ctx = g_vpr_ctx.atom();
// For each net, write all the blocks connected to that net
for (auto net_id : atom_ctx.nlist.nets()) {
int net_weight = 0; //TODO: Find a good metric for weight of the net
fp << endl;
for (auto pin_id : atom_ctx.nlist.net_pins(net_id)) {
fp << size_t(atom_ctx.nlist.pin_block(pin_id)) + 1 << " ";
}
// After all blocks are written, write the weight of the net
fp << net_weight;;
}
}
/* Function to write if the hypergraph has weighted vertices */
void write_weighted_vertices(fstream &fp) {
auto& atom_ctx = g_vpr_ctx.atom();
// For each block (vertex), write the weight on a separate line
// for (auto block_id : atom_ctx.nlist.blocks()) {
for (unsigned int i = 0; i < atom_ctx.nlist.blocks().size(); i++) {
int block_weight = 0; //TODO: Find a good metric for weight of the pin
fp << endl << block_weight;
}
}