Перейти к содержанию
    

Обработка параметров в теле функции systemverilog

Добрый день.
Есть такая задача: на вход модуля поступает массив параметров. Необходимо этот массив обработать и на его основе получить другой массив параметров, который в свою очередь будет использоваться для generate блоков. 
Обычно, для этого я писал тело функции без входных/выходных сигналов, внутри которой производил расчет. А потом параметру присваивал эту функцию. Для простого примера:

function [31:0] calculate_free_gbe (
);
begin
calculate_free_gbe = '0;
for (int i = 0; i < N_GBE; i++)
    begin
    if (FREE_GBE[i] == 1)
        calculate_free_gbe = calculate_free_gbe + 1;
    end
return calculate_free_gbe;
end
endfunction

parameter N_FREE_GBE = calculate_free_gbe();

Выглядит, как костыль, но на практике все считалось Квартусом перед синтезом и на основе результата уже синтезировалась логика.

Но сейчас мне понадобилось вытащить из функции несколько значений (причем разных по размерам) и присвоить их параметрам. Как можно это реализовать?
Я попытался сделать выходные сигналы у функции, но вот как их потом присвоить параметру? 
Может вообще есть какой то другой вариант области в которой можно производить вычисления и создавать новые параметры?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

29 minutes ago, Perdachillo said:

... вытащить из функции несколько значений ...

Несколько функций с одинаковым расчетом и разными переменными  для выхода. Чтобы не считать несколько раз одно и тоже  то одна функция расчета возвращает структуру,  а отдельные функции  берут отдельные поля этой структуры. 

modue #(patameter A=1, B=2, ...) ( ...);
...
typedef struct packed {
  bit [7:0] var_b;
  int       var_a;
} st_FUN_t;

function st_FUN_t fun_ab (int a, b);
  fun_ab.var_a = a;
  fun_ab.var_b = b;
endfunction

function int fun_a ();
st_FUN_t tmp;
  tmp = fun(A,B);
  return tmp.a;
endfunction
  
function int fun_b (); 
...
  return tmp.var_b;
endfunction

// ну и по приколу ;)  
localparam st_FUN_t PAR_AB =  fun_ab(A, B);

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

41 minutes ago, RobFPGA said:

Чтобы не считать несколько раз одно и тоже  то одна функция расчета возвращает структуру,  а отдельные функции  берут отдельные поля этой структуры.

Вероятность того, что квартус, до 15.1 включительно сложится от такого, гораздо выше 80% %) проверено на себе)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

8 minutes ago, des00 said:

Вероятность того, что квартус, до 15.1 включительно сложится от такого, гораздо выше 80% %) проверено на себе)

Значит мне повезло!  В Qu 14.1  как раз и использую такое - возврат структуры констант из функции.  

Но понятное дело сначала проверять такое нужно в синтезаторе на "кошечках".

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

23 minutes ago, RobFPGA said:

Приветствую!

Значит мне повезло!  В Qu 14.1  как раз и использую такое - возврат структуры констант из функции.  

Но понятное дело сначала проверять такое нужно в синтезаторе на "кошечках".

Удачи! Rob.

тут сильно зависит от вложенности, размера и прочего. примеров много, в моей теме про FEC много различных таблиц, после разработки приходилось корчевать, что-то переносить на провода, какие то таблицы редуцировать, где-то делать предрасчет. В LDPC декодере, вообще пришлось делать лайфхак, генарация таблицы в тестбенче в файле и include его же при синтезе. Хотя все банально и просто. трехмерный массив структур.

UPD. А при рассчете таблиц полей галуа, в кодеке рида-соломона, квартус подвисал где то минут на 10, симплифай 9. какой-то ложился насмерть (там тоже пришлось применить лайфхак, подсунув готовый файл)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, RobFPGA сказал:

Несколько функций с одинаковым расчетом и разными переменными  для выхода. Чтобы не считать несколько раз одно и тоже  то одна функция расчета возвращает структуру,  а отдельные функции  берут отдельные поля этой структуры. 


modue #(patameter A=1, B=2, ...) ( ...);
...
typedef struct packed {
  bit [7:0] var_b;
  int       var_a;
} st_FUN_t;

function st_FUN_t fun_ab (int a, b);
  fun_ab.var_a = a;
  fun_ab.var_b = b;
endfunction

function int fun_a ();
st_FUN_t tmp;
  tmp = fun(A,B);
  return tmp.a;
endfunction
  
function int fun_b (); 
...
  return tmp.var_b;
endfunction

// ну и по приколу ;)  
localparam st_FUN_t PAR_AB =  fun_ab(A, B);

 

Идею понял,  спасибо! 

Проверил, даже последняя строка работает.  Только не очень понял зачем дополнительные функции использовать, если можно написать в конце:

parameter A = PAR_AB.var_a;

Тогда и функция один раз выполнится и можно несколько значений выцепить. Или нет? 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

13 minutes ago, Perdachillo said:

Проверил, даже последняя строка работает.  Только не очень понял зачем дополнительные функции использовать, если можно написать в конце

Это было для примера - у меня например такие разные функции возвращают  разные константы которые зависят от входных параметра функции в процессе работы модуля, а не только в момент генерации. А сами константы определяются в одном месте в расчетной функции. Хотя тут вам выбирать как удобнее и нагляднее будет.

И да - не надо  отдельно еще "parameter A = PAR_AB.var_a;."  Можно сразу юзать PAR_AB.var_a везде как обычный paramets 

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 24.10.2019 в 16:43, RobFPGA сказал:

И да - не надо  отдельно еще "parameter A = PAR_AB.var_a;."  Можно сразу юзать PAR_AB.var_a везде как обычный paramets 

Добрый день. 

Модельсим съел все на ура. А вот Quartus меня захейтил и выдал кучу ошибок. 

Как оказалось, он считает, что нельзя писать: parameter A = PAR_AB.var_a; -- Error(10742): constant expressions cannot contains a heirarchical Identifier.

Поэтому я решил сделать, как вы изначально предложили, через несколько функций. То есть одна рассчитывает структуру, а другие достают определённое значение. Но в результате получил: Error (10192) value for parameter must be constant expression. Если я правильно понял, получилось это потому что структура у меня содержит три массива logic. И соответственно, я в результате параметру присваиваю logic. Или причина в другом? 

Подскажите пожалуйста, как можно этот момент обойти и все таки рассчитать несколько массивов в одной функции? 

Изменено пользователем Perdachillo

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

5 minutes ago, Perdachillo said:

Модельсим съел все на ура. А вот Quartus меня захейтил и выдал кучу ошибок. 

Ну так предупреждал же 

On 10/24/2019 at 3:11 PM, RobFPGA said:

Но понятное дело сначала проверять такое нужно в синтезаторе на "кошечках".

 

6 minutes ago, Perdachillo said:

Error (10192) value for parameter must be constant expression

Вот тут как раз бы и увидеть ваших  милых "кошечек"  А то можно долго гадать что у вас в коде не так, а на деле может у вас вообще "собачки"  какие-нибудь, а не милые кошечки :declare: 

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

24 минуты назад, RobFPGA сказал:

Вот тут как раз бы и увидеть ваших  милых "кошечек"  А то можно долго гадать что у вас в коде не так, а на деле может у вас вообще "собачки"  какие-нибудь, а не милые кошечки :declare: 

Вот они: 

typedef struct packed {
	logic [N_INST_A-1:0][31:0] inst_a;
	logic [N_INST_B-1:0][31:0] inst_b;
	logic [N_INST_C-1:0][31:0] inst_c;
} st_POS;

function st_POS bind_position();
logic [N_INST_A-1:0][31:0] inst_a_position_about_inst_x;
logic [N_INST_B-1:0][31:0] inst_b_position_about_inst_a;
logic [N_INST_C-1:0][31:0] inst_c_position_about_inst_a;
logic [31:0] add_inst_a;
logic inst_a_find;
begin
add_inst_a = 0;
inst_a_find = 0;
for (int i0=0; i0<N_INST_B; i0++)
	begin
	inst_a_find = 0;
	for (int j0=0; j0<N_INST_A; j0++) 
	 	begin
		if (inst_a_position_about_inst_x[j0] == POSITION_INST_B[i0])
			begin
			inst_b_position_about_inst_a[i0] = j0;
			inst_a_find = 1;
		 	end
	 	end
	if (inst_a_find == 0)
	 	begin
		inst_b_position_about_inst_a[i0] = add_inst_a;
		inst_a_position_about_inst_x[add_inst_a] = POSITION_INST_B[i0];
		add_inst_a = add_inst_a + 1;
	 	end
	end
inst_a_find = 0;
for (int i1=0; i1<N_INST_C; i1++)
	begin
	inst_a_find = 0;
	for (int j1=0; j1<N_INST_A; j1++) 
	 	begin
		if (inst_a_position_about_inst_x[j1] == POSITION_INST_C[i1])
			begin
			inst_c_position_about_inst_a[i1] = j1;
			inst_a_find = 1;
		 	end
	 	end
	if (inst_a_find == 0)
	 	begin
		inst_c_position_about_inst_a[i1] = add_inst_a;
		inst_a_position_about_inst_x[add_inst_a] = POSITION_INST_C[i1];
		add_inst_a = add_inst_a + 1;
	 	end
	end
bind_position.inst_a = inst_a_position_about_inst_x;
bind_position.inst_b = inst_b_position_about_inst_a;
bind_position.inst_c = inst_c_position_about_inst_a;
return bind_position;
end
endfunction

function [N_INST_A-1:0][31:0] fun_get_inst_a_pos();
st_POS pos;
pos = bind_position();
return pos.inst_a;
endfunction

function [N_INST_B-1:0][31:0] fun_get_inst_b_pos();
st_POS pos;
pos = bind_position();
return pos.inst_b;
endfunction

function [N_INST_C-1:0][31:0] fun_inst_c_inst_b_pos();
st_POS pos;
pos = bind_position();
return pos.inst_c;
endfunction

// parameter st_POS POS = bind_position();
parameter [N_INST_A-1:0][31:0] POSITION_INST_A = fun_get_inst_a_pos();
parameter [N_INST_B-1:0][31:0] POSITION_INST_B_ABOUT_INST_A = fun_get_inst_b_pos();
parameter [N_INST_C-1:0][31:0] POSITION_INST_C_ABOUT_INST_A = fun_inst_c_inst_b_pos(); 

Оперирую по сути только параметрами, входных/выходных аргументов у функций нет..
Кстати Quartus 17.1

Изменено пользователем Perdachillo

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

неупакованный массив структур сделайте, может поможет.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

42 минуты назад, des00 сказал:

неупакованный массив структур сделайте, может поможет.

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

Чтобы сделать структуру неупакованной нужно делать массивы внутри неё неупакованными. И, следовательно, функции, которые достают значение из структуры тоже должны быть неупакованными. А функции могут быть неупакованными вообще? 

Quartus не дал сделать параметры wire. При этом parameter logic [31:0] - работает. 

Для того чтобы не приводить кучу строк кода, я задал параметры в чистом виде перед объявлением структуры, чтобы исключить тот факт что параметр рассчитывается не от параметра:

parameter N_INST_A = 5;                                        
parameter N_INST_B = 6;                                                                                
parameter N_INST_C = 2;                                        
parameter integer POSITION_INST_B [N_INST_B-1:0] = '{5,4,32'hF01,32'hF00,32'hF00,0};                  
parameter integer POSITION_INST_C [N_INST_C-1:0] = '{4,32'hF01};

В результате все равно ошибка -  value for parameter POSITION_INSTA_A must be constant expressions 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 minutes ago, Perdachillo said:

Quartus не дал сделать параметры wire. При этом parameter logic [31:0] - работает.

module tst (input int addr, output int a, b, c);
...............
wire [N_INST_A-1:0][31:0] POSITION_INST_A               = fun_get_inst_a_pos();
wire [N_INST_B-1:0][31:0] POSITION_INST_B_ABOUT_INST_A  = fun_get_inst_b_pos();
wire [N_INST_C-1:0][31:0] POSITION_INST_C_ABOUT_INST_A  = fun_inst_c_inst_b_pos();

always_comb begin
  a = POSITION_INST_A[addr];
  b = POSITION_INST_B_ABOUT_INST_A[addr];
  c = POSITION_INST_C_ABOUT_INST_A[addr];
end
  
endmodule

вот так сработает. а так, слишком сложная генерация таблицы для квартуса.

ЗЫ. В ROM это не синтезируется. паттерны не те, не умеет квартус не упакованный многомерный массив в ROM укладывать) .

ЗЗЫ. ресурса минимум

Quote

Estimate of Logic utilization (ALMs needed)

Combinational ALUT usage for logic
-- 7 input functions
-- 6 input functions
-- 5 input functions
-- 4 input functions
-- <=3 input functions

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

Да у вас тут стая псов  :biggrin:

function st_POS bind_position();
logic [N_INST_A-1:0][31:0] inst_a_position_about_inst_x;
...
for (int i0=0; i0<N_INST_B; i0++) begin 
  inst_a_find = 0;
  for (int j0=0; j0<N_INST_A; j0++)  begin
    if (inst_a_position_about_inst_x[j0] == POSITION_INST_B[i0]) begin
      inst_b_position_about_inst_a[i0] = j0;
      inst_a_find = 1;
    end
  end
  if (inst_a_find == 0) begin
    inst_b_position_about_inst_a[i0] = add_inst_a;
    inst_a_position_about_inst_x[add_inst_a] = POSITION_INST_B[i0];
    add_inst_a = add_inst_a + 1;
  end
end

Сначала используем, а потом кормим присваиваем значение?  Вот Qu и гавкает :shok:

Удачи! Rob 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

56 минут назад, RobFPGA сказал:

Сначала используем, а потом кормим присваиваем значение?  Вот Qu и гавкает :shok:

Да действительно вы правы, я обнулил массивы перед этим и, кажется, ошибка ушла..

Я предполагал, что массив будет содержать неопределённые значения 32'dx и постепенно наполнятся. Думал, что неопределённое значение не равно любому другому значению и нет смысла обнулять его в начале. 

А Quartus видимо считает, что неопределённое значение не может быть constant expressions. 

Всем спасибо за помощь! 

Изменено пользователем Perdachillo

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...