├── .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
--------------------------------------------------------------------------------