diff options
| author | 2025-08-15 22:44:36 +0330 | |
|---|---|---|
| committer | 2025-08-15 22:44:36 +0330 | |
| commit | 20790228a29b036e0aa9d91cfca15b2d52697331 (patch) | |
| tree | 67b538767482cc06ea0dcff85d47de957a72df9b /pu2/pu2.c | |
| parent | benchmark + operations + extra stufferinos (diff) | |
more cooler and more betterer
Diffstat (limited to 'pu2/pu2.c')
| -rw-r--r-- | pu2/pu2.c | 254 |
1 files changed, 157 insertions, 97 deletions
@@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200809L #include "pu2.out.c" #include <stdio.h> #include <time.h> @@ -42,27 +43,38 @@ error_debug(string fail_point, string code, int sz) { } } + int line_start = error_pos; + while (line_start > 0 && code[ line_start - 1 ] != '\n') { line_start--; } + + int line_end = error_pos; + while (line_end < sz && code[ line_end ] != '\n' && code[ line_end ] != '\0') { line_end++; } + + int tmp = line; + int lineno_width = 1; + while (tmp >= 10) { + lineno_width++; + tmp /= 10; + } + fprintf( stderr, - "\x1b[1m\x1b[31merror:\x1b[0m " - "\x1b[1massembly failed\x1b[0m " + "\x1b[1m\x1b[31merror:\x1b[0m \x1b[1massembly failed\x1b[0m " "at \x1b[36mline %d\x1b[0m, \x1b[36mcolumn %d\x1b[0m " "(\x1b[33mposition %d\x1b[0m):\n", line, col, error_pos); - int line_start = error_pos; - while (line_start > 0 && code[ line_start - 1 ] != '\n') { line_start--; } - - int line_end = error_pos; - while (line_end < sz && code[ line_end ] != '\n' && code[ line_end ] != '\0') { line_end++; } - - fprintf(stderr, " \x1b[1m"); - for (i = line_start; i < line_end; i++) { fputc(code[ i ], stderr); } - fprintf(stderr, "\x1b[0m\n"); + fprintf( + stderr, + " %*d | \x1b[1m%.*s\x1b[0m\n", + lineno_width, + line, + line_end - line_start, + code + line_start); - fprintf(stderr, " "); + /* print caret line aligned under the column */ + fprintf(stderr, " %*s | ", lineno_width, ""); for (i = line_start; i < error_pos; i++) { fputc((code[ i ] == '\t') ? '\t' : ' ', stderr); } fprintf(stderr, "\x1b[1m\x1b[31m^\x1b[0m \x1b[90mparsing stopped here\x1b[0m\n"); } @@ -173,6 +185,11 @@ typedef struct { slice value; } entry; +typedef struct { + entry data; + byte arg_count; +} macro; + clean_slice_ref(slice *val) { free(val->ref); } #define static_len(G) (sizeof(G) / sizeof((G)[ 0 ])) @@ -187,26 +204,21 @@ clean_slice_ref(slice *val) { free(val->ref); } emit(opcode.acc, 1); \ emit(opcode.str, 0); \ }) -#define run_err(result) \ +#define run_err(result, ...) \ ({ \ - printf("\n"); \ + ERR_code = init_I; \ + fprintf(stderr, "\n"); \ error_debug((result), ERR_code, strlen(ERR_code)); \ - printf("\nir2 error message: %s\n", ERR); \ - printf("\n"); \ + fprintf(stderr, "\n\x1b[1m\x1b[31mir2 error:\x1b[0m "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n\n"); \ exit(1); \ }) -#define checkskip(char, message) \ +#define checkskip(char, ...) \ ({ \ - if (!*I) { \ - ERR = (message); \ - run_err(I); \ - } \ - if (*I++ != (char) ) { \ - ERR = (message); \ - ERR_code = init_I; \ - run_err(I - 1); \ - } \ + if (!*I) { run_err(I, __VA_ARGS__); } \ + if (*I++ != (char) ) { run_err(I - 1, __VA_ARGS__); } \ }) #define scanword() \ ({ \ @@ -245,8 +257,7 @@ clean_slice_ref(slice *val) { free(val->ref); } Data[ -1 ] = 0; \ value = Data - m; \ } else { \ - ERR = "expected value (number, character, string)"; \ - run_err(I); \ + run_err(I, "expected value (number, character, string)"); \ } \ value; \ }) @@ -295,7 +306,7 @@ string ERR; string ERR_code; int *Code = &m[ 4000 ]; int *Data = &m[ static_len(m) - 1 ]; // grows downwards -_ir2(string I, entry macros[ 1 << 9 ]) { +_ir2(string I, macro macros[ 1 << 9 ]) { string init_I = I; ERR = "all good"; @@ -319,10 +330,7 @@ _ir2(string I, entry macros[ 1 << 9 ]) { if (*I == '@') { I++; - if (!isdigit(*I)) { - ERR = "expected a digit after @"; - run_err(I); - } + if (!isdigit(*I)) { run_err(I, "expected a digit after @"); } int mem2_index = strtol(I, &I, 10); @@ -387,8 +395,7 @@ _ir2(string I, entry macros[ 1 << 9 ]) { // parse macro stuff if (!isalpha(*I) && *I != '_') { - ERR = "expected letter at macro name"; - run_err(I - 1); + run_err(I - 1, "expected letter or underscore at macro name"); } slice name = scanword(); @@ -398,10 +405,18 @@ _ir2(string I, entry macros[ 1 << 9 ]) { skip_space(&I); + string before = I; + int arg_count = strtol(I, &I, 10); + if (I == before) { + run_err(I, "expected number (argument count) in macro definition parens"); + } + + skip_space(&I); + checkskip( ')', - "expected close paren in macro definition (hint: macros do not take named " - "arguments)"); + "expected close paren in macro definition (hint: macro defintions only take an " + "argument count)"); skip_space(&I); @@ -410,26 +425,26 @@ _ir2(string I, entry macros[ 1 << 9 ]) { // find open space in macros int x; for (x = 0; x < (1 << 9); x++) { - entry g = macros[ x ]; - if (g.key.ref == NULL) { goto DONE; } + macro g = macros[ x ]; + if (g.data.key.ref == NULL) { goto DONE; } } - ERR = "macro count exceeded 1<<9"; - run_err(I - 1); + run_err(I - 1, "registered macro count exceeded 1<<9 (how?)"); DONE:; skip_space(&I); // might aswell skip whitespace for funsies. - entry *g = ¯os[ x ]; - g->key = name; - g->value.ref = I; - g->value.len = 0; + macro *g = ¯os[ x ]; + g->data.key = name; + g->data.value.ref = I; + g->data.value.len = 0; + g->arg_count = arg_count; int dep = 0; while (dep != 0 || *I != '}') { if (*I == '{') dep++; if (*I == '}') dep--; - g->value.len++; + g->data.value.len++; I++; if (*I == 0) { @@ -449,8 +464,7 @@ _ir2(string I, entry macros[ 1 << 9 ]) { string old = I; int value = strtol(I, &I, 10); if (old == I && *I != ')') { - ERR = "invalid input to exit blob, expected number"; - run_err(I - 1); + run_err(I - 1, "invalid input to exit blob, expected number"); } skip_space(&I); @@ -497,11 +511,10 @@ _ir2(string I, entry macros[ 1 << 9 ]) { slice arguments[ 1 << 7 ]; size_t arg_count = 0; + string fail_I = I; + while (*I != ')') { - if (!*I) { - ERR = "reached EOF whilst looking for closing paren on blob"; - run_err(I); - } + if (!*I) run_err(fail_I, "reached EOF whilst looking for closing paren on blob"); checkskip('[', "expected bracket in blob argument (macro-type)"); arguments[ arg_count ].len = 0; @@ -525,8 +538,7 @@ _ir2(string I, entry macros[ 1 << 9 ]) { skip_space(&I); if (*I != ',' && *I != ')') { - ERR = "expected comma or closing paren in blob"; - run_err(I); + run_err(I, "expected comma or closing paren in blob"); } if (*I == ',') { @@ -537,6 +549,8 @@ _ir2(string I, entry macros[ 1 << 9 ]) { arg_count++; } + fail_I = I; + checkskip(')', "expected closing paren after blob arguments"); skip_space(&I); checkskip(';', "expected semicolon after blob"); @@ -545,16 +559,22 @@ _ir2(string I, entry macros[ 1 << 9 ]) { // find index size_t i; for (i = 0; i < (1 << 9); i++) { - entry cur = macros[ i ]; - if (cur.key.len != name.len) continue; - if (strncmp(name.ref, cur.key.ref, name.len) == 0) goto FOUND; + macro cur = macros[ i ]; + if (cur.data.key.len != name.len) continue; + if (strncmp(name.ref, cur.data.key.ref, name.len) == 0) goto FOUND; } - ERR = "could not find a macro by that name"; - run_err(I); + run_err(I, "could not find a macro by that name"); FOUND:; - slice target = macros[ i ].value; + if (arg_count != macros[ i ].arg_count) { + run_err( + fail_I, + "macro argument count mismatch (expected %i, got %li)", + macros[ i ].arg_count, + arg_count); + } + slice target = macros[ i ].data.value; string N = target.ref; string oldN = N; memslice new = { target.len, malloc(target.len) }; @@ -613,11 +633,12 @@ _ir2(string I, entry macros[ 1 << 9 ]) { } ir2(string I) { - entry macros[ 1 << 9 ]; + macro macros[ 1 << 9 ] = {0}; _ir2(I, macros); } -string op_names[] = { "hlt", "imm", "lod", "str", "swp", "add", "sub", "and", "not", "acc" }; +string op_names[] = { "hlt", "imm", "lod", "str", "swp", "add", "sub", + "and", "not", "acc", "a2u", "u2a", "b2u", "u2b" }; unsigned long long rdtsc(void) { unsigned hi, lo; @@ -646,14 +667,39 @@ double bench_cycle(int instr) { return (double) m[ 7 ] / seconds / 1e6; } -benchmark() { +double bench2_cycle(int instr) { + unsigned long long start, end; + double vminst_count, cpu_cycles; + int i; + for (i = 0; i < S - 2; i += 2) { + m[ i ] = instr; + m[ i + 1 ] = 5; + } + m[ S - 2 ] = 0; + m[ S - 1 ] = 0; + m[ 7 ] = 0; + c = 0; + start = rdtsc(); + pu2(); + end = rdtsc(); + cpu_cycles = (double) (end - start); + vminst_count = (double) m[ 7 ]; + printf("pu2/real: %f\n", cpu_cycles / vminst_count); + return cpu_cycles / vminst_count; +} + +benchmark(double (*target)(int)) { double results[ 13 ]; - double sum = 0; - for (i = 0; i < 13; i++) { - results[ i ] = bench_cycle(i); + double sum = 0; + int count = 0; + int i; + for (i = 1; i < 14; i++) { + printf("running: %s\n", op_names[ i ]); + results[ i ] = target(i); sum += results[ i ]; + count++; } - sum /= 13; + sum /= count; unsigned long long start, end; start = rdtsc(); @@ -661,18 +707,57 @@ benchmark() { end = rdtsc(); float clock_speed = (end - start) / 1e6; - printf("clock speed ~ %.6f MHz\n", clock_speed); printf("results sum: %f\n", sum); - printf("instructions per cycle: %f\n", clock_speed / sum); + if (target == bench_cycle) { + printf("clock speed ~ %.6f MHz\n", clock_speed); + printf("instructions per cycle: %f\n", clock_speed / sum); + } } -main() { +long nstime() { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_nsec; +} + +main(int argc, char **argv) { + if (argc == 1) { + return printf( + "\nusage:\n" + " %s <file_name> open and compile ir2-compliant code\n" + " %s --bench benchmark pu2\n\n", + argv[ 0 ], + argv[ 0 ]); + } + + if (strcmp(argv[ 1 ], "--bench") == 0) { + benchmark(bench_cycle); + benchmark(bench2_cycle); + exit(0); + } + + char *filename = argv[ 1 ]; + size_t file_size; + string contents = read_file(filename, &file_size); + if (contents == NULL) { + perror("unable to open file"); + exit(1); + } + size_t o_size; - ir2(read_file("code.i2", &o_size)); + long before = nstime(); + long cycles_bef = rdtsc(); + ir2(contents); + long cycles_aft = rdtsc(); + long after = nstime(); m[ 7 ] = 4000; + // fprintf(stderr, "assembly took %li nanoseconds (%li cycles)\n", (after - before), (cycles_aft - cycles_bef)); + free(contents); + size_t res_size = Code - &m[ 4000 ]; // --- BYTES PRINTING --- + // for(i = 0; i < res_size; i++) { // printf("%X%X ", m[4000+i]>>4, m[4000+i]&0b1111); // if(i % 8 == 7) printf("\n"); @@ -681,6 +766,7 @@ main() { // printf("\n\n"); // --- OPCODES PRINTING --- + // for (i = 0; i < res_size; i++) { // int op = m[ 4000 + i++ ]; // int data = m[ 4000 + i ]; @@ -690,30 +776,4 @@ main() { // printf("\n\n"); emu(); - printf("result: %i\n", m[ 10 ]); -} - -main2(int argc, char **argv) { - if (argc == 1) { - return printf( - "\nusage:\n" - " %s <file_name>\n\n", - argv[ 0 ]); - } - - char *filename = argv[ 1 ]; - size_t file_size; - char *contents = read_file(filename, &file_size); - - E = 0; - K = &m[ 1024 ]; - as2(contents); - - if (E != 0) { - error_debug(E, contents, file_size); - exit(1); - } - - m[ 7 ] = 1024; - emu(); } |
