~ cd 13. использование vpi
Icarus Verilog реализует часть API PLI 2.0 в Verilog. Это позволяет программистам писать код на языке C, взаимодействующий с симуляторами Verilog, для выполнения задач, которые иначе невозможно решить с помощью прямого Verilog. Многие разработчики Verilog, особенно те, кто использует Verilog только как инструмент синтеза, могут смело игнорировать весь вопрос PLI (и эту главу), но разработчики, которые хотят взаимодействовать с внешним миром при моделировании, не могут обойтись без VPI.
Остальная часть этой статьи предполагает наличие некоторых знаний о программировании на языке Си, ПЛИС Verilog и компиляторе, установленном в вашей системе. В большинстве случаев Icarus Verilog предполагает, что используемый вами компилятор — GNU Compilation System, поэтому советы и инструкции, приведенные ниже, отражают это. Если вы не программист на Си или не планируете использовать модули VPI, можете пропустить всю эту статью. Внизу есть ссылки для получения информации по более общим темам.
13.1. Как это работает
% vvp -m sample foo.vvp
Время выполнения vvp загружает модули сначала, до выполнения симуляции или даже до компиляции кода vvp. Часть загрузки включает вызов процедур инициализации. Эти процедуры регистрируют во времени выполнения все системные задачи и функции, которые реализует модуль. Как только это сделано, загрузчик времени выполнения может сопоставить имена вызываемых системных задач проекта с их реализациями в модулях VPI.
(Существует специальный модуль system.vpi, который всегда загружается для обеспечения основных системных задач).
void (*vlog_startup_routines[])() = {
hello_register,
0
};
Обратите внимание, что таблица «vlog_startup_routines» представляет собой массив указателей функций, последний из которых равен 0, чтобы отметить конец. При желании программист может организовать модуль таким образом, чтобы включить в эту таблицу множество стартовых функций.
Задача функций запуска, собранных в таблице запуска, — объявить системные задачи и функции, которые предоставляет модуль. Модуль может реализовать столько задач/функций, сколько пожелает, поэтому модуль можно с полным правом назвать библиотекой системных задач и функций.
13.2. Компиляция модулей VPI
% gcc -c -fpic hello.c
% gcc -shared -o hello.vpi hello.o -lvpi
% iverilog-vpi hello.c
Команда «iverilog-vpi» принимает в качестве аргументов исходные файлы вашего модуля VPI, компилирует их с использованием соответствующих флагов компилятора и компонует их в модуль vpi с любыми библиотеками и флагами компоновщика, необходимыми для конкретной системы. Эта простая команда создает модуль «hello.vpi» с минимальными затратами.
13.3. Пример
# include <vpi_user.h>
static int hello_compiletf(char*user_data)
{
return 0;
}
static int hello_calltf(char*user_data)
{
vpi_printf("Hello, World!\n");
return 0;
}
void hello_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.tfname = "$hello";
tf_data.calltf = hello_calltf;
tf_data.compiletf = hello_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = 0;
vpi_register_systf(&tf_data);
}
void (*vlog_startup_routines[])() = {
hello_register,
0
};
module main;
initial $hello;
endmodule
% iverilog-vpi hello.c
% iverilog -o hello.vvp hello.v
% vvp -M. -mhello hello.vvp
Hello, World!
Компиляция и компоновка в этом примере удобно объединены в команду «iverilog-vpi». Затем команда «iverilog» компилирует исходный файл Verilog «hello.v» в программу «hello.vvp». Далее команда «vvp» демонстрирует использование флагов «-M» и «-m» для указания каталога поиска модуля vpi и имени модуля vpi. В частности, они указывают команде «vvp», где найти модуль, который мы только что скомпилировали.
Команда «vvp», выполненная как указано выше, загружает модуль «hello.vpi», который она находит в текущем рабочем каталоге. Когда модуль загружен, происходит сканирование таблицы vlog_startup_routines и выполняется функция «hello_register». Функция «hello_register», в свою очередь, сообщает «vvp» о системных задачах, которые включены в данный модуль.
После загрузки всех модулей загружается файл проектирования «hello.vvp», и его вызов системной задачи «$hello» сопоставляется с версией, объявленной модулем. Пока «vvp» компилирует исходный файл «hello.vvp», все обращения к «$hello» передаются функции «compiletf». Эта функция вызывается во время компиляции и может быть использована для проверки параметров системных задач или функций. Ее можно оставить пустой, как сейчас, или не указывать совсем. Функция «compiletf» может помочь производительности, собирая проверки параметров во время компиляции, так что их не нужно делать каждый раз при запуске системной задачи, что потенциально экономит время выполнения в целом.
Когда время выполнения выполняет вызов системной задачи hello, в загруженном модуле вызывается функция «hello_calltf», и таким образом генерируется вывод. Функция «calltf» вызывается во время выполнения, когда код Verilog фактически выполняет системную задачу. Именно здесь находится активный код задачи.
13.4. Типы возврата системных функций
Icarus Verilog поддерживает системные функции так же, как и системные задачи, но есть одно осложнение. Обратите внимание, что модуль, который вы компилируете, загружается только программой «vvp». В основном это не является проблемой, но при разработке выражений необходимо следить за типами, поэтому основному компилятору необходимо знать возвращаемый тип функций.
Начиная с Icarus Verilog v11, решение довольно простое. Имена и расположение пользовательских VPI-модулей могут быть переданы компилятору через флаги «iverilog» -m и -L и переменную окружения IVERILOG_VPI_MODULE_PATH. Компилятор загрузит и проанализирует указанные модули, чтобы автоматически определить все возвращаемые типы функций. Компилятор также автоматически передаст программе «vvp» имена и расположение указанных модулей, так что их не нужно будет указывать снова в командной строке «vvp».
# Example sft declarations of some common functions
$random vpiSysFuncInt
$bitstoreal vpiSysFuncReal
$realtobits vpiSysFuncSized 64 unsigned
Это демонстрирует формат файла и типы поддержки. Каждая строка содержит комментарий (начинается с «#») или объявление типа для одной функции. Объявление начинается с имени системной функции (включая ведущий символ «$») и заканчивается типом. Поддерживаются следующие типы:
- vpiSysFuncInt
- vpiSysFuncReal
- vpiSysFuncSized
Любые функции, не имеющие явного объявления типа в файле SFT, неявно принимаются за «vpiSysFuncSized 32 unsigned».
Автор модуля предоставляет вместе с файлом «.vpi», который является модулем, файл «.sft», в котором объявлены все возвращаемые типы функций. Например, если файл имеет имя «example.sft», передайте его в командную строку «iverilog» или в командный файл точно так же, как если бы это был обычный исходный файл.
13.5. Модули Cadence PLI
С помощью модуля cadpli Icarus Verilog может загружать приложения PLI1, которые были скомпилированы и скомпонованы для динамической загрузки в Verilog-XL или NC-Verilog. Это позволяет пользователям Icarus Verilog запускать модули сторонних разработчиков, которые были скомпилированы для взаимодействия с XL или NC. Очевидно, что это работает только в той операционной системе, для запуска которой было скомпилировано PLI-приложение. Например, модуль для Linux может быть загружен и запущен только под Linux. Кроме того, 64-битная версия vvp может загружать только 64-битные PLI1-приложения и т. д.
% vvp -mcadpli a.out -cadpli=./product.so:my_boot
Аргумент «-mcadpli» заставляет vvp загрузить библиотечный модуль cadpli.vpl. Это активирует интерпретатор с аргументом -cadpli=. Аргумент -cadpli=<модуль>: заставляет vvp через модуль cadpli загрузить загружаемое PLI-приложение, вызвать функцию my_boot для получения таблицы veriusertfs и просканировать эту таблицу для регистрации системных задач и функций, экспортируемых этим объектом. Формат расширенного аргумента -cadpli= по сути такой же, как и аргумент +loadpli1= в Verilog-XL.
Интеграция с этого момента не вызывает затруднений. PLI-приложение практически не знает, что его вызывает Icarus Verilog, а не Verilog-XL, и работает так же, как и в других случаях.
13.6. Другие ссылки
Поскольку выше описано только то, как заставить PLI/VPI работать с Icarus Verilog, вот несколько ссылок на материалы, которые помогут разобраться с общими аспектами работы PLI/VPI.
Principles of Verilog PLI by Swapnajit Mittra. ISBN 0-7923-8477-6
The Verilog PLI Handbook by Stuart Sutherland. ISBN 0-7923-8489-X