Мои маленькие реле: Brainfuck компьютер — это реальность

m0lysfg74dvrhabcw-sbs1lld7g.jpeg
Прошел ровно год с момента прошлой публикации и я подумал что первое апреля — отличный день для ежегодного дайджеста по моим трем безумным компьютерным проектам. В тот раз проект существовал только на бумаге, теперь же — определенно стал реальностью.
Подкатом звенящие релейные блоки, самые быстрые в мире вычисления на реле (но это не точно), монтаж накруткой, вакуумные индикаторы и моргающие светодиодики.

khqa4myljg149ffbe7kjbmlmh_q.jpeg
Рисунок 1: Потрепанный жизнью и мною лично томик Войцеховского «Радиоэлектронные игрушки», 1979 г.
Давным давно, когда вокруг все было большим, а я маленьким (году так в 2002-м), отец подарил мне книгу Войцеховского «Радиоэлектронные игрушки». Тогда у меня не было компьютера, а про интернет и вовсе не слышал и знакомая многим книга оказалась просто кладезью занимательных электронных приборов. Было среди них и описание электронно-вычислительной машины и схема простенькой модели на телефонных реле. Эту модель, будучи на втором курсе университета в 2008-м году, я собрал для доклада по истории компьютеров.
cn1w-35bc5xkah3gs2f8hgr8fgc.jpeg
Рисунок 2: РЦВМ — 4-разрядное АЛУ

В то время я уже вовсю изучал просторы интернета и будучи в курсе о существовании и релейного компьютера Гарри Портера, и релейного компьютера №2 и релейного компьютера Цузе — я задумался о постройке собственного агрегата.
Для тех, кто слабо представляет что там у других, предлагаю к просмотру свой видеообзор самодельных релейных компьютеров. За год он самую малость устарел, но не перестал быть менее интересным:


В том же 2008-м, на занятиях по теоретическим основам электротехники, я определился с главным компонентом — герконовым реле. В одной из лабораторок в с удивлением наблюдал на осциллограмме, как малютка РЭС55 работала на частоте 50Гц. Это произвело на меня неизгладимое впечатление и я начал копить герконовые реле.

И спустя десятилетие проект с огромной скоростью движется к релизу. С мертвой точки все сдвинулось в ноябре 2016-го, когда родилась текущая архитектура. К сожалению я решил изготовить все печатные платы самостоятельно… в результате целый квадратный метр двухстороннего текстолита превратился в черную дыру и засосал в себя несколько сотен человеко-часов свободного времени, что для наемного работника равняется примерно полугоду. С апреля по ноябрь 2к17-го практически ничего не происходило.

slisnf0apkc-ncrszkk55oxehxu.jpeg

Архитектура машины соответствует машине Тьюринга. Имеется лента с данными — оперативная память на 64 килослова (16 разрядное слово). ОЗУ — микросхемы кэша от какой-то мат. платы под Intel Pentium. За аутентичностью — идите в… раздел «Аутентичность». Микросхемная ОЗУ используется в большинстве известных мне самодельных релейных компьютеров.

Центральный элемент — 16-разрядный сумматор с параллельным переносом. Он отвечает как за вычисление номера следующей инструкции, так и работает с данными и указателем на них.
На входах сумматора висят 16-разрядный временный регистр и 12 разрядный командный регистр. 12 бит подается также и на старшие 4 бита сумматора, что дает «полноценные» 16 бит. Тут важно что сумматор правильно работает и со сложением и с вычитанием 12-битного числа.
Недостаток очевиден — за раз мы можем перепрыгнуть только на 2^12 инструкций назад, или вперед, либо изменить указатель или данные на эту величину. Первое — надо учитывать при написании программ, по второму — всегда можно повторить процедуру.
Вычитание идет в доп.коде. Параллельный перенос обеспечивает постоянную задержку вычисления — всего лишь 3 последовательно-стоящие реле. Это не более 2 мс.
К выходу сумматора через защелки подключаются IP регистр и AP регистр, а также вход ОЗУ.


Вычисления

Основных операций — ровно две штуки. В одном случае мы работаем с вычислением нового значения указателя, в другом — нового значения данных.

Каждый нарастающий фронт запускается вычисление нового номера инструкции. По сути делается IP++. После вычисления, IP подается на адресный вход платы памяти и через шину данных инструкция попадает в командный регистр. Старшие 4 бита определяют будущую инструкцию, младшие 12 скорее всего не равны нулю и в будущем сумматор изменит лежащее во временном регистре число ровно на эту величину.

Каждый спадающий фронт начинается выполнение операции.
Для операций с AP и IP регистрами последовательность действий выглядит так:


  1. Через шину адреса содержимое IP (AP) регистра копируется во временный регистр;
  2. Временный и командный регистры подаются на вход сумматора. Через 2 мс на выходе сумматора будет готов ответ.
  3. Ответ записывается в IP или AP регистр.
    Есть некоторые особенности. Для команд AP+BIAS и AP-BIAS все именно так, для условных команд, когда делается например IP=(*AP==0?) IP+1: IP±BIAS нам еще нужно на шину данных выгрузить текущее значение ячейки данных и снять информацию с нуль-детектора.

Для операций AP+BIAS и AP-BIAS последовательность немного различается


  1. Через шину данных текущее значение ячейки памяти записывается во временный регистр.
  2. Временный и командный регистры подаются на вход сумматора. Через 2 мс на выходе сумматора будет готов ответ.
  3. AP регистр продолжает подаваться на вход платы памяти. Ответ с сумматора пишется напрямую в память.
    Вычисления всегда происходят в 16-разрядном режиме. А вот нулевой флаг условного перехода определяется как:
Z = ((16bit?) *AP : (*AP) & 0x00FF == 0) ;

С прошлого раза ничего не изменилось.


Модуль

h19b9mwdk162l0g8x5iwtbweypo.jpeg
Рисунок 3: Модуль компьютера. Слева-на-право: модуль D-триггера, диодный модуль, модуль 2AND/2XOR
В основе — небольшой модуль 40×64 мм. Каждый модуль представляет собой печатную плату с 4 реле, на которых реализована простая логическая операция. Имеется разъем на 16 контактов (есть модули на 12 и 14 контактов) и до 4 светодиодов. Все размеры — строго зафиксированы.
anjzuocj0hnbubswwexxtukvn_e.jpeg
Рисунок 4: Модули в процессе сборки

Например:


  1. Модуль 2AND/2XOR — 2 независимых друг от друга логические операции — 2AND и 2XOR. 32 штуки используются в блоке сумматора, по два модуля на бит. Сначала были запаяны все 4 светодиода, но схемотехника модуля такова, что два реле на каждом модуле включены параллельно, и для уменьшения потребляемой блоком мощности, половина светодиодов была снята.
  2. Модуль D-триггер — 64 штуки уходят на два регистровых блока. Из них 60 — триггеры без сигнала Enable.
  3. Модуль диодный — просто 8 диодов на плате для реализации многовходового диодного OR. Грязный хак, но позволяет экономить как на реле (это сейчас у меня еще порядка 400 реле в запасе), так и на времени — как по сравнению с реле сигнал передается на выход такого логического элемента мгновенно.
  4. Модуль 2& — Это базовый кирпичик. По сути — 4 реле с контактом на переключение для реализации абсолютно любой логической схемы. Пойдут на блоки логики в неизвестном количестве.
  5. Универсальный 2AND/2OR который сделан так, что позволяет реализовать практически какую угодно логическую функцию — 4AND, 4OR, 4AND-NOT, 4OR-NOT и так далее. Тоже пойдет на блок логики в неизвестном количестве.

Как я сказал — потратив впустую кучу времени на изготовление самодельных печатных плат я психанул и заказал полный комплект плат у китайцев. В первую же неделю я собрал первые модули. А еще через месяц были готовы все модули для блока сумматора.
xn72gzk6fnala_kjqcga1ycq-cc.jpeg
Рисунок 5: Блок сумматора


Блок

32 модуля по 8 модулей в 4 ряда объединяются в функциональный блок. Всего блоков 5 (в худшем случае — 6):


  1. Блок сумматора — 16-разрядный полный сумматор. Два 16-разрядных входа для чисел, 1 линия переноса нулевого разряда, Два выхода. На одном — операция суммирования, на другом — XOR между входами. Может использоваться как самостоятельная операция.
  2. Блок регистров IP/AP — Два независимых 16-разрядных регистра без сигнала Enable. Выводы Q и ~Q используются напрямую и подаются через защелки куда следует. Можно было и запаять 4 реле, но ради экономии реле функционал вынесен на внешние защелки.
  3. Блок регистров TMP/CMD — Регистров тут три. Один — 16-разрядный — временный регистр. Точно такой же как и IP или AP. Второй — 12-разрядный, его выход подключается ко входу сумматора через защелку. Третий — 4-разрядный, со встроенным сигналом Enable. Он используется для хранения текущей инструкции.
  4. Блоки логики — 2 штуки. Либо три. Схема — до сих пор неизвестна. Предварительные расчеты показывают, что 64 модуля будет достаточно (GOTO: Плата памяти).

В основании каждого блока базовая плата — 200×150 мм, не имеющая разводки. Все что на ней есть — это 32 разъема и торчащие снизу квадратные пины для монтажа накруткой.
s_pntl-inevaow8u_8bnzg-710k.jpeg
Рисунок 6: Базовая плата и корзинка к ней

Просто так торчащие в разъеме модули — это ненадежно. Они будут болтаться туда-сюда, смещаться от тряски и всячески снижать надежность конструкции. Для их фиксации я нарисовал и распечатал специальные корзинки с пазами. В них модули уж точно никуда не денутся — поездку на поезде до москвы и обратно они пережили без проблем.
Корзинку можно было бы нарисовать и полегче — слоем в 0,32 мм ее печатать чуть больше 10 часов. Три корзинки напечатаны PLA-пластиком, еще две — HIPS. Последний, из-за отсутствия у моего принтера кожуха, при печати ощутимо коробит.
Можно заметить, что блок сумматора не имеет ушей для крепления. Корзинка для него была напечатана самой первой. Потом я эти уши либо доклею, либо напечатаю новую корзину.
y3esa50tcletmcbmu5zn5nhxhrk.jpeg
Рисунок 7: Блок сумматора и блок логики.


Монтаж накруткой

На базовой плате нас ждут 600 выводов, которые надо соединить между собой. Благо что соединять нужно не вот прям все, а лишь почти все. С другой стороны легче от этого не становится.
Берем в руки специальный инструмент, моток провода и ножка за ножкой накручиваем схему соединений.
wjakgvtczgj932i6vpb77xjpb_e.jpeg
Рисунок 8: Монтаж накруткой блока сумматора
Это лишь начало работы. Ну как начало. Сначала был тихий ужас — провода лежали как попало, одни перемычки длинные, другие слишком длинные… Немного научившись делать лучше чем было, я снял большую часть перемычек и перекрутил все заново — стал натягивать перемычки струной. Так и провода не болтаются, и результат выглядит намного лучше. Старался класть так, чтобы провода не давили на углы не своих пинов. В результате — ни одного замыкания. От первой попытки остались только земляные линии.
bq6te3y4th4_ahzqaa12kto6llw.jpeg
Рисунок 9: Монтаж накруткой блока сумматора. Итоговый результат
В настоящий момент получается не вот прям аккуратно, но для первой платы очень даже хороший результат, я считаю. До сих пор не научился класть провод виток к витку, то ли инструмент кривой, то ли руки…
У тов. есть подробная статья по данному способу монтажа.
Кроме блока сумматора нужен блок регистров. Вернее, два блока регистров. Еще пара месяцев — и еще 64 модуля собраны и протестированы. Осталось накрутить базовую плату.


Как это было.

pqu-2ianoeafpk1aubms_sevths.jpeg
Рисунок 10: Индикаторный модуль
Текущее состояние регистров процессора надо на чем-то отображать и я решил, что вакуумные индикаторы будут в самый раз. На плате 100×100 мм (ибо 10 штук такого размера можно у китайцев за 5$ заказать) разместились 6 индикаторов ИВ-6, триггеры К155ТМ8 и микроконтроллер. Индикация здесь — динамическая.
Еще есть 16-разрядный вход для прямого считывания состояния регистра и UART-порт, для получения команд от платы памяти.
Сейчас прошивка умеет считывать состояние 16-разрядного порта и в HEX-формате выводить его на индикатор. Всего таких модулей мне потребуется 4 штуки. Три будут выводить текущее состояние регистров — IP, AP и CMD регистра дабы иметь более удобную визуализацию текущих хранимых значений. Четвертый — будет показывать общее количество выполненных инструкций.

ttu8s6chfwlltkbgkzbsbrldz0k.jpeg
Рисунок 11: модуль защелки
Модуль защелки состоит из 8 реле РЭС43. Внутри — два замыкающих контакта. Слева и справа — светодиоды, отображающие текущее состояние входа и выхода.
Размер защелки — 100×100 мм. Требуемое количество — 8 штук. Две готовы, осталось собрать еще шесть.

ouzwvtghdzcjmuywgdroiiovasi.jpeg
Рисунок 12: Плата памяти. Общий вид
Самый огромный блок, содержащий в первую очередь две микросхемы статического ОЗУ на 64 Кбайт и схемы согласования к адресным входам и порту данных. На плате располагается микроконтроллер ATmega1280. Жизненно-важных задач у него две:


  1. Загрузка программы и начальных данных в ОЗУ. Скомпилированный бинарник нужно поместить в память. Для этого будет возможность подключиться к плате памяти по UART или telnet (через Wi-Fi) и загрузить исполняемый файл. МК прочитает заголовок и разложит секции кода и данных в ОЗУ. Мне совершенно лень это делать с помощью тумблеров и кнопок — программа на brainfuck, умеющая делать что-то сложнее HelloWorld содержит тысячи инструкций. Есть в заначке пара козырей на этот счет, но о них — в другой раз.
  2. Реализует команды чтения данных из консоли и записи в нее. Да-да инструкции ».» и »,» реализуются с помощью МК. Вернее, релейная логика информирует МК о том, что сейчас надо передать в консоль состояние шины данных, либо наоборот вывести на шину данных значение из консоли. По сути, МК работает преобразователем параллельного интерфейса в UART. Да, это вполне можно исполнить на какой-нибудь спец. микросхеме и я подумаю об этом.
    До сих пор не решил что делать с 16-разрядным режимом. Конечно большинство программ написаны под 8-разрядный brainfuck и тут все просто — читаем и пишем младший байт. А в 16-разрядном режиме что делать? Выводить все слово или тоже только младший байт?
    Помимо основных, у МК есть ряд побочных задач, без которых в принципе можно обойтись, но они нацелены на удобство пользования машиной:
  3. МК отвечает за вывод небольшой области памяти на светодиодную матрицу 32×16 пикс. Делает это он пока шина адреса и шина данных не занята основной логикой. Тут я не уверен, что для МК вообще найдется время на шине, так что вопрос требует проверки. Но в заголовке программы будет стартовый адрес для отображения и я попробую заставить его работать. Индикация — динамическая. За один такт выводятся сразу два столбца данных.
  4. При активации в бинарнике флага защищенного режима работы памяти, в случае попытки исполнения секции данных, либо записи в секцию памяти МК сгенерирует исключение «Segmentation Fault». Так мы можем следить за тем, чтобы программа не лезла куда не следует. Читать секцию памяти не запрещено.
  5. При активации флага контроля кода, МК активирует симулятор и будет выполнять в нем те же инструкции, что и компьютер, сравнивая ожидаемый и получаемый результаты. Если результат будет отличаться, сработает исключение «Machine Error». Это будет означать, что произошла ошибка в вычислениях и возможно один модуль начал сбоить. Либо мы слишком задрали тактовую частоту и реле уже не успевают вычислять. Как раз с помощью этого функционала я буду пытаться выжать максимум из машины — что-то должно будет контролировать корректность работы в этот период.

Есть еще временная, но таки жизненно-важная функция платы памяти — эмуляция блока логики, пока его нет. На плате памяти имеются линии ввода и вывода и мы можем подавать на блоки нужные сигналы. Так, подключив все управляющие линии к плате памяти и написав программу, выдающую нужные последовательности команд получится в самые короткие сроки:


  1. запустить первые программы на исполнение;
  2. отладить алгоритмы и схемотехнику блока логики, что увеличит шансы на его безошибочную сборку и работу впоследствии.
    Потом, собирая нужные модули блоков логики, все функции будут постепенно переведены «в железо». Когда МК перестанет отвечать за логику — проект будет считаться завершенным.

Проект изначально не задумывался как чисто релейный, без применения транзисторов и микросхем. С одной стороны — компьютер получается гибридный и теряет в радиационной стойкости, с другой — большинство релейных компьютеров имеют аналогичный недуг. В финальной версии машины так и будет использоваться микросхема памяти и микроконтроллер. Ферритовая память будет использована в другом, уже «Silicon-Free» проекте.

Для компенсации эффекта неканона я обзавелся электронной печатной машинкой «Robotron S6130»
7qscqpvy4fjdknrgucm0ryum5im.jpeg
Рисунок 13: Электронная печатная машинка ромашкового типа.

К сожалению, машинка досталась мне в потрепанном жизнью состоянии. Она долгое время использовалась в бухгалтерии, но в итоге была брошена умирать в гордом одиночестве.


Рекомендую к просмотру уникальный обзор этого монстра.
Непосредственно механика в хорошем состоянии, однако сильно досталось процессорной плате, на которой стояла пара NiCd аккумуляторов Д-0,25. Они благополучно протекли и сильно залили электролитом все вокруг.

Я хочу ее восстановить и использовать в качестве терминала ввода-вывода для компьютера.Однако помимо неисправности электронной части, машинка имеет русскую ромашку (диск с буквами) и русские клавиши. Второе — решается наклейками, первое — надо искать и тут мне пока не везет. Про то что требуется картридж с красящей лентой я вообще молчу. Хотя бы бумага у меня для нее есть…

Если по электронике будет принято решение что она безвозвратно утрачена, то попробую найти донора, либо — разработаю новую электронную начинку. Сделать плату управления пригоршней шаговиков — не самая сложная задача. Сложнее будет перевести с немецкого мануал и понять ТЗ. Конечно, эта машина заслуживает отдельной статьи по результатам оживления. Против нее пока — приоритет выполняемых работ.

Всех тех, кто дочитал до этого места — ждет награда в виде трещащих и жужжащих релейных блоков.

Для начала — попробуем подать на вход реле меандр, через транзисторный каскад:
aa9sobefi3g2phsqmkudkq9cafw.jpeg
Рисунок 14: Скоростное тестирование герконового реле РЭС55. Желтый сигнал — на катушке, синий — на контактах
Так как вход осциллографа имеет некоторую емкость и после размыкания контакта реле она остается в воздухе и начинается саморазряд, мы видим обратную экспоненту. На частоте 1,7кГц! Для реле! Для одного маленького герконового реле! Обычные глохнут на 20Гц или немного выше. На номинальной частоте в 100 Гц нарастающий и спадающий фронты примерно по 600 мкс. Здесь они настолько мелкие (200 мкс), поскольку в катушке на момент следующего включения еще остается энергия с предыдущего.

Подаем напряжение на блоки, на входы подрубаем переключатели от советских измерительных приборов.
yxzvpakpbgnygfzcnkxcvllaxvq.jpeg
Рисунок 15: Блок сумматора и блок регистров в работе
Оно считает! Круто.


Так это выглядело с места событий. Сначала я хотел переделать переключатели под 16-разрядные. Подключить индикаторы и на вход и на выход, но… Не удержался.

Ну и раз все работает, да и реле оказалось способно на безумные скорости, подаем меандр на линию переноса:


И врубаем 500Гц. Сумматор справляется, хотя по звуку этого не скажешь. На самом деле звук чистый, но конденсаторный микрофон считает иначе. Насколько мне известно, это самый быстрый релейный сумматор в мире:)

3vetilfxdaaga8060ahosnruc34.jpeg
Рисунок 16: Проектирование каркаса компьютера
Постепенно собираются недостающие шесть штук защелок и начинает проектироваться каркас будущей машины. На чертеже шесть блоков на случай если не хватит 64 модуля на логику. А если хватит — место под нижний центральный блок останется пустым.
Одновременно с этим я пишу прошивку для платы памяти, дабы она могла заменить пока отсутствующий блок логики. Уже летом компьютер сможет исполнить свою первую программу.


Три компьютера???

Да, три. Первый — текущий BrainfuckPC. Второй — пневмонический компьютер, с кодовым названием FluidicPC.


О третьем радиационно-стойком будущем монстре уже можно найти упоминания в интернете, но я не хочу распыляться между проектами и сначала хочу доделать текущий — анонса по нему пока не делаю.

fnl2xu1n17czsdx6lbs5u2yzkmi.jpeg
Рисунок 17: Комутаторные декатроны А101, А102 и А103
Хотя по этой картинке уже можно догадаться о чем будет идти речь.


ЗАЧЕЕЕЕМ???777


1fbf24c164974f8fabba8e7e03e5856b.jpg

Ссылки

Весь проект продолжает быть полностью открытым. Посему основные ссылки по проекту:


  1. https://github.com/radiolok/RelayComputer2 — репозиторий с принципиальными схемами и разводками печатных плат. Там же находятся прошивки индикаторного модуля и платы памяти
  2. https://hackaday.io/project/18599-brainfuck-relay-computer на этой страничке я публикую еженедельные и не очень отчеты о том что было проделано. Сейчас вы читаете статью, чуть более чем полностью состоящую из этих заметок. С переводом, комментариями и дополнениями.
  3. https://github.com/radiolok/bfutils компилятор и эмулятор.

© Geektimes