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 355

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
*/
19
 
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
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, list_head *item_modified);
57
list_head *core_list_insert_new(list_head *insert_point
58
        , list_data *info, list_head **memblock, list_data **datablock
59
        , list_head *memblock_end, list_data *datablock_end);
60
typedef ee_s32(*list_cmp)(list_data *a, list_data *b, core_results *res);
61
list_head *core_list_mergesort(list_head *list, list_cmp cmp, core_results *res);
62
 
63
ee_s16 calc_func(ee_s16 *pdata, core_results *res) {
64
        ee_s16 data=*pdata;
65
        ee_s16 retval;
66
        ee_u8 optype=(data>>7) & 1; /* bit 7 indicates if the function result has been cached */
67
        if (optype) /* if cached, use cache */
68
                return (data & 0x007f);
69
        else { /* otherwise calculate and cache the result */
70
                ee_s16 flag=data & 0x7; /* bits 0-2 is type of function to perform */
71
                ee_s16 dtype=((data>>3) & 0xf); /* bits 3-6 is specific data for the operation */
72
                dtype |= dtype << 4; /* replicate the lower 4 bits to get an 8b value */
73
                switch (flag) {
74
                        case 0:
75
                                if (dtype<0x22) /* set min period for bit corruption */
76
                                        dtype=0x22;
77
                                retval=core_bench_state(res->size,res->memblock[3],res->seed1,res->seed2,dtype,res->crc);
78
                                if (res->crcstate==0)
79
                                        res->crcstate=retval;
80
                                break;
81
                        case 1:
82
                                retval=core_bench_matrix(&(res->mat),dtype,res->crc);
83
                                if (res->crcmatrix==0)
84
                                        res->crcmatrix=retval;
85
                                break;
86
                        default:
87
                                retval=data;
88
                                break;
89
                }
90
                res->crc=crcu16(retval,res->crc);
91
                retval &= 0x007f;
92
                *pdata = (data & 0xff00) | 0x0080 | retval; /* cache the result */
93
                return retval;
94
        }
95
}
96
/* Function: cmp_complex
97
        Compare the data item in a list cell.
98
 
99
        Can be used by mergesort.
100
*/
101
ee_s32 cmp_complex(list_data *a, list_data *b, core_results *res) {
102
        ee_s16 val1=calc_func(&(a->data16),res);
103
        ee_s16 val2=calc_func(&(b->data16),res);
104
        return val1 - val2;
105
}
106
 
107
/* Function: cmp_idx
108
        Compare the idx item in a list cell, and regen the data.
109
 
110
        Can be used by mergesort.
111
*/
112
ee_s32 cmp_idx(list_data *a, list_data *b, core_results *res) {
113
        if (res==NULL) {
114
                a->data16 = (a->data16 & 0xff00) | (0x00ff & (a->data16>>8));
115
                b->data16 = (b->data16 & 0xff00) | (0x00ff & (b->data16>>8));
116
        }
117
        return a->idx - b->idx;
118
}
119
 
120
void copy_info(list_data *to,list_data *from) {
121
        to->data16=from->data16;
122
        to->idx=from->idx;
123
}
124
 
125
/* Benchmark for linked list:
126
        - Try to find multiple data items.
127
        - List sort
128
        - Operate on data from list (crc)
129
        - Single remove/reinsert
130
        * At the end of this function, the list is back to original state
131
*/
132
ee_u16 core_bench_list(core_results *res, ee_s16 finder_idx) {
133
        ee_u16 retval=0;
134
        ee_u16 found=0,missed=0;
135
        list_head *list=res->list;
136
        ee_s16 find_num=res->seed3;
137
        list_head *this_find;
138
        list_head *finder, *remover;
139
        list_data info;
140
        ee_s16 i;
141
 
142
        info.idx=finder_idx;
143
        /* find <find_num> values in the list, and change the list each time (reverse and cache if value found) */
144
        for (i=0; i<find_num; i++) {
145
                info.data16= (i & 0xff) ;
146
                this_find=core_list_find(list,&info);
147
                list=core_list_reverse(list);
148
                if (this_find==NULL) {
149
                        missed++;
150
                        retval+=(list->next->info->data16 >> 8) & 1;
151
                }
152
                else {
153
                        found++;
154
                        if (this_find->info->data16 & 0x1) /* use found value */
155
                                retval+=(this_find->info->data16 >> 9) & 1;
156
                        /* and cache next item at the head of the list (if any) */
157
                        if (this_find->next != NULL) {
158
                                finder = this_find->next;
159
                                this_find->next = finder->next;
160
                                finder->next=list->next;
161
                                list->next=finder;
162
                        }
163
                }
164
                if (info.idx>=0)
165
                        info.idx++;
166
#if CORE_DEBUG
167
        ee_printf("List find %d: [%d,%d,%d]\n",i,retval,missed,found);
168
#endif
169
        }
170
        retval+=found*4-missed;
171
        /* sort the list by data content and remove one item*/
172
        if (finder_idx>0)
173
                list=core_list_mergesort(list,cmp_complex,res);
174
        remover=core_list_remove(list->next);
175
        /* CRC data content of list from location of index N forward, and then undo remove */
176
        finder=core_list_find(list,&info);
177
        if (!finder)
178
                finder=list->next;
179
        while (finder) {
180
                retval=crc16(list->info->data16,retval);
181
                finder=finder->next;
182
        }
183
#if CORE_DEBUG
184
        ee_printf("List sort 1: %04x\n",retval);
185
#endif
186
        remover=core_list_undo_remove(remover,list->next);
187
        /* sort the list by index, in effect returning the list to original state */
188
        list=core_list_mergesort(list,cmp_idx,NULL);
189
        /* CRC data content of list */
190
        finder=list->next;
191
        while (finder) {
192
                retval=crc16(list->info->data16,retval);
193
                finder=finder->next;
194
        }
195
#if CORE_DEBUG
196
        ee_printf("List sort 2: %04x\n",retval);
197
#endif
198
        return retval;
199
}
200
/* Function: core_list_init
201
        Initialize list with data.
202
 
203
        Parameters:
204
        blksize - Size of memory to be initialized.
205
        memblock - Pointer to memory block.
206
        seed -  Actual values chosen depend on the seed parameter.
207
                The seed parameter MUST be supplied from a source that cannot be determined at compile time
208
 
209
        Returns:
210
        Pointer to the head of the list.
211
 
212
*/
213
list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed) {
214
        /* calculated pointers for the list */
215
        ee_u32 per_item=16+sizeof(struct list_data_s);
216
        ee_u32 size=(blksize/per_item)-2; /* to accomodate systems with 64b pointers, and make sure same code is executed, set max list elements */
217
        list_head *memblock_end=memblock+size;
218
        list_data *datablock=(list_data *)(memblock_end);
219
        list_data *datablock_end=datablock+size;
220
        /* some useful variables */
221
        ee_u32 i;
222
        list_head *finder,*list=memblock;
223
        list_data info;
224
 
225
        /* create a fake items for the list head and tail */
226
        list->next=NULL;
227
        list->info=datablock;
228
        list->info->idx=0x0000;
229
        list->info->data16=(ee_s16)0x8080;
230
        memblock++;
231
        datablock++;
232
        info.idx=0x7fff;
233
        info.data16=(ee_s16)0xffff;
234
        core_list_insert_new(list,&info,&memblock,&datablock,memblock_end,datablock_end);
235
 
236
        /* then insert size items */
237
        for (i=0; i<size; i++) {
238
                ee_u16 datpat=((ee_u16)(seed^i) & 0xf);
239
                ee_u16 dat=(datpat<<3) | (i&0x7); /* alternate between algorithms */
240
                info.data16=(dat<<8) | dat;             /* fill the data with actual data and upper bits with rebuild value */
241
                core_list_insert_new(list,&info,&memblock,&datablock,memblock_end,datablock_end);
242
        }
243
        /* and now index the list so we know initial seed order of the list */
244
        finder=list->next;
245
        i=1;
246
        while (finder->next!=NULL) {
247
                if (i<size/5) /* first 20% of the list in order */
248
                        finder->info->idx=i++;
249
                else {
250
                        ee_u16 pat=(ee_u16)(i++ ^ seed); /* get a pseudo random number */
251
                        finder->info->idx=0x3fff & (((i & 0x07) << 8) | pat); /* make sure the mixed items end up after the ones in sequence */
252
                }
253
                finder=finder->next;
254
        }
255
        list = core_list_mergesort(list,cmp_idx,NULL);
256
#if CORE_DEBUG
257
        ee_printf("Initialized list:\n");
258
        finder=list;
259
        while (finder) {
260
                ee_printf("[%04x,%04x]",finder->info->idx,(ee_u16)finder->info->data16);
261
                finder=finder->next;
262
        }
263
        ee_printf("\n");
264
#endif
265
        return list;
266
}
267
 
268
/* Function: core_list_insert
269
        Insert an item to the list
270
 
271
        Parameters:
272
        insert_point - where to insert the item.
273
        info - data for the cell.
274
        memblock - pointer for the list header
275
        datablock - pointer for the list data
276
        memblock_end - end of region for list headers
277
        datablock_end - end of region for list data
278
 
279
        Returns:
280
        Pointer to new item.
281
*/
282
list_head *core_list_insert_new(list_head *insert_point, list_data *info, list_head **memblock, list_data **datablock
283
        , list_head *memblock_end, list_data *datablock_end) {
284
        list_head *newitem;
285
 
286
        if ((*memblock+1) >= memblock_end)
287
                return NULL;
288
        if ((*datablock+1) >= datablock_end)
289
                return NULL;
290
 
291
        newitem=*memblock;
292
        (*memblock)++;
293
        newitem->next=insert_point->next;
294
        insert_point->next=newitem;
295
 
296
        newitem->info=*datablock;
297
        (*datablock)++;
298
        copy_info(newitem->info,info);
299
 
300
        return newitem;
301
}
302
 
303
/* Function: core_list_remove
304
        Remove an item from the list.
305
 
306
        Operation:
307
        For a singly linked list, remove by copying the data from the next item
308
        over to the current cell, and unlinking the next item.
309
 
310
        Note:
311
        since there is always a fake item at the end of the list, no need to check for NULL.
312
 
313
        Returns:
314
        Removed item.
315
*/
316
list_head *core_list_remove(list_head *item) {
317
        list_data *tmp;
318
        list_head *ret=item->next;
319
        /* swap data pointers */
320
        tmp=item->info;
321
        item->info=ret->info;
322
        ret->info=tmp;
323
        /* and eliminate item */
324
        item->next=item->next->next;
325
        ret->next=NULL;
326
        return ret;
327
}
328
 
329
/* Function: core_list_undo_remove
330
        Undo a remove operation.
331
 
332
        Operation:
333
        Since we want each iteration of the benchmark to be exactly the same,
334
        we need to be able to undo a remove.
335
        Link the removed item back into the list, and switch the info items.
336
 
337
        Parameters:
338
        item_removed - Return value from the <core_list_remove>
339
        item_modified - List item that was modified during <core_list_remove>
340
 
341
        Returns:
342
        The item that was linked back to the list.
343
 
344
*/
345
list_head *core_list_undo_remove(list_head *item_removed, list_head *item_modified) {
346
        list_data *tmp;
347
        /* swap data pointers */
348
        tmp=item_removed->info;
349
        item_removed->info=item_modified->info;
350
        item_modified->info=tmp;
351
        /* and insert item */
352
        item_removed->next=item_modified->next;
353
        item_modified->next=item_removed;
354
        return item_removed;
355
}
356
 
357
/* Function: core_list_find
358
        Find an item in the list
359
 
360
        Operation:
361
        Find an item by idx (if not 0) or specific data value
362
 
363
        Parameters:
364
        list - list head
365
        info - idx or data to find
366
 
367
        Returns:
368
        Found item, or NULL if not found.
369
*/
370
list_head *core_list_find(list_head *list,list_data *info) {
371
        if (info->idx>=0) {
372
                while (list && (list->info->idx != info->idx))
373
                        list=list->next;
374
                return list;
375
        } else {
376
                while (list && ((list->info->data16 & 0xff) != info->data16))
377
                        list=list->next;
378
                return list;
379
        }
380
}
381
/* Function: core_list_reverse
382
        Reverse a list
383
 
384
        Operation:
385
        Rearrange the pointers so the list is reversed.
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
 
395
list_head *core_list_reverse(list_head *list) {
396
        list_head *next=NULL, *tmp;
397
        while (list) {
398
                tmp=list->next;
399
                list->next=next;
400
                next=list;
401
                list=tmp;
402
        }
403
        return next;
404
}
405
/* Function: core_list_mergesort
406
        Sort the list in place without recursion.
407
 
408
        Description:
409
        Use mergesort, as for linked list this is a realistic solution.
410
        Also, since this is aimed at embedded, care was taken to use iterative rather then recursive algorithm.
411
        The sort can either return the list to original order (by idx) ,
412
        or use the data item to invoke other other algorithms and change the order of the list.
413
 
414
        Parameters:
415
        list - list to be sorted.
416
        cmp - cmp function to use
417
 
418
        Returns:
419
        New head of the list.
420
 
421
        Note:
422
        We have a special header for the list that will always be first,
423
        but the algorithm could theoretically modify where the list starts.
424
 
425
 */
426
list_head *core_list_mergesort(list_head *list, list_cmp cmp, core_results *res) {
427
    list_head *p, *q, *e, *tail;
428
    ee_s32 insize, nmerges, psize, qsize, i;
429
 
430
    insize = 1;
431
 
432
    while (1) {
433
        p = list;
434
        list = NULL;
435
        tail = NULL;
436
 
437
        nmerges = 0;  /* count number of merges we do in this pass */
438
 
439
        while (p) {
440
            nmerges++;  /* there exists a merge to be done */
441
            /* step `insize' places along from p */
442
            q = p;
443
            psize = 0;
444
            for (i = 0; i < insize; i++) {
445
                psize++;
446
                            q = q->next;
447
                if (!q) break;
448
            }
449
 
450
            /* if q hasn't fallen off end, we have two lists to merge */
451
            qsize = insize;
452
 
453
            /* now we have two lists; merge them */
454
            while (psize > 0 || (qsize > 0 && q)) {
455
 
456
                                /* decide whether next element of merge comes from p or q */
457
                                if (psize == 0) {
458
                                    /* p is empty; e must come from q. */
459
                                    e = q; q = q->next; qsize--;
460
                                } else if (qsize == 0 || !q) {
461
                                    /* q is empty; e must come from p. */
462
                                    e = p; p = p->next; psize--;
463
                                } else if (cmp(p->info,q->info,res) <= 0) {
464
                                    /* First element of p is lower (or same); e must come from p. */
465
                                    e = p; p = p->next; psize--;
466
                                } else {
467
                                    /* First element of q is lower; e must come from q. */
468
                                    e = q; q = q->next; qsize--;
469
                                }
470
 
471
                        /* add the next element to the merged list */
472
                                if (tail) {
473
                                    tail->next = e;
474
                                } else {
475
                                    list = e;
476
                                }
477
                                tail = e;
478
                }
479
 
480
                        /* now p has stepped `insize' places along, and q has too */
481
                        p = q;
482
        }
483
 
484
            tail->next = NULL;
485
 
486
        /* If we have done only one merge, we're finished. */
487
        if (nmerges <= 1)   /* allow for nmerges==0, the empty list case */
488
            return list;
489
 
490
        /* Otherwise repeat, merging lists twice the size */
491
        insize *= 2;
492
    }
493
#if COMPILER_REQUIRES_SORT_RETURN
494
        return list;
495
#endif
496
}

powered by: WebSVN 2.1.0

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