diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ed08f3a1756867c18241faf6399e8a58f036105..66806e70a888b16879579b9d279d1ba512187f9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) # Add compiler flags if(CMAKE_COMPILER_IS_GNUCC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -std=c++14") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g3 -fpermissive -std=c++17 -pthread") endif() @@ -22,11 +22,7 @@ message(STATUS "Building Petri Net parser ...") include_directories("${PARSER_DIR}/src") add_subdirectory(${PARSER_DIR}) -# add sylvan -message(STATUS "Building Sylvan ...") -set(SYLVAN_DIR "${CMAKE_SOURCE_DIR}/third-party/sylvan") -include_directories(${SYLVAN_DIR}) -add_subdirectory(${SYLVAN_DIR}) + # build spot if it is not installed on the system find_library(SPOT_LIBRARY "spot") @@ -40,7 +36,7 @@ if(NOT SPOT_LIBRARY) ExternalProject_Add(SpotLibrary PREFIX ${SPOT_DIR} - URL http://www.lrde.epita.fr/dload/spot/spot-2.9.tar.gz + URL http://www.lrde.epita.fr/dload/spot/spot-2.9.4.tar.gz DOWNLOAD_NO_PROGRESS YES CONFIGURE_COMMAND ./configure --disable-doxygen --disable-python --enable-silent-rules --silent --prefix=<INSTALL_DIR> BUILD_COMMAND make -j diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 759b2b3fdb27fb58ba3005404da1455546b3b3cb..2672d0438ec6b1f9253e75119d0b26ef50704980 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,18 +27,12 @@ add_executable(mc-sog main.cpp NewNet.h CommonSOG.cpp CommonSOG.h - DistributedSOG.cpp - DistributedSOG.h - HybridSOG.cpp - HybridSOG.h - threadSOG.cpp - threadSOG.h LDDGraph.cpp LDDGraph.h LDDState.cpp LDDState.h TransSylvan.cpp - sylvan_sog.c + SpotSogState.cpp SpotSogState.h SpotSogIterator.cpp @@ -53,24 +47,18 @@ add_executable(mc-sog main.cpp SogKripke.h ModelCheckBaseMT.cpp ModelCheckBaseMT.h - ModelCheckLace.cpp - ModelCheckLace.h + SogKripkeTh.cpp SogKripkeTh.h SogKripkeStateTh.cpp SogKripkeStateTh.h SogKripkeIteratorTh.cpp SogKripkeIteratorTh.h - ModelCheckerTh.cpp - ModelCheckerTh.h + stacksafe.cpp stacksafe.h SafeDequeue.cpp SafeDequeue.h - ModelCheckerThV2.cpp - ModelCheckerThV2.h - MCHybridSOG.cpp - MCHybridSOG.h HybridKripke.cpp HybridKripke.h HybridKripkeIterator.cpp @@ -79,12 +67,16 @@ add_executable(mc-sog main.cpp HybridKripkeState.h SylvanWrapper.cpp SylvanWrapper.h - ) + SylvanCacheWrapper.cpp SylvanCacheWrapper.h + ModelCheckerCPPThread.cpp ModelCheckerCPPThread.h + ModelCheckerTh.cpp ModelCheckerTh.h + threadSOG.cpp threadSOG.h + HybridSOG.cpp HybridSOG.h + MCHybridSOG.cpp MCHybridSOG.h) target_link_libraries(mc-sog bddx spot - sylvan RdP ${MPI_LIBRARIES} ${OPENSSL_LIBRARIES} diff --git a/src/CommonSOG.cpp b/src/CommonSOG.cpp index ea44c8242996cedcacf5b69d070b235821e9cfd2..6ef58343684d375b591961dca8b6932e7c620bd7 100644 --- a/src/CommonSOG.cpp +++ b/src/CommonSOG.cpp @@ -1,11 +1,10 @@ +#include <string> +#include "SylvanWrapper.h" #include "CommonSOG.h" -#include "sylvan.h" -#include "sylvan_seq.h" -#include <sylvan_sog.h> -#include <sylvan_int.h> + #include <stack> -#define GETNODE(mdd) ((mddnode_t)llmsset_index_to_ptr(nodes, mdd)) + const vector<class Place> *_places = NULL; CommonSOG::CommonSOG() { @@ -28,10 +27,9 @@ MDD CommonSOG::Accessible_epsilon(MDD From) { M1 = M2; for (Set::const_iterator i = m_nonObservable.begin(); !(i == m_nonObservable.end()); i++) { //fireTransition - MDD succ = fireTransition(M2, m_tb_relation[(*i)].getMinus(), m_tb_relation[(*i)].getPlus()); - M2 = lddmc_union_mono(M2, succ); + M2 = SylvanWrapper::lddmc_union_mono(M2, succ); } @@ -62,7 +60,7 @@ MDD CommonSOG::ImageForward(MDD From) { MDD Res = lddmc_false; for (Set::const_iterator i = m_nonObservable.begin(); !(i == m_nonObservable.end()); i++) { MDD succ = fireTransition(From, m_tb_relation[(*i)].getMinus(), m_tb_relation[(*i)].getPlus()); - Res = lddmc_union_mono(Res, succ); + Res = SylvanWrapper::lddmc_union_mono(Res, succ); } return Res; } @@ -73,16 +71,16 @@ MDD CommonSOG::Canonize(MDD s, unsigned int level) { if (level > m_nbPlaces || s == lddmc_false) { return lddmc_false; } - if (isSingleMDD(s)) { + if (SylvanWrapper::isSingleMDD(s)) { return s; } MDD s0 = lddmc_false, s1 = lddmc_false; bool res = false; do { - if (get_mddnbr(s, level) > 1) { - s0 = ldd_divide_rec(s, level); - s1 = ldd_minus(s, s0); + if (SylvanWrapper::get_mddnbr(s, level) > 1) { + s0 = SylvanWrapper::ldd_divide_rec(s, level); + s1 = SylvanWrapper::ldd_minus(s, s0); res = true; } else { level++; @@ -100,9 +98,9 @@ MDD CommonSOG::Canonize(MDD s, unsigned int level) { Reach = s1; do { // cout<<"premiere boucle interne \n"; - Front = ldd_minus(ImageForward(Front), Reach); - Reach = lddmc_union_mono(Reach, Front); - s0 = ldd_minus(s0, Front); + Front = SylvanWrapper::ldd_minus(ImageForward(Front), Reach); + Reach = SylvanWrapper::lddmc_union_mono(Reach, Front); + s0 = SylvanWrapper::ldd_minus(s0, Front); } while ((Front != lddmc_false) && (s0 != lddmc_false)); } if ((s0 != lddmc_false) && (s1 != lddmc_false)) { @@ -110,16 +108,16 @@ MDD CommonSOG::Canonize(MDD s, unsigned int level) { Reach = s0; do { // cout<<"deuxieme boucle interne \n"; - Front = ldd_minus(ImageForward(Front), Reach); - Reach = lddmc_union_mono(Reach, Front); - s1 = ldd_minus(s1, Front); + Front = SylvanWrapper::ldd_minus(ImageForward(Front), Reach); + Reach = SylvanWrapper::lddmc_union_mono(Reach, Front); + s1 = SylvanWrapper::ldd_minus(s1, Front); } while (Front != lddmc_false && s1 != lddmc_false); } MDD Repr = lddmc_false; - if (isSingleMDD(s0)) { + if (SylvanWrapper::isSingleMDD(s0)) { Repr = s0; } else { @@ -127,10 +125,10 @@ MDD CommonSOG::Canonize(MDD s, unsigned int level) { } - if (isSingleMDD(s1)) { - Repr = lddmc_union_mono(Repr, s1); + if (SylvanWrapper::isSingleMDD(s1)) { + Repr = SylvanWrapper::lddmc_union_mono(Repr, s1); } else { - Repr = lddmc_union_mono(Repr, Canonize(s1, level)); + Repr = SylvanWrapper::lddmc_union_mono(Repr, Canonize(s1, level)); } @@ -173,22 +171,22 @@ bool CommonSOG::Set_Div(MDD &M) const { Reached = lddmc_false; From = M; do { - + Reached = lddmc_false; for (i = m_nonObservable.begin(); !(i == m_nonObservable.end()); i++) { - MDD To = fireTransition(From, m_tb_relation[(*i)].getMinus(), m_tb_relation[(*i)].getPlus()); - Reached = lddmc_union_mono(Reached, To); - //Reached=To; + Reached = SylvanWrapper::lddmc_union_mono(Reached, To); } if (Reached == From) { - return true; + MDD Reached_obs=lddmc_false; + for (i = m_observable.begin(); !(i == m_observable.end()) && (Reached_obs==lddmc_false); i++) { + Reached_obs= fireTransition(From, m_tb_relation[(*i)].getMinus(), m_tb_relation[(*i)].getPlus()); + } + if (Reached_obs==lddmc_false) return true; + return false; } From = Reached; - Reached = lddmc_false; - - } while (Reached != lddmc_false && Reached != lddmc_true); - + } while (Reached != lddmc_false); return false; } @@ -205,13 +203,7 @@ bool CommonSOG::Set_Bloc(MDD &M) const { //BLOCAGE } -string CommonSOG::getTransition(int pos) { - return m_graph->getTransition(pos); -} -string CommonSOG::getPlace(int pos) { - return m_graph->getPlace(pos); -} LDDGraph *CommonSOG::m_graph; struct elt_t { @@ -222,76 +214,17 @@ struct elt_t { }; MDD CommonSOG::fireTransition(MDD cmark, MDD minus, MDD plus) { - return lddmc_firing_mono(cmark,minus,plus); - // for an empty set of source states, or an empty transition relation, return the empty set - - MDD result; - mddnode_t n_cmark, n_plus, n_minus; - uint32_t value, value_minus, value_plus; - std::stack<elt_t> lstack; - elt_t elt; - elt.cmark = cmark; - elt.plus = plus; - elt.minus = minus; - elt.level = 0; - lstack.push(elt); - result = lddmc_false; - uint32_t *currentMarking = new uint32_t[m_nbPlaces]; - elt_t relt; - bool goDown = false; - //MDD temp; - while (!lstack.empty() || goDown) { - if (!goDown) { - elt = lstack.top(); - lstack.pop(); - n_cmark = GETNODE(elt.cmark); - n_minus = GETNODE(elt.minus); - n_plus = GETNODE(elt.plus); - value = mddnode_getvalue(n_cmark); - value_minus = mddnode_getvalue(n_minus); - value_plus = mddnode_getvalue(n_plus); - } else goDown = false; - - //cout << "Level : " << elt.level << endl; - //cout << "Current : " << value << " Minus : " << value_minus << " Plus : " << value_plus << endl; - if (value >= value_minus) { - *(currentMarking + elt.level) = value - value_minus + value_plus; - if (elt.level == m_nbPlaces - 1) { - MDD b = ldd_cube(currentMarking, m_nbPlaces); - result = lddmc_union_mono(result, b); - } else { // Goto next level and push right - if (mddnode_getright(n_cmark) != lddmc_false) { // Look for another node in the same level - relt = elt; - relt.cmark = mddnode_getright(n_cmark); - lstack.push(relt); - } - //} while (temp>lddmc_true); - if (elt.level < m_nbPlaces - 1) { // Go down - elt.level++; - elt.cmark = mddnode_getdown(n_cmark); - n_cmark = GETNODE(elt.cmark); - elt.minus = mddnode_getdown(n_minus); - n_minus = GETNODE(elt.minus); - elt.plus = mddnode_getdown(n_plus); - n_plus = GETNODE(elt.plus); - goDown = true; - value = mddnode_getvalue(n_cmark); - value_minus = mddnode_getvalue(n_minus); - value_plus = mddnode_getvalue(n_plus); - } - } - } else { - // Look for another node in the same level - elt.cmark = mddnode_getright(n_cmark); - while (elt.cmark>lddmc_true && !goDown) { - n_cmark = GETNODE(elt.cmark); - value = mddnode_getvalue(n_cmark); - if (value >= value_minus) goDown = true; else elt.cmark = mddnode_getright(n_cmark); - } + return SylvanWrapper::lddmc_firing_mono(cmark,minus,plus); +} - } - } - delete[]currentMarking; +//string_view CommonSOG::getTransition(int pos) { + // cout<<"yes it is : "<<m_transitions.at(pos).name<<endl; + // cout<<"Ok "<<m_graph->getTransition(pos)<<endl; +// return string_view {m_transitions.at(pos).name}; +//} - return result; +string_view CommonSOG::getPlace(int pos) { + // cout<<"yes it is : "<<m_transitions.at(pos).name<<endl; + // cout<<"Ok "<<m_graph->getPlace(pos)<<endl; + return string_view {m_graph->getPlace(pos)}; } \ No newline at end of file diff --git a/src/CommonSOG.h b/src/CommonSOG.h index e5136a0c038b0413f48cb58213c00bec26b3f46e..5f6f7e166a4e6247d32bba1565d0f2f2fc905c5a 100644 --- a/src/CommonSOG.h +++ b/src/CommonSOG.h @@ -28,17 +28,23 @@ class CommonSOG vector<TransSylvan>* getTBRelation(); Set * getNonObservable(); unsigned int getPlacesCount(); - set<uint16_t> & getPlaceProposition() {return m_place_proposition;} - string getTransition(int pos); - string getPlace(int pos); + inline set<uint16_t> & getPlaceProposition() {return m_place_proposition;} + inline string_view getTransition(int pos) { + { + return string_view {m_transitions.at(pos).name}; + } + } + string_view getPlace(int pos); + + protected: NewNet* m_net; int m_nbPlaces = 0; static LDDGraph *m_graph; vector<TransSylvan> m_tb_relation; MDD m_initialMarking; - map<string, uint16_t> m_transitionName; - map<uint16_t,string> m_placeName; + map<string, uint16_t> * m_transitionName; + map<uint16_t,string> * m_placeName; Set m_observable; Set m_nonObservable; Set InterfaceTrans; diff --git a/src/HybridKripke.cpp b/src/HybridKripke.cpp index ad06063e81ae32c176c928064f6d714e73ceeb00..9194765858bd6a9e4d83d65b2d7c3771b8ed1eb9 100644 --- a/src/HybridKripke.cpp +++ b/src/HybridKripke.cpp @@ -79,9 +79,11 @@ HybridKripkeIterator* HybridKripke::succ_iter(const spot::state* s) const { it->recycle(*st,cond); return it; } +#ifdef TESTENABLE SylvanWrapper::m_agg++; SylvanWrapper::m_Size+=ss->getSize(); cout<<"Expolored states : "<<SylvanWrapper::m_Size<<" , Explored agg : "<<SylvanWrapper::m_agg<<" , Avg per agg : " <<SylvanWrapper::m_Size/SylvanWrapper::m_agg<<endl; +#endif return new HybridKripkeIterator(*st,cond); } @@ -93,13 +95,13 @@ bdd HybridKripke::state_condition(const spot::state* s) const list<uint16_t>* marked_place=ss->getMarkedPlaces(); bdd result=bddtrue; for (auto it=marked_place->begin();it!=marked_place->end();it++) { - string name=m_net->getPlaceName(*it); + string name=string(m_net->getPlaceName(*it)); spot::formula f=spot::formula::ap(name); result&=bdd_ithvar((dict_->var_map.find(f))->second); } list<uint16_t>* unmarked_place=ss->getUnmarkedPlaces(); for (auto it=unmarked_place->begin();it!=unmarked_place->end();it++) { - string name=m_net->getPlaceName(*it); + string name=string(m_net->getPlaceName(*it)); spot::formula f=spot::formula::ap(name); result&=!bdd_ithvar((dict_->var_map.find(f))->second); } diff --git a/src/HybridKripkeIterator.cpp b/src/HybridKripkeIterator.cpp index 7202533a5693ea7e09dc3d892d80b4f2cac50bb3..579cbb77078fdd334968833d6cb1b110fc3bb8ab 100644 --- a/src/HybridKripkeIterator.cpp +++ b/src/HybridKripkeIterator.cpp @@ -41,7 +41,7 @@ bdd HybridKripkeIterator::cond() const { //cout<<"entering "<<__func__<<endl; succ_t succ_elt=m_current_state->getListSucc()->at(m_current_edge); if (succ_elt.transition==-1) return bddtrue; - string name=m_net->getTransitionName(succ_elt.transition); + string name=string(m_net->getTransitionName(succ_elt.transition)); spot::bdd_dict *p=m_dict_ptr->get(); spot::formula f=spot::formula::ap(name); bdd result=bdd_ithvar((p->var_map.find(f))->second); diff --git a/src/HybridSOG.cpp b/src/HybridSOG.cpp index cd4f52f2b3f87583972063642a1aadd6cdbd5302..b626ccfd50df21f315dc623a9753a659fa71abf6 100644 --- a/src/HybridSOG.cpp +++ b/src/HybridSOG.cpp @@ -4,13 +4,8 @@ using namespace std; #include <stdio.h> -#include "sylvan_seq.h" -#include "sylvan_sog.h" -#include <sylvan_int.h> - -using namespace sylvan; #include <openssl/md5.h> -#define GETNODE(mdd) ((mddnode_t)llmsset_index_to_ptr(nodes, mdd)) + #define LENGTH_ID 16 //#define LENGTH_MSG 180 @@ -55,16 +50,10 @@ HybridSOG::HybridSOG(const NewNet &R,bool init) { - lace_init(1, 0); - lace_startup(0, NULL, NULL); - - // Simple Sylvan initialization, also initialize MDD support - sylvan_set_limits(2LL<<31, 2, 1); // sylvan_set_limits(2LL<<31, 2, 1); - //sylvan_set_sizes(1LL<<27, 1LL<<31, 1LL<<20, 1LL<<22); - - sylvan_init_package(); - sylvan_init_ldd(); - sylvan_gc_enable(); + SylvanWrapper::sylvan_set_limits ( 16LL<<30, 8, 0 ); + SylvanWrapper::sylvan_init_package(); + SylvanWrapper::sylvan_init_ldd(); + SylvanWrapper::init_gc_seq(); m_net=&R; m_init=init; @@ -72,14 +61,14 @@ HybridSOG::HybridSOG(const NewNet &R,bool init) int i, domain; vector<Place>::const_iterator it_places; - init_gc_seq(); + //_______________ m_transitions=R.transitions; m_observable=R.Observable; m_nonObservable=R.NonObservable; m_place_proposition=R.m_formula_place; - m_transitionName=R.transitionName; - m_placeName=R.m_placePosName; + m_transitionName=&R.transitionName; + m_placeName=&R.m_placePosName; InterfaceTrans=R.InterfaceTrans; m_nbPlaces=R.places.size(); @@ -92,8 +81,8 @@ HybridSOG::HybridSOG(const NewNet &R,bool init) { liste_marques[i] =it_places->marking; } - m_initialMarking=lddmc_cube(liste_marques,R.places.size()); - ldd_refs_push(m_initialMarking); + m_initialMarking=SylvanWrapper::lddmc_cube(liste_marques,R.places.size()); + //# ldd_refs_push(m_initialMarking); delete []liste_marques; // place names @@ -129,11 +118,11 @@ HybridSOG::HybridSOG(const NewNet &R,bool init) postc[it->first] = postc[it->first] + it->second; } - MDD _minus=lddmc_cube(prec,m_nbPlaces); - ldd_refs_push(_minus); + MDD _minus=SylvanWrapper::lddmc_cube(prec,m_nbPlaces); + //#ldd_refs_push(_minus); - MDD _plus=lddmc_cube(postc,m_nbPlaces); - ldd_refs_push(_plus); + MDD _plus=SylvanWrapper::lddmc_cube(postc,m_nbPlaces); + //#ldd_refs_push(_plus); m_tb_relation.push_back(TransSylvan(_minus,_plus)); } //sylvan_gc_seq(); @@ -170,10 +159,10 @@ void *HybridSOG::doCompute() LDDState *c=new LDDState; MDD Complete_meta_state=Accessible_epsilon(m_initialMarking); c->m_lddstate=Complete_meta_state; - ldd_refs_push(Complete_meta_state); + //#ldd_refs_push(Complete_meta_state); // MDD reduced_initialstate=Canonize(Complete_meta_state,0); - convert_wholemdd_stringcpp(Complete_meta_state,*chaine); + SylvanWrapper::convert_wholemdd_stringcpp(Complete_meta_state,*chaine); //DisplayMessage(chaine->c_str()); //write_to_dot("normal.dot",Complete_meta_state); //exit(0); @@ -209,7 +198,7 @@ void *HybridSOG::doCompute() initialstate=Canonize(Complete_meta_state,0); } //#endif // REDUCE - convert_wholemdd_stringcpp(initialstate,*chaine); + SylvanWrapper::convert_wholemdd_stringcpp(initialstate,*chaine); pthread_mutex_lock(&m_spin_msg[0]); @@ -312,17 +301,17 @@ void *HybridSOG::doCompute() MDD ldd_reachedclass=Accessible_epsilon(get_successor(e.first.second,t)); - ldd_refs_push(ldd_reachedclass); + //#ldd_refs_push(ldd_reachedclass); if (id_thread==1) - if (isGCRequired()) + if (SylvanWrapper::isGCRequired()) { pthread_mutex_lock(&m_gc_mutex); #ifdef DEBUG_GC displayMDDTableInfo(); #endif // DEBUG_GC - sylvan_gc_seq(); + //# sylvan_gc_seq(); #ifdef DEBUG_GC displayMDDTableInfo(); @@ -340,7 +329,7 @@ void *HybridSOG::doCompute() //MDD Reduced=ldd_reachedclass; string* message_to_send1=new string(); - convert_wholemdd_stringcpp(ldd_reachedclass,*message_to_send1); + SylvanWrapper::convert_wholemdd_stringcpp(ldd_reachedclass,*message_to_send1); get_md5(*message_to_send1,Identif); @@ -410,7 +399,7 @@ void *HybridSOG::doCompute() #endif //MDD Reduced=ldd_reachedclass; string* message_to_send2=new string(); - convert_wholemdd_stringcpp(reached,*message_to_send2); + SylvanWrapper::convert_wholemdd_stringcpp(reached,*message_to_send2); get_md5(*message_to_send2,Identif); @@ -479,7 +468,7 @@ void *HybridSOG::doCompute() pthread_mutex_lock(&m_spin_stack[min_charge]); m_st[min_charge].push(Pair(couple(Agregate,MState),fire)); pthread_mutex_unlock(&m_spin_stack[min_charge]); - ldd_refs_push(MState); + //#ldd_refs_push(MState); m_charge[min_charge]++; } @@ -884,8 +873,8 @@ MDD HybridSOG::decodage_message(const char *chaine) list_marq[j]=(uint32_t)((unsigned char)chaine[index]-1); index++; } - MDD N=lddmc_cube(list_marq,m_nbPlaces); - M=lddmc_union_mono(M,N); + MDD N=SylvanWrapper::lddmc_cube(list_marq,m_nbPlaces); + M=SylvanWrapper::lddmc_union_mono(M,N); } return M; } @@ -921,48 +910,7 @@ void * HybridSOG::threadHandler(void *context) return ((HybridSOG*)context)->doCompute(); } -void HybridSOG::convert_wholemdd_stringcpp(MDD cmark,string &res) -{ - typedef pair<string,MDD> Pair_stack; - vector<Pair_stack> local_stack; - - unsigned int compteur=0; - MDD explore_mdd=cmark; - - string chaine; - - res=" "; - local_stack.push_back(Pair_stack(chaine,cmark)); - do - { - Pair_stack element=local_stack.back(); - chaine=element.first; - explore_mdd=element.second; - local_stack.pop_back(); - compteur++; - while ( explore_mdd!= lddmc_false && explore_mdd!=lddmc_true) - { - mddnode_t n_val = GETNODE(explore_mdd); - if (mddnode_getright(n_val)!=lddmc_false) - { - local_stack.push_back(Pair_stack(chaine,mddnode_getright(n_val))); - } - unsigned int val = mddnode_getvalue(n_val); - chaine.push_back((unsigned char)(val)+1); - explore_mdd=mddnode_getdown(n_val); - } - /*printchaine(&chaine);printf("\n");*/ - res+=chaine; - } - while (local_stack.size()!=0); - //delete chaine; - - compteur=(compteur<<1) | 1; - res[1]=(unsigned char)((compteur>>8)+1); - res[0]=(unsigned char)(compteur & 255); - -} void HybridSOG::get_md5(const string& chaine,unsigned char *md_chaine) diff --git a/src/HybridSOG.h b/src/HybridSOG.h index 323a19b0ef32ea5eb79666494807363caa286e8d..6e2e395d6e4025ef4549c37ad3f75d150e82c186 100644 --- a/src/HybridSOG.h +++ b/src/HybridSOG.h @@ -88,9 +88,6 @@ private: int m_charge[128]; int m_init; - - /// Convert an MDD to a string caracter (for the send) - void convert_wholemdd_stringcpp(MDD cmark, string &chaine); /// Convert a string caracter to an MDD MDD decodage_message(const char *chaine); /// there is a message to receive? diff --git a/src/LDDGraph.cpp b/src/LDDGraph.cpp index a09fa9d909a69e59574458e1d3f4d789ff859af7..99e8ad6783782b892a5abdabf6170af7cfc687e7 100644 --- a/src/LDDGraph.cpp +++ b/src/LDDGraph.cpp @@ -1,5 +1,5 @@ #include "LDDGraph.h" -#include <sylvan.h> + #include <string.h> #include <map> #include "SylvanWrapper.h" @@ -15,9 +15,7 @@ void LDDGraph::setInitialState(LDDState *c) { } -LDDState *LDDGraph::getInitialState() const { - return m_GONodes.at(0); -} + /*----------------------find()----------------*/ LDDState *LDDGraph::find(LDDState *c) { @@ -133,7 +131,7 @@ int LDDGraph::NbBddNode(LDDState *S, size_t &nb) { void LDDGraph::printCompleteInformation() { long count_ldd = 0L; for (MetaLDDNodes::const_iterator i = m_GONodes.begin(); !(i == m_GONodes.end()); i++) { - count_ldd += lddmc_nodecount((*i)->m_lddstate); + count_ldd += SylvanWrapper::lddmc_nodecount((*i)->m_lddstate); m_nbMarking+= SylvanWrapper::getMarksCount((*i)->m_lddstate); } cout << "\n\nGRAPH SIZE : \n"; @@ -215,18 +213,24 @@ LDDState *LDDGraph::getLDDStateById(unsigned int id) { return m_GONodes.at(id); } -string LDDGraph::getTransition(uint16_t pos) { +string_view LDDGraph::getTransition(uint16_t pos) { map<string, uint16_t>::iterator it = m_transition->begin(); + while (it != m_transition->end()) { - if (it->second == pos) + + if (it->second == pos) { + //cout<<"first : "<<it->first<<endl; + return it->first; + } it++; } + return it->first; } -string LDDGraph::getPlace(uint16_t pos) { +string_view LDDGraph::getPlace(uint16_t pos) { return m_places->find(pos)->second; } diff --git a/src/LDDGraph.h b/src/LDDGraph.h old mode 100644 new mode 100755 index fbc991610080f2355d4f04e5f5cb4322209ccfec..1d7413b8115cdd0d1e18113203354171044ab188 --- a/src/LDDGraph.h +++ b/src/LDDGraph.h @@ -23,8 +23,8 @@ class LDDGraph CommonSOG *m_constructor; public: CommonSOG* getConstructor() {return m_constructor;} - string getTransition(uint16_t pos); - string getPlace(uint16_t pos); + string_view getTransition(uint16_t pos); + string_view getPlace(uint16_t pos); void setPlace(map<uint16_t,string>& list_places); void setTransition(map<string,uint16_t>& list_transitions); MetaLDDNodes m_GONodes; @@ -51,7 +51,10 @@ class LDDGraph void insert(LDDState*); LDDGraph(CommonSOG *constuctor) {m_nbArcs=m_nbMarking=0;m_constructor=constuctor;} void setInitialState(LDDState*); //Define the initial state of this graph - LDDState* getInitialState() const; + //LDDState* getInitialState() const; + LDDState *getInitialState() const { + return m_GONodes.at(0); + } void printCompleteInformation(); virtual ~LDDGraph(); }; diff --git a/src/LDDState.cpp b/src/LDDState.cpp index 8d51f374b2845e98972704c650e90f3208642219..0028e856038a1d92181db7383d5df9e7b16dd65f 100644 --- a/src/LDDState.cpp +++ b/src/LDDState.cpp @@ -1,10 +1,9 @@ -#include <sylvan.h> -#include <sylvan_int.h> #include "LDDState.h" #include "LDDGraph.h" #include <iostream> -#define GETNODE(mdd) ((mddnode_t)llmsset_index_to_ptr(nodes, mdd)) +#include "SylvanWrapper.h" + LDDState::~LDDState() { //dtor @@ -30,20 +29,16 @@ vector<pair<LDDState*, int>>* LDDState::getSuccessors() { vector<uint16_t> LDDState::getMarkedPlaces(set<uint16_t>& lplacesAP) { vector<uint16_t> result; MDD mdd=m_lddstate; - uint16_t depth=0; - while (mdd>lddmc_true) - { - //printf("mddd : %d \n",mdd); - mddnode_t node=GETNODE(mdd); - if (lplacesAP.find(depth)!=lplacesAP.end()) - if (mddnode_getvalue(node)==1) { + int depth=0; + for (auto & iter : lplacesAP) { + mddnode_t node=SylvanWrapper::GETNODE(mdd); + for (; depth < iter; depth++) { + mdd=SylvanWrapper::mddnode_getdown(node); + node=SylvanWrapper::GETNODE(mdd); + } + if (SylvanWrapper::mddnode_getvalue(node)!=0) { result.push_back(depth); - } - - mdd=mddnode_getdown(node); - depth++; - } return result; } @@ -51,20 +46,35 @@ vector<uint16_t> LDDState::getMarkedPlaces(set<uint16_t>& lplacesAP) { vector<uint16_t> LDDState::getUnmarkedPlaces(set<uint16_t>& lplacesAP) { vector<uint16_t> result; MDD mdd=m_lddstate; - - uint16_t depth=0; + int depth=0; + for (auto & iter : lplacesAP) { + mddnode_t node=SylvanWrapper::GETNODE(mdd); + for (; depth < iter; depth++) { + mdd=SylvanWrapper::mddnode_getdown(node); + node=SylvanWrapper::GETNODE(mdd); + } + if (SylvanWrapper::mddnode_getvalue(node)==0) { + result.push_back(depth); + } + } + return result; + /*cout<<"Display begin"<<endl; + for (auto & iter : lplacesAP) + cout<<iter<<endl; + cout<<"Display end"<<endl;*/ + /*uint16_t depth=0; while (mdd>lddmc_true) { //printf("mddd : %d \n",mdd); - mddnode_t node=GETNODE(mdd); + mddnode_t node=SylvanWrapper::GETNODE(mdd); if (lplacesAP.find(depth)!=lplacesAP.end()) - if (mddnode_getvalue(node)==0) { + if (SylvanWrapper::mddnode_getvalue(node)==0) { result.push_back(depth); } - mdd=mddnode_getdown(node); + mdd=SylvanWrapper::mddnode_getdown(node); depth++; } - return result; + return result;*/ } diff --git a/src/LDDState.h b/src/LDDState.h old mode 100644 new mode 100755 index a56dbe4afbbed7069e3cfef96a2160b7c7de848f..e261f9e4ab62207cfc29e84d4874cd5b57cdf0c6 --- a/src/LDDState.h +++ b/src/LDDState.h @@ -1,12 +1,12 @@ #ifndef LDDSTATE_H #define LDDSTATE_H -#include <sylvan.h> + #include <set> #include <vector> #include <string> - +#include "SylvanWrapper.h" using namespace std; -using namespace sylvan; + typedef set<int> Set; class LDDState { @@ -34,7 +34,7 @@ class LDDState { bool isVirtual() {return m_virtual;} void setVirtual(){m_virtual=true;} void setDiv(bool di) {m_boucle=di;} - bool isDiv() {return m_boucle;} + inline bool isDiv() {return m_boucle;} void setDeadLock(bool de) {m_blocage=de;} bool isDeadLock() {return m_blocage;} inline void setVisited() {m_visited=true;} diff --git a/src/MCHybridSOG.cpp b/src/MCHybridSOG.cpp index 7986e0506a5aee8e2e213d158331ecee53ea4ecc..957c9cca2ed918b7f584d563d5120e86a4387acb 100644 --- a/src/MCHybridSOG.cpp +++ b/src/MCHybridSOG.cpp @@ -3,13 +3,9 @@ #include <cstdio> -#include "sylvan_sog.h" -#include "sylvan_seq.h" -#include <sylvan_int.h> -#include "SylvanWrapper.h" #include <openssl/md5.h> -#define GETNODE(mdd) ((mddnode_t)llmsset_index_to_ptr(nodes, mdd)) + #define LENGTH_ID 16 //#define LENGTH_MSG 180 @@ -25,25 +21,19 @@ #define TAG_ACK_SUCC 11 #define TAG_NOTCOMPLETED 20 //#define DEBUG_GC 1 -using namespace sylvan; + using namespace std; MCHybridSOG::MCHybridSOG ( const NewNet &R,MPI_Comm &comm_world,bool init ) { m_comm_world=comm_world; - lace_init ( 1, 0 ); - lace_startup ( 0, NULL, NULL ); - - //sylvan_set_limits ( 16LL<<30, 8, 0 ); - sylvan_set_limits ( 16LL<<30, 8, 0 ); - - //sylvan_set_limits ( 2LL<<31, 2, 1 ); // sylvan_set_limits(2LL<<31, 2, 1); - //sylvan_set_sizes(1LL<<27, 1LL<<31, 1LL<<20, 1LL<<22); + SylvanWrapper::sylvan_set_limits ( 16LL<<30, 8, 0 ); - sylvan_init_package(); - sylvan_init_ldd(); - sylvan_gc_enable(); - displayMDDTableInfo(); + //sylvan_init_package(); + SylvanWrapper::sylvan_init_package(); + SylvanWrapper::sylvan_init_ldd(); + SylvanWrapper::init_gc_seq(); + SylvanWrapper::displayMDDTableInfo(); m_net=&R; m_init=init; @@ -51,14 +41,14 @@ MCHybridSOG::MCHybridSOG ( const NewNet &R,MPI_Comm &comm_world,bool init ) int i, domain; vector<Place>::const_iterator it_places; - init_gc_seq(); + //#init_gc_seq(); //_______________ m_transitions=R.transitions; m_observable=R.Observable; m_nonObservable=R.NonObservable; m_place_proposition=R.m_formula_place; - m_transitionName=R.transitionName; - m_placeName=R.m_placePosName; + m_transitionName=&R.transitionName; + m_placeName=&R.m_placePosName; InterfaceTrans=R.InterfaceTrans; m_nbPlaces=R.places.size(); @@ -70,8 +60,8 @@ MCHybridSOG::MCHybridSOG ( const NewNet &R,MPI_Comm &comm_world,bool init ) for ( i=0,it_places=R.places.begin(); it_places!=R.places.end(); i++,it_places++ ) { liste_marques[i] =it_places->marking; } - m_initialMarking=lddmc_cube ( liste_marques,R.places.size() ); - ldd_refs_push ( m_initialMarking ); + m_initialMarking=SylvanWrapper::lddmc_cube ( liste_marques,R.places.size() ); + //#ldd_refs_push ( m_initialMarking ); delete []liste_marques; // place names @@ -102,11 +92,11 @@ MCHybridSOG::MCHybridSOG ( const NewNet &R,MPI_Comm &comm_world,bool init ) postc[it->first] = postc[it->first] + it->second; } - MDD _minus=lddmc_cube ( prec,m_nbPlaces ); - ldd_refs_push ( _minus ); + MDD _minus=SylvanWrapper::lddmc_cube ( prec,m_nbPlaces ); + //#ldd_refs_push ( _minus ); - MDD _plus=lddmc_cube ( postc,m_nbPlaces ); - ldd_refs_push ( _plus ); + MDD _plus=SylvanWrapper::lddmc_cube ( postc,m_nbPlaces ); + //#ldd_refs_push ( _plus ); m_tb_relation.push_back ( TransSylvan ( _minus,_plus ) ); } //sylvan_gc_seq(); @@ -135,17 +125,21 @@ void *MCHybridSOG::doCompute() /****************************************** initial state ********************************************/ if ( task_id==0 && id_thread==0 ) { string* chaine=new string(); + + LDDState *c=new LDDState; MDD Complete_meta_state=Accessible_epsilon ( m_initialMarking ); c->m_lddstate=Complete_meta_state; - ldd_refs_push ( Complete_meta_state ); + //#ldd_refs_push ( Complete_meta_state ); // MDD reduced_initialstate=Canonize(Complete_meta_state,0); - convert_wholemdd_stringcpp ( Complete_meta_state,*chaine ); + + SylvanWrapper::convert_wholemdd_stringcpp ( Complete_meta_state,*chaine ); get_md5 ( *chaine,Identif ); //lddmc_getsha(Complete_meta_state, Identif); uint16_t destination= ( uint16_t ) ( Identif[0]%n_tasks ); c->setProcess ( destination ); if ( destination==0 ) { + m_nbmetastate++; Set fire=firable_obs ( Complete_meta_state ); m_st[1].push ( Pair ( couple ( c,Complete_meta_state ),fire ) ); @@ -159,8 +153,11 @@ void *MCHybridSOG::doCompute() m_graph->insertSHA ( c ); memcpy ( c->m_SHA2,Identif,16 ); initialstate=Canonize ( Complete_meta_state,0 ); + //#endif // REDUCE - convert_wholemdd_stringcpp ( initialstate,*chaine ); + SylvanWrapper::convert_wholemdd_stringcpp ( initialstate,*chaine ); + + pthread_mutex_lock ( &m_spin_msg[0] ); m_msg[0].push ( MSG ( chaine,destination ) ); pthread_mutex_unlock ( &m_spin_msg[0] ); @@ -229,18 +226,20 @@ void *MCHybridSOG::doCompute() int t = * ( e.second.begin() ); e.second.erase ( t ); reached_class=new LDDState(); + + MDD ldd_reachedclass=Accessible_epsilon ( get_successor ( e.first.second,t ) ); - ldd_refs_push ( ldd_reachedclass ); + //#ldd_refs_push ( ldd_reachedclass ); if ( id_thread==1 ) //displayMDDTableInfo(); - if ( isGCRequired() ) { + if ( SylvanWrapper::isGCRequired() ) { m_gc_mutex.lock(); #ifdef DEBUG_GC displayMDDTableInfo(); #endif // DEBUG_GC - sylvan_gc_seq(); + // sylvan_gc_seq(); #ifdef DEBUG_GC displayMDDTableInfo(); @@ -258,7 +257,7 @@ void *MCHybridSOG::doCompute() //MDD Reduced=ldd_reachedclass; string* message_to_send1=new string(); - convert_wholemdd_stringcpp ( ldd_reachedclass,*message_to_send1 ); + SylvanWrapper::convert_wholemdd_stringcpp ( ldd_reachedclass,*message_to_send1 ); get_md5 ( *message_to_send1,Identif ); @@ -312,12 +311,12 @@ void *MCHybridSOG::doCompute() #ifndef REDUCE reached=Canonize ( ldd_reachedclass,0 ); - ldd_refs_push ( ldd_reachedclass ); +//# ldd_refs_push ( ldd_reachedclass ); #endif //MDD Reduced=ldd_reachedclass; string* message_to_send2=new string(); - convert_wholemdd_stringcpp ( reached,*message_to_send2 ); + SylvanWrapper::convert_wholemdd_stringcpp ( reached,*message_to_send2 ); m_graph->addArc(); m_graph_mutex.lock(); e.first.first->Successors.insert ( e.first.first->Successors.begin(),LDDEdge ( reached_class,t ) ); @@ -359,13 +358,13 @@ void *MCHybridSOG::doCompute() Agregate->m_lddstate=MState; if ( !m_graph->insertFind( Agregate ) ) { //cout<<"enter D"<<endl; - ldd_refs_push ( MState ); + //#ldd_refs_push ( MState ); Agregate->setDiv ( Set_Div ( MState ) ); Agregate->setDeadLock ( Set_Bloc ( MState ) ); Agregate->setProcess ( task_id ); //m_graph_mutex.lock(); string* chaine=new string(); - convert_wholemdd_stringcpp ( MState,*chaine ); + SylvanWrapper::convert_wholemdd_stringcpp ( MState,*chaine ); get_md5 ( *chaine,Identif ); delete chaine; memcpy ( Agregate->m_SHA2,Identif,16 ); @@ -416,15 +415,15 @@ void MCHybridSOG::read_message() //cout<<"message tag :"<<m_status.MPI_TAG<<" by task "<<task_id<<endl; if ( m_status.MPI_TAG==TAG_ASK_STATE ) { //cout<<"TAG ASKSTATE received by task "<<task_id<<" from "<<m_status.MPI_SOURCE<<endl; - char mess[25]; + char mess[17]; MPI_Recv ( mess,16,MPI_BYTE,m_status.MPI_SOURCE,m_status.MPI_TAG,MPI_COMM_WORLD,&m_status ); bool res; m_waitingAgregate=false; size_t pos=m_graph->findSHAPos ( mess,res ); if ( !res ) { - + //cout<<"Not found"<<endl; m_waitingAgregate=true; - memcpy ( m_id_md5,mess,16 ); // Added for stats + memcpy ( m_id_md5,mess,16 ); } else { sendPropToMC ( pos ); } @@ -471,7 +470,6 @@ void MCHybridSOG::read_message() // cout<<"TAG INITIAL received by task "<<task_id<<endl; MPI_Recv ( &v, 1, MPI_INT, m_status.MPI_SOURCE, m_status.MPI_TAG, MPI_COMM_WORLD, &m_status ); LDDState *i_agregate=m_graph->getInitialState(); - char message[22]; memcpy ( message,i_agregate->getSHAValue(),16 ); uint16_t id_p=i_agregate->getProcess(); @@ -638,8 +636,8 @@ MDD MCHybridSOG::decodage_message ( const char *chaine ) list_marq[j]= ( uint32_t ) ( ( unsigned char ) chaine[index]-1 ); index++; } - MDD N=lddmc_cube ( list_marq,m_nbPlaces ); - M=lddmc_union_mono ( M,N ); + MDD N=SylvanWrapper::lddmc_cube ( list_marq,m_nbPlaces ); + M=SylvanWrapper::lddmc_union_mono ( M,N ); } return M; } @@ -649,44 +647,7 @@ void * MCHybridSOG::threadHandler ( void *context ) return ( ( MCHybridSOG* ) context )->doCompute(); } -void MCHybridSOG::convert_wholemdd_stringcpp ( MDD cmark,string &res ) -{ - typedef pair<string,MDD> Pair_stack; - vector<Pair_stack> local_stack; - - unsigned int compteur=0; - MDD explore_mdd=cmark; - - string chaine; - - res=" "; - local_stack.push_back ( Pair_stack ( chaine,cmark ) ); - do { - Pair_stack element=local_stack.back(); - chaine=element.first; - explore_mdd=element.second; - local_stack.pop_back(); - compteur++; - while ( explore_mdd!= lddmc_false && explore_mdd!=lddmc_true ) { - mddnode_t n_val = GETNODE ( explore_mdd ); - if ( mddnode_getright ( n_val ) !=lddmc_false ) { - local_stack.push_back ( Pair_stack ( chaine,mddnode_getright ( n_val ) ) ); - } - unsigned int val = mddnode_getvalue ( n_val ); - chaine.push_back ( ( unsigned char ) ( val )+1 ); - explore_mdd=mddnode_getdown ( n_val ); - } - /*printchaine(&chaine);printf("\n");*/ - res+=chaine; - } while ( local_stack.size() !=0 ); - //delete chaine; - - compteur= ( compteur<<1 ) | 1; - res[1]= ( unsigned char ) ( ( compteur>>8 )+1 ); - res[0]= ( unsigned char ) ( compteur & 255 ); - -} void MCHybridSOG::get_md5 ( const string& chaine,unsigned char *md_chaine ) @@ -722,7 +683,7 @@ void MCHybridSOG::sendSuccToMC() MPI_Send ( mess_tosend,message_size,MPI_BYTE,n_tasks, TAG_ACK_SUCC,MPI_COMM_WORLD ); } - +/* set<uint16_t> MCHybridSOG::getMarkedPlaces ( LDDState *agg ) { set<uint16_t> result; @@ -741,8 +702,9 @@ set<uint16_t> MCHybridSOG::getMarkedPlaces ( LDDState *agg ) } return result; -} +}*/ +/* set<uint16_t> MCHybridSOG::getUnmarkedPlaces ( LDDState *agg ) { set<uint16_t> result; @@ -763,17 +725,16 @@ set<uint16_t> MCHybridSOG::getUnmarkedPlaces ( LDDState *agg ) } return result; -} +}*/ // Send propositions to Model checker void MCHybridSOG::sendPropToMC ( size_t pos ) { LDDState *agg=m_graph->getLDDStateById ( pos ); - uint64_t size=SylvanWrapper::getMarksCount(agg->m_lddstate); // Added for stats - set<uint16_t> marked_places=getMarkedPlaces ( agg ); - set<uint16_t> unmarked_places=getUnmarkedPlaces ( agg ); + vector<uint16_t> marked_places=agg->getMarkedPlaces ( m_place_proposition ); + vector<uint16_t> unmarked_places=agg->getUnmarkedPlaces ( m_place_proposition ); uint16_t s_mp=marked_places.size(); uint16_t s_up=unmarked_places.size(); - char mess_to_send[8+s_mp*2+s_up*2+5+8]; // 8 Added for stats + char mess_to_send[8+s_mp*2+s_up*2+5]; memcpy ( mess_to_send,&pos,8 ); //cout<<"************* Pos to send :"<<pos<<endl; size_t indice=8; @@ -793,7 +754,5 @@ void MCHybridSOG::sendPropToMC ( size_t pos ) divblock=divblock | ( agg->isDeadLock() <<1 ); memcpy ( mess_to_send+indice,&divblock,1 ); indice++; - memcpy(mess_to_send+indice,&size,8); // Added for stats - indice+=8; MPI_Send ( mess_to_send,indice,MPI_BYTE,n_tasks, TAG_ACK_STATE, MPI_COMM_WORLD ); } diff --git a/src/MCHybridSOG.h b/src/MCHybridSOG.h index b4e5c3fef766e288b098dd0cb5c30e6312bcfa34..db2b5c5a644b2a49db8d9ff361044d553c7714af 100644 --- a/src/MCHybridSOG.h +++ b/src/MCHybridSOG.h @@ -89,10 +89,9 @@ private: // int n_tasks, task_id; int m_charge[128]; - int m_init; + int m_init; + - /// Convert an MDD to a string caracter (for the send) - void convert_wholemdd_stringcpp(MDD cmark, string &chaine); /// Convert a string caracter to an MDD MDD decodage_message(const char *chaine); /// there is a message to receive? @@ -117,8 +116,8 @@ private: int m_nbsend = 0, m_nbrecv = 0; MPI_Status m_status; - set<uint16_t> getUnmarkedPlaces(LDDState *agg); - set<uint16_t> getMarkedPlaces(LDDState *agg); + /*set<uint16_t> getUnmarkedPlaces(LDDState *agg); + set<uint16_t> getMarkedPlaces(LDDState *agg);*/ }; diff --git a/src/ModelCheckBaseMT.cpp b/src/ModelCheckBaseMT.cpp index c756b69a27eb522eff4c54fe0c0940b662f2ea7e..5a5d01fd343cf72bb06a385cd5e6094b24c1ca28 100644 --- a/src/ModelCheckBaseMT.cpp +++ b/src/ModelCheckBaseMT.cpp @@ -1,11 +1,7 @@ #include "ModelCheckBaseMT.h" -#include "sylvan.h" -#include "sylvan_seq.h" -#include <sylvan_sog.h> -#include <sylvan_int.h> +#include "SylvanWrapper.h" -using namespace sylvan; ModelCheckBaseMT::ModelCheckBaseMT(const NewNet &R,int nbThread) { m_nb_thread=nbThread; @@ -16,8 +12,8 @@ void ModelCheckBaseMT::loadNet() { m_graph=new LDDGraph(this); preConfigure(); - m_graph->setTransition(m_transitionName); - m_graph->setPlace(m_placeName); + m_graph->setTransition(*m_transitionName); + m_graph->setPlace(*m_placeName); } ModelCheckBaseMT::~ModelCheckBaseMT() diff --git a/src/ModelCheckerCPPThread.cpp b/src/ModelCheckerCPPThread.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d49fb1966f18c9adf158a4e8d4c930b8ac687a0b --- /dev/null +++ b/src/ModelCheckerCPPThread.cpp @@ -0,0 +1,218 @@ +#include "ModelCheckerCPPThread.h" +//#include "sylvan.h" +//#include <sylvan_int.h> +#include <functional> +#include <iostream> +#include <unistd.h> + +#include "SylvanWrapper.h" +#define GETNODE(mdd) ((mddnode_t)llmsset_index_to_ptr(nodes, mdd)) + +using namespace std; + +ModelCheckerCPPThread::ModelCheckerCPPThread ( const NewNet &R, int nbThread ) : + ModelCheckBaseMT ( R, nbThread ) +{ +} +size_t +getMaxMemoryV3() +{ + long pages = sysconf ( _SC_PHYS_PAGES ); + long page_size = sysconf ( _SC_PAGE_SIZE ); + return pages * page_size; +} +void ModelCheckerCPPThread::preConfigure() +{ + + /*lace_init ( 1, 0 ); + lace_startup ( 0, NULL, NULL ); + size_t max = 16LL<<34; + if ( max > getMaxMemoryV3() ) { + max = getMaxMemoryV3() /10*9; + }*/ + SylvanWrapper::sylvan_set_limits ( 16LL<<30, 8, 0 ); + + //sylvan_init_package(); + SylvanWrapper::sylvan_init_package(); + SylvanWrapper::sylvan_init_ldd(); + SylvanWrapper::init_gc_seq(); + SylvanWrapper::displayMDDTableInfo(); + + vector<Place>::const_iterator it_places; + m_transitions = m_net->transitions; + m_observable = m_net->Observable; + m_place_proposition = m_net->m_formula_place; + m_nonObservable = m_net->NonObservable; + + m_transitionName = &m_net->transitionName; + m_placeName = &m_net->m_placePosName; + + InterfaceTrans = m_net->InterfaceTrans; + + cout << "Nombre de places : " << m_nbPlaces << endl; + cout << "Derniere place : " << m_net->places[m_nbPlaces - 1].name << endl; + + uint32_t *liste_marques = new uint32_t[m_net->places.size()]; + uint32_t i; + for ( i = 0, it_places = m_net->places.begin(); it_places != m_net->places.end(); i++, it_places++ ) { + liste_marques[i] = it_places->marking; + } + + m_initialMarking = SylvanWrapper::lddmc_cube ( liste_marques, m_net->places.size() ); + + SylvanWrapper::lddmc_refs_push ( m_initialMarking ); + uint32_t *prec = new uint32_t[m_nbPlaces]; + uint32_t *postc = new uint32_t[m_nbPlaces]; + // Transition relation + for ( vector<Transition>::const_iterator t = m_net->transitions.begin(); t != m_net->transitions.end(); t++ ) { + // Initialisation + for ( i = 0; i < m_nbPlaces; i++ ) { + prec[i] = 0; + postc[i] = 0; + } + // Calculer les places adjacentes a la transition t + set<int> adjacentPlace; + for ( vector<pair<int, int> >::const_iterator it = t->pre.begin(); it != t->pre.end(); it++ ) { + adjacentPlace.insert ( it->first ); + prec[it->first] = prec[it->first] + it->second; + //printf("It first %d \n",it->first); + //printf("In prec %d \n",prec[it->first]); + } + // arcs post + for ( vector<pair<int, int> >::const_iterator it = t->post.begin(); it != t->post.end(); it++ ) { + adjacentPlace.insert ( it->first ); + postc[it->first] = postc[it->first] + it->second; + + } + for ( set<int>::const_iterator it = adjacentPlace.begin(); it != adjacentPlace.end(); it++ ) { + MDD Precond = lddmc_true; + Precond = Precond & ( ( *it ) >= prec[*it] ); + } + + MDD _minus = SylvanWrapper::lddmc_cube ( prec, m_nbPlaces ); + SylvanWrapper::lddmc_refs_push ( _minus ); + MDD _plus = SylvanWrapper::lddmc_cube ( postc, m_nbPlaces ); + SylvanWrapper::lddmc_refs_push ( _plus ); + m_tb_relation.push_back ( TransSylvan ( _minus, _plus ) ); + } + delete[] prec; + delete[] postc; + ComputeTh_Succ(); + + +} + + + + +void ModelCheckerCPPThread::Compute_successors() +{ + int id_thread; + + id_thread = m_id_thread++; + + //cout<<" I'm here thread id " <<m_id_thread<<endl; + Set fire; + + if ( id_thread == 0 ) { + LDDState *c = new LDDState; + MDD Complete_meta_state=Accessible_epsilon ( m_initialMarking ); + /*SylvanWrapper::getMarksCount(Complete_meta_state); + exit(0);*/ + + SylvanWrapper::lddmc_refs_push ( Complete_meta_state ); + + fire = firable_obs ( Complete_meta_state ); + c->m_lddstate = Complete_meta_state; + c->setDeadLock ( Set_Bloc ( Complete_meta_state ) ); + c->setDiv ( Set_Div ( Complete_meta_state ) ); + m_graph->setInitialState ( c ); + m_graph->insert ( c ); + m_common_stack.push ( Pair ( couple ( c, Complete_meta_state ), fire ) ); + m_condStack.notify_one(); + m_finish_initial = true; + } + LDDState *reached_class; + //pthread_barrier_wait ( &m_barrier_builder ); + Pair e; + do { + std::unique_lock<std::mutex> lk ( m_mutexStack ); + m_condStack.wait(lk,std::bind(&ModelCheckerCPPThread::hasToProcess,this)); + lk.unlock(); + + if ( m_common_stack.try_pop ( e ) && !m_finish ) { + while ( !e.second.empty() && !m_finish ) { + int t = *e.second.begin(); + e.second.erase ( t ); + MDD reduced_meta = Accessible_epsilon ( get_successor ( e.first.second, t ) ); + SylvanWrapper::lddmc_refs_push ( reduced_meta ); + reached_class = new LDDState(); + reached_class->m_lddstate = reduced_meta; + LDDState *pos = m_graph->find ( reached_class ); + if ( !pos ) { + m_graph->addArc(); + m_graph->insert ( reached_class ); + fire = firable_obs ( reduced_meta ); + reached_class->setDeadLock ( Set_Bloc ( reduced_meta ) ); + reached_class->setDiv ( Set_Div ( reduced_meta ) ); + m_common_stack.push ( Pair ( couple ( reached_class, reduced_meta ), fire ) ); + m_condStack.notify_one(); + m_graph_mutex.lock(); + e.first.first->Successors.insert ( e.first.first->Successors.begin(), LDDEdge ( reached_class, t ) ); + reached_class->Predecessors.insert ( reached_class->Predecessors.begin(), LDDEdge ( e.first.first, t ) ); + m_graph_mutex.unlock(); + } else { + delete reached_class; + m_graph->addArc(); + m_graph_mutex.lock(); + e.first.first->Successors.insert ( e.first.first->Successors.begin(), LDDEdge ( pos, t ) ); + pos->Predecessors.insert ( pos->Predecessors.begin(), LDDEdge ( e.first.first, t ) ); + m_graph_mutex.unlock(); + } + + } + e.first.first->setCompletedSucc();m_condBuild.notify_one(); + } //end advance + + } while ( !m_finish ); + + +} + +void ModelCheckerCPPThread::threadHandler ( void *context ) +{ + SylvanWrapper::lddmc_refs_init(); + ( ( ModelCheckerCPPThread* ) context )->Compute_successors(); +} + +void ModelCheckerCPPThread::ComputeTh_Succ() +{ + + m_id_thread = 0; + + pthread_barrier_init ( &m_barrier_builder, NULL, m_nb_thread + 1 ); + + m_finish=false; + for ( int i = 0; i < m_nb_thread; i++ ) { + int rc; + m_list_thread[i]= new thread ( threadHandler,this ); + if ( m_list_thread==nullptr ) { + cout << "error: pthread_create, rc: " << rc << endl; + } + } +} + +ModelCheckerCPPThread::~ModelCheckerCPPThread() +{ + m_finish = true; + m_condStack.notify_all(); + //pthread_barrier_wait ( &m_barrier_builder ); + for ( int i = 0; i < m_nb_thread; i++ ) { + m_list_thread[i]->join(); + delete m_list_thread[i]; + } + +} +bool ModelCheckerCPPThread::hasToProcess() const { + return m_finish || !m_common_stack.empty(); +} diff --git a/src/ModelCheckerCPPThread.h b/src/ModelCheckerCPPThread.h new file mode 100644 index 0000000000000000000000000000000000000000..204e6c085fba978f3ad41ec5b6f8479c62e8dee2 --- /dev/null +++ b/src/ModelCheckerCPPThread.h @@ -0,0 +1,36 @@ +#ifndef ModelCheckerCPPThread_H +#define ModelCheckerCPPThread_H +#include "ModelCheckBaseMT.h" +#include "stacksafe.h" +#include "SafeDequeue.h" +#include <atomic> +#include <thread> +#include <mutex> +#include <condition_variable> +typedef pair<LDDState *, int> couple_th; +typedef stack<pair<LDDState *,int>> pile_t; +/* + * Multi-threading with C++14 Library + */ +class ModelCheckerCPPThread : public ModelCheckBaseMT +{ +public: + ModelCheckerCPPThread(const NewNet &R,int nbThread); + ~ModelCheckerCPPThread(); + static void threadHandler(void *context); + void Compute_successors(); + void ComputeTh_Succ(); +private: + void preConfigure(); + bool hasToProcess() const; + + SafeDequeue<Pair> m_common_stack; + atomic<uint8_t> m_id_thread; + std::mutex m_mutex; + pthread_barrier_t m_barrier_builder; + volatile bool m_finish=false; + std::condition_variable m_condStack; + std::mutex m_mutexStack; + thread* m_list_thread[128]; +}; +#endif diff --git a/src/ModelCheckerTh.cpp b/src/ModelCheckerTh.cpp index 10ce48cc82ace9b3f71c478295c62b4074d5c8ed..397209979bd5112387319491a8e816df1dc2c6af 100644 --- a/src/ModelCheckerTh.cpp +++ b/src/ModelCheckerTh.cpp @@ -1,11 +1,6 @@ #include "ModelCheckerTh.h" +#include <unistd.h> -#include "sylvan.h" -#include "sylvan_seq.h" -#include <sylvan_sog.h> -#include <sylvan_int.h> - -using namespace sylvan; ModelCheckerTh::ModelCheckerTh(const NewNet &R, int nbThread) : ModelCheckBaseMT(R, nbThread) { @@ -19,19 +14,15 @@ getMaxMemory() } void ModelCheckerTh::preConfigure() { - lace_init(1, 0); - lace_startup(0, NULL, NULL); - size_t max = 16LL<<30; - if (max > getMaxMemory()) max = getMaxMemory()/10*9; - sylvan_set_limits(16LL<<29, 8, 0); - - sylvan_init_package(); - sylvan_init_ldd(); - displayMDDTableInfo(); + SylvanWrapper::sylvan_set_limits ( 16LL<<29, 8, 0 ); + SylvanWrapper::sylvan_init_package(); + SylvanWrapper::sylvan_init_ldd(); + SylvanWrapper::init_gc_seq(); + SylvanWrapper::displayMDDTableInfo(); vector<Place>::const_iterator it_places; - init_gc_seq(); + //init_gc_seq(); m_transitions = m_net->transitions; @@ -39,8 +30,8 @@ void ModelCheckerTh::preConfigure() { m_place_proposition = m_net->m_formula_place; m_nonObservable = m_net->NonObservable; - m_transitionName = m_net->transitionName; - m_placeName = m_net->m_placePosName; + m_transitionName = &m_net->transitionName; + m_placeName = &m_net->m_placePosName; InterfaceTrans = m_net->InterfaceTrans; @@ -53,8 +44,8 @@ void ModelCheckerTh::preConfigure() { liste_marques[i] = it_places->marking; } - m_initialMarking = lddmc_cube(liste_marques, m_net->places.size()); - ldd_refs_push(m_initialMarking); + m_initialMarking = SylvanWrapper::lddmc_cube(liste_marques, m_net->places.size()); + //ldd_refs_push(m_initialMarking); uint32_t *prec = new uint32_t[m_nbPlaces]; uint32_t *postc = new uint32_t[m_nbPlaces]; // Transition relation @@ -83,10 +74,10 @@ void ModelCheckerTh::preConfigure() { Precond = Precond & ((*it) >= prec[*it]); } - MDD _minus = lddmc_cube(prec, m_nbPlaces); - ldd_refs_push(_minus); - MDD _plus = lddmc_cube(postc, m_nbPlaces); - ldd_refs_push(_plus); + MDD _minus = SylvanWrapper::lddmc_cube(prec, m_nbPlaces); + //#ldd_refs_push(_minus); + MDD _plus = SylvanWrapper::lddmc_cube(postc, m_nbPlaces); + //#ldd_refs_push(_plus); m_tb_relation.push_back(TransSylvan(_minus, _plus)); } delete[] prec; @@ -104,7 +95,7 @@ void* ModelCheckerTh::Compute_successors() { if (id_thread == 0) { LDDState *c = new LDDState; MDD Complete_meta_state=Accessible_epsilon(m_initialMarking); - ldd_refs_push(Complete_meta_state); + //#ldd_refs_push(Complete_meta_state); fire = firable_obs(Complete_meta_state); c->m_lddstate = Complete_meta_state; @@ -150,7 +141,7 @@ void* ModelCheckerTh::Compute_successors() { } #endif MDD reduced_meta = Accessible_epsilon(get_successor(e.first.second, t)); - ldd_refs_push(reduced_meta); + //#ldd_refs_push(reduced_meta); reached_class = new LDDState(); reached_class->m_lddstate = reduced_meta; //pthread_spin_lock(&m_accessible); @@ -253,4 +244,3 @@ bool ModelCheckerTh::isNotTerminated() { } return !res; } - diff --git a/src/ModelCheckerTh.h b/src/ModelCheckerTh.h index 23fb2923d9634409bf1bef6f8fcb852dcdafdcaa..a94b6c74b01c45a2b71d10f9ce6360683dd95748 100644 --- a/src/ModelCheckerTh.h +++ b/src/ModelCheckerTh.h @@ -14,7 +14,6 @@ public: static void *threadHandler(void *context); void *Compute_successors(); void ComputeTh_Succ(); - private: void preConfigure(); bool isNotTerminated(); diff --git a/src/NewNet.cpp b/src/NewNet.cpp index 5b2e4b6c51ff7f3cbc3244ffcffdd2f063edf6c3..b73c7574631b6e82200d4e184fa799ea981266a7 100644 --- a/src/NewNet.cpp +++ b/src/NewNet.cpp @@ -84,7 +84,7 @@ NewNet::NewNet(const char *f, const char *Formula_trans, const char *Int_trans) { places.clear(); transitions.clear(); - placeName.clear(); + m_placeName.clear(); transitionName.clear(); } if (strlen(Formula_trans) > 0) @@ -132,7 +132,7 @@ NewNet::NewNet(const char *f, const set<string> & f_trans) { places.clear(); transitions.clear(); - placeName.clear(); + m_placeName.clear(); transitionName.clear(); } if (f_trans.size() > 0) @@ -165,7 +165,7 @@ void NewNet::setListObservable(const set<string> & list_t) { int pos_trans(TRANSITIONS T, string trans); Observable.clear(); - for (auto it=placeName.begin();it!=placeName.end();it++) { + for (auto it=m_placeName.begin();it!=m_placeName.end();it++) { pair<int,string> elt((*it).second,(*it).first); m_placePosName.insert(elt); } @@ -183,9 +183,8 @@ void NewNet::setListObservable(const set<string> & list_t) { cout<<"Error: "<<*i<<" is not a transition!"<<endl; // Check if the proposition corresponds to a place - map<string, uint16_t>::iterator pi = placeName.find(*i); - if (pi!=placeName.end()) - cout<<"Place was found!"<<endl; + map<string, uint16_t>::iterator pi = m_placeName.find(*i); + assert (pi!=m_placeName.end()); m_formula_place.insert(pi->second); m_lplaceAP.insert(*i); // Adding adjacent transitions of a place as observable transitions @@ -207,7 +206,7 @@ void NewNet::setListObservable(const set<string> & list_t) else { Formula_Trans.insert(pos); - map<string,uint16_t>::iterator ti=transitionName.find(*i); + map<string ,uint16_t>::iterator ti=transitionName.find(*i); Observable.insert(pos); } } @@ -365,10 +364,10 @@ ostream &operator<<(ostream &os, const Set &s) /*----------------------------------------------------------------------*/ bool NewNet::addPlace(const string &place, int marking, int capacity) { - map<string, uint16_t>::const_iterator pi = placeName.find(place); - if (pi == placeName.end()) + map<string , uint16_t>::const_iterator pi = m_placeName.find(place); + if (pi == m_placeName.end()) { - placeName[place] = places.size(); + m_placeName[string(place)] = places.size(); Place p(place, marking, capacity); places.push_back(p); return true; @@ -379,10 +378,10 @@ bool NewNet::addPlace(const string &place, int marking, int capacity) bool NewNet::addQueue(const string &place, int capacity) { - map<string, uint16_t>::const_iterator pi = placeName.find(place); - if (pi == placeName.end()) + map<string , uint16_t>::const_iterator pi = m_placeName.find(place); + if (pi == m_placeName.end()) { - placeName[place] = places.size(); + m_placeName[place] = places.size(); Place p(place, -1, capacity); places.push_back(p); return true; @@ -393,10 +392,10 @@ bool NewNet::addQueue(const string &place, int capacity) bool NewNet::addLossQueue(const string &place, int capacity) { - map<string, uint16_t>::const_iterator pi = placeName.find(place); - if (pi == placeName.end()) + map<string, uint16_t>::const_iterator pi = m_placeName.find(place); + if (pi == m_placeName.end()) { - placeName[place] = places.size(); + m_placeName[place] = places.size(); Place p(place, -2, capacity); places.push_back(p); return true; @@ -422,8 +421,8 @@ bool NewNet::addTrans(const string &trans) bool NewNet::addPre(const string &place, const string &trans, int valuation) { int p, t; - map<string, uint16_t>::const_iterator pi = placeName.find(place); - if (pi == placeName.end() || places[pi->second].isQueue()) + map<string, uint16_t>::const_iterator pi = m_placeName.find(place); + if (pi == m_placeName.end() || places[pi->second].isQueue()) return false; else p = pi->second; @@ -440,8 +439,8 @@ bool NewNet::addPre(const string &place, const string &trans, int valuation) bool NewNet::addPost(const string &place, const string &trans, int valuation) { int p, t; - map<string, uint16_t>::const_iterator pi = placeName.find(place); - if (pi == placeName.end() || places[pi->second].isQueue()) + map<string, uint16_t>::const_iterator pi = m_placeName.find(place); + if (pi == m_placeName.end() || places[pi->second].isQueue()) return false; else p = pi->second; @@ -458,12 +457,12 @@ bool NewNet::addPost(const string &place, const string &trans, int valuation) bool NewNet::addPreQueue(const string &place, const string &trans, int valuation) { int p, t; - map<string, uint16_t>::const_iterator pi = placeName.find(place); - if (pi == placeName.end() || !places[pi->second].isQueue()) + map<string , uint16_t>::const_iterator pi = m_placeName.find(place); + if (pi == m_placeName.end() || !places[pi->second].isQueue()) return false; else p = pi->second; - map<string, uint16_t>::const_iterator ti = transitionName.find(trans); + map<string , uint16_t>::const_iterator ti = transitionName.find(trans); if (ti == transitionName.end()) return false; else @@ -477,12 +476,12 @@ bool NewNet::addPostQueue(const string &place, const string &trans, int valuation) { int p, t; - map<string, uint16_t>::const_iterator pi = placeName.find(place); - if (pi == placeName.end() || !places[pi->second].isQueue()) + map<string , uint16_t>::const_iterator pi = m_placeName.find(place); + if (pi == m_placeName.end() || !places[pi->second].isQueue()) return false; else p = pi->second; - map<string, uint16_t>::const_iterator ti = transitionName.find(trans); + map<string , uint16_t>::const_iterator ti = transitionName.find(trans); if (ti == transitionName.end()) return false; else @@ -496,8 +495,8 @@ bool NewNet::addInhibitor(const string &place, const string &trans, int valuation) { int p, t; - map<string, uint16_t>::const_iterator pi = placeName.find(place); - if (pi == placeName.end()) + map<string, uint16_t>::const_iterator pi = m_placeName.find(place); + if (pi == m_placeName.end()) return false; else p = pi->second; @@ -515,8 +514,8 @@ bool NewNet::addPreAuto(const string &place, const string &trans, const string &valuation) { int p, t, v; - map<string, uint16_t>::const_iterator pi = placeName.find(place); - if (pi == placeName.end() || places[pi->second].isQueue()) + map<string, uint16_t>::const_iterator pi = m_placeName.find(place); + if (pi == m_placeName.end() || places[pi->second].isQueue()) return false; else p = pi->second; @@ -525,8 +524,8 @@ bool NewNet::addPreAuto(const string &place, const string &trans, return false; else t = ti->second; - map<string, uint16_t>::const_iterator pv = placeName.find(valuation); - if (pv == placeName.end() || places[pv->second].isQueue()) + map<string, uint16_t>::const_iterator pv = m_placeName.find(valuation); + if (pv == m_placeName.end() || places[pv->second].isQueue()) return false; else v = pv->second; @@ -539,8 +538,8 @@ bool NewNet::addPostAuto(const string &place, const string &trans, const string &valuation) { int p, t, v; - map<string, uint16_t>::const_iterator pi = placeName.find(place); - if (pi == placeName.end() || places[pi->second].isQueue()) + map<string, uint16_t>::const_iterator pi = m_placeName.find(place); + if (pi == m_placeName.end() || places[pi->second].isQueue()) return false; else p = pi->second; @@ -549,8 +548,8 @@ bool NewNet::addPostAuto(const string &place, const string &trans, return false; else t = ti->second; - map<string, uint16_t>::const_iterator pv = placeName.find(valuation); - if (pv == placeName.end() || places[pi->second].isQueue()) + map<string, uint16_t>::const_iterator pv = m_placeName.find(valuation); + if (pv == m_placeName.end() || places[pi->second].isQueue()) return false; else v = pv->second; @@ -562,8 +561,8 @@ bool NewNet::addPostAuto(const string &place, const string &trans, bool NewNet::addReset(const string &place, const string &trans) { int p, t; - auto pi = placeName.find(place); - if (pi == placeName.end()) + auto pi = m_placeName.find(place); + if (pi == m_placeName.end()) return false; else p = pi->second; diff --git a/src/NewNet.h b/src/NewNet.h index 8341cf38abf3fbd2be968cfc56401652bcb2b265..d394cc8e3754fe2326c6a6f7821ebdc18596404a 100644 --- a/src/NewNet.h +++ b/src/NewNet.h @@ -69,7 +69,7 @@ class NewNet : public RdPMonteur { /* Attributs */ vector<class Place> places; vector<class Transition> transitions; - map<string, uint16_t> placeName; + map<string, uint16_t> m_placeName; map<string, uint16_t> transitionName; Set Observable; Set NonObservable; @@ -106,14 +106,13 @@ class NewNet : public RdPMonteur { int nbTransition() const { return transitions.size(); }; set<string>& getListTransitionAP() {return m_ltransitionAP;} set<string>& getListPlaceAP() {return m_lplaceAP;} - string& getPlaceName(size_t pos) { return m_placePosName.find(pos)->second;} - string& getTransitionName(size_t pos) { return m_transitionPosName.find(pos)->second;} + string_view getPlaceName(size_t pos) { return m_placePosName.find(pos)->second;} + string_view getTransitionName(size_t pos) { return m_transitionPosName.find(pos)->second;} map<uint16_t,string> m_placePosName; private: map<uint16_t,string> m_transitionPosName; - set<string> m_ltransitionAP; set<string> m_lplaceAP; diff --git a/src/SogKripke.cpp b/src/SogKripke.cpp index d8229149513944a4e85c1a209d11fc3778be760c..27bd925a14ac24d891e9c19c31db997d2cbb1c76 100644 --- a/src/SogKripke.cpp +++ b/src/SogKripke.cpp @@ -58,13 +58,13 @@ bdd SogKripke::state_condition(const spot::state* s) const bdd result=bddtrue; // Marked places for (auto it=marked_place.begin();it!=marked_place.end();it++) { - string name=m_sog->getPlace(*it); + string name=string(m_sog->getPlace(*it)); spot::formula f=spot::formula::ap(name); result&=bdd_ithvar((dict_->var_map.find(f))->second); } vector<uint16_t> unmarked_place=ss->getLDDState()->getUnmarkedPlaces(m_sog->getConstructor()->getPlaceProposition()); for (auto it=unmarked_place.begin();it!=unmarked_place.end();it++) { - string name=m_sog->getPlace(*it); + string name=string(m_sog->getPlace(*it)); spot::formula f=spot::formula::ap(name); result&=!bdd_ithvar((dict_->var_map.find(f))->second); } diff --git a/src/SogKripkeIterator.cpp b/src/SogKripkeIterator.cpp index f7de0915f81eb897c7b40e16ea8c039dbf1779d3..0cd41ae59bb71dc3080a32db07e5313749eac7d0 100644 --- a/src/SogKripkeIterator.cpp +++ b/src/SogKripkeIterator.cpp @@ -45,7 +45,7 @@ SogKripkeState* SogKripkeIterator::dst() const bdd SogKripkeIterator::cond() const { if (m_lsucc.at(m_current_edge).second==-1) return bddtrue; - string name=m_graph->getTransition(m_lsucc.at(m_current_edge).second); + string name=string(m_graph->getTransition(m_lsucc.at(m_current_edge).second)); //cout<<"Value "<<m_lddstate->getSuccessors()->at(m_current_edge).second<<" Transition name "<<name<<endl; spot::bdd_dict *p=m_dict_ptr->get(); diff --git a/src/SogKripkeIteratorTh.cpp b/src/SogKripkeIteratorTh.cpp index 44356a32e7a64f8b0319f33a6720e2263f5a59e5..7b09c764d8bb9a01c1a0467b35acd5ac881d577d 100644 --- a/src/SogKripkeIteratorTh.cpp +++ b/src/SogKripkeIteratorTh.cpp @@ -54,10 +54,10 @@ bdd SogKripkeIteratorTh::cond() const if ( m_lsucc.at ( m_current_edge ).second==-1 ) { return bddtrue; } - string name=m_builder->getTransition ( m_lsucc.at ( m_current_edge ).second ); + spot::formula f=spot::formula::ap (string(m_builder->getTransition ( m_lsucc.at ( m_current_edge ).second ))); spot::bdd_dict *p=m_dict_ptr->get(); - spot::formula f=spot::formula::ap ( name ); bdd result=bdd_ithvar ( ( p->var_map.find ( f ) )->second ); + //cout<<"leaving "<<__func__<<endl; return result & spot::kripke_succ_iterator::cond(); } diff --git a/src/SogKripkeTh.cpp b/src/SogKripkeTh.cpp index ee2f5bae67cf28feb7b60a9e78ba40f9ccb70c6c..6f727c434d6786e00ad90de87250be6d8d5f59e8 100644 --- a/src/SogKripkeTh.cpp +++ b/src/SogKripkeTh.cpp @@ -59,10 +59,10 @@ SogKripkeIteratorTh* SogKripkeTh::succ_iter(const spot::state* s) const { bdd cond = state_condition(ss); if (iter_cache_) { - auto it = static_cast<SogKripkeIteratorTh*>(iter_cache_); + /*auto it = static_cast<SogKripkeIteratorTh*>(iter_cache_); iter_cache_ = nullptr; // empty the cache it->recycle(aggregate, cond); - return it; + return it;*/ } return new SogKripkeIteratorTh(aggregate,cond); @@ -81,20 +81,21 @@ bdd SogKripkeTh::state_condition(const spot::state* s) const auto ss = static_cast<const SogKripkeStateTh*>(s); vector<uint16_t> marked_place = ss->getLDDState()->getMarkedPlaces(m_builder->getPlaceProposition()); - +#ifdef TESTENABLE SylvanWrapper::m_Size+=SylvanWrapper::getMarksCount(ss->getLDDState()->getLDDValue()); SylvanWrapper::m_agg++; cout<<"Expolored states : "<<SylvanWrapper::m_Size<<" , Explored agg : "<<SylvanWrapper::m_agg<<" , Avg per agg : " <<SylvanWrapper::m_Size/SylvanWrapper::m_agg<<endl; +#endif bdd result=bddtrue; // Marked places for (auto it=marked_place.begin();it!=marked_place.end();it++) { - string name=m_builder->getPlace(*it); + string name=string(m_builder->getPlace(*it)); spot::formula f=spot::formula::ap(name); result&=bdd_ithvar((dict_->var_map.find(f))->second); } vector<uint16_t> unmarked_place=ss->getLDDState()->getUnmarkedPlaces(m_builder->getPlaceProposition()); for (auto it=unmarked_place.begin();it!=unmarked_place.end();it++) { - string name=m_builder->getPlace(*it); + string name=string(m_builder->getPlace(*it)); spot::formula f=spot::formula::ap(name); result&=!bdd_ithvar((dict_->var_map.find(f))->second); } diff --git a/src/SogKripkeTh.h b/src/SogKripkeTh.h index 46c06ce67e8461050fecebef7082edb3189854e1..f482a0ea57793331960b2ae6c24e0a1cbaefc20e 100644 --- a/src/SogKripkeTh.h +++ b/src/SogKripkeTh.h @@ -17,14 +17,9 @@ class SogKripkeTh: public spot::kripke { SogKripkeIteratorTh* succ_iter(const spot::state* s) const override; std::string format_state(const spot::state* s) const override; bdd state_condition(const spot::state* s) const override; - ModelCheckBaseMT *m_builder; - protected: - private: - std::map<int, int> place_prop; - //LDDGraph* m_sog; }; #endif // SOGKRIPKE_H_INCLUDED diff --git a/src/SogTwa.h b/src/SogTwa.h index 5a39479ed0d8a71ebec8141115bb36ce3f343128..21a3a35d2d976533736f0ceb5c7f29598a60f87b 100644 --- a/src/SogTwa.h +++ b/src/SogTwa.h @@ -13,7 +13,6 @@ class SogTwa : public spot::twa SpotSogIterator* succ_iter(const spot::state* s) const override; std::string format_state(const spot::state* s) const override; - protected: private: LDDGraph* m_sog; diff --git a/src/SpotSogIterator.cpp b/src/SpotSogIterator.cpp index 62b14d346834652a355a888de088864cfbe32862..ae61c6374b317de2060b94026dcbfdeb644b8d7f 100644 --- a/src/SpotSogIterator.cpp +++ b/src/SpotSogIterator.cpp @@ -45,7 +45,7 @@ SpotSogState* SpotSogIterator::dst() const bdd SpotSogIterator::cond() const { if (m_lsucc.at(m_current_edge).second==-1) return bddtrue; - string name=m_graph->getTransition(m_lsucc.at(m_current_edge).second); + string name=string(m_graph->getTransition(m_lsucc.at(m_current_edge).second)); //cout<<"Value "<<m_lddstate->getSuccessors()->at(m_current_edge).second<<" Transition name "<<name<<endl; spot::bdd_dict *p=m_dict_ptr->get(); diff --git a/src/SylvanCacheWrapper.cpp b/src/SylvanCacheWrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..83680b6dde6bf537993236c159faa4a9d3ca8c95 --- /dev/null +++ b/src/SylvanCacheWrapper.cpp @@ -0,0 +1,148 @@ +// +// Created by chiheb on 25/09/2020. +// +#include <string.h> // memset +#include <sys/mman.h> // for mmap +#include <cstdlib> +#include <cstdio> +#include <cstdint> +#include <cerrno> +#include "SylvanCacheWrapper.h" + +#ifndef compiler_barrier +#define compiler_barrier() { asm volatile("" ::: "memory"); } +#endif + +#ifndef cas +#define cas(ptr, old, new) (__sync_bool_compare_and_swap((ptr),(old),(new))) +#endif + +void SylvanCacheWrapper::cache_create(size_t _cache_size, size_t _max_size) +{ +#if CACHE_MASK + // Cache size must be a power of 2 + if (__builtin_popcountll(_cache_size) != 1 || __builtin_popcountll(_max_size) != 1) { + fprintf(stderr, "cache_create: Table size must be a power of 2!\n"); + exit(1); + } +#endif + + m_cache_size = _cache_size; + m_cache_max = _max_size; +#if CACHE_MASK + cache_mask = cache_size - 1; +#endif + + if (m_cache_size > m_cache_max) { + fprintf(stderr, "cache_create: Table size must be <= max size!\n"); + exit(1); + } + + m_cache_table = (cache_entry_t)mmap(0, m_cache_max * sizeof(struct cache_entry), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + m_cache_status = (uint32_t*)mmap(0, m_cache_max * sizeof(uint32_t), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + if (m_cache_table == (cache_entry_t)-1 || m_cache_status == (uint32_t*)-1) { + fprintf(stderr, "cache_create: Unable to allocate memory: %s!\n", strerror(errno)); + exit(1); + } + + m_next_opid = 512LL << 40; +} + +/** + * dd must be MTBDD, d2/d3 can be anything + */ +int __attribute__((unused)) +SylvanCacheWrapper::cache_get3(uint64_t opid, uint64_t dd, uint64_t d2, uint64_t d3, uint64_t *res) +{ + return cache_get(dd | opid, d2, d3, res); +} + +int SylvanCacheWrapper::cache_get(uint64_t a, uint64_t b, uint64_t c, uint64_t *res) +{ + const uint64_t hash = cache_hash(a, b, c); +#if CACHE_MASK + volatile uint32_t *s_bucket = m_cache_status + (hash & m_cache_mask); + cache_entry_t bucket = m_cache_table + (hash & m_cache_mask); +#else + volatile uint32_t *s_bucket = m_cache_status + (hash % m_cache_size); + cache_entry_t bucket = m_cache_table + (hash % m_cache_size); +#endif + const uint32_t s = *s_bucket; + compiler_barrier(); + // abort if locked or if part of a 2-part cache entry + if (s & 0xc0000000) return 0; + // abort if different hash + if ((s ^ (hash>>32)) & 0x3fff0000) return 0; + // abort if key different + if (bucket->a != a || bucket->b != b || bucket->c != c) return 0; + *res = bucket->res; + compiler_barrier(); + // abort if status field changed after compiler_barrier() + return *s_bucket == s ? 1 : 0; +} + +/* Rotating 64-bit FNV-1a hash */ +uint64_t SylvanCacheWrapper::cache_hash(uint64_t a, uint64_t b, uint64_t c) +{ + const uint64_t prime = 1099511628211; + uint64_t hash = 14695981039346656037LLU; + hash = (hash ^ (a>>32)); + hash = (hash ^ a) * prime; + hash = (hash ^ b) * prime; + hash = (hash ^ c) * prime; + return hash; +} + +/** + * dd must be MTBDD, d2/d3 can be anything + */ +int __attribute__((unused)) +SylvanCacheWrapper::cache_put3(uint64_t opid, uint64_t dd, uint64_t d2, uint64_t d3, uint64_t res) +{ + return cache_put(dd | opid, d2, d3, res); +} + +int SylvanCacheWrapper::cache_put(uint64_t a, uint64_t b, uint64_t c, uint64_t res) +{ + const uint64_t hash = cache_hash(a, b, c); +#if CACHE_MASK + volatile uint32_t *s_bucket = cache_status + (hash & cache_mask); + cache_entry_t bucket = cache_table + (hash & cache_mask); +#else + volatile uint32_t *s_bucket = m_cache_status + (hash % m_cache_size); + cache_entry_t bucket = m_cache_table + (hash % m_cache_size); +#endif + const uint32_t s = *s_bucket; + // abort if locked + if (s & 0x80000000) return 0; + // abort if hash identical -> no: in iscasmc this occasionally causes timeouts?! + const uint32_t hash_mask = (hash>>32) & 0x3fff0000; + // if ((s & 0x7fff0000) == hash_mask) return 0; + // use cas to claim bucket + const uint32_t new_s = ((s+1) & 0x0000ffff) | hash_mask; + if (!cas(s_bucket, s, new_s | 0x80000000)) return 0; + // cas succesful: write data + bucket->a = a; + bucket->b = b; + bucket->c = c; + bucket->res = res; + compiler_barrier(); + // after compiler_barrier(), unlock status field + *s_bucket = new_s; + return 1; +} + + + + + + + + + +size_t SylvanCacheWrapper::m_cache_size; // power of 2 +size_t SylvanCacheWrapper::m_cache_max; +cache_entry_t SylvanCacheWrapper::m_cache_table; +uint32_t* SylvanCacheWrapper::m_cache_status; +uint64_t SylvanCacheWrapper::m_next_opid; \ No newline at end of file diff --git a/src/SylvanCacheWrapper.h b/src/SylvanCacheWrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..3502e6dffc3cfea11d28d7d048e7df861c8dc87b --- /dev/null +++ b/src/SylvanCacheWrapper.h @@ -0,0 +1,87 @@ +// +// Created by chiheb on 25/09/2020. +// + +#ifndef PMC_SOG_SYLVANCACHEWRAPPER_H +#define PMC_SOG_SYLVANCACHEWRAPPER_H + +/** + * Literals for cache + */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +// MDD operations +static const uint64_t CACHE_MDD_RELPROD = (20LL<<40); +static const uint64_t CACHE_MDD_MINUS = (21LL<<40); +static const uint64_t CACHE_MDD_UNION = (22LL<<40); +static const uint64_t CACHE_MDD_INTERSECT = (23LL<<40); +static const uint64_t CACHE_MDD_PROJECT = (24LL<<40); +static const uint64_t CACHE_MDD_JOIN = (25LL<<40); +static const uint64_t CACHE_MDD_MATCH = (26LL<<40); +static const uint64_t CACHE_MDD_RELPREV = (27LL<<40); +static const uint64_t CACHE_MDD_SATCOUNT = (28LL<<40); +static const uint64_t CACHE_MDD_DIVIDE = (29LL<<40); +static const uint64_t CACHE_LDD_MINUS = (30LL<<40); +static const uint64_t CACHE_LDD_FIRE = (31LL<<40); +static const uint64_t CACHE_LDD_UNION = (32LL<<40); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + + + + + + +/** + * This cache is designed to store a,b,c->res, with a,b,c,res 64-bit integers. + * + * Each cache bucket takes 32 bytes, 2 per cache line. + * Each cache status bucket takes 4 bytes, 16 per cache line. + * Therefore, size 2^N = 36*(2^N) bytes. + */ + +struct __attribute__((packed)) cache6_entry { + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t res; + uint64_t d; + uint64_t e; + uint64_t f; + uint64_t res2; +}; +typedef struct cache6_entry *cache6_entry_t; + +struct __attribute__((packed)) cache_entry { + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t res; +}; + +typedef struct cache_entry *cache_entry_t; +class SylvanCacheWrapper { +public: + static void cache_create(size_t _cache_size, size_t _max_size); + static int __attribute__((unused)) cache_get3(uint64_t opid, uint64_t dd, uint64_t d2, uint64_t d3, uint64_t *res); + static int __attribute__((unused)) cache_put3(uint64_t opid, uint64_t dd, uint64_t d2, uint64_t d3, uint64_t res); + static int cache_put(uint64_t a, uint64_t b, uint64_t c, uint64_t res); + static int cache_get(uint64_t a, uint64_t b, uint64_t c, uint64_t *res); +private: + static size_t m_cache_size; // power of 2 + static size_t m_cache_max; + static cache_entry_t m_cache_table; + static uint32_t* m_cache_status; + static uint64_t m_next_opid; + static uint64_t cache_hash(uint64_t a, uint64_t b, uint64_t c); +}; + + +#endif //PMC_SOG_SYLVANCACHEWRAPPER_H diff --git a/src/SylvanWrapper.cpp b/src/SylvanWrapper.cpp index 2fb461ffc21c4b7db17aa10506143f3bf5c28037..7fdfb8e605d032d3cf5e48ceb13fd65d8c791411 100644 --- a/src/SylvanWrapper.cpp +++ b/src/SylvanWrapper.cpp @@ -3,51 +3,992 @@ // -#include "sylvan.h" -#include "LDDState.h" -#include <sylvan_int.h> -#include "sylvan_seq.h" -//#include <sylvan_sog.h> - +//#include "sylvan.h" +// #include "LDDState.h" #include <functional> +#include <vector> +#include <cassert> +#include <cstring> // memset +#include <sys/mman.h> // for mmap #include <iostream> -#include <fstream> - +#include <string> +#include "SylvanCacheWrapper.h" #include "SylvanWrapper.h" -#define GETNODE(mdd) ((mddnode_t)llmsset_index_to_ptr(nodes, mdd)) -using namespace sylvan; + + +#define DECLARE_THREAD_LOCAL(name, type) __thread type name +#define INIT_THREAD_LOCAL(name) +#define SET_THREAD_LOCAL(name, value) name = value +#define LOCALIZE_THREAD_LOCAL(name, type) + +DECLARE_THREAD_LOCAL(my_region, uint64_t); +DECLARE_THREAD_LOCAL(lddmc_refs_key, lddmc_refs_internal_t); +//lddmc_refs_internal_t lddmc_refs_key; using namespace std; +MDD lddmc_false = 0; +MDD lddmc_true = 1; + -uint64_t SylvanWrapper::m_Size=0; -uint64_t SylvanWrapper::m_agg=0; /************************************** * Computes number of markings in an MDD * @param cmark : an MDD */ -uint64_t SylvanWrapper::getMarksCount ( MDD cmark ) -{ +uint64_t SylvanWrapper::getMarksCount(MDD cmark) { //typedef pair<string,MDD> Pair_stack; vector<MDD> local_stack; - uint64_t compteur=0; - MDD explore_mdd=cmark; - local_stack.push_back ( cmark ); + uint64_t compteur = 0; + MDD explore_mdd; + local_stack.push_back(cmark); do { - explore_mdd=local_stack.back(); + explore_mdd = local_stack.back(); local_stack.pop_back(); compteur++; - while ( explore_mdd!= lddmc_false && explore_mdd!=lddmc_true ) { - mddnode_t n_val = GETNODE ( explore_mdd ); - if ( mddnode_getright ( n_val ) !=lddmc_false ) { - local_stack.push_back ( mddnode_getright ( n_val ) ); + while (explore_mdd != lddmc_false && explore_mdd != lddmc_true) { + mddnode_t n_val = GETNODE(explore_mdd); + if (mddnode_getright(n_val) != lddmc_false) { + local_stack.push_back(mddnode_getright(n_val)); } - unsigned int val = mddnode_getvalue ( n_val ); - explore_mdd=mddnode_getdown ( n_val ); + //unsigned int val = mddnode_getvalue ( n_val ); + explore_mdd = mddnode_getdown(n_val); } - } while ( local_stack.size() !=0 ); + } while (!local_stack.empty()); return compteur; } + + +llmsset2_t SylvanWrapper::llmsset_create(size_t initial_size, size_t max_size) { + llmsset2_t dbs = nullptr; + if (posix_memalign((void **) &dbs, LINE_SIZE, sizeof(struct llmsset2)) != 0) { + fprintf(stderr, "llmsset_create: Unable to allocate memory!\n"); + exit(1); + } + +#if LLMSSET_MASK + /* Check if initial_size and max_size are powers of 2 */ + if (__builtin_popcountll(initial_size) != 1) { + fprintf(stderr, "llmsset_create: initial_size is not a power of 2!\n"); + exit(1); + } + + if (__builtin_popcountll(max_size) != 1) { + fprintf(stderr, "llmsset_create: max_size is not a power of 2!\n"); + exit(1); + } +#endif + + if (initial_size > max_size) { + fprintf(stderr, "llmsset_create: initial_size > max_size!\n"); + exit(1); + } + + // minimum size is now 512 buckets (region size, but of course, n_workers * 512 is suggested as minimum) + + if (initial_size < 512) { + fprintf(stderr, "llmsset_create: initial_size too small!\n"); + exit(1); + } + + dbs->max_size = max_size; + llmsset_set_size(dbs, initial_size); + + /* This implementation of "resizable hash table" allocates the max_size table in virtual memory, + but only uses the "actual size" part in real memory */ + + dbs->table = (uint64_t *) mmap(nullptr, dbs->max_size * 8, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, + 0); + dbs->data = (uint8_t *) mmap(nullptr, dbs->max_size * 16, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, + 0); + + /* Also allocate bitmaps. Each region is 64*8 = 512 buckets. + Overhead of bitmap1: 1 bit per 4096 bucket. + Overhead of bitmap2: 1 bit per bucket. + Overhead of bitmapc: 1 bit per bucket. */ + + dbs->bitmap1 = (uint64_t *) mmap(0, dbs->max_size / (512 * 8), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + dbs->bitmap2 = (uint64_t *) mmap(0, dbs->max_size / 8, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + dbs->bitmapc = (uint64_t *) mmap(0, dbs->max_size / 8, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + if (dbs->table == (uint64_t *) -1 || dbs->data == (uint8_t *) -1 || dbs->bitmap1 == (uint64_t *) -1 || + dbs->bitmap2 == (uint64_t *) -1 || dbs->bitmapc == (uint64_t *) -1) { + fprintf(stderr, "llmsset_create: Unable to allocate memory: %s!\n", strerror(errno)); + exit(1); + } + +#if defined(madvise) && defined(MADV_RANDOM) + madvise(dbs->table, dbs->max_size * 8, MADV_RANDOM); +#endif + + // forbid first two positions (index 0 and 1) + dbs->bitmap2[0] = 0xc000000000000000LL; + + dbs->hash_cb = NULL; + dbs->equals_cb = NULL; + dbs->create_cb = NULL; + dbs->destroy_cb = NULL; + + // yes, ugly. for now, we use a global thread-local value. + // that is a problem with multiple tables. + // so, for now, do NOT use multiple tables!! + + /*LACE_ME;*/ + INIT_THREAD_LOCAL(my_region); + + llmsset_reset_region(); + + return dbs; +} + + +void SylvanWrapper::llmsset_reset_region() { + LOCALIZE_THREAD_LOCAL(my_region, uint64_t); + my_region = (uint64_t) -1; // no region + SET_THREAD_LOCAL(my_region, my_region); +} + +/** + * Set the table size of the set. + * Typically called during garbage collection, after clear and before rehash. + * Returns 0 if dbs->table_size > dbs->max_size! + */ +void SylvanWrapper::llmsset_set_size(llmsset2_t dbs, size_t size) { + /* check bounds (don't be rediculous) */ + if (size > 128 && size <= dbs->max_size) { + dbs->table_size = size; +#if LLMSSET_MASK + /* Warning: if size is not a power of two, you will get interesting behavior */ + dbs->mask = dbs->table_size - 1; +#endif + /* Set threshold: number of cache lines to probe before giving up on node insertion */ + dbs->threshold = 192 - 2 * __builtin_clzll(dbs->table_size); + } +} + +void +SylvanWrapper::sylvan_set_limits(size_t memorycap, int table_ratio, int initial_ratio) { + if (table_ratio > 10 || table_ratio < -10) { + fprintf(stderr, "sylvan_set_limits: table_ratio unreasonable (between -10 and 10)\n"); + exit(1); + } + + size_t max_t = 1; + size_t max_c = 1; + if (table_ratio > 0) { + max_t <<= table_ratio; + } else { + max_c <<= -table_ratio; + } + + size_t cur = max_t * 24 + max_c * 36; + if (cur > memorycap) { + fprintf(stderr, "sylvan_set_limits: memory cap incompatible with requested table ratio\n"); + } + + while (2 * cur < memorycap && max_t < 0x0000040000000000) { + max_t *= 2; + max_c *= 2; + cur *= 2; + } + + if (initial_ratio < 0) { + fprintf(stderr, "sylvan_set_limits: initial_ratio unreasonable (may not be negative)\n"); + exit(1); + } + + size_t min_t = max_t, min_c = max_c; + while (initial_ratio > 0 && min_t > 0x1000 && min_c > 0x1000) { + min_t >>= 1; + min_c >>= 1; + initial_ratio--; + } + + m_table_min = min_t; + m_table_max = max_t; + m_cache_min = min_c; + m_cache_max = max_c; +} + +/** + * Initializes Sylvan. + */ +void SylvanWrapper::sylvan_init_package(void) { + if (m_table_max == 0) { + fprintf(stderr, "sylvan_init_package error: table sizes not set (sylvan_set_sizes or sylvan_set_limits)!"); + exit(1); + } + + /* Create tables */ + m_nodes = llmsset_create(m_table_min, m_table_max); + SylvanCacheWrapper::cache_create(m_cache_min, m_cache_max); + + /* Initialize garbage collection */ + m_gc = 0; + + /***************** Not yet **************************************/ +//#if SYLVAN_AGGRESSIVE_RESIZE +// main_hook = TASK(sylvan_gc_aggressive_resize); +//#else +// main_hook = TASK(sylvan_gc_normal_resize); +//#endif + + + //sylvan_stats_init(); +} + +void SylvanWrapper::sylvan_init_ldd() { + /*sylvan_register_quit(lddmc_quit); + sylvan_gc_add_mark(TASK(lddmc_gc_mark_external_refs)); + sylvan_gc_add_mark(TASK(lddmc_gc_mark_protected)); + sylvan_gc_add_mark(TASK(lddmc_gc_mark_serialize));*/ + //m_lddmc_protected_created=0; // Should be initialized in the constructor + refs_create(&m_lddmc_refs, 1024); + if (!m_lddmc_protected_created) { + protect_create(&m_lddmc_protected, 4096); + m_lddmc_protected_created = 1; + } + + //LACE_ME; + lddmc_refs_init(); +} + +void SylvanWrapper::lddmc_refs_init_task() { + lddmc_refs_internal_t s = (lddmc_refs_internal_t) malloc(sizeof(struct lddmc_refs_internal)); + s->pcur = s->pbegin = (const MDD **) malloc(sizeof(MDD *) * 1024); + s->pend = s->pbegin + 1024; + s->rcur = s->rbegin = (MDD *) malloc(sizeof(MDD) * 1024); + s->rend = s->rbegin + 1024; + /* s->scur = s->sbegin = (lddmc_refs_task_t)malloc(sizeof(struct lddmc_refs_task) * 1024); + s->send = s->sbegin + 1024;*/ + SET_THREAD_LOCAL(lddmc_refs_key, s); +} + +void SylvanWrapper::lddmc_refs_init() { + INIT_THREAD_LOCAL(lddmc_refs_key); + lddmc_refs_init_task(); + // sylvan_gc_add_mark(TASK(lddmc_refs_mark)); +} + + +void SylvanWrapper::refs_create(refs_table2_t *tbl, size_t _refs_size) { + if (__builtin_popcountll(_refs_size) != 1) { + fprintf(stderr, "refs: Table size must be a power of 2!\n"); + exit(1); + } + + tbl->refs_size = _refs_size; + tbl->refs_table = (uint64_t *) mmap(0, tbl->refs_size * sizeof(uint64_t), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (tbl->refs_table == (uint64_t *) -1) { + fprintf(stderr, "refs: Unable to allocate memory: %s!\n", strerror(errno)); + exit(1); + } +} + +void SylvanWrapper::protect_create(refs_table2_t *tbl, size_t _refs_size) { + if (__builtin_popcountll(_refs_size) != 1) { + fprintf(stderr, "refs: Table size must be a power of 2!\n"); + exit(1); + } + + tbl->refs_size = _refs_size; + tbl->refs_table = (uint64_t *) mmap(0, tbl->refs_size * sizeof(uint64_t), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (tbl->refs_table == (uint64_t *) -1) { + fprintf(stderr, "refs: Unable to allocate memory: %s!\n", strerror(errno)); + exit(1); + } +} + +size_t SylvanWrapper::llmsset_get_size(const llmsset2_t dbs) { + return dbs->table_size; +} + +/* + * Initialize GC + */ +void SylvanWrapper::init_gc_seq() { + m_sequentiel_refs = lddmc_refs_key; +} + +/* + * Return sizes + */ +size_t SylvanWrapper::seq_llmsset_count_marked(llmsset2_t dbs) { + return llmsset_count_marked_seq(dbs, 0, dbs->table_size); +} + +//******************************************** +size_t SylvanWrapper::llmsset_count_marked_seq(llmsset2_t dbs, size_t first, size_t count) { + if (count > 512) { + size_t split = count / 2; + + size_t right = llmsset_count_marked_seq(dbs, first + split, count - split); + size_t left = llmsset_count_marked_seq(dbs, first, split); + return left + right; + } else { + size_t result = 0; + uint64_t *ptr = dbs->bitmap2 + (first / 64); + if (count == 512) { + result += __builtin_popcountll(ptr[0]); + result += __builtin_popcountll(ptr[1]); + result += __builtin_popcountll(ptr[2]); + result += __builtin_popcountll(ptr[3]); + result += __builtin_popcountll(ptr[4]); + result += __builtin_popcountll(ptr[5]); + result += __builtin_popcountll(ptr[6]); + result += __builtin_popcountll(ptr[7]); + } else { + uint64_t mask = 0x8000000000000000LL >> (first & 63); + for (size_t k = 0; k < count; k++) { + if (*ptr & mask) result += 1; + mask >>= 1; + if (mask == 0) { + ptr++; + mask = 0x8000000000000000LL; + } + } + } + return result; + } +} + +void SylvanWrapper::displayMDDTableInfo() { + printf("%zu of %zu buckets filled!\n", seq_llmsset_count_marked(m_nodes), llmsset_get_size(m_nodes)); +} + +MDD SylvanWrapper::lddmc_cube(uint32_t *values, size_t count) { + if (count == 0) return lddmc_true; + return lddmc_makenode(*values, lddmc_cube(values + 1, count - 1), lddmc_false); +} + +MDD SylvanWrapper::lddmc_makenode(uint32_t value, MDD ifeq, MDD ifneq) { + if (ifeq == lddmc_false) return ifneq; + + + assert(ifneq != lddmc_true); + if (ifneq != lddmc_false) assert(value < mddnode_getvalue(LDD_GETNODE(ifneq))); + + struct mddnode n; + mddnode_make(&n, value, ifneq, ifeq); + + int created; + uint64_t index = llmsset_lookup(m_nodes, n.a, n.b, &created); + if (index == 0) { + /* lddmc_refs_push(ifeq); + lddmc_refs_push(ifneq);*/ + + // sylvan_gc();/*********************************************************************************************/ + /*lddmc_refs_pop(1);*/ + + index = llmsset_lookup(m_nodes, n.a, n.b, &created); + if (index == 0) { + fprintf(stderr, "MDD Unique table full, %zu of %zu buckets filled!\n", seq_llmsset_count_marked(m_nodes), + llmsset_get_size(m_nodes)); + exit(1); + } + } + + /*if (created) { + sylvan_stats_count(LDD_NODES_CREATED); + + } + else sylvan_stats_count(LDD_NODES_REUSED);*/ + + return (MDD) index; +} + +mddnode_t SylvanWrapper::LDD_GETNODE(MDD mdd) { + return ((mddnode_t) llmsset_index_to_ptr(m_nodes, mdd)); +} + +inline uint64_t +SylvanWrapper::llmsset_lookup2(const llmsset2_t dbs, uint64_t a, uint64_t b, int *created, const int custom) { + uint64_t hash_rehash = 14695981039346656037LLU; + if (custom) hash_rehash = dbs->hash_cb(a, b, hash_rehash); + else hash_rehash = llmsset_hash(a, b, hash_rehash); + + const uint64_t step = (((hash_rehash >> 20) | 1) << 3); + const uint64_t hash = hash_rehash & MASK_HASH; + uint64_t idx, last, cidx = 0; + int i = 0; + +#if LLMSSET_MASK + last = idx = hash_rehash & dbs->mask; +#else + last = idx = hash_rehash % dbs->table_size; +#endif + + for (;;) { + volatile uint64_t *bucket = dbs->table + idx; + uint64_t v = *bucket; + + if (v == 0) { + if (cidx == 0) { + // Claim data bucket and write data + cidx = claim_data_bucket(dbs); + if (cidx == (uint64_t) -1) return 0; // failed to claim a data bucket + if (custom) dbs->create_cb(&a, &b); + uint64_t *d_ptr = ((uint64_t *) dbs->data) + 2 * cidx; + d_ptr[0] = a; + d_ptr[1] = b; + } + if (cas(bucket, 0, hash | cidx)) { + if (custom) set_custom_bucket(dbs, cidx, custom); + *created = 1; + m_g_created++; + return cidx; + } else { + v = *bucket; + } + } + + if (hash == (v & MASK_HASH)) { + uint64_t d_idx = v & MASK_INDEX; + uint64_t *d_ptr = ((uint64_t *) dbs->data) + 2 * d_idx; + if (custom) { + if (dbs->equals_cb(a, b, d_ptr[0], d_ptr[1])) { + if (cidx != 0) { + dbs->destroy_cb(a, b); + release_data_bucket(dbs, cidx); + } + *created = 0; + return d_idx; + } + } else { + if (d_ptr[0] == a && d_ptr[1] == b) { + if (cidx != 0) release_data_bucket(dbs, cidx); + *created = 0; + return d_idx; + } + } + } + + //sylvan_stats_count(LLMSSET_LOOKUP); + + // find next idx on probe sequence + idx = (idx & CL_MASK) | ((idx + 1) & CL_MASK_R); + if (idx == last) { + if (++i == dbs->threshold) return 0; // failed to find empty spot in probe sequence + + // go to next cache line in probe sequence + hash_rehash += step; + +#if LLMSSET_MASK + last = idx = hash_rehash & dbs->mask; +#else + last = idx = hash_rehash % dbs->table_size; +#endif + } + } +} + +uint64_t SylvanWrapper::llmsset_lookup(const llmsset2_t dbs, const uint64_t a, const uint64_t b, int *created) { + return llmsset_lookup2(dbs, a, b, created, 0); +} + +uint64_t SylvanWrapper::llmsset_hash(const uint64_t a, const uint64_t b, const uint64_t seed) { + // The FNV-1a hash for 64 bits + const uint64_t prime = 1099511628211; + uint64_t hash = seed; + hash = (hash ^ a) * prime; + hash = (hash ^ b) * prime; + return hash ^ (hash >> 32); +} + + +uint64_t SylvanWrapper::claim_data_bucket(const llmsset2_t dbs) { + LOCALIZE_THREAD_LOCAL(my_region, uint64_t); + //printf("%d \n",my_region); + //printf("Value of my region %d \n",my_region); + for (;;) { + if (my_region != (uint64_t) -1) { + // find empty bucket in region <my_region> + //printf("My region : %d\n",my_region); + uint64_t *ptr = dbs->bitmap2 + (my_region * 8); + int i = 0; + for (; i < 8;) { + uint64_t v = *ptr; + if (v != 0xffffffffffffffffLL) { + int j = __builtin_clzll(~v); + *ptr |= (0x8000000000000000LL >> j); + return (8 * my_region + i) * 64 + j; + } + i++; + ptr++; + } + } else { + //printf("yep!"); + // special case on startup or after garbage collection" + // my_region += (lace_get_worker()->worker*(dbs->table_size/(64*8)))/lace_workers(); + } + uint64_t count = dbs->table_size / (64 * 8); + for (;;) { + // check if table maybe full + if (count-- == 0) return (uint64_t) -1; + + my_region += 1; + if (my_region >= (dbs->table_size / (64 * 8))) my_region = 0; + + // try to claim it + uint64_t *ptr = dbs->bitmap1 + (my_region / 64); + uint64_t mask = 0x8000000000000000LL >> (my_region & 63); + uint64_t v; + restart: + v = *ptr; + if (v & mask) continue; // taken + if (cas(ptr, v, v | mask)) break; + else goto restart; + } + SET_THREAD_LOCAL(my_region, my_region); + } +} + +void SylvanWrapper::release_data_bucket(const llmsset2_t dbs, uint64_t index) { + uint64_t *ptr = dbs->bitmap2 + (index / 64); + uint64_t mask = 0x8000000000000000LL >> (index & 63); + *ptr &= ~mask; +} + + +void SylvanWrapper::set_custom_bucket(const llmsset2_t dbs, uint64_t index, int on) { + uint64_t *ptr = dbs->bitmapc + (index / 64); + uint64_t mask = 0x8000000000000000LL >> (index & 63); + if (on) *ptr |= mask; + else *ptr &= ~mask; +} + +MDD __attribute__((unused)) SylvanWrapper::lddmc_refs_push(MDD lddmc) { + LOCALIZE_THREAD_LOCAL(lddmc_refs_key, lddmc_refs_internal_t); + *(lddmc_refs_key->rcur++) = lddmc; + if (lddmc_refs_key->rcur == lddmc_refs_key->rend) return lddmc_refs_refs_up(lddmc_refs_key, lddmc); + else return lddmc; +} + +void __attribute__((unused)) SylvanWrapper::lddmc_refs_pop(long amount) { + LOCALIZE_THREAD_LOCAL(lddmc_refs_key, lddmc_refs_internal_t); + lddmc_refs_key->rcur -= amount; +} + + +MDD __attribute__((noinline)) SylvanWrapper::lddmc_refs_refs_up(lddmc_refs_internal_t lddmc_refs_key, MDD res) { + + long size = lddmc_refs_key->rend - lddmc_refs_key->rbegin; + lddmc_refs_key->rbegin = (MDD *) realloc(lddmc_refs_key->rbegin, sizeof(MDD) * size * 2); + lddmc_refs_key->rcur = lddmc_refs_key->rbegin + size; + lddmc_refs_key->rend = lddmc_refs_key->rbegin + (size * 2); + return res; +} + +size_t SylvanWrapper::lddmc_nodecount(MDD mdd) { + size_t result = lddmc_nodecount_mark(mdd); + lddmc_nodecount_unmark(mdd); + return result; +} + +void SylvanWrapper::lddmc_nodecount_unmark(MDD mdd) { + if (mdd <= lddmc_true) return; + mddnode_t n = LDD_GETNODE(mdd); + if (mddnode_getmark(n)) { + mddnode_setmark(n, 0); + lddmc_nodecount_unmark(mddnode_getright(n)); + lddmc_nodecount_unmark(mddnode_getdown(n)); + } +} + +/** + * Count number of nodes in MDD + */ + +size_t SylvanWrapper::lddmc_nodecount_mark(MDD mdd) { + if (mdd <= lddmc_true) return 0; + mddnode_t n = LDD_GETNODE(mdd); + if (mddnode_getmark(n)) return 0; + mddnode_setmark(n, 1); + return 1 + lddmc_nodecount_mark(mddnode_getdown(n)) + lddmc_nodecount_mark(mddnode_getright(n)); +} + +MDD SylvanWrapper::lddmc_union_mono(MDD a, MDD b) { + /* Terminal cases */ + if (a == b) return a; + if (a == lddmc_false) return b; + if (b == lddmc_false) return a; + assert(a != lddmc_true && b != lddmc_true); // expecting same length + + /* Test gc */ + // LACE_ME; + // sylvan_gc_test(); + + //sylvan_stats_count(LDD_UNION); + + /* Improve cache behavior */ + if (a < b) { + MDD tmp = b; + b = a; + a = tmp; + } + + /* Access cache */ + MDD result; + if (SylvanCacheWrapper::cache_get3(CACHE_LDD_UNION, a, b, 0,&result)) { + // std::cout<<"Cache succeeded!"<<std::endl; + return result; + } + + + /* Get nodes */ + mddnode_t na = GETNODE(a); + mddnode_t nb = GETNODE(b); + + const int na_copy = mddnode_getcopy(na) ? 1 : 0; + const int nb_copy = mddnode_getcopy(nb) ? 1 : 0; + const uint32_t na_value = mddnode_getvalue(na); + const uint32_t nb_value = mddnode_getvalue(nb); + + /* Perform recursive calculation */ + if (na_copy && nb_copy) { + + MDD right = lddmc_union_mono(mddnode_getright(na), mddnode_getright(nb)); + MDD down = lddmc_union_mono(mddnode_getdown(na), mddnode_getdown(nb)); + result = lddmc_make_copynode(down, right); + } else if (na_copy) { + MDD right = lddmc_union_mono(mddnode_getright(na), b); + result = lddmc_make_copynode(mddnode_getdown(na), right); + } else if (nb_copy) { + MDD right = lddmc_union_mono(a, mddnode_getright(nb)); + result = lddmc_make_copynode(mddnode_getdown(nb), right); + } else if (na_value < nb_value) { + MDD right = lddmc_union_mono(mddnode_getright(na), b); + result = lddmc_makenode(na_value, mddnode_getdown(na), right); + } else if (na_value == nb_value) { + + MDD right = lddmc_union_mono(mddnode_getright(na), mddnode_getright(nb)); + + MDD down = lddmc_union_mono(mddnode_getdown(na), mddnode_getdown(nb)); + result = lddmc_makenode(na_value, down, right); + } else /* na_value > nb_value */ + { + MDD right = lddmc_union_mono(a, mddnode_getright(nb)); + result = lddmc_makenode(nb_value, mddnode_getdown(nb), right); + } + + + SylvanCacheWrapper::cache_put3(CACHE_LDD_UNION, a, b, 0, result); + + return result; +} + +MDD SylvanWrapper::lddmc_make_copynode(MDD ifeq, MDD ifneq) { + struct mddnode n; + mddnode_makecopy(&n, ifneq, ifeq); + + int created; + uint64_t index = llmsset_lookup(m_nodes, n.a, n.b, &created); + if (index == 0) { + //lddmc_refs_push(ifeq); + //lddmc_refs_push(ifneq); + /*LACE_ME; + sylvan_gc();*/ + //lddmc_refs_pop(1); + + index = llmsset_lookup(m_nodes, n.a, n.b, &created); + if (index == 0) { + fprintf(stderr, "MDD Unique table full, %zu of %zu buckets filled!\n", seq_llmsset_count_marked(m_nodes), + llmsset_get_size(m_nodes)); + exit(1); + } + } + + /*if (created) sylvan_stats_count(LDD_NODES_CREATED); + else sylvan_stats_count(LDD_NODES_REUSED);*/ + + return (MDD) index; +} + + +bool SylvanWrapper::isSingleMDD(MDD mdd) { + mddnode_t node; + + while (mdd > lddmc_true) { + node = GETNODE(mdd); + if (mddnode_getright(node) != lddmc_false) return false; + mdd = mddnode_getdown(node); + } + return true; +} + +// Renvoie le nbre de noeuds à un niveau donné +int SylvanWrapper::get_mddnbr(MDD mdd, int level) { + mddnode_t node; + for (int j = 0; j < level; j++) { + node = GETNODE(mdd); + mdd = mddnode_getdown(node); + } + int i = 0; + + while (mdd != lddmc_false) { + mddnode_t r = GETNODE(mdd); + mdd = mddnode_getright(r); + i++; + } + return i; +} + +MDD SylvanWrapper::ldd_divide_internal(MDD a, int current_level, int level) { + /* Terminal cases */ + + if (a == lddmc_false) return lddmc_false; + if (a == lddmc_true) return lddmc_true; + + MDD result; + if (SylvanCacheWrapper::cache_get3(CACHE_MDD_DIVIDE, a, current_level, level, &result)) + { + return result; + } + + mddnode_t node_a = GETNODE(a); + const uint32_t na_value = mddnode_getvalue(node_a); + + + /* Perform recursive calculation */ + if (current_level <= level) { + + MDD down = ldd_divide_internal(mddnode_getdown(node_a), current_level + 1, level); + MDD right = lddmc_false; + result = lddmc_makenode(na_value, down, right); + } else { + MDD right = ldd_divide_internal(mddnode_getright(node_a), current_level, level); + MDD down = ldd_divide_internal(mddnode_getdown(node_a), current_level + 1, level); + result = lddmc_makenode(na_value, down, right); + } + + SylvanCacheWrapper::cache_put3(CACHE_MDD_DIVIDE, a, current_level, level, result); + return result; +} + + +MDD SylvanWrapper::ldd_divide_rec(MDD a, int level) { + return ldd_divide_internal(a, 0, level); +} + +MDD SylvanWrapper::ldd_minus(MDD a, MDD b) { + /* Terminal cases */ + if (a == b) return lddmc_false; + if (a == lddmc_false) return lddmc_false; + if (b == lddmc_false) return a; + assert(b != lddmc_true); + assert(a != lddmc_true); // Universe is unknown!! // Possibly depth issue? + + /* Test gc */ + //sylvan_gc_test(); + + // sylvan_stats_count(LDD_MINUS); + + MDD result; + if (SylvanCacheWrapper::cache_get(CACHE_LDD_MINUS, a, b, &result)) { + return result; + } + /* Get nodes */ + mddnode_t na = GETNODE(a); + mddnode_t nb = GETNODE(b); + uint32_t na_value = mddnode_getvalue(na); + uint32_t nb_value = mddnode_getvalue(nb); + + /* Perform recursive calculation */ + if (na_value < nb_value) { + MDD right = ldd_minus(mddnode_getright(na), b); + result = lddmc_makenode(na_value, mddnode_getdown(na), right); + } else if (na_value == nb_value) { +// lddmc_refs_spawn(SPAWN(lddmc_minus, mddnode_getright(na), mddnode_getright(nb))); + MDD down = ldd_minus(mddnode_getdown(na), mddnode_getdown(nb)); + // lddmc_refs_push(down); + MDD right = ldd_minus(mddnode_getright(na), mddnode_getright(nb)); + //lddmc_refs_pop(1); + result = lddmc_makenode(na_value, down, right); + } else /* na_value > nb_value */ + { + result = ldd_minus(a, mddnode_getright(nb)); + } + SylvanCacheWrapper::cache_put(CACHE_LDD_MINUS, a, b, result); + return result; +} + + +MDD SylvanWrapper::lddmc_firing_mono(MDD cmark, MDD minus, MDD plus) { + // for an empty set of source states, or an empty transition relation, return the empty set + if (cmark == lddmc_true) return lddmc_true; + if (minus == lddmc_false || plus == lddmc_false) return lddmc_false; + + MDD result; + MDD _cmark = cmark, _minus = minus, _plus = plus; + + if (SylvanCacheWrapper::cache_get3(CACHE_LDD_FIRE, cmark, minus, plus, &result)) { + return result; + } + MDD cache_cmark=cmark; + mddnode_t n_cmark = GETNODE(_cmark); + mddnode_t n_plus = GETNODE(_plus); + mddnode_t n_minus = GETNODE(_minus); + + + result = lddmc_false; + + for (;;) { + uint32_t value; + value = mddnode_getvalue(n_cmark); + uint32_t value_minus = mddnode_getvalue(n_minus); + uint32_t value_plus = mddnode_getvalue(n_plus); + if (value >= value_minus) { + MDD result2 = + lddmc_makenode(value - value_minus + value_plus, + lddmc_firing_mono(mddnode_getdown(n_cmark), mddnode_getdown(n_minus), + mddnode_getdown(n_plus)), lddmc_false); + + + if (result2 != lddmc_false) result = lddmc_union_mono(result, result2); + } + cmark = mddnode_getright(n_cmark); + if (cmark == lddmc_false) break; + n_cmark = GETNODE(cmark); + } + SylvanCacheWrapper::cache_put3(CACHE_LDD_FIRE, cache_cmark, minus, plus, result); + return result; +} + +// so: proj: -2 (end; quantify rest), -1 (end; keep rest), 0 (quantify), 1 (keep) +MDD SylvanWrapper::lddmc_project( const MDD mdd, const MDD proj) +{ + if (mdd == lddmc_false) return lddmc_false; // projection of empty is empty + if (mdd == lddmc_true) return lddmc_true; // projection of universe is universe... + mddnode_t p_node = GETNODE(proj); + uint32_t p_val = mddnode_getvalue(p_node); + if (p_val == (uint32_t)-1) return mdd; + if (p_val == (uint32_t)-2) return lddmc_true; // because we always end with true. + + MDD result; + if (SylvanCacheWrapper::cache_get3(CACHE_MDD_PROJECT, mdd, proj, 0, &result)) + { + return result; + } + + mddnode_t n = LDD_GETNODE(mdd); + + if (p_val == 1) // keep + { + MDD down = lddmc_project( mddnode_getdown(n), mddnode_getdown(p_node)); + //lddmc_refs_push(down); + // MDD right = lddmc_refs_sync(SYNC(lddmc_project)); + //lddmc_refs_pop(1); + result = lddmc_makenode(mddnode_getvalue(n), down, right); + } else // quantify + { + if (mddnode_getdown(n) == lddmc_true) // assume lowest level + { + result = lddmc_true; + } + else + { + int count = 0; + result = lddmc_false; + MDD p_down = mddnode_getdown(p_node), _mdd=mdd; + while (1) + { + //lddmc_refs_spawn(SPAWN(lddmc_project, mddnode_getdown(n), p_down)); + MDD down= lddmc_project (mddnode_getdown(n), p_down); + result = lddmc_union_mono(result, down); + count++; + _mdd = mddnode_getright(n); + assert(_mdd != lddmc_true); + if (_mdd == lddmc_false) break; + n = LDD_GETNODE(_mdd); + } + + + } + } + + SylvanCacheWrapper::cache_put3(CACHE_MDD_PROJECT, mdd, proj, 0, result); + return result; +} + +int SylvanWrapper::isGCRequired() +{ + return (m_g_created>llmsset_get_size(m_nodes)/2); +} + +void SylvanWrapper::convert_wholemdd_stringcpp(MDD cmark,string &res) +{ + typedef pair<string,MDD> Pair_stack; + vector<Pair_stack> local_stack; + + unsigned int compteur=0; + MDD explore_mdd=cmark; + + string chaine; + + res=" "; + local_stack.push_back(Pair_stack(chaine,cmark)); + do + { + Pair_stack element=local_stack.back(); + chaine=element.first; + explore_mdd=element.second; + local_stack.pop_back(); + compteur++; + while ( explore_mdd!= lddmc_false && explore_mdd!=lddmc_true) + { + mddnode_t n_val = GETNODE(explore_mdd); + if (mddnode_getright(n_val)!=lddmc_false) + { + local_stack.push_back(Pair_stack(chaine,mddnode_getright(n_val))); + } + unsigned int val = mddnode_getvalue(n_val); + + chaine.push_back((unsigned char)(val)+1); + explore_mdd=mddnode_getdown(n_val); + } + /*printchaine(&chaine);printf("\n");*/ + res+=chaine; + } + while (local_stack.size()!=0); + //delete chaine; + + compteur=(compteur<<1) | 1; + res[1]=(unsigned char)((compteur>>8)+1); + res[0]=(unsigned char)(compteur & 255); + +} + + + + + + +size_t SylvanWrapper::m_table_min = 0; +size_t SylvanWrapper::m_table_max = 0; +size_t SylvanWrapper::m_cache_min = 0; +size_t SylvanWrapper::m_cache_max = 0; +/** + * This variable is used for a cas flag so only one gc runs at one time + */ +volatile int SylvanWrapper::m_gc; +llmsset2_t SylvanWrapper::m_nodes; +/** + * External refrences + */ +refs_table2_t SylvanWrapper::m_lddmc_refs; +refs_table2_t SylvanWrapper::m_lddmc_protected; +int SylvanWrapper::m_lddmc_protected_created = 0; + +/* + * Internal references + */ +lddmc_refs_internal_t SylvanWrapper::m_sequentiel_refs; +//lddmc_refs_internal_t SylvanWrapper::m_lddmc_refs_key; + +/** Sylvan table**/ +uint32_t SylvanWrapper::m_g_created; \ No newline at end of file diff --git a/src/SylvanWrapper.h b/src/SylvanWrapper.h index 8988d9b302dad91adec34fb34d4be91f06a69731..325cd8260a7eead3f8cb8f76b939a3b16c223edc 100644 --- a/src/SylvanWrapper.h +++ b/src/SylvanWrapper.h @@ -4,13 +4,256 @@ #ifndef PMC_SOG_SYLVANWRAPPER_H #define PMC_SOG_SYLVANWRAPPER_H +#include <cstdint> +#include <cstddef> +/** + * Lockless hash table (set) to store 16-byte keys. + * Each unique key is associated with a 42-bit number. + * + * The set has support for stop-the-world garbage collection. + * Methods llmsset_clear, llmsset_mark and llmsset_rehash implement garbage collection. + * During their execution, llmsset_lookup is not allowed. + * + * WARNING: Originally, this table is designed to allow multiple tables. + * However, this is not compatible with thread local storage for now. + * Do not use multiple tables. + */ + +/** + * hash(a, b, seed) + * equals(lhs_a, lhs_b, rhs_a, rhs_b) + * create(a, b) -- with a,b pointers, allows changing pointers on create of node, + * but must keep hash/equals same! + * destroy(a, b) + */ + + +typedef uint64_t (*llmsset_hash_cb)(uint64_t, uint64_t, uint64_t); + +typedef int (*llmsset_equals_cb)(uint64_t, uint64_t, uint64_t, uint64_t); + +typedef void (*llmsset_create_cb)(uint64_t *, uint64_t *); + +typedef void (*llmsset_destroy_cb)(uint64_t, uint64_t); + + +typedef uint64_t MDD; // Note: low 40 bits only +extern MDD lddmc_false; //= 0; +extern MDD lddmc_true;// = 1; + +typedef struct llmsset2 { + uint64_t *table; // table with hashes + uint8_t *data; // table with values + uint64_t *bitmap1; // ownership bitmap (per 512 buckets) + uint64_t *bitmap2; // bitmap for "contains data" + uint64_t *bitmapc; // bitmap for "use custom functions" + size_t max_size; // maximum size of the hash table (for resizing) + size_t table_size; // size of the hash table (number of slots) --> power of 2! +#if LLMSSET_MASK + size_t mask; // size-1 +#endif + size_t f_size; + llmsset_hash_cb hash_cb; // custom hash function + llmsset_equals_cb equals_cb; // custom equals function + llmsset_create_cb create_cb; // custom create function + llmsset_destroy_cb destroy_cb; // custom destroy function + int16_t threshold; // number of iterations for insertion until returning error +} *llmsset2_t; + +/** + * LDD node structure + * + * RmRR RRRR RRRR VVVV | VVVV DcDD DDDD DDDD (little endian - in memory) + * VVVV RRRR RRRR RRRm | DDDD DDDD DDDc VVVV (big endian) + */ +typedef struct __attribute__((packed)) mddnode { + uint64_t a, b; +} *mddnode_t; // 16 bytes + +/** + * Implementation of external references + * Based on a hash table for 40-bit non-null values, linear probing + * Use tombstones for deleting, higher bits for reference count + */ +typedef struct { + uint64_t *refs_table; // table itself + size_t refs_size; // number of buckets + + /* helpers during resize operation */ + volatile uint32_t refs_control; // control field + uint64_t *refs_resize_table; // previous table + size_t refs_resize_size; // size of previous table + size_t refs_resize_part; // which part is next + size_t refs_resize_done; // how many parts are done +} refs_table2_t; +/************************************** From lace.h******/ + + + +typedef struct lddmc_refs_internal { + const MDD **pbegin, **pend, **pcur; + MDD *rbegin, *rend, *rcur; +} *lddmc_refs_internal_t; + + +#ifndef cas +#define cas(ptr, old, new) (__sync_bool_compare_and_swap((ptr),(old),(new))) +#endif +/* Typical cacheline size of system architectures */ +#ifndef LINE_SIZE +#define LINE_SIZE 64 +#endif +// The LINE_SIZE is defined in lace.h +static const uint64_t CL_MASK = ~(((LINE_SIZE) / 8) - 1); +static const uint64_t CL_MASK_R = ((LINE_SIZE) / 8) - 1; +/* 40 bits for the index, 24 bits for the hash */ +#define MASK_INDEX ((uint64_t)0x000000ffffffffff) +#define MASK_HASH ((uint64_t)0xffffff0000000000) + +class SylvanWrapper { +public: + static uint64_t getMarksCount(MDD cmark); + + static llmsset2_t llmsset_create(size_t initial_size, size_t max_size); + + static void llmsset_set_size(llmsset2_t dbs, size_t size); + + static void sylvan_set_limits(size_t memorycap, int table_ratio, int initial_ratio); + + static void sylvan_init_package(void); + + static mddnode_t GETNODE(MDD mdd) { return ((mddnode_t) llmsset_index_to_ptr(m_nodes, mdd)); } + + static void *llmsset_index_to_ptr(const llmsset2_t dbs, size_t index) { + return dbs->data + index * 16; + } + + // Explore basic operations : to isolated to another file + static inline uint64_t __attribute__((unused)) mddnode_getright(mddnode_t n) { + return (n->a & 0x0000ffffffffffff) >> 1; + } + + static inline uint32_t __attribute__((unused)) mddnode_getvalue(mddnode_t n) { + return *(uint32_t *) ((uint8_t *) n + 6); + } + + static inline uint64_t __attribute__((unused)) mddnode_getdown(mddnode_t n) { + return n->b >> 17; + } + + static void sylvan_init_ldd(); + + static void refs_create(refs_table2_t *tbl, size_t _refs_size); + + static void protect_create(refs_table2_t *tbl, size_t _refs_size); + + static void init_gc_seq(); + + static size_t llmsset_get_size(const llmsset2_t dbs); + + static size_t seq_llmsset_count_marked(llmsset2_t dbs); + + static size_t llmsset_count_marked_seq(llmsset2_t dbs, size_t first, size_t count); + + static void displayMDDTableInfo(); + + static MDD lddmc_cube(uint32_t *values, size_t count); + + static MDD lddmc_makenode(uint32_t value, MDD ifeq, MDD ifneq); + + static mddnode_t LDD_GETNODE(MDD mdd); + + static MDD __attribute__((unused)) lddmc_refs_push(MDD lddmc); + + static void __attribute__((unused)) lddmc_refs_pop(long amount); + + static MDD __attribute__((noinline)) lddmc_refs_refs_up(lddmc_refs_internal_t lddmc_refs_key, MDD res); + + static size_t lddmc_nodecount(MDD mdd); + + static MDD lddmc_union_mono(MDD a, MDD b); + + static bool isSingleMDD(MDD mdd); + + static int get_mddnbr(MDD mdd, int level); + + static MDD ldd_divide_rec(MDD a, int level); + + static MDD ldd_divide_internal(MDD a, int current_level, int level); + + static MDD ldd_minus(MDD a, MDD b); + + static MDD lddmc_firing_mono(MDD cmark, MDD minus, MDD plus); + + static size_t lddmc_nodecount_mark(MDD mdd); + + static void lddmc_nodecount_unmark(MDD mdd); + + static MDD lddmc_make_copynode(MDD ifeq, MDD ifneq); + + static void lddmc_refs_init(); + + static void lddmc_refs_init_task(); + + // sylvan_int.h + static inline void __attribute__((unused)) + mddnode_makecopy(mddnode_t n, uint64_t right, uint64_t down) { + n->a = right << 1; + n->b = ((down << 1) | 1) << 16; + } + + static inline uint8_t __attribute__((unused)) mddnode_getcopy(mddnode_t n) { + return n->b & 0x10000 ? 1 : 0; + } + + static inline uint8_t __attribute__((unused)) mddnode_getmark(mddnode_t n) { + return n->a & 1; + } + + static inline void __attribute__((unused)) mddnode_setmark(mddnode_t n, uint8_t mark) { + n->a = (n->a & 0xfffffffffffffffe) | (mark ? 1 : 0); + } + + //sylvan_table.c + static inline void __attribute__((unused)) + mddnode_make(mddnode_t n, uint32_t value, uint64_t right, uint64_t down) { + n->a = right << 1; + n->b = down << 17; + *(uint32_t *) ((uint8_t *) n + 6) = value; + } + + static inline uint64_t + llmsset_lookup2(const llmsset2_t dbs, uint64_t a, uint64_t b, int *created, const int custom); + + static uint64_t llmsset_lookup(const llmsset2_t dbs, const uint64_t a, const uint64_t b, int *created); + + static uint64_t llmsset_hash(const uint64_t a, const uint64_t b, const uint64_t seed); + + static uint64_t claim_data_bucket(const llmsset2_t dbs); + + static void release_data_bucket(const llmsset2_t dbs, uint64_t index); + + static void set_custom_bucket(const llmsset2_t dbs, uint64_t index, int on); + + static void llmsset_reset_region(); + static MDD lddmc_project( const MDD mdd, const MDD proj); + static int isGCRequired(); + static void convert_wholemdd_stringcpp(MDD cmark,std::string &res); +private: + static llmsset2_t m_nodes; + static size_t m_table_min, m_table_max, m_cache_min, m_cache_max; + static volatile int m_gc; + + static refs_table2_t m_lddmc_refs; // External references + static refs_table2_t m_lddmc_protected;// External references + static int m_lddmc_protected_created;// External references + + static lddmc_refs_internal_t m_sequentiel_refs; + //static lddmc_refs_internal_t m_lddmc_refs_key; // This is local to a thread + + static uint32_t m_g_created; - class SylvanWrapper { - public: - static uint64_t getMarksCount ( MDD cmark ); - static uint64_t m_Size; - static uint64_t m_agg; }; diff --git a/src/TransSylvan.cpp b/src/TransSylvan.cpp index c532bbbdefa953c2df8829db2e6838264e2079fa..c72581f05ccdd6ec3767888f9bcddc91380cd9be 100644 --- a/src/TransSylvan.cpp +++ b/src/TransSylvan.cpp @@ -1,3 +1,7 @@ +#include <cstdint> +#include <cstddef> +#include <string> +#include "SylvanWrapper.h" #include "TransSylvan.h" TransSylvan::TransSylvan(const MDD &_minus, const MDD &_plus):m_minus(_minus),m_plus(_plus) diff --git a/src/TransSylvan.h b/src/TransSylvan.h index 0db9fcd2c3dc01d33c735057959b1cd63cc79737..0c9849c431a8700ea0a764de31386cd87ecb8676 100755 --- a/src/TransSylvan.h +++ b/src/TransSylvan.h @@ -1,7 +1,8 @@ #ifndef TRANSSYLVAN_H -#include <sylvan.h> #define TRANSSYLVAN_H -using namespace sylvan; + + + class TransSylvan { public: TransSylvan(const MDD &_minus, const MDD &_plus); diff --git a/src/main.cpp b/src/main.cpp index 9b6e7cd38036d8d4d90e052265cdf0352a1463cb..c20e178cbf04f210890c79c044ba73120d42a540 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,15 +6,13 @@ #include <fstream> #include <mpi.h> -#include "DistributedSOG.h" + +#include "LDDGraph.h" +#include "ModelCheckerCPPThread.h" +#include "ModelCheckerTh.h" #include "threadSOG.h" #include "HybridSOG.h" #include "MCHybridSOG.h" -#include "LDDGraph.h" -#include "ModelCheckLace.h" -#include "ModelCheckerTh.h" -#include "ModelCheckerThV2.h" - #include <spot/misc/version.hh> #include <spot/twaalgos/dot.hh> #include <spot/tl/parse.hh> @@ -119,277 +117,284 @@ int main(int argc, char **argv) { MPI_Comm_size(MPI_COMM_WORLD, &n_tasks); MPI_Comm_rank(MPI_COMM_WORLD, &task_id); - if (n_tasks == 1) { - if (n_tasks == 1 && (!strcmp(argv[1], "otfL") || !strcmp(argv[1], "otfC") || !strcmp(argv[1], "otfP"))) { - cout << "Performing on the fly Model checking..." << endl; - if (!strcmp(argv[1], "otfP")) - cout << "Multi-threaded algorithm based on Pthread library!" << endl; - else if (!strcmp(argv[1], "otfL")) - cout << "Multi-threaded algorithm based on Lace framework!" << endl; - else + + if (n_tasks == 1) { + if (n_tasks == 1 && (!strcmp(argv[1], "otfL") || !strcmp(argv[1], "otfC") || !strcmp(argv[1], "otfP"))) { + cout << "Performing on the fly Model checking..." << endl; + if (!strcmp(argv[1], "otfP")) + cout << "Multi-threaded algorithm based on Pthread library!" << endl; + else if (!strcmp(argv[1], "otfL")) + cout << "Multi-threaded algorithm based on Lace framework!" << endl; + else cout << "Multi-threaded algorithm based on C++ Thread library!" << endl; - cout << "Building automata for not(formula)\n"; - auto d = spot::make_bdd_dict(); - - spot::twa_graph_ptr af = spot::translator(d).run(not_f); - cout << "Formula automata built.\n"; - /*cout << "Want to save the graph in a dot file ?"; - char c; - cin >> c; - if (c == 'y') { - fstream file; - string st(formula); - st += ".dot"; - file.open(st.c_str(), fstream::out); - spot::print_dot(file, af); - file.close(); - } - cout << "Loading net information..." << endl;*/ - ModelCheckBaseMT *mcl; - if (!strcmp(argv[1], "otfL")) - mcl = new ModelCheckLace(Rnewnet, nb_th); - else if (!strcmp(argv[1], "otfP")) - mcl = new ModelCheckerTh(Rnewnet, nb_th); - else - mcl = new ModelCheckerThV2(Rnewnet, nb_th); - mcl->loadNet(); - auto k = std::make_shared<SogKripkeTh>(d, mcl, Rnewnet.getListTransitionAP(), Rnewnet.getListPlaceAP()); - cout << "Performing on the fly Modelchecking" << endl; - if (strcmp(algorithm, "")) { - cout << "Spot emptiness check algorithm : "<<algorithm<< endl; - shared_ptr < spot::twa_product > product = make_shared<spot::twa_product>(k,af); - //spot::couvreur99_check_shy check = spot::couvreur99_check_shy(product); - /****************************/ - const char *err; - spot::emptiness_check_instantiator_ptr echeck_inst = spot::make_emptiness_check_instantiator(algorithm, &err); - - if (!echeck_inst) { - cerr << "Failed to parse argument near `" << err << "'" << endl; - cerr << "Spot unknown emptiness algorithm" << endl; - exit(2); - } - auto startTime = std::chrono::steady_clock::now(); - spot::emptiness_check_ptr echptr = echeck_inst->instantiate(product); - bool res = (echptr->check() == 0); - auto finalTime = std::chrono::steady_clock::now(); - displayTime(startTime, finalTime); - displayCheckResult(res); - /****************************/ - - - - /*auto startTime = std::chrono::steady_clock::now(); - bool res = (check.check() == 0); - auto finalTime = std::chrono::steady_clock::now(); - displayTime(startTime, finalTime); - displayCheckResult(res);*/ - - } else { - auto startTime = std::chrono::steady_clock::now(); - bool res = (k->intersecting_run(af) == 0); - auto finalTime = std::chrono::steady_clock::now(); - displayTime(startTime, finalTime); - displayCheckResult(res); - /* - if (!resauto run = k->intersecting_run(af)) { - cout << "formula is violated by the following run:\n" << *run << endl; - cout << "==================================" << endl; - /*run->highlight(5); // 5 is a color number. - fstream file; - file.open("violated.dot",fstream::out); - cout<<"Property is violated!"<<endl; - cout<<"Check the dot file."<<endl; - spot::print_dot(file, k, ".kA"); - file.close();*/ - /*} else { - std::cout << "formula is verified\n"; - auto finalTime = std::chrono::high_resolution_clock::now(); - displayTime(startTime, finalTime); - - }*/ - } - - delete mcl; - } - - else { - cout << "number of task = 1 \n " << endl; - bool uselace = (!strcmp(argv[1], "lc")) || (!strcmp(argv[1], "l")); - threadSOG DR(Rnewnet, nb_th, uselace); - LDDGraph g(&DR); - - if (nb_th == 1) { - cout << "******************Sequential version******************* \n" << endl; - DR.computeSeqSOG(g); - g.printCompleteInformation(); - } else { - cout << "*******************Multithread version****************** \n" << endl; - if (!strcmp(argv[1], "p")) { - cout << "Construction with pthread library." << endl; - cout << "Count of threads to be created: " << nb_th << endl; - DR.computeDSOG(g, false); - g.printCompleteInformation(); - } else if (!strcmp(argv[1], "pc")) { - cout << "Canonized construction with pthread library." << endl; - cout << "Count of threads to be created: " << nb_th << endl; - DR.computeDSOG(g, true); - g.printCompleteInformation(); - } else if (!strcmp(argv[1], "l")) { - cout << "Construction with lace framework." << endl; - cout << "Count of workers to be created: " << nb_th << endl; - DR.computeSOGLace(g); - g.printCompleteInformation(); - } else if (!strcmp(argv[1], "lc")) { - cout << "Canonised construction with lace framework." << endl; - cout << "Count of workers to be created: " << nb_th << endl; - DR.computeSOGLaceCanonized(g); - g.printCompleteInformation(); - } + cout << "Building automata for not(formula)\n"; + auto d = spot::make_bdd_dict(); + + spot::twa_graph_ptr af = spot::translator(d).run(not_f); + cout << "Formula automata built.\n"; + /*cout << "Want to save the graph in a dot file ?"; + char c; + cin >> c; + if (c == 'y') { + fstream file; + string st(formula); + st += ".dot"; + file.open(st.c_str(), fstream::out); + spot::print_dot(file, af); + file.close(); + } + cout << "Loading net information..." << endl;*/ + ModelCheckBaseMT *mcl; + /*if (!strcmp(argv[1], "otfL")) + mcl = new ModelCheckLace(Rnewnet, nb_th); + else*/ + if (!strcmp(argv[1], "otfP")) + mcl = new ModelCheckerTh(Rnewnet, nb_th); + else + mcl = new ModelCheckerCPPThread(Rnewnet, nb_th); + mcl->loadNet(); + auto k = std::make_shared<SogKripkeTh>(d, mcl, Rnewnet.getListTransitionAP(), Rnewnet.getListPlaceAP()); + cout << "Performing on the fly Modelchecking" << endl; + if (strcmp(algorithm, "")) { + cout << "Spot emptiness check algorithm : "<<algorithm<< endl; + shared_ptr < spot::twa_product > product = make_shared<spot::twa_product>(k,af); + //spot::couvreur99_check_shy check = spot::couvreur99_check_shy(product); + /****************************/ + const char *err; + spot::emptiness_check_instantiator_ptr echeck_inst = spot::make_emptiness_check_instantiator(algorithm, &err); + + if (!echeck_inst) { + cerr << "Failed to parse argument near `" << err << "'" << endl; + cerr << "Spot unknown emptiness algorithm" << endl; + exit(2); + } + auto startTime = std::chrono::steady_clock::now(); + spot::emptiness_check_ptr echptr = echeck_inst->instantiate(product); + bool res = (echptr->check() == 0); + auto finalTime = std::chrono::steady_clock::now(); + displayTime(startTime, finalTime); + displayCheckResult(res); + /****************************/ + + /*auto startTime = std::chrono::steady_clock::now(); + bool res = (check.check() == 0); + auto finalTime = std::chrono::steady_clock::now(); + displayTime(startTime, finalTime); + displayCheckResult(res);*/ + + } else { + auto startTime = std::chrono::steady_clock::now(); + bool res = (k->intersecting_run(af) == 0); + auto finalTime = std::chrono::steady_clock::now(); + displayTime(startTime, finalTime); + displayCheckResult(res); /* - cout << "Perform Model checking ?"; - char c; - cin >> c; - if (c == 'y') { - cout << "Building automata for not(formula)\n"; - auto d = spot::make_bdd_dict(); - // d->register_ap("jbhkj"); - spot::twa_graph_ptr af = spot::translator(d).run(not_f); - cout << "Formula automata built.\n"; - cout << "Want to save the graph in a dot file ?"; - cin >> c; - if (c == 'y') { - fstream file; - string st(formula); - st += ".dot"; - file.open(st.c_str(), fstream::out); - spot::print_dot(file, af); - file.close(); - } - //auto k = std::make_shared<SogKripke>(d,DR.getGraph(),R.getListTransitionAP(),R.getListPlaceAP()); - - spot::twa_graph_ptr k = spot::make_twa_graph( - std::make_shared<SogKripke>(d, DR.getGraph(), Rnewnet.getListTransitionAP(), Rnewnet.getListPlaceAP()), - spot::twa::prop_set::all(), true); - - cout << "SOG translated to SPOT succeeded.." << endl; - cout << "Want to save the graph in a dot file ?"; - cin >> c; - if (c == 'y') { - fstream file; - string st(argv[3]); - st += ".dot"; - file.open(st.c_str(), fstream::out); - spot::print_dot(file, k, "ka"); - file.close(); - } - if (auto run = k->intersecting_run(af)) { - run->highlight(5); - fstream file; - file.open("violated.dot", fstream::out); - cout << "Property is violated" << endl; - cout << "Check the dot file to get a violation run" << endl; - spot::print_dot(file, k, ".kA"); - file.close(); - } else - std::cout << "formula is verified\n"; - }*/ - - } - } + if (!resauto run = k->intersecting_run(af)) { + cout << "formula is violated by the following run:\n" << *run << endl; + cout << "==================================" << endl; + /*run->highlight(5); // 5 is a color number. + fstream file; + file.open("violated.dot",fstream::out); + cout<<"Property is violated!"<<endl; + cout<<"Check the dot file."<<endl; + spot::print_dot(file, k, ".kA"); + file.close();*/ + /*} else { + std::cout << "formula is verified\n"; + auto finalTime = std::chrono::high_resolution_clock::now(); + displayTime(startTime, finalTime); + + }*/ + } + delete mcl; + } + + else { + cout << "number of task = 1 \n " << endl; + bool uselace = (!strcmp(argv[1], "lc")) || (!strcmp(argv[1], "l")); + threadSOG DR(Rnewnet, nb_th, uselace); + LDDGraph g(&DR); + + if (nb_th == 1) { + cout << "******************Sequential version******************* \n" << endl; + DR.computeSeqSOG(g); + g.printCompleteInformation(); + } else { + cout << "*******************Multithread version****************** \n" << endl; + if (!strcmp(argv[1], "p")) { + cout << "Construction with pthread library." << endl; + cout << "Count of threads to be created: " << nb_th << endl; + DR.computeDSOG(g, false); + g.printCompleteInformation(); + } else if (!strcmp(argv[1], "pc")) { + cout << "Canonized construction with pthread library." << endl; + cout << "Count of threads to be created: " << nb_th << endl; + DR.computeDSOG(g, true); + g.printCompleteInformation(); + } /*else if (!strcmp(argv[1], "l")) { + cout << "Construction with lace framework." << endl; + cout << "Count of workers to be created: " << nb_th << endl; + DR.computeSOGLace(g); + g.printCompleteInformation(); + } else if (!strcmp(argv[1], "lc")) { + cout << "Canonised construction with lace framework." << endl; + cout << "Count of workers to be created: " << nb_th << endl; + DR.computeSOGLaceCanonized(g); + g.printCompleteInformation(); + }*/ + + cout << "Perform Model checking ?"; + char c; + cin >> c; + if (c == 'y') { + cout << "Building automata for not(formula)\n"; + auto d = spot::make_bdd_dict(); + + spot::twa_graph_ptr af = spot::translator(d).run(not_f); + cout << "Formula automata built.\n"; + cout << "Want to save the graph in a dot file ?"; + cin >> c; + if (c == 'y') { + fstream file; + string st(formula); + st += ".dot"; + file.open(st.c_str(), fstream::out); + spot::print_dot(file, af); + file.close(); + } + //auto k = std::make_shared<SogKripke>(d,DR.getGraph(),R.getListTransitionAP(),R.getListPlaceAP()); + + spot::twa_graph_ptr k = spot::make_twa_graph( + std::make_shared<SogKripke>(d, DR.getGraph(), Rnewnet.getListTransitionAP(), Rnewnet.getListPlaceAP()), + spot::twa::prop_set::all(), true); + + cout << "SOG translated to SPOT succeeded.." << endl; + cout << "Want to save the graph in a dot file ?"; + cin >> c; + if (c == 'y') { + fstream file; + string st(argv[3]); + st += ".dot"; + file.open(st.c_str(), fstream::out); + spot::print_dot(file, k, "ka"); + file.close(); + } + if (auto run = k->intersecting_run(af)) { + run->highlight(5); + fstream file; + file.open("violated.dot", fstream::out); + cout << "Property is violated" << endl; + cout << "Check the dot file to get a violation run" << endl; + spot::print_dot(file, k, ".kA"); + file.close(); + } else + std::cout << "formula is verified\n"; + } + + } + } + + + } + + if (n_tasks > 1) { + if (nb_th > 1) { + if (task_id == 0) + cout << "**************Hybrid version**************** \n" << endl; + if (strcmp(argv[1], "otf")) { + HybridSOG DR(Rnewnet); + LDDGraph g(&DR); + if (task_id == 0) + cout << "Building the Distributed SOG by " << n_tasks << " processes..." << endl; + DR.computeDSOG(g); + } else { + n_tasks--; + if (task_id == n_tasks) { + cout << "Model checking on the fly..." << endl; + cout << " One process will perform Model checking" << endl; + cout << n_tasks << " process will build the Distributed SOG" << endl; + } + MPI_Comm gprocess; + MPI_Comm_split(MPI_COMM_WORLD, task_id == n_tasks ? 0 : 1, task_id, &gprocess); + //cout<<" Task id "<<task_id<<"/"<<n_tasks<<endl; + if (task_id != n_tasks) { + cout << "N task :" << n_tasks << endl; + MCHybridSOG DR(Rnewnet, gprocess, false); + LDDGraph g(&DR); + DR.computeDSOG(g); + } else { + cout << "************************************" << endl; + cout << "On the fly Model checker by process " << task_id << endl; + auto d = spot::make_bdd_dict(); + spot::twa_graph_ptr af = spot::translator(d).run(not_f); + auto k = std::make_shared<HybridKripke>(d, Rnewnet.getListTransitionAP(), Rnewnet.getListPlaceAP(), Rnewnet); + if (strcmp(algorithm, "")) { + std::shared_ptr < spot::twa_product > product = make_shared<spot::twa_product>(af, k); + const char *err; + spot::emptiness_check_instantiator_ptr echeck_inst = spot::make_emptiness_check_instantiator(algorithm, &err); + + if (!echeck_inst) { + cerr << "Failed to parse argument near `" << err << "'" << endl; + cerr << "Spot unknown emptiness algorithm" << endl; + exit(2); + } + else + cout<<"Spot emptiness check algorithm : "<<algorithm<<endl; + auto startTime = std::chrono::high_resolution_clock::now(); + spot::emptiness_check_ptr echptr = echeck_inst->instantiate(product); + bool res = (echptr->check() == 0); + auto finalTime = std::chrono::high_resolution_clock::now(); + displayTime(startTime, finalTime); + displayCheckResult(res); + /*spot::couvreur99_check check = spot::couvreur99_check(product); + auto startTime = std::chrono::steady_clock::now(); + bool res = (check.check() == 0); + auto finalTime = std::chrono::steady_clock::now(); + displayTime(startTime, finalTime); + displayCheckResult(res);*/ + } else { + auto startTime = std::chrono::steady_clock::now(); + bool res = (k->intersecting_run(af) == 0); + auto finalTime = std::chrono::steady_clock::now(); + displayTime(startTime, finalTime); + displayCheckResult(res); + } + + /*if (auto run = k->intersecting_run(af)) + { + std::cout << "formula is violated by the following run:\n"<<*run<<endl; + auto t2 = std::chrono::high_resolution_clock::now(); + std::cout << "temps de verification " + << std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count() + << " milliseconds\n"; + cout<<"=================================="<<endl; + } + else + { + std::cout << "formula is verified\n"; + auto t2 = std::chrono::high_resolution_clock::now(); + std::cout << "temps de verification " + << std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count() + << " milliseconds\n"; + + }*/ + } + } + } else { + /*cout << "*************Distibuted version******************* \n" << endl; + { + DistributedSOG DR(Rnewnet);cout<<"Spot emptiness check algorithm : "<<algorithm<<endl; + LDDGraph g(nullptr); + DR.computeDSOG(g); + }*/ + } + } + + + + + - } - if (n_tasks > 1) { - if (nb_th > 1) { - if (task_id == 0) - cout << "**************Hybrid version**************** \n" << endl; - if (strcmp(argv[1], "otf")) { - HybridSOG DR(Rnewnet); - LDDGraph g(&DR); - if (task_id == 0) - cout << "Building the Distributed SOG by " << n_tasks << " processes..." << endl; - DR.computeDSOG(g); - } else { - n_tasks--; - if (task_id == n_tasks) { - cout << "Model checking on the fly..." << endl; - cout << " One process will perform Model checking" << endl; - cout << n_tasks << " process will build the Distributed SOG" << endl; - } - MPI_Comm gprocess; - MPI_Comm_split(MPI_COMM_WORLD, task_id == n_tasks ? 0 : 1, task_id, &gprocess); - //cout<<" Task id "<<task_id<<"/"<<n_tasks<<endl; - if (task_id != n_tasks) { - cout << "N task :" << n_tasks << endl; - MCHybridSOG DR(Rnewnet, gprocess, false); - LDDGraph g(&DR); - DR.computeDSOG(g); - } else { - cout << "************************************" << endl; - cout << "On the fly Model checker by process " << task_id << endl; - auto d = spot::make_bdd_dict(); - spot::twa_graph_ptr af = spot::translator(d).run(not_f); - auto k = std::make_shared<HybridKripke>(d, Rnewnet.getListTransitionAP(), Rnewnet.getListPlaceAP(), Rnewnet); - if (strcmp(algorithm, "")) { - std::shared_ptr < spot::twa_product > product = make_shared<spot::twa_product>(af, k); - const char *err; - spot::emptiness_check_instantiator_ptr echeck_inst = spot::make_emptiness_check_instantiator(algorithm, &err); - - if (!echeck_inst) { - cerr << "Failed to parse argument near `" << err << "'" << endl; - cerr << "Spot unknown emptiness algorithm" << endl; - exit(2); - } - else - cout<<"Spot emptiness check algorithm : "<<algorithm<<endl; - auto startTime = std::chrono::high_resolution_clock::now(); - spot::emptiness_check_ptr echptr = echeck_inst->instantiate(product); - bool res = (echptr->check() == 0); - auto finalTime = std::chrono::high_resolution_clock::now(); - displayTime(startTime, finalTime); - displayCheckResult(res); - /*spot::couvreur99_check check = spot::couvreur99_check(product); - auto startTime = std::chrono::steady_clock::now(); - bool res = (check.check() == 0); - auto finalTime = std::chrono::steady_clock::now(); - displayTime(startTime, finalTime); - displayCheckResult(res);*/ - } else { - auto startTime = std::chrono::steady_clock::now(); - bool res = (k->intersecting_run(af) == 0); - auto finalTime = std::chrono::steady_clock::now(); - displayTime(startTime, finalTime); - displayCheckResult(res); - } - - /*if (auto run = k->intersecting_run(af)) - { - std::cout << "formula is violated by the following run:\n"<<*run<<endl; - auto t2 = std::chrono::high_resolution_clock::now(); - std::cout << "temps de verification " - << std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count() - << " milliseconds\n"; - cout<<"=================================="<<endl; - } - else - { - std::cout << "formula is verified\n"; - auto t2 = std::chrono::high_resolution_clock::now(); - std::cout << "temps de verification " - << std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count() - << " milliseconds\n"; - - }*/ - } - } - } else { - cout << "*************Distibuted version******************* \n" << endl; - { - DistributedSOG DR(Rnewnet);cout<<"Spot emptiness check algorithm : "<<algorithm<<endl; - LDDGraph g(nullptr); - DR.computeDSOG(g); - } - } - } MPI_Finalize(); return (EXIT_SUCCESS); diff --git a/src/sha2.c b/src/sha2.c new file mode 100755 index 0000000000000000000000000000000000000000..69c7e7d5afaeb298f285170e687e9323864969f7 --- /dev/null +++ b/src/sha2.c @@ -0,0 +1,1052 @@ +/* + * FILE: sha2.c + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <string.h> /* memcpy()/memset() or bcopy()/bzero() */ +#include <assert.h> /* assert() */ +#include "sha2.h" + +/* + * ASSERT NOTE: + * Some sanity checking code is included using assert(). On my FreeBSD + * system, this additional code can be removed by compiling with NDEBUG + * defined. Check your own systems manpage on assert() to see how to + * compile WITHOUT the sanity checking code on your system. + * + * UNROLLED TRANSFORM LOOP NOTE: + * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform + * loop version for the hash transform rounds (defined using macros + * later in this file). Either define on the command line, for example: + * + * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c + * + * or define below: + * + * #define SHA2_UNROLL_TRANSFORM + * + */ + + +/*** SHA-256/384/512 Machine Architecture Definitions *****************/ +/* + * BYTE_ORDER NOTE: + * + * Please make sure that your system defines BYTE_ORDER. If your + * architecture is little-endian, make sure it also defines + * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are + * equivilent. + * + * If your system does not define the above, then you can do so by + * hand like this: + * + * #define LITTLE_ENDIAN 1234 + * #define BIG_ENDIAN 4321 + * + * And for little-endian machines, add: + * + * #define BYTE_ORDER LITTLE_ENDIAN + * + * Or for big-endian machines: + * + * #define BYTE_ORDER BIG_ENDIAN + * + * The FreeBSD machine this was written on defines BYTE_ORDER + * appropriately by including <sys/types.h> (which in turn includes + * <machine/endian.h> where the appropriate definitions are actually + * made). + */ +#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) +#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN +#endif + +/* + * Define the followingsha2_* types to types of the correct length on + * the native archtecture. Most BSD systems and Linux define u_intXX_t + * types. Machines with very recent ANSI C headers, can use the + * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H + * during compile or in the sha.h header file. + * + * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t + * will need to define these three typedefs below (and the appropriate + * ones in sha.h too) by hand according to their system architecture. + * + * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t + * types and pointing out recent ANSI C support for uintXX_t in inttypes.h. + */ +#ifdef SHA2_USE_INTTYPES_H + +typedef uint8_t sha2_byte; /* Exactly 1 byte */ +typedef uint32_t sha2_word32; /* Exactly 4 bytes */ +typedef uint64_t sha2_word64; /* Exactly 8 bytes */ + +#else /* SHA2_USE_INTTYPES_H */ + +typedef u_int8_t sha2_byte; /* Exactly 1 byte */ +typedef u_int32_t sha2_word32; /* Exactly 4 bytes */ +typedef u_int64_t sha2_word64; /* Exactly 8 bytes */ + +#endif /* SHA2_USE_INTTYPES_H */ + + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +/* NOTE: Most of these are in sha2.h */ +#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) +#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) +#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) + + +/*** ENDIAN REVERSAL MACROS *******************************************/ +#if BYTE_ORDER == LITTLE_ENDIAN +#define REVERSE32(w,x) { \ + sha2_word32 tmp = (w); \ + tmp = (tmp >> 16) | (tmp << 16); \ + (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ +} +#define REVERSE64(w,x) { \ + sha2_word64 tmp = (w); \ + tmp = (tmp >> 32) | (tmp << 32); \ + tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ + ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ + (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ + ((tmp & 0x0000ffff0000ffffULL) << 16); \ +} +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) { \ + (w)[0] += (sha2_word64)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} + +/* + * Macros for copying blocks of memory and for zeroing out ranges + * of memory. Using these macros makes it easy to switch from + * using memset()/memcpy() and using bzero()/bcopy(). + * + * Please define either SHA2_USE_MEMSET_MEMCPY or define + * SHA2_USE_BZERO_BCOPY depending on which function set you + * choose to use: + */ +#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) +/* Default to memset()/memcpy() if no option is specified */ +#define SHA2_USE_MEMSET_MEMCPY 1 +#endif +#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) +/* Abort with an error if BOTH options are defined */ +#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! +#endif + +#ifdef SHA2_USE_MEMSET_MEMCPY +#define MEMSET_BZERO(p,l) memset((p), 0, (l)) +#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) +#endif +#ifdef SHA2_USE_BZERO_BCOPY +#define MEMSET_BZERO(p,l) bzero((p), (l)) +#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) +#endif + + +/*** THE SIX LOGICAL FUNCTIONS ****************************************/ +/* + * Bit shifting and rotation (used by the six SHA-XYZ logical functions: + * + * NOTE: The naming of R and S appears backwards here (R is a SHIFT and + * S is a ROTATION) because the SHA-256/384/512 description document + * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this + * same "backwards" definition. + */ +/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +#define R(b,x) ((x) >> (b)) +/* 32-bit Rotate-right (used in SHA-256): */ +#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) +/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ +#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) + +/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) +#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) +#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) +#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) + +/* Four of six logical functions used in SHA-384 and SHA-512: */ +#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) +#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) +#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) +#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) + +/*** INTERNAL FUNCTION PROTOTYPES *************************************/ +/* NOTE: These should not be accessed directly from outside this + * library -- they are intended for private internal visibility/use + * only. + */ +void SHA512_Last(SHA512_CTX*); +void SHA256_Transform(SHA256_CTX*, const sha2_word32*); +void SHA512_Transform(SHA512_CTX*, const sha2_word64*); + + +/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ +/* Hash constant words K for SHA-256: */ +static const sha2_word32 K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Initial hash value H for SHA-256: */ +static const sha2_word32 sha256_initial_hash_value[8] = { + 0x6a09e667UL, + 0xbb67ae85UL, + 0x3c6ef372UL, + 0xa54ff53aUL, + 0x510e527fUL, + 0x9b05688cUL, + 0x1f83d9abUL, + 0x5be0cd19UL +}; + +/* Hash constant words K for SHA-384 and SHA-512: */ +static const sha2_word64 K512[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +/* Initial hash value H for SHA-384 */ +static const sha2_word64 sha384_initial_hash_value[8] = { + 0xcbbb9d5dc1059ed8ULL, + 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, + 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, + 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, + 0x47b5481dbefa4fa4ULL +}; + +/* Initial hash value H for SHA-512 */ +static const sha2_word64 sha512_initial_hash_value[8] = { + 0x6a09e667f3bcc908ULL, + 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, + 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, + 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, + 0x5be0cd19137e2179ULL +}; + +/* + * Constant used by SHA256/384/512_End() functions for converting the + * digest to a readable hexadecimal character string: + */ +static const char *sha2_hex_digits = "0123456789abcdef"; + + +/*** SHA-256: *********************************************************/ +void SHA256_Init(SHA256_CTX* context) { + if (context == (SHA256_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); + context->bitcount = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-256 round macros: */ + +#if BYTE_ORDER == LITTLE_ENDIAN + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE32(*data++, W256[j]); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + W256[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + + +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + (W256[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND256(a,b,c,d,e,f,g,h) \ + s0 = W256[(j+1)&0x0f]; \ + s0 = sigma0_256(s0); \ + s1 = W256[(j+14)&0x0f]; \ + s1 = sigma1_256(s1); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + ROUND256_0_TO_15(a,b,c,d,e,f,g,h); + ROUND256_0_TO_15(h,a,b,c,d,e,f,g); + ROUND256_0_TO_15(g,h,a,b,c,d,e,f); + ROUND256_0_TO_15(f,g,h,a,b,c,d,e); + ROUND256_0_TO_15(e,f,g,h,a,b,c,d); + ROUND256_0_TO_15(d,e,f,g,h,a,b,c); + ROUND256_0_TO_15(c,d,e,f,g,h,a,b); + ROUND256_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds to 64: */ + do { + ROUND256(a,b,c,d,e,f,g,h); + ROUND256(h,a,b,c,d,e,f,g); + ROUND256(g,h,a,b,c,d,e,f); + ROUND256(f,g,h,a,b,c,d,e); + ROUND256(e,f,g,h,a,b,c,d); + ROUND256(d,e,f,g,h,a,b,c); + ROUND256(c,d,e,f,g,h,a,b); + ROUND256(b,c,d,e,f,g,h,a); + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, T2, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#if BYTE_ORDER == LITTLE_ENDIAN + /* Copy data while converting to host byte order */ + REVERSE32(*data++,W256[j]); + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* Apply the SHA-256 compression function to update a..h with copy */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0); + + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA256_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; + SHA256_Transform(context, (sha2_word32*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + context->bitcount += len << 3; + return; + } + } + while (len >= SHA256_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA256_Transform(context, (sha2_word32*)data); + context->bitcount += SHA256_BLOCK_LENGTH << 3; + len -= SHA256_BLOCK_LENGTH; + data += SHA256_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + context->bitcount += len << 3; + } +} + +void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { + sha2_word32 *d = (sha2_word32*)digest; + unsigned int usedspace; + + /* Sanity check: */ + assert(context != (SHA256_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount,context->bitcount); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA256_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + } + } else { + /* Set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Set the bit count: */ + sha2_word64* ptr = (sha2_word64*)(&context->buffer[SHA256_SHORT_BLOCK_LENGTH]); + *ptr = context->bitcount; + + /* Final transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE32(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH); +#endif + } + + /* Clean up state data: */ + MEMSET_BZERO(context, sizeof(SHA256_CTX)); +} + +char *SHA256_End(SHA256_CTX* context, char buffer[]) { + sha2_byte digest[SHA256_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA256_CTX*)0); + + if (buffer != (char*)0) { + SHA256_Final(digest, context); + + for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(SHA256_CTX)); + } + MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH); + return buffer; +} + +char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) { + SHA256_CTX context; + + SHA256_Init(&context); + SHA256_Update(&context, data, len); + return SHA256_End(&context, digest); +} + + +/*** SHA-512: *********************************************************/ +void SHA512_Init(SHA512_CTX* context) { + if (context == (SHA512_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-512 round macros: */ +#if BYTE_ORDER == LITTLE_ENDIAN + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE64(*data++, W512[j]); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + W512[j]; \ + (d) += T1, \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ + j++ + + +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + (W512[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND512(a,b,c,d,e,f,g,h) \ + s0 = W512[(j+1)&0x0f]; \ + s0 = sigma0_512(s0); \ + s1 = W512[(j+14)&0x0f]; \ + s1 = sigma1_512(s1); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + ROUND512_0_TO_15(a,b,c,d,e,f,g,h); + ROUND512_0_TO_15(h,a,b,c,d,e,f,g); + ROUND512_0_TO_15(g,h,a,b,c,d,e,f); + ROUND512_0_TO_15(f,g,h,a,b,c,d,e); + ROUND512_0_TO_15(e,f,g,h,a,b,c,d); + ROUND512_0_TO_15(d,e,f,g,h,a,b,c); + ROUND512_0_TO_15(c,d,e,f,g,h,a,b); + ROUND512_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds up to 79: */ + do { + ROUND512(a,b,c,d,e,f,g,h); + ROUND512(h,a,b,c,d,e,f,g); + ROUND512(g,h,a,b,c,d,e,f); + ROUND512(f,g,h,a,b,c,d,e); + ROUND512(e,f,g,h,a,b,c,d); + ROUND512(d,e,f,g,h,a,b,c); + ROUND512(c,d,e,f,g,h,a,b); + ROUND512(b,c,d,e,f,g,h,a); + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + REVERSE64(*data++, W512[j]); + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* Apply the SHA-512 compression function to update a..h with copy */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0); + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + ADDINC128(context->bitcount, freespace << 3); + len -= freespace; + data += freespace; + SHA512_Transform(context, (sha2_word64*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + ADDINC128(context->bitcount, len << 3); + return; + } + } + while (len >= SHA512_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA512_Transform(context, (sha2_word64*)data); + ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); + len -= SHA512_BLOCK_LENGTH; + data += SHA512_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + ADDINC128(context->bitcount, len << 3); + } +} + +void SHA512_Last(SHA512_CTX* context) { + unsigned int usedspace; + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount[0],context->bitcount[0]); + REVERSE64(context->bitcount[1],context->bitcount[1]); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA512_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA512_Transform(context, (sha2_word64*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2); + } + } else { + /* Prepare for final transform: */ + MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits): */ + sha2_word64 *ptr = (sha2_word64*)(&context->buffer[SHA512_SHORT_BLOCK_LENGTH]); + *ptr = context->bitcount[1]; + ptr = (sha2_word64*)(&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8]); + *ptr = context->bitcount[0]; + + /* Final transform: */ + SHA512_Transform(context, (sha2_word64*)context->buffer); +} + +void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + SHA512_Last(context); + + /* Save the hash data for output: */ +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(SHA512_CTX)); +} + +char *SHA512_End(SHA512_CTX* context, char buffer[]) { + sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0); + + if (buffer != (char*)0) { + SHA512_Final(digest, context); + + for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(SHA512_CTX)); + } + MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH); + return buffer; +} + +char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) { + SHA512_CTX context; + + SHA512_Init(&context); + SHA512_Update(&context, data, len); + return SHA512_End(&context, digest); +} + + +/*** SHA-384: *********************************************************/ +void SHA384_Init(SHA384_CTX* context) { + if (context == (SHA384_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) { + SHA512_Update((SHA512_CTX*)context, data, len); +} + +void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != (SHA384_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + SHA512_Last((SHA512_CTX*)context); + + /* Save the hash data for output: */ +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 6; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(SHA384_CTX)); +} + +char *SHA384_End(SHA384_CTX* context, char buffer[]) { + sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA384_CTX*)0); + + if (buffer != (char*)0) { + SHA384_Final(digest, context); + + for (i = 0; i < SHA384_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(SHA384_CTX)); + } + MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH); + return buffer; +} + +char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) { + SHA384_CTX context; + + SHA384_Init(&context); + SHA384_Update(&context, data, len); + return SHA384_End(&context, digest); +} + diff --git a/src/sha2.h b/src/sha2.h new file mode 100755 index 0000000000000000000000000000000000000000..bf759ad45ba01030013d19832d4201a99e12dc8b --- /dev/null +++ b/src/sha2.h @@ -0,0 +1,197 @@ +/* + * FILE: sha2.h + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ + */ + +#ifndef __SHA2_H__ +#define __SHA2_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Import u_intXX_t size_t type definitions from system headers. You + * may need to change this, or define these things yourself in this + * file. + */ +#include <sys/types.h> + +#ifdef SHA2_USE_INTTYPES_H + +#include <inttypes.h> + +#endif /* SHA2_USE_INTTYPES_H */ + + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) + + +/*** SHA-256/384/512 Context Structures *******************************/ +/* NOTE: If your architecture does not define either u_intXX_t types or + * uintXX_t (from inttypes.h), you may need to define things by hand + * for your system: + */ +#if 0 +typedef unsigned char u_int8_t; /* 1-byte (8-bits) */ +typedef unsigned int u_int32_t; /* 4-bytes (32-bits) */ +typedef unsigned long long u_int64_t; /* 8-bytes (64-bits) */ +#endif +/* + * Most BSD systems already define u_intXX_t types, as does Linux. + * Some systems, however, like Compaq's Tru64 Unix instead can use + * uintXX_t types defined by very recent ANSI C standards and included + * in the file: + * + * #include <inttypes.h> + * + * If you choose to use <inttypes.h> then please define: + * + * #define SHA2_USE_INTTYPES_H + * + * Or on the command line during compile: + * + * cc -DSHA2_USE_INTTYPES_H ... + */ +#ifdef SHA2_USE_INTTYPES_H + +typedef struct _SHA256_CTX { + uint32_t state[8]; + uint64_t bitcount; + uint8_t buffer[SHA256_BLOCK_LENGTH]; +} SHA256_CTX; +typedef struct _SHA512_CTX { + uint64_t state[8]; + uint64_t bitcount[2]; + uint8_t buffer[SHA512_BLOCK_LENGTH]; +} SHA512_CTX; + +#else /* SHA2_USE_INTTYPES_H */ + +typedef struct _SHA256_CTX { + u_int32_t state[8]; + u_int64_t bitcount; + u_int8_t buffer[SHA256_BLOCK_LENGTH]; +} SHA256_CTX; +typedef struct _SHA512_CTX { + u_int64_t state[8]; + u_int64_t bitcount[2]; + u_int8_t buffer[SHA512_BLOCK_LENGTH]; +} SHA512_CTX; + +#endif /* SHA2_USE_INTTYPES_H */ + +typedef SHA512_CTX SHA384_CTX; + + +/*** SHA-256/384/512 Function Prototypes ******************************/ +#ifndef NOPROTO +#ifdef SHA2_USE_INTTYPES_H + +void SHA256_Init(SHA256_CTX *); +void SHA256_Update(SHA256_CTX*, const uint8_t*, size_t); +void SHA256_Final(uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*); +char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); +char* SHA256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); + +void SHA384_Init(SHA384_CTX*); +void SHA384_Update(SHA384_CTX*, const uint8_t*, size_t); +void SHA384_Final(uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*); +char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); +char* SHA384_Data(const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]); + +void SHA512_Init(SHA512_CTX*); +void SHA512_Update(SHA512_CTX*, const uint8_t*, size_t); +void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); +char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); +char* SHA512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); + +#else /* SHA2_USE_INTTYPES_H */ + +void SHA256_Init(SHA256_CTX *); +void SHA256_Update(SHA256_CTX*, const u_int8_t*, size_t); +void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*); +char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); +char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); + +void SHA384_Init(SHA384_CTX*); +void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t); +void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*); +char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); +char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]); + +void SHA512_Init(SHA512_CTX*); +void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t); +void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); +char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); +char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); + +#endif /* SHA2_USE_INTTYPES_H */ + +#else /* NOPROTO */ + +void SHA256_Init(); +void SHA256_Update(); +void SHA256_Final(); +char* SHA256_End(); +char* SHA256_Data(); + +void SHA384_Init(); +void SHA384_Update(); +void SHA384_Final(); +char* SHA384_End(); +char* SHA384_Data(); + +void SHA512_Init(); +void SHA512_Update(); +void SHA512_Final(); +char* SHA512_End(); +char* SHA512_Data(); + +#endif /* NOPROTO */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SHA2_H__ */ + diff --git a/src/threadSOG.cpp b/src/threadSOG.cpp index 847cf0bb681b2c79422e47291506c82a5116458e..b06eda55111b7276c0af65e8b516146b31a44a97 100644 --- a/src/threadSOG.cpp +++ b/src/threadSOG.cpp @@ -5,19 +5,16 @@ //#define DEBUG_GC #include "threadSOG.h" -#include "sylvan.h" -#include "sylvan_seq.h" -#include <sylvan_sog.h> -#include <sylvan_int.h> -using namespace sylvan; + +/* void write_to_dot(const char *ch,MDD m) { FILE *fp=fopen(ch,"w"); lddmc_fprintdot(fp,m); fclose(fp); -} +}*/ /*************************************************/ @@ -29,23 +26,14 @@ void write_to_dot(const char *ch,MDD m) threadSOG::threadSOG(const NewNet &R, int nbThread,bool uselace,bool init) { m_nb_thread=nbThread; - if (uselace) { - lace_init(m_nb_thread, 10000000); - } - else lace_init(1, 0); - lace_startup(0, NULL, NULL); - - // Simple Sylvan initialization, also initialize MDD support - //sylvan_set_sizes(1LL<<27, 1LL<<27, 1LL<<20, 1LL<<22); - sylvan_set_limits(16LL<<30, 8, 0); - - //sylvan_set_limits(2LL<<30, 16, 3); - //sylvan_set_sizes(1LL<<30, 2LL<<20, 1LL<<18, 1LL<<20); - //sylvan_init_bdd(1); - sylvan_init_package(); - sylvan_init_ldd(); - LACE_ME; - displayMDDTableInfo(); + uselace=uselace; + SylvanWrapper::sylvan_set_limits ( 16LL<<30, 8, 0 ); + + //sylvan_init_package(); + SylvanWrapper::sylvan_init_package(); + SylvanWrapper::sylvan_init_ldd(); + SylvanWrapper::init_gc_seq(); + SylvanWrapper::displayMDDTableInfo(); /*sylvan_gc_hook_pregc(TASK(gc_start)); sylvan_gc_hook_postgc(TASK(gc_end)); sylvan_gc_enable();*/ @@ -56,7 +44,7 @@ threadSOG::threadSOG(const NewNet &R, int nbThread,bool uselace,bool init) vector<Place>::const_iterator it_places; - init_gc_seq(); + //_______________ @@ -65,12 +53,12 @@ threadSOG::threadSOG(const NewNet &R, int nbThread,bool uselace,bool init) m_place_proposition=R.m_formula_place; m_nonObservable=R.NonObservable; - m_transitionName=R.transitionName; - m_placeName=R.m_placePosName; + m_transitionName=&R.transitionName; + m_placeName=&R.m_placePosName; - /* cout<<"Toutes les Transitions:"<<endl; - map<string,uint16_t>::iterator it2=m_transitionName.begin(); - for (;it2!=m_transitionName.end();it2++) { + cout<<"Toutes les Transitions:"<<endl; + map<string,uint16_t>::iterator it2=m_transitionName->begin(); + for (;it2!=m_transitionName->end();it2++) { cout<<(*it2).first<<" : "<<(*it2).second<<endl;} @@ -78,7 +66,7 @@ threadSOG::threadSOG(const NewNet &R, int nbThread,bool uselace,bool init) cout<<"Transitions observables :"<<endl; Set::iterator it=m_observable.begin(); for (;it!=m_observable.end();it++) {cout<<*it<<" ";} - cout<<endl;*/ + cout<<endl; InterfaceTrans=R.InterfaceTrans; m_nbPlaces=R.places.size(); cout<<"Nombre de places : "<<m_nbPlaces<<endl; @@ -90,7 +78,7 @@ threadSOG::threadSOG(const NewNet &R, int nbThread,bool uselace,bool init) liste_marques[i] =it_places->marking; } - m_initialMarking=lddmc_cube(liste_marques,R.places.size()); + m_initialMarking=SylvanWrapper::lddmc_cube(liste_marques,R.places.size()); uint32_t *prec = new uint32_t[m_nbPlaces]; uint32_t *postc= new uint32_t [m_nbPlaces]; @@ -126,10 +114,10 @@ threadSOG::threadSOG(const NewNet &R, int nbThread,bool uselace,bool init) Precond = Precond & ((*it) >= prec[*it]); } - MDD _minus=lddmc_cube(prec,m_nbPlaces); - ldd_refs_push(_minus); - MDD _plus=lddmc_cube(postc,m_nbPlaces); - ldd_refs_push(_plus); + MDD _minus=SylvanWrapper::lddmc_cube(prec,m_nbPlaces); + //#ldd_refs_push(_minus); + MDD _plus=SylvanWrapper::lddmc_cube(postc,m_nbPlaces); + //#ldd_refs_push(_plus); m_tb_relation.push_back(TransSylvan(_minus,_plus)); } @@ -190,14 +178,14 @@ void threadSOG::computeSeqSOG(LDDGraph &g) c->m_lddstate=Complete_meta_state; //TabMeta[m_nbmetastate]=c->m_lddstate; m_nbmetastate++; - old_size=lddmc_nodecount(c->m_lddstate); + //max_meta_state_size=bdd_pathcount(Complete_meta_state); st.push(Pair(couple(c,Complete_meta_state),fire)); g.setInitialState(c); g.insert(c); //LACE_ME; - g.m_nbMarking+=lddmc_nodecount(c->m_lddstate); + g.m_nbMarking+=SylvanWrapper::lddmc_nodecount(c->m_lddstate); do { m_NbIt++; @@ -216,7 +204,7 @@ void threadSOG::computeSeqSOG(LDDGraph &g) MDD Complete_meta_state=Accessible_epsilon(get_successor(e.first.second,t)); //MDD reduced_meta=Canonize(Complete_meta_state,0); - ldd_refs_push(Complete_meta_state); + //#ldd_refs_push(Complete_meta_state); //ldd_refs_push(reduced_meta); //sylvan_gc_seq(); @@ -301,7 +289,7 @@ void * threadSOG::doCompute() // cout<<bddtable<<M0<<endl; MDD Complete_meta_state(Accessible_epsilon(m_initialMarking)); - ldd_refs_push(Complete_meta_state); + //#ldd_refs_push(Complete_meta_state); // MDD canonised_initial=Canonize(Complete_meta_state,0); //ldd_refs_push(canonised_initial); fire=firable_obs(Complete_meta_state); @@ -309,7 +297,7 @@ void * threadSOG::doCompute() c->m_lddstate=Complete_meta_state; //m_TabMeta[m_nbmetastate]=c->m_lddstate; m_nbmetastate++; - m_old_size=lddmc_nodecount(c->m_lddstate); + m_old_size=SylvanWrapper::lddmc_nodecount(c->m_lddstate); //max_meta_state_size=bdd_pathcount(Complete_meta_state); m_st[0].push(Pair(couple(c,Complete_meta_state),fire)); @@ -356,7 +344,7 @@ void * threadSOG::doCompute() MDD Complete_meta_state=Accessible_epsilon(get_successor(e.first.second,t)); - ldd_refs_push(Complete_meta_state); + //#ldd_refs_push(Complete_meta_state); //MDD reduced_meta=Canonize(Complete_meta_state,0); //ldd_refs_push(reduced_meta); @@ -367,7 +355,7 @@ void * threadSOG::doCompute() // #ifdef DEBUG_GC // displayMDDTableInfo(); // #endif // DEBUG_GC - sylvan_gc_seq(); + //# sylvan_gc_seq(); // #ifdef DEBUG_GC // displayMDDTableInfo(); // #endif // DEBUG_GC @@ -463,16 +451,16 @@ void * threadSOG::doComputeCanonized() // cout<<bddtable<<M0<<endl; MDD Complete_meta_state(Accessible_epsilon(m_initialMarking)); - ldd_refs_push(Complete_meta_state); + //#ldd_refs_push(Complete_meta_state); MDD canonised_initial=Canonize(Complete_meta_state,0); - ldd_refs_push(canonised_initial); + //#ldd_refs_push(canonised_initial); fire=firable_obs(Complete_meta_state); c->m_lddstate=canonised_initial; //m_TabMeta[m_nbmetastate]=c->m_lddstate; m_nbmetastate++; - m_old_size=lddmc_nodecount(c->m_lddstate); + m_old_size=SylvanWrapper::lddmc_nodecount(c->m_lddstate); //max_meta_state_size=bdd_pathcount(Complete_meta_state); m_st[0].push(Pair(couple(c,Complete_meta_state),fire)); @@ -521,10 +509,10 @@ void * threadSOG::doComputeCanonized() MDD Complete_meta_state=Accessible_epsilon(get_successor(e.first.second,t)); - ldd_refs_push(Complete_meta_state); + //#ldd_refs_push(Complete_meta_state); MDD reduced_meta=Canonize(Complete_meta_state,0); - ldd_refs_push(reduced_meta); + //#ldd_refs_push(reduced_meta); if (id_thread==0) { @@ -532,7 +520,7 @@ void * threadSOG::doComputeCanonized() // #ifdef DEBUG_GC // displayMDDTableInfo(); // #endif // DEBUG_GC - sylvan_gc_seq(); + //# sylvan_gc_seq(); // #ifdef DEBUG_GC // displayMDDTableInfo(); // #endif // DEBUG_GC @@ -619,8 +607,8 @@ void threadSOG::computeDSOG(LDDGraph &g,bool canonised) cout << "number of threads "<<m_nb_thread<<endl; int rc; m_graph=&g; - m_graph->setTransition(m_transitionName); - m_graph->setPlace(m_placeName); + m_graph->setTransition(*m_transitionName); + m_graph->setPlace(*m_placeName); m_id_thread=0; pthread_mutex_init(&m_mutex, NULL); @@ -701,7 +689,7 @@ threadSOG::~threadSOG() /******************* Functions computing SOG with Lace *****************/ /***** Saturation with Lace *********/ - +/* TASK_3 (MDD, ImageForwardLace,MDD, From, Set* , NonObservable, vector<TransSylvan>*, tb_relation) { MDD Res=lddmc_false; @@ -762,14 +750,15 @@ TASK_3 (MDD, Accessible_epsilon_lace, MDD, From, Set*, nonObservable, vector<Tra return M2; } - +*/ /********************* Compute SOG with lace *********************************************/ +/* void threadSOG::computeSOGLace(LDDGraph &g) { clock_gettime(CLOCK_REALTIME, &start); Set fire; m_graph=&g; - m_graph->setTransition(m_transitionName); + m_graph->setTransition(*m_transitionName); m_graph->setPlace(m_placeName); m_nbmetastate=0; m_MaxIntBdd=0; @@ -850,16 +839,16 @@ void threadSOG::computeSOGLace(LDDGraph &g) tps = (finish.tv_sec - start.tv_sec); tps += (finish.tv_nsec - start.tv_nsec) / 1000000000.0; std::cout << "TIME OF CONSTRUCTION OF THE SOG " << tps << " seconds\n"; -} +}*/ /********************* Compute canonized SOG with lace *********************************************/ /******************************Canonizer with lace framework **********************************/ -TASK_DECL_3(MDD, lddmc_canonize,MDD, unsigned int, threadSOG *) -#define lddmc_canonize(s,level,ds) CALL(lddmc_canonize, s, level,ds) - +/*TASK_DECL_3(MDD, lddmc_canonize,MDD, unsigned int, threadSOG *) +#define lddmc_canonize(s,level,ds) CALL(lddmc_canonize, s, level,ds)*/ +/* TASK_IMPL_3(MDD, lddmc_canonize,MDD, s,unsigned int, level, threadSOG * ,ds) { @@ -934,7 +923,7 @@ TASK_IMPL_3(MDD, lddmc_canonize,MDD, s,unsigned int, level, threadSOG * ,ds) if (isSingleMDD(s1)) { /*lddmc_refs_spawn(SPAWN(lddmc_canonize,s0,level,ds)); Repr=lddmc_refs_sync(SYNC(lddmc_canonize));*/ - Repr=CALL(lddmc_canonize,s0,level,ds); +/* Repr=CALL(lddmc_canonize,s0,level,ds); Repr=lddmc_union(Repr,s1); } else { @@ -1045,7 +1034,7 @@ void threadSOG::computeSOGLaceCanonized(LDDGraph &g) tps = (finish.tv_sec - start.tv_sec); tps += (finish.tv_nsec - start.tv_nsec) / 1000000000.0; std::cout << "TIME OF CONSTRUCTION OF THE SOG " << tps << " seconds\n"; -} +}*/ diff --git a/third-party/sylvan b/third-party/sylvan deleted file mode 160000 index 035a0aca68ec77dbfe8b48ed8c58c3ebf8a469bb..0000000000000000000000000000000000000000 --- a/third-party/sylvan +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 035a0aca68ec77dbfe8b48ed8c58c3ebf8a469bb