/*
 * master.c
 * Main module. Loops over all connections and processes them.
 * [eichin:19880309.1200EST]
 */

#include <msimdecl.h>


Time globaltime;
ropeptr nextfree;
int debug=0;

/*
 * There are alternate implementations here:
 * 	1. scan the list once, find the mininum time, and jump back to
 * 	it. This is an O(#wires) search every tick.
 * 	2. maintain a linked list of events; this is O(#wires/2)
 * 	search for new events to insert on every change. This is
 * 	worse, and harder to debug.
 */

enum { DONE=0, MOREWIRES } run_once(allwires)
     Wirelist allwires;
{
  /*
   * The main loop of the system simply iterates over the list of
   * wires, simulating the next ``time''.
   */
#define LOWTIME 0
  Wirelist wires = allwires;	/* so it is saved for p_file... */
  WFileptr savfile = NULL;
  Wire savwire = NULL;
  Time savtime = LOWTIME;
  
  START(wires);

  while(wires->tag.CTL != END)
    {
      switch(wires->tag.WIRELIST)
	{
	case WIRE:
	  {
	    Wire tmpwire, t2wire;
	    Timeline tmpline;
	    Event_data savevent;

	    t2wire = tmpwire = wires->data.WIRELIST.wire;

	    START(tmpwire);
	    
	    find_item(tmpwire, WIRE, THEN);

	    tmpline = tmpwire->data.WIRE.then;
		    
	    /*
	     * all we REALLY want to keep is the wire. event
	     * is time. Also, only do this if there IS a
	     * future...
	     */
	    if(tmpline->tag.CTL != END)
	      {
		savevent = tmpline->data.EVENT;
		if((LOWTIME == savtime) || (savtime > savevent))
		  {
		    savwire = t2wire;
		    savtime = savevent;
		    break;	/* we got one now, skip out */
		  }
	      }
	  }
	  break;
	case WFILE:
	  {
	    savfile = wires->data.WIRELIST.wfile;
	  }
	  break;
	default:
	  break;
	}
      INC(wires);
    }
  if ( savfile && savfile->next && (!savtime || (savfile->next < savtime)) )
    {
      /* the file is the next tick */
      process_file(savfile, allwires);
    }
  else if (savtime)
    {
      /* There WAS a valid tick */
      globaltime = savtime;
      process_event(savwire);
    }
  else
    {
      /* NOTHING happened! */
      return(DONE);
    }
  return(MOREWIRES);
}

run_all(wires)
     Wirelist wires;
{
  while(run_once(wires))
    {
      if (debug) printf("Clock = %10d\n", globaltime);
    }
  if (debug) printf("Clock = %10d\n", globaltime);
  if (debug) disp_wirelist(wires);
}
     
init_run()
{
  globaltime = 0;
  nextfree = NULL;
  return(0);
}
