«Случай — это псевдоним Бога, когда Он не хочет подписываться своим собственным именем.» А. Франс

Проектирование цифровых систем на языках описания аппаратуры/Лекция 12

Материал из Wiki
Перейти к: навигация, поиск
Лекции ПЦСЯОА

Лекции

Практические

Доп. материалы

Заголовок
Введение в OS-VVM и функциональное покрытие (functional coverage).
Автор
Ланкевич Ю.Ю.
Нижний колонтитул
Проектирование цифровых систем на языках описания аппаратуры/Лекция 12
Дополнительный нижний колонтитул
Ланкевич Ю.Ю., 04:20, 2 ноября 2020


Содержание

Слайд:Введение

Слайд:Защищенный тип protected

Защищенный тип (protected) базируется на концепции, похожей на классы в объектно-ориентированном подходе, известном из других языков программирования. Тип protected позволяет объединить данные и операции, выполняемые над ними, в один объект (инкапсуляция), таким образом, скрываются детали реализации типов данных от пользователей.

Полное определение типа protected состоит из двух частей: декларации и тела (body) типа. Объявления в декларативной части типа могут включать декларации подпрограмм (процедур и функций), спецификации атрибутов и конструкции подключения, использующие ключевое слово use. Тела подпрограмм объявляются в теле типа protected. Подпрограммы, описанные при декларации типа protected, называются методами. Ниже приведён пример декларации защищенного типа COUNTER_TYPE:

type COUNTER_TYPE is protected
    procedure Set (num : integer);
    procedure Inc;
    impure function get return integer;
end protected COUNTER_TYPE;

Элементы, объявленные внутри тела типа protected, не доступны для использования вне этого типа. Таким образом, единственный способ доступа к этим элементам, это использование методов, объявленных при декларации типа. Единственным ограничением для методов является то, что формальные параметры методов не могут быть типа access или file.

Тело типа protected задаёт детали реализации данного типа, в теле типа могут быть описаны: декларации и тела подпрограмм, пакетов; декларации типов, подтипов, констант, переменных, файлов и alias (переименований); декларации атрибутов, спецификации и др. Пример тела защищенного типа COUNTER_TYPE:

type COUNTER_TYPE is protected body 
    variable count : integer := 0;
    procedure Set ( num : integer) is
    begin
        count := num ;
    end procedure Set;
    procedure Inc is
    begin
        count := count + 1 ;
    end procedure Inc;
    impure function Get return integer is
    begin
        return count;
    end function Get;
end protected body COUNTER_TYPE;

Только локальные либо общие (shared) переменные могут быть типа protected. Передача значения одной переменной типа protected другой переменной не допускается. Как следствие, переменная защищенного типа не должна иметь присвоения начального значения при декларации. Аналогичным образом, операторы отношений (например, равенства (“=”) и неравенства (“/=”)) не могут использоваться для переменных защищенного типа.

Для того чтобы вызвать методы (функции, процедуры) защищенного типа, нужно указать имя переменной и имя метода, разделенные точкой, например, если переменная объявлена как:

shared variable Cnt : COUNTER_TYPE; тогда она может использоваться так:

if (Cnt.Get = 6) then . . В выражении выше вызывается метод Get переменной Cnt, который возвращает значение внутренней переменной count.

Использование защищённых типов в OS-VVM защищает пользователя от довольно сложных структур и подпрограмм, поддерживающих генерацию псевдослучайных тестов и функциональное покрытие.

Слайд:Пакет RandomPkg

В пакете RandomPkg декларируется защищенный тип RandomPType, который включает в себя начальное значение (seed) псевдослучайного генератора и набор функций для генерации случайных чисел в различных форматах и диапазонах. Генерация псевдослучайных чисел с использованием типа RandomPType проходит в три этапа: декларация переменной данного типа, настройка генератора (в простейшем случае задание начального значения seed) и получение псевдослучайного числа, как показано в следующем примере.

 -- декларация переменной RV
variable RV : RandomPType;
...
-- задание начального значения seed
RV.InitSeed(RV’instance_name);
X <= RV.RandInt(1, 10); -- получение
-- псевдослучайного числа в диапазоне [1, 10]

Метод RandInt является перегруженным, т.е. для него описано несколько реализаций с различным набором входных аргументов, как показано в примере.

RndGenProc : process
    -- защищённый тип из RandomPkg
    variable RV : RandomPType ;
    variable D  : integer ;
begin
    -- Задание значения seeds
    RV.InitSeed(RV'instance_name);
    -- Получение значения 
    -- из диапазона [0, 255]
    D := RV.RandInt(0, 255);
    . . .
    -- Получение значения в
    -- диапазоне [1, 9], исключая
    -- значения 2, 4, 6, 8
    D := RV.RandInt(1, 9, (2, 4, 6, 8));
    . . .
    -- Получение значения из
    -- набора чисел 1, 3, 7, 9.
    D := RV.RandInt( (1, 3, 7, 9) );
    . . .
    -- Получение значения из
    -- набора 1, 3, 7, 9, исключая
    -- значения 3, 7
    D:=RV.RandInt((1, 3, 7, 9), (3, 7));

В приведенном примере дополнительные круглые скобки используются для задания аргумента, имеющего тип integer_vector и представляющего собой массив чисел. В пакете RandomPkg описан также ряд функций генерации псевдослучайных чисел, имеющих упрощенный вызов (сокращенный набор указываемых при вызове входных аргументов).

Функции генерации псевдослучайных чисел доступны не только для целых чисел, но и для векторных типов std_logic_vector (метод RandSlv), unsigned (RandUnsigned) и signed (RandSigned). При этом значения параметров по-прежнему задаются как целые числа (integer), но при вызове этих функций нужно указать еще дополнительный параметр – разрядность генерируемого вектора.

. . .
    variable DataSlv : std_logic_vector(7 downto 0);
begin
    . . .
    -- Получение значения
    -- из диапазона [0, 255]
    DataSlv := RV.RandSlv(0, 255, 8);

По умолчанию, функции генерации возвращают псевдослучайные числа, подчиняющиеся равномерному закону распределения (реализованному с помощью процедуры uniform пакета math_real из библиотеки IEEE). В пакете реализованы другие законы распределения: FAVOR_SMALL (распределение с преобладанием малых значений), FAVOR_BIG (распределение с преобладанием больших значений), NORMAL (нормальный закон распределения, закон Гаусса), POISSON (распределение Пуассона). Получить другой закон распределения можно двумя способами. Первый – это использовать метод SetRandomParm для задания закона распределения по умолчанию, например:

RV.SetRandomParm(NORMAL, 5.0, 2.0);

В этом случае все функции генерации псевдослучайных чисел (Rand*) будут возвращать числа, подчиняющиеся нормальному распределению. В случае, если нужно генерировать только целые псевдослучайные числа, можно использовать перегруженные функции Uniform, FavorSmall, FavorBig, Normal, Poisson, которые возвращают псевдослучайные значения, подчиняющихся соответствующим законам распределения, независимо от закона распределения, заданного по умолчанию.

Кроме стандартных законов распределения случайной величины в пакете существует возможность взвешенной генерации – так называют [5] генерацию по произвольному закону распределения с помощью указания списка требуемых значений целых чисел и их вероятностей появления (весов). Для взвешенной генерации псевдослучайных чисел в типе RandomPType есть две группы перегруженных функций DistVal* и Dist*. При вызове функций группы DistVal* в качестве аргумента задаётся массив пар чисел (число, вес). При вызове функций из другой группы Dist* задаётся массив (integer_vector) весов. Например, функция DistValInt вызывается с массивом пар значений.

Data := RV.DistValInt( ((1, 7), (3, 2), (5, 1)) ); Первый элемент в паре это значение, а второй – его вес. Частота, с которой каждое значение будет возникать, зависит от вероятности, которая определяется по формуле [вес/(сумма всех весов)]. В приведённом примере в результате многократного вызова метода DistValInt появление числа 1 будет с вероятностью 7/10 или 70%, числа 3 – 20%, а числа 5 – 10%.

Функция DistInt является упрощённой версией DistValInt, в которой задаются только веса. Числа генерируются в диапазоне от 0 до N – 1, где N –количество заданных весов. Например, результат многократного вызова

Data := RV.DistValInt( ((1, 7), (3, 2), (5, 1)) ); функции DistInt будет следующим: вероятность выпадения числа 0 будет 70%, числа 1 – 20%, а числа 2 – 10%.

Слайд:Пакет CoveragePkg

Пакет CoveragePkg включает описание новых типов данных и функций, которые позволяют создавать корзины для точек покрытия и перекрестного покрытия, собирать контролируемые значения переменных (сигналов), проверять полноту покрытия, выводить отчет о результатах покрытия. Но наиболее важной функцией пакета CoveragePkg является возможность организации интеллектуального покрытия (intelligent coverage), под которым понимается выбор псевдослучайного значения (или набора значений для перекрестного покрытия) из диапазона непокрытых значений.

В методологии OS-VVM функциональное покрытие осуществляется сбором значений переменных и сигналов VHDL проекта при выполнении моделирования.

Для организации покрытия в VHDL-программе необходимо создать переменную защищенного типа CovPType и описать модель покрытия путем задания необходимых корзин. Далее в соответствии с планом тестирования с помощью метода ICover осуществляется сбор значений переменных или сигналов в заданные моменты времени (или по определенным событиям). Полученные данные о покрытии можно использовать для управления псевдослучайной генерацией тестов при использовании метода RandCovPoint. Метод IsCovered позволяет проверить достигнуто ли полное покрытие всех корзин. С помощью методов WriteCovDb и ReadCovDb можно сохранить и загрузить базу данных о покрытии, что позволяет осуществить объединение данных о покрытии по нескольким запускам моделирования, которые могут выполняться параллельно. Далее рассмотрим этап создания корзин более подробно.
Основные этапы работы с функциями пакета CoveragePkg:

Подключение пакета

use work.CoveragePkg.all;

Декларация объекта покрытия

shared variable CovX, CovXY : CovPType;

Генерация корзин

GenBin(0, 7); — 8 корзин, 1 значение в каждой

GenBin(0, 255, 16); — 16 корзин одинакового размера}

Создание точек покрытия, либо перекрестного покрытия

CovX.AddBins(GenBin(0, 31, 8));

CovX.AddBins(GenBin(32, 47, 1));

CovXY.AddCross(GenBin(0, 7), GenBin(0, 7));

Выборка (сбор) значений

CovX.ICover(X);

Проверка полноты покрытия

if CovX.IsCovered then

Оценка непокрытой области

NotCov := CovX.CountCovHoles;

Генерация псевдослучайных тестов

X := CovX.RandCovPoint; — выбор непокрытых значений

Вывод отчета

CovX.WriteBin; — отчет может быть достаточно большим

Сохранение базы данных

CovX.WriteCovDb(“covdb.txt”, OpenKind => WRITE_MODE);

Слайд:Использование пакетов

Слайд:Пример OS-VVM тесбенча

Слайд:UVVM