Обмен технологиями

Тестирование соответствия архитектуры Riscv

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Причина, по которой мы фокусируемся непосредственно на riscv-arch-test, заключается в том, что среда тестирования RISCOF использует riscv-arch-test.
Вставьте сюда описание изображения

1. Архитектурный тест

Архитектурный тест — это одиночный тест, представляющий наименьший тестовый код, который можно скомпилировать и запустить. Он написан на ассемблере, а его продуктом является тестовая подпись. Архитектурный тест может состоять из нескольких тестовых случаев.

2. Архитектурный пул тестов RISC-V

Пул архитектурных тестов RISC-V состоит из всех утвержденных архитектурных тестов, которые могут быть скомпилированы платформой тестирования в набор архитектурных тестов. Библиотеки тестирования архитектуры RISC-V должны быть независимыми от цели тестирования (и, следовательно, должны корректно работать на любой совместимой цели). Обратите внимание, что это нефункциональное тестирование не заменяет проверку или тестирование устройства.

2.1 Структура тестового пула

architectural-tests-suite (root)
|-- <architecture>_<mode>/<feature(s)>, where
<architecture> is [ RV32I | RV64I | RV32E ]
<mode> is [ M | MU | MS | MSU ], where
   M   Machine      mode tests - tests execute in M-mode only
   MU  Machine/User mode tests - tests execute in both M- & U-modes (S-mode may exist)
   MS  Machine/Supv mode tests - tests execute in both M- & S-modes (not U-mode)
   MSU All          mode tests - tests execute in all of M-, S-, & U-Modes
<feature(s)> are the lettered extension [A | B | C | M ...] or subextension [Zifencei | Zam | ...] when the tests involve extensions, or more general names when tests cut across extension definitionss (e.g. Priv, Interrupt, Vm). The feature string consists of an initial capital letter, followed by any further letters in lower case.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Регистр характеристик набора команд процессора машинного режима (MISA)
миса = 0x800000000094112f
Двоичное представление: 100000000000000000000000000000000000000100101000001000100101111
Вставьте сюда описание изображения

riscv-arch-test/riscv-test-suite$ ls
env/ Makefile.include README.md rv32e_m/ rv32i_m/ rv64i_m/
riscv-arch-test/riscv-test-suite/rv64i_m$ ls
A/ B/ C/ CMO/ D/ F/ I/ K/ M/ privilege/ P_unratified/ Zfh/ Zfinx/ Zicond/ Zifencei/

3. Архитектурный тестовый набор RISC-V

Набор архитектурных тестов RISC-V — это набор тестов, выбранных из пула архитектурных тестов для проверки соответствия конкретной конфигурации RISC-V. Результаты тестирования получаются в виде сигнатуры тестового набора. Выбор теста основан на конфигурации утверждений цели, спецификации, среде выполнения или требованиях платформы. Соответствующий процессор или модель процессора должны иметь ту же подпись Gold Reference Test Suite, что и конкретная тестируемая конфигурация.

4. Тестовый случай

Тестовые случаи являются частью архитектурного тестирования и проверяют только одну функцию спецификации.
Примечание. Тест может содержать несколько тестовых примеров, и каждый тестовый пример имеет свои собственные условия включения теста (определяемые параметром cond_str макроса RVTEST_CASE).

4.1 Именование тестов

<test objective>-<test number>.S
  • 1

riscv-arch-test/riscv-test-suite/rv64i_m/I/src$ ls
add-01.S and-01.S bge-01.S bne-01.S lb-align-01.S lhu-align-01.S misalign1-jalr-01.S sd-align-01.S slliw-01.S sltiu-01.S sraiw-01.S srliw-01.S sw-align-01.S
addi-01.S andi-01.S bgeu-01.S fence-01.S lbu-align-01.S lui-01.S or-01.S sh-align-01.S sllw-01.S sltu-01.S sraw-01.S srlw-01.S xor-01.S
addiw-01.S auipc-01.S blt-01.S jal-01.S ld-align-01.S lw-align-01.S ori-01.S sll-01.S slt-01.S sra-01.S srl-01.S sub-01.S xori-01.S
addw-01.S beq-01.S bltu-01.S jalr-01.S lh-align-01.S lwu-align-01.S sb-align-01.S slli-01.S slti-01.S srai-01.S srli-01.S subw-01.S

5. Инфраструктура тестирования сборки (в качестве примера возьмем ./rv32i_m/I/src/add-01.S)

//
// This assembly file tests the add instruction of the RISC-V I extension for the add covergroup.
// 
#include "model_test.h"
#include "arch_test.h"
RVTEST_ISA("RV32I")

.section .text.init
.globl rvtest_entry_point
rvtest_entry_point:
RVMODEL_BOOT
RVTEST_CODE_BEGIN

#ifdef TEST_CASE_1

RVTEST_CASE(0,"//check ISA:=regex(.*32.*);check ISA:=regex(.*I.*);def TEST_CASE_1=True;",add)

RVTEST_SIGBASE( x3,signature_x3_1)

inst_0:
// rs2 == rd != rs1, rs1==x4, rs2==x24, rd==x24, rs1_val > 0 and rs2_val > 0, rs2_val == 1, rs1_val == (2**(xlen-1)-1), rs1_val != rs2_val, rs1_val == 2147483647
// opcode: add ; op1:x4; op2:x24; dest:x24; op1val:0x7fffffff;  op2val:0x1
TEST_RR_OP(add, x24, x4, x24, 0x80000000, 0x7fffffff, 0x1, x3, 0, x18)

inst_1:
// rs1 == rs2 != rd, rs1==x10, rs2==x10, rd==x28, rs1_val > 0 and rs2_val < 0, rs2_val == -257, rs1_val == 131072
// opcode: add ; op1:x10; op2:x10; dest:x28; op1val:0x20000;  op2val:0x20000
TEST_RR_OP(add, x28, x10, x10, 0x40000, 0x20000, 0x20000, x3, 4, x18)

inst_2:
// rs1 == rs2 == rd, rs1==x21, rs2==x21, rd==x21, rs1_val < 0 and rs2_val < 0, rs1_val == -16777217
// opcode: add ; op1:x21; op2:x21; dest:x21; op1val:-0x1000001;  op2val:-0x1000001
TEST_RR_OP(add, x21, x21, x21, 0xfdfffffe, -0x1000001, -0x1000001, x3, 8, x18)
......
......
......
RVTEST_CODE_END
RVMODEL_HALT

RVTEST_DATA_BEGIN
.align 4

rvtest_data:
.word 0xbabecafe
.word 0xbabecafe
.word 0xbabecafe
.word 0xbabecafe
RVTEST_DATA_END

RVMODEL_DATA_BEGIN
rvtest_sig_begin:
sig_begin_canary:
CANARY;

signature_x3_0:
    .fill 0*(XLEN/32),4,0xdeadbeef

signature_x3_1:
    .fill 17*(XLEN/32),4,0xdeadbeef

signature_x8_0:
    .fill 16*(XLEN/32),4,0xdeadbeef

signature_x1_0:
    .fill 512*(XLEN/32),4,0xdeadbeef

signature_x1_1:
    .fill 43*(XLEN/32),4,0xdeadbeef

#ifdef rvtest_mtrap_routine

tsig_begin_canary:
CANARY;
mtrap_sigptr:
    .fill 64*(XLEN/32),4,0xdeadbeef
tsig_end_canary:
CANARY;

#endif

#ifdef rvtest_gpr_save

gpr_save:
    .fill 32*(XLEN/32),4,0xdeadbeef

#endif

sig_end_canary:
CANARY;
rvtest_sig_end:
RVMODEL_DATA_END
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

Краткое объяснение приведенного выше ассемблерного кода выглядит следующим образом:

  1. Заголовок для включения комментариев

#Этот файл сборки тестирует инструкцию добавления расширения RISC-V I для добавления группы обложек.

  1. Включает заголовочные файлы

#включить «model_test.h»
#включить «arch_test.h»

Каждый тест должен включать только следующие файлы заголовков:
model_test.h — определяет макросы, специфичные для цели, включая обязательные и дополнительные макросы: (например, RVMODEL_xxx)
Arch_test.h — определяет предопределенные тестовые макросы, включая обязательные и дополнительные макросы: (например, RVTEST_xxx)

  1. Установите TVM теста

RVTEST_ISA(“RV32I”)

  1. Тестовый целевой загрузочный код

RVMODEL_BOOT

  1. Начало процедуры инициализации георадара и тестового кода

RVTEST_CODE_BEGIN

  1. Определите строку RVTEST_CASE и условия

#ifdef ТЕСТ_СЛУЧАЙ_1
// этот тест предназначен для устройств, реализующих расширение rv32I, и требует включения компиляции
// макрос TEST_CASE_1. Этот тест будет способствовать добавлению метки покрытия.
RVTEST_CASE(0,“//проверка ISA:=regex(.32.);проверьте ISA:=regex(.Я.);def TEST_CASE_1=True;”,add)

  1. Инициализирует указатель на область подписи

RVTEST_SIGBASE( x16,signature_x16_1) // x16 будет указывать на метку signature_x16_1 в области подписи

  1. Определите тестовые случаи
inst_0:
// rs2 == rd != rs1, rs1==x4, rs2==x24, rd==x24, rs1_val > 0 and rs2_val > 0, rs2_val == 1, rs1_val == (2**(xlen-1)-1), rs1_val != rs2_val, rs1_val == 2147483647
// opcode: add ; op1:x4; op2:x24; dest:x24; op1val:0x7fffffff;  op2val:0x1
TEST_RR_OP(add, x24, x4, x24, 0x80000000, 0x7fffffff, 0x1, x3, 0, x18)

inst_1:
// rs1 == rs2 != rd, rs1==x10, rs2==x10, rd==x28, rs1_val > 0 and rs2_val < 0, rs2_val == -257, rs1_val == 131072
// opcode: add ; op1:x10; op2:x10; dest:x28; op1val:0x20000;  op2val:0x20000
TEST_RR_OP(add, x28, x10, x10, 0x40000, 0x20000, 0x20000, x3, 4, x18)
...
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
//Tests for a instructions with register-register operand
#define TEST_RR_OP(inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, testreg) 
    TEST_CASE(testreg, destreg, correctval, swreg, offset, 
      LI(reg1, MASK_XLEN(val1))                        ;
      LI(reg2, MASK_XLEN(val2))                        ;
      inst destreg, reg1, reg2                        ;
    )
#define TEST_CASE(testreg, destreg, correctval, swreg, offset, code... )        ;
    code                                ;
    RVTEST_SIGUPD(swreg,destreg,offset)        ;
    RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval)

 /* automatically adjust base and offset if offset gets too big, resetting offset                                 */
 /* RVTEST_SIGUPD(basereg, sigreg)          stores sigreg at offset(basereg) and updates offset by regwidth         */
 /* RVTEST_SIGUPD(basereg, sigreg,newoff) stores sigreg at newoff(basereg) and updates offset to regwidth+newoff */
#define RVTEST_SIGUPD(_BR,_R,...)                        ;
  .if NARG(__VA_ARGS__) == 1                                ;
        .set offset,_ARG1(__VA_OPT__(__VA_ARGS__,0))        ;
  .endif                                                ;
  CHK_OFFSET(_BR, REGWIDTH,0)                                ;
  SREG _R,offset(_BR)                                        ;
  .set offset,offset+REGWIDTH
  
  RVMODEL_IO_ASSERT_GPR_EQ 定义在target的model_test.h中```

在咱们得model_test.h中将RVMODEL_IO_ASSERT_GPR_EQ 宏定义如下:比较错误的话,往0xF00000801

```c
#define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I)  
    li _S, 0xF0000080;         
    mv t0, _R;                 
    li t3, _I;                 
    beq t0, t3, 1f;            
    li t2, 1;                  
    sw t2, 0(_S);              
    j 2f;                      
1:                             
    li t2, 0;                  
    sw t2, 0(_S);              
2:                             
    nop;```

在tb.v中加入监测对AXI 写地址总线,地址0xF0000080的监测,如果出现fail_cnt >0,可以判断该testcase错误

```c
// RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval) used to check destreg == correctval
// destreg != correctva write testreg 1, else write testreg 0
always @(posedge `CPU_CLK) begin
    if ((cpu_awaddr[31:0] == 32'hF000_0080) && cpu_wvalid && `clk_en && (cpu_wstrb[15:0] == 16'hf)) begin
       if(`SOC_TOP.biu_pad_wdata == 1'b1) begin
         fail_cnt ++;
       end
    end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  1. Изменить регистр базы подписей
// this will change the signature base register to x3. x3 will not point to signature_x3_0 in
// the signature region
RVTEST_SIGBASE( x3,signature_x3_0)

// continue with new test cases ..
TEST_RR_OP(add, x4, x24, x27, 0x55555955, 0x00000400, 0x55555555, x3, 0, x5)
...
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. Завершите тест и остановите тестовую цель
RVTEST_CODE_END
RVMODEL_HALT
  • 1
  • 2
  1. Создать раздел тестовых входных данных
RVTEST_DATA_BEGIN
rvtest_data:
.word 0xbabecafe
RVTEST_DATA_END
  • 1
  • 2
  • 3
  • 4
  1. Создать предварительно загруженную область подписи
RVMODEL_DATA_BEGIN
rvtest_sig_begin:
sig_begin_canary:
CANARY;

signature_x3_0:
    .fill 0*(XLEN/32),4,0xdeadbeef

signature_x3_1:
    .fill 17*(XLEN/32),4,0xdeadbeef

signature_x8_0:
    .fill 16*(XLEN/32),4,0xdeadbeef

signature_x1_0:
    .fill 512*(XLEN/32),4,0xdeadbeef

signature_x1_1:
    .fill 43*(XLEN/32),4,0xdeadbeef

#ifdef rvtest_mtrap_routine

tsig_begin_canary:
CANARY;
mtrap_sigptr:
    .fill 64*(XLEN/32),4,0xdeadbeef
tsig_end_canary:
CANARY;

#endif

#ifdef rvtest_gpr_save

gpr_save:
    .fill 32*(XLEN/32),4,0xdeadbeef

#endif

sig_end_canary:
CANARY;
rvtest_sig_end:
RVMODEL_DATA_END
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

6. Подпись тестового случая

Сигнатура тестового примера представлена ​​одним или несколькими значениями. Значение будет записано в память, начиная с адреса, указанного в RVMODEL_DATA_BEGIN, и заканчивая адресом, указанным в RVMODEL_DATA_END. Подписи легко генерируются с помощью макроса RVTEST_SIGUPD.

7. Тестовая подпись

Тестовая сигнатура — это характеристическое значение, генерируемое при выполнении архитектурного теста. Сигнатура теста может состоять из нескольких сигнатур тестовых примеров, которым предшествует отдельная строка, содержащая имя теста и уникальное значение, указывающее его версию. Цель теста отвечает за извлечение значений из памяти и их соответствующее форматирование с использованием метаданных, предоставленных фреймворком, с помощью макросов RVMODEL_DATA_BEGIN и RVMODEL_DATA_END.Значение сигнатуры тестового примера записывается строками, начиная со старшего байта слева, в формате<hex_value> , где длина значения будет 32 бита (то есть 8 символов), тогда как фактический тестовый расчет не учитывает длину значения. Файлы следует хранить, начиная со значения по наименьшему адресу подписи (то есть от RVMODEL_DATA_BEGIN до RVMODEL_DATA_END). Кроме того, подпись всегда должна начинаться на 16-байтовой (128-битной) границе, а размер подписи должен быть кратен 4 байтам (то есть она также должна заканчиваться на 4-байтовой границе).

8. Подпись тестового набора

Сигнатура набора тестов определяется как набор сигнатур тестов, которые действительны для данного набора архитектурных тестов. Он представляет собой тестовую сигнатуру набора архитектурных тестов, выбранного для конкретной конфигурации RISC-V.

9. Система тестирования RISCOF

RISCOF — RISC-V Compatibility Framework — это платформа на основе Python, которая позволяет использовать набор наборов архитектурных тестов RISC-V для проверки целей RISC-V (аппаратных или программных реализаций) на совместимость со стандартом Golden Reference RISC-V. Модельный секс.
Вставьте сюда описание изображения
Валидатор конфигурации RISC-V: RISCV-Config
Генератор тестов на соответствие RISC-V: RISC-V CTG
Покрытие RISC-V ISA: RISC-V ISAC
Чтобы RISCOF мог нормально запустить тест, необходимо предоставить следующий контент:

  • config.ini: Этот файл является базовым файлом конфигурации и соответствует синтаксису ini. Этот файл будет собирать такую ​​информацию, как: имя DUT/справочного плагина, путь к плагину, путь к файлу YAML на основе riscv-config и т. д.
  • Каталог dut-plugin: RISCOF требует, чтобы тестируемая модель DUT была предоставлена ​​в виде подключаемого модуля Python. Плагин Python на самом деле представляет собой файл Python, который содержит определенные стандартные и определенные функции для выполнения компиляции, выполнения тестов и действий по извлечению сигнатур. Имя этого файла Python должно иметь префикс riscof_ и должно существовать в каталоге dut-plugin. Вы можете обратиться к разделу «Файл подключаемого модуля Python», чтобы узнать, как написать этот файл Python.
    Этот каталог также должен содержать файлы YAML isa и платформы на основе riscv-config, которые предоставляют определение DUT. Эти файлы YAML будут использоваться для фильтрации тестов, которые необходимо запустить на тестируемом устройстве.
    Наконец, в каталоге dut-plugin должен существовать каталог env, содержащий файлы среды, такие как model_test.h, необходимые для компиляции и запуска тестов. Пожалуйста, обратитесь к спецификации TestFormat за определениями макросов, которые можно использовать в файле model_test.h. Каталог env также может содержать другие файлы, такие как сценарии компоновщика и сценарии постобработки, которые могут понадобиться пользователям.
  • Каталог reference-plugin: Подобно подключаемому модулю DUT, RISCOF также требует подключаемого модуля эталонной модели. Структура каталогов и файлов такая же, как и у DUT. Однако файлы YAML isa и платформы не требуются, поскольку RISCOF всегда будет выбирать файлы YAML для всех целей из подключаемого модуля DUT.
    Чтобы упростить работу, RISCOF генерирует для пользователей стандартные шаблоны настроек тестируемого устройства и эталонной модели с помощью команд настройки, как показано на следующем рисунке:

$ riscof настройка --dutname=spike

Приведенная выше команда создаст следующие файлы и каталоги в текущем каталоге:

├──config.ini # файл конфигурации для riscof
├──spike/ # Шаблоны плагинов DUT
├── окружающая среда
│ ├── link.ld # Скрипт компоновщика DUT
│ └── model_test.h # Файл заголовка, специфичный для DUT
├── riscof_spike.py # плагин DUT python
├── spike_isa.yaml # DUT ISA yaml на основе riscv-config
└── spike_platform.yaml # yaml платформы DUT на основе riscv-config
├──sail_cSim/ # шаблоны справочных плагинов
├── окружающая среда
│ ├── link.ld # Ссылка на скрипт компоновщика
│ └── model_test.h # Заголовочный файл, специфичный для эталонной модели
├── в этом.py
└── riscof_sail_cSim.py # Плагин Python для эталонной модели.

Просто измените приведенный выше шип на плагин C920. Конечно, вам нужно изменить каждый файл конфигурации и файл Python.
c920_isa.yaml

hart_ids: [0]
hart0:
  ISA: RV64IMAFDCVZicsr_Zicbom_Zicbop_Zicboz_Zihintpause_Zfh_Zca_Zcb_Zcd_Zba_Zbb_Zbc_Zbs
  physical_addr_sz: 40
  User_Spec_Version: "2.2"
  Privilege_Spec_Version: "1.10"
  hw_data_misaligned_support: false
  pmp_granularity: 4
  supported_xlen: [64]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

c920_platform.yaml

mtime:
  implemented: true
  address: 0xBFF8
mtimecmp:
  implemented: true
  address: 0x4000
nmi:
  label: nmi_vector
reset:
  address: 0x000000000 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Выполнение следующей команды извлечет список дел из test_list.yaml и запустит каждый случай. Некоторые из них можно закомментировать и запускать только некоторые случаи.

riscof запустить --config=config.ini
–suite=riscv-arch-test/riscv-test-suite/
–env=riscv-arch-test/riscv-test-suite/env
–testfile=riscof_work/test_list.yaml

Выполнение следующей команды создаст test_list.yaml и запустит регрессию.

riscof запустить --config=config.ini
–suite=riscv-arch-test/riscv-test-suite/
–env=riscv-arch-test/riscv-test-suite/env

10. Результаты испытаний

Вставьте сюда описание изображения
Анализ причин ошибки:
Первый:
Вставьте сюда описание изображения
Это потому, что во время компиляции произошла ошибка.

    INFO | Compiling test: /ssd_fes/jiongz/desktop/github/c920_riscof1/riscv-arch-test/riscv-test-suite/rv64i_m/I/src/beq-01.S
   ERROR | /opt/picocom/ThirdParty_Libs/T-head/C920_R2S0P21/C920_R2S0_manuals_and_tools/manuals_and_tools/08_toolchain_900_series_cpu_toolchain/V2.8.0/Xuantie-900-gcc-elf-newlib-x86_64-V2.8.0/bin/../lib/gcc/riscv64-unknown-elf/10.4.0/../../../../riscv64-unknown-elf/bin/ld: main.elf section `.text' will not fit in region `MEM1'
collect2: error: ld returned 1 exit status
  • 1
  • 2
  • 3

Второй тип:
Вставьте сюда описание изображения
Просто с920 по умолчанию не включает определенную команду.
Вставьте сюда описание изображения

11. Форма сигнала rv64i_m/I/src/add-01.S

В model_test.h также есть макрос для дампа подписи и завершения моделирования.

// This will dump the test results (signature) via the testbench dump module.
#define RVMODEL_HALT                                          
    signature_dump:                                           
      la   a0, begin_signature;                               
      la   a1, end_signature;                                 
      li   a2, 0xF0000040;                                    
    signature_dump_loop:                                      
      bge  a0, a1, signature_dump_end;                        
      lw   t0, 0(a0);                                         
      sw   t0, 0(a2);                                         
      addi a0, a0, 4;                                         
      j    signature_dump_loop;                               
    signature_dump_end:                                       
      nop;                                                    
    terminate_simulation:                                     
      li   a0, 0xF0000000;                                    
      li   a1, 0xCAFECAFE;                                    
      sw   a1, 0(a0);                                         
      j    terminate_simulation
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

Соответствует tb.v

always @(posedge `CPU_CLK or negedge `CPU_RST) begin
    if (!`CPU_RST) begin
        msi <= 1'b0;
        mei <= 1'b0;
        mti <= 1'b0;
    end else begin
        //if ((wb_cpu.cyc == 1'b1) && (wb_cpu.stb == 1'b1) && (wb_cpu.we == 1'b1) && (cpu_awaddr[31:0] == 32'hF000_0000)) begin
        if ((cpu_awaddr[31:0] == 32'hF000_0000) && cpu_wvalid && `clk_en && (cpu_wstrb[15:0] == 16'hf)) begin
            case (`SOC_TOP.biu_pad_wdata[31:0])
                32'hCAFE_CAFE: begin // end simulation
                    $display("Finishing simulation.");
                    #100;
                    if(fail_cnt >0) begin
                     $error("This case test failed!");
                    end
                    $finish;
                end
                ......
 end

// Signature Dump
int dump_file; // Declare file handle
always @(posedge `CPU_CLK) begin
    if ((cpu_awaddr[31:0] == 32'hF000_0040) && cpu_wvalid && `clk_en && (cpu_wstrb[15:0] == 16'hf)) begin
        if (!dump_file) begin // Check if file is already open
            dump_file = $fopen("DUT-c920.signature", "w"); // Open file if not already opened
        end
        //for (int i = 7; i >= 0; i--) begin
        //    $fwrite(dump_file, "%hn", `SOC_TOP.biu_pad_wdata[i*4 +: 4]); // Write data
        //end
        $fwrite(dump_file, "%hn", `SOC_TOP.biu_pad_wdata[31:0]); // Write data
    end
    else if((cpu_awaddr[31:0] == 32'hF000_0000) && cpu_wvalid && `clk_en && (cpu_wstrb[15:0] == 16'hf)) begin
        if (dump_file) begin // If file is open, close it
            $fclose(dump_file);
            dump_file = 0; // Reset file handle to 0 indicating file is closed
        end
    end
end

// RVMODEL_IO_ASSERT_GPR_EQ(testreg, destreg, correctval) used to check destreg == correctval
// destreg != correctva write testreg 1, else write testreg 0
always @(posedge `CPU_CLK) begin
    if ((cpu_awaddr[31:0] == 32'hF000_0080) && cpu_wvalid && `clk_en && (cpu_wstrb[15:0] == 16'hf)) begin
       if(`SOC_TOP.biu_pad_wdata == 1'b1) begin
         fail_cnt ++;
       end
    end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
#include "model_test.h"
#include "arch_test.h"
RVTEST_ISA("RV64I")

.section .text.init
.globl rvtest_entry_point
rvtest_entry_point:
RVMODEL_BOOT
RVTEST_CODE_BEGIN

#ifdef TEST_CASE_1

RVTEST_CASE(0,"//check ISA:=regex(.*64.*);check ISA:=regex(.*I.*);def TEST_CASE_1=True;",add)

RVTEST_SIGBASE( x8,signature_x8_1)

inst_0:
// rs1 == rs2 != rd, rs1==x0, rs2==x0, rd==x20, rs1_val > 0 and rs2_val > 0, rs1_val == 4, rs1_val==4 and rs2_val==6148914691236517206, rs1_val != rs2_val
// opcode: add ; op1:x0; op2:x0; dest:x20; op1val:0x0;  op2val:0x0
TEST_RR_OP(add, x20, x0, x0, 0x0, 0x0, 0x0, x8, 0, x16)

inst_1:
// rs2 == rd != rs1, rs1==x2, rs2==x26, rd==x26, rs1_val > 0 and rs2_val < 0, rs2_val == -1073741825
// opcode: add ; op1:x2; op2:x26; dest:x26; op1val:0x5;  op2val:-0x40000001
TEST_RR_OP(add, x26, x2, x26, 0xffffffffc0000004, 0x5, -0x40000001, x8, 8, x16)

inst_2:
// rs1 == rs2 == rd, rs1==x22, rs2==x22, rd==x22, rs1_val < 0 and rs2_val < 0, rs1_val == -8388609
// opcode: add ; op1:x22; op2:x22; dest:x22; op1val:-0x800001;  op2val:-0x800001
TEST_RR_OP(add, x22, x22, x22, 0xfffffffffefffffe, -0x800001, -0x800001, x8, 16, x16)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

Содержимое «riscof_work/rv64i_m/I/src/add-01.S/dut/DUT-c920.signature» следующее:

е7д4б281
6f5ca309
00000000
00000000
с0000004
фффффффф
fefffffe
фффффффф
ффффффбф
007fffff
00000080
00000000
66666665
е6666666
00000001
00000000
0001фффф
80000000
10000001
00000000
ффффффф

Вставьте сюда описание изображения
Вставьте сюда описание изображения