SkyEye硬件模拟平台,第三部分: 硬件仿真实现之一

SkyEye的设计实现

 
 
 

 


级别: 初级

陈渝 ([email protected])清华大学

2004 年 10 月 01 日

 

前两篇文章分别介绍了 SkyEye 项目及其安装,下面的几篇文章将对其设计实现展开讨论。

一. SkyEye的总体结构

SkyEye 基于GDB/ARMulator(目前由David McCullough 维护),并进行了全面的改变和扩展。SkyEye建立在GNU GDB的底层,可以模仿多种完整的嵌入式计算机系统,目前模拟的硬件包括CPU、内存、I/O寄存器、时钟、UART、网络芯片、MMU、CACHE,将来还会模拟 LCD、USB等各种硬件。在SkyEye上运行的操作系统和各种系统软件"意识"不到它们是在一个虚拟的计算机系统上运行。

SkyEye从总体上分为四个层次:

  • 用户接口模块:包括命令行用户界面和图形用户界面,完成处理用户的输入命令,并把相关调试数据输出给用户的任务。这一部分基本上直接利用了GDB的用户接口模块,并在此基础上有一定的扩充。
  • 符号处理模块:主要处理执行文件的头信息,解释执行文件中内嵌的debuger调试信息,对符号表的管理,对源代码表达式的解析,定位源代码中的语句位置和机器码的位置关系等。这一部分也是直接利用了GDB的符号处理模块,也正是有了这个模块的支持,SkyEye可以支持源码级调试。
  • 目标控制模块:主要完成执行控制(如中断程序的执行,设置中断条件等),程序栈结构分析,对具体目标硬件的控制(如本地调试、远程调试和模拟调试的控制)。这一部分完成对SkyEye上运行的软件的控制,提供了多种调试手段。
  • 目标模拟模块:这一部分是SkyEye的核心。它的功能是模仿计算机系统中的主要硬件(包括CPU、内存和各种硬件外设等)的执行,对执行文件的机器指令进行解释,并模拟执行每一条机器指令,产生相应的硬件响应等。






二. SkyEye目标模拟模块功能划分



SkyEye目标模拟模块模拟的硬件逻辑结构图如图 0 1所示。SkyEye目标模拟模块从功能上可分为如下几大模块:

  • 配置选项解析和初始化模块:在模拟硬件开始运行前,根据配置文件的选项,控制对模拟硬件的配置和初始化。相关文件包括:
    • arminit.c:控制各种模拟硬件的初始化
    • skyeye_config.[ch]:解析配置文件的选项行
    • skyeye_options.c:根据各种硬件的选项,完成各种配置
  • 处理器模拟宏模块:主要完成与处理器体系结构相关的模拟,它可细分为:CPU指令模拟执行模块、MMU/CACHE模拟模块、CoProcessor(又称协处理器)模拟模块。
  • CPU指令模拟执行模块:其主要任务是:当模拟硬件开始运行,完成指令读取,指令译码,指令执行的工作;如果CPU状态发生了改变,调整指令和各种寄存器值;在指令执行前,调用开发板IO模拟模块的io_do_cycle驱动模拟各种外设的行为。主要的文件包括:
    • armemu.[ch]:模拟CPU的3级流水线,并具体执行各种指令
  • MMU/CACHE 模拟模块:本模块分为两部分:与具体CPU类型无关的MMU/CACHE模拟子模块和与具体CPU类型相关的模拟子模块。主要的任务是:根据配置文件进行初始化;进行MMU/CACHE模拟;执行与MMU/CACHE相关的指令。如果CPU指令模拟模块执行读写存储器的操作指令,则转到MMU/CACHE 模拟模块。如果模拟的CPU类型不支持MMU(如ARM7TDMI),则SkyEye会根据将访问的地址,直接转到MEMORY模拟模块或开发板IO模拟模块;否则转到具体CPU类型相关的模拟子模块进行MMU/CACHE模拟。主要的文件包括两部分:
    • 与具体CPU类型无关的MMU/CACHE模拟子模块:
      • armvirt.c、armmmu.c、mmu/*.[ch]
    • 与具体CPU类型相关的MMU/CACHE模拟子模块:
      • sa_mmu.[ch]:模拟strongarm的MMU/CACHE
      • arm7100_mmu.[ch]:模拟arm7[12]0T的MMU/CACHE
      • xscale_copro.c:模拟xscale的MMU/CACHE
      • arm920t_mmu.[ch]:模拟arm920t的MMU/CACHE
  • CoProcessor(又称协处理器)模拟模块:其主要任务是:完成各种协处理器的初始化;执行各种协处理器的指令。实际上MMU/CACHE模拟模块的一部分工作是模拟ARM的第15号协处理器,它的主要功能是配置MMU/CACHE等。主要的文件包括:
    • armcopro.c:根据配置信息,完成对ARM协处理器的初始化配置
    • xscale_copro.c:模拟xscale的协处理器cp13、cp14、cp15
    • sa_mmu.[ch]、arm7100_mmu.[ch]:模拟strongarm、ep7312的协处理器cp15
    • arm920t_mmu.[ch]:模拟arm920t的协处理器cp13、cp14、cp15
  • IO模拟宏模块:本模块包含各种逻辑行为各异的外设模拟,主要包括系统IO模拟模块、网络芯片模拟模块、LCD模拟模块等。
  • 系统IO模拟模块:本模块的主要任务包括:根据配置文件进行IO和外设初始化;完成各种外部IO设备的模拟(如时钟计数器累加、产生中断、LCD显示等);进行各种特定CPU和外设的IO寄存器读写的模拟。本模块与各种具体的开发板和CPU有很紧密的联系,主要的文件包括:
    • armio.[ch]:建立在各个特定模拟子模块上的抽象层模块
    • skyeye_mach_at91.c:模拟Atmel AT91X40开发板
    • skyeye_mach_ep7312.c:模拟cirrus ep7312开发板
    • skyeye_mach_pxa.c:模拟intel xscale lubbock开发板
    • skyeye_mach_s3c4510b.c:模拟基于samsung s3c4510b的开发板
    • skyeye_mach_s3c44b0.c:模拟基于samsung s3c44b0的开发板
    • skyeye_mach_sa.c:模拟基于intel strongam的adsbitsy开发板
    • skyeye_mach_lpc.c:模拟基于philip lpc2249的开发板
    • skyeye_mach_sharp.c:模拟基于sharp lh7a400的开发板
    • skyeye_mach_at91rm92.c:模拟基于atmel at91rm9200的开发板
    • skyeye_mach_cs89712.c:模拟基于cs89712的开发板
  • 网络芯片模拟模块:本模块主要完成了对8019AS网络芯片的模拟工作,主要任务包括:模拟8019AS的控制逻辑、8019AS与具体开发板IO模拟模块的接口、虚拟网络输入输出接口处理。主要的文件包括:
    • skyeye-ne2k.[ch]:8019AS的硬件逻辑模拟
    • skyeye_mach_at91.c:部分内容完成接收虚拟网络输入处理模拟
    • skyeye_net_tuntap.c:配置tuntap虚拟网络的接口
    • skyeye_net_vnet.c:配置vnet虚拟网络的接口
    • vnet.c、if_vnet.h:独立存在的软件包,vnet虚拟网络的具体实现
  • LCD/TouchScreen 模拟模块:本模块主要完成LCD/TouchScreen控制逻辑的模拟,是目前唯一需要GUI支持的模块,它的主要任务是:配置LCD /TouchScreen硬件模拟、模拟LCD/TouchScreen控制逻辑。有关LCD/TouchScreen模拟相关的文件包括:
    • skyeye_lcd.[ch]: LCD/TouchScreen配置和LCD/TouchScreen模拟的通用控制逻辑
    • skyeye_mach_*.c:与开发板相关LCD/TouchScreen的控制逻辑和中断处理,目前支持ep7312和pxa255的skyeye模拟。
  • MEMORY模拟模块:本模块与具体的CPU和开发板无关,它的主要任务包括:根据配置文件进行内存初始化,并加载binary image文件;进行RAM/ROM读写的模拟。主要的文件包括:
    • armmem.[ch]:主要完成RAM/ROM读写模拟






三. SkyEye关键数据结构

SkyEye 目标模拟模块中,各种数据结构很多,用于模拟硬件总体机构定义的主要数据结构有skyeye_config_t和ARMul_State。把握这两个数据结构,是理解整个skyeye模拟的硬件体系结构的关键,在这两个数据结构上进行进一步细化分析,则可充分了解skyeye的硬件体系结构细节。

1. skyeye_config数据结构

skyeye_config_t结构描述了SkyEye模拟的整个硬件的静态配置,它的具体内容如下:

typedef struct {
        cpu_config_t *cpu;
        machine_config_t *mach;
        mem_config_t mem;
        net_config_t net[NET_MAXNICNUM_PER_HOST];
        uart_config_t uart;
        log_config_t log;
        ARMword start_address;
	    ARMword no_lcd;
        char config_file[MAX_FILE_NAME];
} skyeye_config_t;

skyeye_config_t 结构包含了CPU核心配置信息-cpu、开发板配置信息-mach、memory map 配置信息-mem、网络芯片和网络环境配置信息-net、面向主机的输入输出配置信息-uart、测试记录输出配置信息-log、模拟执行起始地址配置信息-start_address、是否有LCD-no_lcd和记录文件名信息-config_file。这里面与模拟硬件紧密相关的是CPU核心配置信息、开发板配置信息、memory map 配置信息、网络芯片和网络环境、LCD配置信息。

2. cpu_config_t数据结构

描述CPU核心的结构定义在cpu_config_t数据结构中,具体内容如下:

typedef struct {
        const char *cpu_arch_name; 
        const char *cpu_name; 
        ARMword cpu_val;
        ARMword cpu_mask; 
        ARMword cachetype;
} cpu_config_t;

其具体描述解释如下:

  • cpu_arch_name:描述了arm cpu体系结构的名称,根据ARM CPU内核的发展,其体系结构已经从Version1发展到了Version5,其最新版本为Version5TE。而Intel在其基础上又进行了自己的扩展体系结构StrongARM(基于ARM version4)和XScale(基于ARM version5)。目前SkyEye支持"armv3"、"armv4"、"arm5"、"arm5TE"、"xscale"的体系结构。
  • cpu_name:描述了具体的arm cpu名称,如arm7TDMI、ARM720T、StrongARM1100/1110、XScale PXA2xx等。目前SkyEye支持"arm710"、"arm7TDMI"、"arm720t"、"sa1100"、"xscale"等。
  • cpu_val:这是用来表示process id,一般而言每种具体的ARM CPU 都有一个ID,更详细的描述可参考《ARM Architecture Reference Manual》的B2-6。操作系统根据这个ID来识别cpu的类型并执行相关配置。
  • cpu_mask:这是用来确定process id的屏蔽位数。由于process id中的某些位用于其它目的,并不用来表示具体的CPU类型。实际上操作系统在确定CPU类型时用到的数字是cpu_val&cpu_mask。
  • cache_type:基于ARM内核的CPU种类繁多,但如果根据CACHE类型来分,可分为三种:无CACHE类型、统一结构CACHE类型和哈佛结构CACHE类型。 SkyEye支持这三种类型。统一结构CACHE类型的CPU中,指令和数据共用同一个CACHE;而哈佛结构CACHE类型的CPU中,存在相互独立的数据CACHE和指令CACHE。无CACHE的CPU尺寸比有CACHE的CPU尺寸要小很多,成本上有优势,但在性能上要低于有CACHE的CPU。

SkyEye定义了一个cpu_config_t结构的数组(位于skyeye_option.c中),结构如下:

cpu_config_t arm_cpu[] = {
      {"armv3", "arm710",      0x41007100, 0xfff8ff00, DATACACHE},
      {"armv3", "arm7tdmi",   0x41007700, 0xfff8ff00, NONCACHE},
      {"armv4", "arm720t",     0x41807200, 0xffffff00,  DATACACHE},
      {"armv4", "sa1110",       0x6901b110, 0xfffffff0,   INSTCACHE},
      {"armv4", "sa1100",       0x4401a100, 0xffffffe0,   INSTCACHE},
      {"xscale", "xscale",         0x69052100, 0xfffffff0,   INSTCACHE}
};

3. machine_config_t数据结构

machine_config_t结构描述了开发板配置信息,定义在skyeye_config.h中,具体内容如下:

typedef struct machine_config{
    const char *machine_name;  
    void (*mach_init)(ARMul_State *state,/
                      struct machine_config *this_mach);
    void (*mach_io_do_cycle)(ARMul_State *state);
    void (*mach_io_reset)(ARMul_State *state);
    void (*mach_update_int)(ARMul_State *state);
    ARMword (*mach_io_read_byte)(ARMul_State *state, ARMword addr);
    void (*mach_io_write_byte)(ARMul_State *state, ARMword addr,/   
                                 ARMword data);
    ARMword (*mach_io_read_halfword)(ARMul_State *state, /
                                           ARMword addr);
    void (*mach_io_write_halfword)(ARMul_State *state, ARMword addr,/
                                     ARMword data);
    ARMword (*mach_io_read_word)(ARMul_State *state, ARMword addr);
    void (*mach_io_write_word)(ARMul_State *state, ARMword addr,/   
                                 ARMword data);} machine_config_t;
}machine_config_t

其具体描述解释如下:

  • machine_name:开发板的名称。目前支持的开发板有:atmel的基于AT91X40 CPU的开发板、基于Cirrus Logic ep7312的开发板、基于Intel StrongARM的adsbitsy开发板、基于Intel XScale PXA25x的Lubbock开发板等。
  • mach_init:开发板初始化配置函数,主要初始化一些与开发板相关的变量和配置mach_io_do_cycyle、mach_io_read/write_byte/halfword /word函数。mach_init函数被wrappe.c中的init函数调用。
  • mach_io_reset:开发板运行初始化函数。主要初始化与开发板相关的变量。
  • mach_update_int :定义了与开发板相关的中断处理函数。
  • mach_io_read/write_*:分别定义与开发板相关的I/O函数。

SkyEye定义了一个machine_config_t结构的数组(位于skyeye_option.c中),结构如下:

machine_config_t arm_machines[] = {     
      {"at91",              at91_mach_init,          NULL, ......},
      {"ep7312",         ep7312_mach_init,      NULL, ......},
      {"s3c4510b",      s3c4510b_mach_init,  NULL, ......},
      {"s3c44b0",        s3c44b0_mach_init,    NULL, ......},
      {"sa1100",          sa1100_mach_init,      NULL, ......},
      {"pxa_lubbock",  pxa_mach_init,           NULL, ......} …… 
};

4. mem_config_t和mem_bank_t数据结构

SkyEye 的内存映射配置结构由mem_config_t和mem_bank_t数据结构描述。ARM体系结构与x86体系结构在I/O内存映射上有所不同。X86 体系结构可以使用I/O端口来映射外部设备上的寄存器和设备内存;而ARM体系结构是通过标准的memory地址空间来映射外设的寄存器或设备内存,而且在通常情况下,I/O地址空间不会通过CACHE进行缓存。目前SkyEye支持三种类型的内存映射:ROM SPACE(只读)、RAM SPACE(可读写)、IO SPACE(可读写,与特定开发板相关)。SkyEye对这三种类型的内存映射的处理是不同的。在SkyEye中把一段连续的地址空间称为一个 mem_bank,多个mem_bank之间不一定连续。mem_config_t数据结构的具体内容如下:

typedef struct {
        int bank_num;
        int current_num;
        mem_bank_t mem_banks[MAX_BANK];
} mem_config_t;

其中 bank_num用来记录当前的硬件配置中的mem_bank总数,current_num是用于解析skyeye.conf中的mem_bank配置信息的一个辅助变量,mem_banks数组具体记录了每个mem_bank的类型和相关的访问函数。mem_bank_t数据结构的具体内容如下:

typedef struct mem_bank_t {
  ARMword (*read_byte)(ARMul_State *state, ARMword addr);
  void (*write_byte)(ARMul_State *state, ARMword addr, ARMword data);
  ARMword (*read_halfword)(ARMul_State *state, ARMword addr);
  void(*write_halfword)(ARMul_State *state, ARMword addr, ARMword data);
  ARMword (*read_word)(ARMul_State *state, ARMword addr);
  void (*write_word)(ARMul_State *state, ARMword addr, ARMword data);
  unsigned long   addr, len;
  char    filename[MAX_STR];
  unsigned type;
} mem_bank_t;

其中的read/write_* 函数指针分别对应了不同类型内存映射的访问函数;addr表示mem_bank的起始地址;len表示mem_bank_的大小;filename是 binary image文件名;type表示mem_bank的类型。函数指针赋值等配置过程由skyeye_options.c中的函数 do_mem_bank_option完成。如果在skyeye.conf中存在binary image文件名,则do_mem_bank_option函数会把文件内容读入到对应的mem_bank中。







5. net_config_t数据结构

SkyEye支持网络模拟,目前描述网络配置的数据结构是net_config_t,它的具体内容如下:

typedef struct {
   int state;
   unsigned char macaddr[6];
   unsigned char  hostip[4]; 
   int ethmod;
   int fd;                     
   int hubindex; 
   int (*net_init)(int index, unsigned char *macaddr, unsigned char *hostip);
   unsigned char (*net_output)(int if_fd, ARMul_State *state,/
                   unsigned char startpage,unsigned short packet_len);
   void  (*net_input)(int if_fd, ARMul_State *state);
}net_config_t;

其中各个field的含义描述如下:

  • state是一个布尔变量,它为1表示网络芯片工作,它为0表示网络芯片不工作。
  • macaddr用来保存网络芯片的mac地址
  • hostip用来保存主机上与SkyEye进行网络通信所用的IP地址
  • ethmod:表示与主机的模拟网络交互的方式;目前定义的交互方式有:
    • #define NET_MOD_LINUX 0
    • #define NET_MOD_TUNTAP 1
    • #define NET_MOD_WIN 2
    • #define NET_MOD_VNET 3

目前可以使用的两种方式有 NET_MOD_VNET(与SkyEye提供的vnet.o内核模块进行网络交互)和 NET_MOD_TUNTAP(与linux的tun.on内核模块进行网络交互)。

  • fd:表示SkyEye用于与主机进行网络交互的设备文件描述符。
  • hubindex:用于NET_MOD_VNET方式,表示所处的是第几个虚拟hub网段。如果它的值是i,则处于第i个hub网段中。
  • net_init/net_input/net_output:这三个函数与具体的模拟网络交互方式有关,分别完成初始化操作和与主机网络的输入输出操作。相关的实现在文件skyeye_net_*.c中。

有关8019AS模拟芯片(NE2000兼容)的具体配置与实现位于文件skyeye-ne2k.[ch]中。有关网络模拟的具体实现可参考错误!未找到引用源。节。

6. ARMul_State数据结构

上面讲述的是与SkyEye的硬件配置相关的数据结构,可以理解为一种静态硬件配置的数据结构,这些数据结构中的域基本不随着SkyEye模拟硬件的运行而改变。而ARMul_State描述的是一种动态硬件配置的数据结构,它保存了随着SkyEye模拟硬件的运行而时刻改变的硬件数据。由于 ARMul_State中的域数量繁多,大体分为

  • 与CPU模拟相关的域
  • 与协处理器模拟相关的域
  • 与内存和MMU/CACHE相关的域
    • 与统计相关的域
    • 与具体开发板相关的io部分

这里只描述其中关键的部分:

  • 与CPU模拟相关的域
    • ARMword Reg[16]:CPU当前模式下的寄存器值
    • ARMword RegBank[7][16]:CPU所有七种模式下的寄存器值
    • ARMword Cpsr:CPU的当前程序状态寄存器
    • ARMword Spsr[7]:CPU所有七种模式下的程序状态保存寄存器
    • ARMdword Accumulator:40bit的累加寄存器,目前用于xscale体系结构中
    • ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags, Sflag,TFlag:各种状态位
    • ARMword Bank:CPU对应模式寄存器组的索引值
    • ARMword Mode:CPU模式索引值
    • ARMword instr, pc:pc是目前正在执行的程序指针,instr是pc所指地址的内容
    • ARMword loaded, decoded:loaded是正在加载的指令,decoded是正在解码的指令
    • unsigned NfiqSig:FIQ信号
    • unsigned NirqSig:IRQ信号
  • 与协处理器模拟相关的域
    • ARMul_CPInits *CPInit[16]:16个协处理器的初始化函数
    • ARMul_CPExits *CPExit[16]:16个协处理器的退出函数
    • ARMul_LDCs *LDC[16]:16个协处理器的LDC指令函数
    • ARMul_STCs *STC[16]:16个协处理器的STC指令函数
    • ARMul_MRCs *MRC[16]:16个协处理器的MRC指令函数
    • ARMul_MCRs *MCR[16]:16个协处理器的MCR指令函数
    • ARMul_CDPs *CDP[16]:16个协处理器的CDP指令函数
    • ARMul_CPReads *CPRead[16]:16个协处理器的读CP寄存器函数
    • ARMul_CPWrites *CPWrite[16]:16个协处理器的写CP寄存器函数
    • unsigned char *CPData[16]:16个协处理器的数据指针
    • ARMword CP14R0_CCD:在xscale体系结构的CP14协处理器中,用于统计时钟周期
  • 与内存和MMU/CACHE相关的域
    • mmu_state_t mmu:mmu/cache的数据结构,在armmmu.h中定义,详解请参考"SkyEye的MMU/CACHE和Memory模拟实现"一节
    • mem_state_t mem:memory的数据结构,在armmem.h中定义,详解请参考"SkyEye的MMU/CACHE和Memory模拟实现"一节
  • 与统计相关的域
    • unsigned long NumScycles, NumNcycles, NumIcycles, NumCcycles, NumFcycles:用于统计不同状态下的周期数
    • unsigned long NumInstrs:当前执行的指令数

其它与特定CPU和开发板相关的各种io寄存器的定义放到了各个与开发板相关的文件中,如skyeye_mach_at91/ep7312/pxa/sa.c等处,详解请参考"SkyEye的开发板IO模拟实现"。

与具体开发板相关的io部分
ARMul_io mach_io;
其中ARMul_io的结构目前为

struct ARMul_io
{
	ARMword *instr; //to display the current interrupt state
	ARMword *net_flag;//to judge if network is enabled
	ARMword *net_int; //netcard interrupt
	ARMword *lcd_is_enable;   	   //turn lcd on?
	ARMword *lcd_addr_begin;   //the begining display mem addr of lcd 
	ARMword *lcd_addr_end;     //the end      display mem addr of lcd
};

instr是记录当前的中断状态
net_flag判断网络选项是否打开
net_int用来记录网络中断号
lcd_is_enable来记录LCD是否使能
lcd_addr_begin记录lcd显存的起始位置
lcd_addr_end记录显存的结束位置

7. SkyEye逻辑执行流程

了解SkEye的总体逻辑执行流程,对了解硬件的体系结构和软件/硬件的接口有较大帮助。从总体上,可把SkyEye逻辑执行流程按执行的时间顺序划分为两个阶段:

1. SkyEye加载与配置处理过程

2. SkyEye模拟执行过程

第一阶段为第二阶段的正常执行做了充分的准备,具体的执行内容包括;

  • 读入带调试信息的操作系统执行文件(由GDB完成)
  • 根据配置文件skyeye.conf的信息配置模拟硬件
  • 如果skyeye.conf中存在binary image格式文件,加载这些文件
  • 根据操作系统执行文件的内容加载调试信息(由GDB完成)
  • 根据操作系统执行文件信息加载执行文件中的代码段和数据段等(由GDB完成)
  • 执行相关模拟硬件的初始化函数

其中总的初始化函数是位于wrapper.c中的init函数,它调用如下函数完成整个模拟硬件的初始化工作:

  1. ARMul_EmulateInit:初始化与执行机器指令相关的数据ARMul_ImmedTable和ARMul_BitList
  2. ARMul_NewState:初始化结构为ARMul_State的全局变量state
  3. skyeye_option_init:初始化全局变量skyeye_config
  4. skyeye_read_config:读取配置文件skyeye.conf并根据配置文件进行相关配置
  5. nic_init:根据配置文件信息配置网络模拟环境
  6. skyeye_config.mach->mach_init(state, skyeye_config.mach):根据配置文件信息配置CPU和开发板的相关I/O函数
  7. ARMul_Reset(state):进一步初始化全局变量state,并根据配置文件信息配置MMU/CACHE和memory
  8. io_reset:初始化特定CPU和开发板的IO寄存器

第二阶段根据特定硬件的配置描述,开始执行特定硬件模拟处理。整个过程围绕CPU执行指令展开,根据模拟硬件可分为如下几个阶段:

  • CPU执行三级流水线处理,即取指令、译码、执行指令,主要处理集中在armemu.c中的ARMul_Emulate32/26函数。
  • 在执行指令过程中,如果有中断产生,CPU调整运行模式,并改变指令指向中断向量起始地址,主要处理集中在arminit.c中的函数ARMul_Abort函数、armemu.c中的ARMul_Emulate32/26函数。
  • 在执行指令过程中,如果指令是协处理器指令,则把指令转交给协处理器模拟模块进行进一步处理,主要处理集中在文件armcopro.c、xscale_copro.c等文件中。
  • 在执行指令过程中,如果发现指令是访问内存/IO的指令,则根据SkyEye模拟的特定CPU是否有MMU/CACHE分别进行处理:
    • 如果CPU有MMU/CACHE,则进入MMU/CACHE模拟模块,如果还需要内存访问,则进入memory模拟模块处理。如果访问地址属于IO地址空间,则转到特定CPU和开发板的IO模拟模块处理。
    • 如果CPU没有MMU/CACHE,则直接进入memory模拟模块处理。如果访问地址属于IO地址空间,则转到特定CPU和开发板的IO模拟模块处理。

处理访问内存/IO的指令的相关内容集中在armvirt.c;与MMU/CACHE处理、read/write buffer(用于StrongARM和XScale体系结构的模拟)处理相关的文件包括armmmu.[ch]、mmu/*.[ch];与访问 memory模拟有关的内容主要集中在armmem.[ch]中。

  • 如果要执行IO地址访问,这具体的处理过程由特定CPU和开发板IO模拟模块中的read/write_byte/halfword/word函数处理。
    • 为了模拟外设的执行,在执行指令过程的每一个周期,会执行一个io_do_cycle函数,它会调用特定CPU和开发板的IO模拟模块中的*_io_do_cycle函数,完成对时钟、网络输入输出、UART输入输出等的处理,并根据条件产生中断信号。

下一篇文章将讨论 CPU/开发板仿真。



参考资料

  • 本文节自 《源码开放的嵌入式系统软件分析与实践——基于SkyEye和ARM开发平台》一书的第三章,对 SkyEye 开源项目感兴趣的可以阅读本书。

  • SkyEye硬件模拟平台, 第一部分: SkyEye 介绍
  • SkyEye硬件模拟平台,第二部分: 安装与使用
  • 在 developerWorks Linux 专区 可以找到更多为 Linux 开发者准备的参考资料。


关于作者

 

陈渝, 清华大学,通过 [email protected] 可以和他联系。

你可能感兴趣的:(数据结构,struct,网络,IO,cache,平台)