Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Верификация цифровых устройств. Курс лекций. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
06.09.2026
Размер:
1 Мб
Скачать
даже в другой файл при необходимости. Тогда, чтобы указать, что реализуется функция из класса, перед именем функции ставится имя класса и
class bus_operation;
endclass: bus_operation
function void bus_operationdisplay(); $display("Addr: %h Data: %h ", addr, data); endfunction
∷ .
bit[31:0] addr, cmd,data[32]; extern function void display();
3.2.2. Наследование
В работе достаточно часто может возникать необходимость в
создании похожих классов. Например, операции чтения и записи на шине могут иметь много общих полей и методов, таких как вычис­ление контрольной суммы, передача адреса и т.п. Создание двух разных классов – это дополнительная работа и возможность внесе­ния новых ошибок.
Для решения таких задач SystemVerilog поддерживает механиз-
мы наследования. В примере ниже можно выделить общие данные и методы операций чтения и записи в отдельный класс, а затем унаследовать от него два класса для каждой операции. Пример наследования:
class bus_operation;
bit[31:0] addr, data[32];
... endclass
class write_bus_operation extends bus_operation;
const bit[31:0] cmd = 1; ...
endclass
class read_bus_operation extends bus_operation;
constbit[31:0] cmd = 2; ...
endclass
– 31 –
Классы-наследники будут иметь все те же поля и методы, кото-
рые были у базового класса. Если конструктор базового класса имеет какие-либо аргументы, то конструктор в классе-наследнике должен иметь свой конструктор и вызывать конструктор базового класса в первой строке своего конструктора, используя ключевое слово super:
super.new(init);
Как и в С++, в SystemVerilog можно переопределять функции в
классах-наследниках. Для этого функция в базовом классе должна быть помечена как виртуальная. Пример перегрузки функций:
class bus_operation;
virtual function void display;
$display("Addr: %h Data: %h ", addr, data);
endfunction endclass
class write_bus_operation extends bus_operation;
virtual function void display;
super.display(); $display("cmd = %d",cmd); endfunction
endclass
При вызове функции display для экземпляра класса
write_bus_operation вызовется функция, описанная в этом классе,
а не функция родительского класса.
С классами-наследниками можно работать, используя дескрип­тор на базовый класс. Поскольку класс-наследник копирует все по­ля базового класса, то обращения к таким полям доступны на осно­ве любого дескриптора.
bus_operation bo;
write_bus_operation wbo;
wbo = new();
bo = wbo;
$display(bo.addr);
bo.display;
– 32 –
При обращении к полю адреса будет успешно напечатан адрес операции. Но, несмотря на то, что используется дескриптор на ба­зовый класс, вызов функции
display вызовет функцию класса-
наследника, так как она была переопределена. В SystemVerilog для функций, объявленных виртуальными, для определения типа вы­зываемой функции используется не тип дескриптора, а тип объекта, на который он показывает. Если не указывать функцию как
al, то будет вызываться функция, соответствующая типу дескрип-
virtu-
тора.
Если рассмотреть обратную ситуацию, когда дескриптор класса­наследника показывает на объект базового класса, то это недопу­стимо и вызовет ошибку компилятора. Соответственно, если необ­ходимо присвоить классу-наследнику значение дескриптора из ба­зового класса, необходимо выполнять проверку, что тот указывает на верный объект. Для этого применяется функция
$cast:
wbo = new();
bo = wbo;
if(!$cast(tmp, bo))$display("cannot assign tmp to bo ");
Дескриптор tmp будет указывать на объект, только если его тип соответствует типу дескриптора; т.е., если объявить
read_bus_operation tmp;
то присвоение выполнено не будет и функция $cast вернет false в качестве результата.
SystemVerilog позволяет создавать абстрактные классы – это классы, которые используются как основа для других классов, но при этом нельзя создавать объекты такого типа. В рассмотренном выше примере класс bus_operation можно объявить абстрактным. Для этого надо при объявлении класса указать ключевое слово
virtual.
virtual class bus_operation;
pure virtual function void display(); ...
endclass
– 33 –
Можно создать дескриптор с типом bus_operation, но не объект такого типа. Методы виртуальных классов не обязательно должны быть реализованы. Они могут быть объявлены как чисто виртуаль­ные методы с использованием ключевого слова pure. Такие методы обязательно должны быть перегружены в классах-наследниках, чтобы иметь возможность создать объекты данного типа.
3.2.3. Параллельные потоки
В простом Verilog есть два способа группировки операторов – с помощью операторов ры
begin ... end выполняются последовательно, а операторы
fork ... join – параллельно. Последние очень ограничены в том,
что все операции внутри того, как программа сможет продолжаться. SystemVerilog пред­ставляет два новых способа создания потоков – с помощью опера­торов
fork ... join _none и fork ... join_any. join_none не
ждет завершения потоков и продолжает работу сразу после их со­здания,
join_any ждет завершения одного любого потока.
initial begin $display("@%0t: start fork...join example", $time); #10 $display("@%0t: sequential after #10", $time); fork $display("@%0t: parallel start", $time); #50 $display("@%0t: parallel after #50", $time); #10 $display("@%0t: parallel after #10", $time); begin #30 $display("@%0t: sequential after #30", $time); #10 $display("@%0t: sequential after #10", $time); end join $display("@%0t: after join", $time); #80 $display("@%0t: finish after #80", $time);
end
Все операции между fork-join будут выполняться параллельно, операции между
join может быть заменен на join_none или join_any. Результаты
при работе с разными типами join представлены ниже:
begin ... end или fork ... join. Операто-
fork ... join должны завершиться до
begin ... end выполняются последовательно.
– 34 –
fork ... join join _none join_any
@0: start fork...join ex­ample @10: sequential after #10 @10: parallel start @20: parallel after #10 @40: sequential after #30 @50: sequential after #10 @60: parallel after #50 @60: after join @140: finish after #80
@0: start fork...join @10: sequential after #10 @10: after join @10: parallel start @20: parallel after #10 @40: sequential after #30 @50: sequential after #10 @60: parallel after #50 @90: finish after #80
@0: start fork...join ex­ample @10: sequential after #10 @10: parallel start @10: after join @20: parallel after #10 @40: sequential after #30 @50: sequential after #10 @60: parallel after #50 @90: finish after #80
– 35 –
Лекция 4. UVM структура тестового окружения
Введение
В лекции представлена методология UVM. Описана история ее создания и предшествующие этому процессы. Рассмотрена общая архитектура тестового окружения, построенного в соответствии с данной методологией. Основу взаимодействия внутри этого окру­жения составляет механизм TLM. Также подробно рассмотрен принцип работы TLM, типы и назначение основных видов портов и протоколы взаимодействия.
4.1. История UVM
Универсальная методология проверки (Universal Verification Methodology (UVM)) – стандартизированная методология верифи­кации интегральных схем. UVM является развитием OVM (Open Verification Methodology – методологии открытой верификации), которая в значительной степени основана на eRM (e Reuse Methodology).
Методология e Reuse (eRM) была первой методологией верифи­кации, ориентированной на повторное использование верификаци­онного окружения. eRM использовала язык everification language, разработанный Verisity Design в 2001 г. и выпущенный в 2002 г. Методология была составлена из методических рекомендаций по таким темам, как:
«Соглашения об именах файлов»;
«Функциональное разбиение тестового стенда»;
«Рекомендации по упаковке кода»;
«Библиотеки последовательностей и классов сообщений».
Методология eRM получила широкое распространение и одоб­рение среди инженеров-верификаторов.
В 2006 г. компания Mentor Graphics выпустила библиотеку базо­вых классов, написанную в SystemVerilog, – «Усовершенствован­ная методология проверки» (Advanced Verification Methodology – AVM). Чуть позже, в 2007 г., Cadence выпускает свою библиоте-
– 36 –
ку – URM (Universal Reuse Methodology) – «Универсальная мето­дология повторного использования». Из основных особенностей обеих библиотек можно отметить использование TLM транзакций и open-source реализацию.
В 2008 г. Mentor и Cadence совместно выпускают Open Verifica­tion Methodology (OVM) – «Открытая методология верификации». OVM имела несколько версий, последняя версия, OVM 2.1.2, вы­пущена в 2011 г.
Заключительный на данный момент шаг развития – библиотека классов UVM. Она значительно упрощает разработку верификаци­онных окружений, автоматизируя многие процессы, например, ге­нерацию последовательностей и базовые операции с данными – такие как копирование, сравнение, упаковка. Данная методология в отличие от предыдущих разрабатывалась независимо от поставщи­ков симуляторов. Она является стандартом компании Accellera с поддержкой нескольких поставщиков: Aldec, Cadence, Mentor­Graphics и Synopsys.
4.2. Архитектура тестового окружения UVM
Библиотека классов UVM предоставляет базовые элементы, та­кие как иерархия компонентов, модель транзакций (TLM), конфи­гурационная база данных и т.д., которые позволяют разработчику ускорить создание тестового окружения. На рис. 4.1 представлена обычная архитектура тестового окружения, построенного на базе UVM. Она соответствует общим рекомендациям для тестового окружения для случайного тестирования.
Верхний модуль Testbench предназначен для подключения те­стируемого устройства DUT и тестового окружения. Test является компонентом UVM верхнего уровня в тестовом окружении. Тест UVM обычно выполняет три основные функции: создание тестово­го окружения, его настройку и формирование тестовых последова­тельностей. Как правило, создается один базовый класс теста с подключенным объектом тестовой среды и другими общими для всех тестов компонентами, а затем создаются отдельные тесты как наследники базового.
– 37 –
Рис. 4.1. Тестовое окружение UVM
Environment – тестовое окружение. Его задача – объединение всех остальных компонент тестового окружения. При этом может быть несколько уровней Environment. Для каждого интерфейса мо­жет быть свое тестовое окружение, затем они могут объединяться по подсистемам и наконец – общая среда верхнего уровня.
Задача Scoreboard – проверять поведение DUT. Он принимает транзакции с входов и выходов DUT, выполняет транзакции через некую эталонную модель для получения ожидаемых результатов, а затем сравнивает ожидаемый результат с фактическим выходом.
Agent работает с отдельными интерфейсами DUT. Как правило, агент включает в себя генератор последовательностей Sequencer для управления потоком сигналов, драйвер Driver – для формиро­вания воздействия на физическом уровне и монитор Monitor – для наблюдения за интерфейсом.
– 38 –
Генератор последовательностей управляется последовательно­стями. Они не входят в иерархию тестового окружения. Последова­тельности могут иметь свою иерархию, где одна последователь­ность запускает несколько других. Последовательности могут от­носиться к одной транзакции и создаваться как на время, так и ра­ботать постоянно все время моделирования.
4.3. TLM
Как отмечалось ранее, при разработке тестового окружения важно правильно выбирать необходимые уровни абстракции в ра­боте с данными. При тестировании устройства, которое обрабаты­вает пакеты данных, для того чтобы получить эти пакеты, нет необходимости задумываться о физическом уровне и сигналах ши­ны, которые будут эти пакеты передавать. Хотя фактический ин­терфейс к тестируемому устройству в конечном итоге представляет собой отдельные сигналы, но формирование пакетов и поверка ре­зультатов должны выполняться на уровне транзакций.
UVM предоставляет набор интерфейсов и каналов связи на уровне транзакций, которые можно использовать для соединения элементов верификационного окружения на уровне транзакций – TLM. Использование универсального интерфейса для передачи данных между компонентами позволяет безболезненно заменять одни элементы другими.
Эта концепция также позволяет собрать тестовое окружение по UVM с моделью DUT на уровне транзакций, а затем повторно ис­пользовать это же окружение для тестирования RTL. Все, что тре­буется – это заменить модель уровня транзакций на RTL, добавив необходимый интерфейс.
В библиотеке UVM предусмотрены две версии TLM. TLM-1 – система передачи сообщений. Эти интерфейсы не связаны между собой. Ни один из интерфейсов не обеспечивает явных аннотаций синхронизации. TLM-2.0, хотя и позволяет передавать данные и синхронизировать их передачу между независимыми процессами, в основном предназначен для высокопроизводительного моделиро-
– 39 –
вания систем на основе шины с отображением в памяти. В данном курсе рассматривается только TLM-1.
В UVM транзакция – это объект класса, который включает лю­бую информацию, необходимую для моделирования единицы свя­зи между двумя компонентами. Количество и тип информации в транзакциях определяется уровнем абстракции, на котором данная транзакция используется. При этом транзакции могут включать в себя в том числе и другие транзакции более низких уровней аб­стракции.
Предположим, что стоит цель – разработать тестовое окружение для проверки IP-ядра последовательного интерфейса UART. IP­ядро имеет две линии – Rx и Tx – для передачи данных через по­следовательный порт и простой шинный интерфейс для подключе­ния к процессору. Отдельные транзакции через последовательный интерфейс тогда можно описать следующим образом:
class uart_trans extends uvm_sequence_item;
byte data;
bit crc;
...
endclass
Класс транзакции унаследован от uvm_sequence_item – базового класса элементов последовательностей. Про последовательности речь пойдет позже. В простейшем случае генератор последователь­ностей должен формировать элементы и передавать их на исполне­ние в драйвер. Для взаимодействия генератора и драйвера в таком случае как раз и применяется интерфейс TLM-1.
TLM интерфейсы определяют набор методов, которые исполь­зуют объекты транзакции в качестве аргументов. Для каждого ин­терфейса определяется понятие порта (port) и экспорта (export). TLM порт определяет набор методов (интерфейс прикладного программирования (API)), который будет использоваться для конкретного соединения, в то время как TLM экспорт обеспе­чивает реализацию этих методов. Подключение порта к экспорту позволяет выполнить реализацию при вызове метода порта (рис. 4.2).
– 40 –