OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [bootloaders/] [orpmon/] [coremark/] [core_list_join.c] - Blame information for rev 728

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 355 julius
/*
2
Author : Shay Gal-On, EEMBC
3
 
4
This file is part of  EEMBC(R) and CoreMark(TM), which are Copyright (C) 2009
5
All rights reserved.
6
 
7
EEMBC CoreMark Software is a product of EEMBC and is provided under the terms of the
8
CoreMark License that is distributed with the official EEMBC COREMARK Software release.
9
If you received this EEMBC CoreMark Software without the accompanying CoreMark License,
10
you must discontinue use and download the official release from www.coremark.org.
11
 
12
Also, if you are publicly displaying scores generated from the EEMBC CoreMark software,
13
make sure that you are in compliance with Run and Reporting rules specified in the accompanying readme.txt file.
14
 
15
EEMBC
16
4354 Town Center Blvd. Suite 114-200
17
El Dorado Hills, CA, 95762
18 406 julius
*/
19 355 julius
 
20
#include "coremark.h"
21
/*
22
Topic: Description
23
        Benchmark using a linked list.
24
 
25
        Linked list is a common data structure used in many applications.
26
 
27
        For our purposes, this will excercise the memory units of the processor.
28
        In particular, usage of the list pointers to find and alter data.
29
 
30
        We are not using Malloc since some platforms do not support this library.
31
 
32
        Instead, the memory block being passed in is used to create a list,
33
        and the benchmark takes care not to add more items then can be
34
        accomodated by the memory block. The porting layer will make sure
35
        that we have a valid memory block.
36
 
37
        All operations are done in place, without using any extra memory.
38
 
39
        The list itself contains list pointers and pointers to data items.
40
        Data items contain the following:
41
 
42
        idx - An index that captures the initial order of the list.
43
        data - Variable data initialized based on the input parameters. The 16b are divided as follows:
44
        o Upper 8b are backup of original data.
45
        o Bit 7 indicates if the lower 7 bits are to be used as is or calculated.
46
        o Bits 0-2 indicate type of operation to perform to get a 7b value.
47
        o Bits 3-6 provide input for the operation.
48
 
49
*/
50
 
51
/* local functions */
52
 
53 406 julius
list_head *core_list_find(list_head * list, list_data * info);
54
list_head *core_list_reverse(list_head * list);
55
list_head *core_list_remove(list_head * item);
56
list_head *core_list_undo_remove(list_head * item_removed,
57
                                 list_head * item_modified);
58
list_head *core_list_insert_new(list_head * insert_point, list_data * info,
59
                                list_head ** memblock, list_data ** datablock,
60
                                list_head * memblock_end,
61
                                list_data * datablock_end);
62
typedef ee_s32(*list_cmp) (list_data * a, list_data * b, core_results * res);
63
list_head *core_list_mergesort(list_head * list, list_cmp cmp,
64
                               core_results * res);
65 355 julius
 
66 406 julius
ee_s16 calc_func(ee_s16 * pdata, core_results * res)
67
{
68
        ee_s16 data = *pdata;
69 355 julius
        ee_s16 retval;
70 406 julius
        ee_u8 optype = (data >> 7) & 1; /* bit 7 indicates if the function result has been cached */
71
        if (optype)             /* if cached, use cache */
72 355 julius
                return (data & 0x007f);
73 406 julius
        else {                  /* otherwise calculate and cache the result */
74
                ee_s16 flag = data & 0x7;       /* bits 0-2 is type of function to perform */
75
                ee_s16 dtype = ((data >> 3) & 0xf);     /* bits 3-6 is specific data for the operation */
76
                dtype |= dtype << 4;    /* replicate the lower 4 bits to get an 8b value */
77 355 julius
                switch (flag) {
78 406 julius
                case 0:
79
                        if (dtype < 0x22)       /* set min period for bit corruption */
80
                                dtype = 0x22;
81
                        retval =
82
                            core_bench_state(res->size, res->memblock[3],
83
                                             res->seed1, res->seed2, dtype,
84
                                             res->crc);
85
                        if (res->crcstate == 0)
86
                                res->crcstate = retval;
87
                        break;
88
                case 1:
89
                        retval =
90
                            core_bench_matrix(&(res->mat), dtype, res->crc);
91
                        if (res->crcmatrix == 0)
92
                                res->crcmatrix = retval;
93
                        break;
94
                default:
95
                        retval = data;
96
                        break;
97 355 julius
                }
98 406 julius
                res->crc = crcu16(retval, res->crc);
99
                retval &= 0x007f;
100
                *pdata = (data & 0xff00) | 0x0080 | retval;     /* cache the result */
101 355 julius
                return retval;
102
        }
103
}
104 406 julius
 
105 355 julius
/* Function: cmp_complex
106
        Compare the data item in a list cell.
107
 
108
        Can be used by mergesort.
109
*/
110 406 julius
ee_s32 cmp_complex(list_data * a, list_data * b, core_results * res)
111
{
112
        ee_s16 val1 = calc_func(&(a->data16), res);
113
        ee_s16 val2 = calc_func(&(b->data16), res);
114 355 julius
        return val1 - val2;
115
}
116
 
117
/* Function: cmp_idx
118
        Compare the idx item in a list cell, and regen the data.
119
 
120
        Can be used by mergesort.
121
*/
122 406 julius
ee_s32 cmp_idx(list_data * a, list_data * b, core_results * res)
123
{
124
        if (res == NULL) {
125
                a->data16 = (a->data16 & 0xff00) | (0x00ff & (a->data16 >> 8));
126
                b->data16 = (b->data16 & 0xff00) | (0x00ff & (b->data16 >> 8));
127 355 julius
        }
128
        return a->idx - b->idx;
129
}
130
 
131 406 julius
void copy_info(list_data * to, list_data * from)
132
{
133
        to->data16 = from->data16;
134
        to->idx = from->idx;
135 355 julius
}
136
 
137
/* Benchmark for linked list:
138
        - Try to find multiple data items.
139
        - List sort
140
        - Operate on data from list (crc)
141
        - Single remove/reinsert
142
        * At the end of this function, the list is back to original state
143
*/
144 406 julius
ee_u16 core_bench_list(core_results * res, ee_s16 finder_idx)
145
{
146
        ee_u16 retval = 0;
147
        ee_u16 found = 0, missed = 0;
148
        list_head *list = res->list;
149
        ee_s16 find_num = res->seed3;
150 355 julius
        list_head *this_find;
151
        list_head *finder, *remover;
152
        list_data info;
153
        ee_s16 i;
154
 
155 406 julius
        info.idx = finder_idx;
156 355 julius
        /* find <find_num> values in the list, and change the list each time (reverse and cache if value found) */
157 406 julius
        for (i = 0; i < find_num; i++) {
158
                info.data16 = (i & 0xff);
159
                this_find = core_list_find(list, &info);
160
                list = core_list_reverse(list);
161
                if (this_find == NULL) {
162 355 julius
                        missed++;
163 406 julius
                        retval += (list->next->info->data16 >> 8) & 1;
164
                } else {
165 355 julius
                        found++;
166 406 julius
                        if (this_find->info->data16 & 0x1)      /* use found value */
167
                                retval += (this_find->info->data16 >> 9) & 1;
168 355 julius
                        /* and cache next item at the head of the list (if any) */
169
                        if (this_find->next != NULL) {
170
                                finder = this_find->next;
171
                                this_find->next = finder->next;
172 406 julius
                                finder->next = list->next;
173
                                list->next = finder;
174 355 julius
                        }
175
                }
176 406 julius
                if (info.idx >= 0)
177 355 julius
                        info.idx++;
178
#if CORE_DEBUG
179 406 julius
                ee_printf("List find %d: [%d,%d,%d]\n", i, retval, missed,
180
                          found);
181 355 julius
#endif
182
        }
183 406 julius
        retval += found * 4 - missed;
184
        /* sort the list by data content and remove one item */
185
        if (finder_idx > 0)
186
                list = core_list_mergesort(list, cmp_complex, res);
187
        remover = core_list_remove(list->next);
188 355 julius
        /* CRC data content of list from location of index N forward, and then undo remove */
189 406 julius
        finder = core_list_find(list, &info);
190 355 julius
        if (!finder)
191 406 julius
                finder = list->next;
192 355 julius
        while (finder) {
193 406 julius
                retval = crc16(list->info->data16, retval);
194
                finder = finder->next;
195 355 julius
        }
196
#if CORE_DEBUG
197 406 julius
        ee_printf("List sort 1: %04x\n", retval);
198 355 julius
#endif
199 406 julius
        remover = core_list_undo_remove(remover, list->next);
200 355 julius
        /* sort the list by index, in effect returning the list to original state */
201 406 julius
        list = core_list_mergesort(list, cmp_idx, NULL);
202 355 julius
        /* CRC data content of list */
203 406 julius
        finder = list->next;
204 355 julius
        while (finder) {
205 406 julius
                retval = crc16(list->info->data16, retval);
206
                finder = finder->next;
207 355 julius
        }
208
#if CORE_DEBUG
209 406 julius
        ee_printf("List sort 2: %04x\n", retval);
210 355 julius
#endif
211
        return retval;
212
}
213 406 julius
 
214 355 julius
/* Function: core_list_init
215
        Initialize list with data.
216
 
217
        Parameters:
218
        blksize - Size of memory to be initialized.
219
        memblock - Pointer to memory block.
220
        seed -  Actual values chosen depend on the seed parameter.
221
                The seed parameter MUST be supplied from a source that cannot be determined at compile time
222
 
223
        Returns:
224
        Pointer to the head of the list.
225
 
226
*/
227 406 julius
list_head *core_list_init(ee_u32 blksize, list_head * memblock, ee_s16 seed)
228
{
229 355 julius
        /* calculated pointers for the list */
230 406 julius
        ee_u32 per_item = 16 + sizeof(struct list_data_s);
231
        ee_u32 size = (blksize / per_item) - 2; /* to accomodate systems with 64b pointers, and make sure same code is executed, set max list elements */
232
        list_head *memblock_end = memblock + size;
233
        list_data *datablock = (list_data *) (memblock_end);
234
        list_data *datablock_end = datablock + size;
235 355 julius
        /* some useful variables */
236
        ee_u32 i;
237 406 julius
        list_head *finder, *list = memblock;
238 355 julius
        list_data info;
239
 
240
        /* create a fake items for the list head and tail */
241 406 julius
        list->next = NULL;
242
        list->info = datablock;
243
        list->info->idx = 0x0000;
244
        list->info->data16 = (ee_s16) 0x8080;
245 355 julius
        memblock++;
246
        datablock++;
247 406 julius
        info.idx = 0x7fff;
248
        info.data16 = (ee_s16) 0xffff;
249
        core_list_insert_new(list, &info, &memblock, &datablock, memblock_end,
250
                             datablock_end);
251
 
252 355 julius
        /* then insert size items */
253 406 julius
        for (i = 0; i < size; i++) {
254
                ee_u16 datpat = ((ee_u16) (seed ^ i) & 0xf);
255
                ee_u16 dat = (datpat << 3) | (i & 0x7); /* alternate between algorithms */
256
                info.data16 = (dat << 8) | dat; /* fill the data with actual data and upper bits with rebuild value */
257
                core_list_insert_new(list, &info, &memblock, &datablock,
258
                                     memblock_end, datablock_end);
259 355 julius
        }
260
        /* and now index the list so we know initial seed order of the list */
261 406 julius
        finder = list->next;
262
        i = 1;
263
        while (finder->next != NULL) {
264
                if (i < size / 5)       /* first 20% of the list in order */
265
                        finder->info->idx = i++;
266
                else {
267
                        ee_u16 pat = (ee_u16) (i++ ^ seed);     /* get a pseudo random number */
268
                        finder->info->idx = 0x3fff & (((i & 0x07) << 8) | pat); /* make sure the mixed items end up after the ones in sequence */
269 355 julius
                }
270 406 julius
                finder = finder->next;
271 355 julius
        }
272 406 julius
        list = core_list_mergesort(list, cmp_idx, NULL);
273 355 julius
#if CORE_DEBUG
274
        ee_printf("Initialized list:\n");
275 406 julius
        finder = list;
276 355 julius
        while (finder) {
277 406 julius
                ee_printf("[%04x,%04x]", finder->info->idx,
278
                          (ee_u16) finder->info->data16);
279
                finder = finder->next;
280 355 julius
        }
281
        ee_printf("\n");
282
#endif
283
        return list;
284
}
285
 
286
/* Function: core_list_insert
287
        Insert an item to the list
288
 
289
        Parameters:
290
        insert_point - where to insert the item.
291
        info - data for the cell.
292
        memblock - pointer for the list header
293
        datablock - pointer for the list data
294
        memblock_end - end of region for list headers
295
        datablock_end - end of region for list data
296
 
297
        Returns:
298
        Pointer to new item.
299
*/
300 406 julius
list_head *core_list_insert_new(list_head * insert_point, list_data * info,
301
                                list_head ** memblock, list_data ** datablock,
302
                                list_head * memblock_end,
303
                                list_data * datablock_end)
304
{
305 355 julius
        list_head *newitem;
306 406 julius
 
307
        if ((*memblock + 1) >= memblock_end)
308 355 julius
                return NULL;
309 406 julius
        if ((*datablock + 1) >= datablock_end)
310 355 julius
                return NULL;
311 406 julius
 
312
        newitem = *memblock;
313 355 julius
        (*memblock)++;
314 406 julius
        newitem->next = insert_point->next;
315
        insert_point->next = newitem;
316
 
317
        newitem->info = *datablock;
318 355 julius
        (*datablock)++;
319 406 julius
        copy_info(newitem->info, info);
320
 
321 355 julius
        return newitem;
322
}
323
 
324
/* Function: core_list_remove
325
        Remove an item from the list.
326
 
327
        Operation:
328
        For a singly linked list, remove by copying the data from the next item
329
        over to the current cell, and unlinking the next item.
330
 
331
        Note:
332
        since there is always a fake item at the end of the list, no need to check for NULL.
333
 
334
        Returns:
335
        Removed item.
336
*/
337 406 julius
list_head *core_list_remove(list_head * item)
338
{
339 355 julius
        list_data *tmp;
340 406 julius
        list_head *ret = item->next;
341 355 julius
        /* swap data pointers */
342 406 julius
        tmp = item->info;
343
        item->info = ret->info;
344
        ret->info = tmp;
345 355 julius
        /* and eliminate item */
346 406 julius
        item->next = item->next->next;
347
        ret->next = NULL;
348 355 julius
        return ret;
349
}
350
 
351
/* Function: core_list_undo_remove
352
        Undo a remove operation.
353
 
354
        Operation:
355
        Since we want each iteration of the benchmark to be exactly the same,
356
        we need to be able to undo a remove.
357
        Link the removed item back into the list, and switch the info items.
358
 
359
        Parameters:
360
        item_removed - Return value from the <core_list_remove>
361
        item_modified - List item that was modified during <core_list_remove>
362
 
363
        Returns:
364
        The item that was linked back to the list.
365
 
366
*/
367 406 julius
list_head *core_list_undo_remove(list_head * item_removed,
368
                                 list_head * item_modified)
369
{
370 355 julius
        list_data *tmp;
371
        /* swap data pointers */
372 406 julius
        tmp = item_removed->info;
373
        item_removed->info = item_modified->info;
374
        item_modified->info = tmp;
375 355 julius
        /* and insert item */
376 406 julius
        item_removed->next = item_modified->next;
377
        item_modified->next = item_removed;
378 355 julius
        return item_removed;
379
}
380
 
381
/* Function: core_list_find
382
        Find an item in the list
383
 
384
        Operation:
385
        Find an item by idx (if not 0) or specific data value
386
 
387
        Parameters:
388
        list - list head
389
        info - idx or data to find
390
 
391
        Returns:
392
        Found item, or NULL if not found.
393
*/
394 406 julius
list_head *core_list_find(list_head * list, list_data * info)
395
{
396
        if (info->idx >= 0) {
397 355 julius
                while (list && (list->info->idx != info->idx))
398 406 julius
                        list = list->next;
399 355 julius
                return list;
400
        } else {
401
                while (list && ((list->info->data16 & 0xff) != info->data16))
402 406 julius
                        list = list->next;
403 355 julius
                return list;
404
        }
405
}
406 406 julius
 
407 355 julius
/* Function: core_list_reverse
408
        Reverse a list
409
 
410
        Operation:
411
        Rearrange the pointers so the list is reversed.
412
 
413
        Parameters:
414
        list - list head
415
        info - idx or data to find
416
 
417
        Returns:
418
        Found item, or NULL if not found.
419
*/
420
 
421 406 julius
list_head *core_list_reverse(list_head * list)
422
{
423
        list_head *next = NULL, *tmp;
424 355 julius
        while (list) {
425 406 julius
                tmp = list->next;
426
                list->next = next;
427
                next = list;
428
                list = tmp;
429 355 julius
        }
430
        return next;
431
}
432 406 julius
 
433 355 julius
/* Function: core_list_mergesort
434
        Sort the list in place without recursion.
435
 
436
        Description:
437
        Use mergesort, as for linked list this is a realistic solution.
438
        Also, since this is aimed at embedded, care was taken to use iterative rather then recursive algorithm.
439
        The sort can either return the list to original order (by idx) ,
440
        or use the data item to invoke other other algorithms and change the order of the list.
441
 
442
        Parameters:
443
        list - list to be sorted.
444
        cmp - cmp function to use
445
 
446
        Returns:
447
        New head of the list.
448
 
449
        Note:
450
        We have a special header for the list that will always be first,
451
        but the algorithm could theoretically modify where the list starts.
452
 
453
 */
454 406 julius
list_head *core_list_mergesort(list_head * list, list_cmp cmp,
455
                               core_results * res)
456
{
457
        list_head *p, *q, *e, *tail;
458
        ee_s32 insize, nmerges, psize, qsize, i;
459 355 julius
 
460 406 julius
        insize = 1;
461 355 julius
 
462 406 julius
        while (1) {
463
                p = list;
464
                list = NULL;
465
                tail = NULL;
466 355 julius
 
467 406 julius
                nmerges = 0;     /* count number of merges we do in this pass */
468 355 julius
 
469 406 julius
                while (p) {
470
                        nmerges++;      /* there exists a merge to be done */
471
                        /* step `insize' places along from p */
472
                        q = p;
473
                        psize = 0;
474
                        for (i = 0; i < insize; i++) {
475
                                psize++;
476
                                q = q->next;
477
                                if (!q)
478
                                        break;
479
                        }
480 355 julius
 
481 406 julius
                        /* if q hasn't fallen off end, we have two lists to merge */
482
                        qsize = insize;
483 355 julius
 
484 406 julius
                        /* now we have two lists; merge them */
485
                        while (psize > 0 || (qsize > 0 && q)) {
486 355 julius
 
487
                                /* decide whether next element of merge comes from p or q */
488
                                if (psize == 0) {
489 406 julius
                                        /* p is empty; e must come from q. */
490
                                        e = q;
491
                                        q = q->next;
492
                                        qsize--;
493 355 julius
                                } else if (qsize == 0 || !q) {
494 406 julius
                                        /* q is empty; e must come from p. */
495
                                        e = p;
496
                                        p = p->next;
497
                                        psize--;
498
                                } else if (cmp(p->info, q->info, res) <= 0) {
499
                                        /* First element of p is lower (or same); e must come from p. */
500
                                        e = p;
501
                                        p = p->next;
502
                                        psize--;
503 355 julius
                                } else {
504 406 julius
                                        /* First element of q is lower; e must come from q. */
505
                                        e = q;
506
                                        q = q->next;
507
                                        qsize--;
508 355 julius
                                }
509
 
510 406 julius
                                /* add the next element to the merged list */
511 355 julius
                                if (tail) {
512 406 julius
                                        tail->next = e;
513 355 julius
                                } else {
514 406 julius
                                        list = e;
515 355 julius
                                }
516
                                tail = e;
517 406 julius
                        }
518 355 julius
 
519
                        /* now p has stepped `insize' places along, and q has too */
520
                        p = q;
521 406 julius
                }
522 355 julius
 
523 406 julius
                tail->next = NULL;
524 355 julius
 
525 406 julius
                /* If we have done only one merge, we're finished. */
526
                if (nmerges <= 1)       /* allow for nmerges==0, the empty list case */
527
                        return list;
528
 
529
                /* Otherwise repeat, merging lists twice the size */
530
                insize *= 2;
531
        }
532 355 julius
#if COMPILER_REQUIRES_SORT_RETURN
533
        return list;
534
#endif
535
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.