Table of Contents

Кросс-система МИКРОБ

Обьединенный институт ядерных исследований

Лаборатория вычислительной техники и автоматизации

А. П. Сапожников

Дубна 1985 г.

В процессе создания ЭВМ, работающих по принципу микропрограммного управления, достаточно трудоемкой работой является подготовка микропрограмм. Кроме того, для сокращения сроков разработки в целом, изготовление микропрограмм необходимо вести параллельно с изготовлением аппаратуры, используя кросс-средства на инструментальных ЭВМ. К числу таких кросс-средств принадлежит и описываемая здесь кросс-система МИКРОБ, работающая на ЭВМ БЭСМ-6.

Общие положения

Микропрограмма - последовательность слов микропрограммной памяти (микрокоманд), адресуемых целочисленным адресом = 0,1,2,… Все микрокоманды имеют одну и ту же разрядность N, определенную заранее.

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

Такой подход характерен для т.н. Горизонтального программирования. При этом микроассемблер, по существу, представляет из себя генератор битовых строк постоянной длины. Универсальность же его заключается в способности настраиваться на заданный формат микрокоманды.

Архитектура кросс-системы МИКРОБ

|---------|      /-----------------\      |------------|
|  текст  |      |   м и к р о -   |      |  описание  |
|программы|=====>|а с с е м б л е р|<=====|  формата   |
|         |      |                 |      |микрокоманды|
|---------|      \-|-------------^-/      |------------|
                   |             |
                   |             |
                   |  а р х и в  |
        |----------v--------|----v------------|
        |    библиотека     |   глобальный    |
        | обьектных модулей |    контекст     |
        |----------|--------|-----------------|
                   |
                   |
           /-------v-------\
           |   загрузчик   |
           \-------|-------/
                   |
                   |
            |------v------|
            | двоичный код|
            |-------------|

Кросс-система МИКРОБ имеет много общего со “взрослыми” системами программирования на языках высокого уровня:

1. Вызов транслятора

Пакет задачи, запускаемой на БЭСМ-6 с целью трансляции микропрограмм, выглядит следующим образом:

          *nаме .....
          *pass:.....
          *time:.....
          *library:23,25
           <заказ архива под номером 30>
           <заказ, если надо, файла с текстом>
          *call microb [ :<ук.мл> [ ,<список> ] ]
   или:
          *call micini [ :<ук.мл> [ ,<список> ] ]

В квадратные скобки [ ] здесь и далее мы будем заключать необязательные параметры или синтаксические конструкции. Здесь необязательный параметр <ук.мл> задает адрес начала файла, содержащего тексты микропрограмм. Причем трансляции подлежат только микропрограммы, указанные в списке. При пустом списке транслируется весь файл. При отсутствии <ук.мл> текст читается из пакета задачи. Признаком конца текста считается карта *end

MICROB - вход для трансляции. При этом считается, что описание формата микрокоманды (т.н. Глобальный контекст) уже записано в архив ассемблера.

MICINI - вход при первоначально пустом архиве. При этом текст, подлежащий трансляции, предваряется описанием формата микрокоманды.

2. Трансляция глобального контекста

Глобальный контекст микропрограммы состоит из

Глобальный контекст оформляется в виде псевдопрограммы, имеющей имя DEFINE:

             define:prog n,к;               - заголовок
                  ..........
                    end;                    - конец

Здесь N задает разрядность микрокоманды, К - разрядность ПЗУ констант. Биты в микрокоманде нумеруются справа налево: N, N-1, …,2,1. При неуказании К = 64.

Внутри псевдопрограммы DEFINE находятся инструкции, определяющие поля микрокоманды и глобальные имена, которые считаются предописанными во всех микропрограммах.

Несколько замечаний терминологического характера:

По аналогии с ассемблерами уровня 2, на язык так и просятся слова “переменная” и “значение”. Однако в микропрограммах не бывает рабочих ячеек памяти, а содержимое полей микрокоманд не меняется в ходе работы. Поэтому, говоря о микроассемблере, мы должны иметь в виду, что любое имя в программе - это всего лишь мнемоника для обозначения числа или адреса.

Все-таки в дальнейшем, ради краткости, мы будем называть значением выражения сумму его термов, взятых со своими знаками. Термы, входящие в выражение, могут быть трех типов:

В правильном выражении должно выполняться соотношение

    0 <= NP-NN <= 1

где NP - число относительных адресов со знаком “+”,

  NN - число относительных адресов со знаком "-";

этого типа, со знаком “+”, и при условии, что NP = NN.

2.1. Формат микрокоманды

Кроме разрядности N формат микрокоманды характеризуется еще набором полей, ее составляющих. Для описания одного поля служит инструкция FIELD:

<ИМЯ ПОЛЯ>:FIELD N1,N2 [,N3 ]

Допускается вложение одних полей в другие, перекрытие полей не допускается (аналогично фортранным DO - циклам). Порядок описания полей - произвольный.

Для поля кода операции секвенсора в качестве параметра N3 необходим указывать маркирующую конструкцию /С/

Для поля адреса микропрограммы в качестве параметра N3 необходимо указывать маркирующую конструкцию /А/

2.2. Определение глобальных имен

Глобальные имена определяются с помощью инструкций EQU и BLOCK:

<ИМЯ>:EQU <ВЫРАЖЕНИЕ>;

Здесь новое <имя> определяется как число, равное значению <выражения>. Трансляция глобального контекста производится за один проход, поэтому все имена, входящие в <выражение>, должны быть уже определены.

<ИМЯ>:BLOCK <СПИСОК ИМЕН>;

Это способ “группового” определения имен, аналогичный фортрановскому common-блоку. <имя> должно быть уже определено.

Nаме:block nам1,nам2(2),nам3;            - эквивалентно
   nам1:equ nаме;    nам2:equ nам1+1;    nам3:equ nам2+2;

В левой части инструкции BLOCK разрешено указывать шестнадцатиричные числа с префиксом “*”:

*1а:block а,в(5),с;                      - эквивалентно
   а:equ $1а;    в:equ $1в;    с:equ $20;

Шестнадцатиричные числа в правой части инструкции (входящие в качестве термов в выражения) снабжаются префиксом “$” /доллар/).

2.3. Описание констант из ПЗУ

В адресном поле микрокоманды кроме адреса по ОЗУ микропрограмм может находиться адрес по ПЗУ констант. Для этого в адресном выражении достаточно указать имя константы. Имена констант являются глобальными, т.е. Предописанными в любой подпрограмме. Константы размещаются в ПЗУ в порядке появления их описаний, начиная с адреса 0. Формат описания константы:

<ИМЯ>:CONST <ШЕСТНАДЦАТИРИЧНОЕ ЧИСЛО>;

Разрядность всех констант одинакова. Она задается в инструкции DEFINE . Левые нули в константах можно опускать.

2.4. Немного о синтаксисе

На одной карте находится одна инструкция. Формат - не фиксированный инструкция может начинаться с любой позиции карты. Пробелы, вообще говоря, являются разделителями. Пробелы между разделителем и началом следующей лексемы игнорируются. Разделители: двоеточие, точка с запятой, запятая, плюс, минус. Общий формат инструкции:

[ <имя>: ] <код инструкции>  [ <параметры> ];

Все символы после “;” до конца текущей карты рассматриваются как комментарий. В частности, на карте может находиться только комментарий, если “;” расположена в 1-й позиции. Если после инструкции комментария нет, символ “;” можно опустить.

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

2.5. Пример

          *libra:23,25
          *file:scratch,30,w
          *call micini
           define:prog 72;        - разрядность = 72
          ;        по умолчанию разрядность пзу = 64
          ;
          ;     определим поля микрокоманды:
           seqv:field 72,64,/с/;  - код микрооперации
              а:field 50,63,/а/;  - адреса переходов
            алу:field 49,40;      - к о п   а л у
             ci:field 39,
          >39,1;            - пример карты-продолжения
          ;
          ;     определим коды секвенсора:
           jump:equ 0
           test:equ jump+1
          ;
          ;     определим коды   а л у:
           *0:block and,or,sub,add,mul;
          ;
          ;     парочка  пзу - констант:
            к1:const ffff;
            к2:const 1234567890abcdef;
          ;
          ;     и еще несколько глобальных имен:
            one:equ 1
            two:equ 2-one+1;
            ten:equ 9+two-one
                end;
          *end

3. Трансляция микропрограмм

Вся микропрограмма складывается из отдельных блоков - подпрограмм. Допускается раздельная трансляция подпрограмм. Результатом трансляции является модуль загрузки, записанный в библиотеку обьектных модулей. При этом, если в библиотеке уже была программа с таким же именем, то старая версия уничтожается (аналогично библиотекам в мониторной системе “дубна”). При трансляции используется уже имеющийся в архиве глобальный контекст. Перечислим теперь синтаксические конструкции, из которых складывается подпрограмма:

<ИМЯ ПОДПРОГРАММЫ>:PROG [ <ХАРАКТЕРИСТИКА> ] ;

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

END;
<ИМЯ ВХОДА>:ENTRY;
EXTERN <СПИСОК ИМЕН>;
                    <ИМЯ>:EQU   <ВЫРАЖЕНИЕ>;
<ИМЯ ИЛИ *<ШЕСТН.чИСЛО>>:BLOCK <СПИСОК ИМЕН>;

эти конструкции “работают” так же, как в 2.2.

Но, в отличие от глобального контекста, здесь значением выражения может быть не только число, но и адрес. Допускается использование еще не определенных имен. Переопределение глобальных имен не допускается.

<ИМЯ ПОЛЯ>:VALUE <ВЫРАЖЕНИЕ>;

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

[<МЕТКА>:]<КОП>  <СПИСОК ПОЛЕЙ И ИХ ЗНАЧЕНИЙ>;

<КОП> - код микрооперации (его еще иногда называют кодом операции секвенсора). Это символическое имя, определенное в глобальном или локальном контексте.

Например:      *6:block рор,push;

ассемблер подставляет значение имени <КОП> в то поле микрокоманды, которое помечено маркировкой /С/. (см. 2.1).

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

<имя поля> = <выражение>

либо просто именем поля (для однобитовых полей). Если в списке какое-то поле не указано, то в команду заносится начальное значение этого поля, указанное инструкцией VALUE или взятое из глобального контекста.

Здесь возможны неоднозначности при наличии вложенных полей. Для определенности принято следующее решение: незаполненные поля просматриваются в порядке убывания их ширины (т.е.расстояния между левой и правой границами). Далее, если поле получило значение, то заполненными считаются и все вложенные в него поля.

Маркировка адресного поля (см. 2.1) позволяет отслеживать случаи ошибочного заполнения неадресных полей адресной информацией.

Примеры микрокоманд:

Рассмотрим небольшой фрагмент микропрограммы. При этом мы воспользуемся глобальным контекстом, описанным в (2.4).

               снеск1:test а=снеск2,ci,алу=sub
                      jump а=*-1
               снеск2:jump а=inter,алу=add

Поле SEQV (оно отмечено маркировкой /С/ ) заполняется в первой команде кодом 1 (test=1), а во второй и третьей - кодом 0 (jump=0).

В поле А попадут соответственно адреса меток СНЕСК2, СНЕСК1 и INTER. Терм “*” в адресных выражениях, как и в большинстве обычных ассемблеров, означает текущее состояние счетчика относительных адресов внутри подпрограммы. Окончательная настройка программы по адресам выполняется загрузчиком.

В поле АЛУ попадет в первом случае код 2, в третьем - код 3. Для второй команды “сработает” правило умолчания, и в поле АЛУ попадет код 0.

Поле CI во всех трех командах равно 1. В первой команде оно явно указано в списке полей (наличие имени однобитового поля в списке влечет заполнение его кодом 1). В остальных командах оно заполнится “1” по умолчанию.

Если бы нам требовалось при умолчании полагать CI = 0, то следовало бы изменить начальное значение этого поля с помощью инструкции value:

  CI:VALUE 0;

3.1. Управление печатью листинга

Карта *nо list , встретившаяся в любом месте текста программы, отключает печать листинга. Карта *full list , встретившаяся в любом месте текста программы, включает печать листинга. Ошибочные карты распечатываются безусловно.

Листинг программы печатается строками шириной 128 позиций. Строка соответствует одной инструкции микроассемблера. Формат строки:

Аааа  ннн....н   llllll:кккк....к

Если инструкция не умещается в 128 позиций, производится перенос в следующую строку листинга, причем поля а-l печатаются пустыми. Перенос производится на границе элементов списка полей микрокоманды.

При ошибках в программе ошибочный фрагмент отмечается символом “*” в следующей строке листинга. В большинстве случаев мест0нахождение ошибки отмечается с точностью до символа, в крайнем случае - с точностью до лексемы.

3.2. Диагностика

После текста подпрограммы в листинге печатается таблица использования меток и внешних имен. Для каждого имени выдается список относительных адресов программы, где используется это имя. В начале списка находится относительный адрес метки в программе или символ “е” (для внешних программ).

3.3. Семантический контроль микрокоманд

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

            Flist <имя поля>=<список>

например, правило: flist тур=тур1,тур2,тур7 означает, что в выражение, задающее значение поля тур , могут входить термы тур1, тур2, тур7 и только они. Если в какой-то микрокоманде встретится фрагмент тур=тур4 , то это будет считаться ошибкой. Если список не умещается во входной строке, оставьте там последнюю уместившуюся запятую, и продолжайте список с новой строки. Ограничение на количество правил “flist”: суммарная длина всех списков - не более 1500.

            Снеск field1+field2-field3

этот пример следует читать так: если заданы значения (неважно, какие) полей field1 и field2, но не задано field3, то такая комбинация полей в микрокоманде - ошибочна. Всего правил “снеск” может быть не более 200, в каждом правиле - не более 6 членов.

Диагностика “семантическая ошибка” снабжается номером нарушенного семантического правила. Кроме того, символ “*” отмечает позицию сканера входной строки в момент последнего нарушения правила.

3.4. Макросы

Часто повторяющиеся фрагменты микрокоманд можно описать единожды в виде макроопределения. Макроопределения размещаются во входном файле среди семантических правил (относительный порядок - несуществен) до начала первой транслируемой программы. Макроопределение занимает ровно одну строку и выглядит так:

Macro <имя> <заменяющий текст>

имя макроса не более чем из 6 символов. В заменяющем тексте все символы существенны, кроме хвостовых пробелов. Отсюда следует возможность пустых макросов, когда в заменяющем тексте нет ни одного символа, отличного от пробела. Макровызов осуществляется указанием в нужном месте текста микрокоманды имени макроса, обрамленного символом “%”. Пример:

   макроопределение:   macro м1 f1=с1,f2=с2,f3=1
   макровызов:         cont f5=5,%м1%,f7
   окончательный итог: cont f5=5,f1=с1,f2=с2,f3=1,f7

Всего может быть до 400 макросов. Суммарный обьем заменяющих текстов - до 24000 символов. Повторное определение макроса не контролируется.

3.5. Псевдокомментарий

В системе предусмотрена возможность подготовки карты памяти микропрограмм (например, для прожига в ПЗУ списка входных точек программы). Это делается с помощью псевдокомментария

;prom:<список индексов>

         например:

;prom:n1,n2-n3,n4-n5,n6

Здесь список шестнадцатиричных чисел задает отдельные индексы или диапазоны индексов в так называемом переключателе начальных адресов (ПНА). В соответствующие строки ПНА загрузчик занесет абсолютный адрес микрокоманды, следующей в тексте программы за псевдокомментарием ;prom:…

Повторное использование одного и того же индекса в ПНА контролируется загрузчиком. Индексы задаются в диапазоне от 0 до ffff.

4. Архив кросс-системы

Архив всегда заказывается в пакете задачи под логическим номером 30 и в режиме записи. С точки зрения системы архив представляет из себя виртуальную память прямого доступа. Каждое слово этой памяти адресуется своим целочисленным адресом = 0,1,2

Распределение виртуальной памяти:

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

Таким образом, таблица имен является одновременно и каталогом библиотеки модулей загрузки. В описании подпрограммы хранится виртуальный адрес начала ее модуля загрузки в библиотеке и размеры модуля загрузки. Модуль состоит из двух частей:

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

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

Свободная память в архиве используется системой как рабочая область. В частности, ассемблер использует ее для хранения текста транслируемой программы (схема трансляции - двухпроходная). Каталог архива может быть распечатан по директиве

                   *call miccat
             или   *call miccat:rом

В последнем случае выдается еще и содержимое п з у констант. Исключение программы из архива делается с помощью директивы

                   *call delete:<имя программы>

5. Получение двоичной программы

Для получения двоичной программы используется связывающий загрузчик. Пакет задачи в этом случае выглядит следующим образом:

          *nаме .....
          *pass:.....
          *time:.....
          *library:23,25
           <заказ архива под номером 30>
          *call micloa:<имя головной программы> [=а]
          *end file

Разумеется, вызвать загрузчик можно и сразу же по окончании трансляции текста программы.

Загрузка начинается с заданного шестнадцатиричного адреса А. При неуказании полагается А = 0. Двоичный образ загруженной программы помещается в свободную область архива кросс-системы. Оттуда он может быть выведен, например, на перфоленту. В настоящее время загрузчик, закончив свою работу, просто распечатывает получаемый код в шестнадцатиричном виде.

Таблица загрузки печатается в таком же виде, что и таблица загрузки в мониторной системе “дубна”. И точно также, в списке загрузки могут печататься диагностические сообщения:

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

В нашем варианте загрузчика используется только младшая цифра характеристики. Она уточняет начальный адрес загружаемой программы:

Список загрузки формируется в common-блоке

common /linf1/ ь(9),list(3,1000)

1-имя программы, 2-ее характеристика, 3-адрес.

Для связи с системой моделирования ПУЛЬС имеется второй вход в загрузчик:

*call impuls:nр,nа,nо

Еще один вход в загрузчик сделан для передачи готовой программы в пультовой процессор МКБ-8601 (пока это iвм рс/хт в к.227):

*call mpsend:<имя головной программы> [=а]

Как уже было сказано выше, результат сборки микропрограммы записывается загрузчиком в свободную область архива кросс-системы ( ее адрес в 5-м слове архива ). Собранная программа предваряется переключателем нач. Адресов ( П Н А ), длиной 16400 слов, сформированным согласно псевдокомментарию ;prom: (см.3.5).

ПНА можно вывести из архива по карте

*CALL MICPNA:N,ТУР

Где N - номер ПНА = 0,1,2,…,8

    ТУР = high  или  low  - определяет, какой байт
          выводить: старший (high) или младший (low).