1/*
2 * Copyright (c) 2014, 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, CAB F.78, Universitaetstr 6, CH-8092 Zurich.
8 */
9
10#include <barrelfish/barrelfish.h>
11
12#include <thc/thc.h>
13
14#include <if/omap_sdma_defs.h>
15#include <if/omap_sdma_thc.h>
16
17#include <stdio.h>
18#include <string.h>
19
20#include "bulk_sim.h"
21
22#define FRAME_SIZE (16UL*1024*1024)
23#define FRAME_COUNT (8UL)
24
25static struct capref src_frame[FRAME_COUNT];
26static struct capref dst_frame[FRAME_COUNT];
27
28#define BENCH_MIN_SIZE (64)
29#define BENCH_MAX_SIZE FRAME_SIZE
30
31#define BENCH_ROUNDS   10
32
33#define MEASURE(outval, CALL) {                     \
34    uint64_t start, end;                            \
35    sys_debug_hardware_global_timer_read(&start);   \
36    CALL;                                           \
37    sys_debug_hardware_global_timer_read(&end);     \
38    assert(start > measure_overhead);               \
39    start -= measure_overhead;                      \
40    assert(end > measure_overhead);                 \
41    end -= measure_overhead;                        \
42    outval = end - start;                           \
43} while(0);
44
45static uint64_t measure_overhead;
46
47errval_t vspace_map_whole_frame(void **retbuf, struct capref cap)
48{
49    errval_t err;
50    struct frame_identity id;
51
52    err = invoke_frame_identify(cap, &id);
53    if (err_is_fail(err)) return err;
54
55    return vspace_map_one_frame(retbuf, id.bytes, cap, NULL, NULL);
56}
57
58
59static void measure_init(void)
60{
61    size_t runs = 10000;
62    uint64_t start, end;
63    sys_debug_hardware_global_timer_read(&start);
64    for (int i=0; i<runs; i++) {
65        sys_debug_hardware_global_timer_read(&end);
66    }
67
68    measure_overhead = (end - start) / runs;
69}
70
71static void bench_frames_init(void)
72{
73    errval_t err;
74    size_t retbytes;
75
76    for (size_t i=0; i<FRAME_COUNT; i++) {
77        err = frame_alloc(&src_frame[i], FRAME_SIZE, &retbytes);
78        assert(err_is_ok(err));
79        assert(retbytes >= FRAME_SIZE);
80    }
81
82    for (size_t i=0; i<FRAME_COUNT; i++) {
83        err = frame_alloc(&dst_frame[i], FRAME_SIZE, &retbytes);
84        assert(err_is_ok(err));
85        assert(retbytes >= FRAME_SIZE);
86    }
87}
88
89enum TransferMode {
90    TransferMode_MAPPED,
91    TransferMode_PREMAPPED,
92    TransferMode_SDMA,
93    TransferMode_SDMA_ASYNC,
94};
95
96static const char *TRANSFER_MODE[] = {
97    "Mapped", "Premapped", "SDMA", "SDMA Async"
98};
99
100static void bench_run_sdma_async(bool iterate, size_t len)
101{
102    DO_FINISH({
103        for (uint32_t id=0; id<FRAME_COUNT; id++) {
104            ASYNC({
105                uint32_t slot = iterate ? id : 0;
106                bulk_sdma_transfer(dst_frame[slot], src_frame[slot], len);
107            });
108        }
109    });
110}
111
112
113
114static void bench_run(enum TransferMode mode, bool iterate)
115{
116    for (size_t len=BENCH_MIN_SIZE; len<=BENCH_MAX_SIZE; len*=2) {
117
118        uint64_t cycles[BENCH_ROUNDS];
119
120        switch(mode) {
121        case TransferMode_MAPPED:
122
123            for(int i=0; i<BENCH_ROUNDS; i++) {
124                MEASURE(cycles[i], {
125                    for (uint32_t id=0; id<FRAME_COUNT; id++) {
126                        uint32_t slot = iterate ? id : 0;
127                        bulk_mapped_transfer(dst_frame[slot], src_frame[slot], len);
128                    }
129                });
130            }
131
132            break;
133        case TransferMode_PREMAPPED:
134
135            for(int i=0; i<BENCH_ROUNDS; i++) {
136                MEASURE(cycles[i], {
137                    for (uint32_t id=0; id<FRAME_COUNT; id++) {
138                        uint32_t slot = iterate ? id : 0;
139                        bulk_premapped_transfer(slot, slot, len);
140                    }
141                });
142            }
143
144            break;
145        case TransferMode_SDMA:
146
147            for(int i=0; i<BENCH_ROUNDS; i++) {
148                MEASURE(cycles[i], {
149                    for (uint32_t id=0; id<FRAME_COUNT; id++) {
150                        uint32_t slot = iterate ? id : 0;
151                        bulk_sdma_transfer(dst_frame[slot], src_frame[slot], len);
152                    }
153                });
154            }
155
156            break;
157        case TransferMode_SDMA_ASYNC:
158
159                for(int i=0; i<BENCH_ROUNDS; i++) {
160                    MEASURE(cycles[i], {
161                        bench_run_sdma_async(iterate, len);
162                    });
163                }
164
165                break;
166        }
167
168
169
170        for(int i=0; i<BENCH_ROUNDS; i++) {
171            printf("%15s | %12zu | %4lu | %12"PRIu64"\n",
172                TRANSFER_MODE[mode], len, iterate, cycles[i]);
173        }
174    }
175}
176
177static void bench_mapped(void)
178{
179    uint64_t cycles;
180    MEASURE(cycles, {
181        bulk_mapped_setup();
182    });
183
184    printf("bulk_mapped_setup: %"PRIu64"\n", cycles);
185
186    bench_run(TransferMode_MAPPED, false);
187    bench_run(TransferMode_MAPPED, true);
188}
189
190static void bench_premapped(void)
191{
192    uint64_t cycles;
193    MEASURE(cycles, {
194        bulk_premapped_setup(dst_frame, FRAME_COUNT, src_frame, FRAME_COUNT);
195    });
196
197    printf("bulk_premapped_setup: %"PRIu64"\n", cycles);
198
199
200    bench_run(TransferMode_PREMAPPED, false);
201    bench_run(TransferMode_PREMAPPED, true);
202}
203
204static void bench_sdma(void)
205{
206    uint64_t cycles;
207    MEASURE(cycles, {
208        bulk_sdma_setup();
209    });
210
211    printf("bulk_sdma_setup: %"PRIu64"\n", cycles);
212
213    bench_run(TransferMode_SDMA, false);
214    bench_run(TransferMode_SDMA, true);
215    bench_run(TransferMode_SDMA_ASYNC, false);
216    bench_run(TransferMode_SDMA_ASYNC, true);
217}
218
219
220int main(int argc, char *argv[])
221{
222    debug_printf("Initializing.\n");
223    measure_init();
224    bench_frames_init();
225
226    printf("           Type |      Payload | NumT |        Ticks\n");
227
228    bench_mapped();
229    bench_premapped();
230    bench_sdma();
231
232    printf("----------------------------------------------------\n");
233
234    return 0;
235}
236