Forth https://fforum.winglion.ru/ |
|
Как создать RISC-процессор 2024 https://fforum.winglion.ru/viewtopic.php?f=3&t=3392 |
Страница 1 из 1 |
Автор: | Total Vacuum [ Сб янв 13, 2024 23:24 ] |
Заголовок сообщения: | Как создать RISC-процессор 2024 |
Словил себя на мысли, что коль скоро простейший форт-процессор с 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-ам. Пора начинать? ![]() |
Автор: | Hishnik [ Сб янв 13, 2024 23:55 ] |
Заголовок сообщения: | Re: Как создать RISC-процессор 2024 |
Да никуда не денется, оно обычно заводится. Главное, не пытаться сразу "сделать странное", интереснее делать под конкретные подключенные устройства. Оно будет и проверкой, и конкретным ориентиром для изменений. |
Автор: | Total Vacuum [ Ср янв 17, 2024 01:28 ] |
Заголовок сообщения: | Re: Как создать RISC-процессор 2024 |
Тут из "странного", пожалуй, только крохотная ширина инструкции. Под операнд отведено только 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:22 ] |
Заголовок сообщения: | Re: Как создать RISC-процессор 2024 |
Хех, завелось-таки в связке с виртуальной машиной. Скомпилировались и работают 3d-бродилка на форте и пара сишных тестов (змейка и эффект огня), с другими тестами также проблем не будет. Виртуальную машину сразу делал в варианте с поддержкой "аппаратного" стека, но проверил также и с ядром, в котором стек реализован программно. Бродилка при переходе от программного стека к аппаратному сразу худеет на 1Kb (примерно 3Kb до 2Kb). Точно не помню, но толщина таких же прошивок под ARM/Thumb была где-то 4-5Kb, для x86 было где-то 2Kb, а для форт-процессора 584 байта. ![]() Кстати, если планируется использовать сабж в связке с Фортом (а оно именно так и планируется), то можно провернуть такой трюк: оставить пару-тройку регистров для промежуточных вычислений, а в остальные регистры загнать адреса форт-примитивов, тогда каждый из них можно будет вызывать однобайтовой инструкцией call rx. В таком варианте бродилка худеет до 1.8K. ![]() Интересно, какие еще фишки заложить, чтобы такой процессор был максимально forth-friendly? upd. Как и ожидалось, все сишные тесты под r8 успешно скомпилировались и работают. Для адаптации под новый процессор транслятор си пришлось поменять буквально в паре мест, чуточку больше правок пришлось сделать в форте, который пожирает выхлоп транслятора си, упрощенный вариант ассемблера на макросах fasm делается элементарно (штатный тоже надо будет сделать, но позже), ну и небольшое ядро форт-системы на этом ассемблере пришлось набросать. Если сравнивать плотность кода, например, на бродилке, то цифры такие: Код: file vm size xv4 * Т.е. плотность кода для этого теста получается примерно на одном уровне с x86 (16 бит), но при этом раза в 3 жирнее, чем код для форт-процессора, а arm и thumb ожидаемо дают заметно более рыхлый код. Змейка под r8 примерно в 2 с лишним раза толще аналогичной под форт-процессор:----- --------- ---- --- ---- --- --------- [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 Код: [snake.c] В целом, если сравнивать с плотностью кода для форт-процессоров, будет проигрыш раза в 2-4, что не смертельно. О производительности не переживаю, ибо планирую при помощи широкого машинного слова (а 8-битные команды как раз позволяют утрамбовать много таких команд в слово разумного размера) выполнять несколько команд параллельно. Эти и другие тесты тут: http://totalvacuum.ru/density.ziprisc r8 3227-435=2792 2.2 reg calls x86 2413 1.9 forth cpu16v4 1593-296=1297 1.0 Интересный пример с "hello, world". Там версия под x86 весит меньше forth-версии (74 vs 99). Дело в том, что в x86 printc и printf реализованы на asm, а в форт-процессоре написаны на Си и компилируютя при помощи далеко не самого эффективного компилятора. Но стоит лишь переписать эти два определения хотя бы на Форте, как бинарник худеет с 99 до 72 байт. На форт-ассемблере будет еще меньше. И это при том, что в x86 сама строка весит 12 байт (без завершающего нуля), а в форт-процессоре Гарвард, память программ недоступна для чтения, поэтому строка выкладывается в RAM байт за байтом, а код, который это делает, весит 36 байт (получается 3 байта на символ, в теории может быть и до 4 с половиной), а в r8 вообще чудовищные 6 байт на символ получаются. Такая вот ахиллесова пята отросла. ![]() ![]() Кстати, на маленьких прошивках r8 начинает сильнее отставать от форт-процессора и x86, но это из-за того, что в прошивке присутствует код, который выполняет инициализацию регистров адресами форт-примитивов. Ну и сишные реализации printc и т.д. в сравнении с ассемблерными в x86 добавляют бодипозитива. Но при увеличении размера прошивки вклад этого кода уменьшается и прошивка сравнивается по размеру с x86. upd. Сделал трансляцию в verilog варварским способом: вместо полноценного транслятора накидал простенькую утилиту, которая в com-файле пропускает реализацию виртуальной машины, а далее побайтно выводит прошивку в виде Код: code[16'hAAAA]=8'hBB; Так что теперь можно приступать к реализации в ПЛИС. И выходит, что в таких простых случаях свой ассемблер не обязательно писать.
|
Автор: | Total Vacuum [ Вт янв 30, 2024 17:45 ] |
Заголовок сообщения: | Re: Как создать RISC-процессор 2024 |
Нулевая версия процессора 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 В принципе, получилось довольно удобно. Если назначить по паре специальных регистров для циклов, стеков и строк, то будет еще удобнее. Но все-таки со стороны виднее, может какие-то команды следует убрать/добавить/заменить? Например, есть мысли объединить a+=n/a-=n, а освободившийся опкод задействовать для чего-то другого. Или jz объединить с jmp, а слот jnz освободить. Или наоборот только jnz оставить. Т.е. кандидаты на освобождение и уплотнение есть, но на что именно их заменить, пока не вижу. Как вариант, можно утрамбовать в один освободившийся слот 16 "безоперандных" команды, которые издеваются над текущим "аккумулятором" или над стеком возвратов, например, negate/not/invert/shl/shr/ror/push/pop/... 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 ![]() Ну а если наоборот двигаться в сторону упрощения, то можно было бы заменить inc/dec/nand на or/xor/and, ну и jnz на jmp за компанию. |
Автор: | Hishnik [ Ср янв 31, 2024 02:21 ] |
Заголовок сообщения: | Re: Как создать RISC-процессор 2024 |
Total Vacuum писал(а): Остался единственный момент, с которым пока не могу разобраться: почему-то Gowin прошивку для Форт-процессора размещает в BSRAM, а для RISC-процессора практически такое же описание трамбует в ячейки LUT. Если к памяти нет доступа на запись, она трактуется синтезатором как ROM. Соответственно, для нее можно подобрать эквивалентную схему, которая будет давать такой же ответ на поданные адреса. |
Автор: | Total Vacuum [ Ср янв 31, 2024 15:15 ] |
Заголовок сообщения: | Re: Как создать RISC-процессор 2024 |
Почистил немного исходник, поубирал избыточный код, в результате прошивка переползла в BSRAM. 16-битная черная магия... ![]() Понадобилось проверить, работает ли крохотный OLED-дисплей 0.91'' 128x32. Накидал софтовый I2C и задрыгал ногами SCL/SDA программно через GPIO, на удивление почти сразу же заработало ![]() ![]() ![]() http://totalvacuum.ru/oledtest.jpg |
Автор: | Hishnik [ Пт фев 02, 2024 20:04 ] |
Заголовок сообщения: | Re: Как создать RISC-процессор 2024 |
Ну и правильно! В сравнении с отладкой аппаратного модуля использовать процессор для управления лапками ПЛИС существенно удобнее. Не говоря уже об отладке поддержки конкретного устройства. И почему бы не называть такое видеоускорителем, оно же по факту ускоряет определенный аспект работы системы. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |