Newer
Older
* УМ-П (с переменным форматом команд)
* УМ-1 (одноадресная)
* УМ-С (стековая)
* УМ-Р (решистровая)
* УМ с модификацией адресов ???
* Работа с плавающей запятой
* Добавить howto install and use
* Переделать документацию модулей
## Модельная машина
Модельная машина - это чистая архитектурная концепция, позволяющая понять
логику функционирования центральных процессоров. По своей структуре она близка
к компьютерам первого поколения. Подробнее читайте по ссылкам внизу.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
## Quickstart
Установка пакета происходит командой:
# python3 -m pip install --upgrade modelmachine
После этого вам станет доступна консольная команда `modelmachine`.
Для проверки сделайте `modelmachine test`. Будет выполнена серия тестов,
все тесты должны закончиться успехом.
Посмотрите примеры в папке <samples>, по их образу можно начинать писать
программы для модельных машин. Запуск программы делается командой:
$ modelmachine run program.mmach
### Пример
bordachenkova_mm3
[config]
input = 0x100,0x101
output = 0x103
[code]
; x = ((a * -21) % 50 - b) ** 2 == 178929
03 0100 0005 0103 ; x := a * -21
04 0103 0006 0102 ; [0102] := x / 50, x := x % 50
02 0103 0101 0103 ; x := x - b
03 0103 0103 0103 ; x := x * x
99 0000 0000 0000 ; halt
; ---------------------
FFFFFFFFFFFFEB ; -21
00000000000032 ; 50
[input]
-123 456
* Первая строчка - обязательное название архитектуры. Список поддерживаемых
архитектур смотри ниже.
* После этого должна идти секция `config`, описывающая ячейки памяти,
по которым нужно производить ввод и вывод.
* После этого секция кода, содержащая набор 16-ричных чисел, записываемых в
память модельной машины. Пропускать часть машинного слова нельзя.
Рекомендуется писать по одному машинному слову в строке, по желанию
разбивая разряды на части пробелами.
* Все, что идет после символа `;` - комментарий.
* Пустые строки игнорируются.
* После этого идет секция ввода - несколько чисел, разделенных пробельными
символами. Их число должно совпадать с числом ячеек для ввода в параметре
`input` в секции `config`.
* По окончании работы на экран будут напечатаны десятичные числа со знаком,
лежащие в ячейках, перечисленных в параметре `output` в секции `config`.
## Внутреннее устройство
Данная реализация модельной машины состоит из классов, разбитых на
файлы-модули:
* `memory.py` - память; делится на два класса: `регистровая` и
`оперативная`; оперативная делится на `little-endian` и `big-endian`
* `numeric.py` - целочисленная арифметика с фиксированным числом
двоичных знаков
* `alu.py` - арифметико-логическое устройство, работает с четко
специализированными регистрами: `R1`, `R2`, `S`, `FLAGS` и `IP`.
* `cu.py` *в процессе реализации* - контролирующее устройство, выполняющее
считывание команд из памяти и запускающее необходимые методы в
арифметико-логическом устройстве
* `io.py` - устройство ввода-вывода
* `cpu.py` - финальное объединение составляющих устройств в единое целое
Здесь дано поверхностное описание модулей. За более подробным
### memory.py
`AbstractMemory` - класс абстрактной памяти, предоставляющий интерфейс для
надежной связи частей компьютера. Основные методы: `fetch` и `put`, которые
принимают на вход адрес в памяти и количество битов, с которыми нужно работать,
количество должно быть кратно размеру ячейки (слова). Строго
`RandomAccessMemory` - класс, реализующий память прямого доступа. При
инициализации указывается размер машинного слова и количество этих слов. Если
`is_protected=True`, то при попытке считывания из неинициализированной ячейки
будет выброшено исключение, иначе, метод `fetch` вернет нуль.
`RegisterMemory` - класс, реализующий регистровую память. Метод `add_register`
добавляет регистр определенного размера или проверяет, что уже добавленный
регистр имеет правильный размер.
### numeric.py
Класс Integer реализует целочисленную арифметику фиксированной длины.
Поддерживаемые операторы: `+`, `-`, `*`, `/`, `%`, `==`, `!=`. Плюс методы
`get_value` и `get_data`. Округление при делении производится в сторону нуля.
### alu.py
Арифметико-логическое устройство работает с четко специализированными
регистрами:
* `R1`, `R2`, `S` для арифметических операций.
* `FLAGS` для хранения флагов состояния.
* `IP` *только* для пересылки туда адреса из регистра `R1` при условных
переходах.
* Арифметические команды: `add`, `sub`, `smul`, `sdiv`, `umul`, `udiv`,
`sdivmod`, `udivmod`. За исключением команд `divmod` арифметические
команды работают следующим образом: `S := R1 op R2`.
Плюс в зависимости от результата выставляется регистр `FLAGS` - комбинация
флагов CF, OF, SF и ZF.
* `add` и `sub` - сложение и вычитание соответсвенно.
* `smul` и `sdiv` - знаковое умножение и деление соответсвенно.
* `umul` и `udiv` - беззнаковое умножение и деление соответсвенно.
* `sdivmod` и `udivmod` - знаковое и беззнаковое соответственно деление с
остатком. `S := R1 / R2; R1 := R1 % R2`.
* Команда пересылки `move`: `S := R1`.
* Команды безусловного перехода `jump` и условного перехода `cond_jump`
работают по схеме `IP := R1`, режим работы `cond_jump` зависит от того,
какие дополнительные аргументы будут переданы.
* Команда останова `halt` просто выставляет флаг остановки HALT в
регистре флагов
### cu.py
Управляющее устройство.
#### AbstractControlUnit
Обычно управляющее устройство работает по схеме:
1. `fetch_and_decode` - загрузка и расшифровка очередной команды.
в регистре `IP` загружается в регистр `IR`, затем из него извлекается
код операции и адреса операндов, затем счетчик `IP` увеличивается на
длину только что считанной команды.
2. `load` - данные по только что считанным адресам загружаются в регистры
процессора `R1` и `R2`
3. `execute` - в зависимости от кода операции в арифметико-логическом
устройстве запускается та или иная схема вычислений.
4. `write_back` - результат вычислений записывается куда полагается (например,
Все эти методы поддерживаются в `AbstractControlUnit`.
Также в нем написаны использующие их методы, являющиеся интерфейсом
устройства управления:
* `step` - сделать один шаг, описанный алгоритмом выше.
* `get_status` - вернуть статус процессора (выполняется/остановлен).
Остановка производится командой останова `halt`.
* `run` - выполнять один шаг за другим, пока процессор не будет остановлен.
Далее, наследники `AbstractControlUnit` определяют первые 4 метода.
### io.py
Устройство ввода-вывода.
* При инициализации устанавливается адрес с которого нужно загружать
программы пользователя.
* Метод `load_source` загружает последовательность шеснадцатиричных слов
по указанному адресу.
* Метод `load_data` загружает данные (полученные из строки чисел)
по данным адресам.
* Методы `get_int` и `put_int` работают с содержимым одного слова.
Размер слова устанавливается при инициализации.
### cpu.py
Финальная сборка всех составных устройств в единое целое.
* Поддерживается доступ к составным устройствам. Например, доступ
к устройству ввода/вывода можно получить через `cpu.io_unit`,
к регистрам через `cpu.registers` и так далее.
* `load_program` - загрузка программы, конфигурации и данных в оперативную
память.
* `print_result` - печать результата работы программы.
* `run_file` - загрузка, исполнение и печать результата.
## Поддерживаемые архитектуры
### Как добавить новую архитектуру?
1. Выписать все команды устройстройства и их коды.
2. Добавить их в таблицу ниже и описание еще ниже.
3. Добавить новый класс устройства управления на основе существующего.
4. Добавить новый класс CPU использующий это устройство управления,
добавить этот класс в список `CPU_LIST` в файле `cpu.py`.
5. Добавить тесты для обоих этих классов в файлы `tests/test_cu.py` и
`tests/test_cpu.py`.
6. Добавить примеры в папку `samples`.
7. Прислать pull request.
### Таблица команд модельных машин
|OPCODE|mm-3|mm-2|mm-v|
|:-----|:--:|:--:|:--:|
|0x00 |move|move|move|
|0x01 |add |add |add |
|0x02 |sub |sub |sub |
|0x03 |smul|smul|smul|
|0x04 |sdiv|sdiv|sdiv|
|0x05 | |comp|comp|
|0x13 |umul|umul|umul|
|0x14 |udiv|udiv|udiv|
|0x80 |jump|jump|jump|
|0x81 | == | == | == |
|0x82 | != | != | != |
|0x83 |< s|< s|< s|
|0x84 |>= s|>= s|>= s|
|0x85 |<= s|<= s|<= s|
|0x86 |> s|> s|> s|
|0x93 |< u|< u|< u|
|0x94 |>= u|>= u|>= u|
|0x95 |<= u|<= u|<= u|
|0x96 |> u|> u|> u|
|0x99 |halt|halt|halt|
Знаки сравнения в таблице означают команды условного перехода. Как они
работают читайте в книге *[1]* и ниже по тексту.
|Мнемонический код|Обозначение выше|Расшифровка/описание |
|:----------------|:--------------:|:--------------------------------|
|JEQ | == |jump if equal |
|JNEQ | != |jump if not equal |
|SJL | < s |signed jump if less |
|SJGEQ | >= s |signed jump if greater or equal |
|SJLEQ | <= s |signed jump if less or equal |
|SJG | > s |signed jump if greater |
|UJL | < u |unsigned jump if less |
|UJGEQ | >= u |unsigned jump if greater or equal|
|UJLEQ | <= u |unsigned jump if less or equal |
|UJG | > u |unsigned jump if greater |
* Размер ячейки оперативной памяти: 7 байт.
* Размер адреса: 2 байта.
* Арифметические вычисления производятся с одной ячейкой оперативной памяти.
* Код команды помещается в одну ячейку оперативной памяти `КОП А1 А2 А3`.
Действия процессора для арифметических инструкций (`add`, `sub`,
`smul`, `sdiv`, `umul`, `udiv`) `КОП A1 A2 A3`:
1. Загрузить содержимое ячейки оперативной памяти с адресом `А1` в
2. Загрузить содержимое ячейки оперативной памяти с адресом `А2` в
3. Запустить в АЛУ схему, реализующую операцию, задаваемую `КОП`.
4. Записать результат из регистра `S` в ячейку оперативной памяти с
адресом `А3`.
Если выполняется операция деления, в оперативную память записываются
два результата: частное – в ячейку с адресом `А3`, остаток – в следующую
ячейку, по адресу `(А3+1) mod 16^4`.
* Условные переходы: сравниваются `R1` и `R2`, в зависимости от результата
происходит `IP := A3`.
* Команда пересылки `move`: [A3] := R1.
* Размер ячейки оперативной памяти: 5 байт.
* Размер адреса: 2 байта.
* Арифметические вычисления производятся с одной ячейкой оперативной памяти.
* Код команды помещается в одну ячейку оперативной памяти `КОП А1 А2`.
Действия для арифметических команд `add`, `sub`, `smul`, `sdiv`, `umul`,
`udiv`:
2. Запустить в АЛУ схему `sub` (в том числе выставить регистр `FLAGS`)
* `jump A1 A2`: `IP := A2`
* `move A1 A2`: `[A1] := [A2]`
* Команда останова `halt` взводит флаг `HALT` в регистре `FLAGS`
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
### bordachenkova_mmv
* Размер ячейки оперативной памяти: 1 байт.
* Размер адреса: 2 байта.
* Арифметические вычисления производятся со словами в 5 ячеек оперативной
памяти.
* Код команды занимает разное количество ячеек в зависимости от выполняемой
операции.
Таблица кодов команд:
|Код команды|Мнемоник|Формат |Длина (в байтах)|
|:----------|:------:|:---------|---------------:|
|0x00 |move |move A1 A2| 5|
|0x01 |add |add A1 A2| 5|
|0x02 |sub |sub A1 A2| 5|
|0x03 |smul |smul A1 A2| 5|
|0x04 |sdiv |sdiv A1 A2| 5|
|0x05 |comp |comp A1 A2| 5|
|0x13 |umul |umul A1 A2| 5|
|0x14 |udiv |udiv A1 A2| 5|
|0x80 |jump |jump A1 | 3|
|0x81 |jeq |jeq A1 | 3|
|0x82 |jneq |jneq A1 | 3|
|0x83 |sjl |sjl A1 | 3|
|0x84 |sjgeq |sjgeq A1 | 3|
|0x85 |sjleq |sjleq A1 | 3|
|0x86 |sjg |sjg A1 | 3|
|0x93 |ujl |ujl A1 | 3|
|0x94 |ujgeq |ujgeq A1 | 3|
|0x95 |ujleq |ujleq A1 | 3|
|0x96 |ujg |ujg A1 | 3|
|0x99 |halt |halt | 1|
Действия для арифметических команд `add`, `sub`, `smul`, `sdiv`, `umul`,
`udiv`:
1. `R1 := [A1], R2 := [A2]`
2. Запустить в АЛУ схему, реализующую операцию, задаваемую `КОП`.
3. `[A1] := S`
Действия для команды сравнения `cmp`:
1. `R1 := [A1], R2 := [A2]`
2. Запустить в АЛУ схему `sub` (в том числе выставить регистр `FLAGS`)
* `jump A1`: `IP := A1`
* Условные переходы делаются исходя из регистра `FLAGS`
* `move A1 A2`: `[A1] := [A2]`
* Команда останова `halt` взводит флаг `HALT` в регистре `FLAGS`
1. E. А. Бордаченкова - "Модельные ЭВМ" <http://al.cs.msu.su/files/ModComp.pdf>
2. Е. А. Бордаченкова - "Архитектура ЭВМ. Учебные машины. Методическое пособие"
<http://al.cs.msu.su/files/bordachenkova.architecture.model.machines.2010.doc>
3. В. Г. Баула - "Введение в архитектуру ЭВМ и системы программирования"
<http://arch.cs.msu.ru/Page2.htm>
4. <http://cmcmsu.no-ip.info/1course/um3.command.set.htm>