From 38f9b3344ab6e1e0ccfe1a1d638aaf9102ed165a Mon Sep 17 00:00:00 2001 From: Aba Date: Sat, 26 Aug 2023 12:59:33 -0700 Subject: [PATCH] Add basic DPI-C firmware for xsim & verilator --- .gitignore | 3 ++- c/example.c | 5 ++++ c/model.h | 10 ++++++++ c/runtime.h | 49 ++++++++++++++++++++++++++++++++++++++++ test/py/param_test.py | 25 ++++++++++++-------- test/sv/dnn_engine_tb.sv | 34 +++++++++++++++------------- test/sv/model.svh | 12 +++++----- 7 files changed, 105 insertions(+), 33 deletions(-) create mode 100644 c/example.c create mode 100644 c/model.h create mode 100644 c/runtime.h diff --git a/.gitignore b/.gitignore index c034ee8..5906292 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,8 @@ asic/* *.pickle test/vectors test/xsim -test/c +test/oldc +test/xsc* test/obj_dir test/models diff --git a/c/example.c b/c/example.c new file mode 100644 index 0000000..818218b --- /dev/null +++ b/c/example.c @@ -0,0 +1,5 @@ +#include "runtime.h" + +int example_main (){ + return 0; +} \ No newline at end of file diff --git a/c/model.h b/c/model.h new file mode 100644 index 0000000..6d9203a --- /dev/null +++ b/c/model.h @@ -0,0 +1,10 @@ +const int N_BUNDLES = 6; + +Bundle_t bundles [] = { + {.w_wpt=2368, .w_wpt_p0=2368, .x_wpt=424, .x_wpt_p0=424, .y_wpt=16, .y_wpt_last=96, .y_nl=4, .y_w=3, .n_it=8, .n_p=3 }, + {.w_wpt=2208, .w_wpt_p0=2208, .x_wpt=840, .x_wpt_p0=840, .y_wpt=24, .y_wpt_last=96, .y_nl=4, .y_w=5, .n_it=6, .n_p=8 }, + {.w_wpt=1568, .w_wpt_p0=608, .x_wpt=1256, .x_wpt_p0=424, .y_wpt=32, .y_wpt_last=96, .y_nl=4, .y_w=6, .n_it=4, .n_p=6 }, + {.w_wpt=1176, .w_wpt_p0=312, .x_wpt=2088, .x_wpt_p0=424, .y_wpt=64, .y_wpt_last=128, .y_nl=4, .y_w=7, .n_it=3, .n_p=4 }, + {.w_wpt=1176, .w_wpt_p0=744, .x_wpt=6248, .x_wpt_p0=3752, .y_wpt=192, .y_wpt_last=192, .y_nl=4, .y_w=8, .n_it=3, .n_p=2 }, + {.w_wpt=392, .w_wpt_p0=272, .x_wpt=398, .x_wpt_p0=268, .y_wpt=192, .y_wpt_last=192, .y_nl=2, .y_w=1, .n_it=1, .n_p=427 } +}; \ No newline at end of file diff --git a/c/runtime.h b/c/runtime.h new file mode 100644 index 0000000..fa84fc5 --- /dev/null +++ b/c/runtime.h @@ -0,0 +1,49 @@ +typedef struct { + const int w_wpt, w_wpt_p0; // words per transfer + const int x_wpt, x_wpt_p0; + const int y_wpt, y_wpt_last; + const int y_nl, y_w; + const int n_it, n_p; +} Bundle_t; + +#include "model.h" +#include + +#ifdef VERILATOR + #define EXT_C "C" +#else + #define EXT_C +#endif + + +extern EXT_C void load_x (svBit* done, int* ib_out, int* ip_out) { + + static int ib=0, ip=0, it=0; + *done =0; + + // Nested for loop [for ib: for ip: for it: {}] inverted to increment once per call + ++ it; if (it >= bundles[ib].n_it) { it = 0; + ++ ip; if (ip >= bundles[ib].n_p) { ip = 0; + ++ ib; if (ib >= N_BUNDLES) { ib = 0; + *done =1; + }}} + *ib_out = ib; + *ip_out = ip; +} + + +extern EXT_C void load_w (svBit* done, int* ib_out, int* ip_out, int* it_out) { + + static int ib=0, ip=0, it=0; + *done =0; + + // Nested for loop [for ib: for ip: for it: {}] inverted to increment once per call + ++ it; if (it >= bundles[ib].n_it) { it = 0; + ++ ip; if (ip >= bundles[ib].n_p) { ip = 0; + ++ ib; if (ib >= N_BUNDLES) { ib = 0; + *done =1; + }}} + *ib_out = ib; + *ip_out = ip; + *it_out = it; +} \ No newline at end of file diff --git a/test/py/param_test.py b/test/py/param_test.py index fc6902d..e7725fa 100644 --- a/test/py/param_test.py +++ b/test/py/param_test.py @@ -138,7 +138,9 @@ def compile(c): if SIM == 'xsim': SOURCES_STR = " ".join([os.path.normpath('../' + s) for s in SOURCES]) # since called from subdir xvlog_cmd = fr'{XIL_PATH}\xvlog -sv {SOURCES_STR}' - xelab_cmd = fr'{XIL_PATH}\xelab {TB_MODULE} --snapshot {TB_MODULE} -log elaborate.log --debug typical' + xelab_cmd = fr'{XIL_PATH}\xelab {TB_MODULE} --snapshot {TB_MODULE} -log elaborate.log --debug typical -sv_lib dpi' + xsc_cmd = fr'{XIL_PATH}\xsc ../../c/example.c' + assert subprocess.run(xsc_cmd, cwd="xsim", shell=True).returncode == 0 assert subprocess.run(xvlog_cmd, cwd="xsim", shell=True).returncode == 0 assert subprocess.run(xelab_cmd, cwd="xsim", shell=True).returncode == 0 @@ -148,7 +150,7 @@ def compile(c): assert subprocess.run(cmd).returncode == 0 if SIM == "verilator": - cmd = f"verilator --binary -j 0 -Wno-fatal --relative-includes --top {TB_MODULE} " + " ".join(SOURCES) + cmd = f"verilator --binary -j 0 -Wno-fatal --relative-includes --top {TB_MODULE} " + " ".join(SOURCES) + ' -CFLAGS -DVERILATOR ../c/example.c' print(cmd) assert subprocess.run(cmd.split(' ')).returncode == 0 @@ -227,9 +229,11 @@ def test_dnn_engine(COMPILE): c = make_compile_params(COMPILE) bundles = model.layers[2:] - with open('sv/model.svh', 'w') as f: - f.write(f"localparam N_BUNDLES = {len(bundles)};\n\n") - f.write(f"Bundle_t bundles [N_BUNDLES] = '{{\n") + with open('sv/model.svh', 'w') as vh, open ('../c/model.h', 'w') as ch: + vh.write(f"localparam N_BUNDLES = {len(bundles)};\n\n") + vh.write(f"Bundle_t bundles [N_BUNDLES] = '{{\n") + ch.write(f"const int N_BUNDLES = {len(bundles)};\n\n") + ch.write(f"Bundle_t bundles [] = {{\n") for b in bundles: print(f'-----------------{b.idx}-----------------------') @@ -246,12 +250,13 @@ def test_dnn_engine(COMPILE): y_wpt = b.r.CO_PRL*b.c.ROWS y_wpt_last = b.r.CO_PRL*b.c.ROWS*(b.r.KW//2+1) - f.write(f" '{{w_wpt:{b.we[-1].size}, w_wpt_p0:{b.we[0].size}, x_wpt:{b.xe[-1].size}, x_wpt_p0:{b.xe[0].size}, y_wpt:{y_wpt}, y_wpt_last:{y_wpt_last}, y_nl:{b.r.XN*b.r.L}, y_w:{b.r.XW-b.r.KW//2}, n_it:{b.r.IT}, n_p:{b.r.CP} }}") + vh.write(f" '{{ w_wpt:{b.we[-1].size}, w_wpt_p0:{b.we[0].size}, x_wpt:{b.xe[-1].size}, x_wpt_p0:{b.xe[0].size}, y_wpt:{y_wpt}, y_wpt_last:{y_wpt_last}, y_nl:{b.r.XN*b.r.L}, y_w:{b.r.XW-b.r.KW//2}, n_it:{b.r.IT}, n_p:{b.r.CP} }}") + ch.write(f" {{.w_wpt={b.we[-1].size}, .w_wpt_p0={b.we[0].size}, .x_wpt={b.xe[-1].size}, .x_wpt_p0={b.xe[0].size}, .y_wpt={y_wpt}, .y_wpt_last={y_wpt_last}, .y_nl={b.r.XN*b.r.L}, .y_w={b.r.XW-b.r.KW//2}, .n_it={b.r.IT}, .n_p={b.r.CP} }}") if b.idx != len(bundles)-1: - f.write(',\n') - f.write(f"\n}};") - - + vh.write(',\n') + ch.write(',\n') + vh.write(f"\n}};") + ch.write(f"\n}};") ''' RUN SIMULATION ''' diff --git a/test/sv/dnn_engine_tb.sv b/test/sv/dnn_engine_tb.sv index bfcfba1..b8925bc 100644 --- a/test/sv/dnn_engine_tb.sv +++ b/test/sv/dnn_engine_tb.sv @@ -3,7 +3,7 @@ `include "../../rtl/include/params.svh" `include "../xsim/sim_params.svh" -typedef struct packed { +typedef struct { int w_wpt, w_wpt_p0; // words per transfer int x_wpt, x_wpt_p0; int y_wpt, y_wpt_last; @@ -70,24 +70,26 @@ module dnn_engine_tb; bit done_y = 0; string w_path, x_path, y_path; + int xib=0, xip=0, wib=0, wip=0, wit=0; + bit x_done, w_done; + import "DPI-C" function void load_x(inout bit x_done, inout int xib, xip); + import "DPI-C" function void load_w(inout bit w_done, inout int wib, wip, wit); initial - for (int ib=0; ib < N_BUNDLES; ib++) - for (int ip=0; ip < bundles[ib].n_p; ip++) - for (int it=0; it < bundles[ib].n_it; it++) begin - $sformat(w_path, "%s%0d_%0d_%0d_w.txt", DIR_PATH, ib, ip, it); - source_k.axis_push (w_path); - $display("done w: %0d_%0d_%0d_w.txt", ib, ip, it); - end + while (1) begin + $sformat(w_path, "%s%0d_%0d_%0d_w.txt", DIR_PATH, wib, wip, wit); + source_k.axis_push(w_path); + load_w (w_done, wib, wip, wit); + if (w_done) break; + end - initial - for (int ib=0; ib < N_BUNDLES; ib++) - for (int ip=0; ip < bundles[ib].n_p; ip++) - for (int it=0; it < bundles[ib].n_it; it++) begin - $sformat(x_path, "%s%0d_%0d_x.txt", DIR_PATH, ib, ip); - source_x.axis_push (x_path); - $display("done x: %0d_%0d_x.txt", ib, ip); - end + initial + while (1) begin + $sformat(x_path, "%s%0d_%0d_x.txt", DIR_PATH, xib, xip); + source_x.axis_push(x_path); + load_x (x_done, xib, xip); + if (x_done) break; + end `define RAND_DELAY repeat($urandom_range(1000/READY_PROB-1)) @(posedge aclk) #1; diff --git a/test/sv/model.svh b/test/sv/model.svh index e865996..7fcbe7d 100644 --- a/test/sv/model.svh +++ b/test/sv/model.svh @@ -1,10 +1,10 @@ localparam N_BUNDLES = 6; Bundle_t bundles [N_BUNDLES] = '{ - '{w_wpt:2368, w_wpt_p0:2368, x_wpt:424, x_wpt_p0:424, y_wpt:16, y_wpt_last:96, y_nl:4, y_w:3, n_it:8, n_p:3 }, - '{w_wpt:2208, w_wpt_p0:2208, x_wpt:840, x_wpt_p0:840, y_wpt:24, y_wpt_last:96, y_nl:4, y_w:5, n_it:6, n_p:8 }, - '{w_wpt:1568, w_wpt_p0:608, x_wpt:1256, x_wpt_p0:424, y_wpt:32, y_wpt_last:96, y_nl:4, y_w:6, n_it:4, n_p:6 }, - '{w_wpt:1176, w_wpt_p0:312, x_wpt:2088, x_wpt_p0:424, y_wpt:64, y_wpt_last:128, y_nl:4, y_w:7, n_it:3, n_p:4 }, - '{w_wpt:1176, w_wpt_p0:744, x_wpt:6248, x_wpt_p0:3752, y_wpt:192, y_wpt_last:192, y_nl:4, y_w:8, n_it:3, n_p:2 }, - '{w_wpt:392, w_wpt_p0:272, x_wpt:398, x_wpt_p0:268, y_wpt:192, y_wpt_last:192, y_nl:2, y_w:1, n_it:1, n_p:427 } + '{ w_wpt:2368, w_wpt_p0:2368, x_wpt:424, x_wpt_p0:424, y_wpt:16, y_wpt_last:96, y_nl:4, y_w:3, n_it:8, n_p:3 }, + '{ w_wpt:2208, w_wpt_p0:2208, x_wpt:840, x_wpt_p0:840, y_wpt:24, y_wpt_last:96, y_nl:4, y_w:5, n_it:6, n_p:8 }, + '{ w_wpt:1568, w_wpt_p0:608, x_wpt:1256, x_wpt_p0:424, y_wpt:32, y_wpt_last:96, y_nl:4, y_w:6, n_it:4, n_p:6 }, + '{ w_wpt:1176, w_wpt_p0:312, x_wpt:2088, x_wpt_p0:424, y_wpt:64, y_wpt_last:128, y_nl:4, y_w:7, n_it:3, n_p:4 }, + '{ w_wpt:1176, w_wpt_p0:744, x_wpt:6248, x_wpt_p0:3752, y_wpt:192, y_wpt_last:192, y_nl:4, y_w:8, n_it:3, n_p:2 }, + '{ w_wpt:392, w_wpt_p0:272, x_wpt:398, x_wpt_p0:268, y_wpt:192, y_wpt_last:192, y_nl:2, y_w:1, n_it:1, n_p:427 } }; \ No newline at end of file