- Барсуков Максим Андреевич, P3215
- Вариант:
alg -> asm | stack | harv | hw | tick -> instr | struct | stream | port | pstr | prob2 | cache - Упрощённый вариант:
asm | stack | harv | hw | instr | struct | stream | port | pstr | prob2
Расширенная форма Бэкуса —Наура:
<program> ::= <section_data> <section_text> | <section_text> <section_data> | <section_text>
<section_data> ::= ".data\n" <declaration>*
<section_text> ::= ".text\n" (<label_def> | <instruction> | <label_def> <instruction>)*
<declaration> ::= <label_def> (<array> | <reserve>)
<instruction> ::= <label_arg_command> | <number_arg_command> | <without_arg_command>
<label_def> ::= (<name> ":" (" ")*) | (<name> ":" (" ")* "\n")
<array> ::= (<array_element> "," (" ")*)* <array_element>+
<reserve> ::= "res" (" ")+ <number>
<array_element> ::= ("\"" <any_ascii> "\"" | <number>)
<label_arg_command> ::= ("push" | "jump" | "jz" | "jnz" | "js" | "jns" | "call") (" ")+ <name>
<number_arg_command> ::= ("push" | "input" | "output") (" ")+ <number>
<without_arg_command> ::= ("nop" | "halt" | "add" | "sub" | "mul" | "div" | "mod"
| "cmp" | "and" | "or" | "xor" | "inc" | "dec" | "neg" | "not" | "ret" | "pop"
| "swap" | "dup" | "over" | "over3" | "load" | "store" | "debug")
<number> ::= [-2^31; 2^31 - 1]
<name> ::= (<letter_or_>)+
<letter_or_> ::= <letter> | ("_")
<letter> ::= [a-z] | [A-Z].text-- секция, в которой все последующие слова (до конца файла или объявления.data) интерпретируются, как инструкции или их аргументы или комментарии или метки;.data-- секция, в которой все последующие слова (до конца файла или объявления.data) интерпретируются как инициализация или резервация сегментов памяти для пользовательских данных;label-- метка, которая является указателем на адрес памяти инструкции за ней (если метка в section.text) или является указателем на первый элемент зарезервированого сегмента памяти (если метка в section.data);res n-- оператор, который может писаться после объявления метки в секции данных, обозначающий, что необходимо зарезервироватьnслов памяти под эту метку;push n-- кладет значениеnна вершину стэка. Еслиn- метка, то кладет адрес, который она описывает, еслиn- число, то кладет само значениеn. ВАЖНО: так как у меня гарвардская архитектура,push labelя могу выполнять только для label из Data Memory;pop-- удаляет верхний элемент со стэка;jump label-- команда безусловного перехода. Устанавливает следующую команду, как ту, на которую указывает label - из Program Memory;jz label-- если на вершине стэка 0, то выполняетjump, иначе переход к следующей команде;jnz label-- если на вершине стэка не 0, то выполняетjump, иначе переход к следующей команде;js label-- если на вершине стэка отрицательное число, то выполняетjump, иначе переход к следующей команде;jns label-- если на вершине стэка не отрицательное число, то выполняетjump, иначе переход к следующей команде;call label-- сохраняет на стэке вызывов адрес следующей команды и переходит к выполнению инструкции за label;ret-- устанавливает следующую команду, как ту, что лежит на верху стэка вызовов и удаляет элемент с верхушки стэка вызовов;input n-- считывает один символ из порта n и записывает его на верх стэка;output n-- записывает в порт n значение из верхушки стэка;halt-- завершение программы;add-- складывает значение на вершине стэка и значение следующее после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;sub-- вычитает значение на вершине стэка и значение следующее после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;mul-- перемножает значение на вершине стэка и значение следующее после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;div-- делит значение на вершине стэка и значение следующее после вершины стэка нацело, результат помещает на вершину стэка, операнды убираются со стэка;mod-- берёт остаток от деления значения на вершине стэка на значение следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;cmp-- вычитает значение на вершине стэка и значение следующее после вершины стэка, результат помещает на вершину стэка, операнды НЕ убираются со стэка;and-- битовое И значения на вершине стэка и значения следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;or-- битовое ИЛИ значения на вершине стэка и значения следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;xor-- битовое исключающее ИЛИ значения на вершине стэка и значения следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;not-- битовое НЕ значения на вершине стэка;swap-- меняет местами значение на вершине стэка и значение следующее после вершины стэка;dup-- кладёт на вершину стэка значение с вершине стэка;over-- кладёт на вершину стэка значение следующее после вершины стэка;over3-- кладёт на вершину стэка значение следующее после значения, следующего после вершины стэка;inc-- увеличивает значение верхушки стэка на 1;dec-- уменьшает значение верхушки стэка на 1;neg-- устанавливает значение верхушки стэка на отрицательное (* (-1));load-- интерпретирует значение на вершине стэка, как адрес по которому из памяти загружает значение на вершину стэка.store-- интерпретирует значение следующее после вершины стэка, как адрес по которому нужно записать значение на вершине стэка.debug-- команда отладки. Вывод в устройство ввода-вывода 1 отладочную информацию о текущем значении процессора и останавливает программу до нажатия пользователем любой клавиши.nop-- пустая команда. Совершается тик, переходят к следующей инструкции.
Начинаются со знака ; и идут до конца строки.
-
В программе не может быть дублирующихся меток.
-
Метка памяти данных задается на той же строке, что и данные:
hello_world: "Hello, world!"-
Так как строки Pascal-string, компилятор сам упаковывает их во время компиляции (ставит первым словом строки длину строки).
-
Метка памяти команд задается на строке предшествующей инструкции, на которую указывает метка, либо на той же самой строке:
foo:
push 10
...
bar: nop
...
Программа выполняется последовательно, одна инструкция за другой.
- Распределяется статически на этапе трансляции
- Строковые литералы помещаются в память в начале работы программы в формате Pascal-string.
- Под динамически считываемые строки пользователь сам определяет, как будет считываться строка. Он может выделить некоторый буфер через
res n, или расположить строку в конце памяти и считывать сколько необходимо (или пока хватает памяти).
В любом месте секции .text доступен стэк и операции над его верхними значениями. Видимость меток глобальная.
Литералы могут быть представлены в виде чисел и меток (в последствии интерпретируются как числа), в секции .data можно объявлять строки. Типизация отсутсвует, так как пользователь языка может интерпретировать любые данные как захочет и может с ними выполнить любые из возможных операций.
- Гарвардская архитектура
- Резмер машинного слова:
- Память данных - 32 бит;
- Память команд - 32 бит.
- Имеет линейное адресное пространство.
- В памяти данных хранятся статические строки и переменных
- В памяти команд хранятся инструкции для выполнения
- Взаимодействие с памятью данных происходит при помощи инструкций
loadиstore. - Адресации:
- Прямая абсолютная (например,
push label) - Косвенная (у команд
load,storeодин из операндов является указателем на ячейку памяти)
- Прямая абсолютная (например,
Program memory
+------------------------------+
| 00 : jump n |
| ... |
| n : _start: instruction1 |
| ... |
+------------------------------+
Data memory
+------------------------------+
| 00 : array 1 |
| ... |
| n : array 2 |
| ... |
+------------------------------+
- Для работы с регистрами отведена память, организованная в виде стека. Программист напрямую имеет доступ к
TOS, верхушкеStack Registers, заранее инициализированной памяти вData Memory, а также, используя различные условные и безусловный переходы, может изменятьPC; - Память данных разделена на массивы - разделение определяет пользователь, именуя каждый массив лейблом;
- Массив может состоять из строк, чисел и свободного места (заполнено нулями), зарезервированного на определенное количество байт. Все данные в массивах и все массивы идут последовательно;
- Инструкции хранятся в
Program Memory; - Для операндов пользователю отводится 24 бита, т.к. предполагается, что оставшиеся 8 бит будет занимать информация о инструкции (например опкод);
- Используя команду
push numberлитерал используется при помощи непосредственной адресации; - Используя команду
storeлитерал будет загружен в статическую память;
- Имеются стек данных и стек возвратов.
- Оба поддерживают операции
pushиpop - Стек данных поддерживает операции
dupиswap, а также чтение из второй от вершины ячейки (предполагается реализация на уровне схемотехники).
Регистры:
- PC - счетчик команд
- AR - регистр адреса
Особенности процессора:
- Машинное слово -- знаковое 32-ух битное число;
- Доступ памяти осуществляется через указатель на вершине
Stack Register. Установить можно при помощиpush label; - Устройство ввода-вывод: port-mapped
- Поток управления:
- Инкрементирование
PC; - Условный/безусловный переход;
- Адрес из вершины
Call Stack.
- Инкрементирование
| Команда | Число тактов | Стек ДО | Стек ПОСЛЕ | Описание | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| PUSH [value] | 1 |
|
|
пушит на вершину стека свой аргумент, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| PUSH [label] | 1 |
|
|
пушит на вершину стека свой адрес своего аргумента, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| LOAD | 2 |
|
|
загружает значение из памяти, адрес берется из вершины стека, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| STORE | 2 |
|
|
сохраняет значение из вершины стека, адрес берется из второй ячейки | ||||||||
| POP | 1 |
|
|
удаляет вершину стека, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| ADD SUB MUL DIV MOD AND OR XOR MOD MOD MOD |
1 |
|
|
выполняет арифметическую операцию, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| CMP | 1 |
|
|
выполняет a - b, сохраняет операнды, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| INC DEC |
1 |
|
|
выполняет инкремент или декремент, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| INPUT [port] | 1 |
|
|
читает из устройства ввода-вывода с порта один символ, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| OUTPUT [port] | 1 |
|
|
записывает вершину стека в порт | ||||||||
| DUP | 1 |
|
|
дублирует значение с вершины стека | ||||||||
| SWAP | 1 |
|
|
меняет местами верхние 2 значения в стеке, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| OVER | 1 |
|
|
кладёт на вершину стэка значение следующее после вершины стэка, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| OVER3 | 1 |
|
|
кладёт на вершину стэка значение второе после вершины стэка, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
| JUMP [addr] JZ [addr] JNZ [addr] JS [addr] JNS [addr] |
1 | - | - | прыжок на инструкцию на основании выставленных флагов. JUMP - безусловный, JZ - прыжок, если ноль, JNZ - прыжок, если не ноль, JS/JNS - прыжок, если отрицательное/не отрицательное |
||||||||
| CALL [addr] | 1 | - | - | вызов функции по адресу addr | ||||||||
| RET | 1 | - | - | возврат из функции | ||||||||
| DEBUG | 1 | - | - | вывод отладочной информации на устройство на порту 1, остановка программы до действий пользователя | ||||||||
| NOP | 1 | - | - | пустая инструкция | ||||||||
| HALT | 1 | - | - | остановить выполнение |
Инструкции представлены в формате JSON:
{
"opcode": "jump",
"operand": 123,
"address": 10
}где:
opcode- код операции (Opcode - тип данных, определенный в isa)operand- аргумент инструкцииaddress- указывает адрес инструкции в памяти инструкций.
Реализация транслятора: translator
Интерфейс командной строки:
- Получить справку:
poetry run translator --help
usage: translator [-h] source_file target_instrs_file target_data_file
CSA Lab 3 translator.
positional arguments:
source_file File with asm code
target_instrs_file File to write instructions after compilation
target_data_file File to write data after compilation
options:
-h, --help show this help message and exit
poetry run translator [-h] <source_file> <target_instrs_file> <target_data_file>
- Первый аргумент - путь до файла с исходным кодом,
- второй аргумент - путь до файла, куда будут записаны инструкции, сохраненные в
json. - третий аргумент - путь до файла, куда будут записаны массивы данных, инициализированные в пользовательской программе, сохраненные в
json.
Трансляция секции .data:
- Реализована в
get_data; - Сначала определяется место в коде, где объявлена секция
.data; - Потом лейбл отделяется от данных;
- В
get_codes_from_dataданные преобразуются в последовательность чисел:- Функция
str2list_intвозвращает массив, в котором строка представляется как массив байт, на позициях одиночных чисел и резервирования - пустые массивы; - Функция
get_integersудалят из данных строки, возвращает массив одиночных чисел и резервированной памяти; - Далее на пустые места вставляются одиночные числа и массивы резервирования;
- В конце все данные выпрямляются в один итоговый массив.
- Функция
Трансляция секции .text:
translate_without_operands: инструкции разбиваются на токены, запоминаются номера меток. Возвращается высокоуровневая структура, описывающая инструкции;translate_operands: в джампы подставляются номера инструкций в зависимости от лейбла, вpush labelзаменяются метки на адреса в памяти, проверяются ограничения на аргументы;- Код из высокоурвневой структуры переводится в бинарный вид в функции
write_code, определенной вisa
Правила:
- Не более одного определения секций
.dataи.text - Одиночные числа, объявленные в
.dataдолжны принимать значения [-2^31; 2^31 - 1]; - Метка в секции
.dataзадается на той же строке, что и данные. Данные задаются на одной строке; - Метка в секции
.textзадается перед инструкцией, на которую он указывает; - Обязательна метка
_start;
Реализация модели процессора: machne
Интерфейс командной строки:
- Получить справку:
poetry run machine --help
usage: machine [-h] [--log_level {FATAL,ERROR,WARN,INFO,DEBUG,NOTSET,}] [--output_ports {1,2,1;2}] instructions_file data_file input_file
CSA Lab 3 machine runner.
positional arguments:
instructions_file File with instructions
data_file File with data
input_file File with user input
options:
-h, --help show this help message and exit
--log_level {FATAL,ERROR,WARN,INFO,DEBUG,NOTSET}
Log level
--output_ports {1,2,1;2}
IO ports to print output
- Первый аргумент - путь до файла с инструкциями,
- Второй аргумент - путь до файла с данными.
- Третий аргумент - путь до файла, откуда берется ввод пользователя.
- Опция
--log_level- позволяет установить уровень логирования. - Опция
--output_ports- позволяет выбрать, с каких устройств ввода-вывода по портам данные будут также выводиться в терминал при запуске.
Разработаны IOController, который на основании порта [0-15] использует устройство ввода-вывода. Сделано несколько устройств ввода-вывода (реализация в io.py):
IO0: ввод данных посимвольно из stdin (реализация через файл<input_file>). Если данные закончились, отдает EOF (-1). Использование:INPUT 0IO1: вывод ячейки в stdout как символа (для значения 97 выведетa). Использование:OUTPUT 1IO2: вывод ячейки в stdout как числа (для значения 97 выведет97). Использование:OUTPUT 1IO8: ввод данных из бесконечного потока символов'1', ..., '9', '0', '1', .... Читает по одному символу из этого потока. Использование:INPUT 8
Реализован в data_path
Сигналы (обрабатываются за один такт, реализованы в виде методов класса)
latch_data_addr- защёлкнуть значение в data_addrlatch_tos- защёлкнуть вершину стекаstore/load- сигналы записи / чтения памяти данныхoperation- сигнал, определяющий операцию алуread/write/port- сигналы чтения / записи / порта устройства ввода вывода
Флаги:
Z- zero - отражает нулевое значение в вершине стекаN- negative - отражает отрицательное значение в вершине стека
Реализован в control_unit
- hardwired - внутренняя логика дешифратора инструкций скрыта. В данной модели реализована на Python.
- Метод
decode_and_execute_instructionмоделирует выполнение полного цикла инструкции. _tick- имитирует работу счетчика тактов.
Сигналы:
latch_pc- защелкнуть значение в program_counterread- чтение из памяти инструкций
Особенности работы модели:
- Цикл симуляции осуществляется в функции
simulation. - Шаг моделирования соответствует одной инструкции с выводом состояния в журнал.
- Для журнала состояний процессора используется стандартный модуль
logging. - Остановка модели осуществляется при следующих условиях:
- достижение инструкции halt;
- переполнение стека или чтение из пустого стека;
- отсутствие данных для чтения из порта ввода;
- чтение или запись в несуществующий адрес памяти.
- Модель может быть остановлена и возобновлена командой
debug.
Тестирование выполняется при помощи golden test-ов.
- Конфигурация лежит в директории tests
GitHub Actions при совершении push-а автоматически
- запускает golden-тесты (задание
test) - проверяет форматирование Python и запускает линтеры (
ruff) - проверяет форматирование Markdown (
markdownlint)
Конфигурация для GitHub Actions находится в файлах python.yml и markdown.yml
Golden-тесты:
❯ poetry run coverage run -m pytest . -v
============================================================================================ test session starts ============================================================================================
platform linux -- Python 3.12.2, pytest-7.4.4, pluggy-1.5.0 -- /home/max/.cache/pypoetry/virtualenvs/csa3-stack-machine-Mqil_AOd-py3.12/bin/python
cachedir: .pytest_cache
rootdir: /home/max/prog/itmo/csa3-stack-machine
configfile: pyproject.toml
plugins: golden-0.2.2
collected 6 items
tests/golden_test.py::test_translator_and_machine[golden/prob2.yml] PASSED [ 16%]
tests/golden_test.py::test_translator_and_machine[golden/0_to_9.yml] PASSED [ 33%]
tests/golden_test.py::test_translator_and_machine[golden/cat.yml] PASSED [ 50%]
tests/golden_test.py::test_translator_and_machine[golden/hello_username.yml] PASSED [ 66%]
tests/golden_test.py::test_translator_and_machine[golden/hello_world.yml] PASSED [ 83%]
tests/golden_test.py::test_translator_and_machine[golden/string_utils.yml] PASSED [100%]
============================================================================================= 6 passed in 1.62s =============================================================================================
Покрытие:
❯ poetry run coverage report -m
Name Stmts Miss Cover Missing
-------------------------------------------------------------------------
src/__init__.py 0 0 100%
src/constants.py 9 0 100%
src/isa/__init__.py 6 0 100%
src/isa/data.py 16 0 100%
src/isa/dump.py 16 0 100%
src/isa/instruction.py 18 1 94% 23
src/isa/json_utils.py 15 0 100%
src/isa/memory.py 33 0 100%
src/isa/opcode.py 48 2 96% 56, 64
src/machine/__init__.py 0 0 100%
src/machine/components/__init__.py 0 0 100%
src/machine/components/alu.py 27 2 93% 50, 52
src/machine/components/call_stack.py 18 0 100%
src/machine/components/data_stack.py 48 2 96% 35-36
src/machine/components/io.py 80 8 90% 11, 15, 29, 58, 69, 86, 109, 123
src/machine/components/memory.py 20 1 95% 21
src/machine/control_unit.py 89 3 97% 114-117
src/machine/data_path.py 41 0 100%
src/machine/main.py 44 25 43% 35-45, 49-53, 57-77, 81
src/machine/simulation.py 41 3 93% 24, 26, 31
src/main.py 8 3 62% 9-11
src/translator/__init__.py 3 0 100%
src/translator/data_translator.py 82 4 95% 15-16, 104-105
src/translator/instructions_translator.py 69 2 97% 21, 35
src/translator/main.py 34 7 79% 50-57, 61
src/translator/utils.py 15 0 100%
tests/__init__.py 0 0 100%
tests/golden_test.py 32 0 100%
-------------------------------------------------------------------------
TOTAL 812 63 92%
Алгоритмы согласно варианту:
Дополнительные алгоритмы:
- string_utils - набор функций для удобной работы со строками.
- 0_to_9.yml - демонстрация работы IO8.
Исходный код:
.data
hello_str: "Hello, world!"
.text
_start:
push hello_str
load
cycle:
jz ext
swap
inc
load
output 1
pop
swap
dec
jmp cycle
pop
pop
haltМашинный код:
[
{"address": 0, "opcode": "jmp", "operand": 1},
{"address": 1, "opcode": "push", "operand": 0},
{"address": 2, "opcode": "load", "operand": null},
{"address": 3, "opcode": "jz", "operand": 12},
{"address": 4, "opcode": "swap", "operand": null},
{"address": 5, "opcode": "inc", "operand": null},
{"address": 6, "opcode": "load", "operand": null},
{"address": 7, "opcode": "output", "operand": 1},
{"address": 8, "opcode": "pop", "operand": null},
{"address": 9, "opcode": "swap", "operand": null},
{"address": 10, "opcode": "dec", "operand": null},
{"address": 11, "opcode": "jmp", "operand": 3},
{"address": 12, "opcode": "pop", "operand": null},
{"address": 13, "opcode": "pop", "operand": null},
{"address": 14, "opcode": "halt", "operand": null}
]Данные:
[
{"address": 0, "value": 13},
{"address": 1, "value": 72},
{"address": 2, "value": 101},
{"address": 3, "value": 108},
{"address": 4, "value": 108},
{"address": 5, "value": 111},
{"address": 6, "value": 44},
{"address": 7, "value": 32},
{"address": 8, "value": 119},
{"address": 9, "value": 111},
{"address": 10, "value": 114},
{"address": 11, "value": 108},
{"address": 12, "value": 100},
{"address": 13, "value": 33}
]Вывод:
source LoC: 20 code instr: 15
============================================================
Hello, world!
instr_counter: 123 ticks: 137
Журнал (не весь):
DEBUG simulation:run TICK: 70, PC: 8, AR: 7, MEM_OUT: 32, TOS: [32, 7, 7] , pop |
DEBUG simulation:run TICK: 71, PC: 9, AR: 7, MEM_OUT: 32, TOS: [7, 7] , swap |
DEBUG simulation:run TICK: 72, PC: 10, AR: 7, MEM_OUT: 32, TOS: [7, 7] , dec |
DEBUG simulation:run TICK: 73, PC: 11, AR: 7, MEM_OUT: 32, TOS: [6, 7] , jmp 3 |
DEBUG simulation:run TICK: 74, PC: 3, AR: 7, MEM_OUT: 32, TOS: [6, 7] , jz 12 |
DEBUG simulation:run TICK: 75, PC: 4, AR: 7, MEM_OUT: 32, TOS: [6, 7] , swap |
DEBUG simulation:run TICK: 76, PC: 5, AR: 7, MEM_OUT: 32, TOS: [7, 6] , inc |
DEBUG simulation:run TICK: 77, PC: 6, AR: 7, MEM_OUT: 32, TOS: [8, 6] , load |
DEBUG simulation:run TICK: 79, PC: 7, AR: 8, MEM_OUT: 119, TOS: [119, 8, 6] , output 1 |
DEBUG io:log_io OUTPUT: w
DEBUG simulation:run TICK: 80, PC: 8, AR: 8, MEM_OUT: 119, TOS: [119, 8, 6] , pop |
DEBUG simulation:run TICK: 81, PC: 9, AR: 8, MEM_OUT: 119, TOS: [8, 6] , swap |
DEBUG simulation:run TICK: 82, PC: 10, AR: 8, MEM_OUT: 119, TOS: [6, 8] , dec |
DEBUG simulation:run TICK: 83, PC: 11, AR: 8, MEM_OUT: 119, TOS: [5, 8] , jmp 3 |
DEBUG simulation:run TICK: 84, PC: 3, AR: 8, MEM_OUT: 119, TOS: [5, 8] , jz 12 |
DEBUG simulation:run TICK: 85, PC: 4, AR: 8, MEM_OUT: 119, TOS: [5, 8] , swap |
DEBUG simulation:run TICK: 86, PC: 5, AR: 8, MEM_OUT: 119, TOS: [8, 5] , inc |
DEBUG simulation:run TICK: 87, PC: 6, AR: 8, MEM_OUT: 119, TOS: [9, 5] , load |
DEBUG simulation:run TICK: 89, PC: 7, AR: 9, MEM_OUT: 111, TOS: [111, 9, 5] , output 1 |
DEBUG io:log_io OUTPUT: o
DEBUG simulation:run TICK: 90, PC: 8, AR: 9, MEM_OUT: 111, TOS: [111, 9, 5] , pop |
DEBUG simulation:run TICK: 91, PC: 9, AR: 9, MEM_OUT: 111, TOS: [9, 5] , swap |
DEBUG simulation:run TICK: 92, PC: 10, AR: 9, MEM_OUT: 111, TOS: [5, 9] , dec |
DEBUG simulation:run TICK: 93, PC: 11, AR: 9, MEM_OUT: 111, TOS: [4, 9] , jmp 3 |
DEBUG simulation:run TICK: 94, PC: 3, AR: 9, MEM_OUT: 111, TOS: [4, 9] , jz 12 |
DEBUG simulation:run TICK: 95, PC: 4, AR: 9, MEM_OUT: 111, TOS: [4, 9] , swap |
DEBUG simulation:run TICK: 96, PC: 5, AR: 9, MEM_OUT: 111, TOS: [9, 4] , inc |
DEBUG simulation:run TICK: 97, PC: 6, AR: 9, MEM_OUT: 111, TOS: [10, 4] , load |
DEBUG simulation:run TICK: 99, PC: 7, AR: 10, MEM_OUT: 114, TOS: [114, 10, 4] , output 1 |
DEBUG io:log_io OUTPUT: r
DEBUG simulation:run TICK: 100, PC: 8, AR: 10, MEM_OUT: 114, TOS: [114, 10, 4] , pop |
DEBUG simulation:run TICK: 101, PC: 9, AR: 10, MEM_OUT: 114, TOS: [10, 4] , swap |
DEBUG simulation:run TICK: 102, PC: 10, AR: 10, MEM_OUT: 114, TOS: [4, 10] , dec |
DEBUG simulation:run TICK: 103, PC: 11, AR: 10, MEM_OUT: 114, TOS: [3, 10] , jmp 3 |
DEBUG simulation:run TICK: 104, PC: 3, AR: 10, MEM_OUT: 114, TOS: [3, 10] , jz 12 |
DEBUG simulation:run TICK: 105, PC: 4, AR: 10, MEM_OUT: 114, TOS: [3, 10] , swap |
DEBUG simulation:run TICK: 106, PC: 5, AR: 10, MEM_OUT: 114, TOS: [10, 3] , inc |
DEBUG simulation:run TICK: 107, PC: 6, AR: 10, MEM_OUT: 114, TOS: [11, 3] , load |
DEBUG simulation:run TICK: 109, PC: 7, AR: 11, MEM_OUT: 108, TOS: [108, 11, 3] , output 1 |
DEBUG io:log_io OUTPUT: l
DEBUG simulation:run TICK: 110, PC: 8, AR: 11, MEM_OUT: 108, TOS: [108, 11, 3] , pop |
DEBUG simulation:run TICK: 111, PC: 9, AR: 11, MEM_OUT: 108, TOS: [11, 3] , swap |
DEBUG simulation:run TICK: 112, PC: 10, AR: 11, MEM_OUT: 108, TOS: [3, 11] , dec |
DEBUG simulation:run TICK: 113, PC: 11, AR: 11, MEM_OUT: 108, TOS: [2, 11] , jmp 3 |
DEBUG simulation:run TICK: 114, PC: 3, AR: 11, MEM_OUT: 108, TOS: [2, 11] , jz 12 |
DEBUG simulation:run TICK: 115, PC: 4, AR: 11, MEM_OUT: 108, TOS: [2, 11] , swap |
DEBUG simulation:run TICK: 116, PC: 5, AR: 11, MEM_OUT: 108, TOS: [11, 2] , inc |
DEBUG simulation:run TICK: 117, PC: 6, AR: 11, MEM_OUT: 108, TOS: [12, 2] , load |
DEBUG simulation:run TICK: 119, PC: 7, AR: 12, MEM_OUT: 100, TOS: [100, 12, 2] , output 1 |
DEBUG io:log_io OUTPUT: d
DEBUG simulation:run TICK: 120, PC: 8, AR: 12, MEM_OUT: 100, TOS: [100, 12, 2] , pop |
DEBUG simulation:run TICK: 121, PC: 9, AR: 12, MEM_OUT: 100, TOS: [12, 2] , swap |
DEBUG simulation:run TICK: 122, PC: 10, AR: 12, MEM_OUT: 100, TOS: [2, 12] , dec |
DEBUG simulation:run TICK: 123, PC: 11, AR: 12, MEM_OUT: 100, TOS: [1, 12] , jmp 3 |
DEBUG simulation:run TICK: 124, PC: 3, AR: 12, MEM_OUT: 100, TOS: [1, 12] , jz 12 |
DEBUG simulation:run TICK: 125, PC: 4, AR: 12, MEM_OUT: 100, TOS: [1, 12] , swap |
DEBUG simulation:run TICK: 126, PC: 5, AR: 12, MEM_OUT: 100, TOS: [12, 1] , inc |
DEBUG simulation:run TICK: 127, PC: 6, AR: 12, MEM_OUT: 100, TOS: [13, 1] , load |
DEBUG simulation:run TICK: 129, PC: 7, AR: 13, MEM_OUT: 33, TOS: [33, 13, 1] , output 1 |
DEBUG io:log_io OUTPUT: !
DEBUG simulation:run TICK: 130, PC: 8, AR: 13, MEM_OUT: 33, TOS: [33, 13, 1] , pop |
DEBUG simulation:run TICK: 131, PC: 9, AR: 13, MEM_OUT: 33, TOS: [13, 1] , swap |
DEBUG simulation:run TICK: 132, PC: 10, AR: 13, MEM_OUT: 33, TOS: [1, 13] , dec |
DEBUG simulation:run TICK: 133, PC: 11, AR: 13, MEM_OUT: 33, TOS: [0, 13] , jmp 3 |
DEBUG simulation:run TICK: 134, PC: 3, AR: 13, MEM_OUT: 33, TOS: [0, 13] , jz 12 |
DEBUG simulation:run TICK: 135, PC: 12, AR: 13, MEM_OUT: 33, TOS: [0, 13] , pop |
DEBUG simulation:run TICK: 136, PC: 13, AR: 13, MEM_OUT: 33, TOS: [13] , pop |
DEBUG simulation:run TICK: 137, PC: 14, AR: 13, MEM_OUT: 33, TOS: [] , halt |
DEBUG simulation:simulation memory: DATA: [
0: 13
1: 72
2: 101
3: 108
4: 108
5: 111
6: 44
7: 32
8: 119
9: 111
10: 114
11: 108
12: 100
13: 33
]
INFO simulation:simulation output_buffer (port 1): 'Hello, world!'
INFO simulation:simulation output_buffer (port 2): ''
| ФИО | алг | LoC | code инстр. | инстр. | такт. |
| Барсуков Максим Андреевич | cat | 47 | 38 | 198 | 234 |
| Барсуков Максим Андреевич | hello_world | 20 | 15 | 123 | 137 |
| Барсуков Максим Андреевич | hello_username | 86 | 60 | 677 | 774 |
| Барсуков Максим Андреевич | prob2 | 69 | 44 | 513 | 597 |