diff --git a/.pic/Labs/lab_05_decoder/rv32i_BIS.png b/.pic/Labs/lab_05_decoder/rv32i_BIS.png index efe3fa4..f32b3ec 100644 Binary files a/.pic/Labs/lab_05_decoder/rv32i_BIS.png and b/.pic/Labs/lab_05_decoder/rv32i_BIS.png differ diff --git a/.pic/Labs/lab_05_decoder/rv32i_summary.png b/.pic/Labs/lab_05_decoder/rv32i_summary.png index ee25aeb..ce7cd5b 100644 Binary files a/.pic/Labs/lab_05_decoder/rv32i_summary.png and b/.pic/Labs/lab_05_decoder/rv32i_summary.png differ diff --git a/.pic/Labs/lab_05_decoder/rv32i_summary.xlsx b/.pic/Labs/lab_05_decoder/rv32i_summary.xlsx index f7719ef..39101bf 100644 Binary files a/.pic/Labs/lab_05_decoder/rv32i_summary.xlsx and b/.pic/Labs/lab_05_decoder/rv32i_summary.xlsx differ diff --git a/Labs/05. Main decoder/README.md b/Labs/05. Main decoder/README.md index 9c0d7f5..4ce0b3c 100644 --- a/Labs/05. Main decoder/README.md +++ b/Labs/05. Main decoder/README.md @@ -37,7 +37,9 @@ ![../../.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* -### Неподдерживаемые инструкции +### SYSTEM-инструкции -В базовом наборе инструкций **RISC-V** к операциям `SYSTEM` относятся `ECALL` и `EBREAK`, к операциям `MISC-MEM` – операция `FENCE`. В реализуемом процессорном ядре эти инструкции не должны приводить ни к каким изменениям. Иначе говоря, они должны быть реализованы как инструкция `NOP` (**no operation**). -Инструкция `FENCE` в **RISC-V** необходима при работе с несколькими аппаратными потоками, или хартами (hart – «hardware thread»). В **RISC-V** используется расслабленная модель памяти (**relaxed memory model**): потоки «видят» все инструкции чтения и записи, которые исполняются другими потоками, однако видимый порядок этих инструкций может отличаться от реального. Инструкция `FENCE`, использованная между двумя инструкциями чтения и/или записи гарантирует, что остальные потоки увидят первую инструкцию перед второй. Реализация `FENCE` является опциональной в **RISC-V** и в данном случае в ней нет необходимости, так как в системе не предполагается наличия нескольких аппаратных потоков. -Инструкции `ECALL` и `EBREAK` должны вызывать исключение с последующим переходом в обработчик исключения (вызова операционной системы и перехода в привилегированный режим работы). Помимо этого, их вызов должен обновить содержимое некоторых управляющих регистров (**Control & Status Registers** – **CSR**). На текущий момент эти инструкции не будут использоваться, а потому могут быть реализованы как `NOP`. +SYSTEM-инструкции используются для доступа к системным функциям и могут требовать привилегированный доступ. Данные инструкции могут быть разделены на два класса: -Список инструкций с указанием их типов и функциональным назначением: +- Обращение к регистрам статуса и контроля (**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) @@ -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` из прошлой лабораторной имеет схожую структуру, с некоторыми изменениями. -В первую очередь изменились входы и выходы процессора: +В первую очередь изменились входы и выходы процессора (помимо появления двух непонятных модулей): - память инструкций вынесена наружу процессора, таким образом, у процессора появляются входы и выходы: `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`). -Изменилось и число источников записи в регистровый файл: их осталось два: результат операции на АЛУ и данные, считанные с внешней памяти. Выборка осуществляется сигналом декодера `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` может принять любое значение (поскольку сигнал разрешения записи в регистровый файл равен нулю, не важно, каким будет источник данных для записи в регистровый файл, т.к. в него все равно ничего не будет записано). @@ -131,6 +148,8 @@ |a_sel_o |Управляющий сигнал мультиплексора для выбора первого операнда АЛУ | |b_sel_o |Управляющий сигнал мультиплексора для выбора второго операнда АЛУ | |alu_op_o |Операция АЛУ | +|csr_op_o |Операция модуля CSR | +|csr_we_o |Разрешение на запись в CSR | |mem_req_o |Запрос на доступ к памяти (часть интерфейса памяти) | |mem_we_o |Сигнал разрешения записи в память, «write enable» (при равенстве нулю происходит чтение) | |mem_size_o |Управляющий сигнал для выбора размера слова при чтении-записи в память (часть интерфейса памяти)| @@ -140,6 +159,7 @@ |branch_o |Сигнал об инструкции условного перехода | |jal_o |Сигнал об инструкции безусловного перехода jal | |jalr_o |Сигнал об инструкции безусловного перехода jalr | +|mret_o |Сигнал об инструкции возврата из прерывания/исключения mret | Единственным входным сигналом этого модуля является `fetched_instr_i`. @@ -148,22 +168,23 @@ - неравенства двух младших битов opcode значению `11`; - некорректного значения `func3` или `func7` для данной операции; - если значение `opcode` не совпадает ни с одним из известных и следовательно операция не определена. +- если это инструкция `ECALL` / `EBREAK`. При реализации декодера его удобнее описывать разбив все инструкции на однотипные группы, как это сделано ниже. Коды операций в таблице 5-битные потому, что 2 младших бита полноценного 7-битного кода операции должны отдельно проверяться и быть равны `11` -|Операция|Opcode| Описание операции | Краткая запись | -|--------|------|----------------------------------------------------------------------------------------------|------------------------------------| -|OP |01100 |Записать в `rd` результат вычисления АЛУ над `rs1` и `rs2` |`rd = alu_op(rs1, rs2)` | -|OP_IMM |00100 |Записать в `rd` результат вычисления АЛУ над `rs1` и `imm` |`rd = alu_op(rs1, imm)` | -|LUI |01101 |Записать в `rd` значение непосредственного операнда U-типа `imm_u` |`rd = imm << 12` | -|LOAD |00000 |Записать в `rd` данные из памяти по адресу `rs1+imm` |`rd = Mem[rs1 + imm]` | -|STORE |01000 |Записать в память по адресу `rs1+imm` данные из `rs2` |`Mem[rs1 + imm] = rs2` | -|BRANCH |11000 |Увеличить счетчик команд на значение `imm`, если верен результат сравнения `rs1` и `rs2` |`if cmp_op(rs1, rs2) then PC += imm`| -|JAL |11011 |Записать в `rd` следующий адрес счетчика команд, увеличить счетчик команд на значение `imm` |`rd = PC + 4; PC += imm` | -|JALR |11001 |Записать в `rd` следующий адрес счетчика команд, в счетчик команд записать `rs1+imm` |`rd = PC + 4; PC = rs1+imm` | -|AUIPC |00101 |Записать в `rd` результат сложения непосредственного операнда U-типа `imm_u` и счетчика команд|`rd = PC + (imm << 12)` | -|MISC-MEM|00011 |Не производить операцию | `-` | -|SYSTEM |11100 |Не производить операцию | `-` | +|Операция|Opcode| Описание операции | Краткая запись | +|--------|------|-------------------------------------------------------------------------------------------------------|------------------------------------| +|OP |01100 |Записать в `rd` результат вычисления АЛУ над `rs1` и `rs2` |`rd = alu_op(rs1, rs2)` | +|OP_IMM |00100 |Записать в `rd` результат вычисления АЛУ над `rs1` и `imm` |`rd = alu_op(rs1, imm)` | +|LUI |01101 |Записать в `rd` значение непосредственного операнда U-типа `imm_u` |`rd = imm << 12` | +|LOAD |00000 |Записать в `rd` данные из памяти по адресу `rs1+imm` |`rd = Mem[rs1 + imm]` | +|STORE |01000 |Записать в память по адресу `rs1+imm` данные из `rs2` |`Mem[rs1 + imm] = rs2` | +|BRANCH |11000 |Увеличить счетчик команд на значение `imm`, если верен результат сравнения `rs1` и `rs2` |`if cmp_op(rs1, rs2) then PC += imm`| +|JAL |11011 |Записать в `rd` следующий адрес счетчика команд, увеличить счетчик команд на значение `imm` |`rd = PC + 4; PC += imm` | +|JALR |11001 |Записать в `rd` следующий адрес счетчика команд, в счетчик команд записать `rs1+imm` |`rd = PC + 4; PC = rs1+imm` | +|AUIPC |00101 |Записать в `rd` результат сложения непосредственного операнда U-типа `imm_u` и счетчика команд |`rd = PC + (imm << 12)` | +|MISC-MEM|00011 |Не производить операцию | `-` | +|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 [2:0] b_sel_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_we_o, output logic [2:0] mem_size_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 branch_o, output logic jal_o, - output logic jalr_o + output logic jalr_o, + output logic mret ); import riscv_pkg::*;