实验3SimpleScalar与程序优化.docx
《实验3SimpleScalar与程序优化.docx》由会员分享,可在线阅读,更多相关《实验3SimpleScalar与程序优化.docx(11页珍藏版)》请在冰点文库上搜索。
实验3SimpleScalar与程序优化
实验3--SimpleScalar与程序优化
实验3SimpleScalar与程序优化
201208010218路志桐计科二班
1、简介:
SimpleScalar是上世纪由威斯康辛大学发布的一款开源模拟器,具备良好的可移植性和可扩展性。
作为一款时钟精确的模拟器,SimpleScalar采用执行驱动方式模拟,包含功能模拟和性能模拟。
SimpleScalar的指令集架构采用C语言宏声明,目前3.0版本主要支持PISA指令集和Alpha指令集。
根据模拟的目的不同,SimpleScalar包含多个模拟器实体,从最简单的Sim-fast到最为复杂的Sim-outorder,可分别用于功能模拟、Cache配置策略、流水线、前瞻预测等体系结构问题的全面研究。
2、安装:
1、首先从官网上下载相关的文件:
Simpletools-2v0.tgz;
Simplesim-3v0e.tar.gz;
Simpleutils-990811.tar.gz;
Gcc-2.7.2.3.ss_.tar.gz;
2、然后安装flex,build-essential
$sudoapt-getinstallflex;
$sudoapt-getinstallbuild-essential;
本来还需要bison的,不过之前安装过了,略过。
另外除此之外我们还需要配置一下环境变量
安装目录:
$exportIDIR=/home/my/simplescalar
设置主机:
$exportHOST=i686-pc-linux
设置目的机器成小字段机器:
$exportTARGET=sslittle-na-sstrix
3、设置完环境之后我们便可以安装simpletools了
进入到目的地址后,我们用tarxzvf命令将之前下载下来的simpletools解压;
由于simplescalar需要Gcc2.7以上版本支持,所以我们需要通过rm命令移除原先电脑自带的Gcc。
$cd$IDIR
$tarxzvfsimpletools-2v0.tgz$rm-rfgcc-2.6.3
4、其次是simpleutils
$tarxzvfsimpleutils-990811.tar.gz
$cdsimpleutils-990811
然后编译前要打开simpleutils-990811/ld下的文件ldlex.l并且将里面全部的yy_current_buffer替换成大写,否则代码将会报错。
然后就可以进行编译
$./configure-host=$HOST-target=$TARGET-with-gnu-as-with-gnu-ld-prefix=$IDIR
$make
$makeinstall
5、接下来安装simplesim3.0
$cd$IDIR
$tarxzvfsimplesim-3v0e.tgz
$cdsimplesim-3.0
$makeconfig-alpha
$make
6、最后安装gcc2.7编译器套件
$cd$IDIR
$tarxzvfgcc-2.7.2.3.ss.tar.gz
$cdgcc-2.7.2.3
$exportPATH=$PATH:
/home/YOUR_USER_NAME/simplescalar/sslittle-na-sstrix/bin
$./configure-host=$HOST-target=$TARGET-with-gnu-as-with-gnu-ld-prefix=$IDIR
这里面有好几处代码需要修改,我们一一修改了相应的代码
!
修改代码:
./Makefile
Line130:
增加-I/usr/include或-I./include——>-I/usr/include
!
修改代码:
./protoize.c
$sudochmod+wprotoize.c!
修改权限
#include–>#include
!
修改代码:
./obstack.h
$sudochmod+wobstack.h!
修改权限
*((void**)__o->next_free)++=((void*)datum);—–>
*((void**)__o->next_free++)=((void*)datum);
!
复制补丁文件
$cp./patched/sys/cdefs.h../sslittle-na-sstrix/include/sys/cdefs.h
$cp../sslittle-na-sstrix/lib/libc.a../lib/
$cp../sslittle-na-sstrix/lib/crt0.o../lib/
!
解压ar-ranlib.tar.gz到$IDIR/sslittle-na-sstrix/bin
!
修改ar及ranlib的权限
$sudochmod+warranlib
$sudochmod+xarranlib
$cd$IDIR/gcc-2.7.2.3
$make
!
修改代码:
./insn-output.c
Line675/750/823:
末尾增加“\”
$make
!
修改代码:
./objc/sendmsg.c
$sudochmod+wobjc/sendmsg.c!
修改权限
Line35:
增加#defineSTRUCT_VALUE0
$makeLANGUAGES="cc++"CFLAGS="-O"CC="gcc"
!
若出错,修改./cxxmain.c,删掉2978-2979行,即:
char*malloc();
char*realloc();
!
若无cxxmain,返回上文./Makefile确认修改,再继续重复流程
$makeLANGUAGES="cc++"CFLAGS="-O"CC="gcc"
$makeinstallLANGUAGES="cc++"CFLAGS="-O"CC="gcc"
最后安装完成之后随意写一个C语言代码进行测试。
用如下命令编译$IDIR/bin/sslittle-na-sstrix-gcc-o11.c
然后运行$IDIR/simplesim-3.0/sim-safe1
发现可以运行,安装成功
3、代码优化:
比较各种分支预测技术的性能
SimpleScalar分支预测的实现方法是:
先确定是否采取分支,即进行分支方向探测,然后是生成分支地址,对于调用返回指令,就在RAS上直接作相关操作,普通分支指令则需要利用BTB来地址探测,如果命中的话则生成地址。
然后对两步进行综合,地址命中且分支预测为采取,返回分支目标地址;地址不命中且分支预测为采取,返回1;只要分支预测为不采取,就返回0。
包括在仿真器上运行的三个程序的结果统计数据表格,以及对各种分支预测方法的对比分析。
每一列对应的运行参数分别为:
(1)test-math
./sim-bpred-bpredtakentests/bin.little/test-math
./sim-bpred-bprednottakentests/bin.little/test-math
./sim-bpred-bpredbimod-bpred:
bimod512tests/bin.little/test-math
./sim-bpred-bpredbimod-bpred:
bimod1024tests/bin.little/test-math
./sim-bpred-bpred2lev-bpred:
2lev11024801tests/bin.little/test-math
./sim-bpred-bpred2lev-bpred:
2lev16461tests/bin.little/test-math
./sim-bpred-bpredcomb-bpred:
comb1024-bpred:
2lev1102480-bpred:
bimod1024tests/bin.little/test-math
alwaystaken
alwaysnottaken
bimod
(512)
bimod
(1024)
2-level
(1,1024,8,0)
2-level
(1,64,6,1)
comb
(1024)
(1,1024,8,0)
(1024)
sim_total_insn
213688
213688
213688
213688
213688
213688
213688
sim_total_refs
56897
56897
56897
56897
56897
56897
56897
sim_num_branches
38591
38591
38591
38591
38591
38591
38591
sim_elapsed_time
1
1
1
1
1
1
1
sim_inst_rate
213688
213688
213688
213688
213688
213688
213688
sim_IPB
5.5372
5.5372
5.5372
5.5372
5.5372
5.5372
5.5372
bpred_bimod.lookups
38591
38591
38591
38591
38591
38591
38591
bpred_bimod.updates
38591
38591
38591
38591
38591
38591
38591
bpred_bimod.addr_hits
25661
21938
33692
34237
34242
27844
35570
bpred_bimod.dir_hits
25661
21938
34195
34732
34794
28387
36011
bpred_bimod.misses
12930
16653
4396
3859
3797
10204
2580
bpred_bimod.jr_hits
3543
3543
3528
3528
3528
3528
3528
bpred_bimod.jr_seen
3543
3543
3543
3543
3543
3543
3543
bpred_bimod.jr_non_ras_hits.PP
3543
3543
28
28
28
28
28
bpred_bimod.jr_non_ras_seen.PP
3543
3543
41
41
41
41
41
bpred_bimod.bpred_addr_rate
0.6649
0.5685
0.8731
0.8872
0.8873
0.7215
0.9217
bpred_bimod.bpred_dir_rate
0.6649
0.5685
0.8861
0.9000
0.9016
0.7356
0.9331
bpred_bimod.bpred_jr_rate
1.0000
1.0000
0.9958
0.9958
0.9958
0.9985
0.9958
bpred_bimod.bpred_jr_non_ras_rate.PP
1.0000
1.0000
0.6829
0.6829
0.6829
0.6829
0.6829
bpred_bimod.retstack_pushes
0
0
3504
3504
3504
3504
3504
bpred_bimod.retstack_pops
0
0
3502
3502
3502
3502
3502
bpred_bimod.used_ras.PP
0
0
3502
3502
3502
3502
3502
bpred_bimod.ras_hits.PP
0
0
3500
3500
3500
3500
3500
bpred_bimod.ras_rate.PP
Error:
dividebyzero
Error:
dividbyzero
0.9994
0.9994
0.9994
0.9994
0.9994
根据得到的统计数据得知,在上述的分支预测器配置中,复合式的地址预测命中率与分支方向预测命中率最高。
代码分析
在sim-bpred.c中检查了输入的动态预测方法选项,并创建了相应的分支预测器。
sim_check_options(structopt_odb_t*odb,intargc,char**argv)函数中:
if(!
mystricmp(pred_type,"taken"))
{//创建预测器实例
bpred=bpred_create(BPredTaken,0,0,0,0,0,0,0,0,0);
}
在sim_main函数中:
while(TRUE)
{
regs.regs_R[MD_REG_ZERO]=0;
#ifdefTARGET_ALPHA
regs.regs_F.d[MD_REG_ZERO]=0.0;
#endif
/*获取下一条指令*/
MD_FETCH_INST(inst,mem,regs.regs_PC);
/*指令计数*/
sim_num_insn++;
/*setdefaultreferenceaddressandaccessmode*/
addr=0;is_write=FALSE;
/*setdefaultfault-none*/
fault=md_fault_none;
/*对指令译码*/
MD_SET_OPCODE(op,inst);
/*执行指令*/
switch(op)
{
#defineDEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3) \
caseOP:
\
SYMCAT(OP,_IMPL); \
break;
#defineDEFLINK(OP,MSK,NAME,MASK,SHIFT) \
caseOP:
\
panic("attemptedtoexecutealinkingopcode");
#defineCONNECT(OP)
#defineDECLARE_FAULT(FAULT) \
{fault=(FAULT);break;}
#include"machine.def"
default:
panic("attemptedtoexecuteabogusopcode");
}
if(fault!
=md_fault_none)
fatal("fault(%d)detected@0x%08p",fault,regs.regs_PC);
if(MD_OP_FLAGS(op)&F_MEM)
{
sim_num_refs++;
if(MD_OP_FLAGS(op)&F_STORE)
is_write=TRUE;
}
if(MD_OP_FLAGS(op)&F_CTRL)
{
md_addr_tpred_PC;
structbpred_update_tupdate_rec;
sim_num_branches++;
if(pred)//如果分支预测器创建成功
{
/*获取预测的下条指令的地址*/
pred_PC=bpred_lookup(pred,
/*分支地址*/regs.regs_PC,
/*目的地址*/target_PC,
/*指令操作码*/op,
/*call?
*/MD_IS_CALL(op),
/*return?
*/MD_IS_RETURN(op),
/*stashanupdateptr*/&update_rec,
/*stashreturnstackptr*/&stack_idx);
/*判断从分支预测器返回的下条指令地址是否合法*/
if(!
pred_PC)//不合法,(当返回0时,表示采用分支不转移预测)
{
/*分支不转移,pc直接加一*/
pred_PC=regs.regs_PC+sizeof(md_inst_t);
}
/*根据指令执行的实际结果,来更新分支预测器*/
bpred_update(pred,
/*分支地址*/regs.regs_PC,
/*resolvedbranchtarget*/regs.regs_NPC,
/*分支是否转移*/regs.regs_NPC!
=(regs.regs_PC+
sizeof(md_inst_t)),
/*predtaken?
*/pred_PC!
=(regs.regs_PC+
sizeof(md_inst_t)),
/*correctpred?
*/pred_PC==regs.regs_NPC,
/*opcode*/op,
/*predictorupdatepointer*/&update_rec);
}
}
/*checkforDLitedebuggerentrycondition*/
if(dlite_check_break(regs.regs_NPC,
is_write?
ACCESS_WRITE:
ACCESS_READ,
addr,sim_num_insn,sim_num_insn))
dlite_main(regs.regs_PC,regs.regs_NPC,sim_num_insn,®s,mem);
/*gotothenextinstruction*/
regs.regs_PC=regs.regs_NPC;
regs.regs_NPC+=sizeof(md_inst_t);
/*finishearly?
*/
if(max_insts&&sim_num_insn>=max_insts)
return;
}