一生一芯记录(一)

1.工程shell脚本

tree:
.
├── build.sh
└── projects
└── counter
├── csrc
│ └── main.cpp
└── vsrc
└── top.v

./build.sh -e counter -b -s 得到波形
./build.sh -e counter -w vlt_dump.vcd  用gtkwave查看波形

build.sh(原版的精简):

#!/bin/bash

#./build.sh -e counter -b -s
#./build.sh -e counter -w vlt_dump.vcd
#./build.sh -e counter -c build_test
VERSION="1.19"

help() {
    echo "Version v"$VERSION
    echo "Usage:"
    echo "build.sh [-e project_name] [-b] [-t top_file] [-s] [-a parameters_list] [-f] [-l] [-g] [-w] [-c] [-d] [-m] [-r test_cases]"
    echo "Description:"
    echo "-e: Specify a example project. For example: -e counter. If not specified, the default directory \"cpu\" will be used."
    echo "-b: Build project using verilator and make tools automatically. It will generate the \"build\"(difftest) or \"build_test\" subfolder under the project directory."
    echo "-t: Specify a file as verilog top file. If not specified, the default filename \"top.v\" will be used. This option is invalid when connected difftest."
    echo "-s: Run simulation program. Use the \"build_test\" or \"build\"(difftest) folder as work path."
    echo "-a: Parameters passed to the simulation program. For example: -a \"1 2 3 ......\". Multiple parameters require double quotes."
    echo "-f: C++ compiler arguments for makefile. For example: -f \"-DGLOBAL_DEFINE=1 -ggdb3\". Multiple parameters require double quotes. This option is invalid when connected difftest."
    echo "-l: C++ linker arguments for makefile. For example: -l \"-ldl -lm\". Multiple parameters require double quotes. This option is invalid when connected difftest."
    echo "-w: Open the latest waveform file(.vcd) using gtkwave under work path. Use the \"build_test\" or \"build\"(difftest) folder as work path."
    echo "-c: Delete \"build\" and \"build_test\" folders under the project directory."
    exit 0
}

build_verilator_proj() {
    cd $PROJECT_PATH
    # get all .cpp files
    CSRC_LIST=`find $PROJECT_PATH/$CSRC_FOLDER -name "*.cpp"`
    for CSRC_FILE in ${CSRC_LIST[@]}
    do
        CSRC_FILES="$CSRC_FILES $CSRC_FILE"
    done
    # get all vsrc subfolders
    VSRC_SUB_FOLDER=`find $VSRC_FOLDER -type d`
    for SUBFOLDER in ${VSRC_SUB_FOLDER[@]}
    do
        INCLUDE_VSRC_FOLDERS="$INCLUDE_VSRC_FOLDERS -I$SUBFOLDER"
    done
    # get all csrc subfolders
    CSRC_SUB_FOLDER=`find $PROJECT_PATH/$CSRC_FOLDER -type d`
    for SUBFOLDER in ${CSRC_SUB_FOLDER[@]}
    do
        INCLUDE_CSRC_FOLDERS="$INCLUDE_CSRC_FOLDERS -I$SUBFOLDER"
    done

    # compile
    mkdir $BUILD_FOLDER 1>/dev/null 2>&1
    eval "verilator --x-assign unique --cc --exe --trace --assert -O3 -CFLAGS \"-std=c++11 -Wall $INCLUDE_CSRC_FOLDERS $CFLAGS\" $LDFLAGS -o $PROJECT_PATH/$BUILD_FOLDER/$EMU_FILE \
        -Mdir $PROJECT_PATH/$BUILD_FOLDER/emu-compile $INCLUDE_VSRC_FOLDERS --build $V_TOP_FILE $CSRC_FILES"
    if [ $? -ne 0 ]; then
        echo "Failed to run verilator!!!"
        exit 1
    fi
    cd $SHELL_PATH
}

# Initialize variables
SHELL_PATH=$(dirname $(readlink -f "$0"))
MYINFO_FILE=$SHELL_PATH"/myinfo.txt"
EMU_FILE="emu"
BUILD_FOLDER="build_test"
DIFF_BUILD_FOLDER="build"
VSRC_FOLDER="vsrc"
CSRC_FOLDER="csrc"
BUILD="false"
V_TOP_FILE="top.v"
SIMULATE="false"
CHECK_WAVE="false"
CLEAN="false"
PARAMETERS=
CFLAGS=
LDFLAGS=
GDB="false"


# Check parameters
while getopts 'he:bt:sa:f:l:wc:' OPT; do
    case $OPT in
        h) help;;
        e) PROJECT_FOLDER="$OPTARG";;
        b) BUILD="true";;
        t) V_TOP_FILE="$OPTARG";;
        s) SIMULATE="true";;
        a) PARAMETERS="$OPTARG";;
        f) CFLAGS="$OPTARG";;
        l) LDFLAGS="$OPTARG";;
        w) CHECK_WAVE="true";;
        c) CLEAN="true";;
        ?) help;;
    esac
done

[[ $LDFLAGS ]] && LDFLAGS="-LDFLAGS "\"$LDFLAGS\"

PROJECT_PATH=$SHELL_PATH/projects/$PROJECT_FOLDER
BUILD_PATH=$PROJECT_PATH/$BUILD_FOLDER
[[ "$DIFFTEST" == "true" ]] && V_TOP_FILE=$DIFFTEST_TOP_FILE



# Clean
if [[ "$CLEAN" == "true" ]]; then
    rm -rf $PROJECT_PATH/$BUILD_FOLDER $PROJECT_PATH/$DIFF_BUILD_FOLDER $PROJECT_PATH/out
    unlink $PROJECT_PATH/$DIFFTEST_FOLDER 1>/dev/null 2>&1
    echo "Cleaned!..."
    exit 0
fi

# Build project
if [[ "$BUILD" == "true" ]]; then
    build_verilator_proj
fi

# Simulate
if [[ "$SIMULATE" == "true" ]]; then
    cd $BUILD_PATH

    # run simulation program
    echo "Simulating..."
    ./$EMU_FILE $PARAMETERS

    if [ $? -ne 0 ]; then
        echo "Failed to simulate!!!"
        FAILED="true"
    fi
    cd $SHELL_PATH
fi

# Check waveform
if [[ "$CHECK_WAVE" == "true" ]]; then
    cd $BUILD_PATH
    WAVE_FILE=`ls -t | grep .vcd | head -n 1`
    if [ -n "$WAVE_FILE" ]; then
        gtkwave $WAVE_FILE
        if [ $? -ne 0 ]; then
            echo "Failed to run gtkwave!!!"
            exit 1
        fi
    else
        echo "*.vcd file does not exist!!!"
    fi
    
    cd $SHELL_PATH
fi

[[ "$FAILED" == "true" ]] && exit 1

top.v:

//top.v
module top (
    input clk,
    input reset,
    output reg [3:0] out);
    
    always @(posedge clk) begin
        out <= reset ? 0 : out + 1;
    end
    
endmodule

main.cpp:

//test.cpp
#include "verilated.h"     //Defines common routines
#include "Vtop.h"  //原verilog的模块名为top,所以这里是Vtop.h
#include <cstdio>

#ifdef VM_TRACE         // --trace
#include <verilated_vcd_c.h>
static VerilatedVcdC* fp;      //to form *.vcd file
#endif

static Vtop* dut_ptr;   //design under test of top

void test(int time)
{
    dut_ptr->clk = 1;
    dut_ptr->eval();

#ifdef VM_TRACE
    fp->dump(time * 2 + 1);
#endif

    dut_ptr->clk = 0;
    dut_ptr->eval();

#ifdef VM_TRACE
    fp->dump(time * 2 + 2);
#endif
}

int main()
{
    dut_ptr = new Vtop;  //instantiating module top

    dut_ptr->reset = 0;
    dut_ptr->clk = 0;
    dut_ptr->eval();
    
#ifdef VM_TRACE
    // !!!  ATTENTION  !!!//
    //  Call Verilated::traceEverOn(true) first.
    //  Then create a VerilatedVcdC object.    
    Verilated::traceEverOn(true);
    printf("Enabling waves ...\n");
    fp = new VerilatedVcdC;     //instantiating .vcd object   
    dut_ptr->trace(fp, 99);     //trace 99 levels of hierarchy
    fp->open("vlt_dump.vcd");   
    fp->dump(0);
#endif

    int cycle = 0;
    printf("Enter the test cycle:\t");
    int ret = scanf("%d", &cycle);
    for (int i = 0; i < cycle; i++) {
        test(i);
    }
#ifdef VM_TRACE
    fp->close();
    delete fp;
#endif
    delete dut_ptr;
    return 0;
}

在shell脚本中有以下语句,可以见到verilator

eval "verilator --x-assign unique --cc --exe --trace --assert -O3 -CFLAGS \"-std=c++11 -Wall $INCLUDE_CSRC_FOLDERS $CFLAGS\" $LDFLAGS -o $PROJECT_PATH/$BUILD_FOLDER/$EMU_FILE \
        -Mdir $PROJECT_PATH/$BUILD_FOLDER/emu-compile $INCLUDE_VSRC_FOLDERS --build $V_TOP_FILE $CSRC_FILES"
        
其中可以能过 verilator --help查看如下:
    --x-assign <mode>           Assign non-initial Xs to this value
    uniq 可检查文本文件中重复出现的行列。
    --cc                        Create C++ output
    --exe                       Link to create executable
    --trace                     Enable waveform creation
    --assert                    Enable all assertions
    -CFLAGS <flags>            C++ compiler arguments for makefile
    -Wall                      Enable all style warnings
    -Mdir <directory>          Name of output object directory
    --build                     Build model executable/library after Verilation
1.Verilator 读取输入的 Verilog 代码,确定所有“顶级模块”,即未用作其他单元下的实例的模块或程序。
    如果--top-module使用,则确定顶部模块并移除所有其他顶部模块,否则MULTITOP给出警告。
2.Verilator 将 C++/SystemC 代码写入输出文件到 --Mdir选项指定的目录中,或者默认为“obj_dir”。
    前缀设置为--prefix, 或默认为顶级模块的名称。
3.如果--exe使用,Verilator 创建 makefile 以生成模拟可执行文件,否则它创建 makefile 以生成包含对象的存档 (.a)4.如果使用了--build选项,它会调用GNU Make或 CMake来构建模型。
5.为获得最佳性能,请使用选项运行 Verilator 。该 选项将需要更长的时间来运行 Verilator,并且可能会增加在性能交易中重置错误的风险;
    有关这些选项,请参阅上述文档。-O3 --x-assign fast --x-initial fast --noassert-O3--x-assign fast --x-initial fast
6.如何在 C++ 中生成波形(轨迹)?另请参阅 SystemC 模式下跟踪的下一个问题。
    A.--trace选项传递给 Verilator,并在顶级 C 代码中调用Verilated::traceEverOn(true). 然后您可以使用 $dumpfile
        和$dumpvars来启用跟踪,就像使用任何 Verilog 模拟器一样。见examples/make_tracing_c分布。
    B.或者,对于更细粒度的控制,或具有多个 Verilated 模块的 C++ 文件,您也可以完全从 C++ 创建跟踪。
        创建一个 VerilatedVcdC 对象,并在每次eval()调用后立即在主循环中调用 trace_object->dump(contextp->time()),最后调用trace_object->close().

例子2

.v

//top.v
module top (
    input clk,
    input reset,
    input a,
    input b,
    output reg  out);
    
    always @(posedge clk) begin
        if (reset)begin
            out<=0;
        end
        else begin
            out<= a&b;
        end
    end
    
endmodule

.cpp:

//test.cpp
#include "verilated.h"     //Defines common routines
#include "Vtop.h"  
#include <cstdio>
#include <cstdlib>
#include <ctime>

#ifdef VM_TRACE         // --trace
#include <verilated_vcd_c.h>
static VerilatedVcdC* fp;      //to form *.vcd file
#endif

static Vtop* dut_ptr;   //design under test of top

void test(int tt_time)
{
dut_ptr->clk = 0;
dut_ptr->eval();
#ifdef VM_TRACE
    fp->dump(tt_time * 4 + 1);
#endif

dut_ptr->a=rand()%2;
dut_ptr->b=rand()%2;
dut_ptr->eval();
#ifdef VM_TRACE
    fp->dump(tt_time * 4 + 2);
#endif


dut_ptr->a=rand()%2;
dut_ptr->b=rand()%2;
dut_ptr->clk=1;
dut_ptr->eval();
#ifdef VM_TRACE
    fp->dump(tt_time * 4 + 3);
#endif

dut_ptr->a=rand()%2;
dut_ptr->b=rand()%2;
dut_ptr->eval();
#ifdef VM_TRACE
    fp->dump(tt_time * 4 + 4);
#endif
}

int main()
{
    dut_ptr = new Vtop;  //instantiating module top

    dut_ptr->reset = 0;
    dut_ptr->clk = 0;
    dut_ptr->eval();
    srand((int)time(NULL));  // 产生随机种子  把0换成NULL也行
    
#ifdef VM_TRACE
    // !!!  ATTENTION  !!!//
    //  Call Verilated::traceEverOn(true) first.
    //  Then create a VerilatedVcdC object.    
    Verilated::traceEverOn(true);
    printf("Enabling waves ...\n");
    fp = new VerilatedVcdC;     //instantiating .vcd object   
    dut_ptr->trace(fp, 99);     //trace 99 levels of hierarchy
    fp->open("vlt_dump.vcd");   
    fp->dump(0);
#endif

    int cycle = 0;
    printf("Enter the test cycle:\t");
    int ret = scanf("%d", &cycle);
    for (int i = 0; i < cycle; i++) {
        test(i);
        //ab_out(i);
    }
#ifdef VM_TRACE
    fp->close();
    delete fp;
#endif
    delete dut_ptr;
    return 0;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Greate AUK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值