Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Пт дек 13, 2024 10:47

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 8 ] 
Автор Сообщение
 Заголовок сообщения: Как создать RISC-процессор 2024
СообщениеДобавлено: Сб янв 13, 2024 23:24 
Не в сети
Аватара пользователя

Зарегистрирован: Ср июл 03, 2019 11:10
Сообщения: 485
Откуда: Москва
Благодарил (а): 57 раз.
Поблагодарили: 24 раз.
Словил себя на мысли, что коль скоро простейший форт-процессор с 4-битными командами жив-здоров и прекрасно себя чувствует, то и RISC-процессор с примерно таким же набором команд взлетит.
Например, в одном из Форт-процессоров такой перечень команд:
Код:
0 1 2 3 push0 jz call ret @ ! swap pick nand - mla rshift
Тогда в RISC-процессоре взять jz/call/ret для ужимок и прыжков, +/-/*/rshift/nand в качестве арифметики, ldr/str вместо @/!, а также пару mov-ов для заталкивания литералов в регистры. Процентов на 100 уверен, что заработает. Для определенности будем считать, что 16-битный, 16 регистров и 16 команд, при желании оно потом легко отмасштабируется. А вот машинное слово в 4 бита не утрамбуется, но в байт вполне: 4 бита на опкод и еще 4 на immediate/register. И даже ассемблер на первом этапе можно не делать: вполне сгодится fasm с его макросами.
Название пока не придумал, но пусть будет RISC-8. :)
Сценарий примерно такой:
- родить систему команд;
- ассемблер на макросах fasm;
- виртуальная машина на ПК;
- Форт, ну и Си заодно, раз уж он в процессе;
- реализация на Verilog.
По ощущениям должно получиться достаточно легко, код должен получиться достаточно плотным (про чудовищную плотность кода Форт-процессоров я вообще молчу, у меня на некоторых прошивках ARM/Thumb//x86 раз в 5-10 проигрывает) и при этом в перспективе при параллельном выполнении нескольких команд большие литералы будут складываться в регистр за такт, что позволит не сильно проигрывать в скорости традиционным RISC-ам. Пора начинать? :)


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Как создать RISC-процессор 2024
СообщениеДобавлено: Сб янв 13, 2024 23:55 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7990
Благодарил (а): 26 раз.
Поблагодарили: 144 раз.
Да никуда не денется, оно обычно заводится. Главное, не пытаться сразу "сделать странное", интереснее делать под конкретные подключенные устройства. Оно будет и проверкой, и конкретным ориентиром для изменений.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Как создать RISC-процессор 2024
СообщениеДобавлено: Ср янв 17, 2024 01:28 
Не в сети
Аватара пользователя

Зарегистрирован: Ср июл 03, 2019 11:10
Сообщения: 485
Откуда: Москва
Благодарил (а): 57 раз.
Поблагодарили: 24 раз.
Тут из "странного", пожалуй, только крохотная ширина инструкции. Под операнд отведено только 4 бита, так что особо не разгуляешься.
Именно поэтому одной из 16 команд должна быть команда, которая назначает текущий активный регистр, над которым (до следующего переназначения регистра) производятся всевозможные манипуляции. Можно даже считать с натяжкой, что в системе 16 "аккумуляторов", но в каждый момент времени активен только один. Для простоты обзовем его a.
Для запихивания чисел имеется пара команд (обозначения команд пока условные):
Код:
a = n ;   a = 16a + n ;
Из регистровых операций такое:
Код:
a = rx ;   a += rx ;   a -= rx ;   a *= rx ;   a >>= rx ;   a = a nand rx ;
Для чтения/записи из памяти традиционные load/store:
Код:
a = [ rx ] ;   [ rx ] = a ;
Прыжки:
Код:
call rx ;   ret ;   jz rx ;   jmp rx ;
Ну и осталось место под пару команд, тут можно либо инкремент/декремент конкретного регистра сделать (без назначения его активным), может пригодиться для стеков и обработки строк
Код:
++ rx ;   -- rx ;
или же сделать уменьшение/увеличение регистра a на константу, тоже достаточно полезная в хозяйстве вещь
Код:
a += n ;   a -= n ;
По load/store, кстати, тоже есть варианты. Через них можно организовать стек программно (с ручным инкрементом/декрементом указателя стека), либо возможен вариант с "аппаратными" стеками для одного-двух выбранных регистров, например, r12 и r13, когда при записи/чтении в стек через эти регистры производится их автоматический декремент/инкремент. Более того, можно и для строковых манипуляций или копирования буферов выделить пару регистров и делать автоинкремент при записи и чтении. Также, как вариант, могут быть регистры для организации циклов со счетчиком. Или может сделать настраиваемое при записи/чтении поведение каждого регистра, правда пока не знаю как. При этом в остальном такие "особенные" регистры ничем не будут отличаться от прочих, над ними точно так же можно производить арифметические манипуляции, как и над остальными. Тут простор для творчества, одним словом.

Что-то мне подсказывает, что плотность кода будет заметно выше, чем в ARM или Thumb, а может даже удастся посостязаться в этом компоненте с каким-нибудь CISC, допустим, с x86. И хотя на первый взгляд кажется, что такое изделие будет проигрывать другим по скорости, однако при желании мы всегда имеем возможность выполнить несколько простых операций одновременно за такт. Более того, сами RISC-и зачастую не умеют делать за такт элементарные вещи, например, прыгать или пихать произвольное число в произвольный регистр, так что и в этом компоненте пободаемся :)


Последний раз редактировалось Total Vacuum Ср янв 17, 2024 22:44, всего редактировалось 1 раз.

Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Как создать RISC-процессор 2024
СообщениеДобавлено: Ср янв 17, 2024 22:22 
Не в сети
Аватара пользователя

Зарегистрирован: Ср июл 03, 2019 11:10
Сообщения: 485
Откуда: Москва
Благодарил (а): 57 раз.
Поблагодарили: 24 раз.
Хех, завелось-таки в связке с виртуальной машиной. Скомпилировались и работают 3d-бродилка на форте и пара сишных тестов (змейка и эффект огня), с другими тестами также проблем не будет.
Виртуальную машину сразу делал в варианте с поддержкой "аппаратного" стека, но проверил также и с ядром, в котором стек реализован программно. Бродилка при переходе от программного стека к аппаратному сразу худеет на 1Kb (примерно 3Kb до 2Kb). Точно не помню, но толщина таких же прошивок под ARM/Thumb была где-то 4-5Kb, для x86 было где-то 2Kb, а для форт-процессора 584 байта. :) Позже гляну более точно.
Кстати, если планируется использовать сабж в связке с Фортом (а оно именно так и планируется), то можно провернуть такой трюк: оставить пару-тройку регистров для промежуточных вычислений, а в остальные регистры загнать адреса форт-примитивов, тогда каждый из них можно будет вызывать однобайтовой инструкцией call rx. В таком варианте бродилка худеет до 1.8K. :)

Интересно, какие еще фишки заложить, чтобы такой процессор был максимально forth-friendly?

upd. Как и ожидалось, все сишные тесты под r8 успешно скомпилировались и работают. Для адаптации под новый процессор транслятор си пришлось поменять буквально в паре мест, чуточку больше правок пришлось сделать в форте, который пожирает выхлоп транслятора си, упрощенный вариант ассемблера на макросах fasm делается элементарно (штатный тоже надо будет сделать, но позже), ну и небольшое ядро форт-системы на этом ассемблере пришлось набросать. Если сравнивать плотность кода, например, на бродилке, то цифры такие:
Код:
                file vm  size xv4 *
----- --------- ---- --- ---- --- ---------
[wolf3d.f]
arm   lpc2129            4656 8.0
thumb stm32f042          3940 6.7
risc  r8        2818-435=2383 4.1 sw stack
risc  r8        2261-435=1826 3.1 hw stack
x86                      1799 3.1
risc  r8        1952-435=1517 2.6 reg calls
forth cpu16v1   1011-248= 763 1.3
forth cpu16v2    995-251= 744 1.3
forth cpu16v3    915-296= 619 1.1
forth cpu16v4    880-296= 584 1.0
Т.е. плотность кода для этого теста получается примерно на одном уровне с x86 (16 бит), но при этом раза в 3 жирнее, чем код для форт-процессора, а arm и thumb ожидаемо дают заметно более рыхлый код. Змейка под r8 примерно в 2 с лишним раза толще аналогичной под форт-процессор:
Код:
[snake.c]
risc  r8        3227-435=2792 2.2 reg calls
x86                      2413 1.9
forth cpu16v4   1593-296=1297 1.0
В целом, если сравнивать с плотностью кода для форт-процессоров, будет проигрыш раза в 2-4, что не смертельно. О производительности не переживаю, ибо планирую при помощи широкого машинного слова (а 8-битные команды как раз позволяют утрамбовать много таких команд в слово разумного размера) выполнять несколько команд параллельно. Эти и другие тесты тут: http://totalvacuum.ru/density.zip
Интересный пример с "hello, world". Там версия под x86 весит меньше forth-версии (74 vs 99). Дело в том, что в x86 printc и printf реализованы на asm, а в форт-процессоре написаны на Си и компилируютя при помощи далеко не самого эффективного компилятора. Но стоит лишь переписать эти два определения хотя бы на Форте, как бинарник худеет с 99 до 72 байт. На форт-ассемблере будет еще меньше. И это при том, что в x86 сама строка весит 12 байт (без завершающего нуля), а в форт-процессоре Гарвард, память программ недоступна для чтения, поэтому строка выкладывается в RAM байт за байтом, а код, который это делает, весит 36 байт (получается 3 байта на символ, в теории может быть и до 4 с половиной), а в r8 вообще чудовищные 6 байт на символ получаются. Такая вот ахиллесова пята отросла. :) В r8 может быть частично вылечено введением строковых регистров r10/r11 как в x86 es:si/ss:di для lodsb/stosb, тогда будет 3 байта на символ. Ну или фон Нейман :)
Кстати, на маленьких прошивках r8 начинает сильнее отставать от форт-процессора и x86, но это из-за того, что в прошивке присутствует код, который выполняет инициализацию регистров адресами форт-примитивов. Ну и сишные реализации printc и т.д. в сравнении с ассемблерными в x86 добавляют бодипозитива. Но при увеличении размера прошивки вклад этого кода уменьшается и прошивка сравнивается по размеру с x86.

upd. Сделал трансляцию в verilog варварским способом: вместо полноценного транслятора накидал простенькую утилиту, которая в com-файле пропускает реализацию виртуальной машины, а далее побайтно выводит прошивку в виде
Код:
code[16'hAAAA]=8'hBB;
Так что теперь можно приступать к реализации в ПЛИС. И выходит, что в таких простых случаях свой ассемблер не обязательно писать.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Как создать RISC-процессор 2024
СообщениеДобавлено: Вт янв 30, 2024 17:45 
Не в сети
Аватара пользователя

Зарегистрирован: Ср июл 03, 2019 11:10
Сообщения: 485
Откуда: Москва
Благодарил (а): 57 раз.
Поблагодарили: 24 раз.
Нулевая версия процессора R8 ожидаемо заработала (пока в самом примитивном варианте с программной реализацией стека данных). Проект под Tang Nano 9K и несколько простых тестов:
http://totalvacuum.ru/mcur8tn9.zip
Для сравнения одна из первых версий Форт-процессора с теми же тестами:
http://totalvacuum.ru/mcu16tn9.zip
Тесты лежат в папке FIRMWARE, каждый тест пересобирается через соответствующий rebuild.bat, после чего нужно сделать Rebuild All в Gowin IDE и залить в ПЛИС. В Форт-процессоре глубина стеков ограничена (define `DEPTH 16), для некоторых тестов этого недостаточно, поэтому чтобы работало, для факториала и Фибоначчи (fact.c и fib.c) ставил наугад 32, а для теста с ферзями (nq.c) 64. В RISC-процессоре ограничен только стек возвратов, а стек данных лежит в RAM, поэтому здесь проще: без увеличения параметра DEPTH работают все тесты, кроме Фибоначчи.
Остался единственный момент, с которым пока не могу разобраться: почему-то Gowin прошивку для Форт-процессора размещает в BSRAM, а для RISC-процессора практически такое же описание трамбует в ячейки LUT.

Система команд сейчас такая:
Код:
0X 0000[im]           a=16a+n
1X 0001[im] inc n     a+=n
2X 0010[im] dec n     a-=n
3X 0011[im] num n     a=n
4X 0100[rx] reg rx    a@rx
5X 0101[rx] mul rx    a*=rx
6X 0110[rx] nand rx   a=a nand rx
7X 0111[rx] ldr rx    a=[rx]
8X 1000[rx] shr rx    a>>=rx
9X 1001[rx] add rx    a+=rx
AX 1010[rx] sub rx    a-=rx
BX 1011[rx] mov rx    a=rx
CX 1100[rx] call rx   call rx
DX 1101[rx] jz rx     jz rx
EX 1110[rx] jnz rx    jnz rx
FX 1111[rx] str rx    [rx]=a

FF 11111111 ret       ret
В принципе, получилось довольно удобно. Если назначить по паре специальных регистров для циклов, стеков и строк, то будет еще удобнее. Но все-таки со стороны виднее, может какие-то команды следует убрать/добавить/заменить? Например, есть мысли объединить a+=n/a-=n, а освободившийся опкод задействовать для чего-то другого. Или jz объединить с jmp, а слот jnz освободить. Или наоборот только jnz оставить. Т.е. кандидаты на освобождение и уплотнение есть, но на что именно их заменить, пока не вижу. Как вариант, можно утрамбовать в один освободившийся слот 16 "безоперандных" команды, которые издеваются над текущим "аккумулятором" или над стеком возвратов, например, negate/not/invert/shl/shr/ror/push/pop/... :D
Ну а если наоборот двигаться в сторону упрощения, то можно было бы заменить inc/dec/nand на or/xor/and, ну и jnz на jmp за компанию.


Последний раз редактировалось Total Vacuum Ср янв 31, 2024 23:44, всего редактировалось 1 раз.

Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Как создать RISC-процессор 2024
СообщениеДобавлено: Ср янв 31, 2024 02:21 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7990
Благодарил (а): 26 раз.
Поблагодарили: 144 раз.
Total Vacuum писал(а):
Остался единственный момент, с которым пока не могу разобраться: почему-то Gowin прошивку для Форт-процессора размещает в BSRAM, а для RISC-процессора практически такое же описание трамбует в ячейки LUT.

Если к памяти нет доступа на запись, она трактуется синтезатором как ROM. Соответственно, для нее можно подобрать эквивалентную схему, которая будет давать такой же ответ на поданные адреса.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Как создать RISC-процессор 2024
СообщениеДобавлено: Ср янв 31, 2024 15:15 
Не в сети
Аватара пользователя

Зарегистрирован: Ср июл 03, 2019 11:10
Сообщения: 485
Откуда: Москва
Благодарил (а): 57 раз.
Поблагодарили: 24 раз.
Почистил немного исходник, поубирал избыточный код, в результате прошивка переползла в BSRAM. 16-битная черная магия... :D

Понадобилось проверить, работает ли крохотный OLED-дисплей 0.91'' 128x32. Накидал софтовый I2C и задрыгал ногами SCL/SDA программно через GPIO, на удивление почти сразу же заработало :) Понятно, что для таких случаев лучше иметь аппаратный I2C на верилоге. Собственно, так и сделано во всех серийных микроконтроллерах: на борту один или несколько модулей I2C на все случаи жизни. Я тоже накидаю модуль I2C (а также SPI и много чего еще), когда руки дойдут. Но в софт-процессорах есть другие альтернативы: можно сделать не просто I2C, а сразу реализовать поддержку, например, SSD1306 (как в моем дисплее) на верилоге и скармливать ему данные через регистры или общий кусок памяти. Или можно отдельное процессорное ядро сделать, которое также будет взаимодействовать с основным процессором через общую BRAM или регистры. И будет заниматься исключительно обработкой поступающих данных и выводом на дисплей. Если такое видеоускорителем обозвать, оно не обидится :D
Изображение
http://totalvacuum.ru/oledtest.jpg


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Как создать RISC-процессор 2024
СообщениеДобавлено: Пт фев 02, 2024 20:04 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7990
Благодарил (а): 26 раз.
Поблагодарили: 144 раз.
Ну и правильно! В сравнении с отладкой аппаратного модуля использовать процессор для управления лапками ПЛИС существенно удобнее. Не говоря уже об отладке поддержки конкретного устройства. И почему бы не называть такое видеоускорителем, оно же по факту ускоряет определенный аспект работы системы.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 8 ] 

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB