Download | Plain Text | Line Numbers
/**
* @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 <iostream>
#include <set>
#include <stdexcept>
#ifdef DEBUG
# include <iostream>
# include <iomanip>
#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 T>
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 T>
class CCPU
{
typedef typename std::set<CDisplay<T> *>::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<T> &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<T> *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<T> *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<T> *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<T> *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<CDisplay<T> *>& 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<T> m_registers;
unsigned m_regcnt;
CMem<T> *m_memory;
const CProgram<T> *m_program;
std::set<CDisplay<T> *> m_displays;
bool m_flagzero;
bool m_flagsign;
};
/*----------------------------------------------------------------------------*/
template <class T>
CCPU<T>::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<T>);
m_displays.insert(new CDisplayWHEX<T>);
}
/*----------------------------------------------------------------------------*/
template <class T>
CCPU<T>::~CCPU()
{
/* delete displays */
for (displayiterator it = m_displays.begin() ; it != m_displays.end(); ++it)
delete *it;
}
/*----------------------------------------------------------------------------*/
template <class T>
void CCPU<T>::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<unsigned>(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 <class T>
void CCPU<T>::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: */