OVM/Basic OVM/Session5 - Connecting Components — различия между версиями
ANA (обсуждение | вклад) (Новая страница: «{{OVM TOC}} 600px Здравствуйте, я Джон Эйнли из компан…») |
Yura (обсуждение | вклад) |
||
(не показана 1 промежуточная версия 1 участника) | |||
Строка 1: | Строка 1: | ||
{{OVM TOC}} | {{OVM TOC}} | ||
− | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf| | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=1|600px]] |
− | Здравствуйте, я Джон Эйнли | + | Здравствуйте, я Джон Эйнли из компании Дулос. |
− | из компании Дулос. | + | Это пятое занятие по основам OVM. Его тема - соединение компонентов. |
+ | Мы познакомимся с тем, как создавать несколько компонентов OVM | ||
+ | в окружении верификации и как собирать их воедино. | ||
+ | Также мы подробнее рассмотрим архитектуру отдельного компонента. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=2|600px]] | |
− | + | ||
− | + | На предыдущем занятии я говорил, что типичный компонент OVM | |
− | + | состоит из контроллера, драйвера и монитора. | |
+ | Идея в том, чтобы использовать компонент как стандартный строительный блок | ||
+ | в окружении верификации OVM. Такая конфигурация компонентов | ||
+ | называется агентом. Эта структура не является единственно | ||
+ | возможной. Вы не обязаны строить окружение верификации | ||
+ | исключительно из агентов с такой структурой, однако это неплохая отправная точка, | ||
+ | позволяющая обеспечить стандартизацию и согласованность между компонентами | ||
+ | верификации из различных источников. Поэтому при обсуждении создания и | ||
+ | соединения компонентов будет разумно использовать описанную структуру | ||
+ | агентов в качестве примера, отправной точки. И именно так мы сейчас и поступим. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=3|600px]] | |
− | + | ||
− | и | + | Я уже неоднократно упоминал компоненты OVM, и теперь самое время взглянуть на |
− | + | формальную иерархию классов OVM. Здесь мы вступаем на территорию | |
+ | объектно-ориентированного программирования. На слайде представлена диаграмма | ||
+ | иерархии классов в обозначениях, немного напоминающих язык UML. | ||
+ | Классы, изображенные ниже, расширяют, или наследуют тем, | ||
+ | что изображены выше. Внутри широкой рамки в нижней части | ||
+ | диаграммы показаны все виды компонентов OVM. Они применяются для описания структуры. | ||
+ | В OVM имеется много классов, причем все они наследуют единственному | ||
+ | базовому классу ovm_component, который в свою очередь является производным от класса | ||
+ | ovm_report_object, а тот - от класса ovm_object, с которым мы встречались на | ||
+ | предыдущем занятии. В нижней части диаграммы мы видим различные компоненты OVM, | ||
+ | в частности ovm_env для уже знакомого нам ovm_test, а также такие компоненты, как | ||
+ | ovm_agent и ovm_driver. Позже мы узнаем, что некоторые из компонентов | ||
+ | полностью взаимозаменяемы и отличаются только названиями. | ||
+ | Но есть также компоненты с уникальными свойствами, присущими только им. | ||
+ | Во многих случаях у вас есть выбор. Например, можно воспользоваться как | ||
+ | ovm_env, так и ovm component. А это означает, что выбор того или иного | ||
+ | компонента OVM - вопрос стиля кодирования и единообразия, | ||
+ | а не технической необходимости. Тем не менее, на данном занятии | ||
+ | я буду выбирать подходящий тип компонента исходя из той роли, которую он играет. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=4|600px]] | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
+ | Стало быть, в данном случае мы возьмем компонент ovm_agent. | ||
+ | Итак, создадим определенный пользователем компонент верификации, | ||
+ | расширив базовый класс ovm_agent. Однако подчеркну еще раз: я мог бы расширить | ||
+ | ovm_component, или даже ovm_monitor или ovm_env, и в данном случае получился бы | ||
точно такой же результат. | точно такой же результат. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=5|600px]] | |
− | + | ||
− | Это стандартный код, который следует | + | Итак, в строке 2 мы регистрируем my_agent как ovm_component. |
− | включать обязательно. | + | Это стандартный код, который следует включать обязательно. |
+ | Впоследствии агент будет создавать экземпляры контроллера и драйвера, | ||
+ | поэтому мы объявляем в классе два описателя: my_sequencer_h и my_driver_h. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=6|600px]] | |
− | + | ||
− | + | Далее следует метод new, конструктор класса, и стандартные методы, | |
− | + | build и connect. С методом build мы уже встречались ранее, | |
+ | а метод connect для нас внове. Он служит для соединения дочерних компонентов, | ||
+ | и чуть позже я подробнее объясню, как он работает. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=7|600px]] | |
− | + | Однако начнем с расширения метода build. Сначала метод build, как обычно, вызывает | |
− | + | метод базового класса super.build,а затем создает экземпляры контроллера и драйвера, | |
+ | с помощью волшебного заклинания type_id::create. Передаваемые методу create аргументы | ||
+ | очень важны. Первый аргумент, как и раньше, это имя экземпляра,которое должно совпадать с | ||
+ | именем переменной. Второй аргумент – родитель, мы всегда будем | ||
+ | использовать в этом качестве "this", встроенную в SystemVerilog переменную, которая | ||
+ | обозначает текущий объект, с которым мы работаем. В объектно-ориентированной терминологии метод | ||
+ | create называется фабричным. Фабричные методы - это один из так называемых паттернов | ||
+ | объектно-ориентированного программирования, то есть заведомо хороших способов решить | ||
+ | определенную задачу.Конкретно, фабричный метод позволяет создать объект | ||
+ | и в то же время переопределить тип объекта, создаваемого где-то в другом месте. | ||
+ | На первый взгляд кажется, что здесь мы создаем объекты типа my_sequencer | ||
+ | и my_driver, и по умолчанию так оно и есть. Однако имеется возможность переопределить | ||
+ | типы компонентов, создаваемых этими фабричными методами. Так, в каком-то конкретном тесте, | ||
+ | не изменяя исходный код данного конкретного агента ни на йоту, мы могли бы переопределить поведение | ||
+ | фабричных методов, заставив их создавать иные компоненты, последовательности или драйверы. | ||
+ | С помощью этого механизма мы можем настраивать поведение того или иного компонента верификации | ||
+ | в конкретном тесте: А. не изменяя ни единой строки кода и Б. не заставляя автора | ||
+ | компонента верификации предвидеть все возможные модификации. | ||
+ | Ему достаточно просто воспользоваться фабричным методом. Так что это весьма полезный механизм. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=8|600px]] | |
− | + | ||
− | + | Мы рассмотрели метод build, применяемый для конструирования компонентов в | |
− | + | окружении верификации. Далее идет метод connect, который служит для соединения компонентов | |
+ | более низкого уровня между собой. В данном случае соединяются драйвер и контроллер. | ||
+ | Как видите, метод connect агента вызывает метод connect драйвера, | ||
+ | чтобы соединить оба компонента нижнего уровня. Сам код соединения – это | ||
+ | обычный исполняемый код. Технически его можно было бы включить в метод build, | ||
+ | и все работало бы точно так же. Однако стилистически правильнее и | ||
+ | настоятельно рекомендуется размещать код соединения компонентов нижнего уровня | ||
+ | в теле метода connect, хотя бы из соображений единообразия. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=9|600px]] | |
− | + | ||
− | + | Взглянув на код метода connect более пристально, вы увидите ссылки на два | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | Взглянув на код метода connect | + | |
− | более пристально, | + | |
− | + | ||
− | вы увидите ссылки на два | + | |
выделенных жирным шрифтом компонента: | выделенных жирным шрифтом компонента: | ||
Строка 313: | Строка 111: | ||
sequence_item_export. | sequence_item_export. | ||
− | Понятия порта и экспортера - выходцы из мира | + | Понятия порта и экспортера - выходцы из мира моделирования на уровне транзакций. |
− | моделирования на уровне транзакций. | + | Они заимствованы из стандарта System C TLM. В данном контексте можно считать, что |
+ | порты и экспортеры – это просто описатели дочерних компонентов, необходимые для того, | ||
+ | чтобы их можно было связать. Итак, чтобы связать драйвер с контроллером, | ||
+ | мы берем описатель драйвера, sequence_item_port, описатель контроллера, | ||
+ | sequence_item_export, и соединяем их, устанавливая соединение | ||
+ | между контролем и драйвером. Можете считать, что эти порты уровня транзакций | ||
+ | - своеобразные вариации на тему портов в системах Verilog или VHDL. | ||
+ | На самом деле, они не полностью эквивалентны портам VHDL или Verilog, | ||
+ | но, если смотреть с высоты птичьего полета, то выполняют они ту же функцию | ||
+ | соединения между собой деталей внутреннего устройства отдельных компонентов. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=10|600px]] | |
− | + | ||
− | + | Итак, я познакомил вас с методами build и connect, | |
− | + | которые в OVM называются фазовыми методами. А теперь я опишу сами фазы OVM | |
+ | более формально. Идея в том, что каждый компонент | ||
+ | в иерархии верификации должен сконструировать свои дочерние компоненты | ||
+ | и должен обладать неким основным поведением, выполняемым в ходе моделирования. | ||
+ | Кроме того, он может выполнять какие-то служебные функции: открывать файлы, | ||
+ | выводить результаты и так далее. Поэтому действия всех компонентов верификации | ||
+ | в процессе моделирования необходимо координировать. Именно для этого и предназначены | ||
+ | стандартные фазы OVM. Каждый компонент выполняет стандартный набор фаз. | ||
+ | Этот механизм позволяет координировать поведение всех компонентов, входящих в | ||
+ | иерархию верификации. Давайте рассмотрим пример. Мы создадим | ||
+ | пользовательский класс my_component, расширяющий базовый класс ovm_component. | ||
+ | Как вы, наверное, помните, класс ovm_component является базовым | ||
+ | для целого семейства различных классов компонентов. Обычно | ||
+ | выбирается какой-то конкретный класс, скажем ovm_agent, ovm_driver или ovm_monitor, | ||
+ | который отражает ваше намерение. Но технически вполне допустимо | ||
+ | создавать пользовательский класс, расширяя ovm_component. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=11|600px]] | |
− | + | ||
− | + | В данном примере мы так и поступим. Кое-что из показанного в этом примере мы | |
− | + | уже видели раньше. Начинаем с метода new. Метод new, строго говоря, не является | |
+ | фазой, это просто конструктор, часть языка SystemVerilog. | ||
+ | Но для удобства можете считать, что это фаза 0. Как правило, в OVM метод new не должен делать | ||
+ | ничего, кроме вызова метода new базового класса. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=12|600px]] | |
− | + | ||
− | + | Далее идет метод build, который мы начали писать ранее. Он создает | |
− | + | дочерние компоненты. Как я уже отмечал, методы new и build должны | |
− | + | вызывать соответственно методы new и build базового класса. | |
− | + | Таким образом, оба метода new и build вызываются в порядке строго сверху вниз, | |
− | + | то есть начиная с уровня окружения верификации вглубь. | |
− | + | Пока вы еще не освоились с OVM более основательно, очень важно помнить, что компоненты | |
− | + | в окружении верификации строятся сверху вниз. Напротив, все остальные фазовые методы | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | Далее идет метод build, который мы начали | + | |
− | писать ранее. Он создает | + | |
− | + | ||
− | дочерние компоненты. | + | |
− | + | ||
− | Как я уже отмечал, методы new и build должны | + | |
− | вызывать соответственно методы new и build | + | |
− | + | ||
− | базового класса. | + | |
− | + | ||
− | Таким образом, оба метода new и build | + | |
− | вызываются в порядке строго сверху вниз, | + | |
− | + | ||
− | то есть начиная с уровня окружения | + | |
− | верификации вглубь. | + | |
− | + | ||
− | Пока вы еще не освоились с OVM более | + | |
− | основательно, | + | |
− | + | ||
− | очень важно помнить, что компоненты | + | |
− | + | ||
− | в окружении верификации строятся | + | |
− | сверху вниз. | + | |
− | + | ||
− | Напротив, все остальные фазовые методы | + | |
вызываются снизу вверх. | вызываются снизу вверх. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=13|600px]] | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | Следующей стандартной фазой (необязательной) является фаза соединения, | |
− | + | на которой соединяются порты и экспортеры дочерних компонентов, а точнее | |
+ | их виртуальные интерфейсы. Методы connect вызываются снизу вверх, | ||
+ | начиная с компонентов верификации самого нижнего уровня. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=14|600px]] | |
− | + | ||
− | + | Затем идет стандартная фаза start_of_simulation, которая, как следует из названия, | |
− | + | вызывается в начале моделирования. Название этой фазы заимствовано | |
+ | из системы System C. В System C имеется аналогичный обратный вызов, | ||
+ | выполняемый в начале моделирования, и называется он точно так же: | ||
+ | start_of_simulation. Обычно на этой фазе производятся такие | ||
+ | служебные операции, как открытие файлов для чтения или записи в процессе моделирования. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=15|600px]] | |
− | + | Затем начинается само моделирование, оно выполняется на фазе run, | |
− | + | и, как мы видели раньше, run - это единственная задача. | |
+ | В Verilog задача, конечно, может быть продолжительной, | ||
+ | выполнять обработчики событий, расходуя на это модельное время. | ||
+ | За фазой run следуют еще две фазы, предназначенные для выполнения | ||
+ | служебных операций в самом конце моделирования. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=16|600px]] | |
− | + | ||
− | + | На слайде показана фаза report, на которой можно вывести отчет о результатах | |
− | + | после того как собственно моделирование завершилось. Таким образом, фазовые методы позволяют | |
+ | координировать и синхронизировать действия разнообразных компонентов, | ||
+ | находящихся на разных уровнях иерархии верификации. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=17|600px]] | |
− | + | ||
− | + | Резюмируем все, что мы узнали об анатомии компонента OVM. | |
− | + | Компания Mentor настоятельно рекомендует при написании компонента OVM | |
+ | располагать его элементы в порядке, показанном на данном слайде. | ||
+ | Так, во второй строке мы всегда регистрируем компонент в библиотеке классов OVM. | ||
+ | Затем объявляются все внешние интерфейсы, включая как виртуальные интерфейсы, | ||
+ | так и порты и экспортеры, если их необходимо объявить явно. | ||
+ | Далее идут объявления описателей внутренних компонентов, | ||
+ | в данном случае контроллера и драйвера. И потом все стандартные фазовые методы | ||
+ | в надлежащем порядке: сначала конструктор, за ним | ||
+ | собственно фазы, build, connect и так далее. | ||
− | + | [[file:module_basic_ovm_session5_connecting_components_jaynsley.pdf|page=18|600px]] | |
− | + | ||
− | координировать и суммировать действия | + | Итак, на этом занятии я объяснил, как создавать экземпляры нескольких компонентов |
− | всех агентов. | + | в иерархии верификации. Мы видели, что использование фабричных |
+ | методов позволяет создавать компоненты так, чтобы в отдельных тестах | ||
+ | один компонент можно было подменить другим. Мы видели, что стандартные фазы | ||
+ | используются для координации действий нескольких компонентов. | ||
+ | А также что OVM предписывает способ структурирования компонентов верификации | ||
+ | с тем, чтобы повысить степень их повторного использования, | ||
+ | а также поддержать единый стиль кодирования. Мы познакомились с типичной структурой: | ||
+ | имеется так называемый агент, который состоит из контроллера, | ||
+ | драйвера и монитора, а окружение верификации обычно содержит | ||
+ | несколько агентов. Как правило, один агент представляет один | ||
+ | коммуникационный канал, шину или порт в тестируемом устройстве. | ||
+ | Например, если в тестируемом устройстве имеется шина Amber, | ||
+ | то в качестве ее формирователя мог бы выступать агент Amber. | ||
+ | Если имеется USB-соединение, то для USB-порта заводится отдельный агент. И так далее. | ||
+ | Окружение верификации, как правило, содержит несколько агентов, | ||
+ | по одному для каждого из основных интерфейсов тестируемого устройства. | ||
+ | А, помимо них, существуют другие компоненты верификации, задача которых - | ||
+ | координировать и суммировать действия всех агентов. |
Текущая версия на 13:14, 25 ноября 2013
Здравствуйте, я Джон Эйнли из компании Дулос. Это пятое занятие по основам OVM. Его тема - соединение компонентов. Мы познакомимся с тем, как создавать несколько компонентов OVM в окружении верификации и как собирать их воедино. Также мы подробнее рассмотрим архитектуру отдельного компонента.
На предыдущем занятии я говорил, что типичный компонент OVM состоит из контроллера, драйвера и монитора. Идея в том, чтобы использовать компонент как стандартный строительный блок в окружении верификации OVM. Такая конфигурация компонентов называется агентом. Эта структура не является единственно возможной. Вы не обязаны строить окружение верификации исключительно из агентов с такой структурой, однако это неплохая отправная точка, позволяющая обеспечить стандартизацию и согласованность между компонентами верификации из различных источников. Поэтому при обсуждении создания и соединения компонентов будет разумно использовать описанную структуру агентов в качестве примера, отправной точки. И именно так мы сейчас и поступим.
Я уже неоднократно упоминал компоненты OVM, и теперь самое время взглянуть на формальную иерархию классов OVM. Здесь мы вступаем на территорию объектно-ориентированного программирования. На слайде представлена диаграмма иерархии классов в обозначениях, немного напоминающих язык UML. Классы, изображенные ниже, расширяют, или наследуют тем, что изображены выше. Внутри широкой рамки в нижней части диаграммы показаны все виды компонентов OVM. Они применяются для описания структуры. В OVM имеется много классов, причем все они наследуют единственному базовому классу ovm_component, который в свою очередь является производным от класса ovm_report_object, а тот - от класса ovm_object, с которым мы встречались на предыдущем занятии. В нижней части диаграммы мы видим различные компоненты OVM, в частности ovm_env для уже знакомого нам ovm_test, а также такие компоненты, как ovm_agent и ovm_driver. Позже мы узнаем, что некоторые из компонентов полностью взаимозаменяемы и отличаются только названиями. Но есть также компоненты с уникальными свойствами, присущими только им. Во многих случаях у вас есть выбор. Например, можно воспользоваться как ovm_env, так и ovm component. А это означает, что выбор того или иного компонента OVM - вопрос стиля кодирования и единообразия, а не технической необходимости. Тем не менее, на данном занятии я буду выбирать подходящий тип компонента исходя из той роли, которую он играет.
Стало быть, в данном случае мы возьмем компонент ovm_agent. Итак, создадим определенный пользователем компонент верификации, расширив базовый класс ovm_agent. Однако подчеркну еще раз: я мог бы расширить ovm_component, или даже ovm_monitor или ovm_env, и в данном случае получился бы точно такой же результат.
Итак, в строке 2 мы регистрируем my_agent как ovm_component. Это стандартный код, который следует включать обязательно. Впоследствии агент будет создавать экземпляры контроллера и драйвера, поэтому мы объявляем в классе два описателя: my_sequencer_h и my_driver_h.
Далее следует метод new, конструктор класса, и стандартные методы, build и connect. С методом build мы уже встречались ранее, а метод connect для нас внове. Он служит для соединения дочерних компонентов, и чуть позже я подробнее объясню, как он работает.
Однако начнем с расширения метода build. Сначала метод build, как обычно, вызывает метод базового класса super.build,а затем создает экземпляры контроллера и драйвера, с помощью волшебного заклинания type_id::create. Передаваемые методу create аргументы очень важны. Первый аргумент, как и раньше, это имя экземпляра,которое должно совпадать с именем переменной. Второй аргумент – родитель, мы всегда будем использовать в этом качестве "this", встроенную в SystemVerilog переменную, которая обозначает текущий объект, с которым мы работаем. В объектно-ориентированной терминологии метод create называется фабричным. Фабричные методы - это один из так называемых паттернов объектно-ориентированного программирования, то есть заведомо хороших способов решить определенную задачу.Конкретно, фабричный метод позволяет создать объект и в то же время переопределить тип объекта, создаваемого где-то в другом месте. На первый взгляд кажется, что здесь мы создаем объекты типа my_sequencer и my_driver, и по умолчанию так оно и есть. Однако имеется возможность переопределить типы компонентов, создаваемых этими фабричными методами. Так, в каком-то конкретном тесте, не изменяя исходный код данного конкретного агента ни на йоту, мы могли бы переопределить поведение фабричных методов, заставив их создавать иные компоненты, последовательности или драйверы. С помощью этого механизма мы можем настраивать поведение того или иного компонента верификации в конкретном тесте: А. не изменяя ни единой строки кода и Б. не заставляя автора компонента верификации предвидеть все возможные модификации. Ему достаточно просто воспользоваться фабричным методом. Так что это весьма полезный механизм.
Мы рассмотрели метод build, применяемый для конструирования компонентов в окружении верификации. Далее идет метод connect, который служит для соединения компонентов более низкого уровня между собой. В данном случае соединяются драйвер и контроллер. Как видите, метод connect агента вызывает метод connect драйвера, чтобы соединить оба компонента нижнего уровня. Сам код соединения – это обычный исполняемый код. Технически его можно было бы включить в метод build, и все работало бы точно так же. Однако стилистически правильнее и настоятельно рекомендуется размещать код соединения компонентов нижнего уровня в теле метода connect, хотя бы из соображений единообразия.
Взглянув на код метода connect более пристально, вы увидите ссылки на два выделенных жирным шрифтом компонента:
sequence_item_port и sequence_item_export.
Понятия порта и экспортера - выходцы из мира моделирования на уровне транзакций. Они заимствованы из стандарта System C TLM. В данном контексте можно считать, что порты и экспортеры – это просто описатели дочерних компонентов, необходимые для того, чтобы их можно было связать. Итак, чтобы связать драйвер с контроллером, мы берем описатель драйвера, sequence_item_port, описатель контроллера, sequence_item_export, и соединяем их, устанавливая соединение между контролем и драйвером. Можете считать, что эти порты уровня транзакций - своеобразные вариации на тему портов в системах Verilog или VHDL. На самом деле, они не полностью эквивалентны портам VHDL или Verilog, но, если смотреть с высоты птичьего полета, то выполняют они ту же функцию соединения между собой деталей внутреннего устройства отдельных компонентов.
Итак, я познакомил вас с методами build и connect, которые в OVM называются фазовыми методами. А теперь я опишу сами фазы OVM более формально. Идея в том, что каждый компонент в иерархии верификации должен сконструировать свои дочерние компоненты и должен обладать неким основным поведением, выполняемым в ходе моделирования. Кроме того, он может выполнять какие-то служебные функции: открывать файлы, выводить результаты и так далее. Поэтому действия всех компонентов верификации в процессе моделирования необходимо координировать. Именно для этого и предназначены стандартные фазы OVM. Каждый компонент выполняет стандартный набор фаз. Этот механизм позволяет координировать поведение всех компонентов, входящих в иерархию верификации. Давайте рассмотрим пример. Мы создадим пользовательский класс my_component, расширяющий базовый класс ovm_component. Как вы, наверное, помните, класс ovm_component является базовым для целого семейства различных классов компонентов. Обычно выбирается какой-то конкретный класс, скажем ovm_agent, ovm_driver или ovm_monitor, который отражает ваше намерение. Но технически вполне допустимо создавать пользовательский класс, расширяя ovm_component.
В данном примере мы так и поступим. Кое-что из показанного в этом примере мы уже видели раньше. Начинаем с метода new. Метод new, строго говоря, не является фазой, это просто конструктор, часть языка SystemVerilog. Но для удобства можете считать, что это фаза 0. Как правило, в OVM метод new не должен делать ничего, кроме вызова метода new базового класса.
Далее идет метод build, который мы начали писать ранее. Он создает дочерние компоненты. Как я уже отмечал, методы new и build должны вызывать соответственно методы new и build базового класса. Таким образом, оба метода new и build вызываются в порядке строго сверху вниз, то есть начиная с уровня окружения верификации вглубь. Пока вы еще не освоились с OVM более основательно, очень важно помнить, что компоненты в окружении верификации строятся сверху вниз. Напротив, все остальные фазовые методы вызываются снизу вверх.
Следующей стандартной фазой (необязательной) является фаза соединения, на которой соединяются порты и экспортеры дочерних компонентов, а точнее их виртуальные интерфейсы. Методы connect вызываются снизу вверх, начиная с компонентов верификации самого нижнего уровня.
Затем идет стандартная фаза start_of_simulation, которая, как следует из названия, вызывается в начале моделирования. Название этой фазы заимствовано из системы System C. В System C имеется аналогичный обратный вызов, выполняемый в начале моделирования, и называется он точно так же: start_of_simulation. Обычно на этой фазе производятся такие служебные операции, как открытие файлов для чтения или записи в процессе моделирования.
Затем начинается само моделирование, оно выполняется на фазе run, и, как мы видели раньше, run - это единственная задача. В Verilog задача, конечно, может быть продолжительной, выполнять обработчики событий, расходуя на это модельное время. За фазой run следуют еще две фазы, предназначенные для выполнения служебных операций в самом конце моделирования.
На слайде показана фаза report, на которой можно вывести отчет о результатах после того как собственно моделирование завершилось. Таким образом, фазовые методы позволяют координировать и синхронизировать действия разнообразных компонентов, находящихся на разных уровнях иерархии верификации.
Резюмируем все, что мы узнали об анатомии компонента OVM. Компания Mentor настоятельно рекомендует при написании компонента OVM располагать его элементы в порядке, показанном на данном слайде. Так, во второй строке мы всегда регистрируем компонент в библиотеке классов OVM. Затем объявляются все внешние интерфейсы, включая как виртуальные интерфейсы, так и порты и экспортеры, если их необходимо объявить явно. Далее идут объявления описателей внутренних компонентов, в данном случае контроллера и драйвера. И потом все стандартные фазовые методы в надлежащем порядке: сначала конструктор, за ним собственно фазы, build, connect и так далее.
Итак, на этом занятии я объяснил, как создавать экземпляры нескольких компонентов в иерархии верификации. Мы видели, что использование фабричных методов позволяет создавать компоненты так, чтобы в отдельных тестах один компонент можно было подменить другим. Мы видели, что стандартные фазы используются для координации действий нескольких компонентов. А также что OVM предписывает способ структурирования компонентов верификации с тем, чтобы повысить степень их повторного использования, а также поддержать единый стиль кодирования. Мы познакомились с типичной структурой: имеется так называемый агент, который состоит из контроллера, драйвера и монитора, а окружение верификации обычно содержит несколько агентов. Как правило, один агент представляет один коммуникационный канал, шину или порт в тестируемом устройстве. Например, если в тестируемом устройстве имеется шина Amber, то в качестве ее формирователя мог бы выступать агент Amber. Если имеется USB-соединение, то для USB-порта заводится отдельный агент. И так далее. Окружение верификации, как правило, содержит несколько агентов, по одному для каждого из основных интерфейсов тестируемого устройства. А, помимо них, существуют другие компоненты верификации, задача которых - координировать и суммировать действия всех агентов.