/*! \file sc.c 
 *
 * Main file for using SyncChart C macros
 *
 * See README.txt for general information.
 * See LICENSE.txt for licensing information.
 * For further information, see
 * http://www.informatik.uni-kiel.de/rtsys/sc/ .
 *
 * @author Reinhard v. Hanxleden,
 * rvh@informatik.uni-kiel.de
 */

#include "sc.h"


// ===================================================================
//! Computing the id of next thread to be dispatched.
/*! Uses obvious algorithm, run time linear in position of highest bit.
 * Note that there are also alternatives that run logarithmic to bit vector size.
 * See eg http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog .
 * Which is actually faster depends on application.
 */
void selectCid() {
  int act;
  
  _cid = 0;
  for (act = active; act > 1; act >>= 1)
    _cid++;
}


// ===================================================================
//! Tracing routines
void vec2names(char *prefix, char* suffix, bitvector ids, const char *names[])
{
#ifdef mytrace 
  int id = 0;
  int first = 1;
 
  printf("%s", prefix);
  while (ids) {
    if (ids & 1) {
      if (first) {
	first = 0;
      } else {
	printf(", ");
      }
      printf(" %d/", id);
      if (names) {
	printf("%s", names[id]);
	printVal(id);
      } else {
	printf("%s", state[id]);
      }
    }
    ids >>= 1;
    id++;
  }

  if (first) {
    printf("<init>");
  }
  printf("%s", suffix);
#endif
}



// ===================================================================
//! The main program
/*! Returns 0 iff outputs generated by program match reference trace
 */
int main()
{
  int runInstrCnt;          // Instructions in one run
  int runsInstrCnt = 0;     // Instructions accumulated over all runs
  int outputsOK = 1;        // Outputs of simulation correct?
  int notDone;              // Current run not done yet?
  int init;                 // Is initial tick?
  signalvector tickInputs;  // Input values for a tick
  signalvector tickOutputs; // Reference output values for a tick
  signalvector tickSignals; // Reference signal values for a tick

  // Execute all runs
  for (runCnt = 0; (runCnt < runMax) && outputsOK; runCnt++) {
    printf("#### RUN %d STARTS ##################################\n",	
	   runCnt);

    runInstrCnt = 0;
    tickCnt = 0;
    init = 1;
    enabled = 0;

    do {                                   // Execute all ticks of one run
      tickInstrCnt = 0;
      getInputs();
      tickInputs = signals;
      
      trace3("==== TICK %d STARTS, inputs = 0%o, enabled = 0%o\n",
	     tickCnt, tickInputs, enabled);
      vec2names("==== Inputs (id/name): ", "\n", tickInputs, s2signame);
      vec2names("==== Enabled (id/state): ", "\n", enabled, 0);

      notDone = tick(init);  // Call automaton function
      init = 0;
      
      runInstrCnt += tickInstrCnt;
      trace2("==== TICK %d terminates after %d instructions.\n",
	     tickCnt, tickInstrCnt);
      vec2names("==== Enabled (id/state): ", "\n", enabled, 0);
      vec2names("==== Resulting signals (name/id): ", "", signals, s2signame);
      outputsOK = checkOutputs(&tickOutputs);
      if (outputsOK) {
	tickSignals = tickInputs | tickOutputs;
	if (signals == tickSignals) {
	  trace0(", Outputs OK.\n\n");
	} else {
	  vec2names(", Outputs NOT OK - expected signals ", "!!\n\n",
		 tickSignals, s2signame);
	  outputsOK = 0;
	}
      } else {
	notDone = 0;
      }

      tickCnt++;
      if (tickCnt >= tickMax) {
	printf("==== Executed tickMax = %d ticks, terminate.\n", tickMax);
	notDone = 0;
      }

    } while (notDone && outputsOK);
    
    printf("#### RUN %d terminates after %d instructions\n\n",
	   runCnt, runInstrCnt);					
    runsInstrCnt += runInstrCnt;
  };
  
  printf("#### All runs terminate, after %d instructions\n\n", runsInstrCnt);					
  return !outputsOK;
}
