ЛР5. Обновление методички

Добавлена поддержка инструкций CSR + mret, чтобы в последствии не
возвращаться к этому модулю.
This commit is contained in:
Andrei Solodovnikov
2023-09-14 13:28:30 +03:00
parent aa24ff90bb
commit d665991ba3
4 changed files with 49 additions and 25 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 KiB

After

Width:  |  Height:  |  Size: 484 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 236 KiB

View File

@@ -37,7 +37,9 @@
![../../.pic/Labs/lab_05_decoder/rv32i_BIS.png](../../.pic/Labs/lab_05_decoder/rv32i_BIS.png) ![../../.pic/Labs/lab_05_decoder/rv32i_BIS.png](../../.pic/Labs/lab_05_decoder/rv32i_BIS.png)
*Таблица 1. Базовый набор инструкций из [спецификации RISC-V](https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf) (стр. 130)* *Таблица 1. Базовый набор инструкций из [спецификации RISC-V](https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf) (стр. 130), Стандартное расширение Zicsr(стр. 131), а так же привилегированная инструкция mret([спецификация привилегированной архитектуры RISC-V](https://github.com/riscv/riscv-isa-manual/releases/download/riscv-isa-release-1239329-2023-05-23/riscv-privileged.pdf), стр. 144)*
| Кодирование | Описание | | Кодирование | Описание |
|-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| |-------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -50,13 +52,28 @@
*Таблица 2. Описание типов форматов кодирования инструкций ISA RISC-V* *Таблица 2. Описание типов форматов кодирования инструкций ISA RISC-V*
### Неподдерживаемые инструкции ### SYSTEM-инструкции
В базовом наборе инструкций **RISC-V** к операциям `SYSTEM` относятся `ECALL` и `EBREAK`, к операциям `MISC-MEM` операция `FENCE`. В реализуемом процессорном ядре эти инструкции не должны приводить ни к каким изменениям. Иначе говоря, они должны быть реализованы как инструкция `NOP` (**no operation**). SYSTEM-инструкции используются для доступа к системным функциям и могут требовать привилегированный доступ. Данные инструкции могут быть разделены на два класса:
Инструкция `FENCE` в **RISC-V** необходима при работе с несколькими аппаратными потоками, или хартами (hart «hardware thread»). В **RISC-V** используется расслабленная модель памяти (**relaxed memory model**): потоки «видят» все инструкции чтения и записи, которые исполняются другими потоками, однако видимый порядок этих инструкций может отличаться от реального. Инструкция `FENCE`, использованная между двумя инструкциями чтения и/или записи гарантирует, что остальные потоки увидят первую инструкцию перед второй. Реализация `FENCE` является опциональной в **RISC-V** и в данном случае в ней нет необходимости, так как в системе не предполагается наличия нескольких аппаратных потоков.
Инструкции `ECALL` и `EBREAK` должны вызывать исключение с последующим переходом в обработчик исключения (вызова операционной системы и перехода в привилегированный режим работы). Помимо этого, их вызов должен обновить содержимое некоторых управляющих регистров (**Control & Status Registers** **CSR**). На текущий момент эти инструкции не будут использоваться, а потому могут быть реализованы как `NOP`.
Список инструкций с указанием их типов и функциональным назначением: - Обращение к регистрам статуса и контроля (**CSR**)
- Все остальные инструкции (возможно из набора привилегированных инструкций)
Для будущей поддержки прерываний, нам потребуется декодировать инструкции обоих классов.
Обращение к регистрам статуса и контроля осуществляется шестью инструкциями стандартного расширения `Zicsr`. Каждая из этих инструкций (если у нее легальные поля) осуществляет запись в CS-регистры и регистровый файл.
Кроме того, для возврата управления основному потоку инструкций, нужна дополнительная `SYSTEM`-инструкция привилегированного набора команд `MRET`.
Единственное что нужно сделать при появлении этой инструкции — это сформировать единицу на одноименном выходе.
Перечисленные выше инструкции являются "дополнительными" — их намеренно их добавили сверх стандартного набора инструкций, чтобы обеспечить требуемый нашей системе функционал. Однако осталось ещё две SYSTEM-инструкции, которые мы должны уметь декодировать, поскольку они есть в стандартном наборе инструкций.
Инструкции `ECALL` и `EBREAK` должны вызывать исключение. Единственное исключение, которое будет поддерживаться нашей системой, это исключение через сигнал `illegal_instr_o`, поэтому в рамках данного цикла лабораторных работ вам предлагается выставлять `illegal_instr_o == 1`, когда приходят эти инструкции (что довольно легко описать, ведь получается что если SYSTEM-инструкция не является `MRET` либо инструкцией из набора `Zicsr`, то это либо нелегальная инструкция, либо `ECALL` / `EBREAK`, которые ведут себя точно так же как и нелегальная инструкция).
### MISC-MEM инструкция
В базовом наборе инструкций **RISC-V** к `MISC-MEM`-операции относится инструкция `FENCE`. В реализуемом процессорном ядре эта инструкция не должны приводить ни к каким изменениям. Инструкция `FENCE` в **RISC-V** необходима при работе с несколькими аппаратными потоками, или хартами (hart «hardware thread»). В **RISC-V** используется расслабленная модель памяти (**relaxed memory model**): потоки «видят» все инструкции чтения и записи, которые исполняются другими потоками, однако видимый порядок этих инструкций может отличаться от реального. Инструкция `FENCE`, использованная между двумя инструкциями чтения и/или записи гарантирует, что остальные потоки увидят первую инструкцию перед второй. Реализация `FENCE` является опциональной в **RISC-V** и в данном случае в ней нет необходимости, так как в системе не предполагается наличия нескольких аппаратных потоков. Данная инструкция должна быть реализована как `NOP` (no operation).
![../../.pic/Labs/lab_05_decoder/rv32i_summary.png](../../.pic/Labs/lab_05_decoder/rv32i_summary.png) ![../../.pic/Labs/lab_05_decoder/rv32i_summary.png](../../.pic/Labs/lab_05_decoder/rv32i_summary.png)
@@ -70,11 +87,11 @@
Приведенная архитектура не является заданием для текущей лабораторной работы, лишь отражает то, как в дальнейшем будет подключаться и использоваться реализуемый в данной лабораторной основной дешифратор. Приведенная архитектура не является заданием для текущей лабораторной работы, лишь отражает то, как в дальнейшем будет подключаться и использоваться реализуемый в данной лабораторной основной дешифратор.
![../../.pic/Labs/lab_06_dp/fig_01.drawio.png](../../.pic/Labs/lab_06_dp/fig_01.drawio.png) ![../../.pic/Labs/lab_11_irq_integration/fig_01.drawio.png](../../.pic/Labs/lab_11_irq_integration/fig_01.drawio.png)
Предложенная микроархитектура процессора `CYBERcobra 3000 Pro 2.0` из прошлой лабораторной имеет схожую структуру, с некоторыми изменениями. Предложенная микроархитектура процессора `CYBERcobra 3000 Pro 2.0` из прошлой лабораторной имеет схожую структуру, с некоторыми изменениями.
В первую очередь изменились входы и выходы процессора: В первую очередь изменились входы и выходы процессора (помимо появления двух непонятных модулей):
- память инструкций вынесена наружу процессора, таким образом, у процессора появляются входы и выходы: `instr_addr_o` и `instr_i`; - память инструкций вынесена наружу процессора, таким образом, у процессора появляются входы и выходы: `instr_addr_o` и `instr_i`;
- помимо прочего, у модуля появились сигналы интерфейса памяти данных: - помимо прочего, у модуля появились сигналы интерфейса памяти данных:
@@ -88,7 +105,7 @@
Так же добавились источники операндов АЛУ: программный счетчик, множество констант из инструкций и микроархитектурных констант. Выбор нужных операндов для АЛУ осуществляется с помощью двух мультиплексоров, управляемых сигналами декодера `src_a_op_sel_o` и `src_b_op_sel_o` (для краткости на схеме обозначены как `src_a_sel` и `src_b_sel`). Так же добавились источники операндов АЛУ: программный счетчик, множество констант из инструкций и микроархитектурных констант. Выбор нужных операндов для АЛУ осуществляется с помощью двух мультиплексоров, управляемых сигналами декодера `src_a_op_sel_o` и `src_b_op_sel_o` (для краткости на схеме обозначены как `src_a_sel` и `src_b_sel`).
Изменилось и число источников записи в регистровый файл: их осталось два: результат операции на АЛУ и данные, считанные с внешней памяти. Выборка осуществляется сигналом декодера `wb_sel_o`. Изменилось и число источников записи в регистровый файл: их стало 3: результат операции на АЛУ, данные, считанные с внешней памяти и данные из модуля регистров статуса и контроля. Выборка осуществляется сигналом декодера `wb_sel_o`.
### Интерфейс памяти ### Интерфейс памяти
@@ -119,7 +136,7 @@
Несмотря на то, что для записи во внешнюю память ключевыми сигналами будут описанные выше, это не означает, что остальные выходные сигналы декодера могут быть абы какими. Несмотря на то, что для записи во внешнюю память ключевыми сигналами будут описанные выше, это не означает, что остальные выходные сигналы декодера могут быть абы какими.
Поскольку операция `lw` не является операцией перехода, сигналы `jal_o`, `jalr_o` и `branch_o` должны быть равны нулю (иначе процессор совершит переход, а инструкция `lw` этого не подразумевает). Точно так же, поскольку во время записи во внешнюю память, в регистровый файл не должно быть ничего записано, сигнал `gpr_we_o` так же должен быть равен нулю. Поскольку операция `lw` не является операцией перехода, сигналы `jal_o`, `jalr_o` и `branch_o` должны быть равны нулю (иначе процессор совершит переход, а инструкция `lw` этого не подразумевает). Точно так же, поскольку во время записи во внешнюю память, в регистровый файл не должно быть ничего записано, сигналы `gpr_we_o` и `csr_we_o` так же должны быть равны нулю.
А вот сигнал `wb_sel` может принять любое значение (поскольку сигнал разрешения записи в регистровый файл равен нулю, не важно, каким будет источник данных для записи в регистровый файл, т.к. в него все равно ничего не будет записано). А вот сигнал `wb_sel` может принять любое значение (поскольку сигнал разрешения записи в регистровый файл равен нулю, не важно, каким будет источник данных для записи в регистровый файл, т.к. в него все равно ничего не будет записано).
@@ -131,6 +148,8 @@
|a_sel_o |Управляющий сигнал мультиплексора для выбора первого операнда АЛУ | |a_sel_o |Управляющий сигнал мультиплексора для выбора первого операнда АЛУ |
|b_sel_o |Управляющий сигнал мультиплексора для выбора второго операнда АЛУ | |b_sel_o |Управляющий сигнал мультиплексора для выбора второго операнда АЛУ |
|alu_op_o |Операция АЛУ | |alu_op_o |Операция АЛУ |
|csr_op_o |Операция модуля CSR |
|csr_we_o |Разрешение на запись в CSR |
|mem_req_o |Запрос на доступ к памяти (часть интерфейса памяти) | |mem_req_o |Запрос на доступ к памяти (часть интерфейса памяти) |
|mem_we_o |Сигнал разрешения записи в память, «write enable» (при равенстве нулю происходит чтение) | |mem_we_o |Сигнал разрешения записи в память, «write enable» (при равенстве нулю происходит чтение) |
|mem_size_o |Управляющий сигнал для выбора размера слова при чтении-записи в память (часть интерфейса памяти)| |mem_size_o |Управляющий сигнал для выбора размера слова при чтении-записи в память (часть интерфейса памяти)|
@@ -140,6 +159,7 @@
|branch_o |Сигнал об инструкции условного перехода | |branch_o |Сигнал об инструкции условного перехода |
|jal_o |Сигнал об инструкции безусловного перехода jal | |jal_o |Сигнал об инструкции безусловного перехода jal |
|jalr_o |Сигнал об инструкции безусловного перехода jalr | |jalr_o |Сигнал об инструкции безусловного перехода jalr |
|mret_o |Сигнал об инструкции возврата из прерывания/исключения mret |
Единственным входным сигналом этого модуля является `fetched_instr_i`. Единственным входным сигналом этого модуля является `fetched_instr_i`.
@@ -148,22 +168,23 @@
- неравенства двух младших битов opcode значению `11`; - неравенства двух младших битов opcode значению `11`;
- некорректного значения `func3` или `func7` для данной операции; - некорректного значения `func3` или `func7` для данной операции;
- если значение `opcode` не совпадает ни с одним из известных и следовательно операция не определена. - если значение `opcode` не совпадает ни с одним из известных и следовательно операция не определена.
- если это инструкция `ECALL` / `EBREAK`.
При реализации декодера его удобнее описывать разбив все инструкции на однотипные группы, как это сделано ниже. Коды операций в таблице 5-битные потому, что 2 младших бита полноценного 7-битного кода операции должны отдельно проверяться и быть равны `11` При реализации декодера его удобнее описывать разбив все инструкции на однотипные группы, как это сделано ниже. Коды операций в таблице 5-битные потому, что 2 младших бита полноценного 7-битного кода операции должны отдельно проверяться и быть равны `11`
|Операция|Opcode| Описание операции | Краткая запись | |Операция|Opcode| Описание операции | Краткая запись |
|--------|------|----------------------------------------------------------------------------------------------|------------------------------------| |--------|------|-------------------------------------------------------------------------------------------------------|------------------------------------|
|OP |01100 |Записать в `rd` результат вычисления АЛУ над `rs1` и `rs2` |`rd = alu_op(rs1, rs2)` | |OP |01100 |Записать в `rd` результат вычисления АЛУ над `rs1` и `rs2` |`rd = alu_op(rs1, rs2)` |
|OP_IMM |00100 |Записать в `rd` результат вычисления АЛУ над `rs1` и `imm` |`rd = alu_op(rs1, imm)` | |OP_IMM |00100 |Записать в `rd` результат вычисления АЛУ над `rs1` и `imm` |`rd = alu_op(rs1, imm)` |
|LUI |01101 |Записать в `rd` значение непосредственного операнда U-типа `imm_u` |`rd = imm << 12` | |LUI |01101 |Записать в `rd` значение непосредственного операнда U-типа `imm_u` |`rd = imm << 12` |
|LOAD |00000 |Записать в `rd` данные из памяти по адресу `rs1+imm` |`rd = Mem[rs1 + imm]` | |LOAD |00000 |Записать в `rd` данные из памяти по адресу `rs1+imm` |`rd = Mem[rs1 + imm]` |
|STORE |01000 |Записать в память по адресу `rs1+imm` данные из `rs2` |`Mem[rs1 + imm] = rs2` | |STORE |01000 |Записать в память по адресу `rs1+imm` данные из `rs2` |`Mem[rs1 + imm] = rs2` |
|BRANCH |11000 |Увеличить счетчик команд на значение `imm`, если верен результат сравнения `rs1` и `rs2` |`if cmp_op(rs1, rs2) then PC += imm`| |BRANCH |11000 |Увеличить счетчик команд на значение `imm`, если верен результат сравнения `rs1` и `rs2` |`if cmp_op(rs1, rs2) then PC += imm`|
|JAL |11011 |Записать в `rd` следующий адрес счетчика команд, увеличить счетчик команд на значение `imm` |`rd = PC + 4; PC += imm` | |JAL |11011 |Записать в `rd` следующий адрес счетчика команд, увеличить счетчик команд на значение `imm` |`rd = PC + 4; PC += imm` |
|JALR |11001 |Записать в `rd` следующий адрес счетчика команд, в счетчик команд записать `rs1+imm` |`rd = PC + 4; PC = rs1+imm` | |JALR |11001 |Записать в `rd` следующий адрес счетчика команд, в счетчик команд записать `rs1+imm` |`rd = PC + 4; PC = rs1+imm` |
|AUIPC |00101 |Записать в `rd` результат сложения непосредственного операнда U-типа `imm_u` и счетчика команд|`rd = PC + (imm << 12)` | |AUIPC |00101 |Записать в `rd` результат сложения непосредственного операнда U-типа `imm_u` и счетчика команд |`rd = PC + (imm << 12)` |
|MISC-MEM|00011 |Не производить операцию | `-` | |MISC-MEM|00011 |Не производить операцию | `-` |
|SYSTEM |11100 |Не производить операцию | `-` | |SYSTEM |11100 |Записать в `rd` значение `csr`. Обновить значение `csr` с помощью `rs1`. (либо `mret`/`ecall`/`ebreak`)|`csr = csr_op(rs1); rd = csr` |
## Инструменты ## Инструменты
@@ -225,15 +246,18 @@ module decoder_riscv (
output logic [1:0] a_sel_o, output logic [1:0] a_sel_o,
output logic [2:0] b_sel_o, output logic [2:0] b_sel_o,
output logic [4:0] alu_op_o, output logic [4:0] alu_op_o,
output logic [2:0] csr_op_o,
output logic csr_we_o,
output logic mem_req_o, output logic mem_req_o,
output logic mem_we_o, output logic mem_we_o,
output logic [2:0] mem_size_o, output logic [2:0] mem_size_o,
output logic gpr_we_o, output logic gpr_we_o,
output logic wb_sel_o, //write back selector output logic [1:0] wb_sel_o, //write back selector
output logic illegal_instr_o, output logic illegal_instr_o,
output logic branch_o, output logic branch_o,
output logic jal_o, output logic jal_o,
output logic jalr_o output logic jalr_o,
output logic mret
); );
import riscv_pkg::*; import riscv_pkg::*;