401|5

78

帖子

0

资源

一粒金砂(中级)

【GD32E503评测】——04.MCU CoreMark性能测试 [复制链接]

本帖最后由 xld0932 于 2021-2-14 21:46 编辑

    CoreMark是用来衡量嵌入式系统中中心处理单元(CPU,或叫做微控制器MCU)性能的标准。该标准于2009年由EEMBC组织的Shay Gla-On提出,并且试图将其发展成为工业标准,从而代替陈旧的Dhrystone标准。代码使用C语言写成,包含如下的运算法则:列举(寻找并排序),数学矩阵操作(普通矩阵运算)和状态机(用来确定输入流中是否包含有效数字),最后还包括CRC(循环冗余校验)。

    为什么不用Dhrystone,而用CoreMark呢?Dhrystone是测量处理器运算能力的最常见基准程序之一,常用于处理器的整型运算性能的测量。程序是用C语言编写的,因此C编译器的编译效率对测试结果也有很大影响,所以Dhrystone还有许多漏洞,比如易被非法利用、人为痕迹明显、代码长度太短、缺乏验证及标准的运行规则等。

 

    一、准备工作

    1.1.到CoreMark官网上去下载开源的源代码:https://www.eembc.org/coremark/index.php(点击网页上的Download,然后跳转到GitHub上下载源代码)

1.png 2.png 3.png     1.2.在下载的CoreMark源码中,我们只使用到了simple中的port接口适配文件和根目录下的源文件

4.png     1.3.基础工程是基于上篇文章的代码上进行添加的;

 

二、移植CoreMark

    2.1.将CoreMark源代码添加到项目工程,如下图所示

5.png     2.2.将工程的Optimization配置到O3级别,添加CoreMark的头文件路径,如下图所示:

6.png 7.png     2.3.修改原先的main函数,因为CoreMark代码自带一个main入口函数,所以需要屏蔽之前我们自己写的main函数,如所示:

/*******************************************************************************
 * @brief * @param       
 * @retval      
 * @attention *******************************************************************************/
int user_main(void)
{
    InitSystem();

    while(1)
    {
        TASK_Scheduling();

        MCU_DAC_OutputHandler();
    }
}

    2.4.修改SysTick_Handler函数,用于CoreMark运算过程中的计时处理,如所示:

/*!
    \brief      this function handles SysTick exception
    \param[in]  none
    \param[out] none
    \retval     none
*/
void SysTick_Handler(void)
{
#if 0
    SysTick_Tick++;
    TASK_TimeSlice(SysTick_Tick);
#else
    CoreMark_IncTick();
#endif
}

    2.5.在core_portme.c文件中添加移植的代码,如下所示:

/**
 * 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
 */


/* Includes ------------------------------------------------------------------*/
#include "config.h"
#include "coremark.h"


/* Private defines ----------------------------------------------------------*/
#define ITERATIONS  6000


/* Private variables --------------------------------------------------------*/
volatile uint8_t stop_time_flg = 1;


/* Exported function prototypes ---------------------------------------------*/
extern void InitSystem(void);


#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 = 0x0;


/**
 * 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.
 */


/**
 * 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 NSECS_PER_SEC                   1000
#define CORETIMETYPE                    clock_t 
#define MYTIMEDIFF(fin,ini)             ((fin)-(ini))
#define TIMER_RES_DIVIDER               1
#define EE_TICKS_PER_SEC                (NSECS_PER_SEC / TIMER_RES_DIVIDER)


/**
 * Define Host specific (POSIX), or target specific global time variables.
 */
static CORETIMETYPE start_time_val = 0, stop_time_val = 0;


/**
 * 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)
{
    stop_time_flg = 0;
    stop_time_val = 0;
}


/**
 * 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)
{
	stop_time_flg = 1;
}


/**
 * 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 accomodate 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 accomodate 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[])
{
    InitSystem();

    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;
}


/**
 * @brief  : time.h
 * @param  : 
 * @returns: 
 * @details: 
 */
void CoreMark_IncTick(void)
{
    if(stop_time_flg == 0) stop_time_val++;
}


/************************ (C) COPYRIGHT ************************END OF FILE****/

 

三、运行调试

    将程序都移植完成后,对项目工程进行编译,编译无误后下载到开发板进行运行测试;

    在第一次下载运行后,串口就输出“ERROR! Must execute for at least 10 secs for a valid result!”的错误提示,如下图所示:

8.png     执行的时间小于了10秒钟,我们修改了core_portme.c中的ITERATIONS这个宏定义值,将原先的2500修改到6000,再次尝试运行时,程序运行正常,测试结果如下所示:

9.png     从上图我们可以看到CoreMark的测试结果值为576.6,当然这是基于上一个工程的基础上做的一个移植,程序运行还有可优化的空间,后面再继续研究!

 

四、源代码

Project_CoreMark.zip (438.96 KB, 下载次数: 0)

赞赏

1

查看全部赞赏

个人签名We are a team and we work as a team !

回复

197

帖子

0

资源

一粒金砂(中级)

AC5和AC6会有差异,而且优化等级也有影响。

个人签名

gitee/casy


回复

197

帖子

0

资源

一粒金砂(中级)

500多分不算高,stm32H7可以达到2000+

个人签名

gitee/casy


回复

798

帖子

2

资源

版主

测评写的不错,就喜欢你这样的测评帖子,感谢老铁的分享!期待后续

点评

谢谢  详情 回复 发表于 2021-2-17 22:54

回复

78

帖子

0

资源

一粒金砂(中级)

w494143467 发表于 2021-2-17 14:51 测评写的不错,就喜欢你这样的测评帖子,感谢老铁的分享!期待后续

谢谢

个人签名We are a team and we work as a team !

回复

3339

帖子

1

资源

五彩晶圆(初级)

576.6 代表什么意思?

个人签名人已离开,无事别找,找也找不到。

回复
您需要登录后才可以回帖 登录 | 注册

最新文章 更多>>
    关闭
    站长推荐上一条 1/6 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表