2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Der Grund, warum wir uns direkt auf riscv-arch-test konzentrieren, liegt darin, dass das RISCOF-Testframework riscv-arch-test verwendet.
Ein Architekturtest ist ein einzelner Test, der den kleinsten Testcode darstellt, der kompiliert und ausgeführt werden kann. Es ist im Assembler-Code geschrieben und sein Produkt ist eine Testsignatur. Ein Architekturtest kann aus mehreren Testfällen bestehen.
Der RISC-V-Architekturtestpool besteht aus allen genehmigten Architekturtests, die vom Testframework zu einer Architekturtestsuite zusammengestellt werden können. Testbibliotheken für die RISC-V-Architektur müssen testzielunabhängig sein (und sollten daher auf jedem kompatiblen Ziel ordnungsgemäß ausgeführt werden). Bitte beachten Sie, dass dieser nicht funktionale Test kein Ersatz für eine Verifizierung oder einen Gerätetest ist.
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.
Machine Mode Processor Instruction Set Characteristics Register (MISA)
misa = 0x800000000094112f
Binäre Darstellung: 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/ Privileg/ P_nicht ratifiziert/ Zfh/ Zfinx/ Zicond/ Zifencei/
Die RISC-V-Architekturtestsuite besteht aus einer Reihe von Tests, die aus dem Architekturtestpool ausgewählt werden, um die Konformität einer bestimmten RISC-V-Konfiguration zu testen. Testergebnisse werden in Form einer Testsuite-Signatur erhalten. Die Testauswahl basiert auf der Assertionskonfiguration, der Spezifikation, der Ausführungsumgebung oder den Plattformanforderungen des Ziels. Ein kompatibler Prozessor oder ein kompatibles Prozessormodell sollte dieselbe Gold Reference Test Suite-Signatur aufweisen wie die spezifische getestete Konfiguration.
Testfälle sind Teil des Architekturtests und testen nur eine Funktion der Spezifikation.
Hinweis: Ein Test kann mehrere Testfälle enthalten und jeder Testfall hat seine eigenen Testeinschlussbedingungen (definiert durch den Parameter cond_str des Makros RVTEST_CASE).
<test objective>-<test number>.S
riscv-arch-test/riscv-test-suite/rv64i_m/I/src$ ls
add-01.S und-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 oder-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
//
// 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
Eine kurze Erklärung des obigen Assemblercodes lautet wie folgt:
#Diese Assemblydatei testet den Add-Befehl der RISC-V I-Erweiterung für die Add-Covergroup.
#include „model_test.h“
#include „arch_test.h“
Jeder Test sollte nur die folgenden Header-Dateien enthalten:
model_test.h – definiert zielspezifische Makros, einschließlich erforderlicher und optionaler Makros: (z. B. RVMODEL_xxx)
arch_test.h – definiert vordefinierte Testmakros, einschließlich erforderlicher Makros und optionaler Makros: (z. B. RVTEST_xxx)
RVTEST_ISA("RV32I")
RVMODEL_BOOT
RVTEST_CODE_BEGIN
#ifdef TEST_CASE_1
// dieser Test ist für Geräte gedacht, die die rv32I-Erweiterung implementieren und erfordert die Aktivierung der Kompilierung
// Makro TEST_CASE_1. Dieser Test trägt zum Coverage-Label „add“ bei.
RVTEST_CASE(0,“//prüfe ISA:=regex(.32.);überprüfen Sie ISA:=regex(.ICH.);def TEST_CASE_1=True;”, hinzufügen)
RVTEST_SIGBASE( x16,signature_x16_1) // x16 zeigt auf das Label signature_x16_1 im Signaturbereich
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)
...
...
//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 宏定义如下:比较错误的话,往0xF0000080写1
```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
// 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)
...
...
RVTEST_CODE_END
RVMODEL_HALT
RVTEST_DATA_BEGIN
rvtest_data:
.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
Eine Testfallsignatur wird durch einen einzelnen oder mehrere Werte dargestellt. Der Wert wird beginnend bei der durch RVMODEL_DATA_BEGIN angegebenen Adresse und endend bei der durch RVMODEL_DATA_END angegebenen Adresse in den Speicher geschrieben. Signaturen können ganz einfach mit dem Makro RVTEST_SIGUPD generiert werden.
Die Testsignatur ist der charakteristische Wert, der durch den Architekturtestlauf generiert wird. Eine Testsignatur kann aus mehreren Testfallsignaturen bestehen, denen eine separate Zeile vorangestellt ist, die den Namen des Tests und einen eindeutigen Wert zur Angabe seiner Version enthält. Das Testziel ist dafür verantwortlich, die Werte aus dem Speicher zu extrahieren und sie mithilfe der vom Framework bereitgestellten Metadaten mithilfe der Makros RVMODEL_DATA_BEGIN und RVMODEL_DATA_END entsprechend zu formatieren.Der Testfallsignaturwert wird in Zeilen geschrieben, beginnend mit dem höchstwertigen Byte links im Format<hex_value> , wobei die Länge des Werts 32 Bit (also 8 Zeichen) beträgt, während die eigentliche Testberechnung die Länge des Werts nicht berücksichtigt. Dateien sollten beginnend mit dem Wert an der niedrigsten Adresse der Signatur gespeichert werden (d. h. von RVMODEL_DATA_BEGIN bis RVMODEL_DATA_END). Darüber hinaus sollte die Signatur immer an einer 16-Byte-Grenze (128-Bit) beginnen und die Größe der Signatur sollte ein Vielfaches von 4 Bytes sein (d. h. sie sollte auch an einer 4-Byte-Grenze enden).
Eine Testsuite-Signatur ist als eine Reihe von Testsignaturen definiert, die für eine bestimmte architektonische Testsuite gültig sind. Es stellt die Testsignatur der Architekturtestsuite dar, die für eine bestimmte RISC-V-Konfiguration ausgewählt wurde.
RISCOF – Das RISC-V-Kompatibilitätsframework ist ein Python-basiertes Framework, das die Verwendung einer Reihe von RISC-V-Architekturtestsätzen ermöglicht, um RISC-V-Ziele (Hardware- oder Softwareimplementierungen) auf Kompatibilität mit der standardmäßigen RISC-V Golden Reference zu testen Modelsex.
RISC-V-Konfigurationsvalidator: RISCV-Config
Generator für RISC-V-Konformitätstests: RISC-V CTG
RISC-V ISA-Abdeckung: RISC-V ISAC
Damit RISCOF den Test normal ausführen kann, müssen die folgenden Inhalte bereitgestellt werden:
$ riscof setup --dutname=spike
Der obige Befehl generiert die folgenden Dateien und Verzeichnisse im aktuellen Verzeichnis:
├──config.ini # Konfigurationsdatei für riscof
├──spike/ # DUT-Plugin-Vorlagen
├── Umgebung
│ ├── link.ld # DUT-Linker-Skript
│ └── model_test.h # DUT-spezifische Header-Datei
├── riscof_spike.py # DUT-Python-Plugin
├── spike_isa.yaml # DUT ISA yaml basierend auf riscv-config
└── spike_platform.yaml # DUT-Plattform-YAML basierend auf Riscv-Konfiguration
├──sail_cSim/ # Referenz-Plugin-Vorlagen
├── Umgebung
│ ├── link.ld # Referenz-Linker-Skript
│ └── model_test.h # Referenzmodellspezifische Headerdatei
├── drin.py
└── riscof_sail_cSim.py # Referenzmodell-Python-Plugin.
Ändern Sie einfach den obigen Spike in das C920-Plugin. Natürlich müssen Sie jede Konfigurationsdatei und Python-Datei ändern.
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]
c920_platform.yaml
mtime:
implemented: true
address: 0xBFF8
mtimecmp:
implemented: true
address: 0x4000
nmi:
label: nmi_vector
reset:
address: 0x000000000
Durch Ausführen des folgenden Befehls wird die Fallliste aus test_list.yaml extrahiert und jeder Fall ausgeführt. Sie können einige davon auskommentieren und nur einige Fälle ausführen.
riscof run --config=config.ini
–suite=riscv-arch-test/riscv-test-suite/
–env=riscv-arch-test/riscv-test-suite/env
–testfile=riscof_work/test_list.yaml
Durch Ausführen des folgenden Befehls wird test_list.yaml generiert und die Regression ausgeführt
riscof run --config=config.ini
–suite=riscv-arch-test/riscv-test-suite/
–env=riscv-arch-test/riscv-test-suite/env
Fehlerursachenanalyse:
Der erste:
Dies liegt daran, dass beim Kompilieren ein Fehler aufgetreten ist
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
Der zweite Typ:
Es ist nur so, dass c920 einen bestimmten Befehl standardmäßig nicht aktiviert.
Es gibt auch ein Makro in model_test.h für die Dump-Signatur und die Abschlusssimulation
// 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
Entsprechend 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
#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)
Der Inhalt von „riscof_work/rv64i_m/I/src/add-01.S/dut/DUT-c920.signature“ lautet wie folgt:
e7d4b281
6f5ca309
00000000
00000000
c0000004
ffffffff
fefffffe
ffffffff
ffffffbf
007ffffff
00000080
00000000
66666665
e6666666
00000001
00000000
0001ffff
80000000
10000001
00000000
fffffeff