FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

cocotbを試す(2.自分のデザインで実験)

cocotbの導入が完了したので、次は自分のデザインに適用してみよう。

github.com

ユニットif_unitに、単体テストを実施してみよう。 まずは、リセット直後にAXIチャネルIF_MARVALIDがアサートされることをチェックしてみよう。

TOPLEVEL := if_unit
TOPLEVEL_LANG ?= verilog

PWD=$(shell pwd)
# COCOTB=$(PWD)/../../..
COCOTB=/home/masayuki/work/cocotb

ifeq ($(OS),Msys)
WPWD=$(shell sh -c 'pwd -W')
PYTHONPATH := $(WPWD)/../model;$(PYTHONPATH)
else
WPWD=$(shell pwd)
PYTHONPATH := $(WPWD)/../model:$(PYTHONPATH)
endif
export PYTHONPATH

COMPILE_ARGS = -I$(WPWD)/../ -I$(WPWD)/../pulsar2_core/ -D SIMULATION

VERILOG_SOURCES = $(WPWD)/../pulsar2_core/if_unit.v $(WPWD)/../pulsar2_core/ic_unit.v
GPI_IMPL := vpi

export TOPLEVEL_LANG

MODULE ?= test_if_unit

include $(COCOTB)/makefiles/Makefile.inc
include $(COCOTB)/makefiles/Makefile.sim

MODULE/TOPLEVEL/COMPILE_ARGS/VERILOG_SOURCESを指定している。 VERILOG_SOURCESは通常通りVerilogファイルを指定すれば良いが、例えばヘッダファイルなどのインクルードディレクトリを指定したいときは、COMPILE_ARGSを指定する。

COMPILE_ARGS = -I$(WPWD)/../ -I$(WPWD)/../pulsar2_core/ -D SIMULATION

次に、テストパタンをPythonで書いてみよう。./test/test_if_unit.py

clock_period = 100

@cocotb.test()
def test_if_unit (dut):
    """ Test for AXI fetch after Reset """

    cocotb.fork(clock_gen(dut.CPU_CLK, period=clock_period))

    dut.CPU_RESET <= 1
    dut.EXPIN_PC_INIT <= 0xbfc00000

    yield RisingEdge(dut.CPU_CLK)
    yield RisingEdge(dut.CPU_CLK)
    dut.CPU_RESET <= 0

    yield Timer(1000)

    if int(dut.IF_MARVALID) != 1:
        raise TestFailure ("After 10-cycle later, IF_MARVALID is not asserted, IF_MARVALID=%d" % dut.IF_MARVALID)
    else:
        dut.log.info("Ok!")

@cocotb.coroutine
def clock_gen(signal, period=10000):
    while True:
        signal <= 0
        yield Timer(period/2)
        signal <= 1
        yield Timer(period/2)

dut.CPU_RESETでリセット端子を操作しており、dut.CPU_CLKがクロックに相当する。 Pythonの記述は良く分からないが、

    cocotb.fork(clock_gen(dut.CPU_CLK, period=clock_period))

がクロックを生成しているものと思われる。

    clock_period = 100

    yield Timer(1000)

    if int(dut.IF_MARVALID) != 1:
        raise TestFailure ("After 10-cycle later, IF_MARVALID is not asserted, IF_MARVALID=%d" % dut.IF_MARVALID)
    else:
        dut.log.info("Ok!")

リセットが解除されてから10サイクル後にdut.IF_MARVALIDをチェックしている。今回はスレーブを付けていないので、MARVALIDは立ちっぱなしのはずだ。

makeを叩けば、実行できる。

$ make
make results.xml
make[1]: ディレクトリ `/home/masayuki/work/pulsar-2/design/tests' に入ります
mkdir -p sim_build
iverilog -o sim_build/sim.vvp -D COCOTB_SIM=1 -I/home/masayuki/work/pulsar-2/design/tests/../ -I/home/masayuki/work/pulsar-2/design/tests/../pulsar2_core/ -D SIMULATION  /home/masayuki/work/pulsar-2/design/tests/../pulsar2_core/if_unit.v /home/masayuki/work/pulsar-2/design/tests/../pulsar2_core/ic_unit.v
PYTHONPATH=/home/masayuki/work/cocotb/build/libs/x86_64:/home/masayuki/work/cocotb:/home/masayuki/work/pulsar-2/design/tests:/home/masayuki/work/pulsar-2/design/tests/../model:/home/masayuki/work/pulsar-2/design/tests/../model: LD_LIBRARY_PATH=/home/masayuki/work/cocotb/build/libs/x86_64::/usr/lib:/usr/lib:/usr/lib:/usr/lib MODULE=test_if_unit \
        TESTCASE= TOPLEVEL=if_unit \
        vvp -M /home/masayuki/work/cocotb/build/libs/x86_64 -m gpivpi sim_build/sim.vvp   
     -.--ns INFO     cocotb.gpi                                GpiCommon.cpp:47   in gpi_print_registered_impl       VPI registered
     0.00ns INFO     cocotb.gpi                                  gpi_embed.c:229  in embed_sim_init                  Running on Icarus Verilog version 0.10.0 (devel)
     0.00ns INFO     cocotb.gpi                                  gpi_embed.c:230  in embed_sim_init                  Python interpreter initialised and cocotb loaded!
     0.00ns INFO     cocotb.gpi                                  __init__.py:103  in _initialise_testbench           Running tests with Cocotb v1.0 from /home/masayuki/work/cocotb
     0.00ns INFO     cocotb.gpi                                  __init__.py:119  in _initialise_testbench           Seeding Python random module with 1435502701
     0.00ns INFO     cocotb.regression                         regression.py:153  in initialise                      Found test test_if_unit.test_if_unit
     0.00ns INFO     cocotb.regression                         regression.py:254  in execute                         Running test 1/1: test_if_unit
     0.00ns INFO     ..utine.test_if_unit.0x2ad7eeeab450       decorators.py:186  in send                            Starting test: "test_if_unit"
                                                                                                                               Description:  Test for AXI fetch after Reset 
VCD info: dumpfile if_unit.vcd opened for output.
     1.15ns INFO     cocotb.if_unit                          test_if_unit.py:28   in test_if_unit                    Ok!
     1.15ns INFO     cocotb.regression                         regression.py:201  in handle_result                   Test Passed: test_if_unit
     1.15ns INFO     cocotb.regression                         regression.py:162  in tear_down                       Passed 1 tests (0 skipped)
     1.15ns INFO     cocotb.regression                         regression.py:168  in tear_down                       Shutting down...
make[1]: ディレクトリ `/home/masayuki/work/pulsar-2/design/tests' から出ます