- 1. Системные Задачи и функции VPI
- 1.1. Прикладная процедура sizetf VPI
- 1.2. Прикладная процедура compiletf VPI
- 1.3. Прикладная процедура calltf VPI
- 1.4. Аргументы для прикладных процедур sizetf, compiletf и calltf
- 2. Механизм VPI
- 2.1. Обратные вызовы VPI
- 2.2. VPI доступ к объектам Verilog HDL и объектам моделирования
- 2.3. Обработка ошибок
- 2.4. Наличие функций
- 2.5. Обход выражений
1. Системные Задачи и функции VPI
Определяемые пользователем системные задачи и функции создаются с помощью процедуры vpi_register_systf() (см. 27.34). Регистрация системных задач должна происходить до элаборации или разрешения ссылок.
Предполагаемая модель использования заключается в размещении ссылки на процедуру в массиве vlog_startup_routines[]. Эта процедура будет регистрировать все определяемые пользователем системные задачи и функции при вызове.
С помощью процедур VPI может выполнять следующие действия:
- Указывать имя определяемой пользователем системной задачи/функции, которое может быть включено в исходные описания Verilog HDL; имя определяемой пользователем системной задачи/функции должно начинаться со знака доллара ($), например $get_vector.
- Предоставляет одно или несколько приложений PLI C для вызова программным продуктом (например, логическим симулятором).
- Определяет, какие приложения PLI C должны быть вызваны и когда эти приложения должны быть вызваны, когда пользовательское имя системной задачи/функции встречается в исходном описании Verilog HDL.
- Определяет, следует ли рассматривать приложения PLI как функции (которые возвращают значение) или как задачи (аналогично подпрограммам в других языках программирования).
- Определите аргумент data, который будет использоваться в команде для приложений PLI при каждом их вызове
Также с помощью механизмов обратного вызова в VPI можно создавать приложения, которые не привязаны напрямую к заданной пользователем системной задаче/функции.
Системные задачи на основе VPI имеют подпрограммы sizetf, compiletf и calltf, которые выполняют определенные действия для задачи/функции. Подпрограммы sizetf, compiletf и calltf вызываются в определенные периоды во время обработки. Назначение каждой из этих процедур объясняется в пунктах 1.1—1.4.
1.1. Прикладная процедура sizetf VPI
Прикладная процедура sizetf VPI может использоваться совместно с системными функциями, определяемыми пользователем. Функция должна возвращать значение, и программные продукты, выполняющие системную функцию, должны определить, сколько бит в ширину должно иметь возвращаемое значение. Когда следует вызывать sizetf, описано в 2.4 и 27.34.1. Каждая процедура sizetf должна вызываться не более одного раза. Она должна вызываться, если связанная с ней системная функция присутствует в проекте. Значение, возвращаемое процедурой sizetf, должно быть числом битов, которое процедура calltf должна предоставить в качестве возвращаемого значения для системной функции. Если процедура sizetf не указана, то системная функция, определенная пользователем, должна возвращать 32 бита. Процедура sizetf не должна вызываться для системных задач, определяемых пользователем, или для функций, sysfunctype которых установлен в vpiRealFunc.
1.2. Прикладная процедура compiletf VPI
Прикладная процедура compiletf VPI должна вызываться, когда имя определяемой пользователем системной задачи/функции встречается во время прохода или компиляции исходного кода Verilog HDL. Эта процедура обычно используется для проверки корректности любых аргументов, переданных пользовательской системной задаче/функции в исходном коде Verilog HDL. compiletf должна вызываться один раз для каждого экземпляра системной задачи/функции в исходном описании. Предоставление процедуры compiletf необязательно, но рекомендуется, чтобы все аргументы, используемые с системной задачей/функцией, должны быть проверены на корректность, чтобы избежать проблем, когда calltf или другие процедуры PLI читают и выполняют операции над аргументами. Когда вызывается compiletf, описано в 2.4 и 27.34.1.
1.3. Прикладная процедура calltf VPI
for (i = 1; i <= 1024; i = i + 1)
@(posedge clk) $get_vector("test_vector.pat", input_bus);
В этом примере calltf может считать тестовый вектор из файла test_vector.pat (первый аргумент задачи/функции), возможно, манипулировать вектором, чтобы привести его в надлежащий формат для Verilog, а затем присвоить значение вектора второму аргументу задачи/функции под названием input_bus.
1.4. Аргументы для прикладных процедур sizetf, compiletf и calltf
Процедуры sizetf, compiletf и calltf принимают один аргумент. Когда программный продукт вызывает эти процедуры, он передает им значение, переданное в поле user_data структуры s_vpi_systf_data при регистрации определяемой пользователем системной задачи/функции. См. 27.34.
2. Механизм VPI
VPI предоставляет процедуры, которые позволяют разработчикам приложений получать доступ к информации, содержащейся в проекте Verilog, и позволяют средствам динамически взаимодействовать с программным продуктом. Приложения VPI могут включать калькуляторы задержек и аннотаторы, соединение симулятора Verilog с другими системами моделирования и CAE, а также специализированные задачи отладки.
Функции VPI можно сгруппировать в две основные области:
- Динамическое взаимодействие программных продуктов с использованием обратных вызовов VPI
- Доступ к объектам Verilog HDL и объектам, специфичным для моделирования
2.1. Обратные вызовы VPI
Динамическое взаимодействие программных продуктов должно осуществляться с помощью зарегистрированного механизма обратного вызова. Обратные вызовы VPI должны позволять приложению запрашивать, чтобы программный продукт Verilog HDL, например, логический симулятор, вызывал определенное пользователем приложение, когда происходит определенное действие. Например, приложение может запросить вызов прикладной процедуры my_monitor() при изменении значения определенной сети или вызов my_cleanup() при завершении выполнения программного продукта.
Средство обратного вызова VPI должно предоставлять приложению средства для динамического взаимодействия с программным продуктом, обнаруживая появление изменений значений, продвижение времени, окончание моделирования и т.д. Эта функция позволяет интегрироваться с другими системами моделирования, выполнять специализированные проверки времени, сложные функции отладки и т.д.
Причины, по которым должны предоставляться обратные вызовы, можно разделить на четыре категории:
- Событие моделирования (например, изменение значения в сети или выполнение поведенческой инструкции)
- Время моделирования (например, в конце временной очереди или по истечении определенного промежутка времени)
- Действие или функция симулятора (например, завершение компиляции, завершение моделирования, перезапуск или переход в интерактивный режим)
- Выполнение системных задач/функций, определяемых пользователем
Обратные вызовы VPI должны быть зарегистрированы приложением с помощью функций vpi_register_cb() и vpi_register_ systf(). Эти функции указывают конкретную причину обратного вызова, прикладные процедуры, которые должны быть вызваны, и какие системные и пользовательские данные должны быть переданы приложению обратного вызова, когда происходит обратный вызов. Также предусмотрена возможность вызова функций обратного вызова при первом вызове программы Verilog HDL. Это средство используется в основном для регистрации системных задач и функций, определяемых пользователем.
2.2. VPI доступ к объектам Verilog HDL и объектам моделирования
Доступные объекты Verilog HDL и объекты моделирования, а также их взаимосвязи и свойства описываются с помощью диаграмм модели данных. Эти диаграммы представлены в разделе 6. Диаграммы модели данных указывают на процедуры и константы, необходимые для доступа и манипулирования объектами в прикладной среде. Соответствующий набор процедур для доступа к этим объектам определен в п. 27.
VPI также включает в себя набор служебных процедур для таких функций, как сравнение дескрипторов, обработка файлов и перенаправленная печать, которые описаны в таблице 26-9.
Подпрограммы VPI обеспечивают доступ к объектам в инстанцированном проекте Verilog. Инстанцированная конструкция — это конструкция, в которой каждый экземпляр объекта имеет уникальный доступ. Например, если модуль m содержит провод w и дважды объявлен экземпляром как m1 и m2, то m1.w и m2.w — это два разных объекта, каждый со своим набором связанных объектов и свойств.
VPI разработан как интерфейс моделирования, с доступом как к объектам Verilog HDL, так и к конкретным объектам моделирования. Этот интерфейс моделирования отличается от интерфейса иерархического языка, который предоставляет доступ к информации HDL, но не предоставляет информацию об объектах моделирования.
2.3. Обработка ошибок
Для определения того, произошла ли ошибка, должна быть предусмотрена процедура vpi_chk_error(). Процедура vpi_chk_ error() должна возвращать ненулевое значение, если в ранее вызванной процедуре VPI произошла ошибка. Также могут быть установлены обратные вызовы при возникновении ошибки. Процедура vpi_chk_error() может предоставлять подробную информацию об ошибке.
2.4. Наличие функций
Некоторые функции VPI должны возникать на ранних стадиях выполнения инструмента. Для того чтобы этот процесс происходил упорядоченно, некоторые функциональные возможности должны быть ограничены на ранних стадиях. В частности, когда выполняются процедуры в массиве vlog_startup_routines[ ], доступно очень мало функций. В это время могут быть вызваны только две процедуры:
- vpi_register_systf() — vpi_register_cb()
Кроме того, процедура vpi_register_cb() может быть вызвана только по следующим причинам:
- cbEndOfCompile
- cbStartOfSimulation
- cbEndOfSimulation
- cbUnresolvedSystf
- cbError
- cbPLIError
Более подробное объяснение использования массива vlog_startup_routines[ ] см. в разделе 27.34.
Следующая самая ранняя фаза — это вызов процедуры sizetf для системных функций, определяемых пользователем. На этой фазе дополнительный доступ не разрешен. После вызова процедуры sizetf вызываются процедуры, зарегистрированные по причине cbEndOfCompile. На этом этапе и далее до завершения выполнения инструмента все функциональные возможности доступны.
2.5. Обход выражений
Процедуры VPI обеспечивают доступ к любому выражению, которое может быть записано в HDL. Работа с этими выражениями может быть сложной, поскольку в HDL могут быть записаны очень сложные выражения. Выражения с несколькими операндами приводят к обработке типа vpiOperation. Чтобы определить количество операндов, обратитесь к свойству vpiOpType. Эта операция будет оцениваться после своих подвыражений. Поэтому она имеет наименьший приоритет в выражении.
void traverseExpr(vpiHandle expr) {
vpiHandle subExprI, subExprH;
switch (vpi_get(vpiExpr,expr)) {
case vpiOperation:
subExprI = vpi_iterate(vpiOperand, expr);
if (subExprI)
while (subExprH = vpi_scan(subExprI))
traverseExpr(subExprH);
/* иначе он имеет тип op vpiNullOp */
break;
default:
/* Можно сделать что угодно с объектом листа. */
break;
}
}