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函数,它调用如下函数完成整个模拟硬件的初始化工作:
ARMul_EmulateInit:初始化与执行机器指令相关的数据ARMul_ImmedTable和ARMul_BitList
ARMul_NewState:初始化结构为ARMul_State的全局变量state
skyeye_option_init:初始化全局变量skyeye_config
skyeye_read_config:读取配置文件skyeye.conf并根据配置文件进行相关配置
nic_init:根据配置文件信息配置网络模拟环境
skyeye_config.mach->mach_init(state, skyeye_config.mach):根据配置文件信息配置CPU和开发板的相关I/O函数
ARMul_Reset(state):进一步初始化全局变量state,并根据配置文件信息配置MMU/CACHE和memory
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输入输出等的处理,并根据条件产生中断信号。