#include <vector>
#include <queue>
namespace ov {
using namespace std;
enum opts { // opts are pas-1 bits aftr last ram ptr (2**ras)-1 and can be w/r from prg
DEFAULT,
BUFOUT, // output from program in VM is always possible and no blocks
BUFIN, // input to program in VM is always possible and no blocks
BUFCLR, // clears whatever is in the buffer
OPTSLEN
}; // read those last bits with the COPY instruction with source/dest on last pointer
enum iobits {
INA, // input available, clear when read
IN, // input bit
OUTA, // output available, set when have output, cleared by VM when wrote
OUT, // output bit
IOLEN
};
enum instrs {
COPY,
NAND
};
struct instr { // deserializirana inštrukcija
unsigned int s = 0; // source
unsigned int d = 0; // destination
bool i = 0; // instruction
bool p = 0; // enobitni padding, lahko za metainštrukcije
}; // privzeto inicializiran na NOOP inštrukcijo
template<typename value_type, typename index_type, class Memory> class Mmu {
private:
class Cell {
private:
friend class Mmu;
Mmu & mmu;
index_type index;
Cell (Mmu & mmu, index_type index)
: mmu(mmu), index(index) {}
public:
operator value_type (void) {
return mmu.memory.peek(index);
}
value_type operator= (value_type value) {
mmu.memory.poke(index, value);
return value;
}
};
public:
Memory & memory;
Mmu (Memory & memory) : memory(memory) {}
Cell operator[] (index_type index) {
return Cell(*this, index);
}
value_type & operator() (index_type index) {
return memory.peek(index);
}
};
class Ov;
template<typename value_type, typename index_type> class Ram {
private:
vector<value_type> storage;
public:
Ov * ov;
value_type peek (index_type);
void poke(index_type, value_type);
Ram (Ov *);
};
/* v Program (memory) bi lahko uporabili metainštrukcije (tisti padding bit) v
* vsaki inštrukciji in v metainštrukcijah reprezentirali assembly org (lokacijo).
* s tem bi lahko imeli npr. 128 biten program counter in s tem zelo preproste jumpe,
* ne bi pa bilo treba narediti 2^128 vektor in posledično binarno datoteko.
* Tak način bi bilo verjetno težko implementirati na dejanski strojni opremi,
* tukaj pa bi v enem passu čez cel deserializan program memory zaznali te org
* metainštrukcije in naredili neko tabelo oziroma prevajalnik program counterja
* v lokacijo v vektorju. problem je, da bi se morala prevajalska tabela vsakič znova
* regenerirati, ko spreminjamo program memory.
* */
template<typename value_type, typename index_type> class Program {
private:
vector<value_type> storage;
public:
Ov * ov;
value_type & peek (index_type addr) {
return storage[addr];
}
void poke (index_type addr, value_type val) {
storage[addr] = val;
}
Program (Ov *);
};
class Ov {
private:
public:
queue<bool> inbuf;
queue<bool> outbuf;
#define IS2RAS(is) ((is*8-2)/2)
class ras { // IS
private: // IT
public: // REALLY
unsigned short int & is; // THIS
operator unsigned short int (void) { // HARD
return IS2RAS(is); // TO
} // DEFINE
ras (class Ov * ov) : is(ov->is) {} // A
}; // GETTER
ras ras{this}; // FUNCTION
class rs {
private:
public:
unsigned short int & is;
operator unsigned int (void) {
return 1 << IS2RAS(is);
}
rs (class Ov * ov) : is(ov->is) {}
};
rs rs{this};
class ps {
private:
public:
unsigned short int & pas;
operator unsigned int (void) {
return 1 << pas;
}
ps (class Ov * ov) : pas(ov->pas) {}
};
ps ps{this};
unsigned short int is;
unsigned short int pas;
bool io[IOLEN];
bool opts[OPTSLEN];
unsigned int pc = 0; /* where the program starts --- at zero or where? */
Ram<bool, unsigned int> rstor{this};
Mmu<bool, unsigned int, class Ram<bool, unsigned int>> ram{rstor};
Program<struct instr, unsigned int> pstor{this};
Mmu<struct instr, unsigned, class Program<struct instr, unsigned>> pm{pstor};
Ov (unsigned short int is = 2, unsigned short int pas = 16)
: is(is), pas(pas) {
for (int i = 0; i < OPTSLEN; i++)
opts[i] = 0;
for (int i = 0; i < IOLEN; i++)
io[i] = 0;
}
void step (void);
bool out (void);
char outc (void);
void in (bool);
void inc (char);
struct instr deserialize (const char *);
void deserialize (istream &, unsigned int);
void pd (ostream); // print debug
};
}