Loading

一个SystemC线程与SystemVerilog线程通信的例子

由于项目需要,现在编写了一个systemc的reference model要加入到一个systemverilog的uvm框架里面去。

现在碰到的问题是systemc这边的model是以线程的模式持续运行的,而不是发一个input package给一个output package的模式,因此需要实现:

  1. 整体框架运行在sv中,使用vcs仿真器

  2. 同时拉起一个sc线程和一个sv线程

  3. sv的线程可以控制sc线程中的一个锁的上锁和解锁

经过一番实验后完成的demo如下:

sc代码:

#include "systemc.h"
#include "svdpi.h"
#include "svdpi_src.h"
#include <unistd.h>
#include <iostream>

using namespace std;

extern "C" {
    void wait_for_time(int delay_time);
    bool get_lock();
}

SC_MODULE(ThreadExample) {
    SC_CTOR(ThreadExample) {
        SC_THREAD(thread_func);
    }

    void thread_func() {

        while (true) {
            cout << "systemc thread running" << endl;
            wait_for_time(5);
            while(get_lock())
                wait_for_time(1);
        }
    }
};

extern "C" {

    void echo(char* str) {
        printf("%s\n",str);
    }

    int sc_main(int argc, char* argv[]) {
        ThreadExample thread_example("ThreadExample");
        cout << "thread crearted" << endl;
        sc_start();
        return 0;
    }

    void sc_main_wrapper(int argc, svOpenArrayHandle argv) {
        char* argv_main[argc];
        for (int i = 0; i < argc; i++)
        {
            char ** p = (char **) svGetArrElemPtr(argv, i);
            argv_main[i] = *p;
        }
        sc_main(argc, argv_main); 
    }
}

sv代码:

// tb.sv
module tb;
    import "DPI-C" context task sc_main_wrapper(int argc, string argv[]);  
    import "DPI-C" function void echo(string str);

    export "DPI-C" task wait_for_time;
    export "DPI-C" function get_lock;

    task wait_for_time(input int delay_time);
      //$display("sc time is",$time);
      repeat(delay_time) begin
        #1;
      end
    endtask

    bit lock = 1;

    function bit get_lock();
      return lock;
    endfunction

    string argv[5]; 

    initial begin
      argv[0] = "./uvm";
      argv[1] = "-f";
      argv[2] = "../../../sw/project/build/rvcim.hex";
      argv[3] = "-R";
      argv[4] = "32";

      fork
        begin
          while (1) begin
            $display("sv thread1 running");
            $display("sv time is",$time);
            lock = ~lock;
            $display("lock is ",lock);
            #10;
          end
        end
        begin
          sc_main_wrapper(5, argv);
        end
      join_none
    end
endmodule  

执行结果(截取部分):

sv thread1 running
sv time is              378240
lock is 0
systemc thread running
systemc thread running
sv thread1 running
sv time is              378250
lock is 1
sv thread1 running
sv time is              378260
lock is 0
systemc thread running
systemc thread running
sv thread1 running
sv time is              378270
lock is 1
sv thread1 running
sv time is              378280
lock is 0
systemc thread running
systemc thread running
sv thread1 running
sv time is              378290
lock is 1
sv thread1 running
sv time is              378300
lock is 0
systemc thread running
systemc thread running
sv thread1 running
sv time is              378310
lock is 1
sv thread1 running
sv time is              378320
lock is 0
systemc thread running
systemc thread running
sv thread1 running
sv time is              378330

可以看到运行状态符合预期。

之前碰到的一个问题是,如果在sc线程上锁后等待的while里面不加延时的话,那么整个仿真时间无法再前进,从而sv线程也无法执行到解锁,因此sc线程无法解锁也会一直卡死,最后两个线程一起进入死锁这样一个状态。所以通过给while里面增加一个延时就可以巧妙的解决掉这个问题了。

posted @ 2024-03-13 17:56  sasasatori  阅读(259)  评论(0编辑  收藏  举报