2022-07-07 19:59:51 +03:00
|
|
|
|
UTest
|
|
|
|
|
|
=====
|
|
|
|
|
|
|
|
|
|
|
|
UTest - приложение для одиночного или группового запуска и контроля выполнения тестбенчей на языке Verilog/SystemVerilog.
|
|
|
|
|
|
На данный момент реализована поддержка только [Icarus Verilog](http://iverilog.icarus.com/), но в дальнейшем
|
2022-07-09 12:34:40 +03:00
|
|
|
|
планирую добавить поддержку [Verilator](https://www.veripool.org/verilator/) и [SymbiYosys](https://github.com/YosysHQ/sby).
|
|
|
|
|
|
|
|
|
|
|
|
Параметры командной строки
|
|
|
|
|
|
--------------------------
|
2022-07-07 19:59:51 +03:00
|
|
|
|
|
|
|
|
|
|
Если вызвать приложение с параметром `--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.
|
2022-07-09 12:34:40 +03:00
|
|
|
|
-r, --norestart Do not restart testbench with waveform dump enabled if
|
2022-07-07 19:59:51 +03:00
|
|
|
|
test failed (true by default)
|
2022-08-09 09:50:11 +03:00
|
|
|
|
-s, --static Use static work dir for initial debug purposes
|
2022-07-07 19:59:51 +03:00
|
|
|
|
-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
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2022-07-09 12:34:40 +03:00
|
|
|
|
При успешном завершении теста программа по удаляет рабочую папку. Запретить это делать можно опцией `--keep`.
|
|
|
|
|
|
|
|
|
|
|
|
По умолчанию, для ускорения прохождения тестов создание дампов сигналов отключено. При этом, в случае неудачного
|
|
|
|
|
|
завершения тест автоматически перезапускается с созданием дампа. Однако, если тест длительный, потеря времени на
|
|
|
|
|
|
перезапуск может перекрыть выигрыш от несоздания дампа. Для управления этим поведением в программе есть две
|
|
|
|
|
|
опции - `--dump` и `--norestart`. Опция `--dump` заставляет программу делать дампы для всех тестов, как удачных, так
|
|
|
|
|
|
и неудачных, что позволяет избежать перезапуска для создания дампа. Опция `--no-restart` запрещает перезапуск неудачных
|
|
|
|
|
|
тестов, что позволяет максимально сэкономить время, но оставляет без дампов.
|
|
|
|
|
|
|
|
|
|
|
|
Чтобы старые рабочие папки не засоряли файловую систему, их можно удалить запуском программы с опцией `--clean`.
|
|
|
|
|
|
Программа удалит все папки, для которых есть сценарий тестбенча. Если файла сценария больше нет, то можно воспользоваться
|
|
|
|
|
|
опцией `--force-clean`.
|
|
|
|
|
|
|
|
|
|
|
|
По умолчанию программа запускает тесты в нескольких потоках, количество которых зависит от числа процессоров в системе.
|
|
|
|
|
|
Опцией `--jobs` можно управлять количеством потоков - от одного и более.
|
|
|
|
|
|
|
|
|
|
|
|
Параметр `--verbose` управляет количеством информации, которая будет выведена на экран в процессе тестирования. Без неё
|
|
|
|
|
|
для успешных тестов будет выведена только важные сообщения. С этой опцией для всех тестов будет показан полный лог
|
|
|
|
|
|
вызова компилятора и симулятора, а так же все строки, которые будут выведены тестбенчем. При этом, независимо от этой опции
|
|
|
|
|
|
весь вывод тестбенчей будет сохранён в логи в рабочих папках (если указано опция `--keep` или тест завершился неудачей).
|
|
|
|
|
|
|
|
|
|
|
|
Опция `--nocolor` отключает раскраску вывода. Это может быть полезно в случае перенаправления вывода в файл.
|
|
|
|
|
|
|
|
|
|
|
|
Опция `--defines` выводит на экран исходник include-файла с макросами вывода информационных сообщений в тестбенче на Verilog:
|
|
|
|
|
|
|
|
|
|
|
|
```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` и использует их в качестве сценариев запуска
|
|
|
|
|
|
тестбенчей. Если параметром указать файл, то будет использован только этот файл. Если запустить программу без параметров,
|
|
|
|
|
|
она будет искать сценарии в текущей папке.
|
2022-07-07 19:59:51 +03:00
|
|
|
|
|
|
|
|
|
|
Сценарии запуска тестбенчей описываются на языке Scheme (а именно [Guile](https://www.gnu.org/software/guile/), на котором
|
|
|
|
|
|
и написана программа), и представляют из себя скрипт, который возвращает функцию (или список функций). Эта функция
|
|
|
|
|
|
(функции) будет вызвана в процессе запуска тестов, и в зависимости от результатов её выполнения тест будет помечен как
|
2022-07-09 12:34:40 +03:00
|
|
|
|
успешный или неуспешный. Функция вызывается в контексте приложения, по этому ей доступны все переменные и функции,
|
2022-07-07 19:59:51 +03:00
|
|
|
|
объявленные в коде приложения.
|
|
|
|
|
|
|
|
|
|
|
|
Функция возвращает булево значение, и имеет один опциональный аргумент типа symbol.
|
|
|
|
|
|
Если функция вызвана без аргументов, она должна выполнить тестбенч и вернуть `#true` или `#false` в зависимости
|
|
|
|
|
|
от результата его выполнения. Если функции передается агрумент, то она должна вернуть некоторые метаданные в зависимости
|
2022-07-09 12:34:40 +03:00
|
|
|
|
от значения аргумента, или `#false` если таких метаданных нет. Сейчас используется два типа метаданных - название теста
|
2022-07-07 19:59:51 +03:00
|
|
|
|
(агрумент `'name`) и описание теста (аргумент `'description`).
|
|
|
|
|
|
|
2022-07-09 12:34:40 +03:00
|
|
|
|
Для того, чтобы не писать вручную диспетчеризацию аргументов в приложении есть макрос `utest/tb`, который упрощает
|
2022-07-07 19:59:51 +03:00
|
|
|
|
описание сценариев:
|
|
|
|
|
|
|
|
|
|
|
|
```scheme
|
|
|
|
|
|
(utest/tb
|
|
|
|
|
|
("Name"
|
|
|
|
|
|
"First line of testbench description"
|
|
|
|
|
|
"Second line of testbench description")
|
|
|
|
|
|
|
|
|
|
|
|
;; testbench body
|
|
|
|
|
|
)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
После имени макроса в скобках указывается имя тестбенча и произвольное количество строк описания. Если аргументов нет,
|
2022-07-09 12:34:40 +03:00
|
|
|
|
тестбенч будет помечен как `noname`. Имя тестбенча используется для именования рабочей папки, при этом пробелы заменяются
|
|
|
|
|
|
на подчеркивания, а заглавные буквы на прописные. Желательно не употреблять в имени тестбенча специальные символы и не
|
|
|
|
|
|
использовать слишком длинные имена.
|
2022-07-07 19:59:51 +03:00
|
|
|
|
|
|
|
|
|
|
После скобочек с именем и описанием следует тело тестбенча. Тело - это любой валидный код на Guile, который будет выполнен
|
|
|
|
|
|
в процессе запуска тестбенчей. Результат работы этого кода должно быть булево значение, показывающее успешность выполнения
|
|
|
|
|
|
теста. Весь вывод в `stdout` будет перехвачен и отфильтрован в соответствии со значением флага `--verbose` и типом
|
|
|
|
|
|
выводимого текста.
|
|
|
|
|
|
|
|
|
|
|
|
Для типизации вывода можно использовать функцию `utest/log`. Первый параметр функции - тип выводимого
|
|
|
|
|
|
текста (опциональный), второй - строка формата как в функции `format`. Возможны три варианта значения типа: `'info`,
|
|
|
|
|
|
`'warning` и `'error`. Сообщения всех трёх типов будет выведено на экран вне зависимости от флага `--verbose`, но если
|
|
|
|
|
|
тип не указать, сообщение будет выведено только в режиме `--verbose`. Независимо от типа сообщения и флага `--verbose` все
|
|
|
|
|
|
сообщения будут сохранены в логе в рабочей папке теста.
|
|
|
|
|
|
|
2022-07-09 12:34:40 +03:00
|
|
|
|
Тесты можно собрать в список для запуска нескольких вариантов с разными параметрами, дефайнами, исходниками или другими
|
|
|
|
|
|
опциями.
|
|
|
|
|
|
|
|
|
|
|
|
В теле тестбенча в общем случае можно выполнять любые действия, не только запуск симуляции RTL. Но т.к. программа была
|
|
|
|
|
|
написана предназначена для симуляции RTL, в ней есть некоторые полезные для этого функции.
|
|
|
|
|
|
|
2022-07-07 19:59:51 +03:00
|
|
|
|
Запуск симуляции в Icarus Verilog выполняется с помощью функции `utest/run-simulation-iverilog`. Функция принимает два
|
|
|
|
|
|
обязательных параметра и несколько опциональных:
|
|
|
|
|
|
|
|
|
|
|
|
```scheme
|
|
|
|
|
|
(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)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2022-07-09 12:34:40 +03:00
|
|
|
|
*Все аргументы, кроме `parameters` и `defines`, которые принимают список, так же могут принимать и одиночные значения.
|
|
|
|
|
|
В список `includes` по-умолчанию включена папка с файлом сценария*
|
2022-07-07 19:59:51 +03:00
|
|
|
|
|
|
|
|
|
|
Функция возвращает `#true` в случае успешного завершения теста, и `#false` в случае ошибки. Далее приведен пример использования:
|
|
|
|
|
|
|
|
|
|
|
|
```scheme
|
|
|
|
|
|
(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. В случае успешного выполнения на экран будет выведен
|
|
|
|
|
|
следующий текст:
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
В случае неудачного завершения теста тест перезапускается с дампом всех сигналов в файл (это поведение можно отключить
|
|
|
|
|
|
опцией `--no-restart`). Кроме того, в случае ошибки будет выведен полный лог симулятора и его параметры.
|
|
|
|
|
|
|
2022-07-09 12:34:40 +03:00
|
|
|
|
Все относительные пути в аргументах функции `utest/run-simulation-iverilog` считаются относительными папке со сценарием.
|
2022-07-07 19:59:51 +03:00
|
|
|
|
|
2022-07-09 12:34:40 +03:00
|
|
|
|
Тестбенч Verilog
|
|
|
|
|
|
----------------
|
2022-07-07 19:59:51 +03:00
|
|
|
|
|
2022-07-09 12:34:40 +03:00
|
|
|
|
Тестбенч на Verilog ни чем не отличается от самого обычного тестбенча, кроме того, что он должен сигнализировать об ошибке
|
|
|
|
|
|
с помощью вывода информационного сообщения `log_error((...))`.
|
2022-07-07 19:59:51 +03:00
|
|
|
|
|
2022-07-09 12:34:40 +03:00
|
|
|
|
Для удобства работы программа предопределяет два макроопределения:
|
|
|
|
|
|
|
|
|
|
|
|
- `UTEST_BASE_DIR` - макрос с путём к папке, в которой находится сценарий запуска. Может быть нужен, например для указания
|
|
|
|
|
|
на файл с входными данными для теста.
|
|
|
|
|
|
- `UTEST_WORK_DIR` - путь ко временной рабочей папке теста. Сюда можно сохранить результаты тестбенча для последующей
|
|
|
|
|
|
проверки в коде сценария.
|
2022-09-13 15:52:01 +03:00
|
|
|
|
- `UTEST_TESTBENCH` - флаг для определения того, что код выполняется в среде UTest (`ifdef UTEST_TESTBENCH ...`).
|
2022-07-09 12:34:40 +03:00
|
|
|
|
|
|
|
|
|
|
Примеры
|
|
|
|
|
|
-------
|
2022-07-07 19:59:51 +03:00
|
|
|
|
|
2022-07-09 12:34:40 +03:00
|
|
|
|
В папке [examples](examples) находятся примеры сценариев и тестбенча.
|