Эх сурвалжийг харах

add: 加个跑分的库 coremark, 切勿与lvgl一起启用

Wendal Chen 4 жил өмнө
parent
commit
baf0e6dcad

+ 1 - 0
README.md

@@ -92,6 +92,7 @@ sys.run()
 * [elua](http://www.eluaproject.net/) eLua 虽然已经停更多年,但精神犹在
 * [FlashDB](https://gitee.com/Armink/FlashDB) 一款支持 KV 数据和时序数据的超轻量级数据库
 * [cJSON](https://github.com/DaveGamble/cJSON) Ultralightweight JSON parser in ANSI C
+* [coremark](https://github.com/eembc/coremark) MCU性能测试(跑分)
 
 ## 免费服务
 

+ 595 - 0
components/coremark/core_list_join.c

@@ -0,0 +1,595 @@
+/*
+Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Original Author: Shay Gal-on
+*/
+
+#include "coremark.h"
+/*
+Topic: Description
+        Benchmark using a linked list.
+
+        Linked list is a common data structure used in many applications.
+
+        For our purposes, this will excercise the memory units of the processor.
+        In particular, usage of the list pointers to find and alter data.
+
+        We are not using Malloc since some platforms do not support this
+library.
+
+        Instead, the memory block being passed in is used to create a list,
+        and the benchmark takes care not to add more items then can be
+        accommodated by the memory block. The porting layer will make sure
+        that we have a valid memory block.
+
+        All operations are done in place, without using any extra memory.
+
+        The list itself contains list pointers and pointers to data items.
+        Data items contain the following:
+
+        idx - An index that captures the initial order of the list.
+        data - Variable data initialized based on the input parameters. The 16b
+are divided as follows: o Upper 8b are backup of original data. o Bit 7
+indicates if the lower 7 bits are to be used as is or calculated. o Bits 0-2
+indicate type of operation to perform to get a 7b value. o Bits 3-6 provide
+input for the operation.
+
+*/
+
+/* local functions */
+
+list_head *core_list_find(list_head *list, list_data *info);
+list_head *core_list_reverse(list_head *list);
+list_head *core_list_remove(list_head *item);
+list_head *core_list_undo_remove(list_head *item_removed,
+                                 list_head *item_modified);
+list_head *core_list_insert_new(list_head * insert_point,
+                                list_data * info,
+                                list_head **memblock,
+                                list_data **datablock,
+                                list_head * memblock_end,
+                                list_data * datablock_end);
+typedef ee_s32 (*list_cmp)(list_data *a, list_data *b, core_results *res);
+list_head *core_list_mergesort(list_head *   list,
+                               list_cmp      cmp,
+                               core_results *res);
+
+ee_s16
+calc_func(ee_s16 *pdata, core_results *res)
+{
+    ee_s16 data = *pdata;
+    ee_s16 retval;
+    ee_u8  optype
+        = (data >> 7)
+          & 1;  /* bit 7 indicates if the function result has been cached */
+    if (optype) /* if cached, use cache */
+        return (data & 0x007f);
+    else
+    {                             /* otherwise calculate and cache the result */
+        ee_s16 flag = data & 0x7; /* bits 0-2 is type of function to perform */
+        ee_s16 dtype
+            = ((data >> 3)
+               & 0xf);       /* bits 3-6 is specific data for the operation */
+        dtype |= dtype << 4; /* replicate the lower 4 bits to get an 8b value */
+        switch (flag)
+        {
+            case 0:
+                if (dtype < 0x22) /* set min period for bit corruption */
+                    dtype = 0x22;
+                retval = core_bench_state(res->size,
+                                          res->memblock[3],
+                                          res->seed1,
+                                          res->seed2,
+                                          dtype,
+                                          res->crc);
+                if (res->crcstate == 0)
+                    res->crcstate = retval;
+                break;
+            case 1:
+                retval = core_bench_matrix(&(res->mat), dtype, res->crc);
+                if (res->crcmatrix == 0)
+                    res->crcmatrix = retval;
+                break;
+            default:
+                retval = data;
+                break;
+        }
+        res->crc = crcu16(retval, res->crc);
+        retval &= 0x007f;
+        *pdata = (data & 0xff00) | 0x0080 | retval; /* cache the result */
+        return retval;
+    }
+}
+/* Function: cmp_complex
+        Compare the data item in a list cell.
+
+        Can be used by mergesort.
+*/
+ee_s32
+cmp_complex(list_data *a, list_data *b, core_results *res)
+{
+    ee_s16 val1 = calc_func(&(a->data16), res);
+    ee_s16 val2 = calc_func(&(b->data16), res);
+    return val1 - val2;
+}
+
+/* Function: cmp_idx
+        Compare the idx item in a list cell, and regen the data.
+
+        Can be used by mergesort.
+*/
+ee_s32
+cmp_idx(list_data *a, list_data *b, core_results *res)
+{
+    if (res == NULL)
+    {
+        a->data16 = (a->data16 & 0xff00) | (0x00ff & (a->data16 >> 8));
+        b->data16 = (b->data16 & 0xff00) | (0x00ff & (b->data16 >> 8));
+    }
+    return a->idx - b->idx;
+}
+
+void
+copy_info(list_data *to, list_data *from)
+{
+    to->data16 = from->data16;
+    to->idx    = from->idx;
+}
+
+/* Benchmark for linked list:
+        - Try to find multiple data items.
+        - List sort
+        - Operate on data from list (crc)
+        - Single remove/reinsert
+        * At the end of this function, the list is back to original state
+*/
+ee_u16
+core_bench_list(core_results *res, ee_s16 finder_idx)
+{
+    ee_u16     retval = 0;
+    ee_u16     found = 0, missed = 0;
+    list_head *list     = res->list;
+    ee_s16     find_num = res->seed3;
+    list_head *this_find;
+    list_head *finder, *remover;
+    list_data  info;
+    ee_s16     i;
+
+    info.idx = finder_idx;
+    /* find <find_num> values in the list, and change the list each time
+     * (reverse and cache if value found) */
+    for (i = 0; i < find_num; i++)
+    {
+        info.data16 = (i & 0xff);
+        this_find   = core_list_find(list, &info);
+        list        = core_list_reverse(list);
+        if (this_find == NULL)
+        {
+            missed++;
+            retval += (list->next->info->data16 >> 8) & 1;
+        }
+        else
+        {
+            found++;
+            if (this_find->info->data16 & 0x1) /* use found value */
+                retval += (this_find->info->data16 >> 9) & 1;
+            /* and cache next item at the head of the list (if any) */
+            if (this_find->next != NULL)
+            {
+                finder          = this_find->next;
+                this_find->next = finder->next;
+                finder->next    = list->next;
+                list->next      = finder;
+            }
+        }
+        if (info.idx >= 0)
+            info.idx++;
+#if CORE_DEBUG
+        ee_printf("List find %d: [%d,%d,%d]\n", i, retval, missed, found);
+#endif
+    }
+    retval += found * 4 - missed;
+    /* sort the list by data content and remove one item*/
+    if (finder_idx > 0)
+        list = core_list_mergesort(list, cmp_complex, res);
+    remover = core_list_remove(list->next);
+    /* CRC data content of list from location of index N forward, and then undo
+     * remove */
+    finder = core_list_find(list, &info);
+    if (!finder)
+        finder = list->next;
+    while (finder)
+    {
+        retval = crc16(list->info->data16, retval);
+        finder = finder->next;
+    }
+#if CORE_DEBUG
+    ee_printf("List sort 1: %04x\n", retval);
+#endif
+    remover = core_list_undo_remove(remover, list->next);
+    /* sort the list by index, in effect returning the list to original state */
+    list = core_list_mergesort(list, cmp_idx, NULL);
+    /* CRC data content of list */
+    finder = list->next;
+    while (finder)
+    {
+        retval = crc16(list->info->data16, retval);
+        finder = finder->next;
+    }
+#if CORE_DEBUG
+    ee_printf("List sort 2: %04x\n", retval);
+#endif
+    return retval;
+}
+/* Function: core_list_init
+        Initialize list with data.
+
+        Parameters:
+        blksize - Size of memory to be initialized.
+        memblock - Pointer to memory block.
+        seed - 	Actual values chosen depend on the seed parameter.
+                The seed parameter MUST be supplied from a source that cannot be
+   determined at compile time
+
+        Returns:
+        Pointer to the head of the list.
+
+*/
+list_head *
+core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed)
+{
+    /* calculated pointers for the list */
+    ee_u32 per_item = 16 + sizeof(struct list_data_s);
+    ee_u32 size     = (blksize / per_item)
+                  - 2; /* to accommodate systems with 64b pointers, and make sure
+                          same code is executed, set max list elements */
+    list_head *memblock_end  = memblock + size;
+    list_data *datablock     = (list_data *)(memblock_end);
+    list_data *datablock_end = datablock + size;
+    /* some useful variables */
+    ee_u32     i;
+    list_head *finder, *list = memblock;
+    list_data  info;
+
+    /* create a fake items for the list head and tail */
+    list->next         = NULL;
+    list->info         = datablock;
+    list->info->idx    = 0x0000;
+    list->info->data16 = (ee_s16)0x8080;
+    memblock++;
+    datablock++;
+    info.idx    = 0x7fff;
+    info.data16 = (ee_s16)0xffff;
+    core_list_insert_new(
+        list, &info, &memblock, &datablock, memblock_end, datablock_end);
+
+    /* then insert size items */
+    for (i = 0; i < size; i++)
+    {
+        ee_u16 datpat = ((ee_u16)(seed ^ i) & 0xf);
+        ee_u16 dat
+            = (datpat << 3) | (i & 0x7); /* alternate between algorithms */
+        info.data16 = (dat << 8) | dat;  /* fill the data with actual data and
+                                            upper bits with rebuild value */
+        core_list_insert_new(
+            list, &info, &memblock, &datablock, memblock_end, datablock_end);
+    }
+    /* and now index the list so we know initial seed order of the list */
+    finder = list->next;
+    i      = 1;
+    while (finder->next != NULL)
+    {
+        if (i < size / 5) /* first 20% of the list in order */
+            finder->info->idx = i++;
+        else
+        {
+            ee_u16 pat = (ee_u16)(i++ ^ seed); /* get a pseudo random number */
+            finder->info->idx = 0x3fff
+                                & (((i & 0x07) << 8)
+                                   | pat); /* make sure the mixed items end up
+                                              after the ones in sequence */
+        }
+        finder = finder->next;
+    }
+    list = core_list_mergesort(list, cmp_idx, NULL);
+#if CORE_DEBUG
+    ee_printf("Initialized list:\n");
+    finder = list;
+    while (finder)
+    {
+        ee_printf(
+            "[%04x,%04x]", finder->info->idx, (ee_u16)finder->info->data16);
+        finder = finder->next;
+    }
+    ee_printf("\n");
+#endif
+    return list;
+}
+
+/* Function: core_list_insert
+        Insert an item to the list
+
+        Parameters:
+        insert_point - where to insert the item.
+        info - data for the cell.
+        memblock - pointer for the list header
+        datablock - pointer for the list data
+        memblock_end - end of region for list headers
+        datablock_end - end of region for list data
+
+        Returns:
+        Pointer to new item.
+*/
+list_head *
+core_list_insert_new(list_head * insert_point,
+                     list_data * info,
+                     list_head **memblock,
+                     list_data **datablock,
+                     list_head * memblock_end,
+                     list_data * datablock_end)
+{
+    list_head *newitem;
+
+    if ((*memblock + 1) >= memblock_end)
+        return NULL;
+    if ((*datablock + 1) >= datablock_end)
+        return NULL;
+
+    newitem = *memblock;
+    (*memblock)++;
+    newitem->next      = insert_point->next;
+    insert_point->next = newitem;
+
+    newitem->info = *datablock;
+    (*datablock)++;
+    copy_info(newitem->info, info);
+
+    return newitem;
+}
+
+/* Function: core_list_remove
+        Remove an item from the list.
+
+        Operation:
+        For a singly linked list, remove by copying the data from the next item
+        over to the current cell, and unlinking the next item.
+
+        Note:
+        since there is always a fake item at the end of the list, no need to
+   check for NULL.
+
+        Returns:
+        Removed item.
+*/
+list_head *
+core_list_remove(list_head *item)
+{
+    list_data *tmp;
+    list_head *ret = item->next;
+    /* swap data pointers */
+    tmp        = item->info;
+    item->info = ret->info;
+    ret->info  = tmp;
+    /* and eliminate item */
+    item->next = item->next->next;
+    ret->next  = NULL;
+    return ret;
+}
+
+/* Function: core_list_undo_remove
+        Undo a remove operation.
+
+        Operation:
+        Since we want each iteration of the benchmark to be exactly the same,
+        we need to be able to undo a remove.
+        Link the removed item back into the list, and switch the info items.
+
+        Parameters:
+        item_removed - Return value from the <core_list_remove>
+        item_modified - List item that was modified during <core_list_remove>
+
+        Returns:
+        The item that was linked back to the list.
+
+*/
+list_head *
+core_list_undo_remove(list_head *item_removed, list_head *item_modified)
+{
+    list_data *tmp;
+    /* swap data pointers */
+    tmp                 = item_removed->info;
+    item_removed->info  = item_modified->info;
+    item_modified->info = tmp;
+    /* and insert item */
+    item_removed->next  = item_modified->next;
+    item_modified->next = item_removed;
+    return item_removed;
+}
+
+/* Function: core_list_find
+        Find an item in the list
+
+        Operation:
+        Find an item by idx (if not 0) or specific data value
+
+        Parameters:
+        list - list head
+        info - idx or data to find
+
+        Returns:
+        Found item, or NULL if not found.
+*/
+list_head *
+core_list_find(list_head *list, list_data *info)
+{
+    if (info->idx >= 0)
+    {
+        while (list && (list->info->idx != info->idx))
+            list = list->next;
+        return list;
+    }
+    else
+    {
+        while (list && ((list->info->data16 & 0xff) != info->data16))
+            list = list->next;
+        return list;
+    }
+}
+/* Function: core_list_reverse
+        Reverse a list
+
+        Operation:
+        Rearrange the pointers so the list is reversed.
+
+        Parameters:
+        list - list head
+        info - idx or data to find
+
+        Returns:
+        Found item, or NULL if not found.
+*/
+
+list_head *
+core_list_reverse(list_head *list)
+{
+    list_head *next = NULL, *tmp;
+    while (list)
+    {
+        tmp        = list->next;
+        list->next = next;
+        next       = list;
+        list       = tmp;
+    }
+    return next;
+}
+/* Function: core_list_mergesort
+        Sort the list in place without recursion.
+
+        Description:
+        Use mergesort, as for linked list this is a realistic solution.
+        Also, since this is aimed at embedded, care was taken to use iterative
+   rather then recursive algorithm. The sort can either return the list to
+   original order (by idx) , or use the data item to invoke other other
+   algorithms and change the order of the list.
+
+        Parameters:
+        list - list to be sorted.
+        cmp - cmp function to use
+
+        Returns:
+        New head of the list.
+
+        Note:
+        We have a special header for the list that will always be first,
+        but the algorithm could theoretically modify where the list starts.
+
+ */
+list_head *
+core_list_mergesort(list_head *list, list_cmp cmp, core_results *res)
+{
+    list_head *p, *q, *e, *tail;
+    ee_s32     insize, nmerges, psize, qsize, i;
+
+    insize = 1;
+
+    while (1)
+    {
+        p    = list;
+        list = NULL;
+        tail = NULL;
+
+        nmerges = 0; /* count number of merges we do in this pass */
+
+        while (p)
+        {
+            nmerges++; /* there exists a merge to be done */
+            /* step `insize' places along from p */
+            q     = p;
+            psize = 0;
+            for (i = 0; i < insize; i++)
+            {
+                psize++;
+                q = q->next;
+                if (!q)
+                    break;
+            }
+
+            /* if q hasn't fallen off end, we have two lists to merge */
+            qsize = insize;
+
+            /* now we have two lists; merge them */
+            while (psize > 0 || (qsize > 0 && q))
+            {
+
+                /* decide whether next element of merge comes from p or q */
+                if (psize == 0)
+                {
+                    /* p is empty; e must come from q. */
+                    e = q;
+                    q = q->next;
+                    qsize--;
+                }
+                else if (qsize == 0 || !q)
+                {
+                    /* q is empty; e must come from p. */
+                    e = p;
+                    p = p->next;
+                    psize--;
+                }
+                else if (cmp(p->info, q->info, res) <= 0)
+                {
+                    /* First element of p is lower (or same); e must come from
+                     * p. */
+                    e = p;
+                    p = p->next;
+                    psize--;
+                }
+                else
+                {
+                    /* First element of q is lower; e must come from q. */
+                    e = q;
+                    q = q->next;
+                    qsize--;
+                }
+
+                /* add the next element to the merged list */
+                if (tail)
+                {
+                    tail->next = e;
+                }
+                else
+                {
+                    list = e;
+                }
+                tail = e;
+            }
+
+            /* now p has stepped `insize' places along, and q has too */
+            p = q;
+        }
+
+        tail->next = NULL;
+
+        /* If we have done only one merge, we're finished. */
+        if (nmerges <= 1) /* allow for nmerges==0, the empty list case */
+            return list;
+
+        /* Otherwise repeat, merging lists twice the size */
+        insize *= 2;
+    }
+#if COMPILER_REQUIRES_SORT_RETURN
+    return list;
+#endif
+}

+ 442 - 0
components/coremark/core_main.c

@@ -0,0 +1,442 @@
+/*
+Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Original Author: Shay Gal-on
+*/
+
+/* File: core_main.c
+        This file contains the framework to acquire a block of memory, seed
+   initial parameters, tun t he benchmark and report the results.
+*/
+#include "coremark.h"
+
+/* Function: iterate
+        Run the benchmark for a specified number of iterations.
+
+        Operation:
+        For each type of benchmarked algorithm:
+                a - Initialize the data block for the algorithm.
+                b - Execute the algorithm N times.
+
+        Returns:
+        NULL.
+*/
+static ee_u16 list_known_crc[]   = { (ee_u16)0xd4b0,
+                                   (ee_u16)0x3340,
+                                   (ee_u16)0x6a79,
+                                   (ee_u16)0xe714,
+                                   (ee_u16)0xe3c1 };
+static ee_u16 matrix_known_crc[] = { (ee_u16)0xbe52,
+                                     (ee_u16)0x1199,
+                                     (ee_u16)0x5608,
+                                     (ee_u16)0x1fd7,
+                                     (ee_u16)0x0747 };
+static ee_u16 state_known_crc[]  = { (ee_u16)0x5e47,
+                                    (ee_u16)0x39bf,
+                                    (ee_u16)0xe5a4,
+                                    (ee_u16)0x8e3a,
+                                    (ee_u16)0x8d84 };
+void *
+iterate(void *pres)
+{
+    ee_u32        i;
+    ee_u16        crc;
+    core_results *res        = (core_results *)pres;
+    ee_u32        iterations = res->iterations;
+    res->crc                 = 0;
+    res->crclist             = 0;
+    res->crcmatrix           = 0;
+    res->crcstate            = 0;
+
+    for (i = 0; i < iterations; i++)
+    {
+        crc      = core_bench_list(res, 1);
+        res->crc = crcu16(crc, res->crc);
+        crc      = core_bench_list(res, -1);
+        res->crc = crcu16(crc, res->crc);
+        if (i == 0)
+            res->crclist = res->crc;
+    }
+    return NULL;
+}
+
+#if (SEED_METHOD == SEED_ARG)
+ee_s32 get_seed_args(int i, int argc, char *argv[]);
+#define get_seed(x)    (ee_s16) get_seed_args(x, argc, argv)
+#define get_seed_32(x) get_seed_args(x, argc, argv)
+#else /* via function or volatile */
+ee_s32 get_seed_32(int i);
+#define get_seed(x) (ee_s16) get_seed_32(x)
+#endif
+
+#if (MEM_METHOD == MEM_STATIC)
+ee_u8 static_memblk[TOTAL_DATA_SIZE];
+#endif
+char *mem_name[3] = { "Static", "Heap", "Stack" };
+/* Function: main
+        Main entry routine for the benchmark.
+        This function is responsible for the following steps:
+
+        1 - Initialize input seeds from a source that cannot be determined at
+   compile time. 2 - Initialize memory block for use. 3 - Run and time the
+   benchmark. 4 - Report results, testing the validity of the output if the
+   seeds are known.
+
+        Arguments:
+        1 - first seed  : Any value
+        2 - second seed : Must be identical to first for iterations to be
+   identical 3 - third seed  : Any value, should be at least an order of
+   magnitude less then the input size, but bigger then 32. 4 - Iterations  :
+   Special, if set to 0, iterations will be automatically determined such that
+   the benchmark will run between 10 to 100 secs
+
+*/
+
+#if MAIN_HAS_NOARGC
+MAIN_RETURN_TYPE
+ee_main(void)
+{
+    int   argc = 0;
+    char *argv[1];
+#else
+MAIN_RETURN_TYPE
+ee_main(int argc, char *argv[])
+{
+#endif
+    ee_u16       i, j = 0, num_algorithms = 0;
+    ee_s16       known_id = -1, total_errors = 0;
+    ee_u16       seedcrc = 0;
+    CORE_TICKS   total_time;
+    core_results results[MULTITHREAD];
+#if (MEM_METHOD == MEM_STACK)
+    ee_u8 stack_memblock[TOTAL_DATA_SIZE * MULTITHREAD];
+#endif
+    /* first call any initializations needed */
+    portable_init(&(results[0].port), &argc, argv);
+    /* First some checks to make sure benchmark will run ok */
+    if (sizeof(struct list_head_s) > 128)
+    {
+        ee_printf("list_head structure too big for comparable data!");
+        return MAIN_RETURN_VAL;
+    }
+    results[0].seed1      = get_seed(1);
+    results[0].seed2      = get_seed(2);
+    results[0].seed3      = get_seed(3);
+    results[0].iterations = get_seed_32(4);
+#if CORE_DEBUG
+    results[0].iterations = 1;
+#endif
+    results[0].execs = get_seed_32(5);
+    if (results[0].execs == 0)
+    { /* if not supplied, execute all algorithms */
+        results[0].execs = ALL_ALGORITHMS_MASK;
+    }
+    /* put in some default values based on one seed only for easy testing */
+    if ((results[0].seed1 == 0) && (results[0].seed2 == 0)
+        && (results[0].seed3 == 0))
+    { /* performance run */
+        results[0].seed1 = 0;
+        results[0].seed2 = 0;
+        results[0].seed3 = 0x66;
+    }
+    if ((results[0].seed1 == 1) && (results[0].seed2 == 0)
+        && (results[0].seed3 == 0))
+    { /* validation run */
+        results[0].seed1 = 0x3415;
+        results[0].seed2 = 0x3415;
+        results[0].seed3 = 0x66;
+    }
+#if (MEM_METHOD == MEM_STATIC)
+    results[0].memblock[0] = (void *)static_memblk;
+    results[0].size        = TOTAL_DATA_SIZE;
+    results[0].err         = 0;
+#if (MULTITHREAD > 1)
+#error "Cannot use a static data area with multiple contexts!"
+#endif
+#elif (MEM_METHOD == MEM_MALLOC)
+    for (i = 0; i < MULTITHREAD; i++)
+    {
+        ee_s32 malloc_override = get_seed(7);
+        if (malloc_override != 0)
+            results[i].size = malloc_override;
+        else
+            results[i].size = TOTAL_DATA_SIZE;
+        results[i].memblock[0] = portable_malloc(results[i].size);
+        results[i].seed1       = results[0].seed1;
+        results[i].seed2       = results[0].seed2;
+        results[i].seed3       = results[0].seed3;
+        results[i].err         = 0;
+        results[i].execs       = results[0].execs;
+    }
+#elif (MEM_METHOD == MEM_STACK)
+for (i = 0; i < MULTITHREAD; i++)
+{
+    results[i].memblock[0] = stack_memblock + i * TOTAL_DATA_SIZE;
+    results[i].size        = TOTAL_DATA_SIZE;
+    results[i].seed1       = results[0].seed1;
+    results[i].seed2       = results[0].seed2;
+    results[i].seed3       = results[0].seed3;
+    results[i].err         = 0;
+    results[i].execs       = results[0].execs;
+}
+#else
+#error "Please define a way to initialize a memory block."
+#endif
+    /* Data init */
+    /* Find out how space much we have based on number of algorithms */
+    for (i = 0; i < NUM_ALGORITHMS; i++)
+    {
+        if ((1 << (ee_u32)i) & results[0].execs)
+            num_algorithms++;
+    }
+    for (i = 0; i < MULTITHREAD; i++)
+        results[i].size = results[i].size / num_algorithms;
+    /* Assign pointers */
+    for (i = 0; i < NUM_ALGORITHMS; i++)
+    {
+        ee_u32 ctx;
+        if ((1 << (ee_u32)i) & results[0].execs)
+        {
+            for (ctx = 0; ctx < MULTITHREAD; ctx++)
+                results[ctx].memblock[i + 1]
+                    = (char *)(results[ctx].memblock[0]) + results[0].size * j;
+            j++;
+        }
+    }
+    /* call inits */
+    for (i = 0; i < MULTITHREAD; i++)
+    {
+        if (results[i].execs & ID_LIST)
+        {
+            results[i].list = core_list_init(
+                results[0].size, results[i].memblock[1], results[i].seed1);
+        }
+        if (results[i].execs & ID_MATRIX)
+        {
+            core_init_matrix(results[0].size,
+                             results[i].memblock[2],
+                             (ee_s32)results[i].seed1
+                                 | (((ee_s32)results[i].seed2) << 16),
+                             &(results[i].mat));
+        }
+        if (results[i].execs & ID_STATE)
+        {
+            core_init_state(
+                results[0].size, results[i].seed1, results[i].memblock[3]);
+        }
+    }
+
+    /* automatically determine number of iterations if not set */
+    if (results[0].iterations == 0)
+    {
+        secs_ret secs_passed = 0;
+        ee_u32   divisor;
+        results[0].iterations = 1;
+        while (secs_passed < (secs_ret)1)
+        {
+            results[0].iterations *= 10;
+            start_time();
+            iterate(&results[0]);
+            stop_time();
+            secs_passed = time_in_secs(get_time());
+        }
+        /* now we know it executes for at least 1 sec, set actual run time at
+         * about 10 secs */
+        divisor = (ee_u32)secs_passed;
+        if (divisor == 0) /* some machines cast float to int as 0 since this
+                             conversion is not defined by ANSI, but we know at
+                             least one second passed */
+            divisor = 1;
+        results[0].iterations *= 1 + 10 / divisor;
+    }
+    /* perform actual benchmark */
+    start_time();
+#if (MULTITHREAD > 1)
+    if (default_num_contexts > MULTITHREAD)
+    {
+        default_num_contexts = MULTITHREAD;
+    }
+    for (i = 0; i < default_num_contexts; i++)
+    {
+        results[i].iterations = results[0].iterations;
+        results[i].execs      = results[0].execs;
+        core_start_parallel(&results[i]);
+    }
+    for (i = 0; i < default_num_contexts; i++)
+    {
+        core_stop_parallel(&results[i]);
+    }
+#else
+    iterate(&results[0]);
+#endif
+    stop_time();
+    total_time = get_time();
+    /* get a function of the input to report */
+    seedcrc = crc16(results[0].seed1, seedcrc);
+    seedcrc = crc16(results[0].seed2, seedcrc);
+    seedcrc = crc16(results[0].seed3, seedcrc);
+    seedcrc = crc16(results[0].size, seedcrc);
+
+    switch (seedcrc)
+    {                /* test known output for common seeds */
+        case 0x8a02: /* seed1=0, seed2=0, seed3=0x66, size 2000 per algorithm */
+            known_id = 0;
+            ee_printf("6k performance run parameters for coremark.");
+            break;
+        case 0x7b05: /*  seed1=0x3415, seed2=0x3415, seed3=0x66, size 2000 per
+                        algorithm */
+            known_id = 1;
+            ee_printf("6k validation run parameters for coremark.");
+            break;
+        case 0x4eaf: /* seed1=0x8, seed2=0x8, seed3=0x8, size 400 per algorithm
+                      */
+            known_id = 2;
+            ee_printf("Profile generation run parameters for coremark.");
+            break;
+        case 0xe9f5: /* seed1=0, seed2=0, seed3=0x66, size 666 per algorithm */
+            known_id = 3;
+            ee_printf("2K performance run parameters for coremark.");
+            break;
+        case 0x18f2: /*  seed1=0x3415, seed2=0x3415, seed3=0x66, size 666 per
+                        algorithm */
+            known_id = 4;
+            ee_printf("2K validation run parameters for coremark.");
+            break;
+        default:
+            total_errors = -1;
+            break;
+    }
+    if (known_id >= 0)
+    {
+        for (i = 0; i < default_num_contexts; i++)
+        {
+            results[i].err = 0;
+            if ((results[i].execs & ID_LIST)
+                && (results[i].crclist != list_known_crc[known_id]))
+            {
+                ee_printf("[%u]ERROR! list crc 0x%04x - should be 0x%04x",
+                          i,
+                          results[i].crclist,
+                          list_known_crc[known_id]);
+                results[i].err++;
+            }
+            if ((results[i].execs & ID_MATRIX)
+                && (results[i].crcmatrix != matrix_known_crc[known_id]))
+            {
+                ee_printf("[%u]ERROR! matrix crc 0x%04x - should be 0x%04x",
+                          i,
+                          results[i].crcmatrix,
+                          matrix_known_crc[known_id]);
+                results[i].err++;
+            }
+            if ((results[i].execs & ID_STATE)
+                && (results[i].crcstate != state_known_crc[known_id]))
+            {
+                ee_printf("[%u]ERROR! state crc 0x%04x - should be 0x%04x",
+                          i,
+                          results[i].crcstate,
+                          state_known_crc[known_id]);
+                results[i].err++;
+            }
+            total_errors += results[i].err;
+        }
+    }
+    total_errors += check_data_types();
+    /* and report results */
+    ee_printf("CoreMark Size    : %lu", (long unsigned)results[0].size);
+    ee_printf("Total ticks      : %lu", (long unsigned)total_time);
+#if HAS_FLOAT
+    ee_printf("Total time (secs): %f", time_in_secs(total_time));
+    if (time_in_secs(total_time) > 0)
+        ee_printf("Iterations/Sec   : %f",
+                  default_num_contexts * results[0].iterations
+                      / time_in_secs(total_time));
+#else
+    ee_printf("Total time (secs): %d", time_in_secs(total_time));
+    if (time_in_secs(total_time) > 0)
+        ee_printf("Iterations/Sec   : %d",
+                  default_num_contexts * results[0].iterations
+                      / time_in_secs(total_time));
+#endif
+    if (time_in_secs(total_time) < 10)
+    {
+        ee_printf(
+            "ERROR! Must execute for at least 10 secs for a valid result!");
+        total_errors++;
+    }
+
+    ee_printf("Iterations       : %lu",
+              (long unsigned)default_num_contexts * results[0].iterations);
+    ee_printf("Compiler version : %s", COMPILER_VERSION);
+    ee_printf("Compiler flags   : %s", COMPILER_FLAGS);
+#if (MULTITHREAD > 1)
+    ee_printf("Parallel %s : %d", PARALLEL_METHOD, default_num_contexts);
+#endif
+    ee_printf("Memory location  : %s", MEM_LOCATION);
+    /* output for verification */
+    ee_printf("seedcrc          : 0x%04x", seedcrc);
+    if (results[0].execs & ID_LIST)
+        for (i = 0; i < default_num_contexts; i++)
+            ee_printf("[%d]crclist       : 0x%04x", i, results[i].crclist);
+    if (results[0].execs & ID_MATRIX)
+        for (i = 0; i < default_num_contexts; i++)
+            ee_printf("[%d]crcmatrix     : 0x%04x", i, results[i].crcmatrix);
+    if (results[0].execs & ID_STATE)
+        for (i = 0; i < default_num_contexts; i++)
+            ee_printf("[%d]crcstate      : 0x%04x", i, results[i].crcstate);
+    for (i = 0; i < default_num_contexts; i++)
+        ee_printf("[%d]crcfinal      : 0x%04x", i, results[i].crc);
+    if (total_errors == 0)
+    {
+        ee_printf(
+            "Correct operation validated. See README.md for run and reporting "
+            "rules.");
+#if HAS_FLOAT
+        if (known_id == 3)
+        {
+            ee_printf("CoreMark 1.0 : %f / %s %s",
+                      default_num_contexts * results[0].iterations
+                          / time_in_secs(total_time),
+                      COMPILER_VERSION,
+                      COMPILER_FLAGS);
+#if defined(MEM_LOCATION) && !defined(MEM_LOCATION_UNSPEC)
+            ee_printf(" / %s", MEM_LOCATION);
+#else
+            ee_printf(" / %s", mem_name[MEM_METHOD]);
+#endif
+
+#if (MULTITHREAD > 1)
+            ee_printf(" / %d:%s", default_num_contexts, PARALLEL_METHOD);
+#endif
+            ee_printf("");
+        }
+#endif
+    }
+    if (total_errors > 0)
+        ee_printf("Errors detected");
+    if (total_errors < 0)
+        ee_printf(
+            "Cannot validate operation for these seed values, please compare "
+            "with results on a known platform.");
+
+#if (MEM_METHOD == MEM_MALLOC)
+    for (i = 0; i < MULTITHREAD; i++)
+        portable_free(results[i].memblock[0]);
+#endif
+    /* And last call any target specific code for finalizing */
+    portable_fini(&(results[0].port));
+
+    return MAIN_RETURN_VAL;
+}

+ 359 - 0
components/coremark/core_matrix.c

@@ -0,0 +1,359 @@
+/*
+Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Original Author: Shay Gal-on
+*/
+
+#include "coremark.h"
+/*
+Topic: Description
+        Matrix manipulation benchmark
+
+        This very simple algorithm forms the basis of many more complex
+algorithms.
+
+        The tight inner loop is the focus of many optimizations (compiler as
+well as hardware based) and is thus relevant for embedded processing.
+
+        The total available data space will be divided to 3 parts:
+        NxN Matrix A - initialized with small values (upper 3/4 of the bits all
+zero). NxN Matrix B - initialized with medium values (upper half of the bits all
+zero). NxN Matrix C - used for the result.
+
+        The actual values for A and B must be derived based on input that is not
+available at compile time.
+*/
+ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val);
+ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval);
+void   matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val);
+void   matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
+void   matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
+void   matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
+void   matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val);
+
+#define matrix_test_next(x)      (x + 1)
+#define matrix_clip(x, y)        ((y) ? (x)&0x0ff : (x)&0x0ffff)
+#define matrix_big(x)            (0xf000 | (x))
+#define bit_extract(x, from, to) (((x) >> (from)) & (~(0xffffffff << (to))))
+
+#if CORE_DEBUG
+void
+printmat(MATDAT *A, ee_u32 N, char *name)
+{
+    ee_u32 i, j;
+    ee_printf("Matrix %s [%dx%d]:\n", name, N, N);
+    for (i = 0; i < N; i++)
+    {
+        for (j = 0; j < N; j++)
+        {
+            if (j != 0)
+                ee_printf(",");
+            ee_printf("%d", A[i * N + j]);
+        }
+        ee_printf("\n");
+    }
+}
+void
+printmatC(MATRES *C, ee_u32 N, char *name)
+{
+    ee_u32 i, j;
+    ee_printf("Matrix %s [%dx%d]:\n", name, N, N);
+    for (i = 0; i < N; i++)
+    {
+        for (j = 0; j < N; j++)
+        {
+            if (j != 0)
+                ee_printf(",");
+            ee_printf("%d", C[i * N + j]);
+        }
+        ee_printf("\n");
+    }
+}
+#endif
+/* Function: core_bench_matrix
+        Benchmark function
+
+        Iterate <matrix_test> N times,
+        changing the matrix values slightly by a constant amount each time.
+*/
+ee_u16
+core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc)
+{
+    ee_u32  N   = p->N;
+    MATRES *C   = p->C;
+    MATDAT *A   = p->A;
+    MATDAT *B   = p->B;
+    MATDAT  val = (MATDAT)seed;
+
+    crc = crc16(matrix_test(N, C, A, B, val), crc);
+
+    return crc;
+}
+
+/* Function: matrix_test
+        Perform matrix manipulation.
+
+        Parameters:
+        N - Dimensions of the matrix.
+        C - memory for result matrix.
+        A - input matrix
+        B - operator matrix (not changed during operations)
+
+        Returns:
+        A CRC value that captures all results calculated in the function.
+        In particular, crc of the value calculated on the result matrix
+        after each step by <matrix_sum>.
+
+        Operation:
+
+        1 - Add a constant value to all elements of a matrix.
+        2 - Multiply a matrix by a constant.
+        3 - Multiply a matrix by a vector.
+        4 - Multiply a matrix by a matrix.
+        5 - Add a constant value to all elements of a matrix.
+
+        After the last step, matrix A is back to original contents.
+*/
+ee_s16
+matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val)
+{
+    ee_u16 crc     = 0;
+    MATDAT clipval = matrix_big(val);
+
+    matrix_add_const(N, A, val); /* make sure data changes  */
+#if CORE_DEBUG
+    printmat(A, N, "matrix_add_const");
+#endif
+    matrix_mul_const(N, C, A, val);
+    crc = crc16(matrix_sum(N, C, clipval), crc);
+#if CORE_DEBUG
+    printmatC(C, N, "matrix_mul_const");
+#endif
+    matrix_mul_vect(N, C, A, B);
+    crc = crc16(matrix_sum(N, C, clipval), crc);
+#if CORE_DEBUG
+    printmatC(C, N, "matrix_mul_vect");
+#endif
+    matrix_mul_matrix(N, C, A, B);
+    crc = crc16(matrix_sum(N, C, clipval), crc);
+#if CORE_DEBUG
+    printmatC(C, N, "matrix_mul_matrix");
+#endif
+    matrix_mul_matrix_bitextract(N, C, A, B);
+    crc = crc16(matrix_sum(N, C, clipval), crc);
+#if CORE_DEBUG
+    printmatC(C, N, "matrix_mul_matrix_bitextract");
+#endif
+
+    matrix_add_const(N, A, -val); /* return matrix to initial value */
+    return crc;
+}
+
+/* Function : matrix_init
+        Initialize the memory block for matrix benchmarking.
+
+        Parameters:
+        blksize - Size of memory to be initialized.
+        memblk - Pointer to memory block.
+        seed - Actual values chosen depend on the seed parameter.
+        p - pointers to <mat_params> containing initialized matrixes.
+
+        Returns:
+        Matrix dimensions.
+
+        Note:
+        The seed parameter MUST be supplied from a source that cannot be
+   determined at compile time
+*/
+ee_u32
+core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p)
+{
+    ee_u32  N = 0;
+    MATDAT *A;
+    MATDAT *B;
+    ee_s32  order = 1;
+    MATDAT  val;
+    ee_u32  i = 0, j = 0;
+    if (seed == 0)
+        seed = 1;
+    while (j < blksize)
+    {
+        i++;
+        j = i * i * 2 * 4;
+    }
+    N = i - 1;
+    A = (MATDAT *)align_mem(memblk);
+    B = A + N * N;
+
+    for (i = 0; i < N; i++)
+    {
+        for (j = 0; j < N; j++)
+        {
+            seed         = ((order * seed) % 65536);
+            val          = (seed + order);
+            val          = matrix_clip(val, 0);
+            B[i * N + j] = val;
+            val          = (val + order);
+            val          = matrix_clip(val, 1);
+            A[i * N + j] = val;
+            order++;
+        }
+    }
+
+    p->A = A;
+    p->B = B;
+    p->C = (MATRES *)align_mem(B + N * N);
+    p->N = N;
+#if CORE_DEBUG
+    printmat(A, N, "A");
+    printmat(B, N, "B");
+#endif
+    return N;
+}
+
+/* Function: matrix_sum
+        Calculate a function that depends on the values of elements in the
+   matrix.
+
+        For each element, accumulate into a temporary variable.
+
+        As long as this value is under the parameter clipval,
+        add 1 to the result if the element is bigger then the previous.
+
+        Otherwise, reset the accumulator and add 10 to the result.
+*/
+ee_s16
+matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval)
+{
+    MATRES tmp = 0, prev = 0, cur = 0;
+    ee_s16 ret = 0;
+    ee_u32 i, j;
+    for (i = 0; i < N; i++)
+    {
+        for (j = 0; j < N; j++)
+        {
+            cur = C[i * N + j];
+            tmp += cur;
+            if (tmp > clipval)
+            {
+                ret += 10;
+                tmp = 0;
+            }
+            else
+            {
+                ret += (cur > prev) ? 1 : 0;
+            }
+            prev = cur;
+        }
+    }
+    return ret;
+}
+
+/* Function: matrix_mul_const
+        Multiply a matrix by a constant.
+        This could be used as a scaler for instance.
+*/
+void
+matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val)
+{
+    ee_u32 i, j;
+    for (i = 0; i < N; i++)
+    {
+        for (j = 0; j < N; j++)
+        {
+            C[i * N + j] = (MATRES)A[i * N + j] * (MATRES)val;
+        }
+    }
+}
+
+/* Function: matrix_add_const
+        Add a constant value to all elements of a matrix.
+*/
+void
+matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val)
+{
+    ee_u32 i, j;
+    for (i = 0; i < N; i++)
+    {
+        for (j = 0; j < N; j++)
+        {
+            A[i * N + j] += val;
+        }
+    }
+}
+
+/* Function: matrix_mul_vect
+        Multiply a matrix by a vector.
+        This is common in many simple filters (e.g. fir where a vector of
+   coefficients is applied to the matrix.)
+*/
+void
+matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
+{
+    ee_u32 i, j;
+    for (i = 0; i < N; i++)
+    {
+        C[i] = 0;
+        for (j = 0; j < N; j++)
+        {
+            C[i] += (MATRES)A[i * N + j] * (MATRES)B[j];
+        }
+    }
+}
+
+/* Function: matrix_mul_matrix
+        Multiply a matrix by a matrix.
+        Basic code is used in many algorithms, mostly with minor changes such as
+   scaling.
+*/
+void
+matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
+{
+    ee_u32 i, j, k;
+    for (i = 0; i < N; i++)
+    {
+        for (j = 0; j < N; j++)
+        {
+            C[i * N + j] = 0;
+            for (k = 0; k < N; k++)
+            {
+                C[i * N + j] += (MATRES)A[i * N + k] * (MATRES)B[k * N + j];
+            }
+        }
+    }
+}
+
+/* Function: matrix_mul_matrix_bitextract
+        Multiply a matrix by a matrix, and extract some bits from the result.
+        Basic code is used in many algorithms, mostly with minor changes such as
+   scaling.
+*/
+void
+matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
+{
+    ee_u32 i, j, k;
+    for (i = 0; i < N; i++)
+    {
+        for (j = 0; j < N; j++)
+        {
+            C[i * N + j] = 0;
+            for (k = 0; k < N; k++)
+            {
+                MATRES tmp = (MATRES)A[i * N + k] * (MATRES)B[k * N + j];
+                C[i * N + j] += bit_extract(tmp, 2, 4) * bit_extract(tmp, 5, 7);
+            }
+        }
+    }
+}

+ 152 - 0
components/coremark/core_portme.c

@@ -0,0 +1,152 @@
+/*
+Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Original Author: Shay Gal-on
+*/
+#include "coremark.h"
+#include "core_portme.h"
+
+#if VALIDATION_RUN
+volatile ee_s32 seed1_volatile = 0x3415;
+volatile ee_s32 seed2_volatile = 0x3415;
+volatile ee_s32 seed3_volatile = 0x66;
+#endif
+#if PERFORMANCE_RUN
+volatile ee_s32 seed1_volatile = 0x0;
+volatile ee_s32 seed2_volatile = 0x0;
+volatile ee_s32 seed3_volatile = 0x66;
+#endif
+#if PROFILE_RUN
+volatile ee_s32 seed1_volatile = 0x8;
+volatile ee_s32 seed2_volatile = 0x8;
+volatile ee_s32 seed3_volatile = 0x8;
+#endif
+volatile ee_s32 seed4_volatile = ITERATIONS;
+volatile ee_s32 seed5_volatile = 0;
+/* Porting : Timing functions
+        How to capture time and convert to seconds must be ported to whatever is
+   supported by the platform. e.g. Read value from on board RTC, read value from
+   cpu clock cycles performance counter etc. Sample implementation for standard
+   time.h and windows.h definitions included.
+*/
+CORETIMETYPE
+barebones_clock()
+{
+    extern long luat_mcu_ticks(void);
+    return (CORETIMETYPE)luat_mcu_ticks();
+}
+/* Define : TIMER_RES_DIVIDER
+        Divider to trade off timer resolution and total time that can be
+   measured.
+
+        Use lower values to increase resolution, but make sure that overflow
+   does not occur. If there are issues with the return value overflowing,
+   increase this value.
+        */
+#define GETMYTIME(_t)              (*_t = barebones_clock())
+#define MYTIMEDIFF(fin, ini)       ((fin) - (ini))
+#define TIMER_RES_DIVIDER          1
+#define SAMPLE_TIME_IMPLEMENTATION 1
+#define EE_TICKS_PER_SEC           (CLOCKS_PER_SEC / TIMER_RES_DIVIDER)
+
+/** Define Host specific (POSIX), or target specific global time variables. */
+static CORETIMETYPE start_time_val, stop_time_val;
+
+/* Function : start_time
+        This function will be called right before starting the timed portion of
+   the benchmark.
+
+        Implementation may be capturing a system timer (as implemented in the
+   example code) or zeroing some system parameters - e.g. setting the cpu clocks
+   cycles to 0.
+*/
+void
+start_time(void)
+{
+    GETMYTIME(&start_time_val);
+}
+/* Function : stop_time
+        This function will be called right after ending the timed portion of the
+   benchmark.
+
+        Implementation may be capturing a system timer (as implemented in the
+   example code) or other system parameters - e.g. reading the current value of
+   cpu cycles counter.
+*/
+void
+stop_time(void)
+{
+    GETMYTIME(&stop_time_val);
+}
+/* Function : get_time
+        Return an abstract "ticks" number that signifies time on the system.
+
+        Actual value returned may be cpu cycles, milliseconds or any other
+   value, as long as it can be converted to seconds by <time_in_secs>. This
+   methodology is taken to accommodate any hardware or simulated platform. The
+   sample implementation returns millisecs by default, and the resolution is
+   controlled by <TIMER_RES_DIVIDER>
+*/
+CORE_TICKS
+get_time(void)
+{
+    CORE_TICKS elapsed
+        = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
+    return elapsed;
+}
+/* Function : time_in_secs
+        Convert the value returned by get_time to seconds.
+
+        The <secs_ret> type is used to accommodate systems with no support for
+   floating point. Default implementation implemented by the EE_TICKS_PER_SEC
+   macro above.
+*/
+secs_ret
+time_in_secs(CORE_TICKS ticks)
+{
+    secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
+    return retval;
+}
+
+ee_u32 default_num_contexts = 1;
+
+/* Function : portable_init
+        Target specific initialization code
+        Test for some common mistakes.
+*/
+void
+portable_init(core_portable *p, int *argc, char *argv[])
+{
+    if (sizeof(ee_ptr_int) != sizeof(ee_u8 *))
+    {
+        ee_printf(
+            "ERROR! Please define ee_ptr_int to a type that holds a "
+            "pointer!\n");
+    }
+    if (sizeof(ee_u32) != 4)
+    {
+        ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
+    }
+    p->portable_id = 1;
+}
+/* Function : portable_fini
+        Target specific final code
+*/
+void
+portable_fini(core_portable *p)
+{
+    p->portable_id = 0;
+}
+

+ 214 - 0
components/coremark/core_portme.h

@@ -0,0 +1,214 @@
+/*
+Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Original Author: Shay Gal-on
+*/
+/* Topic : Description
+        This file contains configuration constants required to execute on
+   different platforms
+*/
+#ifndef CORE_PORTME_H
+#define CORE_PORTME_H
+/************************/
+/* Data types and settings */
+/************************/
+/* Configuration : HAS_FLOAT
+        Define to 1 if the platform supports floating point.
+*/
+#ifndef HAS_FLOAT
+#define HAS_FLOAT 1
+#endif
+/* Configuration : HAS_TIME_H
+        Define to 1 if platform has the time.h header file,
+        and implementation of functions thereof.
+*/
+#ifndef HAS_TIME_H
+#define HAS_TIME_H 1
+#endif
+/* Configuration : USE_CLOCK
+        Define to 1 if platform has the time.h header file,
+        and implementation of functions thereof.
+*/
+#ifndef USE_CLOCK
+#define USE_CLOCK 1
+#endif
+/* Configuration : HAS_STDIO
+        Define to 1 if the platform has stdio.h.
+*/
+#ifndef HAS_STDIO
+#define HAS_STDIO 0
+#endif
+/* Configuration : HAS_PRINTF
+        Define to 1 if the platform has stdio.h and implements the printf
+   function.
+*/
+#ifndef HAS_PRINTF
+#define HAS_PRINTF 0
+#endif
+
+/* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION
+        Initialize these strings per platform
+*/
+#ifndef COMPILER_VERSION
+#ifdef __GNUC__
+#define COMPILER_VERSION "GCC"__VERSION__
+#else
+#define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)"
+#endif
+#endif
+#ifndef COMPILER_FLAGS
+#define COMPILER_FLAGS \
+    "-Os"
+#endif
+#ifndef MEM_LOCATION
+#define MEM_LOCATION "STACK"
+#endif
+
+/* Data Types :
+        To avoid compiler issues, define the data types that need ot be used for
+   8b, 16b and 32b in <core_portme.h>.
+
+        *Imprtant* :
+        ee_ptr_int needs to be the data type used to hold pointers, otherwise
+   coremark may fail!!!
+*/
+typedef signed short   ee_s16;
+typedef unsigned short ee_u16;
+typedef signed int     ee_s32;
+typedef double         ee_f32;
+typedef unsigned char  ee_u8;
+typedef unsigned int   ee_u32;
+typedef ee_u32         ee_ptr_int;
+typedef unsigned int   ee_size_t;
+#define NULL ((void *)0)
+/* align_mem :
+        This macro is used to align an offset to point to a 32b value. It is
+   used in the Matrix algorithm to initialize the input memory blocks.
+*/
+#define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3))
+
+/* Configuration : CORE_TICKS
+        Define type of return from the timing functions.
+ */
+#define CORETIMETYPE ee_u32
+typedef ee_u32 CORE_TICKS;
+
+/* Configuration : SEED_METHOD
+        Defines method to get seed values that cannot be computed at compile
+   time.
+
+        Valid values :
+        SEED_ARG - from command line.
+        SEED_FUNC - from a system function.
+        SEED_VOLATILE - from volatile variables.
+*/
+#ifndef SEED_METHOD
+#define SEED_METHOD SEED_VOLATILE
+#endif
+
+/* Configuration : MEM_METHOD
+        Defines method to get a block of memry.
+
+        Valid values :
+        MEM_MALLOC - for platforms that implement malloc and have malloc.h.
+        MEM_STATIC - to use a static memory array.
+        MEM_STACK - to allocate the data block on the stack (NYI).
+*/
+#ifndef MEM_METHOD
+#define MEM_METHOD MEM_STACK
+#endif
+
+/* Configuration : MULTITHREAD
+        Define for parallel execution
+
+        Valid values :
+        1 - only one context (default).
+        N>1 - will execute N copies in parallel.
+
+        Note :
+        If this flag is defined to more then 1, an implementation for launching
+   parallel contexts must be defined.
+
+        Two sample implementations are provided. Use <USE_PTHREAD> or <USE_FORK>
+   to enable them.
+
+        It is valid to have a different implementation of <core_start_parallel>
+   and <core_end_parallel> in <core_portme.c>, to fit a particular architecture.
+*/
+#ifndef MULTITHREAD
+#define MULTITHREAD 1
+#define USE_PTHREAD 0
+#define USE_FORK    0
+#define USE_SOCKET  0
+#endif
+
+/* Configuration : MAIN_HAS_NOARGC
+        Needed if platform does not support getting arguments to main.
+
+        Valid values :
+        0 - argc/argv to main is supported
+        1 - argc/argv to main is not supported
+
+        Note :
+        This flag only matters if MULTITHREAD has been defined to a value
+   greater then 1.
+*/
+#ifndef MAIN_HAS_NOARGC
+#define MAIN_HAS_NOARGC 1
+#endif
+
+/* Configuration : MAIN_HAS_NORETURN
+        Needed if platform does not support returning a value from main.
+
+        Valid values :
+        0 - main returns an int, and return value will be 0.
+        1 - platform does not support returning a value from main
+*/
+#ifndef MAIN_HAS_NORETURN
+#define MAIN_HAS_NORETURN 0
+#endif
+
+/* Variable : default_num_contexts
+        Not used for this simple port, must contain the value 1.
+*/
+extern ee_u32 default_num_contexts;
+
+typedef struct CORE_PORTABLE_S
+{
+    ee_u8 portable_id;
+} core_portable;
+
+/* target specific init/fini */
+void portable_init(core_portable *p, int *argc, char *argv[]);
+void portable_fini(core_portable *p);
+
+#if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) \
+    && !defined(VALIDATION_RUN)
+#if (TOTAL_DATA_SIZE == 1200)
+#define PROFILE_RUN 1
+#elif (TOTAL_DATA_SIZE == 2000)
+#define PERFORMANCE_RUN 1
+#else
+#define VALIDATION_RUN 1
+#endif
+#endif
+
+int ee_printf(const char *fmt, ...);
+
+#define ITERATIONS 10000
+
+#define CLOCKS_PER_SEC 1000
+
+#endif /* CORE_PORTME_H */

+ 330 - 0
components/coremark/core_state.c

@@ -0,0 +1,330 @@
+/*
+Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Original Author: Shay Gal-on
+*/
+
+#include "coremark.h"
+/* local functions */
+enum CORE_STATE core_state_transition(ee_u8 **instr, ee_u32 *transition_count);
+
+/*
+Topic: Description
+        Simple state machines like this one are used in many embedded products.
+
+        For more complex state machines, sometimes a state transition table
+implementation is used instead, trading speed of direct coding for ease of
+maintenance.
+
+        Since the main goal of using a state machine in CoreMark is to excercise
+the switch/if behaviour, we are using a small moore machine.
+
+        In particular, this machine tests type of string input,
+        trying to determine whether the input is a number or something else.
+        (see core_state.png).
+*/
+
+/* Function: core_bench_state
+        Benchmark function
+
+        Go over the input twice, once direct, and once after introducing some
+   corruption.
+*/
+ee_u16
+core_bench_state(ee_u32 blksize,
+                 ee_u8 *memblock,
+                 ee_s16 seed1,
+                 ee_s16 seed2,
+                 ee_s16 step,
+                 ee_u16 crc)
+{
+    ee_u32 final_counts[NUM_CORE_STATES];
+    ee_u32 track_counts[NUM_CORE_STATES];
+    ee_u8 *p = memblock;
+    ee_u32 i;
+
+#if CORE_DEBUG
+    ee_printf("State Bench: %d,%d,%d,%04x\n", seed1, seed2, step, crc);
+#endif
+    for (i = 0; i < NUM_CORE_STATES; i++)
+    {
+        final_counts[i] = track_counts[i] = 0;
+    }
+    /* run the state machine over the input */
+    while (*p != 0)
+    {
+        enum CORE_STATE fstate = core_state_transition(&p, track_counts);
+        final_counts[fstate]++;
+#if CORE_DEBUG
+        ee_printf("%d,", fstate);
+    }
+    ee_printf("\n");
+#else
+    }
+#endif
+    p = memblock;
+    while (p < (memblock + blksize))
+    { /* insert some corruption */
+        if (*p != ',')
+            *p ^= (ee_u8)seed1;
+        p += step;
+    }
+    p = memblock;
+    /* run the state machine over the input again */
+    while (*p != 0)
+    {
+        enum CORE_STATE fstate = core_state_transition(&p, track_counts);
+        final_counts[fstate]++;
+#if CORE_DEBUG
+        ee_printf("%d,", fstate);
+    }
+    ee_printf("\n");
+#else
+    }
+#endif
+    p = memblock;
+    while (p < (memblock + blksize))
+    { /* undo corruption is seed1 and seed2 are equal */
+        if (*p != ',')
+            *p ^= (ee_u8)seed2;
+        p += step;
+    }
+    /* end timing */
+    for (i = 0; i < NUM_CORE_STATES; i++)
+    {
+        crc = crcu32(final_counts[i], crc);
+        crc = crcu32(track_counts[i], crc);
+    }
+    return crc;
+}
+
+/* Default initialization patterns */
+static ee_u8 *intpat[4]
+    = { (ee_u8 *)"5012", (ee_u8 *)"1234", (ee_u8 *)"-874", (ee_u8 *)"+122" };
+static ee_u8 *floatpat[4] = { (ee_u8 *)"35.54400",
+                              (ee_u8 *)".1234500",
+                              (ee_u8 *)"-110.700",
+                              (ee_u8 *)"+0.64400" };
+static ee_u8 *scipat[4]   = { (ee_u8 *)"5.500e+3",
+                            (ee_u8 *)"-.123e-2",
+                            (ee_u8 *)"-87e+832",
+                            (ee_u8 *)"+0.6e-12" };
+static ee_u8 *errpat[4]   = { (ee_u8 *)"T0.3e-1F",
+                            (ee_u8 *)"-T.T++Tq",
+                            (ee_u8 *)"1T3.4e4z",
+                            (ee_u8 *)"34.0e-T^" };
+
+/* Function: core_init_state
+        Initialize the input data for the state machine.
+
+        Populate the input with several predetermined strings, interspersed.
+        Actual patterns chosen depend on the seed parameter.
+
+        Note:
+        The seed parameter MUST be supplied from a source that cannot be
+   determined at compile time
+*/
+void
+core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p)
+{
+    ee_u32 total = 0, next = 0, i;
+    ee_u8 *buf = 0;
+#if CORE_DEBUG
+    ee_u8 *start = p;
+    ee_printf("State: %d,%d\n", size, seed);
+#endif
+    size--;
+    next = 0;
+    while ((total + next + 1) < size)
+    {
+        if (next > 0)
+        {
+            for (i = 0; i < next; i++)
+                *(p + total + i) = buf[i];
+            *(p + total + i) = ',';
+            total += next + 1;
+        }
+        seed++;
+        switch (seed & 0x7)
+        {
+            case 0: /* int */
+            case 1: /* int */
+            case 2: /* int */
+                buf  = intpat[(seed >> 3) & 0x3];
+                next = 4;
+                break;
+            case 3: /* float */
+            case 4: /* float */
+                buf  = floatpat[(seed >> 3) & 0x3];
+                next = 8;
+                break;
+            case 5: /* scientific */
+            case 6: /* scientific */
+                buf  = scipat[(seed >> 3) & 0x3];
+                next = 8;
+                break;
+            case 7: /* invalid */
+                buf  = errpat[(seed >> 3) & 0x3];
+                next = 8;
+                break;
+            default: /* Never happen, just to make some compilers happy */
+                break;
+        }
+    }
+    size++;
+    while (total < size)
+    { /* fill the rest with 0 */
+        *(p + total) = 0;
+        total++;
+    }
+#if CORE_DEBUG
+    ee_printf("State Input: %s\n", start);
+#endif
+}
+
+static ee_u8
+ee_isdigit(ee_u8 c)
+{
+    ee_u8 retval;
+    retval = ((c >= '0') & (c <= '9')) ? 1 : 0;
+    return retval;
+}
+
+/* Function: core_state_transition
+        Actual state machine.
+
+        The state machine will continue scanning until either:
+        1 - an invalid input is detected.
+        2 - a valid number has been detected.
+
+        The input pointer is updated to point to the end of the token, and the
+   end state is returned (either specific format determined or invalid).
+*/
+
+enum CORE_STATE
+core_state_transition(ee_u8 **instr, ee_u32 *transition_count)
+{
+    ee_u8 *         str = *instr;
+    ee_u8           NEXT_SYMBOL;
+    enum CORE_STATE state = CORE_START;
+    for (; *str && state != CORE_INVALID; str++)
+    {
+        NEXT_SYMBOL = *str;
+        if (NEXT_SYMBOL == ',') /* end of this input */
+        {
+            str++;
+            break;
+        }
+        switch (state)
+        {
+            case CORE_START:
+                if (ee_isdigit(NEXT_SYMBOL))
+                {
+                    state = CORE_INT;
+                }
+                else if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-')
+                {
+                    state = CORE_S1;
+                }
+                else if (NEXT_SYMBOL == '.')
+                {
+                    state = CORE_FLOAT;
+                }
+                else
+                {
+                    state = CORE_INVALID;
+                    transition_count[CORE_INVALID]++;
+                }
+                transition_count[CORE_START]++;
+                break;
+            case CORE_S1:
+                if (ee_isdigit(NEXT_SYMBOL))
+                {
+                    state = CORE_INT;
+                    transition_count[CORE_S1]++;
+                }
+                else if (NEXT_SYMBOL == '.')
+                {
+                    state = CORE_FLOAT;
+                    transition_count[CORE_S1]++;
+                }
+                else
+                {
+                    state = CORE_INVALID;
+                    transition_count[CORE_S1]++;
+                }
+                break;
+            case CORE_INT:
+                if (NEXT_SYMBOL == '.')
+                {
+                    state = CORE_FLOAT;
+                    transition_count[CORE_INT]++;
+                }
+                else if (!ee_isdigit(NEXT_SYMBOL))
+                {
+                    state = CORE_INVALID;
+                    transition_count[CORE_INT]++;
+                }
+                break;
+            case CORE_FLOAT:
+                if (NEXT_SYMBOL == 'E' || NEXT_SYMBOL == 'e')
+                {
+                    state = CORE_S2;
+                    transition_count[CORE_FLOAT]++;
+                }
+                else if (!ee_isdigit(NEXT_SYMBOL))
+                {
+                    state = CORE_INVALID;
+                    transition_count[CORE_FLOAT]++;
+                }
+                break;
+            case CORE_S2:
+                if (NEXT_SYMBOL == '+' || NEXT_SYMBOL == '-')
+                {
+                    state = CORE_EXPONENT;
+                    transition_count[CORE_S2]++;
+                }
+                else
+                {
+                    state = CORE_INVALID;
+                    transition_count[CORE_S2]++;
+                }
+                break;
+            case CORE_EXPONENT:
+                if (ee_isdigit(NEXT_SYMBOL))
+                {
+                    state = CORE_SCIENTIFIC;
+                    transition_count[CORE_EXPONENT]++;
+                }
+                else
+                {
+                    state = CORE_INVALID;
+                    transition_count[CORE_EXPONENT]++;
+                }
+                break;
+            case CORE_SCIENTIFIC:
+                if (!ee_isdigit(NEXT_SYMBOL))
+                {
+                    state = CORE_INVALID;
+                    transition_count[CORE_INVALID]++;
+                }
+                break;
+            default:
+                break;
+        }
+    }
+    *instr = str;
+    return state;
+}

+ 249 - 0
components/coremark/core_util.c

@@ -0,0 +1,249 @@
+/*
+Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Original Author: Shay Gal-on
+*/
+
+#include "coremark.h"
+/* Function: get_seed
+        Get a values that cannot be determined at compile time.
+
+        Since different embedded systems and compilers are used, 3 different
+   methods are provided: 1 - Using a volatile variable. This method is only
+   valid if the compiler is forced to generate code that reads the value of a
+   volatile variable from memory at run time. Please note, if using this method,
+   you would need to modify core_portme.c to generate training profile. 2 -
+   Command line arguments. This is the preferred method if command line
+   arguments are supported. 3 - System function. If none of the first 2 methods
+   is available on the platform, a system function which is not a stub can be
+   used.
+
+        e.g. read the value on GPIO pins connected to switches, or invoke
+   special simulator functions.
+*/
+#if (SEED_METHOD == SEED_VOLATILE)
+extern volatile ee_s32 seed1_volatile;
+extern volatile ee_s32 seed2_volatile;
+extern volatile ee_s32 seed3_volatile;
+extern volatile ee_s32 seed4_volatile;
+extern volatile ee_s32 seed5_volatile;
+ee_s32
+get_seed_32(int i)
+{
+    ee_s32 retval;
+    switch (i)
+    {
+        case 1:
+            retval = seed1_volatile;
+            break;
+        case 2:
+            retval = seed2_volatile;
+            break;
+        case 3:
+            retval = seed3_volatile;
+            break;
+        case 4:
+            retval = seed4_volatile;
+            break;
+        case 5:
+            retval = seed5_volatile;
+            break;
+        default:
+            retval = 0;
+            break;
+    }
+    return retval;
+}
+#elif (SEED_METHOD == SEED_ARG)
+ee_s32
+parseval(char *valstring)
+{
+    ee_s32 retval  = 0;
+    ee_s32 neg     = 1;
+    int    hexmode = 0;
+    if (*valstring == '-')
+    {
+        neg = -1;
+        valstring++;
+    }
+    if ((valstring[0] == '0') && (valstring[1] == 'x'))
+    {
+        hexmode = 1;
+        valstring += 2;
+    }
+    /* first look for digits */
+    if (hexmode)
+    {
+        while (((*valstring >= '0') && (*valstring <= '9'))
+               || ((*valstring >= 'a') && (*valstring <= 'f')))
+        {
+            ee_s32 digit = *valstring - '0';
+            if (digit > 9)
+                digit = 10 + *valstring - 'a';
+            retval *= 16;
+            retval += digit;
+            valstring++;
+        }
+    }
+    else
+    {
+        while ((*valstring >= '0') && (*valstring <= '9'))
+        {
+            ee_s32 digit = *valstring - '0';
+            retval *= 10;
+            retval += digit;
+            valstring++;
+        }
+    }
+    /* now add qualifiers */
+    if (*valstring == 'K')
+        retval *= 1024;
+    if (*valstring == 'M')
+        retval *= 1024 * 1024;
+
+    retval *= neg;
+    return retval;
+}
+
+ee_s32
+get_seed_args(int i, int argc, char *argv[])
+{
+    if (argc > i)
+        return parseval(argv[i]);
+    return 0;
+}
+
+#elif (SEED_METHOD == SEED_FUNC)
+/* If using OS based function, you must define and implement the functions below
+ * in core_portme.h and core_portme.c ! */
+ee_s32
+get_seed_32(int i)
+{
+    ee_s32 retval;
+    switch (i)
+    {
+        case 1:
+            retval = portme_sys1();
+            break;
+        case 2:
+            retval = portme_sys2();
+            break;
+        case 3:
+            retval = portme_sys3();
+            break;
+        case 4:
+            retval = portme_sys4();
+            break;
+        case 5:
+            retval = portme_sys5();
+            break;
+        default:
+            retval = 0;
+            break;
+    }
+    return retval;
+}
+#endif
+
+/* Function: crc*
+        Service functions to calculate 16b CRC code.
+
+*/
+ee_u16
+crcu8(ee_u8 data, ee_u16 crc)
+{
+    ee_u8 i = 0, x16 = 0, carry = 0;
+
+    for (i = 0; i < 8; i++)
+    {
+        x16 = (ee_u8)((data & 1) ^ ((ee_u8)crc & 1));
+        data >>= 1;
+
+        if (x16 == 1)
+        {
+            crc ^= 0x4002;
+            carry = 1;
+        }
+        else
+            carry = 0;
+        crc >>= 1;
+        if (carry)
+            crc |= 0x8000;
+        else
+            crc &= 0x7fff;
+    }
+    return crc;
+}
+ee_u16
+crcu16(ee_u16 newval, ee_u16 crc)
+{
+    crc = crcu8((ee_u8)(newval), crc);
+    crc = crcu8((ee_u8)((newval) >> 8), crc);
+    return crc;
+}
+ee_u16
+crcu32(ee_u32 newval, ee_u16 crc)
+{
+    crc = crc16((ee_s16)newval, crc);
+    crc = crc16((ee_s16)(newval >> 16), crc);
+    return crc;
+}
+ee_u16
+crc16(ee_s16 newval, ee_u16 crc)
+{
+    return crcu16((ee_u16)newval, crc);
+}
+
+ee_u8
+check_data_types()
+{
+    ee_u8 retval = 0;
+    if (sizeof(ee_u8) != 1)
+    {
+        ee_printf("ERROR: ee_u8 is not an 8b datatype!\n");
+        retval++;
+    }
+    if (sizeof(ee_u16) != 2)
+    {
+        ee_printf("ERROR: ee_u16 is not a 16b datatype!\n");
+        retval++;
+    }
+    if (sizeof(ee_s16) != 2)
+    {
+        ee_printf("ERROR: ee_s16 is not a 16b datatype!\n");
+        retval++;
+    }
+    if (sizeof(ee_s32) != 4)
+    {
+        ee_printf("ERROR: ee_s32 is not a 32b datatype!\n");
+        retval++;
+    }
+    if (sizeof(ee_u32) != 4)
+    {
+        ee_printf("ERROR: ee_u32 is not a 32b datatype!\n");
+        retval++;
+    }
+    if (sizeof(ee_ptr_int) != sizeof(int *))
+    {
+        ee_printf(
+            "ERROR: ee_ptr_int is not a datatype that holds an int pointer!\n");
+        retval++;
+    }
+    if (retval > 0)
+    {
+        ee_printf("ERROR: Please modify the datatypes in core_portme.h!\n");
+    }
+    return retval;
+}

+ 183 - 0
components/coremark/coremark.h

@@ -0,0 +1,183 @@
+/*
+Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Original Author: Shay Gal-on
+*/
+
+/* Topic: Description
+        This file contains  declarations of the various benchmark functions.
+*/
+
+/* Configuration: TOTAL_DATA_SIZE
+        Define total size for data algorithms will operate on
+*/
+#ifndef TOTAL_DATA_SIZE
+#define TOTAL_DATA_SIZE 2 * 1000
+#endif
+
+#define SEED_ARG      0
+#define SEED_FUNC     1
+#define SEED_VOLATILE 2
+
+#define MEM_STATIC 0
+#define MEM_MALLOC 1
+#define MEM_STACK  2
+
+#include "core_portme.h"
+
+#if HAS_STDIO
+#include <stdio.h>
+#endif
+#if HAS_PRINTF
+#define ee_printf printf
+#endif
+
+/* Actual benchmark execution in iterate */
+void *iterate(void *pres);
+
+/* Typedef: secs_ret
+        For machines that have floating point support, get number of seconds as
+   a double. Otherwise an unsigned int.
+*/
+#if HAS_FLOAT
+typedef double secs_ret;
+#else
+typedef ee_u32 secs_ret;
+#endif
+
+#if MAIN_HAS_NORETURN
+#define MAIN_RETURN_VAL
+#define MAIN_RETURN_TYPE void
+#else
+#define MAIN_RETURN_VAL  0
+#define MAIN_RETURN_TYPE int
+#endif
+
+void       start_time(void);
+void       stop_time(void);
+CORE_TICKS get_time(void);
+secs_ret   time_in_secs(CORE_TICKS ticks);
+
+/* Misc useful functions */
+ee_u16 crcu8(ee_u8 data, ee_u16 crc);
+ee_u16 crc16(ee_s16 newval, ee_u16 crc);
+ee_u16 crcu16(ee_u16 newval, ee_u16 crc);
+ee_u16 crcu32(ee_u32 newval, ee_u16 crc);
+ee_u8  check_data_types(void);
+void * portable_malloc(ee_size_t size);
+void   portable_free(void *p);
+ee_s32 parseval(char *valstring);
+
+/* Algorithm IDS */
+#define ID_LIST             (1 << 0)
+#define ID_MATRIX           (1 << 1)
+#define ID_STATE            (1 << 2)
+#define ALL_ALGORITHMS_MASK (ID_LIST | ID_MATRIX | ID_STATE)
+#define NUM_ALGORITHMS      3
+
+/* list data structures */
+typedef struct list_data_s
+{
+    ee_s16 data16;
+    ee_s16 idx;
+} list_data;
+
+typedef struct list_head_s
+{
+    struct list_head_s *next;
+    struct list_data_s *info;
+} list_head;
+
+/*matrix benchmark related stuff */
+#define MATDAT_INT 1
+#if MATDAT_INT
+typedef ee_s16 MATDAT;
+typedef ee_s32 MATRES;
+#else
+typedef ee_f16 MATDAT;
+typedef ee_f32 MATRES;
+#endif
+
+typedef struct MAT_PARAMS_S
+{
+    int     N;
+    MATDAT *A;
+    MATDAT *B;
+    MATRES *C;
+} mat_params;
+
+/* state machine related stuff */
+/* List of all the possible states for the FSM */
+typedef enum CORE_STATE
+{
+    CORE_START = 0,
+    CORE_INVALID,
+    CORE_S1,
+    CORE_S2,
+    CORE_INT,
+    CORE_FLOAT,
+    CORE_EXPONENT,
+    CORE_SCIENTIFIC,
+    NUM_CORE_STATES
+} core_state_e;
+
+/* Helper structure to hold results */
+typedef struct RESULTS_S
+{
+    /* inputs */
+    ee_s16              seed1;       /* Initializing seed */
+    ee_s16              seed2;       /* Initializing seed */
+    ee_s16              seed3;       /* Initializing seed */
+    void *              memblock[4]; /* Pointer to safe memory location */
+    ee_u32              size;        /* Size of the data */
+    ee_u32              iterations;  /* Number of iterations to execute */
+    ee_u32              execs;       /* Bitmask of operations to execute */
+    struct list_head_s *list;
+    mat_params          mat;
+    /* outputs */
+    ee_u16 crc;
+    ee_u16 crclist;
+    ee_u16 crcmatrix;
+    ee_u16 crcstate;
+    ee_s16 err;
+    /* ultithread specific */
+    core_portable port;
+} core_results;
+
+/* Multicore execution handling */
+#if (MULTITHREAD > 1)
+ee_u8 core_start_parallel(core_results *res);
+ee_u8 core_stop_parallel(core_results *res);
+#endif
+
+/* list benchmark functions */
+list_head *core_list_init(ee_u32 blksize, list_head *memblock, ee_s16 seed);
+ee_u16     core_bench_list(core_results *res, ee_s16 finder_idx);
+
+/* state benchmark functions */
+void   core_init_state(ee_u32 size, ee_s16 seed, ee_u8 *p);
+ee_u16 core_bench_state(ee_u32 blksize,
+                        ee_u8 *memblock,
+                        ee_s16 seed1,
+                        ee_s16 seed2,
+                        ee_s16 step,
+                        ee_u16 crc);
+
+/* matrix benchmark functions */
+ee_u32 core_init_matrix(ee_u32      blksize,
+                        void *      memblk,
+                        ee_s32      seed,
+                        mat_params *p);
+ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc);

+ 127 - 0
components/coremark/cvt.c

@@ -0,0 +1,127 @@
+/*
+Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#include <math.h>
+#define CVTBUFSIZE 80
+static char CVTBUF[CVTBUFSIZE];
+
+static char *
+cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag)
+{
+    int    r2;
+    double fi, fj;
+    char * p, *p1;
+
+    if (ndigits < 0)
+        ndigits = 0;
+    if (ndigits >= CVTBUFSIZE - 1)
+        ndigits = CVTBUFSIZE - 2;
+    r2    = 0;
+    *sign = 0;
+    p     = &buf[0];
+    if (arg < 0)
+    {
+        *sign = 1;
+        arg   = -arg;
+    }
+    arg = modf(arg, &fi);
+    p1  = &buf[CVTBUFSIZE];
+
+    if (fi != 0)
+    {
+        p1 = &buf[CVTBUFSIZE];
+        while (fi != 0)
+        {
+            fj    = modf(fi / 10, &fi);
+            *--p1 = (int)((fj + .03) * 10) + '0';
+            r2++;
+        }
+        while (p1 < &buf[CVTBUFSIZE])
+            *p++ = *p1++;
+    }
+    else if (arg > 0)
+    {
+        while ((fj = arg * 10) < 1)
+        {
+            arg = fj;
+            r2--;
+        }
+    }
+    p1 = &buf[ndigits];
+    if (eflag == 0)
+        p1 += r2;
+    *decpt = r2;
+    if (p1 < &buf[0])
+    {
+        buf[0] = '\0';
+        return buf;
+    }
+    while (p <= p1 && p < &buf[CVTBUFSIZE])
+    {
+        arg *= 10;
+        arg  = modf(arg, &fj);
+        *p++ = (int)fj + '0';
+    }
+    if (p1 >= &buf[CVTBUFSIZE])
+    {
+        buf[CVTBUFSIZE - 1] = '\0';
+        return buf;
+    }
+    p = p1;
+    *p1 += 5;
+    while (*p1 > '9')
+    {
+        *p1 = '0';
+        if (p1 > buf)
+            ++*--p1;
+        else
+        {
+            *p1 = '1';
+            (*decpt)++;
+            if (eflag == 0)
+            {
+                if (p > buf)
+                    *p = '0';
+                p++;
+            }
+        }
+    }
+    *p = '\0';
+    return buf;
+}
+
+char *
+ecvt(double arg, int ndigits, int *decpt, int *sign)
+{
+    return cvt(arg, ndigits, decpt, sign, CVTBUF, 1);
+}
+
+char *
+ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf)
+{
+    return cvt(arg, ndigits, decpt, sign, buf, 1);
+}
+
+char *
+fcvt(double arg, int ndigits, int *decpt, int *sign)
+{
+    return cvt(arg, ndigits, decpt, sign, CVTBUF, 0);
+}
+
+char *
+fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf)
+{
+    return cvt(arg, ndigits, decpt, sign, buf, 0);
+}

+ 41 - 0
components/coremark/luat_lib_coremark.c

@@ -0,0 +1,41 @@
+#include "luat_base.h"
+
+#include "printf.h"
+
+#define LUAT_LOG_TAG "coremark"
+#include "luat_log.h"
+
+void ee_main(void);;
+
+int ee_printf(const char *fmt, ...) {
+    va_list va;
+    va_start(va, fmt);
+    char buff[512];
+    vsnprintf_(buff, 512, fmt, va);
+    va_end(va);
+    LLOGD("%s", buff);
+    return 0;
+}
+
+// uint32_t ee_iterations = 0;
+
+static int l_coremark_run(lua_State *L) {
+    // if (lua_isinteger(L, 1))
+    //     ee_iterations = luaL_checkinteger(L, 1);
+    // else
+    //     ee_iterations = 10*10000;
+    ee_main();
+    return 0;
+}
+
+#include "rotable.h"
+static const rotable_Reg reg_coremark[] =
+{
+    { "run" ,         l_coremark_run ,0},
+    { NULL,             NULL ,        0}
+};
+
+LUAMOD_API int luaopen_coremark( lua_State *L ) {
+    luat_newlib(L, reg_coremark);
+    return 1;
+}

+ 33 - 0
demo/coremark/main.lua

@@ -0,0 +1,33 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "coremark"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 一定要添加sys.lua !!!!
+local sys = require "sys"
+
+--添加硬狗防止程序卡死
+--wdt.init(15000)--初始化watchdog设置为15s
+--sys.timerLoopStart(wdt.feed, 10000)--10s喂一次狗
+
+sys.taskInit(function()
+    sys.wait(2000)
+    if coremark then
+        if mcu and (rtos.bsp() == "air101" or rtos.bsp() == "air103") then
+            mcu.setClk(240)
+        end
+        log.info("coremark", "G0-----------------------------")
+        coremark.run()
+        log.info("coremark", "Done---------------------------")
+    else
+        log.info("coremark", "need coremark lib")
+    end
+end)
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 1 - 0
luat/include/luat_libs.h

@@ -93,3 +93,4 @@ LUAMOD_API int luaopen_lcdseg( lua_State *L );
 LUAMOD_API int luaopen_fdb( lua_State *L );
 
 LUAMOD_API int luaopen_keyboard( lua_State *L );
+LUAMOD_API int luaopen_coremark( lua_State *L );