├── .gitmodules ├── README.md ├── fig.png ├── riscv.sh ├── test.py └── tree.png /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "open-test-cases"] 2 | path = open-test-cases 3 | url = https://github.com/pku-minic/open-test-cases 4 | [submodule "MiniVM"] 5 | path = MiniVM 6 | url = https://github.com/pku-minic/MiniVM 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 编译原理课程实践 测试用代码 2 | 3 | ## 使用前准备 4 | 5 | * ```bash 6 | git clone --recursive https://github.com/wangchang327/compiler-lab-test-driver.git 7 | ``` 8 | 9 | * 确保可执行文件和测试代码在同一路径下, 并填写正确的测试样例和 MiniVM 的位置. 执行时, 会首先 ```make all``` 进行编译, 所以还需要 ```Makefile```. 如要不作任何更动而运行, 目录结构应当如图所示: 10 | 11 | 12 | 13 | * 如要测试 RISC-V 生成, 还需要提前打开一个名为 ```riscv``` 的 docker 虚拟机: 14 | 15 | ```bash 16 | docker run -it --name riscv --rm riscv-dev-env 17 | ``` 18 | 19 | ## 使用 20 | 21 | ````bash 22 | python3 test.py e/t/r --verbose 23 | ```` 24 | 25 | ```--verbose``` 时打印每一行的输出, 不打印更易看清每个样例的运行时间. 26 | 27 | 输出图示: 28 | 29 | 30 | -------------------------------------------------------------------------------- /fig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchang327/compiler-lab-test-driver/76453f3e8edf64a27a8f838c09ae52f6431d236f/fig.png -------------------------------------------------------------------------------- /riscv.sh: -------------------------------------------------------------------------------- 1 | riscv32-unknown-linux-gnu-gcc output.S -o output -L/root -lsysy -static 2 | rm -f test.tmp.out 3 | if [ ! -f "test.in" ]; then 4 | qemu-riscv32-static output > test.tmp.out 5 | else 6 | qemu-riscv32-static output < test.in > test.tmp.out 7 | fi 8 | x=$? 9 | echo "" >> test.tmp.out 10 | echo $x >> test.tmp.out 11 | rm -f test.in 12 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | # wangchang 2 | import os 3 | import argparse 4 | import time 5 | 6 | parser = argparse.ArgumentParser() 7 | parser.add_argument('text', type=str, help='The phase to test') 8 | parser.add_argument('--verbose', action='store_true', help='Print details') 9 | args = parser.parse_args() 10 | 11 | 12 | class bcolors: 13 | OKBLUE = '\033[94m' 14 | OKCYAN = '\033[96m' 15 | OKGREEN = '\033[92m' 16 | WARNING = '\033[93m' 17 | FAIL = '\033[91m' 18 | ENDC = '\033[0m' 19 | 20 | 21 | def delblankline(infile, outfile): 22 | infopen = open(infile, 'r') 23 | outfopen = open(outfile, 'w+') 24 | 25 | lines = infopen.readlines() 26 | for line in lines: 27 | if line.split(): 28 | outfopen.writelines(line) 29 | else: 30 | outfopen.writelines('') 31 | 32 | infopen.close() 33 | outfopen.close() 34 | 35 | 36 | test_dir = 'open-test-cases/sysy/section1/functional_test' 37 | minivm_dir = 'MiniVM' 38 | 39 | mode = '' 40 | if args.text[0] == 'e': 41 | mode = '-e' 42 | elif args.text[0] == 't': 43 | mode = '-t' 44 | 45 | if mode != '': 46 | print('Building minivm') 47 | os.system( 48 | 'cd ' + minivm_dir + 49 | ' && rm -rf build && mkdir build && cd build && cmake .. && make -j8') 50 | print('') 51 | 52 | print('Building compiler') 53 | os.system('make -j8 compiler') 54 | print('') 55 | 56 | pass_count, fail_count = 0, 0 57 | compile_t, run_t = [], [] 58 | ignored = False 59 | test_files = os.listdir(test_dir) 60 | for fl in test_files: 61 | name, ext = fl.split('.')[0], fl.split('.')[1] 62 | if ext != 'sy': 63 | continue 64 | if (mode == '-t' or mode == '') and (name[0] 65 | == '9') and (name[1] >= '2' 66 | and name[1] <= '7'): 67 | ignored = True 68 | continue 69 | start = time.time() 70 | os.system('./compiler -S {} {} -o output.S'.format( 71 | mode, test_dir + '/' + name + '.sy')) 72 | end = time.time() 73 | compile_t.append((end - start) * 1000.0) 74 | print('Compilation done') 75 | 76 | print('Testing {}'.format(name)) 77 | 78 | if mode != '': 79 | start = time.time() 80 | if os.path.exists(test_dir + '/' + name + '.in'): 81 | ret_val = os.system( 82 | minivm_dir + 83 | '/build/minivm {} output.S < {} > test.tmp.out'.format( 84 | '-t' if mode == '-t' else '', test_dir + '/' + name + 85 | '.in')) 86 | else: 87 | ret_val = os.system(minivm_dir + 88 | '/build/minivm {} output.S > test.tmp.out'. 89 | format('-t' if mode == '-t' else '')) 90 | end = time.time() 91 | ret_val = ret_val >> 8 92 | os.system('echo "" >> test.tmp.out') 93 | os.system('echo {} >> test.tmp.out'.format(ret_val)) 94 | else: 95 | os.system('docker cp riscv.sh riscv:/root/') 96 | os.system('docker cp output.S riscv:/root/') 97 | if os.path.exists(test_dir + '/' + name + '.in'): 98 | os.system( 99 | 'docker cp {} riscv:/root/test.in'.format(test_dir + '/' + 100 | name + '.in')) 101 | start = time.time() 102 | os.system('docker exec -it riscv bash /root/riscv.sh') 103 | end = time.time() 104 | os.system('docker cp riscv:/root/test.tmp.out .') 105 | delblankline('test.tmp.out', 'test.out') 106 | print('\tDone executing the compiler and minivm\n\t|') 107 | run_t.append(end - start) 108 | print('\tTakes time: {:.4f}s'.format(end - start)) 109 | 110 | try: 111 | myoutput = open('test.out', 'r') 112 | delblankline(test_dir + '/{}.out'.format(name), 'std.out') 113 | stdoutput = open('std.out', 'r') 114 | except BaseException: 115 | print('\tOpening file error. Aborted') 116 | exit(1) 117 | 118 | print('\tComparing output') 119 | passed = True 120 | mydata = myoutput.readlines() 121 | stddata = stdoutput.readlines() 122 | 123 | try: 124 | for i in range(len(stddata)): 125 | mydata[i] = mydata[i].strip() 126 | stddata[i] = stddata[i].strip() 127 | if stddata[i] != '' and args.verbose: 128 | print( 129 | '\t|\tLine {}: My output is {}; Standard output is {}; Passed: {}' 130 | .format(i + 1, mydata[i], stddata[i], 131 | mydata[i] == stddata[i])) 132 | passed = passed and (mydata[i] == stddata[i]) 133 | except BaseException: 134 | passed = False 135 | 136 | myoutput.close() 137 | stdoutput.close() 138 | if not passed: 139 | print(bcolors.FAIL + '\tFAILED!\n' + bcolors.ENDC) 140 | fail_count += 1 141 | input("Press enter to continue") 142 | else: 143 | pass_count += 1 144 | print(bcolors.OKGREEN + '\tPASSED!\n' + bcolors.ENDC) 145 | 146 | ign_info = "(6 Ignored)" if ignored else "" 147 | print(bcolors.OKBLUE + "\nFinished. {} Passed / {} Failed: [{}%] {}".format( 148 | pass_count, fail_count, int(pass_count / 149 | (pass_count + fail_count) * 100), ign_info) + 150 | bcolors.ENDC) 151 | print(bcolors.OKBLUE + 152 | "Total compilation time: {:.2f}ms. Maximum compilation time: {:.2f}ms". 153 | format(sum(compile_t), max(compile_t)) + bcolors.ENDC) 154 | print(bcolors.WARNING + 155 | "Total run time: {:.4f}s. Maximum run time: {:.4f}s\n".format( 156 | sum(run_t), max(run_t)) + bcolors.ENDC) 157 | 158 | print('Cleaning up') 159 | os.system('cd ' + minivm_dir + ' && rm -rf build') 160 | os.system('rm -f output.S && rm -f *.out && make clean') 161 | -------------------------------------------------------------------------------- /tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangchang327/compiler-lab-test-driver/76453f3e8edf64a27a8f838c09ae52f6431d236f/tree.png --------------------------------------------------------------------------------