/** * @module ccpu * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief CPU implementation. Used as a container for memory and instructions. * Implements a run method to execute the program (= the instructions). * @date 26.05.2009 */ #ifndef CCPU_H #define CCPU_H 1 #include #include #include #ifdef DEBUG # include # include #endif /** * @class CCPUError * * Exception thrown by implemententations of CCPU */ class CCPUError : public std::invalid_argument { public: /** * @method CCPUError * @brief Default exception ctor * @param what message to pass along * @return - * @globalvars none * @exception none * @pre none * @post none */ CCPUError(const std::string& what) : std::invalid_argument(what) {} }; #include "cmem.h" #include "displays.h" #include "cprogram.h" /* forward declare CProgram */ template class CProgram; /** * @class CCPU * * CPU implementation. Used as a container for memory and instructions. * Implements a run method to execute the program (= the instructions). */ template class CCPU { typedef typename std::set *>::iterator displayiterator; public: /** * @method CCPU * @brief Default ctor * @param cnt number of registers to allocate for this cpu * @param datatype reference instance of datatype to copy from * @return - * @globalvars none * @exception none * @pre none * @post none */ CCPU(const unsigned cnt, T& datatype); /** * @method ~CCPU * @brief Default dtor * @param - * @return - * @globalvars none * @exception none * @pre none * @post none */ ~CCPU(); /** * @method getRegisterCount * @brief get number of registers * @param - * @return number of registers * @globalvars none * @exception none * @pre none * @post none */ const unsigned getRegisterCount() const { return m_regcnt; } /** * @method getRegisters * @brief get reference to registers vector * @param - * @return reference to registers vector * @globalvars none * @exception none * @pre none * @post none */ std::vector &getRegisters() { return m_registers; } /** * @method setMemory * @brief set memory of cpu * @param memory pointer to memory * @return - * @globalvars none * @exception none * @pre none * @post none */ void setMemory(CMem *memory) { m_memory = memory; } /** * @method getMemory * @brief get pointer to memory * @param - * @return pointer to memory * @globalvars none * @exception none * @pre none * @post none */ CMem *getMemory() const { return m_memory; } /** * @method setProgram * @brief set program to execute * @param program pointer to program * @return - * @globalvars none * @exception none * @pre none * @post none */ void setProgram(const CProgram *program) { m_program = program; } /** * @method getProgram * @brief get pointer to program * @param - * @return pointer to program * @globalvars none * @exception none * @pre none * @post none */ const CProgram *getProgram() { return m_program; } /** * @method getDisplays * @brief get set of pointers to displays * @param - * @return reference to set of pointers to displays * @globalvars none * @exception none * @pre none * @post none */ const std::set *>& getDisplays() { return m_displays; } /** * @method setFlagZero * @brief set zero flag * @param value new value of zero flag * @return - * @globalvars none * @exception none * @pre none * @post none */ void setFlagZero(const bool value) { m_flagzero = value; } /** * @method getFlagZero * @brief get value of zero flag * @param - * @return value of zero flag * @globalvars none * @exception none * @pre none * @post none */ const bool getFlagZero() { return m_flagzero; } /** * @method setFlagSign * @brief set sign flag * @param value new value of sign flag * @return - * @globalvars none * @exception none * @pre none * @post none */ void setFlagSign(const bool value) { m_flagsign = value; } /** * @method getFlagSign * @brief get value of sign flag * @param - * @return value of sign flag * @globalvars none * @exception none * @pre none * @post none */ const bool getFlagSign() { return m_flagsign; } /** * @method run * @brief execute current program * @param - * @return - * @globalvars none * @exception CCPUError * @pre m_memory and m_program still exist * @post none */ void run(); #if DEBUG /** * @method dumpRegisters * @brief dump content of registers to outputstream * @param out outputstream to write to * @return void * @globalvars none * @exception none * @pre none * @post none */ void dumpRegisters(std::ostream& out); #endif private: /* members */ T m_datatype; std::vector m_registers; unsigned m_regcnt; CMem *m_memory; const CProgram *m_program; std::set *> m_displays; bool m_flagzero; bool m_flagsign; }; /*----------------------------------------------------------------------------*/ template CCPU::CCPU(const unsigned cnt, T& datatype) : 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) { /* create displays */ m_displays.insert(new CDisplayWDEZ); m_displays.insert(new CDisplayWHEX); } /*----------------------------------------------------------------------------*/ template CCPU::~CCPU() { /* delete displays */ for (displayiterator it = m_displays.begin() ; it != m_displays.end(); ++it) delete *it; } /*----------------------------------------------------------------------------*/ template void CCPU::run() { if (m_memory == NULL) throw CCPUError("CPU has no memory"); if (m_program == NULL) throw CCPUError("CPU has no program to execute"); if (m_regcnt == 0) throw CCPUError("CPU has no registers"); bool run = true; while(run) { unsigned pc = static_cast(m_registers[0]); /* end of the program reached */ if (pc == m_program->size()) break; /* pc is out of bound */ if (pc > m_program->size()) throw CCPUError("Programcounter is out of bound"); /* execute instruction */ try { (*m_program->at(pc))(this); ++m_registers[0]; } catch(CInstructionError& ex) { throw CCPUError(ex.what()); } } } /*----------------------------------------------------------------------------*/ #if DEBUG template void CCPU::dumpRegisters(std::ostream& out) { out << "[REGISTER DUMP]" << std::endl; for(unsigned i = 0; i < getRegisterCount(); ++i) { out << "[" << std::setw(4) << std::setfill('0') << i << "] " << m_registers[i] << std::endl; } } #endif #endif /* vim: set et sw=2 ts=2: */