zoukankan      html  css  js  c++  java
  • 数字IC设计-15-DPI(延续)

    简介


    供SV,无论是构建测试激励,或模拟硬件的并行行为,DPI这是非常方便。上次我们介绍SV内通“import”导入和电话C性能。

    在本节,通过一个简单的例子来说明C什么语言的函数调用SV的task和function。


    1,SV部分


    /*
    * test.v  Rill create for dpi test at 2014-10-20
    */
    
    `timescale 1ns/1ns
    
    module tb;
       import "DPI-C" context function int c_func(input int num);// or import "DPI-C" context task c_display(input int num);
          
          reg tmp;
          
          initial begin
    	 #10
    	   tmp = c_func(1);
          end
    
       m1 M1();
       m2 M2();
       
    endmodule // top
    
    module m1;
       import "DPI-C" context function void c_get_m1_scope();
       export "DPI" function m1_add;
    
       reg tmp;
       reg [7:0] m1_value;
       
       function int m1_add(input [7:0] num);
          m1_add = num + m1_value; //or return (num + m1_value);
       endfunction // m1_add
    
       initial begin
          c_get_m1_scope();
          m1_value = 8'd100;
       end
       
    endmodule // m1
    
    
    module m2;
       import "DPI-C" context function void c_get_m2_scope();
       export "DPI-C" task m2_add;
    
       reg tmp;
       reg [31:0] m2_value;
       
       task m2_add(input int num,output int sum);
          sum = num + m2_value;
       endtask // m2_add
    
       initial begin
          c_get_m2_scope();
          m2_value = 32'd200;
       end
    
    endmodule // m1
    



    2,C部分


    /*
    * test.c  Rill create for dpi test at 2014-10-20
    */
    
    #include <stdio.h>
    #include <svdpi.h>
    
    svScope tmp_scope;
    svScope m1_scope;
    svScope m2_scope;
    
    //import task/funcs from sv
    extern int m1_add();
    extern int m2_add();
    
    //==scope switch
    void c_get_tmp_scope(void)
    {
      tmp_scope = svGetScope();
    }
    
    void c_set_tmp_scope(void)
    {
      svSetScope(tmp_scope);
    }
    
    void c_get_m1_scope(void)
    {
      m1_scope = svGetScope();
    }
    
    void c_set_m1_scope(void)
    {
      svSetScope(m1_scope);
    }
    
    void c_get_m2_scope(void)
    {
      m2_scope = svGetScope();
    }
    
    void c_set_m2_scope(void)
    {
      svSetScope(m2_scope);
    }
    
    //==export c funcs to sv
    int c_func(int num)
    {
      int m1 = 0;
      int m2 = 0;
    
      c_get_tmp_scope();
      c_set_m1_scope();
      m1 = m1_add(num);
      c_set_tmp_scope();
      printf("m1:%d
    ",m1);
    
      c_get_tmp_scope();
      c_set_m2_scope();
      m2_add(num,&m2);
      c_set_tmp_scope();
      printf("m2:%d
    ",m2);
    
      return 0; 
    }
    




    3,脚本


    #! /bin/bash
    
    #
    # test.sh
    # usage: ./test.sh c/w/r
    # Rill create 2014-10-20
    #
    
    
    TOP_MODULE=tb
    
    tcl_file=run.tcl
    
    CDS_INST_DIR=/home/openrisc/opt/edatools/IUS08.20
    
    
    if [ $# != 1 ];then
    echo "args must be c/w/r"
    exit 0
    fi
    
    if [ $1 == "c" ]; then
    echo "compile rtl lib..."
    ncvlog -f ./vflist -sv -update -LINEDEBUG;
    ncelab -delay_mode zero -access +rwc -timescale 1ns/10ps ${TOP_MODULE}
    
    echo "compile dpi lib"
    if [ -e libdpi.so ];then
    rm libdpi.so -f
    fi
    
    gcc -fPIC -shared -o libdpi.so test.c -I$CDS_INST_DIR/tools/inca/include
    exit 0
    fi
    
    
    if [ -e ${tcl_file} ];then
    rm ${tcl_file} -f
    fi
    touch ${tcl_file}
    
    if [ $1 == "w" ];then
    echo "open wave..."
    echo "database -open waves -into waves.shm -default;" >> ${tcl_file}
    echo "probe -shm -variable -all -depth all;" >> ${tcl_file}
    echo "run" >> ${tcl_file}
    echo "exit" >> ${tcl_file}
    fi
    
    if [ $1 == "w" -o $1 == "r" ];then
    echo "sim start..."
    ncsim  ${TOP_MODULE} -input ${tcl_file}
    fi
    
    echo "$(date) sim done!"
    


    4,说明

    细致体会我们上面构造的样例,有几个问题须要弄清楚。

    a。scope的含义:

    在SV端。m1是不能直接调用m2中的task/function的。所以m1里面调用的C函数也不能直接调用m2中export出来的task/function。假设想调用,必须进行scope切换。

    b。SV端,有task和function的区分。可是在C端,并没有区分,一律是C函数。


    5,关于用C模拟硬件的并行行为

    方式a,将流水后面的模块写在前面。这样的方式我们之前介绍过(http://blog.csdn.net/rill_zhen/article/details/8464930),这里不再赘述。

    方式b,将全部并行的信号写成例如以下形式:

    用c,n两个变量模拟reg的值。

    用init和update两个函数模拟reg的行为。

    /*
    * parallel.c  Rill create for simulater test at 2014-10-20
    */
    
    
    struct signal;
    
    struct sig_ops
    {
    	int (*init) (struct signal*);
    	int (*update) (struct signal*);
    };
    
    struct signal
    {
    	unsigned int c; //current cycle value
    	unsigned int n; //next cycle value
    	
    	char name[32];
    	struct sig_ops* ops;
    };
    
    /* veritual functions
    int sig_init(struct signal* signal)
    {
    	return signal->ops->init(signal);
    }
    
    int sig_update(struct signal* signal)
    {
    	return signal->ops->update(signal);
    }
    */
    
    //actual functions
    int test_init(struct signal* signal)
    {
    	signal->c = 0;
    	signal->n = 0;
    	return 0;
    }
    
    int test_update(struct signal* signal)
    {
    	signal->c = signal->n;
    	return 0;
    }
    
    
    
    int signal_create(struct signal* signal,char * name)
    {
    	signal->name = name;
    }
    
    //============main.c====================//
    //example signal
    struct signal test;
    struct sig_ops test_ops =
    {
    	test_init,
    	test_update,
    };
    
    int main()
    {
    	signal_create(&test,"test");
    	//when reset
    	test->ops->init(&test);
    	//per cycle
    	test->ops->update(&test);
    	
    	return 0;	
    }





  • 相关阅读:
    网站跨站点单点登录实现--cookie
    sql order by 排序多个字段
    JAVA字符串格式化-String.format()的使用
    Cent OS 常用配置命令
    键盘事件keydown、keypress、keyup随笔整理总结
    Chrome 开发者工具使用技巧
    JS打开新窗口防止被浏览器阻止的方法[转]
    javaBean与map类型相互转换
    【转载】 自动化机器学习(AutoML)之自动贝叶斯调参
    国内还不错的量化交易平台
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4823942.html
Copyright © 2011-2022 走看看