Skip to content

punzik/hdl-unit-test-suite

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 

Repository files navigation

UTest

UTest - приложение для одиночного или группового запуска и контроля выполнения тестбенчей на языке Verilog/SystemVerilog. На данный момент реализована поддержка только Icarus Verilog, но в дальнейшем планирую добавить поддержку Verilator и SymbiYosys.

Параметры командной строки

Если вызвать приложение с параметром --help, она выведет текст справки с описанием параметров:

Usage: ./utest.scm [OPTION]... [FILE|PATH]
Run testbenches with recursive search in the PATH, or in the current folder
if PATH is not specified. If argument is a file, testbench is launched from FILE.

Options:
  -k, --keep           Do not delete work directory if test is pass.
  -d, --dump           Force dump waveforms.
  -r, --norestart      Do not restart testbench with waveform dump enabled if
                       test failed (true by default)
  -s, --static         Use static work dir for initial debug purposes
  -n, --nocolor        Do not use color for print log
  -j, --jobs NUM       Use NUM threads for running testbenches. If <=0
                       use as many threads as there are processors in the system.
  -f, --defines        Print useful Verilog defines
  -c, --clean          Delete work folders that have a corresponding makefile.
      --force-clean    Delete all work folders regardless of the presence of a makefile.
  -v, --verbose        Verbose output
  -h, --help           Print this message and exit

При успешном завершении теста программа по удаляет рабочую папку. Запретить это делать можно опцией --keep.

По умолчанию, для ускорения прохождения тестов создание дампов сигналов отключено. При этом, в случае неудачного завершения тест автоматически перезапускается с созданием дампа. Однако, если тест длительный, потеря времени на перезапуск может перекрыть выигрыш от несоздания дампа. Для управления этим поведением в программе есть две опции - --dump и --norestart. Опция --dump заставляет программу делать дампы для всех тестов, как удачных, так и неудачных, что позволяет избежать перезапуска для создания дампа. Опция --no-restart запрещает перезапуск неудачных тестов, что позволяет максимально сэкономить время, но оставляет без дампов.

Чтобы старые рабочие папки не засоряли файловую систему, их можно удалить запуском программы с опцией --clean. Программа удалит все папки, для которых есть сценарий тестбенча. Если файла сценария больше нет, то можно воспользоваться опцией --force-clean.

По умолчанию программа запускает тесты в нескольких потоках, количество которых зависит от числа процессоров в системе. Опцией --jobs можно управлять количеством потоков - от одного и более.

Параметр --verbose управляет количеством информации, которая будет выведена на экран в процессе тестирования. Без неё для успешных тестов будет выведена только важные сообщения. С этой опцией для всех тестов будет показан полный лог вызова компилятора и симулятора, а так же все строки, которые будут выведены тестбенчем. При этом, независимо от этой опции весь вывод тестбенчей будет сохранён в логи в рабочих папках (если указано опция --keep или тест завершился неудачей).

Опция --nocolor отключает раскраску вывода. Это может быть полезно в случае перенаправления вывода в файл.

Опция --defines выводит на экран исходник include-файла с макросами вывода информационных сообщений в тестбенче на Verilog:

`ifndef UTEST_VERILOG_DEFINES
 `define UTEST_VERILOG_DEFINES

// Log level string prefixes for use with $display function.
// Example usage: $display("%sError message", `LOG_ERR);
 `define LOG_INFO "INFO#"
 `define LOG_WARN "WARN#"
 `define LOG_ERR  "FAIL#"

// Dirty hacked redefine of $display function. Must be used with two parentheses.
// Example usage: `log_info(("Information message"));
 `define log_info(msg)  begin $display({`LOG_INFO, $sformatf msg}); end
 `define log_warn(msg)  begin $display({`LOG_WARN, $sformatf msg}); end
 `define log_error(msg) begin $display({`LOG_ERR, $sformatf msg}); end
`endif

Эти макросы можно применять в тестбенче на Verilog для вывода информационных сообщений, в частности для оповещения UTest об ошибке в симуляции. К сожалению, в Icarus Verilog это пока единственная возможность сообщить об ошибке в тесте, т.к. при вызове функций $error и $fatal симулятор возвращает нулевой exit code. В следующей версии авторы обещают исправить это досадное недоразумение.

Сценарии запуска тестбенчей

Программа рекурсивно ищет все файлы с расширением *.utest в папке PATH и использует их в качестве сценариев запуска тестбенчей. Если параметром указать файл, то будет использован только этот файл. Если запустить программу без параметров, она будет искать сценарии в текущей папке.

Сценарии запуска тестбенчей описываются на языке Scheme (а именно Guile, на котором и написана программа), и представляют из себя скрипт, который возвращает функцию (или список функций). Эта функция (функции) будет вызвана в процессе запуска тестов, и в зависимости от результатов её выполнения тест будет помечен как успешный или неуспешный. Функция вызывается в контексте приложения, по этому ей доступны все переменные и функции, объявленные в коде приложения.

Функция возвращает булево значение, и имеет один опциональный аргумент типа symbol. Если функция вызвана без аргументов, она должна выполнить тестбенч и вернуть #true или #false в зависимости от результата его выполнения. Если функции передается агрумент, то она должна вернуть некоторые метаданные в зависимости от значения аргумента, или #false если таких метаданных нет. Сейчас используется два типа метаданных - название теста (агрумент 'name) и описание теста (аргумент 'description).

Для того, чтобы не писать вручную диспетчеризацию аргументов в приложении есть макрос utest/tb, который упрощает описание сценариев:

(utest/tb
 ("Name"
  "First line of testbench description"
  "Second line of testbench description")

 ;; testbench body
 )

После имени макроса в скобках указывается имя тестбенча и произвольное количество строк описания. Если аргументов нет, тестбенч будет помечен как noname. Имя тестбенча используется для именования рабочей папки, при этом пробелы заменяются на подчеркивания, а заглавные буквы на прописные. Желательно не употреблять в имени тестбенча специальные символы и не использовать слишком длинные имена.

После скобочек с именем и описанием следует тело тестбенча. Тело - это любой валидный код на Guile, который будет выполнен в процессе запуска тестбенчей. Результат работы этого кода должно быть булево значение, показывающее успешность выполнения теста. Весь вывод в stdout будет перехвачен и отфильтрован в соответствии со значением флага --verbose и типом выводимого текста.

Для типизации вывода можно использовать функцию utest/log. Первый параметр функции - тип выводимого текста (опциональный), второй - строка формата как в функции format. Возможны три варианта значения типа: 'info, 'warning и 'error. Сообщения всех трёх типов будет выведено на экран вне зависимости от флага --verbose, но если тип не указать, сообщение будет выведено только в режиме --verbose. Независимо от типа сообщения и флага --verbose все сообщения будут сохранены в логе в рабочей папке теста.

Тесты можно собрать в список для запуска нескольких вариантов с разными параметрами, дефайнами, исходниками или другими опциями.

В теле тестбенча в общем случае можно выполнять любые действия, не только запуск симуляции RTL. Но т.к. программа была написана предназначена для симуляции RTL, в ней есть некоторые полезные для этого функции.

Запуск симуляции в Icarus Verilog выполняется с помощью функции utest/run-simulation-iverilog. Функция принимает два обязательных параметра и несколько опциональных:

(utest/run-simulation-iverilog
   sources                              ; List of source files
   top                                  ; Name of the top module

   #:iverilog-executable "iverilog"     ; Icarus Verilog compiler executable path
   #:vvp-executable      "vvp"          ; Icarus Verilog simularot executable path
   #:modpaths            '()            ; iverilog -y
   #:modtypes            '(".v" ".sv")  ; iverilog -Y
   #:includes            '()            ; ivetilog -I
   #:lang                "2012"         ; Language version (1995, 2001, 2005, 2005-sv, 2009, 2012)
   #:parameters          '()            ; Top module parameters (list (list NAME VALUE))
   #:defines             '()            ; Preprocessor defines (list NAME|(list NAME VALUE))
   #:features            '()            ; iverilog -g
   #:separate            #f             ; iverilog -u
   #:plusargs            '()            ; List of plusargs
   #:vpimods             '()            ; iverilog -m, vvp -m
   #:vpipaths            '()            ; iverilog -L, vvp -M
   #:warnings            "all"          ; List of warning classes (iverilog -W...)
   #:dumpformat          'fst           ; Format of dump files. Posibly values: vcd, lxt, lxt2, fst
   #:timeout             '(1 ms)        ; Testbench execution timeout (in simulation time)
   )

Все аргументы, кроме parameters и defines, которые принимают список, так же могут принимать и одиночные значения. В список includes по-умолчанию включена папка с файлом сценария

Функция возвращает #true в случае успешного завершения теста, и #false в случае ошибки. Далее приведен пример использования:

(map
 (lambda (n data-width)
   (utest/tb
    ((format "uart_tx_test~a" n)
     "Testbench for the UART transmitter RTL code"
     (format "DATA_WIDTH = ~a" data-width))

    (utest/log 'info "Example information message")

    ;; Start simulation
    (utest/run-simulation-iverilog
     '("uart_tx.sv" "uart_tx_tb.sv")
     "uart_tx_tb"
     #:includes   "."
     #:parameters `((DATA_WIDTH ,data-width))
     #:defines    '(TESTBENCH)
     #:timeout    '(5 ms))))
 '(1 2 3)
 '(8 16 24))

Сценарий возвращает три теста с разным значением параметра DATA_WIDTH. В случае успешного выполнения на экран будет выведен следующий текст:

output example

В случае неудачного завершения теста тест перезапускается с дампом всех сигналов в файл (это поведение можно отключить опцией --no-restart). Кроме того, в случае ошибки будет выведен полный лог симулятора и его параметры.

Все относительные пути в аргументах функции utest/run-simulation-iverilog считаются относительными папке со сценарием.

Тестбенч Verilog

Тестбенч на Verilog ни чем не отличается от самого обычного тестбенча, кроме того, что он должен сигнализировать об ошибке с помощью вывода информационного сообщения log_error((...)).

Для удобства работы программа предопределяет два макроопределения:

  • UTEST_BASE_DIR - макрос с путём к папке, в которой находится сценарий запуска. Может быть нужен, например для указания на файл с входными данными для теста.
  • UTEST_WORK_DIR - путь ко временной рабочей папке теста. Сюда можно сохранить результаты тестбенча для последующей проверки в коде сценария.
  • UTEST_TESTBENCH - флаг для определения того, что код выполняется в среде UTest (ifdef UTEST_TESTBENCH ...).

Примеры

В папке examples находятся примеры сценариев и тестбенча.

About

Simple HDL (only Verilog for now) unit-test tool

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages