Skip to content

Commit e3543da

Browse files
committed
Implement damaged nodes, Enhance logging and parsing
Implement damaged nodes Enhance some error messages/actions Demote some debug messages to spam Enhance IO node configuration parsing Additional self-checks Remove some magic numbers
1 parent 4a3027f commit e3543da

File tree

5 files changed

+122
-118
lines changed

5 files changed

+122
-118
lines changed

tis.c

+52-36
Original file line numberDiff line numberDiff line change
@@ -94,31 +94,37 @@ int init_layout(tis_t* tis, char* layoutfile, int layoutmode) {
9494
while(isspace(ch = fgetc(layout))) {
9595
// discard whitespace
9696
}
97+
tis->nodes[i] = calloc(1, sizeof(tis_node_t));
98+
tis->nodes[i]->row = i / tis->cols;
99+
tis->nodes[i]->col = i % tis->cols;
100+
tis->nodes[i]->writereg = TIS_REGISTER_INVALID;
97101
switch(ch) {
98102
case 'C': // compute
99103
case 'c':
100-
tis->nodes[i] = calloc(1, sizeof(tis_node_t));
101104
tis->nodes[i]->type = TIS_NODE_TYPE_COMPUTE;
102105
tis->nodes[i]->id = id++;
103-
tis->nodes[i]->row = i / tis->cols;
104-
tis->nodes[i]->col = i % tis->cols;
105-
tis->nodes[i]->writereg = TIS_REGISTER_INVALID;
106106
tis->nodes[i]->last = TIS_REGISTER_INVALID;
107107
break;
108108
case 'M': // memory (assume stack memory)
109109
case 'm':
110110
case 'S': // stack memory
111111
case 's':
112-
error("Not yet implemented\n");
112+
tis->nodes[i]->type = TIS_NODE_TYPE_MEMORY_STACK;
113+
tis->nodes[i]->index = 0;
114+
error("Node type not yet implemented\n");
115+
fclose(layout);
113116
return INIT_FAIL;
114117
case 'R': // random access memory
115118
case 'r':
116-
error("Not yet implemented\n");
119+
tis->nodes[i]->type = TIS_NODE_TYPE_MEMORY_RAM;
120+
tis->nodes[i]->index = 0;
121+
error("Node type not yet implemented\n");
122+
fclose(layout);
117123
return INIT_FAIL;
118-
case 'D': // damaged
124+
case 'D': // damaged / disabled
119125
case 'd':
120-
error("Not yet implemented\n");
121-
return INIT_FAIL;
126+
tis->nodes[i]->type = TIS_NODE_TYPE_DAMAGED;
127+
break;
122128
case EOF:
123129
error("Unexpected EOF while reading node specifiers\n");
124130
fclose(layout);
@@ -169,19 +175,24 @@ int init_layout(tis_t* tis, char* layoutfile, int layoutmode) {
169175
}
170176
} else if(tis->inputs[index]->type == TIS_IO_TYPE_IOSTREAM_ASCII ||
171177
tis->inputs[index]->type == TIS_IO_TYPE_IOSTREAM_NUMERIC) {
172-
if(strcasecmp(buf, "STDIN") == 0 ||
173-
strcasecmp(buf, "-") == 0) {
174-
debug("Set I%zu to use stdin\n", index);
175-
tis->inputs[index]->file.file = stdin; // TODO make sure this doesn't already have a file
176-
} else {
177-
debug("Set I%zu to use file %.*s\n", index, BUFSIZE, buf);
178-
if((tis->inputs[index]->file.file = fopen(buf, "r")) == NULL) {
179-
error("Unable to open %.*s for reading\n", BUFSIZE, buf); // TODO what to do about this? error out?
178+
if(tis->inputs[index]->file.file == NULL) {
179+
if(strcasecmp(buf, "STDIN") == 0 ||
180+
strcasecmp(buf, "-") == 0) {
181+
debug("Set I%zu to use stdin\n", index);
182+
tis->inputs[index]->file.file = stdin; // TODO make sure this doesn't already have a file
183+
} else {
184+
debug("Set I%zu to use file %.*s\n", index, BUFSIZE, buf);
185+
if((tis->inputs[index]->file.file = fopen(buf, "r")) == NULL) {
186+
error("Unable to open %.*s for reading\n", BUFSIZE, buf); // TODO what to do about this? error out?
187+
}
188+
register_file_handle(tis->inputs[index]->file.file);
180189
}
181-
register_file_handle(tis->inputs[index]->file.file);
190+
} else {
191+
goto skip_io_token;
182192
}
183193
} else {
184194
// TODO node type not implemented? internal error?
195+
goto skip_io_token;
185196
}
186197
break;
187198
case 1:
@@ -198,25 +209,30 @@ int init_layout(tis_t* tis, char* layoutfile, int layoutmode) {
198209
}
199210
} else if(tis->outputs[index]->type == TIS_IO_TYPE_IOSTREAM_ASCII ||
200211
tis->outputs[index]->type == TIS_IO_TYPE_IOSTREAM_NUMERIC) {
201-
if(strcasecmp(buf, "STDOUT") == 0 ||
202-
strcasecmp(buf, "-") == 0) {
203-
debug("Set O%zu to use stdout\n", index);
204-
tis->outputs[index]->file.file = stdout; // TODO make sure this doesn't already have a file
205-
} else if(strcasecmp(buf, "STDERR") == 0) {
206-
debug("Set O%zu to use stderr\n", index);
207-
tis->outputs[index]->file.file = stderr;
212+
if(tis->outputs[index]->file.file == NULL) {
213+
if(strcasecmp(buf, "STDOUT") == 0 ||
214+
strcasecmp(buf, "-") == 0) {
215+
debug("Set O%zu to use stdout\n", index);
216+
tis->outputs[index]->file.file = stdout; // TODO make sure this doesn't already have a file
217+
} else if(strcasecmp(buf, "STDERR") == 0) {
218+
debug("Set O%zu to use stderr\n", index);
219+
tis->outputs[index]->file.file = stderr;
220+
} else {
221+
debug("Set O%zu to use file %.*s\n", index, BUFSIZE, buf);
222+
if((tis->outputs[index]->file.file = fopen(buf, "a")) == NULL) {
223+
error("Unable to open %.*s for writing\n", BUFSIZE, buf); // TODO what to do about this? error out?
224+
}
225+
register_file_handle(tis->outputs[index]->file.file);
226+
}
208227
} else if(tis->outputs[index]->type == TIS_IO_TYPE_IOSTREAM_NUMERIC &&
209228
sscanf(buf, "%d", &(tis->outputs[index]->file.sep)) == 1) {
210-
// nothing to do
229+
debug("Set O%zu separator to %d\n", index, tis->outputs[index]->file.sep);
211230
} else {
212-
debug("Set O%zu to use file %.*s\n", index, BUFSIZE, buf);
213-
if((tis->outputs[index]->file.file = fopen(buf, "a")) == NULL) {
214-
error("Unable to open %.*s for writing\n", BUFSIZE, buf); // TODO what to do about this? error out?
215-
}
216-
register_file_handle(tis->outputs[index]->file.file);
231+
goto skip_io_token;
217232
}
218233
} else {
219-
// TODO node type not implemented? internal error?
234+
// TODO io node type not implemented? internal error?
235+
goto skip_io_token;
220236
}
221237
break;
222238
case 2:
@@ -277,7 +293,7 @@ int init_nodes(tis_t* tis, char* sourcefile) {
277293
*nl = '\0';
278294
}
279295

280-
debug("parse line: %.*s\n", BUFSIZE, buf);
296+
spam("Parse line: %.*s\n", BUFSIZE, buf);
281297

282298
if(buf[0] == '\0') {
283299
// empty line; ignore
@@ -533,7 +549,7 @@ int tick(tis_t* tis) {
533549
tis->nodes[i]->laststate = state;
534550
}
535551
}
536-
debug("quiescent = %d\n", quiescent);
552+
spam("System quiescent? %d\n", quiescent);
537553
return quiescent;
538554
}
539555

@@ -609,8 +625,8 @@ int main(int argc, char** argv) {
609625
break;
610626
case 3:
611627
sourcefile = argvector[0];
612-
tis.rows = atoi(argvector[1]);
613-
tis.cols = atoi(argvector[2]);
628+
tis.rows = atoi(argvector[1]); // TODO ensure that there is nothing else in this arg
629+
tis.cols = atoi(argvector[2]); // TODO ensure that there is nothing else in this arg
614630
debug("Read dimensions %zur %zuc from command line\n", tis.rows, tis.cols);
615631
break;
616632
default:

tis_node.c

+17-12
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,40 @@ tis_node_state_t run(tis_t* tis, tis_node_t* node) {
2727
return TIS_NODE_STATE_WRITE_WAIT;
2828
} else if(result == TIS_OP_RESULT_ERR) {
2929
error("An error has occurred!!!\n");
30-
//custom_abort();
30+
bork();
3131
} else {
32-
// BAD INTERNAL ERROR BAD
33-
//custom_abort();
32+
// BAD INTERNAL ERROR BAD this is out of sync with the enum
33+
error("INTERNAL: An error has occurred!!!\n");
34+
bork();
3435
}
36+
} else if(node->type == TIS_NODE_TYPE_DAMAGED) {
37+
return TIS_NODE_STATE_IDLE;
3538
}
3639
return TIS_NODE_STATE_IDLE;
3740
}
3841

3942
tis_node_state_t run_defer(tis_t* tis, tis_node_t* node) {
4043
if(node->type != TIS_NODE_TYPE_COMPUTE) {
4144
// only compute node can defer
42-
//custom_abort();
45+
error("INTERNAL: Cannot run deferred instructions on this node type\n");
46+
bork();
4347
} else {
4448
tis_op_result_t result = step_defer(tis, node, node->code[node->index]);
4549
if(result == TIS_OP_RESULT_OK) {
4650
node->index = (node->index + 1) % TIS_NODE_LINE_COUNT;
4751
return TIS_NODE_STATE_RUNNING;
4852
} else if(result == TIS_OP_RESULT_READ_WAIT) {
4953
// internal error
50-
//custom_abort();
54+
bork();
5155
} else if(result == TIS_OP_RESULT_WRITE_WAIT) {
5256
return TIS_NODE_STATE_WRITE_WAIT;
5357
} else if(result == TIS_OP_RESULT_ERR) {
5458
error("An error has occurred!!!\n");
55-
//custom_abort();
59+
bork();
5660
} else {
57-
// BAD INTERNAL ERROR BAD
58-
//custom_abort();
61+
// BAD INTERNAL ERROR BAD this is out of sync with the enum
62+
error("INTERNAL: An error has occurred!!!\n");
63+
bork();
5964
}
6065
}
6166
return TIS_NODE_STATE_IDLE;
@@ -144,7 +149,7 @@ tis_op_result_t write_port_register_maybe(tis_t* tis, tis_node_t* node, tis_regi
144149
node->writebuf = value;
145150
// TODO if writing down from bottom row, write output instead, and return OK
146151
if((reg == TIS_REGISTER_DOWN || reg == TIS_REGISTER_ANY) && node->row+1 == tis->rows) {
147-
debug("Write value %d to output index %zu\n", value, node->col);
152+
spam("Write value %d to output index %zu\n", value, node->col);
148153
return output(tis->outputs[node->col], value);
149154
}
150155
// TODO experiment: does writing to output claim 1 or 2 ticks? (move to other claims 2)
@@ -162,7 +167,7 @@ tis_op_result_t write_port_register_defer_maybe(tis_t* tis, tis_node_t* node, ti
162167
}
163168

164169
tis_op_result_t read_register(tis_t* tis, tis_node_t* node, tis_register_t reg, int* value) {
165-
debug("Attempting read from register %s on node @%d\n", reg_to_string(reg), node->id);
170+
spam("Attempting read from register %s on node @%d\n", reg_to_string(reg), node->id);
166171
switch(reg) {
167172
case TIS_REGISTER_ACC:
168173
*value = node->acc;
@@ -189,7 +194,7 @@ tis_op_result_t read_register(tis_t* tis, tis_node_t* node, tis_register_t reg,
189194
}
190195

191196
tis_op_result_t write_register(tis_t* tis, tis_node_t* node, tis_register_t reg, int value) {
192-
debug("Attempting write to register %s on node @%d (value %d)\n", reg_to_string(reg), node->id, value);
197+
spam("Attempting write to register %s on node @%d (value %d)\n", reg_to_string(reg), node->id, value);
193198
switch(reg) {
194199
case TIS_REGISTER_ACC:
195200
node->acc = value;
@@ -217,7 +222,7 @@ tis_op_result_t write_register(tis_t* tis, tis_node_t* node, tis_register_t reg,
217222
}
218223

219224
tis_op_result_t write_register_defer(tis_t* tis, tis_node_t* node, tis_register_t reg) {
220-
debug("Attempting write to register %s on node @%d (defer)\n", reg_to_string(reg), node->id);
225+
spam("Attempting write to register %s on node @%d (defer)\n", reg_to_string(reg), node->id);
221226
switch(reg) {
222227
case TIS_REGISTER_ACC:
223228
case TIS_REGISTER_BAK:

tis_node.h

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

44
#include "tis_types.h"
55

6-
// TODO Are these correct?
7-
#define TIS_NODE_LINE_COUNT 15
8-
#define TIS_NODE_LINE_LENGTH 19
9-
106
tis_node_state_t run(tis_t* tis, tis_node_t* node);
117
tis_node_state_t run_defer(tis_t* tis, tis_node_t* node);
128

tis_ops.c

+25-43
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ tis_op_result_t step(tis_t* tis, tis_node_t* node, tis_op_t* op) {
1010
tis_op_result_t result = TIS_OP_RESULT_OK;
1111
char* jump = NULL;
1212
int value = 0;
13-
debug("Run instruction %s on node @%d\n", op_to_string(op->type), node->id);
13+
spam("Run instruction %s on node @%d\n", op_to_string(op->type), node->id);
1414
// TODO assert correct nargs? This is checked when parsing though...
1515
switch(op->type) {
1616
case TIS_OP_TYPE_ADD:
@@ -32,34 +32,16 @@ tis_op_result_t step(tis_t* tis, tis_node_t* node, tis_op_t* op) {
3232
case TIS_OP_TYPE_JEZ:
3333
if(node->acc == 0) {
3434
goto jump_label;
35-
/*if(op->src.type == TIS_OP_ARG_TYPE_LABEL) {
36-
jump = op->src.label;
37-
} else {
38-
error("INTERNAL: Unable to jump to non-label argument on node @%d\n", node->id);
39-
result = TIS_OP_RESULT_ERR;
40-
}*/
4135
}
4236
break;
4337
case TIS_OP_TYPE_JGZ:
4438
if(node->acc > 0) {
4539
goto jump_label;
46-
/*if(op->src.type == TIS_OP_ARG_TYPE_LABEL) {
47-
jump = op->src.label;
48-
} else {
49-
error("INTERNAL: Unable to jump to non-label argument on node @%d\n", node->id);
50-
result = TIS_OP_RESULT_ERR;
51-
}*/
5240
}
5341
break;
5442
case TIS_OP_TYPE_JLZ:
5543
if(node->acc < 0) {
5644
goto jump_label;
57-
/*if(op->src.type == TIS_OP_ARG_TYPE_LABEL) {
58-
jump = op->src.label;
59-
} else {
60-
error("INTERNAL: Unable to jump to non-label argument on node @%d\n", node->id);
61-
result = TIS_OP_RESULT_ERR;
62-
}*/
6345
}
6446
break;
6547
case TIS_OP_TYPE_JMP:
@@ -74,12 +56,6 @@ tis_op_result_t step(tis_t* tis, tis_node_t* node, tis_op_t* op) {
7456
case TIS_OP_TYPE_JNZ:
7557
if(node->acc != 0) {
7658
goto jump_label;
77-
/*if(op->src.type == TIS_OP_ARG_TYPE_LABEL) {
78-
jump = op->src.label;
79-
} else {
80-
error("INTERNAL: Unable to jump to non-label argument on node @%d\n", node->id);
81-
result = TIS_OP_RESULT_ERR;
82-
}*/
8359
}
8460
break;
8561
case TIS_OP_TYPE_JRO:
@@ -154,7 +130,7 @@ tis_op_result_t step(tis_t* tis, tis_node_t* node, tis_op_t* op) {
154130
break;
155131
}
156132
if(jump != NULL) {
157-
debug("Jumping to label %.20s on node @%d\n", jump, node->id);
133+
spam("Jumping to label %.20s on node @%d\n", jump, node->id);
158134
int i = 0;
159135
for(; i < TIS_NODE_LINE_COUNT; i++) {
160136
if(node->code[i]->label != NULL && strcmp(jump, node->code[i]->label) == 0) {
@@ -163,34 +139,40 @@ tis_op_result_t step(tis_t* tis, tis_node_t* node, tis_op_t* op) {
163139
}
164140
}
165141
if(i == TIS_NODE_LINE_COUNT) {
166-
// unable to jump to missing label TODO message
142+
// unable to jump to missing label
143+
error("Label %.20s not found in node @%d, unable to jump\n", jump, node->id);
167144
result = TIS_OP_RESULT_ERR;
168145
}
169146
}
170-
debug("Run instruction %s on node @%d result %s\n", op_to_string(op->type), node->id, result_to_string(result));
147+
spam("Run instruction %s on node @%d result %s\n", op_to_string(op->type), node->id, result_to_string(result));
171148
return result;
172149
} else {
173-
error("Not yet implemented\n"); // TODO
150+
error("INTERNAL: Cannot run instructions on this node type\n");
174151
return TIS_OP_RESULT_ERR;
175152
}
176153
}
177154

178155
tis_op_result_t step_defer(tis_t* tis, tis_node_t* node, tis_op_t* op) {
179-
// This should only be called when deferring a write to an external port
180-
// The only op that can do that is MOV
181-
tis_op_result_t result;
182-
debug("Run instruction %s on node @%d (defer)\n", op_to_string(op->type), node->id);
183-
if(op->type != TIS_OP_TYPE_MOV) {
184-
// TODO internal error
185-
result = TIS_OP_RESULT_ERR;
186-
} else {
187-
if(op->dst.type == TIS_OP_ARG_TYPE_REGISTER) {
188-
result = write_register_defer(tis, node, op->dst.reg);
189-
} else {
190-
error("INTERNAL: Invalid dest arg type for MOV (%d) on node @%d\n", op->dst.type, node->id);
156+
if(node->type == TIS_NODE_TYPE_COMPUTE) {
157+
// This should only be called when deferring a write to an external port
158+
// The only op that can do that is MOV
159+
tis_op_result_t result;
160+
spam("Run instruction %s on node @%d (defer)\n", op_to_string(op->type), node->id);
161+
if(op->type != TIS_OP_TYPE_MOV) {
162+
error("INTERNAL: Only MOV instructions may be deferred; node @%d\n", node->id);
191163
result = TIS_OP_RESULT_ERR;
164+
} else {
165+
if(op->dst.type == TIS_OP_ARG_TYPE_REGISTER) {
166+
result = write_register_defer(tis, node, op->dst.reg);
167+
} else {
168+
error("INTERNAL: Invalid dest arg type for MOV (%d) on node @%d\n", op->dst.type, node->id);
169+
result = TIS_OP_RESULT_ERR;
170+
}
192171
}
172+
spam("Run instruction %s on node @%d (defer) result %s\n", op_to_string(op->type), node->id, result_to_string(result));
173+
return result;
174+
} else {
175+
error("INTERNAL: Cannot run deferred instructions on this node type\n");
176+
return TIS_OP_RESULT_ERR;
193177
}
194-
debug("Run instruction %s on node @%d (defer) result %s\n", op_to_string(op->type), node->id, result_to_string(result));
195-
return result;
196178
}

0 commit comments

Comments
 (0)