Movidius软件手册阅读 2017-09-04

选取了部分内容进行记录,主要用于理解总体框架。水平有限,如有理解错误,欢迎指正!

2LEON:

2.3.1寻址范围:

完全权限,但OS在CSS,RT在MSS.直接到各自区域地址更好.

2.3.2启动:

OS从ROM开始执行固件,固件从flash、其他存储或通过SPI连接的核加载应用代码。加载之后,boot loader将权限交给应用程序的Leon入口点,进行一些基本的初始化操作,然后调用main()或者POSIX_Init()。
启动必须从OS开始,即便只是为了启动RT或者SHAVE。
可以通过SPI、I2C、EBI等方式开始启动。

2.3.3对数据缓存的注意:

多个核的同步读写问题

2.3.4Leon工具:

用gcc和binutile编译和连接,用elf格式做object和可执行文件。均存在于sparc-elf-gcc包内。

2.3.6中断处理:

中断处理入口都在SPARC汇编中指定并优化以确保中断处理开销尽可能低。注意:浮点寄存器在终端服务程序中不能正确保存,因此不安全。OS和RT有各自的中断控制器。

2.3.7计时器:

每个核都有独自的计时器块。有8个通用计时器,一个自由计数器/一个随机数生成器/一个看门狗计时器。通过预分频系统时钟使计时器运行在较低速度。每个通用计时器都可以产生独立的中断给对应的Leon核中断控制器。

2.3.8辅助状态寄存器(ASR):

特殊说明ASR17,因为ASR17可以定制Leon处理器。

2.4OS的应用:

OS虽然能处理数值计算,但是在这方面能力明显弱于SHAVES。OS更适合于管理外围器件,数据流控制及应用状态管理,所有的计算应用趋向于在SHAVES内完成。

2.4.1OS内存特点:

OS拥有256KB的L2缓存,适用于运行小的操作系统,即使操作系统代码存储在DDR内存中。L1缓存有32KB(指令和数据各自),可以更快加速OS。
OS可以通过CMX或者DDR来执行。系统设计针对DDR运行做了缓存大小的优化使其更小耗费。

3SHAVE:

包含宽且深的寄存器堆及超长指令字。在功能单元和处理器级别上具有高并行性核高通量。包含IRF和VRF两个寄存器堆。

3.1.1整数寄存器堆IRF:

32X32bit,主要做整数操作,也可用于读写指令。IAU和SAU对这些寄存器进行操作。

3.1.2向量寄存器堆VRF:

32X128bit。

3.1.3整数运算单元IAU:

整数操作及移位和逻辑运算

3.1.4标量运算单元SAU:

浮点操作,除普通计算外,也支持一些复杂浮点运算:求倒,sine,均方根,对数,指数等。该单元也支持IRF的整数操作,以便更好的实现并行。

3.1.6比较移动单元CMU:

用于从一个寄存器复制和移动数据到另一个。可以任意组合并支持多种长度。同时用于比较不同数据类型。通过设定条件代码寄存器与多个输入进行比较。允许在VRF寄存器上一次比较多个数据。

3.1.7存取单元LSU:

对两个寄存器堆进行数据存取操作。可与其他单元配合进行操作,见SHAVE和ISA文档。

3.1.8分支单元BRU:

提供分支,SHAVE有5个周期的延迟,可以用来填充其他指令。

3.1.9预测执行单元PEU:

有助于完成条件分支或者LSU和VAU单元的条件存储。

3.2.1指令代码注意:

SHAVE对L1和L缓存都有权限。L1缓存包含1KB数据缓存和2KB指令缓存。

3.2.2数据使用注意:

SHAVE可使用1KB的L1数据缓存和256KB的L2缓存。L2配置为16X16KB,LSU可以分配到任意部分。L2缓存行为64bits。写数据默认使用回写机制(write-back)而不是直接写到内>>>存。可以通过申明 sve_writethru 信号来强制执行直写机制(write-through)。

3.3标准库支持:C/C++

3.4互斥器Mutexes:

多核共享资源,Mutexes块允许单个处理器独占资源。
8个独立互斥器,SHAVE可以预测互斥器是否可用以避免繁忙等待,Leon可以轮流查阅状态或者enable互斥器中断。互斥器一般用于读写数据结构,如任务链表,或者访问共享资源。

3.4.2使用方法:

获得互斥器,运行互斥过程,返回互斥,在结束SHAVE运行前确保互斥器被释放。

3.5SHAVE汇编

3.6SHAVE典型用法:

看eample代码

3.6.1SIPP:

有一种典型的SIPP用法是与SIPP引擎结合使用。SIPP见SIPP User Guide。

4内存

4.2内存范围:

CMX 2MB LEON访问花费低 SHAVE花费低;DDR 128MB/512MB Leon花费高 SHAVE L1低 L2一般 随机访问花费高。

4.3CMX:

链接矩阵,由16X128KB片段(slice)组成,共2MB。
每个SHAVE对其自己的slice访问时有更高的带宽和更低的功耗;slice12-15不与任何SHAVE配对,可用于其他用途。slice归属是一种很弱的概念,每个SHAVE都能以相同的花费访问CMX的其他slice。但是slice之间的路由资源是有限的,同时访问各自归属的slice更节省功耗。

4.3.3CMX配置:

两种配置:config0 for 硬件测试;config1 for应用开发。所有slice都是同样的配置。

4.4数据布局优化:

防止SHAVE程序运行时阻塞。

4.4.2阻塞源及缓解方法

4.5带宽:

4.5.1DDR带宽:

MA2150使用DDR2 533MHz,理论带宽为4GB/s.(533MHz*64bits?)

4.5.2片上带宽:

独立读写128/64bit意味着片上带宽很少可能是限制因素。

4.6内存映射:

见debugger documentation。

5MDK 系统

5.1介绍:

概括描述编译系统。编译系统提供了建立应用的主要方法,含配置和功能目标。主要功能在共用makefiles中已经完成,但是小的操作还是必要的。

5.2编译流程:

需要注意的是SHAVE代码需要对每个工程分别编译,每个工程可以有一个或者多个SHAVE应用。SHAVE C源文件通过内部开发的工具moviCompile编译。

5.3主编译目标:

MDK编译系统包含一套可用的目标,以建立最终的执行文件。

5.3.2可用的目标:

目标按照各自的角色被分到不同文件。generic.mk,generalsettings.mk…等

5.3.3Mvlibs:

5.4Makefile:Leon code

5.4.1推荐的开始方法:

5.4.2包含MDK预先编译流程功能:

每个应用程序的Makefile必须包含如下的共用定义(generic.mk)。

5.4.3调整编译选项:

如果必要,直接在Makefile的末尾增加。

5.4.4包含组件:

组件可以简单的通过在ComponentList变量中枚举进行包含。如果组件中有SHAVE代码需要在连接前包含到库中,可以通过说明进行操作:SHAVE_COMPONENTS=yes

5.5Makefile:SHAVE代码

5.5.1添加SHAVE代码:

开始添加代码时需要首先决定哪些应用程序(apps)是必要的。一旦apps被定义,对于每一个app,可能都需要从现存的例子中复制一套规则,比如从ShaveHelloWorld中复制。其中的一部分内容需要修改,可见此章说明。

5.5.2SHAVE应用程序的编译规则:

不需要使用编译库和SHAVE组件的apps,需要遵循的规则;需要使用编译库和SHAVE组件的apps,需要遵循的规则。

5.6Makefiles:连接SHAVE apps到核:

一旦apps打包到各.mvlib文件中,这些apps就会放入核内并产生SHAVE库,如例子shXlib,shvXuniqlib。并且需要枚举这些mvlib到SHAVE_APP_LIBS变量内。
编译SHAVE库需要的规则都在通用makefiles内,用户只需要定义要用的SHAVE_APPS。
每个SHAVE应用可以映射到任意SHAVE或者多个SHAVES。一个SHAVE可以用于多个SHAVE应用。

5.6.1使用shvXlib:

使用绝对地址和独立符号防止apps到核内,需要使用shvXlib名称增加该apps给每个SHAVE。例如:

5.6.2使用shvXuniqlib:

这个库用于将符号合并到一个并共享。当使用shvXuniqlib文件,一个额外的规则需要放置到文件内。

5.7编译系统功能目标:

除了编译系统和提供配置选项,MDKmakefile结构也允许编译一些功能目标来简化开发。

5.7.1make help:

显示帮助信息,包含剪短的目标描述

5.7.2make all:

发生改变后编译目标

5.7.3make run:

编译所有项并通过moviDebug在一个目标上运行。
…其他功能

6RTEMS:

讲述集成到MDK内的RTEMS,如何在Myriad2上开发RTEMS应用,如何定制和扩展RTEMS。

6.3目录结构

6.4写RTEMS应用程序:

写RTMES应用和写普通MDK应用类似。
两个附加变量需要被设置到RTEMS应用中:MV_SOC_OS和RTEMS_BUILD_NAME。
MV_SOC_OS变量用于通知编译系统我们正在使用RTEMS。该变量默认设置为‘none’。对于RTEMS应用,变量值需要设置为‘rtems’。
RTEMS_BUILD_NAME用于选择RTEMS编译类型。目前提供两种编译类型:预编译(prebuild)和定制编译(custom)。选择prebuild编译类型时将使用prebuild RTEMS库和头文件来编译应用程序,可以通过设置变量值为‘b-prebuild’来实现;设置变量值为‘b-custom’将使用从RTEMS源文件编译得到的库文件和头文件。
注意:custom编译只能在编译完成RTEMS源文件后使用。否则编译所需的这些库文件和头文件将无法找到。

6.4.1POSIX API(可移植操作系统接口API):

RTEMS实现了大部分的POSIX1003.1标准。支持许多POSIX过程,用户及SUSP(Single-USer,Single Process)方式中的面向群的过程(group oriented routines)。
RTEMS可应用的完整的POSIX部分标准可参考RTEMS网站上的POSIX完整指南。
POSIX应用程序的默认程序入口点是POSIX_Init()。它可以通过定义变量CONFIGURE_POSIX_INIT_THREAD_ENTRY_POINT为其他值做更改。
POSIX应用所需的RTEMS对象的最大数量需要通过配置进行提供,配置变量为:CONFIGURE_MAXIMUM_POSIX_THREADS,CONFIGURE_MAXIMUM_POSIX_SEMAPHORES。
如果使用超过配置的对象数量将会导致运行错误。
注意:除了POSIX API外还可以使用经典的RTEMS API。其配置参数名与POSIX类似,需要注意不能使用错误。POSIX配置宏的名称总是包含‘POSIX’,未包含的应该是经典RTEMS API。

6.4.2应用程序配置:

对于每个使用RTEMS的应用程序,至少需要提供一个基本的配置。配置信息包含:每个时钟周期的长度,可创建的RTEMS对象最大数目,初始化任务,及应用程序的设备驱动。该信息存放于会在系统初始化时传递给RTEMS的数据结构中。样表见文档该章。

6.5线程处理:

通过POSIX API允许线程创建、配置和同步,RTEMS提供多线程支持。

6.5.1线程配置:

线程属性可以通过传输pthread_attr_t结构给pthread_create函数来配置。C type可以用于控制调度策略。pthread_attr_t的成员不能被直接访问,他们只能被设置或者通过POSIX API提供的函数来查询。
RTEMS应用的两种常用调度策略是:SCHED_FIFO和SCHED_RR。
SCHED_FIFO是一种先进先出调度策略,开始新线程前每个线程要依次运行完。
SCHED_RR是时间片轮流调度策略。每个线程有一个分配的时间片,一旦线程开始,它将运行直到分配时间结束或者被其他原因阻塞。线程配置的例子见本章文档。

6.5.2线程示例程序:

MDK中有两个例子使用POSIX线程:
mdk/examples/myriad2/HowTo/rtems_apps/simpleRTEMS_posix:一个运行两个线程的简单的应用程序,展示用时间片的方式切换线程。
mdk/examples/myriad2/HowTo/rtems_apps/simpleRTEMS_shave_async:一个示例展示如何从RTEMS线程中启动SHAVES。示例中对一张图片的上半部分和下半部分使用了两种不同的处理方法。两种方法运行在不同的SHAVES上,每个SHAVE从不同的线程开始。
第二个示例同时展示了阻塞正在运行的SHAVE线程的一种方法。这样其他线程只能等到SHAVE返回的结果后才能继续运行。为实现该方法,线程在使用旗语异步开启SHAVE后被阻塞。可见本章文档示例。
当表示SHAVE完成工作的中断信号出现时,线程将被重回准备状态。在中断处理程序调用sem_post时,将会释放旗语并唤醒阻塞的线程。

6.6编译系统:

RTEMS的源代码在MDK中已经包含并允许客户修改。一些步骤需要被遵循以从源代码中编译RTEMS:make all、make compile-、make all ENABLE_DEBUG=yes、make install等。具体见本章文档。

6.7在两个LEONs上运行RTEMS:

为在两个LEONs上运行RTEMS,RTEMS_ON_BOTH_LEONS需要被设置为‘yes’。如果RTEMS_BUILD_NAME被设置为‘b-custom’使用两个LEONs的应用程序将使用二进制文件路径为:mdk/common/rtems/prebuiltcustom/build/myriad2:LeonOS需要使用的库和包含文件来自于b-los路径;LeonRT使用的来自于b-lrt路径。
如果RTEMS_BUILD_NAME变量设置为‘b-prebuild’,两个Leons将使用同样的RTEMS库mdk/common/rtems/prebuilt。

7MDK软件:

MDK包含的通用代码包括驱动、组件及示例应用。

7.2示例应用程序:

示例程序分为几个子路径:myriad1,myriad2和移动部分(portable)。Myriad1和Myriad2路径有四个类别的示例:Demo,HowTo,Progressive and SIPP;portable路径下不包含Demo。

7.2.2Progressive:

Progressive类别用于培训学习。这些例子从简单的Leon或者Shave打印开始,发展到复杂的并行计算或者DMA优化使用。

7.2.3HowTo:

该类别的示例展示了实现各种MDK软件开发目的的例子。

7.2.4Demo:

仅包含MaxFlops示例,展示如何运行卷积核处理图像,使用的SHAVE汇编代码。

7.2.5SIPP:

包含基于SIPP的示例。具体可见SIPP用户手册。

7.3包含测试数据到应用程序:

Sparc-elf-objcopy用于包含原始数据到elf文件。

7.3.2步骤:

见文档该章

7.4处理器内部通信:

LeonOS,LeonRT和12个SHAVES如何相互通信及在应用程序开发中需要跟踪哪些东西。

7.4.2从SHAVE访问Leon变量:

如果变量在Leon中被申明(int myvar[4]),SHAVE访问它的方法是简单的通过变量名:extern int myvar[4] (变量在OS中申明)或者extern int lrt_myvar[4](变量在RT中被申明),然后可以跟其他变量一样使用。

7.4.3从leon访问SHAVE变量:

假设同样的变量myvar被连接到mvlib文件的应用程序所申明,并被放置到Shave3中。这样,当从Leon访问该变量时,需要使用的方法是:extern u32 someapp3_myvar[4]。然后使用someapp3_myvar如其他变量一样。

7.4.4使用统一符号:

有时需要多个SHAVES使用相同物理地址的同一个变量。例如一个特殊的SHAVE函数或者变量需要被所有的SHAVEs共享。这样可以通过统一符号来实现。这样需要在SHAVE的mvlib文件中定义的变量不需要在shave3和shave4中定义为extern u32 someapp3_myvar[4],extern u32 someapp4_myvar[4]。而是将这个变量定义为myvar通过创建symuniq文件并用规则创建shvXuniqlib文件。可以参考Makefile规则的相关部分来了解使用细节。

7.4.5从Leon来使用SHAVE入口函数:

7.4.6LeonOS-LeonRT:

RT的入口函数作为RT的starting执行点,可以在OS侧访问,如:extern u32 lrt_start。

7.4.7LeonOS-LeonRT-SHAVES:

OS调用RT,RT调用SHAVE的方法。更详细的信息在编译过程中的创建mvlib部分。

7.5同步SHAVE运行函数和异步SHAVE运行函数:

同步运行需要调用如下函数void swcStartShave(),void swcStartShaveCC()。异步运行需要调用函数:void swcStartShaveAsync(),void swcStartShaveAsyncCC()。

7.6动态加载:

动态加载代码到SHAVE核运行

7.6.2动态加载文件类型:

两类可动态加载:‘Mbin’文件和‘shvdlib’文件。动态加载由库函数swcShaveLoader完成。

8分析应用程序:

该部分主要目标是以分析执行速度信息为例提供一个基本的指导,涉及MDK软件包的可选项并解释其中的一些限制。该部分不提供所有的分析内容,比如:功率消耗分析,指令级并行等。

8.2分析myriad2 SHAVEs的硬件支持:

SHAVE处理器有2个64bit的硬件计数器可以配置用来计数各个指标。

8.3分析myriad2 SHAVEs的软件支持:

swcTestUtils,使用详细信息可以在doxygenated MDK文档中找到。因为只有两个计数器可用,为了计数所有指标必须多次执行相同的代码

posted @ 2018-02-07 17:46  Osler  阅读(1927)  评论(0编辑  收藏  举报