summaryrefslogtreecommitdiffstats
path: root/tpu.c
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-07-25 00:47:01 +0200
committerLouis Burda <quent.burda@gmail.com>2023-07-25 00:47:01 +0200
commit40d8eb449ed072b47bfbe953a191708f761c53a0 (patch)
tree63ed15404eb3acd99a9ca0f77654b2c97efe54d9 /tpu.c
parent29894d56e144223629e558070cbc52080e21342e (diff)
downloadtis100-40d8eb449ed072b47bfbe953a191708f761c53a0.tar.gz
tis100-40d8eb449ed072b47bfbe953a191708f761c53a0.zip
Reimplement value passing and improve curses ui
Diffstat (limited to 'tpu.c')
-rw-r--r--tpu.c161
1 files changed, 127 insertions, 34 deletions
diff --git a/tpu.c b/tpu.c
index 64ede3e..269476f 100644
--- a/tpu.c
+++ b/tpu.c
@@ -6,9 +6,23 @@
#include <stddef.h>
#include <string.h>
-/* NOTES:
- * do two passes (one with only movs) for 'async' ports, result is the same
- */
+const char *dir_reprs[] = {
+ "LEFT", "RIGHT", "UP", "DOWN"
+};
+
+const char *status_reprs[] = {
+ "IDLE", "RUN", "READ", "WRITE"
+};
+
+const char *inst_reprs[] = {
+ "NOP", "MOV", "SWP", "SAV", "ADD", "SUB",
+ "NEG", "JMP", "JEZ", "JNZ", "JGZ", "JLZ", "JRO"
+};
+
+const char *op_reprs[] = {
+ "ACC", "BAK", "NIL", "LEFT", "RIGHT",
+ "UP", "DOWN", "ANY", "LAST", "LIT", "<NAME>"
+};
static enum tpu_port_dir
op_to_dir(enum tpu_inst_op_type op)
@@ -109,28 +123,48 @@ label_map_get(struct label_map *map, const char *name)
}
void
+tpu_port_init(struct tpu_port *port)
+{
+ port->attached = false;
+ port->dst_port = NULL;
+ port->dst_tpu = NULL;
+ port->type = PORT_BIDI;
+ port->clr_post_run = false;
+ port->reading = false;
+ port->writing = false;
+ port->in = -1;
+ port->out = -1;
+}
+
+void
+tpu_port_deinit(struct tpu_port *port)
+{
+ /* empty */
+}
+
+void
tpu_init(struct tpu *tpu)
{
size_t i;
+ tpu->status = STATUS_IDLE;
+
tpu->x = 0;
tpu->y = 0;
- tpu->last = -1;
+
+ tpu->steps = 0;
+ tpu->idle_steps = 0;
+
+ tpu->pc = 0;
tpu->acc = 0;
tpu->bak = 0;
tpu->inst_cnt = 0;
- tpu->pc = 0;
- tpu->status = STATUS_IDLE;
label_map_init(&tpu->labels);
- for (i = 0; i < 4; i++) {
- tpu->ports[i].attached = false;
- tpu->ports[i].dst_port = NULL;
- tpu->ports[i].dst_tpu = NULL;
- tpu->ports[i].type = PORT_BIDI;
- tpu->ports[i].reading = false;
- tpu->ports[i].in = -1;
- tpu->ports[i].out = -1;
- }
+
+ tpu->last = -1;
+ tpu->io_port = -1;
+ for (i = 0; i < 4; i++)
+ tpu_port_init(&tpu->ports[i]);
}
void
@@ -195,18 +229,26 @@ void
tpu_update_ports(struct tpu *tpu)
{
struct tpu_port *port;
+ int i;
- if (tpu->read_port >= 0) {
- port = &tpu->ports[tpu->read_port];
- if (port->reading) {
- if (port->attached && port->dst_port->out >= 0) {
- port->in = port->dst_port->out;
- port->dst_port->out = -1;
- port->reading = false;
- }
- } else if (tpu->status == STATUS_RUN) {
+ for (i = 0; i < 4; i++) {
+ port = &tpu->ports[i];
+ if (!port->attached) continue;
+ if (port->out >= 0 && port->dst_port->in < 0) {
+ port->dst_port->reading = false;
+ port->dst_port->in = port->out;
+ port->writing = false;
+ port->out = -1;
+ }
+ if (port->dst_port->out >= 0 && port->in < 0) {
+ port->reading = false;
+ port->in = port->dst_port->out;
+ port->dst_port->writing = false;
+ port->dst_port->out = -1;
+ }
+ if (tpu->status == STATUS_RUN && port->clr_post_run) {
port->in = -1;
- tpu->read_port = -1;
+ port->clr_post_run = false;
}
}
}
@@ -268,9 +310,9 @@ tpu_add_inst(struct tpu *tpu, enum tpu_inst_type inst_type,
}
/* tpu can always write to an empty port (->out), but only
- * read values from a port (->in) if there is a writer attached
- * and offering a value (->dst_port->out). the read value (->in)
- * is cleared at the end of an instruction step */
+ * read values if there is a writer attached and offering a value
+ * (->dst_port->out) -- the read value (->in) is cleared at the end of
+ * an instruction step */
static int
tpu_port_read(struct tpu *tpu, enum tpu_port_dir dir)
@@ -278,9 +320,9 @@ tpu_port_read(struct tpu *tpu, enum tpu_port_dir dir)
struct tpu_port *port;
port = &tpu->ports[dir];
+ port->clr_post_run = true;
if (port->in < 0) {
port->reading = true;
- tpu->read_port = (int) dir;
return -1;
}
return port->in;
@@ -292,7 +334,10 @@ tpu_port_write(struct tpu *tpu, enum tpu_port_dir dir, uint8_t lit)
struct tpu_port *port;
port = &tpu->ports[dir];
- if (port->out >= 0) return false;
+ if (port->out >= 0) {
+ port->writing = true;
+ return false;
+ }
port->out = lit;
return true;
}
@@ -479,12 +524,21 @@ tpu_exec(struct tpu *tpu, struct tpu_inst *inst)
}
}
-void
+enum tpu_status
tpu_step(struct tpu *tpu)
{
- if (tpu->pc >= tpu->inst_cnt) return;
- tpu->status = tpu_exec(tpu, &tpu->insts[tpu->pc]);
- if (tpu->pc >= tpu->inst_cnt) tpu->pc = 0;
+ if (tpu->pc < tpu->inst_cnt) {
+ tpu->status = tpu_exec(tpu, &tpu->insts[tpu->pc]);
+ if (tpu->pc >= tpu->inst_cnt) tpu->pc = 0;
+ } else {
+ tpu->status = STATUS_IDLE;
+ }
+
+ tpu->steps += 1;
+ if (tpu->status != STATUS_RUN)
+ tpu->idle_steps += 1;
+
+ return tpu->status;
}
void
@@ -551,3 +605,42 @@ tpu_map_get(struct tpu_map *map, size_t x, size_t y)
return (*link)->tpu;
}
+
+void
+tis_init(struct tis *tis)
+{
+ tpu_map_init(&tis->tpu_map);
+ tpu_port_init(&tis->stdin_port);
+ tpu_port_init(&tis->stdout_port);
+}
+
+void
+tis_deinit(struct tis *tis)
+{
+ tpu_map_deinit(&tis->tpu_map);
+ tpu_port_deinit(&tis->stdin_port);
+ tpu_port_deinit(&tis->stdout_port);
+}
+
+bool
+tis_step(struct tis *tis)
+{
+ struct tpu_map_link *link;
+ bool running;
+ size_t i;
+
+ running = false;
+ for (i = 0; i < TPU_MAP_BUCKETS; i++) {
+ link = tis->tpu_map.buckets[i];
+ for (; link; link = link->next)
+ running |= (tpu_step(link->tpu) == STATUS_RUN);
+ }
+
+ for (i = 0; i < TPU_MAP_BUCKETS; i++) {
+ link = tis->tpu_map.buckets[i];
+ for (; link; link = link->next)
+ tpu_update_ports(link->tpu);
+ }
+
+ return running;
+}