# EpicSim **Repository Path**: xfangzhen/EpicSim ## Basic Information - **Project Name**: EpicSim - **Description**: EpicSim is a Verilog compiler. It is suitable for use as a simulator - **Primary Language**: C++ - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 27 - **Created**: 2021-08-18 - **Last Updated**: 2024-06-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # EpicSim 入门指南 EpicSim 是一个Verilog编译器。它使用于仿真模拟,建议在Red Hat和CentOS系统下运行。本手册说明使用于所有环境。 该项目基于icarus iverilog进行二次开发,遵循LGPL开源协议。特别感谢Stephen Williams (steve@icarus.com) ## 1.基于源码安装 基于源码的编译过程设计的既简单又实用。如果你对目标系统和C/C++编译器有基本了解,就能很容易的从源码构建出发行版本。实际的编程经验不是必须的,但是在遇到问题时很有帮助。 ### 1.1 编译所需环境 在类UNIX系统上编译EpicSim源码,需要提前安装以下软件: - CMake - GNU Make - ISO C++ Compiler - bison and flex - gperf 3.0 or later - readline 4.2 or later - termcap - bash ### 1.2 编译 解压tar压缩包,依次运行如下命令: ```bash cd EpicSim mkdir build cd build cmake .. make install ``` 安装完成后,设置环境变量: ```bash cd EpicSim #bash export PATH="target_installation_path/EpicSim/install/bin:$PATH" #cshell setenv PATH target_installation_path/EpicSim/install/bin:$PATH" ``` ## 2. Hello, World! 作为用户,你想做的第一件事可能就是学习如何编译和执行最简单的设计,我用下面的设计作为例子进行仿真。 ```verilog module main; initial begin $display("Hello, World"); $finish ; end endmodule ``` 1.把上面的代码放到一个文本文件里,命名为`hello.vl`。或者直接从EpicSim下的examples目录拷贝出来。 2.用 `epicsim` 命令编译程序: ```bash % epicsim hello.vl ``` 3. 编译后会生成 `epicsim-run` 文件,运行输出如下: ```bash Hello, World ``` 也可以执行下面两个步骤运行编译后的程序: ```bash % epicsim-driver hello.vl -o epicsim-run % epicsim-vvp ./epicsim-run ``` ```bash Hello, World ``` 到此,程序已经被运行了。那么发生了哪些事情呢?第一步,`epicsim-driver` 命令,读取并解释源文件,然后生成编译结果。编译后的格式可以通过命令行开关选择,默认使用 `vvp`,并由 `epicsim-vvp` 运行。 `epicsim-driver` 和 `epicsim-vvp` 是提供用户调用EpicSim的命令。编译器实际的编译方式是由命令行开关控制。前面的例子,编译器用默认的`vvp`格式编译源代码,然后由`epicsim-vvp`运行 ## 3. EpicSim 工作原理 工具里包含有解释器,解释器会读取Verilog(带后缀)文件,然后生成内部网表。网表经过一系列转换步骤,转换成更优,更实用的形式。最终由代码生成器输出。转换步骤和代码生成都是可以通过命令行进行选择。 ### 3.1 预处理 预处理工作是另一个独立的程序`ivlpp`来完成的。该程序实现了`include` 和 `define`指令,处理后生成不含`include` 和 `define`指令的结果。生成结果是一个带有指令的行编号的单文件。所以,真正的编译器只会收到单独的一个输入文件。可以通过 `ivlpp/ivlpp.txt` 查看更多的细节 ### 3.2 语法解析 Verilog 编译器首先先解析 Verilog 源文件。解析的输出结果是"`pform`"里的模块对象。 `pform` 主要是编译步骤的直接反映(参考`pform.h`)。可能存在空引用,而且还不清楚哪个模块是根模块 通过对`ivl`子命令使用`-P `标志,可以看到最终可读的`pform`版本。`ivl`会将`pform`转储到名为 `` 的文件中。(注意,除非调试`ivl`子命令,否则通常不会这样做。) ### 3.3 展开阶段 展开阶段将 `pform` 生成一个网表。驱动程序选择(根据用户请求或智能猜测)根模块来详细展开,解析引用并扩展实例以形成设计网表(参考 `netlist.txt`)。最后的语义检查和一些简单的优化也是在展开过程中执行。网表包括了所有的行为描述,以及门和线。 展开行为由`elaborate()`函数实现。 通过向编译器使用`-N `标志,可以看到网表展开和优化后的最终可读版本。如果展开成功,最终的网表(即在优化之后但在代码生成之前)将被转储到名为``的文件中。 展开过程分为两个步骤: - 范围和参数的展开。 - 结构和行为的展开。 #### 3.3.1 范围展开 范围展开会遍历`pform`以查找范围和参数。NetScope 对象树被构建并放置在Design 对象中,根模块由根NetScope 对象表示。`elab_scope.cc`文件包含了这一步骤大部分的实现代码。 范围展开行为的最后(在遍历pform之后)会扫描 NetScope 对象树,以定位在范围展开期间收集的defparam赋值行为。这是为了参数可以被defparam重写。 #### 3.3.2 网表展开 在范围和参数以及NetScope项目树完全形成之后,展开程序会再次遍历`pform`以生成结构和行为网表。并对参数进行展开和计算,所以代码生成的所有常量现在都在本地已知,只需通过 `pform`即可生成网表。 ### 3.4 优化 优化是一系列处理步骤的集合,针对不依赖于目标技术的性能优化。下面是一些有用的转换示例: - 消除零效应电路 - 减少组合 - 常量传播 可以通过在`ivl`命令行上指定`-F`标志来开启优化功能 ### 3.5 代码生成 代码生成是指通过使用设计的网表来驱动代码生成器(参考`target.h`)。可能需要转变设计以适应技术。 Design 类里的`emit()`方法是用来执行这个步骤的。它遍历设计元素,在需要时调用目标函数以生成实际输出。 用户可以在命令行中用`-t`标记选择目标代码生成器。 ## 4 不支持的结构 - 指定要解析的块,但通常会被忽略。 - 不支持三态寄存器. `tri0` 和 `tri1` 是支持的. - Tran 原语, 例如 `tran`, `tranif1`, `tranif0`, `rtran`, `rtranif1`, 和 `rtranif0` 不被支持. - 不支持非阻塞赋值中的事件控件,例如: ```verilog a <= @(posedge clk) b; ``` ## 5 常用的标志/选项 `-o `: 指定输出的编译结果文件. `-f `: 指定要读入的文件. `-D `: 定义一个常量,名为:macro,值为:value. `-s `: 指定根模块. `T min|typ|max`: 指定模拟器的使用的时间 (最小, 标准, 最大) 。 默认是 标准.