/* SCCS @(#)NslMultiClockScheduler.java 1.27 -- 09/20/99 -- 19:18:37 */ // Copyright: Copyright (c) 1997 University of Southern California Brain Project. // Copyright: This software may be freely copied provided the toplevel // Copyright: COPYRIGHT file is included with each such copy. // Copyright: Email nsl@java.usc.edu. // // NslMultiClockScheduler.java // ////////////////////////////////////////////////////////////////////// /** * NslMultiClockScheduler - a multi-clocked scheduler. In NslMultiClockScheduler, each module can have its run_step_size, or each has different run time interval. In the currnt implementation, the run_step_size must be set by nslSetRunDelta in makeinst in NslModule. Otherwise, the module will have system default time step and in order to activate this parameter, the whole model has to be removed from the scheduler and re-initialize. The run step size of each module should be the maximum possible step size without making chaotic behaviour in the model. Run step size of modules without execution part, like top-level modules, should be 0. This could improve the performance of simulation * @see NslModule#nslSetRunDelta, NslModule#nslGetRunDelta */ package nslj.src.system; import nslj.src.lang.NslModule; import nslj.src.lang.NslClass; import nslj.src.display.*; import java.lang.*; import java.util.Vector; import java.util.Enumeration; public class NslMultiClockScheduler extends NslScheduler { NslSystem system; Vector clockRunList; // a list of vectors, in which contains // modules with a same run time step size Vector clockTrainList; // a list of vectors, in which contains // modules with a same train time step size // it keep checking the minimum run step size in the module. // it is used to warn the system the possibility that the // system run step size is larger than the required run step // size. double _min_step_size=Double.MAX_VALUE; double epsilon; int endModules; boolean firstEpoch; boolean stepEpoch; //boolean startingScheduler; public NslMultiClockScheduler(NslSystem sys) { system = sys; notFinished = true; stepEpoch = firstEpoch = false; cycleSuspended = epochSuspended = moduleSuspended = true; } public void createRunListRecursive(NslModule module) { Vector moduleChildren = module.nslGetModuleChildrenVector(); addModuleToClockRunList(module); Enumeration e = moduleChildren.elements(); while(e.hasMoreElements()) { createRunListRecursive((NslModule)e.nextElement()); } } public void createTrainListRecursive(NslModule module) { Vector moduleChildren = module.nslGetModuleChildrenVector(); addModuleToClockTrainList(module); Enumeration e = moduleChildren.elements(); while(e.hasMoreElements()) { createTrainListRecursive((NslModule)e.nextElement()); } } public void getNumModulesRecursive(NslModule module) { Vector moduleChildren = module.nslGetModuleChildrenVector(); numModules++; //System.err.println(""+numModules+".-"+module.nslGetName()); Enumeration e = moduleChildren.elements(); while(e.hasMoreElements()) { getNumModulesRecursive((NslModule)e.nextElement()); } } public int getNumModules() { numModules = 0; getNumModulesRecursive(system.nslGetModelRef()); return numModules; } public void createSchedulerRunList() { clockRunList = new Vector(10,10); createRunListRecursive(system.nslGetModelRef()); } public void createSchedulerTrainList() { clockTrainList = new Vector(10,10); createTrainListRecursive(system.nslGetModelRef()); } /** * Add module into the scheduler. * If there exists a list of * modules with the same run step size as the object module, * the module will be added to the corresponding list. * Otherwise, a list of module with that run step size will be created. * There is no maximum number of those lists, but keeping it * minimal can significantly speed up the simulation. * @param module - module to be added. * */ public void addModuleToClockRunList(NslModule module) { if(module==null) throw new NullPointerException(); //numModules++; Enumeration E = clockRunList.elements(); NslClockSchedulerModuleVector V; double stepsize = module.nslGetRunDelta(); while (E.hasMoreElements()) { V = (NslClockSchedulerModuleVector)E.nextElement(); if (V.nslGetRunDelta() == stepsize) { V.addElement(module); return; } } // no module vector or step size is new if (stepsize > 0 && stepsize < _min_step_size) { _min_step_size = stepsize; system.nslSetRunDelta(stepsize); } V = new NslClockSchedulerModuleVector(stepsize); V.addElement(module); clockRunList.addElement(V); return; } public void addModuleToClockTrainList(NslModule module) { if(module==null) throw new NullPointerException(); //numModules++; Enumeration E = clockTrainList.elements(); NslTrainClockSchedulerModuleVector V; double stepsize = module.nslGetTrainDelta(); while (E.hasMoreElements()) { V = (NslTrainClockSchedulerModuleVector)E.nextElement(); if (V.nslGetTrainDelta() == stepsize) { V.addElement(module); return; } } // no module vector or step size is new if (stepsize > 0 && stepsize < _min_step_size) { _min_step_size = stepsize; system.nslSetTrainDelta(stepsize); } V = new NslTrainClockSchedulerModuleVector(stepsize); V.addElement(module); clockTrainList.addElement(V); return; } public void checkSystemStatus() { if (schedulerMode=='R' && system._runDeltaChanged) { createSchedulerRunList(); epsilon = system.nslGetDelta()/2; system._runDeltaChanged=false; } else if (schedulerMode=='T' && system._trainDeltaChanged) { createSchedulerTrainList(); epsilon = system.nslGetDelta()/2; system._trainDeltaChanged=false; } } /** * Run the active modules until time time * in the basic step size specified in NslSystem * The modules registered in the scheduler will run * with an interval specified by the run step size. */ public void run() { double endTime; int endEpochs; NslDisplaySystemVector dsv = system.display_system_list; // scheduler //System.err.println("Starting Scheduler"); //System.err.println("initModule"); initModule(); contEndTime = actualEndTime = endTime = system.getEndTime(); contNumEpochs = actualNumEpochs = endEpochs = system.getEpochs(); contNumModules = actualNumModules = endModules = getNumModules(); while (notFinished) { try { //System.err.println("Cleaning variables"); //system.initAll(); //System.err.println("Wating for commands"); schedulerState = 'W'; synchronized (this) { while (epochSuspended || cycleSuspended || moduleSuspended || system.getEndTime() == 0.0) { wait(); if (system.getEndTime() == 0.0) { system.continueCmd(); } } //if (startingScheduler) { //contEndTime = actualEndTime = endTime = system.getEndTime(); //contNumEpochs = actualNumEpochs = endEpochs = system.getEpochs(); //contNumModules = actualNumModules = endModules = getNumModules(); //} else { //if (actualNumModules==endModules) { // actualNumModules = endModules = getNumModules(); //} else if (actualNumModulesmodule and its child modules * recursively. * @param module */ public void initTrainRecursively(NslModule module) { Vector moduleChildren = module.nslGetModuleChildrenVector(); Enumeration e = moduleChildren.elements(); if ((system.schedulerMethod.equals("pre"))|| (system.schedulerMethod.equals("mixed"))) { //module.nslInitTempTrain(); module.initTrain(); while (e.hasMoreElements()) { initTrainRecursively((NslModule)e.nextElement()); } } else if (system.schedulerMethod.equals("post")) { while (e.hasMoreElements()) { initTrainRecursively((NslModule)e.nextElement()); } module.nslInitTempTrain(); module.initTrain(); } } public void trainOneCycle() { double curtime = system.getCurTime(); Enumeration f, e = clockTrainList.elements(); NslModule module; NslTrainClockSchedulerModuleVector v; curNumModules = 0; while (e.hasMoreElements() && curNumModules < endModules) { v = (NslTrainClockSchedulerModuleVector)e.nextElement(); if (v.isRunnable(curtime)) { f = v.elements(); while(f.hasMoreElements() && curNumModules < endModules) { module = (NslModule)f.nextElement(); // Train only if the run enable flag is set //System.err.println("Steping module: "+module.nslGetName()); if(module.nslGetTrainEnableFlag()) { module.simTrain(); } curNumModules++; try { synchronized (this) { while (moduleSuspended || (contNumModules != numModules && !(curNumModules < contNumModules)) ) { wait(); } if (actualNumModulesmodule and its child modules * recursively. * @param module */ public void initRunRecursively(NslModule module) { Vector moduleChildren = module.nslGetModuleChildrenVector(); Enumeration e = moduleChildren.elements(); if ((system.schedulerMethod.equals("pre"))|| (system.schedulerMethod.equals("mixed"))) { module.nslInitTempRun(); module.initRun(); while (e.hasMoreElements()) { initRunRecursively((NslModule)e.nextElement()); } } else if (system.schedulerMethod.equals("post")) { while (e.hasMoreElements()) { initRunRecursively((NslModule)e.nextElement()); } // module.nslInitTempRun(); module.initRun(); } } public void runOneCycle() { double curtime = system.getCurTime(); Enumeration f, e = clockRunList.elements(); NslModule module; NslClockSchedulerModuleVector v; curNumModules = 0; while (e.hasMoreElements() && curNumModules < endModules) { v = (NslClockSchedulerModuleVector)e.nextElement(); if (v.isRunnable(curtime)) { f = v.elements(); while(f.hasMoreElements() && curNumModules < endModules) { module = (NslModule)f.nextElement(); // Run only if the run enable flag is set //System.err.println("Steping module: "+module.nslGetName()); if(module.nslGetRunEnableFlag()) { module.simRun(); } curNumModules++; try { synchronized (this) { while (moduleSuspended || (contNumModules != numModules && !(curNumModules < contNumModules)) ) { wait(); } if (actualNumModulesmodule and its child modules * recursively. * @param module */ public void updateBuffers(NslModule module) { Vector moduleChildren = module.nslGetModuleChildrenVector(); NslModule child; Enumeration e = moduleChildren.elements(); module.nslUpdateBuffers(); while(e.hasMoreElements()) { child = (NslModule)e.nextElement(); updateBuffers(child); } } public void breakAll() { synchronized (this) { moduleSuspended = true; cycleSuspended = true; epochSuspended = true; } } public void breakModules() { synchronized (this) { moduleSuspended = true; } } public void breakCycles() { synchronized (this) { cycleSuspended = true; } } public void breakEpochs() { synchronized (this) { epochSuspended = true; } } public void continueAll() { synchronized (this) { contNumEpochs = system.getEpochs(); epochSuspended = false; contEndTime = system.getEndTime(); cycleSuspended = false; contNumModules = numModules; moduleSuspended = false; notify(); } } public void continueCycle() { synchronized (this) { contNumEpochs = system.getFinishedEpochs() + 1; epochSuspended = false; contEndTime = system.getEndTime(); cycleSuspended = false; contNumModules = numModules; moduleSuspended = false; notify(); } } public void continueEpoch() { synchronized (this) { contNumEpochs = system.getEpochs(); epochSuspended = false; contEndTime = system.getEndTime(); cycleSuspended = false; contNumModules = numModules; moduleSuspended = false; notify(); } } public void continueModule() { synchronized (this) { contNumEpochs = system.getFinishedEpochs() + 1; epochSuspended = false; contEndTime = system.getCurTime() + system.nslGetDelta(); cycleSuspended = false; contNumModules = curNumModules+1; moduleSuspended = false; notify(); } } public void continueAll(double endTime) { synchronized (this) { contNumEpochs = system.getEpochs(); epochSuspended = false; contEndTime = endTime; cycleSuspended = false; contNumModules = numModules; moduleSuspended = false; notify(); } } public void continueCycle(int endCycle) { synchronized (this) { contNumEpochs = system.getEpochs(); epochSuspended = false; contEndTime = endCycle*system.nslGetDelta(); cycleSuspended = false; contNumModules = numModules; moduleSuspended = false; notify(); } } public void continueEpoch(int endEpochs) { synchronized (this) { contNumEpochs = endEpochs; epochSuspended = false; contEndTime = system.getEndTime(); cycleSuspended = false; contNumModules = numModules; moduleSuspended = false; notify(); } } public void continueModule(int end) { synchronized (this) { contNumEpochs = system.getFinishedEpochs() + 1; epochSuspended = false; contEndTime = system.getCurTime() + system.nslGetDelta(); cycleSuspended = false; contNumModules = end; moduleSuspended = false; notify(); } } /** * reset the scheduler, clear all nslConnection and modules in the scheduler * ready for next model to run. */ public void reset() { if (schedulerMode=='R') { if (schedulerState == 'W') { system.initRun(); system.init_displays(); system.init_run_char='A'; //after initRunList(); } else { if (simulationType=='E') { initRunEpoch(); initRun(); } else if (simulationType=='C') { initRun(); } } } else { if (schedulerState == 'W') { system.initTrain(); system.init_displays(); system.init_run_char='A'; //after initTrainList(); } else { if (simulationType=='E') { initTrainEpoch(); initTrain(); } else if (simulationType=='C') { initTrain(); } } } /*synchronized (this) { moduleSuspended = false; cycleSuspended = false; epochSuspended = false; resetScheduler = true; notify(); }*/ //system.continueCmd(); /* Enumeration E = clock_list.elements(); NslClockSchedulerModuleVector V; while (E.hasMoreElements()) { V = (NslClockSchedulerModuleVector)E.nextElement(); V.reset(); } clock_list.removeAllElements(); system.cur_time = 0.0;*/ } }