Структурная схема «Koyaanisqatsi-CPU»
![Структура Койяанискаци](https://habrastorage.org/getpro/habr/post_images/6cf/09d/4dd/6cf09d4dd7f5c69ebbb98a4b01b2d3ad.png)
SVG-Файл (актуальная версия)
Лирика
Античные времена знакомы каждому не только бессмертными произведениями от пера Гомера, но и таблицей умножения Пифагора, геометрией Евклида и винтом Архимеда под знаком Пи, которыми человечество научилось пользоваться в полной мере лишь относительно недавно. Если в античности искусством было не только уметь писать стихи и прозу, но и проектировать катапульты или стенобитные орудия, то сейчас существуют жёсткие рамки и разделения, когда вывести очередную самодостаточную красивую и полезную формулу является искусством лишь как формальная игра слов. Математика правит современным миром безраздельно, цинично переплетаясь с миром искусства, нагло вторгаясь хитрейшими вычислениями во все сферы нашего досуга, отдыха и быта, диктуя свои правила и законы, под давлением которых выцветают и пёстрые краски знаменитых шедевров, переходя в ядовитые оттенки полнометражек.
Содержание
К сожалению, зачастую математика способна искажать наше восприятие окружающего мира своим давлением ТУ в рамках экономики, когда Пломбир или Птичье Молоко не могут уже вызывать ту игру вкусовых ощущений, которые задумывались кондитерами как вольный полёт неограниченной фантазии под руководством опыта и мастерства.
Современные инженеры слепо оперируют сухими цифрами, не вспоминая об искусстве как начале всех начал и поддаваясь требованиям рынка, глухого бизнеса и слепой к эстетике экономики, в свете которых формируются неуклюжие или даже уродливые стандарты, как например ASCII, скэн-код или IA-32. Если скэн-код выделен был в спартанском прототипе дизайна клавиатуры, был продиктован расположением клавиш на матрице, стал стандартом лишь по чистой случайности захваченного рынка ЭВМ, то не совсем понятно, отчего ASCII-таблица не такая уж красивая и внятная, как могла бы выглядеть в идеале и уж не понятно, какие такие ТУ её могли исказить:
Некоторые неочевидные несоответствия
ASCII-код | Символ напротив | Как могло быть в идеале |
---|---|---|
32₁₆: «2» | 22₁₆: «"» | «2» похожа на «%» |
35₁₆: «5» | 25₁₆: «%» | «5» похожа на «$» |
36₁₆: «6» | 26₁₆: «&» | «6» похожа на «(» |
37₁₆: «7» | 27₁₆: «'» | «7» похожа на «?» |
38₁₆: «8» | 28₁₆: «(» | «8» похожа на «&» |
39₁₆: «9» | 29₁₆: «)» | «6» и «9» симметричны как «(» и «)» |
Выделив под управляющие коды никому не нужные уже 32 комбинации, авторами была создана благоприятная почва, где до сих пор всё встречаются такие сорняки, как «БНОПНЯ» и «Кракозябры» в самом неожиданном и даже противном своём проявлении.
Та же сухая экономика своими цифрами вынуждала инженеров Intel упрощать первый процессор, в угоду угрюмой совместимости с далеко не самой лучшей архитектурой той поры, своим спринтерским стремлением выбросить на массовый рынок свой чип. Никто не задумывался тогда, что безобразный машинный код тот станет стандартом мирового уровня, на который без боли и стыда посмотреть никак нельзя будет уж! Никому в голову не пришло переключиться от математического искусства измерения наносекунд задежки и граммов проволочек на эстетическую картину изделия, чтобы система команд не уходила в своём физическом пике энтропии в океан хаоса: Ведь сейчас уже не важно, какие такие цели тогда преследовались инженерами, так как суперскалярным ядром любого современного процессора поддержка многострадальной системы команд x86 давно совершается уровнем эмуляции как чистая формальность, продиктованная положением рыночных требований, о которые разбился тот Itanium…
Койяанискаци — как крик души!
Если читатель хотя бы раз пытался обратиться к своему компьютеру напрямую и с помощью ассемблера запрограммировать какой-либо код, то не может не знать уже о существовании так называемого объектного кода, байт-кода самого процессора, который существенно далёк от восприятия неподготовленным умом и требует иметь систематический набор специфических знаний о битовых полях и компоновке кода.В противоположность известных всем процессоров «Intel», марку которых довольно легко запоминать и выговаривать, «Койяанискаци» задумывался как процессор, имя которого сложнее произнести, чем разобраться в его архитектуре и научиться его программировать на самом элементарном уровне машинного кода редакторами дампа, чтобы проверить, действительно ли стоит прогибаться под радиолюбительские ТУ и невозможно сформировать красивую систему команд, понятную на уровне интуиции?
Не имеется ввиду код стиля «O'Kей, процик, вычисли мне среднее факториальное», а планировался машинный код с минимальным уровнем вхождения в основы искусства его программирования, не требующего жёсткой зубрёжки и заучивания всех команд.
Кратко задуманный процессор можно описать как некий программируемый контроллер с системой команд без каких-либо битовых полей, где сам шестнадцатеричный байт продиктованный и озвученный устно должен нести краткую и понятную информацию о совершаемой командой действии команды, приближая чтение дампа к чтению формул.
Код | Команда | Примечание |
---|---|---|
A1 | REG A1 | Выбрать регистр A₁ |
B2 | REG B2 | Выбрать регистр B₂ |
AB | ARG A,B | Использовать в АЛУ аргументы в порядке «A,B» — приёмник результата слева и источник данных справа |
2E | EOR A1,B2 | Мы выбрали A₁ и B₂, указали порядок «A,B» и теперь «Eor» знает, откуда брать данные и куда поместить результат |
EF | EIF | Код условного выполнения «Execute If False» следующей команды только в случае, если ФАЛЬШ — признак флага АЛУ ZF сброшен |
A3 | REG A3 | Эта команда, следующая за условием «EIF» исполнится и выберет регистр A₃ только в случае сброшенного ZF. Тем самым, все последующие команды будут работать либо с регистром A₁, либо с регистром A₃ |
4B | SUB A?,B4 | Здесь код 4B правым нибблом «B» означает Вычитание «suB», а левый ниббл «4» указывает на индекс источника — «B₄». А так как предыдущая команда «A3» по условию может быть выполнена или пропущена, то складывается ситуация с условным разветвлением на команды «SUB A1,B4» или «SUB A3,B4» |
Введение
Начальный дизайн процессора задумывался как шуточный автомат со сквозным байт-кодом и возможностью кодировать дамп сценария даже без необходимости обращения к таблице команд до полного их заучивания. Ставилась простая задача разработки простого процессорного устройства, в котором любые из 30 РОН можно заменить на всякую периферию из датчиков, двигателей и соленоидов. В таком дизайне имеется уникальная возможность организации почти непосредственного взаимодействия всех требуемых устройств без надобности в высоких частоте и производительности.Например, PICO-8 и Gigatron, а также MegaProcessor или MyCPU хоть и разработаны специалистами, но никто не подходил к вопросу с чувством эстета, опираясь на сухой технологический расчёт.
К тому же, те же языки программирования, как КОБОЛ, хоть и задумывались с акцентом на гуманитарии, но в широком практическом применении оказались непрактичными и неудобными…
Сейчас, с заменой файлов конфигурации *.inf и *.ini на *.xml, получается, что история снова повторяется…
Архитектура процессора
В самом начале планирования архитектуры процессора не ставилось никакой задачи добиться хотя бы частичной совместимости с какой-либо из имеющихся архитектур, щедро предлагаемыми ведущей индустрией современности. Напротив, основной целью ставилась задача разработать простой процессор, шестнадцатеричным кодированием всех команд в дампе можно было бы заменить ассемблер и даже обойтись без него, так как сами тетрады байта должны представлять аббревиатуры самих команд, а не сухо бинарно кодировать некий абстрактный байт-код с неясными битовыми полями.Конвейер
Конвейер отсутствует по причине его ненадобности в рамках экспериментальности…Регистровый файл
Весь процессор основан на регистровом файле из четырёх функциональных групп по десять ячеек в каждой. Хотя операции АЛУ возможны над любыми ячейками, правила корректного оперирования с ними соблюдать необходимо более-менее строго. Здесь стоит просто запомнить логику и назначение этих функциональных групп:Группа | Назначение | Примечание |
---|---|---|
A₀…₉ | Аккумулятор | A₀ хранит флажки статуса АЛУ |
B₀…₉ | Base / База | B₀ хранит Базу возврата из подпрограммы |
C₀…₉ | Counter / Счётчик | C₀ хранит Смещение возврата из подпрограммы |
D₀…₉ | Device / Устройство | Можно организовать кеш |
Особенностью регистрового файла является свободное назначение практически всех регистров, которые можно заменить внешней периферией малой степени интеграции, что позволяет показания всяких датчиков или управлять электроприводом напрямую через ссылку как на обыкновенный РОН.
Подпрограммы
Так как процессор достаточно прост и не имеет встроенных аппаратных механизмов организации стековых операций, регистры B₀:C₀ сохраняют адрес, на котором была размещена операция обращения к подпрограмме. Программист при необходимости сам обязан позаботиться о всех операциях работы со стеком и описать их алгоритмом. Для облегчения разработки алгоритма, следует использовать небольшую библиотеку кратких подфункций, выполняющих необходимые операции ветвления и вызова всяких пользовательских подпрограмм, реализующие механизмы стека программным уровнем.Библиотеку можно найти отдельным файлом в ресурсах репозитория этого проекта.
Работа с памятью
При доступе к внешней памяти нужная ячейка адресуется парой активных регистров Bi и Cj, где Bi указывает на Базу Блока по 256 ячеек и Cj указывает в блоке на конкретную ячейку. Медленная память может удлинить цикл доступа сигналом Wait.Кеш и периферия
Регистры D₀…₉ не следует использовать в активных вычислительных процессах, так как они управляют периферией непосредственного доступа с мгновенным откликом и пригодны для организации процессорного кеша и контекстного регистрового файла.Формат команд Койяанискаци
Первостепенной целью в разработке процессора ставилась задача совмещения RISC-кода с внешней читабельностью бинарного представления команд шестнадцатеричным дампом, где алфавитно-цифровые символы двух нибблов несут смысловую нагрузку в виде своеобразных аббревиатур, пригодных к использованию в качестве мнемоники.Код | Нибблы | Аббревиатурная нагрузка |
---|---|---|
A1 | A 1 | Активировать в группе A регистр #1 |
BE | B E | Загрузить в активный регистр группы B извлечённые (Extract) данные из памяти |
EC | E C | Исполнить (Execute) операции только в случае переноса (Carry) по флагу CF |
EE | E E | Исполнить (Execute) операции только в случае эквивалентности (Equal) по флагу ZF |
30 | 3 0 | Префикс репетиции команды 3 раза, где «0» символизирует скобки «()», что условно можно обозначить как «3×(…)» |
CB | C B | Подготовить регистровые группы C и B для АЛУ-операции составом «C,B» |
1A | 1 A | Работать с регистром #1 группы второго операнда при выполнении операции сложения (Add) |
Эффективные и префиксные операции Койяанискаци
Таблица
Код | Класс | Примечание |
---|---|---|
0A⋮9A | АЛУ | Вычисление суммы с произвольным членом трансляции с помещением в активный приёмник |
0B⋮9B | АЛУ | Вычисление разности с произвольным членом трансляции с помещением в активный приёмник |
0C⋮9C | АЛУ | Вычисление побитовой конъюнкции с произвольным членом трансляции с помещением в активный приёмник |
0D⋮9D | АЛУ | Вычисление побитовой дизъюнкции с произвольным членом трансляции с помещением в активный приёмник |
0E⋮9E | АЛУ | Вычисление побитового логического модуля с произвольным членом трансляции с помещением в активный приёмник |
0F⋮9F | Регистры | Копирование данных произвольного члена трансляции в активный приёмник |
A0…A9 | Регистры | Выбор активного члена группы A |
B0…B9 | Регистры | Выбор активного члена группы B |
C0…C9 | Регистры | Выбор активного члена группы C |
D0…D9 | Регистры | Выбор активного члена группы D |
AA…AD | АЛУ | Выбор группы приёмников результата и трансляторов данных A,A / A,B / A,C / A,D |
BA…BD | АЛУ | Выбор группы приёмников результата и трансляторов данных B,A / B,B / B,C / B,D |
CA…CD | АЛУ | Выбор группы приёмников результата и трансляторов данных C,A / C,B / C,C / C,D |
DA…DD | АЛУ | Выбор группы приёмников результата и трансляторов данных D,A / D,B / D,C / D,D |
AE | Память | Извлечение данных из памяти в активный член группы A |
AF | Память | Помещение результата из активного члена группы A в память |
BE | Память | Извлечение данных из памяти в активный член группы B |
BF | Память | Помещение результата из активного члена группы B в память |
CE | Память | Извлечение данных из памяти в активный член группы C |
CF | Память | Помещение результата из активного члена группы C в память |
DE | Память | Извлечение данных из памяти в активный член группы D |
DF | Память | Помещение результата из активного члена группы D в память |
EA | Условие | Выполнение по активному флагу SF |
EB | Условие | Выполнение по снятому флагу SF |
EC | Условие | Выполнение по активному флагу CF |
ED | Условие | Выполнение по снятому флагу CF |
EE | Условие | Выполнение по активному флагу ZF |
EF | Условие | Выполнение по снятому флагу ZF |
F0…FF | Функции | Обращение к программной функции по адресам F000…FF00 |
Система команд Койяанискаци
Практически все команды кодируются WYSIWYG-стилем акына:«Что вижу, то значит». Шестнадцатеричная кодировка отчасти является аббревиатурой самой команды и всё задумывалось так, чтобы большинство команд просто совершали понятные действия.- 00: HLT (останов программы) — крайне логичный и гармоничный код!
- 01…99: Используется BCD-код приращения к активному регистру-приёмнику — код 56 означает именно 56₁₀, а не 0x56₁₆
- 20…90: Префикс повтора операции от 2 до 9 раз или пропуск группы операций по условию записью 2…9×(………)
- A0…A9, B0…B9, C0…C9: Безвременные префиксы выбора активного регистра указанной группы — A₀…A₉, B₀…B₉, C₀…C₉ соответственно
- D0…D9: Выбор активного устройства группы Devices — D₀…D₉
- AA…AD, BA…BD, CA…CD, DA…DD: Безвременные префиксы выбора сочетания операндов для АЛУ-операций — A,A…D,D соответственно
- E0…E7: Обращение к расширению (Extension) через подпрограмму — CALL 0xE000…0xE700
- F1…F9: Обращение к функции (Function) с указанным индексом — CALL 0xF100…0xF900
- E8…EF: Условный префикс к исполнению кода следующей операции — Enable if SF/PF/CF/ZF
- F0: Завершение текущей функции (Function Over — как Game Over)
- AE/BE/CE/DE: Извлечение (Extract) данных из памяти в указанный регистр
- AF/BF/CF/DF: Запись/фиксация (Fix) данных указанного регистра в память
- FA…FF: Вызов прочих функций — CALL 0xFA00…0xFF00
- 0A/1A/2A…9A: АЛУ-операция «Сумма» (Add) над группой операндов — индекс правого операнда указывается явно 0…9
- 0B/1B/2B…9B: АЛУ-операция «Вычитание» (suB) над группой операндов — индекс правого операнда указывается явно 0…9
- 0C/1C/2C…9C: АЛУ-операция «Конъюнкция» (Conjunct/and) над группой операндов — индекс правого операнда указывается явно 0…9
- 0D/1D/2D…9D: АЛУ-операция «Дизъюнкция» (Disjunct/or) над группой операндов — индекс правого операнда указывается явно 0…9
- 0E/1E/2E…9E: АЛУ-операция «Исключающее ИЛИ» (Exclusive or/Eor/xor) над группой операндов — индекс правого операнда указывается явно 0…9
Основы программирования Койяанискаци
Однако, тут не стоит думать, что «процессор акына» совсем ничего не требует от продвинутого пользователя-программиста: Минимальный порог вхождения преодолеть всё-таки придётся… А значит, придётся чуточку поднапрячься и преодолеть порог!(Здесь подразумевается, что читатель уже имеет все базовые понятия и принципы, позволяющие ориентироваться в синтаксической конструкции и строить выражения…)
Сложение величин из регистров A₁ и B₂ традиционно можно представить выражением «A1 += B2» или мнемонической записью «ADD A1,B2», которую и следует оформить в машинный код. Так как архитектура процессора предельно проста и организовалась на польской записи, буквально необходимо сначала предопределить используемые в операции операнды, чтобы потом произвести саму конкретную операцию вычисления.
Так как используется сочетание регистров «A1» и «B2» в порядке «An,Bn», то под их определение следует указать машинный код AB₁₆. Выбор индексов на конкретных операндах выполняется кодами A1₁₆ и B2₁₆, что указывает на буквальность кодов. Так как индекс правого операнда равен двум, то в коде АЛУ-операции «Сумма» его следует указать явно в левой тетраде как 2A₁₆. Тем самым, становится очевидным размещения кода всего выражения как «A1 AB B2 2A». Но так как индекс B₂ указан явно в АЛУ-операции, байт команды «B2» можно исключить из цепочки, так как сам регистр B₂ не является приёмником результата и код сократится до одной из двух комбинаций записи «A1 AB 2A» или «AB A1 2A», так как от расположения префиксов перед операциями результат не изменяется и всё зависит от стиля программиста.
Выражение «A1 = A1 + B2 - B3 & B4 | B5 ^ B6» можно описать последовательностью «A1 AB 2A 3B 4C 5D 6E», так как в каждом следующем коде операции явно указан и индекс правого операнда, что позволяет писать код компактно и производительно.
Префиксы повтора
Для расширения функциональности некоторых операций существует группа префиксов предустановки счётчика упреждения цикла выборки очередного кода или расширения адресации. Арифметические операции выполняются циклом, а логически — смещением бит на заданную величину. Операции доступа к произвольной ячейке памяти просто выбирают индекс пары Bx:Cx указателя.- «(REP 9)(XOR A1,B1)» эквивалентно «A1 ^= SWAP(B1)» (реверсия бит)
- «(REP 8)(XOR A1,B1)» эквивалентно «A1 ^= ~B1»
- «(REP 7)(ADD A1,B1)» эквивалентно «A1 += B1 * 7»
- «(REP 6)(XOR A1,B1)» эквивалентно «A1 ^= B1 << 6»
- «(REP 5)(EXT A1)» эквивалентно «A1 = *(B5:C5)»
- «(REP 4)(HLT 0xFE00)» эквивалентно «CALL 0xFE40»
- «(REP 3)(RET)» эквивалентно «RET(B3:C3)»
Максимально доступно каждому любителю
Так как Logisim куда доступнее и проще того же Proteus и компактнее KiCAD, вся схема процессора разрабатывалась в рамках проекта именно Logisim, чтобы проект был по-детски прост и лёгок для использовании заинтересованными любителями. По предварительным подсчётам, если схему проекта попытаться собирать микросхемами серии 74xx или отечественной номенклатуры, понадобится порядка 250 корпусов…При грамотном подходе проектирования процессоров с применением мультиплексоров и специализированных микросхем РОН, число всех микросхем может снизиться всего до сотни корпусов с повышением производительности без переходов в Z-состояние.
Если смущает использование ПЗУ для дешифрации команд, имеется набросок схемы с использованием уровня комбинаторики, по которой можно осознать, что и красивую систему команд можно декодировать простейшим способом логических вентилей, без ущерба концептуальной задумки!
Эмуляция?
Никакого программного эмулятора не задумывалось специально, чтобы архитектурно процессор изначально готовился к реализации на физических макетных платах и не содержал в себе решений, которые аппаратно крайне сложно будет реализовывать в силу излишней вольности в эмуляторе. Вся схема разрабатывалась несколько лет в часы досуга эпизодически и несколько раз перерисовывалась вся с чистого листа.Ссылки
Скачать исходные файлы симуляции можно здесь.Ознакомиться с Verilog-моделью можно здесь.
Эмулятор с ассемблером/дизассемблером и демо-кодом «Автослалом» — здесь (автозапуск / «классический режим»)…
Эмуляция Койяанискаци на процессоре i8080/z80/580ВМ80 — здесь
Пошаговое построение данного процессора начинается здесь…