des00 25 25 июля, 2015 Опубликовано 25 июля, 2015 · Жалоба Наткнулся на очередной перл от квартуса. В этот раз 14.1. Итак положим есть проект, в котором есть хитро сгенерированные таблицы : module test_pipa (input logic iclk, input logic [3 : 0] addr, input logic [1 : 0] sel, output logic [7 : 0] odat); typedef int tab_t [4][16]; tab_t tab; assign tab = get_tab(0); function automatic tab_t get_tab (input bit nul); get_tab = '{ '{1, 43, 435, 21, 44, 976, 53, 4, 11, 143, 35, 121, 144, 76, 153, 14}, '{5, 543, 35, 521, 544, 76, 553, 54, 511, 43, 535, 21, 44, 576, 53, 514}, '{2, 243, 235,121, 544, 6, 3, 674, 611, 3143, 835, 3121, 1144, 976, 6153, 414}, '{2, 293, 235,121, 599, 6, 3, 679, 611, 3193, 835, 3121, 1199, 976, 6153, 919} }; endfunction typedef logic [7 :0] btab_t [4][16]; btab_t btab; assign btab = get_btab(0); // 5LC/5REG AriaV //assign btab = get_btab2(0); // 21LC/5REG (????) always_ff @(posedge iclk) begin odat <= btab[sel][addr]; end function automatic btab_t get_btab (input bit nul); tab_t mtab; // mtab = get_tab(0); // for (int i = 0; i < 4; i++) begin for (int j = 0; j < 16; j++) begin get_btab[i][j] = (35 + 3*mtab[i][j] % 27) % 35; end end endfunction function automatic btab_t get_btab2 (input bit nul); for (int i = 0; i < 4; i++) begin for (int j = 0; j < 16; j++) begin get_btab2[i][j] = (35 + 3*tab[i][j] % 27) % 35; end end endfunction endmodule В зависимости от того какая функция используется get_btab/get_btap2 ресурс для 5 ой арии/сыклона отличается в 4 раза, можете проверить :) Причем во втором случае находиться кучка делителей, занимающих нулевой ресурс, но при этом сам модуль значительно толще. Судя по всему есть там баг, с доступом к константным массивам находящимися выше по иерархии. Он считает их не константными и пихает под них логику, которая не используется. Эффект проверен начиная с 9.1. Будьте внимательны Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Timmy 1 25 июля, 2015 Опубликовано 25 июля, 2015 · Жалоба Интересно, если объявлять константы с const или localparam, баг тоже будет проявляться? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 25 июля, 2015 Опубликовано 25 июля, 2015 · Жалоба Интересно, если объявлять константы с const или localparam, баг тоже будет проявляться? квалификатор const насколько я помню не поддерживается квартусами (до 9.1 точно). с localparam ом возможны различные глюки : несмотря на то, что в стандарте четко оговорена последовательность анализа константных параметров, разные версии квартуса не всегда понимают это корректно, квеста тоже (причем тупо не инициализирует константы), поэтому на сигналах самый безопасный вариант. ЗЫ. Имеются в виду параметры - одномерные и многомерные массивы. С числами проблем я не замечал (ну кроме квартуса 8.1) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 25 июля, 2015 Опубликовано 25 июля, 2015 · Жалоба есть два типа оптимизации: 1) оптимизация внутри функций, имеющая все необходимые инструменты для всяких там loop unroll и прочих программизмов SV 2) оптимизация логики на основе анализа графа внутри функции работает 1), до генерации логики, и если ему доступно значение чисел - есть локальная переменная в которую вы скопировали сигналы (а фактически скопировались константы), то оптимизация отрабатывает на ура. в противном случае он видит глобальные сигналы, и не проверяя их (не положено!) генерит полную логику функции. и скармливает оптимизатору 2) отсюда и разница. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 25 июля, 2015 Опубликовано 25 июля, 2015 · Жалоба внутри функции работает 1), до генерации логики, и если ему доступно значение чисел - есть локальная переменная в которую вы скопировали сигналы (а фактически скопировались константы), то оптимизация отрабатывает на ура. в противном случае он видит глобальные сигналы, и не проверяя их (не положено!) генерит полную логику функции. и скармливает оптимизатору 2) отсюда и разница. Логично, была такая версия. Но тогда непонятен вот такой момент. Меняем немного код : function automatic btab_t get_btab2 (input bit nul); for (int i = 0; i < 4; i++) begin for (int j = 0; j < 16; j++) begin //get_btab2[i][j] = (35 + 3*tab[i][j] % 27) % 35; get_btab2[i][j] = mod(35 + mod(3*tab[i][j], 27), 35); end end endfunction function automatic int mod (input int a, int base); int tmp; mod = a; for (int i = 0; i < 5; i++) begin // правда тут цифры 5 мало, т.к. 6153/27 = 227. Но для общности изложения пойдет. if (mod >= base) mod = (mod - base); else break; end endfunction И вуаля, то что доктор прописал. Но это похоже уже оптимизатор постарался. Дооптимизировал таки. и до кучи, упростим задачу : сделаем матрицу параметров одномерной. module test_popa (input logic iclk, input logic [3 : 0] addr, output logic [7 : 0] odat); typedef int tab_t [16]; tab_t tab; assign tab = get_tab(0); function automatic tab_t get_tab (input bit nul); get_tab = '{5, 543, 35, 521, 544, 76, 553, 54, 511, 43, 535, 21, 44, 576, 53, 514}; endfunction typedef logic [7 :0] btab_t [16]; btab_t btab; assign btab = get_btab(0); // 5LC/5REG //assign btab = get_btab2(0); // 5LC/5REG always_ff @(posedge iclk) begin odat <= btab[addr]; end function automatic btab_t get_btab (input bit nul); tab_t mtab; // mtab = get_tab(0); // for (int j = 0; j < 16; j++) begin get_btab[j] = (35 + 3*mtab[j] % 27) % 35; end endfunction function automatic btab_t get_btab2 (input bit nul); for (int j = 0; j < 16; j++) begin get_btab2[j] = (35 + 3*tab[j] % 27) % 35; end endfunction endmodule результат одинаковый. т.е. идея с оптимизацией дюже избирательна :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 25 июля, 2015 Опубликовано 25 июля, 2015 · Жалоба в первом куске кода опять-таки есть момент копирования констант в момент вызова функции mod ( строчка mod = a;) т.е. оптимизатор 1) имеет значения констант, что позволяет иметь в момент сборки функции get_btab2 всё, чтобы сгенерировать минимальную логику. а со вторым куском кода оптимизатор типа 2) лучше справился, просто из-за меньшего размера исходного графа перед оптимизацией. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 25 июля, 2015 Опубликовано 25 июля, 2015 · Жалоба в первом куске кода опять-таки есть момент копирования констант в момент вызова функции mod ( строчка mod = a;) т.е. оптимизатор 1) имеет значения констант не соглашусь, это чисто верилоговская фенечка и assign btab = get_btab3(tab); ... function automatic btab_t get_btab3 (input tab_t tab); tab_t mtab; mtab = tab; for (int i = 0; i < 4; i++) begin for (int j = 0; j < 16; j++) begin get_btab3[i][j] = (35 + 3*tab[i][j] % 27) % 35; end end endfunction дает такой же попсовый результат Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 25 июля, 2015 Опубликовано 25 июля, 2015 · Жалоба попсовый - это какой? function automatic btab_t get_btab3 (input tab_t tab); тут вы сами запретили копирование значений в тело функции, явно указав что на вход придут априори неизвестные сигналы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 25 июля, 2015 Опубликовано 25 июля, 2015 · Жалоба попсовый - это какой? ресурс в 4 раза больше. тут вы сами запретили копирование значений в тело функции, явно указав что на вход придут априори неизвестные сигналы. а другого способа, если исключить генерацию таблицы внутри, нет. В этом способе синтезатор не может не видеть что на вход функции приходят константы. Резюмирую тему : способов передачи параметров в подобных примерах 2 : сгенерировать таблицу внутри функции или передать ее снаружи (через интерфейс функции или через глобальное пространство имен). Примеры показывают что результат синтеза функции с передачей параметров зависит от размерности таблицы. Одномерные таблицы, пусть и большие прекрасно оптимизируются, многомерные (даже маленькие) оптимизируются из рук вон плохо. Сей момент надо теперь помнить при разработке как фичу. Причем забавно, что когда смотришь на уровни элементов ПЛИСа, там тупо висят константы в лютах, но заведение этих констант в рабочую логику приводит к увеличению слоев логики и тактовая падает процентов на 20. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 25 июля, 2015 Опубликовано 25 июля, 2015 · Жалоба а другого способа, если исключить генерацию таблицы внутри, нет бинго. логика синтезируется только для вызываемой функции самого верхнего уровня. при этом синтезатор просматривает на всю глубину - т.е. при вызове функции "BBB" внутри функции "AAA" сначала производится получение выходного значения функции "BBB" без генерации логики для "BBB". В этом способе синтезатор не может не видеть что на вход функции приходят константы. ага, но только после синтеза соответствующей логики для функции. синтезировать минимальную логику, реализующую функцию, зная константы на этапе генерации этой логики значительно проще, чем оптимизировать большой кусок логики с константами на входах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 26 июля, 2015 Опубликовано 26 июля, 2015 · Жалоба бинго. Осталось проверить это в симпифае и виваде Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться