Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 814325e

Browse files
committedMar 28, 2018
IO overhaul
IO pseudonodes now behave correctly Timings are correct Zero rows is now valid, to do translation (or cat)
1 parent 8887af1 commit 814325e

File tree

5 files changed

+172
-17
lines changed

5 files changed

+172
-17
lines changed
 

‎tis.c

+63-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "tis_types.h"
1010
#include "tis_node.h"
11+
#include "tis_io.h"
1112

1213
#define INIT_OK 0
1314
#define INIT_FAIL 1
@@ -85,11 +86,11 @@ int init_layout(tis_t* tis, char* layoutfile, int layoutmode) {
8586

8687
tis->size = tis->rows*tis->cols;
8788

88-
if(tis->size == 0) {
89+
if(tis->cols == 0) {
8990
if(layout != NULL) {
9091
fclose(layout);
9192
}
92-
error("Cannot initialize with zero rows or columns\n"); // But zero rows are fine, right? TODO this would mean I have to run the outputs separately from the bottom row
93+
error("Cannot initialize with zero columns\n"); // But zero rows are fine, it works as a translator: printf "hello" | ./tis -l /dev/null "0 1 I0 ASCII - O0 NUMERIC - 10"
9394
return INIT_FAIL;
9495
}
9596

@@ -164,7 +165,9 @@ int init_layout(tis_t* tis, char* layoutfile, int layoutmode) {
164165
}
165166
mode = 0;
166167
tis->inputs[index] = calloc(1, sizeof(tis_io_node_t));
168+
tis->inputs[index]->col = index;
167169
tis->inputs[index]->type = TIS_IO_TYPE_INVALID;
170+
tis->inputs[index]->writereg = TIS_REGISTER_INVALID;
168171
} else if(fscanf(layout, " O%zu ", &index) == 1) {
169172
debug("Found an output for index %zu\n", index);
170173
if(index >= tis->cols) {
@@ -174,6 +177,9 @@ int init_layout(tis_t* tis, char* layoutfile, int layoutmode) {
174177
}
175178
mode = 1;
176179
tis->outputs[index] = calloc(1, sizeof(tis_io_node_t));
180+
tis->outputs[index]->col = index;
181+
tis->outputs[index]->type = TIS_IO_TYPE_INVALID;
182+
tis->outputs[index]->writereg = TIS_REGISTER_INVALID;
177183
} else if(fscanf(layout, " %"STR(BUFSIZE)"s ", buf) == 1) { // The format string is " %128s ", but changes with BUFSIZE
178184
switch(mode) {
179185
case 0:
@@ -279,13 +285,17 @@ int init_layout(tis_t* tis, char* layoutfile, int layoutmode) {
279285
}
280286
// set first input to TIS_IO_TYPE_IOSTREAM_NUMERIC
281287
tis->inputs[0] = calloc(1, sizeof(tis_io_node_t));
288+
tis->inputs[0]->col = 0;
282289
tis->inputs[0]->type = opts.default_i_type;
283290
tis->inputs[0]->file.file = stdin;
291+
tis->inputs[0]->writereg = TIS_REGISTER_INVALID;
284292
// set last output to TIS_IO_TYPE_IOSTREAM_NUMERIC
285293
tis->outputs[tis->cols - 1] = calloc(1, sizeof(tis_io_node_t));
294+
tis->outputs[tis->cols - 1]->col = tis->cols - 1;
286295
tis->outputs[tis->cols - 1]->type = opts.default_o_type;
287296
tis->outputs[tis->cols - 1]->file.file = stdout;
288297
tis->outputs[tis->cols - 1]->file.sep = '\n';
298+
tis->outputs[tis->cols - 1]->writereg = TIS_REGISTER_INVALID;
289299
}
290300

291301
return INIT_OK;
@@ -577,22 +587,69 @@ void pre_exit() {
577587
*/
578588
int tick(tis_t* tis) {
579589
int quiescent = 1;
580-
char deferred[tis->size];
590+
int offset = tis->cols;
591+
char deferred_all[tis->size + 2*offset];
592+
char *deferred_i = deferred_all;
593+
char *deferred_n = deferred_all + offset;
594+
char *deferred_o = deferred_all + offset + tis->size;
595+
596+
// First stage: run most things
597+
for(size_t i = 0; i < tis->cols; i++) {
598+
if(tis->inputs[i] != NULL) {
599+
tis_node_state_t state = run_input(tis, tis->inputs[i]);
600+
deferred_i[i] = (state == TIS_NODE_STATE_WRITE_WAIT);
601+
if(!deferred_i[i]) {
602+
quiescent = quiescent && state != TIS_NODE_STATE_RUNNING && state == tis->inputs[i]->laststate;
603+
tis->inputs[i]->laststate = state;
604+
}
605+
}
606+
}
581607
for(size_t i = 0; i < tis->size; i++) {
582608
tis_node_state_t state = run(tis, tis->nodes[i]);
583-
deferred[i] = (state == TIS_NODE_STATE_WRITE_WAIT);
584-
if(!deferred[i]) {
609+
deferred_n[i] = (state == TIS_NODE_STATE_WRITE_WAIT);
610+
if(!deferred_n[i]) {
585611
quiescent = quiescent && state != TIS_NODE_STATE_RUNNING && state == tis->nodes[i]->laststate;
586612
tis->nodes[i]->laststate = state;
587613
}
588614
}
615+
for(size_t i = 0; i < tis->cols; i++) {
616+
if(tis->outputs[i] != NULL) {
617+
tis_node_state_t state = run_output(tis, tis->outputs[i]);
618+
deferred_o[i] = (state == TIS_NODE_STATE_WRITE_WAIT);
619+
if(!deferred_o[i]) {
620+
quiescent = quiescent && state != TIS_NODE_STATE_RUNNING && state == tis->outputs[i]->laststate;
621+
tis->outputs[i]->laststate = state;
622+
}
623+
}
624+
}
625+
626+
// Second stage: run deferrals
627+
for(size_t i = 0; i < tis->cols; i++) {
628+
if(tis->inputs[i] != NULL) {
629+
if(deferred_i[i]) {
630+
tis_node_state_t state = run_input_defer(tis, tis->inputs[i]);
631+
quiescent = quiescent && state != TIS_NODE_STATE_RUNNING && state == tis->inputs[i]->laststate;
632+
tis->inputs[i]->laststate = state;
633+
}
634+
}
635+
}
589636
for(size_t i = 0; i < tis->size; i++) {
590-
if(deferred[i]) {
637+
if(deferred_n[i]) {
591638
tis_node_state_t state = run_defer(tis, tis->nodes[i]);
592639
quiescent = quiescent && state != TIS_NODE_STATE_RUNNING && state == tis->nodes[i]->laststate;
593640
tis->nodes[i]->laststate = state;
594641
}
595642
}
643+
for(size_t i = 0; i < tis->cols; i++) {
644+
if(tis->outputs[i] != NULL) {
645+
if(deferred_o[i]) {
646+
tis_node_state_t state = run_output_defer(tis, tis->outputs[i]);
647+
quiescent = quiescent && state != TIS_NODE_STATE_RUNNING && state == tis->outputs[i]->laststate;
648+
tis->outputs[i]->laststate = state;
649+
}
650+
}
651+
}
652+
596653
spam("System quiescent? %d\n", quiescent);
597654
return quiescent;
598655
}

‎tis_io.c

+91-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,97 @@
33

44
#include "tis_types.h"
55

6+
// These are duplicated from the header
7+
tis_op_result_t input(tis_io_node_t* io, int* value);
8+
tis_op_result_t output(tis_io_node_t* io, int value);
9+
10+
tis_node_state_t run_input(tis_t* tis, tis_io_node_t* io) {
11+
(void)tis;
12+
if(io == NULL) {
13+
return TIS_NODE_STATE_IDLE;
14+
}
15+
if(io->writereg != TIS_REGISTER_INVALID) {
16+
// still waiting for current write
17+
return TIS_NODE_STATE_WRITE_WAIT;
18+
}
19+
spam("Input node I%zu attempting to write\n", io->col);
20+
tis_op_result_t result = input(io, &(io->writebuf));
21+
if(result == TIS_OP_RESULT_OK) {
22+
return TIS_NODE_STATE_WRITE_WAIT;
23+
} else if(result == TIS_OP_RESULT_READ_WAIT) {
24+
return TIS_NODE_STATE_READ_WAIT;
25+
} else {
26+
// BAD INTERNAL ERROR BAD this is out of sync with the enum
27+
error("INTERNAL: An error has occurred!!!\n");
28+
bork();
29+
}
30+
}
31+
32+
tis_node_state_t run_output(tis_t* tis, tis_io_node_t* io) {
33+
if(io == NULL) {
34+
return TIS_NODE_STATE_IDLE;
35+
}
36+
spam("Output node O%zu attempting to read\n", io->col);
37+
tis_op_result_t result;
38+
if(tis->rows == 0) { // if reading up with no rows, read input instead
39+
if(tis->inputs[io->col] == NULL || tis->inputs[io->col]->writereg != TIS_REGISTER_DOWN) {
40+
return TIS_NODE_STATE_READ_WAIT;
41+
}
42+
result = output(io, tis->inputs[io->col]->writebuf);
43+
tis->inputs[io->col]->writereg = TIS_REGISTER_NIL;
44+
if(result == TIS_OP_RESULT_OK) {
45+
spam("Output node O%zu read success\n", io->col);
46+
return TIS_NODE_STATE_RUNNING;
47+
} else {
48+
// BAD INTERNAL ERROR BAD this is out of sync with the enum
49+
error("INTERNAL: An error has occurred!!!\n");
50+
bork();
51+
}
52+
}
53+
tis_node_t* neigh = tis->nodes[(tis->rows-1)*tis->cols + io->col];
54+
if(neigh == NULL || !(neigh->writereg == TIS_REGISTER_DOWN || neigh->writereg == TIS_REGISTER_ANY)) {
55+
return TIS_NODE_STATE_READ_WAIT;
56+
}
57+
result = output(io, neigh->writebuf);
58+
if(neigh->writereg == TIS_REGISTER_ANY) {
59+
neigh->last = TIS_REGISTER_DOWN;
60+
}
61+
neigh->writereg = TIS_REGISTER_NIL;
62+
if(result == TIS_OP_RESULT_OK) {
63+
spam("Output node O%zu read success\n", io->col);
64+
return TIS_NODE_STATE_RUNNING;
65+
} else {
66+
// BAD INTERNAL ERROR BAD this is out of sync with the enum
67+
error("INTERNAL: An error has occurred!!!\n");
68+
bork();
69+
}
70+
}
71+
72+
tis_node_state_t run_input_defer(tis_t* tis, tis_io_node_t* io) {
73+
(void)tis;
74+
spam("Input node I%zu attempting to write (defer)\n", io->col);
75+
if(1 /* TODO is input */ ) {
76+
if(io->writereg == TIS_REGISTER_NIL) { // if NIL, the previous write was handled, reset it all
77+
io->writereg = TIS_REGISTER_INVALID;
78+
spam("Input node I%zu write deferred success\n", io->col);
79+
return TIS_NODE_STATE_RUNNING;
80+
} else {
81+
io->writereg = TIS_REGISTER_DOWN;
82+
return TIS_NODE_STATE_WRITE_WAIT;
83+
}
84+
} else {
85+
// TODO internal error
86+
bork();
87+
}
88+
}
89+
90+
tis_node_state_t run_output_defer(tis_t* tis, tis_io_node_t* io) {
91+
(void)tis;
92+
(void)io;
93+
// TODO internal error
94+
bork();
95+
}
96+
697
tis_op_result_t input(tis_io_node_t* io, int* value) {
798
if(io == NULL) {
899
return TIS_OP_RESULT_READ_WAIT;
@@ -37,9 +128,6 @@ tis_op_result_t input(tis_io_node_t* io, int* value) {
37128

38129
#define TIS_NUMERIC_SEP " " // separator to use when printing in NUMERIC mode
39130
tis_op_result_t output(tis_io_node_t* io, int value) {
40-
if(io == NULL) {
41-
return TIS_OP_RESULT_WRITE_WAIT;
42-
}
43131
int out = EOF;
44132
switch(io->type) {
45133
case TIS_IO_TYPE_IOSTREAM_ASCII:

‎tis_io.h

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
#include "tis_types.h"
55

6+
tis_node_state_t run_input(tis_t* tis, tis_io_node_t* io);
7+
tis_node_state_t run_output(tis_t* tis, tis_io_node_t* io);
8+
9+
tis_node_state_t run_input_defer(tis_t* tis, tis_io_node_t* io);
10+
tis_node_state_t run_output_defer(tis_t* tis, tis_io_node_t* io);
11+
612
tis_op_result_t input(tis_io_node_t* io, int* value);
713
tis_op_result_t output(tis_io_node_t* io, int value);
814

‎tis_node.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,12 @@ tis_op_result_t read_port_register_maybe(tis_t* tis, tis_node_t* node, tis_regis
141141
return TIS_OP_RESULT_READ_WAIT;
142142
} else if(reg == TIS_REGISTER_UP) {
143143
if(node->row == 0) { // if reading up from top row, read input instead
144-
return input(tis->inputs[node->col], value); // TODO experiment: can io read happen every tick, or only every other? -> read is every other, starting with a prep cycle
144+
if(tis->inputs[node->col] == NULL || tis->inputs[node->col]->writereg != TIS_REGISTER_DOWN) {
145+
return TIS_OP_RESULT_READ_WAIT;
146+
}
147+
*value = tis->inputs[node->col]->writebuf;
148+
tis->inputs[node->col]->writereg = TIS_REGISTER_NIL;
149+
return TIS_OP_RESULT_OK;
145150
}
146151
tis_node_t* neigh = tis->nodes[(node->row-1)*tis->cols + node->col];
147152
if(neigh == NULL || !(neigh->writereg == TIS_REGISTER_DOWN || neigh->writereg == TIS_REGISTER_ANY)) {
@@ -202,14 +207,9 @@ tis_op_result_t read_port_register_maybe(tis_t* tis, tis_node_t* node, tis_regis
202207
* TODO future enhancement to randomly order, giving a source of randomness
203208
*/
204209
tis_op_result_t write_port_register_maybe(tis_t* tis, tis_node_t* node, tis_register_t reg, int value) {
210+
(void)tis;
211+
(void)reg;
205212
node->writebuf = value;
206-
// if writing down from bottom row, write output instead, and return OK
207-
if((reg == TIS_REGISTER_DOWN || reg == TIS_REGISTER_ANY) && node->row+1 == tis->rows) {
208-
spam("Write value %d to output index %zu\n", value, node->col);
209-
return output(tis->outputs[node->col], value);
210-
}
211-
// TODO experiment: does writing to output claim 1 or 2 ticks? (move to other claims 2) -> it's 2
212-
// TODO experiment: does writing to ANY favor outputs or other nodes? -> no, it acts like another row of nodes below
213213
return TIS_OP_RESULT_WRITE_WAIT;
214214
}
215215
tis_op_result_t write_port_register_defer_maybe(tis_t* tis, tis_node_t* node, tis_register_t reg) {

‎tis_types.h

+4
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ typedef struct tis_node {
179179

180180
typedef struct tis_io_node {
181181
tis_io_type_t type;
182+
size_t col;
182183
char* name; // optional
183184
union {
184185
struct {
@@ -191,6 +192,9 @@ typedef struct tis_io_node {
191192
int arg; // either increment or multiplier
192193
} seq;
193194
};
195+
int writebuf; // (used by communicative types)
196+
tis_register_t writereg; // UpDownLeftRightAny -> ready, Nil -> complete, Invalid -> quiet (used by all types)
197+
tis_node_state_t laststate; // managed externally
194198
} tis_io_node_t;
195199

196200
typedef struct tis {

0 commit comments

Comments
 (0)
Please sign in to comment.