Почему ловушка Rocket Chip на FPGA после выполнения кода в DRAM

Я пытаюсь установить и запустить версию Rocket Chip на плате Nexys4 DDR. Пока мне удалось сгенерировать verilog, синтезировать дизайн и прикрепить зонд jtag (segger jlink). Доступ к регистрам и памяти можно получить через openocd и gdb. После загрузки небольшого фрагмента asm ядро ​​начинает выполнение, но сразу после первой выполненной инструкции переходит на 0x0000000. Я предполагаю, что это ловушки, и поскольку вектор ловушек не инициализирован, ядро ​​заканчивается на 0. Кто-нибудь знает, как это исправить?

Симуляция ядра работает как с верилятором, так и с vcs. В обоих случаях ядро ​​без проблем выполняет три инструкции asm.

Протестированный код asm:

.section .text                                                                  
.global _start                                                                  
_start:                                                                         
    add x0,x0,x0                                                                
    add x0,x0,x0                                                                                                                             
    j _start

связано с этим скриптом:

SECTIONS
{
    . = 0x80000000;
    .text : { *(.text) }
}

Дамп объекта:

Disassembly of section .text:

0000000080000000 <_start>:
    80000000:   00000033                add     zero,zero,zero
    80000004:   00000033                add     zero,zero,zero
    80000008:   ff9ff06f                j       80000000 <_start>

person mdxg    schedule 07.08.2019    source источник


Ответы (1)


Недавно столкнулся с аналогичной проблемой с DDR4, GDB и чипом SiFive RISC. После загрузки кода в DDR4 и попытки выйти из вектора сброса RISCV немедленно перейдет к 0x00000000. После отладки с помощью Xilinx ILA мы обнаружили, что, хотя мы программировали пространство памяти DDR4 с помощью GDB, RISCV кэшировал часть кода внутренне и лишь изредка подталкивал часть к DDR4. С точки зрения RISCV, это считается нормальным, потому что, когда вы делаете шаг, он решает использовать кеш, если он доступен, иначе он получит код из DDR4. Но предположим, что ваш ЦП выполняет несколько пакетов доступа к DDR, потому что для повышения эффективности ему требуется много кода. Часть этого большого фрагмента кода, который может быть пустым пространством, если ваша программа действительно мала, не была запрограммирована, и, следовательно, ECC рассчитывается неправильно.

После перехода на 0x00000000 проверьте регистр причины машины. Посмотрите, указывает ли он 0x2, недопустимая инструкция. В моем случае я увидел это, потому что шина обнаружила «ошибку шины», которая была вызвана ошибкой ECC для наполовину запрограммированного пакета DDR.

Один из способов обойти это может заключаться в том, чтобы дополнить ваш ELF кучей дополнительных нулей в конце, чтобы размер заставлял кеш сбрасываться в память. Как только DDR действительно запрограммирован и ECC верны, вы больше не должны видеть недопустимую инструкцию. Дайте мне знать, работает ли это для вас или нет.

person Rich Maes    schedule 09.08.2019
comment
Большое спасибо за ответ :) Через несколько дней я вернулся к проблеме и нашел причину с помощью ваших советов. Я проверил регистр mcause после перехода на 0x0000000, и да, он показал 0x2 для недопустимой инструкции. Я переключил DRAM с помощью небольшого блока BRAM, но все осталось по-прежнему. После этого я контролировал порт памяти с помощью ILA и блокировал чтение инструкций, выдаваемое ядром. Оказалось, что vivado упаковал ядро ​​с 32-битным интерфейсом вместо 64-битного. Таким образом, старшие 32 бита всегда были нулевыми и, следовательно, не действовали в качестве инструкции. - person mdxg; 15.08.2019