Я Харрисов не читал. Было в планах переделать на побайтовый доступ, когда буду кэш приделывать, для ООО кажется без него не обойтись. ARM'овское руководство что-то не ищется.
Так это зависит от устройства памяти. Понятно, что с побайтовым доступом можно писать за один такт, но если подключат микросхему с 32 ножками данных, тогда вариантов не много, за один такт не получится.
always@(posedge clock) begin
old_data <= rom[d_addr[31:2]];
end
wire [31:0] new_data = {byte_mask[3] ? aligned_out[31:24] : old_data[31:24],
byte_mask[2] ? aligned_out[23:16] : old_data[23:16],
byte_mask[1] ? aligned_out[15:8] : old_data[15:8],
byte_mask[0] ? aligned_out[7:0] : old_data[7:0]};
always@(posedge clock) begin
if (old_data_w) begin
rom[old_addr[31:2]] <= new_data;
end
end
Кажется, я этот момент откладывал до появления кэша.
А вот заводить ещё один порт записи в регистры совсем не хотелось бы, сейчас модуль регистров занимает 36 ячеек логики, а так значения придётся комбинировать и 36 превратится в тысячу или две. Они-то появятся, если вектор ядер приделать, но это на будущее.
Угу, тоже начал подумывать. То ли piggy, то ли trainy, раз уж паровозик на логотип затесался. Куда лучше залить? Можно было бы на гитхаб, но не понятно, что с ним дальше будет, РФ из списка локаций при регистрации убрали.
А я только пошёл разбираться с B расширением и структуру команд переписать успел. У вас готовый модуль был? Получается, не шибко битовое расширение ускоряет. Ещё бы посмотреть, сколько ячеек отъест.
Если все 32 бита делить, то 5 МГц. Давайте считать, 5 * 20 = 100 МГц для 40 нм. Для 2 ГГц получается максимум 20 тактов. И как я уже в статье писал, есть ещё потенциал для оптимизации.
Учитывая, что современная оперативка хоть и заявляет высокие рабочие частоты, но внутри работает на всё тех же 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), и все такие разные.
Я Харрисов не читал. Было в планах переделать на побайтовый доступ, когда буду кэш приделывать, для ООО кажется без него не обойтись. ARM'овское руководство что-то не ищется.
Так это зависит от устройства памяти. Понятно, что с побайтовым доступом можно писать за один такт, но если подключат микросхему с 32 ножками данных, тогда вариантов не много, за один такт не получится.
Кажется, я этот момент откладывал до появления кэша.
А вот заводить ещё один порт записи в регистры совсем не хотелось бы, сейчас модуль регистров занимает 36 ячеек логики, а так значения придётся комбинировать и 36 превратится в тысячу или две. Они-то появятся, если вектор ядер приделать, но это на будущее.
Поискал в коде по "for", и там особо нечего разматывать, кроме матричных вычислений. Может если на конкретную функцию тег повесить, меньше кода будет.
Угу, тоже начал подумывать. То ли piggy, то ли trainy, раз уж паровозик на логотип затесался. Куда лучше залить? Можно было бы на гитхаб, но не понятно, что с ним дальше будет, РФ из списка локаций при регистрации убрали.
А я только пошёл разбираться с B расширением и структуру команд переписать успел. У вас готовый модуль был? Получается, не шибко битовое расширение ускоряет. Ещё бы посмотреть, сколько ячеек отъест.
Да где ж их проводить, это надо ASIC если не делать, то хотя бы моделировать, а я с такими вещами не знаком.
Если все 32 бита делить, то 5 МГц. Давайте считать, 5 * 20 = 100 МГц для 40 нм. Для 2 ГГц получается максимум 20 тактов. И как я уже в статье писал, есть ещё потенциал для оптимизации.
Учитывая, что современная оперативка хоть и заявляет высокие рабочие частоты, но внутри работает на всё тех же 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), и все такие разные.