Skip to content

bilyardvmetro/CSA-Lab4

Repository files navigation

Архитектура Компьютера. Лабораторная работа 4

Поленов Кирилл Александрович P3213

Вариант

asm | risc | harv | mc | tick | binary | stream | mem | pstr | prob2

25/30 баллов. Не ответил на вопрос "как схемотехнически устроен IO Controller"

Язык программирования

Синтаксис

Язык ассемблерного типа для RISC системы команд

<program> ::= <data_section> <code_section>

<data_section> ::= "." "data" { <data_definition> }
            
<code_section> ::= "." "code" { <instruction> | <macro_definition> | <macro_invocation> }

<instruction> ::=
               "lui" <register> "," { <string> | <number> }
               | "addi" <register> "," <register> "," { <string> | <number> } [ <comment> ]
               | "ori" <register> "," <register> "," { <string> | <number> } [ <comment> ]
               | "sw" <register> "," <register> "," { <number> } [ <comment> ]
               | "lw" <register> "," <register> "," { <number> } [ <comment> ]
               | "add" <register> "," <register> "," <register> [ <comment> ]
               | "sub" <register> "," <register> "," <register> [ <comment> ]
               | "mul" <register> "," <register> "," <register> [ <comment> ]
               | "mulh" <register> "," <register> "," <register> [ <comment> ]
               | "div" <register> "," <register> "," <register> [ <comment> ]
               | "and" <register> "," <register> "," <register> [ <comment> ]
               | "or" <register> "," <register> "," <register> [ <comment> ]
               | "xor" <register> "," <register> "," <register> [ <comment> ]
               | "jal" <register> "," <label> [ <comment> ]
               | "jalr" <register> "," <register> "," <label> [ <comment> ]
               | "beq" <register> "," <register> "," <label> [ <comment> ]
               | "bne" <register> "," <register> "," <label> [ <comment> ]
               | "bgt" <register> "," <register> "," <label> [ <comment> ]
               | "blt" <register> "," <register> "," <label> [ <comment> ]
               | "halt" [ <comment> ]
               | <label> [ <comment> ]

<macro_definition> ::= "%" "macro" <identifier> [ "(" <macro_parameter_list> ")" ] { <instruction> } "%" "endmacro" [ <comment> ]

<macro_parameter_list> ::= <identifier> { "," <identifier> }

<macro_invocation> ::= <identifier> [ "(" <macro_argument_list> ")" ] [ <comment> ]

<macro_argument_list> ::= <macro_argument> { "," <macro_argument> }

<macro_argument> ::= <label> | <string> | <number> | <register>

<data_definition> ::= <label> <data_value> { "," <data_value> } [ <comment> ]

<data_value> ::= <string> | <number>

<register> ::= { "t" | "s" | "a" } <number> | "r0" | "ra" | "bp" | "sp"

<label> ::= <identifier> ":"

<identifier> ::= <letter> { <letter> | <digit> }

<number> ::= <digit> { <digit> }

<string> ::= "\"" { <character> } "\""

<letter> ::= "a" | "b" | "c" | ... | "z"
           | "A" | "B" | "C" | ... | "Z"

<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

<character> ::= <any printable ASCII character except quotation mark>

<comment> ::= ";" { <any printable ASCII character> }

Директивы

  • %hi(literal) - загрузить верхние 20 бит литерала
  • %lo(literal) - загрузить нижние 12 бит литерала
.data
    message: "Hello, world!"

.code
    lui bp, %hi(message)      ; загрузить верхние 20 бит адреса метки message
    ori bp, bp, %lo(message)  ; загрузить нижние 12 бит адреса метки message без расширения знака
  • .org <address> - задать начальный адрес секции
  • .data - создает секцию памяти данных
  • .code - создает секцию памяти команд
  • %macro <macro definition> %endmacro - пара директив задающие пользовательскую макрооперацию

Пример макроса

%macro load_str_ptr(address)
    lui bp, %hi(%1)
    ori bp, bp, %lo(%1)
%endmacro

%macro load_and_add(rd, rs, offset, value)
    lw %1, %2, %3
    addi %1, %1, %4
%endmacro
    
.data
    message: "Hello, world!"

.code
    load_str_ptr(message) ; Вызов макроса load_str_ptr с аргументом message
    load_and_add(s1, s2, 0, 5) ; Вызов макроса load_and_add с несколькими аргументами
    halt

Команды

Команда Описание
lui <rd>, <k> Загрузить верхние 20 бит литерала в регистр
sw <rs2>, <rs1>, <offset> Сохранить слово из rs2 по адресу из rs1 со смещением offset
lw <rd>, <rs1>, <offset> Загрузить слово в rd c адреса из rs1 со смещением offset
addi <rd>, <rs1>, <k>* Сложить содержимое регистра rs1 с литералом k
и поместить результат в регистр rd
add <rd>, <rs1>, <rs2> Сложить содержимое регистра rs1 с содержимым регистра rs2
и поместить результат в регистр rd
sub <rd>, <rs1>, <rs2> Вычесть содержимое регистра rs1 из содержимого регистра rs2
и поместить результат в регистр rd
mul <rd>, <rs1>, <rs2> Умножить содержимое регистра rs1 на содержимое регистра rs2
и поместить результат в регистр rd
mulh <rd>, <rs1>, <rs2> Умножить содержимое регистра rs1 на содержимое регистра rs2
и поместить верхние 32 бита результата в регистр rd
div <rd>, <rs1>, <rs2> Разделить содержимое регистра rs1 на содержимое регистра rs2
и поместить результат в регистр rd
and <rd>, <rs1>, <rs2> Совершить логическое И содержимого регистра rs1 и содержимого регистра rs2
и поместить результат в регистр rd
or <rd>, <rs1>, <rs2> Совершить логическое ИЛИ содержимого регистра rs1 и содержимого регистра rs2 и поместить результат в регистр rd
ori <rd>, <rs1>, <k>* Совершить логическое ИЛИ содержимого регистра rs1 и литерала k
и поместить результат в регистр rd
xor <rd>, <rs1>, <rs2> Совершить исключающее ИЛИ содержимого регистра rs1 и содержимого регистра rs2
и поместить результат в регистр rd
jal <rd>, <k>*1 Перейти на адрес pc + k, сохранив адрес возврата в регистр rd.
Аналог call и jump
jalr <rd>, <rs1>, <k>*1 Перейти на адрес из rs1, сохранив адрес возврата в регистр rd.
Аналог call и return
beq <rs1>, <rs2>, <k> Перейти на адрес pc + k,
если содержимое rs1 равно содержимому rs2
bne <rs1>, <rs2>, <k> Перейти на адрес pc + k,
если содержимое rs1 не равно содержимому rs2
bgt <rs1>, <rs2>, <k> Перейти на адрес pc + k,
если содержимое rs1 больше содержимого rs2. Для сравнения знаковых чисел
blt <rs1>, <rs2>, <k> Перейти на адрес pc + k,
если содержимое rs1 меньше содержимого rs2. Для сравнения знаковых чисел
halt Остановить процессор

* - расширяет знак литерала k

*1 - Если подать регистр r0 как аргумент <rd>, адрес возврата не будет сохранен.

Стратегия вычислений

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

Области видимости

В языке не существует как таковых областей видимости, однако есть пара моментов:

  • Секция данных и команд не имеют прямого доступа друг к другу
  • На аппаратном уровне невозможно прочитать команду из памяти команд как данные и наоборот

Типизация. Виды литералов

  • Язык является беcтиповым. Все сущности считаются последовательностью бит различной длины в пределах машинного слова
  • Регистры являются универсальными контейнерами для хранения переменных в виде битовых последовательностей
  • Интерпретация содержимого регистров зависит от инструкций, которые к ним применяются. К примеру инструкция add подразумевает, что операндами являются числа. Инструкция lw подразумевает, что один регистров-операндов содержит адрес в памяти
  • Отсутствие статической проверки типов
  • Отсутствие неявных преобразований

Однако в контексте ассемблера битовые последовательности можно разделить на следующие категории:

  • Знаковые числа
  • Адреса
  • Символы
  • Строки (последовательности символов)

Литералы соответствуют одной из категорий перечисленных выше

Организация памяти

  • Размер машинного слова - 32 бита
  • Модель памяти соответствует Гарвардской архитектуре
  • Присутствует 3 вида памяти: Память инструкций, Память данных, Память микрокоманд
  • Адреса памяти данных и памяти команд представляют собой беззнаковые 32 битные числа
  • Обращение к памяти происходит только по абсолютному адресу
  • Память команд является read-only на аппаратном уровне
  • Память Команд
    • Инструкции имеют фиксированную длину - 32 бита
    • Инструкции хранятся в ячейках размером 32 бита
  • Память Данных
    • Данные хранятся в ячейках размером 32 бита
  • Обращение к памяти происходит только через регистры
  • ALU не имеет прямого доступа к памяти
  • Модель включает в себя 32 регистра
  • За управление регистрами отвечает Register File
  • Регистр r0 - Zero register (значение всегда равно 0)
  • Регистр r31 - системный для временного хранения imm/offset значений
  • Стек не является аппаратной частью и располагается в конце памяти данных. Для аргументов и возвращаемых значений функций следует использовать регистры согласно соглашению
  • По умолчанию все переменные отображаются в память данных в порядке их инициализации в секции .data
  • Переменные могут быть отображены на регистры только при явной загрузке в регистры
  • Порядок расположения литералов в памяти данных соответствует порядку их объявления в секции .data
  • Литералы превышающие 32 бита хранятся в памяти следующим образом:
        Data Memory
+-----------------------------+
|      ...                    |
| n       lit_low             |
| n+1     lit_high            |
|      ...                    |
+-----------------------------+

Где lit_low нижние 32-бита литерала, lit_high верхние 32-бита литерала

Общий вид организации памяти

       Instruction memory
+-----------------------------+
| 00       binary instr       |
| 01       binary instr       |
|      ...                    |
+-----------------------------+


        Data Memory
+-----------------------------+    +-------+
| 00       data               | <--|IN_BUF |
| 01       data               | <--|OUT_BUF|
|      ...                    |    +-------+
| 10       data               |
| 11       data               |
|      ...                    |
+-----------------------------+
|            Stack            |
+-----------------------------+
| ???      end                |
|      ...                    |
| MAX      begin              |
+-----------------------------+

       Microprogram memory
+-----------------------------+
| 00       signals            |
| 01       signals            |
|      ...                    |
+-----------------------------+

Типы команд

Register type (R-type) команды

type destination register operation source register 1 source register 2 op extension
7 bits 5 bits 3 bits 5 bits 5 bits 7 bits

type = 1000000

Инструкция Operation code Op extension code
add 001 0000001
sub 001 0000010
mul 010 0000001
mulh 010 0000010
div 010 0000011
and 011 0000001
or 011 0000010
xor 011 0000011

Immediate type (I-type) команды

type destination register operation source register 1 immediate value/offset [0-11] bits
7 bits 5 bits 3 bits 5 bits 12 bits

type = 0100000

Инструкция Operation code
lw 001
addi 010
ori 011
jalr 100
halt 101

Store type (S-type) команды

type offset [0-4] bits operation source register 1 source register 2 offset [5-11] bits
7 bits 5 bits 3 bits 5 bits 5 bits 7 bits

type = 0010000

Инструкция Operation code
sw 001

Branch type (B-type) команды

type offset [0-4] bits operation source register 1 source register 2 offset [5-11] bits
7 bits 5 bits 3 bits 5 bits 5 bits 7 bits

type = 0001000

Инструкция Operation code
beq 001
bne 010
bgt 011
blt 100

Upper type (U-type) команды

type destination register immediate value [12-31] bits
7 bits 5 bits 20 bits

type = 0000100

Инструкция Operation code
lui -

Jump type (J-type) команды

type destination register immediate value [0-19] bits
7 bits 5 bits 20 bits

type = 0000010

Инструкция Operation code
jal -

Бинарные коды регистров

Регистр Бин. код
r0 00000
ra 00001
sp 00010
bp 00011
t0 00100
t1 00101
t2 00110
t3 00111
t4 01000
t5 01001
t6 01010
s0 01011
s1 01100
s2 01101
s3 01110
s4 01111
s5 10000
s6 10001
s7 10010
s8 10011
s9 10100
s10 10101
s11 10110
a0 10111
a1 11000
a2 11001
a3 11010
a4 11011
a5 11100
a6 11101
a7 11110
r31 11111

Описание регистров и их назначение

  • r0 - системный регистр всегда хранящий 0
  • ra - адрес возврата
  • sp - указатель вершины стека
  • bp - указатель на буфер строки
  • t0-t6 - регистры для временного хранения внутри функции. Caller-saved регистры
  • s0 - может использоваться как указатель на фрейм стека
  • s0, s1-s11 - регистры для сохранения значений перед вызовом функции и восстановить после. Callee-saved регистры
  • a0-a7 - регистры для передачи аргументов/возвращаемых значений в функцию
  • r31 - системный регистр для временного хранения imm/offset

Система команд

Набор инструкций

Работа с данными

Инструкция Тип Результат Описание
lui <rd>, <k> U-type rd <- k << 12 Загрузить верхние 20 бит литерала в регистр
sw <rs2>, <rs1>, <offset> S-Type rs2 -> mem[rs1 + offset] Сохранить слово из rs2 по адресу из rs1 со смещением offset
lw <rd>, <rs1>, <offset> I-type rd <- mem[rs1 + offset] Загрузить слово в rd c адреса из rs1 со смещением offset

Арифметика

Инструкция Тип Результат Описание
addi <rd>, <rs1>, <k>* I-type rd <- rs1 + k Сложить содержимое rs1 с литералом k
и поместить результат в регистр rd
add <rd>, <rs1>, <rs2> R-type rd <- rs1 + rs2 Сложить содержимое rs1 с содержимым rs2
и поместить результат в регистр rd
sub <rd>, <rs1>, <rs2> R-type rd <- rs1 - rs2 Вычесть содержимое rs1 из содержимого rs2
и поместить результат в регистр rd
mul <rd>, <rs1>, <rs2> R-type rd <- rs1 * rs2 Умножить содержимое rs1 на содержимое rs2
и поместить результат в регистр rd
mulh <rd>, <rs1>, <rs2> R-type rd <- (rs1 * rs2) >> 32 Умножить содержимое rs1 на содержимое rs2
и поместить верхние 32 бита результата в регистр rd
div <rd>, <rs1>, <rs2> R-type rd <- rs1 / rs2 Разделить содержимое rs1 на содержимое rs2
и поместить результат в регистр rd

* - расширяет знак литерала k

Битовые операции

Инструкция Тип Результат Описание
ori <rd>, <rs1>, <k>* I-type rd <- rs1 | k Совершить логическое ИЛИ содержимого rs1 и литерала k
и поместить результат в регистр rd
and <rd>, <rs1>, <rs2> R-type rd <- rs1 & rs2 Совершить логическое И содержимого rs1 и содержимого rs2
и поместить результат в регистр rd
or <rd>, <rs1>, <rs2> R-type rd <- rs1 | rs2 Совершить логическое ИЛИ содержимого rs1 и содержимого rs2
и поместить результат в регистр rd
xor <rd>, <rs1>, <rs2> R-type rd <- rs1 ^ rs2 Совершить исключающее ИЛИ содержимого rs1 и содержимого rs2
и поместить результат в регистр rd

* - расширяет знак литерала k

Условные и безусловные переходы

Инструкция Тип Результат Описание
jal <rd>, <k>* J-type rd <- pc + 4, pc <- pc + k Перейти на адрес pc + k,
сохранив адрес возврата в регистр rd. Аналог call и jump
jalr <rd>, <rs1>, <k>* I-type rd <- pc + 4, pc <- rs1 Перейти на адрес из rs1,
сохранив адрес возврата в регистр rd. Аналог call и return
halt I-type - Остановить процессор
beq <rs1>, <rs2>, <k> B-type if rs1 == rs2 then pc <- pc + k Перейти на адрес pc + k,
если содержимое rs1 равно содержимому rs2
bne <rs1>, <rs2>, <k> B-type if rs1 != rs2 then pc <- pc + k Перейти на адрес pc + k,
если содержимое rs1 не равно содержимому rs2
bgt <rs1>, <rs2>, <k> B-type if rs1 > rs2 then pc <- pc + k Перейти на адрес pc + k,
если содержимое rs1 больше содержимого rs2
blt <rs1>, <rs2>, <k> B-type if rs1 < rs2 then pc <- pc + k Перейти на адрес pc + k,
если содержимое rs1 меньше содержимого rs2

* - Если подать регистр r0 как аргумент rd, адрес возврата не будет сохранен.

Потактовый цикл исполнения инструкций

  1. Instruction fetch: 3 такта
    • mpc + 1 -> mpc, pc + 1 -> pc
    • ins_mem[pc] -> decoder, lookUpTableIndex(decoder) -> IR, mpc + 1 -> mpc
    • IR -> mpc
  2. Instruction execution: N тактов
Инструкция Кол-во тактов Потактовое выполнение
lui <rd>, <k> 1 k << 12 -> rd
sw <rs2>, <rs1>, <offset> 3 offset -> r31,
rs1 + r31 -> r31,
rs2 -> data_mem[r31]
lw <rd>, <rs1>, <offset> 3 offset -> r31,
rs1 + r31 -> r31,
data_mem[r31] -> rd
addi <rd>, <rs1>, <k> 2 k -> r31,
rs1 + r31 -> rd
add <rd>, <rs1>, <rs2> 1 rs1 + rs2 -> rd
sub <rd>, <rs1>, <rs2> 1 rs1 - rs2 -> rd
mul <rd>, <rs1>, <rs2> 1 rs1 * rs2 -> rd
mulh <rd>, <rs1>, <rs2> 1 (rs1 * rs2) >> 32 -> rd
div <rd>, <rs1>, <rs2> 1 rs1 / rs2 -> rd
ori <rd>, <rs1>, <k> 2 k -> r31,
rs1 | r31 -> rd
and <rd>, <rs1>, <rs2> 1 rs1 & rs2 -> rd
or <rd>, <rs1>, <rs2> 1 rs1 | rs2 -> rd
xor <rd>, <rs1>, <rs2> 1 rs1 ^ rs2 -> rd
jal <rd>, <k> 3 pc + 1 -> rd,
k -> r31,
pc + r31 -> pc
jalr <rd>, <rs1>, <k> 3 pc + 1 -> rd,
k -> r31,
rs1 + r31 -> pc
halt 1 Stop machine
beq <rs1>, <rs2>, <k> 3 k -> r31,
rs1 - rs2 -> NZ,
if Z then pc + r31 -> pc
bne <rs1>, <rs2>, <k> 3 k -> r31,
rs1 - rs2 -> NZ,
if Z then pc + 1 -> pc
bgt <rs1>, <rs2>, <k> 3 k -> r31,
rs1 - rs2 -> NZ,
if NZ=00 then pc + r31 -> pc
blt <rs1>, <rs2>, <k> 3 k -> r31,
rs1 - rs2 -> NZ,
if NZ=10 then pc + r31 -> pc

Микрокоманды

Микрокоманда Описание
latch_ir Прочитать команду из памяти команд
и защелкнуть соответствующий ей индекс LookUpTable в IR
latch_mpc Защелкнуть значение в MPC
sel_mpc_inc_one Управляющий сигнал для выбора 1 в качестве инкремента для MPC
sel_mpc_inc_two_if_z Управляющий сигнал для выбора 2 в качестве инкремента для MPC если Z == 1
sel_mpc_inc_two_if_greater Управляющий сигнал для выбора 2 в качестве инкремента для MPC если NZ == 00
sel_mpc_inc_two_if_lower Управляющий сигнал для выбора 2 в качестве инкремента для MPC если NZ == 10
sel_mpc_increment Управляющий сигнал для выбора инкремента MPC
sel_mpc_look_up_index Управляющий сигнал для выбора записи операции из IR в MPC
sel_mpc_zero Управляющий сигнал для выбора записи 0 в MPC
latch_regn Защелкнуть значение в регистр
latch_reg31 Защелкнуть значение в регистр r31
sel_left_reg Управляющий сигнал для выбора регистра на левый выход Register File
sel_right_reg Управляющий сигнал для выбора регистра на правый выход Register File
sel_left_reg31 Управляющий сигнал для выбора регистра r31 на левый выход Register File
sel_right_reg31 Управляющий сигнал для выбора регистра r31на правый выход Register File
sel_data_src_alu Управляющий сигнал для выбора результата из ALU для записи в Register File
sel_data_src_mem Управляющий сигнал для выбора данных из памяти данных для записи в Register File
sel_data_src_cu Управляющий сигнал для выбора данных из Control Unit для записи в Register File
sel_pc_inc Управляющий сигнал для выбора инкремента PC
sel_pc_alu Управляющий сигнал для выбора записи в PC результата из ALU
sel_alu_r_rf Управляющий сигнал для выбора подачи правого выхода Register File на правый вход ALU
sel_alu_l_rf Управляющий сигнал для выбора подачи левого выхода Register File на левый вход ALU
sel_alu_r_inc Управляющий сигнал для выбора подачи единицы на правый вход ALU
sel_alu_l_pc Управляющий сигнал для выбора подачи PC на левый вход ALU
alu_add Выполнить сложение в ALU
alu_sub Выполнить вычитание в ALU
alu_mul Выполнить умножение в ALU
alu_mulh Выполнить умножение, а затем логический сдвиг вправо на 32 в ALU
alu_div Выполнить деление в ALU
alu_and Выполнить логическое И в ALU
alu_or Выполнить логическое ИЛИ в ALU
alu_xor Выполнить исключающее ИЛИ в ALU
latch_pc Защелкнуть значение в PC
write_data_mem Прочитать ячейку из памяти данных
read_data_mem Записать данные в ячейку памяти данных
halt Остановить процессор

Транслятор

Интерфейс командной строки: translator.go <input_file> <target_code_file> <target_data_file> Реализовано в модуле: translator.go

Он выполняет несколько ключевых шагов:

  • Удаление комментариев: Функция cleanComments удаляет комментарии, что упрощает дальнейшую обработку.

  • Подстановка макросов: Функция expandMacros подставляет макросы в места их вызова и удаляет их определения из кода.

  • Далее происходит составление таблицы меток в памяти команд и памяти данных, а также обработка директив .org, .data, .code в функции ProcessAssemblyCode

  • Подстановка смещений, раскрытие директив %hi %lo происходит в функции ResolveSymbols. Одновременно с этим заполняется выходной файл памяти данных и отладочный файл с дампом памятей

  • Конвертация инструкций в бинарные представления и их запись в выходной файл памяти команд в функции ConvertProgramToBinary

  • Запуск трансляции: Основная функция main считывает исходный файл, выполняет трансляцию и записывает результат в целевые файлы.

Система ввода-вывода

  • Реализован mem-mapped IO
  • По умолчанию индексы mmioIn и mmioOut равны 0 и 1 соответственно. Ячейки можно конфигурировать через константы mmioIn и mmioOut в файле memory.go
  • Конфигурацию ячеек следует проводить предельно внимательно с использованием директивы .org. В противном случае могут произойти коллизии ячеек mem-mapped IO с ячейками памяти данных, что вызывает неопределенное поведение
  • Ввод-вывод производится путем обращения к ячейкам mmioIn и mmioOut в Data Memory
  • При обращении к ячейкам mmioOut и mmioOut происходит считывание и запись в буфер соответственно
  • Для работы с вводом-выводом используются те же команды, что и для обычной работы с памятью: lw, sw
  • Если в in буфере кончаются элементы - процессор прекращает работу

Модель процессора

Схема целиком

DataPath

DataPath

Реализация

Состоит из:

  • ALU
  • Register File
  • Data memory
  • Instruction memory
  • IO Controller
  • Program Counter (PC)
  • Sign Extender для расширения знака imm/offset значений всех инструкций кроме ori

Сигналы:

  • latch_reg_n - защелкнуть значение в регистр n
  • alu_op - сигнал операции АЛУ
  • latch_pc - защелкнуть значение в PC
  • write_mem - записать значение в память
  • read_mem - считать значение из памяти
  • sel_pc - селектор мультиплексора к PC (инкремент или запись значения из АЛУ)
  • sel_data_src - селектор мультиплексора к register file (запись результата из АЛУ, запись imm/offset из CU, запись значения из памяти)
  • sel_alu_r - селектор мультиплексора на правый вход АЛУ (единица, выход из register file)
  • sel_alu_l - селектор мультиплексора на левый вход АЛУ (PC, выход из register file)

Флаги:

  • NZ - 2-битовый флаг. N выставляется, если результат на выходе АЛУ отрицательный, Z выставляется, если результат на выходе АЛУ 0. 1-й бит N, 2-й бит Z

Register File

RegisterFile

Реализация

  • системный регистр r0 имеет подтяжку 0 и неизменяем
  • системный регистр r31 нужен для временного хранения imm/offset
  • r1-r30 регистры для использования программистом

Сигналы:

  • latch_reg_n описан в разделе DataPath
  • sel_left_reg - селектор подачи содержимого регистра на левый вход АЛУ
  • sel_left_reg - селектор подачи содержимого регистра на правый вход АЛУ

Control Unit

ControlUnit

Реализация

Состоит из:

  • Instruction decoder - декодер бинарной инструкции. Определяет индекс начальной для инструкции микрокоманды в LookUpTable, отправляет в Signal Dispatcher индексы регистров, а imm/offset значения в DataPath.

    • Содержит LookUpTable маппинга инструкций на соответствующие им микропрограммы.
  • IR (Index Register) - регистр для хранения индекса LookUpTable

  • MPC (MicroProgram Counter) - счетчик микропрограмм

  • MP memory - память микропрограмм

  • Signal Dispatcher - отправляет управляющие сигналы микропрограмм в DataPath и анализирует флаги результата

Процесс выполнения программы:

  1. На вход CU поступает бинарная инструкция из памяти инструкций
  2. По совокупности типа команды, опкода и расширение опкода из LookUpTable достается индекс микропрограммы для инструкции. Индексы регистров уходят в Signal Dispatcher, imm/offset значения в DataPath
  3. Индекс из LookUpTable уходит в IR операнды в OR
  4. Значение из IR уходит в MPC. По нему из памяти микрокоманд достается микропрограмма
  5. Signal Dispatcher отправляет управляющие сигналы микропрограммы в DataPath

Сигналы:

  • latch_ir - защелкнуть значение в IR
  • latch_mpc - защелкнуть значение в MPC
  • sel_mpc_inc - селектор инкремента mpc (mpc + 1, mpc + 2). Нужен для Branch-Type команд, которые зависят от флагов NZ
  • sel_mpc - выбрать следующее значение для mpc (mpc inc, LookUpTable Index from IR, 0)

Выполнение микропрограмм происходит в функции dispatchSignal. Цикл декодирования инструкций происходит в функции decodeInstruction.

Тестирование

Описание алгоритмов

  • cat - печатать данные, поданные через ввод
  • cat_macro - печатать данные, поданные через ввод. В алгоритме присутствует примера макроса
  • dwrod_mul - умножение двух чисел, не помещающихся в 32-битную сетку
  • hello - вывести hello world
  • hello_user_name - Запросить у пользователя его имя, считать его, вывести на экран приветствие
  • prob2 - Найти разность между квадратом суммы и суммой квадратов первых ста натуральных чисел
  • sort - Пользователь загружает в систему список чисел, который выводится в отсортированном формате

Описание тестирования

  • Тестирование осуществляется при помощи golden test-ов
  • Модуль запускающий тестирование находится в goldentest
  • Конфигурации тестов находятся в директории testdata
  • Запустить тесты:
cd /goldentest
go test -v

Составляющие тест-кейса на примере программы prob2

in_src: |-
  ; Найти разность между квадратом суммы и суммой квадратов первых ста натуральных чисел.
  .org 2
  .data
    in_addr:    0
    out_addr:   1
    limit:      46340   ; его квадрат суммы максимально занимает 32 бита

  .code    
    lui t2, %hi(in_addr)
    addi t2, t2, %lo(in_addr)
    lw t2, t2, 0
...
mem_dump: |
  <memory> - <address> - <HEXCODE> - <mnemonic>/<value_dec>>
  Таблицы символов (адресация по словам):
    Память данных:
      in_addr: 2
      limit: 4
      out_addr: 3
    Память команд:
      calc: 19
      end: 22
      loop: 13
  --------------------------------------------------------
  dataMem    2:    0    0
  dataMem    3:    1    1
  dataMem    4:    B504    46340
  progMem    0:    08600000    lui t2, 0
  progMem    1:    40646002    addi t2, t2, 2
  progMem    2:    40626000    lw t2, t2, 0
  progMem    3:    08500000    lui t1, 0
  progMem    4:    40545003    addi t1, t1, 3
  progMem    5:    40525000    lw t1, t1, 0
  progMem    6:    08300000    lui bp, 0
  ...
out_code: |
  000000000000600801000000026064400200000000606240030000000000500804000000035054400500000000505240060000000000300807000000043034400800000000303240090000000060c2400a0000000060c2400b0000008ac106100c000000017075410d000000057607100e00000081dbd2800f000000817b45801000000001e2e280110000000170754112000000faff0f041300000081d6d4801400000002d7f280150000008057022016000000fffffb41

out_data: |
  020000000000000003000000010000000400000004b50000
in: |
  100
stdout: |
  Stop Reason: HALT
  Instructions executed: 618
  Microprograms executed: 14014
  Output decimal: [25164150]
  Output hex: 17FF976
log: |

...
  • in_src - исходный код программы на разработанном языке
  • mem_dump - дамп памяти после трансляции
  • out_code - содержимое бинарного файла \<program name\>_code.bin
  • out_data - содержимое бинарного файла \<program name\>_data.bin
  • in - строка на ввод процессора
  • stdout - вывод работы процессора
  • log - журнал выполнения

Пример тестирования:

go test -v
=== RUN   TestPrograms
=== RUN   TestPrograms/cat
=== RUN   TestPrograms/cat_macro
=== RUN   TestPrograms/dword_mul
=== RUN   TestPrograms/hello
=== RUN   TestPrograms/hello_user_name
=== RUN   TestPrograms/prob2
=== RUN   TestPrograms/sort
--- PASS: TestPrograms (0.37s)
    --- PASS: TestPrograms/cat (0.05s)
    --- PASS: TestPrograms/cat_macro (0.04s)
    --- PASS: TestPrograms/dword_mul (0.04s)
    --- PASS: TestPrograms/hello (0.07s)
    --- PASS: TestPrograms/hello_user_name (0.06s)
    --- PASS: TestPrograms/prob2 (0.06s)
    --- PASS: TestPrograms/sort (0.05s)
PASS
ok      goldentest      0.558s

Использование транслятора

translator.exe <input_file> <target_code_file> <target_data_file>

Использование процессора

machine.exe <compiled_code> <compiled_data> Optional(<input_file>)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages