В данной статье будут описаны установка и применение бесплатного ПО для моделирования схем цифровой логики на языке Verilog как альтернативы коммерческих продуктов Incisve от компании Cadense и ModelSim от компании MentorGraphics. Сравнение моделирования в ModelSim и Verilator. Так же будет рассмотрена универсальная методолгия верификации — UVM.
Установка ПО для SystemC UVM
1. Верилятор
Одним из языков описания аппаратуры является verilog. На этом языке можно написать модуль.
Например, есть схема счетика:
Его код будет выглядеть так:
reg [3:0]counter;
always @(posedge clk or posedge reset)
if(reset)
counter <= 4'd0;
else
counter <= counter + 1'd1;
После симуляции получим вейвформы:
Видно, что по фронту тактовой частоты в регистры счетчика будет записываться очередное значение, на единицу большее, чем предыдущее.
Написанный модуль может иметь и более сложную структуру, проверить все состояния которого вручную будет сложно. Нам понадобится автоматизированное тестирование. Для этого необходимо разработать тестовое окружение на одном из языков программирования. Тестовое окружение даст нам возможность провести полную функциональную проверку устройства.
Для тестирование кода проекта помимо таких языков как Verilog, SystemVerilog, Python (для написания моделей), можно использовать язык SystemC. SystemC — язык проектирования и верификации моделей системного уровня, реализованный в виде C++ библиотеки с открытым исходным кодом.
Один из способов верификации Verilog модулей с помощью SystemC является трансляция verilog файлов в С++. Поможет нам в этом Verilator.
Verilator — это самый быстрый бесплатный симулятор Verilog HDL, который превосходит большинство коммерческих симуляторов. Verilator компилирует синтезируемый SystemVerilog (обычно это не код тестового стенда), а также некоторые утверждения SystemVerilog и Synthesis в однопоточный или многопоточный код C ++ или SystemC. Verilator был разработан для больших проектов, где быстродействие симуляции имеет первостепенное значение, и особенно хорошо подходит для генерации исполняемых моделей процессоров для групп разработчиков встроенного программного обеспечения. Verilator используется для имитации многих очень больших многомиллионных конструкций шлюзов с тысячами модулей и поддерживается многими поставщиками IP-технологий, включая IP от Arm и всех известных поставщиков RISC-V IP.
Verilator, возможно, не лучший выбор, если вы ожидаете полнофункциональную замену NC-Verilog, VCS или другого коммерческого симулятора Verilog, или поведенческого симулятора Verilog для очень маленького проекта. Однако, если вы Ищите путь для переноса синтезируемого Verilog на C ++ или SystemC, и ваша команда может свободно писать только код на C ++, это бесплатный компилятор Verilog для Вас.
Для установки последней версии на Ubuntu: качаем архив по ссылке с официального сайта.
Устанавливаем:
#sudo apt-get install make autoconf g++ flex bison # Prerequisites
unsetenv VERILATOR_ROOT # For csh; ignore error if on bash
unset VERILATOR_ROOT # For bash
tar xvzf verilator*.t*gz
cd verilator*
./configure
make
sudo make install
2. GTK Wave
GTKWave является полнофункциональным средством просмотра вейвформ а так же позволяет конвертировать файлы из формата vcd в формат fst, более удобный и быстрый.
Устанавливаем:
sudo apt-get install gtkwave
3. SYSTEMC
Язык проектирования и верификации моделей системного уровня, реализованный в виде C++ библиотеки с открытым исходным кодом.
Как уже говорилось ранее, verilator поддерживает systemc, поэтому нужно создать проект, в котором тестбенч будет описан на systemc, а исходные файлы на синтезируемом verilog. Для этого нам понадобятся библиотеки для компилятора g++, которые предоставляет компания Accelera. Accellera Systems Initiative — это независимая некоммерческая организация, занимающаяся созданием, поддержкой, продвижением и продвижением стандартов проектирования, моделирования и верификации на уровне системы для использования во всемирной электронной промышленности.
Скачиваем архив:
http://accellera.org/images/downloads/standards/systemc/systemc-2.3.1a.tar.gz
Устанавливаем:
tar -xvf systemc-2.3.1a.tar.gz
cd sytemc-2.3.1a
mkdir objdir
sudo ./configure --prefix=/usr/local/systemc-2.3.1a/
sudo make
sudo make install
cd ../
4. UVM для SYSTEMC
В данной статье будет рассмотрен проект, в котором реализована средства верификации UVM. Верификация — это подтверждение соответствия конечного продукта предопределённым эталонным требованиям. Одним их инструментов верификации могут быть тесты. Для того чтобы запустить тестовые последовательности на моделях реальных устройств на уровне RTL описания необходимо разработать тестовое окружение.
UVM — (Universal Verification Methodology) универсальная методология верификации, стандарт, позволяющий эффективно разрабатывать и повторно использовать окружающую среду проверки IP-блоков. UVM — это методология верификации в задачи которой входит организация эффективного окружения вокруг тестируемого блока. Ее преимущества:
п
- онятная структура в виде выделенных блоков решающих конкретные
- задачи;
- возможность повторного использования блоков в последующих проектах;
- максимально возможная автоматизация верификации;
- максимально полная отчётная информация позволяющая при появлении ошибки максимально быстро и точно выявить её причины и предложить пути решения.
Методологии UVM состоят из двух частей: набора правил построения тестового окружения и библиотеки заготовок блоков для верификации, например, генератор текстов, сборщик статистики и т.д. Главным достоинством UVM является универсальность и совместимость со сторонними окружениями.
Так как systemc поддерживает методологию UVM, перейдем к установке необходимых библиотек.
Скачиваем архив:
https://www.accellera.org/images/downloads/drafts-review/uvm-systemc-1.0-beta2.tar.gz
Устанавливаем:
tar -xvf uvm-systemc-1.0-beta2.tar.gz
cd uvm-systemc-1.0-beta2/
mkdir objdir
sudo ./configure --prefix=/usr/local/systemc_uvm/ --with-systemc=/usr/local/systemc-2.3.1a
sudo make
sudo make install
Создаем альянс:
sudo mkdir /usr/local/uvm_systemc_aliance
Копируем в эту папку содержимое папок /usr/local/uvm_systemc_aliance/ и /usr/local/systemc-2.3.1/
Скачиваем готовый проект по ссылке:
https://github.com/paprikun/SYSTEMC/
Открываем папку verilator examples.
В папке rtl лежит описание устройства. В данном примере это ШИМ контроллер.
В папке sim makefile файл для сборки проекта.
В папке tb код для верилятора. В папке tb/uvm приведен пример uvm окружения. Файл main является входной точкой в тестировании, соединияет тестируемое устройство с uvm окружением.
Пробуем собрать проект из папки sim командой make all. Видим ошибку:
/usr/local/uvm_systemc_aliance//include/systemc.h:120:16: error: ‘std::gets’ has not been declared
using std::gets;
Исправляем заменой строки 120:
#if defined(__cplusplus) && (__cplusplus < 201103L)
using std::gets;
#endif
Еще раз пробуем запустить тестбенч и натыкаемся на warning:
/usr/local/uvm_systemc_aliance//include/sysc/packages/boost/get_pointer.hpp:21:40: warning: ‘template<class> class std::auto_ptr’ is deprecated [-Wdeprecated-declarations]
template<class T> T * get_pointer(std::auto_ptr<T> const& p)
Меняем auto_ptr на unique_ptr.
Сборка проекта и симуляция
Теперь когда библиотеки установлены и исправны собираем проект: make all. В папке sim должен появится исполнительный файл simu. Это объект, созданный компилятором. Запускаем его командой ./simu. Должно появится следующее:
SystemC 2.3.1-Accellera --- Jun 28 2019 11:39:29
Copyright (c) 1996-2014 by all Contributors,
ALL RIGHTS RESERVED
Universal Verification Methodology for SystemC (UVM-SystemC)
Version: 1.0-beta2 Date: 2018-10-24
Copyright (c) 2006 - 2018 by all Contributors
See NOTICE file for all Contributors
ALL RIGHTS RESERVED
Licensed under the Apache License, Version 2.0
UVM_INFO @ 0 s: reporter [RNTST] Running test ...
simulation real time = 9 sec
UVM_INFO uvm_default_report_server.cpp(666) @ 179490249010 ps: reporter [UVM/REPORT/SERVER]
--- UVM Report Summary ---
** Report counts by severity
UVM_INFO : 1
UVM_WARNING : 0
UVM_ERROR : 0
UVM_FATAL : 0
** Report counts by id
[RNTST] 1
UVM_INFO @ 179490249010 ps: reporter [FINISH] UVM-SystemC phasing completed; simulation finished
Когда завершится симуляция запись wafeform закончится. Файл simu.vcd можно открыть программой gtkwave:
Для отображения сигналов слева выбираем SystemC, далее зажав Shift выбираем любые сигналы, и жмем Append. В панели инструментов при наведении курсора появляются подсказки. Скрол мыши работает, нужно зажать shift или cntrl.
Так же есть способы конвертировать этот файл в другой, меньшего размера.
Если есть modelsim сделаем конвертацию. В терминале введем команду vsim. В терминале modelsim:
vcd2wlf simu.vcd simu.wlf
Или с помощью gtkwave в терминале linux:
vcd2lxt simu.vcd simu.lxt
vcd2lxt2 simu.vcd simu.lxt2
Для сравнения времени моделирования был создан похожий проект, но уже для Modelsim. Папка modelsim_example. Сходим образом создано UVM окружение. Синтаксис похожий несмотря на то что разные языки. Если установлен Modelsim с поддержкой uvm можно запустить командой make all.
Помимо окружения в обеих проектах сделан замер реального времени моделирования.
По времени получилась разница:
Среда | wafeform | команда для запуска | время моделирования (сек.) |
Modelsim | да | make sim TRACE=1 | 18 |
Verilator | да | make sim TRACE=1 | 9 |
Modelsim | нет | make sim TRACE=0 | 10 |
Verilator | нет | make sim TRACE=0 | 4 |
Как видно из таблицы verilator имеет преимущество. Данные представлены для ПК с 8Гб оперативной памяти, 8ми ядерным процессором, частотой 800 МГц, загрузкой одного ядра.
Сравним объем файлов:
simu.vcd | 807.7 MB |
simu.wlf (конвертация, создан в Verilator) | 41 MB |
simu.wlf (создан в modelsim) | 9.3 MB |
simu.lxt | 128 MB |
simu.lxt2 | 162 МБ |
Здесь verilator проигрывает, но можно поэкспериментировать с созданием вейвформ и глубиной трассировки, периодом записи (начало и конец записи вейвформ можно сместить). С каким файлом работать решать Вам.
В ходе тестирования, помимо времени самого моделирования, было обнаружено расхождение вычитывания входных данных с шины in. Если данные с шины in меняются во время фронта clk, Modelsim считал данные после фронта, verilator до:
input clk;
input [7:0] in;
reg [7:0] in_last_ ;
...
always @(posedge clk)
begin
...
in_last_ <= in;
...
end
При тестировании этот момент нужно учитывать, так как часть тестового окружения для разных симуляторов будет работать по-разному.
Также verilator не учитывает «x» состояния сигнала и переводит всё в «0»;
UVM TESTBENCH
Рассмотрим тестовое окружение, папка tb/uvm.
UVM testbench представляет собой окружение над устройством. В данном примере устройство ШИМ контроллер. Схема UVM окружения:
Как видно на схеме UVM состоит из блоков (классов). Каждый блок исполняет свои функции. В примере представлена одна из возможных компоновок тестового окружения. Название и функционал каждого класса соответствует классу от которого он наследован. Рассмотрим каждый класс подробнее.
Environment- файл env.h или env.svh. Это класс, который может содержать один или несколько классов agent, в которых происходит соединение трех классов: sequencer, driver, monitor. В примере агента нет, но его функция реализована в классе env. Для теста нам нужно написать некоторую последовательность действий — секвенс.
Перейдем к коду запуска секвенса:
sequence_[n]->start(sqr, NULL);
Sequencer (секвенсор) — файл sequncer.h. В system verilog получилось использовать sequencer по умолчанию. Класс, который содержит одну или несколько последовательностей sequence (секвенс) (файлы sequence_a.h, sequence_a.svh). Каждая последовательность представляет собой цепочку действий. Одним из таких действий может быть отправка транзакции. Транзакция — передача данных из одного класса в другой. Класс, в котором описаны транзакции — bus_trans. Далее будет описание двух классов, каждый из которых идеологически имеет свои определенные функции: driver и monitor.
Driver — файл drv.h, drv.svh. Класс, который принимает транзакции от секвенсора и транслирует их в сигналы. Драйвер служит помощником секвенсора на более низком уровне. Рассмотрим отправку одной посылки.
Секвенс открывает окно транзакции, драйвер детектирует это событие и начинает принимать данные. Секвенс ждет ответа от драйвера. Драйвер моделирует сигналы для устройства, затем сигнализирует секвенсору что окно можно закрыть. Идея заключается в том, что секвенсер работает на высоком уровне, а драйвер на более низком.
Сигналы подключены через шину интерфейса к устройству. Интерфейс описан в файлах vip_if.h, vip_if.svh.
Далее необходимо проверить, совпадает ли выходные сигналы с ожидаемыми. Есть два пути решения:
- Написание модели для устройства
- Проверка сигналов через агент UVM
В примере рассмотрен второй вариант. Чтобы проверить устройство на функциональном уровне необходимо сверить выходные данные с ожидаемыми. Требованием к устройству была корректность заданной скважности сигнала и периода сигнала. Для наблюдения за выходными сигналами написан новый класс — Мonitor (файл monitor.h, monitor.svh). Обычно, в тестовом окружении монитор переводит сигналы в транзакции (на более высокий уровень) и отправляются в класс сравнения — scoreboard.
В данном примере сигналы сразу проверяются. В случае расхождения ожидаемого значения с измеренным, тест останавливается.
Автор: paprikun