see http://mbed.org/users/no2chem/notebook/mbed-clock-control--benchmarks/

Dependencies:   mbed

Committer:
no2chem
Date:
Sun Jan 24 15:46:26 2010 +0000
Revision:
0:b5d3bd64d2dc

        

Who changed what in which revision?

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