From dd3f21e9242981e0bbfc95f4f8fc2aa8f90f3d9a Mon Sep 17 00:00:00 2001
From: Marius Bozga <Marius.Bozga@univ-grenoble-alpes.fr>
Date: Mon, 31 Jan 2022 09:46:06 +0100
Subject: [PATCH] refactor dfs loop

---
 src/simulator-t/explorator.C | 138 +++++++++++++++++++----------------
 src/simulator-t/explorator.h |   8 +-
 src/simulator/label.C        |   8 ++
 src/simulator/label.h        |   1 +
 4 files changed, 91 insertions(+), 64 deletions(-)

diff --git a/src/simulator-t/explorator.C b/src/simulator-t/explorator.C
index 378e9b4..78d7329 100644
--- a/src/simulator-t/explorator.C
+++ b/src/simulator-t/explorator.C
@@ -442,9 +442,9 @@ void IfDfsExplorator::run(IfConfig* start) {
   tt->tail = NULL;
   tt->pending = NULL;
   tt->label = NULL;
-  tt->cnt_env = 0;
   tt->state = start ? start : m_engine->start();
   tt->state->setMark((q_count++) | REACHED | STACKED);
+  tt->feeds = 0;
 
   dfs.depth++;
   dfs.stack = tt;
@@ -457,15 +457,8 @@ void IfDfsExplorator::run(IfConfig* start) {
     st = dfs.stack;
     su = st->pending;
 
-    if (su != NULL) {      
-      int from_env = 0;
-      if(opt_limit_env >= 0) 
-          for(int ec = su->label->getLength()-1; ec>=0;ec--)
-              if(su->label->getAt(ec)->getKind() == IfEvent::FEED) {
-                  from_env++;
-              }
-if(opt_limit_env == -1 || st->cnt_env + from_env <= opt_limit_env)
-{
+    if (su != NULL) {
+
       if (! (su->state->getMark() & REACHED)) {
         tt = new Stack;
         tt->tail = st;
@@ -473,53 +466,36 @@ if(opt_limit_env == -1 || st->cnt_env + from_env <= opt_limit_env)
         tt->state = su->state;
         tt->label = su->label->copy();
         tt->state->setMark((q_count++) | REACHED | STACKED);
-        tt->cnt_env = st->cnt_env + from_env;
+        tt->feeds = st->feeds + su->label->count(IfEvent::FEED);
         
         dfs.depth++;
         dfs.stack = tt;
-try {
-        m_engine->run(tt->state);
-} catch(IfDynamicError d) {
-        // catch Instance Addressing Faults 
-        std::ofstream file("dump.scn");
-        file << "<scenario>";
-        printStackScn(file);
-        file << "</scenario>";
-        file.close();     
-        exit(1);
-}
+        
+        try {
+          m_engine->run(tt->state);
+        } catch(IfDynamicError d) { // instance addressing fault
+          printScn("dump.scn");
+          exit(1);
+        }
+        
         if (m_flags & PO) restrict();
-
-        if (m_flags & FB) {
-          int bCnt = 0;
-          for(Successor* fbs = dfs.stack->pending; fbs != NULL; fbs = fbs->next) bCnt++;
-          if(bCnt >= FIND_BRANCH_MIN) {
-                cout << "-- More than " << FIND_BRANCH_MIN << " dependent branches found in state. Scenario saved in fb.scn.\n";
-                cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n";
-                for(Successor* fbs = dfs.stack->pending; fbs != NULL; fbs = fbs->next) {
-                        cout << "-----------------------\n";
-                        fbs->label->printXML(cout);
-                }
-                cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n";
-                std::ofstream file("fb.scn");
-                file << "<scenario>";
-                printStackScn(file);
-                file << "</scenario>";
-                file.close(); 
-                m_flags &= ~FB;
-          }
+        
+        if (m_flags & FB && length(dfs.stack->pending) >= FIND_BRANCH_MIN) {
+          dumpBranches();
+          m_flags &= ~FB;
         }
-
+        
+        if (opt_limit_env != -1) restrictFeeds();
+        
         visit(tt->state);
       }
       
       visit(st->state, su->label, su->state);
-} 
+      t_count++;
+      
       st->pending = su->next;
       delete su->label;
       delete su;
-
-      t_count++;
     }
     
     else {
@@ -587,6 +563,26 @@ void IfDfsExplorator::restrict() {
   }
 }
 
+void IfDfsExplorator::restrictFeeds() {
+  if (opt_limit_env < 0)
+    return;
+
+  // remove successors exceeding the number of allowed feeds ...
+  Successor* su = dfs.stack->pending, *st;
+  dfs.stack->pending = NULL;
+  for(; su != NULL; su = st) {
+    st = su->next;
+    if (dfs.stack->feeds + su->label->count(IfEvent::FEED) <= opt_limit_env) {
+      su->next = dfs.stack->pending;
+      dfs.stack->pending = su;
+    }
+    else {
+      delete su->label;
+      delete su;
+    }
+  }
+}
+
 void IfDfsExplorator::status() const {
   IfExplorator::status();
 #ifndef win32native
@@ -604,32 +600,50 @@ void IfDfsExplorator::visit(const IfConfig* source) {
 
   IfExplorator::visit(source);
 
-  if(opt_limit_scn > 0 && (errorScnCnt+successScnCnt)>=opt_limit_scn) 
+  if (opt_limit_scn > 0 && (errorScnCnt+successScnCnt)>=opt_limit_scn) 
     return;
 
   if (((m_flags & MS) && source->isObsSuccess()) ||
-       ((m_flags & ME) && source->isObsError())) {
+      ((m_flags & ME) && source->isObsError())) {
     char fileName[64];
-
-    if ( source->isObsSuccess() ) sprintf(fileName, "s%d.scn", ++successScnCnt);
-    if ( source->isObsError() ) sprintf(fileName, "e%d.scn", ++errorScnCnt);
-
-    std::ofstream file(fileName);
-    file << "<scenario>";
-    printStackScn(file);
-    file << "</scenario>";
-    file.close();
+    if (source->isObsSuccess()) sprintf(fileName, "s%d.scn", ++successScnCnt);
+    if (source->isObsError()) sprintf(fileName, "e%d.scn", ++errorScnCnt);
+    printScn(fileName);
   }
 }
 
-void IfDfsExplorator::printStackScn(std::ostream &out, Stack* left) {
-  if(left == NULL) left = dfs.stack;
-  if(left == NULL) return;
-  if(left->tail && left->tail->label)
-    printStackScn(out, left->tail);
-  if(left->label) {
+void IfDfsExplorator::printScn(const char* filename) const {
+  std::ofstream file(filename);
+  file << "<scenario>";
+  printStackRec(file, dfs.stack);
+  file << "</scenario>";
+  file.close();
+}
+
+void IfDfsExplorator::printStackRec(std::ostream &out, const Stack* left) const {
+  if (left == NULL) return;
+  if (left->tail && left->tail->label)
+    printStackRec(out, left->tail);
+  if (left->label)
     left->label->printXML(out);
+}
+
+void IfDfsExplorator::dumpBranches() const {
+  cout << "-- More than " << FIND_BRANCH_MIN << " dependent branches found in state. Scenario saved in fb.scn.\n";
+  cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n";
+  for(Successor* fbs = dfs.stack->pending; fbs != NULL; fbs = fbs->next) {
+    cout << "-----------------------\n";
+    fbs->label->printXML(cout);
   }
+  cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n";
+  printScn("fb.scn");
+}
+
+unsigned IfDfsExplorator::length(const Successor* list) const {
+  unsigned count = 0;
+  for(Successor* su = (Successor*) list; su != NULL; su = su->next)
+    count++;
+  return count;
 }
 
 /*
diff --git a/src/simulator-t/explorator.h b/src/simulator-t/explorator.h
index 0eadd2e..5ddeb3f 100644
--- a/src/simulator-t/explorator.h
+++ b/src/simulator-t/explorator.h
@@ -168,6 +168,7 @@ class IfDfsExplorator : public IfExplorator {
 
   unsigned m_ind_flags;
   void restrict(); // partial order reduction
+  void restrictFeeds(); // feeds limit reduction
   
   virtual void visit(const IfConfig* source);
   virtual void visit(const IfConfig* source, const IfLabel* label, const IfConfig* target) // C++ bug
@@ -181,11 +182,11 @@ class IfDfsExplorator : public IfExplorator {
   };
   
   struct Stack {
+    unsigned feeds;
     IfConfig* state;
     IfLabel* label;
     Successor* pending;
     Stack* tail;
-    int cnt_env;
   };
 
  protected:
@@ -195,7 +196,10 @@ class IfDfsExplorator : public IfExplorator {
   } dfs;
 
  private:
-  virtual void printStackScn(std::ostream& file, Stack* left = NULL);
+  void printScn(const char*) const;
+  void printStackRec(std::ostream&, const Stack*) const;
+  void dumpBranches() const;
+  unsigned length(const Successor*) const;
 
 };
 
diff --git a/src/simulator/label.C b/src/simulator/label.C
index 42cc3a2..8402039 100644
--- a/src/simulator/label.C
+++ b/src/simulator/label.C
@@ -298,6 +298,14 @@ void IfLabel::strip(int (*Visible)(const IfEvent*)) {
   setAt(k++, NULL);
 }
 
+unsigned IfLabel::count(const IfEvent::Kind kind) const {
+  int k = 0;
+  for(int i = 0; getAt(i); i++)
+    if (getAt(i)->getKind() == kind)
+      k++;
+  return k;
+}
+
 int IfLabel::compare(const IfLabel* label) const {
   return m_events.compare(&label->m_events);
 }
diff --git a/src/simulator/label.h b/src/simulator/label.h
index bdb2727..c0c2730 100644
--- a/src/simulator/label.h
+++ b/src/simulator/label.h
@@ -216,6 +216,7 @@ class IfLabel : public IfObject {
 
  public:
   void strip(int (*Visible)(const IfEvent*));
+  unsigned count(const IfEvent::Kind) const;
 
  public:
   DECLARE_STORABLE(IfLabel);
-- 
GitLab