Эмулятор МК-61. Охота в потемках

| рубрика «Калькуляторы» | автор site_editor
Метки: ,

От редактора. После публикации статьи Алексея Сугоняева "Перенос эмулятора МК-61 на платформу msp430" встал вопрос о расширении возможностей МК-61. В самом деле, почему бы не добавить устройству немного памяти, ведь для этого даже не надо ничего паять на макете, достаточно изменить работу эмулятора! Вот что из этого получилось. Алексей продолжает рассказывать.

МК61

Неожиданный поворот

После моей публикации, совершенно случайно я наткнулся на статью Алексея Полушкина “Усовершенствованный микрокалькулятор Б3-34” на сайте Кон-Тики. В глаза бросился бутерброд из двух микросхем К145ИР2, собранный для увеличения памяти Б3-34. Опираясь на опыт предыдущих исследований, мы знаем, что вся память МК-61 содержится в кольцевой магистрали М. Схема Б3-34 состоит из микросхем ИК1302, ИК1303 и двух регистров ИР2. Количество шагов программы при таком объеме магистрали — 98, количество регистров — 14. Автору статьи удалось добиться увеличения памяти программ и, видимо, регистров тоже. Зная объемы ЗУ каждой микросхемы комплекта, можно предположить, что у Б3-34 теперь появилось 42 + 42 + 252 + 252 + 252 = 840 тетрад, то есть 7 * 840/42 = 140 шагов памяти программ и 840/42 = 20 регистров памяти. Ого, вот так модернизация! К сожалению, точные количественные характеристики улучшений автор не привел. В комментариях к статье пользователи ПМК интересовались, неужели память добавилась и сколько же ее стало? “Неожиданный поворот истории, — подумал я, — неужели все так просто?” Конечно, проверять предположения, запаивая в кольцо МК-61 еще один регистр ИР2 — дело и безнадежное и бессмысленное: корпусировка комплекта К745 для МК-61 — та еще штучка. Но… а зачем? Ведь у меня уже есть эмулятор МК-61 и добавить в массив ringM[] еще одну ИР2 дело нескольких минут. “Да хоть десять ИР2”, — подумал я и приступил к эксперименту.

Кольцевая магистраль МК-61 особенности

В погоне за производительностью эмулятора я не стал делать удобного смещения в кольце М нулевого пакета с шагами 0-6 программы МК-61. Совершенно зря, как выяснилось. Теперь я решил исправить этот недостаток, сделав доступ к регистрам и шагам программы линейным смещением в массиве с шагом в 42 байта. И тут всплыли неожиданные особенности организации кольца М: тасуя микросхемы по кругу, добиться перехода пакета с шагами 0-6 в первые 42 байта массива ringM было невозможно. Точнее, достичь этого можно было лишь нарушив порядок их коммутации. Это выглядело подозрительным: неужели разработчики калькулятора МК-61 заранее обрекли себя на неудобство в доступе к содержимому магистрали М? Я решил заглянуть в заводскую схему, выписав последовательность коммутации оттуда. Ниже — вырезка соответствующих блоков с разметкой магистрали.

Входы микросхем согласно еще советским ГОСТ-ам должны находится слева УГО, справа УГО находятся выхода. Паспорт на К745ИК130х мне не удалось найти, однако паспорт на К145ИК1302 и схема Б3-34 это также подтверждают. Таким образом, становится виден порядок коммутации микросхем в магистраль, заложенный в схему: ИК1302 -> ИК1303 -> ИК1306 -> ИР2.1 -> ИР2.2 с замыканием ИР2.2 в кольцо на ИК1302. Продемонстрируем различия в коммутации микросхем в эмуляторе и на схеме:

Налицо “чехарда” ИК130х, сейчас же хватаюсь за исходный код эмулятора МК-61 С.Тарасова. И... наблюдаю в полный рост свой эпический “косяк”. Привожу код, демонстрирующий мою неаккуратность

void MK61Emu::Tick()
{
    m_IK1302->input = m_IR2_2->output;
    m_IK1302->Tick();
    m_IK1303->input = m_IK1302->output;
    m_IK1303->Tick();
    if (m_mode == mk61emu_mode_61)
    {
        m_IK1306->input = m_IK1303->output;
        m_IK1306->Tick();
        m_IR2_1->input = m_IK1306->output;
    }
    else
        m_IR2_1->input = m_IK1303->output;

    m_IR2_1->Tick();
    m_IR2_2->input = m_IR2_1->output;
    m_IR2_2->Tick();
    m_IK1302->M[((m_IK1302->mtick >> 2) + 41) % 42] = m_IR2_2->output;
}

Согласно этому фрагменту подключение соответствует схеме, видимо при переделки магистрали на монолитный массив я проглядел этот нюанс, сделав размещение во таким:

IK1302_pM = (uint8_t*) &ringM[42+42];
IK1303_pM = (uint8_t*) &ringM[42];
IK1306_pM = (uint8_t*) &ringM[0];

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

const uint8_t* IK1302_M_START = &ringM[42+252];
const uint8_t* IK1303_M_START = &ringM[42+252+42];
const uint8_t* IK1306_M_START = &ringM[42+252+42+42];

IK1302_pM = (uint8_t*) IK1302_M_START;
IK1303_pM = (uint8_t*) IK1303_M_START;
IK1306_pM = (uint8_t*) IK1306_M_START;

Видно, что в кольцо после ИР2.2 пришлось разместить 42 тетрады, не принадлежащие ни одной микросхеме, только так пакет 0 с шагами 0-6 становился в начало массива ringM. Как будто эти 42 тетрады отошли по кругу в начало кольца из ИР2.1:

Эмулятор продолжал работать, все запланированные тесты проходили исправно. При внесении в ШАГ-0 команды и просмотра области массива в отладчике код команды обнаруживался в пакете-0 в начале массива ringM[]. Делаем следующий шаг: добавляем память в кольцо.

Небольшое отступление. Как человек очень любопытный, на самом деле этот шаг я сделал, еще даже не исправив эмулятор, согласно схеме, точнее про эту ошибку я еще не знал. Добавил я сразу одну ИР2 в массив магистрали, Сергей Тарасов и Виталий Самуров тому свидетели :) И конечно сразу же попытался что то писать в шаги 105, 106, 107. И вроде бы получилось, однако… Однако, как показали эксперименты, памяти добавилось всего 7 шагов. Поскольку смещения микросхем в массиве в то время не соответствовали линейной развертке, было очень трудно понять в каком месте программной памяти осуществляется заворот. Процедуры просмотра памяти программ (DumpCode) в эмуляторе на MSP430 использовали развертку добытую в отладчике еще в самом начале эпопеи и поэтому “бессовестно врали” отображая шаги 105..111 на шаг 70. Все эти соображения мы с С.Тарасовым проверили через простенькую программу и петли на 70 шаг не обнаружили. Тогда стало понятно что организацию массива надо привести в порядок. Если добавилось 7 шагов, рассуждал я, то значит добавился пакет памяти в 42 тетрады, а, значит, добавился еще один регистр. И он действительно добавился — регистр F. Конечно же напрямую доступ к нему не получить (хотя может быть я чего-то и не знаю), только косвенно. В регистры от 0 до Е был записан набор чисел: 0, 1, 2, 3, 4, 5, 6, 7, 8, 15, 10, 11, 12, 13, потом считан для проверки возможного наложения. Нет, наложения не произошло — это демонстрирует экран терминала MK-61 на MSP430. “РЕЖ” — это клавиша МК-51, осуществляющая замену клавиши “К” в МК-61. Терминал MK61msp демонстрирует, что косвенная запись КП9, а затем и чтение по КИП9, прошли успешно.

Таким образом мы выяснили, что при добавлении 252 тетрад в память магистрали М для МК-61 добавляется всего 42. А значит добавление целого регистра ИР2 избыточно.

Модернизированный МК-61 на платформе MSP430 без излишеств получил в кольцо дополнительно 42 тетрады (байта) следующим образом:

const uint8_t* IK1302_M_START = &ringM[42+42+252];
const uint8_t* IK1303_M_START = &ringM[42+42+252+42];
const uint8_t* IK1306_M_START = &ringM[42+42+252+42+42];

IK1302_pM = (uint8_t*) IK1302_M_START;
IK1303_pM = (uint8_t*) IK1303_M_START;
IK1306_pM = (uint8_t*) IK1306_M_START;

Эмулятор опять прошел все тесты, не показав снижения производительности, что косвенно подтверждает: размер кольца не должен влиять на длительность цикла.

Тайны и загадки МК-61, будут ли ответы?

Фактически за цикл каждый пакет из 42 тетрад пробегает по кольцу N раз. Размер кольца в пакетах 630/42=15 и (630+42)/42=16. Тогда 560/15 = 37,3(3) и 560/16 = 35 дает нам N для MK-61 и измененного МК-61. Почему это не влияет на производительность — понятно: количество циклов не меняется. Но почему это не влияет на правильность вычислений — совсем неясно. Более того, непонятно и дробное число проходов пакета по кольцу. В эмуляторе С.Вакуленко есть наводящие на размышления строки:

i = k % 14;
if (i >= 12) {
    // Clear display.
} else {
    if (i < 3) {
        // Exponent.

    } else {
        // Mantissa.

    }

    if (ik1302.dot == 11) {
        // Run mode: blink once per step with dots enabled.

    } else if (ik1302.enable_display) {
        // Manual mode.

    } else {
        // Clear display.

    }
}

Как видно из кода, для отображения на дисплеи мантиссы и порядка используется остаток от деления на 14 в интервале 0..11. Все что выше, этапы 12, 13 и 14, вероятно, используется для вычислений другого рода. 560/14 = 40 дает целое число групп вычислений. 40 раз за цикл аппаратура работает над каждым десятичным разрядом. Что характеризует величина “40”? Указывает ли она на максимально возможное количество обработок числа? Заранее заложенная избыточность по количеству этапов? А что же означает отсутствие жесткой позиции микросхемы в кольце?

МК-61 не так прост как хотелось бы и, по всей вероятности, мы только в начале очень длинного пути по открытию тайн отечественных программируемых калькуляторов.