Revision 391bbc7b68686318ecd16acb71d520614176e602 authored by Mike Stewart on 02 October 2019, 05:15:17 UTC, committed by Mike Stewart on 02 October 2019, 05:15:17 UTC
1 parent 602413b
Raw File
yaLVDC.c
/*
 * Copyright 2019 Ronald S. Burkey <info@sandroid.org>
 *
 * This file is part of yaAGC.
 *
 * yaAGC is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * yaAGC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with yaAGC; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Filename:    yaLVDC.c
 * Purpose:     Emulator for LVDC CPU
 * Compiler:    GNU gcc.
 * Reference:   http://www.ibibio.org/apollo
 * Mods:        2019-09-18 RSB  I originally intended to add LVDC-emulation
 * 				capability the the yaOBC program, but I'm
 * 				just too lazy and would prefer to write it
 * 				from scratch.
 */

#include <stdio.h>
#include "yaLVDC.h"

//////////////////////////////////////////////////////////////////////////////
// Cross-platform timekeeping stuff.  Use *NIX-style functions times() and
// sysconf(_SC_CLK_TCK) for measuring time passage, and use sleepMilliseconds()
// to sleep for a while.  Note that sleepMilliseconds(0) actually does nothing,
// and does not relinquish any control.

#ifdef WIN32

#include <windows.h>
struct tms
  {
    clock_t tms_utime; /* user time */
    clock_t tms_stime; /* system time */
    clock_t tms_cutime; /* user time of children */
    clock_t tms_cstime; /* system time of children */
  };
#define _SC_CLK_TCK (1000)
#define sysconf(x) (x)
#define times(p) (clock_t)GetTickCount ()

void
sleepMilliseconds(unsigned Milliseconds)
{
  if (Milliseconds == 0)
    return;
  Sleep (Milliseconds);
}

#else // *NIX.

#include <unistd.h>
#include <time.h>
#include <sys/times.h>
void
sleepMilliseconds(unsigned Milliseconds)
{
  struct timespec Req, Rem;
  if (Milliseconds == 0)
    return;
  Req.tv_sec = Milliseconds / 1000;
  Req.tv_nsec = (Milliseconds % 1000) * 1000 * 1000; // 10 milliseconds.
  nanosleep(&Req, &Rem);
}

#endif

//////////////////////////////////////////////////////////////////////////////
// Main program.

// Length of an LVDC CPU's "computer cycle".
#define SECONDS_PER_CYCLE (168.0/2048000) // About 82us.
double cyclesPerTick;

int
main (int argc, char *argv[])
{
  int retVal = 1;
  int i;
  clock_t startingTime, currentTime;
  unsigned long cycleCount = 0;
  struct tms TmsStruct;

  // Setup and initialization.
  if (parseCommandLineArguments (argc, argv))
    goto done;
  // Note that readCore() must occur after readAssemblies(), since if present,
  // the core-memory file overrides the core-memory image from the assembler.
  if (readAssemblies (assemblyBasenames, MAX_PROGRAMS))
    goto done;
  if (readCore())
    goto done;
  dPrintouts(); // Some optional printouts for debugging.

  cyclesPerTick = 1.0 / (SECONDS_PER_CYCLE * sysconf(_SC_CLK_TCK));
  startingTime = times(&TmsStruct);
  state.hop = state.core[0][0][2][0];

  // Emulation.
  while (1)
    {
      unsigned long targetCycles;

      currentTime = times(&TmsStruct);
      targetCycles = (currentTime - startingTime) * cyclesPerTick;
      while (cycleCount < targetCycles)
	{
	  int cyclesUsed = 0;
	  if (runOneInstruction(&cyclesUsed))
	    goto done;
	  cycleCount += cyclesUsed;
	}

      // Sleep for a little to avoid hogging 100% CPU time.  The amount
      // we choose doesn't really matter.
      sleepMilliseconds(10);
    }

retVal = 0;
done: ;
for (i = 0; i < numErrorMessages; i++)
fprintf (stderr, "%s\n", errorMessageStack[i]);
return (retVal);
}
back to top