Основная идея DiffTest: для двух реализаций, основанных на одной и той же спецификации, при одинаковых входных данных их поведение должно быть согласованным. Возвращаясь к конструкции процессора, для двух реализаций согласно руководству riscv, при условии одной и той же корректной программы, изменения их состояния (регистры, память) должны быть согласованы для двух реализаций:
Один из них — наш процессор;
Альтернативно выберите симулятор в качестве эталонной реализации. Каждый раз, когда обе стороны завершают выполнение инструкции, они проверяют состояние своих соответствующих регистров и памяти. Если они обнаруживают, что статус противоречив, они немедленно сообщают об ошибке и останавливают выполнение клиентской программы (что эквивалентно вынесению утверждения об утверждении). каждую инструкцию).
DiffTest = метод онлайн-проверки поведения на уровне команд
Онлайн = проверка во время запуска программы
Уровень инструкций = каждая выполненная инструкция проверяется
Может преобразовать любую программу в тесты уровня инструкций и подтвердить статус.
Поддержка программ, которые не закончатся, например ОС
Не нужно заранее знать результат процедуры
Потому что мы сравниваем поведение выполнения инструкций, а не семантику программы.
Наиболее широкое применение DiffTest:Если после выполнения сотен или тысяч инструкций возникают ошибки декодирования или выполнения, как нам быстро найти первую инструкцию с ошибкой? Это адская трудность.
В этой статье мы выберем следующий пример для иллюстрации:
QEMU как эталонный объект (REF)
НЭМУ как испытуемый (DUT)
Конечно, если вам нужно протестировать аппаратное обеспечение процессора, процессор также можно использовать в качестве тестируемого устройства.
2 DiffTest при поддержке NEMU
make menuconfig
1
Войдите в «Тестирование и отладка» -> «Включить дифференциальное тестирование» -> «Эталонный дизайн», как показано ниже:
Когда NEMU используется для ИУ, вы можете выбрать 5 режимов симулятора в качестве эталонного симулятора REF.
QEMU, режим динамической библиотеки, код находится в NEMU/tools/qemu-dl-diff/
QEMU, режим Socket, код находится в NEMU/tools/qemu-socket-diff/
KVM, код находится в NEMU/tools/kvm-diff/
НЕМУ
ШИП
Что касается последних трех, автор не проводил каких-либо конкретных исследований, поэтому в этой статье они не будут представлены.
3 QEMU делает REF (режим динамической библиотеки)
Вы можете изменить NEMU/tools/qemu-dl-diff/, скомпилированный в динамическую библиотеку riscv64-qemu-so. Связь между NEMU, динамическими библиотеками и QEMU:
Динамическая библиотека: riscv64-qemu-so, которая экспортирует серию функциональных интерфейсов difftest_xx.
QEMU: В исполняемом файле qemu-system-riscv64 имеются функциональные интерфейсы серии cpu_xx, gdb_xx и qemu_xx.
NEMU: программа riscv64-nemu-interpreter вызывает динамическую библиотеку, которая затем вызывает QEMU.
конкретный процесс:
Исполняемая программа NEMU riscv64-nemu-interpreter загружает riscv64-qemu-so, вызывая функцию dlopen, и анализирует функциональные символы серии difftest_xx для последующих вызовов.
Затем NEMU вызывает функцию difftest_init для инициализации.
В функции difftest_init функция dlopen будет вызвана снова, чтобы загрузить исполняемый файл qemu-system-riscv64 и проанализировать серии функциональных символов cpu_xx, gdb_xx и qemu_xx. Эти функциональные символы фактически являются базовым кодом реализации серии функций difftest_xx. .
В файле qemu-system-riscv64 проанализированная функция является основной функцией, а затем функция difftest_init вызовет ее для запуска программы qemu.
Затем, если все в порядке, можно вызвать функцию qemu для сравнения результатов инструкций.
4 QEMU для REF (режим сокета)
Вы можете изменить NEMU/tools/qemu-сокет-diff/, скомпилированный в динамическую библиотеку riscv64-qemu-so. Связь между NEMU, динамическими библиотеками и QEMU:
Динамическая библиотека: riscv64-qemu-so, которая экспортирует серию функциональных интерфейсов difftest_xx.
QEMU: Исполняемый файл qemu-system-riscv64 имеет функциональные интерфейсы серий cpu_xx и gdb_xx.
NEMU: программа riscv64-nemu-interpreter вызывает динамическую библиотеку. Динамическая библиотека отправляет пакет команды через сокет. QEMU получает пакет, анализирует его и решает, какую функцию вызвать для выполнения на основе конкретной команды.
конкретный процесс:
Исполняемая программа NEMU riscv64-nemu-interpreter загружает riscv64-qemu-so, вызывая функцию dlopen, и анализирует функциональные символы серии difftest_xx для последующих вызовов.
Затем NEMU вызывает функцию difftest_init для инициализации.
В функции difftest_init дочерний процесс выполнит fork() и запустит QEMU, вызвав функцию execlp, в то время как родительский процесс продолжает выполняться, подключается к QEMU через сокет и вызывает функцию init_isa для инициализации;
Затем, если все нормально, можно сравнить результаты команды через сокет.