Download | Plain Text | No Line Numbers


  1. /**
  2.  * @module mycpu
  3.  * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
  4.  * @brief mycpu executes a programfile (in simple assembler) by parsing the
  5.  * programfile first. This creates a vector of instructions, which will
  6.  * be executed in linear order (except jumps) afterwards. In order to
  7.  * initialize the memory of the cpu before execution an optional
  8.  * memoryfile can be passed as commandline option.
  9.  * @date 26.05.2009
  10.  * @par Exercise
  11.  * 4
  12.  */
  13.  
  14. #include <boost/program_options.hpp>
  15. #include <boost/lexical_cast.hpp>
  16. #include <iostream>
  17. #include <fstream>
  18. #include <stdexcept>
  19. #include <stdlib.h>
  20. #include "cdat.h"
  21. #include "cdatset.h"
  22. #include "cdatn.h"
  23. #include "ccpu.h"
  24. #include "cmem.h"
  25. #include "cprogram.h"
  26.  
  27. #define REGISTERS 256
  28.  
  29. using namespace std;
  30. namespace po = boost::program_options;
  31.  
  32. /**
  33.  * @func cpu_run
  34.  * @brief template for executing cpu with different datatype
  35.  * @param me string to name of me
  36.  * @param vm po::variables_map
  37.  * @param registers number of registers
  38.  * @param datatype instance of datatype
  39.  * @return -
  40.  * @globalvars none
  41.  * @exception none
  42.  * @pre none
  43.  * @post none
  44.  */
  45. template<class T>
  46. void cpu_run(string& me, po::variables_map& vm, unsigned registers, T& datatype)
  47. {
  48. CMem<T> memory;
  49. /* optionally initialize memory from file */
  50. if (vm.count("memory"))
  51. {
  52. string memoryfile(vm["memory"].as<string>());
  53. ifstream file(memoryfile.c_str(), ios::in);
  54. if (!file.is_open())
  55. throw runtime_error("Unable to open memoryfile '" + memoryfile + "' for reading.");
  56.  
  57. try
  58. {
  59. memory.initialize(file, datatype);
  60. file.close();
  61. }
  62. catch(CMemError& ex)
  63. {
  64. file.close();
  65. std::stringstream sstr;
  66. sstr << "Error while reading from memoryfile:" << endl << " " << ex.what();
  67. throw runtime_error(sstr.str());
  68. }
  69.  
  70. #if DEBUG
  71. memory.dump(cerr);
  72. #endif
  73. }
  74.  
  75. /* create program instance */
  76. CProgram<T> program;
  77. string programfile(vm["compile"].as<string>());
  78. ifstream file(programfile.c_str(), ios::in);
  79. if (!file.is_open())
  80. throw runtime_error("Unable to open programfile '" + programfile + "' for reading.");
  81.  
  82. try
  83. {
  84. program.compile(file);
  85. file.close();
  86. }
  87. catch(CProgramError& ex)
  88. {
  89. file.close();
  90. std::stringstream sstr;
  91. sstr << "Error while compiling programfile:" << endl << " " << ex.what();
  92. throw runtime_error(sstr.str());
  93. }
  94.  
  95. #if DEBUG
  96. program.dump(cerr);
  97. #endif
  98.  
  99. /* execute the program */
  100. CCPU<T> cpu(registers, datatype);
  101. try
  102. {
  103. cpu.setMemory(&memory);
  104. cpu.setProgram(&program);
  105. cpu.run();
  106. #if DEBUG
  107. //cpu.dumpRegisters(cerr);
  108. #endif
  109. }
  110. catch(CCPUError& ex)
  111. {
  112. std::stringstream sstr;
  113. sstr << "Error while executing program:" << endl << " " << ex.what();
  114. #if DEBUG
  115. memory.dump(cerr);
  116. #endif
  117. throw runtime_error(sstr.str());
  118. }
  119. }
  120.  
  121. /**
  122.  * @func main
  123.  * @brief program entry point
  124.  * @param argc standard parameter of main
  125.  * @param argv standard parameter of main
  126.  * @return 0 on success, not 0 otherwise
  127.  * @globalvars none
  128.  * @exception none
  129.  * @pre none
  130.  * @post terminate with 0 if success else 1.
  131.  *
  132.  * parse commandline options, create and initialize memory,
  133.  * create cprogram instance, which parses the programfile and
  134.  * execute CCPU::run()
  135.  * On error print error message to stderr.
  136.  * Unknown commandline options will print a usage message.
  137.  */
  138. int main(int argc, char* argv[])
  139. {
  140. string me(argv[0]);
  141.  
  142. /* define commandline options */
  143. po::options_description desc("Allowed options");
  144. desc.add_options()
  145. ("help,h", "this help message")
  146. ("format,f", po::value<string>(), "input format")
  147. ("compile,c", po::value<string>(), "input programfile")
  148. ("memory,m", po::value<string>(), "input memoryfile");
  149.  
  150. /* parse commandline options */
  151. po::variables_map vm;
  152. try
  153. {
  154. po::store(po::parse_command_line(argc, argv, desc), vm);
  155. po::notify(vm);
  156. }
  157. catch(po::error& ex)
  158. {
  159. cerr << me << ": Error: " << ex.what() << endl;
  160. return 1;
  161. }
  162.  
  163. /* print usage upon request or missing params */
  164. if (vm.count("help") || !vm.count("compile"))
  165. {
  166. cout << "Usage: " << me << " [-f <format>] -c <programfile> [-m <memoryfile>]" << endl;
  167. cout << desc << endl;
  168. return 0;
  169. }
  170.  
  171. /* create memory, program and cpu from templates */
  172. try
  173. {
  174. if (vm.count("format"))
  175. {
  176. string format(vm["format"].as<string>());
  177. if (format == "s")
  178. {
  179. CDatSet datatype(0);
  180. cpu_run<CDatSet>(me, vm, REGISTERS, datatype);
  181. }
  182. else
  183. {
  184. unsigned bc;
  185. try
  186. {
  187. bc = boost::lexical_cast<unsigned>(format);
  188. }
  189. catch(boost::bad_lexical_cast& ex)
  190. {
  191. cerr << me << ": Paramater 'format' has invalid or unknown format." << endl;
  192. return 1;
  193. }
  194.  
  195. if (bc < 2 || bc > 32)
  196. {
  197. cerr << me << ": Paramater 'format' must be inbetween 2 and 32." << endl;
  198. return 1;
  199. }
  200.  
  201. CDatN datatype(0, bc);
  202. cpu_run<CDatN>(me, vm, REGISTERS, datatype);
  203. }
  204. }
  205. else
  206. {
  207. CDat<int> datatype(0);
  208. cpu_run<CDat<int> >(me, vm, REGISTERS, datatype);
  209. }
  210. }
  211. catch(runtime_error& ex)
  212. {
  213. cerr << me << ": " << ex.what() << endl;
  214. return 1;
  215. }
  216.  
  217. return 0;
  218. }
  219.  
  220. /* vim: set et sw=2 ts=2: */
  221.