13 /* magic value to indicate upstream is dead */
16 /* only relevant instructions */
20 /* Doing nothing, waiting for an instruction */
22 #define STATE_READ_INSTRUCTION 10
23 #define STATE_READ_NEWS_ADDRESS 20
24 #define STATE_READ_NEWS_DATA 30
25 /* Propagating the last received instruction
26 (or waiting for neighbour to be ready so I can propagate) */
27 #define STATE_PROPAGATE 1
28 #define STATE_PROPAGATE2 11
29 /* Executing some instruction */
30 #define STATE_EXECUTE 2
31 /* Sending NEWS to neighbour
32 (or waiting for neighbour to be ready so I can send) */
34 #define STATE_NEWS2 13
35 #define STATE_NEWS3 23
37 // UART encoding is: to send the byte [b] we write [b * 2 + 1] in the
38 // given location, then on the next cycle we write 0.
40 static void wait_cycles(int cycles
) {
43 millis
+= (long)(rand() % 100 - 50);
45 ts
.tv_sec
= millis
/ 1000;
46 ts
.tv_nsec
= (millis
% 1000) * 100000;
50 /* sleep for 150-250ms */
51 static void wait_one_cycle(void) {
55 #define BLOG_THREAD_STARTED 0
56 #define BLOG_UART_BAD_KIND 1
57 #define BLOG_READ_INSTRUCTION 2
58 #define BLOG_READ_NEWS_ADDRESS 3
59 #define BLOG_READ_NEWS_DATA 4
60 #define BLOG_BECAME_NOT_READY 5
61 #define BLOG_INVALID_STATE 6
62 #define BLOG_EXECUTED_INSTR 7
63 #define BLOG_MANUFACTURED_INSTRUCTION 8
64 #define BLOG_READ_KIND 9
65 #define BLOG_TRY_SENDING_NEWS 10
66 #define BLOG_DONE_SENDING_NEWS 11
68 const char *blog_what
[] = {
74 "ERROR: downstream became not ready!",
75 "ERROR: invalid state",
76 "executed instruction",
77 "manufactured instruction",
78 "read kind from uart",
79 "trying to send news",
80 "finished sending news",
89 static volatile struct blog blog
[1000];
90 static volatile int blog_n
= 0;
92 void display_post(int i
) {
93 printf("\033[3%dm%d: %s (%d)\033[0m\n", blog
[i
].who
+ 1, blog
[i
].who
, blog_what
[blog
[i
].what
], blog
[i
].data
);
96 void post(int who
, int what
, int data
) {
99 blog
[idx
].what
= what
;
100 blog
[idx
].data
= data
;
104 #define POST(what, data) post(id, what, data)
106 int uart_data(int x
) {
110 static void tx(volatile int *uart_tx
, int data
) {
113 // assert(*uart_tx == 0);
116 #define TX(data) tx(uart_tx, uart_data(data))
117 #define KILL_UART() tx(uart_tx, 2)
119 static int rx(volatile int *uart_rx
) {
125 #define RX() rx(uart_rx)
127 void worker(int id
, volatile int *uart_tx
, volatile int *uart_rx
, volatile int *ready_out
, volatile const int *ready_in
){
128 int current_instr
= 0;
130 int state
= STATE_IDLE
;
133 POST(BLOG_THREAD_STARTED
, 0);
135 int read
, kind
, instruction
, address
, data
;
142 if(read
== 2) { // upstream dead!
146 if(!read
) /* nothing on uart */
149 POST(BLOG_READ_KIND
, kind
);
151 state
= STATE_READ_INSTRUCTION
;
153 state
= STATE_READ_NEWS_ADDRESS
;
155 POST(BLOG_UART_BAD_KIND
, kind
);
158 case STATE_READ_INSTRUCTION
:
161 if(!read
) /* nothing on uart */
163 instruction
= read
>> 1;
164 current_instr
= instruction
;
166 POST(BLOG_READ_INSTRUCTION
, instruction
);
167 state
= STATE_PROPAGATE
;
170 case STATE_READ_NEWS_ADDRESS
:
173 if(!read
) /* nothing on uart */
176 current_instr
= address
;
177 POST(BLOG_READ_NEWS_ADDRESS
, address
);
178 state
= STATE_READ_NEWS_DATA
;
181 case STATE_READ_NEWS_DATA
:
184 if(!read
) /* nothing on uart */
187 /* we now have the address in [current_instr] and data in [data].
188 We write a NOP instruction because we have no memory. */
189 current_instr
= INSTR_NOP
;
191 POST(BLOG_READ_NEWS_DATA
, data
);
192 state
= STATE_EXECUTE
;
195 case STATE_PROPAGATE
:
198 TX(1); /* we're writing an instruction */
199 state
= STATE_PROPAGATE2
;
202 case STATE_PROPAGATE2
:
204 POST(BLOG_BECAME_NOT_READY
, state
);
205 state
= STATE_PROPAGATE
;
209 state
= STATE_EXECUTE
;
213 wait_one_cycle(); // execution takes time! (not really)
214 if(current_instr
== INSTR_ROUTE
) {
216 POST(BLOG_EXECUTED_INSTR
, current_instr
);
217 // POST(BLOG_TRY_SENDING_NEWS, 0);
221 POST(BLOG_EXECUTED_INSTR
, current_instr
);
234 POST(BLOG_BECAME_NOT_READY
, state
);
244 POST(BLOG_BECAME_NOT_READY
, state
);
251 // POST(BLOG_DONE_SENDING_NEWS, 0);
255 POST(BLOG_INVALID_STATE
, state
);
262 #define MASTER_SEND_INSTRUCTION 0
263 #define MASTER_SEND_INSTRUCTION2 10
264 #define MASTER_WAIT_FOR_NEWS 1
265 #define MASTER_READ_NEWS_ADDRESS 11
266 #define MASTER_READ_NEWS_DATA 21
267 #define MASTER_WAIT_FOR_PROPAGATE 2
268 #define MASTER_WAIT_FOR_PROPAGATE2 12
270 void master(volatile int *uart_tx
, volatile int *uart_rx
, volatile int *ready_out
, volatile const int *ready_in
){
271 int instructions_left
= 10;
272 int state
= MASTER_SEND_INSTRUCTION
;
273 int ignore_next_rx
= 0;
275 int read
, kind
, instruction
, data
, rnd
;
279 POST(BLOG_THREAD_STARTED
, 0);
283 case MASTER_SEND_INSTRUCTION
:
284 if(!instructions_left
) { /* done! */
291 state
= MASTER_SEND_INSTRUCTION2
;
294 case MASTER_SEND_INSTRUCTION2
:
296 POST(BLOG_BECAME_NOT_READY
, state
);
297 state
= MASTER_SEND_INSTRUCTION
;
300 /* manufacture an instruction */
303 instruction
= INSTR_NOP
;
305 instruction
= INSTR_ROUTE
;
307 instruction
= INSTR_ROUTE
; /* actually READ */
309 POST(BLOG_MANUFACTURED_INSTRUCTION
, rnd
);
313 if(instruction
== INSTR_ROUTE
)
314 state
= MASTER_WAIT_FOR_NEWS
;
316 state
= MASTER_WAIT_FOR_PROPAGATE
;
319 case MASTER_WAIT_FOR_PROPAGATE
:
322 if(!read
) /* nothing on uart */
326 state
= MASTER_WAIT_FOR_PROPAGATE2
;
327 else /* kind == 2 is also bad here */
328 POST(BLOG_UART_BAD_KIND
, kind
);
331 case MASTER_WAIT_FOR_PROPAGATE2
:
334 if(!read
) /* nothing on uart */
336 instruction
= read
>> 1; /* we don't care about this */
337 state
= MASTER_SEND_INSTRUCTION
;
340 case MASTER_WAIT_FOR_NEWS
:
343 if(!read
) /* nothing on uart */
348 else if(kind
== 1) /* propagation, ignore next byte */
350 else if(kind
== 2) { /* ka-ching! */
351 state
= MASTER_READ_NEWS_ADDRESS
;
353 POST(BLOG_UART_BAD_KIND
, kind
);
356 case MASTER_READ_NEWS_ADDRESS
:
359 if(!read
) /* nothing on uart */
361 /* we do not care about the address, we go read the data */
362 state
= MASTER_READ_NEWS_DATA
;
365 case MASTER_READ_NEWS_DATA
:
368 if(!read
) /* nothing on uart */
371 POST(BLOG_READ_NEWS_DATA
, data
);
372 state
= MASTER_SEND_INSTRUCTION
;
376 POST(BLOG_INVALID_STATE
, state
);
386 static pthread_t threads
[5];
388 void* spawn_thread(void* index
) {
389 switch((long)index
) {
391 master(uarts
+ 0, uarts
+ 4, ready
+ 4, ready
+ 0);
394 worker(1, uarts
+ 1, uarts
+ 0, ready
+ 0, ready
+ 1);
397 worker(2, uarts
+ 2, uarts
+ 1, ready
+ 1, ready
+ 2);
400 worker(3, uarts
+ 3, uarts
+ 2, ready
+ 2, ready
+ 3);
403 worker(4, uarts
+ 4, uarts
+ 3, ready
+ 3, ready
+ 4);
406 printf("Spawned bad thread %ld\n", (long)index
);
412 for(long i
= 0 ; i
< 5 ; i
++)
413 pthread_create(threads
+ i
, NULL
, spawn_thread
, (void*)i
);
414 for(int i
= 0 ; i
< 5 ; i
++)
415 pthread_join(threads
[i
], NULL
);
416 // for(int i = 0; i < blog_n; i++)