A fistful of relays. Часть 3 — декодер команд и управляющий автомат
Он работает полностью на электромагнитных реле и будет состоять из четырех блоков.
На сегодняшний день я закончил уже три из них: АЛУ, регистровый файл и управляющий модуль, который декодирует инструкции раздает остальным блокам указания что делать.
Тёплый ламповый щелкающий звук тактового генератора:
Архитектура
Сначала я думал над гарвардской архитектурой для компьютера, но потом решил, что данные удобнее будет вводить из того же ПЗУ, что и программы. Поэтому теперь у меня будет 8-битная шина адреса и 16-битная шина данных. Все 16 бит используются для чтения кода инструкции и для передачи двух операндов в АЛУ. Данные же считываются в регистр через младшие 8 бит этой шины.
Все инструкции имеют одинаковую ширину, поэтому их чтение получилось совсем простым — достаточно защёлкнуть то, что пришло по шине данных. При этом те же самые реле частично выполняют функции декодирования инструкций, ведь в каждом из них по 4 переключателя.
В результате загрузкой, хранением и декодированием кода инструкции занимаются всего 46 реле, что меньше, чем у HPRC, который я использовал как образец.
Каждая инструкция выполняется за 10 тактов. Так много нужно потому что реле не могут срабатывать по фронту сигнала как микросхемы с несколькими параллельными входами. Приходится выделять целый такт на защёлкивание результата, например. Некоторым командам требуется на 1–2 такта меньше, но я не стал усложнять схему, поэтому эти 10 тактов пробегают всегда:
Команды процессора похожи на ARM — результат вычислений можно поместить в любой регистр. Например, возможна такая безумная операция как XOR PC, A, B. При вызове функции адрес возврата кладётся в регистр L (link register). Обращения к памяти только с помощью отдельных инструкций загрузки (но памяти всё равно пока нет).
Зато, в отличие от ARM, ширина кода инструкции значительно больше ширины регистров. Благодаря этому все загрузки констант, адресов, а также переходы кодируются одной инструкцией.
Есть флаги условного выполнения для переходов — можно проверять знак результата вычислений, равенство нулю и переполнение. Инструкции MOV, CALL и JUMP кодируются почти одинаково, да и делают почти одно и то же. JUMP — это просто пересылка значения в PC. Поэтому есть приятный побочный эффект — для MOV также работает возможность условного выполнения. Т.е. можно выполнить (или не выполнить) MOV NZ, A, 255.
Кроме загрузок и пересылок управляющий модуль умеет подключать регистры к АЛУ и получать результат из него. АЛУ делает сложение, вычитание, OR, XOR, AND, NOT, разные сдвиги на 1 бит. Причём в инструкциях АЛУ есть флаг, который отключает запись результата. То есть команда работает как CMP или TEST на x86, но при этом можно выбрать любую операцию. Например, проверить флаги, как если бы выполнился OR, но не портить никаких регистров.
А теперь попробуем со всем этим взлететьСейчас у компьютера нет никакой памяти кроме регистров, поэтому выполняемую инструкцию можно набрать с помощью тумблеров. Зато потом он может делать ее до бесконечности:
Поддерживаются две частоты тактовых импульсов. Более медленный режим нужен для наблюдения за происходящим внутри компьютера:
Никакой отладчик не нужен — дамп регистров считывается просто глазами:
Дальше осталось реализовать запоминающие устройства. Сейчас уже готов корпус для модуля, где они будут располагаться, так что скоро можно будет запустить программу сразу из нескольких инструкций.
Страница проекта на github: github.com/Dovgalyuk/Relay
Первая часть описания: https://habrahabr.ru/post/220865/
Вторая часть описания: https://habrahabr.ru/post/258337/