Синхронизация с правками публикуемого издания (#101)

* СП. Обновление предисловия

* СП. Обновление введения

* СП. Обновление лаб

* СП. Обновление доп материалов

* СП. Введение

* СП. Введение

* СП. ЛР№4, 15

* СП. Базовые конструкции Verilog

* Update Implementation steps.md

* СП. ЛР 4,5,7,8,14

* СП. ЛР№8

* Синхронизация правок

* СП. Финал

* Исправление ссылки на рисунок

* Обновление схемы

* Синхронизация правок

* Добавление белого фона .drawio-изображениям

* ЛР2. Исправление нумерации рисунка
This commit is contained in:
Andrei Solodovnikov
2025-02-12 17:53:52 +03:00
committed by GitHub
parent d251574bbc
commit 9739429d6e
168 changed files with 79781 additions and 961 deletions

View File

@@ -104,15 +104,15 @@ logic [63:0] system_counter_at_start;
- `delay` — регистр, ассоциированный с адресами `0x08` (младшие 32 бита) и `0x0c` (старшие 32 бита). Число тактов, спустя которое таймер (когда тот будет включен) сгенерирует прерывание. Данный регистр изменяется только сбросом, либо запросом на запись.
- `mode` — регистр, ассоциированный с адресом `0x10`. Режим работы таймера:
- `OFF` — отключен (не генерирует прерывания)
- `NTIMES` — включен до тех пор, пока не сгенерирует N прерываний (Значение N хранится в регистре `repeat_counter` и обновляется после каждого сгенерированного прерывания). После генерации N прерываний, переходит в режим `OFF`.
- `NTIMES` — включен до тех пор, пока не сгенерирует N прерываний (значение N хранится в регистре `repeat_counter` и обновляется после каждого сгенерированного прерывания). После генерации N прерываний, переходит в режим `OFF`.
- `FOREVER` — бесконечная генерация прерываний. Не отключится, пока режим работы прерываний не будет изменен.
- `next_mode` — комбинационный сигнал, который подается на вход записи в регистр `mode` (аналог `next_state` из ЛР№15). Данный сигнал меняется только запросами на запись по адресу `0x10` или в случае, если `repeat_counter == 0` в режиме `NTIMES`. Поскольку этому сигналу можно присваивать только значения сигналов такого же типа (`timer_mods`), либо константы из перечисления, запросы на запись можно реализовать через блок `case` (где перебираются 3 возможных значения `write_data_i`).
- `next_mode` — комбинационный сигнал, который подается на вход записи в регистр `mode` (аналог `next_state` из ЛР№15). Данный сигнал меняется только запросами на запись по адресу `0x10` или в случае, если `repeat_counter == 0` в режиме `NTIMES`. Поскольку этому сигналу можно присваивать только сигналы того же типа (`mode`/`next_mode`), либо константы из перечисления, запросы на запись можно реализовать через блок `case` (где перебираются 3 возможных значения `write_data_i`).
- `repeat_counter` — регистр, ассоциированный с адресом `0x14`. Количество повторений для режима `NTIMES`. Уменьшается в момент генерации прерывания в этом режиме в случае, если еще не равен нулю.
- `system_counter_at_start` — неархитектурный регистр, хранящий значение системного счётчика на момент начала отсчета таймера. Обновляется при генерации прерывания (если это не последнее прерывание в режиме `NTIMES`) и при запросе на запись в регистр `mode` значения не `OFF`.
Выходной сигнал interrupt_request_o должен быть равен единице, если текущий режим работы не `OFF`, а сумма `system_counter_at_start` и `delay` равна `system_counter`.
Для подключения данного таймера к системной шине, мы воспользуемся первым свободным базовым адресом, оставшимся после ЛР13: `0x08`. Таким образом, для обращения к системному счётчику, процессор будет использовать адрес `0x08000000` для обращения к регистру `delay` `0x08000008` и т.п.
Для подключения данного таймера к системной шине, мы воспользуемся первым свободным базовым адресом, оставшимся после ЛР13: `0x08`. Таким образом, для обращения к системному счётчику, процессор будет использовать адрес `0x08000000` для обращения к регистру `delay` `0x08000008` и т.п.
### Настройка Coremark
@@ -144,7 +144,7 @@ barebones_clock()
_Листинг 2. Код функции `barebones_clock`._
После ЛР14 вы уже должны представлять, что здесь происходит. Мы создали указатель с абсолютным адресом `0x08000000` — адресом системного счётчика. Разыменование данного указателя вернет текущее значение системного счётчика, что и должно быть результатом вызова этой функции. Поскольку тест закончится менее чем за секунду, не обязательно загружать значение старших 32 бит (они будут не равны нулю только спустя 2³²тактов / 10⁶тактов/с ≈ 429c).
После ЛР14 вы уже должны представлять, что здесь происходит. Мы создали указатель с абсолютным адресом `0x08000000` — адресом системного счётчика. Разыменование данного указателя вернет текущее значение системного счётчика, что и должно быть результатом вызова этой функции. Поскольку тест закончится менее чем за секунду, не обязательно загружать значение старших 32 бит (они будут не равны нулю только спустя 2³²тактов / 10⁶тактов/с ≈ 429c).
Для того, чтобы корректно преобразовать тики системного счётчика во время, используется функция [`time_in_secs`](https://github.com/eembc/coremark/blob/d5fad6bd094899101a4e5fd53af7298160ced6ab/barebones/core_portme.c#L117), которая уже реализована, но для работы которой нужно определить макрос `CLOCKS_PER_SEC`, характеризующий тактовую частоту, на которой работает процессор. Давайте определим данный макрос сразу над макросом [`EE_TICKS_PER_SEC`](https://github.com/eembc/coremark/blob/d5fad6bd094899101a4e5fd53af7298160ced6ab/barebones/core_portme.c#L62):
@@ -178,7 +178,7 @@ uart_send_char(char c)
_Листинг 3. Код функции `uart_send_char_`._
`0x06000000` — базовый адрес контроллера UART TX из ЛР13 (и адрес передаваемых этим контроллером данных).
`0x06000000` — базовый адрес контроллера UART TX из ЛР13 (и адрес передаваемых этим контроллером данных).
`0x08` — смещение до адреса регистра `busy` в адресном пространстве этого контроллера.
#### 3. Реализация функции первичной настройки
@@ -268,7 +268,7 @@ _Листинг 5. Последовательность команд для ко
### Запуск моделирования
Программирование 32KiB по UART займет ощутимое время, поэтому вам предлагается проинициализировать память инструкций и данных "по-старинке" через системные функции `$readmemh`.
Программирование 34KiB по UART займет ощутимое время, поэтому вам предлагается проинициализировать память инструкций и данных "по-старинке" через системные функции `$readmemh`.
Если все было сделано без ошибок, то примерно через `300ms` после снятия сигнала сброса с ядра процессора выход `tx_o` начнет быстро менять свое значение, сигнализируя о выводе результатов программы, которые отобразятся в `tcl console` примерно еще через `55ms` в виде _листинга 6_ (вывод сообщения будет завершен приблизительно на `355ms` времени моделирования).
@@ -301,7 +301,7 @@ _Листинг 6. Лог вывода результатов coremark. Знач
1. Ко входу `rst_i` модуля подключите сигнал `core_reset_o` программатора. Таким образом, системный счётчик начнет работать только когда память системы будет проинициализирована.
2. Сигнал прерывания этого модуля подключать не обязательно, т.к. coremark будет осуществлять чтение путем опроса системного счётчика, а не по прерыванию.
4. В случае, если до этого в Л№Р13 вашим устройством вывода было не UART TX, вам необходимо подключить к системной шине готовый модуль [uart_tx_sb_ctrl](../Made-up%20modules/lab_13.uart_tx_sb_ctrl.sv).
5. Получите исходники программы coremark. Для этого можно либо склонировать [репозиторий](https://github.com/eembc/coremark/tree/d5fad6bd094899101a4e5fd53af7298160ced6ab), либо скачать его в виде архива.
5. Получите исходный код программы coremark. Для этого можно либо склонировать [репозиторий](https://github.com/eembc/coremark/tree/d5fad6bd094899101a4e5fd53af7298160ced6ab), либо скачать его в виде архива.
6. Добавьте реализацию платформозависимых функций программы coremark. Для этого в папке `barebones` необходимо:
1. в файле `core_portme.c`:
1. [реализовать](#1-реализация-функции-измеряющей-время) функцию `barebones_clock`, возвращающую текущее значение системного счётчика;
@@ -311,7 +311,7 @@ _Листинг 6. Лог вывода результатов coremark. Знач
7. Добавьте с заменой в корень программы файлы [Makefile](Makefile), [linker_script.ld](linker_script.ld) и [startup.S](../14.%20Programming/startup.S).
8. Скомпилируйте программу вызовом `make`.
1. Если кросскомпилятор расположен не в директории `C:/riscv_cc`, перед вызовом `make` вам необходимо соответствующим образом отредактировать первую строчку в `Makefile`.
2. В случае отсутствия на компьютере утилиты `make`, вы можете самостоятельно скомпилировать программу вызовом команд, представленных в разделе ["Компиляция"](#компиляция).
2. В случае отсутствия на компьютере утилиты `make`, вы можете самостоятельно скомпилировать программу вызовом команд, представленных в параграфе ["Компиляция"](#компиляция).
9. Временно измените размер памяти инструкций до 64KiB, а памяти данных до 16KiB, изменив значение параметров `INSTR_MEM_SIZE_BYTES` и `DATA_MEM_SIZE_BYTES` в пакете `memory_pkg` на `32'h10_000` и `32'h4_000` соответственно.
10. Проинициализируйте память инструкций и память данных файлами `coremark_instr.mem` и `coremark_data.mem`, полученными в ходе компиляции программы.
1. Память можно проинициализировать двумя путями: с помощью вызова системной функции `$readmemh`, либо же с помощью программатора. Однако имейте в виду, что инициализация памятей с помощью программатора будет достаточно долго моделироваться в виду большого объема программы.
@@ -361,7 +361,7 @@ Iterations/Sec : 3.446111
Обычно, для сравнения между собой нескольких реализаций микроархитектур, более достоверной считается величина "кормарк / МГц", т.е. число кормарков, поделённое на тактовую частоту процессора, поскольку время прохождения теста напрямую зависит от тактовой частоты. Это значит, что чип с менее удачной микроархитектурной реализацией может выиграть по кормарку просто потому, что он был выпущен по лучшей технологии, позволяющей запустить его на больших частотах. Кормарк/МГц нормализует результаты, позволяя сравнивать микроархитектурные решения, не заботясь о том, на какой частоте был получен результат.
Более того, при сравнении с другими результатами, необходимо учитывать флаги оптимизации, которые использовались при компиляции программы, поскольку они также влияют на результат. Например, если собрать coremark с уровнем оптимизаций `-O1`, результат нашей системы скакнёт до 11.23 кормарков, что всего лишь является следствием того, что программа стала меньше обращаться к памяти вследствие оптимизаций. Именно поэтому результаты coremark указываются вместе с опциями, с которыми тот был собран.
Более того, при сравнении с другими результатами, необходимо учитывать флаги оптимизации, которые использовались при компиляции программы, поскольку они также влияют на результат. Например, если собрать coremark с уровнем оптимизаций `-O1`, результат нашей системы скакнёт до 11.23 кормарков, что всего лишь является следствием того, что программа стала меньше обращаться к памяти после оптимизаций. Именно поэтому результаты coremark указываются вместе с опциями, с которыми тот был собран.
Мы не будем уходить в дебри темных паттернов маркетинга и вместо этого будет оценивать производительность в лоб: сколько кормарков в секунду смог прогнать наш процессор без каких-либо оптимизаций в сравнении с представленными результатами других систем вне зависимости от их оптимизаций.
@@ -371,7 +371,7 @@ Iterations/Sec : 3.446111
![../../.pic/Labs/lab_16_coremark/fig_01.png](../../.pic/Labs/lab_16_coremark/fig_01.png)
На что мы можем обратить внимание? Ну, во-первых, мы видим, что ближайший к нам микроконтроллер по кормарку — это `ATmega2560` с результатом `4.25` кормарка. Т.е. наш процессор по производительности схож с микроконтроллерами Arduino.
На что мы можем обратить внимание? Ну, во-первых, мы видим, что соседний с нашим микроконтроллер по кормарку — это `ATmega2560` с результатом `4.25` кормарка. Т.е. наш процессор по производительности схож с микроконтроллерами Arduino.
Есть ли здесь еще что-нибудь интересное? Посмотрим в верх таблицы, мы можем увидеть производителя Intel с их микропроцессором [Intel 80286](https://ru.wikipedia.org/wiki/Intel_80286). Как написано на вики, данный микропроцессор был в 3-6 раз производительней [Intel 8086](https://ru.wikipedia.org/wiki/Intel_8086), который соперничал по производительности с процессором [Zilog Z80](https://en.wikipedia.org/wiki/Zilog_Z80), который устанавливался в домашний компьютер [TRS-80](https://en.wikipedia.org/wiki/TRS-80).