4.9 Export ( Direct Programming Interface)

4.9.9 Running Another process in parallel

With power of SystemVerilog DPI task, we can run both simulation and another process in parallel, polling status of the invoked process. Video capture is here.
Below is an example process from gallery of matplotlib. ( You need additional installations, numpy and matplotlib as python library for run.)

01import numpy as np
02import matplotlib.pyplot as plt
03import matplotlib.animation as animation
04 
05def data_gen():
06    t = data_gen.t
07    cnt = 0
08    while cnt < 500:
09        cnt+=1
10        t += 0.05
11        yield t, np.sin(2*np.pi*t) * np.exp(-t/10.)
12data_gen.t = 0
13 
14fig = plt.figure()
15ax = fig.add_subplot(111)
16line, = ax.plot([], [], lw=2)
17ax.set_ylim(-1.1, 1.1)
18ax.set_xlim(0, 5)
19ax.grid()
20xdata, ydata = [], []
21def run(data):
22    # update the data
23    t,y = data
24    xdata.append(t)
25    ydata.append(y)
26    xmin, xmax = ax.get_xlim()
27 
28    if t >= xmax:
29        ax.set_xlim(xmin, 2*xmax)
30        ax.figure.canvas.draw()
31    line.set_data(xdata, ydata)
32 
33    return line,
34 
35ani = animation.FuncAnimation(fig, run, data_gen, blit=True, interval=10,
36    repeat=False)
37plt.show()


We invoke this process (animation) by C as imported task in SystemVerilog per following cpp source.Please note this is real multi-process, not quasi-mulltithread.
Generally speaking, simulator engine is single process, and DPI is not thread-safe for multiple threads. However you can invoke multiple process or threads if you take care of your own threads.

Important point is to pass the control to simulation kernel by calling exported task , "delay".
With the task,we can poll status of invoked process every 1000 clks.

01#include <windows.h>
02#include <vpi_user.h>
03#include <svdpi.h>
04#include <cassert>
05#include <iostream>
06#include "..\source\dpi_veritak_header.h"
07 
08 
09extern "C"  __declspec(dllexport) int process_run() //task
10{      
11        STARTUPINFO si;
12        PROCESS_INFORMATION pi;
13        const char command[]="C:\\Python33\\python decade.py";
14         
15        //Run Python animation
16        bool success=CreateProcess(NULL, (LPSTR)command, NULL, NULL, TRUE, 0, NULL, NULL, &si, π);
17        if (success){
18                WaitForInputIdle(pi.hProcess, INFINITE);
19                while (1){
20                        DWORD status=WaitForSingleObject(pi.hProcess, 0);//
21                        if (status==WAIT_TIMEOUT){//If process still exists
22                                delay(1000);//We will be alive after 1000clks
23 
24                                 
25                        }else {
26                                //If the process exits, we also exit.
27                                CloseHandle(pi.hThread);
28                                CloseHandle(pi.hProcess);
29                                return 0;
30                        }
31                }
32                 
33        }
34        return 0;
35}</iostream></cassert></svdpi.h></vpi_user.h></windows.h>


In SystemVerilog source,we make 4 threads. If any of thread finishes, then we'll exit.

01program hello_dpi_world;
02 
03         
04        import "DPI-C" context task process_run();
05        export "DPI-C" task delay;
06 
07        bit clk=0;
08        int counter=0;
09 
10 
11        task delay(longint rep1) ;
12                repeat(rep1) begin
13                        @(negedge clk);
14                end
15        endtask
16 
17         
18 
19        initial
20                fork //4 threads run in parallel
21                        forever #10                     clk=~clk;
22                        forever @(posedge clk) counter<=counter+1;
23                        process_run();
24                        wait (counter==20000000);
25                join_any
26                //Finished!
27         
28 
29 
30endprogram