OVM/OVM методология/Механика OVM/4.8
Содержание |
Тестирование и тестовые окружения
Благодаря правильному использованию конфигураций, для производство, и поэтапного процесса разработки, можно создать тестбенч для верификации, что позволяет подавать случайные воздействия больше, чем просто сгенерированный stimuls. Например, если тестбенч написан, чтобы количество драйверов на шине можно настраивать, то же тестбенч может быть повторно использован на нескольких тестах, каждый из которых может указать другой (возможно, случайно) число драйверов. Как вы можете видеть, гибкость OVM позволяет запускать каждую из этих различных тестов без изменения тестбенча. OVM также обеспечивает явные ovm_test классы в качестве контейнера для испытаний. Как правило, на top-level модуль будет экземпляром ovm_test, который в свою очередь настраивает и создает тестбенч. Дополнительные тесты могут быть написаны как расширения базовым тестам, которые включают новую конфигурацию и директивы factory, в результате чего сами тесты относительно короткий, четкий и простой в обслуживании. В действительности, ovm_test это просто другое расширение ovm_component. Поскольку тесты и testbenches просто компонентами, они тоже могут быть созданы и переопределены через factory.
Диаграмма UML выше иллюстрирует отношения между тестом и окружением. И тесты и окружение (ENV) компоненты. Тест содержит окружение. Среда содержит top-level компонет тестбенча и их соединений. Для определенния окружения, вы может хотите иметь несколько тестов. Кроме того, для конкретного теста, вы, возможно, пожелаете осуществлять его на твои окружения. factory позволяет менять тесты, окружения, или то и то.
4.9.5 Изменение потока управления (Altering the Flow of Control)
Большую часть времени, когда вы выдаете отчет, отчет отображается или отправить файл, а затем контроль возобновляется в последующих состояниях. Есть случаи, когда вы хотите изменить поток управления, основанный на сообщениях, которое выдается. Наиболее очевидный случай остановка тестбенча. EXIT событие заканчивает тестбенч сразу после отправки сообщения до того как тест выполниться до конца. Действие COUNT увеличивает на единицу quit_count, и тестбенч заканчивается, когда quit_count достигает max_quit_count. Как правило, вы будете использовать эти действия чтобы, прервать цикл выполнения программы, в котором может произойти ошибка в неопределенное время, или предотвратить каскадные сообщения об ошибках из запутанного (неопределенного) источника ошибки.
4.9 Reporting
OVM предоставляет богатый набор классов и функций для генерации и фильтрации сообщений. Объекты OVM типа сообщения содержит три вида функций:
- Отображение сообщений в едином порядке по различным направлениям
- Фильтрация сообщений
- Изменение потока управления в результате сообщения в печати
4.9.1 Базовые сообщения (Basic Messaging)
function void ovm_report_info( string id, string message, int verbosity = OVM_MEDIUM, string filename = "", int line = 0); function void ovm_report_warning( string id, string message, int verbosity = OVM_MEDIUM, string filename = "", int line = 0); function void ovm_report_error( string id, string message, int verbosity = LOW, string filename = "", int line = 0); function void ovm_report_fatal( string id, string message, int verbosity = OVM_NONE, string filename = "", int line = 0);
Каждая из этих четырех функций выдает сообщение, которое имеет несколько компонентов: статус, уровень детализации, идентификатор, сообщение, имя файла и номер строки.
Статус. Статус сообщение может принимать значения OVM_INFO, OVM_WARNING, OVM_ERROR, или OVM_FATAL. Выбор тяжести меняет окончательный текст, который напечатан тексте в котором указана серьезность. Это также влияет на то, как сообщение обрабатывается. Например, вызов ovm_report_fatal заканчивает выполнения тестбенча. Другие способы, в которых статус влияет на обработку сообщений, обсуждаются в разделе 4.9.2.
Идентификатор сообщения содержит произвольную строку, которая используется для идентификации строк. Идентификатор печатается как часть текста сообщения, и это также влияет на сообщения обрабатываются.
Сообщение. Сообщение тело текстового сообщения.
Уровень детализации. Уровень детализации сообщения является произвольным числом, которое по отношению к текущей настройки детализации является порогом, после которого сообщения с уровень детализации на уровне или ниже порога будут напечатаны, а те что выше, будут игнорироваться. Это способ фильтрации сообщений. Вы можете задать свой порог для тестбенча. Функция для изменения уровня порога set_report_verbosity_level (INT уровень).
Имя файла и номер строки. Это необязательные аргументы, роль которого заключается в обеспечении файла и номер строки содержащем информацию о произошедшем событии.
4.9.2 Сообщения о событиях (Message Actions)
Message Actions ставит соответствие каждому сообщению действие, которые определяют, как именно она обрабатывается. Действие представлено битовым вектором, в котором каждый бит представляет одно из возможных действий. Вы можете задать несколько действий, включив один или более битов в векторе. Таким образом, вы не должны помнить, какой бит за что отвечает, OVM умеет выполнять действия перечисления, которое можно использовать, чтобы указать действие. В следующей таблице описываются возможные действия:
Action | Definition |
---|---|
NO_ACTION | Do not execute an action. |
OVM_DISPLAY | Display the message on the standard output device. |
OVM_LOG | Send the message to a file. |
OVM_COUNT | Increment quit_count. When quit_count reaches a predetermined threshold, terminate the testbench. |
OVM_EXIT | Terminate the testbench immediately. |
OVM_CALL_HOOK | Call the appropriate hook function. |
OVM_STOP Call | $stop after the message has been processed. |
quit_count и max_quit_count хранятся в глобальной месте. Вы можете изменить max_quit_count со следующей функцией:
set_max_quit_count(int q);
Сочетание статуса сообщения и идентификатор определяют выполняемое действие. Обработчик сообщений держит набор таблиц, которые определяют действия и файл направления сообщений по идентификатору и серьезности. (Мы вскоре увидим, как эти таблицы созданы.) Во-первых, обработчик сообщения смотрит, если есть действие, указанное для комбинации идентификатора и тяжесть в сообщении. Если его нет, то обработчик сообщения смотрит, если есть действие, указанное только для идентификатора. Если он не находит, то он ищет действий по степени тяжести. OVM объекты сообщений гарантируют, что всегда есть действие для каждой степени тяжести. Действия по умолчанию показаны в следующей таблице.
Severity | Default Action |
---|---|
OVM_INFO | OVM_DISPLAY |
OVM_WARNING | OVM_DISPLAY |
OVM_ERROR | OVM_DISPLAY или OVM_COUNT |
OVM_FATAL | OVM_DISPLAY или OVM_EXIT |
Только действия по умолчанию, определяются тяжестью, как показано в таблице выше. Вы должны установить любые другие действия по идентификатору или комбинацию идентификатора и тяжесть с помощью функций (собственных, сами разрабатываем нужные функции), предназначенными именно для этой цели.
4.9.3 Message Files
Для отправки сообщений в файл, необходимо сначала открыть файл и изменить соответствующие меры сообщение для OVM_LOG.Удобное место, чтобы сделать это в методе компонента build(), например:
class component extends ovm_component; FILE f; function void build(); f = $fopen("logfile", "w"); set_report_default_file(f); set_report_severity_action(OVM_INFO, OVM_LOG); set_report_severity_action(OVM_WARNING, OVM_LOG); set_report_severity_action(OVM_ERROR, OVM_LOG); set_report_severity_action(OVM_FATAL, OVM_LOG | OVM_EXIT); endfunction
function void report(); $fclose(f); endfunction
4.9.4 Обработчик сообщений (Message Handlers)
Каждое сообщение объекта имеет обработчик сообщений (ovm_report_handler), связанный с ним. В докладе обработчик напрямую не доступны пользователю, хотя и содержит локальные данные, что состояние объекта отчета. В объект сообщения не содержит в себе данных отчета, только интерфейс который посылает отчет, то есть функции, работа с которыми передана в обработчику. Чтобы проиллюстрировать эту концепцию, давайте посмотрим на примере иерархические связи, которые мы обсуждали в разделе 4.2.1. Они, как и все иерархии компонентов, имеют обработчик сообщений, связанный с каждым компонентом.
Чтобы изменить характеристики отчетов по отдельным компонентам, необходимо изменить только отбработчик сообщений. Например, инициирующий данный вызов в компоненте sink2:
set_report_id_action(“fsm”, OVM_LOG);
вызывает все сообщения с идентификатором "fsm" должны войти в файл. Поскольку этот вызов был сделан в sink2, это относится только к сообщениям которые выдают sink2. Сообщения которые выдаются от любой другой компонент в этом тестбенче не влияют, даже если они также имеют "fsm" идентификатор. Чтобы сделать аналогичные изменения на по всей суб-иерархии, вы можете оформить тот же вызов на каждый компонент, или вы можете позвонить в иерархическом эквивалент set_report_id_action () метод. В этом случае, вы могли бы назвать:
set_report_id_action_hier(“fsm”, LOG);
Если вы сделаете этот призыв в sinker, вы будете влиять на sinker и все компоненты в иерархии под ним. На рисунке ниже, закрашены отработавшие обработчики сообщений.
В следующей таблице приведены все методы для изменения обработчика сообщений и файлов и их иерархические эквиваленты.
Local Method | Hierarchical Method |
---|---|
set_report_verbosity_level | set_report_verbosity_level_hier |
set_report_default_file | set_report_default_file_hier |
set_report_severity_action | set_report_severity_action_hier |
set_report_id_action | set_report_id_action_hier |
set_report_severity_id_action | set_report_severity_id_action_hier |
set_report_severity_file | set_report_severity_file_hier |
set_report_id_file | set_report_id_file_hier |
set_report_severity_id_file | set_report_severity_id_file_hier |
4.9.5 Переключение потока управления (Altering the Flow of Control)
В большинстве случаев, когда вы выдаете сообщение, сообщение отображается или отправляется в файл, а затем управление возобновляется в последующих состояниях. Есть случаи, когда вы хотите изменить поток управления основываясь на выдаваемых сообщениях. Наиболее очевидный случай это прекращение выполнения тестбенча. EXIT действие заканчивает выполнения тестбенча сразу после отправки сообщения не дожидаясь завершения работы. Действие COUNT наращивает на единицу quit_count, и тест бенч заканчивается, когда quit_count достигает max_quit_count. Как правило, вы будете использовать эти действия чтобы, предотвратить непрерывный цикл выполнения программы в состоянии ошибки в неопределенное заранее время, или предотвратить каскадные сообщения об ошибках из запутанных источников ошибки.
function void build(); set_report_max_quit_count(10); set_report_severity_action(OVM_ERROR, OVM_DISPLAY | OVM_LOG | OVM_COUNT); endfunction
Another way to alter the flow of control when a report is issued is through report hooks. The report object provides this set of virtual functions. They provide a place where you can gain control when any report is issued or a report of a specific severity is issued to do additional filtering, counting, sanity checking, and so forth. The OVM report object provides five report hooks, one for each severity, and a catch-all hook that is called no matter what the severity of the report.
Например функция build() выше устанавливает max_quit_count в 10 и поручает обработчику сообщений каждый раз выдавать сообщение об ошибке (то есть, будет вызываться ovm_report_error ()) и показывать сообщение на экране, и записью в лог-файл и увеличивать значение quit_count. В десятый раз выдается ошибка, тестбенч останавливается.
Еще один способ изменить поток управления, когда сообщение выдается через hooks сообщение. В объекте сообщения предоставлены эти виртуальные функции. Они представляют собой место, где можно получить управление при любой сообщении или сообщений, которые выдаются с определенной степенью серьезности, сделать дополнительную фильтрацию, подсчет, дополнительную проверку, и так далее. Объект OVM report содержит пять отчетов hooks, по одному для каждой тяжести и общий hooks, который вызывается независимо от того, какая степень тяжести у сообщения.
virtual function bit report_hook( string id, string message, int verbosity, string filename, int line); virtual function bit report_message_hook( string id, string message, int verbosity, string filename, int line); virtual function bit report_warning_hook( string id, string message, int verbosity, string filename, int line); virtual function bit report_error_hook( string id, string message, int verbosity, string filename, int line); virtual function bit report_fatal_hook( string id, string message, int verbosity, string filename, int line);
Первое, что вы заметите, что эти функции имеют точно такой же аргумент, что и функции ovm_report_*. Причина в том, что все аргументы, переданные ovm_report_* также передаются на hooks. Кроме того, необходимо заметить, что каждая из этих функций возвращает значение, один бит. Обработка продолжается, только если оба hooks возвращают 1. По умолчанию hooks, hooks из базового класса при вызове, если явно не определено другого, всегда возвращает 1. Если возвращаемое значение равно 0, то обработка прекращается, и это аналогично тому что сообщение вообще не выдавалось. Через код возврата hooks, вы можете сделать более подробную фильтрации сообщений. В качестве примера того, как можно использовать возращенные коды, скажем, что вы не хотите видеть сообщения с вашего тетсбенча во время инициализации, которая занимает 250 микросекунд. После завершения инициализации, вы хотите увидеть все сообщения.
function bit report_hook(input string id, input string mess, input verbosity, string filename, int line); return ($time > 250000); endfunction
Глобальный hooks вызывается первым, а затем вызывается hooks соответствующей тяжести. Для того чтобы активировать hooks, вы должны включить их, когда будем устанавливать действия для объекта OVM_CALL_HOOK. Удобное место, чтобы сделать это функция build():
class component extends ovm_component; FILE f; function void build(); f = $fopen("logfile", "w"); set_report_default_file(f); set_report_severity_action(OVM_INFO, OVM_LOG | OVM_CALL_HOOK); set_report_severity_action(OVM_WARNING, OVM_LOG | OVM_CALL_HOOK); set_report_severity_action(OVM_ERROR, OVM_LOG | OVM_CALL_HOOK); set_report_severity_action(OVM_FATAL, OVM_LOG | EXIT | OVM_CALL_HOOK); endfunction
Hooks are run in the component in which they are implemented. Just as each component has its own set of methods, they also have their own hooks. If you want to run the same hook in different components, you’ll have to implement it in each component. A straightforward way to do this is to create your own component base class that inherits from ovm_component and that has your hook implementations.
Hooks выполняются в компоненте, в которой они добавлены. Подобно тому, как каждый компонент имеет свой собственный набор методов, они также имеют свои Hooks. Если вы хотите запустить тот же Hooks в различных компонентах, вы должны реализовать его в каждом компоненте. Простой способ сделать это, создать свой собственный компонент на основе базового класса, который наследуется от ovm_component и в которой и реализован ваш hook.
4.10 Резюме
Понимание концепций, обсуждаемых в этой главе, позволяет построить основные элементы тестбенча с использованием OVM. Вы можете создавать произвольные иерархии классов на основе компонентов, соединить их, настроить их, запустить их, и закрыть их. В последующих главах на основе этих понятий с некоторыми дополнениями, с объяснениями пройдем путь создания структуры тестбенча, пригодной для многоразового использования в дальнейшем.