Add: generate test from comment in assembly file
This commit is contained in:
		
							
								
								
									
										71
									
								
								scripts/gen_test.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								scripts/gen_test.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | |||||||
|  | import re | ||||||
|  |  | ||||||
|  | source_code = open('test.S', 'r') | ||||||
|  | Lines = source_code.readlines() | ||||||
|  | test_file = [] | ||||||
|  |  | ||||||
|  | def get_test(test, instr_addr, final = False): | ||||||
|  |     result = "" | ||||||
|  |  | ||||||
|  |     pattern_r = re.compile(r'R\[(\d+)\]=(\d+)') | ||||||
|  |     pattern_pc = re.compile(r'PC=(\d+)') | ||||||
|  |     pattern_mem = re.compile(r'MEM\[(\d+)\]=(\d+)') | ||||||
|  |  | ||||||
|  |     # Use the patterns to search for matches in the input string | ||||||
|  |     match_r = pattern_r.search(test) | ||||||
|  |     match_pc = pattern_pc.search(test) | ||||||
|  |     match_mem = pattern_mem.search(test) | ||||||
|  |  | ||||||
|  |     if match_r: | ||||||
|  |         number1 = match_r.group(1) | ||||||
|  |         number2 = match_r.group(2) | ||||||
|  |         result = f"{number1}={number2}" | ||||||
|  |     elif match_pc: | ||||||
|  |         number_pc = match_pc.group(1) | ||||||
|  |         result = f"32={number_pc}" | ||||||
|  |     elif match_mem: | ||||||
|  |         number1_mem = match_mem.group(1) | ||||||
|  |         number2_mem = match_mem.group(2) | ||||||
|  |         result = f"{int(number1_mem) + 33}={number2_mem}" | ||||||
|  |      | ||||||
|  |     if result != "" and not final: | ||||||
|  |         result = f"{instr_addr}:{result}" | ||||||
|  |      | ||||||
|  |     return result | ||||||
|  |  | ||||||
|  | instr_addr = 0 | ||||||
|  | for line in Lines: | ||||||
|  |     if line.isspace() or ':' in line or line[0] == '#': | ||||||
|  |         continue | ||||||
|  |     elif '#' in line: | ||||||
|  |         tests = re.split(r'\s|,', line[line.find('#') + 1:]) | ||||||
|  |         for test in tests: | ||||||
|  |             new_test = get_test(test, instr_addr) | ||||||
|  |             if new_test != "": | ||||||
|  |                 test_file.append(new_test) | ||||||
|  |     instr_addr += 4 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # save test_file to a file named test.tmp | ||||||
|  | with open('test.tmp', 'w') as f: | ||||||
|  |     for item in test_file: | ||||||
|  |         f.write("%s\n" % item) | ||||||
|  |  | ||||||
|  | final_test_file = [] | ||||||
|  | # go through Line in reverse order | ||||||
|  | for line in reversed(Lines): | ||||||
|  |     if line.isspace() or ':' in line: | ||||||
|  |         continue | ||||||
|  |     elif line[0] == '#': | ||||||
|  |         tests = re.split(r'\s|,', line[1:]) | ||||||
|  |         for test in tests: | ||||||
|  |             new_test = get_test(test, instr_addr, True) | ||||||
|  |             if new_test != "": | ||||||
|  |                 final_test_file.append(new_test) | ||||||
|  |     else: | ||||||
|  |         break | ||||||
|  |  | ||||||
|  | # save test_file to a file named test.tmp | ||||||
|  | with open('test.final.tmp', 'w') as f: | ||||||
|  |     for item in final_test_file: | ||||||
|  |         f.write("%s\n" % item) | ||||||
| @@ -9,11 +9,20 @@ module tb_risc_v_cpu (); | |||||||
|  |  | ||||||
|     /* File management variable */ |     /* File management variable */ | ||||||
|     integer    bin_file_inputs; |     integer    bin_file_inputs; | ||||||
|  |     integer    code_file_inputs; | ||||||
|     reg [8:0]  read_instruction_1; |     reg [8:0]  read_instruction_1; | ||||||
|     reg [8:0]  read_instruction_2; |     reg [8:0]  read_instruction_2; | ||||||
|     reg [8:0]  read_instruction_3; |     reg [8:0]  read_instruction_3; | ||||||
|     reg [8:0]  read_instruction_4; |     reg [8:0]  read_instruction_4; | ||||||
|  |  | ||||||
|  |     reg [113:0]  test [0:100]; | ||||||
|  |     integer      instruction_addr; | ||||||
|  |     reg [5:0]    reg_number; | ||||||
|  |     reg [31:0]   reg_test_value; | ||||||
|  |     integer curent_addr; | ||||||
|  |     integer res; | ||||||
|  |     reg [8:0] dump; | ||||||
|  |  | ||||||
|     risc_v_cpu risc_v_cpu ( |     risc_v_cpu risc_v_cpu ( | ||||||
|         .clock(clk), |         .clock(clk), | ||||||
|         .reset(reset), |         .reset(reset), | ||||||
| @@ -33,7 +42,7 @@ module tb_risc_v_cpu (); | |||||||
|         /* Loading Binary File */ |         /* Loading Binary File */ | ||||||
|         bin_file_inputs = $fopen("./../tb/test_source_code/tb_riscv_cpu/test.bin", "r"); |         bin_file_inputs = $fopen("./../tb/test_source_code/tb_riscv_cpu/test.bin", "r"); | ||||||
|         if (bin_file_inputs == 0) begin |         if (bin_file_inputs == 0) begin | ||||||
|             $display("data_file handle was NULL"); |             $display("bin file handle was NULL"); | ||||||
|             $finish; |             $finish; | ||||||
|         end |         end | ||||||
|  |  | ||||||
| @@ -60,13 +69,107 @@ module tb_risc_v_cpu (); | |||||||
|             end |             end | ||||||
|         end |         end | ||||||
|  |  | ||||||
|         for (i = 0; i < 100; i = i + 1) begin |         $fclose(bin_file_inputs); | ||||||
|             `next_cycle |  | ||||||
|             // run |         /* Extract Value to Test From File */ | ||||||
|  |         code_file_inputs = $fopen("./../tb/test_source_code/tb_riscv_cpu/test.tmp", "r"); | ||||||
|  |         if (code_file_inputs == 0) begin | ||||||
|  |             $display("source code file handle was NULL"); | ||||||
|  |             $finish; | ||||||
|         end |         end | ||||||
|  |  | ||||||
|         // final test |         i = 0; | ||||||
|         `assert_no_wait("FOR LOOP - REG[5]: 1", risc_v_cpu.registers_bank.registers[5], 32'b1010) |         for (i = 0; i < 100; i = i + 1) begin   // Fill test data structure of 1, | ||||||
|  |             test[i] = {114{1'b1}};              // to represent the empty state | ||||||
|  |         end | ||||||
|  |          | ||||||
|  |         while (!$feof(code_file_inputs)) | ||||||
|  |         begin | ||||||
|  |             res = $fscanf(code_file_inputs, "%d:%d=%d\n", instruction_addr, reg_number, reg_test_value); | ||||||
|  |             if (res != 3) begin     // If fscanf failed, the test file structure is wrong, then exit | ||||||
|  |                 $display("Parsing test file failed"); | ||||||
|  |                 $finish; | ||||||
|  |             end | ||||||
|  |  | ||||||
|  |             $display ("Line %d: %d:%b=%b ]", res, instruction_addr, reg_number, reg_test_value); | ||||||
|  |  | ||||||
|  |             if (test[instruction_addr][5:0] == 6'b111111) begin | ||||||
|  |                 test[instruction_addr][5:0] = reg_number; | ||||||
|  |                 test[instruction_addr][37:6] = reg_test_value; | ||||||
|  |             end else if (test[instruction_addr][43:38] == 6'b111111) begin | ||||||
|  |                 $display ("1"); | ||||||
|  |                 test[instruction_addr][43:38] = reg_number; | ||||||
|  |                 test[instruction_addr][75:44] = reg_test_value; | ||||||
|  |             end else if (test[instruction_addr][81:76] == 6'b111111) begin | ||||||
|  |                 test[instruction_addr][81:76] = reg_number; | ||||||
|  |                 test[instruction_addr][113:83] = reg_test_value; | ||||||
|  |             end | ||||||
|  |         end | ||||||
|  |  | ||||||
|  |         $fclose(code_file_inputs); | ||||||
|  |  | ||||||
|  |         /* Run The Program */ | ||||||
|  |  | ||||||
|  |         for (i = 0; i < 100; i = i + 1) begin | ||||||
|  |             if (test[risc_v_cpu.program_counter.pc_addr][5:0] != 6'b111111) begin | ||||||
|  |                 curent_addr = risc_v_cpu.program_counter.pc_addr; | ||||||
|  |                 `next_cycle | ||||||
|  |                 if (test[curent_addr][5:0] != 6'b111111) begin | ||||||
|  |                     if (test[curent_addr][5:0] < 6'b100000) begin | ||||||
|  |                         `assert_no_wait("TEST - REG", risc_v_cpu.registers_bank.registers[test[curent_addr][4:0]], test[curent_addr][37:6]) | ||||||
|  |                     end else if (test[curent_addr][5:0] == 6'b100000) begin | ||||||
|  |                         `assert_no_wait("TEST - PC", risc_v_cpu.program_counter.pc_addr, test[curent_addr][37:6]) | ||||||
|  |                     end else if (test[curent_addr][5:0] > 6'b100000) begin | ||||||
|  |                         `assert_no_wait("TEST - MEM", risc_v_cpu.memory.memory[test[curent_addr][5:0]], test[curent_addr][37:6]) | ||||||
|  |                     end | ||||||
|  |                 end | ||||||
|  |                 if (test[curent_addr][43:38] != 6'b111111) begin | ||||||
|  |                     if (test[curent_addr][43:38] < 6'b100000) begin | ||||||
|  |                         `assert_no_wait("TEST - REG", risc_v_cpu.registers_bank.registers[test[curent_addr][42:38]], test[curent_addr][75:44]) | ||||||
|  |                     end else if (test[curent_addr][43:38] == 6'b100000) begin | ||||||
|  |                         `assert_no_wait("TEST - PC", risc_v_cpu.program_counter.pc_addr, test[curent_addr][75:44]) | ||||||
|  |                     end else if (test[curent_addr][43:38] > 6'b100000) begin | ||||||
|  |                         `assert_no_wait("TEST - MEM", risc_v_cpu.memory.memory[test[curent_addr][43:38]], test[curent_addr][75:44]) | ||||||
|  |                     end | ||||||
|  |                 end | ||||||
|  |                 if (test[curent_addr][81:76] != 6'b111111) begin | ||||||
|  |                     if (test[curent_addr][81:76] < 6'b100000) begin | ||||||
|  |                         `assert_no_wait("TEST - REG", risc_v_cpu.registers_bank.registers[test[curent_addr][80:76]], test[curent_addr][81:76]) | ||||||
|  |                     end else if (test[curent_addr][81:76] == 6'b100000) begin | ||||||
|  |                         `assert_no_wait("TEST - PC", risc_v_cpu.program_counter.pc_addr, test[curent_addr][113:83]) | ||||||
|  |                     end else if (test[curent_addr][81:76] > 6'b100000) begin | ||||||
|  |                         `assert_no_wait("TEST - MEM", risc_v_cpu.memory.memory[test[curent_addr][81:76]], test[curent_addr][81:76]) | ||||||
|  |                     end | ||||||
|  |                 end | ||||||
|  |             end | ||||||
|  |             else | ||||||
|  |                 `next_cycle | ||||||
|  |         end | ||||||
|  |  | ||||||
|  |         /* Test State After Execution */ | ||||||
|  |         code_file_inputs = $fopen("./../tb/test_source_code/tb_riscv_cpu/test.final.tmp", "r"); | ||||||
|  |         if (code_file_inputs == 0) begin | ||||||
|  |             $display("source code file handle was NULL"); | ||||||
|  |             $finish; | ||||||
|  |         end | ||||||
|  |  | ||||||
|  |         while (!$feof(code_file_inputs)) | ||||||
|  |         begin | ||||||
|  |             res = $fscanf(code_file_inputs, "%d=%d\n", reg_number, reg_test_value); | ||||||
|  |             $display ("Line %d: %b=%b ]", res, reg_number, reg_test_value); | ||||||
|  |             if (res != 2) begin     // If fscanf failed, the test file structure is wrong, then exit | ||||||
|  |                 $display("Parsing test file failed"); | ||||||
|  |                 $finish; | ||||||
|  |             end | ||||||
|  |  | ||||||
|  |             if (reg_number < 6'b100000) begin | ||||||
|  |                 `assert_no_wait("FINAL TEST - REG", risc_v_cpu.registers_bank.registers[reg_number[4:0]], reg_test_value) | ||||||
|  |             end else if (reg_number == 6'b100000) begin | ||||||
|  |                 `assert_no_wait("FINAL TEST- PC", risc_v_cpu.program_counter.pc_addr, reg_test_value) | ||||||
|  |             end else if (reg_number > 6'b100000) begin | ||||||
|  |                 `assert_no_wait("FINAL TEST - MEM", risc_v_cpu.memory.memory[test[curent_addr][5:0]], reg_test_value) | ||||||
|  |             end | ||||||
|  |         end | ||||||
|          |          | ||||||
|         `end_message |         `end_message | ||||||
|     end |     end | ||||||
|   | |||||||
| @@ -1,9 +1,11 @@ | |||||||
| # t0 = 0 | # t0 = 0 | ||||||
| li      t0, 0 | li      t0, 0 | ||||||
| li      t2, 10 | li      t2, 10 # R[2]=10, MEM[1]=6 | ||||||
| loop_head: | loop_head: | ||||||
| bge     t0, t2, loop_end | bge     t0, t2, loop_end | ||||||
| # Repeated code goes here | # Repeated code goes here | ||||||
| addi    t0, t0, 1 | addi    t0, t0, 1 # PC=16 | ||||||
| j		loop_head | j		loop_head | ||||||
| loop_end: | loop_end: | ||||||
|  |  | ||||||
|  | # R[0]=0 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user