Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Пт фев 07, 2025 11:48

...
Google Search
Forth-FAQ Spy Grafic

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




Ответить
Имя пользователя:
Заголовок:
Текст сообщения:
Введите текст вашего сообщения. Длина сообщения в символах не более: 60000

Размер шрифта:
Цвет шрифта
Настройки:
BBCode ВКЛЮЧЕН
[img] ВЫКЛЮЧЕН
[flash] ВЫКЛЮЧЕН
[url] ВКЛЮЧЕН
Смайлики ВЫКЛЮЧЕНЫ
Отключить в этом сообщении BBCode
Не преобразовывать адреса URL в ссылки
Вопрос
Теперь гостю придется вводить здесь пароль. Не от своей учетной записи, а ПАРОЛЬ ДЛЯ ГОСТЯ, получить который можно после регистрации на форуме через ЛС.:
Этот вопрос предназначен для выявления и предотвращения автоматических регистраций.
   

Обзор темы - Как создать RISC-процессор 2024
Автор Сообщение
  Заголовок сообщения:  Re: Как создать RISC-процессор 2024  Ответить с цитатой
Ну и правильно! В сравнении с отладкой аппаратного модуля использовать процессор для управления лапками ПЛИС существенно удобнее. Не говоря уже об отладке поддержки конкретного устройства. И почему бы не называть такое видеоускорителем, оно же по факту ускоряет определенный аспект работы системы.
Сообщение Добавлено: Пт фев 02, 2024 20:04
  Заголовок сообщения:  Re: Как создать RISC-процессор 2024  Ответить с цитатой
Почистил немного исходник, поубирал избыточный код, в результате прошивка переползла в BSRAM. 16-битная черная магия... :D

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

Если к памяти нет доступа на запись, она трактуется синтезатором как ROM. Соответственно, для нее можно подобрать эквивалентную схему, которая будет давать такой же ответ на поданные адреса.
Сообщение Добавлено: Ср янв 31, 2024 02:21
  Заголовок сообщения:  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
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 за компанию.
Сообщение Добавлено: Вт янв 30, 2024 17:45
  Заголовок сообщения:  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 *
----- --------- ---- --- ---- --- ---------
[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;
Так что теперь можно приступать к реализации в ПЛИС. И выходит, что в таких простых случаях свой ассемблер не обязательно писать.
Сообщение Добавлено: Ср янв 17, 2024 22:22
  Заголовок сообщения:  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-и зачастую не умеют делать за такт элементарные вещи, например, прыгать или пихать произвольное число в произвольный регистр, так что и в этом компоненте пободаемся :)
Сообщение Добавлено: Ср янв 17, 2024 01:28
  Заголовок сообщения:  Re: Как создать RISC-процессор 2024  Ответить с цитатой
Да никуда не денется, оно обычно заводится. Главное, не пытаться сразу "сделать странное", интереснее делать под конкретные подключенные устройства. Оно будет и проверкой, и конкретным ориентиром для изменений.
Сообщение Добавлено: Сб янв 13, 2024 23:55
  Заголовок сообщения:  Как создать 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-ам. Пора начинать? :)
Сообщение Добавлено: Сб янв 13, 2024 23:24

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


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