RISC Lab: уровни 48–67
В разработке. Уровни 48–67 заявлены в карте уровней и программе курса, но ещё не играбельны; сроки не объявлены. Этот обзор описывает учебную траекторию для планирования, а не готовые задания. Публичная страница модуля: хаб «Микроархитектура RISC».
Главная идея части 5
Первые 47 уровней дают ученику одну модель процессора: машину с одним аккумулятором, машинные команды и Verilog. Пятая часть переводит его на другую модель. Сначала школьник строит и понимает простой 32-битный RISC-процессор, выполняющий команды последовательно (48–60), затем разбирается, как ускорить его конвейером, сохранив правильность программ (61–67).
Часть начинается не с форматов инструкций, а с вопроса «зачем понадобилась другая архитектура». Уровень 48 ставит старую и новую машины рядом: одну и ту же арифметическую задачу ученик решает дважды и сам видит, что даёт набор регистров вместо одного аккумулятора.
Три этапа
- 48–51. От аккумулятора к RISC. Отдельные компоненты: регистровая модель, регистровый файл, 32-битное АЛУ, константа внутри команды.
- 52–60. От блоков к работающему процессору. Память, ветвления, циклы, функции, сборка полного однотактного ядра учебного RV32I-подмножества и вывод его на плату.
- 61–67. От последовательного исполнения к конвейеру. Пять стадий, конвейерные регистры, конфликты данных и управления, измерение ускорения.
Этап 1–2: однотактное ядро (48–60)
- 48 «Прощай, аккумулятор!» Сравнение аккумуляторной и регистровой машин на одной задаче. Ученик записывает 42 в
x5, пробует изменитьx0и убеждается, что там всегда ноль, читает два регистра через два порта одновременно. Цель: понять, зачем нужна регистровая архитектура, до разговоров о форматах команд. - 49 «Анатомия R-команды» Команда
add x5, x6, x7разбирается на поляrd,rs1,rs2. Ученик собирает RegFile32: 32 регистра, декодер записи, два порта чтения; запись происходит по фронту такта,x0изменить нельзя. - 50 «АЛУ на 32 бита» Знакомый сумматор переносится на 32 бита. Арифметика (сложение, вычитание), логика (AND, OR, XOR), сдвиги, знаковое и беззнаковое сравнение, флаг Zero для будущих ветвей. Проверка на граничных значениях.
- 51 «Константа внутри команды» Команда
addi x1, x0, -1: второй операнд лежит прямо в машинном слове. Ученик собирает SignExt32 (12 бит расширяются до 32 со знаком), разбирает I-формат, вручную раскладывает команду на поля и сверяет результат с мини-ассемблером. - 52 «Память по правилам» Load/store-архитектура: арифметика работает только с регистрами, с памятью её связывают команды
lwиsw. Адрес считается в АЛУ из регистра и смещения; выравнивание по четыре байта. Здесь ученик впервые выходит за пределы регистрового файла. - 53 «Шаг на четыре» PC+4 и первая условная ветвь BEQ: смещение в B-формате разрезано на части машинного слова. Ученик прослеживает, как меняется PC при переходе и при обычном выполнении.
- 54 «Цикл на BNE» Счётчик, сравнение и BNE: первый цикл на собственной машине. Перед запуском ученик предсказывает число тактов, потом сверяет прогноз с трассой.
- 55 «Сумма массива» Настоящая программа: база массива собирается через LUI+ADDI, проход по элементам через LW, сумма накапливается в регистре. Программа использует сразу память, ветвление и арифметику.
- 56 «Вызов и возврат» JAL и JALR: адрес возврата кладётся в
ra. Ученик пишет небольшую функцию, вызывает её и возвращается; вложенный вызов требует сохранитьraв памяти. Так появляется понятие стека. - 57 «Вложенные вызовы и стек» Одного
raна один вызов: функция A вызывает B — и адрес возврата затёрт. Ученик пишет пролог и эпилог (сохранение и восстановлениеraчерезsw/lw), инициализируетspи собирает вложенный вызов main → A → B: кадр растёт в памяти вниз, от старшего адреса к младшему. Защитное слово ниже стека ловит переполнение ошибкойERR_DATA_ADDRESS_FORBIDDEN. - 58 «Собираем RV32I» Полное однотактное ядро учебного RV32I-подмножества: PC, память команд, декодер, регистровый файл, АЛУ, память данных, управление. Ученик соединяет блоки, подключает управляющие сигналы и запускает программы разных типов.
- 59 «Knight Rider RISC» Бегущая строка на светодиодах через memory-mapped I/O и экспорт проекта для Tang Nano 9K. Процессор из симулятора получает физический выход, по образцу части 4.
- 60 «Лаборатория верификации» Сценарная проверка: ученик сам формулирует воздействия и ожидания, проверяет промежуточные состояния и ловит подсаженный баг — тест, который проходит и на правильной, и на сломанной схеме, ничего не проверяет.
Контрольная точка после уровней 58–59. Ученик должен не просто запустить программу, а объяснить прохождение конкретной инструкции через процессор: что сделает декодер, какие управляющие сигналы откроются, куда пойдёт результат. Хорошая проверка: одна и та же программа (счётчик, Фибоначчи, сумма массива) даёт одинаковый результат на полном ядре и падает на нём же при отключённом forwarding, stall или flush — эти режимы пригодятся на третьем этапе.
Этап 3: конвейер (61–67)
- 61 «Почему такт длинный» Критический путь однотактной машины: за один такт инструкция проходит все блоки подряд, и такт длинный. Отсюда карта пяти стадий IF, ID, EX, MEM, WB и идея разбить путь на участки.
- 62 «Между стадиями» Четыре конвейерных регистра IF/ID, ID/EX, EX/MEM, MEM/WB: данные, управляющие сигналы и номер
rdедут вместе. Ученик прослеживает, какие значения передаются между стадиями. - 63 «Пять команд в полёте» Чтение трассы: каскадная диаграмма, заполнение и опустошение конвейера, положение каждой команды на такте k. Конвейер заполняется не мгновенно: на краях выполнения есть накладные расходы, зато в середине машина завершает примерно одну инструкцию за такт. Отдельная инструкция при этом не становится быстрее.
- 64 «Короткий путь» Зависимая пара
add x5, x6, x7/sub x8, x5, x9: вторая команда хочет прочитатьx5раньше, чем первая записала результат. RAW-конфликт и forwarding: результат идёт к АЛУ напрямую из поздней стадии, минуя запись в регистровый файл; для выбора источника нужны проверки зависимостей. - 65 «Пузырь загрузки» Пара
lw x5, 0(x6)/add x7, x5, x8: forwarding не успевает, потому что результатlwпоявляется слишком поздно. Ученик реализует обнаружение load-use и остановку конвейера ровно на один такт; остановка не должна терять или повторять инструкции. - 66 «Призраки неверного пути» Условный переход: конвейер уже выбрал следующие инструкции, а условие ещё не разрешено. Flush удаляет команды неверно выбранного пути до того, как они изменят архитектурное состояние. Ученик проверяет условные и безусловные переходы и считает цену каждого взятого перехода.
- 67 «Knight Rider Pipeline» Финальное конвейерное ядро: одна программа на однотактной и конвейерной машине, сравнение числа тактов с учётом остановок и сбросов, расчёт CPI, экспорт ZIP. Опорные формулы:
Texec = Cycles × Tclk, для пяти стадий без особых ситуацийCycles = Nretired + 4; сверху добавляются потерянные такты от stall и flush, считать нужно именно потерянные такты, а не число вставленных пузырей.
Контрольная точка после уровня 67. Ученик обосновывает ускорение расчётом и объясняет, почему на конкретной программе оно может оказаться небольшим: зависимости и переходы добавляют такты, а производительность определяется и числом тактов, и длительностью каждого такта.
Методическая граница
Цель части 5 — не «выучить архитектуру RISC-V». Цель точнее: ученик самостоятельно понимает устройство, работу и ограничения учебного 32-битного RISC-процессора, реализующего выбранное подмножество RV32I, а затем разбирается, как его ускоряет пятистадийный конвейер.
Две вершины стоит оценивать отдельно. К концу однотактного этапа (58) ученик уже построил настоящий процессор и имеет право считать задачу выполненной. Конвейер (61–67) — отдельная вершина: как он меняет работу машины, какие новые проблемы создаёт и как измеряется реальное ускорение. Не делайте конвейер обязательным условием признания результата на 58.
Вопросы для обсуждения
- Чем регистровая машина лучше аккумуляторной для выражения
a = (b + c) × (d − e)? Сколько команд и промежуточных записей в памяти нужно каждой модели? - Зачем архитекторы «потратили» один регистр на постоянный ноль? Какие команды упрощаются благодаря
x0? - Почему в B-формате смещение разрезано на части, а не лежит одним куском? Что это экономит в аппаратуре?
- Что случится, если убрать запись по фронту такта из регистрового файла и писать сразу?
- Почему forwarding спасает пару «сложение, затем вычитание», но не пару «загрузка, затем сложение»? Нарисуйте стадии обеих пар.
- Конвейер завершает около одной инструкции за такт. Значит ли это, что каждая инструкция выполняется за один такт?
Критерии оценки
- Вершина 1 (к уровню 59). Собрал: однотактное ядро запускает программу с памятью, ветвлением и вызовом функции. Объяснил: прослеживает одну инструкцию через все блоки и называет управляющие сигналы. Перенёс: объясняет, что изменится в ядре при добавлении новой инструкции.
- Вершина 2 (к уровню 67). Собрал: конвейерное ядро проходит ту же программу. Объяснил: читает каскадную диаграмму, называет конфликт по диаграмме (RAW, load-use, control) и способ его обработки. Перенёс: считает CPI для новой программы с учётом stall и flush и предсказывает, где ускорение будет малым.
- На протяжении части. Прогноз до запуска: на уровнях 54 и 63 ученик сначала предсказывает поведение машины (число тактов, диаграмму), потом сверяет с трассой. Держите этот ритм: расхождение прогноза с наблюдением — лучший повод для разбора.
Материалы
- Хаб «Микроархитектура RISC» — публичная страница модуля с картой всех 20 уровней.
- Программа курса — таймлайн, часть 5 помечена как анонс.
- Гайды уровней 48–67 появятся в списке гайдов по мере выпуска уровней.