RISC-V с нуля
В этой статье мы исследуем различные низкоуровневые концепции (компиляция и компоновка, примитивные среды выполнения, ассемблер и многое другое) через призму архитектуры RISC-V и её экосистемы. Я сам веб-разработчик, на работе ничем таким не занимаюсь, но мне это очень интересно, отсюда и родилась статья! Присоединяйтесь ко мне в этом беспорядочном путешествии в глубины низкоуровневого хаоса.
Сначала немного обсудим RISC-V и важность этой архитектуры, настроим цепочку инструментов RISC-V и запустим простую программу C на эмулированном оборудовании RISC-V.
Содержание
Что такое RISC-V?
RISC-V — это свободная архитектура набора команд. Проект зародился в Калифорнийском университете в Беркли в 2010 году. Важную роль в его успехе сыграла открытость кода и свобода использования, что резко отличалось от многих других архитектур. Возьмите ARM: чтобы создать совместимый процессор, вы должны заплатить авансовый сбор от $1 млн до $10 млн, а также выплачивать роялти 0,5−2% с продаж. Свободная и открытая модель делает RISC-V привлекательным вариантом для многих, в том числе для стартапов, которые не могут оплатить лицензию на ARM или другой процессор, для академических исследователей и (очевидно) для сообщества open source.
Стремительный рост популярности RISC-V не остался незамеченным. ARM запустила сайт, который пытался (довольно безуспешно) подчеркнуть предполагаемые преимущества ARM над RISC-V (сайт уже закрыт). Проект RISC-V поддерживают многие крупные компании, включая Google, Nvidia и Western Digital.
Настройка инструментов QEMU и RISC-V
Мы не сможем запустить код на процессоре RISC-V, пока не настроим окружение. К счастью, для этого не нужен физический процессор RISC-V, вместо него возьмём qemu. Для установки следуйте инструкциям для вашей операционной системы. У меня MacOS, поэтому достаточно ввести одну команду:
Удобно, что qemu поставляется с несколькими готовыми к работе машинами (см. опцию qemu-system-riscv32 -machine ).
Далее установим OpenOCD для RISC-V и инструменты RISC-V.
Загружаем готовые сборки RISC-V OpenOCD и инструментов RISC-V здесь.
Извлекаем файлы в любой каталог, у меня это
/usys/riscv . Запомните его для будущего использования.
Задайте переменные среды RISCV_OPENOCD_PATH и RISCV_PATH , чтобы другие программы могли найти нашу цепочку инструментов. Это может выглядеть по-разному в зависимости от ОС и оболочки: я добавил пути в файл
Создадим в /usr/local/bin символическую ссылку для этого исполняемого файла, чтобы в любой момент запускать его без указания полного пути на
И вуаля, у нас рабочий набор инструментов RISC-V! Все наши исполняемые файлы, такие как riscv64-unknown-elf-gcc , riscv64-unknown-elf-gdb , riscv64-unknown-elf-ld и другие, лежат в
Привет, RISC-V!
Обновление 26 мая 2019 года:
К сожалению, из-за бага в RISC-V QEMU, программа freedom-e-sdk ‘hello world’ в QEMU больше не работает. Для решения этой проблемы выпущен патч, но пока можете пропустить этот раздел. Эта программа не понадобится в дальнейших разделах статьи. Я отслеживаю ситуацию и обновлю статью после исправления бага.
Для дополнительной информации см. этот комментарий.
Настроив инструменты, давайте запустим простую программу RISC-V. Начнём с клонирования репозитория freedom-e-sdk от SiFive:
По традиции, начнём с программы ‘Hello, world’ из репозитория freedom-e-sdk . Используем готовый Makefile , который они предоставляют для компиляции этой программы в режиме отладки:
И запускаем в QEMU:
Это отличное начало. Можно запустить и другие примеры из freedom-e-sdk . После этого напишем и попробуем отладить собственную программу на C.
Наивный подход
Начнём с простой программы, которая бесконечно складывает два числа.
Мы хотим запустить эту программу, и первым делом нужно скомпилировать её для процессора RISC-V.
Здесь создаётся файл a.out , такое имя gcc по умолчанию даёт исполняемым файлам. Теперь запускаем этот файл в qemu :
Мы выбрали машину virt , с которой изначально поставляется riscv-qemu .
Теперь, когда наша программа работает внутри QEMU с сервером GDB на localhost:1234 , подключимся к нему клиентом RISC-V GDB с отдельного терминала:
И мы внутри GDB!
Можем попытаться запустить в GDB команды run или start для исполняемого файла a.out , но в данный момент это не сработает по понятной причине. Мы компилировали программу как riscv64-unknown-elf-gcc , так что хост должен работать на архитектуре riscv64 .
Но есть выход! Такая ситуация — одна из основных причин существования клиент-серверной модели GDB. Мы можем взять исполняемый файл riscv64-unknown-elf-gdb и вместо запуска на хосте указать ему некую удалённую цель (сервер GDB). Как вы помните, мы только что запустили riscv-qemu и сказали запустить сервер GDB на localhost:1234 . Просто подключаемся к этому серверу:
Теперь можно установить некоторые точки останова:
И, наконец, указываем GDB continue (сокращённая команда c ), пока не достигнем точки останова:
Вы быстро заметите, что процесс никак не завершается. Это странно… разве мы не должны немедленно достичь точки останова b 5 ? Что случилось?

Тут видно несколько проблем:
- Текстовый UI не может найти источник. Интерфейс должен отображать наш код и любые близлежащие точки останова.
- GDB не видит текущей строки выполнения ( L?? ) и выводит счётчик 0x0 ( PC: 0x0 ).
- Какой-то текст в строке ввода, который в полном виде выглядит так: 0x0000000000000000 in ?? ()
Приподнимая завесу -v
Чтобы понять происходящие, нужно сделать шаг назад и поговорить, как на самом деле работает наша простая программа на С под капотом. Функция main выполняет простое сложение, но что это на самом деле? Почему он должен называться main , а не origin или begin ? Согласно конвенции все исполняемые файлы начинают выполняться с функции main , но какая магия обеспечивает такое поведение?
Чтобы ответить на эти вопросы, давайте повторим нашу команду GCC с флагом -v , чтобы получить более подробную выдачу, что на самом деле происходит.
Выдача большая, так что не будем просматривать весь листинг. Важно отметить, что хотя GCC формально является компилятором, но по умолчанию выполняет ещё и компоновку (чтобы ограничиться только компиляцией и сборкой, следует указать флаг -c ). Почему это важно? Ну, взгляните на фрагмент из подробной выдачи gcc :
Я понимаю, что даже в сокращённом виде это много, поэтому позвольте объяснить. В первой строке gcc выполняет программу collect2 , передаёт аргументы crt0.o , crtbegin.o и crtend.o , флаги -lgcc и —start-group . Описание collect2 можно почитать здесь: если вкратце, collect2 организует различные функции инициализации во время запуска, делая компоновку в один или несколько проходов.
Таким образом, GCC компонует несколько файлов crt с нашим кодом. Как вы можете догадаться, crt означает ‘C runtime’. Здесь подробно расписано, для чего предназначен каждый crt , но нас интересует crt0 , который выполняет одно важное дело:
Суть «начальной загрузки» зависит от платформы, но обычно она включает в себя важные задачи, такие как установка стекового фрейма, передача аргументов командной строки и вызов main . Да, наконец-то мы нашли ответ на вопрос: именно _start вызывает нашу основную функцию!
Поиск нашего стека
Мы решили одну загадку, но как это приближает нас к первоначальной цели — запуску простой программы на C в gdb ? Осталось решить несколько проблем: первая из них связана с тем, как crt0 настраивает наш стек.
Как мы видели выше, gcc по умолчанию выполняет компоновку crt0 . Параметры по умолчанию выбираются на основе нескольких факторов:
-
, соответствующий структуре machine-vendor-operatingsystem . У нас это riscv64-unknown-elf
- Целевая архитектура, rv64imafdc
- Целевая ABI, lp64d
В команде qemu-system-riscv64 -machine virt -m 128M -gdb tcp::1234 -kernel a.out мы использовали машину virt . К счастью, qemu позволяет легко сбросить информацию о машине в дамп dtb (device tree blob).
Данные dtb трудно читать, поскольку это в основном двоичный формат, но есть утилита командной строки dtc (device tree compiler), которая может преобразовать файл в нечто более читаемое.
На выходе файл riscv64-virt.dts , где мы видим много интересной информации о virt : количество доступных ядер процессора, расположение памяти различных периферийных устройств, таких как UART, расположение встроенной памяти (ОЗУ). Стек должен быть в этой памяти, поэтому поищем его с помощью grep :
Как видим, у этого узла в качестве device_type указано ‘memory’. Судя по всему, мы нашли то, что искали. По значениям внутри reg = <. > ; можно определить, где начинается банк памяти и какова его длина.
В спецификации devicetree видим, что синтаксис reg — это произвольное количество пар (base_address, length) . Однако внутри reg четыре значения. Странно, разве для одного банка памяти не хватит двух значений?
Опять же из спецификации devicetree (поиск свойства reg ) мы узнаём, что количество ячеек <u32> для указания адреса и длины определяется свойствами #address-cells и #size-cells в родительском узле (или в самом узле). Эти значения не указаны в нашем узле памяти, а родительский узел памяти — просто корневая часть файла. Поищем в ней эти значения:
Оказывается, и для адреса, и для длины требуется по два 32-битных значения. Это означает, что со значениями reg = <0x00 0x80000000 0x00 0x8000000>; наша память начинается с 0x00 + 0x80000000 (0x80000000) и занимает 0x00 + 0x8000000 (0x8000000) байт, то есть заканчивается по адресу 0x88000000 , что соответствует 128 мегабайтам.
Компоновка
С помощью qemu и dtc мы нашли адреса ОЗУ в виртуальной машине virt. Мы также знаем, что gcc по умолчанию компонует crt0 , не настраивая стек как нам нужно. Но как использовать эту информацию, чтобы в итоге запустить и отладить программу?
Поскольку crt0 нас не устраивает, есть один очевидный вариант: написать собственный код, а затем скомпоновать его с объектным файлом, который получился после компиляции нашей простой программы. Наш crt0 должен знать, где начинается верхняя часть стека, чтобы правильно инициализировать его. Мы могли бы жёстко закодировать значение 0x80000000 непосредственно в crt0 , но это не очень подходящее решение с учётом изменений, которые могут понадобиться в будущем. Что если мы захотим использовать в эмуляторе другой CPU, такой как sifive_e , с другими характеристиками?
К счастью, мы далеко не первые задаём этот вопрос, и уже существует хорошее решение. Компоновщик GNU ld позволяет определить символ, доступный из нашего crt0 . Мы можем определить символ __stack_top , подходящий для разных процессоров.
Вместо того, чтобы писать с нуля собственный файл компоновщика, есть смысл взять скрипт по умолчанию с ld и немного изменить его для поддержки дополнительных символов. Что такое скрипт компоновщика? Вот хорошее описание:
Зная это, давайте скопируем скрипт компоновщика по умолчанию riscv64-unknown-elf-ld в новый файл:
В этом файле много интересной информации, гораздо больше, чем мы можем обсудить в этой статье. Подробная выдача с ключом —Verbose включает информацию о версии ld , поддерживаемых архитектурах и многое другое. Это всё хорошо знать, но в скрипте компоновщика такой синтаксис недопустим, поэтому откроем текстовый редактор и удалим из файла всё лишнее.
После этого запустим команду MEMORY, чтобы вручную определить, где будет __stack_top . Найдите строку, которая начинается с OUTPUT_ARCH(riscv) , она должна быть в верхней части файла, и под ней добавьте команду MEMORY :
Мы создали блок памяти под названием RAM , для которого допустимы чтение ( r ), запись ( w ) и хранение исполняемого кода ( x ).
Отлично, мы определили макет памяти, соответствующий спецификациям нашей машины virt RISC-V. Теперь можно его использовать. Мы хотим поместить в память наш стек.
Нужно определить символ __stack_top . Открываем свой скрипт компоновщика ( riscv64-virt.ld ) в текстовом редакторе и добавляем несколько строк:
Как видите, мы определяем __stack_top с помощью команды PROVIDE. Символ будет доступен из любой программы, связанной с этим скриптом (предполагая, что сама программа не определит сама что-то с именем __stack_top ). Устанавливаем значение __stack_top как ORIGIN(RAM) . Мы знаем, что это значение равно 0x80000000 плюс LENGTH(RAM) , которая составляет 128 мегабайт ( 0x8000000 байт). Это означает, что наш __stack_top установлен в 0x88000000 .
Для краткости не буду здесь приводит весь файл компоновщика, его можно просмотреть здесь.
Стоп! Hammertime! Runtime!
Теперь у нас есть всё необходимое для создания своей среды выполнения C. На самом деле это довольно простая задача, вот весь файл crt0.s :
Сразу обращает на себя большое количество строк, которые начинаются с точки. Это файл для ассемблера as . Строки с точки называются директивами ассемблера: они предоставляют информацию для ассемблера. Это не исполняемый код, как ассемблерные инструкции RISC-V, такие как jal и add .
Пробежимся по файлу строка за строкой. Мы будем работать с различными стандартными регистрами RISC-V, поэтому ознакомьтесь с этой таблицей, где рассматриваются все регистры и их назначение.
Как указано в руководстве GNU по ассемблеру ‘as’, эта строка сообщает ассемблеру внести следующий код в раздел .init , который является выделяемым ( a ) и исполняемым ( x ). Этот раздел — ещё одно широко распространенное соглашение для запуска кода в пределах операционной системы. Мы работаем на чистом железе без ОС, поэтому в нашем случае такая инструкция может быть не совсем необходима, но в любом случае это хорошая практика.
.global делает следующий символ доступным для ld . Без этого не пройдёт компоновка, потому что команда ENTRY(_start) в скрипте компоновщика указывает на символ _start как точку входа в исполняемый файл. Следующая строка сообщает ассемблеру, что мы начинаем определение символа _start .
Эти директивы .cfi информируют о структуре фрейма и о том, как его обработать. Директивы .cfi_startproc и .cfi_endproc сигнализируют о начале и конце функции, а .cfi_undefined ra сообщает ассемблеру, что регистр ra не должен быть восстановлен до любого значения, содержащегося в нем до запуска _start .
Эти директивы .option изменяют поведение ассемблера в соответствии с кодом, когда нужно применить определённый набор опций. Здесь подробно описано, почему важно использование .option в данном сегменте:
… поскольку мы при возможности ослабляем (relax) адресацию последовательностей до более коротких последовательностей относительно GP, начальная загрузка GP не должна быть ослаблена и должна выдаваться примерно так:
чтобы после релаксации получился такой код:
А теперь последняя часть нашего crt0.s :
Здесь мы наконец-то можем использовать символ __stack_top , над созданием которого мы столько трудились. Псевдоинструкция la (load address), загружает значение __stack_top в регистр sp (указатель стека), устанавливая его для использования в оставшейся части программы.
Затем add s0, sp, zero складывает значения регистров sp и zero (который на самом деле является регистром x0 с жёсткой привязкой к 0) и помещает результат в регистр s0 . Это специальный регистр, который необычен в нескольких отношениях. Во-первых, это «сохраняемый регистр», то есть он сохраняется при вызовах функций. Во-вторых, s0 иногда действует как указатель фрейма, который даёт каждому вызову функции небольшое пространство в стеке для хранения параметров, передаваемых этой функции. Как вызовы функций работают со стеком и указателями фреймов — очень интересная тема, которой легко можно посвятить отдельную статью, но пока просто знайте, что в нашей среде выполнения важно инициализировать указатель фрейма s0 .
Далее мы видим инструкцию jal zero, main . Здесь jal означает переход и компоновку (Jump And Link). Инструкция ожидает операндов в виде jal rd (destination register), offset_address . Функционально jal записывает значение следующей инструкции (регистр pc плюс четыре) в rd , а затем устанавливает регистр pc на текущее значение pc плюс адрес смещения c расширением знака, эффективно «вызывая» этот адрес.
Как упоминалось выше, x0 жёстко привязан к литеральному значению 0, и запись в него бесполезна. Поэтому может показаться странным, что мы в качестве регистра назначения используем регистр zero , который ассемблеры RISC-V интерпретируют как регистр x0 . Ведь это означает безусловный переход к offset_address . Зачем так делать, ведь в других архитектурах есть явная инструкция безусловного перехода?
Этот странный шаблон jal zero, offset_address на самом деле является умной оптимизацией. Поддержка каждой новой инструкции означает увеличение и, следовательно, удорожание процессора. Поэтому чем проще ISA, тем лучше. Вместо того, чтобы загрязнять пространство инструкций двумя инструкциями jal и unconditional jump , архитектура RISC-V поддерживает только jal , а безусловные переходы поддерживаются через jal zero, main .
В RISC-V очень много подобных оптимизаций, большинство из которых принимают форму так называемых псевдоинструкций. Ассемблеры знают, как перевести их в реальные аппаратные инструкции. Например, псевдоинструкцию безусловного перехода j offset_address ассемблеры RISC-V переводят в jal zero, offset_address . Полный список официально поддерживаемых псевдоинструкций см. в спецификации RISC-V (версия 2.2).
Наша последняя строчка — это директива ассемблера .end , которая просто обозначает конец файла.
Отладка, но теперь по-настоящему
Пытаясь отладить простую программу C на процессоре RISC-V, мы решили множество проблем. Сначала с помощью qemu и dtc нашли нашу память в виртуальной машине virt RISC-V. Затем использовали эту информацию для ручного управления размещением памяти в нашей версии дефолтного скрипта компоновщика riscv64-unknown-elf-ld , что позволило точно определить символ __stack_top . Затем использовали этот символ в собственной версии crt0.s , которая настраивает наш стек и глобальные указатели и, наконец, вызвали функцию main . Теперь можно достичь поставленной цели и запустить отладку нашей простой программы в GDB.
Напомним, вот сама программа на C:
Компилирование и компоновка:
Тут мы указали гораздо больше флагов, чем в прошлый раз, поэтому давайте пройдёмся по тем, которые не описали раньше.
-ffreestanding сообщает компилятору, что стандартная библиотека может не существовать, поэтому не нужно делать предположений о её обязательном наличии. Этот параметр не требуется при запуске приложения на своём хосте (в операционной системе), но в данном случае это не так, поэтому важно сообщить компилятору эту информацию.
-Wl — разделённый запятыми список флагов для передачи компоновщику ( ld ). Здесь —gc-sections означает «секции сбора мусора», а ld получает указание удалить неиспользуемые секции после компоновки. Флаги -nostartfiles , -nostdlib и -nodefaultlibs сообщают компоновщику не обрабатывать стандартные системные файлы запуска (например, дефолтный crt0 ), стандартные реализации системной stdlib и стандартные системные дефолтные связываемые библиотеки. У нас свой скрипт crt0 и компоновщик, поэтому важно передать эти флаги, чтобы значения по умолчанию не конфликтовали с нашей пользовательской настройкой.
-T указывает путь к нашему скрипту компоновщика, который в нашем случае просто riscv64-virt.ld . Наконец, мы указываем файлы, которые хотим скомпилировать, собрать и скомпоновать: crt0.s и add.c . Как и раньше, в результате получается полноценный и готовый к запуску файл под названием a.out .
Теперь запустим наш красивенький новенький исполняемый файл в qemu :
Теперь запустите gdb , не забудьте загрузить символы отладки для a.out , указав его последним аргументом:
Затем подключим наш клиент gdb к серверу gdb , который мы запустили как часть команды qemu :
Установим точку останова в main:
И начнём выполнение программы:
Из приведённого выдачи понятно, что мы успешно попали в точку останова на строке 2! Это видно и в текстовом интерфейсе, наконец-то у нас правильная строка L , значение PC: равно L2 , а PC: — 0x8000001e . Если вы делали всё как в статье, то выдача будет примерно такой:

С этого момента можно использовать gdb как обычно: -s для перехода к следующей инструкции, info all-registers для проверки значений внутри регистров по мере выполнения программы и т. д. Экспериментируйте в своё удовольствие… мы, конечно, немало поработали ради этого!
Что дальше?
Сегодня мы многого добились и, надеюсь, многому научились! У меня никогда не было формального плана для этой и последующих статей, я просто следовал тому, что мне наиболее интересно в каждый момент. Поэтому не уверен, что будет дальше. Мне особенно понравилось глубокое погружение в инструкцию jal , так что может в следующей статье возьмём за основу знания, полученные здесь, но заменим add.c какой-нибудь программой на чистом ассемблере RISC-V. Если у вас есть что-то конкретное, что вы хотели бы увидеть или какие-то вопросы, открывайте тикеты.
Вместо Intel и NVIDIA: в чем прорыв стандарта RISC-V

RISC-V (Reduced Instruction Set Computing — Five) — это набор команд для проектирования микропроцессоров. Микропроцессор — это устройство, которое обрабатывает информацию, выполняет инструкции компьютерной программы, арифметические и логические операции.
Стандарт разработала команда ученых из университета Беркли в 2010 году. В 2015 году был основан некоммерческий фонд RISC-V с целью создания открытого сообщества разработчиков программного и аппаратного обеспечения, основанного на RISC-V.
В чем прорыв?
Сама по себе технология не является новым изобретением. Стандарт основан на идеях компьютерной архитектуры, которым уже более 40 лет. Главный прорыв заключается в том, что RISC-V — это открытый стандарт и им может воспользоваться любой желающий бесплатно.
Именно благодаря такому подходу Массачусетский технологический институт внес архитектуру в список десяти прорывных технологий 2023 года. «РБК Тренды» ранее писал об этих технологиях.

Микропроцессоры встроены во многие электронные устройства, например, в компьютеры, ноутбуки, планшеты, смартфоны. До появления RISC-V производители электронной техники могли купить микропроцессор только у компаний, которые их производили, таких как Intel, NVIDIA, Qualcomm. Однако архитектура таких микропроцессоров закрытая и не универсальная. Если они не подходили к устройству, то производителям приходилось заказывать их дизайн и разработку за отдельную плату.
RISC-V же предлагает универсальный стандарт, который доступен всем. Поэтому и крупные производители, и программисты-любители могут спроектировать свой микропроцессор бесплатно.
Как устроен RISC-V
RISC-V включает в себя набор команд (инструкций), которые позволяют разработчикам запрограммировать базовые функции микропроцессора. Команды RISC-V можно разделить на несколько категорий:
- команды для выполнения арифметических и логических операций;
- команды для управления потоком выполнения программы;
- команды для чтения и записи данных в память;
- команды для чтения и записи данных в защищенные регистры, установки режима прерываний и т.д.
RISC-V имеет модульную структуру, поэтому разработчики могут выбирать только те команды, которые им нужны для конкретных задач.
Кроме того, RISC-V предоставляет механизмы для поддержки векторных операций, которые позволяют выполнить одну операцию сразу над несколькими данными. Это может быть полезно в областях, где требуется быстрое выполнение вычислений, например, графика, научные вычисления и т.д.
Где найти наборы команд RISC-V
Набор инструкций для RISC-V можно найти на официальном сайте RISC-V в разделе Specifications. Кроме того, стандарт постоянно дорабатывается и расширяется. Обновления можно скачать на странице Wikipedia. В документации описаны наборы команд и то, как ими воспользоваться.
Также существуют открытые проекты, которые используют RISC-V. В их документации можно найти много полезной информации. Примеры проектов:
-
— набор инструментов для компиляции кода, который поддерживает архитектуру RISC-V; — набор компиляторов — программ, которые переводят текст, написанный на языке программирования, в набор машинных кодов. Проект разрабатывает компиляторы для различных языков программирования, например, C, C++, Objective-C, Ada, Fortran и других, которые поддерживают архитектуру RISC-V; — эмулятор — программное обеспечение, которое позволяет одной компьютерной системе вести себя подобно другой компьютерной системе. Например, ПК выполнять функции планшета или смартфона. Эмулятор QEMU поддерживает множество архитектур, включая RISC-V, и может использоваться для тестирования и исправления ошибок программного обеспечения для этой архитектуры; — операционная система реального времени с открытым исходным кодом, которая поддерживает архитектуру RISC-V. Операционная система реального времени — система, которая обрабатывает сигналы в строго определенное время; — проект, разработанный в Университете Беркли, который предоставляет открытую реализацию процессора на базе архитектуры RISC-V.

Как на этом заработать
Существует несколько способов заработать на RISC-V, однако для этого потребуются знания и опыт в области электроники, программирования и архитектуры процессоров:
RISC-V .

Core IP to support a rich set of RISC-V latest extensions, enabling more edge cloud and high-performance computing applications running on RISC-V.
High-quality RISC-V chips of all manufacturers and applications from China
Developer Board
RISC-V processor development board for your project.
Project
RISC-V processor technical support and production for your commercial, industrial and military projects.
Manufacturer
Product
Specifications
ISA Specification
The specifications shown below represent the current, ratified releases. Work is being done on GitHub.
- Volume 1, Unprivileged Spec v. 20191213 [PDF]
- Volume 2, Privileged Spec v. 20211203 [PDF]
- Recently ratified, but not yet integrated, extension specifications
Past ratified releases include the term “ratified” in the release tag.
Non-ISA Specifications
If you are looking for a complete list of specifications, including our non-ISA specifications and our Compatibility Test Framework, visit the RISC-V Technical Specifications page.
About RISC-V.
RISC-V is an open standard Instruction Set Architecture (ISA) enabling a new era of processor innovation through open collaboration
RISC-V International is the global non-profit home of the open standard RISC-V Instruction Set Architecture (ISA), related specifications, and stakeholder community
More than 3,100 RISC-V members across 70 countries contribute and collaborate to define RISC-V open specifications as well as convene and govern related technical, industry, domain, and special interest groups.
RISC-V combines a modular technical approach with an open, royalty-free ISA — meaning that anyone, anywhere can benefit from the IP contributed and produced by RISC-V. As a non-profit, RISC-V does not maintain any commercial interest in products or services. As an open standard, anyone may leverage RISC-V as a building block in their open or proprietary solutions and services.
RISC-V does not take a political position on behalf of any geography. We are proud to see organizations from around the world working together in this new era of processor innovation. RISC-V was founded in 2015 as the RISC-V Foundation and is incorporated today as RISC-V International Association in Switzerland.
Understanding the RISC-V ISA Open Standard
At the base level, the RISC-V ISA and extensions ratified by RISC-V International are royalty free and open base building blocks for anyone to build their own solutions and services on. The RISC-V ISA and ratified extensions are provided under globally accepted open licenses that are permanently open and remain available for all.
Beyond RISC-V International, the community has opportunity to provide their own free or proprietary IP, implementations, solutions, and services for which RISC-V has no commercial or governance interest.
RISC-V International is wholly committed to design freedom, choice, and flexibility, and supports open architecture extensions to the RISC-V ISA. We do not support work on alternative versions of the RISC-V ISA.
Open source and global standards have a long history of success because they have a license framework that ensures anyone, anywhere can have ongoing access to them.
Google объявил RISC-V одной из первичных архитектур для Android. Что это значит для рынка?
Android решили портировать на новую архитектуру — RISC-V. Мы поговорили с экспертами и выяснили, что ожидает мобильных разработчиков.


Кадр: сериал «Видоизменённый углерод»

В начале года представители Google пришли на конференцию RISC-V Summit и заявили, что им очень интересна эта архитектура. Хотя ранее они долго хранили молчание и не говорили, что уже работают в этом направлении. Разбираемся, как может измениться мир Android-разработки и зачем всё это компании Google.
«Что это значит для рынка?» — новая рубрика, в которой мы рассказываем, как те или иные события влияют на рынок и жизнь простых разработчиков.
Что такое RISC-V
RISC-V — это открытая система команд и архитектура для процессоров. Любая компания может использовать её бесплатно — как тот же Linux или веб-сервер Apache. RISC-V, как следует из названия, основана на подходе RISC (reduced instruction set computer), который предполагает использование оптимизированных команд в работе процессора.
Часто под reduced (англ. — уменьшенный) ошибочно понимается малое число инструкций, но на самом деле это слово характеризует объём команд и время выполнения — в том числе родного цикла доступа к памяти. Плюс каждая конструкция обладает фиксированной длиной. К семейству RISC-процессоров относят RISC-V, PowerPC, ARM и другие.
В противовес RISC существует подход CISC (complex instruction set computer) — его используют, например, в Intel и AMD. При таком подходе у инструкций может быть разная длина, а сами инструкции отвечают за довольно большие операции. С точки зрения «железа» поздние модели процессоров Intel выполнены как RISC-процессоры, но «программно» всё ещё работают на CISC-схеме, то есть все CISC-инструкции перед выполнением конвертируются в RISC-инструкции.
Архитектура RISC-V довольно популярна у производителей умных часов и других устройств, а также в микроконтроллерах. Поддержка RISC-V уже есть в ядре Linux и, например, в Haiku, а сама архитектура развивается в рамках и при поддержке Linux Foundation.
Мы портировали на RISC-V систему Haiku — причём эту архитектуру мы предпочли ARM. Почему? Ну просто ARM отпугнула меня своей сложной системой прерываний, большим количеством режимов процессора, сложностью MMU и так далее. На процесс портирования Haiku большое влияние оказал проект xv6 (реализация классического Unix Денниса Ритчи и Брайана Кернигана на RISC-V. — Ред.). В качестве эмулятора RISC-V я использовал TinyEMU, хотя для этой архитектуры их очень много.
Что касается RISC-V и Android — для нашего проекта это очень выгодно: когда появятся Android-устройства под RISC-V, мы сможем запускать Haiku на планшетах и смартфонах.
Илья Чугин,
автор порта RISC-V для Haiku (ник в Matrix x512)
История вопроса
Ещё в октябре 2022 года китайские инженеры объявили о том, что начали работу по запуску Android на архитектуре RISC-V. Дело в том, что из-за санкций США (а санкции эти с каждым годом становятся все жёстче) у них не было доступа к технологиям производства других чипов, и открытая RISC-V сразу стала желанной.
А раз из двух ведущих мобильных операционных систем использовать можно было только Android, то именно его инженеры из Поднебесной и решили «накатить» на RISC-V. Очевидно, Google пошёл им навстречу и подсветил какие-то закрытые нюансы близких к «железу» слоёв своей мобильной ОС.
Именно коммиты китайских инженеров составили основу нового GitHub-репозитория RISC-V Android — причём главный вклад внесла Alibaba Group.
Сейчас Android поддерживает архитектуры ARM, MIPS и x86. Поддержка RISC-V ещё не добавлена. Поддержку в эмуляторе обещают добавить совсем скоро, а Android Runtime подружится с RISC-V в первом квартале 2023 года — так обещают гугловцы.
Наиболее «горячая» архитектура сегодня — ARM. Процессор M1 от Apple в своё время просто взорвал мир IT. И вокруг ARM разгорелась нешуточная борьба. NVIDIA пыталась купить ARM за 40 млрд долларов, но другие компании не дали ей этого сделать — сделку признали незаконной и NVIDIA дали от ворот поворот. Ещё бы: в дополнение к своим крутым графическим чипам NVIDIA в случае успешной сделки заполучила бы ещё и права на топовую архитектуру микропроцессоров. А значит, она могла бы закрыть её от тех же Intel и AMD, став, по сути, монополистом.
Сейчас всё больше стран выказывают интерес к RISC-V и всё больше устройств начинают эти процессоры поддерживать. Другое дело, что ещё не создано ни одного производительного процессора уровня смартфона, сервера или персонального компьютера. Есть только выпущенный в Китае ноутбук — но и тот очень слабый. С другой стороны, процессоры на ядре RISC-V очень классные и уже эффективны для интернета вещей, умных часов и так далее — а значит, рано или поздно они разовьются и на этой архитектуре выйдет что-то производительное.
Сейчас Европа делает ставку на RISC-V. В России в своё время тоже были сильные лоббисты, которые хотели «убить» «Эльбрус», «Байкал» и остальные российские процессоры. Они требовали признать RISC-V «единственно верной» архитектурой и инвестировать только в неё. У подобных лоббистов ноги растут из компаний типа Intel, Samsung и IBM — то есть той когорты монополистов, которая не смогла навязать прямую борьбу ARM.
Кстати, именно они в своё время не дали NVIDIA купить ARM и с помощью своих связей заблокировали сделку — потому что боялись, что ARM попадёт «не в те руки», а точнее, полностью окажется в руках одной компании, которая таким образом получит мощное преимущество перед остальными участниками рынка.
Поэтому включение в Android поддержки процессора RISC-V — это логичный ход и понятная диверсификация рисков: если вдруг кто-то всё же сможет купить ARM, у Google всегда будет на что перескочить.
Лично я не вижу ничего плохого в том, что появляется больше разных архитектур. Другое дело, что Android как был закрытой операционной системой на уровне «железа», так ею и останется — даже несмотря на поддержку открытой архитектуры RISC-V. Посредством своих правил лицензирования Google продолжает контролировать всех производителей смартфонов и добровольно такой контроль ослаблять явно не будет. И если, например, китайцы продолжат дальше развивать свою открытую версию ARM-архитектуры, они не смогут обеспечить поддержку «большого» Android для всех устройств на базе своего процессора для всего мира.
Максим Горшенин,
блогер, популяризатор российской микроэлектроники
На что это повлияет
Большая часть экспертов настроена довольно скептически — по их мнению, включение RISC-V в Android пока мало что изменит. Максимум это позволит увеличить автономность и улучшить работу камеры телефона, однако качество реализации RISC-V в чипах ещё не достигло того уровня, чтобы стимулировать мощные инновации в мобильной сфере.
Я думаю, что принципиально ничего не изменится — как для разработчиков, так и для пользователей. У Google с недавних пор конфликт с ARM, и они просто хотят ни от кого не зависеть, но в целом это точно такой же RISC, как и в ARM (которая называется Advanced RISC Machines). Единственный интересный момент — это может быть шаг к Chromebook на RISC-процессорах.
А так в коде ОС это скорее поменяет низкоуровневые вызовы, которые пишут сами разработчики Android и которые прикрыты интерфейсными API для мобильных разработчиков. Так что в целом это просто логичный шаг Google, вполне утилитарный — и на мой взгляд, тут нет каких-то серьёзных планов.
Другое дело, что Google — это гигант, а значит, сейчас все, кто вкладывался в развитие RISC-V (а это опенсорсный проект), будут выглядеть весомее (например, те же «Байкалы»).
Алексей Гладков,
автор канала Mobile Developer
Вызывает сомнение и текущее развитие чипов на RISC-V: самые мощные образцы (да и те не производятся массово), сравнимы по характеристикам с довольно старыми процессорами известных брендов. Так, JH7110 аналогичен SoC в Samsung Galaxy S3 2012 года выпуска (правда, JH7110 — 64-разрядный), а TH1520 похож на SoC в Galaxy S7 образца 2016 года.
Сама технология RISC-V перспективна, но прямо сейчас я не вижу предпосылок для её широкой популярности в мобильном сегменте. И тут непонятно — то ли блокером является отсутствие поддержки RISC-V в Android, то ли просто никто из производителей особо не спешит идти в мобильный сегмент. Но поддержка RISC-V как минимум даст возможность производить устройства с процессорами на этой архитектуре под ОС Android и стимулирует появление очередного Android NDK.
Даст ли это толчок к тому, что производители начнут выпускать устройства на RISC-V, — пока непонятно. Но это может подтолкнуть к переходу на RISC-V производителей из России и Китая, которые сейчас отрезаны от ARM-технологий.
К тому же сейчас очень популярны чипы Qualcomm (они основаны на хорошо зарекомендовавшей себя архитектуре ARM, под которую выпущено много ПО). Например, тот же Apple плотно сидит на ARM. А вот удачных чипов на основе RISC-V я ещё не видел. Кроме того, никакие техногиганты тоже не заявляли о создании процессоров на RISC-V. Возможно, кто-то уже их делает, но не массово — а пока какой-нибудь крупный бренд не заявит о том, что начал ставить RISC-V-чипы в свои смартфоны, всё это останется просто программной поддержкой без практического применения и влияния на рынок.
У RISC-V пока нет явных преимуществ, кроме того, что это открытая и бесплатно лицензируемая архитектура — за неё не нужно платить, как за тот же ARM. Архитектуру RISC-V можно свободно модифицировать и изменять, лицензия это позволяет. А вот преимуществ в производительности или каких-то других выигрышных моментов, которые бы стимулировали переходить с ARM на RISC-V, у открытой архитектуры пока нет. Но если на RISC-V появятся достойные чипы, они вполне могут стать очень популярными.
Кирилл Розов,
автор телеграм-канала и ютуб-канала Android Broadcast
Однако есть и технооптимисты, которые видят классные следствия появления RISC-V в экосистеме Android — хоть и в относительно далёком будущем.
Архитектура RISC-V предлагает гораздо большую гибкость, масштабируемость и расширяемость за счёт открытого исходного кода — в отличие от тех же ARM и x86. Её включение в Android может привести к нескольким важным последствиям для мобильной разработки:
- Благодаря более простой архитектуре, по сравнению с традиционными чипами, время автономной работы и производительность мобильных устройств увеличится. А значит, вырастут базовые показатели MAU и DAU, от чего выиграют все производители Android-приложений.
- Мобильные разработчики увеличат контроль над аппаратным и программным обеспечением устройств, что приведёт к созданию более инновационных и оптимизированных мобильных приложений. Например, могут начать появляться приложения, поддерживающие VR-гарнитуры со встроенным отслеживанием движения, — ведь благодаря низкому энергопотреблению процессоров на базе RISC-V получится создать гарнитуру, которую можно носить в течение длительного периода времени без риска перегрева.
- Архитектура с открытым исходным кодом будет способствовать созданию совместной среды разработки для мобильных устройств и приложений, что позволит небольшим digital-компаниям конкурировать с лидерами индустрии.
Алексей Лачевский,
СEO digital-агентства Trinity Monsters