Приветствую тебя, мой уважаемый читатель на просторах 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). Проект собран для работы.