Verilog Matlab 聯合仿真

一、概述

?????????在進行仿真時,有時候一部分參考模型(reference model)來自于Matlab,這就需要通過某種方法調用并運行Matlab的參考模型。verilog并不支持直接調用Matlab,但是可以通過DPI接口調用C函數,而Matlab又預留了為C開放的API接口,因此在SV中調用Matlab可以通過如下步驟來實現:

  1. Verilog通過DPI調用C,為C中某些變量賦值
  2. 從verilog中傳遞來的變量通過適當的類型轉換傳遞到Matlab中
  3. ?C通過API啟動Matlab并調用Matlab中的函數/模型
  4. Matlab函數運算結果返回C,并通過適當的數據類型轉換返回給verilog

二、verilog 與 C 通信

1、數據格式轉換??

????????C中并沒有SV中的一些變量類型,例如bit,reg等,因此SV與C通信首先需要將SV中的數據類型轉化為C可以識別的類型,部分典型變量類型的對應關系如下所示(這些類型都定義在svdpi.h頭文件中):

SystemVerilogC(input)C(output)
bytecharchar*
intintint*
realdoubledouble*
reg[N:0]/logic[N:0]const svLogicVecVal*svLogicVecVal*
bit[N:0]const svBitVecVal*svBitVecVal*
open array[]svOpenArrayHandlesvOpenArrayHandles

2、C側代碼編寫

?????????C側除了要包含一些要用到的基礎的頭文件(例如stdio.h)以外,還需要包含上述提到的svdpi.h頭文件:

    #include "svdpi.h"

????????該頭文件中定義了SV與C通信的類型轉換,以及C對這些數據類型的操作方法。

????????另外,C側代碼并不一定需要main函數,Verilog僅把C代碼當成task或function調用。例如,在C側編寫函數如下:

int factorial(int i)
{if(i <= 1) return 1;else return(i * factorial(i - 1));
}

3、Verilog側代碼編寫

????????若想在Verilog中使用編寫的C函數,則需要在進行導入(注意導入函數的可見范圍):

import "DPI-C" function int factorial(input int i);

? ? ? ? 之后便可以在可見范圍內的module等地方使用該函數了,例如:

module test;
int result;
......
initial begin
result = factorial(5);
......
end
endmodule

?三、C 與 Matlab 通信

1、C側代碼編寫

1)啟動Matlab引擎

????????C可以通過Matlab引擎指針來啟動Matlab引擎,該引擎由Matlab軟件包含的engine.h提供:

#include "engine.h"

????????由于C啟動Matlab需要用到Matlab引擎指針,之后便可以使用engOpen函數獲取引擎指針,例如:

Engine *ep;
if(!(ep = engOpen("\0")))printf("\nCan't start Matlab engine!\n");

????????engOpen函數原型如下:?

#include "engine.h"
Engine *engOpen(const char *startcmd);

????????其參數為啟動指令字符串,若在Windows環境下,則啟動指令必須為空,在Linux環境下,啟動指令為空時在當前主機啟動,若啟動指令為主機名,則在指定主機上啟動,若為其它Matlab指令字符串,則Matlab會在啟動時執行該指令。該函數返回Engine指針,若啟動失敗則返回NULL。

2)定義數據類型

????????此外,Matlab中數據以矩陣的形式存儲,因此還要包含定義矩陣類型以及操作方法的頭文件matrix.h:

#include "matrix.h"

????????Matlab中以矩陣形式存儲數據,將C中的變量傳遞給Matlab(或反過來)時,需要定義Matlab能夠識別的矩陣形式的變量,即mxArray類型,通常定義mxArray類型變量為指針變量,例如:

mxArray *mxarr_ptr = NULL;

????????在定義完mxArray類型指針變量之后,可能還需要指定其大小和類型,需要用到mxCreateDoubleMatrix函數,該函數原型如下:

#include "matrix.h"
mxArray *mxCreateDoubleMatrix(mwSize m, mwSize n, mxComplexity ComplexFlag);

????????其中,第一個參數和第二個參數代表創建m行n列的矩陣空間,第三個參數指定矩陣為實矩陣(mxREAL)還是復矩陣(mxCOMPLEX)。

3)C向Matlab傳輸數據

????????結合前一節可以知道,若想向Matlab傳遞數據,首先應將C中普通類型的變量賦值到mxArray類型的變量中,此時需要用到mxSetPr函數,該函數原型如下:

#include "matrix.h"
void mxSetPr(mxArray *pm, double *pr);

????????其中,第一個參數為mxArray類型的指針,第二個參數為double類型的指針。(在Matlab2018a版本以后,mxSetPr函數不再被建議使用,而應該使用mxSetDoubles函數)

????????此外,當double類型指針未被分配空間時,則首先需要使用mxCalloc函數對其動態分配內存空間(注意不能使用calloc或malloc函數),其原型如下:

#include "matrix.h"
#include <stdlib.h>
void *mxCalloc(mwSize n, mwSize size);

????????其中,第一個參數為分配內存的單元數量,第二個參數為每個單元的大小(通常搭配sizeof函數使用),如果成功,函數返回動態內存的起始位置,否則返回NULL。

????????接下來就需要將mxArray類型的變量傳遞至Matlab中,此時需要用到engPutVariable函數,該函數原型如下:

#include "engine.h"
int engPutVariable(Engine *ep, const char *name, const mxArray *pm);

????????其中,第一個參數為引擎指針,第二個參數為Matlab中變量的名字,第三個參數為mxArray類型變量的指針,當操作成功時返回1,否則返回0

??需要注意的是,如果指定的名字在Matlab中不存在,則會在Matlab中創建該名字的變量并為其賦值,如果該名字已存在,則會將原變量替換為新變量,此外,傳遞的變量最大為2GB。

4)C調用Matlab程序

????????Matlab提供了從C傳遞指令的engEvalString函數,其原型如下所示:

#include "engine.h"
int engEvalString(Engine *ep, const char *string);

? ? ? ??其中,第一個參數為引擎指針,第二個參數為指令字符串,若引擎關閉或指針為空則返回1,否則返回0,即使Matlab并不能識別該指令。

????????通過該函數,我們便可以像在Matlab console中執行指令一樣調用Matlab函數(.m文件),但需要注意的是,在調用函數或模型前,首先需要將Matlab的工作路徑設置正確,例如:

//--假設在/sv_matlab/demo/目錄下存放有func_add.m文件,用于將兩個數相加
engEvalString("path('/sv_matlab/demo/',path);");
//--在C中直接調用上述函數將兩數相加,前提是Matlab中已經有a,b兩個變量
engEvalString("func_add(a,b)");

5)C從Matlab獲取數據

????????我們需要先從Matlab獲取變量至C中的mxArray類型變量中,之后再將mxArray類型變量中的數據提取到C的普通類型變量中。首先,我們需要使用engGetVariable函數獲取mxArray變量,該函數原型如下:

#include "engine.h"
mxArray *engGetVariable(Engine *ep, const char *name);

????????其中,第一個參數為引擎指針,第二個參數為Matlab中變量名字的字符串,當指定的名稱字符串不存在時,函數返回NULL,否則返回指向該變量的mxArray指針。

????????之后,我們需要使用mxGetPr函數從mxArray類型變量中獲取值,該函數原型如下:

#include "matrix.h"
mxDouble *mxGetPr(const mxArray *pm);

????????其參數為mxArray類型變量的指針,如果指定的mxArray類型變量的指針為NULL,則返回函數NULL,否則返回指向mxArray中存儲數據的指針。

6)釋放內存

????????在C和Matlab處理完相應的數據之后,可能需要為一些變量之前分配的空間釋放其內存以防止內存泄漏。

????????使用mxFree函數釋放由mxCalloc分配的內存,其函數原型如下:

#include "matrix.h"
void mxFree(void *ptr);

????????使用mxDestroyArray函數釋放由mxCreateDoubleMatrix分配的內存,其函數原型如下:

#include "matrix.h"
void mxDestroyArray(mxArray *pm);

7)關閉Matlab引擎

?????????在處理完所有數據并釋放完成內存后,可以使用前面提到的engEvalString函數來關閉Matlab引擎,例如:

engEvalString(ep,"close");

2、Matlab側代碼編寫

????????對于Verilog調用Simulink Model進行聯合仿真的情況,其中一個方法就是,可以將Matlab中所有的變量,無論是輸入還是輸出,均打包成一個函數包,這樣我們就可以通過engEvalString函數來調用整個模型。

四、Verilog & Matlab交互示例

????????我們以從verilog中向Matlab中傳遞兩個變量并將兩個變量在Matlab中相加后返回給Verilog為例,再梳理一邊該流程。首先是Verilog側代碼(這里用的是SV):

`timescale 1ns/1ps
import "DPI-C" function real func_add(const real a, const real b);
module test;real val1;real val2;real result;initial beginval1 = 0.3;val2 = 1.1;result = func_add(val1, val2);  //調用C函數$display("SV got result = %0f", result);#10;$finish();end
endmodule

????????然后是C側代碼:

#include <stdlib.h>
#include <stdio.h>
#include "svdpi.h"
#include "engine.h"
#include "matrix.h"
double func_add(double a, double b)
{double *val1;double *val2;double *result;val1 = (double *)mxCalloc(1, sizeof(double));val2 = (double *)mxCalloc(1, sizeof(double));*val1 = a;*val2 = b;mxArray = *mxarr_val1 = mxCreateDoubleMatrix(1, 1, mxREAL);mxArray = *mxarr_val2 = mxCreateDoubleMatrix(1, 1, mxREAL);mxArray = *mxarr_result = NULL;Engine *ep;if(!(ep = engOpen("\0")))printf("\nCan't start Matlab engine!\n");else{engEvalString("path('/sv_matlab/demo/',path);");mxSetPr(mxarr_val1, val1);mxSetPr(mxarr_val2, val2);engPutVariable(ep, "a", mxarr_val1);engPutVariable(ep, "b", mxarr_val2);engEvalString(ep, "result = func_demo(a,b)");mxarr_result = engGetVariable(ep, "result");result = mxGetPr(mxarr_result);return *result;}
}

????????最后是Matlab側代碼:

function result = func_demo(a, b)result = a + b;
return

因為涉及到調用C函數,因此在跑仿真之前需要先對C文件進行編譯,例在/sv_matlab/demo/c目錄下有自己編寫的C函數,則需要按如下方式對其編譯:

gcc demo/c/func_add.c -o demo/c/libdpi.so \-I /appl/tools/cadence/XCELIUM2009/tools.lnx86/inca/include/ \-std=c99 -fPIC -shared -leng -lmx -lmex

其中參數:

-o?指定生成的結果文件,結果文件名為libdpi.so,SV將默認查找這個庫內的C函數

-I 指定編譯包含的頭文件庫(這里要用到包含svdpi.h的路徑),由仿真工具提供,這里以XCELIUM為例

-fPIC 告訴編譯器產生與位置無關代碼

-shared 表示生成庫能被別的程序鏈接

-leng -lmx 和 -lmex 編譯matlab庫所需的參數,主要用于編譯和鏈接

在編譯完成之后,便可以啟動SV的仿真了,如果C函數沒有發生變化,則重復SV側仿真無需再次編譯C函數。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/253393.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/253393.shtml
英文地址,請注明出處:http://en.pswp.cn/news/253393.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

轉 alsa錄音放音執行流程詳解

前言&#xff1a; linux中&#xff0c;無論是oss還是alsa體系&#xff0c;錄音和放音的數據流必須分析清楚。先分析alsa驅動層&#xff0c;然后關聯到alsa庫層和應用層。 鏈接分析&#xff1a; core/pcm_native.c文件中.mmap snd_pcm_mmap調用snd_pcm_mmap_data(substream, fi…

jenkins之qq企業郵箱配置

一、配置qq企業郵箱 1、登錄jenkins后臺管理&#xff0c;選擇 系統管理 ? 系統設置 2、SMTP server配置 3、郵件通知配置 配置ssl等參數 點擊 高級 4、發送郵件測試 總結&#xff1a;郵箱配置不成程分析 1、管理員賬號和默認發送賬號不一致。2、smtp服務器設置不正確;qq企業…

關于iOS里的做動畫方法的差別與注意事項

CoreAnimation與UIView.animation... 這兩個方式的主要差別在于&#xff0c;前者如果不主動設置&#xff0c;那么在動畫做完以后&#xff0c;會恢復原狀。后者則不會&#xff0c;動畫做完后是什么樣&#xff0c;控件就是什么樣。 UIView.animation...是什么 首先我們來做一個動…

mysql-5.7 持久化統計信息詳解

一、持久化統計信息的意義&#xff1a; 統計信息用于指導mysql生成執行計劃&#xff0c;執行計劃的準確與否直接影響到SQL的執行效率&#xff1b;如果mysql一重啟 之前的統計信息就沒有了&#xff0c;那么當SQL語句來臨時&#xff0c;那么mysql就要收集統計信息然后再生成SQL語…

關于傳感器”英寸“計量

傳感器上的n是指對角線長度為16mm或18mm的n倍 以英寸代指的傳感器大小稱為靶面尺寸。 在CCD/CMOS出現之前&#xff0c;攝像機是利用一種叫作“光導攝像管&#xff08;Vidicon Tube&#xff09;”的成像器件感光成像的&#xff0c;這是一種特殊設計的電子管&#xff0c;其直徑的…

關于USB-AUDIO使用ALSA編程的一點問題

轉載自&#xff1a;http://blog.chinaunix.net/uid-25272011-id-3153434.html 最近在調試一款原相PAP7501攝像頭中的USB的麥克風&#xff0c;USB層走的應該是標準的UAC協議&#xff0c;具體可以見USB的官網&#xff1a;http://www.usb.org/developers/devclass_docs#approved&a…

讓input變成不可編輯狀態的方法

有時候&#xff0c;我們希望表單中的文本框是只讀的&#xff0c;讓用戶不能修改其中的信息&#xff0c;如使<input type"text" name"input1" value"中國"> 的內容&#xff0c;"中國"兩個字不可以修改。實現的方式歸納一下&#…

npm run dev 在本地調試出現跨域問題解決方法

npm run dev 在本地調試出現跨域問題 在localhost:8080調試時會出現跨域問題&#xff0c;如圖&#xff1a; 我的項目是用webpack作為前端自動化構建工具&#xff0c;可以在webpack-dev-server中配置跨域。webpack-dev-server是一個小型的nodejs服務器&#xff0c;是基于express…

alsa聲音編程介紹

http://blog.csdn.net/q553716434/article/details/7881552 period(周期):硬件中中斷間的間隔時間。它表示輸入延時。 聲卡接口中有一個指針來指示聲卡硬件緩存區中當前的讀寫位置。只要接口在運行&#xff0c;這個指針將循環地指向緩存區中的某個位置。 frame size sizeof(o…

五、python模塊以及包

模塊&#xff1a;編寫的別的程序中重用一些代碼。 1 模塊的寫法&#xff1a; 創建一個.py文件&#xff0c;該文件中包含函數與變量。使用撰寫python解釋器本身的本地語言來編寫模塊。比如使用C代碼編寫python模塊&#xff0c;并且在編譯后&#xff0c;可以通過標準的python解釋…

jeecg選擇按鈕帶入其他單據值

前端的標簽 <input class"inputxt" id"fshimian" name"fshimian" ignore"ignore" datatype"*" value"${shizhePage.fshimian}" /> <t:choose hiddenName"fshimian" hiddenid"fname"…

alsa編程

alsa 編程 分類&#xff1a; linux 2012-08-18 20:13 124人閱讀 評論(0) 收藏 舉報 編程parametersbufferloopsaccessplayback轉載自&#xff1a;http://blog.csdn.net/spygg/article/details/7824750 ALSA(Advanced Linux Sound Architecture)是由內核驅動,標準的API庫和一系…

Fiddler4入門——手機抓包

一、下載工具包 百度搜索”fiddler 下載“ &#xff0c;安裝最新版本 下載的軟件安裝包為“fiddler_4.6.20171.26113_setup.exe”格式&#xff0c;雙擊安裝。安裝成功&#xff0c;在“開始”-“所有程序”&#xff0c;就會看見這樣的圖標&#xff0c;若是常用的話&#xff0c;也…

Node.js Performance

https://blog.risingstack.com/node-js-performance-monitoring-with-prometheus/轉載于:https://www.cnblogs.com/skating/p/7544838.html

(五)DOM4j進行XML文件的解析及生成

DOM4j本身還是需要使用SAX建立解析器&#xff0c;然后通過文檔依次找到根節點&#xff0c;再通過根節點查找每一個節點的內容. 1.寫操作 import java.io.File;import java.io.FileOutputStream;import java.util.Iterator; import org.dom4j.Document;import org.dom4j.Documen…

Linux系統基礎.作業

要求以root用戶登錄系統&#xff0c;右擊桌面打開終端&#xff0c;查看當前登陸Linux系統所使用的用戶名 查看哪些用戶在系統上工作 修改當前時間為2018年8月26號11:28 查看2015年10月份日歷 使用兩種方法查看ls命令的使用說明 清除屏幕 ctrlL使用“useradd tom”命令新建tom用…

Alsa中PCM參數設置

分類&#xff1a; LINUX 1) PCM設備的句柄.2) 指定同時可供回放或截獲的PCM流的方向3) 提供一些關于我們想要使用的設置選項的信息,比如緩沖區大小,采樣率,PCM數據格式等4) 檢查硬件是否支持設置選項.4.1) 初始化PCM變量4.2) 分配hwparams結構4.3) 打開PCM設備4.4) 以聲卡的全部…

java5

java基礎&#xff08;五&#xff09;命名規則&#xff1a; 名字中只能包含->字母、_、數字、$&#xff0c;且開頭不能為數字包名必須都小寫文件名首字母和后面英文文件單詞首字母都要大寫變量和方法名 首字母小寫&#xff0c;后面英文單詞首字母大寫java中的方法&#xff1a…

最新歷史版本 :H.265

原來對264有深入的研究&#xff0c;現在想詳細了解下265啦&#xff0c;愿265盡快廣泛的使用起來&#xff0c;人們可以享受無處不在的視覺盛宴。 H.265是ITU-T VCEG 繼H.264之后所制定的新的視頻編碼標準。H.265標準圍繞著現有的視頻編碼標準H.264&#xff0c;保留原來的某些技術…

凱撒密碼、GDP格式化輸出、99乘法表

1.愷撒密碼的編碼 sinput(請輸入明文:) print(密文為:) for i in s:print(chr(ord(i)3),end)運行結果為&#xff1a; 2.國家名稱 GDP總量&#xff08;人民幣億元&#xff09; 中國 &#xffe5;765873.4375 澳大利亞 &#xffe5; 78312.4375 &#xff08;國家名稱左對齊&am…