A Method and System for Verifying the debug Function of the RISCV Architecture

The verification method, compiled using simulation tools and toolchains, solves the complex verification problem of debug functionality under the RISCV architecture, enabling a fast and flexible verification process that covers Host JTAG, openocd, and gdb behaviors, simplifying the debugging and problem localization process.

CN114201348BActive Publication Date: 2025-08-01GUANGDONG STARFIVE TECH LTD
View PDF 2 Cites 0 Cited by

Patent Information

Application Number
CN202111542262.7
Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
Filing Date
2021-12-16
Publication Date
2025-08-01
Estimated Expiration
2041-12-16

AI Technical Summary

Technical Problem

Existing technologies make it difficult to fully verify debug functionality under the RISC-CV architecture. In particular, the collaborative working process between the host and the DUT CPU is complex and time-consuming, making debugging difficult and unable to meet the needs of rapid verification.

Method used

The simulation tool is used to compile the Testbench to generate simulation execution files. The RISCV Toolchain and host toolchain are used to compile the CPU test case and C model. The hex file and so dynamic library file are passed by parameters. The simulation execution is achieved by combining the JTAG Driver and C model domain, and the debug function is verified in a coordinated manner.

Benefits of technology

It achieves verification of Host JTAG, openocd, and gdb behavior in a wide range of ways, with short simulation time, simple debugging, rapid problem localization, shortened verification cycle, high flexibility, and no need to recompile DUT and Testbench.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN114201348B_ABST
    Figure CN114201348B_ABST
Patent Text Reader

Abstract

The present invention relates to the technical field of CPUs, and specifically relates to a method and system for verifying the debug function of the RISCV architecture. In the present invention, a simulation tool is used to compile the Testbench to generate a simulation execution file; the RISCV Toolchain is used to compile the CPU testcase and convert it into a hex file for the Testbench to load onto the DUT CPU; the host toolchain is used to compile the c model and the model test to obtain a.so dynamic library; the simulation execution file is run, and the hex file and the so library file are passed through parameters to achieve the loading of the simulation execution file; the Debug function of the RISCV architecture is verified through the cooperation of the model test and the DUT CPU test. The present invention is flexible, and verification personnel can customize test cases according to their own needs. The simulation time is short, the debugging is simple, the problem positioning is simple, the verification cycle is short, and it can converge quickly. When modifying test cases or models, there is no need to recompile the DUT and the Testbench.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] The present invention relates to the technical field of CPUs, and particularly to a method and system for verifying the debug function of the RISCV architecture. Background Art

[0002] The debug function of the Riscv architecture is that, as Figure 1 shown, the user sends a message to the openocd software through the gdb software on the Host host, and the openocd software sends the message specified by the RISCV architecture to the DUT CPU through the JTAG cable, so as to achieve the purpose of controlling the DUT CPU through the Host host.

[0003] For the verification of the Debug function under the RISCV architecture, the Host and the DUT CPU work together. Although the Host is the master control end, the DUT CPU also needs to participate. Therefore, for traditional verification methods, only making Host use cases or DUTCPU use cases cannot achieve the purpose of verifying the debug function under the RISCV architecture.

[0004] In addition, since there are multiple layers of protocol parsing and conversion in the process from the Host to the DUT CPU, for example, for a simple breakpoint function for the user, the gdb needs to send gdb protocol messages to the openocd, the openocd parses the gdb protocol messages, converts them into RISCV architecture debug messages, and then converts them into JTAG protocols, and sends them to the DUT CPU through the cable, while the DUT CPU needs to parse the JTAG protocol messages back into RISCV architecture debug messages and process them through this message. The whole process is complex and hierarchical. Therefore, for verification, it is necessary to verify not only whether the DUT CPU can accept JTAG protocol messages and whether it can correctly convert back to RISCV architecture debug messages and other lower-level logics, but also whether it can achieve the higher-level function of gdb controlling the DUT CPU.

[0005] To solve this problem, we designed a verification method to verify the RISCV architecture Debug function. Summary of the Invention

[0006] In view of the deficiencies of the prior art, the present invention discloses a method and system for verifying the debug function of the RISCV architecture to solve the above problems.

[0007] The present invention is realized through the following technical solutions:

[0008] In a first aspect, the present invention provides a method for verifying the debug function of the RISCV architecture, including the following steps:

[0009] S1 Initialize, compile the Testbench using a simulation tool to generate a simulation execution file;

[0010] S2 Compile the CPU testcase using the RISCV Toolchain and convert it into a hex file for the Testbench to load onto the DUT CPU;

[0011] S3 Compile the C model and model test using the host toolchain to obtain a so dynamic library file;

[0012] S4 Run the simulation execution file and load the simulation execution file by passing the hex file and the so dynamic library file through parameters;

[0013] S5 Finally, verify the Debug function of the RISCV architecture through the cooperation of the model test and the DUT CPU test;

[0014] A RISCV architecture debug function verification system for implementing the above method, comprising:

[0015] A Testbench for connecting the C model domain and the Testcase to achieve separate compilation of the Testbench;

[0016] A C model domain for simulating the behaviors of the JTAG protocol and openocd and providing corresponding functions for the Testcase to call;

[0017] A Testcase including a program running on the DUT CPU and a modeltest compiled together with the C model on the host.

[0018] Furthermore, in the above method, when implementing the JTAG Driver, the JTAG Driver is defined as a System Verilog module with inputs of clock, reset, and jtag_TDI; and outputs of jtag_TCK, jtag_TMS, jtag_TDI, and jtag_TRSTn;

[0019] Declare a dpi function jtag_plugin_tick inside the module, and call the jtag_plugin_tick function when each jtag clock cycle arrives.

[0020] Furthermore, in the method, when implementing the C model, the JTAG Model of the C model is designed as a multi-threaded program, and the main thread process is as follows:

[0021] The jtag_plugin_tick function comes in and first determines whether g_thread is null. If it is null, it creates sem_wr and sem_rd semaphores for inter-thread synchronization, and then calls pthread_create to create the g_thread child thread; if g_thread is not null, the child thread is not created;

[0022] Determine whether the end flag is 1. If the end flag is 1, call test_finish to end the simulation; if the end flag is 0, continue;

[0023] Wait for the sem_wr semaphore; and when there is data to be sent, send the jtag data;

[0024] Get the data back from jtag_tdo and send the sem_rd semaphore to notify the child thread g_thread that the sending is complete;

[0025] Returns to the jtag_plugin_tick function.

[0026] Furthermore, in the method, the process of the child thread is as follows:

[0027] Enter g_thread_main and call jtag_reset to reset jtag;

[0028] Call the testcase_main function;

[0029] Set finish to 1 to notify the main thread that the use case is finished;

[0030] The child thread exits.

[0031] Furthermore, in the method, the use case function and jtag_reset function in the child thread will call the lower-level function jtag_drive to implement the jtag signal driver. At this time, the function will interact with the main thread and send the jtag signal to the main thread, so that the main thread can send it to the JTAG Driver after receiving it.

[0032] Furthermore, in the method, the process of the jtag_drive sub-function is as follows:

[0033] Enter jtag_drive, set tck to 0, set g_signal and other jtag signals;

[0034] Post sem_wr semaphore to notify the main thread that the jtag signal is ready;

[0035] Wait for sem_rd semaphore, the function returns;

[0036] Set tck to 1;

[0037] Post sem_wr semaphore to notify the main thread that the jtag signal is ready;

[0038] Wait for sem_rd semaphore, the function returns;

[0039] Retrieve jtag_tdo data and return.

[0040] Furthermore, in the method, the jtag_reset function is written as follows:

[0041] Void jtag_reset(){

[0042] For(int i=0;i<6;i++){

[0043] Jtag_drive(1,0);

[0044] }

[0045] Jtag_drive(0,0);

[0046] }.

[0047] Furthermore, in the method, the following functions are written according to the jtag protocol, which are respectively used to set the dtm address and read and write dtm data, void dtm_set_ir(char addr); Uint32_t dtm_dr(uint32_t data).

[0048] Furthermore, the testbench includes a DUT CPU and a JTAG Driver. The DUT CPU is the target device under test, and the JTAG Driver is a module that is connected to the DUT CPU via JTAG signals on one side and to the C model domain via a DPI interface on the other side.

[0049] The C model domain includes JTAG Model and openocd Model, which respectively simulate the JTAG protocol and openocd behavior;

[0050] Part of the Testcase is a program running on the DUT CPU, which is compiled using the RISCV Toolchain and is a program running on the DUT CPU; the other part is on the host, and the so dynamic library file is compiled together by the C model and model test.

[0051] The beneficial effects of the present invention are:

[0052] This method has a wide coverage, validating basic host JTAG behavior, OpenOCD behavior, and even GDB behavior. It is flexible, allowing verification personnel to customize use cases based on their needs. It offers fast simulation times, simplified debugging, simple problem location, and a short verification cycle, enabling rapid convergence. Modifying use cases or models with this method eliminates the need to recompile the DUT and testbench. BRIEF DESCRIPTION OF THE DRAWINGS

[0053] In order to more clearly illustrate the embodiments of the present invention or the technical solutions in the prior art, the following briefly introduces the drawings required for use in the embodiments or the description of the prior art. Obviously, the drawings described below are only some embodiments of the present invention. For ordinary technicians in this field, other drawings can be obtained based on these drawings without paying any creative work.

[0054] Figure 1 This is the Riscv architecture diagram of the background technology of the present invention;

[0055] Figure 2 This is a framework diagram of the RISCV architecture debug function verification system of the present invention;

[0056] Figure 3 This is a flow chart of the main thread function jtag_plugin_tick function according to an embodiment of the present invention;

[0057] Figure 4 This is a flowchart of a sub-thread according to an embodiment of the present invention;

[0058] Figure 5 This is a flowchart of the jtag_drive sub-function according to an embodiment of the present invention. DETAILED DESCRIPTION

[0059] To make the objectives, technical solutions, and advantages of the embodiments of the present invention more clear, the technical solutions in the embodiments of the present invention will be clearly and completely described below in conjunction with the accompanying drawings in the embodiments of the present invention. Obviously, the described embodiments are only part of the embodiments of the present invention, not all of the embodiments. Based on the embodiments of the present invention, all other embodiments obtained by ordinary technicians in this field without making creative efforts shall fall within the scope of protection of the present invention.

[0060] Example 1

[0061] This embodiment provides a method for verifying the debug function of the RISCV architecture, including the following steps:

[0062] S1 Initialization, use the simulation tool to compile the Testbench and generate the simulation execution file;

[0063] S2 Use the RISCV Toolchain to compile the CPU testcase and convert it into a hex file for the Testbench to load onto the DUT CPU;

[0064] S3 Use the host toolchain to compile the C model and model test to obtain the so dynamic library file;

[0065] S4 Run the simulation execution file and load the hex file and so dynamic library file through parameter passing to achieve the loading of the simulation execution file;

[0066] S5 Finally, complete the verification of the Debug function of the RISCV architecture through the cooperation of the model test and the DUT CPU test.

[0067] Compared with the existing debug verification method in the riscv - tests tool package, this embodiment is a complete verification means that combines gdb, openocd, testbench, and DUT (Design Under Test). This method is used to verify whether the entire process works properly and is quite useful in the later stage of verification.

[0068] However, it is not applicable in the initial and middle stages of verification because if this set of processes is used for verification, the simulation time is very long. If there are errors, the debugging time is long, it is very difficult to locate problems, reproduce problems, and the verification modification cycle is long, which will seriously slow down the project progress. Therefore, the method of this embodiment has a wide coverage. It can verify the basic behavior of Host JTAG, the behavior of openocd, and even the behavior of gdb. It is flexible, and verification personnel can customize test cases according to their own needs.

[0069] In this embodiment, compared with the existing method of writing a Host JTAG model in System Verilog language to simulate the Host JTAG behavior and writing directed test cases to verify the functions of the DUT, this method is more inclined to directed test cases. Fixed stimuli are written through directed test cases to verify basic functions. However, it is not flexible enough. It is difficult for verification personnel to change the Host JTAG behavior according to their own needs. And if the model is modified, the DUT and Testbench need to be recompiled. Therefore, the method in this embodiment has a short simulation time, simple debugging, simple problem location, short verification cycle, and can converge quickly. Modifying test cases or models does not require recompiling the DUT and Testbench.

[0070] Embodiment 2

[0071] At the specific implementation level, this embodiment provides an implementation of a JTAG Driver. The JTAG Driver is defined as a System Verilog module. The inputs are clock, reset, and jtag_TDI; the outputs are jtag_TCK, jtag_TMS, jtag_TDI, and jtag_TRSTn. The function jtag_plugin_tick of dpi is declared inside the module. When each jtagclock cycle arrives, the jtag_plugin_tick function is called. The implementation of this function is in the JTAG Model in the C model domain.

[0072] This embodiment also provides an implementation of a C model. As can be seen from the implementation of the JTAG Driver, the jtag_plugin_tick function is called once for each jtagclock, and it is actively called by the JTAG Driver side and passively executed by the C model side. From the perspective of the entire design, it is hoped that the C model will be actively executed and the JTAG Driver will be controlled through jtag. Therefore, the JTAG Model of the C model is designed as a multi-threaded program.

[0073] Embodiment 3

[0074] Based on Embodiment 2, as shown in Figure 3 this embodiment provides a process of the main thread function jtag_plugin_tick function, which is as follows:

[0075] When the `jtag_plugin_tick` function is entered, it first checks if `g_thread` is `null`. If it is `null`, it means it is the first call. In this case, it creates the semaphores `sem_wr` and `sem_rd` for inter-thread synchronization, and then calls `pthread_create` to create the child thread `g_thread`. If `g_thread` is not `null`, it means the child thread has already been created.

[0076] Then it checks if the end flag is 1. If the end flag is 1, it means the model test considers the test case can end. At this time, it calls `test_finish` to end the simulation. If the end flag is 0, it continues.

[0077] Wait for the semaphore `sem_wr`, that is, wait for the child thread to be ready with the data to be sent via JTAG. This function will return only when the child thread has data to send. That is to say, once this function returns, it has obtained the data to be sent.

[0078] Since there is data to be sent, send the JTAG data (jtag_TCK, jtag_TMS, jtag_TDI, jtag_TRSTn).

[0079] Get the data back from jtag_tdo.

[0080] Send the semaphore `sem_rd` to notify the child thread `g_thread` that the sending is complete.

[0081] Return to the `jtag_plugin_tick` function.

[0082] Embodiment 4

[0083] Based on Embodiment 3, as shown in Figure 4 This embodiment provides a process for the child thread, which is as follows:

[0084] Enter `g_thread_main`, call `jtag_reset` to reset the JTAG;

[0085] Call the `testcase_main` function, which is provided by each test case. Here, it just provides a hook function to call the main function of the test case;

[0086] Set `finish` to 1 to notify the main thread that the test case has ended;

[0087] The child thread exits.

[0088] In this embodiment, the use case function and the jtag_reset function in the sub-thread will call the lower-level function jtag_drive to implement the signal driving of JTAG. This function will interact with the main thread and send the JTAG signals to be sent to the main thread. Then, after the main thread receives them, it can send them to the JTAG Driver to achieve the purpose of communication.

[0089] Embodiment 5

[0090] Based on Embodiment 2, as shown in Figure 5 This embodiment provides a process for the sub-function jtag_drive:

[0091] Char jtag_drive(char tms, char tdi);

[0092] Enter jtag_drive, set tck to 0, and set other JTAG signals for g_signal;

[0093] Post the sem_wr semaphore to notify the main thread that the JTAG signal is ready;

[0094] Wait for the sem_rd semaphore. The return of the function means that the main thread has taken away the JTAG signal;

[0095] Set tck to 1;

[0096] Post the sem_wr semaphore to notify the main thread that the JTAG signal is ready;

[0097] Wait for the sem_rd semaphore. The return of the function means that the main thread has taken away the JTAG signal;

[0098] Retrieve the jtag_tdo data and return.

[0099] After defining the above lower-level functions in this embodiment, the JTAG Model can be developed. For example, for the jtag_reset function, its logic is to pull up tms for multiple cycles and then pull it down to complete the reset. Therefore, the jtag_reset function can be written as follows:

[0100] Void jtag_reset(){

[0101] For(int i = 0; i < 6; i++){

[0102] Jtag_drive(1, 0);

[0103] }

[0104] Jtag_drive(0,0);

[0105] }

[0106] Similarly, in this embodiment, the following functions can be written according to the JTAG protocol for setting the DTM address and reading and writing DTM data respectively.

[0107] Void dtm_set_ir(char addr);

[0108] Uint32_t dtm_dr(uint32_t data);

[0109] With the JTAG Model, the openocd Model can be developed based on it in the previous development. The specific implementation will not be listed one by one.

[0110] Embodiment 6

[0111] On other levels, corresponding test cases can be developed based on the C model domain in this embodiment. Since the models at each level have been constructed, the verification work can start from the verification of the lowest-level JTAG path and proceed step by step upward. First, write the test cases related to the JTAG path, which are completed by calling the JTAG Model. After the verification of the JTAG path is completed, start writing the test cases for the openocd path to complete the openocd verification.

[0112] This embodiment discloses a DTM test case. The RISC-V architecture stipulates that the DTM module has an IDCODE register with an address of 0x01, and it is assumed that its value should be 0xaa.

[0113] Write a test case to test whether the value of this register can be read through JTAG.

[0114] Uint32_t testcase_main(void){

[0115] Uint32_t rdata;

[0116] Dtm_set_ir(DTM_IDCODE);

[0117] Rdata = dtm_dr(0);

[0118] If(rdata != 0xaa){

[0119] Printf(“error!”);

[0120] Return -1;

[0121] }

[0122] Return 0;

[0123] }}

[0124] Example 7

[0125] Refer to Figure 2 As shown, this embodiment provides a RISCV architecture debug function verification system, which is divided into three parts:

[0126] One is the Testbench. It mainly includes two parts: the DUT CPU and the JTAG Driver. The DUT CPU is the target object to be tested. The JTAG Driver is a module that connects to the DUT CPU through JTAG signals on one side and connects to the Cmodel domain through the DPI interface on the other side. The purpose of its existence is to connect the C model domain and the Testcase, so that the Testbench can be compiled independently. When modifying the C model or the Testcase, there is no need to recompile the Testbench and the DUT.

[0127] The second is the C model domain. It mainly includes the JTAG Model and the openocd Model. They respectively simulate the behaviors of the JTAG protocol and openocd, and provide corresponding functions for the Testcase to call. This part is written by model engineers.

[0128] The third is the Testcase. The Testcae is divided into two parts. One part is the program running on the DUT CPU. This part of the program is compiled using the RISCV Toolchain and is the program running on the DUT CPU. The other part is on the host and is a so dynamic library file obtained by compiling the Cmodel and the model test together.

[0129] In summary, the present invention has a wide coverage. It can not only verify the basic behaviors of the Host JTAG, but also verify the behaviors of openocd and even gdb. The present invention is flexible. Verification personnel can customize test cases according to their own needs. The present invention has a short simulation time, simple debugging, simple problem location, short verification cycle, and can converge quickly. When modifying test cases or models in the present invention, there is no need to recompile the DUT and the Testbench.

[0130] The above embodiments are only used to illustrate the technical solutions of the present invention, rather than to limit it; although the present invention has been described in detail with reference to the foregoing embodiments, those of ordinary skill in the art should understand that: they can still modify the technical solutions recorded in the foregoing embodiments, or perform equivalent replacements on some of the technical features; and these modifications or replacements do not make the essence of the corresponding technical solutions deviate from the spirit and scope of the technical solutions of the embodiments of the present invention.

Claims

1. A method for verifying the debug function of the RISCV architecture, characterized in that, The method includes the following steps: S1 Initialization: Compile the Testbench using a simulation tool to generate a simulation execution file; S2 Use the RISCV Toolchain to compile the CPU testcase and convert it into a hex file for the Testbench to load onto the DUT CPU; S3 Use the host toolchain to compile the C model domain and model test to obtain a so dynamic library file; S4 Run the simulation execution file and load the simulation execution file by passing the hex file and the so dynamic library file through parameters; S5 Finally, verify the debug function of the RISCV architecture through the cooperation of the model test and the CPU testcase; Testbench, which is used to connect the C model domain and the Testcase to achieve separate compilation of the Testbench; C model domain, which is used to simulate the behavior of the JTAG protocol and openocd and provide corresponding functions for the Testcase to call; Testcase, part of the Testcase is a program running on the DUT CPU, which is compiled using the RISCV Toolchain; the other part is on the host and is compiled into a so dynamic library file by the C model domain and the model test together; The Testbench includes a DUT CPU and a JTAG Driver. The DUT CPU is the target object to be tested, and the JTAG Driver is a module that is connected to the DUT CPU through jtag signals on one side and connected to the C model domain through the DPI interface on the other side; The C model domain includes a JTAG Model and an openocd Model, which respectively simulate the behavior of the JTAG protocol and openocd.

2. The RISCV architecture debug function verification method according to claim 1, wherein In the method, when implementing the JTAG Driver, the JTAG Driver is defined as a System Verilog module, with inputs being clock, reset, and jtag_TDI; The outputs are jtag_TCK, jtag_TMS, jtag_TDI, and jtag_TRSTn; Declare a dpi function jtag_plugin_tick inside the module, and call the jtag_plugin_tick function when each jtag clock cycle arrives.

3. A method for verifying the debug function of a RISCV architecture according to claim 2, characterized in that In the method, when implementing the C model domain, design the JTAG Model of the C model domain as a multi-threaded program. The main thread process is as follows: When the `jtag_plugin_tick` function is entered, it first checks if `g_thread` is `null`. If it is `null`, it creates the semaphore `sem_wr` and the semaphore `sem_rd` for inter-thread synchronization, and then calls `pthread_create` to create a child thread. If `g_thread` is not `null`, it does not create a child thread. It checks if the end flag is 1. If the end flag is 1, it calls `test_finish` to end the simulation. If the end flag is 0, it continues. It waits for the semaphore `sem_wr`; and when there is data to be sent, it sends the JTAG data. It retrieves data from `jtag_tdo` and sends the semaphore `sem_rd` to notify the child thread `g_thread` that the sending is complete. It returns to the `jtag_plugin_tick` function.

4. The RISCV architecture debug function verification method according to claim 3, wherein In the described method, the process of the child thread is as follows: It enters `g_thread_main` and calls `jtag_reset` to reset the JTAG. It calls the `testcase_main` function. It sets `finish` to 1 to notify the main thread that the test case has ended. The child thread exits.

5. A method for verifying the debug function of a RISCV architecture according to claim 4, characterized in that, In the described method, the test case function and the `jtag_reset` function in the child thread will call the `jtag_drive` function to implement the signal driving of the JTAG. At this time, the `jtag_drive` function will interact with the main thread, sending the JTAG signals that need to be sent to the main thread, so that the main thread can send them to the JTAG Driver after receiving them.

6. The RISCV architecture debug function verification method according to claim 5, wherein In the described method, the process of the `jtag_drive` function is as follows: It enters `jtag_drive`, sets `tck` to 0, and sets the JTAG signal of `g_signal`. It posts the semaphore `sem_wr` to notify the main thread that the JTAG signal is ready. It waits for the semaphore `sem_rd`. It sets `tck` to 1. It posts the semaphore `sem_wr` to notify the main thread that the JTAG signal is ready. It waits for the semaphore `sem_rd`. It returns the `jtag_tdo` data.

7. A method for verifying the debug function of a RISC-V architecture according to claim 5, characterized in that, In the described method, the `jtag_reset` function is written as follows: Void jtag_reset(){ for(int i = 0; i < 6; i++){ jtag_drive(1, 0); } jtag_drive(0, 0); }。 8. A method for verifying the debug function of a RISCV architecture according to claim 7, characterized in that, In the described method, the following functions are written according to the JTAG protocol, which are used to set the DTM address and read / write DTM data respectively, Void dtm_set_ir(char addr); Uint32_t dtm_dr(uint32_t data).

Citation Information

Patent Citations

  • USB PD rapid charging protocol chip verification method based on RISC _ V processor

    CN110058974A

  • RISCV architecture multi-core CPU memory consistency simulation verification method

    CN113467911A