加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[转载]Systemverilog中DPI使用指南--2

(2014-02-21 16:39:30)
标签:

转载

 

第1章 任务和函数

1.1 导入的任务和函数

语法:

import "DPI" [c_identifier =] [pure][context] function type name (args);

import "DPI" [c_identifier =] [context] task name (args);

规则说明:

1.       Context
使用context修饰的函数和任务,可以访问申明时的范围内的变量,而不仅仅局限在他的参数上。函数可以是purecontext或者其他类型的,任务只能是context或者non-context类型的。Context会导致仿真的效率变低,所以应当慎重使用。如果某个导出的函数或者任务,在C的环境中,需要通过PLIVPI访问SV范围内的全局变量,或者调用EXPORT的函数或任务,那么需要Context修饰符。

// SystemVerilog side, test.sv

module top;

   import "DPI" context function void c_display();

   export "DPI" task sv_display;

   m1 m1_inst();

   m2 m2_inst();

   initial begin

     c_display();

   end

   task sv_display();

     $display("SV: top");

   endtask

endmodule

module m1;

   import "DPI" context function void c_display();

   export "DPI" task sv_display;

   initial begin

      c_display();

   end

   task sv_display();

      $display("SV: m1");

   endtask

endmodule

module m2;

   import "DPI" context function void c_display();

   export "DPI" task sv_display;

   initial begin

     c_display;

   end

   task sv_display();

      $display("SV: m2");

   endtask

endmodule

#include <svdpi.h>

extern int sv_display();

   void c_display() {

     io_printf("nC: c_displayn");

     sv_display(); }

这个TB的执行结果如下:

C: c_display

SV: m1

C: c_display

SV: m2

C: c_display

SV: top

 

// SystemVerilog side, test.sv

module top;

   import "DPI" context function void c_display();

   export "DPI" task sv_display;

   m1 m1_inst();

   m2 m2_inst();

   initial begin

     #1;

     c_display();

   end

   task sv_display();

     $display("SV: top");

   endtask

endmodule

module m1;

import "DPI" context function void c_display();

   import "DPI" context function void mygetscope();

   export "DPI" task sv_display;

   initial begin

      mygetscope();

      c_display();

   end

   task sv_display();

     $display("SV: m1");

   endtask

endmodule

module m2;

   import "DPI" context function void c_display();

   export "DPI" task sv_display;

   initial begin

      #1;

      c_display;

   end

   task sv_display();

      $display("SV: m2");

   endtask

endmodule

 

#include <svdpi.h>

#include <vcsuser.h>

   extern int sv_display();

   svScope myscope;

   void mygetscope() {

      myscope = svGetScope();

   }

   void c_display() {

      svSetScope(myscope);

      io_printf("nC: c_displayn");

      sv_display();

   }

这个TB的执行结果如下:

C: c_display

SV: m1

C: c_display

SV: m1

C: c_display

SV: m1

显然,在C函数中修改了Scope,那么sv_display将使用这个Scope中的导出任务。

2.       Pure
使用Pure的函数能够提高仿真效率。当函数的结果仅仅依赖它的输入参数时,可以使用pure修饰符,这样的函数是non_void类型的,他的参数没有outputinout类型。这样的函数不能进行任何文件操作,访问任何其余的变量。

3.       输入参数的方向。
可以是inputoutputinout,不能是ref

4.       函数的返回值
必须是简单类型。

1.2 导出的任务和函数

语法:

export "DPI" [c_identifier =] function name;

export "DPI" [c_identifier =] task name;

1.3 示例

#include <svdpi.h>

extern void abp_write(int, int);

void c_test(int base) {

  int addr, data;

  for(addr=base; addr<base+5; addr++) {

    data = addr * 100;

    apb_write(addr, data);

    printf("C_TEST: APB_Write :  addr = 0x%8x, data = 0x%8xn",

addr, data);

  }

}

// SystemVerilog side, test.sv

import "DPI" context task c_test(input int base_addr);

program top;

  semaphore bus_sem = new(1);

    export "DPI" task apb_write;

  task apb_write(input int addr, data);

   bus_sem.get(1);

   #10 $display("VLOG : APB Write : Addr = %x, Data = %x  ", addr, data);

   bus_sem.put(1);

  endtask

    initial begin

    fork

      c_test(32&apos;h1000);

      c_test(32&apos;h2000);

    join

  end

endprogram

0

  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有