2011年5月14日 星期六

DPI再了解(十四)

C Side Library Functions

A number of library functions are available that help you get information about the SystemVerilog side from the C side. Some of these library functions are also useful in controlling the SystemVerilog side of the interface. Some of these functions are described below.
Library functions related to scope

Function: svGetScope
Use: Gets the current SystemVerilog scope of an imported function.
Function prototype: svScope svGetScope();

Function: svSetScope
Use: Sets the current SystemVerilog scope of an imported function.
Function prototype: svScope svSetScope(const svScope);

Function: svGetNameFromScope
Use: Gets the fully qualified current SystemVerilog path of an imported function from a scope handle.
Function prototype: const char* svGetNameFromScope(const svScope);

Function: svGetScopeFromName
Use: Sets the current SystemVerilog scope of an imported function.
Function prototype: svScope svGetScopeFromName(const char*);

Library functions related to packed arrays

Function: svGetSelectBit
Use: Reads a bit-select index i of an array reference svBitPackedArrRef of type Bit.
Function prototype: svBit svGetSelectBit(const svBitPackedArrRef s, int i);

Function: svPutSelectBit
Use: Writes the value of a bit s to a bit-select index i of an array reference svBitPackedArrRef of type Bit.
Function prototype: void svPetSelectBit(svBitPackedArrRef d, int i, svBit s);

Function: svGetSelectLogic
Use: Reads a bit-select index i of an array reference svLogicPackedArrRef of type Logic.
Function prototype: svLogic svGetSelectLogic(const svLogicPackedArrRef s, int i);

Function: svPutSelectLogic
Use: Writes the value of a bit s to a bit-select index i of an array reference svLogicPackedArrRef of type Logic.
Function prototype: void svPutSelectLogic(svLogicPackedArrRef d, int i, svLogic s);

Function: svSizeOfArray
Use: Returns the total size of an array in bytes or 0 if the array is not in C layout.
Function prototype: int svSizeOfArray(const svOpenArrayHandle);

Function: svGetArrElemPtr
Use: Returns a pointer to an element [index1][index2]... of an array or NULL if the array is not in C layout. The array does not have to be packed.
Function prototype: void *svGetArrElemPtr(const svOpenArrayHandle, int index1, int index2,...);

Function: svGetArrElemPtr
Use: Returns a pointer to an element [index1][index2]... of an array or NULL if the array is not in C layout.
Function prototype: void *svGetArrElemPtr(const svOpenArrayHandle, int index1, int index2,...);

We wrap up our DPI tutorial with this. One word of caution: although this tutorial has covered materials that will help you kick start your DPI knowledge, this is only tip of the iceberg. DPI provides more facilities in addition to what have been discissed here. You are encouraged to explore those advanced topics from a SystemVerilog text or the Language Reference Manual.

參考http://www.project-veripage.com/dpi_tutorial_10.php

淡定

指有泰山崩于前而面不改色的镇定程度,遇事沉稳中又积极果断,老练里却又重视有佳,胜不骄,败不馁; 淡定形容一种勇气。 淡定,是一种思想境界,是一种心态,是生活的一种状态。
<引自百度: http://baike.baidu.com/view/240772.htm>

wiki查不到,但比較接近的英文為Calm

C variable types and declarations

可參考維基百科
裡面有詳細的敘訴
http://en.wikipedia.org/wiki/C_variable_types_and_declarations

C++ 的friend

C++類別的存取限制 如private, protected, public 等
另外還有一個東西 可以超越這一切的限制 這就是friend

friend 可以用來宣告另外一個類別 或者是一個函式(function)
任何被宣告為 friend 的類別或函式 都可以無視存取限定 直接存取所有的變數或函式
friend的使用方法如下所示
class A;
void SetValue(A *pObjA,int n);

class A
{
friend void SetValue(A *pObjA,int n);
private:
int m_nValue;
}

void SetValue(A *pObjA,int n)
{
pObjA->m_nValue = n;
}

類別A中的 m_nValue是宣告為private
本來是無法讓SetValue()來存取的 但由於SetValue()也被宣告為friend
所以我們可以在SetValue中來存取m_nValue;

friend也可以用在類別身上 被宣告為friend的類別其成員函式可以無視存取限制
任意存取所有的變數或者是函式


從前 不知道是誰的簽名檔上寫著
private就好像是你的老婆 protected就好像是你的小孩 public就好像是你家的狗
但這個講法的破洞就是
只要是friend 不管是老婆 小孩 還是狗 通通都可以碰

參考自http://blog.yam.com/swwuyam/article/11865502
另有一篇關於friend 重載
http://caterpillar.onlyfun.net/Gossip/CppGossip/friendOverLoadOperator.html

Google Blogger 發生問題

2011/05/13 Google Blogger 發生問題
除造成13不能寫日誌外
也造成12日的檔案遺失

只要重新寫上囉

How to Know Random Seed Value

在跑systemverilog 模擬時使用random seed 要如何知道這個random Seed 的值是多少



Cadence IUS: 在IUS的Shell script 使用+svseed = random, 這樣它的seed就會在每次模擬時自動改變, 這樣我們要如何知道變動後的Seed Number是多少



Answer

在Log 上就可以看到svseed : set randomly command line from tcl : xxxxxx

看到的xxxxxx就是compiler階段產生的Seed Number

如果要Debug 就可以將xxxxxx放到Script 中 +svseed=xxxxxx

就會與上次使用+svseed = random產生一樣的模擬結果


據資料顯示

Synopsys 的VCS也是顯示在Log檔上面

IUS Merge Coverage

以前用過
但臨時要再用時又要查過
現在寫出來以免又忘記了

在IUS的模擬路徑下

如果沒有額外設定
就會看到一個放coverage的路徑
./cov_work

./cov_work/design/xxx
xxx代表目錄名稱
每一個目錄都代表一個模擬的項目
test_name或test_pattern

然後使用
iccr
進入command mode

使用load_test *
可以將所有的coverage項目吃進來
如xxx, xxx1, xxx2, ...

再用
merge xxx * -output all
就會產生合成後的coverage
放再./cov_work/design/all這個目錄下

再用iccr -gui就可以很容易看到合併後的coverage

DPI再了解(十三)

Cadence 使用export 在CPP的模式

參考例如下
#include "svdpi.h"
#include "veriuser.h"

extern "C" {

extern void ex_task();

void import_task() {
io_printf("C: Before calling export function\n");
ex_task();
io_printf("C: After calling export function\n");
}
}


`timescale 1ns/100ps
module main();
export "DPI-C" ex_task = function export_task;
import "DPI-C" context function void import_task();

function export_task();
$display("SV: Entered the export function, wait for some time: %0d", $time);
endfunction

initial begin
$display("SV: Before calling import function %0d", $time);
#1;
import_task();
#1;
$display("SV:After calling function %0d", $time);
end

endmodule

Verdi 從2010.04之後提供全新架構的FSDB PLI

這是從官網上得到的

我們一般都是使用Method 3

另外兩種做法是否好用就見仁見智了


新的FSDB PLI針對System Verilog有更完整的support,有比較好的perfo rmance。
另外也支援同時dump不同的fsdb檔案。

針對dump options的設定,可以透過
simulator command line、environment variable以及FSDB dump command三種方式指定。
例如要指定一個dump的fsdb檔名, 可以用三種不同的方式來達成:

1.Specify the file name on the simulator command line:

> simv +fsdbfile+dump1.fsdb

2. Specify the file name via an environment variable

> setenv FSDB_FILE dump1.fsdb

3. Specify the file name in a FSDB dumping command

$fsdbDumpvars(“+fsdbfile+ dump1.fsdb”);

優先順序為:Method 1 > Method 2 > Method 3

Cadence IUS simulator link新dumper的方式:

Set share library path
setenv LD_LIBRARY_PATH ${NOVAS_INSTDIR}/share/PLI/ IUS/${PLATFORM}
其中$NOVAS_INSTDIR是Verdi安裝目錄
$PLATFORM為工作站平台:如LINUX或LINUX64 或SOL7_32bit或SOL7_62bit
Compile design and run simulation
ncverilog –f run.f +ncaccess+r


Synopsys VCS simulator link新dumper的方式:

Set share library path
setenv LD_LIBRARY_PATH ${NOVAS_INSTDIR}/share/PLI/ VCS/${PLATFORM}
Compile design and run simulation
vcs –f run.f -debug_pp +vcsd +vpi -P ${NOVAS_INSTDIR}/share/PLI/ VCS/${PLATFORM}/novas.tab \
${NOVAS_INSTDIR}/share/PLI/ VCS/${PLATFORM}/pli.a


Mentor ModelSim simulator link新dumper的方式:

Set share library path
setenv LD_LIBRARY_PATH ${NOVAS_INSTDIR}/share/PLI/ MODELSIM/${PLATFORM}
Compile design and run simulation
vsim -pli ${NOVAS_INSTDIR}/share/PLI/ MODELSIM/${PLATFORM}/novas_ fli.so system -c -do mti.do

verilog 如何設定初始值

$deposit — Deposit a value onto a net

$deposit(top.module.net, value);



Modelsim

force –deposit  top.module.net  value



VCS似乎以上兩種都支援



Verilog

Wire net;

Initial begin

#10 force top.module.net = 1;

#20 release top.module.net;

End

2011年5月11日 星期三

SystemC-定点数据类型

參考 http://www.fpgastudy.com/a/course/SystemC/710.html

SystemC专门定义了有符号和无符号的定点数据类型,而且还允许设定定点数据类型的量化和溢出行为。

SystemC的4种基本定点数据类型为:

sc_fixed
sc_ufixed
sc_fix
sc_ufix

sc_fixed和sc_ufixed的参数是静态的,在程序中设定后不能再修改,而sc_fix和sc_ufix的参数是非静态的,其字长和整数部分长 度可以是变量。sc_fixed和sc_fix是有符号整数,而sc_ufixed和sc_ufix是无符号整数。

定点数据类型的定义方法如下:

sc_fixed x;
sc_ufixed y;
sc_fix x(list of options); //可选项较多,读者可以参考SystemC 库中的sc_fix.h文件
sc_ufix y(list of options); //可选项较多,读者可以参考SystemC 库中的sc_ufix.h文件

sc_fixed和sc_ufixed的参数的含义如下:

(1)wl——总字长,即用于表示一个定点数的总的比特数。

(2)iwl——整数部分字长,即小数点左边的比特数。

(3)q_mode——量化模式。当一个运算的结果的精度大于定点数所能表示的精度时就要根据量化模式将尾数进行取舍。

(4)o_mode——溢出模式。当一个运算的结果大于定点数所能够表示的最大值时,就要根据溢出模式将数据进行处理。

(5)n_bits——饱和比特的位数。该参数仅用于溢出模式,它定义了在特定的具有饱和行为的溢出模式下饱和比特的位数。

x、y是所定义的定点对象。定点数据类型在加法器、乘法器和FFT运算、滤波器等需要算术逻辑的设计中特别有用。定点数据类型声明的一个例子如下:

sc_fixed<16,8,SC_RND_ZERO,SC_SAT> fx_val;

字长和整数部分字长是定点数据的两个重要参数。字长wl是用于表示一个定点数的总的比特数,它必须是大于0的。整数部分长度iwl也称为整数字长,可以是 正数、负数,也可以大于总字长。下面列出了几种典型的情况,图中X代表任意值,S是符号扩展位,根据符号的情况,可以是0或者1。

SystemC hdl connect

一個synopsys的例子
如何連結systemC 與 verilog

現在惟一的限制在只能針對simulator作設定
如VCS 有其專用之法
IUS也有專用之法

這樣要寫大型的model會被限制住

top.v

`define W 31

module my_top();

parameter PERIOD = 20;

reg clock;

reg [`W:0] value1;
reg [`W:0] value2;

wire [`W:0] add_wire;
reg [`W:0] systemc_signal;
wire [`W:0] sub_wire;
wire [`W:0] control_out;
reg [`W:0] control_out_reg;

integer counter;
integer direction;
integer cycle;

// SystemC model
sc_top_w add1(value1, value2, add_wire); //當作是一個verilog block

// SystemC model
sc_subtracter sub1(value2, value1, sub_wire);//當作是一個verilog block

// 要記得將wire 接好

// Verilog model
v_controller controller1(value1, value2, control_out);


initial begin
value1 = 32'b010; // starts at 2
value2 = 32'b000; // starts at 0
counter = 0;
direction = 1;
cycle = 0;
end

// clock generator
always begin
clock = 1'b0;
#PERIOD
forever begin
#(PERIOD/2) clock = 1'b1;
#(PERIOD/2) clock = 1'b0;
end
end

// stimulus generator
always @(posedge clock) begin
value1 <= counter+2;
value2 <= 32'b010; // stays at 2 after here.
control_out_reg <= control_out;

if (direction == 1) // incrementing...
if (counter == 9) begin
counter = counter - 1;
direction = 0;
end
else
counter = counter + 1;
else // decrementing...
if (counter == 0) begin
counter = counter + 1;
direction = 1;
end
else
counter = counter - 1;
end

// display generator
always @(posedge clock) begin

$display("--------------------------------");
$display("Cycle %0d for values A=%0d and B=%0d", cycle, value1, value2);
$display("Res: A+/-B=%0d A-B=%0d \nController=%0d Systemc_signal=%0d",
add_wire, sub_wire, control_out,systemc_signal);
$display("--------------------------------");
// end after 100 cycles are executed
cycle = cycle + 1;
if (cycle == 100)
$finish;

end
endmodule

module v_controller(ina, inb, outx);
input [31:0] ina;
input [31:0] inb;
output [31:0] outx;

reg [31:0] outx_reg;

always @(ina or inb) begin
outx_reg <= ina * inb;
end

assign outx = outx_reg;

endmodule


#include "systemc.h"
#include "hdl_connect.h"

SC_MODULE(sc_addsub)
{
public:
sc_in > ina;
sc_in > inb;
sc_out > outx;
sc_signal > outM;
sc_signal sc_control_sig;
SC_CTOR(sc_addsub):ina("ina"), inb("inb"), outx("outx"),outM("outM"),sc_control_sig("sc_control_sig")
{
SC_METHOD(sc_addsub_action);
sensitive << ina << inb << sc_control_sig;
}

void sc_addsub_action() {
if((( sc_control_sig ).read() %3) == 0) {
outx.write(ina.read().get_word(0) + inb.read().get_word(0));
outM.write(ina.read().get_word(0) + inb.read().get_word(0));

} else {
outx.write(ina.read().get_word(0) - inb.read().get_word(0));
outM.write(ina.read().get_word(0) + inb.read().get_word(0));
}
}
};
#endif

SC_MODULE(sc_subtracter)
{
public:
sc_in > ina;
sc_in > inb;
sc_out > outx;

SC_CTOR(sc_subtracter):ina("ina"),inb ("inb"), outx("outx")

{
SC_METHOD(sc_subtracter_action);
sensitive << ina << inb;
}

void sc_subtracter_action() {
sc_lv<32> val;
val = ina.read();
val = val.get_word(0) - inb.read().get_word(0);
outx.write( val );
}
};

SC_MODULE(sc_top_w)
{
public:
sc_in > ina;
sc_in > inb;
sc_out > outx;

sc_addsub *m_add1;

SC_CTOR(sc_top_w): ina ("ina"), inb ("inb"), outx ("Outx")

{
m_add1 = new sc_addsub("add1");

m_add1->ina(ina);
m_add1->inb(inb);
m_add1->outx(outx);

hdl_connect_v(m_add1->sc_control_sig, "my_top.controller1.outx_reg", HDL_INPUT, 1);
hdl_connect_v(m_add1->outM, "my_top.systemc_signal", HDL_OUTPUT,1);
}

};

2011年5月10日 星期二

EDA 在virtual PC 上的使用限制(一)

如果使用分享硬碟/目錄的方式
常會使得link的過程發生錯誤

只要將執行目錄放在Linux的硬碟目錄下
就可以執行成功
可能是分享硬碟/目錄的磁區格式不合之故

DPI再了解(十二)

VCS直接使用 DPI

方法一
vcs –sverilog top.sv c_test.c
vcs –sverilog top.sv c_test.cpp

方法二
gcc –shared –fPIC test.c –o test/libtest.so
vcs –sverilog model.v test/libtest.so

2011年5月9日 星期一

DPI再了解(十一)

// Class style to SV

typedef bit [31:0] u_int32;

class myTrans;
rand u_int32 addr;
rand u_int32 data;

constraint c_addr { addr inside {[0:100]}; }
endclass // myTrans


import "DPI-C" function chandle model_new();
import "DPI-C" function void model_process(input chandle inst, inout u_int32 addr, data);

class Model;
chandle inst;

function new();
this.inst = model_new();
endfunction : new

function void proc(myTrans trans); // "process" is reserved keyword
model_process(this.inst, trans.addr, trans.data);
endfunction : proc
endclass : Model


class stimGen;
myTrans trans;
Model model;

function new();
model = new();
endfunction : new


task run();
trans = new();
trans.randomize();
$display("SV : pre_process : trans.addr=%x, trans.data=%x", trans.addr, trans.data);
model.proc(trans);
$display("SV : post_process: trans.addr=%x, trans.data=%x", trans.addr, trans.data);
endtask // run

endclass // stimGen


module test();

stimGen sg;
initial begin
sg = new();
sg.run();
end

endmodule


#include
#include
#include "systemc.h"
//#include // Needed for io_printf
//#include "vc_hdrs.h" // VCS specific header
typedef unsigned int u_int32;

class myTrans {
public:
u_int32 addr;
u_int32 data;
};


class model {
public:
model();
void process(u_int32* addr, u_int32* data);
};

model::model()
{
printf("C++: Constructing a model\n");
}

void model::process(u_int32* addr, u_int32* data)
{
printf("C++: processing %x %x\n", addr, data);
*addr = *addr + 1;
*data = *data + 2;
}


#ifdef __cplusplus
extern "C" {
#endif

////////////////////////////////////////////////////////////////////////
// The DPI needs a static C routine to communicate with.
// This one constructs the model object and returns a handle
void* model_new()
{
return new model;
}

////////////////////////////////////////////////////////////////////////
// Tell the model to process a transaction
void model_process(void* inst, u_int32* addr, u_int32* data)
{
model* m = (model *) inst;
/* Pass the individual trans properties over.
You could also construct a trans and pass it instead */
m->process(addr, data);
}

#ifdef __cplusplus
}
#endif

一個簡單的SystemC在Linux下的Makefile

systemC環境

SystemC安裝在/usr/systemc

我們設計的systemC範例為
hello.cpp

在目錄下執行make

就會得到一個執行檔
hello


Makefile檔如下

LIB_DIR=-L/usr/systemc/lib-linux
INC_DIR=-I/usr/systemc/include
LIB=-lsystemc

APP=hello

all:
     g++ -o $(APP).so -g $(APP).cpp $(LIB_DIR) $(INC_DIR) $(LIB)
###g++前面要加一個TAB
clean:
   rm -rf $(APP)
###rm 前面要加一個TAB 

-g 非必要時可以不用

Commands(即為要執行的 Shell 指令)

必須以 <Tab> 開頭。使用 Shell Script 語法。在 Makefile 裡,只要以 <Tab> 開頭都將會被視為 Shell Script 執行。
每條法則必須寫在同一行。每條 Command 會啟動一個新的 Shell,預設為 /bin/sh。若執行完某條 Command 但傳回了錯誤值,make 就會中斷執行。

2011年5月8日 星期日

DPI再了解(十)

 struct在DPI上的使用例
從VCS上改過來的例子


module main();
    typedef struct {
        int a;
        int b;
    } mystruct;

    import "DPI" function void mydisplay(inout mystruct s1);
    mystruct s1;
    initial begin
        s1.a =10;
        s1.b =20;
        $display("SV: s1.a=%0d,s1.b=%0d",s1.a,s1.b);

        mydisplay(s1);
        $display("SV after DPI call: s1.a=%0d,s1.b=%0d",s1.a,s1.b);
    end

endmodule


#include "svdpi.h"
//#include "vcsuser.h"

#include <stdlib.h>
#include <stdio.h>

extern "C" {
    typedef struct {
        int a;
        int b;
    }  mystruct;

    void mydisplay(mystruct *s1) {
        int s2;
        printf("C: gets values from SV, s1.a=%d, s1.b=%d\n",s1->a,s1->b);
        s1->a = 100;
        s1->b = 200;
        printf("C: set values,  s1.a=%d, s1.b=%d\n",s1->a,s1->b);
    }  


}