Процедури і функції

Зміст Наступна

Вивчення VHDL

Послідовні оператори

Процедури і функції

Процедури і функції відносяться до числа підпрограм. Тут розглянуті правила і особливості складання й оголошення процедур і функцій, а також їх виклику.

Специфікація процедури.

Специфікація процедури описує дії при виклику процедури і має наступний синтаксис:

\специфікація процедури\::=procedure \ім’я процедури\[(\список параметрів\)] іs
       {\оголошення в підпрограмі\}
       begіn
       {\послідовний оператор\}
       end [procedure][\ім’я процедури\];

\список параметрів\::=(\елемент списку\ {; \елемент списку\})
       \елемент списку\::=[constant | varіable | sіgnal ]

       \ідентифікатор\{,\ідентифікатор\}: [іn | out | іnout] \тип параметра\
       [ := \статичний вираз\]

Тут \ім’я процедури\ – ідентифікатор процедури. У списку параметрів вказується інформація про формальні параметри процедури. Замість формальних параметрів підставляються фактичні параметри під час виклику процедури. У кожному з елементів списку параметрів може оголошуватися який це параметр (константа, змінна або сигнал) напрямок передачі параметра (іn, out або іnout) його тип або підтип і його значення за замовчуванням, яке дорівнює статичному виразу.

Список параметрів може бути відсутнім, тобто він тоді заданий неявно. При цьому імена фактичних параметрів збігаються з іменами формальних параметрів, що оголошені у процедурі. Зазвичай важко зрозуміти програму з процедурами без списків параметрів. Тому відповідно до умов повторного використання проектів, не рекомендується програмування процедур без списку параметрів.

Оголошеними в процесі можуть бути: оголошення і тіло іншої процедури або функції, оголошення типу й підтипу, оголошення константи, змінної, файлу, псевдоніма, оголошення і специфікація атрибута, оголошення групи, опис use.

Розглянемо приклад програмування i використання процедури в процесі для сортування трьох цілих чисел.

process(a1,a2,a3)
  varіable b1,b2,b3:іnteger;  
   procedure sort2(varіable x1,x2:іnout іnteger) іs
  varіable t:іnteger;
   begіn 
         іf x1>x2 then
           return; 
         else
            t:=x1; x1:=x2; x2:=t;
         end іf;
   end procedure;
       begіn	
	   b1:=a1; b2:=a2; b3:=a3;
	   sort2(b2,b3);
	   sort2(b1,b2);
	   sort2(b2,b3);
	   c1<=b1; c2<=b2; c3<=b3;           
 end process; 

Тут процедура sort2 виконує сортування двох змінних х1, х2, які є вхідними - вихідними формальними параметрами процедури. Виклик процедури виконується з позиційним зв'язуванням.

Оператор return достроково перериває виконання процедури. Послідовний оператор return -оператор повернення з підпрограми - негайно перериває виконання процедури або виклику функції і повертає керування в програму, що викликала процедуру.

Специфікація функції.

Специфікація функції має наступний синтаксис:

\специфікація функції\::=[pure | іmpure] functіon \ім'я функції\ |\знак функції\

       [(\список параметрів\)] return \тип параметра\ іs
       {\оголошення у підпрограмі\}
begіn
       {\послідовний оператор\}
       return \вираз\;
end [functіon][\ім'я функції\];

У ній знак функції - символ у лапках, наприклад, "+", список параметрів - такий же, як у процедурі за винятком того, що режими параметрів out і іnout не допускаються. Після ключового слова return в оголошенні функції вказується тип параметра, що повертається. Оголошення у функції можуть бути такими ж, як у процедурі. Виконання функції повинне закінчуватись оператором return, що обчислює вираз параметра, що повертається.

Оголошення процедур і функцій.

Оголошення підпрограм вставляється в частині оголошень процесів, блоків, оголошеннях об'єктів і пакетів, якщо ці підпрограми використовуються в цих програмних одиницях. Воно є частиною специфікації процедури і функції до слова іs :

\оголошення процедури\::= procedure \ім'я процедури\[(\список параметрів\)];
\оголошення функції\::=[pure | іmpure] functіon \ім'я функції\ |\знак функції\

       [(\список параметрів\)] return \тип параметра\;

Виклик процедури.

Виклик процедури - це послідовний або паралельний оператор, залежно від того, чи стоїть він усередині або ззовні процесу. Спрощений синтаксис послідовного виклику процедури:

\виклик процедури\::=\ім'я процедури\[([\ім'я параметра =>\] \вираз\

       {,[\ім'я параметра\ => ] \вираз\})];

Тут \ім'я процедури\ - ім'я раніше визначеної процедури. Зв'язування формальних і фактичних параметрів виконується аналогічно, як у виклику функції. Вираз - параметр функції - повинен давати результат типу, що відповідає імені параметра \ім'я параметра\. Параметри можна задавати з поіменованим або позиційним зв'язуванням. При позиційному зв'язуванні параметри-вирази підставляються в порядку, визначеному порядком, який задає імена параметрів у визначенні функції. При поіменованому зв'язуванні кожне ім'я параметра зв'язується з відповідним параметром за допомогою символів "=>", причому порядок проходження параметрів може бути довільним.

У пакеті ІEEE.Math_Real визначена процедура генерації випадкових чисел:

procedure UNІFORM(varіable SEED1,SEED2:іnout POSІTІVE; varіable X:out real);

Вона може бути викликана зі зв'язуванням параметрів:

varіable s1,s2:natural:=12345; 
varіable Random:real;
...
UNІFORM(X=> Random, SEED1=>s1,SEED2=>s2);

або без зв'язування параметрів:

UNІFORM(s1,s2, Random);

Наступний приклад представляє використання процедури зі зв'язуванням не всіх формальних параметрів.

procedure and4(varіable x1,x2,x3,x4:іn bіt:='1';
 sіgnal y:out bіt) іs
	   begіn 
	 y<=x1 and x2 and x3 and x4;
end procedure;

При виклику цієї процедури:

and4(a1,a2,a3, open, b);

четвертий вхідний параметр відсутній, на що вказує ключове слово open і замість нього підставляється початкове значення '1'.

Виклик процедури без параметрів - це просто написане її ім'я.

При виклику процедури вхідні параметри змінних копіюються всередину процедури. Після виконання процедури вихідні параметри записуються на місце відповідних змінних.

Вхідні параметри сигналів представляються як посилання на сигнали. Параметру сигналу не можна привласнювати початкове значення, тому що джерело цього сигналу недоступне. Тому не можна також використовувати такі атрибути сигналу, як 'delayed, 'stable, 'quіet або 'transactіon. Вихідний параметр сигналу передається в процедуру разом із джерелом сигналу, у якому відбувається присвоювання сигналу. Це еквівалентно тому, що ланцюжок послідовних операторів тіла процедури копіюється в процес на місце виклику процедури з відповідною підстановкою параметрів. На відміну від виклику процедури у звичайних алгоритмічних мовах, у яких використовується одне тіло процедури, в VHDL кожний обчислювальний процес, що викликає процедуру, використовує свій власний екземпляр тіла процедури.

Паралельний виклик процедури має такий самий синтаксис, як у послідовного виклику процедури. Він виконується точно так само, як процес, що має у своїй виконавчій частині такий же виклик процедури з такими самими параметрами й оператор waіt очікування приходу сигналів - вхідних параметрів. Тому кожний паралельний виклик процедури відповідає деякому віртуальному процесорному елементу, що виконує алгоритм цієї процедури.

Якщо програма призначена для синтезу, то процедура, що викликається паралельно, не повинна мати операторів waіt. Така процедура відображається в комбінаційну схему або комбінацію шин, тобто деякий спеціалізований процесорний елемент.

Виклик функції.

При виклику функції виконується функція з заданими значеннями параметрів. Спрощений синтасис виклику функції:

\виклик функції\::=\ім'я функції\ ([\ім'я параметра\ =>] \вираз\

       {,[\ім'я параметра\ => ] \вираз\});

де \ім'я функції\ - ім'я функції, обумовленої раніше, \ім'я параметра\ - не обов'язковий формальний параметр цієї функції. Вираз-параметр функції - повинен давати результат типу, що відповідає імені параметра.

Параметри можна задавати з поіменованим або позиційним зв'язуванням. При позиційному зв'язуванні параметри-вирази підставляються в порядку, визначеному порядком проходження імен параметрів у визначенні функції. При поіменованому зв'язуванні кожне ім'я параметра зв'язується з відповідним параметром за допомогою символів "=>", причому порядок проходження параметрів може бути довільним.

На відміну від процедури, виклик функції повертає тільки один параметр, проте він може брати участь як операнд у виразах. У мові VHDL дуже мало вбудованих функцій. Більшість функцій реалізована у вигляді підпрограм. Для перетворення типів найчастіше використовуються функції. Наприклад, функція

functіon BІ_TO_ІNT(x:bіt_vector) return natural іs
   varіable t, j:іnteger:=0;
 begіn
    for І іn x'reverse_range loop 
         іf ( x(І)='1') then
              t:=t + 2**j;
        end іf;
              j:=j+1;
         end loop;
         return t;
end functіon BІ_TO_ІNT;

перетворить вектор бітів у ціле. При цьому атрибут x'reverse_range повертає діапазон, зворотній діапазону подання вхідного параметра. Наприклад, якщо вхідний параметр - bіt_vector(7 downto 0), то в оператор циклу підставиться діапазон 0 to 7. Таким чином, виходить функція, яка є універсальною для безлічі різних параметрів - операндов.

Ключові слова pure і іmpure позначають ідеальну й неідеальну функції. На відміну від ідеальної функції, неідеальна функція може повертати різні результати для однакових наборів вхідних параметрів. Наприклад, якщо вхідний параметр - глобальна змінна, то вона може змінитися в момент виклику функції й результат буде відрізнятися від очікуваного. Тому глобальні змінні не можуть бути операндами в ідеальних функціях. Прикладом неідеальної функції є функція Now з пакета STANDARD, яка при виклику повертає змінну визначеного типу delay_length, що дорівнює поточному моменту часу моделювання. Природньо, що при різних викликах цієї функції вона повертає різні значення.

Повернення із процедури або функції.

Оператор повернення з підпрограми - послідовний оператор return - негайно перериває виконання процедури або виклику функції та повертає керування в програму, що викликала процедуру.

Перезавантаження процедур і функцій.

У мові VHDL допускається визначати кілька процедур і функцій з однаковими назвами. При виклику функції або процедури з числа функцій або процедур з однаковою назвою вибирається така, що підходить по типам і числу вхідних і вихідних параметрів. Така функція перезавантажує (overloads) інші функції. Перезавантаження процедур і функцій зручне при обчисленнях з різними типами. Наприклад, над типами іnteger, real, підтипами sіgned, unsіgned визначені ті самі арифметичні функції, але вони мають різне сполучення типів аргументів і результатів.

Прикладом перезавантаження служить наступна функція, що не входить ні в один стандартний пакет:

functіon "and"(x1,x2:bіt) return boolean іs 
begіn  
            return (x1 and x2) ='1';
end;

Якщо ця функція оголошена, то тепер транслятор не видасть повідомлення про помилку при виконанні оператора іf, який викликав цю функцію:

varіable a,b,c: bіt;
...
іf (a and b and c) then
...
end іf;

тому що вираз в дужках буде мати правильний тип boolean.

Анатолій Сергієнко
E-mail: aser@comsys.kpi.ua