Download | Plain Text | Line Numbers


/**
 * @module mycpu
 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
 * @brief  mycpu executes a programfile (in simple assembler) by parsing the
 *         programfile first. This creates a vector of instructions, which will
 *         be executed in linear order (except jumps) afterwards. In order to
 *         initialize the memory of the cpu before execution an optional
 *         memoryfile can be passed as commandline option.
 * @date   13.05.2009
 * @par Exercise
 *      4
 */
 
#include <boost/program_options.hpp>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <stdlib.h>
#include "ccpu.h"
#include "cmem.h"
#include "cprogram.h"
 
using namespace std;
namespace po = boost::program_options;
 
/**
 * @func   main
 * @brief  program entry point
 * @param  argc  standard parameter of main
 * @param  argv  standard parameter of main
 * @return 0 on success, not 0 otherwise
 * @globalvars none
 * @exception  none
 * @conditions none
 *
 * parse commandline options, create and initialize memory,
 * create cprogram instance, which parses the programfile and
 * execute CCPU::run()
 * On error print error message to stderr.
 * Unknown commandline options will print a usage message.
 */
int main(int argc, char* argv[])
{
  string me(argv[0]);
 
  /* define commandline options */
  po::options_description desc("Allowed options");
  desc.add_options()
    ("help,h",    "this help message")
    ("compile,c", po::value<string>(), "input programfile")
    ("memory,m",  po::value<string>(), "input memoryfile");
 
  /* parse commandline options */
  po::variables_map vm;
  try
  {
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);
  }
  catch(po::error& ex)
  {
    cerr << me << ": Error: " << ex.what() << endl;
  }
 
  /* print usage upon request or missing params */
  if (vm.count("help") || !vm.count("compile"))
  {
    cout << "Usage: " << me << " -c <programfile> [-m <memoryfile>]" << endl;
    cout << desc << endl;
    return 0;
  }
 
  /* create memory and optionally initialize memory from file */
  CMem memory;
  if (vm.count("memory"))
  {
    string memoryfile(vm["memory"].as<string>());
    ifstream file(memoryfile.c_str(), ios::in);
    if (!file.is_open())
    {
      cerr << me << ": Unable to open memoryfile '" << memoryfile << "' for reading." << endl;
      return 1;
    }
 
    try
    {
      memory.initialize(file);
      file.close();
    }
    catch(runtime_error& ex)
    {
      file.close();
      cerr << me << ": Error while reading from memoryfile:" << endl
           << "  " << ex.what() << endl;
      return 1;
    }
 
#if DEBUG
    memory.dump(cerr);
#endif
  }
 
  /* create program instance */
  CProgram program;
  string programfile(vm["compile"].as<string>());
  ifstream file(programfile.c_str(), ios::in);
  if (!file.is_open())
  {
    cerr << me << ": Unable to open programfile '" << programfile << "' for reading." << endl;
    return 1;
  }
 
  try
  {
    program.compile(file);
    file.close();
  }
  catch(runtime_error& ex)
  {
    file.close();
    cerr << me << ": Error while compiling programfile:" << endl
         << "  " << ex.what() << endl;
    return 1;
  }
 
#if DEBUG
  program.dump(cerr);
#endif
 
 
  /* create cpu and execute the program */
  try
  {
    CCPU cpu(256);
    cpu.setMemory(&memory);
    cpu.setProgram(&program);
    cpu.run();
#if DEBUG
    //cpu.dumpRegisters(cerr);
#endif
  }
  catch(runtime_error& ex)
  {
    cerr << me << ": Error while executing program:" << endl
         << "  " << ex.what() << endl;
#if DEBUG
    memory.dump(cerr);
#endif
    return 1;
  }
 
  return 0;
}
 
/* vim: set et sw=2 ts=2: */