diff options
| author | Louis Burda <quent.burda@gmail.com> | 2023-07-25 00:47:01 +0200 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2023-07-25 00:47:01 +0200 |
| commit | 40d8eb449ed072b47bfbe953a191708f761c53a0 (patch) | |
| tree | 63ed15404eb3acd99a9ca0f77654b2c97efe54d9 /tpu.c | |
| parent | 29894d56e144223629e558070cbc52080e21342e (diff) | |
| download | tis100-40d8eb449ed072b47bfbe953a191708f761c53a0.tar.gz tis100-40d8eb449ed072b47bfbe953a191708f761c53a0.zip | |
Reimplement value passing and improve curses ui
Diffstat (limited to 'tpu.c')
| -rw-r--r-- | tpu.c | 161 |
1 files changed, 127 insertions, 34 deletions
@@ -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; +} |
