uvm32/host-parallel/host-parallel.c
Toby Jaffey e07eeab043 Make yield a regular syscall taking an argument.
Allows "wait for interrupt"/"wait for event" type operation where VM code blocks until the host has something for it.
2025-12-10 10:35:18 +00:00

111 lines
5.2 KiB
C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "uvm32.h"
#include "../common/uvm32_common_custom.h"
// Run multiple scheduled VMs in parallel until all have ended
#define NUM_VM 4 // number of vms
#define SCHEDULE SCHEDULE_RANDOM // scheduling algorithm
// scheduling algorithms
#define SCHEDULE_ROUNDROBIN() scheduler_index = (scheduler_index + 1) % NUM_VM
#define SCHEDULE_RANDOM() scheduler_index = rand()%NUM_VM
uint8_t rom[] = { // fib.bin
0x23, 0x26, 0x11, 0x00, 0xef, 0x00, 0xc0, 0x16, 0xb7, 0x08, 0x00, 0x01,
0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x05, 0x00, 0x00,
0x93, 0x08, 0x40, 0x00, 0x73, 0x00, 0x00, 0x00, 0x37, 0x05, 0x00, 0x80,
0x13, 0x05, 0x05, 0x1c, 0x93, 0x08, 0x30, 0x00, 0x73, 0x00, 0x00, 0x00,
0x67, 0x80, 0x00, 0x00, 0x13, 0x01, 0x01, 0xfe, 0x23, 0x2c, 0x81, 0x00,
0x13, 0x04, 0x10, 0x00, 0x23, 0x2a, 0x91, 0x00, 0x23, 0x28, 0x21, 0x01,
0x23, 0x26, 0x31, 0x01, 0x23, 0x22, 0x51, 0x01, 0x23, 0x20, 0x61, 0x01,
0x23, 0x2e, 0x11, 0x00, 0x23, 0x24, 0x41, 0x01, 0x13, 0x09, 0x05, 0x00,
0x93, 0x09, 0x00, 0x00, 0x93, 0x04, 0x04, 0x00, 0x93, 0x0a, 0x20, 0x00,
0x13, 0x0b, 0x04, 0x00, 0x63, 0x56, 0x89, 0x02, 0x83, 0x20, 0xc1, 0x01,
0x03, 0x24, 0x81, 0x01, 0x83, 0x24, 0x41, 0x01, 0x03, 0x29, 0x01, 0x01,
0x83, 0x29, 0xc1, 0x00, 0x03, 0x2a, 0x81, 0x00, 0x83, 0x2a, 0x41, 0x00,
0x03, 0x2b, 0x01, 0x00, 0x13, 0x01, 0x01, 0x02, 0x67, 0x80, 0x00, 0x00,
0x63, 0xd0, 0x8a, 0x02, 0x33, 0x8a, 0x34, 0x01, 0x13, 0x05, 0x0a, 0x00,
0xef, 0xf0, 0xdf, 0xf6, 0x93, 0x89, 0x04, 0x00, 0x13, 0x04, 0x14, 0x00,
0x93, 0x04, 0x0a, 0x00, 0x6f, 0xf0, 0x9f, 0xfb, 0x13, 0x85, 0x09, 0x00,
0x63, 0x04, 0x64, 0x01, 0x13, 0x85, 0x04, 0x00, 0xef, 0xf0, 0xdf, 0xf4,
0x13, 0x8a, 0x04, 0x00, 0x6f, 0xf0, 0x1f, 0xfe, 0x13, 0x01, 0x01, 0xfe,
0x23, 0x2c, 0x81, 0x00, 0x23, 0x2a, 0x91, 0x00, 0x23, 0x26, 0x31, 0x01,
0x23, 0x2e, 0x11, 0x00, 0x23, 0x28, 0x21, 0x01, 0x93, 0x04, 0x05, 0x00,
0x13, 0x04, 0x06, 0x00, 0x93, 0x09, 0x20, 0x00, 0x63, 0xd0, 0x99, 0x02,
0x33, 0x89, 0x85, 0x00, 0x13, 0x05, 0x09, 0x00, 0xef, 0xf0, 0x1f, 0xf1,
0x93, 0x05, 0x04, 0x00, 0x93, 0x84, 0xf4, 0xff, 0x13, 0x04, 0x09, 0x00,
0x6f, 0xf0, 0x5f, 0xfe, 0x83, 0x20, 0xc1, 0x01, 0x03, 0x24, 0x81, 0x01,
0x83, 0x24, 0x41, 0x01, 0x03, 0x29, 0x01, 0x01, 0x83, 0x29, 0xc1, 0x00,
0x13, 0x01, 0x01, 0x02, 0x67, 0x80, 0x00, 0x00, 0x13, 0x01, 0x01, 0xff,
0x23, 0x24, 0x81, 0x00, 0x13, 0x04, 0x05, 0x00, 0x13, 0x05, 0x00, 0x00,
0x23, 0x26, 0x11, 0x00, 0xef, 0xf0, 0xdf, 0xec, 0x13, 0x05, 0x10, 0x00,
0xef, 0xf0, 0x5f, 0xec, 0x13, 0x05, 0x04, 0x00, 0x03, 0x24, 0x81, 0x00,
0x83, 0x20, 0xc1, 0x00, 0x13, 0x06, 0x10, 0x00, 0x93, 0x05, 0x00, 0x00,
0x13, 0x01, 0x01, 0x01, 0x6f, 0xf0, 0x9f, 0xf6, 0x13, 0x01, 0x01, 0xff,
0x37, 0x05, 0x00, 0x80, 0x23, 0x26, 0x11, 0x00, 0x13, 0x05, 0x45, 0x1c,
0x93, 0x05, 0x00, 0x00, 0x93, 0x08, 0x30, 0x00, 0x73, 0x00, 0x00, 0x00,
0x13, 0x05, 0x80, 0x02, 0xef, 0xf0, 0x5f, 0xea, 0x37, 0x05, 0x00, 0x80,
0x13, 0x05, 0x05, 0x1d, 0x93, 0x05, 0x00, 0x00, 0x93, 0x08, 0x30, 0x00,
0x73, 0x00, 0x00, 0x00, 0x83, 0x20, 0xc1, 0x00, 0x13, 0x05, 0x80, 0x02,
0x13, 0x01, 0x01, 0x01, 0x6f, 0xf0, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x69, 0x62, 0x28,
0x29, 0x20, 0x6c, 0x6f, 0x6f, 0x70, 0x00, 0x00, 0x66, 0x69, 0x62, 0x28,
0x29, 0x20, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x00
};
int main(int argc, char *argv[]) {
uvm32_state_t vmst[NUM_VM];
uvm32_evt_t evt;
int numVmRunning = NUM_VM;
int scheduler_index = 0;
for (int i=0;i<NUM_VM;i++) {
uvm32_init(&vmst[i]);
uvm32_load(&vmst[i], rom, sizeof(rom));
}
while(numVmRunning > 0) {
if (uvm32_hasEnded(&vmst[scheduler_index])) {
// this vm has already completed, pick another
SCHEDULE();
continue;
}
uvm32_run(&vmst[scheduler_index], &evt, 100); // num instructions before vm considered hung
switch(evt.typ) {
case UVM32_EVT_END:
printf("[VM %d ended]\n", scheduler_index);
numVmRunning--;
break;
case UVM32_EVT_SYSCALL: // vm has paused to handle UVM32_SYSCALL
switch(evt.data.syscall.code) {
case UVM32_SYSCALL_YIELD:
break;
case UVM32_SYSCALL_PRINTLN: {
const char *str = uvm32_getcstr(&vmst[scheduler_index], &evt, ARG0);
if (str[0] != 0) {
printf("[VM %d] %s\n", scheduler_index, str);
}
} break;
case UVM32_SYSCALL_PRINTDEC:
printf("[VM %d] %d\n", scheduler_index, uvm32_getval(&vmst[scheduler_index], &evt, ARG0));
break;
default:
printf("Unhandled syscall 0x%08x\n", evt.data.syscall.code);
break;
}
break;
case UVM32_EVT_ERR:
printf("UVM32_EVT_ERR '%s' (%d)\n", evt.data.err.errstr, (int)evt.data.err.errcode);
break;
default:
break;
}
SCHEDULE();
}
return 0;
}