//BlifSim.cpp
//Vytvoril Karel Houzvicka jako bakalarskou praci na CVUT FEL 2010
#include "../../Multilevel/stdafx.h"
#include <time.h>
#include <stdlib.h>
#include <iostream>
#include <math.h>
#include <map>
#include <time.h>
using namespace std;
#include "../../Kernel/kernelincludes.h"
#include "../../Multilevel/blif.h"

//Bitove pole DC  1,0 -> 1 ; '-' -> 0 
//Prevede string na bitvector
bitvector iTermToBitDC(string IM){
	int i;
	bitvector out(IM.length());
	for(i=IM.length()-1;i>=0;i--){
		if(IM.c_str()[i]=='1'||IM.c_str()[i]=='0'){
			out.setbit(i,1);
		}
	}
	return out;
}

//bitove pole 1, '-' -> 0 
//Prevede string na bitvector
bitvector iTermToBit(string IM){
	int i;
	bitvector out(IM.length());
	for(i=IM.length()-1;i>=0;i--){
		if(IM.c_str()[i]=='1'){
			out.setbit(i,1);
		}
	}
	return out;
}

//simulace jednoho PLA v Blifu.
//vstup: vektor paru (data,dc), pro paralelní simulaci a SoPLA
//vystup: vysledny par (data,dc) PLA
pair<unsigned int,unsigned int> SoPlaSimul(vector <pair<unsigned int,unsigned int>> * iBitV,SoPLA vstupPLA){
    list<Cube> * lCube= vstupPLA.GetData();
	list<Cube>::iterator iter;
	bitvector term,dcterm;
	unsigned int maska,maskadc;
	pair<unsigned int,unsigned int> vysledek=make_pair(0,0xFFFFFFFF);
	unsigned int i;
	unsigned int data;
	unsigned int dc;

	//pokud to je konstanta
	if(iBitV->size()==0){
		if(vstupPLA.GetType()){return make_pair(0xFFFFFFFF,0xFFFFFFFF);}
		else{ return make_pair(0,0xFFFFFFFF);}
		
	}
	for(iter=lCube->begin();iter!=lCube->end();iter++){
		term = iTermToBit((*iter).GetIM());
		dcterm = iTermToBitDC((*iter).GetIM());

		maska=0xFFFFFFFF;
		maskadc=0xFFFFFFFF;
		for(i=0;i<term.size();i++){
			dc=0xFFFFFFFF*dcterm[i];
			data=0xFFFFFFFF*term[i];
			maska=maska&(~dc|(iBitV->at(i).first&data)|(~iBitV->at(i).first&iBitV->at(i).second&~data));
			maskadc=maskadc&(~((iBitV->at(i).second&data)^(iBitV->at(i).first&dc)));
		}		
		
		
		maskadc=~(maskadc^maska);
	    
		vysledek.second=vysledek.first|maska|(vysledek.second&maskadc);	
		vysledek.first=vysledek.first|maska;
	}
	if(!vstupPLA.GetType()){
		vysledek.first=(~vysledek.first)&vysledek.second;
		}
	return vysledek;
}


//Vypise  Bitvector
void vypisVector(bitvector in){
unsigned int i;
		 for (i=0; i< in.size();i++){
			cout<<in[i];
		 }
		 cout<<endl;
}


//predpokladam validni vstup
//Simulace blif
//Vstup je mapa vstupnich symbolu reprezentovana parem (dat, dc)--> 32 vectoru
//Vystupni mapa 32b paru
map<string,pair<unsigned int,unsigned int>> * blifSimul (Blif * bl, map<string,pair<unsigned int,unsigned int>> *mapIn,map<string,pair<unsigned int,unsigned int>> *mapLatch=0){

	unsigned int i,k;
	list<SoPLA>::iterator iter;
	vector<pair<unsigned int, unsigned int>>  simul;
	pair<unsigned int, unsigned int> valueSoPla;
		//vystupni
	 map<string,pair<unsigned int,unsigned int>> * mapOut= new map<string,pair<unsigned int,unsigned int>>() ;
		//vnitrni promenne
	 map<string,pair<unsigned int,unsigned int>> * mapOther= new map<string,pair<unsigned int,unsigned int>>() ;

	 map<string,pair<unsigned int,unsigned int>>::iterator iterMap;
	

	for(i=0;i<bl->GetONames().size();i++){
		mapOut->insert(pair<string, pair<unsigned int, unsigned int>>(bl->GetOName(i),make_pair(0,0)));
	}
	// ted mam inicializovane vsechny pole
	// zacnu prochazet SoPLa

			for(iter=bl->GetData()->begin();iter!=bl->GetData()->end();iter++){

				if((*iter).IsDFF()){continue;}//preskocim latche

				simul.clear();
				for(k=0; k<(*iter).GetINames().size();k++){	//projdu jmena a slozim vstup do PLA 
					
					iterMap = mapIn->find((*iter).GetIName(k));
					if(iterMap!=mapIn->end()){// nalezla se hodnota ve vstupnim vektoru, ten je vzdy platny
						simul.push_back(iterMap->second);
					}else{
						iterMap= mapOther->find((*iter).GetIName(k));
						if(iterMap!=mapOther->end()){//nalezla se hodnota
							simul.push_back(iterMap->second);
						}else{
							iterMap=mapOut->find((*iter).GetIName(k));
							if(iterMap!=mapOut->end()){//nalezla se hodnota, v kombinacnim obvodu vzdy
								simul.push_back(iterMap->second);
							}else{
								iterMap=mapLatch->find((*iter).GetIName(k));
								simul.push_back(iterMap->second);
							}
						}
					}
				}

				// odsimuluji
				 valueSoPla= SoPlaSimul(&simul,(*iter));
					
				//zapisu vysledek
				 iterMap= mapOut->find((*iter).GetName());
				 if(iterMap!=mapOut->end()){
					 (*mapOut)[(*iter).GetName()]=valueSoPla;
				 }else{
					//tady uz musi vyjit index (in je pevne dan)
							(*mapOther)[(*iter).GetName()]=valueSoPla;	
				 }
			}

		//projdu a ulozim novou hodnotu do latch
		for(iter=bl->GetData()->begin();iter!=bl->GetData()->end();iter++){
			if((*iter).IsDFF()==false){break;}
				 iterMap= mapOut->find((*iter).GetIName(0));
				 if(iterMap!=mapOut->end()){
					 (*mapLatch)[(*iter).GetName()]=iterMap->second;
				 }else{
					iterMap= mapOther->find((*iter).GetIName(0));
					 (*mapLatch)[(*iter).GetName()]=iterMap->second;
				 }
		}
		
		delete mapOther;
	return mapOut;
}

//Se vstupnimi vektory provede paralelizaci, zavola simulaci a posleze provede deparalelizaci vystupnich vektoru.
list<bitvector> * startBlifSimul(Blif & bl, list<bitvector> * inList){
	
	list<bitvector> * out= new list<bitvector>()  ; //slozeny vystup
	
	out->clear();
	bitvector out1(bl.GetOutputs());
	bitvector out2(bl.GetOutputs());
	int countIn = inList->size()/2;


	map<string,pair<unsigned int,unsigned int>> mapBlifIn;
	map<string,pair<unsigned int,unsigned int>>  *mapBlifOut;
	map<string,pair<unsigned int,unsigned int>>::iterator iterMap;
	list<bitvector>::iterator iterL,iterL2;

	unsigned int j,i;
	int k;
	unsigned int pomoc;
	unsigned int pomoc2;
	bitvector bv;		//samostatny bitVector
	bitvector bvDC;		//a DC
	unsigned int maska; //maska
//pridani latch, ten se musi simulovat po jednom 
	map <string,pair<unsigned int,unsigned int>> mapLatch;
	list<SoPLA>::iterator iter;
	if(inList->empty()==true){
		return out;
	}
	if(bl.GetData()->begin()->IsDFF()){
		//pridam latch
		for(iter=bl.GetData()->begin();iter!=bl.GetData()->end();iter++){
			if((*iter).IsDFF()==false){break;}
			mapLatch[(*iter).GetName()]=make_pair(0,0xFFFFFFFF);//0,1 -> 0

		}

		for(iterL=inList->begin();iterL!=inList->end();iterL++){
		    iterL2=iterL;
		    iterL2++;
			//vymazu vstupy+ na zacatku nadefinuji
			for(i=0;i<bl.GetINames().size();i++){
				mapBlifIn[bl.GetIName(i)].first=0;
				mapBlifIn[bl.GetIName(i)].second=0;
			}
			bv= (*iterL);
			bvDC=(*iterL2);
			for(j=0;j<bv.size();j++){
				pomoc=0xFFFFFFFF*bv[j];
				pomoc2=0xFFFFFFFF*bvDC[j];
				iterMap=mapBlifIn.find(bl.GetIName(j));
				iterMap->second.first=pomoc;
				iterMap->second.second=pomoc2;			
			
			}
			mapBlifOut = blifSimul(&bl,&mapBlifIn,&mapLatch);

			for(j=0; j<mapBlifOut->size();j++){
				iterMap=(*mapBlifOut).find(bl.GetOName(j));

				if((iterMap->second.first)>0){out1.setbit(j,1);}
										else{out1.setbit(j,0);}
				if((iterMap->second.second)>0){out2.setbit(j,1);}
										else{out2.setbit(j,0);}

				}
			delete mapBlifOut;
			out->push_back(out1);
			out->push_back(out2);
		iterL=iterL2;	
		}
		
	}else{


//***********
		iterL=inList->begin();
		iterL2=iterL;
		iterL2++;
		while(iterL2!=inList->end()){
			maska = 1;
				//vymazu vstupy+ na zacatku nadefinuji
				for(i=0;i<bl.GetINames().size();i++){
					mapBlifIn[bl.GetIName(i)].first=0;
					mapBlifIn[bl.GetIName(i)].second=0;
				}	


				for(i=0; i<32;i++){
					bv= (*iterL);
					bvDC= (*iterL2);			
					for(j=0;j<bv.size();j++){
							pomoc=0xFFFFFFFF*bv[j];
							pomoc2=0xFFFFFFFF*bvDC[j];
							 iterMap=mapBlifIn.find(bl.GetIName(j));
							 iterMap->second.first=(maska&pomoc)|iterMap->second.first;
							 iterMap->second.second=(maska&pomoc2)|iterMap->second.second;

					}
					maska=maska<<1;
					iterL++;
					iterL++;
					iterL2++;
					if (iterL2==inList->end()){
						break;;
					}
					iterL2++;

				}
				mapBlifOut = blifSimul(&bl,&mapBlifIn);
				//z vektoru int na list bitvectoru
				
				maska = 1;
				for (k=0;k<32&&k<countIn;k++){
					for(j=0; j<mapBlifOut->size();j++){
						iterMap=mapBlifOut->find(bl.GetOName(j));

						if((iterMap->second.first&maska)>0){out1.setbit(j,1);}
											else{out1.setbit(j,0);}
						if((iterMap->second.second&maska)>0){out2.setbit(j,1);}
											else{out2.setbit(j,0);}

					}

					out->push_back(out1);
					out->push_back(out2);
					maska=maska<<1;
				}
				delete mapBlifOut;
				countIn=countIn-32;
		}
	}
return out;
}

//generuje maximalni moznou tabulku vstupu. 2^inputs.
list<bitvector> generateInputMax(int inputs){
	vector<unsigned long long int> mocniny;
	list<bitvector> l;
	l.clear();
	bitvector v(inputs);
	bitvector vdc(inputs);
	int i;
	unsigned long long int r,line, zb, div;
	r=1;
	for (i=0; i<inputs;i++){
		r=r*2;
		vdc.setbit(i,true);
	}
	line=0;
	while(line<r){
		div=line;
		for(i=0;i<inputs;i++){
			zb=div%2;
			div=div/2;
			if(zb==1){
				v.setbit(inputs-i-1,1);
			}else{
				v.setbit(inputs-i-1,0);
			}
		}
		l.push_back(v);
		l.push_back(vdc);
		line++;
	}
return l;

}


//metoda na generovani vstupnich vektoru pro simulaci.
//int inputs - velikost vygenerovanych vektoru.
//int count - urcuje pocet vygenerovanych vektoru, kdyz je -1, generuje se uplna tabulka vstupu.
//bool dc - true-> s neurcitymi stavy, false-> bez neurcitych stavu
list<bitvector> generateInput(int inputs, int count, bool dc){
	list<bitvector> l;
	bitvector v(inputs);
	bitvector vdc(inputs);//vector DC
	int randI;
	long int i,j;
	if(count!=-1){
		srand((unsigned)time(0));
		if(dc){
				for(i=0;i<count; i++){
					for(j=0;j<inputs;j++){
						randI= rand() % 2;
						if(randI==1){
							v.setbit(j,true);
						}else{
							v.setbit(j,false);
						}
						randI= rand() % 2;
						if(randI==1){
							vdc.setbit(j,true);
						}else{
							vdc.setbit(j,false);
						}
					}
					l.push_back(v&vdc);
					l.push_back(vdc);
				 }

		}else{
				for (i=0; i<inputs;i++){
					vdc.setbit(i,true); //zatim nastavim na 1(bez dc)
				}
				for(i=0;i<count; i++){
					for(j=0;j<inputs;j++){
						randI= rand() % 2;
						if(randI==1){
							v.setbit(j,true);
						}else{
							v.setbit(j,false);
						}
					}
					l.push_back(v);
					l.push_back(vdc);
				 }
		}
	}else{
		l= generateInputMax(inputs);
	}
	return l;
	}

//Ulozi list bitvectorů in  do souboru filename.
void saveListBitvector(list<bitvector> * in, string fileName){
	list<bitvector>::iterator iter;
	list<bitvector>::iterator iter2;	// na ukladani tretiho stavu, ten ve definovan dcvectorem pod data vektorem
	ofstream stream(fileName.c_str(), ios::out);
	if (!stream.is_open()) throw IOException( "Nemuzu otevrit soubor: " + fileName );
	stream <<(in->begin()->size())<<endl;
	stream<< (in->size()/2)<<endl;
	for(iter=in->begin();iter!=in->end();iter++){
		iter2=iter;	
		iter2++;
		for(unsigned int i=0; i< (*iter).size();i++){
			if((*iter2)[i]){
				stream<<(*iter)[i];
			}else{
				stream<<"-";
			}
		}
		stream<<endl;
		iter=iter2;
	}
	stream.close();
}

//Metoda na ukladani kompletniho vypisu vstupu proti vystupu.
void saveListBitvector(list<bitvector> * in, list<bitvector> * out, string fileName, Blif * bl){
	list<bitvector>::iterator iter, iterO;
	list<bitvector>::iterator iter2, iterO2;	// na ukladani tretiho stavu, ten ve definovan dcvectorem pod data vektorem
	ofstream stream(fileName.c_str(), ios::out);
	if (!stream.is_open()) throw IOException( "Nemuzu otevrit soubor: " + fileName );
	stream <<(in->begin()->size())<<endl;
	stream<< (in->size()/2)<<endl;
	stream <<".model "<<bl->GetModel()<<endl;
	stream<<".inputs";
	for(unsigned int i=0;i<bl->GetInputs(); i++){
		stream<<" "<<bl->GetIName(i);
	}
	stream<<endl;
	stream<<".outputs";
	for(unsigned int i=0;i<bl->GetOutputs(); i++){
		stream<<" "<<bl->GetOName(i);
	}
	stream<<endl;
	iterO=out->begin();
	iterO2=iterO;
	iterO2++;
	for(iter=in->begin();iter!=in->end();iter++){
		iterO2=iterO;
	    iterO2++;

		iter2=iter;	
		iter2++;
		for(unsigned int i=0; i< (*iter).size();i++){
			if((*iter2)[i]){
				stream<<(*iter)[i];
			}else{
				stream<<"-";
			}
		}
		stream<<" ";
		for(unsigned int i=0; i< (*iterO).size();i++){
			if((*iterO2)[i]){
				stream<<(*iterO)[i];
			}else{
				stream<<"-";
			}
		}	
		stream<<endl;
		iterO2++;
		iterO=iterO2;
		iter=iter2;
	}
	stream<<".end"<<endl;
	stream.close();
}

//Metoda, ktera nacita soubor vstupnich vectoru
list<bitvector> loadListBitvector(string fileName, unsigned int inputs){
	list<bitvector> l;
	unsigned int bsize;
	int lsize;
	string line,line2;
	bitvector b;	
	bitvector bDC;
	ifstream stream;
	stream.open(fileName.c_str());

	if (!stream.is_open())throw IOException( "Nemuzu otevrit soubor: " + fileName ); 
		stream>>bsize;
		b.resize(bsize);
		bDC.resize(bsize);
		stream>>lsize;
		if(bsize!=inputs){
			l.clear();
			stream.close();
			throw IOException( "Chyba ve vstupu. Vstupni vektory nemaji pozadovanou velikost." ); 	
		}

		for(int i =0; i< lsize;i++){
			do {
				getline(stream,line);
				if (stream.eof()){
						l.clear();
						stream.close();
						throw IOException( "Chyba ve vstupu." ); 	
					}
			}
			while(line.length()==0||line.c_str()[0]=='.'||line.c_str()[0]=='#');

			if(line.length()<bsize){
				l.clear();
				stream.close();
				throw IOException( "Chyba ve vstupu." ); 				
			}
			//test vstupu
			line2="";
			for(unsigned int j=0;j<bsize;j++){
				if(line.c_str()[j]=='0'||line.c_str()[j]=='1'||line.c_str()[j]=='-'){
					line2=line2+line.c_str()[j];
				}else{
					l.clear();
					stream.close();
					throw IOException( "Chyba ve vstupu." ); 	
				}

			}
				b=iTermToBit(line2);
				bDC=iTermToBitDC(line2);
			
			l.push_back(b);
			l.push_back(bDC);
		}	
		stream.close();
		return l;
}

//Provede predzpracovani souboru BLIF pro rychlejsi simulaci.
void predzpracovani(Blif * bl){
	map<string, bool> mapValid;
	unsigned int k,i;
	bool jde;
 	map<string, bool>::iterator iterMap;
	list<SoPLA>::iterator iter;
	int nezarazeno=bl->GetData()->size();
	list<SoPLA> nova;
	//latch
	for(iter=bl->GetData()->begin();iter!=bl->GetData()->end();iter++){
		if((*iter).IsDFF()){
			(*iter).tmp=55;
			//pridam latch, ktery je platny
			mapValid.insert(pair<string, bool>((*iter).GetName(),true));
			nova.push_back(*iter);
			nezarazeno--;
		}
	}
	//vstupy vzdy platne
	for(i=0;i<bl->GetINames().size();i++){
		mapValid.insert(pair<string, bool>(bl->GetIName(i),true));
	}
	//vystupy na zacatku neplatne
	for(i=0;i<bl->GetONames().size();i++){
		mapValid.insert(pair<string, bool>(bl->GetOName(i),false));
	}
	//+ vnitrni promenne
	
	while(nezarazeno>0){
		for(iter=bl->GetData()->begin();iter!=bl->GetData()->end();iter++){
			if((*iter).tmp==55){continue;}
			jde=true;
				for(k=0; k<(*iter).GetINames().size();k++){	//projdu jmena a slozim vstup do PLA 
					iterMap=mapValid.find((*iter).GetIName(k));
					if(iterMap!=mapValid.end()){// nalezla se hodnota
						if(iterMap->second==false){
							jde=false;
							break;
						}
					}else{	//nenalezla-> nova vnitrni
						mapValid.insert(pair<string, bool>((*iter).GetIName(k),false));
						jde=false;
						break;
					}
				}

				if(jde){
					(*iter).tmp=55;
					if(mapValid.find((*iter).GetName())!=mapValid.end()){//pro deklarace (.names k /n1)
						mapValid[(*iter).GetName()]=true;
					}else{
						mapValid.insert(pair<string, bool>((*iter).GetName(),true));
					}
					nova.push_back(*iter);
					nezarazeno--;
					break;
				}
		}
	}
	bl->GetData()->clear();
	bl->GetData()->swap(nova);
}

//Vypise list bitvectoru na konzoli.
void vypisMnozinu(list<bitvector> * mnozina){
	list<bitvector>::iterator iter,iter2;
	for(iter=mnozina->begin();iter!=mnozina->end();iter++){
		iter2=iter;
		iter2++;
		cout<<endl;
		for (unsigned int i=0; i<(*iter).size();i++){
				if((*iter)[i]&&(*iter2)[i]){
					cout<<"1";
				}else{
					if((*iter2)[i]==false){
						cout<<"-";
					}else{
						cout<<"0";
					}
				}
		}
		cout<<endl;
		iter=iter2;
	}
}

//Metoda, pro nacteni cisla ze vstupnich parametru.
int strToInt(string in){
	int vystup=0;
	int rad = 1;
	for(int i = in.length()-1;i>=0;i--){
		if(in.c_str()[i]<'0'||in.c_str()[i]>'9'){
			return -1;//chyba
		}
		vystup=vystup+rad*(in.c_str()[i]-'0');
		rad=rad*10;
	}
	return vystup;
}

void napoveda(){
	cout<<"BlifSim, program na simulaci obvodu BLIF."<<endl;
	cout<<"Vytvoril Karel Houzvicka, jako bakalarskou praci na CVUT FEL roku 2010."<<endl<<endl;
	cout<<"Napoveda."<<endl;
	cout<<"Program simuluje kombinacni a sekvencni obvody BLIF i s plne neurcenymi vstupy. Sekvencni obvody zapsane pomoci tabulek LUTu a pouzivajici .latch."<<endl;
	cout<<"Parametry:"<<endl;
	cout<<"1. soubor blif"<<endl;
	cout<<"   '?' napoveda"<<endl;
	cout<<"2. vstupni soubor"<<endl;
	cout<<"   vstupni soubor s vektory"<<endl;
	cout<<"   '-gf' pro kompletni tabulku stavu"<<endl;
	cout<<"   '-g 500' generovani 500 vektoru bez dc"<<endl;
	cout<<"   '-gdc 500' s neurcitymi stavy"<<endl;
	cout<<"3. vystupni soubor"<<endl;
	cout<<"   '-sf out.txt' ulozi vstupy a vystupy proti sobe"<<endl;
	cout<<"   '-s out.txt' ulozi jen vystupy"<<endl;
	cout<<"   '-t' testovaci mod. Bez vypisu podrobnosti o blifu a bez ulozeni vysledku."<<endl;
	cout<<" kdyz neni zadan vystupni soubor, tak out.txt"<<endl;
}

//Parametry:
//1. soubor blif
//   "?" napoveda
//2. vstupni soubor
//   vstupni soubor s vektory
//   "-gf" pro kompletni tabulku stavu
//   "-g 500" generovani 500 vektoru bez dc
//   "-gdc 500" s neurcitymi stavy
//3. vystupni soubor
//   "-sf out.txt" ulozi vstupy a vystupy proti sobe
//   "-s out.txt" ulozi jen vystupy
//   "-t" testovaci mod. Bez vypisu podrobnosti o blifu a bez ulozeni vysledku.
// kdyz neni zadan vystupni soubor, tak out.txt
int main(int argc, char** argv)
{
	string  iStr, vstup, vystup="";
	char  s_char[50];
	Blif bl;
	unsigned int i;
	list<bitvector> mnozina;
	list<bitvector> * mnozinaOut;
	list<bitvector>::iterator iter;
	int pocet;
	bool dc;
	list<SoPLA>::iterator iter2;
	string s_charStr;
	bool test=false;
	
    string ar, ar2;
	for(int p=0;p<argc;p++){
		ar=argv[p];
		if(ar=="-t"){
			test=true;
			break;
		}
		if(ar=="?"){
			napoveda();
			return 0;
		}
	}
	if(!test){
		cout<<"BlifSim, program na simulaci obvodu BLIF."<<endl;
		cout<<"Vytvoril Karel Houzvicka, jako bakalarskou praci na CVUT FEL roku 2010."<<endl<<endl;
	}

	try{
		if(argc>1){
			bl.LoadBlif(argv[1]);
			s_charStr=argv[1];
		}else{
			cout<<"Zadejte vstupni soubor :"<<endl;
			cin.getline(s_char,50);
			bl.LoadBlif(s_char);
			s_charStr=s_char;
		}
	}

	catch (IOException e){
			cout<<e.GetMsg()<<endl;
			return 0;
		}

	if(bl.GetData()->size()==0){
		cout<<"Chyba v souboru: "<<s_charStr<<endl;
		return 0;
	}
	predzpracovani(&bl);
	
	//zjisteni poctu LUTu, protoze v seznamu LUTu jsou i latche
	int pocetLUTu=bl.GetData()->size();
	for(iter2=bl.GetData()->begin();iter2!=bl.GetData()->end();iter2++){
		if(iter2->IsDFF()){
			pocetLUTu--;
		}else{
			break;
		}

	}
	if(!test){
		
		cout<<"Test BLIF"<<endl<<"Soubor "<<s_charStr<<":"<<endl;
		cout<<"Pocet LUTu: "<<pocetLUTu<<endl;
		cout<<"vstupy ("<<bl.GetINames().size()<<"): "<<endl;
			for(i=0; i<bl.GetINames().size();i++){
			cout<<bl.GetIName(i)<<" ";
		}
		cout<<endl;
		cout<<"vystupy ("<<bl.GetONames().size()<<"): "<<endl;
			for(i=0; i<bl.GetONames().size();i++){
			cout<<bl.GetOName(i)<<" ";
		}
		cout<<endl<<endl;	
	}else{
		cout<<s_charStr<<";"<<bl.GetINames().size()<<";"<<bl.GetONames().size()<<";"<<pocetLUTu<<";";
	}



	//zpracovani dalsich parametru
	
	int p=0;
	int argp=0;
	bool full=false;

	if(argc>2){
		if(argc<4){
			cout<<"Chyba v parametrech."<<endl;
			return 0;
		}
		ar= argv[2];
		argp=2;
		if(ar=="-gf"){
			mnozina.clear();
			mnozina = generateInput(bl.GetInputs(),-1,false);
		}else{
			if(ar=="-g"){
				argp++;
				pocet=strToInt(argv[argp]);
				if(pocet==-1){
					cout<<"Chyba v parametrech."<<endl;
					return 0;
				}
				mnozina.clear();
				mnozina = generateInput(bl.GetInputs(),pocet,false);
			}else{
				if(ar=="-gdc"){
					argp++;
					pocet=strToInt(argv[argp]);
					if(pocet==-1){
						cout<<"Chyba v parametrech."<<endl;
						return 0;
					}
					mnozina.clear();
					mnozina = generateInput(bl.GetInputs(),pocet,true);
				}else{
					vstup=ar;
				}
			}
		}
		argp++;
		if(argp>=argc){
				cout<<"Chyba v parametrech."<<endl;
				return 0;
		}
		ar= argv[argp];
		if(ar=="-sf"||ar=="-s"||ar=="-t"){
			argp++;
			if(argc==argp+1){
				vystup=argv[argp];
			}else{
				vystup="out.txt";
			}
			if(	ar=="-s"){
				full=false;
			}else{
				if(	ar=="-sf"){
					full=true;
				}else{
					if(ar=="-t"){
						test=true;
					}else{
						cout<<"Chyba v parametrech."<<endl;
						return 0;
					}
				}
			}
		}else{
			cout<<"Chyba v parametrech."<<endl;
			return 0;
		}
		if(mnozina.empty()){
			goto simArg;
		}else{
			if(test){
				cout<<pocet<<";";
			}
			goto sim;
		}
	}
	


menu:

	cout<<"Prejete si:"<<endl;
	cout<<"a) Vygenerovat nove vstupy."<<endl;
	cout<<"b) Nacist vstupy ze souboru."<<endl;
	cout<<"c) Zadat vstup rucne."<<endl;
	cout<<"d) Napoveda."<<endl;
	cout<<"x) Konec."<<endl;

	getline(cin,iStr);
	
	if(iStr=="a"){
zadavani:		cout<<"Zadejte pocet vstupnich vectoru:"<<endl;
		cout<<"(Pro 2^n tabulku: -1)"<<endl;
			cin>>pocet;
			cin.clear();
			dc=false;
			cin.ignore(100, '\n');
			if(pocet==0||pocet<-1||cin.fail()){
				cout<<"Zadana spatna hodnota, zkuste to prosim znovu."<<endl;
				goto zadavani;

			}
			if(pocet!=-1){
				cout<<"Prejete si generovat s neurcenymi stavy? (a)"<<endl;
				
				getline(cin,iStr);
				if(iStr=="a"){ dc=true;}
			}
			mnozina.clear();
			mnozina = generateInput(bl.GetInputs(),pocet,dc);
			
			cout<<"Vygenerovano "<<mnozina.size()/2<<" vstupnich vektoru ."<<endl;
			cin.clear();
			//cin.ignore(100, '\n');
			cout<<"Prejete si ulozit vstupni vektory? (a)"<<endl;
			getline(cin,iStr);
			if(iStr=="a"){
				cout<<"Jmeno souboru:"<<endl;
				getline(cin,iStr);
				saveListBitvector(&mnozina,iStr);
			}
			cin.clear();

			cout<<"Prejete si vstupni vektory odsimulovat? (a)"<<endl;
			getline(cin,iStr);
			if(iStr=="a"){
				goto sim;
			}
				
	
	goto menu;		
	}
	if(iStr=="b"){
			cin.clear();
			cout<<"Nazev nacitaneho souboru s vektory:"<<endl;
			getline(cin,vstup);
simArg:		try{
			mnozina = loadListBitvector(vstup,bl.GetInputs());
			}catch (IOException e){
				cout<<e.GetMsg()<<endl;
				return 0;
			}

sim:
			double t2;
			double t=GetMyCPUTime();
			mnozinaOut =startBlifSimul(bl,&mnozina);
		    t2=GetMyCPUTime();
			if(test){
				cout<<(t2-t)<<";"<<((t2-t)/(mnozinaOut->size()/2))*1000000<<endl;
			}else{
				cout<<"Vypocet trval "<<(t2-t)<<"s. Tj. "<<((t2-t)/(mnozinaOut->size()/2))*1000000<<"u (mikro)s na jeden vektor."<<endl;
			}
			cin.clear();
			try{
				if(!test){
					if(vystup==""){
						cout<<"Prejete si ulozit vystupni vectory? (a)"<<endl;
						getline(cin,iStr);
						if(iStr=="a"){
							cin.clear();
							cout<<"Rozsirenou verzi vypisu? (a)"<<endl;
							getline(cin,iStr);
							if(iStr=="a"){
								cout<<"Jmeno souboru:"<<endl;
								getline(cin,vystup);
								saveListBitvector(&mnozina,mnozinaOut,vystup,&bl);
							}else{
					
								cout<<"Jmeno souboru:"<<endl;
								getline(cin,vystup);
								saveListBitvector(mnozinaOut,vystup);
							}
						}
					}else{
						if(full){
							saveListBitvector(&mnozina,mnozinaOut,vystup,&bl);
						}else{
							saveListBitvector(mnozinaOut,vystup);
						}
						delete mnozinaOut;
						mnozina.clear();
						return 0;
					}
				}else{
					delete mnozinaOut;
					mnozina.clear();
					return 0;
				}
			}catch (IOException e){
				cout<<e.GetMsg()<<endl;
				return 0;
			}
			delete mnozinaOut;
			mnozina.clear();
			goto menu;
	}
	if(iStr=="c"){
			cout<<"zadejte vstup:"<<endl;
			 while (getline(cin, iStr)) {	


				 if(iStr.length()!=bl.GetInputs()){
						cout<<"Spatna velikost vstupu. Pozadovana velikost: "<<bl.GetInputs()<<endl;
						return 0;
					}
		 					//test korektnosti vstupu
				 for(i=0;i<iStr.length();i++){
						if(!(iStr.c_str()[i]=='0'||iStr.c_str()[i]=='1'||iStr.c_str()[i]=='-')){
							cout<<"Spatne znaky na vstupu: "<<iStr.c_str()[i]<<endl;
							return 0;
						}
					}

				mnozina.clear();
				mnozina.push_back(iTermToBit(iStr));
				mnozina.push_back(iTermToBitDC(iStr));
				mnozinaOut= startBlifSimul(bl,&mnozina);
				 cout<<"vysledek: ";
				 vypisMnozinu(mnozinaOut);
				 delete mnozinaOut;
				 mnozina.clear();

			 }
			 
	    goto menu;
	}
	if(iStr=="d"){
		napoveda();
		cout<<endl;
        goto menu;
	}
	if(iStr=="x"){
		return 0;
	}
	
	cout<<"Spatna volba."<<endl;
	return 0;
}