Skip to main content

Воскресение Knight TV

  • Эта публикация - перевод статьи. Ее автор - pdp-6.net. Оригинал доступен по ссылке ниже:

Система Knight TV была терминальной системой, созданной Томом Найтом, она была подключена к AI KA10. Он использовал PDP-11/20, чей Unibus был напрямую подключен к PDP-10 интерфейсом 10-11, уникальным для AI. (Сначала мы думали, что было 11/10, но, похоже, это не так)

PDP-11 имел 12 кВт памяти и несколько 16-киловаттных буферов кадров растровых изображений, которые можно было отображать в адресном пространстве Unibus. Буферы кадров генерировали видеосигнал, используемый в качестве входного сигнала для видеокоммутатора, настроенного PDP-11. Выход этого видеопереключателя подавался на телевизоры, которые использовались в качестве терминалов. Для ввода был клавиатурный мультиплексор, к которому были присоединены клавиатуры Knight.

Файл  .; TV BIN может быть загружен в 11 из 10 с помощью программы STUFF, затем 10 и 11 обмениваются данными через общую память.

Система Knight TV была предпочтительным способом общения с ИТС на некоторое время, поэтому не было никаких сомнений, что она должна была воскреснуть!

Планирование

Ларс и я говорили о том, как этот многоуровневый дизайн должен быть реализован. У нас был Рич SIMH на основе KA10 эмулятора для запуска ИТСА. Первый вопрос заключался в том, использовать ли simh для эмуляции PDP-11 или написать новый эмулятор. Поскольку я нахожу сим-код довольно трудным для чтения, и потому что эмуляция - это весело, мы решили, что это будет новый код. Кроме того, поскольку имеется только один 11, но несколько дисплеев / клавиатур, эти 11 лучше всего работают как сервер, к которому затем подключаются клиенты. Это также позволило бы нескольким людям, подключенным к одной и той же удаленной системе, шпионить за консолями друг друга, что является важной функцией.

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

Эмуляция PDP-11

Писать эмуляторы весело, и особенно в случае с PDP-11/10 это достаточно просто сделать за пару дней. Поскольку сначала мы думали, что это ТВ-система PDP-11/10, для этого я и написал эмулятор. Это сработало, потому что разница с 11/20 не так уж велика. Позже я изменил эмулятор, чтобы он вел себя больше как 11/20, но ниже описано, как я написал первую версию.

PDP-11/10 на самом деле та же модель, что и 11/05, и всю соответствующую документацию можно найти на битсейверах. Это младшая модель, очень похожая на оригинальный PDP-11/20: микрокодированная (в отличие от 11/20), 16-битное адресное пространство, без расширенных инструкций (умножение, деление и т. Д.). В состав 11/05 входит несколько периферийных устройств, являющихся частью центрального процессора: линейный тактовый генератор KW11 и подобный KL11 интерфейс TTY. Поскольку он не имеет расширенных инструкций, хакеры MIT оснастили телевизор 11 расширенным арифметическим модулем KE11, устройством, которое находится на странице ввода-вывода Unibus и управляется записью значений в ряд сопоставленных регистров.

Я подумал написать довольно низкоуровневый эмулятор, который на самом деле выполнял бы микрокод, но решил не делать этого. Вместо этого я написал код более высокого уровня, который все еще был вдохновлен схемами и микрокодами. Эмулятор написан на C.

В PDP-11 все устройства ввода-вывода и память подключены к Unibus (это не так во всех моделях, но в нашем случае это так). ЦП является мастером шины, который разрешает доступ к шине. Когда устройству требуется доступ к шине, оно запрашивает доступ к шине с одним из 4 приоритетов (4-7). Чтобы смоделировать это, я сделал структуру для процессора, шины и устройств, подключенных к шине:

// KD11-B - процессор 11/10
struct KD11B
{
        word r[16]; // зарегистрируем блокнот
        word ba; // адрес шины
        word ir; // регистр команд
        Bus *bus; // наш прекрасный Unibus
        byte psw; // слово состояния процессора
        int traps; // флаги для отслеживания ловушек
        int be; // счетчик ошибок шины, чтобы перехватить ошибки двойной шины
        int state; // остановлен, работает или ждет

        // Отслеживаем запросы шин для всех каналов
        struct {
                int (* bg) (void * dev); // обратный вызов для предоставления шины
                void * dev; // устройство, которое запрашивает доступ к шине
        } br [4];

        word sw; // регистр переключателя консоли

        // опущено: внутренние устройства
        // линия часов
        // ...
        // ввод TTY
        // ...
        // вывод TTY
        // ...
};

// Юнибус
struct Bus
{
        Busdev *devs; // связанный список устройств на шине
        uint32 addr; // адреса 18 бит
        word data; // данные 16 бит
};

// Устройство в автобусе
struct Busdev
{
        Busdev *next; // следующий в списке
        void *dev; // указатель на структуру отдельного устройства
        int (*dati)(Bus *bus, void *dev); // читать данные с устройства
        int (*dato)(Bus *bus, void *dev); // записать данные (слово) на устройство
        int (*datob)(Bus *bus, void *dev); // записать данные (байты) на устройство
        int (*svc)(Bus *bus, void *dev); // обратный вызов службы,
                                            // возвращает приоритет запроса шины, если есть
        int (*bg)(void *dev); // обратный вызов для предоставления шины,
                                            // возвращает вектор прерывания
        void (*reset)(void *dev);  // сброс устройства
};
    

Внутренние устройства не используют шину, они обрабатываются кодом процессора. Для данного адреса ответит устройство, которое распознает адрес. Если ни одно устройство не отвечает, время доступа истекает, и ЦП получает ошибку шины. При наличии разрешений на шины ближайшее электрически устройство получит разрешение и передаст его следующему устройству, если оно не запросило доступ к шине. Я смоделировал этот механизм со связанным списком. Для всех типов поведения устройства существуют виртуальные функции, которые соответствуют транзакциям Unibus.

Пока процессор работает (т.е. не остановлен), он будет выполнять инструкции. Если он ожидает, он не будет выполнять инструкции, пока не произойдет прерывание (это указывается битом в переменной traps). Основной цикл выполняет ожидаемое в псевдокоде:

while state != halted
    service-internal-devices()
    service-bus-devices()
    if(state == running || state == waiting && traps)
        state = running
        execute-next-instruction()
    

Выполнение инструкций очень похоже на то, что вы ожидаете от эмулятора, если вы не знакомы с набором инструкций PDP-11, краткая сводка:

PDP-11 имеет 8 регистров общего назначения и 8 режимов адресации, что составляет 6 битов для кодирования любой комбинации регистр + режим. Некоторые инструкции имеют два операнда (поэтому для кодирования обоих требуется 12 битов), некоторые имеют только один операнд (6 битов), инструкции ветвления имеют смещение слова со знаком 8 битов, другие команды не имеют операндов.

Все инструкции с двойным операндом сначала читают исходный операнд и сохраняют его во временном регистре R10, читают целевой операнд и сохраняют его в R11, выполняют операцию (все они - очень простые операции ALU) и сохраняют результат обратно по адресу назначения, который был оставлен без изменений в реестре БА.

Унарные инструкции работают почти так же, просто нет исходного операнда.

Операции ветвления добавляют смещение ветвления в зависимости от того, какие биты состояния установлены.

K11-A - EAE

Модуль K11-A является расширенным арифметическим расширением, он реализует умножение, деление, логические и арифметические сдвиги и нормализацию. Руководство очень хорошо написано, и я рекомендую всем , кто интересуется , как компьютеры делают математику, чтобы прочитать его. Это работает так, что вы устанавливаете его регистры AC и MQ, записывая их unibus-адреса, а затем записываете третье значение в другой адрес для начала вычисления. Затем вы читаете результат от AC и MQ с тех же адресов. Реализация была довольно простой, я просто расшифровал блок-схемы на C.

ТВ оборудование

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

Буферные рамки консоли

Установка имеет максимум 16 кадровых буферов. Каждый FB имеет разрешение 576x454 пикселей, с 16 пикселями на слово, что составляет 037730 слов PDP-11, почти 16 кВт.

CREG (в 0164044) отображает один из теоретически 256 FB в 060000 на Unibus и устанавливает операцию ALU, которая должна выполняться при записи в буферную память. Для более быстрых изменений в FB аппаратное обеспечение может самостоятельно выполнять 16 различных операций ALU вместо того, чтобы PDP-11 выполнял их.

Видео переключатель

Каждый из этих 16 буферов теперь подается на входы видеокоммутатора, который отправляет видеосигнал каждого буфера кадра на любое количество телевизоров. Видеокоммутатор состоит из двух секций (S0 и S1 ниже), каждая из которых имеет 16 входов и 32 выхода. Соответствующие выходы обеих секций смешиваются вместе, чтобы сформировать окончательный сигнал для телевизора. Поскольку в обычном случае вы не хотите смешивать что-либо с консолями, оба раздела имеют нулевой вход на входе 0, что оставляет 15 входов на раздел для консолей.

Это показывает, как 16 консольных кадровых буферов подаются в видеокоммутатор и как микшируется выходной сигнал.

Регистр ВМЗ (на 0764060) управляет переключателем. Для раздела, входного и выходного номера он устанавливает источник выходного сигнала этого раздела для данного входа раздела. Таким образом, каждая консоль может отображаться на каждом телевизоре, если установить выход секции, к которой подключен буфер, и тот же вывод на другом переключателе в 0.

Клавиатурный мультиплексор

К мультиплексору клавиатуры можно подключить до 64 клавиатур. Он управляется регистрами KMS (статус клавиатуры, на 764050) и KMA (адрес клавиатуры, на 764052). Когда мультиплексор получает нажатие клавиши от одной из клавиатур, он отправляет его DMA вместе с номером клавиатуры в буфер в памяти, адрес которого дается KMA. Он также прерывает процессор, чтобы он мог прочитать новый ключ и обработать его.

Подражая всему этому

Реализовать это в C довольно просто. То, как работает видеопереключатель, становится немного сложнее. Поскольку каждый буфер консоли может отображаться на каждом дисплее, а также смешиваться с другим сигналом, это усложняет обновление программ ТВ-клиента.

Исходный код

Наконец, здесь вы можете найти исходный код: https://github.com/aap/pdp11 вместе с некоторыми другими проектами эмуляции PDP-11. Сценарий ITS сборки автоматически создает и запускает его , когда бежал с ./start tv11. Затем вы можете подключиться к 11 с помощью tvcon. Раскладка клавиатуры смоделирована после оригинальной раскладки, но есть опции командной строки, чтобы сделать ее немного более приятной.