Мой маленький триод: Ламповая ЭВМ — это магия

a3k-zdgdfnogrdn3vzoglfrlu-s.jpeg

Экспериментальная 3U декатронная ячейка. Модуль декатрона А103 со схемой шифратора и переноса

Пришло время возобновить славную традицию ежегодного первоапрельского дайджеста по моим безумным вычислительным проектам. В прошлой трилогии [1], [2], [3] я рассказывал про создание де-факто самого быстрого в мире релейного компьютера BrainfuckPC. После трёх лет раздумий я наконец-то готов начать активную фазу строительства уникальной ламповой ЭВМ с кодовым названием DekatronPC.

Минутка истории


Прогулка по немецкому музею в г. Мюнхене за две недели до начала пандемии: У ламповых ЭВМ был очень короткий век. Самым первым цифровым ламповым вычислителем считается — компьютер Атанасова — Берри, увидевший свет в 1942 году. Однако он не являлся программируемым и выполнял строго одну задачу — решение СЛАУ. Всемирно известный программируемый компьютер ЭНИАК на 17.5 тысячах ламп (а также 7 тыс. диодов и 1.5 тыс. реле) — появился в 1945 г. При этом уже в 1947 году был изобретён транзистор, а ещё через 6 лет — заработали первые прототипы транзисторных ЭВМ. В итоге уже к началу 60-х годов транзисторные компьютеры развивались семимильными шагами, с одновременным забвением ламповой вычислительной техники.

qapnks0z7v-lex_iwllkrftitpi.jpegЭНИАК. Национальный исторический памятник и музей Форт Силл. США

Очевидно, что за 60 лет в мире почти не осталось действующих ламповых машин, как минимум из-за ограниченного ресурса самих электронных ламп. В настоящий момент старейшей работающей ЭВМ является Harwell computer 1951 года постройки. Этот небольшой вычислительный комплекс построен на базе вакуумных ламп и газоразрядных декатронов, а также электромагнитных реле. Из-за реле, а также особенностей архитектуры при работе с декатронами, ЭВМ получилась очень медлительной, способной решать единицы операций в секунду. Однако, компьютер вышел весьма надёжным и был способен работать несколько суток подряд без сбоев. В 2012-м году машина была восстановлена и в настоящее время выставляется в Национальном музее вычислительной техники в Блетчли-парк, Англия.

МЭСМ является первой, экспериментальной ЭВМ созданной на территории СССР и запущенной в эксплуатацию в 1951 г. Здесь я хочу обратить внимание, что машина состояла из 6000 ламп, из которых 3500 триодов и 2500 диодов. Это значит, что в машине активно использовалась диодная логика. Вспомним об этом факте при обсуждении схемотехники. В те же годы были созданы машины М1, М2 и М3, правда, согласно википедии, диодная логика в них уже была на полупроводниках.

gcpdi-u6rsn1rri8-pwvl0wqq8o.jpegРазвешанные по стенам блоки МЭСМ и операторский пульт

Одной из наиболее известных отечественных ламповых серийных ЭВМ была малая машина Урал-1, построенная в 1956 г. на базе 1000 ламп. Медленная (100 инструкций в секунду), но надёжная машина, один из экземпляров которой занимался расчётами моделирования траекторий ракет на космодроме Байконур. Низкое быстродействие машины является следствием использования магнитного барабана в роли ОЗУ с частотой вращения 100 об/сек. Полностью укомплектованная ЭВМ Урал-1, судя по всему, осталась только в политехническом музее в Москве. Также пара шкафов от машины сохранились на Байконуре.

yipgjkw-fosppgqzxuvuofo3gs8.jpegАвтор на фоне машины Урал-1 в запасниках политехнического музея, Москва

К сожалению, блоки машины соединялись между собой жгутами проводов без использования разъёмов. Жгуты были перерублены при перемещении ЭВМ в музей. Несмотря на существование документации, попытки восстановить машину не предпринималось. Вместо этого, в панель оператора машины была встроена ПЛИС с эмулятором, которая позволяет сымитировать работу на ЭВМ. Ну, а лампочки на шкафах теперь моргают исключительно для красоты.

cd_aldvdrmxjbleslomcdzvwh7k.jpegУнифицированные модули. Вид сзади (слева), сбоку (справа). Видны октальные ламповые панельки, монтажные колодки, макетные платы

С 1952 г. начинается история ламповых машин серии БЭСМ — с быстродействием от 10 тыс. операций в секунду. Однако БЭСМ-4, выпущенная в 1965 г. уже была транзисторной. А первые прототипы советских транзисторных ЭВМ создавались и раньше.

Что почитать
  • www.computer-museum.ru — шикарный сайт по советской вычислительной технике.
  • www.hnf.de/en/home.html — Сайт музея Heinz Nixdorf, г. Падерборн. Германия. Когда-нибудь я смонтирую видео оттуда.


Основы ламповой логики


Принципиальной разницы между современным компьютером и громадной ламповой ЭВМ нет — и те, и те состоят из множества переплетённых между собой логических элементов. Нюанс заключения в ограниченных технологиях тех лет, выливающихся в несколько большие чем big-tower массогабаритные показатели, при очень скромной вычислительной мощности.

Опираясь на альбомы схем отечественных и зарубежных ЭВМ, пробежимся по основным схемам построения ламповой логики. Как по мне, одними из лучших источников данных схем являются руководства по компьютерам IBM 604, IBM 650, и IBM 700.

▍ Инвертор


Усилительная лампа — например, триод или пентод — являются базовым кирпичиком при построении ламповой логики. Наиболее очевидным способом включения лампы является схема инвертора с общим катодом и нагрузочным анодным резистором. Если на управляющую сетку подать небольшое положительное смещение (здесь — +1В) — то лампа «откроется»: её внутреннее сопротивление будет минимальным, и выход «притянется» к земле, таким образом, на нём будет сигнал низкого уровня (+50В). Если же на сетку подать запирающее напряжение — в данном случае -50В — то лампа «закроется», её внутреннее сопротивление будет стремиться к бесконечности и на выходе будет сигнал высокого уровня.
gan9hfgkrffwbvmac_yambkkwuk.jpegИнвертор. IBM 604

Фактически инвертор уже реализует логическую операцию НЕ. Основной недостаток такой схемы заключается в несимметричной работе ключа. При подаче лог.1 лампа открывается и за счет низкого внутреннего сопротивления быстро разряжает ёмкость подключённой нагрузки, обеспечивая крутой спадающий фронт. Однако при подаче лог. 0 лампа закрывается, ее внутреннее сопротивление стремится к бесконечности и заряд ёмкости нагрузки происходит через анодный резистор. Его сопротивление существенно больше сопротивления открытой лампы — в итоге нарастающий фронт затягивается. Аналогично себя ведёт транзисторная схема с открытым коллектором. Будь у лампы комплиментарный ключ — можно было бы собрать двухтактные схемы и всё было бы намного проще, но это — физически невозможно. Частично проблема медленных нарастающих фронтов решается индуктивностью в цепи анода. Запасенная в индуктивности энергия кирпичом ударит в нагрузку, ускоряя закрытие лампы.

Если на один анодный резистор повесить сразу две лампы, то получится базисный логический элемент 2ИЛИ-НЕ (Стрелка Пирса), что означает возможность создания ламповой логической схемы любой конфигурации.

7aspqkwl_lcohynz5cmgour6er8.jpeg
Логический элемент 2ИЛИ-НЕ

С помощью резистивных делителей на входе, а также отрицательного смещения в -100В, логические уровни +150 — +50В преобразовываются в сигналы +1 -50В необходимые для управляющей сетки. Конденсаторы в цепи делителей используются для компенсации паразитной сеточной ёмкости и корректируют нарастающие фронты управляющих сигналов. На выходе будет сигнал низкого уровня — +50В, если подать лог.1 на любой из входов элемента.

▍ Катодный повторитель


Катодный повторитель — ещё один вариант включения лампы. В этом случае катод лампы через резистор подключён к источнику отрицательного напряжения -100В. Сигнал на выходе по уровням напряжения будет примерно соответствовать входным — +25 — -25В на входе и +26 — -22В на выходе.
rryf7_zs9fc5mgxahnbfszjtcse.jpegКатодный повторитель

Зачем он такой нужен? Как и эмиттерный повторитель на транзисторе — согласовать высокое выходное сопротивление с низким. Например, декатрон имеет анодный ток в 500 мкА. Этого достаточно чтобы отобрать 10–20 мкА для управления одной-двумя лампами без изменения режима работы разряда, но если нам надо подключить к декатрону 10–20 ламп — то без повторителя не обойтись.

l_uzogbtkjwvag5eanw_ayoqgau.jpeg
Логическое ИЛИ на катодном повторителе

Если на один катодный резистор посадить сразу несколько ламп, то получится многовходовое ИЛИ. К сожалению, из-за коэффициента усиления по напряжению чуть меньше единицы, на одних катодных повторителях далеко не уедешь.

▍ Катодно-связанная логика


Возможно, кто-то вспомнит, что ЭСЛ логика какое-то время уделывала по скорости ТТЛ и КМОП. На лампе тоже можно сделать такое, получив катодно-связанную логику. По сути, в роли логического элемента выступает дифференциальный каскад на двух триодах, использующих общий катодный и анодный резисторы. При этом на одну управляющую сетку подаётся некоторое напряжение смещения, а на вторую — управляющий сигнал.

6gw_y-l-pex3jyt6aztdzul6xb4.jpegДифф. каскад в роли логического элемента. Компьютер ACE от Алана Тьюринга

Несмотря на работу ламп в усилительном режиме и высокое быстродействие, сразу бросается в глаза удвоение ламп. С другой стороны, у дифф. каскада сразу два выхода — прямой и инверсный. Второй недостаток можно обнаружить, оценив схему сумматора на лампах:

4jxy_hfpc2rqy9l9srv1tkpxarq.jpegСумматор на дифф. каскадах

Не многовато ли тут напряжений смещения? Всё же удобно, когда в ЭВМ везде используются одни и те же уровни напряжения. Например, +150 — +50.

▍ Диодная логика


Описанные выше схемы включения ламп предлагают ограниченное количество логических элементов. Попробуем добавить на вход лампы логику на диодах в различных комбинациях. Диоды можно использовать и сами по себе, например, для создания многовходовых элементов И, ИЛИ. Несколько диодных плат в релейном компьютере BrainfuckPC использовались именно в качестве многовходовых ИЛИ. С одной стороны, они повышали быстродействие — по сравнению с релейным каскадом, требующим 300–400 мкс времени на срабатывание реле, диоды работали мгновенно. С другой стороны, при напряжении питания реле в 5В и падения напряжения на германиевых диодах в 0,7В у меня были проблемы со стабильностью работы схемы — 86% питающего напряжения было недостаточно для обеспечения необходимой скорости срабатывания реле.

g2xbjbjnqschfbntrr5t0gvk11q.jpeg
Диодные логические элементы И (слева), ИЛИ (справа)

В моей ЭВМ я планирую использовать диодную логику с инвертирующим усилителем или эмиттерным повторителем. В этом случае на диодах и подтягивающих резисторах собирается практически любая логическая схема, будь то многовходовое И, ИЛИ, а также их комбинации. Этот сигнал подаётся на усилитель и далее по схеме. Такой вариант прост в разработке, и довольно экономичен — напряжение и ток в диодной цепи небольшой, а значит, и потребляемая мощность по цепи управления будет низкая. Но главное — диоды требуют в полтора раза меньше мощности на накал. Например, сдвоенный диод 6×7Б потребляет 1,9Вт по цепи 6.3В, в то время как сдвоенный триод 6Н17Б — 2,8Вт.

pwn_bcjbjrn14mcaliwe6zaagzi.jpegРазличные схемы диодной логики с усилительным каскадом на лампе

Язык программирования brainfuck


Как и релейная машина, DekatronPC создаётся для выполнения программ, написанных, на, пожалуй, самом популярном эзотерическом языке программирования brainfuck.

q_shmxehqypxvxhersztfsggnee.jpegРис. 2: Инструкции языка brainfuck

Brainfuck — тьюринг-полный язык, а значит, в теории, на нём можно написать всё что угодно. Но реализация реальных задач может занять нереальное количество времени. Язык идеально подходит для парногоненормального программирования, а также нахождения друзей и разрушения семей.

В языке 8 инструкций, которые крутятся вокруг 30 тысяч ячеек памяти данных разрядностью 8 бит.

  • С помощью инструкций < и > мы можем перемещаться по памяти данных влево или вправо, выбирая ту или иную ячейку данных. При этом память закольцована, т.е. ячейки с номерами 29999 и 0 являются соседними
  • Инструкциями + и - мы можем изменять значение в текущей ячейке данных на единицу вверх или вниз в диапазоне от 0 до 255.
  • С помощью инструкций . и ,  — реализуется интерактивность. С их помощью можно напечатать в консоли значение текущей ячейки данных, или ввести символ с терминала в ОЗУ.
  • Последние две инструкции [ и ] — используются для организации циклов. Всё что внутри скобок является телом цикла. Допускается вложенность циклов. На границах цикла проверяется состояние текущей ячейки данных. Если оно не равно нулю — необходимо выполнить тело цикла.


Существование компиляторов из языка C в brainfuck как бы намекает о том, что этих инструкций более чем достаточно для написания всего что угодно. Но плотность кода — никакущая. Для выполнения простейших операций, например, сложения значений двух ячеек памяти, требуется исполнить сотни инструкций brainfuck. Но почему новая ЭВМ называется DekatronPC, а не BrainfuckPC2.0?

Декатрон


akyd2hzu0zjy6qxgovnxok2nv6w.jpegДекатрон А103 со стеклянным баллоном и без него. Хорошо видны центральный анод и 30 катодов вокруг него

По мнению большинства самодельщиков, декатрон является бесполезным артефактом, на котором можно сделать разве что крутилку. Из всего обилия схем с декатронами могу похвалить только творчество тов. Woddy, который сделал красивые индикаторы уровня с помощью динамической индикации.

На самом деле декатрон является счётно-коммутаторным прибором. При подаче управляющих импульсов декатрон будет совершать операцию инкремента и декремента. Да эта лампа просто создана для языка brainfuck! Посудите сами — +1 и -1 к текущему значению, +1 и -1 к номеру ячейки данных, и +1 и -1 для счётчика инструкций — 6 инструкций из 8 можно реализовать на декатроне!
giybmpbhxbo256dgw8m0jdnt6mk.gif
Перемещение тлеющего разряда в декатроне

Конструктивно декатрон представляет собой плоский диск анода, вокруг которого расположены 30 катодов. Десять из них — основные катоды — выведены на цоколь баллона (у счётных катодов на цоколь выведен только нулевой катод и общий). Ещё две группы по 10 подкадов соединяются внутри баллона и равномерно располагаются по кругу — по одному подкатоду каждой группы между каждым катодом. После подачи напряжения на декатрон, между анодом и одним из основных катодов загорается тлеющий разряд. Подавая импульсы отрицательного напряжения определённой последовательности на подкатоды, мы можем перемещать разряд между катодами в любую сторону.

Один декатрон может считать от 0 до 9. Объединяя декатроны в цепочку, можно получить многоразрядные реверсивные счётчики. Например, счётчик на базе трёх декатронов способен считать от 0 до 999. С декатроном есть как минимум две проблемыособенности по сравнению со счётчиком на вакуумных лампах:

Во-первых, газонаполненные приборы очень медленные. Например, самый быстрый октальный декатрон А106 способен развить скорость счёта всего лишь в 100 тыс. импульсов в секунду. А самый быстрый сверхминиатюрный декатрон А110 — 1 млн. импульсов. В то же время на вакуумных лампах можно создать счётчики, работающие на существенно более высоких скоростях. С другой стороны, А110 у меня есть в необходимом количестве, да и достигнуть 1MIPS на лампах — ещё надо постараться.

mgfbbukpbju92czcuhuoxicgqmy.jpegСверхминиатюрный коммутаторный декатрон А110 рядом с октальным декатроном А101. Скорость счёта до 1МГц

Во-вторых, декатрон мало того что считает от 0 до 9, так ещё и делает это в позиционном коде.
Так как вся адресация в машине всё же идёт в двоичных кодах, появляется необходимость шифратора позиционного кода в двоично-десятичный и обратно.
В первом случае всё относительно просто, нужно лишь 4 многовходовых ИЛИ и дело в шляпе. Тем более что выходной сигнал с декатрона +30 — 0В — с лёгкостью можно скорректировать до +10 — -20В и подавать на катодные повторители через диодную логику.

В итоге на разряд схемы считывания требуется 8 сдвоенных диодов и 2 сдвоенных триода.

d1fiwg5ehjwgqlqd1i5h8sybpqy.jpegСхема включения декатрона и схемы шифратора из позиционного кода в двоично-десятичный. На сдвоенных диодах реализовано многовходовое ИЛИ и катодный повторитель в роли усилителя сигнала

А вот дешифратор из двоично-десятичного в позиционный код существенно сложнее. Во-первых, чтобы записать данные в декатрон, на нужный катод необходимо подать отрицательное смещение в -150В. Во-вторых, необходимо для всех 4 бит двоично-десятичного кода иметь прямые и инверсные сигналы, чтобы из них в необходимой комбинации набрать код нужного катода. В-третьих, все 10 четырехвходовых И должны быть неактивными большую часть времени. Итоговая схема — монструозна.

На то, чтобы записать нужное число в декатрон потребуется 29 сдвоенных триодов! 20 штук в роли логических И, 4 — на входные инверторы и ещё 5 — непосредственно на лампы, притягивающие катоды к -150В. В дополнение к этому ещё три лампы уйдут на схемы управления двумя подкатодами. За счёт этого общее количество ламп декатронного счётчика становится больше чем для варианта счётчика только на вакуумных лампах. Хорошо что не всё так плохо и схема записи на каждом декатроне мне не нужна.

lyccdntbvkvnovnu0zwvxejnbck.jpegОчень малая часть схемы записи. Слева схема двойного инвертирования со смещением логических уровней до -100 -200В, далее — 4-х входовое И с сигналом разрешения записи

А вот ещё одна особенность: двоично-десятичный код шириной в 4 бита, использует только 10 комбинаций из 16 возможных. В итоге имеем лишь 62.5% использования всего адресного пространства ОЗУ. Да, можно реализовать схему управления так, чтобы после 7 декатрон устанавливался в 0 и наоборот, переведя его таким образом в восьмеричный режим работы. Но схема управления декатронами настолько усложняется, что проще найти ещё пару кубов ферритовой памяти, чем городить огород с переносом. Он и так непрост и требует как минимум 6 сдвоенных диодов и 2 сдвоенных триода на каждый разряд для своей реализации.

В отличие от схем ламповой логики, у меня нет каких-либо источников, где я могу взять готовую схему управления декатроном. Приходится опираться на теорию работы декатрона и немного — на отдельные статьи 50-х годов про тот же Harwel Dekatron. Как итог — у меня нет гарантии, что схемы, описанные выше, будут работать именно так, как задумано. Да, на вакуумных лампах счётчики выйдут значительно проще, но я поставил задачу собрать их именно на декатронах со всеми сопутствующими проблемами.

Кстати, о Harwel Dekatron. Давайте внимательно рассмотрим схемотехнику базовой декатронной ячейки:

pavyxif2fwcovg7jzhb90okhmvg.jpeg

В центре схемы — непосредственно сам коммутаторный декатрон, правда, почему-то на целых 11 катодов. Каждый из них подтянут своим резистором к источнику отрицательного напряжения -16В. Сделано это, чтобы сигнал с неактивного катода запер диод логики и лампу шифратора. Лампа, в свою очередь, управляет обмоткой реле и сигнал уходит куда-то дальше. Схема считывания очень похожа на мою с тем лишь отличием, что тут не двоично-десятичная запись. Смотрите как подключены катоды декатронов к лампам шифратора. Их, кстати, пять, что даже для 11 катодов — много. Технически с каждым новым импульсом выходной сигнал будет изменяться ровно на 1 бит. Тут есть какая-то реданданси, о которой мне неизвестно.

Не менее интересным является схема записи нового числа в декатрон. Чтобы сделать это, замыкается один из 10 контактов реле, которые подключают определённый катод к входу какого-то усилителя считывания и декатрон сбрасывается в нуль с помощью схемы сброса. Далее на декатрон поступает ряд импульсов до тех пор, пока текущее значение в нём не сравняется с требуемым. Очень надеюсь, что равнозначность катодов всё же не только на бумаге и у меня получится записать любое число в декатрон, просто притянув нужный катод к -150В.

Поэтому в настоящий момент я занят сборкой экспериментальной декатронной ячейки на декатроне А103 и пальчиковых лампах 6Н15П и 6×2П. В её задачу входит проверить эти схемы на вшивость. Для этого я использую именно пальчиковые, а не сверхминиатюрные лампы и навесной монтаж вместо печатных плат. После того как вся ячейка будет готова, а схемы управления — зафиксированы, я разработаю печатные платы и соберу модули уже на сверхминиатюрных лампах.

7krcfl7jfndtfslbvzp0tdxy_wc.jpeg3d-модель экспериментальной декатронной ячейки

На данной модели представлены — слева направо:

  • Плата конвертера двоично-десятичного кода в позиционный,
  • Плата усилителей сигнала,
  • Плата декатрона, со схемой считывания и переноса разряда,
  • Плата стабилизаторов напряжения,
  • Блок трансформаторов питания.


Таки да — один разряд декатрона на пальчиковых лампах занимает 3U корпус глубиной 350 мм. Всего декатронов 17. Всё же сверхминиатюрные лампы имеют смысл :)

wbcqai9lqufs7m1gx851bog7x7i.jpeg
Тёплая ламповая миниатюризация наглядно. Слева направо — октальные лампы 6Н13С и 6П9, пальчиковая лампа 6Н3П, сверхминиатюрная лампа 6Н17Б и стержневая лампа 1Ж17Б. Тут не хватает нувистора, он в два раза короче сверхминиатюрных ламп

В реальности эта ячейка будет выглядеть немного иначе — на всех платах кроме декатронной (так как она уже физически существует и представлена на КДПВ) ещё нужно перетасовать лампы, блок питания со стабилизаторами уедет назад для большего пространства, поставить вентиляторы охлаждения, ну и всё в таком духе. Сверху и снизу ещё нужно будет закрыть ячейку оргстеклом и можно будет возить её по различным выставкам.

Архитектура ламповой машины


Несмотря на сложности управления, идея создать ламповую ЭВМ на базе декатронов, да ещё и с набором инструкций brainfuck овладела мной. Последние три года я размышлял о том, как будет работать эта машина, как будет выглядеть, как её собирать… На данный момент я уже окончательно определился с архитектурой будущей машины, схемотехникой модулей в общем виде.

Я поставил перед собой задачу построить самый быстрый ламповый компьютер на базе декатронных многоразрядных счётчиков, способный выполнять программы на языке brainfuck без какой-либо прекомпиляции — за что меня ругали в эпоху релейного компьютера. Хотя я всё же добавил несколько новых инструкций, которые можно реализовать на разработанной архитектуре. Из других условий — я неограничен в технологиях производства, но непосредственно в самой ЭВМ запрещено использование кремниевых полупроводников. Допускаются только германиевые диоды и селеновые столбы. Они были и в 51-м году. Использование, например, кенотронов в роли выпрямителей увеличит расчётное потребление машины примерно в 2 раза — с 10 до 20кВт. В цепи обвязки ферритовой памяти использование германиевых диодов в принципе не избежать — иначе один только блок памяти займёт серверную стойку. А то и две.

yy8iwrq7ps8wejt9avhqkmu1nb8.jpegАрхитектура ядра лампового компьютера

Структурно машину можно разбить на три больших блока:

  1. Instruction Ptr Block — Отвечает за выборку очередной инструкции из памяти программ.
  2. Address Ptr Block — Отвечает за исполнение инструкций касаемо данных — прогулки по памяти, изменение значения в ячейке, работа с терминалом
  3. Блок логики, контролирующий работу машины


Сами блоки состоят из модулей: многоразрядных реверсивных счётчиков, модулей памяти, буферов и т.п. Все эти базовые кирпичики имеют три линии управления: сигнал ЗАПРОС (Request), флаг ЗАНЯТ (Busy) и флаг ГОТОВ (Ready). По сигналу ЗАПРОС, модуль счётчика, например, начнёт считать адрес новой инструкции. По сигналу ЗАПРОС, модуль памяти, например, начинает выгружать данные по новому адресу. Тут-то уж зачем? Ну, если у нас только ферритовая память — то это ни к чему, а если ферритовая память работает в роли кэша для накопителей на магнитной ленте — то при смене кэш-линеек время выборки может быть увеличено.

Думаешь я шучу?
Нет, у меня и структурная схема имеется:
ym_fkje46nallg9e-no9cpj6ik8.jpegПринцип работы ферритовой памяти в роли кэша для внешних накопителей

Это было придумано потому, что найти даже 30 кбайт ферритовой памяти ОЧЕНЬ проблематично. Вместе с этим НМЛ СМ5300 позволяет записать на ленту несколько мегабайт. И либо мы делаем ферритовую память на очень малый объём данных или программ, либо начинаем веселье.

Три кэш-линейки для того, чтобы нивелировать задержки доступа к НМЛ. В каждой линейке расположен 1Кб инструкций. В каждый момент времени есть текущая кэш-линейка, на которую указывает счётчик инструкций, предыдущая и следующая. Когда IP Counter станет указывать на следующую линейку — она тут же станет текущей, текущая — предыдущей, а та, что была предыдущей — начнёт заполняться следующей порцией данных с НМЛ. Предыдущая кэш-линейка нужна для того, чтобы быстро бежать назад при выполнении циклов.

А если серьёзно — я ещё не пытался воспроизвести эту логику в SystemVerilog для эмулятора. Но хочу попробовать. На это он и эмулятор, но об этом позднее. Совершенно не представляю, насколько это реально будет собрать в железе. Вероятно, для отсчёта номера ячейки в кэше при загрузке данных придётся делать ещё один счётчик.


В итоге каждый узел работает в режиме запрос-ожидание-ответ. У блоков есть такие же сигналы. Но и логика их обработки сложнее. Не могу однозначно ответить на вопрос насколько такой подход лучше или хуже обычного секвенсора. Я решил использовать его из-за сложности конечных автоматов каждых блоков.

▍ Instruction Ptr Block


qjtrt8xrvckdls0ebi6yr8bgkzc.jpeg

Этот блок содержит два счётчика, модуль памяти программ и логику работы с циклами. Первый счётчик (IP Counter) на базе 6 декатронов определяет номер инструкции, которая считывается из памяти программ.

В дополнение к нему идёт счётчик глубины вложенности циклов (Loop Counter) — сумматора в будущем компьютере нет, а значит, начало или конец тела текущего цикла придётся искать вручную, банально шагая счётчиком инструкций назад (или вперёд) до тех пор, пока не будет найдено начало именно нашего цикла. Трёхразрядного счётчика будет более чем достаточно — в brainfuck-программах, написанных людьми, даже больше 20–30 уровней вложенности циклов — редкость.

Блок выборки инструкций, получив от блока логики сигнал ЗАПРОС, должен выдать следующую инструкцию на выходе. Дальнейшие действия блока зависят от текущей исполняемой инструкции. Если она не является условной — т.е. одна из ±<>.,  — то счётчику инструкций достаточно сделать +1, зачитать новую инструкцию из памяти программ и выдать её на выходной буфер. Делать это, кстати, можно одновременно с исполнением текущей инструкции в блоке данных. Да, тёплый ламповый конвейер — к моменту завершения текущей операции мы сможем сразу начать новую.

Сложности начинаются с инструкциями границ цикла. Надо обработать условную операцию и либо выполнить инструкции в теле цикла, либо нет. Вариантов тут четыре. Допустим, есть следующий код цикла, реализующий операцию MOV — Мы будем делать +1 в ячейке n+1, и -1 в ячейке n до тех пор, пока ячейка n не равна нулю.

[>+<-]


При выполнении этого цикла может быть четыре варианта действий:

  1. Мы на инструкции [ и текущая ячейка не равна нулю — нужно выполнить тело цикла.
  2. Мы на инструкции ] и текущая ячейка не равна нулю — нужно вернуться в начало цикла, чтобы выполнить его ещё раз.
  3. Мы на инструкции [ и текущая ячейка равна нулю — нужно промотать тело цикла, не выполняя его.
  4. Мы на инструкции ] и текущая ячейка равна нулю — выполнение цикла завершено просто идём дальше


Их можно обобщить в два варианта развития событий:

  • При вариантах 1 и 4 компьютер просто продолжает выполнять инструкции друг за другом.
  • Варианты 2 и 3 требуют промотать тело цикла. Счётчик будет считать либо назад (для варианта 2) либо вперёд (3) в поисках ответной скобки цикла.


Чтобы промотать тело цикла, нужно пошагово изменять значение счётчика инструкций, делать выборку инструкции по этому адресу и Не подавая её на выходной буфер, смотреть, что же за инструкция сидит по этому адресу. Например, если мы начали с открывающей скобки [, и идём вперёд — то при нахождении закрывающей скобки] промотку можно считать завершённой. Но вот в процессе промотки мы наткнулись на ещё одну открывающую скобку [ — от вложенного цикла. Тут-то и пригодится счётчик глубины вложенностей. В самом начале промотки на нашей оригинальной открывающей скобе [ делаем ему +1 и потом будем делать +1 всякий раз, встречая открывающую скобку [, и -1 встречая закрывающую скобку ]. Как только после очередной закрывающей скобки ] значение счётчика станет равным нулю — поиск можно останавливать — цикл мы промотали. Точно так же это работает и в обратную сторону, разве что скобки меняются местами.

6edbn4b3l6e006a94-3yonu4cua.jpeg
Поиск начала цикла слева. Пошагово передвигаемся назад, изменяя значение счётчика вложенностей циклов

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

▍ Data Ptr Block


rxjgjvolal5r_yfa0lwiepu0pmq.jpeg

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

Один счётчик (AP Counter) считающий от 0 до 29999, будет определять номер текущей ячейки данных. Для чистого brainfuck необходимо будет сделать сброс старшего счётчика в нуль после 2 и наоборот. Один декатрон легко установить в нужное значение. Сложно прогнать сигналы переноса через все разряды.

По адресу этого счётчика происходит выборка данных из ОЗУ в четвёртый счётчик — Data Counter. Он умеет считать от 0 до 255. т.е. мы загружаем в декатрон наше старое значение, делаем инкремент или декремент и выгружаем данные обратно в память. Или же — мы можем напечатать текущее значение в терминале, или, минуя декатронный счётчик — занести число из терминала сразу в ОЗУ. Так как в программах на brainfuck инструкции инкремента/декремента ячейки ОЗУ и значения, как правило, идут группами, то это не значит, что потребуется постоянно загружать/выгружать данные в счётчик и обратно. Этого можно избежать, добавив флаг занятости ОЗУ.

Допустим, кусок программы на brainfuck выглядит так:

>>>>>+++++<<<<<


Без использования флага занятости машина будет загружать данные в счётчик Data после каждой инструкции > или <. И выгружать данные после каждой операции + или -. Таким образом, будет 10 операций чтения и 5 операций записи. А это всё — время. С флагом занятости, ЭВМ сделает ровно по одной операции чтения и записи:

  1. После выполнения пяти инструкций > AP Counter увеличится на 5
  2. Перед выполнением инструкции + Проверка флага занятости покажет, что он не взят. Значит, перед операцией инкремента данных нужно загрузить эти данные в счётчик
  3. После выполнения пяти инструкций + Data Counter увеличится на 5
  4. Перед выполнением инструкции < Проверка флага занятости покажет, что он взят. Значит, необходимо сначала выгрузить данные из счётчика Data в ОЗУ
  5. После выполнения пяти инструкций < AP Counter уменьшится на 5 до начального значения

▍ Какова цена счётчиков?


muso-kuv3_xrdilcx7jzatt2le0.jpegПримерная компоновка плат будущей машины. Слева плата декатронного счётчика, справа — модуль ламповой логики

На всю машину потребуется 17 декатронов. Из них, только 3 декатрона счётчика данных потребуют всю обвязку. Остальные три счётчика не требуют полной схемы записи. Достаточно дешёвой схемы сброса декатрона в нуль. Хотя для старшего разряда счётчика адреса требуется сбрасывать декатрон в 0 или 2 — чтобы после декремента нуля получить 29999.
Счётчик глубины вложенностей не требует даже схемы чт

© Habrahabr.ru