Приветствую тебя, мой уважаемый читатель на просторах RISC-V!
Мы начинаем очень интересную тему, которой будет посвящена целая глава, это изучение RISC-V. Я считаю, что это очень интересная тема чтобы в нее углубится, так мировое сообщество производителей железо начало уделять много внимания этому проекту (участники RISC-V) и не только поэтому, это полностью свободное решение в плане прототипирования. Тут вспоминаются слова Линуса Торвальдса о свободном ПО (они будут так же уместны и для свободного CPU).
«Программы — как секс: лучше, когда бесплатно.»
Немного о RISC-V.
RISC-V – представляет собой открытую архитектуру набора инструкций (ISA) на основе установленных принципов сокращенных набора команд (RISC). В отличие от большинства ISA, RISC-V ISA может свободно использоваться для любых целей, позволяя любому проектировать, производить и продавать микросхемы RISC-V и программное обеспечение. Хотя это не первый открытый ISA, важно, потому что он предназначен для использования в современных компьютеризированных устройствах, таких как облачные технологии, мобильные телефоны и встраиваемые системы. Такое использование требует, чтобы fpga дизайнеры учитывали эффективность и производительность использования энергии. Набор инструкций также содержит значительное количество поддерживаемого программного обеспечения, которое позволяет избежать ранних слабостей новых наборов инструкций. Проект начался в 2010 году в Калифорнийском университете в Беркли, но многие участники являются добровольцами и промышленными разработчиками за пределами академического сообщества. RISC-V ISA был разработан с учетом небольших, быстрых и маломощных реализаций в реальном времени, но без чрезмерного усложнения архитектуры для конкретного типа микроархитектуры.
В рамках статьи рассмотрим, как запустить RISC-V на fpga, в частности на Xilinx Zynq. Базовым проектом будет fpga-zynq от ucb-bar. В этом проекте используется Rocket Chip генератор (лучший способ следить за новостями о RISC-V – https://twitter.com/risc_v и https://riscv.org/news/). Ядро будет сгенерировано с помощью Rocket Chip генератора из исходников на Chisel.
О Chisel
Chisel – это язык разработки аппаратного обеспечения с открытым исходным кодом, разработанный в UC Berkeley, который поддерживает расширенную аппаратную конструкцию с использованием высокопараметризированных генераторов и многоуровневых аппаратных языков.
- Язык аппаратного обеспечения
- Встроенный в язык программирования Scala
- Алгебраическая конструкция и связь
- Абстрактные типы данных и интерфейсы
- Массовые подключения
- Иерархическое + объектно-ориентированное + функциональное построение
- Высокая параметризация с использованием метапрограммирования в Scala
- Поддерживает разбиение доменных языков
- Достаточного размера стандартная библиотека, включая единицы с плавающей запятой
- Несколько тактовых доменов
- Создает низкоуровневый Verilog, предназначенный для перехода на стандартные средства ASIC или FPGA
- Открытый исходный код на github с модифицированной лицензией BSD
- Полный комплект документов
- Растущее сообщество последователей
Пример кода на chisel:
import chisel3._ import chisel3.util._ //A n-bit adder with carry in and carry out class Adder(val n:Int) extends Module { val io = IO(new Bundle { val A = Input(UInt(n.W)) val B = Input(UInt(n.W)) val Cin = Input(UInt(1.W)) val Sum = Output(UInt(n.W)) val Cout = Output(UInt(1.W)) }) //create an array of FullAdders val FAs = Array.fill(n)(Module(new FullAdder()).io) val carry = Wire(Vec(n+1, UInt(1.W))) val sum = Wire(Vec(n, Bool())) //first carry is the top level carry in carry(0) := io.Cin //wire up the ports of the full adders for (i <- 0 until n) { FAs(i).a := io.A(i) FAs(i).b := io.B(i) FAs(i).cin := carry(i) carry(i+1) := FAs(i).cout sum(i) := FAs(i).sum.toBool() } io.Sum := Cat(sum.reverse) io.Cout := carry(n) }
import chisel3._ import scala.collection.mutable.ArrayBuffer /** Four-by-four multiply using a look-up table. */ class Mul extends Module { val io = IO(new Bundle { val x = Input(UInt(4.W)) val y = Input(UInt(4.W)) val z = Output(UInt(8.W)) }) val muls = new ArrayBuffer[UInt]() // -------------------------------- \\ // Calculate io.z = io.x * io.y by // building filling out muls // -------------------------------- \\ for (i <- 0 until 16) for (j <- 0 until 16) muls += (i * j).U(8.W) val tbl = Vec(muls) io.z := tbl((io.x << 4.U) | io.y) }
Более подробное описание на https://github.com/ucb-bar/chisel-tutorial, уроки по изучению chisel можно скачать следующим образом:
$ git clone https://github.com/ucb-bar/chisel-tutorial.git
$ cd chisel-tutorial
$ git fetch origin
$ git checkout release
Rocket Chip на Zynq FPGA
Git проекта https://github.com/ucb-bar/fpga-zynq. Этот репозиторий содержит файлы, необходимые для запуска rocket RISC-V на разных платах Zynq FPGA (Zybo, Zedboard, ZC706) с Vivado 2016.2. Предпринимались попытки не только автоматизировать процесс создания файлов для этих плат, но и уменьшить дублирование, а также размер этого репозитория. Предварительно созданные образы доступны в подмодулях git, и они только поверхностно клонируются, если требуется.
Данная система позволит вам запустить бинарный код RISC-V на ядре rocket, созданный на поддерживаемой ПЛИС Zynq. В этом разделе описывается совокупность всех задействованных частей и прокси-сервера, описывается остальная часть документации. Переход сверху вниз от бинарного кода RISC-V к системе разработки:
Целевое приложение (бинарный код RISC-V) будет работать поверх любого ядра, в котором работает Rocket Chip. Компилируется с помощью riscv-gcc или riscv-llvm.
RISC-V Kernel (прокси-ядро или RISC-V Linux) работает поверх rocket chip. Прокси-ядро чрезвычайно легкое и предназначено для использования с одним бинарным файлом, связанным с Newlib, в то время как RISC-V Linux подходит для всего остального.
Rocket Chip (rocket ядро с инструкциями L1 и кэшами данных) создается на FPGA. Многие из его структур, как правило, относятся к различным жестким блокам, включая BRAM и DSP-фрагменты. Он связывается с ядром ARM хоста на Zynq через AXI.
Front-end Server (riscv-fesvr) работает на ядре ARM хоста и обеспечивает интерфейс к rocket чипу, работающему на FPGA (подключенном через AXI).
Zynq ARM Core ( одно или двух ядерный Cortex A9) запускает Linux и упрощает взаимодействие с FPGA.
Плата FPGA (Zybo, Zedboard или ZC706) содержит FPGA Zynq и несколько устройств ввода / вывода. При включении питания SD-карта используется для настройки FPGA и загрузку Linux на ядре ARM.
Внешняя связь (TTY через последовательный порт на USB или telnet / ssh через Ethernet) позволяет системе разработки взаимодействовать с платой FPGA.
Система разработки (ПК с SD-кард-ридером) генерирует образ для настройки FPGA.
$ git clone https://github.com/ucb-bar/fpga-zynq.git
$ cd fpga-zynq/zedboard/
$ make init-submodules
$ make rocket
[info] Running zynq.Generator /home/user/fpga-zynq/common/build zynq Top zynq ZynqConfig [info] [0.002] Elaborating design... Generated Address Map io:cbus:debug 0 - fff, RWX io:pbus:TL2:bootrom 1000 - 1fff, RX io:pbus:TL2:clint 2000000 - 200ffff, RW io:cbus:plic c000000 - fffffff, RW mem 80000000 - 8fffffff, RWX [C] Generated Interrupt Vector Generated Configuration String plic { priority 0xc000000; pending 0xc001000; ndevs 0; }; rtc { addr 0x200bff8; }; ram { 0 { addr 0x80000000; size 0x10000000; }; }; core { 0 { 0 { isa rv64imafds; timecmp 0x2004000; ipi 0x2000000; plic { m { ie 0xc002000; thresh 0xc200000; claim 0xc200004; }; s { ie 0xc002080; thresh 0xc201000; claim 0xc201004; }; }; }; }; }; bootrom { addr 0x1000; size 0x1000; } clint { addr 0x2000000; size 0x10000; } [info] [5.865] Done elaborating. [success] Total time: 13 s, completed Apr 12, 2018 3:18:54 PM java -Xmx2G -Xss8M -XX:MaxPermSize=256M -cp /home/user/fpga-zynq/rocket-chip/firrtl/utils/bin/firrtl.jar firrtl.Driver -i /home/user/fpga-zynq/common/build/Top.ZynqConfig.fir -o /home/user/fpga-zynq/common/build/Top.ZynqConfig.v -X verilog OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=256M; support was removed in 8.0 cp /home/user/fpga-zynq/common/build/Top.ZynqConfig.v src/verilog/Top.ZynqConfig.v
Запуск проекта в Xilinx Vivado.
Выполняем следующие команды:
source /media/mcuby/fpga/Xilinx/Vivado/2017.4/settings64.sh (в начале путь до установленной Xilinx Vivado)
gedit src/tcl/zedboard_bd.tcl (необходимо заменить на свою версию Xilinx Vivado, set scripts_vivado_version 2017.4)
make vivado (из каталога платы zedboard)
После запуска Xilinx Vivado, Вы увидите, что на блок диаграмме нет RISC V, он находится в rocketchip_wrapper(rocketchip_wrapper.v). Проект собран для работы.