From 34483e07a0548d32651cda4ca4282f3cf8cae870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Neuwirth?= Date: Tue, 12 May 2009 15:27:58 +0200 Subject: adding rest of files --- ue3/mycpu/Makefile | 6 +- ue3/mycpu/ccpu.cpp | 97 +++++++++++++++++++++ ue3/mycpu/ccpu.h | 77 +++++++++++++++++ ue3/mycpu/cdat.h | 14 ++++ ue3/mycpu/cinstruction.cpp | 104 +++++++++++++++++++++++ ue3/mycpu/cinstruction.h | 196 +++++++++++++++++++++++++++++++++++++++++++ ue3/mycpu/cmem.cpp | 65 ++++++++++++++ ue3/mycpu/cmem.h | 94 +++++++++++++++++++++ ue3/mycpu/cprogram.cpp | 109 ++++++++++++++++++++++++ ue3/mycpu/cprogram.h | 106 +++++++++++++++++++++++ ue3/mycpu/mycpu.cpp | 94 +++++++++++++++++++++ ue3/mycpu/test/test_prog | 13 +++ ue3/mycpu/test/test_prog_mem | 1 + 13 files changed, 973 insertions(+), 3 deletions(-) create mode 100644 ue3/mycpu/ccpu.cpp create mode 100644 ue3/mycpu/ccpu.h create mode 100644 ue3/mycpu/cinstruction.cpp create mode 100644 ue3/mycpu/cinstruction.h create mode 100644 ue3/mycpu/cmem.cpp create mode 100644 ue3/mycpu/cmem.h create mode 100644 ue3/mycpu/cprogram.cpp create mode 100644 ue3/mycpu/cprogram.h create mode 100644 ue3/mycpu/mycpu.cpp create mode 100644 ue3/mycpu/test/test_prog create mode 100644 ue3/mycpu/test/test_prog_mem diff --git a/ue3/mycpu/Makefile b/ue3/mycpu/Makefile index 6f57741..76b6244 100644 --- a/ue3/mycpu/Makefile +++ b/ue3/mycpu/Makefile @@ -8,11 +8,11 @@ DEBUGFLAGS= -DNDEBUG INCLUDE_PATH= -I/usr/local/include CXXFLAGS= -O -ansi -pedantic-errors -Wall $(INCLUDE_PATH) $(DEBUGFLAGS) LDFLAGS= -LIBS= -L/usr/local/lib +LIBS= -L/usr/local/lib -lboost_program_options BIN= mycpu -OBJS= mycpu.o cdat.o -HEADERS= cdat.h +OBJS= mycpu.o ccpu.o cprogram.o cmem.o cinstruction.o +HEADERS= cdat.h ccpu.h cprogram.h cmem.h cinstruction.h .SUFFIXES: .cpp .o diff --git a/ue3/mycpu/ccpu.cpp b/ue3/mycpu/ccpu.cpp new file mode 100644 index 0000000..72ad96c --- /dev/null +++ b/ue3/mycpu/ccpu.cpp @@ -0,0 +1,97 @@ +/** + * @module ccpu + * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) + * @brief class for processing a program + * @date 11.05.2009 + */ + +#include +#include +#include + +#include "ccpu.h" +#include "cinstruction.h" +#include "cprogram.h" +#include "cmem.h" + + +using namespace std; +using namespace boost; + +CCPU::CCPU(const std::string& progfile, const std::string& memfile) + : m_program(progfile), m_memory(memfile) +{ + m_instrtype["inc"] = new CInc(); + m_instrtype["dec"] = new CDec(); + m_instrtype["add"] = new CAdd(); + m_instrtype["sub"] = new CSub(); + m_instrtype["mul"] = new CMul(); + m_instrtype["div"] = new CDiv(); + m_instrtype["load"] = new CLoad(); + m_instrtype["store"] = new CStore(); + m_instrtype["test"] = new CTest(); + m_instrtype["label"] = new CLabel(); + m_instrtype["jumpa"] = new CJumpa(m_program.getJumpAddrs()); + m_instrtype["jumpz"] = new CJumpz(m_program.getJumpAddrs()); + m_instrtype["jumps"] = new CJumps(m_program.getJumpAddrs()); + m_instrtype["write"] = new CWrite(); +} + + +void CCPU::proceed() +{ + + while (m_memory.getRegister("R0") < m_program.getMaxProgramCount()) + { + std::vector& i_list = m_program.getInstruction( + m_memory.getRegister("R0") + ); + + /* switch (m_instrtype[i_list[0]]) + { + case INC: + cout << "fick mich"<< endl<& i_list) +{ + + +} + diff --git a/ue3/mycpu/ccpu.h b/ue3/mycpu/ccpu.h new file mode 100644 index 0000000..6b16ba3 --- /dev/null +++ b/ue3/mycpu/ccpu.h @@ -0,0 +1,77 @@ +/** + * @module ccpu + * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) + * @brief class for parsing simple scriptfiles + * @date 17.04.2009 + */ + +#ifndef CCPU_H +#define CCPU_H + +#include +#include +#include + +#include "cprogram.h" +#include "cmem.h" +#include "cinstruction.h" +/** + * @class CCPU + * + * Parses a simple line based scriptfile with some limitations: + * first function (starting a block) must be a read-command, + * last must be a write-command (ending this block). + * + * read- and write-commands have hard coded parameters, number#1 being a filetype. + * Classes handling certain filetypes must be of type CFile. + * Custom functions will be passed to CFile::callFunc(). + * + * On error ParserError will be thrown. + */ +class CCPU +{ + public: + + + /** + * @method CScriptparser + * @brief Default ctor + * @param scriptfile filename of script to parse + * @return - + * @globalvars none + * @exception bad_alloc + * @conditions none + */ + CCPU(const std::string& progfile, const std::string& memfile); + /** + * @method ~CScriptparser + * @brief Default dtor + * @param - + * @return - + * @globalvars none + * @exception none + * @conditions none + */ + ~CCPU() + {} + + + void proceed(); + + + + void execInstruction( CInstruction& instr, std::vector& i_list); + private: + /* members */ + + CProgram m_program; + CMem m_memory; + std::map m_instrtype; + bool f_zero, f_sign; + // std::string m_memfiler; + +}; + +#endif + +/* vim: set et sw=2 ts=2: */ diff --git a/ue3/mycpu/cdat.h b/ue3/mycpu/cdat.h index dc8a07c..3fda572 100644 --- a/ue3/mycpu/cdat.h +++ b/ue3/mycpu/cdat.h @@ -295,6 +295,20 @@ class CDatT return stream; } + /** + * @method getTypeValue + * @brief returns value as type T + * @param - + * @return m_value + * @globalvars none + * @exception none + * @conditions none + */ + T& getTypeValue() + { + return m_value; + } + private: /* members */ T m_value; diff --git a/ue3/mycpu/cinstruction.cpp b/ue3/mycpu/cinstruction.cpp new file mode 100644 index 0000000..2c8dedf --- /dev/null +++ b/ue3/mycpu/cinstruction.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include "cinstruction.h" +#include "cmem.h" +using namespace std; + +void CInc::exec(CMem& mem, vector& instr) +{ + mem.getRegister(instr[1])++; +} + + +void CDec::exec(CMem& mem, vector& instr) +{ + mem.getRegister(instr[1])--; +} + + +void CAdd::exec(CMem& mem, vector& instr) +{ + mem.getRegister(instr[1]) = mem.getRegister(instr[2]) + + mem.getRegister(instr[3]); +} + + +void CSub::exec(CMem& mem, vector& instr) +{ + mem.getRegister(instr[1]) = mem.getRegister(instr[2]) - + mem.getRegister(instr[3]); +} + + +void CMul::exec(CMem& mem, vector& instr) +{ + mem.getRegister(instr[1]) = mem.getRegister(instr[2]) * + mem.getRegister(instr[3]); +} + + +void CDiv::exec(CMem& mem, vector& instr) +{ + mem.getRegister(instr[1]) = mem.getRegister(instr[2]) / + mem.getRegister(instr[3]); +} + + +void CLoad::exec(CMem& mem, vector& instr) +{ + mem.getRegister(instr[1]) = mem.getMem(instr[2]); +} + + +void CStore::exec(CMem& mem, vector& instr) +{ + mem.setMem(instr[2], mem.getRegister(instr[1])); +} + + +void CTest::test(CMem& mem, vector& instr, bool& f_zero, bool& f_sign) +{ + if(mem.getRegister(instr[1]) == 0) + f_zero = true; + else + f_zero = false; + + if(mem.getRegister(instr[1]) <= 0) + f_sign = true; + else + f_sign = false; +} + + + + + +void CJumpa::exec(CMem& mem, vector& instr) +{ + mem.getRegister(instr[0]) = (int) m_jumpaddr[instr[1]]; +} + + +void CJumpz::exec(CMem& mem, vector& instr, bool& f_zero) +{ + if(f_zero) + mem.getRegister(instr[0]) = (int) m_jumpaddr[instr[1]]; +} + + +void CJumps::exec(CMem& mem, vector& instr, bool& f_sign) +{ + if(f_sign) + mem.getRegister(instr[0]) = (int) m_jumpaddr[instr[1]]; +} + + +void CWrite::exec(CMem& mem, vector& instr) +{ + if(instr[1] == "WDEZ") + cout << mem.getRegister(instr[2]) << endl; + else if (instr[1] == "WHEX") + cout << hex << mem.getRegister(instr[2]) << endl; +} + diff --git a/ue3/mycpu/cinstruction.h b/ue3/mycpu/cinstruction.h new file mode 100644 index 0000000..d393e09 --- /dev/null +++ b/ue3/mycpu/cinstruction.h @@ -0,0 +1,196 @@ +/** + * @module cinstruction + * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) + * @brief abstract class cpu instructions + * @date 17.04.2009 + */ + +#ifndef CINSTRUCTION_H +#define CINSTRUCTION_H +#include +#include +#include "cmem.h" + + + +/** + * @class CInstruction + * + * Parses a simple line based scriptfile with some limitations: + * first function (starting a block) must be a read-command, + * last must be a write-command (ending this block). + * + * read- and write-commands have hard coded parameters, number#1 being a filetype. + * Classes handling certain filetypes must be of type CFile. + * Custom functions will be passed to CFile::callFunc(). + * + * On error ParserError will be thrown. + */ +class CInstruction +{ + public: + + + + + /** + * @method ~CInstruction + * @brief Default dtor + * @param - + * @return - + * @globalvars none + * @exception none + * @conditions none + */ + virtual ~CInstruction() + {} + + + virtual void exec(CMem& mem, std::vector& instr) = 0; + + + + +}; + + + + +class CFlagInstruction : public CInstruction +{ + public: + + void exec(CMem& mem, std::vector& instr) + {} + virtual void exec(CMem& mem, std::vector& instr, bool& flag) = 0; + + +}; + + + +class CInc : public CInstruction +{ + public: + virtual void exec(CMem& mem, std::vector& instr); +}; + + +class CDec : public CInstruction +{ + public: + virtual void exec(CMem& mem, std::vector& instr); +}; + + + +class CAdd : public CInstruction +{ + public: + virtual void exec(CMem& mem, std::vector& instr); +}; + + + +class CSub : public CInstruction +{ + public: + virtual void exec(CMem& mem, std::vector& instr); +}; + + + +class CMul : public CInstruction +{ + public: + virtual void exec(CMem& mem, std::vector& instr); +}; + + + +class CDiv : public CInstruction +{ + public: + virtual void exec(CMem& mem, std::vector& instr); +}; + + + +class CLoad : public CInstruction +{ + public: + virtual void exec(CMem& mem, std::vector& instr); +}; + + + +class CStore : public CInstruction +{ + public: + virtual void exec(CMem& mem, std::vector& instr); +}; + +class CTest : public CFlagInstruction +{ + public: + void exec(CMem& mem, std::vector& instr, bool& flag) + {} + virtual void test(CMem& mem, std::vector& instr, + bool& f_zero, bool& f_sign); +}; + + +class CLabel : public CInstruction +{ + public: + void exec(CMem& mem, std::vector& instr) + {} + +}; + + +class CJumpa : public CInstruction +{ + public: + CJumpa(std::map& jumpaddr) + : m_jumpaddr(jumpaddr) + {} + virtual void exec(CMem& mem, std::vector& instr); + protected: + std::map m_jumpaddr; +}; + + +class CJumpz : public CFlagInstruction +{ + public: + CJumpz(std::map& jumpaddr) + : m_jumpaddr(jumpaddr) + {} + virtual void exec(CMem& mem, std::vector& instr, bool& f_zero); + protected: + std::map m_jumpaddr; +}; + + +class CJumps : public CFlagInstruction +{ + public: + CJumps(std::map& jumpaddr) + : m_jumpaddr(jumpaddr) + {} + virtual void exec(CMem& mem, std::vector& instr, bool& f_sign); + protected: + std::map m_jumpaddr; +}; + + + +class CWrite : public CInstruction +{ + public: + virtual void exec(CMem& mem, std::vector& instr); +}; + +#endif +/* vim: set et sw=2 ts=2: */ diff --git a/ue3/mycpu/cmem.cpp b/ue3/mycpu/cmem.cpp new file mode 100644 index 0000000..d27f74e --- /dev/null +++ b/ue3/mycpu/cmem.cpp @@ -0,0 +1,65 @@ +/** + * @module cprogram + * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) + * @brief class for parsing and saving a program + * @date 11.05.2009 + */ + +#include +#include +#include +#include +#include +#include "cdat.h" +#include "cmem.h" + + + +using namespace std; +using namespace boost; + +CMem::CMem(const std::string& memfile) : + m_memfile(memfile) +{ + + dump(std::cout); + +} + +/*----------------------------------------------------------------------------*/ + +CMem::~CMem() +{ + +} + +/*----------------------------------------------------------------------------*/ + +CDat& CMem::getRegister(const string reg) +{ + istringstream stmp ( + reg.substr(reg.find_first_of("R") + 1, reg.size()) + ); + + unsigned int regnr; + stmp >> regnr; + + // if (regnr >= MAX_REGISTER ) + + if (regnr == m_registers.size()) + { + m_registers.push_back(CDat((int)0)); + return m_registers[m_registers.size() - 1]; + } + + return m_registers[regnr]; +} +/*----------------------------------------------------------------------------*/ + +#ifdef DEBUG +void CMem::dump(std::ostream& out) +{ + out << endl << "Memory file:" << endl << m_memfile << endl; + out << endl << "Memory file content:" << endl; +} +#endif diff --git a/ue3/mycpu/cmem.h b/ue3/mycpu/cmem.h new file mode 100644 index 0000000..923ed01 --- /dev/null +++ b/ue3/mycpu/cmem.h @@ -0,0 +1,94 @@ +/** + * @module cmem + * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) + * @brief class for providing 256 registers. + * @date 11.05.2009 + */ + +#ifndef CMEM_H +#define CMEM_H + +#include +#include + +#include +#ifdef DEBUG +# include +#endif + #include "cdat.h" + + +#define MAX_REGISTER 256; +/** + * @class CMem + * + * Parses a simple line based scriptfile with some limitations: + * first function (starting a block) must be a read-command, + * last must be a write-command (ending this block). + * + * read- and write-commands have hard coded parameters, number#1 being a filetype. + * Classes handling certain filetypes must be of type CFile. + * Custom functions will be passed to CFile::callFunc(). + * + * On error ParserError will be thrown. + */ +class CMem +{ + public: + + /** + * @method CMem + * @brief Default ctor + * @param memoryfile filename + * @return - + * @globalvars none + * @exception bad_alloc + * @conditions none + */ + CMem(const std::string& memfile); + + /** + * @method ~CMem + * @brief Default dtor + * @param - + * @return - + * @globalvars none + * @exception none + * @conditions none + */ + ~CMem(); + + CDat& getRegister(const std::string reg); + + CDat& getMem(const std::string addr) + { + return getRegister("R0"); + } + void setMem(const std::string addr, const CDat& value) + {} + +#ifdef DEBUG + /** + * @method dump + * @brief Dumps the resgister contnent to ostream + * @param out output stream + * @return - + * @globalvars + * @exception + * @conditions + */ + void dump(std::ostream& out); +#endif + + + private: + /* members */ + std::string m_memfile; + + + std::vector m_registers; +}; + +#endif + +/* vim: set et sw=2 ts=2: */ diff --git a/ue3/mycpu/cprogram.cpp b/ue3/mycpu/cprogram.cpp new file mode 100644 index 0000000..9297b6e --- /dev/null +++ b/ue3/mycpu/cprogram.cpp @@ -0,0 +1,109 @@ +/** + * @module cprogram + * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) + * @brief class for parsing and saving a program + * @date 11.05.2009 + */ + +#include +#include +#include +#include +#include +#include +#include "cprogram.h" + + + +using namespace std; +using namespace boost; + +CProgram::CProgram(const std::string& progfile) : + m_programfile(progfile) +{ + parse(); + dump(std::cout); + +} + +/*----------------------------------------------------------------------------*/ + +CProgram::~CProgram() +{ + +} + + + +/*----------------------------------------------------------------------------*/ + +void CProgram::parse() +{ + /* open and read file */ + ifstream file(m_programfile.c_str(), ios::in); + // if (!file) + // throw ParserError("Unable to open scriptfile '" + m_scriptfile + "'."); + + int cur_line_nr = 0; + + while (!file.eof() && file.good()) + { + string cur_line; + + /* read file per line */ + getline(file, cur_line); + if (cur_line.empty()) + continue; + + trim(cur_line); + + /* ignore comments */ + if (cur_line.find_first_of('#') == 0) + continue; + + /*remove commas from current line */ + unsigned int pos; + while (( pos = cur_line.find_first_of(",") ) != string::npos) + cur_line.erase(pos, 1); + + /* add source line*/ + m_progsource.push_back(vector()); + algorithm::split( m_progsource.back(), cur_line, is_any_of(" \t")); + + /* jump addr as line number */ + if(m_progsource[cur_line_nr][0] == "label") + { + int size = m_progsource[cur_line_nr][01].size() - 1; + string label(m_progsource[cur_line_nr][01].substr(0, size)); + m_jumpaddr[label] = cur_line_nr; + } + + cur_line_nr++; + } + file.close(); + +} + +/*----------------------------------------------------------------------------*/ + +#ifdef DEBUG +void CProgram::dump(std::ostream& out) +{ + + out << endl << "Program file:" << endl << m_programfile << endl; + + out << endl << "Program source:" << endl; + for (int i = 0; i < (int) m_progsource.size();i++) + { + for(int x = 0; x < (int) m_progsource[i].size();x++) + out << m_progsource[i][x] << " "; + out << std::endl; + } + + out << endl << "Jump addresses:" << endl; + map::iterator it; + for (it = m_jumpaddr.begin(); it != m_jumpaddr.end(); it++) + out << (*it).first << " " << (*it).second << endl; + +} +#endif diff --git a/ue3/mycpu/cprogram.h b/ue3/mycpu/cprogram.h new file mode 100644 index 0000000..25d0ce2 --- /dev/null +++ b/ue3/mycpu/cprogram.h @@ -0,0 +1,106 @@ +/** + * @module cprogram + * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) + * @brief class for parsing and saving the program instuctions. + * @date 17.04.2009 + */ + +#ifndef CPROGRAM_H +#define CPROGRAM_H + +#include +#include +#include +#include +#ifdef DEBUG +# include +#endif +#include "cdat.h" +/** + * @class CProgram + * + * Parses a simple line based scriptfile with some limitations: + * first function (starting a block) must be a read-command, + * last must be a write-command (ending this block). + * + * read- and write-commands have hard coded parameters, number#1 being a filetype. + * Classes handling certain filetypes must be of type CFile. + * Custom functions will be passed to CFile::callFunc(). + * + * On error ParserError will be thrown. + */ +class CProgram +{ + public: + + /** + * @method CProgram + * @brief Default ctor + * @param programfile filename + * @return - + * @globalvars none + * @exception bad_alloc + * @conditions none + */ + CProgram(const std::string& progfile); + + /** + * @method ~CScriptparser + * @brief Default dtor + * @param - + * @return - + * @globalvars none + * @exception none + * @conditions none + */ + ~CProgram(); + + CDat getMaxProgramCount() + { + return CDat(m_progsource.size()); + } + + std::vector& getInstruction(CDat linenr) + { + return m_progsource[linenr.getTypeValue()]; + } + + std::map& getJumpAddrs() + { + return m_jumpaddr; + } +#ifdef DEBUG + /** + * @method dump + * @brief Dumps the program source to ostream + * @param out output stream + * @return - + * @globalvars + * @exception + * @conditions + */ + void dump(std::ostream& out); +#endif + + protected: + /** + * @method parse + * @brief parse the program file + * @param - + * @return - + * @globalvars none + * @exception ParserError + * @conditions none + */ + void parse(); + + private: + /* members */ + std::string m_programfile; + std::vector > m_progsource; + std::map m_jumpaddr; +}; + +#endif + +/* vim: set et sw=2 ts=2: */ diff --git a/ue3/mycpu/mycpu.cpp b/ue3/mycpu/mycpu.cpp new file mode 100644 index 0000000..af6fe08 --- /dev/null +++ b/ue3/mycpu/mycpu.cpp @@ -0,0 +1,94 @@ +/** + * @module mycpu + * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) + * @brief mycpu reads a program file and optional a memory file given as + * commandline option. + * On error (e.g. unknown function) the program will terminate + * @date 11.05.2009 + * @par Exercise + * 3 + */ + +#include +#include +#include "ccpu.h" + +using namespace std; +namespace po = boost::program_options; + +/** + * @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 + * @conditions none + * + * setup commandline options, parse them and pass scriptfile to scriptparser + * instance. 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") + ("progfile,c", po::value(), "program file") + ("memfile,m", po::value(), "memory file"); + + /* 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 << "Error: " << ex.what() << endl; + } + + /* print usage upon request or missing params */ + if (vm.count("help") || !vm.count("progfile")) + { + cout << "Usage: " << me << " -c [ -m ]" << endl; + cout << desc << endl; + if ( vm.count("help")) + return 0; + return 1; + } + + string memfile(""); + if (vm.count("memfile")) + memfile = vm["memfile"].as(); + + CCPU cpu(vm["progfile"].as(), memfile); + cpu.proceed(); + +/* CScriptparser parser(vm["c"].as()); + try + { + parser.parse(); + } + catch(CScriptparser::ParserError& ex) + { + cerr << me << ": Error while processing scriptfile: " << ex.what() << endl; + if (!ex.getLine().empty()) + cerr << "Scriptline: '" << ex.getLine() << "'" << endl; + return 1; + } + catch(exception& ex) + { + cerr << me << ": Unexpected exception: " << ex.what() << endl; + return 1; + }*/ + + return 0; +} + +/* vim: set et sw=2 ts=2: */ diff --git a/ue3/mycpu/test/test_prog b/ue3/mycpu/test/test_prog new file mode 100644 index 0000000..7c5f929 --- /dev/null +++ b/ue3/mycpu/test/test_prog @@ -0,0 +1,13 @@ +# set R2 = 10 +load R1, R2 + +# start of loop +label Loop: +inc R3 +sub R4, R3, R2 +test R4 +jumpz EndLoop +write WDEZ, R3 +jumpa Loop + +label EndLoop: diff --git a/ue3/mycpu/test/test_prog_mem b/ue3/mycpu/test/test_prog_mem new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/ue3/mycpu/test/test_prog_mem @@ -0,0 +1 @@ +10 -- cgit v1.2.3