#include "stdafx.h"

#include <time.h>

#ifdef _MSC_VER
#pragma hdrstop
#endif

using namespace std;

#include "../../Kernel/kernelincludes.h"
#include "../../Multilevel/Blif.h"
#include "../../Multilevel/Node.h"
#include "../../Multilevel/Signal.h"
#include "../../Multilevel/Network.h"

void Help()
{
	cout << "Syntax: Resynth_order source.blif" << endl;
	cout << "Options:" << endl;
	cout << "  -i        Permute PIs" << endl;
	cout << "  -o        Permute POs" << endl;
	cout << "  -n        Permute nodes" << endl;
	cout << "  -c n      Number of cycles (1 is default)" << endl;
	cout << "  -aig      Count AIG nodes instead of gates" << endl;
}

Network *Permute_nodes( Network *n )
{
	Network *res;
	unsigned int j;
	list<Node>::iterator ndi;

	res = new Network(n);
	res->SetModel("tmp");
	while ( !n->empty() ) {
		j = rand() % n->GetNodes();
		ndi = n->GetNodeByIndex(j);
		res->AddNode(*ndi);
		n->DeleteNode(ndi);
	}
	return res;
}

void Permute_PIs( Network *n )
{
	unsigned int i, j, k;
	string s;

	for ( i = 0; i < n->inputs()*2; i++ ) {
		j = rand() % n->inputs();
		k = rand() % n->inputs();
		s = n->getIName(j);
		n->setIName(j, n->getIName(k));
		n->setIName(k, s);
	}
}

void Permute_POs( Network *n )
{
	unsigned int i, j, k;
	string s;

	for ( i = 0; i < n->outputs()*2; i++ ) {
		j = rand() % n->outputs();
		k = rand() % n->outputs();
		s = n->getOName(j);
		n->setOName(j, n->getOName(k));
		n->setOName(k, s);
	}
}

unsigned int AIGNodes( char *fn )
{
	ifstream f;
	unsigned int n;
	string s;

	f.open(fn);
	f >> s;
	f >> n;
	f >> n;
	f >> n;
	f >> n;
	f >> n;
	f.close();
	return n;
}

int main(int argc, char* argv[])
{
    Blif source, resynblif;
    Blif *dest;
    int i;
	unsigned int j;
	char *src_file = NULL;
	time_t tim;
	Network *net, *net2;
	ofstream dump;
	unsigned int cycles = 1;
	bool pPI = false;
	bool pPO = false;
	bool pN = false;
	unsigned int cyc;
	unsigned int my_min;
	unsigned int my_max;
	unsigned int avg;
	bool aig = false;

	cout << "Resynth_order 1.2, (c) September 2010 by Petr Fiser" << endl;
	if ( argc < 2 ) {
        Help();
        exit(1);
    }
    srand((unsigned) time(&tim));
//    srand(3);

	try {
		i = 1;
		while ( i != argc ) {
			if ( argv[i][0] != '-' && src_file == NULL ) src_file = argv[i];
			else if ( strcmp( argv[i], "-i" ) == 0 ) pPI = true;
			else if ( strcmp( argv[i], "-o" ) == 0 ) pPO = true;
			else if ( strcmp( argv[i], "-n" ) == 0 ) pN = true;
			else if ( strcmp( argv[i], "-c" ) == 0 ) {
				i++;
				cycles =  atoi(argv[i]);
			}
			else if ( strcmp( argv[i], "-aig" ) == 0 ) aig = true;
			else {
				Help();
				exit(1);
			}
			i++;
		}
	} catch (...) {
        Help();
        exit(1);
    }

	if ( src_file == NULL ) {
        Help();
        exit(1);
    }

	try {
		source.LoadBlif(src_file);
	} catch (IOException e) {
			cerr << e.GetMsg() << endl;
			exit(1);
	}

	dump.open("debug.csv");

	cyc = 0;
	dump << "cycle; nodes" << endl;
	my_min = UINT_MAX;
	my_max = 0;
	avg = 0;
	try {
		do {
			net = new Network(source);
			if ( pN ) {
				net2 = Permute_nodes(net);
				delete net;
				net = net2;
			}
			if ( pPI ) Permute_PIs(net);
			if ( pPO ) Permute_POs(net);

			dest = net->ToBlif();
			delete net;
			dest->SaveBlif("to_resyn.blif");
			if ( !aig ) {
				system(RUNSCRIPT("resyn.bat") );
				delete dest;
				resynblif.LoadBlif("from_resyn.blif");
				j = resynblif.GetNodes();
			}
			else {
				system(RUNSCRIPT("aig.bat"));
				j = AIGNodes("out.aig");
			}

			dump << cyc++ << "; " << j << endl;
			if ( my_min > j ) my_min = j;
			if ( my_max < j ) my_max = j;
			avg += j;

		} while (--cycles);
		dump.close();
	} catch (IOException e) {
			cerr << e.GetMsg() << endl;
			exit(1);
	} catch (RuntimeException e) {
			cerr << e.GetMsg() << endl;
			exit(1);
	}
	cerr << src_file << "; " << my_min << "; " << my_max << "; " << (float)avg/(float)cyc << endl;

	return 0;
}
