summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--emulator.cpp100
-rw-r--r--emulator.h35
-rw-r--r--evaluator.cpp40
-rw-r--r--evaluator.h20
-rw-r--r--inst_loader.cpp5
-rw-r--r--inst_loader.h2
-rw-r--r--instruction.cpp26
-rw-r--r--instruction.h28
-rw-r--r--main.cpp16
-rw-r--r--reg.cpp14
-rw-r--r--reg.h46
-rw-r--r--register_address.cpp49
-rw-r--r--register_address.h38
-rw-r--r--test_loader.cpp47
-rw-r--r--test_loader.h6
-rw-r--r--value.cpp104
-rw-r--r--value.h46
18 files changed, 498 insertions, 127 deletions
diff --git a/Makefile b/Makefile
index 4c65015..69c051b 100644
--- a/Makefile
+++ b/Makefile
@@ -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);
+}
diff --git a/emulator.h b/emulator.h
index c47d4f5..48ddff4 100644
--- a/emulator.h
+++ b/emulator.h
@@ -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() { }
diff --git a/reg.h b/reg.h
deleted file mode 100644
index 8d67367..0000000
--- a/reg.h
+++ /dev/null
@@ -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;
+}
diff --git a/value.h b/value.h
index 34484a8..ba1eae1 100644
--- a/value.h
+++ b/value.h
@@ -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_