A RISC-V-based hardware development system

Through a RISC-V-based hardware development system and the collaborative work of multiple debugging modules, the problem of low debugging efficiency in RISC-V processor design is solved, fast and accurate error location and automatic detection are achieved, and the efficiency of processor design is improved.

CN118605909BActive Publication Date: 2025-10-10SHENZHEN UNIV
View PDF 2 Cites 0 Cited by

Patent Information

Application Number
CN202410770378.3
Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
Filing Date
2024-06-14
Publication Date
2025-10-10
Estimated Expiration
2044-06-14

AI Technical Summary

Technical Problem

In RISC-V processor design, existing debugging methods are inefficient and difficult to quickly and accurately locate erroneous instructions. In addition, the simulation process cannot fully record the executed instructions, making it difficult to find the error location.

Method used

A RISC-V-based hardware development system is adopted, including an instruction tracing module, a waveform slicing module, a deadlock detection module, a simulated memory tracing module, a function call tracing module, a peripheral access tracing module, an instruction simulator, a differential debugging comparison module, an integrated debugging module and a calling module. Through the collaborative work of these modules, complete recording and automatic detection of the processor are achieved, thereby improving debugging efficiency.

Benefits of technology

It achieves complete recording of processor operation traces, automatically detects deadlock situations, reduces waveform file size, and flexibly locates instruction error locations, greatly improving the development efficiency of processor design.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN118605909B_ABST
    Figure CN118605909B_ABST
Patent Text Reader

Abstract

The application provides a RISC-V-based hardware development system, comprising an instruction tracking module, a waveform slicing module, a deadlock detection module, an emulated storage tracking module, a function call tracking module, a peripheral access tracking module, an instruction emulator, a differential debugging comparison module, a comprehensive debugging module and a calling module; wherein the waveform period recorded by the waveform slicing module each time can be configured by itself, greatly reducing the space occupied by the generated waveform file; the differential debugging comparison module can adaptively process the execution period of each instruction of a processor, that is, the module can be used for a processor with single period or a processor using multi-stage pipeline technology. Through the use of the RISC-V-based hardware development system of the application for RISC-V processor design, the development and debugging efficiency of the processor can be greatly improved.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] The present invention relates to a hardware development system, and in particular to a RISC-V based hardware development system. Background Art

[0002] With the continuous development of processor technology, the RISC-V instruction set, as an open and scalable instruction set architecture, has gradually attracted attention from the industry. In RISC-V processor design, flexible and efficient development and debugging, as well as the ability to quickly and accurately locate faulty instructions, are key areas.

[0003] Unlike typical ASIC design, processor simulation involves executing instructions. A simple processor test program often involves tens or even hundreds of thousands of instructions, generating waveforms that can reach tens to hundreds of GB in size. Errors in executed instructions often only manifest themselves after dozens or even hundreds of cycles, making it difficult to locate the error. Furthermore, processor simulation cannot fully record all executed instructions, and locating the erroneous instruction may require simultaneously observing the waveforms of dozens of signals within the processor core. This makes debugging a very inefficient method. Summary of the Invention

[0004] The technical problem to be solved by the present invention is to provide a RISC-V based hardware development system to improve the efficiency of hardware development.

[0005] In order to solve the above technical problems, the technical solution adopted by the present invention is: a RISC-V-based hardware development system, comprising: an instruction tracing module, a waveform slicing module, a deadlock detection module, an emulated memory tracing module, a function call tracing module, a peripheral access tracing module, an instruction simulator, a differential debugging comparison module, a comprehensive debugging module and a calling module;

[0006] After the processor is connected to the RISC-V-based hardware development system, the forward cycle is encapsulated as the single_cycle() function, and the calling module calls the waveform slicing module once in the single_cycle() function to perform waveform slicing;

[0007] After the processor completes the reset and initialization information, it enters the main loop of the integrated debugging module. The integrated debugging module issues an execution command to call the cpu_exec() function to let the processor execute instructions;

[0008] The calling module updates the program counter and calls the function tracking module to determine whether the current program counter address is a call or return function;

[0009] The calling module calls the single_cycle() function once to indicate that the processor advances one cycle, and then calls the get_cpu_signals() function to obtain the relevant signals in the processor;

[0010] The calling module calls the deadlock detection module after the single_cycle() function to check whether the processor enters an infinite loop;

[0011] If the processor accesses memory or peripherals during execution, the calling module calls the memory access tracking module and the peripheral access tracking module through the DPIC mechanism to notify the development platform and write the relevant information to the log file;

[0012] After an instruction is executed, the calling module calls the instruction tracking module to record the information of the executed instruction;

[0013] The calling module calls the differential debugging and comparison module to verify whether the processor execution is correct; in the differential debugging and comparison module, the instruction simulator will be notified to execute an instruction, and then the register stack status of the instruction simulator will be obtained and compared with the register stack status of the processor. If the status is the same, the program counter will be updated to continue executing the next instruction. If the status is different, the simulation will be exited and relevant error information will be output.

[0014] Furthermore, a commit module is provided in the write-back stage of the processor, which is specifically configured to commit only when the instruction of the previous cycle is different from the instruction of the current cycle.

[0015] Furthermore, the instruction tracing module is specifically used to write the program counter address and instruction into the logbuf string; call llvm disassembly, input instruction information, and input the disassembled information into logbuf, thereby completing the record of an executed instruction.

[0016] Furthermore, the waveform slicing module is specifically used to record the waveforms of the latest N cycles. If the processor executes correctly during this period, the waveforms of these N cycles are discarded and the waveforms of the next N cycles are recorded again.

[0017] Furthermore, the deadlock detection module is specifically used to record the running cycle of the current delivered instruction. If the current instruction execution exceeds a preset cycle, it is determined that the processor has entered a deadlock, and the hardware development system exits the simulation and outputs relevant debugging information.

[0018] Furthermore, the memory access tracking module is specifically used to output relevant information to a log file according to the type of memory access instruction, memory access address, and memory access data, and record the PC address during memory access.

[0019] Furthermore, the function call tracking module is specifically used to read the corresponding program elf file according to the current instruction, disassemble and output the current function call information to the log file.

[0020] Furthermore, the peripheral access tracking module is specifically used to determine whether it is a peripheral access based on the current memory access address, and output the address of the peripheral access, the peripheral name, and the access data information.

[0021] Furthermore, the differential debugging and comparison module is specifically used to determine whether the current instruction is executed correctly according to the register status in the processor and the instruction simulator after each instruction is executed, and return the determination result to the hardware development system.

[0022] Furthermore, the comprehensive debugging module is specifically used for single-step debugging of the processor, printing registers, setting watchpoints, calculating expressions, scanning memory and exiting simulation.

[0023] The beneficial effects of the present invention are: using a RISC-V-based hardware development system, it is possible to completely record the operation traces of the processor, automatically detect deadlock situations and reduce the size of waveform files, automatically locate the location of instruction errors, and use a variety of debugging methods for flexible development, thereby greatly improving the efficiency of processor design. BRIEF DESCRIPTION OF THE DRAWINGS

[0024] 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 the mechanisms shown in these drawings without paying any creative work.

[0025] Figure 1 This is a diagram showing the overall architecture of a RISC-V-based hardware development system according to an embodiment of the present invention;

[0026] Figure 2 This is a flowchart of the execution of a RISC-V-based hardware development system according to an embodiment of the present invention;

[0027] Figure 3 This is a diagram of the overall architecture of the instruction simulator according to an embodiment of the present invention;

[0028] Figure 4 This is a flowchart of initialization information according to an embodiment of the present invention;

[0029] Figure 5 This is an instruction execution flow chart of an instruction simulator according to an embodiment of the present invention;

[0030] Figure 6This is a diagram of the overall architecture of differential debugging comparison in an embodiment of the present invention;

[0031] Figure 7 This is a flowchart of differential debugging and comparison execution according to an embodiment of the present invention;

[0032] Figure 8 This is a diagram of the architecture of the comprehensive debugging module according to an embodiment of the present invention. DETAILED DESCRIPTION

[0033] The following will clearly and completely describe the technical solutions in the embodiments of the present invention in conjunction with the accompanying drawings. Obviously, the described embodiments are only part of the embodiments of the present invention, not all of the embodiments. All other embodiments obtained by ordinary technicians in this field based on the embodiments of the present invention without making any creative efforts shall fall within the scope of protection of the present invention.

[0034] It should be noted that the descriptions of "first", "second", etc. in the present invention are for descriptive purposes only and should not be understood as indicating or implying their relative importance or implicitly indicating the number of the indicated technical features. Therefore, the features defined as "first" or "second" may explicitly or implicitly include at least one of such features. In addition, the technical solutions between the various embodiments can be combined with each other, but this must be based on the fact that they can be implemented by ordinary technicians in this field. When the combination of technical solutions is contradictory or cannot be implemented, it should be deemed that such a combination of technical solutions does not exist and is not within the scope of protection required by the present invention.

[0035] like Figure 1 As shown, an embodiment of the present invention is: a RISC-V-based hardware development system, comprising: an instruction tracing module, a waveform slicing module, a deadlock detection module, an emulated memory tracing module, a function call tracing module, a peripheral access tracing module, an instruction simulator, a differential debugging comparison module, a comprehensive debugging module and a calling module;

[0036] After the processor is connected to the RISC-V-based hardware development system, the forward cycle is encapsulated as the single_cycle() function, and the calling module calls the waveform slicing module once in the single_cycle() function to perform waveform slicing;

[0037] After the processor completes the reset and initialization information, it enters the main loop of the integrated debugging module. The integrated debugging module issues an execution command to call the cpu_exec() function to let the processor execute instructions;

[0038] The calling module updates the program counter and calls the function tracking module to determine whether the current program counter address is a call or return function;

[0039] The calling module calls the single_cycle() function once to indicate that the processor advances one cycle, and then calls the get_cpu_signals() function to obtain the relevant signals in the processor;

[0040] In order to determine whether an instruction in the processor has been executed, a delivery module needs to be added to the write-back level of the processor. The characteristics of the instructions that can be delivered are shown in Table 1:

[0041] Table 1:

[0042]

[0043]

[0044] In order to prevent the same instruction from being delivered multiple times, the delivery module will store the instructions of the previous cycle, and will only deliver them when the instructions of the previous cycle are different from the instructions of the current cycle. Since the multi-cycle pipeline processor cannot determine the execution cycle of each instruction, a loop is used in the exec_once() function. If the delivery enable signal is not detected to be pulled high, the above execution behavior is repeated, so that it can be compatible with pipeline RISC-V processors of any cycle. Based on this principle, the calling module of the present invention calls the deadlock detection module after the single_cycle() function to check whether the processor has entered a dead loop;

[0045] If the processor accesses memory or peripherals during execution, the calling module calls the memory access tracking module and the peripheral access tracking module through the DPIC mechanism to notify the development platform and write the relevant information to the log file;

[0046] After an instruction is executed, the calling module calls the instruction tracking module to record the information of the executed instruction;

[0047] The calling module calls the differential debugging and comparison module to verify whether the processor execution is correct; in the differential debugging and comparison module, the instruction simulator will be notified to execute an instruction, and then the register stack status of the instruction simulator will be obtained and compared with the register stack status of the processor. If the status is the same, the program counter will be updated to continue executing the next instruction. If the status is different, the simulation will be exited and relevant error information will be output.

[0048] In this solution, the waveform slicing module can configure the waveform period of each recording, significantly reducing the space occupied by the generated waveform file. The differential debugging and comparison module can adapt to the execution cycle of each processor instruction, meaning that it can be used by processors with single-cycle or multi-stage pipeline technology. All of these modules are parameterized, and macros can be used to freely select whether to enable them. By using this RISC-V-based hardware development system, the efficiency of processor development and debugging is greatly improved.

[0049] The following is a detailed introduction to each module:

[0050] Instruction Tracing Module: To record the instructions and program counter address information after each processor execution, the present invention defines a global logbuf string to store each recorded information. First, the program counter address and instruction are written to the logbuf string. Then, LLVM is called to disassemble the instruction information, and the disassembled information is written to the logbuf string. This completes the recording of an executed instruction.

[0051] In addition, the present invention also defines an instruction buffer for outputting the last N instructions after each execution (error or normal execution), making it easier to find the location of the erroneous instruction. First, a ringbuf structure is defined, which contains instbuf, head and count. instbuf is a string array used to store the recorded instruction stream. head is a head pointer used to indicate the location where the next instruction is stored in instbuf, ensuring that instbuf always stores the latest instruction. count is a counter used to indicate whether instbuf has been filled. The size of the instbuf array can be configured, and it is assumed here that the size is 10. First, the inst_enqueue() function is defined to put the instruction into instbuf, and the location where it is put is the value of head. When updating the head pointer, the head is assigned to (head+1)%10 to implement the buffer loop writing function, and count is incremented by 1. Call inst_enqueue() after the current instruction is executed to ensure that the recorded instructions are executed correctly. Secondly, the print_inst() function is defined to print the instruction information in instbuf from new to old. If instbuf has been filled, data from head to 10 will be output first, followed by data from 0 to head - 1. If instbuf has not been filled, data from 0 to head - 1 will be output directly. print_inst() is only called when the simulation exits.

[0052] Waveform Slicing Module: Verilator uses the method of advancing simulation time units to drive simulation. If waveform generation is set, the waveform file needs to be opened at the beginning of the simulation and closed at the end of the simulation. This feature can be used to refresh the waveform file. The present invention defines a waveform refresh counter in the waveform slicing module. When the simulation advances one cycle, the waveform refresh counter increments by 1. When the count reaches N, the waveform file refresh operation is executed, that is, the waveform file is closed and then opened again.

[0053] Deadlock detection module: When the processor enters a deadlock state, instructions cannot enter the next level of the pipeline, resulting in the inability to update the instruction delivery of the last level. The deadlock detection module of the present invention defines a deadlock counter, which judges the instructions in the delivery module after each cycle. If the instruction of the current cycle is the same as the instruction of the previous cycle, the deadlock counter will be incremented by 1. The deadlock counter will be cleared after each instruction is delivered. When the deadlock counter counts to N (N is generally set to several hundred), it can be determined that the processor has entered a deadlock state, and the hardware development system is notified to exit the simulation and print relevant debugging information.

[0054] Memory Access Tracking Module: Memory access operations in the processor can be implemented using Verilator's DPI-C mechanism. This is achieved by calling a C function in Verilog to access a defined memory array (pmem), similar to SRAM access. The present invention defines a memory_trace() function within the DPI-C function call. This function accepts the PC address of the current memory access, the memory address being accessed, the data being accessed, the length of the data being accessed, and the type of memory access (read / write) as parameters, and writes this information to a log file.

[0055] Peripheral Access Tracking Module: The RISC-V manual specifies that RISC-V peripheral access is implemented through memory mapping. This means that memory access instructions are used when accessing peripherals, and the address accessed is no longer a memory address but the address of the peripheral on the bus. Similar to the memory access tracking module, the peripheral access tracking module defines the device_trace() function in the memory access call DPI-C function. This function accepts the PC address of the currently accessed peripheral, the address of the accessed peripheral, the data accessed, the length of the accessed data, and the type of access (read / write) as parameters. It also determines which peripheral is being accessed based on the accessed peripheral address and writes this information to the logfile.

[0056] Function call tracing module: According to the RISC-V manual, function calls and returns are executed by executing the two instructions jal and jalr. Therefore, the present invention defines the trace_func_call() and trace_func_ret() functions to be called when the two instructions jar and jalr are executed. The trace_func_call() function accepts the program counter and target as parameters, where the program counter is the address where the instruction is located, and the target is the first address of the called function. For example, in the following function call, pc = 0x8000000c, target = 0x80000260; 0x8000000c:call[_trm_init@0x80000260]. Sometimes the compiler will optimize the return of a function into a tail call, that is, the pseudo-instruction jr is used when calling the function (expanded to jalr x0,0(rs1)). The return address is not recorded in x1 (return address for jumps), but is recorded in x0 (hardwired to 0, ignores writes), which is equivalent to directly discarding the return address. Therefore, in trace_func_call(), it is also necessary to identify the situation where the destination register of the address is x0, and record the current program counter value (representing the function that will not be displayed as returned). When a function returns, check whether there is a "waiting to return" function in the upper layer. If so, call trace_func_ret() to return together. The trace_func_ret() function accepts the program counter as a parameter, where the program counter is the address where the instruction is located, indicating that the function has returned at the instruction address. In order to identify the names of the calling and returning functions, the present invention parses the .symtab of the elf file. First, a structure SymEntry is defined to store a row in the symbol table (symtab). symbol_tbl is an array of SymEntry type, and each element represents a symbol recorded in the symbol table, that is, a row in .symtab. In the read_symbopl_table() function, the address, information, size and other data of symtbl in the elf file are parsed and copied to symbol_tbl. Then, in the find_symbol_func() function, the function address is converted to the subscript corresponding to symbol_tbl. The function call must jump to the function's first address, while the function return instruction may fall within the range [Value, Value+Size). Therefore, is_call is used to distinguish between calls and returns for more accurate judgment.

[0057] Instruction simulator: The instruction simulator of the present invention adopts trace driver, and the instruction set architecture is RV64IM. It can be compatible with RV32E, RV32I and RV32IM instruction sets through macro switches. Figure 3 As shown, there are two main processes in the instruction simulator: after initializing the information, it enters the main loop of instruction execution.

[0058] Initialization information such as Figure 4As shown, the first step is to initialize the input information. This function determines whether to enable batch mode, specify the log file, the image file required by the differential debugging and comparison module, and the ELF file required by the function call tracing module based on the compilation parameters specified in the Makefile. The random number generator is initialized using the srand() function from the stdlib.h library. The computer's real-time time is obtained using the gettimeofday() function and converted to the value used as the argument to srand(). The log file is initialized, with the default output set to stdout (i.e., terminal output). The specified log file is opened using the w mode of fopen(). If the specified log file cannot be opened, an assertion error is generated. The memory is initialized using the memset() function to assign random numbers to pmem (the defined memory array). The random number seed is the rand() function from the stdlib.h library. According to the RISC-V manual, the program counter address is reset to 0x8000_0000. Therefore, the actual address accessed to pmem is pc-0x8000_0000. During the initialization of the peripherals, different peripheral ports are added according to the supported peripherals. The instruction simulator of the present invention is based on the RV64IM architecture. According to the RISC-V manual, 32 64-bit wide general registers are required. Therefore, a structure cpu is defined, whose structure members include gpr and pc. Among them, cpu.gpr is used to create 32 64-bit wide general registers, and cpu.pc is used to store the program counter address of the next instruction. In the initialization of the ISA, a program segment is first copied to pmem. This is to prevent the instruction simulator from reporting an error when the program image does not exist. Then, cpu.pc of the current instruction is set to the reset value, i.e., 0x8000_0000. According to the RISC-V manual, the 0 register of the general register is always 0, so the cpu.gpr[0] register needs to be assigned to 0. In the initialization test program, first determine whether the img_file pointer is a null pointer. If it is a null pointer, print an error message and return 4096 (this is the default image size). Then use fopen in rb mode to open the image file. If it cannot be opened, use Assert to report an error. After opening the image file, use the fseek() function to move the file pointer to the end of the file. Use the ftell() function to obtain the current file pointer position and thus the file size. Then use the fseek() function again to move the file pointer to the beginning of the file and call the fread() function to read data from the file into pmem. Finally, the size of the test program image file is returned. The instruction simulator serves as a reference for the processor, so initializing the differential debugging and comparison module can simply use an empty function.The integrated debugging module initializes the regular expression first, calling the regcomp() function to compile the regular expression for the current rule. The module then checks whether the return value ret from regcomp() is 0. If not, compilation has failed. Through this loop, all regular expression rules are compiled and stored in the corresponding regex_t structure. Watchpoints are then initialized. These watchpoints are implemented using a linked list with head insertion, so except for the last node, which points to NULL, all other nodes point to the next node. The initialization instruction Buffer sets the head and count values ​​of the ringbuf structure to 0.

[0059] After initialization is completed, the main loop of instruction execution begins. The instruction execution process is as follows: Figure 5 As shown. The present invention defines a structure Decode in the global scope, and its members include pc, snpc, dnpc, isa_inst_val, and logbuf. Among them, Decode.isa_inst_val is used to indicate the instruction under the current instruction set, and Decode.logbuf is used to record the currently executed instruction information in the instruction tracking module. Decode.pc, Decode.snpc, and Decode.dnpc are mainly used for instruction execution. Decode.pc is the program counter address of the current instruction; Decode.snpc is the static nextpc, which is snpc=pc+4 in RV64IM; Decode.dnpc is the dynamic nextpc, and dnpc=snpc by default. When encountering a branch / jump instruction, dnpc will be assigned to the actual jump address. At the same time, a structure CPUState is also maintained in the global scope, and its members include state, halt_pc, and halt_ret. Among them, state is used to determine what state the current simulator is in, and can have the following assignments: RUNNING, STOP, END, ABORT, QUIT. halt_pc is used to indicate the program counter address when the simulator exits runtime, and halt_ret is used to indicate the value of the $a0 register when the simulator exits runtime. This register can indicate whether there is any error in the program execution when the simulator exits.

[0060] The instruction execution process is encapsulated in the cpu_exec() function, which accepts a parameter, n, indicating the number of instructions to execute. Upon entering cpu_exec(), it first checks whether n is less than the set MAX_INST_TO_PRINT to prevent excessive instruction information from being printed on the screen. It then checks the CPUState state. If it is END or ABORT, it returns immediately; otherwise, the state is assigned the value RUNNING by default. Below is the execute() function, which also accepts a parameter, n, indicating the number of instructions to execute. After execution, it prints different results depending on the value of state. If it is RUNNING or STOP, it exits immediately. If it is EEND or ABORT, it prints the program counter address of the instruction at which execution stopped. Finally, it outputs information such as the program execution time and the number of instructions. The execute() function contains a for loop that executes N instructions. The execution of a single instruction is defined as the exec_once() function, which accepts a decoded pointer &s and a global variable, cpu.pc. In exec_once(), both s->pc and s->snpc are first assigned to pc, the current instruction's pc. Next, a function called isa_exec_once() is defined. This function accepts a pointer of type Decode &s as a parameter and primarily implements instruction fetching, decoding, and executing instructions. First, the inst_fetch() instruction fetch function reads the instruction corresponding to the program counter address from the memory array and assigns it to isa_inst_val. This function also updates the value of snpc by incrementing it by 4. Next, a function called decode_exec() is defined. This function accepts a pointer of type Decode &s as a parameter. In decode_exec(), immediate values ​​of type I, U, S, J, and B are decoded according to the RISC-V manual. The addresses of source registers rs1 and rs2 are used to index into general registers src1 and src2. Next, by default, dnpc is assigned to snpc. Next, an INSTPAT macro is defined. In the RISC-V instruction format, instructions can be identified based on opcode, func3, and func7. Therefore, this macro can determine the specific instruction and execute the corresponding operation based on the input instruction format. For example, the input parameter of the add instruction is: INSTPAT("0000000 ?????? ?????? 000 ?????? 01100 11",add,R,R(rd)=src1+src2); when it is recognized as an add instruction, it means that this is an R-type instruction, and the values ​​of rs1 and rs2 are added, and the result is assigned to the rd register.If it is a jump instruction beq, the input parameters are: INSTPAT("???????????? ???????????? 000 ????????? 11000 11",beq,B,s->dnpc=(src1==src2)?(s->pc+imm):s->snpc); the beq instruction is a B-type instruction. The execution process is to determine whether the values ​​of the source registers rs1 and rs2 are equal. If they are equal, the next pc address (i.e., dnpc) is assigned to pc+imm. Otherwise, the next pc address is still snpc. If it is an ebreak instruction, the CPUTRAP() function will be triggered. This function will assign state to END and determine whether the result of program execution is correct based on the value of the $a0 register. After the instruction execution is completed, it returns to the exec_once() function and assigns cpu.pc to dnpc, which is the final nextpc. After executing an instruction, the instruction counter is incremented by 1. Then, the trace_and_difftest() function is called. This function invokes the differential debugging and comparison module and the instruction tracing module, printing the executed instruction traces to the screen as appropriate. Next, the program checks whether the state is RUNNING. If not, the loop is exited, not executing subsequent instructions. The state of the state is then used to determine whether the current simulator is executing the program correctly. Finally, if the current simulator supports peripherals, the peripheral status needs to be refreshed.

[0061] Differential debugging and comparison module: The differential debugging and comparison module of the present invention is divided into two parts, namely the REF part in the instruction simulator and the DUT part in the processor. Figure 6 shown.

[0062] In the REF section, the difftest_memcpy() function is defined. This function copies n bytes from dut to ref's memory, effectively copying the test program to the instruction simulator's memory. The diff_get_regs() function retrieves the register state of ref and returns it to dut. This function defines the cpu-type structure diff_context, which loops through diff_context->gpr[i] and assigns cpu.gpr[i]. The diff_set_regs() function sets the register state of ref to dut. Similar to the diff_get_regs() function, it assigns cpu.gpr[i] to diff_context->gpr[i]. The difftest_regcpy() function copies the program counter and register state between ref and dut. When direction is `DIFFTEST_TO_DUT`, get the register status of ref and pc to dut, that is, call diff_set_regs() function; when direction is `DIFFTEST_TO_REF`, set the register status of ref and pc to dut, that is, call diff_get_regs() function. The function of difftest_exec() function is to let ref execute N instructions. Because the present invention uses the instruction simulator as the ref for differential debugging comparison, ref executing N instructions is to call cpu_exec(n) function. Finally, initialize the differential debugging comparison function of ref, and call the initialization memory and initialization ISA in the initialization information. Since the memory space is too large, and to determine whether the processor behavior is correct, it is essentially only necessary to observe the general registers in the processor core, so the differential debugging comparison module of the present invention only compares the general registers. After completion, the instruction simulator is compiled into a shared object file for dynamic linking.

[0063] In the DUT, the init_difftest() function is first defined. This function uses the dlopen() function to open the passed dynamic library file ref_so_file. Then, through dynamic linking, the API symbols in the dynamic library (i.e., the differential debugging functions defined in the REF section) are resolved and relocated, and their addresses are returned. Next, the differential debugging comparison function of REF is initialized by calling the difftest_init() function of ref. The DUT's memory data, register status, and cpu.pc are then copied to ref, completing the initialization of the entire differential debugging comparison.

[0064] The differential debug comparison flow of the DUT part is shown in Figure 7 The function difftest_step() is defined to be called after exec_once(). The pointer ref_r of the cpu type is defined as the intermediate variable for the REF and DUT differential debug comparison in the function. In the function difftest_step(), if the skip check instruction is judged, only the register state of ref is set as dut. Then ref executes an instruction and the register state of ref is obtained to dut. Finally, the function checkregs() is called to check the general registers of ref and dut. In the function checkregs(), the pc of ref and dut is compared. If the pc is not equal, the state of ref and dut is inconsistent, and the simulation is exited and the current pc address is output. If the pc address is the same, the values of 32 general registers are compared through a for loop. If the values are equal, the processor instruction execution is correct, and the function is returned directly.

[0065] The comprehensive debug module is essentially a loop, which realizes the command line effect by calling the readline library, and then parses the command line input parameters to determine what operation needs to be performed, as shown in Figure 8

[0066] Among them, single-step execution is to call the cpu_exec(n) function, and n is the number input by the command line. Instruction execution directly calls cpu_exec(-1). Since the input parameter of the cpu_exec() function is defined as uint_64t type, -1 will be directly converted to the maximum value of uint_64t. Scanning memory means accessing pmem according to the given memory address, and returning the data corresponding to the memory address.

[0067] The calculation expression first needs to add a regular expression rule, such as arithmetic addition, subtraction, multiplication, and division, logic and, or, equal, not equal, left and right parentheses, decimal and hexadecimal numbers, 32 general registers, and pc. Next, expression splitting is needed to find the main symbol (the symbol with the lowest priority). After finding the main symbol, the expression is calculated. If the expression is only a number, the corresponding value is returned. If the expression is a general register, the value of the corresponding general register is returned. If the expression is pc, the value of cpu.pc is returned. If the expression has parentheses, the outermost parentheses are removed and recursive calls are made. Finally, the main operator calculation is performed, and the calculated value is returned.

[0068] ​Setting watchpoints is implemented using a linked list structure with head insertion, and requires the use of a calculation expression. Assume that at the beginning of the program, when wpc == 0x8000_0000 is entered at pc = 0x8000_0000, the expression evaluates to false and is written to the first node of the linked list. Next, the instruction is executed. When pc = 0x8000_000c, the watchpoint detects that the value of the node changes from false to true, and the state is assigned to STOP, halting instruction execution. This method can achieve a breakpoint-like effect. At the same time, if the watchpoint set is a value in memory, changes in memory data can be monitored, greatly improving debugging efficiency.

[0069] To exit the simulation, you can directly assign the state value to QUIT. At the same time, for the convenience of debugging, the current instruction and PC address will be printed at the same time when exiting.

[0070] Print registers Use a for loop to print out the values ​​of the general registers in cpu.gpr one by one.

[0071] The above descriptions are merely embodiments of the present invention and are not intended to limit the patent scope of the present invention. Any equivalent structure or equivalent process transformation made using the contents of the present invention's description and drawings, or directly or indirectly applied in other related technical fields, are also included in the patent protection scope of the present invention.

Claims

1. A RISC-V based hardware development system, characterized in that: include: Instruction tracing module, waveform slicing module, deadlock detection module, simulated memory tracing module, function call tracing module, peripheral access tracing module, instruction simulator, differential debugging comparison module, integrated debugging module and calling module; After the processor is connected to the RISC-V-based hardware development system, the forward cycle is encapsulated as the single_cycle() function, and the calling module calls the waveform slicing module once in the single_cycle() function to perform waveform slicing; After the processor completes the reset and initialization information, it enters the main loop of the integrated debugging module. The integrated debugging module issues an execution command to call the cpu_exec() function to let the processor execute instructions; The calling module updates the program counter and calls the function tracking module to determine whether the current program counter address is a call or return function; The calling module calls the single_cycle() function once to indicate that the processor advances one cycle, and then calls the get_cpu_signals() function to obtain the relevant signals in the processor; The calling module calls the deadlock detection module after the single_cycle() function to check whether the processor enters an infinite loop; If the processor accesses memory or peripherals during execution, the calling module calls the memory access tracking module and the peripheral access tracking module through the DPIC mechanism to notify the development platform and write the relevant information to the log file; After an instruction is executed, the calling module calls the instruction tracking module to record the information of the executed instruction; The calling module calls the differential debugging and comparison module to verify whether the processor execution is correct; in the differential debugging and comparison module, the instruction simulator will be notified to execute an instruction, and then the register stack status of the instruction simulator will be obtained and compared with the register stack status of the processor. If the status is the same, the program counter will be updated to continue executing the next instruction. If the status is different, the simulation will be exited and relevant error information will be output.

2. The RISC-V based hardware development system according to claim 1, wherein: A commit module is provided in the write-back stage of the processor, which is specifically configured to commit only when the instruction of the previous cycle is different from the instruction of the current cycle.

3. The RISC-V based hardware development system according to claim 1, wherein: The instruction tracing module is specifically used to write the program counter address and instruction into the logbuf string; call llvm disassembly, input instruction information, and input the disassembled information into logbuf, thereby completing the record of an executed instruction.

4. The RISC-V based hardware development system according to claim 1, wherein: The waveform slicing module is specifically used to record the waveforms of the latest N cycles. If the processor executes correctly during this period, the waveforms of these N cycles are discarded and the waveforms of the next N cycles are recorded again.

5. The RISC-V based hardware development system according to claim 1, wherein: The deadlock detection module is specifically used to record the running cycle of the current delivered instruction. If the current instruction execution exceeds a preset cycle, it is determined that the processor has entered a deadlock, and the hardware development system exits the simulation and outputs relevant debugging information.

6. The RISC-V based hardware development system according to claim 1, wherein: The memory access tracking module is specifically used to output relevant information to a log file according to the type of memory access instruction, memory access address, and memory access data, and record the PC address during memory access.

7. The RISC-V based hardware development system according to claim 1, wherein: The function call tracking module is specifically used to read the corresponding program elf file according to the current instruction, disassemble and output the current function call information to the log file.

8. The RISC-V based hardware development system according to claim 1, wherein: The peripheral access tracking module is specifically used to determine whether it is a peripheral access based on the current memory access address, and output the address of the peripheral access, the peripheral name, and the access data information.

9. The RISC-V based hardware development system according to claim 1, wherein: The differential debugging and comparison module is specifically used to determine whether the current instruction is executed correctly according to the register status in the processor and instruction simulator after each instruction is executed, and return the determination result to the hardware development system.

10. The RISC-V based hardware development system according to claim 1, wherein: The comprehensive debugging module is specifically used for single-step debugging of the processor, printing registers, setting monitoring points, calculating expressions, scanning memory and exiting simulation.

Citation Information

Patent Citations

  • Random interrupt debugging verification system based on RISC-V architecture

    CN117422025A

  • Simulator comparison system based on RISC-V processor verification

    CN117892661A