Главная » Хабрахабр » [Перевод] Генерация и тестирование ядра RISC-V

[Перевод] Генерация и тестирование ядра RISC-V

Как я писал в прошлом посте, название моего проекта на GSoC-2016 — «порт RISC-V на Parallella», и первая вещь, которую я должен был сделать, это познакомиться с экосистемой RISC-V. Один из лучших способов это сделать, — посмотреть видео с презентации первого воркшопа RISC-V на Youtube. Для того, чтобы понять самые важные концепции, я рекомендую следующие презентации:
Ещё одна ссылка, если вы интересуетесь Chisel, языком, основанным на Scala, который используется для описания текущей аппаратной реализации ядра RISC-V (ядро Rocket имеет in-order конвейер, BOOM — out-of-order), и любых будущих реализаций.

Краткое руководство по Chisel (Jonathan Bachrach) видео слайды

Работа с Rocket Chip, добавление расширений, инфраструктура ASIC и FPGA (Colin Schmidt) видео слайды

Если вы глубоко заинтересованы в RISC-V и развитии сообщества, я предлагаю вам принять участие в воркшопах.

Наш порт RISC-V на Parallella будет использовать совершенно стандартное ядро, сгенерированное с помощью Rocket Chip из исходников на Chisel (в статье даётся очень хорошее введение). Конечным результатом будет Verilog RTL (в нечитаемом виде, только исходники на Chisel читаемы), который мы можем включить в наш проект FPGA для Parallella, который доступен в репозитории Parallella OH (Open Hardware). Однако я не буду вдаваться в подробности сейчас, всё это будет рассмотрено в следующих постах.

Для того, чтобы компилировать ПО для этого ядра, вы можете использовать тулчейн RISC-V GNU, который можно взять здесь. Есть два варианта компиляции: либо с библиотекой Newlib C, которая используется для программ, работающих на прокси-ядре (proxy kernel, pk) либо компилируете с библиотекой GNU C library (glibc), для компиляции Linux и программ под Linux. Я скомпилировал обе версии, (ядро Linux, релиз 4.1), используя прилагаемые инструкции, и всё заработало, как ожидалось, при симуляции в Spike, референсном симуляторе RISC-V ISA.

Главный репозиторий Rocket Chip связан путём использования субмодулей Git со всеми репозиториями, содержащими исходники (главным образом, Chisel), которые нужны для правильной генерации с использованием своих файлов-обёрток, расположенных в src/main/scala/. Каждый субмодуль связан с определённым комитом, заведомо рабочим, в результате сорка получается стабильной. Лично я не встретил никаких ошибок при генерации дефолтного ядра RV64G (64 бита, [I]nteger, [M]ultiply / Division, [A]tomic, [F] Single Floating, [D]ouble Floating), сокращение IMAFD сокращается до G (General), содержащего L1-кэши инструкций и данных, TLB и FPU с интерфейсами MemIO и HostIO для связи с внешним миром.

В типичной FPGA-системе (как показано на диаграмме из презентации Y.Lee по Rocket Chip), эти два интерфейса нужны для доступа к основной памяти и для загрузки ядра RISC-V (бутстрап). Последний используется для управления CSR (control-status registers) и поддержки системных вызовов (для операций ввода-вывода) из целевой машины (на которой запущено прокси-ядро или ядро Linux) в хост-машину (т.е. в двухядерный процессор ARM в Zynq FPGA), на которой запущен инстанс riscv-fesvr (front end server) для диспетчеризации системных вызовов в операционную систему (т.е. ARM Linux).

Для конфигурирования ядра вы можете также изменить значения внутри файла Config.scala. Этот файл содержит набор конфигураций для различных применений (модель C++, FPGA обычного размера, маленькая FPGA, VLSI, и т.д.). Всё, что делает скрипт, принимающий переменную CONFIG=XXX (т.е. DefaultFPGAConfig), это устанавливает требуемую конфигурацию, используемую для сборки симулятора C++ либо Verilog RTL для FPGA или VLSI. Это очень полезная вещь, если вы хотите экспериментировать с разными доступными опциями, быстро генерировать и тестировать их в программном либо аппаратном виде.

Хорошей идеей является скомпилировать тулчейн (с Newlib лучше всего), прежде чем генерировать любые ядра, так как вам нужно компилировать и запускать тесты для верификации вашего ядра с помощью симулятора C++ или Synopsys VCS. К сожалению, я смог использовать только первый, но не последний. Вы не можете использовать любой симулятор Verilog (например, Verilator, Icarus Verilog, Modelsim, QuestSim), так как тестбенч использует функции DirectC (связывающие тестбенчи Verilog и произвольный код C/C++). К счастью, симулятор С++ обеспечивает вывод VCD и я смог использовать GTKWave для просмотра сгенерированных временных диаграмм тестов.

Я также добавил сессию с простыми командами, нужными для сборки тулчейна RISC-V и генерации ядра RV64G для FPGA. Эти команды будут добавлены в финальный скрипт компиляции, который я разрабатываю для полной автоматизации всего необходимого для того, чтобы получить рабочее ядро RISC-V внутри чипа Zynq на Parallella.

# Скачиваем и инициализируем репозиторий Rocket Chip
git clone https://github.com/ucb-bar/rocket-chip.git
cd rocket-chip
git submodule update --init
export TOP=$(pwd) # Устанавливаем необходимые пакеты (Ubuntu)
sudo apt-get install autoconf automake autotools-dev curl \
libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex \
texinfo gperf libtool patchutils bc # Компилируем тулчейн RISC-V (используется Newlibдля работы без ОС)
export RISCV=$TOP/riscv-tools
# Добавляем всё, что будет скомпилировано, в пути)
export PATH=$PATH:$RISCV/bin
cd $RISCV
git submodule update --init --recursive
# Редактируем файл build.common
# JOBS = Количество ядер / потоков, которые поддерживает ваша машина
./build.sh # Тестируем тулчейн RISC-V, скомпилировав простую программу
# и запускаем её на Spike (симулятор ISA)
# с использованием имеющегося прокси-ядра (pk)
cd $TOP
echo -e '#include <stdio.h>\n int main(void) \
{ printf("Hello world!\\n"); return 0; }' > hello.c
riscv64-unknown-elf-gcc -o hello hello.c
spike pk hello # Опционально: компилируем эмулятор Rocket Chip
# Заменить -j8 на -jN (количество ядер/потоков на вашей машине)
cd $TOP/emulator
make
# Запускаем тесты (внимание: это может занять некоторое время)
# make -j8 run-asm-tests
# make -j8 run-bmark-tests
# лучше просто запустить конкретный тест:
make output/rv64ui-p-add.out # Опционально: компилируем эмулятор Rocket Chip с выводом VCD
# Меняем -j8 на -jN cd $TOP/emulator
# Если у вас нет утилиты vcd2vpd, открываем src/main/scala/Testing.scala
# файл и меняем все .vpd на .vcd (6 раз)
make debug
# Запускаем тесты (внимание: это может занять время и место на диске)
# make -j8 run-asm-tests-debug
# make -j8 run-bmark-tests-debug
# запускаем определённые тесты и тогда нам не нужен приведённый выше # хак при отсутствии утилиты vcd2vpd:
make output/rv64ui-p-add.vcd # Генерируем Rocket Chip Verilog RTL для FPGAs (в fsim/generated-src/)
# Дефолтная конфигурация "DefaultFPGAConfig", но вы не можете её изменить
# например, на "SmallFPGAConfig" если дефолтная реализация с FPU
# не влезает в ваше устройство. Используем make CONFIG=ConfigName verilog для установки # желаемой конфигурации из числа доступных (src/main/scala/Configs.scala)
# Финальный вывод Verilog RTL называется Top.ConfigName.v
cd $TOP/fsim
make verilog

В следующем посте мы рассмотрим, как получить IP-блок из сгенерированного ядра RV64G для того, чтобы его можно было легко подключать к проектам, для тестирования на Zedboard или для использования в большом проекте на Parallella.


x

Ещё Hi-Tech Интересное!

На финишной прямой суборбитального туризма

Два конкурента, Virgin Galactic и Blue Origin, наконец вышли на финишную прямую — обе компании перешли к регулярным испытаниям. 29 мая состоялся второй полет со включением двигателя корабля SpaceShipTwo от Virgin Galactic, а 18 июля — девятый испытательный полет New ...

[Перевод] Как Tinder (слегка) прячет ваше местоположение

В этом году вы со своим приятелем Стивом Стивингтоном основали стартап по отслеживанию пользователей. Бизнес основан на утечке метаданных WhatsApp, которую вы обнаружили. Вам обоим стоило бы ещё поучиться менеджменту, но всё же фирма выросла в мощную, хотя неустойчивую компанию ...