MFMv2.0.10
Movable Feast Machine Simulator 2.0.10
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
AbstractDriver.h
Go to the documentation of this file.
1 /* -*- mode:C++ -*-
2  AbstractDriver.h Base class for all MFM drivers
3  Copyright (C) 2014 The Regents of the University of New Mexico. All rights reserved.
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
18  USA
19 */
20 
28 #ifndef ABSTRACTDRIVER_H
29 #define ABSTRACTDRIVER_H
30 
31 #include <sys/stat.h> /* for mkdir */
32 #include <sys/time.h> /* for gettimeofday */
33 #include <sys/types.h> /* for mkdir */
34 #include <errno.h> /* for errno */
35 #include "Util.h"
36 #include "Utils.h" /* for GetDateTimeNow, Sleep */
37 #include "ExternalConfig.h"
40 #include "FileByteSource.h"
41 #include "FileByteSink.h"
42 #include "itype.h"
43 #include "Grid.h"
44 #include "ElementTable.h"
45 #include "VArguments.h"
46 #include "StdElements.h"
47 #include "ElementRegistry.h"
48 #include "Version.h"
49 
50 
51 #define MAX_PATH_LENGTH 1000
52 #define MIN_PATH_RESERVED_LENGTH 100
53 
54 #define MAX_NEEDED_ELEMENTS 100
55 #define MAX_CONFIGURATION_PATHS 32
56 
57 #define INITIAL_AEPS_PER_FRAME 1
58 
59 namespace MFM
60 {
66  template<class GC>
68  {
69  protected:
70 
75  typedef typename GC::CORE_CONFIG CC;
76 
81  typedef typename CC::PARAM_CONFIG P;
82 
86  typedef typename CC::ATOM_TYPE T;
87 
92  enum { W = GC::GRID_WIDTH};
93 
98  enum { H = GC::GRID_HEIGHT};
99 
104  enum { R = P::EVENT_WINDOW_RADIUS};
105 
109  static const u32 EVENT_WINDOW_RADIUS = R;
110 
114  static const u32 GRID_WIDTH = W;
115 
119  static const u32 GRID_HEIGHT = H;
120 
126 
132 
137  typedef Grid<GC> OurGrid;
138 
144 
145  Element<CC>* m_neededElements[MAX_NEEDED_ELEMENTS];
146  u32 m_neededElementCount;
147 
148  void NeedElement(Element<CC>* element)
149  {
150  if(m_neededElementCount >= MAX_NEEDED_ELEMENTS)
151  {
152  FAIL(OUT_OF_ROOM);
153  }
154 
155  m_neededElements[m_neededElementCount++] = element;
156  }
157 
158  void WriteTimeBasedData(FileByteSink& fp, bool exists)
159  {
160  // Extract short names for parameter types
161  typedef typename GC::CORE_CONFIG CC;
162  typedef typename CC::PARAM_CONFIG P;
163  enum { W = GC::GRID_WIDTH};
164  enum { H = GC::GRID_HEIGHT};
165  enum { R = P::EVENT_WINDOW_RADIUS};
166 
167  if(!exists)
168  {
169  fp.Printf("# AEPS AEPS/Frame AER100 Overhead100");
170  for(u32 i = 0; i < m_neededElementCount; i++)
171  {
172  fp.WriteByte(' ');
173  for(const char* p = m_neededElements[i]->GetName(); *p; p++)
174  {
175  if(isspace(*p))
176  {
177  fp.WriteByte('_');
178  }
179  else
180  {
181  fp.WriteByte(*p);
182  }
183  }
184  }
185  fp.Println();
186  }
187 
188  fp.Print((u64)GetAEPS());
189  fp.WriteByte(' ');
190  fp.Print(GetAEPSPerFrame());
191  fp.WriteByte(' ');
192  fp.Print((u64)(100.0 * GetAER()));
193  fp.WriteByte(' ');
194  fp.Print((u64)(100.0 * GetOverheadPercent()));
195 
196  for(u32 i = 0; i < m_neededElementCount; i++)
197  {
198  fp.WriteByte(' ');
199  fp.Print((u32)GetGrid().GetAtomCount(m_neededElements[i]->GetType()));
200  }
201  fp.Println();
202  }
203 
204  void SetIgnoreThreadingProblems(bool value)
205  {
206  m_ignoreThreadingProblems = value;
207  }
208 
209  void WriteTimeBasedData()
210  {
211  const char* path = GetSimDirPathTemporary("tbd/data.dat");
212  bool exists = true;
213  {
214  FILE* fp = fopen(path, "r");
215  if (!fp)
216  {
217  exists = false;
218  }
219  else
220  {
221  fclose(fp);
222  }
223  }
224  FILE* fp = fopen(path, "a");
225  FileByteSink fbs(fp);
226 
227  WriteTimeBasedData(fbs, exists);
228  fclose(fp);
229  }
230 
239  void UpdateGrid(OurGrid& grid)
240  {
241  const s32 ONE_THOUSAND = 1000;
242  const s32 ONE_MILLION = ONE_THOUSAND*ONE_THOUSAND;
243 
244  grid.Unpause(); // pausing and unpausing should be overhead!
245 
246  u32 startMS = GetTicks(); // So get the ticks after unpausing
247  if (m_ticksLastStopped != 0)
248  m_msSpentOverhead += startMS - m_ticksLastStopped;
249  else
250  m_msSpentOverhead = 0;
251 
252  Sleep(m_microsSleepPerFrame/ONE_MILLION,
253  (u64) (m_microsSleepPerFrame%ONE_MILLION)*ONE_THOUSAND);
254 
255  m_ticksLastStopped = GetTicks(); // and before pausing
256 
257  grid.Pause();
258 
259  u32 thisPeriodMS = m_ticksLastStopped - startMS;
260  m_msSpentRunning += thisPeriodMS;
261 
262  u64 totalEvents = grid.GetTotalEventsExecuted();
263  u32 totalSites = grid.GetTotalSites();
264  m_AEPS = totalEvents / totalSites;
265  m_AER = 1000 * (m_AEPS / m_msSpentRunning);
266 
267  u64 newEvents = totalEvents - m_lastTotalEvents;
268  m_lastTotalEvents = totalEvents;
269 
270  if (thisPeriodMS == 0) {
271  LOG.Warning("Zero ms in sample");
272  thisPeriodMS = 1;
273  }
274  double thisAERsample = 1000.0 * newEvents / totalSites / thisPeriodMS;
275 
276  const double BACKWARDS_AVERAGE_RATE = 0.99;
277  m_recentAER = BACKWARDS_AVERAGE_RATE * m_recentAER +
278  (1 - BACKWARDS_AVERAGE_RATE) * thisAERsample;
279 
280  m_overheadPercent = 100.0*m_msSpentOverhead/(m_msSpentRunning+m_msSpentOverhead);
281 
282  double diff = m_AEPS - m_lastFrameAEPS;
283  double err = MIN(1.0, MAX(-1.0, m_aepsPerFrame - diff));
284 
285  // Correct up to 20% of current each frame
286  m_microsSleepPerFrame = (100+20*err)*m_microsSleepPerFrame/100;
287  m_microsSleepPerFrame = MIN(100000000, MAX(1000, m_microsSleepPerFrame));
288 
289  m_lastFrameAEPS = m_AEPS;
290 
291  CheckEpochProcessing(grid);
292 
293  PostUpdate();
294  }
295 
303  void DecrementAEPSPerFrame(u32 amount)
304  {
305  if(m_aepsPerFrame <= amount)
306  {
307  m_aepsPerFrame = 1;
308  }
309  else
310  {
311  m_aepsPerFrame -= amount;
312  }
313  }
314 
322  void IncrementAEPSPerFrame(u32 amount)
323  {
324  m_aepsPerFrame += amount;
325  if(m_aepsPerFrame >= 1000)
326  {
327  m_aepsPerFrame = 1000;
328  }
329  }
330 
339  virtual void PostReinit(VArguments& args)
340  { }
341 
345  virtual void ReinitEden() = 0;
346 
351  {
352  for(u32 i = 0; i < m_neededElementCount; i++)
353  {
354  GetGrid().Needed(*m_neededElements[i]);
355  }
356 
358  }
359 
363  virtual void PostReinitPhysics()
364  { }
365 
371  virtual void DefineNeededElements() = 0;
372 
376  virtual void PostUpdate()
377  { }
378 
392  virtual void OnceOnly(VArguments& args)
393  {
394  if(!args.Appeared("-d"))
395  {
396  SetDataDirFromArgs(NULL, this);
397  }
398 
399  LOG.Message("Writing to simulation directory '%s'", GetSimDirPathTemporary(""));
400 
401  const char* (subs[]) =
402  {
403  "", "vid", "eps", "tbd", "teps", "save", "screenshot", "autosave"
404  };
405 
406  for(u32 i = 0; i < sizeof(subs) / sizeof(subs[0]); i++)
407  {
408  const char* path = GetSimDirPathTemporary("%s", subs[i]);
409  if(mkdir(path, 0777))
410  {
411  args.Die("Couldn't make simulation sub-directory '%s' : %s",
412  path, strerror(errno));
413  }
414  }
415 
416  /* Initialize tbd.txt */
417  const char* path = GetSimDirPathTemporary("tbd/tbd.txt");
418  FILE* fp = fopen(path, "w");
419  fprintf(fp, "#AEPS activesites empty dreg res wall sort-hits"
420  "sort-misses sort-total sort-hit-pctg\n");
421  fclose(fp);
422 
423  m_elementRegistry.AddPath("~/.mfm/res/elements");
424  m_elementRegistry.AddPath(SHARED_DIR "/res/elements");
425  m_elementRegistry.AddPath("./bin");
426  m_elementRegistry.Init();
427 
429 
430  m_grid.SetIgnoreThreadingProblems(m_ignoreThreadingProblems);
431  }
432 
436  virtual void RunHelper()
437  {
438  bool running = true;
439 
440  while(running)
441  {
442  UpdateGrid(m_grid);
443 
444  if(m_haltAfterAEPS > 0 && m_AEPS > m_haltAfterAEPS)
445  {
446  running = false;
447  }
448  }
449  }
450 
451  void SetAEPSPerEpoch(u32 aeps)
452  {
453  m_AEPSPerEpoch = aeps;
454  }
455 
456  u32 GetAEPSPerEpoch() const
457  {
458  return m_AEPSPerEpoch;
459  }
460 
461  private:
462 
463  OurElementRegistry m_elementRegistry;
464  OurStdElements m_se;
465  OurGrid m_grid;
466 
467  u32 m_ticksLastStopped;
468  u32 m_haltAfterAEPS;
469 
470  u64 m_startTimeMS;
471  u64 m_msSpentRunning;
472  u64 m_msSpentOverhead;
473  s32 m_microsSleepPerFrame;
474  double m_overheadPercent;
475  double m_lastFrameAEPS;
476  u32 m_aepsPerFrame;
477 
478  s32 m_AEPSPerEpoch;
479  u32 m_autosavePerEpochs;
480  u32 m_accelerateAfterEpochs;
481  u32 m_acceleration;
482  u32 m_surgeAfterEpochs;
483 
484  bool m_gridImages;
485  bool m_tileImages;
486 
487  bool m_ignoreThreadingProblems;
488 
489  double m_AEPS;
493  double m_AER;
494 
498  double m_recentAER;
499 
504  u64 m_lastTotalEvents;
505 
506  u32 m_nextEpochAEPS;
507  u32 m_epochCount;
508 
509  VArguments m_varguments;
510 
511  u32 m_configurationPathCount;
512  u32 m_currentConfigurationPath;
513  const char* (m_configurationPaths[MAX_CONFIGURATION_PATHS]);
514 
515  char m_simDirBasePath[MAX_PATH_LENGTH];
516  u32 m_simDirBasePathLength;
517 
518  u32 GetTicks()
519  {
520  struct timeval tv;
521  gettimeofday(&tv, NULL);
522 
523  /* ms since epoch */
524  u64 ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
525 
526  return ms - m_startTimeMS;
527  }
528 
529  /***********************************
530  * MANDATORY VARGUMENTS
531  ***********************************/
532 
533  static void PrintArgUsage(const char* not_needed, void* vargs)
534  {
535  VArguments& args = *((VArguments*)vargs);
536  args.Usage();
537  }
538 
539  static void PrintVersion(const char* not_needed, void* nullForShort)
540  {
541  fprintf(stderr, "%s\n", nullForShort ? MFM_VERSION_STRING_LONG : MFM_VERSION_STRING_SHORT);
542  exit(0);
543  }
544 
545  static void SetLoggingLevel(const char* level, void* not_needed)
546  {
547  LOG.SetLevel(atoi(level));
548  }
549 
550  static void SetSeedFromArgs(const char* seedstr, void* driver)
551  {
552  u32 seed = atoi(seedstr);
553  if(!seed)
554  {
555  seed = time(0);
556  }
557  ((AbstractDriver*)driver)->SetSeed(seed);
558  }
559 
560  static void SetAEPSPerEpochFromArgs(const char* aepsStr, void* driverptr)
561  {
562  AbstractDriver& driver = *((AbstractDriver*)driverptr);
563  VArguments& args = driver.m_varguments;
564 
565  u32 epochAEPS = atoi(aepsStr);
566  if (epochAEPS < 0)
567  {
568  args.Die("AEPS per epoch must be non-negative, not %d", epochAEPS);
569  }
570  driver.SetAEPSPerEpoch(epochAEPS);
571  }
572 
573  static void SetAutosavePerEpochsFromArgs(const char* arg, void* driverptr)
574  {
575  AbstractDriver& driver = *((AbstractDriver*)driverptr);
576  VArguments& args = driver.m_varguments;
577 
578  u32 val = atoi(arg);
579  if (val < 0)
580  {
581  args.Die("Autosave per epochs must be non-negative, not %d", val);
582  }
583  driver.m_autosavePerEpochs = val;
584  }
585 
586  static void SetPicturesPerRateFromArgs(const char* aeps, void* driverptr)
587  {
588  AbstractDriver* driver = (AbstractDriver*)driverptr;
589 
590  driver->m_accelerateAfterEpochs = atoi(aeps);
591  }
592 
593  static void SetSurgePerEpochFromArgs(const char* aeps, void* driverptr)
594  {
595  AbstractDriver* driver = (AbstractDriver*)driverptr;
596 
597  driver->m_surgeAfterEpochs = atoi(aeps);
598 
599  if (driver->m_surgeAfterEpochs > 0) // If actually surging
600  { // it'll happen immediately
601  driver->m_acceleration = 0; // so push acceleration back
602  }
603  }
604 
605  static void SetGridImages(const char* not_needed, void* driver)
606  {
607  ((AbstractDriver*)driver)->m_gridImages = 1;
608  }
609 
610  static void SetTileImages(const char* not_needed, void* driver)
611  {
612  ((AbstractDriver*)driver)->m_tileImages = 1;
613  }
614 
615  static void SetDataDirFromArgs(const char* dirPath, void* driverPtr)
616  {
617  AbstractDriver& driver = *((AbstractDriver*)driverPtr);
618  VArguments& args = driver.m_varguments;
619 
620  if(!dirPath || strlen(dirPath) == 0)
621  {
622  dirPath = "/tmp";
623  }
624 
625  /* Make the main data directory */
626  if(mkdir(dirPath, 0777))
627  {
628  /* It's OK if it already exists */
629  if(errno != EEXIST)
630  {
631  args.Die("Couldn't make directory '%s' : %s", dirPath, strerror(errno));
632  }
633  }
634 
635  u64 startTime = Utils::GetDateTimeNow();
636 
637  snprintf(driver.m_simDirBasePath, MAX_PATH_LENGTH - 1,
638  "%s/%d%06d/", dirPath,
639  Utils::GetDateFromDateTime(startTime),
640  Utils::GetTimeFromDateTime(startTime));
641 
642  driver.m_simDirBasePathLength = strlen(driver.m_simDirBasePath);
643 
644  if(driver.m_simDirBasePathLength >= MAX_PATH_LENGTH - MIN_PATH_RESERVED_LENGTH)
645  {
646  args.Die("Path name too long '%s'", dirPath);
647  }
648  }
649 
650  static void RegisterElementPath(const char* path, void* driverptr)
651  {
652  AbstractDriver& driver = *((AbstractDriver*)driverptr);
653 
654  driver.m_elementRegistry.AddPath(path);
655  }
656 
657  static void SetHaltAfterAEPSFromArgs(const char* aeps, void* driverptr)
658  {
659  AbstractDriver& driver = *((AbstractDriver*)driverptr);
660 
661  driver.m_haltAfterAEPS = atoi(aeps);
662  }
663 
664  static void LoadFromConfigFile(const char* path, void* driverptr)
665  {
666  AbstractDriver& driver = *((AbstractDriver*)driverptr);
667  VArguments& args = driver.m_varguments;
668 
669  if (driver.m_configurationPathCount >= MAX_CONFIGURATION_PATHS)
670  {
671  args.Die("Too many configuration paths, max %d, for '%s'",
672  MAX_CONFIGURATION_PATHS,
673  path);
674  }
675  driver.m_configurationPaths[driver.m_configurationPathCount] = path;
676  ++driver.m_configurationPathCount;
677  }
678 
679  static void SetIgnoreThreadingProblems(const char* not_used, void* driverptr)
680  {
681  AbstractDriver& driver = *((AbstractDriver*)driverptr);
682 
683  LOG.Warning("Threading errors treatead as warnings. Beware of inconsistencies.");
684 
685  driver.SetIgnoreThreadingProblems(true);
686  }
687 
688  void CheckEpochProcessing(OurGrid& grid)
689  {
690  if (m_AEPSPerEpoch >= 0 || m_accelerateAfterEpochs > 0 || m_surgeAfterEpochs > 0)
691  {
692  if (m_AEPS >= m_nextEpochAEPS)
693  {
694  DoEpochEvents(grid, m_epochCount, m_nextEpochAEPS);
695  m_nextEpochAEPS += m_AEPSPerEpoch;
696  ++m_epochCount;
697  }
698  }
699  }
700 
701  public:
702  void AutosaveGrid(u32 epochs)
703  {
704  const char* filename =
705  GetSimDirPathTemporary("autosave/%D-%D.mfs", epochs, (u32) m_AEPS);
706  SaveGrid(filename);
707  }
708 
709  void SaveGrid(const char* filename)
710  {
711 
712  LOG.Message("Saving to: %s", filename);
713  ExternalConfig<GC> cfg(this->GetGrid());
714  FILE* fp = fopen(filename, "w");
715  FileByteSink fs(fp);
716 
717  cfg.Write(fs);
718  fs.Close();
719  }
720 
721  void LoadFromConfigurationPath()
722  {
723  if (m_configurationPathCount > 0)
724  {
725  ++m_currentConfigurationPath;
726  if (m_currentConfigurationPath >= m_configurationPathCount)
727  {
728  m_currentConfigurationPath = 0;
729  }
730  ReloadCurrentConfigurationPath();
731  }
732  }
733 
746  const char* GetSimDirPathTemporary(const char* format, ...) const
747  {
749  buf.Reset();
750  buf.Printf("%s",m_simDirBasePath);
751  va_list ap;
752  va_start(ap, format);
753  buf.Vprintf(format, ap);
754  if (buf.HasOverflowed())
755  {
756  FAIL(OUT_OF_ROOM);
757  }
758  return buf.GetZString();
759  }
760 
761  void ReloadCurrentConfigurationPath()
762  {
763  if(m_configurationPathCount == 0)
764  {
765  return;
766  }
767 
768  const char * path = m_configurationPaths[m_currentConfigurationPath];
769 
770  LOG.Debug("Loading configuration from %s...", path);
771 
772  ExternalConfig<GC> cfg(GetGrid());
773  RegisterExternalConfigFunctions<GC>(cfg);
774  FileByteSource fs(path);
775  if (fs.IsOpen())
776  {
777 
778  cfg.SetByteSource(fs, path);
779 
780  cfg.Read();
781 
782  fs.Close();
783  }
784  else
785  {
786  LOG.Error("Can't read configuration file '%s'", path);
787  }
788  }
789 
790 
797  virtual void DoEpochEvents(OurGrid& grid, u32 epochs, u32 epochAEPS)
798  {
799  LOG.Debug("Epoch %d: %d AEPS", epochs, epochAEPS);
800 
801  grid.CheckCaches();
802 
803  grid.RecountAtoms();
804 
805  if (m_gridImages)
806  {
807  const char * path = GetSimDirPathTemporary("eps/%010d.ppm", epochAEPS);
808  FILE* fp = fopen(path, "w");
809  FileByteSink fbs(fp);
810  grid.WriteEPSImage(fbs);
811  fclose(fp);
812  }
813 
814  if (m_tileImages)
815  {
816  const char * path = GetSimDirPathTemporary("teps/%010d-average.ppm", epochAEPS);
817  FILE* fp = fopen(path, "w");
818  FileByteSink fbs2(fp);
819  grid.WriteEPSAverageImage(fbs2);
820  fclose(fp);
821  }
822 
823 
824 
825  if (m_autosavePerEpochs > 0 && (epochs % m_autosavePerEpochs) == 0)
826  {
827  this->AutosaveGrid(epochs);
828  }
829 
830  if (m_accelerateAfterEpochs > 0 && (epochs % m_accelerateAfterEpochs) == 0)
831  {
832  this->SetAEPSPerEpoch(this->GetAEPSPerEpoch() + m_acceleration);
833  }
834 
835  if (m_accelerateAfterEpochs > 0 &&
836  m_surgeAfterEpochs > 0 &&
837  (epochs % m_surgeAfterEpochs) == 0)
838  {
839  ++m_acceleration;
840  }
841  }
842 
843 
844  AbstractDriver() :
845  m_neededElementCount(0),
846  m_grid(m_elementRegistry),
847  m_ticksLastStopped(0),
848  m_haltAfterAEPS(0),
849  m_startTimeMS(0),
850  m_msSpentRunning(0),
851  m_msSpentOverhead(0),
852  m_microsSleepPerFrame(50000),
853  m_overheadPercent(0.0),
854  m_aepsPerFrame(INITIAL_AEPS_PER_FRAME),
855  m_AEPSPerEpoch(100),
856  m_autosavePerEpochs(1),
857  m_accelerateAfterEpochs(0),
858  m_acceleration(1),
859  m_surgeAfterEpochs(0),
860  m_gridImages(false),
861  m_tileImages(false),
862  m_ignoreThreadingProblems(false),
863  m_AEPS(0),
864  m_recentAER(0),
865  m_lastTotalEvents(0),
866  m_nextEpochAEPS(0),
867  m_epochCount(0),
868  m_configurationPathCount(0),
869  m_currentConfigurationPath(U32_MAX)
870  { }
871 
872  void Init(u32 argc, const char** argv)
873  {
875 
876  SetSeed(1);
877 
878  m_varguments.ProcessArguments(argc, argv);
879 
880  m_startTimeMS = GetTicks();
881 
882  OnceOnly(m_varguments);
883  }
884 
885  VArguments & GetVArguments()
886  {
887  return m_varguments;
888  }
889 
890  void RegisterArgument(const char* description, const char* filter,
891  VArgumentHandleValue func, void* handlerArg,
892  bool runFunc)
893  {
894  m_varguments.RegisterArgument(description, filter, func, handlerArg, runFunc);
895  }
896 
897  void RegisterSection(const char* sectionLabel)
898  {
899  m_varguments.RegisterSection(sectionLabel);
900  }
901 
912  virtual void AddDriverArguments()
913  {
914  RegisterSection("General switches");
915 
916  RegisterArgument("Display this help message, then exit.",
917  "-h|--help", &PrintArgUsage, (void*)(&m_varguments), false);
918 
919  RegisterArgument("Amount of logging output is ARG (0 -> none, 8 -> max)",
920  "-l|--log", &SetLoggingLevel, NULL, true);
921 
922  RegisterArgument("Print the brief version number, then exit.",
923  "-v|--version", &PrintVersion, NULL, false);
924 
925  RegisterArgument("Print the full version number, then exit.",
926  "-V|--Version", &PrintVersion, this, false);
927 
928  RegisterArgument("Set master PRNG seed to ARG (u32)",
929  "-s|--seed", &SetSeedFromArgs, this, true);
930 
931  RegisterArgument("Set epoch length to ARG AEPS",
932  "-e|--epoch", &SetAEPSPerEpochFromArgs, this, true);
933 
934  RegisterArgument("Autosave grid every ARG epochs (default 1; 0 for never)",
935  "-a|--autosave", &SetAutosavePerEpochsFromArgs, this, true);
936 
937  this->RegisterArgument("Increase the epoch length every ARG epochs",
938  "--accelerate",
939  &SetPicturesPerRateFromArgs, this, true);
940 
941  this->RegisterArgument("Increase the epoch length acceleration every ARG epochs",
942  "--surge",
943  &SetSurgePerEpochFromArgs, this, true);
944 
945  RegisterArgument("Each epoch, write grid AEPS image to per-sim eps/ directory",
946  "--gridImages", &SetGridImages, this, false);
947 
948  RegisterArgument("Each epoch, write tile AEPS image to per-sim teps/ directory",
949  "--tileImages", &SetTileImages, this, false);
950 
951  RegisterArgument("If ARG > 0, Halts after ARG elapsed aeps.",
952  "--haltafteraeps", &SetHaltAfterAEPSFromArgs, this, true);
953 
954  RegisterArgument("Store data in per-sim directories under ARG (string)",
955  "-d|--dir", &SetDataDirFromArgs, this, true);
956 
957  RegisterArgument("Add ARG as a path to search for element libraries",
958  "-ep|--elementpath", &RegisterElementPath, this, true);
959 
960  RegisterArgument("Load initial configuration from file at path ARG (string)",
961  "-cp|--configpath", &LoadFromConfigFile, this, true);
962 
963  RegisterArgument("Continue execution after detected thread failures",
964  "--ignorethreadbugs", &SetIgnoreThreadingProblems,
965  this, false);
966  }
967 
968 
969  virtual void ReinitUs()
970  { }
971 
972  u32 GetHaltAfterAEPS()
973  {
974  return m_haltAfterAEPS;
975  }
976 
977  double GetAEPS()
978  {
979  return m_AEPS;
980  }
981 
982  double GetAER()
983  {
984  return m_AER;
985  }
986 
987  void SetAER(double aer)
988  {
989  m_AER = aer;
990  }
991 
992  double GetRecentAER()
993  {
994  return m_recentAER;
995  }
996 
997  void SetRecentAER(double aer)
998  {
999  m_recentAER = aer;
1000  }
1001 
1002  u32 GetAEPSPerFrame()
1003  {
1004  return m_aepsPerFrame;
1005  }
1006 
1007  double GetOverheadPercent()
1008  {
1009  return m_overheadPercent;
1010  }
1011 
1012  OurGrid & GetGrid()
1013  {
1014  return m_grid;
1015  }
1016 
1017  void SetSeed(u32 seed)
1018  {
1019  if(!seed)
1020  {
1021  FAIL(ILLEGAL_ARGUMENT);
1022  }
1023  m_grid.SetSeed(seed);
1024  }
1025 
1026  void Reinit()
1027  {
1028  m_lastFrameAEPS = 0;
1029 
1030  ReinitUs();
1031 
1032  m_grid.Reinit();
1033 
1034  m_grid.Needed(Element_Empty<CC>::THE_INSTANCE);
1035 
1036  ReinitPhysics();
1037 
1038  ReinitEden();
1039 
1040  PostReinit(m_varguments);
1041 
1042  LoadFromConfigurationPath();
1043  }
1044 
1045  void Run()
1046  {
1047  unwind_protect
1048  ({
1049  MFMPrintErrorEnvironment(stderr, &unwindProtect_errorEnvironment);
1050  fprintf(stderr, "Failure reached top-level! Aborting\n");
1051  abort();
1052  },
1053  {
1054  RunHelper();
1055  });
1056  }
1057  };
1058 }
1059 
1060 #endif /* ABSTRACTDRIVER_H */
void RegisterArgument(const char *description, const char *filter, VArgumentHandleValue func, void *handlerArg, bool runFunc)
Definition: VArguments.cpp:25
void Warning(const char *format,...)
Definition: Logger.h:273
Level SetLevel(u32 newLevel)
Definition: Logger.h:127
Grid< GC > OurGrid
Definition: AbstractDriver.h:137
void DecrementAEPSPerFrame(u32 amount)
Definition: AbstractDriver.h:303
virtual void OnceOnly(VArguments &args)
Definition: AbstractDriver.h:392
ElementRegistry< CC > OurElementRegistry
Definition: AbstractDriver.h:125
void IncrementAEPSPerFrame(u32 amount)
Definition: AbstractDriver.h:322
ElementTable< CC > OurElementTable
Definition: AbstractDriver.h:143
Definition: AbstractDriver.h:67
Definition: StdElements.h:38
virtual void PostReinit(VArguments &args)
Definition: AbstractDriver.h:339
virtual void RunHelper()
Definition: AbstractDriver.h:436
virtual void PostReinitPhysics()
Definition: AbstractDriver.h:363
virtual void AddDriverArguments()
Definition: AbstractDriver.h:912
void Reset()
Definition: OverflowableCharBufferByteSink.h:192
void Pause()
Definition: Grid.h:378
void UpdateGrid(OurGrid &grid)
Definition: AbstractDriver.h:239
const char * GetZString()
Definition: OverflowableCharBufferByteSink.h:143
CC::ATOM_TYPE T
Definition: AbstractDriver.h:86
void Error(const char *format,...)
Definition: Logger.h:259
static const u32 GRID_WIDTH
Definition: AbstractDriver.h:114
void CheckCaches()
Definition: Grid.tcc:516
void AddPath(const char *path)
Definition: ElementRegistry.tcc:139
const char * GetSimDirPathTemporary(const char *format,...) const
Definition: AbstractDriver.h:746
virtual void DefineNeededElements()=0
virtual void ReinitEden()=0
Definition: Grid.h:47
StdElements< CC > OurStdElements
Definition: AbstractDriver.h:131
bool HasOverflowed() const
Definition: OverflowableCharBufferByteSink.h:206
Definition: FileByteSink.h:41
Definition: ElementRegistry.h:48
static const u32 EVENT_WINDOW_RADIUS
Definition: AbstractDriver.h:109
CC::PARAM_CONFIG P
Definition: AbstractDriver.h:81
void Unpause()
Definition: Grid.h:387
Definition: OverflowableCharBufferByteSink.h:41
void ReinitPhysics()
Definition: AbstractDriver.h:350
void Die(const char *format,...)
Definition: VArguments.cpp:16
void ProcessArguments(u32 argc, const char **argv)
Definition: VArguments.cpp:91
virtual void WriteByte(u8 ch)
Definition: ByteSink.h:81
GC::CORE_CONFIG CC
Definition: AbstractDriver.h:75
void Print(const char *str, s32 fieldWidth=-1, u8 padChar= ' ')
Definition: ByteSink.cpp:31
void Debug(const char *format,...)
Definition: Logger.h:301
void RegisterSection(const char *label)
Definition: VArguments.cpp:43
virtual void PostUpdate()
Definition: AbstractDriver.h:376
Definition: ElementTable.h:46
void Message(const char *format,...)
Definition: Logger.h:287
Definition: VArguments.h:48
void RecountAtoms()
Definition: Grid.tcc:160
virtual void DoEpochEvents(OurGrid &grid, u32 epochs, u32 epochAEPS)
Definition: AbstractDriver.h:797
Definition: Atom.h:43
bool Appeared(const char *argName) const
Definition: VArguments.cpp:147
static const u32 GRID_HEIGHT
Definition: AbstractDriver.h:119
#define U32_MAX
Definition: itype.h:95