diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | emulator.cpp | 100 | ||||
-rw-r--r-- | emulator.h | 35 | ||||
-rw-r--r-- | evaluator.cpp | 40 | ||||
-rw-r--r-- | evaluator.h | 20 | ||||
-rw-r--r-- | inst_loader.cpp | 5 | ||||
-rw-r--r-- | inst_loader.h | 2 | ||||
-rw-r--r-- | instruction.cpp | 26 | ||||
-rw-r--r-- | instruction.h | 28 | ||||
-rw-r--r-- | main.cpp | 16 | ||||
-rw-r--r-- | reg.cpp | 14 | ||||
-rw-r--r-- | reg.h | 46 | ||||
-rw-r--r-- | register_address.cpp | 49 | ||||
-rw-r--r-- | register_address.h | 38 | ||||
-rw-r--r-- | test_loader.cpp | 47 | ||||
-rw-r--r-- | test_loader.h | 6 | ||||
-rw-r--r-- | value.cpp | 104 | ||||
-rw-r--r-- | value.h | 46 |
18 files changed, 498 insertions, 127 deletions
@@ -1,8 +1,9 @@ +CXXFLAGS+=-g -Wall DEPS := $(OBJS:.o=.d) -include $(DEPS) -debugger: instruction.o reg.o test_loader.o +debugger: main.o evaluator.o emulator.o value.o instruction.o register_address.o test_loader.o g++ -o $@ $^ %.o: %.cpp diff --git a/emulator.cpp b/emulator.cpp new file mode 100644 index 0000000..f2cef7f --- /dev/null +++ b/emulator.cpp @@ -0,0 +1,100 @@ + +#include <iostream> +#include <assert.h> + +#include "emulator.h" + +#include "inst_loader.h" +#include "instruction.h" +#include "register_address.h" + +emulator::emulator( + inst_loader * loader, + int num_temp_regs, + int num_const_regs, + int num_out_regs) + : + m_loader(loader), + m_temp_regs(num_temp_regs), + m_const_regs(num_const_regs, new float_value()), + m_out_regs(num_out_regs) + { } + +void +emulator::run() +{ + std::vector<instruction *> * insts = m_loader->load(); + std::vector<instruction *>::iterator it; + for(it = insts->begin(); it < insts->end(); ++it) { + (*it)->execute(*this); + } +} + +void +emulator::set_constants(float value) +{ + std::vector<float_value *>::iterator it; + for(it = m_const_regs.begin(); it < m_const_regs.end(); ++it) { + (*it)->set_value(value); + } +} + +value * +emulator::get_value(register_address addr) +{ + unsigned int index = calc_reg_index(addr.m_index, addr.m_swizzle); + + switch(addr.m_type) { + case REGISTER_TYPE_TEMP: std::cout << m_temp_regs[index]->to_string() << "\n"; return m_temp_regs[index]->clone(); + case REGISTER_TYPE_CONST: + { + float_value * val = m_const_regs[index]; + std::cout << val->to_string() << "\n"; + if (val->m_has_value) { + return new float_value(*val); + } else { + return new const_value(addr, val); + } + } + case REGISTER_TYPE_OUT: return m_out_regs[index]->clone(); + default: + assert(0); + return NULL; + } +} + +void +emulator::set_value( + register_address addr, + value * val) +{ + unsigned int index = calc_reg_index(addr.m_index, addr.m_swizzle); + + switch(addr.m_type) { + case REGISTER_TYPE_TEMP: + delete m_temp_regs[index]; + m_temp_regs[index] = val; + break; + case REGISTER_TYPE_OUT: + delete m_out_regs[index]; + m_out_regs[index] = val; + break; + default: + assert(0); + } +} + +value * +emulator::get_output_value(int index) +{ + //XXX: Make sure not to go over bounds. + return m_out_regs[index]->simplify(); +} + +unsigned int +emulator::calc_reg_index( + unsigned int index, + enum swizzle swz) +{ + return (index * 4) + (swz - 1); +} @@ -2,11 +2,38 @@ #ifndef EMULATOR_H_ #define EMULATOR_H_ +#include <vector> + +#include "value.h" + +class inst_loader; + class emulator { +public: + emulator( + inst_loader * loader, + int num_temp_regs, + int num_const_regs, + int num_out_regs); + + + void run(); + void set_constants(float value); + value * get_value(register_address addr); + void set_value( + register_address addr, + value * val); + value * get_output_value(int index); + private: - inst_loader loader; - vector<reg> temp_regs; - vector<reg> out_regs; + unsigned int calc_reg_index( + unsigned int index, + enum swizzle swz); + + inst_loader * m_loader; + std::vector<value *> m_temp_regs; + std::vector<float_value *> m_const_regs; + std::vector<value *> m_out_regs; }; -#endif //EMULATOR_H_ +#endif //EMULATOR_H diff --git a/evaluator.cpp b/evaluator.cpp new file mode 100644 index 0000000..1356258 --- /dev/null +++ b/evaluator.cpp @@ -0,0 +1,40 @@ +#include "evaluator.h" + +#include "value.h" + +evaluator::evaluator(const char * display_name) : + m_display_name(display_name) + { } + +value * +evaluator::evaluate( + value * l, + value * r) +{ + return new tree_value(this, l, r); +} + +std::string +evaluator::to_string() +{ + return m_display_name; +} + +add_evaluator::add_evaluator() : + evaluator("+") + { } + +value * +add_evaluator::evaluate( + float_value * l, + float_value * r) +{ + float_value * new_val; + if (!l->m_has_value || !r->m_has_value) { + return this->evaluator::evaluate(l, r); + } + + new_val = new float_value(); + new_val->set_value(l->m_value + r->m_value); + return new_val; +} diff --git a/evaluator.h b/evaluator.h index f3bbe41..e64f27b 100644 --- a/evaluator.h +++ b/evaluator.h @@ -2,11 +2,27 @@ #ifndef EVALUATOR_H_ #define EVALUATOR_H_ -class value; +#include <string> + +#include "value.h" class evaluator { public: - virtual void evaluate(value l, value r); + evaluator(const char * display_name); + virtual value * evaluate( + value * l, + value * r); + + virtual std::string to_string(); +private: + const char * m_display_name; }; +class add_evaluator : public evaluator{ +public: + add_evaluator(); + value * evaluate( + float_value * l, + float_value * r); +}; #endif //EVALUATOR_H_ diff --git a/inst_loader.cpp b/inst_loader.cpp index 928d3f3..49c95d9 100644 --- a/inst_loader.cpp +++ b/inst_loader.cpp @@ -2,8 +2,3 @@ #include "inst_loader.h" -vector<instruction> inst_loader::load() -{ - vector<instruction> * instructions = new vector<instruction>(); - instructions->push_back( -} diff --git a/inst_loader.h b/inst_loader.h index 67976f5..c668a7e 100644 --- a/inst_loader.h +++ b/inst_loader.h @@ -6,7 +6,7 @@ class inst_loader { public: - virtual std::vector<instruction> * load() = 0; + virtual std::vector<instruction *> * load() = 0; }; #endif //INST_LOADER_H_ diff --git a/instruction.cpp b/instruction.cpp index bd754d7..b4bf727 100644 --- a/instruction.cpp +++ b/instruction.cpp @@ -1,22 +1,34 @@ - #include "instruction.h" +#include "emulator.h" + instruction::instruction( const char * name, evaluator * evaluator, - std::vector<reg::address> dst) : + std::vector<register_address> dst) : m_name(name), m_evaluator(evaluator), m_dst(dst) { } - add_instruction::add_instruction( - std::vector<reg::address> dst, - std::vector<reg::address> src0, - std::vector<reg::address> src1) + std::vector<register_address> dst, + std::vector<register_address> src0, + std::vector<register_address> src1) : - instruction("ADD", new evaluator(), dst), + instruction("ADD", new add_evaluator(), dst), m_src0(src0), m_src1(src1) { } + +void +add_instruction::execute(emulator & emulator) +{ + unsigned int i; + for (i = 0; i < m_dst.size(); i++) { + tree_value * val = new tree_value(this->m_evaluator, + emulator.get_value(m_src0[i]), + emulator.get_value(m_src1[i])); + emulator.set_value(m_dst[i], val); + } +} diff --git a/instruction.h b/instruction.h index 09d6594..c1222be 100644 --- a/instruction.h +++ b/instruction.h @@ -5,34 +5,30 @@ #include <vector> #include "evaluator.h" -#include "reg.h" +#include "register_address.h" + +class emulator; class instruction { public: - instruction(const char * name, evaluator * evaluator, std::vector<reg::address> dst); + instruction(const char * name, evaluator * evaluator, std::vector<register_address> dst); + virtual void execute(emulator & emulator) = 0; protected: const char * m_name; evaluator * m_evaluator; - std::vector<reg::address> m_dst; -}; - -class add_instruction : public instruction{ -public: - add_instruction(std::vector<reg::address> dst, std::vector<reg::address>, - std::vector<reg::address> src1); - -private: - std::vector<reg::address> m_src0; - std::vector<reg::address> m_src1; + std::vector<register_address> m_dst; }; -class mov_instruction { +class add_instruction : public instruction { public: - mov_instruction(reg dst[4], reg src0[4]); + add_instruction(std::vector<register_address> dst, std::vector<register_address>, + std::vector<register_address> src1); + void execute(emulator & emulator); private: - reg src0[4]; + std::vector<register_address> m_src0; + std::vector<register_address> m_src1; }; #endif //INSTRUCTION_H_ diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..e0bf367 --- /dev/null +++ b/main.cpp @@ -0,0 +1,16 @@ + +#include <stdio.h> +#include <stdlib.h> + +#include "emulator.h" +#include "test_loader.h" + +int main(int argc, char ** argv) +{ + test_loader * loader = new test_loader(); + emulator * em = new emulator(loader, 1024, 256, 16); + + em->run(); + em->set_constants(0.5); + fprintf(stderr, "Ouput= %s\n", em->get_output_value(0)->to_string().c_str()); +} diff --git a/reg.cpp b/reg.cpp deleted file mode 100644 index ea81b21..0000000 --- a/reg.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -#include "reg.h" - -reg::address::address( - reg_type type, - unsigned int index, - enum swizzle swizzle) - : - m_type(type), - m_index(index), - m_swizzle(swizzle) - { } - -reg::~reg() { } @@ -1,46 +0,0 @@ - -#ifndef REG_H_ -#define REG_H_ - -#include "value.h" - -enum reg_type { - REG_TYPE_TEMP, - REG_TYPE_CONST, - REG_TYPE_IN, - REG_TYPE_OUT -}; - -enum swizzle { - SWIZZLE_EMPTY, - SWIZZLE_X, - SWIZZLE_Y, - SWIZZLE_Z, - SWIZZLE,W -}; - -class reg { -public: - - class address { - public : - address( - reg_type type, - unsigned int index, - enum swizzle swizzle); - - reg_type m_type; - unsigned int m_index; - enum swizzle m_swizzle; - }; - -public: - reg(reg_type type, unsigned int index, enum swizzle swizzle); - ~reg(); - -private: - address m_address; - value m_value; -}; - -#endif //REG_H_ diff --git a/register_address.cpp b/register_address.cpp new file mode 100644 index 0000000..e499da2 --- /dev/null +++ b/register_address.cpp @@ -0,0 +1,49 @@ +#include <sstream> + +#include "register_address.h" + +register_address::register_address( + register_type type, + unsigned int index, + enum swizzle swizzle) + : + m_type(type), + m_index(index), + m_swizzle(swizzle) + { } + +std::string +register_address::to_string() +{ + std::ostringstream s; + + s << register_address::register_type_to_string(m_type) << "[" << m_index << "]." << + swizzle_to_string(m_swizzle); + + return s.str(); +} + +std::string +register_address::register_type_to_string(enum register_type type) +{ + switch(type) { + case REGISTER_TYPE_TEMP: return "TEMP"; + case REGISTER_TYPE_CONST: return "CONST"; + case REGISTER_TYPE_IN: return "IN"; + case REGISTER_TYPE_OUT: return "OUT"; + default: return "NONE"; + } +} + +std::string +register_address::swizzle_to_string(enum swizzle swz) +{ + switch(swz) { + case SWIZZLE_EMPTY: return "_"; + case SWIZZLE_X: return "x"; + case SWIZZLE_Y: return "y"; + case SWIZZLE_Z: return "z"; + case SWIZZLE_W: return "w"; + default: return "?"; + } +} diff --git a/register_address.h b/register_address.h new file mode 100644 index 0000000..c6f4cd0 --- /dev/null +++ b/register_address.h @@ -0,0 +1,38 @@ + +#ifndef REGISTER_ADDRESS_H_ +#define REGISTER_ADDRESS_H_ + +enum register_type { + REGISTER_TYPE_TEMP, + REGISTER_TYPE_CONST, + REGISTER_TYPE_IN, + REGISTER_TYPE_OUT +}; + +enum swizzle { + SWIZZLE_EMPTY, + SWIZZLE_X, + SWIZZLE_Y, + SWIZZLE_Z, + SWIZZLE_W +}; + +class register_address { +public: + + register_address( + register_type type, + unsigned int index, + enum swizzle swizzle); + + std::string to_string(); + + static std::string register_type_to_string(enum register_type type); + static std::string swizzle_to_string(enum swizzle swz); + + register_type m_type; + unsigned int m_index; + enum swizzle m_swizzle; +}; + +#endif //REGISTER_ADDRESS_H_ diff --git a/test_loader.cpp b/test_loader.cpp index abdc2b6..c0fce86 100644 --- a/test_loader.cpp +++ b/test_loader.cpp @@ -3,6 +3,8 @@ #include "test_loader.h" +#include "register_address.h" + std::vector<enum swizzle> test_loader::XYZ() { @@ -13,40 +15,39 @@ test_loader::XYZ() return XYZ; } -std::vector<reg::address> +std::vector<register_address> test_loader::make_register( - reg_type type, + register_type type, unsigned int index, std::vector<enum swizzle> swizzles) { - std::vector<reg::address> new_register; + std::vector<register_address> new_register; std::vector<enum swizzle>::iterator it; for(it = swizzles.begin(); it < swizzles.end(); ++it) { - new_register.push_back(reg::address(type, index, *it)); + new_register.push_back(register_address(type, index, *it)); } + return new_register; } -std::vector<instruction> * +std::vector<instruction *> * test_loader::load() { - reg_type type_scr0; - unsigned int index_src0; - std::vector<instruction> * instructions = new std::vector<instruction>(); - - instructions->push_back(add_instruction( - make_register(REG_TYPE_TEMP, 0, XYZ()), - make_register(REG_TYPE_CONST, 0, XYZ()), - make_register(REG_TYPE_CONST, 0, XYZ()))); - - instructions->push_back(add_instruction( - make_register(REG_TYPE_TEMP, 0, XYZ()), - make_register(REG_TYPE_TEMP, 0, XYZ()), - make_register(REG_TYPE_CONST, 0, XYZ()))); - - instructions->push_back(add_instruction( - make_register(REG_TYPE_OUT, 0, XYZ()), - make_register(REG_TYPE_TEMP, 0, XYZ()), - make_register(REG_TYPE_TEMP, 0, XYZ()))); + std::vector<instruction *> * instructions = new std::vector<instruction *>(); + + instructions->push_back(new add_instruction( + make_register(REGISTER_TYPE_TEMP, 0, XYZ()), + make_register(REGISTER_TYPE_CONST, 0, XYZ()), + make_register(REGISTER_TYPE_CONST, 0, XYZ()))); + + instructions->push_back(new add_instruction( + make_register(REGISTER_TYPE_TEMP, 0, XYZ()), + make_register(REGISTER_TYPE_TEMP, 0, XYZ()), + make_register(REGISTER_TYPE_CONST, 0, XYZ()))); + + instructions->push_back(new add_instruction( + make_register(REGISTER_TYPE_OUT, 0, XYZ()), + make_register(REGISTER_TYPE_TEMP, 0, XYZ()), + make_register(REGISTER_TYPE_TEMP, 0, XYZ()))); return instructions; } diff --git a/test_loader.h b/test_loader.h index 930e091..95e7b76 100644 --- a/test_loader.h +++ b/test_loader.h @@ -8,11 +8,11 @@ class test_loader : public inst_loader { public: - std::vector<instruction> * load(); + std::vector<instruction *> * load(); private: std::vector<enum swizzle> XYZ(); - std::vector<reg::address> make_register( - reg_type type, + std::vector<register_address> make_register( + register_type type, unsigned int index, std::vector<enum swizzle> swizzles); }; diff --git a/value.cpp b/value.cpp new file mode 100644 index 0000000..f210dd1 --- /dev/null +++ b/value.cpp @@ -0,0 +1,104 @@ +#include <sstream> + +#include "value.h" + +#include "evaluator.h" + +tree_value::tree_value( + evaluator * evaluator, + value * lchild, + value * rchild) + : + m_evaluator(evaluator), + m_lchild(lchild), + m_rchild(rchild) + { } + +value * +tree_value::simplify() +{ + if (!m_evaluator) { + return this->clone(); + } + return m_evaluator->evaluate(m_lchild->simplify(), m_rchild->simplify()); +} + +value * +tree_value::clone() +{ + return new tree_value(m_evaluator, + (m_lchild ? m_lchild->clone() : NULL), + (m_rchild ? m_rchild->clone() : NULL)); +} + +std::string +tree_value::to_string() +{ + return "(" + (m_lchild ? m_lchild->to_string() : "?") + ") " + + (m_evaluator ? m_evaluator->to_string() : "?") + " (" + + (m_rchild ? m_rchild->to_string() : "?") + ")"; +} + +const_value::const_value( + register_address address, + float_value * value_ptr) : + value(), + m_reg_address(address), + m_value(value_ptr) + { } + +value * +const_value::simplify() +{ + if (m_value->m_has_value) { + return m_value->clone(); + } else { + return this->clone(); + } +} + +value * +const_value::clone() +{ + return new const_value(m_reg_address, m_value); +} + +std::string +const_value::to_string() +{ + return m_reg_address.to_string(); +} +float_value::float_value() : + m_has_value(false) + { } + +value * +float_value::simplify() +{ + return this; +} + +value * +float_value::clone() +{ + return new float_value(*this); +} + +std::string +float_value::to_string() +{ + std::ostringstream s; + if (!m_has_value) { + s << "?"; + } else { + s << m_value; + } + return s.str(); +} + +void +float_value::set_value(float value) +{ + m_has_value = true; + m_value = value; +} @@ -2,20 +2,56 @@ #ifndef VALUE_H_ #define VALUE_H_ +#include <string> + +#include "register_address.h" + class evaluator; -class reg; class value { +public: + virtual value * simplify() = 0; + virtual value * clone() = 0; + virtual std::string to_string() = 0; -protected: +}; + +class tree_value : public value { +public: + tree_value(evaluator *, value * lchild, value * rchild); + value * simplify(); + value * clone(); + std::string to_string(); +private: evaluator * m_evaluator; - value & m_lchild; - value & m_rchild; + value * m_lchild; + value * m_rchild; +}; + +class float_value : public value { +public: + float_value(); + value * simplify(); + value * clone(); + std::string to_string(); + + void set_value(float value); + + bool m_has_value; + float m_value; }; class const_value : public value { +public: + const_value( + register_address reg, + float_value * value); + value * simplify(); + value * clone(); + std::string to_string(); private: - reg * const_reg; + register_address m_reg_address; + float_value * m_value; }; #endif //VALUE_H_ |