当前位置: 首页 > article >正文

Verilator——最简单、最细节上手教程

目录

  • 前言
  • 工具安装
    • Verilator 安装
    • GTKwave 安装
  • Verilator 基础用法
    • fst格式和vcd格式的wave文件
    • Verilator 的使用
  • Verilator 的进阶使用
    • 与GDB搭配
    • 与makefile搭配
  • Verilator 的高阶用法
    • 访问模块内部数据

前言

此教程会以ubuntu22.04为例
从如何安装,到如何使用
全程帮助你学习和使用verilator

狂肝3h,倾心之作

如有笔误、问题,欢迎指出、讨论~

点赞,收藏,长期翻看~

工具安装

Verilator 安装

利用git进行快速安装(安装方法摘自官网Verilator)

# 安装的前提:
sudo apt-get install git help2man perl python3 make autoconf g++ flex bison ccache
sudo apt-get install libgoogle-perftools-dev numactl perl-doc
sudo apt-get install libfl2  # 只有Ubuntu需要,如果报错就忽略
sudo apt-get install libfl-dev  # 只有Ubuntu需要,如果报错就忽略
sudo apt-get install zlibc zlib1g zlib1g-dev  # 只有Ubuntu需要,如果报错就忽略

git clone https://github.com/verilator/verilator   #只需克隆一次

# Every time you need to build:
unsetenv VERILATOR_ROOT  # 对csh操作,如果是使用bash就忽略
unset VERILATOR_ROOT  # 对bash操作
cd verilator
git pull         # 确保git的仓库是最新的
git tag          # 查看可选版本

#选择以下的其中一个执行:
#git checkout master      # 使用开发分支(例如最近的bug修复版本)
#git checkout stable      # 使用最新的稳定版本
#git checkout v{version}  # 切换到指定版本

autoconf         # 创建脚本
./configure      # 配置并创建makefile
make -j `nproc`  # 构建verilator (如果报错试试只输入“make”)
sudo make install

然后执行

verilator --version	#检查版本,检查是否安装成功

GTKwave 安装

用来查看verilator生成的波形文件

有两种安装方法:

  1. 直接从ubuntu自带的应用商城搜索gtkwave,即可安装在这里插入图片描述
  2. 使用apt-get命令来安装
sudo apt-get install gtkwave
gtkwave --version	//查看版本,检查是否安装成功

Verilator 基础用法

fst格式和vcd格式的wave文件

varilator可以生成两种格式的wave文件:

  1. fst格式
    • FST格式的波形文件大致是VCD格式的1/50
    • 该格式只能用gtkwave打开,其他波形查看软件不支持
  2. vcd格式
    • 文件大小较大
    • 可以用多种波形查看软件查看

鉴于fst格式的优点,以及网上很少关于生成fst格式的教程,因此我以生成fst为例,如若要生成vcd可以上网查阅资料

接下来我将介绍如何使用verilator

Verilator 的使用

cpp为例,并介绍如何生成fst wave文件的生成

可以看官方的例程 :官方c++例程
此处我挑出其中重点的部分来讲解

假设我们用verilog写一个双控开关:

//顶层文件名为top,因此等会include的头文件为Vtop
//若顶层文件名为example,则include的头文件名为Vexample
module top(
  input clk,
  input rst,
  input a,
  input b,
  output f
);
  assign f = a ^ b;
endmodule

仿真过程用c++来描述,文件如下:

//与verilator无关的一些头文件
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//使用verilater必须include
#include "Vtop.h" //仿真模型的头文件,由top.v生成,如果顶层文件名更改则也需要更改
#include <verilated.h>

#define CONFIG_FST_WAVE_TRACE 1

// contextp用来保存仿真的时间
VerilatedContext *contextp = new VerilatedContext;

// 构建一个名为top的仿真模型
Vtop *top = new Vtop{contextp};

//如果生成FST格式的wave
#if CONFIG_FST_WAVE_TRACE
#include "verilated_fst_c.h"			//波形文件所需的头文件
VerilatedFstC *tfp = new VerilatedFstC; // 创建一个波形文件指针
#endif

//仿真的过程
int main(int argc, char **argv)
{
	Verilated::mkdir("build/logs"); // 创建一个日志文件夹

	// 传递参数给verilator
	contextp->commandArgs(argc, argv);

//如果生成FST格式的wave
#if CONFIG_FST_WAVE_TRACE
	contextp->traceEverOn(true);		  // 启用跟踪
	top->trace(tfp, 99);				  // 采样深度为99
	tfp->open("build/logs/cpu_wave.fst"); // 打开波形文件,文件地址和文件名可以自定义
#endif

	/***************对top端口的初始化*******************/
	top->clk = 0;
	top->rst = 0;


	/**************verilator的仿真循环*****************/
	while (!contextp->gotFinish())	// ctrl+c 可以停止仿真
	{
		/************设置vtop仿真的输入信号************/

	int a = rand() & 1;
    int b = rand() & 1;
    top->a = a;
    top->b = b;
    top->clk = !top->clk; // 随着仿真时间倒转clk,产生时钟周期
    top->eval(); //更新电路状态
    printf("a = %d, b = %d, f = %d\n", a, b, top->f);	//按需打印想要的
    
    contextp->timeInc(1); //推动仿真时间
		
#if CONFIG_FST_WAVE_TRACE
		tfp->dump(contextp->time()); // 按照时间采样
#endif
	}

/*****************仿真结束,一些善后工作***************/
#if CONFIG_FST_WAVE_TRACE
	tfp->close(); // 关闭波形文件
#endif

	// 清理top仿真模型,并销毁相关指针,并将指针变为空指针
	top->final();
	delete top;
	top = nullptr;
	delete contextp;
	contextp = nullptr;

	return 0;
}

完成文件的编写后,我们要让verilator编译并运行
在命令行中输入

verilator -Wall top.v top_main.cpp --cc --trace-fst --exe --build
./obj_dir/Vtop   //必须执行这个,才运行仿真,生成波形
gtkwave build/logs/cpu_wave.fst	//用gtk打开波形文件

Verilator 的进阶使用

与GDB搭配

gdb可以很方便得对仿真的过程进行调试

如何使用请详见 “与makefile搭配”

与makefile搭配

如果每次使用verilator都要在命令行中输入以上命令,有点太麻烦了
因此可以利用makefile

########### 不要在变量后面加多余空格,否则会导致变量名出问题 ###########
########### 因此也不要在变量后面加注释,以避免上述情况发生 ###########

#顶层文件的名字
TOPNAME = top

#指定verilator
VERILATOR = verilator


######################## 包含相关文件 ########################
#相关文件的地址
INCLUDE_PATH = ./build/chisel ./src/main/cpp/

#对地址添加 -I的前缀
INCFLAGS = $(addprefix -I, $(INCLUDE_PATH))


######################## cxx编译选项 ########################
CXXFLAGS += $(INCFLAGS) -DTOP_NAME="\"V$(TOPNAME)\""
#生成调试信息
CXXFLAGS += -g
#让错误信息带颜色,不知道有没有用
CXXFLAGS += -fdiagnostics-color=auto
CFLAGS_TRACE += -DITRACE_COND=$(if $(CONFIG_ITRACE_COND),$(call remove_quote,$(CONFIG_ITRACE_COND)),true)
CXXFLAGS  += $(CFLAGS_TRACE)


######################## 链接器编译选项 ########################
#链接器的选项,包含readline库
LDFLAGS += -lreadline


######################## 构建后的项目 ########################
#构建后的地址
BUILD_DIR = ./build/verilator

#构建后文件存放的地址
OBJ_DIR = $(BUILD_DIR)/obj_dir

#可执行文件的地址
BIN = $(OBJ_DIR)/$(TOPNAME)


######################## verilator选项 ########################
#创建生成文件的目录,存放生成的文件
VERILATOR_CFLAGS += --Mdir $(OBJ_DIR)

#优化分配 
VERILATOR_CFLAGS += -x-assign fast

#将所有warning 变成error
VERILATOR_FLAGS += -Wall

#Make waveforms,fst格式
VERILATOR_CFLAGS += --trace-fst

#检查SystemVerilog断言
VERILATOR_CFLAGS += --assert

#debug模式,生成更多调试信息
VERILATOR_FLAGS += --debug

#Add this trace to get a backtrace in gdb
VERILATOR_FLAGS += --gdbbt

# 可用gdb调试
VERILATOR_FLAGS += --gdb

#加速编译
VERILATOR_CFLAGS += -j

#包含verilog中include的文件地址
VERILATOR_CFLAGS += $(INCFLAGS)

#使用DPI-C
VERILATOR_CFLAGS += --vpi

#调用工具链来构建库,不加则由verilator自己构建
VERILATOR_CFLAGS += --build

#指定顶层文件
VERILATOR_CFLAGS += --top-module $(TOPNAME)

#将cxx参数传给gcc编译
VERILATOR_CFLAGS += $(addprefix -CFLAGS , $(CXXFLAGS))

#将ld参数传给ld链接
VERILATOR_CFLAGS += $(addprefix -LDFLAGS , $(LDFLAGS))

#生成C++可执行文件,并指定文件名字
VERILATOR_CFLAGS += --cc --exe -o $(abspath $(BIN))


######################## 查找相关文件 ########################
VSRCS = $(shell find $(abspath ./build/chisel) -name "*.v" -or -name "*.sv")
CSRCS = $(shell find $(abspath ./src/main/cpp) -name "*.c" -or -name "*.cc" -or -name "*.cpp")

run:
	@echo "-------- VERILATE --- AND --- BUILD --------"

#清空再创建目的地目录
	@rm -rf $(OBJ_DIR)
	@mkdir -p $(OBJ_DIR)

#执行命令
	@$(VERILATOR) $(VERILATOR_CFLAGS) $(VSRCS) $(CSRCS)

	@echo
	@echo "-------------------- RUN --------------------"

#清空再创建波形文件夹并
	@rm -rf $(BUILD_DIR)/logs
	@mkdir -p $(BUILD_DIR)/logs

#执行可执行文件,运行并仿真,生成波形
	@$(BIN) +trace

	@echo
	@echo "-------------------- DONE --------------------"
	@echo "To see waveforms, open $(BUILD_DIR)/logs/cpu_wave.fst in a waveform viewer"
	@echo


gdb:
	@echo "-------- VERILATE --- AND --- BUILD --------"

#清空再创建目的地目录
	@rm -rf $(OBJ_DIR)
	@mkdir -p $(OBJ_DIR)

#执行命令
	@$(VERILATOR) $(VERILATOR_CFLAGS) $(VSRCS) $(CSRCS)

	@echo
	@echo "-------------------- GDB --------------------"

#清空再创建波形文件夹并
	@rm -rf $(BUILD_DIR)/logs
	@mkdir -p $(BUILD_DIR)/logs

#gbd执行可执行文件,运行并仿真,生成波形
	gdb -s $(BIN) --args $(BIN)

	@echo
	@echo "-------------------- DONE --------------------"
	@echo "To see waveforms, open $(BUILD_DIR)/logs/cpu_wave.fst in a waveform viewer"
	@echo

然后在当前目录下执行

make run	//执行仿真
make gdb	//使用gdb

即可

Verilator 的高阶用法

访问模块内部数据

前面的介绍中,我们要访问模块的数据,只能访问到顶层模块top的输入输出端口,假如我要访问其中内部的wire和reg数据该怎么办呢?

verilator为在将verilog文件编译为cpp文件进行仿真的时候,我们可以在仿真文件中访问verilator将.v文件转化后的cpp文件来访问数据

只需在上面的仿真文件中增加以下内容

#include "../build/obj_dir/Vtop___024root.h"

//然后就可以通过top来访问了
printf("data:%x",top->rootp->top__DOT__my_regfile__DOT__reg_f[1])
//my_regfile为实例化的模块名
//reg_f为模块中定义的reg型
//若你想输出你想要的数据可以在 ../build/obj_dir/Vtop___024root.h 头文件中寻找

http://www.kler.cn/news/359660.html

相关文章:

  • 后端接收参数的几种常用注解
  • 中国移动机器人将投入养老场景;华为与APUS共筑AI医疗多场景应用
  • 2024年4个好用的录屏软件大盘点,轻松录制精彩瞬间。
  • Redis进阶
  • 浏览器实时更新esp32-c3 Supermini http server 数据
  • 智能汽车制造:海康NVR管理平台/工具EasyNVR多品牌NVR管理工具/设备实现无插件视频监控直播方案
  • Redis主从复制实现原理
  • 汽车行业焕新潮流涌动,联众优车以优质服务响应市场变化
  • vue前端开发框架的常见知识点和应用
  • 【wpf】08 xml文件的存取操作
  • Imagic: Text-Based Real Image Editing with Diffusion Models
  • 基于python3.6读取jsonl文件,并保存到Mysql数据库
  • android NDK 编译提示 is not able to compile a simple test program
  • AI创新驱动教育:科技革命下的教育转型
  • 从上市首份半年报业绩亮点看绿联科技发展
  • 面试之mybatis的一二级缓存
  • 基于深度学习的西红柿成熟度检测系统
  • CTF(二)
  • excel导出加密
  • IDEA下lombok安装及找不到get,set的问题的解决方法