1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
#include <vector>
#include <queue>
#include <string>
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
BUFINCLR, // clears whatever is in the input buffer
BUFOUTCLR, // clears whatever is in the output 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, pri COPY je že
}; // 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:
public:
vector<value_type> storage;
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 vektorja in posledično binarne datoteke.
* 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:
public:
vector<value_type> storage;
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) { // add bound checks
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 [sizeof(struct instr)]);
void deserialize (istream &, unsigned int);
string serialize (struct instr * i, unsigned int);
void pd (ostream &);
};
}
|