Как я писал в прошлом посте, название моего проекта на 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.
В следующем посте мы рассмотрим, как получить IP-блок из сгенерированного ядра RV64G для того, чтобы его можно было легко подключать к проектам, для тестирования на Zedboard или для использования в большом проекте на Parallella.
- Введение (Krste Asanovic) видео слайды
- Тулчейн RISC-V (Andrew Waterman) видео слайды
- SoC-генератор RISC-V “Rocket Chip” в Chisel (Yunsup Lee) видео слайды
- Структура программного стека RISC-V (Sagar Karandikar) видео слайды
- Отладка на RISC-V (Albert Ou) видео слайды
- Портирование нового кода на RISC-V с OpenEmbedded (Martin Maas) видео слайды
- Окружение тестирования RISC-V (Stephen Twigg) видео слайды
Ещё одна ссылка, если вы интересуетесь 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.
Комментарии (24)
eugenk
13.04.2018 01:40Нда… Тот самый случай, когда комментарии оказались намного интереснее самой статьи. Не в обиду автору, а просто в силу моих собственных интересов. Уважаемый Space_Cowboy, а не могли бы Вы написать небольшую статью про chisel? Не в плане пересказа документации, а просто в плане юзабельности его как инструмента, с которым Вы реально работали? Думаю многим будет интересно.
valeriyk
1. Chisel — полная ерунда, никому не советую тратить время. Берите опенсорный RISC-V на верилоге или системверилоге, типа SCR1, и будет вам щастье.
2. Работающего LLVM под RISC-V тоже нету, ну что ж, будем ждать.
3. Самая интересная, по крайней мере для меня, часть ISA — векторное расширение, тоже не готова. Видимо, будет на основе берклевского же Hwacha, но когда — не понятно.
Вывод: побаловаться студентам сгодится.
32bit_me Автор
1. Можно и самому написать, just for fun
2. Кроме бэкенда в релизе LLVM, есть ещё как минимум один на гитхабе, можно попробовать его.
3. Да, векторное расширение интересно.
Space_Cowboy
Наверное поэтому, меторами этого проекта выступают Intel, Google, Nvidia и другие мэйджоры индустрии. А также, его разработкой занимаются люди из института Беркли, из подразделения ARC которое в свое время и разработала архитектуру risc v.
Прежде чем что-то писать и кому-то советовать, не пытались для начала разобраться в теме?)
Chisel же, в свою очередь, является прекрасным инструментом для разработки глубоко параметризируемой цифровой логики. Если вы студет, безусловно, нужно, прежде чем браться за Chisel, добиться глубокого понимания Verilog.
Уже сейчас Сhisel используется во множестве компаний разрабатывающих ASIC, в будующем же думаю Chisel и ему подобные инструменты распространятся повсеместно.
32bit_me Автор
Ещё хочу добавить, что также есть язык SpinalHDL, также являющийся производным от Scala, на нём написано ядро VexRiscV.
valeriyk
«Talk is cheap. Show me the code» (с) Торвальдс.
Сколько строк на Chisel написали лично вы?
Space_Cowboy
Код, конечно же никто вам не покажет) Но могу сказать что на данный момент есть несколько крупных айпи написанных на чизеле(в том числе и мной), которые используются в реальных проектах на продакшн. В целом, достаточно много.
eugenk
А Вы не могли бы поделиться личными впечатлениями от сабжа? Как он по сравнению с верилогом, более удобен или менее? Насколько «прозрачен» код? Т.е. можно ли при некотором воображении и привычке понять во что примерно развернётся описание? Ну и тому подобные вопросы.
VySh
Сомнительное утверждение — вы много вакансий видели где требуется знание chisel? А вендоры EDA поддерживают chisel в своих тулах?
Space_Cowboy
Chisel — это скала, он генерит verilog. Элобарация, симуляция, верификация происходит непосредственно со сгенеренным verilog кодом. Так что вопрос поддержки EDA я не совсем понял.
К тому же, если поинтересоваться тулчейном у разработчиков rtl будь то Verilog, SVerilog или VHDL, в 90% случаях вы встретите самописные скрипты на Питоне, тикле, яваскрипте и еще чем угодно, которые решают те или иные задачи, такие как генерация по заданым параметрам, подключение шин и т.п. Даже если взять покупные IP ядра у крупных вендоров, большинство поставляется с генераторами или даже целими тулами для генерации.
На данный момент таких вакансий нет. Так-же как и достовернных данных о том, сколько компаний использую Chisel на данный момент. Это утверждение дано из личных наблюдений.
valeriyk
А дебажить-то как? То же самое, что писать RTL-код, но симулировать и верифицировать только нетлист, а потом каким-то образом пытаться понять, что пофиксить в RTL, чтобы бага в нетлисте ушла? Спасибо, не надо.
Space_Cowboy
Это не верное утверждение, сгенеренный verilog в полне себе читаем, имена wire-ов и регистров в чизеле сохраняются в верилоге, а комбинационная логика генерится через переменные по типу _T_1 = a & b, _T_2 = _T_1 | c и т.д. Так что сравнивать его с нетлистом некорректно. К тому-же большинство тулов симуляции позволяют развернуть вполне себе наглядный схематик. На первый взгляд может показаться что дебаг усложняется. Но на практике все не так страшно. И дело меняется кардинально если доходит до отладки чужого rtl кода. Если он был сгенерен chisel — ом отлаживать его намного легче если человек писал бы на Verilog.
VySh
Кто гарантирует что ваш генератор сгенерировал корректный верилог из chisel? Может быть есть инструменты, которые могут формально доказать эквивалентность описания verilog и chisel? До тех пор пока солидные дяди типа Mentor, Synopsys и прочих не начнут предоставлять этот самый Chisel to verilog и сопутствующие инструменты, chisel так и останется игрушкой из академической среды. Цена ошибки в микроэлектронике череcчур высока.
Насчёт скриптов и прочего — скрипты используются обычно для генерации топ-левела и glue logic. Сами внутренности — verilog или systemverilog, написанный ручками.
Сколько компаний вы наблюдали? Сколько из тех компаний о которых вы знаете используют chisel для чего-то отличного от RISC-V? Из моих личных наблюдений — chisel за пределами академической среды и RISC-V никому особо не интересен. По крайней мере за те 12 лет, которые я работаю в этой отрасли (и в России, и не в России) я не видел чтобы кто-то им пользовался или хотя бы интересовался. И тренингов никаких по нему нет как будто бы — по Verilog и SystemVerilog много, есть по specman и даже по VHDL, а вот по Chisel — увы.
Space_Cowboy
Chisel гарантирует синтезируемый rtl(баги конечно же никто не исключал, но их достаточно быстро фиксят после репорта). Зачем вам формально верефицировать Сhisel? Вы верефицируете сгенеренный им rtl и впоследствии netlist, Встречая какие-то ошибки поправляете Chisel. В этом плане процесс верификации никак не отличается от стандартного флоу.
Не удивительно, ведь chisel получил полноценный релиз с документацией только в этом году. И при всем этом он еще далек от совершенства. Самое главное что он развивается. Имхо видеть в chisel что-то только для академической среды, при всем его очевидном потенциале в корне не верно. По поводу компаний в Росии знаю 2 крупные, и 2 работающие с fpga. Но учитывая количество их целом, то для России это уже много.
Chisel это не замена verilog, а просто тул для удобства управления им, и упразднения неудобных макросов скриптов генерации и всех прочих самописных надстроек от каждого разработчика. Почитайте доку и туториал там достаточно занятно даже для того чтобы просто поиграться.
VySh
Не Chisel верифицировать, а то что описание на chisel корректно преобразовалось в verilog. Если этого не проверять, то получается игра в испорченный телефон. Вы что-то исправляете на chisel, а в сгенерированном верилоге получается что-то совсем другое.
Space_Cowboy
Об этом не стоит волноваться, т.к. все допустимые конструкции в chisel имеют достаточно однозначную интерпритацию в verilog. И даже если теоретически представить, что такое произошло, то скорей всего это выдаст багу на стадии компиляции/линт и сдц проверок/верификации/синтеза того-же rtl и вы обязательно обратите внимание на тот кусок кода который повлек за собой нежелательное поведение. Я в свою очередь не сталкивался с некоректностью сгенеренного verilog, только лишь с тем что некоторые конструкции в chisel первращались не в те которые я ожидал.
VySh
Нет, это так не работает. Нет гарантий что вы обнаружите ошибку позже во flow. Кроме того чем позже обнаружена ошибка, тем сложнее и дороже её исправить. Если вы находите ошибку при проверке эквивалентности Chisel vs verilog исправить её очень легко. Чтобы обнаружить эту же ошибку на симуляции вам могут понадобится дни и недели моделирования. Если ошибка вылезает после синтеза — всё ещё хуже. Любое пребразование дизайна должно проводиться с последующей проверкой эквивалентности. Нельзя считать что преобразующий тул работает абсолютно правильно. Именно поэтому, к примеру, обязательно делается проверка эквивалентности синтезированного нетлиста исходному RTL коду. И тулы для этой проверки и синтеза желательно иметь от разных вендоров.
valeriyk
Для Chisel это все не нужно. Эквивалентность между RTL и нетлистом нужна, потому что верифицируете вы одно, а в кремний идет другое. А в случае с Chisel вы верифицируете Verilog, который из него получен, т.к. фреймворка по типу UVM, чтобы верифицировать нативный Chisel, наверняка нету. Если бы верифицировали Chisel, то тогда да.
VySh
Если так рассуждать, то и между RTL и нетлистом проверка эквивалентности не нужна — ведь нетлист тоже можно промоделировать и выловить ошибки.
Исправления вносятся в chisel, а в кремний идёт verilog. Если ваш транслятор из chisel в verilog барахлит, то verilog будет постоянно получаться с ошибками и ловить вы их будете на симуляции — долго и муторно.
valeriyk
О том и речь. Только в варианте с Верилогом у вас есть выбор, что моделировать — RTL или нетлист. А в варианте с Chisel'ом выбора нет. Хотя есть шанс, что баги в Chisel'е наложатся на баги в трансляторе и на выходе получится работающий Верилог (по крайней мере, до выхода следующей версии транслятора).
Space_Cowboy
Безусловно резон в том что бэкенд который отвечает за генирацию может иметь в себе ошибки. И смысл в формальной верификации есть, но тем неменее очень мало людей сейчас пишут на plain verilog без задействия самописных генераторов и прочих надстроек, ведь там тоже есть вероятность ошибок. Вот что ответил один из контрибуторов chisel по этому поводу
stackoverflow.com/questions/49800826/chisel-firrtl-verilog-backend-proof-of-work
И еще вопрос где больше риск словить ту мистическую ошибку которая словиться на одной из поздних стадий.
eugenk
Ага. Кстати дико раздражает. Если scala действительно внесёт некий порядок в этот всеобщий бардак, это можно только приветствовать.
eugenk
Прошу прощения, не могли бы Вы это мнение как-то обосновать? Я интересуюсь scala. Правда более не менее всерьёз писал только на scala.js. Даже где-то с год назад устроил тут небольшой флейм на тему, что scala.js круче чем dart в хабе по дарту. Правда в итоге сам вынужден был признать, что возможно и круче, но куда корявее в доступной реализации. Сейчас хочу попробовать chisel. По первым опытам что мне дико понравилось, что работает через jupyter notebook. Даже написал на той же scala.js простенький апплет типа gtkwave для jupyter, работающий прямо из scala. И задумка есть. По мотивам вот этой вот статьи. Хочу сделать 6-канальную плату сбора данных на iCE40-HX8K Breakout Board и повторить опыты Шноля. Как раз готов сейчас пожертвовать ей во благо науке на пару месяцев непрерывного эксперимента. Так что мой интерес не праздный. Как только увидел волшебные слова RISC-V, сразу влез читать. К сожалению статья оказалась не про chisel. Но если Вы можете что-то про него сказать, выслушаю с огромной благодарностью.