Данная реализация модельной машины состоит из классов, разбитых на файлы-модули:
memory.py- память; делится на два класса:регистроваяиоперативная; оперативная делится наlittle-endianиbig-endiancell.py- целочисленная арифметика с фиксированным числом двоичных знаковalu.py- арифметико-логическое устройство, работает с четко специализированными регистрами:R1,R2,S,FLAGSиPC.cu.py- контролирующее устройство, выполняющее считывание команд из памяти и запускающее необходимые методы в арифметико-логическом устройствеio.py- устройство ввода-выводаcpu.py- финальное объединение составляющих устройств в единое целоеasm.py- ассемблер для машины с модификацией адресов
Здесь дано поверхностное описание модулей. За более подробным обращайтесь к документации конкретных модулей и их исходным кодам.
memory.py
AbstractMemory - класс абстрактной памяти, предоставляющий интерфейс для
надежной связи частей компьютера. Основные методы: fetch и put, которые
принимают на вход адрес в памяти и количество битов, с которыми нужно работать,
количество должно быть кратно размеру ячейки (слова). Строго
рекомендуется их использовать везде.
RandomAccessMemory - класс, реализующий память прямого доступа. При
инициализации указывается размер машинного слова и количество этих слов. Если
is_protected=True, то при попытке считывания из неинициализированной ячейки
будет выброшено исключение, иначе, метод fetch вернет нуль.
RegisterMemory - класс, реализующий регистровую память. Метод add_register
добавляет регистр определенного размера или проверяет, что уже добавленный
регистр имеет правильный размер.
cell.py
Класс Cell реализует целочисленную арифметику фиксированной длины.
Поддерживаемые операторы: +, -, *, /, %, ==. Плюс методы
signed и unsigned. Округление при делении производится в сторону нуля.
alu.py
Арифметико-логическое устройство работает с четко специализированными регистрами:
R1,R2,Sдля арифметических операций.FLAGSдля хранения флагов состояния.PCтолько для пересылки туда адреса из регистра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работают по схемеPC := R1, режим работыcond_jumpзависит от того, какие дополнительные аргументы будут переданы. - Команда останова
haltпросто выставляет флаг остановки HALT в регистре флагов
cu.py
Управляющее устройство.
AbstractControlUnit
Обычно управляющее устройство работает по схеме:
fetch_and_decode- загрузка и расшифровка очередной команды. Содержимое ячейки оперативной памяти с адресом записанным в регистреPCзагружается в регистрRI, затем из него извлекается код операции и адреса операндов, затем счетчикPCувеличивается на длину только что считанной команды.load- данные по только что считанным адресам загружаются в регистры процессораR1иR2execute- в зависимости от кода операции в арифметико-логическом устройстве запускается та или иная схема вычислений.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- загрузка, исполнение и печать результата.
Поддерживаемые архитектуры
Как добавить новую архитектуру?
- Выписать все команды устройстройства и их коды.
- Добавить их в таблицу в README и описание там же.
- Добавить новый класс устройства управления по аналогии с существующим.
- Добавить новый класс CPU использующий это устройство управления,
добавить этот класс в список
CPU_LISTв файлеcpu.py. - Добавить тесты для обоих этих классов в файлы
tests/test_cu.pyиtests/test_cpu.py. - Добавить примеры в папку
samples. - Прислать pull request.