[Digital chip] System Verilog call OpenCV read the image by DPI-C

When we conduct image processing IP design verification, how to motivate the input image into a DUT it. SystemVerilog provides a DPI-C interface means that you can call C language to interact, this can be called rich-party libraries C / C ++ language or arithmetic operation can not be performed in the original SV. Many of the examples DPI-C on the website [1] , but based on very few examples of OpenCV, github in a UVM-based engineering [2] , but it looks more complicated for beginners, here call directly explain SV OpenCV function read the image, return to the simple process of RGB.
demo pictures

An interface data type

Each variable has passed DPI-C defines two respective matching faces of SystemVerilog side, while facing the C / C ++. It should ensure that each data type must match compatible.
Data Type Mapping

Second, the interface function call and write

Since no pointer type, pointer type instead of longint used herein, the recorded image data space address. Mat followed by reduction of the OpenCV function constructs an object address Mat, Mat further using methods of reading process is as follows:

1)imread读取图像,申请内存空间保存图片,返回该空间指针pp:readframe()返回指针pp   
2)读取图像时,利用指针pp重新构建Mat对象并使用其方法读取相应的RGB数据:getChannel(pp,i,j,c)返回图像i列j行c通道的灰度级

Call the function code is as follows:

`include "cvFunction.svh"
module  img_tb();
reg [8:0] r,g,b;
reg clk;
longint unsigned img_ptr;
string file_name = "/home/dzqiu/code/verilog_ws/sv_learn/dpi-opencv/test.png";
int width,heigth,pixel_r,pixel_g,pixel_b;
initial begin
    r = 8'h0;
    g = 8'h0;
    b = 8'h0;
    clk = 0;
end
always #5 clk =~clk;
initial begin
    $display("test....\n");
    img_ptr=readframe(file_name);
    width = getWidth();heigth= getHeight();
    for(int i=0;i<heigth;i++)
        for(int j=0;j<width;j++) begin
            @(posedge clk);
            pixel_b = getChannel(img_ptr,i,j,0);
            pixel_g = getChannel(img_ptr,i,j,1);
            pixel_r = getChannel(img_ptr,i,j,2);
        end
    $display("finish a picture.\n");
end
endmodule

Interface function and write function C / C ++ is similar, but it needs to pay attention to the interface data type matching, and use extern "C" tells the C ++ compiler to use C-style, and the use of import statements are declared to be called SystemVerilog, pay attention to the parameters defined when using the C / C ++ data types, data types used SystemVerilog declaration.
The following is the definition of the function cvFunction.c, written using C style

#include "svdpi.h" 
#include "stdio.h"
#include "stdlib.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
extern "C" unsigned long long  allocFrame(int width,int height)
{
    Mat frame(height,width,CV_8UC3);
    void *frame_data = malloc(frame.total()*frame.elemSize());
    return (unsigned long long)frame_data;
}
extern "C" unsigned long long readframe(char * filename)
{
    Mat img = imread(filename,1);
    if(!img.data)
        printf("can not read image\n");
    printf("read image width:%d height:%d\n",img.cols,img.rows);
    HEIGHT = img.rows; WIDTH = img.cols;
    void *frame_data =(void *)allocFrame(img.cols,img.rows);
    Mat frame(img.cols,img.rows,CV_8UC3,(void *)frame_data);
    memcpy(frame.data,img.data,img.total()*img.elemSize());
    return (unsigned long long)frame.data;
}
extern "C"  int getChannel(unsigned long long pp,int i,int j,int c)
{
    Mat img(WIDTH,HEIGHT,CV_8UC3,(void*)pp);
    Vec3b intensity = img.at<Vec3b>(i,j);
    return intensity.val[c];
}
extern "C" int getWidth()
{
    return WIDTH;
}

extern "C" int getHeight()
{
    return HEIGHT;
}  `

The following is the function declaration cvFunction.svh, prepared in accordance with SystemVerilog

`ifndef CVFUNCTION
`define CVFUNCTION
import "DPI-C" context function longint unsigned readframe(string filename);
import "DPI-C" context function void  c_fun_printf(string p_in);
import "DPI-C" context function longint allocFrame();
import "DPI-C" context function int getChannel(longint unsigned pp,int i,int j,int c);
import "DPI-C" context function int getWidth();
import "DPI-C" context function int getHeight();
`endif

Three, g ++ compiler and ModelSim simulator

General modelsim simulation is divided into three steps: 1, vlib build directory 2, vlog compiler 3, vsim open simulation, where you need to add g ++ compiler and OBJ files can be linked before.

1)vlib work
2)vlog -sv -dpiheader dpiheader.h $(SV_FILE) +acc                  //vlog编译SV文件
3)g++ -c -fpic -m64 -I$(MODELSIM_HOME)/include $(CV_COPTS) $<      //g++编译C文件,生成对应.o
4)g++ -shared -m64 $(OBJ) -o $(DPI_OBJ).so $(CV_COPTS) $(CV_LOPTS) //g++将上诉.o文件连接为静态库
5)vsim -64  -sv_lib $(DPI_OBJ) $(TOP_NAME)   -do "run -all"       //vsim开启仿真,并连接静态库,添加波形

Waveform Modelsim add the following:
Modelsim Simulation

Specific Makefile as follows:

#source 
SV_FILE = img_tb.sv
TOP_NAME = img_tb
SRC = cvFunction.c
DPI_OBJ = svdpi
#Too;l
MODELSIM_HOME = /home/dzqiu/Modelsim10.2c/modeltech
VLIB = vlib
VLOG = vlog
VSIM = vsim

CC = g++
OBJ = $(SRC:%.c=%.o)

# definitions needed for OpenCV:
CV_COPTS=`pkg-config --cflags opencv`
CV_LOPTS=`pkg-config --libs opencv`

run : vlib vlog vsim

vlib:
	$(VLIB) work

vlog:
	$(VLOG) -sv -dpiheader dpiheader.h $(SV_FILE) +acc

vsim: $(DPI_OBJ).so
	$(VSIM) -64  -sv_lib $(DPI_OBJ) $(TOP_NAME)   -do "add wave -position insertpoint sim:/img_tb/clk sim:/img_tb/pixel_r sim:/img_tb/pixel_g sim:/img_tb/pixel_b;run -all"


.c.o:
	$(CC) -c -fpic -m64 -I$(MODELSIM_HOME)/include $(CV_COPTS) $<

$(DPI_OBJ).so :$(OBJ)
	$(CC) -shared -m64 $(OBJ) -o $(DPI_OBJ).so $(CV_COPTS) $(CV_LOPTS)

qv:
	LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:$(LIBRARY_PATH) qverilog $(SV_FILE) $(SRC)

clean:
	rm -rf work dpi.so $(DPI_OBJ).so $(OBJ)  transcript *.wlf dpiheader.h

Possible problems encountered
1) g ++ version of the problem skipping incompatible, reference [3]

sudo apt-get install gcc-multilib

2)Modelsim libstdc++.so.6: version `GLIBCXX_3.4.21' not found #386,参考[4]

Reference:
This article source
[1] on github simple call dpi-c of Demo
[2] on github based OpenCV UVM call
[3] regression CSDN & replacing gcc version & compiler error / usr / bin / ld: skipping incompatible solution
[4 ] Modelsim libstdc ++ so.6:. GLIBCXX_3.4.21 `Version 'not found # 386

Guess you like

Origin www.cnblogs.com/dzqiu/p/12656674.html