1##########################################################################
2# Copyright (c) 2009, 2010, ETH Zurich.
3# All rights reserved.
4#
5# This file is distributed under the terms in the attached LICENSE file.
6# If you do not find this file, copies can be found by writing to:
7# ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8##########################################################################
9
10import re
11import debug, tests
12from common import TestCommon, TimeoutError
13from results import RawResults, PassFailResult
14
15class RpcTestCommon(TestCommon):
16    benchmark_type = None
17
18    def get_module_name(self):
19        raise NotImplementedError
20
21    def get_modules(self, build, machine):
22        modules = super(RpcTestCommon, self).get_modules(build, machine)
23        modules.add_module(self.get_module_name())
24        return modules
25
26    def run(self, build, machine, testdir):
27        modules = self.get_modules(build, machine)
28        args = []
29        if self.benchmark_type != None:
30            args = [str(self.benchmark_type)]
31        modules.add_module(self.get_module_name(), args)
32        self.boot(machine, modules)
33        return self.collect_data(machine)
34
35    def process_data(self, testdir, rawiter):
36        results = RawResults('core')
37        times = []
38        core = None
39        for line in rawiter:
40            m = re.match("Running \w+ between core \d+ and core (\d+)", line)
41            if m:
42                if times:
43                    results.add_group(core, times)
44                core = int(m.group(1))
45                times = []
46                continue
47
48            m = re.match("page \d+ took (\d+)", line)
49            if m:
50                assert(core is not None)
51                times.append(int(m.group(1)))
52
53        if len(times) != 0:
54            results.add_group(core, times)
55        return results
56
57@tests.add_test
58class TransportLatencyTest(RpcTestCommon):
59    ''' Transport Latency microbenchmark '''
60    name = "transport_latency"
61
62    def get_module_name(self):
63        return "transport_bench"
64
65    def process_data(self, testdir, rawiter):
66        results = RawResults('iteration')
67        times = []
68        iteration = None
69        for line in rawiter:
70            m = re.match("transport_bench: iteration (\d+)", line)
71            if m:
72                if times:
73                    results.add_group(iteration, times)
74                iteration = int(m.group(1))
75                times = []
76                continue
77
78            m = re.match("page \d+ took (\d+)", line)
79            if m:
80                assert(iteration is not None)
81                times.append(int(m.group(1)))
82
83        if len(times) != 0:
84            results.add_group(iteration, times)
85        return results
86
87@tests.add_test
88class FlounderStubsEmptyTest(RpcTestCommon):
89    ''' Empty flounder stubs '''
90    name = "flounder_stubs_empty"
91
92    def get_module_name(self):
93        return "flounder_stubs_empty_bench"
94
95@tests.add_test
96class FlounderStubsPayloadGlueTest(RpcTestCommon):
97    ''' Payload_Glue flounder stubs '''
98    name = "flounder_stubs_payload_glue"
99    benchmark_type = 0
100
101    def get_module_name(self):
102        return "flounder_stubs_payload_glue_bench"
103
104@tests.add_test
105class FlounderStubsPayload1GlueTest(RpcTestCommon):
106    ''' Payload_Glue1 flounder stubs '''
107    name = "flounder_stubs_payload1_glue"
108    benchmark_type = 2
109
110    def get_module_name(self):
111        return "flounder_stubs_payload_glue_bench"
112
113@tests.add_test
114class FlounderStubsPayload2GlueTest(RpcTestCommon):
115    ''' Payload_Glue2 flounder stubs '''
116    name = "flounder_stubs_payload2_glue"
117    benchmark_type = 3
118
119    def get_module_name(self):
120        return "flounder_stubs_payload_glue_bench"
121
122@tests.add_test
123class FlounderStubsPayload8GlueTest(RpcTestCommon):
124    ''' Payload_Glue8 flounder stubs '''
125    name = "flounder_stubs_payload8_glue"
126    benchmark_type = 4
127
128    def get_module_name(self):
129        return "flounder_stubs_payload_glue_bench"
130
131@tests.add_test
132class FlounderStubsPayload16GlueTest(RpcTestCommon):
133    ''' Payload_Glue16 flounder stubs '''
134    name = "flounder_stubs_payload16_glue"
135    benchmark_type = 5
136
137    def get_module_name(self):
138        return "flounder_stubs_payload_glue_bench"
139
140@tests.add_test
141class FlounderStubsEmptyGlueTest(RpcTestCommon):
142    ''' Empty_Glue flounder stubs '''
143    name = "flounder_stubs_empty_glue"
144    benchmark_type = 1
145
146    def get_module_name(self):
147        return "flounder_stubs_payload_glue_bench"
148
149@tests.add_test
150class FlounderStubsPayloadTest(RpcTestCommon):
151    ''' Payload flounder stubs '''
152    name = "flounder_stubs_payload"
153
154    def get_module_name(self):
155        return "flounder_stubs_payload_bench"
156
157@tests.add_test
158class FlounderStubsPayload1Test(RpcTestCommon):
159    ''' Payload1 flounder stubs '''
160    name = "flounder_stubs_payload1"
161    benchmark_type = 2
162
163    def get_module_name(self):
164        return "flounder_stubs_payload_bench"
165
166@tests.add_test
167class FlounderStubsPayload2Test(RpcTestCommon):
168    ''' Payload2 flounder stubs '''
169    name = "flounder_stubs_payload2"
170    benchmark_type = 3
171
172    def get_module_name(self):
173        return "flounder_stubs_payload_bench"
174
175@tests.add_test
176class FlounderStubsPayload8Test(RpcTestCommon):
177    ''' Payload8 flounder stubs '''
178    name = "flounder_stubs_payload8"
179    benchmark_type = 4
180
181    def get_module_name(self):
182        return "flounder_stubs_payload_bench"
183
184@tests.add_test
185class FlounderStubsPayload16Test(RpcTestCommon):
186    ''' Payload16 flounder stubs '''
187    name = "flounder_stubs_payload16"
188    benchmark_type = 5
189
190    def get_module_name(self):
191        return "flounder_stubs_payload_bench"
192
193@tests.add_test
194class FlounderStubsBufferTest(RpcTestCommon):
195    ''' Buffer flounder stubs '''
196    name = "flounder_stubs_buffer"
197
198    def get_module_name(self):
199        return "flounder_stubs_buffer_bench"
200
201@tests.add_test
202class RouteTest(RpcTestCommon):
203    ''' routing microbenchmark '''
204    name = "route_bench"
205
206    def get_module_name(self):
207        return "route_bench"
208
209@tests.add_test
210class UmpLatencyTest(RpcTestCommon):
211    ''' UMP latency microbenchmark '''
212    name = "ump_latency"
213
214    def get_module_name(self):
215        return "ump_latency"
216
217@tests.add_test
218class UmpExchangeTest(RpcTestCommon):
219    ''' UMP exchange microbenchmark '''
220    name = "ump_exchange"
221
222    def get_module_name(self):
223        return "ump_exchange"
224
225@tests.add_test
226class UmpThroughputTest(RpcTestCommon):
227    ''' UMP throughput microbenchmark '''
228    name = "ump_throughput"
229
230    def get_module_name(self):
231        return "ump_throughput"
232
233@tests.add_test
234class UmpSendTest(RpcTestCommon):
235    ''' UMP send microbenchmark '''
236    name = "ump_send"
237
238    def get_module_name(self):
239        return "ump_send"
240
241@tests.add_test
242class UmpReceiveTest(RpcTestCommon):
243    ''' UMP receive microbenchmark '''
244    name = "ump_receive"
245
246    def get_module_name(self):
247        return "ump_receive"
248
249@tests.add_test
250class UmpCacheTest(RpcTestCommon):
251    ''' UMP cache utilisation microbenchmark '''
252    name = "ump_latency_cache"
253
254    def get_module_name(self):
255        return "ump_latency_cache"
256
257    # XXX: don't attempt to run on an intel machine, as perfmon is unsupported
258    def run(self, build, machine, testdir):
259        perftype = machine.get_perfcount_type()
260        if perftype.startswith('intel'):
261            return ["Test skipped: %s performance monitoring unsupported\n" % perftype]
262        else:
263            return super(RpcTestCommon, self).run(build, machine, testdir)
264
265    def process_data(self, testdir, raw_iter):
266        # check the first line to see if the test actually ran
267        try:
268            firstline = raw_iter.next()
269            if firstline.startswith('Test skipped'):
270                return PassFailResult(True)
271        except StopIteration: # empty results file
272            return PassFailResult(False)
273
274        # process the rest of the file
275        results = {}
276        data = {}
277        index = {}
278        iteration = {}
279        results['Data'] = RawResults('iter', name='dcache')
280        results['Instruction'] = RawResults('iter', name='icache')
281        for cache in ['Data', 'Instruction']:
282            data[cache] = []
283            index[cache] = None
284            iteration[cache] = 1
285
286        for line in raw_iter:
287            m = re.match("(Data|Instruction) cache miss\s+(\d+)\s+(\d+)\s+(\d+)",
288                         line)
289            if m:
290                cache = m.group(1)
291                i = int(m.group(2))
292                value = int(m.group(4)) - int(m.group(3))
293                if index[cache] is not None and i < index[cache]: # new iteration
294                    results[cache].add_group(iteration[cache], data[cache])
295                    iteration[cache] += 1
296                    data[cache] = [value]
297                else:
298                    data[cache].append(value)
299                index[cache] = i
300
301        ret = []
302        for cache in ['Data', 'Instruction']:
303            results[cache].add_group(iteration[cache], data[cache])
304            ret.append(results[cache])
305        return ret
306
307@tests.add_test
308class LrpcTest(RpcTestCommon):
309    ''' LRPC microbenchmark '''
310    name = "lrpc"
311
312    def get_module_name(self):
313        return "lrpc_bench"
314
315    def get_modules(self, build, machine):
316        modules = super(RpcTestCommon, self).get_modules(build, machine)
317        modules.add_module("lrpc_bench", ["server"])
318        modules.add_module("lrpc_bench", ["client"])
319        return modules
320
321    def get_finish_string(self):
322        return "End of benchmarks."
323
324    def run(self, *args):
325        # XXX: want to use the base single-boot implementation
326        return TestCommon.run(self, *args)
327
328    def process_data(self, testdir, raw_iter):
329        results = RawResults('iter')
330        data = []
331        index = None
332        iteration = 1
333        for line in raw_iter:
334            m = re.match("page\s+(\d+)\s+took\s+(\d+)", line)
335            if m:
336                if index is not None and int(m.group(1)) < index:
337                    # new iteration
338                    results.add_group(iteration, data)
339                    iteration += 1
340                    data = [int(m.group(2))]
341                else:
342                    data.append(int(m.group(2)))
343                index = int(m.group(1))
344        results.add_group(iteration, data)
345        return results
346
347@tests.add_test
348class LrpcFPUTest(RpcTestCommon):
349    ''' LRPC FPU microbenchmark '''
350    name = "lrpc_fpu"
351
352    def get_module_name(self):
353        return "lrpc_fpu"
354
355    def get_modules(self, build, machine):
356        modules = super(RpcTestCommon, self).get_modules(build, machine)
357        modules.add_module("lrpc_fpu", ["server"])
358        modules.add_module("lrpc_fpu", ["client"])
359        return modules
360
361    def get_finish_string(self):
362        return "End of LRPC-FPU test:"
363
364    def run(self, *args):
365        # XXX: want to use the base single-boot implementation
366        return TestCommon.run(self, *args)
367
368    def process_data(self, testdir, raw_iter):
369        passed = False
370        for line in raw_iter:
371            if "Everything OK" in line:
372                passed = True
373        return PassFailResult(passed)
374