# include <stdio.h>
# include <stdlib.h>
main ()
{
FILE *fp;
char path[80]="/afs/eos/info/ece/ece521_info/fall98/proj3/traces/";
char fname[20]="124.m88ksim.trace";
int fu_type,dest_reg,src_reg[2],N=2,i,j,k;
int *score_board,tag,time,fu_num;
int fu0,fu1,fu2,p_b=0,p_e=0,file_end=0,tag_bak;
int item,stall=0,full_sq,full_dq,stop,n_stall=0;
int D, S;
typedef struct fu_st
{ /* function unit
*/
int num;
int head;
int latency;
int pipelined;
} function_unit;
function_unit fu[3];
typedef struct register_st
{ /* register file */
int ready;
int tag;
} register_file;
register_file reg_file[128];
typedef struct dispatch_st
{ /* dispatch queue */
int tag;
int fu_type;
int dest_reg;
int src_reg[2];
int valid;
} dispatch_queue;
dispatch_queue *d_q;
typedef struct schedule_st
{ /* schedule queue */
int fu_type;
int fu_num;
int dest_reg;
int dest_tag;
int src_ready[2];
int src_tag[2];
int stage;
int valid;
} schedule_queue;
schedule_queue *s_q;
typedef struct result_st
{ /* result bus */
int tag;
int dest_reg;
int valid;
} result_bus;
result_bus *r_b;
strcat(path,fname);
printf("please input
begin and end:\n"); /* region of debug output */
scanf("%d%d",&p_b,&p_e);
printf("%s\n",fname);
for (N=2;N<=2;N++)
/* changing parameter */
for (fu0=2;fu0<=2;fu0++)
for (fu1=2;fu1<=2;fu1++)
for (fu2=2;fu2<=2;fu2++)
{
fu_num=fu0+fu1+fu2;
for (S=12;S<=12;S++)
for (D=7;D<=7;D++)
{
/* for (S=fu_num+1;S<=2*fu_num;S++)
for (D=fu_num;D<S;D++)
{*/
/* initialize */
tag=1;
/* initial counter */
time=0;
file_end=0;
stop=0;
stall=0;
fu[0].num=fu0;
/* setup function unit */
fu[1].num=fu1;
fu[2].num=fu2;
fu[0].latency=2;
fu[1].latency=1;
fu[2].latency=2;
fu[0].pipelined=1;
fu[1].pipelined=0;
fu[2].pipelined=1;
fu[0].head=0;
fu[1].head=fu[0].num;
fu[2].head=fu[0].num+fu[1].num;
d_q=(dispatch_queue *)malloc(sizeof(dispatch_queue)*D);
s_q=(schedule_queue
*)malloc(sizeof(schedule_queue)*S);
r_b=(result_bus *)malloc(sizeof(result_bus)*fu_num);
score_board=(int *)malloc(sizeof(int)*fu_num);
for (i=0;i<D;i++)
d_q[i].valid=0; /* initial dispatch
queue */
for (i=0;i<128;i++)
{
/* initial register file */
reg_file[i].ready=1;
reg_file[i].tag=0;
}
for (i=0;i<S;i++)
{
/* initial schedule queue */
s_q[i].valid=0;
s_q[i].stage=-1;
}
for (i=0;i<fu_num;i++)
r_b[i].valid=0; /* initial result bus */
fp=fopen(path,"r");
while((file_end==0)||(stop==0))
{
for
(i=0;i<fu_num;i++) score_board[i]=0;
/*
schedule unit */
tag_bak=0;
while
(tag_bak<65000) {
tag_bak=65000;
for (i=0;i<S;i++) {
/* select the smallest tag */
if ((s_q[i].valid==1)&&(s_q[i].stage==-1)&&(s_q[i].src_ready[0]==1)&&(s_q[i].src_ready[1]==1)){
if (s_q[i].dest_tag<tag_bak) {
tag_bak=s_q[i].dest_tag;
item=i;
}
}
}
if (tag_bak<65000) {
/* try to fire it */
i=item;
for (j=fu[s_q[i].fu_type].head;j<fu[s_q[i].fu_type].head+fu[s_q[i].fu_type].num;j++)
{
if (score_board[j]==0) {
score_board[j]=1;
s_q[i].stage=-10;
s_q[i].fu_num=j;
break;
}
}
if (s_q[i].stage==-1) {
tag_bak=65000;
n_stall++;
}
}
}
/*
dispatch unit */
tag_bak=0;
while
(tag_bak<65000) {
tag_bak=65000;
for (i=0;i<D;i++) {
/* select the smallest tag */
if (d_q[i].valid==1) {
if (d_q[i].tag<tag_bak) {
tag_bak=d_q[i].tag;
item=i;
}
}
}
if (tag_bak<65000) {
/* try to issue it */
i=item;
for (j=0;j<S;j++) {
if (s_q[j].valid==0) {
s_q[j].fu_type=d_q[i].fu_type;
s_q[j].dest_reg=d_q[i].dest_reg;
for (k=0;k<2;k++) {
if (reg_file[d_q[i].src_reg[k]].ready==1) {
s_q[j].src_ready[k]=1;
s_q[j].src_tag[k]=reg_file[d_q[i].src_reg[k]].tag;
if (s_q[j].src_tag[k]<0)
s_q[j].src_tag[k]=0;
}
else {
s_q[j].src_tag[k]=reg_file[d_q[i].src_reg[k]].tag;
s_q[j].src_ready[k]=0;
}
}
reg_file[d_q[i].dest_reg].tag=d_q[i].tag;
s_q[j].dest_tag=d_q[i].tag;
reg_file[d_q[i].dest_reg].ready=0;
d_q[i].valid=0;
s_q[j].valid=2;
break;
}
}
if (d_q[i].valid==1) {
tag_bak=65000;
n_stall++;
}
}
}
/* fetch/decode unit */
if ((stall==0)&&(file_end==0)) {
for (i=0;i<N;i++) {
/* try to fetch up to N insts*/
for (j=0;j<D;j++) {
if (d_q[j].valid==0) {
if (fscanf(fp,"%d%d%d%d\n",&fu_type,&dest_reg,&src_reg[0],&src_reg[1])<0)
{
file_end=1;
time--;
tag--;
break;
}
d_q[j].tag=tag++;
d_q[j].fu_type=fu_type;
d_q[j].dest_reg=dest_reg;
d_q[j].src_reg[0]=src_reg[0];
d_q[j].src_reg[1]=src_reg[1];
d_q[j].valid=2;
break;
}
}
if (file_end==1) break;
}
}
full_sq=1;
full_dq=1;
stall=0;
for (i=0;i<S;i++) if (s_q[i].valid==0) full_sq=0;
for (i=0;i<D;i++) if (d_q[i].valid==0) full_dq=0;
if ((full_sq==1)&&(full_dq==1)) {
stall=1;
n_stall++;
}
/* execute unit */
stop=1;
for (i=0;i<S;i++) {
/* search the whole sch. queue */
if (s_q[i].valid==1) {
stop=0;
if (s_q[i].stage>=0) s_q[i].stage++;
if (s_q[i].stage==fu[s_q[i].fu_type].latency+1)
if (s_q[i].dest_tag==reg_file[s_q[i].dest_reg].tag)
reg_file[s_q[i].dest_reg].ready=1;
if (s_q[i].stage==fu[s_q[i].fu_type].latency+1) {
r_b[s_q[i].fu_num].tag=s_q[i].dest_tag;
r_b[s_q[i].fu_num].dest_reg=s_q[i].dest_reg;
r_b[s_q[i].fu_num].valid=1;
score_board[s_q[i].fu_num]=0;
s_q[i].valid=0;
s_q[i].stage=-1;
}
}
}
/* state update */
for (i=0;i<D;i++) if (d_q[i].valid==2) d_q[i].valid=1;
for (i=0;i<S;i++) {
if (s_q[i].valid==2) s_q[i].valid=1;
if (s_q[i].stage==-10) s_q[i].stage=0;
for (j=0;j<2;j++) {
for (k=0;k<fu_num;k++) {
if ((r_b[k].tag==s_q[i].src_tag[j])&&(r_b[k].valid==1)) {
s_q[i].src_ready[j]=1;
}
}
}
}
if ((file_end==1)&&(stop==1)) break;
/* simulation complete */
/* debug output */
/* empty entries skipped */
time++;
if ((time>=p_b)&&(time<=p_e)) {
printf("--- machine state at clock %d ---\n",time);
printf("dispatch queue:\n");
for (i=0;i<D;i++) {
if (d_q[i].valid!=1) continue;
printf("\tI%d:%d|%2d=%2d#%2d\n",d_q[i].tag,d_q[i].fu_type,d_q[i].dest_reg,d_q[i].src_reg[0],d_q[i].src_reg[1]);
}
printf("scoreboard:\n");
for (i=0;i<fu_num;i++) {
if (score_board[i]==0) continue;
printf("\tFU%2d\tbusy\n",i);
}
printf("register file:\n");
for (i=0;i<128;i++) {
if ((reg_file[i].ready==1)&&(reg_file[i].tag==0)) continue;
if (reg_file[i].ready==0)
printf("\tR%2d:\tNR/tag%d\n",i,reg_file[i].tag);
else
printf("\tR%2d:\t R/tag%d\n",i,reg_file[i].tag);
}
printf("schedule queue:\n");
for (i=0;i<S;i++) {
if (s_q[i].valid!=1) continue;
if (s_q[i].stage>=0)
printf("\tDR:%2d/tag %d\tSR0:%s/tag%d\tSR1:%s/tag %d\tt= %d|FU=\
%2d[%d]\n",s_q[i].dest_reg,s_q[i].dest_tag,s_q[i].src_ready[0]==1?"\
R":"NR",s_q[i].src_tag[0],s_q[i].src_ready[1]==1?"\
R":"NR",s_q[i].src_tag[1],s_q[i].stage,s_q[i].fu_num,s_q[i].fu_type);
else
printf("\tDR:%2d/tag %d\tSR0:%s/tag\
%d\tSR1:%s/tag %d\n",s_q[i].dest_reg,s_q[i].dest_tag,s_q[i].src_ready[0]==1?"\
R":"NR",s_q[i].src_tag[0],s_q[i].src_ready[1]==1?" R":"NR",s_q[i].src_tag[1]);
}
printf("result bus:\n");
for (i=0;i<fu_num;i++) {
if (r_b[i].valid!=1) continue;
printf("\tDR:%2d/tag %d\n",r_b[i].dest_reg,r_b[i].tag);
}
printf("\n");
}
for (i=0;i<fu_num;i++) r_b[i].valid=0;
}
/* statistics
output */
printf("(N=%d,FU0=%d,FU1=%d,FU2=%d,D=%d,S=%d)
%s\n",N,fu0,fu1,fu2,D,S,fname);
printf("total:\t%d\n",tag);
printf("dispatched:\t%d\n",tag);
printf("fired:\t%d\n",tag);
printf("completed:\t%d\n",tag);
printf("cycles:\t%d\n",time);
printf("stalls:\t%d\n",n_stall);
printf("fired
per cycle:\t%f\n",1.0*tag/time);
printf("completed
per cycle:\t%f\n",1.0*tag/time);
printf("IPC:\t%f\n",1.0*tag/time);
printf("\n\n");
free(d_q);
free(s_q);
free(r_b);
free(score_board);
fclose(fp);
}
}
}