Download | Plain Text | No 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 26.05.2009
- * @par Exercise
- * 4
- */
-
- #include <boost/program_options.hpp>
- #include <boost/lexical_cast.hpp>
- #include <iostream>
- #include <fstream>
- #include <stdexcept>
- #include <stdlib.h>
- #include "cdat.h"
- #include "cdatset.h"
- #include "cdatn.h"
- #include "ccpu.h"
- #include "cmem.h"
- #include "cprogram.h"
-
- #define REGISTERS 256
-
- using namespace std;
- namespace po = boost::program_options;
-
- /**
- * @func cpu_run
- * @brief template for executing cpu with different datatype
- * @param me string to name of me
- * @param vm po::variables_map
- * @param registers number of registers
- * @param datatype instance of datatype
- * @return -
- * @globalvars none
- * @exception none
- * @pre none
- * @post none
- */
- template<class T>
- void cpu_run(string& me, po::variables_map& vm, unsigned registers, T& datatype)
- {
- CMem<T> memory;
- /* optionally initialize memory from file */
- if (vm.count("memory"))
- {
- string memoryfile(vm["memory"].as<string>());
- ifstream file(memoryfile.c_str(), ios::in);
- if (!file.is_open())
- throw runtime_error("Unable to open memoryfile '" + memoryfile + "' for reading.");
-
- try
- {
- memory.initialize(file, datatype);
- file.close();
- }
- catch(CMemError& ex)
- {
- file.close();
- std::stringstream sstr;
- sstr << "Error while reading from memoryfile:" << endl << " " << ex.what();
- throw runtime_error(sstr.str());
- }
-
- #if DEBUG
- memory.dump(cerr);
- #endif
- }
-
- /* create program instance */
- CProgram<T> program;
- string programfile(vm["compile"].as<string>());
- ifstream file(programfile.c_str(), ios::in);
- if (!file.is_open())
- throw runtime_error("Unable to open programfile '" + programfile + "' for reading.");
-
- try
- {
- program.compile(file);
- file.close();
- }
- catch(CProgramError& ex)
- {
- file.close();
- std::stringstream sstr;
- sstr << "Error while compiling programfile:" << endl << " " << ex.what();
- throw runtime_error(sstr.str());
- }
-
- #if DEBUG
- program.dump(cerr);
- #endif
-
- /* execute the program */
- CCPU<T> cpu(registers, datatype);
- try
- {
- cpu.setMemory(&memory);
- cpu.setProgram(&program);
- cpu.run();
- #if DEBUG
- //cpu.dumpRegisters(cerr);
- #endif
- }
- catch(CCPUError& ex)
- {
- std::stringstream sstr;
- sstr << "Error while executing program:" << endl << " " << ex.what();
- #if DEBUG
- memory.dump(cerr);
- #endif
- throw runtime_error(sstr.str());
- }
- }
-
- /**
- * @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
- * @pre none
- * @post terminate with 0 if success else 1.
- *
- * 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")
- ("format,f", po::value<string>(), "input format")
- ("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;
- return 1;
- }
-
- /* print usage upon request or missing params */
- if (vm.count("help") || !vm.count("compile"))
- {
- cout << "Usage: " << me << " [-f <format>] -c <programfile> [-m <memoryfile>]" << endl;
- cout << desc << endl;
- return 0;
- }
-
- /* create memory, program and cpu from templates */
- try
- {
- if (vm.count("format"))
- {
- string format(vm["format"].as<string>());
- if (format == "s")
- {
- CDatSet datatype(0);
- cpu_run<CDatSet>(me, vm, REGISTERS, datatype);
- }
- else
- {
- unsigned bc;
- try
- {
- bc = boost::lexical_cast<unsigned>(format);
- }
- catch(boost::bad_lexical_cast& ex)
- {
- cerr << me << ": Paramater 'format' has invalid or unknown format." << endl;
- return 1;
- }
-
- if (bc < 2 || bc > 32)
- {
- cerr << me << ": Paramater 'format' must be inbetween 2 and 32." << endl;
- return 1;
- }
-
- CDatN datatype(0, bc);
- cpu_run<CDatN>(me, vm, REGISTERS, datatype);
- }
- }
- else
- {
- CDat<int> datatype(0);
- cpu_run<CDat<int> >(me, vm, REGISTERS, datatype);
- }
- }
- catch(runtime_error& ex)
- {
- cerr << me << ": " << ex.what() << endl;
- return 1;
- }
-
- return 0;
- }
-
- /* vim: set et sw=2 ts=2: */
-