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
|
// Author: Paul Oliver <contact@pauloliver.dev>
// Project: salis-v3
// Defines a minimal viable architecture for the Salis VM.
// Useful for debugging and benchmarking. May be used as a template when
// implementing a new architecture.
{% if args.command in ["bench", "new"] and anc_bytes is defined %}
void arch_core_init(struct Core *core) {
assert(core);
{% if arch_vars.mvec_loop %}
uint64_t addr = {{ uint64_half }};
{% else %}
uint64_t addr = 0;
{% endif %}
for (uint64_t i = 0; i < {{ args.clones }}; ++i) {
uint64_t addr_clone = addr + (({{ mvec_size }} / {{ args.clones }})) * i;
struct Proc *panc = proc_fetch(core, i);
panc->mb0a = addr_clone;
panc->mb0s = {{ anc_bytes|length }};
panc->ip = addr_clone;
panc->sp = addr_clone;
}
}
{% endif %}
{% if args.command in ["load", "new"] %}
void arch_core_save(FILE *f, const struct Core *core) {
assert(f);
assert(core);
(void)f;
(void)core;
}
{% endif %}
{% if args.command in ["load"] %}
void arch_core_load(FILE *f, struct Core *core) {
assert(f);
assert(core);
(void)f;
(void)core;
}
{% endif %}
uint64_t arch_proc_mb0_addr(const struct Core *core, uint64_t pix) {
assert(core);
assert(mvec_proc_is_live(core, pix));
return proc_get(core, pix)->mb0a;
}
uint64_t arch_proc_mb0_size(const struct Core *core, uint64_t pix) {
assert(core);
assert(mvec_proc_is_live(core, pix));
return proc_get(core, pix)->mb0s;
}
uint64_t arch_proc_mb1_addr(const struct Core *core, uint64_t pix) {
assert(core);
assert(mvec_proc_is_live(core, pix));
return proc_get(core, pix)->mb1a;
}
uint64_t arch_proc_mb1_size(const struct Core *core, uint64_t pix) {
assert(core);
assert(mvec_proc_is_live(core, pix));
return proc_get(core, pix)->mb1s;
}
uint64_t arch_proc_ip_addr(const struct Core *core, uint64_t pix) {
assert(core);
assert(mvec_proc_is_live(core, pix));
return proc_get(core, pix)->ip;
}
uint64_t arch_proc_sp_addr(const struct Core *core, uint64_t pix) {
assert(core);
assert(mvec_proc_is_live(core, pix));
return proc_get(core, pix)->sp;
}
uint64_t arch_proc_slice(const struct Core *core, uint64_t pix) {
assert(core);
assert(mvec_proc_is_live(core, pix));
(void)core;
(void)pix;
return 1;
}
void arch_on_proc_kill(struct Core *core) {
assert(core);
assert(core->pnum > 1);
(void)core;
}
void arch_proc_step(struct Core *core, uint64_t pix) {
assert(core);
assert(mvec_proc_is_live(core, pix));
(void)core;
(void)pix;
return;
}
{% if not args.optimized %}
void arch_validate_proc(const struct Core *core, uint64_t pix) {
assert(core);
assert(mvec_proc_is_live(core, pix));
(void)core;
(void)pix;
assert(true);
}
{% endif %}
wchar_t arch_symbol(uint8_t inst) {
switch (inst) {
{% for i in arch_vars.inst_set %}
case {{ loop.index0 }}: return L'{{ i[1] }}';
{% endfor %}
}
}
const char *arch_mnemonic(uint8_t inst) {
switch (inst) {
{% for i in arch_vars.inst_set %}
case {{ loop.index0 }}: return "{{ i[0]|join(' ') }}";
{% endfor %}
}
}
{% if data_push_path is defined %}
void arch_push_data_header() {
assert(g_sim_data);
}
void arch_push_data_line() {
assert(g_sim_data);
}
{% endif %}
|