当前位置: 首页 > 工具软件 > Verilator > 使用案例 >

Verilator记录学习

阎修明
2023-12-01

杂七杂八,都是网上搜集到的例子,对于Verilator一窍不通 希望能够通过这些对自己有个补充作用
若有冒犯请见谅,侵权删除

Verilator官方所给手册 C++例子

mkdir test_our //创建文件夹
cd test_our

cat >our.v <<'EOF'
  module our;  # 定义一个module
     initial  # 定义一个initial块
     	begin   # initial块的开始
     		$display("Hello World"); # debug输出Hello World
     		$finish; # debug完成
     	end # initial块的结束
  endmodule  # our模块的结束
EOF

cat >sim_main.cpp <<'EOF'
  #include "Vour.h"  # our.v被verilator编译成Vour.h   **得改
  #include "verilated.h"  # verialtor官方库
  int main(int argc, char** argv, char** env) {
      VerilatedContext* contextp = new VerilatedContext;  # verilator上下文指针
      contextp->commandArgs(argc, argv);  # 检查参数
      Vour* top = new Vour{contextp};  # 实例化our模块
      while (!contextp->gotFinish()) { # 一直到contextp仿真完成才退出
      	top->eval(); # 更新电路状态,计算输出
      }
      delete top;
      delete contextp;
      return 0;
  }
EOF

MakeFile中核心的编译语句其实就是执行:

verilator -Wall --cc --exe --build top.v sim_main.cpp

执行生成的C++可执行文件,结果生成文件Vxxx
执行编译:

verilator -Wall top.v top_main.cpp --cc --trace --exe --build
#增加了--trace 是为了显示波形的,注意得加上--tarce 否则会报错(若前面有含波形的库)
./obj_dir/Vtop   //必须执行这个,才会出现.vcd文件,需要强制退出
gtkwave wave.vcd //如果报错缺少canberra-gtk-module,apt安装即可

南京大学数字电路 二选一激励代码

#include "verilated.h"
#include "verilated_vcd_c.h"
#include "obj_dir/Vmux21.h"   ***//得改***

VerilatedContext* contextp = NULL;
VerilatedVcdC* tfp = NULL;

static Vmux21* top;

void step_and_dump_wave(){
  top->eval();
  contextp->timeInc(1);
  tfp->dump(contextp->time());
}
void sim_init(){
  contextp = new VerilatedContext;
  tfp = new VerilatedVcdC;
  top = new Vmux21;
  contextp->traceEverOn(true);
  top->trace(tfp, 0);
  tfp->open("dump.vcd");
}

void sim_exit(){
  step_and_dump_wave();
  tfp->close();
}

int main() { //不同情况,不同取值
  sim_init();

  top->s=0; top->a=0; top->b=0;  step_and_dump_wave();   // 将s,a和b均初始化为“0”
                      top->b=1;  step_and_dump_wave();   // 将b改为“1”,s和a的值不变,继续保持“0”,
            top->a=1; top->b=0;  step_and_dump_wave();   // 将a,b分别改为“1”和“0”,s的值不变,
                      top->b=1;  step_and_dump_wave();   // 将b改为“1”,s和a的值不变,维持10个时间单位
  top->s=1; top->a=0; top->b=0;  step_and_dump_wave();   // 将s,a,b分别变为“1,0,0”,维持10个时间单位
                      top->b=1;  step_and_dump_wave();
            top->a=1; top->b=0;  step_and_dump_wave();
                      top->b=1;  step_and_dump_wave();

  sim_exit();
}

语句学习01 *测试模块

#include "verilated_vcd_c.h" //可选,如果要导出vcd则需要加上
#include "VAccumulator.h"
 
vluint64_t main_time = 0;  //initial 仿真时间
 
double sc_time_stamp()
{
    return main_time;
}
 
int main(int argc, char **argv)
{
    Verilated::commandArgs(argc, argv); 
    Verilated::traceEverOn(true); //导出vcd波形需要加此语句
 
    VerilatedVcdC* tfp = new VerilatedVcdC; //导出vcd波形需要加此语句
 
    VAccumulator *top = new VAccumulator("top"); //调用VAccumulator.h里面的IO struct
 
    top->trace(tfp, 0);   
    tfp->open("wave.vcd"); //打开vcd
 
    while (sc_time_stamp() < 20 && !Verilated::gotFinish()) { //控制仿真时间
        top->io_din_0 = main_time + 0; //激励控制
        top->io_din_1 = main_time + 1;
        top->io_din_2 = main_time + 2;
        top->io_din_3 = main_time + 3;
 
        top->eval(); //计算输出
 
        printf("%d + %d + %d + %d = %d\n",top->io_din_0,top->io_din_1,top->io_din_2,top->io_din_3,top->io_dout); //命令行输出仿真结果
        tfp->dump(main_time); //dump wave
        main_time++; //推动仿真时间
    }
    top->final();
    tfp->close();
    delete top;
 
    return 0;
}

例子02

#include <verilated.h> // Defines common routines
#include <iostream> // Need std::cout
#include "Vtop.h" // From Verilating "top.v"
Vtop *top; // Instantiation of model
uint64_t main_time = 0; // Current simulation time
// This is a 64-bit integer to reduce wrap over issues and
// allow modulus. This is in units of the timeprecision
// used in Verilog (or from --timescale-override)
double sc_time_stamp() { // Called by $time in Verilog
return main_time; // converts to double, to match
// what SystemC does
}
int main(int argc, char** argv) {
Verilated::commandArgs(argc, argv); // Remember args
top = new Vtop; // Create model
// Do not instead make Vtop as a file-scope static
// variable, as the "C++ static initialization order fiasco"
// may cause a crash
top->reset_l = 0; // Set some inputs
while (!Verilated::gotFinish()) {
if (main_time > 10) {
top->reset_l = 1; // Deassert reset
}
if ((main_time % 10) == 1) {
top->clk = 1; // Toggle clock
}
if ((main_time % 10) == 6) {
top->clk = 0;
}
top->eval(); // Evaluate model
cout << top->out << endl; // Read a output
main_time++; // Time passes...
}
top->final(); // Done simulating
// // (Though this example doesn't get here)
delete top;
}

补充学习:

-new 运算符 (C++) 是尝试分配和初始化指定类型或占位符类型的对象或对象数组,并返回指向对象(或指向数组初始对象)的适当类型化的非零指针。
使用 new 为 C++ 类对象分配内存时,将在分配内存后调用对象的构造函数。使用 delete 运算符解除由 new 运算符分配的内存。 使用 delete[] 运算符删除由 new 运算符分配的数组。
new学习
new和make的区别
new A() 这样方式的功能如下:
1 在堆上分配空间
2 在分配的空间上调用对象的构造函数
(这也是 new 和 malloc的主要区别,是否调用构造函数)
同理: 在调用 delete obj的时候:
1 首先调用 这个对象 的析构函数
2 然后释放这个对象的空间

C++ . -> :: 符号含义与区别
c++中当定义类对象是指针对象时候,就需要用到->指向类中的成员;当定义一般对象时候时就需要用到"."指向类中的成员。
箭头(->):左边必须为指针;
点号(.):左边必须为实体。把域看作是一个可视窗口全局域的对象在它被定义的整个文件里,一直到文件末尾都是可见的。在一个函数内被定义的对象是局域的(local scope), 它只在定义其的函数体内可见。每个类维持一个域,在这个域之外 ,它的成员是不可见的。

 类似资料: