Уровень 53: Шаг на четыре
Задание
Цель: собрать путь счётчика команд: каждый такт pc = pc + 4, а когда beq берётся (branch & zero) — pc = pc + смещение. База смещения — адрес САМОЙ ветки, смещение задано в байтах (не в словах!), и оно разрезано по слову команды B-формата — разрезает его BImm32. Сумматор add32.v уже готов с уровня 50 — просто инстанцируйте его дважды. Во вкладке «Ассемблер» теперь beq с метками.
До этого PC просто шагал вперёд. Каждая команда занимает 4 байта, поэтому шаг равен четырём. Теперь вы научите процессор менять маршрут: если условие выполнено — прыгнуть, если нет — сделать обычный шаг на четыре.
Что добавляется:
- PC+4 и PC+imm. Сумматор адреса ветки:
PC + imm, где imm — знаковое смещение в байтах. МультиплексорPCSrcвыбирает между ними по сигналу ветки. - B-формат. Смещение 13 бит (с чётным шагом, младший бит всегда 0) разрезано в слове команды на два куска — и не подряд:
imm[12|10:5]в старшем байте иimm[4:1|11]ниже. Разобрать это разрезание — главная головоломка уровня. - beq. Условие берётся из АЛУ: вычитание rs1 − rs2; если результат — ноль, регистры равны. АЛУ уровня 50 уже выдаёт сигнал zero — он наконец находит работу.
- Метки в ассемблере. К ассемблеру добавляется B-кодирование и метки:
beq x5, x6, loop— ассемблер сам считает байтовое смещение до метки.
Проверка: трасса исполнения + предсказание «куда перейдёт beq» — вперёд или назад, и на какой адрес.
Решение для самопроверки
Сначала проследите последовательность команд с веткой по тактам. Решение ниже поможет свериться.
Что должно получиться: beq верен в обоих направлениях: условие истинно — PC стал PC + imm (база — адрес самой ветки), ложно — PC + 4; трасса исполнения и предсказание «куда прыгнет beq» сходятся.
Шаг 1 — соберите смещение. Куски собираются в 13-битное число: {imm[12], imm[10:5], imm[4:1], 1'b0}, затем sign-extend до 32 бит. Младший бит нулевой всегда — все инструкции выровнены по 4 байта, смещение чётное. Перепутанные куски дают переход «куда-то не туда»: негативный тест уровня именно это и ловит.
Шаг 2 — выберите базу адреса. Смещение считается от PC текущей команды ветки, а не от «следующей» и не от нуля. Вторая классическая ошибка — смещение в словах вместо байтов: метка на 2 команды дальше — это +8 байт, а не +2.
Шаг 3 — подключите условие. АЛУ вычитает rs1 − rs2; сигнал zero означает равенство. Сигнал ветки = Branch & zero — он управляет PCSrc. Обратите внимание: вычитание для сравнения не портит регистры — результат АЛУ у ветки просто не записывается в rd.
Шаг 4 — проверьте оба направления. Переход вперёд (метка ниже по коду) и назад (метка выше — так будут выглядеть циклы). Для каждого случая проверьте: условие истинно — PC стал равен PC + imm; условие ложно — PC стал равен PC + 4.
Принцип: условный переход не изменяет порядок команд в памяти. Он изменяет адрес, по которому процессор продолжит чтение инструкций.
Проверь себя
Почему смещение B-формата разрезано непоследовательно?
Это цена компактной команды: биты смещения разложены в фиксированные поля (imm[12|10:5] в старшем байте, imm[4:1|11] ниже), общие для всех B-команд. Младший бит всегда 0 — инструкции выровнены по 4 байта, смещение чётное.