v1vas 0 23 марта, 2015 Опубликовано 23 марта, 2015 (изменено) · Жалоба Дано: Virtex-6 XC6VLX240T Центральный модуль, включающий себя UART и подготовку данных. Есть вычислительные модули, которые коннектятся к центральному, их интерфейс: ( clock : in std_logic; reset : in std_logic; data_input : in std_logic_vector(31 downto 0); data_flag : in std_logic; done : out std_logic; data_ready : out std_logic ) С точки зрения использования ресурсов в плис влезает около 230 таких модулей + центральный. При 64 модулях все это хорошо живет на 200Мгц, данная частота и является целью. При 128 модулях синтезатор уже выдаёт максимальную частоту 140MHz, что не устраивает. Причем, PlanAhead показывает, что критические пути - это линии соединения вычислительных модулей с центральным. Попробовал добавить регистры в эти линии: signal reset_corebuf : std_logic_vector(NCORES - 1 downto 0); signal data_input_corebuf : std_logic_vector((NCORES * 32) - 1 downto 0); signal data_flag_corebuf : std_logic_vector(NCORES - 1 downto 0); signal done_corebuf : std_logic_vector(NCORES - 1 downto 0); signal data_ready_corebuf : std_logic_vector(NCORES - 1 downto 0); process (clk) begin if (rising_edge(clk)) then for i in 0 to NCORES - 1 loop reset_corebuf(i) <= reset; data_input_corebuf((i + 1) * 32 - 1 downto i * 32) <= core_data; data_flag_corebuf(i) <= data_core_flag(i); core_done(i) <= done_corebuf(i); data_core_ready(i) <= data_ready_corebuf(i); end loop; end if; end process; И вот эти промежуточные сигналы уже законнектил к вычислительным модулям. Лучше не стало, хотя по логике - должно. Подскажите пожалуйста, что я делаю не так и куда копать) Изменено 23 марта, 2015 пользователем v1vas Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 24 марта, 2015 Опубликовано 24 марта, 2015 · Жалоба Подскажите пожалуйста, что я делаю не так и куда копать) для начала перестать работать в слепую и выложить схему вашей архитектуры(чем полнее тем лучше), на ней будут видны критические места этой архитектуры. только потом искать решение. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Timmy 1 24 марта, 2015 Опубликовано 24 марта, 2015 · Жалоба И вот эти промежуточные сигналы уже законнектил к вычислительным модулям. Лучше не стало, хотя по логике - должно. Подскажите пожалуйста, что я делаю не так и куда копать) При ручной репликации регистров на все реплицированные сигналы надо повесить атрибут syn_preserve, иначе синтезатор их может оптимизировать в один регистр, из-за чего у вас, вероятно, и не стало лучше. Кроме того, 230*35 - это 8000 независимых длинных линий, которые будут зря жрать электричество и могут переполнить ресурсы интерконнекта. Лучше создать древовидную структуру, например, 16 регистровых групп к центральному блоку, и 8-16 оконечных устройств на каждую регистровую группу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 24 марта, 2015 Опубликовано 24 марта, 2015 · Жалоба Дано: Virtex-6 XC6VLX240T Центральный модуль, включающий себя UART и подготовку данных. С точки зрения использования ресурсов в плис влезает около 230 таких модулей + центральный. Подскажите пожалуйста, что я делаю не так и куда копать) Если не вдаваться в детали, то дело выглядит удивительно... Есть один медленный UART и не понятно кто делает протокол передачи байтов в хост. Дальше еще удивительней. 230 модулей должны работать ОДНОВРЕМЕННО??? Тогда сколько же длится "Обработка в модуле", если ее результат передается не понятно по какому протоколу через медленный UART. Почему-то мне кажется, что если сделать многопоточную обработку одним модулем да еще и на 200Мгц, то он вполне справится за то время, пока UART передает-получает данные в хост. Ну, если уж не один модуль, то десятка вполне хватит... И при таком подходе обнаружится, что кристалл будет заполнен на 10%... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ASN 0 24 марта, 2015 Опубликовано 24 марта, 2015 · Жалоба v1vas У Вас в FPGA более 800 BRAM. Если на выходе каждого модуля UART поставить пакетный буфер из BRAM, то станет возможным "перекачивать" данные во входной пакетный буфер в BRAM центрального модуля. По идее должно улучшить времянку. А лучше вообще сделать мультиплексор сигналов древовидным, как предложил уважаемый Timmy, да и вообще очень навороченным: из нескольких модулей в одну BRAM. Присоединюсь к уважаемым des00 и iosifk, что пока архитектура не очень ясна, трудно что-либо толковое посоветовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
v1vas 0 24 марта, 2015 Опубликовано 24 марта, 2015 · Жалоба Давайте вдаваться в детали, чтобы все не выглядело так ужасно, как это понял iosifk =) Есть вычислительный модуль, в нем достаточно легковесная математика. Он единоразово принимает 34 байта стартовых данных и далее на протяжении примерно 5 500 000 000 шагов (1 шаг - 1 такт) эти данные обрабатывает. При частоте 200МГц - это около 30 секунд. В процессе этих 30 секунд никакие данные модулю больше не нужны. По итогам работы модуля мы на выходе получаем один бит: вычислилось ли интересующее нас значение или нет (флаг data_ready в первом интерфейсе, что я написал). Это происходит в среднем только один раз на 300 000 вариантов входных данных, поэтому мне достаточно просто знать для каких данных это произошло, а все остальное я проверяю на хосте. Ну и соответственно есть флаг done, когда все модули закончили - я им бросаю следующую пачку данных, предварительно принятых по UART, а обратно отправляю номер модуля который что-то вычислил, если он есть. UART - другой частотный домен, заведен на два FIFO - один для отправки данных, один для приемки. Главный модуль: объединяет и контролирует всё это. Общая структура и порядок работы главного модуля: 1) Проверяем FIFO, в котором скапливаются данные прилетевшие с хоста, для каждых 34 байт оказавшихся там - отправляем их в вычислительный модуль. 2) Когда загрузили все модули - ждем, пока все модули посчитают (у всех done = '1') 3) Если у какого-то модуля data_ready = '1' - кидаем номер этого модуля в FIFO для отправки данных на хост 4) Ресетим модули и идем на пункт один Вычислительный модуль: 1) Если data_flag = '1', то в data_input лежат валидные данные. 2) Как накопили 34 байта - начали работу. 3) Если вычислилось то, что нужно data_ready <= '1'; 4) Как закончили done <= '1'; Изначально вычислительные коннектились к основному прозаично: MTMainCores: for i in 0 to NCORES - 1 generate begin CoreEntry: CRMain GENERIC MAP ( CORE_N => i ) PORT MAP ( clock => clk, reset => reset, data_input => core_data, data_flag => data_core_flag(i), done => core_done(i), data_ready => data_mt_ready(i) ); end generate MainCores; Потом добавил регистры, про которые написал в первом сообщении. По совету Timmy добавил им аттрибут "keep": attribute keep : string; attribute keep of reset_corebuf: signal is "true"; attribute keep of data_input_corebuf: signal is "true"; attribute keep of data_flag_corebuf: signal is "true"; attribute keep of done_corebuf: signal is "true"; attribute keep of data_ready_corebuf: signal is "true"; И на текущий момент имею 48084 timing score для 128 модулей и вот такой критический путь: Paths for end point Mmux__n4665412_FRB (SLICE_X98Y138.D3), 312 paths -------------------------------------------------------------------------------- Slack (setup path): -2.621ns (requirement - (data path - clock path skew + uncertainty)) Source: MTMainCores[3].CoreEntry/data_ready_BRB2 (FF) Destination: Mmux__n4665412_FRB (FF) Requirement: 5.000ns Data Path Delay: 7.486ns (Levels of Logic = 5) Clock Path Skew: -0.100ns (1.521 - 1.621) Source Clock: clk_BUFGP rising at 0.000ns Destination Clock: clk_BUFGP rising at 5.000ns Clock Uncertainty: 0.035ns Clock Uncertainty: 0.035ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE Total System Jitter (TSJ): 0.070ns Total Input Jitter (TIJ): 0.000ns Discrete Jitter (DJ): 0.000ns Phase Error (PE): 0.000ns Maximum Data Path at Slow Process Corner: MTMainCores[3].CoreEntry/data_ready_BRB2 to Mmux__n4665412_FRB Location Delay type Delay(ns) Physical Resource Logical Resource(s) ------------------------------------------------- ------------------- SLICE_X70Y134.DQ Tcko 0.337 MTMainCores[3].CoreEntry/data_ready_BRB2 MTMainCores[3].CoreEntry/data_ready_BRB2 SLICE_X70Y132.C1 net (fanout=1) 0.710 MTMainCores[3].CoreEntry/data_ready_BRB2 SLICE_X70Y132.C Tilo 0.068 data_mt_ready<3> MTMainCores[3].CoreEntry/data_ready_rstpot SLICE_X97Y70.B3 net (fanout=5) 2.967 data_ready_corebuf<3> SLICE_X97Y70.B Tilo 0.068 data_mt_ready<7> Mmux__n466542 SLICE_X98Y112.D6 net (fanout=1) 1.627 N19372 SLICE_X98Y112.D Tilo 0.068 MTMainCores[21].CoreEntry/SM_STATE_FSM_FFd4_BRB1 Mmux__n466544 SLICE_X98Y138.C5 net (fanout=1) 1.158 N19376 SLICE_X98Y138.C Tilo 0.068 Mmux__n4665412_FRB N19384 SLICE_X98Y138.D3 net (fanout=1) 0.345 N19384 SLICE_X98Y138.CLK Tas 0.070 Mmux__n4665412_FRB Mmux__n4665412 Mmux__n4665412_FRB ------------------------------------------------- --------------------------- Total 7.486ns (0.679ns logic, 6.807ns route) (9.1% logic, 90.9% route) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 24 марта, 2015 Опубликовано 24 марта, 2015 · Жалоба Общая структура и порядок работы главного модуля: 1) Проверяем FIFO, в котором скапливаются данные прилетевшие с хоста, для каждых 34 байт оказавшихся там - отправляем их в вычислительный модуль. 2) Когда загрузили все модули - ждем, пока все модули посчитают (у всех done = '1') 3) Если у какого-то модуля data_ready = '1' - кидаем номер этого модуля в FIFO для отправки данных на хост 4) Ресетим модули и идем на пункт один Вычислительный модуль: 1) Если data_flag = '1', то в data_input лежат валидные данные. 2) Как накопили 34 байта - начали работу. 3) Если вычислилось то, что нужно data_ready <= '1'; 4) Как закончили done <= '1'; понятно, майнер делаете. Интерфейс ваших данных 34 байта и интерфейс результата перенесите в домен низкой частоты UART (CDC поставьте в вычислительные движки), саму шину на запись сделайте что-то вроде вишбона, на чтение соберите все с большой сдвиговый регистр и результат на хост. Ну и констрейны правильные натравить. И все заробит. ЗЫ. схему бы нарисовали себе, все стало бы как на ладони. У меня бойцы в добровольно-принудительном порядке такое делают. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
v1vas 0 24 марта, 2015 Опубликовано 24 марта, 2015 (изменено) · Жалоба Это не майнер, это очень специфичный брут-форс для очень экзотичной задачи) Но архитектурно идеи те же, согласен. Схему держу в голове, объёма мозга хватает. Но перенесу на бумагу, хорошо, заодно и здесь выложу. За советы спасибо! Начну воплощать. Изменено 24 марта, 2015 пользователем v1vas Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GAYVER 2 3 апреля, 2015 Опубликовано 3 апреля, 2015 · Жалоба Это не майнер, это очень специфичный брут-форс для очень экзотичной задачи) это что же за брутфорс такой, для реализации которого понадобилось фигачить проект на fpga ))? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 3 апреля, 2015 Опубликовано 3 апреля, 2015 · Жалоба Давайте вдаваться в детали, чтобы все не выглядело так ужасно, как это понял iosifk =) Есть вычислительный модуль, в нем достаточно легковесная математика. Он единоразово принимает 34 байта стартовых данных и далее на протяжении примерно 5 500 000 000 шагов (1 шаг - 1 такт) эти данные обрабатывает. При частоте 200МГц - это около 30 секунд. В процессе этих 30 секунд никакие данные модулю больше не нужны. Причем, PlanAhead показывает, что критические пути - это линии соединения вычислительных модулей с центральным. Вот , о чем я и написал... Плохой подход гонять параллельные шины и делать все "в лоб". Сделайте так: В центральный модуль добавье что-то вроде SPI, который будет передавать-принимать из вычислителей данные в последовательном коде. При 30 сек добавить еще несколько тактов на 34 бита - думаю что это проблемой не будет... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dvladim 0 7 апреля, 2015 Опубликовано 7 апреля, 2015 · Жалоба Передача через входную шину идёт редко. Дёргайте data_flag не каждый такт, а раз в три такта плюс set_multicycle_path. PS. Брутфорс экономичнее делать на более мелких ПЛИС как вот эти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 7 апреля, 2015 Опубликовано 7 апреля, 2015 · Жалоба Вот , о чем я и написал... Плохой подход гонять параллельные шины и делать все "в лоб". Сделайте так: В центральный модуль добавье что-то вроде SPI, который будет передавать-принимать из вычислителей данные в последовательном коде. При 30 сек добавить еще несколько тактов на 34 бита - думаю что это проблемой не будет... Я бы даже предложил не просто "вроде SPI", а что-то "вроде JTAG". Т.е. последовательную шину развести транзитом через все модули - это сильно экономит интерконнекты. И так же как в JTAG тем для кого информация не предназначена - режим Байпас - это только 1 триггер на приеме. А тому, кто должен получить данные - 34 бита. Про это подробнее - в моих статьях. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться