Учитывая, что современная оперативка хоть и заявляет высокие рабочие частоты, но внутри работает на всё тех же 150 МГц (надо перемножить частоту на ожидание в тактах), тут любой процессор сольётся, если кучей злоупотреблять. А если кэша хватает, тогда и проблемы нет.
Вы как будто статью не читали (или я недостаточно понятно написал). Для ПЛИС и нет смысла включать однотактовое деление, точно так же как делать однотактовое умножение вручную, это скорее для ASIC. А если с многотактовым, синтезируется примерно 40 МГц.
Ну и если смотреть на процент заполнения флага обращения к памяти, там меньше 20%, так что сольётся, но не прямо в канализацию ) .
ИИ врёт. Регистры процессора могут ведь менять значение по тактовому сигналу, а значение выдавать комбинаторикой. Хотя может чисто терминологически это не считается памятью.
Хоть я и новичок, но на pc[i] = pc_result[i-1] вы меня не разведёте. Очевидно, надо делать для следующего такта pc[i] <= pc_next + i*4, а дальше если повезло и бранчей не было, значит выполнять инструкцию, нет - тогда выбрасывать.
В икарусе работает. Если предположить, что память - это массив регистров, то всё будет нормально выглядеть, на выходе регистра значение всегда есть, только надо с помощью адреса значение нужного получить через комбинаторику, а на входе регистров значение подаётся везде, а флаг записи в регистр выставляется шиной адреса.
Для плиса код будет в следующей статье. Процесс по этапам идёт, сначала простое ядро, чтобы легко понять, как это работает, потом его тестирование в симуляторе, потом ускорение, потом запуск на плис.
Ram logic "rom" is uninferred due to asynchronous read logic
Cannot convert all sets of registers into RAM megafunctions when creating nodes. The resulting number of registers remaining in design exceeds the number of registers in the device or the number specified by the assignment max_number_of_registers_from_uninferred_rams.
Немного ошибся. Почитал статью про fusion, и это не out-of-order, там хотят сливать инструкции в том случае, если целевой регистр совпадает, но ведь это удлиняет путь сигнала. Причём путь удлинится для всех инструкций, а оптимизация получится только для некоторых, так что больше на пессимизацию похоже.
Quartus автоматом подключает, так что без вариантов. А ждать 3 такта на инструкцию, чтобы сначала адрес инструкции задать, потом инструкция приехала, потом для неё данные - слишком большие потери времени.
Я за хорошими показателями на fpga гнался, а не просто в вакууме ) . Для fusion надо ведь отбрасывание команд после джампов делать, чтобы лишнего не выполнилось, так что в любом случае добавлять флаги блокировки "конвейера". Хотя может и правда так легче начать.
Так ведь синхронная память адрес получает на одном такте, а значение выдаёт на другом, так что однотактовым процессором уже не обойтись. Потому и пришлось конвейер делать.
Насчёт B-расширения, может и добавлю, только оно не выглядит простым. zba + zbb + zbs - это 24 команды (без учёта immediate), и все такие разные.
Двумя строчками ниже. Компилятор же по одному файлу компилирует в объектные, потом все объектные линковщик линкует в исполняемый. Тут ошибки точно нет, иначе бы не слинковалось.
Подначиваете следующую статью писать. Удивляться надо будет, если ядра через Ctrl+C, Ctrl+V накопируются и начнут поток параллельно крутить, вот там можно i7 по числу команд за такт обогнать.
В пределе с одним набором регистров (32 штуки) можно за такт 10 команд выполнять. А если вторую копию завести и учесть float, то ещё больше.
На скриншоте x = 7D0, y = 3, это вычисление размера теста, 2000/3=666. Ещё форматирование %d вызывает 2 деления на цифру. Если ворочать json, наверное там бы кэширование деления пригодилось, чтобы частное и остаток два раза не вычислять.
С появлением конвейера CM просядет совсем немножко, об этом в следующей статье, если соберусь.
В видюхах как минимум для нормализации векторов деление используется. При вычислении отражения и освещения. Для тайловых текстур может вычисление остатка понадобиться.
А вот на CPU - это надо подумать.
Может какие-то вычисления конечно-элементных пакетов.
Учитывая, что современная оперативка хоть и заявляет высокие рабочие частоты, но внутри работает на всё тех же 150 МГц (надо перемножить частоту на ожидание в тактах), тут любой процессор сольётся, если кучей злоупотреблять. А если кэша хватает, тогда и проблемы нет.
Вы как будто статью не читали (или я недостаточно понятно написал). Для ПЛИС и нет смысла включать однотактовое деление, точно так же как делать однотактовое умножение вручную, это скорее для ASIC. А если с многотактовым, синтезируется примерно 40 МГц.
Ну и если смотреть на процент заполнения флага обращения к памяти, там меньше 20%, так что сольётся, но не прямо в канализацию ) .
40.7 МГц, 4868 LUT, памяти сделал 64 бита. Не так сильно просело, как ожидал от однотактового выполнения.
ИИ врёт. Регистры процессора могут ведь менять значение по тактовому сигналу, а значение выдавать комбинаторикой. Хотя может чисто терминологически это не считается памятью.
Хоть я и новичок, но на pc[i] = pc_result[i-1] вы меня не разведёте. Очевидно, надо делать для следующего такта pc[i] <= pc_next + i*4, а дальше если повезло и бранчей не было, значит выполнять инструкцию, нет - тогда выбрасывать.
Поднимите руку, у кого тут есть техпроцесс. Возьму, куда-нибудь устроюсь и найду ) .
В икарусе работает. Если предположить, что память - это массив регистров, то всё будет нормально выглядеть, на выходе регистра значение всегда есть, только надо с помощью адреса значение нужного получить через комбинаторику, а на входе регистров значение подаётся везде, а флаг записи в регистр выставляется шиной адреса.
Для плиса код будет в следующей статье. Процесс по этапам идёт, сначала простое ядро, чтобы легко понять, как это работает, потом его тестирование в симуляторе, потом ускорение, потом запуск на плис.
В конвейере всё попилено, так что нет, обойдусь без слепой погони за инструкциями за такт ) .
Синхронный вариант работает, а так:
wire [31:0] i_data;assign i_data = rom[i_data[31:2]];выдаёт ошибку:
Ram logic "rom" is uninferred due to asynchronous read logic
Cannot convert all sets of registers into RAM megafunctions when creating nodes. The resulting number of registers remaining in design exceeds the number of registers in the device or the number specified by the assignment max_number_of_registers_from_uninferred_rams.
Немного ошибся. Почитал статью про fusion, и это не out-of-order, там хотят сливать инструкции в том случае, если целевой регистр совпадает, но ведь это удлиняет путь сигнала. Причём путь удлинится для всех инструкций, а оптимизация получится только для некоторых, так что больше на пессимизацию похоже.
Quartus автоматом подключает, так что без вариантов. А ждать 3 такта на инструкцию, чтобы сначала адрес инструкции задать, потом инструкция приехала, потом для неё данные - слишком большие потери времени.
Я за хорошими показателями на fpga гнался, а не просто в вакууме ) . Для fusion надо ведь отбрасывание команд после джампов делать, чтобы лишнего не выполнилось, так что в любом случае добавлять флаги блокировки "конвейера". Хотя может и правда так легче начать.
Так ведь синхронная память адрес получает на одном такте, а значение выдаёт на другом, так что однотактовым процессором уже не обойтись. Потому и пришлось конвейер делать.
Насчёт B-расширения, может и добавлю, только оно не выглядит простым. zba + zbb + zbs - это 24 команды (без учёта immediate), и все такие разные.
Двумя строчками ниже. Компилятор же по одному файлу компилирует в объектные, потом все объектные линковщик линкует в исполняемый. Тут ошибки точно нет, иначе бы не слинковалось.
В чём запускаете? У меня одна итерация однотактного варианта в икарусе занимает 9 минут, поэтому по умолчанию отключена.
Подначиваете следующую статью писать. Удивляться надо будет, если ядра через Ctrl+C, Ctrl+V накопируются и начнут поток параллельно крутить, вот там можно i7 по числу команд за такт обогнать.
В пределе с одним набором регистров (32 штуки) можно за такт 10 команд выполнять. А если вторую копию завести и учесть float, то ещё больше.
1 наносекунда на низ меандра, одна наносекунда на верх, так что число тиков надо делить на два.
На скриншоте x = 7D0, y = 3, это вычисление размера теста, 2000/3=666. Ещё форматирование %d вызывает 2 деления на цифру. Если ворочать json, наверное там бы кэширование деления пригодилось, чтобы частное и остаток два раза не вычислять.
С появлением конвейера CM просядет совсем немножко, об этом в следующей статье, если соберусь.
В видюхах как минимум для нормализации векторов деление используется. При вычислении отражения и освещения. Для тайловых текстур может вычисление остатка понадобиться.
А вот на CPU - это надо подумать.
Может какие-то вычисления конечно-элементных пакетов.
Это уже не общий код, это вычисления. И для криптографии в микроконтроллерах добавляют отдельные модули.