Как вернуть скрипту результат симуляции Verilog?

result

Появилась простая задача - нужно из скрипта (batch/Windows или bash/Linux) проанализировать результат симуляции Verilog. Причем желательно, чтобы решение работало с разными симуляторами: icarus и modelsim (или другими). Как это сделать?

Первая мысль, которая пришла в голову - найти системную функцию Verilog, которая возвращает результат в операционную систему.

Честно говоря, я почему-то думал, что системная функция $finish([n]) как раз и принимает параметр, значение которого будет возвращено операционной системе. Но при детальном рассмотрении оказалось, что это не так.

Есть две похожих функции $stop([n]) и finish([n]).
Обе функции принимают необязательный параметр n, который определяет, что будет напечатано при остановке:

  • 0 - без сообщений;
  • 1 - печатается время симуляции и местоположение в коде, то есть номер строки, в которой произошла остановка;
  • 2 - время симуляции, местоположение в коде, занимаемая во время симуляции память и процессорное время.

$finish, в отличии от $stop еще и полностью завершает симуляцию, управление возвращается в вызвавшую симулятор программу или скрипт.

Таким образом оказалось, что системная функция $finish() не подходит для моей задачи. Кроме того, нужно заметить, что в симуляторе icarus vvp параметры к функции $finish похоже вообще игнорируются. Обнаружил, что в икарусе при всем при этом, есть специальная системная функция $finish_and_return(n) - вот эта функция делает как раз то, что мне нужно - возвращает код в операционную систему. К сожалению, modelsim не знает этой функции. Так что пришлось искать другие методы.

Я нашел такое решение: я буду результат симуляции (успешно или не успешно) записывать в текстовый файл, а потом в вызывающем скрипте читать текстовый файл и решать что делать в том или ином случае.

Предположим я собираюсь симулировать счетчик с синхронным сбросом:


module counter(
   input wire nreset,
   input wire clk,
   output wire [7:0]out
);

reg [7:0]cnt;
always @( posedge clk )
  if( !nreset)
    cnt <= 0;
  else
    cnt <= cnt+8'd1;

assign out = cnt;

endmodule


Тестбенч у меня будет вот такой:


`timescale 1ns / 1ps

module tb;
reg nrst=1'b1;
reg clock = 1'b0;

always #5
  clock = ~clock;

wire [7:0]w_out;
counter inst(
    .nreset( nrst ),
    .clk( clock ),
    .out( w_out )
);

integer f;
reg [128*8-1:0]msg;
task do_finish;
  input [7:0]code;
begin
  f = $fopen("result.txt");
  if( code==0 )
    $fdisplay(f, "GOOD");
  else
    $fdisplay(f, "BAD %d",code);
  $fclose(f);
  $finish;
end
endtask

integer i,j,k;
initial
begin
//$dumpfile("out.vcd");
//$dumpvars(0,tb);

k=0;
nrst = 1'b0;
#100;
nrst =1'b1;

j=220;
//j=260;
$display("lets wait for %d",j*10);
for(i=0; i<j; i=i+1)
    #10;
k=1;

//report good result
do_finish(0);
end

always @w_out
begin
  //report bad result
  if(w_out==255)
    do_finish(1);
end

endmodule


Пример правда довольно примитивный и искуственный. Этот тестбенч запускает счетчик и ждет некоторое время (явно задано в переменной j=220). Если за это время счетчик не успеет досчитать до 255, то считается, что тест пройден и вызывается задача do_finish(0), где параметр 0 - признак успеха.

Ниже блок always @w_out постоянно мониторит состояние выхода w_out. Если внезапно он станет 255, то считается, что тест провален и вызывается do_finish(1). Здесь единица в аргументе - признак неуспеха.

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

Возвращаемое из симуляции значение передается в задачу do_finish( code );
Эта задача открывает текстовый файл result.txt и пишет туда в зависимости от входного параметра строку "GOOD" или "BAD" с кодом ошибки.

Теперь отстается написать BAT файл для запуска симулятора.
Если использовать симулятор icarus verilog, то run_ivl_test.bat файл может выглядеть вот так:


del result.txt
set SimResult=
iverilog -o qqq tb.v counter.v
vvp qqq
set /p SimResult=<result.txt
echo %SimResult%
IF "%SimResult%" == "GOOD" GOTO :GOOD
echo Test Failed
GOTO :END
:GOOD
echo Test Passed
:END

Перед запуском симулятора на всякий случай удаляю файл result.txt и очищяю переменную окружения SimResult. Потом компилирую верилоговские исходники с помощью iverilog и далее запускаю симулятор vvp.
Ну и в завершение скрипта читаю вновь созданный файл result.txt и в зависимости от его содержимого BAT файл исполняет то или иное действие. Здесь он просто выводит текстовое сообщение. А в принципе может например, посылать e-mail об успешном или проваленном тесте.

Для моделсим все примерно так же. Вот бат файл для моделсим:


del result.txt
set SimResult=
vsim -c -do test.do
set /p SimResult=<result.txt
echo %SimResult%
IF "%SimResult%" == "GOOD" GOTO :GOOD
echo Test Failed
GOTO :END
:GOOD
echo Test Passed
:END

Здесь все точно так же, как и в случае с icarus verilog, только моделсим вызывается командой vsim и получает список команд симулятора в отдельном файле test.do. Файл test.do выглядит вот так:


transcript on
vlib my_work
vlog -work my_work counter.v
vlog -work my_work tb.v
vsim my_work.tb
run -all

Команда transcript on - включает режим эхо, вывод исполняемых команд в консоль.
Команда vlib определяет имя библиотеки в которую будут компилироваться мои Verilog файлы из моего проекта.
Команда vlog компилирует Verilog файл в указанную библиотеку. Может компилировать SystemVerilog файлы, если у файлов расширение .sv или если указана опция компилятора -sv.
Команда vsim принимает имя топ модуля из библиотеки, тот модуль который будет симулироваться.
Ну и последняя команда run -all говорит провести симуляцию от начала до конца.

На самом деле у симулятора ModelSim довольно развитая система команд. Полное руководство можно найти например, здесь.

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

Вот например, как выглядит вывод при запуске симуляции моделсим:


d:\altera\prb>run_mdls_test.bat

d:\altera\prb>del result.txt

d:\altera\prb>set SimResult=

d:\altera\prb>vsim -c -do test.do
Reading D:/altera/16.1/modelsim_ase/tcl/vsim/pref.tcl

# 10.5b

# do test.do
# vlib my_work
# ** Warning: (vlib-34) Library already exists at "my_work".
# vlog -work my_work counter.v
# Model Technology ModelSim - Intel FPGA Edition vlog 10.5b Compiler 2016.10 Oct 5 2016
# Start time: 20:08:17 on Sep 10,2018
# vlog -work my_work counter.v
# -- Compiling module counter
#
# Top level modules:
# counter
# End time: 20:08:17 on Sep 10,2018, Elapsed time: 0:00:00
# Errors: 0, Warnings: 0
# vlog -work my_work tb.v
# Model Technology ModelSim - Intel FPGA Edition vlog 10.5b Compiler 2016.10 Oct 5 2016
# Start time: 20:08:17 on Sep 10,2018
# vlog -work my_work tb.v
# -- Compiling module tb
#
# Top level modules:
# tb
# End time: 20:08:17 on Sep 10,2018, Elapsed time: 0:00:00
# Errors: 0, Warnings: 0
# vsim my_work.tb
# vsim my_work.tb
# Start time: 20:08:18 on Sep 10,2018
# Loading my_work.tb
# Loading my_work.counter
# run -all
# lets wait for 2200
# ** Note: $finish : tb.v(29)
# Time: 2300 ns Iteration: 0 Instance: /tb
# End time: 20:08:18 on Sep 10,2018, Elapsed time: 0:00:00
# Errors: 0, Warnings: 0

d:\altera\prb>set /p SimResult= 0<result.txt

d:\altera\prb>echo GOOD
GOOD

d:\altera\prb>IF "GOOD" == "GOOD" GOTO :GOOD

d:\altera\prb>echo Test Passed
Test Passed
d:\altera\prb>


А вот здесь вывод при использовании icarus verilog:


d:\altera\prb>run_ivl_test.bat

d:\altera\prb>del result.txt

d:\altera\prb>set SimResult=

d:\altera\prb>iverilog -o qqq tb.v counter.v

d:\altera\prb>vvp qqq
lets wait for 2200

d:\altera\prb>set /p SimResult= 0<result.txt

d:\altera\prb>echo GOOD
GOOD

d:\altera\prb>IF "GOOD" == "GOOD" GOTO :GOOD

d:\altera\prb>echo Test Passed
Test Passed
d:\altera\prb>


Итоговое сообщение Test Passed печатает уже BAT файл.

Для чего это все нужно? Это нужно для автоматизации проектирования. Например, несколько программистов пишут код Verilog и вносят его в репозиторий GIT. Можно сделать так, что после каждого комита автоматически будет вызываться симулятор и будет проверять правильность исполнения тестов. По результатам исполнения тестов программисты могут получать уведомления на почту в случае если тест не прошел.

 

Добавить комментарий