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 */ | ||||
|     integer    bin_file_inputs; | ||||
|     integer    code_file_inputs; | ||||
|     reg [8:0]  read_instruction_1; | ||||
|     reg [8:0]  read_instruction_2; | ||||
|     reg [8:0]  read_instruction_3; | ||||
|     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 ( | ||||
|         .clock(clk), | ||||
|         .reset(reset), | ||||
| @@ -33,7 +42,7 @@ module tb_risc_v_cpu (); | ||||
|         /* Loading Binary File */ | ||||
|         bin_file_inputs = $fopen("./../tb/test_source_code/tb_riscv_cpu/test.bin", "r"); | ||||
|         if (bin_file_inputs == 0) begin | ||||
|             $display("data_file handle was NULL"); | ||||
|             $display("bin file handle was NULL"); | ||||
|             $finish; | ||||
|         end | ||||
|  | ||||
| @@ -60,13 +69,107 @@ module tb_risc_v_cpu (); | ||||
|             end | ||||
|         end | ||||
|  | ||||
|         for (i = 0; i < 100; i = i + 1) begin | ||||
|             `next_cycle | ||||
|             // run | ||||
|         $fclose(bin_file_inputs); | ||||
|  | ||||
|         /* 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 | ||||
|  | ||||
|         // final test | ||||
|         `assert_no_wait("FOR LOOP - REG[5]: 1", risc_v_cpu.registers_bank.registers[5], 32'b1010) | ||||
|         i = 0; | ||||
|         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 | ||||
|   | ||||
| @@ -1,9 +1,11 @@ | ||||
| # t0 = 0 | ||||
| li      t0, 0 | ||||
| li      t2, 10 | ||||
| li      t2, 10 # R[2]=10, MEM[1]=6 | ||||
| loop_head: | ||||
| bge     t0, t2, loop_end | ||||
| # Repeated code goes here | ||||
| addi    t0, t0, 1 | ||||
| addi    t0, t0, 1 # PC=16 | ||||
| j		loop_head | ||||
| loop_end: | ||||
| loop_end: | ||||
|  | ||||
| # R[0]=0 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user