Мои маленькие реле: Brainfuck компьютер — это реальность
Прошел ровно год с момента прошлой публикации и я подумал что первое апреля — отличный день для ежегодного дайджеста по моим трем безумным компьютерным проектам. В тот раз проект существовал только на бумаге, теперь же — определенно стал реальностью.
Подкатом звенящие релейные блоки, самые быстрые в мире вычисления на реле (но это не точно), монтаж накруткой, вакуумные индикаторы и моргающие светодиодики.
Рисунок 1: Потрепанный жизнью и мною лично томик Войцеховского «Радиоэлектронные игрушки», 1979 г.
Давным давно, когда вокруг все было большим, а я маленьким (году так в 2002-м), отец подарил мне книгу Войцеховского «Радиоэлектронные игрушки». Тогда у меня не было компьютера, а про интернет и вовсе не слышал и знакомая многим книга оказалась просто кладезью занимательных электронных приборов. Было среди них и описание электронно-вычислительной машины и схема простенькой модели на телефонных реле. Эту модель, будучи на втором курсе университета в 2008-м году, я собрал для доклада по истории компьютеров.
Рисунок 2: РЦВМ — 4-разрядное АЛУ
В то время я уже вовсю изучал просторы интернета и будучи в курсе о существовании и релейного компьютера Гарри Портера, и релейного компьютера №2 и релейного компьютера Цузе — я задумался о постройке собственного агрегата.
Для тех, кто слабо представляет что там у других, предлагаю к просмотру свой видеообзор самодельных релейных компьютеров. За год он самую малость устарел, но не перестал быть менее интересным:
В том же 2008-м, на занятиях по теоретическим основам электротехники, я определился с главным компонентом — герконовым реле. В одной из лабораторок в с удивлением наблюдал на осциллограмме, как малютка РЭС55 работала на частоте 50Гц. Это произвело на меня неизгладимое впечатление и я начал копить герконовые реле.
И спустя десятилетие проект с огромной скоростью движется к релизу. С мертвой точки все сдвинулось в ноябре 2016-го, когда родилась текущая архитектура. К сожалению я решил изготовить все печатные платы самостоятельно… в результате целый квадратный метр двухстороннего текстолита превратился в черную дыру и засосал в себя несколько сотен человеко-часов свободного времени, что для наемного работника равняется примерно полугоду. С апреля по ноябрь 2к17-го практически ничего не происходило.
Архитектура машины соответствует машине Тьюринга. Имеется лента с данными — оперативная память на 64 килослова (16 разрядное слово). ОЗУ — микросхемы кэша от какой-то мат. платы под Intel Pentium. За аутентичностью — идите в… раздел «Аутентичность». Микросхемная ОЗУ используется в большинстве известных мне самодельных релейных компьютеров.
Центральный элемент — 16-разрядный сумматор с параллельным переносом. Он отвечает как за вычисление номера следующей инструкции, так и работает с данными и указателем на них.
На входах сумматора висят 16-разрядный временный регистр и 12 разрядный командный регистр. 12 бит подается также и на старшие 4 бита сумматора, что дает «полноценные» 16 бит. Тут важно что сумматор правильно работает и со сложением и с вычитанием 12-битного числа.
Недостаток очевиден — за раз мы можем перепрыгнуть только на 2^12 инструкций назад, или вперед, либо изменить указатель или данные на эту величину. Первое — надо учитывать при написании программ, по второму — всегда можно повторить процедуру.
Вычитание идет в доп.коде. Параллельный перенос обеспечивает постоянную задержку вычисления — всего лишь 3 последовательно-стоящие реле. Это не более 2 мс.
К выходу сумматора через защелки подключаются IP регистр и AP регистр, а также вход ОЗУ.
Вычисления
Основных операций — ровно две штуки. В одном случае мы работаем с вычислением нового значения указателя, в другом — нового значения данных.
Каждый нарастающий фронт запускается вычисление нового номера инструкции. По сути делается IP++. После вычисления, IP подается на адресный вход платы памяти и через шину данных инструкция попадает в командный регистр. Старшие 4 бита определяют будущую инструкцию, младшие 12 скорее всего не равны нулю и в будущем сумматор изменит лежащее во временном регистре число ровно на эту величину.
Каждый спадающий фронт начинается выполнение операции.
Для операций с AP и IP регистрами последовательность действий выглядит так:
- Через шину адреса содержимое IP (AP) регистра копируется во временный регистр;
- Временный и командный регистры подаются на вход сумматора. Через 2 мс на выходе сумматора будет готов ответ.
- Ответ записывается в IP или AP регистр.
Есть некоторые особенности. Для команд AP+BIAS и AP-BIAS все именно так, для условных команд, когда делается например IP=(*AP==0?) IP+1: IP±BIAS нам еще нужно на шину данных выгрузить текущее значение ячейки данных и снять информацию с нуль-детектора.
Для операций AP+BIAS и AP-BIAS последовательность немного различается
- Через шину данных текущее значение ячейки памяти записывается во временный регистр.
- Временный и командный регистры подаются на вход сумматора. Через 2 мс на выходе сумматора будет готов ответ.
- AP регистр продолжает подаваться на вход платы памяти. Ответ с сумматора пишется напрямую в память.
Вычисления всегда происходят в 16-разрядном режиме. А вот нулевой флаг условного перехода определяется как:
Z = ((16bit?) *AP : (*AP) & 0x00FF == 0) ;
С прошлого раза ничего не изменилось.
Модуль
Рисунок 3: Модуль компьютера. Слева-на-право: модуль D-триггера, диодный модуль, модуль 2AND/2XOR
В основе — небольшой модуль 40×64 мм. Каждый модуль представляет собой печатную плату с 4 реле, на которых реализована простая логическая операция. Имеется разъем на 16 контактов (есть модули на 12 и 14 контактов) и до 4 светодиодов. Все размеры — строго зафиксированы.
Рисунок 4: Модули в процессе сборки
Например:
- Модуль 2AND/2XOR — 2 независимых друг от друга логические операции — 2AND и 2XOR. 32 штуки используются в блоке сумматора, по два модуля на бит. Сначала были запаяны все 4 светодиода, но схемотехника модуля такова, что два реле на каждом модуле включены параллельно, и для уменьшения потребляемой блоком мощности, половина светодиодов была снята.
- Модуль D-триггер — 64 штуки уходят на два регистровых блока. Из них 60 — триггеры без сигнала Enable.
- Модуль диодный — просто 8 диодов на плате для реализации многовходового диодного OR. Грязный хак, но позволяет экономить как на реле (это сейчас у меня еще порядка 400 реле в запасе), так и на времени — как по сравнению с реле сигнал передается на выход такого логического элемента мгновенно.
- Модуль 2& — Это базовый кирпичик. По сути — 4 реле с контактом на переключение для реализации абсолютно любой логической схемы. Пойдут на блоки логики в неизвестном количестве.
- Универсальный 2AND/2OR который сделан так, что позволяет реализовать практически какую угодно логическую функцию — 4AND, 4OR, 4AND-NOT, 4OR-NOT и так далее. Тоже пойдет на блок логики в неизвестном количестве.
Как я сказал — потратив впустую кучу времени на изготовление самодельных печатных плат я психанул и заказал полный комплект плат у китайцев. В первую же неделю я собрал первые модули. А еще через месяц были готовы все модули для блока сумматора.
Рисунок 5: Блок сумматора
Блок
32 модуля по 8 модулей в 4 ряда объединяются в функциональный блок. Всего блоков 5 (в худшем случае — 6):
- Блок сумматора — 16-разрядный полный сумматор. Два 16-разрядных входа для чисел, 1 линия переноса нулевого разряда, Два выхода. На одном — операция суммирования, на другом — XOR между входами. Может использоваться как самостоятельная операция.
- Блок регистров IP/AP — Два независимых 16-разрядных регистра без сигнала Enable. Выводы Q и ~Q используются напрямую и подаются через защелки куда следует. Можно было и запаять 4 реле, но ради экономии реле функционал вынесен на внешние защелки.
- Блок регистров TMP/CMD — Регистров тут три. Один — 16-разрядный — временный регистр. Точно такой же как и IP или AP. Второй — 12-разрядный, его выход подключается ко входу сумматора через защелку. Третий — 4-разрядный, со встроенным сигналом Enable. Он используется для хранения текущей инструкции.
- Блоки логики — 2 штуки. Либо три. Схема — до сих пор неизвестна. Предварительные расчеты показывают, что 64 модуля будет достаточно (GOTO: Плата памяти).
В основании каждого блока базовая плата — 200×150 мм, не имеющая разводки. Все что на ней есть — это 32 разъема и торчащие снизу квадратные пины для монтажа накруткой.
Рисунок 6: Базовая плата и корзинка к ней
Просто так торчащие в разъеме модули — это ненадежно. Они будут болтаться туда-сюда, смещаться от тряски и всячески снижать надежность конструкции. Для их фиксации я нарисовал и распечатал специальные корзинки с пазами. В них модули уж точно никуда не денутся — поездку на поезде до москвы и обратно они пережили без проблем.
Корзинку можно было бы нарисовать и полегче — слоем в 0,32 мм ее печатать чуть больше 10 часов. Три корзинки напечатаны PLA-пластиком, еще две — HIPS. Последний, из-за отсутствия у моего принтера кожуха, при печати ощутимо коробит.
Можно заметить, что блок сумматора не имеет ушей для крепления. Корзинка для него была напечатана самой первой. Потом я эти уши либо доклею, либо напечатаю новую корзину.
Рисунок 7: Блок сумматора и блок логики.
Монтаж накруткой
На базовой плате нас ждут 600 выводов, которые надо соединить между собой. Благо что соединять нужно не вот прям все, а лишь почти все. С другой стороны легче от этого не становится.
Берем в руки специальный инструмент, моток провода и ножка за ножкой накручиваем схему соединений.
Рисунок 8: Монтаж накруткой блока сумматора
Это лишь начало работы. Ну как начало. Сначала был тихий ужас — провода лежали как попало, одни перемычки длинные, другие слишком длинные… Немного научившись делать лучше чем было, я снял большую часть перемычек и перекрутил все заново — стал натягивать перемычки струной. Так и провода не болтаются, и результат выглядит намного лучше. Старался класть так, чтобы провода не давили на углы не своих пинов. В результате — ни одного замыкания. От первой попытки остались только земляные линии.
Рисунок 9: Монтаж накруткой блока сумматора. Итоговый результат
В настоящий момент получается не вот прям аккуратно, но для первой платы очень даже хороший результат, я считаю. До сих пор не научился класть провод виток к витку, то ли инструмент кривой, то ли руки…
У тов. есть подробная статья по данному способу монтажа.
Кроме блока сумматора нужен блок регистров. Вернее, два блока регистров. Еще пара месяцев — и еще 64 модуля собраны и протестированы. Осталось накрутить базовую плату.
Как это было.
Рисунок 10: Индикаторный модуль
Текущее состояние регистров процессора надо на чем-то отображать и я решил, что вакуумные индикаторы будут в самый раз. На плате 100×100 мм (ибо 10 штук такого размера можно у китайцев за 5$ заказать) разместились 6 индикаторов ИВ-6, триггеры К155ТМ8 и микроконтроллер. Индикация здесь — динамическая.
Еще есть 16-разрядный вход для прямого считывания состояния регистра и UART-порт, для получения команд от платы памяти.
Сейчас прошивка умеет считывать состояние 16-разрядного порта и в HEX-формате выводить его на индикатор. Всего таких модулей мне потребуется 4 штуки. Три будут выводить текущее состояние регистров — IP, AP и CMD регистра дабы иметь более удобную визуализацию текущих хранимых значений. Четвертый — будет показывать общее количество выполненных инструкций.
Рисунок 11: модуль защелки
Модуль защелки состоит из 8 реле РЭС43. Внутри — два замыкающих контакта. Слева и справа — светодиоды, отображающие текущее состояние входа и выхода.
Размер защелки — 100×100 мм. Требуемое количество — 8 штук. Две готовы, осталось собрать еще шесть.
Рисунок 12: Плата памяти. Общий вид
Самый огромный блок, содержащий в первую очередь две микросхемы статического ОЗУ на 64 Кбайт и схемы согласования к адресным входам и порту данных. На плате располагается микроконтроллер ATmega1280. Жизненно-важных задач у него две:
- Загрузка программы и начальных данных в ОЗУ. Скомпилированный бинарник нужно поместить в память. Для этого будет возможность подключиться к плате памяти по UART или telnet (через Wi-Fi) и загрузить исполняемый файл. МК прочитает заголовок и разложит секции кода и данных в ОЗУ. Мне совершенно лень это делать с помощью тумблеров и кнопок — программа на brainfuck, умеющая делать что-то сложнее HelloWorld содержит тысячи инструкций. Есть в заначке пара козырей на этот счет, но о них — в другой раз.
- Реализует команды чтения данных из консоли и записи в нее. Да-да инструкции ».» и »,» реализуются с помощью МК. Вернее, релейная логика информирует МК о том, что сейчас надо передать в консоль состояние шины данных, либо наоборот вывести на шину данных значение из консоли. По сути, МК работает преобразователем параллельного интерфейса в UART. Да, это вполне можно исполнить на какой-нибудь спец. микросхеме и я подумаю об этом.
До сих пор не решил что делать с 16-разрядным режимом. Конечно большинство программ написаны под 8-разрядный brainfuck и тут все просто — читаем и пишем младший байт. А в 16-разрядном режиме что делать? Выводить все слово или тоже только младший байт?
Помимо основных, у МК есть ряд побочных задач, без которых в принципе можно обойтись, но они нацелены на удобство пользования машиной: - МК отвечает за вывод небольшой области памяти на светодиодную матрицу 32×16 пикс. Делает это он пока шина адреса и шина данных не занята основной логикой. Тут я не уверен, что для МК вообще найдется время на шине, так что вопрос требует проверки. Но в заголовке программы будет стартовый адрес для отображения и я попробую заставить его работать. Индикация — динамическая. За один такт выводятся сразу два столбца данных.
- При активации в бинарнике флага защищенного режима работы памяти, в случае попытки исполнения секции данных, либо записи в секцию памяти МК сгенерирует исключение «Segmentation Fault». Так мы можем следить за тем, чтобы программа не лезла куда не следует. Читать секцию памяти не запрещено.
- При активации флага контроля кода, МК активирует симулятор и будет выполнять в нем те же инструкции, что и компьютер, сравнивая ожидаемый и получаемый результаты. Если результат будет отличаться, сработает исключение «Machine Error». Это будет означать, что произошла ошибка в вычислениях и возможно один модуль начал сбоить. Либо мы слишком задрали тактовую частоту и реле уже не успевают вычислять. Как раз с помощью этого функционала я буду пытаться выжать максимум из машины — что-то должно будет контролировать корректность работы в этот период.
Есть еще временная, но таки жизненно-важная функция платы памяти — эмуляция блока логики, пока его нет. На плате памяти имеются линии ввода и вывода и мы можем подавать на блоки нужные сигналы. Так, подключив все управляющие линии к плате памяти и написав программу, выдающую нужные последовательности команд получится в самые короткие сроки:
- запустить первые программы на исполнение;
- отладить алгоритмы и схемотехнику блока логики, что увеличит шансы на его безошибочную сборку и работу впоследствии.
Потом, собирая нужные модули блоков логики, все функции будут постепенно переведены «в железо». Когда МК перестанет отвечать за логику — проект будет считаться завершенным.
Проект изначально не задумывался как чисто релейный, без применения транзисторов и микросхем. С одной стороны — компьютер получается гибридный и теряет в радиационной стойкости, с другой — большинство релейных компьютеров имеют аналогичный недуг. В финальной версии машины так и будет использоваться микросхема памяти и микроконтроллер. Ферритовая память будет использована в другом, уже «Silicon-Free» проекте.
Для компенсации эффекта неканона я обзавелся электронной печатной машинкой «Robotron S6130»
Рисунок 13: Электронная печатная машинка ромашкового типа.
К сожалению, машинка досталась мне в потрепанном жизнью состоянии. Она долгое время использовалась в бухгалтерии, но в итоге была брошена умирать в гордом одиночестве.
Рекомендую к просмотру уникальный обзор этого монстра.
Непосредственно механика в хорошем состоянии, однако сильно досталось процессорной плате, на которой стояла пара NiCd аккумуляторов Д-0,25. Они благополучно протекли и сильно залили электролитом все вокруг.
Я хочу ее восстановить и использовать в качестве терминала ввода-вывода для компьютера.Однако помимо неисправности электронной части, машинка имеет русскую ромашку (диск с буквами) и русские клавиши. Второе — решается наклейками, первое — надо искать и тут мне пока не везет. Про то что требуется картридж с красящей лентой я вообще молчу. Хотя бы бумага у меня для нее есть…
Если по электронике будет принято решение что она безвозвратно утрачена, то попробую найти донора, либо — разработаю новую электронную начинку. Сделать плату управления пригоршней шаговиков — не самая сложная задача. Сложнее будет перевести с немецкого мануал и понять ТЗ. Конечно, эта машина заслуживает отдельной статьи по результатам оживления. Против нее пока — приоритет выполняемых работ.
Всех тех, кто дочитал до этого места — ждет награда в виде трещащих и жужжащих релейных блоков.
Для начала — попробуем подать на вход реле меандр, через транзисторный каскад:
Рисунок 14: Скоростное тестирование герконового реле РЭС55. Желтый сигнал — на катушке, синий — на контактах
Так как вход осциллографа имеет некоторую емкость и после размыкания контакта реле она остается в воздухе и начинается саморазряд, мы видим обратную экспоненту. На частоте 1,7кГц! Для реле! Для одного маленького герконового реле! Обычные глохнут на 20Гц или немного выше. На номинальной частоте в 100 Гц нарастающий и спадающий фронты примерно по 600 мкс. Здесь они настолько мелкие (200 мкс), поскольку в катушке на момент следующего включения еще остается энергия с предыдущего.
Подаем напряжение на блоки, на входы подрубаем переключатели от советских измерительных приборов.
Рисунок 15: Блок сумматора и блок регистров в работе
Оно считает! Круто.
Так это выглядело с места событий. Сначала я хотел переделать переключатели под 16-разрядные. Подключить индикаторы и на вход и на выход, но… Не удержался.
Ну и раз все работает, да и реле оказалось способно на безумные скорости, подаем меандр на линию переноса:
И врубаем 500Гц. Сумматор справляется, хотя по звуку этого не скажешь. На самом деле звук чистый, но конденсаторный микрофон считает иначе. Насколько мне известно, это самый быстрый релейный сумматор в мире:)
Рисунок 16: Проектирование каркаса компьютера
Постепенно собираются недостающие шесть штук защелок и начинает проектироваться каркас будущей машины. На чертеже шесть блоков на случай если не хватит 64 модуля на логику. А если хватит — место под нижний центральный блок останется пустым.
Одновременно с этим я пишу прошивку для платы памяти, дабы она могла заменить пока отсутствующий блок логики. Уже летом компьютер сможет исполнить свою первую программу.
Три компьютера???
Да, три. Первый — текущий BrainfuckPC. Второй — пневмонический компьютер, с кодовым названием FluidicPC.
Рисунок 17: Комутаторные декатроны А101, А102 и А103
Хотя по этой картинке уже можно догадаться о чем будет идти речь.
ЗАЧЕЕЕЕМ???777
Ссылки
Весь проект продолжает быть полностью открытым. Посему основные ссылки по проекту:
- https://github.com/radiolok/RelayComputer2 — репозиторий с принципиальными схемами и разводками печатных плат. Там же находятся прошивки индикаторного модуля и платы памяти
- https://hackaday.io/project/18599-brainfuck-relay-computer на этой страничке я публикую еженедельные и не очень отчеты о том что было проделано. Сейчас вы читаете статью, чуть более чем полностью состоящую из этих заметок. С переводом, комментариями и дополнениями.
- https://github.com/radiolok/bfutils компилятор и эмулятор.