지난 포스터에서 언급한 Icarus Verilog 와 함께 open simulator 중 하나의 Verilator 를 이용하여 시뮬레이션을 진행해 보도록 하겠습니다. 이전에 사용한 코드를 기반으로 Verilator 에 사용할 C++ testbench 를 작성하였으며, 해당 코드는 글 마지막에 다운로드 받을 수 있습니다.
Verilator 는 Verilog 혹은 SytemVerilog 를 C++ 나 SystemC 로 변환하여 실행파일을 만들고 시뮬레이션을 돌리기 때문에 빠르다는 장점이 있습니다. 그 동안 회사의 업무에서 전혀 사용하지 않아 개인적으로는 접할 기회가 많이 없었는데 RISC-V 2018 SoftCPU Contest 에 기본 simulator로 선정되기도 하고, Tesla Hot Chips 2019 에 사용 된 것을 보면 꽤 보편화가 된것 같습니다.
1. Verilator 설치 하기
Verilator 역시 소스를 다운 받고 직접 컴파일을 하여 설치 할수 있지만 Package를 이용하여 손쉽게 설치 할 수 있습니다. 자세한 설치 방법은 Verilator Installation 를 참조 하시기 바랍니다.
myskan@TP-P72:~$ sudo apt-get install verilator myskan@TP-P72:~$ verilator --V Verilator 4.028 2020-02-06 rev v4.026-92-g890cecc1 Copyright 2003-2020 by Wilson Snyder. Verilator is free software; you can redistribute it and/or modify the Verilator internals under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. See https://verilator.org for documentation Summary of configuration: Compiled in defaults if not in environment: SYSTEMC = SYSTEMC_ARCH = SYSTEMC_INCLUDE = /usr/include SYSTEMC_LIBDIR = /usr/lib/x86_64-linux-gnu VERILATOR_ROOT = /usr/share/verilator Environment: PERL = SYSTEMC = SYSTEMC_ARCH = SYSTEMC_INCLUDE = SYSTEMC_LIBDIR = VERILATOR_ROOT = VERILATOR_BIN = myskan@TP-P72:~$
2. Testbench 작성
Verilator 의 testbench는 C++ 혹은 SystemC로 작성이 되어야 하는데 여기서는 C++로 작성하였습니다. 기존의 testbench 이었던 acgen_tb.v 에서 생성하였던 신호들을 acgen_tb.cpp 에서 생성하도록 변경 하였습니다. 라인 49는 해당 신호들의 초기화 부분이며, 라인 57의 while 구문에서 시뮬레이션이 반복적으로 수행하면서 기본 testbench 와 동일하게 입력 신호들이 변경되도록 구성 하였습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | #include <verilated.h> // Defines common routines #include "Vacgen_tb.h" #include "verilated_vcd_c.h" #include <iostream> #include <string> #include <cstdlib> #include <cstdio> Vacgen_tb *uut; // Instantiation of module vluint64_t main_time = 0; // Current simulation time double sc_time_stamp () { // Called by $time in Verilog return main_time; // converts to double, to match } int main(int argc, char** argv) { int tclk = 0; int fin_sim = 0; // turn on trace or not? bool vcdTrace = true; VerilatedVcdC* tfp = NULL; Verilated::commandArgs(argc, argv); // Remember args uut = new Vacgen_tb; // Create instance uut->eval(); if (vcdTrace) { Verilated::traceEverOn(true); tfp = new VerilatedVcdC; uut->trace(tfp, 99); std::string vcdname = argv[0]; vcdname += ".vcd"; std::cout << vcdname << std::endl; tfp->open(vcdname.c_str()); } std::cout << "==============================" << std::endl; std::cout << "=== Start Sim === " << std::endl; std::cout << "==============================" << std::endl; // Initalziation uut->clk = 0; uut->rstb = 0; uut->sg_en = 0; uut->vav = 0; uut->eval(); while ((!Verilated::gotFinish()) && !fin_sim) { uut->clk = uut->clk ? 0 : 1; // Toggle clock if (uut->clk) { tclk++; } if (tclk == 10) { uut->rstb = 1; } if (tclk == 20) { uut->vav = 1; } if (tclk == 30) { uut->sg_en = 1; } if (main_time == 28800000) { uut->vav = 0; } if (main_time == 28810000) { uut->vav = 1; } if (main_time == 38810000) { uut->vav = 0; } if (main_time == 58810000) { fin_sim = 1; } uut->eval(); // Evaluate model if (tfp != NULL) { tfp->dump (main_time); } main_time = main_time + 10; // Time passes... } uut->final(); // Done simulating std::cout << "==============================" << std::endl; std::cout << "=== End Sim === " << std::endl; std::cout << "==============================" << std::endl; if (tfp != NULL) { tfp->close(); delete tfp; } delete uut; return 0; } |
3. 컴파일 및 Simulation 하기
Make 화일을 이용하여 컴파일을 하게 되면 acgen_tb 폴더가 생성이 되고 Vacgen_tb 실행 화일이 생성이 됩니다. 해당 화일을 실행 시켜보면 지난 포스터에서 언급한 Icarus Verilog 와 비교하여 시뮬레이션이 정말 빠른 것을 체감 할 수 있습니다.
myskan@TP-P72:~/Work/verilator/awb/fsim$ make verilator -Wno-fatal -I. -I../rtl -I./sim_model --cc acgen_tb.v --trace --exe ../acgen_tb.cpp -Mdir acgen_tb -CFLAGS "-g -O3" make -C acgen_tb -f Vacgen_tb.mk make[1]: Entering directory '/home/myskan/awb/fsim/acgen_tb' g++ -I. -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -g -O3 -c -o acgen_tb.o ../acgen_tb.cpp g++ -I. -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -g -O3 -c -o verilated.o /usr/share/verilator/include/verilated.cpp g++ -I. -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -g -O3 -c -o verilated_vcd_c.o /usr/share/verilator/include/verilated_vcd_c.cpp /usr/bin/perl /usr/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include Vacgen_tb.cpp > Vacgen_tb__ALLcls.cpp g++ -I. -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -g -O3 -c -o Vacgen_tb__ALLcls.o Vacgen_tb__ALLcls.cpp /usr/bin/perl /usr/share/verilator/bin/verilator_includer -DVL_INCLUDE_OPT=include Vacgen_tb__Trace.cpp Vacgen_tb__Syms.cpp Vacgen_tb__Trace__Slow.cpp > Vacgen_tb__ALLsup.cpp g++ -I. -MMD -I/usr/share/verilator/include -I/usr/share/verilator/include/vltstd -DVM_COVERAGE=0 -DVM_SC=0 -DVM_TRACE=1 -faligned-new -fcf-protection=none -Wno-bool-operation -Wno-sign-compare -Wno-uninitialized -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-variable -Wno-shadow -g -O3 -c -o Vacgen_tb__ALLsup.o Vacgen_tb__ALLsup.cpp ar -cr Vacgen_tb__ALL.a Vacgen_tb__ALLcls.o Vacgen_tb__ALLsup.o ranlib Vacgen_tb__ALL.a g++ acgen_tb.o verilated.o verilated_vcd_c.o Vacgen_tb__ALL.a -o Vacgen_tb -lm -lstdc++ make[1]: Leaving directory '/home/myskan/awb/fsim/acgen_tb' myskan@TP-P72:~/awb/fsim$ ./acgen_tb/Vacgen_tb ./acgen_tb/Vacgen_tb.vcd ============================== === Start Sim === ============================== ============================== === End Sim === ============================== myskan@TP-P72:~/awb/fsim$
4. Waveform 확인
gatewave 를 이용하여 waveform을 분석 할 수 있습니다.
myskan@TP-P72:~/Work/verilator/awb/fsim/acgen_tb$ gtkwave Vacgen_tb.vcd &
5. 작성된 코드 및 Makefile
'SoC' 카테고리의 다른 글
UPF 1.0, UPF 2.0, UPF 2.1, UPF 3.0, 그리고 UPF 3.1 (0) | 2020.06.22 |
---|---|
프로세서 검증에 대하여 (0) | 2020.05.11 |
Icarus Verilog 를 이용한 function simulation (3) | 2020.04.30 |
CDC(Clock Domain Crossing)의 동기화 기법 (1) | 2019.10.20 |
FIFO Depth 구하기 (데이터의 bandwidth 이해하기) (0) | 2019.05.16 |