Как я могу скомпилировать C-код, чтобы получить скелет с неподвижным элементом минимальной сборки RISC-V?

У меня есть следующий простой C-код:

   void main(){
    int A = 333;
    int B=244;
    int sum;
    sum = A + B;  
}

Когда я скомпилирую это с помощью

$riscv64-unknown-elf-gcc code.c -o code.o

Если я хочу видеть код сборки, я использую

$riscv64-unknown-elf-objdump -d code.o 

Но когда я изучаю код сборки, я вижу, что это генерирует много кода, который я предполагаю для поддержки ядра Proxy (я новичок в riscv). Однако я не хочу, чтобы этот код поддерживал ядро ​​Proxy, потому что идея состоит в том, чтобы реализовать только этот простой C-код внутри FPGA.

Я читал, что riscv предоставляет три типа компиляции: режим Bare-metal, прокси-сервер newlib и riscv Linux. Согласно предыдущим исследованиям, вид компиляции, который я должен делать, - это режим голого металла. Это связано с тем, что я желаю минимальную сборку без поддержки операционной системы или прокси-сервера ядра. Функции сборки как системного вызова не требуются.

Тем не менее, я еще не смог найти, поскольку я могу скомпилировать код C для получения скелета минимальной программы сборки riscv. Как я могу скомпилировать код C выше в режиме голого металла или получить скелет минимального кода сборки riscv?

Ответ 1

Предупреждение: этот ответ несколько истек -o f -d по состоянию на последнюю Привилегированную спецификацию RISC-V v1.9, которая включает в себя удаление управляющего /tohost регистра (CSR), который был частью -стандартный интерфейс Host-Target (HTIF), который с тех пор был удален. Текущие (по состоянию на сентябрь 2016 г.) riscv-tests вместо этого выполняют сопоставление памяти хранилищем в расположении- tohost, которое в привязанной среде контролируется tohost front-end server.


Если вы действительно и действительно хотите/хотите запускать код RISC-V голым железом, то вот инструкции для этого. Вы теряете кучу полезных вещей, таких как программная эмуляция printf или FP-trap, которую предоставляет riscv-pk (ядро прокси).

Перво-наперво - Спайк загружается в 0x200. Поскольку Spike - это золотая модель симулятора ISA, ваше ядро также должно загружаться с 0x200.

(кашель, по состоянию на 13 июля 2015 года, "основная" ветвь riscv-tools (https://github.com/riscv/riscv-tools) использует более раннюю привилегированную ISA до v1.7 и, следовательно, начинается с 0x2000. В этом посте предполагается, что вы используете v1. 7+, что может потребовать использования ветки riscv-tools "new_privileged_isa").

Поэтому, когда вы разбираете свою голую железную программу, лучше начинать с 0x200 !!! Если вы хотите запустить его поверх прокси-ядра, лучше начать с 0x10000 (а если Linux, то что-то еще больше…).

Теперь, если вы хотите запустить голое железо, вы заставляете себя писать код загрузки процессора. Тьфу. Но давайте разберемся с этим и притворимся, что в этом нет необходимости.

(Вы также можете посмотреть в riscv-tests/env/p описание виртуальной машины для машины с физическим адресом. Вы найдете скрипт компоновщика, который вам нужен, и файл macros.h для описания исходного кода установки. Или еще лучше, в riscv-tests/benchmarks/common.crt.S).


В любом случае, вооружившись вышеизложенным (запутанным) знанием, давайте отбросим все это и начнем с самого начала...

hello.s:
 .align 6
 .globl _start
 _start:
 # screw boot code, we're going minimalist
 # mtohost is the CSR in machine mode
 csrw mtohost, 1;
 1:
 j 1b

и link.ld:

 OUTPUT_ARCH( "riscv" )
 ENTRY( _start )
 SECTIONS
 {
 /* text: test code section */
 . = 0x200;
 .text :
 {
 *(.text)
 }
 /* data: Initialized data segment */
 .data :
 {
 *(.data)
 }
 /* End of uninitalized data segement */
 _end = .;
 }

Теперь, чтобы скомпилировать это...

riscv64-unknown-elf-gcc -nostdlib -nostartfiles -Tlink.ld -o привет привет

Это компилируется в (riscv64-unknown-elf -o bjdump -d привет):

 hello: file format elf64-littleriscv

 Disassembly of section .text:

 0000000000000200 <_start>:
 200: 7810d073 csrwi tohost,1
 204: 0000006f j 204 <_start+0x4>

И запустить его:

spike hello

Это вещь красоты.

Скрипт ссылки размещает наш код в 0x200. Spike будет начинаться с 0x200, а затем записывать # 1 в регистр управления/состояния "tohost", который сообщает Spike "прекратить работу". И затем мы раскручиваем адрес (1: j 1b), пока интерфейсный сервер не получит сообщение и не убьет нас.

Может быть возможно отказаться от сценария компоновщика, если вы сможете выяснить, как сказать компилятору самостоятельно перемещать <_start> в 0x200.


Для других примеров вы можете просмотреть следующие репозитории:

Хранилище riscv-tests содержит минимальные тесты RISC-V ISA (https://github.com/riscv/riscv-tests).

Этот Makefile имеет опции компилятора: https://github.com/riscv/riscv-tests/blob/master/isa/Makefile

Многие из макросов описания "виртуальной машины" и сценариев компоновщика можно найти в riscv-tests/env (https://github.com/riscv/riscv-test-env).

Вы можете взглянуть на "самый простой" тест по адресу (riscv-tests/isa/rv64ui-p-simple.dump).

И вы можете проверить riscv-tests/benchmarks/common для запуска и поддержки кода для запуска голого металла.

Ответ 2

"Дополнительный" код помещается туда gcc и является тем типом материала, который требуется для любой программы. Прокси-ядро разработано так, чтобы обеспечить минимальный объем поддержки, необходимый для запуска подобных вещей. Как только ваш процессор заработает, я бы порекомендовал запускать вещи поверх pk, а не с чистого листа.

А пока, если вы хотите взглянуть на простую сборку, я бы порекомендовал пропустить этап связывания с помощью [-c ':

riscv64-unknown-elf-gcc code.c -c -o code.o
riscv64-unknown-elf-objdump -d code.o

Для примеров запуска кода без pk или linux я бы посмотрел на riscv-тесты.

Ответ 3

Вам нужен небольшой стартер asm, который подготовит среду для запуска вашего c-кода.

Посмотрите на эти примеры из чистого металла https://github.com/michaeljclark/riscv-probe