OVM/Basic OVM/Session3 - OVM "Hello World" — различия между версиями
ANA (обсуждение | вклад) (Новая страница: «{{OVM TOC}} 600px Здравствуйте, я – Джон Эйсли из компани…») |
ANA (обсуждение | вклад) м |
||
Строка 1: | Строка 1: | ||
{{OVM TOC}} | {{OVM TOC}} | ||
− | [[file:module_basic_ovm_session3_ovm_hello_world_jaynsley.pdf| | + | [[file:module_basic_ovm_session3_ovm_hello_world_jaynsley.pdf|page=1|600px]] |
Здравствуйте, я – Джон Эйсли из компании | Здравствуйте, я – Джон Эйсли из компании |
Версия 19:07, 21 ноября 2013
Здравствуйте, я – Джон Эйсли из компании Doulos.
Это третье занятие в серии Основы OVM – OVM «Hello World».
Сейчас мы перейдем от общей информации
об OVM и обратимся к конкретному коду
OVM.
Оставшиеся занятия будут адресованы инженерам-практикам.
Вероятно, вы уже пользовались VHDL или Verilog, может быть, вам уже что-то
известно из SystemVerilog, и я помогу вам начать пользоваться именно OVM.
Итак, идея с OVM «Hello World» – в том, чтобы дать вам реальный эквивалент в
OVM программы C Hello World. Если вы помните, программа Hello World
на языке C – это знаменитая однострочная программа, почти самая короткая из
возможных программа на языке C, которая просто что-то печатает и делает нечто
разумное.
Теперь мы попытаемся сделать то же
самое с OVM.
Однако, чтобы сделать ее осмысленной, программа OVM Hello World фактически
более сложна, чем программа на языке C,
поскольку нам необходима работа
нескольких ключевых элементов.
Поэтому первое, что нам необходимо – это
тестируемая система, или DUT.
Это будет модуль SystemVerilog, который
может быть оберткой для компонента в
другом языке.
Возможно, ваш DUT написан на VHDL – отлично.
Тогда у нас есть верификационная среда, и если вы изучали предыдущие модули,
предыдущие занятия в этом модуле, вы
увидите, что верификационная среда OVM
разделяется на две части: фиксированную
часть, называемую env, т.е. собственно верификационную среду, и переменную
часть, которая представляет собой ovm_test.
Верификационная среда в OVM основана на
классах, так что и тесты, и среда строятся
почти исключительно на основе классов
SystemVerilog, по сравнению с тестируемой
системой, которая была структурной и модульной.
Чтобы создать мостик между основанной на классах верификационной среде и
тестируемой системой, мы используем интерфейс SystemVerilog.
Оказывается, что интерфейс SystemVerilog – самый практичный способ соединения в
SystemVerilog основанного на классах и
модульного кода.
Итак, у нас структурный интерфейсный
модуль и основанная на классах
верификационная среда.
Вся система целиком затем экземплифицируется из модуля
SystemVerilog. Итак, нашим верхним уровнем будет
модуль SystemVerilog – этот модуль SystemVerilog будет экземплифицировать
нашу тестируемую систему, интерфейс SystemVerilog и верификационную среду,
которая состоит из env и test.
Итак, это – общая структура примера, который я собираюсь показать вам.
Теперь нырнем поглубже и рассмотрим код
подробно, начав с интерфейса.
Логически интерфейс SystemVerilog
должен быть первым для компиляции в
SystemVerilog, поскольку он создает общий интерфейс как для верификационной
среды, так и для тестируемого устройства.
И фактически в нашей программе «Hello
World» интерфейс пуст.
Нам не нужно ничего в нем.
Здесь представлен код, который вы бы
фактически написали в интерфейсе, если
бы это была реально тестируемая система.
Вам нужно экземплифицировать штырьки в
DUT.
В данном случае оно может быть пусто.
Затем сама тестируемая система, которая в
данном случае является пустым модулем.
Тестируемая система учитывает интерфейс SystemVerilog в первой строке, чтобы
определить входы и выходы тестируемой системы.
Некоторые современные инструменты синтеза SystemVerilog фактически
синтезируют модуль в этом формате.
Если вы используете инструмент синтеза,
когда вы не хотите синтезировать
интерфейс SystemVerilog, все, что вам
нужно сделать – написать тестируемую
систему в Verilog или VHDL со списком
отдельных штырьков, входящих в
тестируемую систему или выходящих из нее, а затем просто положить это в
обертку, которая содержит интерфейс SystemVerilog.
Это может быть реальный DUT или обертка вокруг DUT.
Теперь мы дошли до верхнего уровня.
Итак, верхним уровнем будет модуль
Verilog – он экземплифицирует интерфейс,
экземплифицирует тестируемую систему и передает интерфейс в строке
экземплификации тестируемой системы.
На этом мы закончим со структурными
компонентами нашего простого примера
Hello World. Теперь обратимся к среде, основанной на
классах. Здесь приведен первый пример класса
SystemVerilog. Фактически весь код, который мы увидим в
оставшихся занятиях, будет основан на классах.
Мы немного займемся объектно-ориентированным
программированием. Если вы уже знакомы с
объектно-ориентированным программированием SystemVerilog или
другим языком программирования типа C++ или Java, отлично.
Если нет – без паники, я попытаюсь объяснить по ходу дела. Здесь мы создаем
определяемую пользователем верификационную среду под названием
my_env путем расширения ovm_env – класса, встроенного в библиотеку OVM, и
мы создаем свою собственную верификационную среду, расширяя класс,
встроенный в OVM; это – обычный вид объектно-ориентированного
программирования, и мы увидим много
похожего в будущем.
В строке 2 класса нам нужно
зарегистрировать этот класс в библиотеке
OVM как компонент OVM.
Поэтому в каком-то смысле просто нужно помнить о том, что это
нужно сделать. Рекомендуется сделать это во второй
строке определения класса. Эта регистрация дает вам ту
автоматизацию, которая не встроена в SystemVerilog.
Так что нужно просто помнить, что это нужно делать всегда, когда вы пишете
компонент в OVM, но это также имеет некоторую практическую пользу в
автоматизации некоторых вещей, которые
окажутся очень полезными позже.
Третье, что нам нужно сделать – это
написать так называемый конструктор для
класса. Если вам уже знакомо
объектно-ориентированное программирование, вы знаете, что
конструктор – особая функция или метод, который вы пишете внутри класса, который
инициализирует объекты, когда они создаются. Итак, в SystemVerilog
конструктор – это специальная функция под названием new. Если вам ничего не
известно о System-Verilog или объектно-ориентированном
программировании, единственное, о чем вам нужно знать здесь – это то, что каждый
класс должен содержать функцию new, и вам настоятельно рекомендуется
пользоваться именно этим стандартным кодом, когда вы пишете класс в OVM.
Другими словами, нам нужна новая функция с именно двумя параметрами –
именем и предком, который внутри
содержит вызов super.new. super.new – еще
один элемент объектно-ориентированного
программирования.
Мы здесь вызываем конструктор базового класса для данного класса.
Другими словами, мы вызываем конструктор класса ovm_env.
Вам нужно знать о методе build следующее. Если вы новичок в области
объектно-ориентированного программирования, вас может немного
смутить жаргон, которым я пользуюсь.
Метод – это термин, обозначающий
функцию, определенную внутри класса.
Итак, метод – это функция, которая принадлежит конкретному объекту
объектно-ориентированного программирования.
Если вам удобно, когда я говорю о методе build, можно понимать его как
функцию.
Работа метода build – это создание
содержимого данной части
верификационной среды.
В нашей программе «Hello World»
верификационная среда так проста, что
метод build должен только вызывать метод build суперкласса, или базового
класса.
Поэтому очень важно, чтобы этот метод
build вызывал super.build, и если бы это
была реальная верификационная среда, которая бы не только умела говорить «Hello
World», то метод build делал бы и
другие вещи.
Последний элемент в этом классе – метод
run класса, который в данном случае,
как вы видите, представляет собой задачу Verilog.
Метод run в определенном смысле является основным методом этого класса.
Метод run содержит поведение, которое реализуется при моделировании.
Это обычно получается в Verilog путем выписывания блока always или – в VHDL –
путем выписывания оператора процесса.
Фактически задача прогона среды OVM
ведет себя как процесс в VHDL или Verilog.
Так что методы new и build эффективно
исполняются во время разработки для
создания верификационной среды и
экземплификации других компонентов,
а метод run исполняется при
моделировании одновременно с другими
процессами в модели SystemVerilog.
Возможно, вы заметили, что метод build – это функция,
метод run – это задача, так
что именно метод run фактически
потребляет время, потраченное на
моделирование.
В программе Hello World данный конкретный метод run просто запускает
моделирование на 10 единиц времени, так что мы начинаем с контроля времени #10,
который запускает моделирование на 10 единиц времени, а затем эта
верификационная среда останавливает моделирование, вызывая запрос останова.
Здесь мы видим метод top.stop_request. Думаю, понятие запроса на останов не
требует подробных объяснений – название говорит само за себя, запрос останавливает
моделирование. ovm_top – это имя объекта, и в частности, этот объект –
высокоуровневый объект иерархии
компонентов.
Так, ovm_top – имя объекта, этот объект
является экземпляром класса, и этот
объект – верхний уровень нашей верификационной среды OVM.
Это – верхний уровень верификационной среды, как противоположность модулю
верхнего уровня.
Так что ovm_top – это не модуль верхнего
уровня в иерархии модулей SystemVerilog, а
что-то совсем другое.
ovm_top – объект верхнего уровня в
основанной на классах верификационной
среде. Так что ovm_top основан на классах. Это ПО, элемент программирования, в
противоположность модулю верхнего уровня Verilog или SystemVerilog.
Итак, теперь мы видим среду OVM,
верификационную среду, давайте
рассмотрим test.
Итак, test – еще один класс, определяемый пользователем.
Здесь у нас есть класс под названием my_test и он написан путем расширения
ovm_test. Итак, опять, ovm_test – это класс,
встроенный в библиотеку OVM, и мы создаем определяемый пользователем тест
путем расширения этого встроенного класса test.
Опять же, не следует забывать в строке 2 зарегистрировать этот класс,
определяемый пользователем с OVM с помощью макроса ovm_component_utils.
Тест тогда будет экземплифицировать среду, так что в терминах структуры
нашего кода SystemVerilog у нас есть test вверху, и test сделает экземпляр среды в
качестве компонента.
Итак, здесь, внутри этого класса, у нас есть
атрибут или свойство класса, которое
можно считать переменной типа my_env и
имя переменной – my_env_h, и мы
сознательно используем суффикс _h при
создании этой переменной.
Это рекомендуется, поскольку эта переменная фактически используется как
индекс. В SystemVerilog при создании переменной
тип этой переменной – класс SystemVerilog, тогда эта переменная фактически
содержит ссылку на объект, и эта
переменная также называется индексом
для этого объекта.
Так что когда вы видите суффикс _h, это
напоминает вам о том, что переменная не
буквально сохраняет объект – она
сохраняет индекс или ссылку на этот объект.
Затем у нас есть стандартные методы, которые мы рассматривали ранее.
Итак, у нас есть конструктор, и вы можете заметить, что этот конструктор следует
точно такому же стандартному коду, как в предыдущем классе, который мы
рассматривали, и это делается сознательно.
И метод build, снова метод build вызывает super.build – это очень важно, но
это другое дело.
В этом случае метод build будет
экземплифицировать верификационную
среду, он будет экземплифицировать компонент my_env, который мы видели
раньше. Эта экземплификация выполняется с
помощью довольно длинной строки кода. На данном этапе я хочу вас попросить
просто воспринимать эту строку кода как магическую формулу.
Воспринимайте ее как есть. У нас есть my_env::type_id::create.
Мы вызываем метод create, который связан с my_env::type, чтобы создать экземпляр
данной верификационной среды my_env.
Затем мы сохраняем логический номер, ссылку на только что созданный объект в
переменной my_env.
Я подробно объясню, что происходит здесь
с этим идентификатором типа.
Откровенно говоря, вам необязательно
знать об этом. Все, что вам необходимо знать – это то, чтобы экземплифицировать
компонент в основанной на классах верификационной среде: просто следуйте
этой магической формуле – и все в порядке.
Нужно передать правильные аргументы в
метод create.
Первый аргумент – это строковое имя данного конкретного
компонента в иерархии компонентов.
Очень хорошая идея – сделать строковое
имя тем же самым, что и имя переменной,
которую мы собираемся использовать, чтобы сохранить индекс данного объекта.
Например, в этом примере строковое имя –
my_env_h, и имя индекса – тоже my_env_h.
То, чтобы они были одинаковыми – не
является техническим требованием: это
нужно для вашего удобства.
Второй аргумент для метода create – это
this.
this – это имя, встроенное в SystemVerilog.
this хранит ссылку на текущий объект.
В объектно-ориентированном
программировании любой код, написанный
внутри класса, исполняется в контексте конкретного объекта.
this в SystemVerilog дает индекс этого конкретного объекта.
Другими словами, что касается нашего примера Hello World, здесь вы находимся
внутри тела test, и this указывает на сам
объект test, который будет предком для остальной верификационной среды.
Другими словами, второй аргумент – это создание предка компонента, который мы
экземплифицируем.
Сейчас мы видим класс, представляющий
нашу верификационную среду, класс,
представляющий test, и оказывается, что
лучшее место для размещения этих
классов в коде SystemVerilog – пакет.
Цель при этом – избежать введения
слишком большого количества имен в
исходный код SystemVerilog. Технически вы могли написать эти классы
на верхнем уровне – при этом имена классов стали бы высокоуровневыми
именами, глобальными именами, и они засоряют ваше пространство глобальных
имен. Поэтому лучше определить все свои классы внутри пакета, а затем
единственное имя, которое входит в глобальное пространство имен – это имя
самого пакета, в данном случае – my_pkg.
Чтобы фактически скомпилировать любой
код OVM, а также написать классы и
поместить их в пакет, нам необходимо
воспользоваться директивой правого
включения для включения заголовков.
Поскольку мы пользовались макросом в коде OVM – если помните, мы пользовались
компонентом макроса регистрации – то нам
необходима директива включения Verilog
ovm_macros.svh в верхней части файла;
и нам также нужно импортировать символы
из самого пакета OVM.
Этот пакет встроен в библиотеку OVM,
которая содержит все внутренние
встроенные классы OVM.
Они импортируются с помощью строки import ovm_pkg::*.
Звездочка – это символ, который импортирует все содержимое пакета OVM.
Итак, мы рассмотрели основанную на классах верификационную среду и тест.
Теперь мы закончим создание модуля верхнего уровня.
Раньше мы видели высокоуровневый модуль, который экземплифицировал
интерфейс, экземплифицировал тестируемую систему – теперь нам нужно
экземплифицировать основанную на классах верификационную среду.
Нам нужно несколько утверждений об импорте.
Мы импортируем содержание ovm_pkg,
импортируем содержание нашего
собственного пакета my_pkg::*, а затем из
процедурного блока – первоначальное
утверждение Verilog – мы делаем вызов run_test.
Итак, run_test – это встроенный метод в OVM, который будет фактически выбирать
и запускать тест. Имя теста, который мы запускаем, мы
передаем как аргумент в метод run_test.
Именно здесь вы выбираете конкретный
тест, который вы хотите запустить.
При выполнении run_test обнаружится
класс, который был назван my_test – это
делается с помощью информации, которая
передавалась при регистрации класса.
Он будет экземплифицировать тест,
который в свою очередь экземплифицирует
верификационную среду, и вся
верификационная среда запускается –
мы запускаем свою программу Hello World.
Итак, мы запускаем эту программу, затем
выполняется моделирование, и мы можем
увидеть несколько сообщений, написанных
в окне транскрипта моделирования. Здесь можно увидеть сообщения,
выходящие из Questasim. Если внимательно посмотреть, вы увидите,
что мы запускаем версию 2.1 библиотеки OVM. Мы запускаем оригинальные коды OVM –
вы видите здесь уведомления об авторских правах Mentor и Cadence.
Далее здесь информационное сообщение о
том, что выполняется тест my_test.
my_test – имя нашего конкретного теста,
который запускается здесь. Затем переходим к остальной части
транскрипта. У нас есть краткий отчет OVM – стандартная информация, одно
информационное сообщение.
Предупреждений и ошибок нет, все хорошо.
Наша модель работает хорошо и без ошибок.
И, наконец, у нас есть замечание, говорящее, что моделирование закончено
успешно в момент 10.
Другими словами, наш запрос на останов
был исполнен по плану после того, как
наша верификационная среда потратила 10
единиц времени. Это – как раз то, что мы хотели.
Итак, это – эквивалент в OVM отображения написанного сообщения Hello World.
Итак, на этом занятии я привел очень простой, но полный пример кода OVM, так
что при желании вы можете написать этот код и запустить его.
Этот код работает в реальных условиях.
Мы изучили различие между основанной на
классах верификационной средой и
модульным миром тестируемой системы, и
фактически увидели, как выглядит код
OVM, чтобы разделить переменную и
фиксированную части верификационной
среды, а затем экземплифицировать и начать тест.
Мы рассмотрим это более подробно на следующем занятии.