Симуляция ракетного чипа показывает неожиданное количество инструкций

Следующие два фрагмента кода отличаются только значением, загруженным в регистр x23, но количество инструкций minstret (сообщаемое имитацией Verilator микросхемы Rocket) существенно различается. Это ошибка или я что-то не так делаю?

Функция read_csr() взята из библиотеки сервера Frontend RISC-V (https://github.com/riscv/riscv-fesvr/blob/master/fesvr/encoding.h), а остальная часть кода [syscalls.c, crt.S, test.ld] похожа на тесты RISC-V (https://github.com/riscv/riscv-tests/tree/master/benchmarks/common).

Я проверил, что скомпилированные двоичные файлы содержат точно такие же инструкции, за исключением разницы в операндах.

Деление 0x0fffffff на 0xff, повторение 1024 раза: 3260 инструкций.

size_t instrs = 0 - read_csr(minstret);

asm volatile (
        "mv             x20,    zero;"
        "li             x21,    1024;"
        "li             x22,    0xfffffff;"
        "li             x23,    0xff;"

    "loop:"
        "div            x24,  x22,  x23;"
        "addi           x20,  x20,  1;"
        "bleu           x20,  x21,  loop;"

    ::: "x20", "x21", "x22", "x23", "x24", "cc"
);

instrs += read_csr(minstret);

Деление 0x0fffffff на 0xffff, повторение 1024 раза: 3083 инструкции.

size_t instrs = 0 - read_csr(minstret);

asm volatile (
        "mv             x20,    zero;"
        "li             x21,    1024;"
        "li             x22,    0xfffffff;"
        "li             x23,    0xffff;"

    "loop:"
        "div            x24,  x22,  x23;"
        "addi           x20,  x20,  1;"
        "bleu           x20,  x21,  loop;"

    ::: "x20", "x21", "x22", "x23", "x24", "cc"
);

instrs += read_csr(minstret);

Здесь 3083 инструкции кажутся правильными (1024 * 3 = 3072). Поскольку minstret подсчитывает удаленные инструкции, кажется странным, что в первом примере было выполнено еще ~ 200 инструкций. Эти результаты всегда одинаковы, независимо от того, сколько раз я запускаю эти две программы.


person radiosonde    schedule 13.06.2018    source источник
comment
как выглядит полная разборка, включая код, считывающий счетчик команд?   -  person old_timer    schedule 14.06.2018
comment
Разборка для случая 0xff: termbin.com/p713 и для случая 0xffff: termbin.com/mrj9. Адреса функций различаются, поэтому vimdiff не очень полезен, но если вы поищете символ loop, вы сможете найти приведенные выше фрагменты.   -  person radiosonde    schedule 14.06.2018
comment
Я забыл упомянуть, что код, считывающий счетчик инструкций, просто csrr a5,minstret.   -  person radiosonde    schedule 14.06.2018
comment
хммм, я понимаю, о чем вы говорите. Я не помню, открывали ли они исходный код своей логики, возможно, есть ярлык для разделения, основанного на ценностях, но это тоже не имело бы смысла. Надеялся, что это было что-то простое, например, выравнивание или небольшая разница в сборке. Но похоже, что это не так.   -  person old_timer    schedule 14.06.2018
comment
Вы обращались к ним по этому поводу?   -  person old_timer    schedule 14.06.2018
comment
Спасибо! Я еще не обращался к ним по этому поводу, но я создам новую проблему в репозитории и сообщу о том, что я там нашел.   -  person radiosonde    schedule 14.06.2018
comment
С какими двумя платформами вы сравниваете? RocketChip смоделирован с помощью Verilator vs. ???   -  person edc    schedule 14.06.2018
comment
Как псевдо-инструкция li реализована на ваших двух платформах?   -  person edc    schedule 14.06.2018
comment
@edc Я сравниваю два двоичных файла (которые различаются значением операнда) на одной платформе (чип Rocket смоделирован с помощью Verilator). Псевдо-инструкция li находится вне цикла, поэтому, насколько я понимаю, она не должна быть виновником 200 дополнительных инструкций. Ассемблерный код, созданный objdump [termbin.com/p713, termbin.com/mrj9], к сожалению, не расширяет псевдоинструкцию li.   -  person radiosonde    schedule 14.06.2018
comment
ох ,, я не видел, что вчера вечером это не тот же двоичный файл, только константы изменены, есть много различий. а для тестового контура выравнивание другое. попробуйте еще раз тест с выравниванием соответствия цикла для обоих и посмотрите, что вы видите ... это само по себе может объяснить то, что вы видите. (Я все время демонстрирую такие вещи, один и тот же машинный код занимает разное количество времени просто из-за выравнивания) ...   -  person old_timer    schedule 14.06.2018
comment
Решено в списке проблем репозитория [github.com/freechipsproject/rocket- чип / issues / 1495]. Я отправлю ответ ниже, если он кому-то поможет.   -  person radiosonde    schedule 14.06.2018


Ответы (1)


Проблема была решена на странице https://github.com/freechipsproject/rocket-chip/issues/1495.

Обслуживание прерывания отладки, которое, по-видимому, используется симуляцией, чтобы узнать, завершился ли тестовый тест, вызвало различия в количестве инструкций. Подробный журнал, созданный Verilator, показывает диапазон адресов отладки (начиная с 0x800), вводимый в разные моменты во время выполнения.

person radiosonde    schedule 14.06.2018