Condivisione della tecnologia

Test di conformità per l'architettura Riscv

2024-07-12

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

Il motivo per cui ci concentriamo direttamente su riscv-arch-test è perché il framework di test RISCOF utilizza riscv-arch-test.
Inserisci qui la descrizione dell'immagine

1. Il test architettonico

Un test architetturale è un singolo test che rappresenta il codice di test più piccolo che può essere compilato ed eseguito. È scritto in codice assembly e il suo prodotto è una firma di test. Un test architetturale può essere costituito da più casi di test.

2. Il pool di test architetturali RISC-V

Il pool di test architetturali RISC-V è costituito da tutti i test architetturali approvati che possono essere compilati dal framework di test in una suite di test architetturali. Le librerie di test dell'architettura RISC-V devono essere indipendenti dalla destinazione del test (e pertanto devono essere eseguite correttamente su qualsiasi destinazione conforme). Tieni presente che questi test non funzionali non sostituiscono la verifica o il test del dispositivo.

2.1 Struttura del pool di test

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

Registro delle caratteristiche del set di istruzioni del processore in modalità macchina (MISA)
messaggio = 0x800000000094112f
Rappresentazione binaria: 100000000000000000000000000000000000000100101000001000100101111
Inserisci qui la descrizione dell'immagine

test-riscv-arch/suite-test-riscv$ ls
rv32e_m/ rv32i_m/ rv64i_m/
test-riscv-arch/suite-di-test-riscv/rv64i_m$ ls
A/ B/ C/ CMO/ D/ F/ I/ K/ M/ privilegio/ P_non ratificato/ Zfh/ Zfinx/ Zicond/ Zifencei/

3. La suite di test architetturali RISC-V

La suite di test dell'architettura RISC-V è un insieme di test selezionati dal pool di test dell'architettura per testare la conformità di una specifica configurazione RISC-V. I risultati dei test vengono ottenuti sotto forma di firma della suite di test. La selezione del test si basa sulla configurazione dell'asserzione, sulle specifiche, sull'ambiente di esecuzione o sui requisiti della piattaforma della destinazione. Un processore o un modello di processore conforme deve visualizzare la stessa firma Gold Reference Test Suite della configurazione specifica sottoposta a test.

4. Il caso di prova

I casi di test fanno parte del test dell'architettura e testano solo una funzione della specifica.
Nota: un test può contenere più casi di test, ognuno dei quali ha le proprie condizioni di inclusione del test (definite dal parametro cond_str della macro RVTEST_CASE).

4.1 Denominazione dei test

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

test-riscv-arch/suite-di-test-riscv/rv64i_m/I/src$ ls
aggiungere-01.S e-01.S bge-01.S bne-01.S lb-align-01.S lhu-align-01.S disalign1-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
allineamento dell' ...

5. Infrastruttura di test di assemblaggio (prendere ./rv32i_m/I/src/add-01.S come esempio)

//
// 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

Una breve spiegazione del codice assembly sopra è la seguente:

  1. Intestazione per includere i commenti

#Questo file di assembly testa l'istruzione add dell'estensione RISC-VI per il covergroup add.

  1. Include file di intestazione

#include “model_test.h”
#include “arch_test.h”

Ogni test dovrebbe includere solo i seguenti file di intestazione:
model_test.h - definisce le macro specifiche del target, incluse le macro obbligatorie e facoltative: (ad esempio RVMODEL_xxx)
arch_test.h - definisce le macro di test predefinite, incluse le macro richieste e le macro opzionali: (come RVTEST_xxx)

  1. Imposta il TVM del test

RVTEST_ISA(“RV32I”)

  1. Codice di avvio specifico del target di prova

RVMODEL_BOOT

  1. Avvio della routine di inizializzazione GPR e codice di prova

CODICE_INIZIO_RVTEST

  1. Definire la stringa RVTEST_CASE e le condizioni

#ifdef CASO_DI_TEST_1
// questo test è pensato per i dispositivi che implementano l'estensione rv32I e richiede l'abilitazione della compilazione
// macro TEST_CASE_1. Questo test contribuirà all'etichetta di copertura "aggiungi".
RVTEST_CASE(0,“//controlla ISA:=regex(.32.);controlla ISA:=regex(.IO.);def TEST_CASE_1=True;”,aggiungi)

  1. Inizializza il puntatore alla regione della firma

RVTEST_SIGBASE( x16,signature_x16_1) // x16 punterà all'etichetta signature_x16_1 nella regione della firma

  1. Definire i casi di prova
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. Cambia registro base della firma
// 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. Termina il test e arresta il target del test
RVTEST_CODE_END
RVMODEL_HALT
  • 1
  • 2
  1. Crea sezione dati di input di prova
RVTEST_DATA_BEGIN
rvtest_data:
.word 0xbabecafe
RVTEST_DATA_END
  • 1
  • 2
  • 3
  • 4
  1. Crea una regione di firma precaricata
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. La firma del caso di prova

Una firma del test case è rappresentata da uno o più valori. Il valore verrà scritto in memoria a partire dall'indirizzo specificato da RVMODEL_DATA_BEGIN e terminando con l'indirizzo specificato da RVMODEL_DATA_END. Le firme vengono generate facilmente utilizzando la macro RVTEST_SIGUPD.

7. La firma del test

La firma del test è il valore caratteristico generato dall'esecuzione del test dell'architettura. Una firma di test può essere costituita da più firme di test case, precedute da una riga separata contenente il nome del test e un valore univoco che ne indica la versione. Il target del test si occupa di estrarre i valori dalla memoria e di formattarli opportunamente, utilizzando i metadati forniti dal framework, utilizzando le macro RVMODEL_DATA_BEGIN e RVMODEL_DATA_END.Il valore della firma del test case è scritto in righe, a partire dal byte più significativo a sinistra, nel formato<hex_value> , dove la lunghezza del valore sarà di 32 bit (quindi 8 caratteri), mentre il calcolo vero e proprio del test non tiene conto della lunghezza del valore. I file devono essere archiviati a partire dal valore all'indirizzo più basso della firma (ovvero da RVMODEL_DATA_BEGIN a RVMODEL_DATA_END). Inoltre, la firma dovrebbe sempre iniziare con un limite di 16 byte (128 bit) e la dimensione della firma dovrebbe essere un multiplo di 4 byte (ovvero dovrebbe anche terminare con un limite di 4 byte).

8. La firma della suite di test

Una firma di test suite è definita come un insieme di firme di test valide per una determinata suite di test architetturale. Rappresenta la firma del test della suite di test dell'architettura selezionata per una specifica configurazione RISC-V.

9. Quadro di test RISCOF

RISCOF: RISC-V Compatibility Framework è un framework basato su Python che consente l'uso di una serie di set di test architetturali RISC-V per testare gli obiettivi RISC-V (implementazioni hardware o software) per la compatibilità con lo standard RISC-V Golden Reference Sesso modello.
Inserisci qui la descrizione dell'immagine
Validatore di configurazione RISC-V: RISCV-Config
Generatore di test di conformità RISC-V: RISC-V CTG
Copertura RISC-V ISA: RISC-V ISAC
Affinché RISCOF possa eseguire normalmente il test, è necessario fornire il seguente contenuto:

  • config.ini: questo file è un file di configurazione di base e segue la sintassi ini. Questo file catturerà informazioni come: il nome del plugin DUT/di riferimento, il percorso del plugin, il percorso del file YAML basato su riscv-config, ecc.
  • directory dut-plugin: RISCOF richiede che il modello DUT testato sia fornito sotto forma di plug-in Python. Un plug-in Python è in realtà un file Python che contiene alcune funzioni standard e definite per eseguire attività di compilazione, esecuzione ed estrazione di firme di test. Il nome di questo file Python deve avere il prefisso riscof_ e deve esistere nella directory dut-plugin. Puoi fare riferimento alla sezione del file plug-in Python per imparare come scrivere questo file Python.
    Questa directory deve contenere anche i file isa e YAML della piattaforma basati su riscv-config, che forniscono la definizione del DUT. Questi file YAML verranno utilizzati per filtrare i test che devono essere eseguiti sul DUT.
    Infine, deve esistere una directory env nella directory dut-plugin, che contiene file di ambiente, come model_test.h, necessari per compilare ed eseguire test. Fare riferimento alla specifica TestFormat per le definizioni delle macro che possono essere utilizzate nel file model_test.h. La directory env può contenere anche altri file, come script del linker e script di post-elaborazione di cui gli utenti potrebbero aver bisogno.
  • directory del plug-in di riferimento: simile al plug-in DUT, RISCOF richiede anche un plug-in del modello di riferimento. La struttura della directory e dei file è la stessa del DUT. Tuttavia, i file YAML isa e della piattaforma non sono necessari perché RISCOF selezionerà sempre i file YAML per tutti gli scopi dal plug-in DUT.
    Per semplificare l'operazione, RISCOF genera modelli preimpostati di DUT standard e di modelli di riferimento per gli utenti tramite comandi di impostazione, come mostrato nella figura seguente:

$ riscof setup --dutname=spike

Il comando precedente genererà i seguenti file e directory nella directory corrente:

├──config.ini # file di configurazione per riscof
├──spike/ # modelli di plugin DUT
├── ambiente
│ ├── link.ld # script di collegamento DUT
│ └── model_test.h # file di intestazione specifico DUT
├── riscof_spike.py # Plugin Python DUT
├── spike_isa.yaml # DUT ISA yaml basato su riscv-config
└── spike_platform.yaml # DUT Platform yaml basato su riscv-config
├──sail_cSim/ # modelli di plugin di riferimento
├── ambiente
│ ├── link.ld # Riferimento allo script del linker
│ └── model_test.h # File di intestazione specifico del modello di riferimento
├── dentro.py
└── riscof_sail_cSim.py # Plugin Python per il modello di riferimento.

Basta modificare il picco precedente nel plug-in C920. Naturalmente, è necessario modificare ciascun file di configurazione e file 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

piattaforma_c920.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

L'esecuzione del comando seguente estrarrà l'elenco dei casi da test_list.yaml ed eseguirà ciascun caso. Puoi commentarne alcuni ed eseguire solo alcuni casi.

riscof esegui --config=config.ini
–suite=riscv-arch-test/riscv-test-suite/
–env=riscv-arch-test/riscv-test-suite/env
–testfile=riscof_work/test_list.yaml

L'esecuzione del comando seguente genererà test_list.yaml ed eseguirà la regressione

riscof esegui --config=config.ini
–suite=riscv-arch-test/riscv-test-suite/
–env=riscv-arch-test/riscv-test-suite/env

10. Risultati dei test

Inserisci qui la descrizione dell'immagine
Analisi delle cause degli errori:
Il primo:
Inserisci qui la descrizione dell'immagine
È perché si è verificato un errore durante la compilazione

    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

Secondo tipo:
Inserisci qui la descrizione dell'immagine
È solo che il c920 non abilita un determinato comando per impostazione predefinita.
Inserisci qui la descrizione dell'immagine

11. Forma d'onda rv64i_m/I/src/add-01.S

C'è anche una macro in model_test.h per la firma del dump e la simulazione della finitura

// 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

Corrispondente a 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

Il contenuto di “riscof_work/rv64i_m/I/src/add-01.S/dut/DUT-c920.signature” è il seguente:

e7d4b281
6f5ca309
00000000
00000000
c0000004
ffffffff
feffffff
ffffffff
ffffffff
007fffff
00000080
00000000
66666665
e6666666
00000001
00000000
0001ffff
80000000
10000001
00000000
ffffffff

Inserisci qui la descrizione dell'immagine
Inserisci qui la descrizione dell'immagine