从面向对象的角度看,仿真该如何把数据保存到文件?

来源:互联网 发布:sdcms 域名未授权 编辑:程序博客网 时间:2024/06/05 07:18

github:https://github.com/C-L-G/stream-to-file-package

面向对象编程在软件设计中一直都是热门话题

什么是OOP,怎么做到OOP,每个软件工程师都有自己的理解。最常见的说法是:对象封装数据和和数据相关的方法!

Verilog,VHDL都不是面向对象的语言。

严格来讲systemverilog也不算是,只是有一点味道而已。

本文只是讲把数据保存到文件而已,就不用这么掉书袋了。


verilog表示我还是C的路子

Verilog的实现差不多像这个样子:

integer handle; // 定义一个整型,我叫他句柄(学MATLAB的叫法,:)

// 建一个initial block 初始化文件

initial beginhandle = $fopen(路径,‘w');end

//always block 写数据

always@(posedge clock)begin$fdisplay(handle,标志性头部);$fwrite(handle,"%d   %d",data0,data1);$fdisplay(handle,"/n");//换行end

//仿真结束关闭文件

initial beginwait(sim_finish);$fclose(handle);end


Ruby觉得很简单

fp= File::open(路径)fp.puts data0,data2,...fp.close
 可以看到只要3行代码,甚至可以写成

File::open(路径) do |f|    f.puts(data0,data1,...)end

要比 Verilog实现简单明了很多。

想想,我们实现把数据保存到文件不可以像Ruby一样简单吗?

为什么要定义一个不关心其值的handle?(其实也关系,0的时候打开文件失败)

还要调用 $fopen打开,$fdisplay $fwrite 写 $fclose关闭?没出来一个文件都要copy一遍代码是很不明智的。

Ruby的原则是DRY---dont repeat yourself,HDL也应该这样。

我的实现思路

我们真正关心的其实只是两样东西而已,

文件的路径

保存的数据

其他的过程和数据可以封装到类里面。

当然,在这FPGA的世界要有触发条件,所以再加一样:

触发信号

用module的方式写出来,应该是这样子的。

save_to_file inst (        .路径          (文件路径),        .数据          (数据),        .触发信号      (触发信号));

本来也可以用task实现,task的方式和OOP的方法更类似,但是task没有触发信号概念(不像always)


systemverilog show time

路径是字符串,数据是可变长度,所以我用sv实现。

1、我定义一个class,在class 包涵几个东西(数据和方法),OOP的做法:

        (1)、定义文件头字符串或者叫个人标志(用sv的string类型保存字符串可比verilog方便多了)

                  verilog 定义字符串是这样的: reg [1023:0]  str = "bbalabala"; 把字符存到reg的类型里面,而且reg的长度必须大于字符串长度x8;

                  sv:string  str = “balabala”;  直接就是新的数据类型,没有verilog的限制

        (2)、打开文件的过程,例化class时直接打开文件

        (3)、把数据写到文件的task,task支持动态类型的数组(sv的数据类型,我用于支持可变长度数据)

                 sv:reg [DSIZE-1:0]   array [LEN-1:0];   LEN长度的数组

                         reg[DSIZE-1:0]    array [   ] ;  动态数组,长度在编译时决定

                         reg[DSIZE-1:0]    seq  [$];  队列,长度可变,可动态添加和删除元素  

        (4)、关闭文件

        (5)、错误提示

2、定义一个module  实现上面的功能

module stream_to_file #(    parameter stringFILE_PATH= "",    parameter stringHEAD_MARK= "",    parameter stringDATA_SPLIT= "",    parameter TRIGGER_TOTAL = 1000)(    input enable ,    input posedge_trigger ,    input negedge_trigger ,    input signal_trigger ,    input int data []);

 文件路径

文件标识头

数据分割符

要截取的总数,默认1000

使能信号

上升沿触发信号

下降沿触发信号

电平触发信号 (这3个用一个也行,3个都用也行)

要保存的数据


直接例化使用和普通module 一样


stream_to_file #(    .FILE_PATH     ("E:/project/tpm.txt"),     // 要保存到的文件路径,最好是全路径,不然会自动保存到仿真默认路径    .HEAD_MARK     ("--@--Young--@--"),        //文件头标识,默认是没有的 “”    .DATA_SPLIT    ("     "),                  //数据分割,默认是4个空格,可以设成 "," ,  ";" "\t" ; "####"    .TRIGGER_TOTAL (1000)                      // 抓取数量,默认 1000行)stream_to_file_inst(    .enable             (1'b1 ),              //使能控制,相当于暂停 开始    .posedge_trigger    (),                   //用XX上升沿,触发抓取    .negedge_trigger    (clock),              //用clock下降沿,触发抓取    .signal_trigger     (),                   //用XX变化,触发抓取,(三个可同时使用)    .data               ('{数据0,数据1,数据2,数据3,数据4,数据5,......,数据n})); //数据格式 ‘{数据0,数据1,....,数据n}  注意一定要加“{”前面的 ‘ ,不然会报错!!!






0 0
原创粉丝点击