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