Download | Plain Text | No Line Numbers


  1. /**
  2.  * @module ccpu
  3.  * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
  4.  * @brief CPU implementation. Used as a container for memory and instructions.
  5.  * Implements a run method to execute the program (= the instructions).
  6.  * @date 26.05.2009
  7.  */
  8.  
  9. #ifndef CCPU_H
  10. #define CCPU_H 1
  11.  
  12. #include <iostream>
  13. #include <set>
  14. #include <stdexcept>
  15. #ifdef DEBUG
  16. # include <iostream>
  17. # include <iomanip>
  18. #endif
  19.  
  20. /**
  21.  * @class CCPUError
  22.  *
  23.  * Exception thrown by implemententations of CCPU
  24.  */
  25. class CCPUError
  26. : public std::invalid_argument
  27. {
  28. public:
  29. /**
  30.   * @method CCPUError
  31.   * @brief Default exception ctor
  32.   * @param what message to pass along
  33.   * @return -
  34.   * @globalvars none
  35.   * @exception none
  36.   * @pre none
  37.   * @post none
  38.   */
  39. CCPUError(const std::string& what)
  40. : std::invalid_argument(what)
  41. {}
  42. };
  43.  
  44. #include "cmem.h"
  45. #include "displays.h"
  46. #include "cprogram.h"
  47.  
  48. /* forward declare CProgram */
  49. template <class T>
  50. class CProgram;
  51.  
  52. /**
  53.  * @class CCPU
  54.  *
  55.  * CPU implementation. Used as a container for memory and instructions.
  56.  * Implements a run method to execute the program (= the instructions).
  57.  */
  58. template <class T>
  59. class CCPU
  60. {
  61. typedef typename std::set<CDisplay<T> *>::iterator displayiterator;
  62.  
  63. public:
  64. /**
  65.   * @method CCPU
  66.   * @brief Default ctor
  67.   * @param cnt number of registers to allocate for this cpu
  68.   * @param datatype reference instance of datatype to copy from
  69.   * @return -
  70.   * @globalvars none
  71.   * @exception none
  72.   * @pre none
  73.   * @post none
  74.   */
  75. CCPU(const unsigned cnt, T& datatype);
  76.  
  77. /**
  78.   * @method ~CCPU
  79.   * @brief Default dtor
  80.   * @param -
  81.   * @return -
  82.   * @globalvars none
  83.   * @exception none
  84.   * @pre none
  85.   * @post none
  86.   */
  87. ~CCPU();
  88.  
  89. /**
  90.   * @method getRegisterCount
  91.   * @brief get number of registers
  92.   * @param -
  93.   * @return number of registers
  94.   * @globalvars none
  95.   * @exception none
  96.   * @pre none
  97.   * @post none
  98.   */
  99. const unsigned getRegisterCount() const
  100. {
  101. return m_regcnt;
  102. }
  103.  
  104. /**
  105.   * @method getRegisters
  106.   * @brief get reference to registers vector
  107.   * @param -
  108.   * @return reference to registers vector
  109.   * @globalvars none
  110.   * @exception none
  111.   * @pre none
  112.   * @post none
  113.   */
  114. std::vector<T> &getRegisters()
  115. {
  116. return m_registers;
  117. }
  118.  
  119. /**
  120.   * @method setMemory
  121.   * @brief set memory of cpu
  122.   * @param memory pointer to memory
  123.   * @return -
  124.   * @globalvars none
  125.   * @exception none
  126.   * @pre none
  127.   * @post none
  128.   */
  129. void setMemory(CMem<T> *memory)
  130. {
  131. m_memory = memory;
  132. }
  133.  
  134. /**
  135.   * @method getMemory
  136.   * @brief get pointer to memory
  137.   * @param -
  138.   * @return pointer to memory
  139.   * @globalvars none
  140.   * @exception none
  141.   * @pre none
  142.   * @post none
  143.   */
  144. CMem<T> *getMemory() const
  145. {
  146. return m_memory;
  147. }
  148.  
  149. /**
  150.   * @method setProgram
  151.   * @brief set program to execute
  152.   * @param program pointer to program
  153.   * @return -
  154.   * @globalvars none
  155.   * @exception none
  156.   * @pre none
  157.   * @post none
  158.   */
  159. void setProgram(const CProgram<T> *program)
  160. {
  161. m_program = program;
  162. }
  163.  
  164. /**
  165.   * @method getProgram
  166.   * @brief get pointer to program
  167.   * @param -
  168.   * @return pointer to program
  169.   * @globalvars none
  170.   * @exception none
  171.   * @pre none
  172.   * @post none
  173.   */
  174. const CProgram<T> *getProgram()
  175. {
  176. return m_program;
  177. }
  178.  
  179. /**
  180.   * @method getDisplays
  181.   * @brief get set of pointers to displays
  182.   * @param -
  183.   * @return reference to set of pointers to displays
  184.   * @globalvars none
  185.   * @exception none
  186.   * @pre none
  187.   * @post none
  188.   */
  189. const std::set<CDisplay<T> *>& getDisplays()
  190. {
  191. return m_displays;
  192. }
  193.  
  194. /**
  195.   * @method setFlagZero
  196.   * @brief set zero flag
  197.   * @param value new value of zero flag
  198.   * @return -
  199.   * @globalvars none
  200.   * @exception none
  201.   * @pre none
  202.   * @post none
  203.   */
  204. void setFlagZero(const bool value)
  205. {
  206. m_flagzero = value;
  207. }
  208.  
  209. /**
  210.   * @method getFlagZero
  211.   * @brief get value of zero flag
  212.   * @param -
  213.   * @return value of zero flag
  214.   * @globalvars none
  215.   * @exception none
  216.   * @pre none
  217.   * @post none
  218.   */
  219. const bool getFlagZero()
  220. {
  221. return m_flagzero;
  222. }
  223.  
  224. /**
  225.   * @method setFlagSign
  226.   * @brief set sign flag
  227.   * @param value new value of sign flag
  228.   * @return -
  229.   * @globalvars none
  230.   * @exception none
  231.   * @pre none
  232.   * @post none
  233.   */
  234. void setFlagSign(const bool value)
  235. {
  236. m_flagsign = value;
  237. }
  238.  
  239. /**
  240.   * @method getFlagSign
  241.   * @brief get value of sign flag
  242.   * @param -
  243.   * @return value of sign flag
  244.   * @globalvars none
  245.   * @exception none
  246.   * @pre none
  247.   * @post none
  248.   */
  249. const bool getFlagSign()
  250. {
  251. return m_flagsign;
  252. }
  253.  
  254. /**
  255.   * @method run
  256.   * @brief execute current program
  257.   * @param -
  258.   * @return -
  259.   * @globalvars none
  260.   * @exception CCPUError
  261.   * @pre m_memory and m_program still exist
  262.   * @post none
  263.   */
  264. void run();
  265.  
  266. #if DEBUG
  267. /**
  268.   * @method dumpRegisters
  269.   * @brief dump content of registers to outputstream
  270.   * @param out outputstream to write to
  271.   * @return void
  272.   * @globalvars none
  273.   * @exception none
  274.   * @pre none
  275.   * @post none
  276.   */
  277. void dumpRegisters(std::ostream& out);
  278. #endif
  279.  
  280. private:
  281. /* members */
  282. T m_datatype;
  283. std::vector<T> m_registers;
  284. unsigned m_regcnt;
  285. CMem<T> *m_memory;
  286. const CProgram<T> *m_program;
  287. std::set<CDisplay<T> *> m_displays;
  288. bool m_flagzero;
  289. bool m_flagsign;
  290. };
  291.  
  292. /*----------------------------------------------------------------------------*/
  293.  
  294. template <class T>
  295. CCPU<T>::CCPU(const unsigned cnt, T& datatype)
  296. : m_datatype(datatype), m_registers(cnt, T(m_datatype) = 0), m_regcnt(cnt), m_memory(NULL), m_program(NULL), m_flagzero(false), m_flagsign(false)
  297. {
  298. /* create displays */
  299. m_displays.insert(new CDisplayWDEZ<T>);
  300. m_displays.insert(new CDisplayWHEX<T>);
  301. }
  302.  
  303. /*----------------------------------------------------------------------------*/
  304.  
  305. template <class T>
  306. CCPU<T>::~CCPU()
  307. {
  308. /* delete displays */
  309. for (displayiterator it = m_displays.begin() ; it != m_displays.end(); ++it)
  310. delete *it;
  311. }
  312.  
  313. /*----------------------------------------------------------------------------*/
  314.  
  315. template <class T>
  316. void CCPU<T>::run()
  317. {
  318. if (m_memory == NULL)
  319. throw CCPUError("CPU has no memory");
  320. if (m_program == NULL)
  321. throw CCPUError("CPU has no program to execute");
  322. if (m_regcnt == 0)
  323. throw CCPUError("CPU has no registers");
  324.  
  325. bool run = true;
  326. while(run)
  327. {
  328. unsigned pc = static_cast<unsigned>(m_registers[0]);
  329.  
  330. /* end of the program reached */
  331. if (pc == m_program->size())
  332. break;
  333.  
  334. /* pc is out of bound */
  335. if (pc > m_program->size())
  336. throw CCPUError("Programcounter is out of bound");
  337.  
  338. /* execute instruction */
  339. try
  340. {
  341. (*m_program->at(pc))(this);
  342. ++m_registers[0];
  343. }
  344. catch(CInstructionError& ex)
  345. {
  346. throw CCPUError(ex.what());
  347. }
  348. }
  349. }
  350.  
  351. /*----------------------------------------------------------------------------*/
  352.  
  353. #if DEBUG
  354. template <class T>
  355. void CCPU<T>::dumpRegisters(std::ostream& out)
  356. {
  357. out << "[REGISTER DUMP]" << std::endl;
  358. for(unsigned i = 0; i < getRegisterCount(); ++i)
  359. {
  360. out << "[" << std::setw(4) << std::setfill('0') << i << "] "
  361. << m_registers[i] << std::endl;
  362. }
  363. }
  364. #endif
  365.  
  366. #endif
  367.  
  368. /* vim: set et sw=2 ts=2: */
  369.