Add examples. Add more info to README
This commit is contained in:
parent
e917908049
commit
8e2514e895
117
README.md
117
README.md
@ -3,7 +3,10 @@ UTest
|
|||||||
|
|
||||||
UTest - приложение для одиночного или группового запуска и контроля выполнения тестбенчей на языке Verilog/SystemVerilog.
|
UTest - приложение для одиночного или группового запуска и контроля выполнения тестбенчей на языке Verilog/SystemVerilog.
|
||||||
На данный момент реализована поддержка только [Icarus Verilog](http://iverilog.icarus.com/), но в дальнейшем
|
На данный момент реализована поддержка только [Icarus Verilog](http://iverilog.icarus.com/), но в дальнейшем
|
||||||
я планирую добавить поддержку [Verilator](https://www.veripool.org/verilator/) и [SymbiYosys](https://github.com/YosysHQ/sby).
|
планирую добавить поддержку [Verilator](https://www.veripool.org/verilator/) и [SymbiYosys](https://github.com/YosysHQ/sby).
|
||||||
|
|
||||||
|
Параметры командной строки
|
||||||
|
--------------------------
|
||||||
|
|
||||||
Если вызвать приложение с параметром `--help`, она выведет текст справки с описанием параметров:
|
Если вызвать приложение с параметром `--help`, она выведет текст справки с описанием параметров:
|
||||||
```
|
```
|
||||||
@ -14,7 +17,7 @@ if PATH is not specified. If argument is a file, testbench is launched from FILE
|
|||||||
Options:
|
Options:
|
||||||
-k, --keep Do not delete work directory if test is pass.
|
-k, --keep Do not delete work directory if test is pass.
|
||||||
-d, --dump Force dump waveforms.
|
-d, --dump Force dump waveforms.
|
||||||
-r, --no-restart Do not restart testbench with waveform dump enabled if
|
-r, --norestart Do not restart testbench with waveform dump enabled if
|
||||||
test failed (true by default)
|
test failed (true by default)
|
||||||
-n, --nocolor Do not use color for print log
|
-n, --nocolor Do not use color for print log
|
||||||
-j, --jobs NUM Use NUM threads for running testbenches. If <=0
|
-j, --jobs NUM Use NUM threads for running testbenches. If <=0
|
||||||
@ -26,22 +29,74 @@ Options:
|
|||||||
-h, --help Print this message and exit
|
-h, --help Print this message and exit
|
||||||
```
|
```
|
||||||
|
|
||||||
Программа рекурсивно ищет все файлы с расширением `*.utest` и использует их в качестве сценариев запуска тестбенчей.
|
При успешном завершении теста программа по удаляет рабочую папку. Запретить это делать можно опцией `--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` и использует их в качестве сценариев запуска
|
||||||
|
тестбенчей. Если параметром указать файл, то будет использован только этот файл. Если запустить программу без параметров,
|
||||||
|
она будет искать сценарии в текущей папке.
|
||||||
|
|
||||||
Сценарии запуска тестбенчей описываются на языке Scheme (а именно [Guile](https://www.gnu.org/software/guile/), на котором
|
Сценарии запуска тестбенчей описываются на языке Scheme (а именно [Guile](https://www.gnu.org/software/guile/), на котором
|
||||||
и написана программа), и представляют из себя скрипт, который возвращает функцию (или список функций). Эта функция
|
и написана программа), и представляют из себя скрипт, который возвращает функцию (или список функций). Эта функция
|
||||||
(функции) будет вызвана в процессе запуска тестов, и в зависимости от результатов её выполнения тест будет помечен как
|
(функции) будет вызвана в процессе запуска тестов, и в зависимости от результатов её выполнения тест будет помечен как
|
||||||
успешный или неуспешный. Функция вызывается в контексте приложения, по этому ёй доступны все переменные и функции,
|
успешный или неуспешный. Функция вызывается в контексте приложения, по этому ей доступны все переменные и функции,
|
||||||
объявленные в коде приложения.
|
объявленные в коде приложения.
|
||||||
|
|
||||||
Функция возвращает булево значение, и имеет один опциональный аргумент типа symbol.
|
Функция возвращает булево значение, и имеет один опциональный аргумент типа symbol.
|
||||||
Если функция вызвана без аргументов, она должна выполнить тестбенч и вернуть `#true` или `#false` в зависимости
|
Если функция вызвана без аргументов, она должна выполнить тестбенч и вернуть `#true` или `#false` в зависимости
|
||||||
от результата его выполнения. Если функции передается агрумент, то она должна вернуть некоторые метаданные в зависимости
|
от результата его выполнения. Если функции передается агрумент, то она должна вернуть некоторые метаданные в зависимости
|
||||||
от значения аргумента, или `#false` если таких метаданных нет. Сейчас использутся два типа метаданных - название теста
|
от значения аргумента, или `#false` если таких метаданных нет. Сейчас используется два типа метаданных - название теста
|
||||||
(агрумент `'name`) и описание теста (аргумент `'description`).
|
(агрумент `'name`) и описание теста (аргумент `'description`).
|
||||||
|
|
||||||
Для того, чтобы не писать вручную диспетчеризацию агрументов в приложении есть макрос `utest/tb`, который упрощает
|
Для того, чтобы не писать вручную диспетчеризацию аргументов в приложении есть макрос `utest/tb`, который упрощает
|
||||||
описание сценариев:
|
описание сценариев:
|
||||||
|
|
||||||
```scheme
|
```scheme
|
||||||
@ -55,7 +110,9 @@ Options:
|
|||||||
```
|
```
|
||||||
|
|
||||||
После имени макроса в скобках указывается имя тестбенча и произвольное количество строк описания. Если аргументов нет,
|
После имени макроса в скобках указывается имя тестбенча и произвольное количество строк описания. Если аргументов нет,
|
||||||
тестбенч будет помечен как `noname`.
|
тестбенч будет помечен как `noname`. Имя тестбенча используется для именования рабочей папки, при этом пробелы заменяются
|
||||||
|
на подчеркивания, а заглавные буквы на прописные. Желательно не употреблять в имени тестбенча специальные символы и не
|
||||||
|
использовать слишком длинные имена.
|
||||||
|
|
||||||
После скобочек с именем и описанием следует тело тестбенча. Тело - это любой валидный код на Guile, который будет выполнен
|
После скобочек с именем и описанием следует тело тестбенча. Тело - это любой валидный код на Guile, который будет выполнен
|
||||||
в процессе запуска тестбенчей. Результат работы этого кода должно быть булево значение, показывающее успешность выполнения
|
в процессе запуска тестбенчей. Результат работы этого кода должно быть булево значение, показывающее успешность выполнения
|
||||||
@ -68,6 +125,12 @@ Options:
|
|||||||
тип не указать, сообщение будет выведено только в режиме `--verbose`. Независимо от типа сообщения и флага `--verbose` все
|
тип не указать, сообщение будет выведено только в режиме `--verbose`. Независимо от типа сообщения и флага `--verbose` все
|
||||||
сообщения будут сохранены в логе в рабочей папке теста.
|
сообщения будут сохранены в логе в рабочей папке теста.
|
||||||
|
|
||||||
|
Тесты можно собрать в список для запуска нескольких вариантов с разными параметрами, дефайнами, исходниками или другими
|
||||||
|
опциями.
|
||||||
|
|
||||||
|
В теле тестбенча в общем случае можно выполнять любые действия, не только запуск симуляции RTL. Но т.к. программа была
|
||||||
|
написана предназначена для симуляции RTL, в ней есть некоторые полезные для этого функции.
|
||||||
|
|
||||||
Запуск симуляции в Icarus Verilog выполняется с помощью функции `utest/run-simulation-iverilog`. Функция принимает два
|
Запуск симуляции в Icarus Verilog выполняется с помощью функции `utest/run-simulation-iverilog`. Функция принимает два
|
||||||
обязательных параметра и несколько опциональных:
|
обязательных параметра и несколько опциональных:
|
||||||
|
|
||||||
@ -96,7 +159,8 @@ Options:
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
*Все агрументы, кроме `parameters` и `defines`, которые принимают список, так же могут принимать и одиночные значения.*
|
*Все аргументы, кроме `parameters` и `defines`, которые принимают список, так же могут принимать и одиночные значения.
|
||||||
|
В список `includes` по-умолчанию включена папка с файлом сценария*
|
||||||
|
|
||||||
Функция возвращает `#true` в случае успешного завершения теста, и `#false` в случае ошибки. Далее приведен пример использования:
|
Функция возвращает `#true` в случае успешного завершения теста, и `#false` в случае ошибки. Далее приведен пример использования:
|
||||||
|
|
||||||
@ -130,27 +194,22 @@ Options:
|
|||||||
В случае неудачного завершения теста тест перезапускается с дампом всех сигналов в файл (это поведение можно отключить
|
В случае неудачного завершения теста тест перезапускается с дампом всех сигналов в файл (это поведение можно отключить
|
||||||
опцией `--no-restart`). Кроме того, в случае ошибки будет выведен полный лог симулятора и его параметры.
|
опцией `--no-restart`). Кроме того, в случае ошибки будет выведен полный лог симулятора и его параметры.
|
||||||
|
|
||||||
Опция `--defines` выводит на экран исходник include-файла с макросами вывода информационных сообщений в тестбенче на Verilog:
|
Все относительные пути в аргументах функции `utest/run-simulation-iverilog` считаются относительными папке со сценарием.
|
||||||
|
|
||||||
```verilog
|
Тестбенч Verilog
|
||||||
`ifndef UTEST_VERILOG_DEFINES
|
----------------
|
||||||
`define UTEST_VERILOG_DEFINES
|
|
||||||
|
|
||||||
// Log level string prefixes for use with $display function.
|
Тестбенч на Verilog ни чем не отличается от самого обычного тестбенча, кроме того, что он должен сигнализировать об ошибке
|
||||||
// Example usage: $display("%sError message", `LOG_ERR);
|
с помощью вывода информационного сообщения `log_error((...))`.
|
||||||
`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
|
|
||||||
```
|
|
||||||
|
|
||||||
С помощью макроса `log_error` можно сообщить в UTest, что во время симуляции произошла ошибка. К сожалению,
|
- `UTEST_BASE_DIR` - макрос с путём к папке, в которой находится сценарий запуска. Может быть нужен, например для указания
|
||||||
в Icarus Verilog это пока единственная возможность сообщить об ошибке в тесте, т.к. при вызове функций `$error`
|
на файл с входными данными для теста.
|
||||||
и `$fatal` симулятор возвращает нулевой exit code. В следующей версии авторы обещают исправить это досадное
|
- `UTEST_WORK_DIR` - путь ко временной рабочей папке теста. Сюда можно сохранить результаты тестбенча для последующей
|
||||||
недоразумение.
|
проверки в коде сценария.
|
||||||
|
|
||||||
|
Примеры
|
||||||
|
-------
|
||||||
|
|
||||||
|
В папке [examples](examples) находятся примеры сценариев и тестбенча.
|
||||||
|
|||||||
37
examples/simple-counter/simple_counter.sv
Normal file
37
examples/simple-counter/simple_counter.sv
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
`timescale 1ps/1ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
module simple_counter #(parameter COUNT = 16,
|
||||||
|
localparam WIDTH = $clog2(COUNT-1)) // <-- ERROR
|
||||||
|
(input wire clock,
|
||||||
|
input wire reset,
|
||||||
|
|
||||||
|
input wire i_inc,
|
||||||
|
input wire i_dec,
|
||||||
|
|
||||||
|
output reg [WIDTH-1:0] o_count);
|
||||||
|
|
||||||
|
logic [WIDTH-1:0] count_next;
|
||||||
|
|
||||||
|
always_comb
|
||||||
|
case ({i_inc, i_dec})
|
||||||
|
2'b01:
|
||||||
|
if (o_count == '0)
|
||||||
|
count_next = WIDTH'(COUNT-1);
|
||||||
|
else
|
||||||
|
count_next = o_count - 1'b1;
|
||||||
|
|
||||||
|
2'b10:
|
||||||
|
if (o_count == WIDTH'(COUNT-1))
|
||||||
|
count_next = '0;
|
||||||
|
else
|
||||||
|
count_next = o_count + 1'b1;
|
||||||
|
|
||||||
|
default: count_next = o_count;
|
||||||
|
endcase
|
||||||
|
|
||||||
|
always_ff @(posedge clock)
|
||||||
|
if (reset) o_count <= '0;
|
||||||
|
else o_count <= count_next;
|
||||||
|
|
||||||
|
endmodule // simple_counter
|
||||||
67
examples/simple-counter/simple_counter_tb.sv
Normal file
67
examples/simple-counter/simple_counter_tb.sv
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
`timescale 1ps/1ps
|
||||||
|
|
||||||
|
`include "utest.vh"
|
||||||
|
|
||||||
|
module simple_counter_tb;
|
||||||
|
logic clock = 1'b0;
|
||||||
|
logic reset = 1'b1;
|
||||||
|
|
||||||
|
always #(10ns/2) clock = ~clock;
|
||||||
|
|
||||||
|
parameter COUNT = 16;
|
||||||
|
parameter ITERATIONS = 100;
|
||||||
|
parameter DIRECTION = 1; // 1 - increment, -1 - decrement, 0 - random
|
||||||
|
|
||||||
|
localparam WIDTH = $clog2(COUNT-1); // <-- ERROR
|
||||||
|
|
||||||
|
logic i_inc;
|
||||||
|
logic i_dec;
|
||||||
|
logic [WIDTH-1:0] o_count;
|
||||||
|
|
||||||
|
simple_counter #(.COUNT(COUNT))
|
||||||
|
DUT (.*);
|
||||||
|
|
||||||
|
int gold_count;
|
||||||
|
|
||||||
|
//// Shows that a `UTEST_BASE_DIR define exists
|
||||||
|
// initial begin
|
||||||
|
// `log_info(("From verilog code. Base dir: %s", `UTEST_BASE_DIR));
|
||||||
|
// end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
i_inc = 1'b0;
|
||||||
|
i_dec = 1'b0;
|
||||||
|
reset = 1'b1;
|
||||||
|
repeat(2) @(posedge clock) #1;
|
||||||
|
|
||||||
|
reset = 1'b0;
|
||||||
|
@(posedge clock) #1;
|
||||||
|
|
||||||
|
gold_count = '0;
|
||||||
|
|
||||||
|
for (int i = 0; i < ITERATIONS; i += 1) begin
|
||||||
|
case (DIRECTION)
|
||||||
|
-1: {i_inc, i_dec} = 2'b01;
|
||||||
|
1: {i_inc, i_dec} = 2'b10;
|
||||||
|
default: {i_inc, i_dec} = 2'($urandom);
|
||||||
|
endcase
|
||||||
|
|
||||||
|
@(posedge clock) #1;
|
||||||
|
|
||||||
|
if (i_inc && !i_dec)
|
||||||
|
gold_count ++;
|
||||||
|
else if (!i_inc && i_dec)
|
||||||
|
gold_count --;
|
||||||
|
|
||||||
|
if (gold_count >= COUNT) gold_count = 0;
|
||||||
|
if (gold_count < 0) gold_count = COUNT-1;
|
||||||
|
|
||||||
|
if (gold_count != int'(o_count))
|
||||||
|
`log_error(("#%0t: Gold count = %0d, DUT count = %0d", $time, gold_count, o_count));
|
||||||
|
end
|
||||||
|
|
||||||
|
repeat(2) @(posedge clock) #1;
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule // simple_counter_tb
|
||||||
44
examples/simple-counter/simple_counter_tb.utest
Normal file
44
examples/simple-counter/simple_counter_tb.utest
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
;; -*- scheme -*-
|
||||||
|
|
||||||
|
;;; Make lists combinations
|
||||||
|
;;; Example: (combinations '(1 2 3) '(a b)) -> '((1 a) (1 b) (2 a) (2 b) (3 a) (3 b))
|
||||||
|
(define (combinations . lists)
|
||||||
|
(cond
|
||||||
|
((null? lists) '())
|
||||||
|
((null? (cdr lists)) (car lists))
|
||||||
|
(else
|
||||||
|
(fold (lambda (comb out)
|
||||||
|
(append out
|
||||||
|
(map (lambda (x)
|
||||||
|
(if (list? comb)
|
||||||
|
(cons x comb)
|
||||||
|
(list x comb)))
|
||||||
|
(car lists))))
|
||||||
|
'() (apply combinations (cdr lists))))))
|
||||||
|
|
||||||
|
;;; Testbenches
|
||||||
|
(map
|
||||||
|
(lambda (l)
|
||||||
|
(let ((count (car l))
|
||||||
|
(direction (cadr l)))
|
||||||
|
(utest/tb
|
||||||
|
((format "c~a_d~a" count direction)
|
||||||
|
"More complex testbench for Simple Counter"
|
||||||
|
(format "COUNT=~a\tDIRECTION=~a" count direction))
|
||||||
|
|
||||||
|
;; Instead of a description, you can display the message in log
|
||||||
|
;; (utest/log 'info "COUNT = ~a" count)
|
||||||
|
|
||||||
|
;; testbench body
|
||||||
|
(utest/run-simulation-iverilog
|
||||||
|
(utest/find-files ".*\\.sv$")
|
||||||
|
"simple_counter_tb"
|
||||||
|
#:parameters `((COUNT ,count)
|
||||||
|
(ITERATIONS ,(* count 3))
|
||||||
|
(DIRECTION ,direction))))))
|
||||||
|
|
||||||
|
(combinations
|
||||||
|
(append '(10 100 1000 16 64 256)
|
||||||
|
(let ((state (seed->random-state 0)))
|
||||||
|
(map (lambda (x) (+ 2 (random 200 state))) (iota 100))))
|
||||||
|
'(1 -1 0)))
|
||||||
12
examples/simple-counter/simple_counter_tb_single.utest
Normal file
12
examples/simple-counter/simple_counter_tb_single.utest
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
;; -*- scheme -*-
|
||||||
|
;; ^^^ this comment tells Emacs to use Scheme mode
|
||||||
|
|
||||||
|
(utest/tb
|
||||||
|
("simple_counter_tb"
|
||||||
|
"Simplest testbench Simple Counter")
|
||||||
|
|
||||||
|
(utest/run-simulation-iverilog
|
||||||
|
;; sources
|
||||||
|
'("simple_counter.sv" "simple_counter_tb.sv")
|
||||||
|
;; top module name
|
||||||
|
"simple_counter_tb"))
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
;; -*- scheme -*-
|
||||||
|
;; ^^^ this comment tells Emacs to use Scheme mode
|
||||||
|
|
||||||
|
(utest/tb
|
||||||
|
("simple_counter_permanent"
|
||||||
|
"Testbench for Simple Counter with permanent work dir")
|
||||||
|
|
||||||
|
;; get base dir and make work dir
|
||||||
|
(let* ((base (utest/base-path))
|
||||||
|
(work (format "~a/work" base)))
|
||||||
|
|
||||||
|
(when (not (file-exists? work))
|
||||||
|
(mkdir work))
|
||||||
|
|
||||||
|
;; parameterize work dir
|
||||||
|
(parameterize
|
||||||
|
((utest/work-path work)
|
||||||
|
(utest/force-dump #t))
|
||||||
|
|
||||||
|
;; testbench body
|
||||||
|
(utest/run-simulation-iverilog
|
||||||
|
;; sources
|
||||||
|
'("simple_counter.sv" "simple_counter_tb.sv")
|
||||||
|
;; top module name
|
||||||
|
"simple_counter_tb"))))
|
||||||
15
examples/simple-counter/utest.vh
Normal file
15
examples/simple-counter/utest.vh
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
`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
|
||||||
Loading…
x
Reference in New Issue
Block a user