📄 skyeye硬件模拟平台,第三部分 硬件仿真实现之三.htm
字号:
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>
typedef struct wb_entry_s{
ARMword pa; //phy_addr
ARMbyte *data;//data
int nb; //number byte to write
}wb_entry_t;
typedef struct wb_s{
int num; //wb_entry_t的总数
int nb; //wb_entry_t中最大字节数
int first; //循环队列头
int last; //循环队列尾
int used; //循环队列中已用wb_entry_t的个数
wb_entry_t *entrys;
}wb_t;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>接口函数</P><A name=IDAEYPTB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>
/*初始化和释放*/
int mmu_wb_init(wb_t *wb_t, int num, int nb);
void mmu_wb_exit(wb_t *wb);
/*数据入Write Buffer*/
void mmu_wb_write_bytess(ARMul_State *state, wb_t *wb_t, ARMword pa,
ARMbyte *data, int n);
/*将Write Buffer中数据全部写入内存*/
void mmu_wb_drain_all(ARMul_State *state, wb_t *wb_t);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>Read Buffer的实现(mmu/rb.[hc])</P>
<P>数据结构</P><A name=IDANYPTB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>
typedef struct rb_entry_s{
ARMword data[RB_WORD_NUM];//array to store data
ARMword va; //first word va
int type; //rb type
fault_t fault; //fault set by rb alloc
}rb_entry_t;
typedef struct rb_s{
int num;
rb_entry_t *entrys;
}rb_t;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>接口函数</P><A name=IDAVYPTB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>
/*初始化和释放*/
int mmu_rb_init(rb_t *rb_t, int num);
void mmu_rb_exit(rb_t *rb_t);
rb_entry_t *mmu_rb_search(rb_t *rb_t, ARMword va);/*查找*/
void mmu_rb_invalidate_entry(rb_t *rb_t, int i);/*无效*/
void mmu_rb_invalidate_all(rb_t *rb_t);
void mmu_rb_load(ARMul_State *state, rb_t *rb_t, int i_rb, int type, ARMword va);/*装入*/
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=IDA2YPTB><SPAN class=atitle3>5.
与具体CPU类型相关的MMU模拟子模块</SPAN></A><BR>与具体CPU类型相关的MMU模拟子模块建立在与具体CPU无关的MMU模拟实现子模块的基础上,通过实现具体CPU的mmu_ops_t,完成具体CPU的MMU模拟。以下详细介绍StrongARM的MMU实现。</P>
<P><A name=IDACZPTB><SPAN class=atitle3>6. StrongARM
MMU的组成结构</SPAN></A><BR>StrongARM的MMU分成指令和数据两部分。指令部分包括一个指令TLB和一个指令CACHE,数据部分包括一个数据TLB,两个数据CACHE(main
CACHE和 mini CACHE),一个Write Buffer和一个Read Buffer。如图 0 3所示:</P>
<P><A name=IDAJZPTB><B>图 0-3 StrongARM数据访问功能部件图</B></A><BR><IMG height=305
alt="图 0-3 StrongARM数据访问功能部件图"
src="SkyEye硬件模拟平台,第三部分 硬件仿真实现之三.files/image005.gif" width=435 border=0
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></P>
<P><A name=IDAWZPTB><SPAN class=atitle3>7. StrongARM
mmu_ops_t的实现</SPAN></A><BR></P><A name=IDA1ZPTB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>
mmu_ops_t sa_mmu_ops = {
sa_mmu_init,
sa_mmu_exit,
sa_mmu_read_byte,
sa_mmu_write_byte,
sa_mmu_read_halfword,
sa_mmu_write_halfword,
sa_mmu_read_word,
sa_mmu_write_word,
sa_mmu_load_instr,
sa_mmu_mcr,
sa_mmu_mrc,
};
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>SA MMU的初始化</P><A name=IDAD0PTB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>
typedef struct sa_mmu_desc_s{
int i_tlb;
cache_desc_t i_cache;
int d_tlb;
cache_desc_t main_d_cache;
cache_desc_t mini_d_cache;
int rb;
wb_desc_t wb;
}sa_mmu_desc_t;
static sa_mmu_desc_t sa11xx_mmu_desc ={
32,
{32, 32, 16, CACHE_WRITE_BACK},
32,
{32, 32, 8, CACHE_WRITE_BACK},
{32, 2, 8, CACHE_WRITE_BACK},
4,
{8, 16}
};
typedef struct sa_mmu_s{
/*指令部分*/
tlb_t i_tlb; /*指令tlb*/
cache_t i_cache; /*指令cache*/
/*数据部分*/
tlb_t d_tlb; /*数据tlb*/
cache_t main_d_cache;/*main cache*/
cache_t mini_d_cache;/*mini cache*/
rb_t rb_t; /*Read Buffer*/
wb_t wb_t; /*Write Buffer*/
}sa_mmu_t;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>int sa_mmu_init(ARMul_State *state);<BR
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">sa_mmu_desc_t 是SA
MMU参数描述的数据结构,sa_mmu_t实现SA MMU
的数据表示。sa_mmu_init根据sa11xx_mmu_desc,完成对state->u.sa_mmu的初始化。</P>
<P>SA MMU的数据读操作</P><A name=IDAP0PTB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>
static fault_t
sa_mmu_read(ARMul_State *state, ARMword va, ARMword *data, ARMword datatype)
{
fault_t fault;
rb_entry_t *rb;
tlb_entry_t *tlb;
cache_line_t *cache;
ARMword pa, real_va,temp,offset;
/*根据CP15 process id register转换地址*/
va = mmu_pid_va_map(va);
real_va=va;
if (MMU_Disabled){
/*如果MMU关闭,直接从内存读取*/
if (datatype==ARM_BYTE_TYPE)
*data = mem_read_byte(state, va);
else if (datatype==ARM_HALFWORD_TYPE)
*data = mem_read_halfword(state, va);
else if (datatype==ARM_WORD_TYPE)
*data = mem_read_word(state, va);
else {
printf("SKYEYE:1 sa_mmu_read error: unknown data type %d\n",datatype);
exit(-1);
}
return 0;
}
/*align 异常检查*/
if (((va & 3 ) && (datatype==ARM_WORD_TYPE) && MMU_Aligned) || \
((va & 1 ) && (datatype==ARM_HALFWORD_TYPE) && MMU_Aligned) ){
d_msg("align\n");
return ALIGNMENT_FAULT;
} // else
va &= ~(WORD_SIZE - 1);
/*TTW得到tlb*/
fault = translate(state, va, D_TLB(), &tlb);
if (fault){
d_msg("translate\n");
return fault;
}
/*访问控制检查*/
fault = check_access(state, va, tlb, 1);
if (fault)
return fault;
/*首先在Read Buffer中查找数据*/
rb = mmu_rb_search(RB(), va);
if (rb){
if (rb->fault)
return rb->fault;
*data = rb->data[(va & (rb_masks[rb->type]-1))>>WORD_SHT];
goto datatrans;
//return 0;
};
/*其次查找main cache*/
cache = mmu_cache_search(state, MAIN_D_CACHE(), va);
if (cache){
*data = cache->data[va_cache_index(va, MAIN_D_CACHE())];
goto datatrans;
//return 0;
}
/*最后查找mini cache*/
cache = mmu_cache_search(state, MINI_D_CACHE(), va);
if (cache){
*data = cache->data[va_cache_index(va, MINI_D_CACHE())];
goto datatrans;
//return 0;
}
/*计算物理地址*/
pa = tlb_va_to_pa(tlb, va);
/*如果在[0xe0000000, 0xe8000000]区间,执行mmu_cache_soft_flush*/
if ((pa >= 0xe0000000) && (pa < 0xe8000000)){
if (tlb_c_flag(tlb)){
if (tlb_b_flag(tlb)){
mmu_cache_soft_flush(state, MAIN_D_CACHE(), pa);
}else{
mmu_cache_soft_flush(state, MINI_D_CACHE(), pa);
}
}
return 0;
}
/*如果B=1,必须先清空Write Buffer*/
if (tlb_b_flag(tlb))
mmu_wb_drain_all(state, WB());
if (tlb_c_flag(tlb) && MMU_DCacheEnabled){
/*如果C=1,并且Data Cache开启,将数据读入Cache*/
cache_t *cache_t;
if (tlb_b_flag(tlb))
cache_t = MAIN_D_CACHE();
else
cache_t = MINI_D_CACHE();
cache = mmu_cache_alloc(state, cache_t, va, pa);
*data = cache->data[va_cache_index(va, cache_t)];
}else{
/*直接从内存读取*/
if (datatype==ARM_BYTE_TYPE)
*data = mem_read_byte(state, pa|(real_va&3));
else if (datatype==ARM_HALFWORD_TYPE)
*data = mem_read_halfword(state,
pa|(real_va&2));
else if (datatype==ARM_WORD_TYPE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -