CPU: Added support for requiring multiple clock cycles for different instruction in the execution unit and updated the gui/internals tab accordingly

This commit is contained in:
(Tim) Efthimis Kritikos 2024-03-06 02:37:55 +00:00
parent 8dc7a27cdb
commit c59791e7e2
3 changed files with 381 additions and 197 deletions

166
cpu.c
View File

@ -8,18 +8,33 @@
struct fetch_data_t *malloc_fetch_data(){
struct fetch_data_t *ret=malloc(sizeof(struct fetch_data_t));
ret->wait_for_exec=0;
ret->exec_done=1;
ret->decode_done=1;
ret->fetch_wait=0;
return ret;
}
void free_fetch_data(struct fetch_data_t *tofree){
free(tofree);
}
int fetch(struct simdata_t *simdata){
free_instr_list(&simdata->cpu_gui_hints->fetching_list);
if(simdata->fetch_data->wait_for_exec!=0){
simdata->fetch_data->fetch_wait=1;
simdata->decode_data->valid=0;
simdata->fetch_data->wait_for_exec--;
simdata->fetch_data->wait_for_exec=0;
return 0;
}
if(simdata->fetch_data->fetch_wait){
if(simdata->fetch_data->exec_done){
simdata->fetch_data->fetch_wait=0;
}else
return 0;
}
if(!simdata->fetch_data->decode_done)
return 0;
simdata->decode_data->in_bytecode=(uint32_t)(simdata->RAM[simdata->registers->PC])<<24|(uint32_t)(simdata->RAM[simdata->registers->PC+1])<<16|(uint32_t)(simdata->RAM[simdata->registers->PC+2])<<8|(uint32_t)(simdata->RAM[simdata->registers->PC+3]);
simdata->decode_data->valid=1;
simdata->decode_data->address=simdata->registers->PC;
@ -35,6 +50,7 @@ struct decode_data_t *malloc_decode_data(){
struct decode_data_t *ret=malloc(sizeof(struct decode_data_t));
if(ret)
ret->valid=0;
ret->exec_done=1;
return ret;
}
void free_decode_data(struct decode_data_t *tofree){
@ -43,8 +59,13 @@ void free_decode_data(struct decode_data_t *tofree){
int decode(struct simdata_t *simdata){
uint16_t opcode,op1,op2,imm;
free_instr_list(&simdata->cpu_gui_hints->decoding_list);
if(simdata->decode_data->exec_done==0){
simdata->fetch_data->decode_done=0;
return 0;
}
if(simdata->decode_data->valid==0){
simdata->exec_data->valid=0;
simdata->fetch_data->decode_done=1;
return 0;
}
switch((simdata->decode_data->in_bytecode&0xE0000000)>>29){
@ -234,6 +255,7 @@ int decode(struct simdata_t *simdata){
default:
return 1;
}
simdata->fetch_data->decode_done=1;
simdata->exec_data->valid=1;
simdata->exec_data->address=simdata->decode_data->address;
add_to_instr_list(&simdata->cpu_gui_hints->decoding_list,simdata->decode_data->address);
@ -267,6 +289,7 @@ struct exec_data_t *malloc_exec_data(){
return 0;
}
ret->valid=0;
ret->cycles_left=0;
return ret;
}
void free_exec_data(struct exec_data_t *tofree){
@ -275,8 +298,41 @@ void free_exec_data(struct exec_data_t *tofree){
free(tofree->out_op);
free(tofree);
}
#define RR_SIMPL_INDX 0
#define RR_COMPLX_INDX 1
#define RR_FCOMPLX_INDX 2
#define MEM_ACCS_INDX 3
#define IMM_LOAD_INDX 4
#define BRNCH_MISS_INDX 5
#define BRNCH_TAKN_INDX 6
#define BRNCH_UNCO_INDX 7
#define CALL_RET_INDX 8
#define RR_FTRI_INDX 9
#define RR_MOVE_INDX 10
int delay_values[]={
1, // register-register (integer) add,sub,inc,dec,shift left/right float add,sub
4, // register-register integer multiply, divide
4, // register-register float multiply, divide
2, // push / pop / read mem / write mem
1, // immediate to register
1, // branch not taken
3, // branch taken
3, // branch unconditional
4, // call/ret
4, // float sin/cos
1 // register-register move
};
int exec(struct simdata_t *simdata){
free_instr_list(&simdata->cpu_gui_hints->executing_list);
if(simdata->exec_data->valid==1){
simdata->fetch_data->exec_done=0;
simdata->decode_data->exec_done=0;
}
if(simdata->exec_data->cycles_left==0){
if(simdata->exec_data->valid==0)
return 0;
int condition=0;
@ -290,6 +346,17 @@ int exec(struct simdata_t *simdata){
case COND_CARRY: condition=simdata->registers->FLAGS&2; break;
case COND_NCARRY: condition=!(simdata->registers->FLAGS&2); break;
}
switch(simdata->exec_data->COND){
case COND_NONE:
simdata->exec_data->cycles_left=delay_values[BRNCH_UNCO_INDX];
break;
default:
if(condition)
simdata->exec_data->cycles_left=delay_values[BRNCH_TAKN_INDX];
else
simdata->exec_data->cycles_left=delay_values[BRNCH_MISS_INDX];
break;
}
if(condition){
if(simdata->exec_data->EXEC_ACTION==CALL){
*(uint32_t*)(simdata->RAM+simdata->registers->SP)=simdata->registers->PC;
@ -302,6 +369,7 @@ int exec(struct simdata_t *simdata){
}
break;
case RET:
simdata->exec_data->cycles_left=delay_values[CALL_RET_INDX];
simdata->registers->SP-=4;
simdata->registers->PC=simdata->RAM[simdata->registers->SP];
break;
@ -317,6 +385,9 @@ int exec(struct simdata_t *simdata){
simdata->registers->GPR[simdata->exec_data->in_op2->data];
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)|
(simdata->registers->GPR[simdata->exec_data->out_op->data] < simdata->registers->GPR[simdata->exec_data->in_op1->data])<<1;
simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX];
break;
case ALU_SUB:
case ALU_CMP:
@ -324,48 +395,81 @@ int exec(struct simdata_t *simdata){
simdata->registers->GPR[simdata->exec_data->in_op1->data];
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)|
(simdata->registers->GPR[simdata->exec_data->out_op->data] > simdata->registers->GPR[simdata->exec_data->in_op1->data])<<1;
simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX];
break;
case ALU_SL:
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)|
((simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x80000000)?2:0);
result = simdata->registers->GPR[simdata->exec_data->in_op1->data]<<1;
simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX];
break;
case ALU_SR:
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)|
((simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x00000001)?2:0);
result = simdata->registers->GPR[simdata->exec_data->in_op1->data]>>1;
simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX];
break;
case ALU_FDIV:
result = ieee754_float_to_uint32(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op2->data])/
uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data]));
simdata->exec_data->cycles_left=delay_values[RR_COMPLX_INDX];
break;
case ALU_FMUL:
result = ieee754_float_to_uint32(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data])*
uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op2->data]));
simdata->exec_data->cycles_left=delay_values[RR_COMPLX_INDX];
break;
case ALU_FADD:
result = ieee754_float_to_uint32(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op2->data])+
uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data]));
simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX];
break;
case ALU_FSUB:
result = ieee754_float_to_uint32(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op2->data])-
uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data]));
simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX];
break;
case ALU_FSIN:
result = ieee754_float_to_uint32(sinf(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data])));
simdata->exec_data->cycles_left=delay_values[RR_FTRI_INDX];
break;
case ALU_FCOS:
result = ieee754_float_to_uint32(cosf(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data])));
simdata->exec_data->cycles_left=delay_values[RR_FTRI_INDX];
break;
case ALU_DEC:
*(uint32_t*)&result = *(uint32_t*)(&simdata->registers->GPR[simdata->exec_data->in_op1->data])-1;
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)|
(simdata->registers->GPR[simdata->exec_data->out_op->data] > simdata->registers->GPR[simdata->exec_data->in_op1->data])<<1;
simdata->exec_data->cycles_left=delay_values[RR_FCOMPLX_INDX];
break;
case ALU_INC:
*(uint32_t*)&result = *(uint32_t*)(&simdata->registers->GPR[simdata->exec_data->in_op1->data])+1;
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)|
(simdata->registers->GPR[simdata->exec_data->out_op->data] > simdata->registers->GPR[simdata->exec_data->in_op1->data])<<1;
simdata->exec_data->cycles_left=delay_values[RR_SIMPL_INDX];
break;
default:
return 1;
@ -379,20 +483,28 @@ int exec(struct simdata_t *simdata){
case MOVE:
switch(simdata->exec_data->out_op->OP_ADDR){
case REGISTERL:
if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE)
if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE){
simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0xFFFF0000)|(0x0000FFFF&
simdata->exec_data->in_op1->data);
else
simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0xFFFF0000)|(0x0000FFFF&
simdata->registers->GPR[simdata->exec_data->in_op1->data]);
simdata->exec_data->cycles_left=delay_values[IMM_LOAD_INDX];
}else{
//simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0xFFFF0000)|(0x0000FFFF&
// simdata->registers->GPR[simdata->exec_data->in_op1->data]);
//simdata->exec_data->cycles_left=
return 1;
}
break;
case REGISTERH:
if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE)
if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE){
simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0x0000FFFF)|((0x0000FFFF&
simdata->exec_data->in_op1->data)<<16);
else
simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0x0000FFFF)|((0x0000FFFF&
simdata->registers->GPR[simdata->exec_data->in_op1->data])<<16);
simdata->exec_data->cycles_left=delay_values[IMM_LOAD_INDX];
}else{
//simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0x0000FFFF)|((0x0000FFFF&
// simdata->registers->GPR[simdata->exec_data->in_op1->data])<<16);
//simdata->exec_data->cycles_left=
return 1;
}
break;
case REGISTER: /* This is for special registers like the SP which is 24bits long */
if(simdata->exec_data->out_op->data==0xFF){
@ -401,19 +513,24 @@ int exec(struct simdata_t *simdata){
simdata->registers->SP=simdata->exec_data->in_op1->data;
else
return 2;
simdata->exec_data->cycles_left=delay_values[IMM_LOAD_INDX];
}else if( simdata->exec_data->in_op1->OP_ADDR==REGISTER ){ /*for completeion, not valid ( yet )*/
if( (simdata->registers->GPR[simdata->exec_data->in_op1->data]&0xFF000000) == 0 )
simdata->registers->SP=simdata->registers->GPR[simdata->exec_data->in_op1->data];
else
return 2;
//if( (simdata->registers->GPR[simdata->exec_data->in_op1->data]&0xFF000000) == 0 )
// simdata->registers->SP=simdata->registers->GPR[simdata->exec_data->in_op1->data];
//else
// return 2;
return 1;
}
}else if(simdata->exec_data->in_op1->OP_ADDR==REGISTER_IND){
if( (simdata->registers->GPR[simdata->exec_data->in_op1->data]&0xFF000000) == 0 )
if( (simdata->registers->GPR[simdata->exec_data->in_op1->data]&0xFF000000) == 0 ){
simdata->registers->GPR[simdata->exec_data->out_op->data]=*(uint32_t*)(simdata->RAM+simdata->registers->GPR[simdata->exec_data->in_op1->data]);
else
simdata->exec_data->cycles_left=delay_values[MEM_ACCS_INDX];
}else
return 2;
}else if(simdata->exec_data->in_op1->OP_ADDR==REGISTER){
simdata->registers->GPR[simdata->exec_data->out_op->data]=simdata->registers->GPR[simdata->exec_data->in_op1->data];
simdata->exec_data->cycles_left=delay_values[RR_MOVE_INDX];
}else
return 1;
break;
@ -423,14 +540,20 @@ int exec(struct simdata_t *simdata){
if(simdata->registers->GPR[simdata->exec_data->out_op->data]==0x00FFFFFC)
if(terminal_output(simdata->registers->GPR[simdata->exec_data->in_op1->data],simdata))
return 1;
simdata->exec_data->cycles_left=delay_values[MEM_ACCS_INDX];
}else
return 1;
break;
default:
return 1;
}
case NOP: break;
break;
case NOP:
simdata->exec_data->cycles_left=1;
break;
case HALT:
simdata->exec_data->cycles_left=1;
simdata->cpu_state=CPU_HALTED;
break;
case PUSH:
@ -439,6 +562,7 @@ int exec(struct simdata_t *simdata){
simdata->RAM[simdata->registers->SP+2]=(simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x00FF0000)>>16;
simdata->RAM[simdata->registers->SP+3]=(simdata->registers->GPR[simdata->exec_data->in_op1->data]&0xFF000000)>>24;
simdata->registers->SP+=4;
simdata->exec_data->cycles_left=delay_values[MEM_ACCS_INDX];
break;
case POP:
simdata->registers->SP-=4;
@ -446,8 +570,18 @@ int exec(struct simdata_t *simdata){
simdata->registers->GPR[simdata->exec_data->in_op1->data]|=simdata->RAM[simdata->registers->SP+1]<<8;
simdata->registers->GPR[simdata->exec_data->in_op1->data]|=simdata->RAM[simdata->registers->SP+2]<<16;
simdata->registers->GPR[simdata->exec_data->in_op1->data]|=simdata->RAM[simdata->registers->SP+3]<<24;
simdata->exec_data->cycles_left=delay_values[MEM_ACCS_INDX];
break;
}
}
if(simdata->exec_data->cycles_left!=0)
simdata->exec_data->cycles_left--;
else
return 1;//internal error
if(simdata->exec_data->cycles_left==0){
simdata->fetch_data->exec_done=1;
simdata->decode_data->exec_done=1;
}
add_to_instr_list(&simdata->cpu_gui_hints->executing_list,simdata->exec_data->address);
return 0;
}

6
cpu.h
View File

@ -3,11 +3,16 @@
struct fetch_data_t{
uint8_t wait_for_exec;
uint8_t exec_done;
uint8_t decode_done;
int fetch_wait;
};
struct decode_data_t{
uint32_t in_bytecode;
uint32_t address; // used only for the gui hints (for now)
uint8_t valid;
uint8_t exec_done;
};
@ -72,6 +77,7 @@ struct exec_data_t {
struct exec_op_t *out_op;
uint32_t address; // used only for the gui hints (for now)
uint8_t valid;
uint8_t cycles_left;
};
char* EXEC_ACTION_t_to_string(enum EXEC_ACTION_t in);

View File

@ -31,7 +31,7 @@ int update_internals(WINDOW *win,struct simdata_t *simdata){
switch(simdata->cpu_structure){
case CPU_STRUCTURE_SIMPLE_PIPELINED:
graph_height=42;
graph_width=59;
graph_width=82;
break;
default:
graph_height=1;
@ -46,103 +46,147 @@ int update_internals(WINDOW *win,struct simdata_t *simdata){
case CPU_STRUCTURE_SIMPLE_PIPELINED:
int fetch_arrow_enter_y;
int decode_arrow_exit_y;
int exec_arrow_y;
boxwidth=50;
/* FETCH BOX */
drawbox(win,startx+boxwidth/2-50/2,starty,startx+boxwidth/2-50/2+50,starty+4);
mvwprintw(win,starty,startx+boxwidth/2-4,"[ FETCH ]");
drawbox(win,startx+20+boxwidth/2-50/2,starty,startx+20+boxwidth/2-50/2+50,starty+6);
mvwprintw(win,starty,startx+20+boxwidth/2-4,"[ FETCH ]");
starty+=2;
mvwprintw(win,starty,startx+boxwidth/2-15/2,"wait_for_exec=%d",simdata->fetch_data->wait_for_exec);
mvwprintw(win,starty,startx+20+boxwidth/2-27/2,"wait_for_exec=%d exec_done=%d",simdata->fetch_data->wait_for_exec,simdata->fetch_data->exec_done);
starty+=2;
mvwprintw(win,starty,startx+20+boxwidth/2-26/2,"fetch_wait=%d decode_done=%d",simdata->fetch_data->fetch_wait,simdata->fetch_data->decode_done);
fetch_arrow_enter_y=starty;
starty+=2;
/* -------> */
mvwaddch(win,starty,startx+boxwidth/2,ACS_TTEE);
mvwaddch(win,starty,startx+20+boxwidth/2,ACS_TTEE);
starty++;
mvwvline(win,starty,startx+boxwidth/2, 0, 2);
mvwvline(win,starty,startx+20+boxwidth/2, 0, 2);
starty+=2;
mvwaddch(win,starty,startx+boxwidth/2,'V');
mvwaddch(win,starty,startx+20+boxwidth/2,'V');
starty+=1;
starty+=1;
/* DECODE BOX */
drawbox(win,startx+boxwidth/2-50/2,starty,startx+boxwidth/2-50/2+50,starty+6);
mvwprintw(win,starty,startx+boxwidth/2-5,"[ DECODE ]");
drawbox(win,startx+20+boxwidth/2-50/2,starty,startx+20+boxwidth/2-50/2+50,starty+6);
mvwprintw(win,starty,startx+20+boxwidth/2-5,"[ DECODE ]");
starty+=2;
mvwprintw(win,starty,startx+boxwidth/2-7/2,"valid=%d",simdata->decode_data->valid);
mvwprintw(win,starty,startx+20+boxwidth/2-19/2,"valid=%d exec_done=%d",simdata->decode_data->valid,simdata->decode_data->exec_done);
decode_arrow_exit_y=starty;
starty+=2;
mvwprintw(win,starty,startx+boxwidth/2-41/2,"in_bytecode=0x%08X address=0x%06X",simdata->decode_data->in_bytecode,simdata->decode_data->address);
mvwprintw(win,starty,startx+20+boxwidth/2-41/2,"in_bytecode=0x%08X address=0x%06X",simdata->decode_data->in_bytecode,simdata->decode_data->address);
starty+=2;
/* -------> */
mvwaddch(win,starty,startx+boxwidth/2,ACS_TTEE);
mvwaddch(win,starty,startx+20+boxwidth/2,ACS_TTEE);
starty++;
mvwvline(win,starty,startx+boxwidth/2, 0, 2);
mvwvline(win,starty,startx+20+boxwidth/2, 0, 2);
starty+=2;
mvwaddch(win,starty,startx+boxwidth/2,'V');
mvwaddch(win,starty,startx+20+boxwidth/2,'V');
starty+=1;
starty+=1;
/* EXECUTE BOX */
drawbox(win,startx+boxwidth/2-50/2,starty,startx+boxwidth/2-50/2+50,starty+21);
mvwprintw(win,starty,startx+boxwidth/2-8,"[ EXECUTE UNIT ]");
drawbox(win,startx+20+boxwidth/2-50/2,starty,startx+20+boxwidth/2-50/2+50,starty+21);
mvwprintw(win,starty,startx+20+boxwidth/2-8,"[ EXECUTE UNIT ]");
starty+=2;
char *tofree;
mvwprintw(win,starty,startx+boxwidth/2-41/2,"valid=%d EXEC_ACTION=%s",simdata->exec_data->valid, (tofree=EXEC_ACTION_t_to_string(simdata->exec_data->EXEC_ACTION)) );
mvwprintw(win,starty,startx+20+boxwidth/2-41/2,"valid=%d EXEC_ACTION=%s",simdata->exec_data->valid, (tofree=EXEC_ACTION_t_to_string(simdata->exec_data->EXEC_ACTION)) );
free(tofree);
starty+=2;
mvwprintw(win,starty,startx+boxwidth/2-41/2,"ALU_OP=%s", (tofree=ALU_OP_t_to_string(simdata->exec_data->ALU_OP)) );
mvwprintw(win,starty,startx+20+boxwidth/2-41/2,"ALU_OP=%s ", (tofree=ALU_OP_t_to_string(simdata->exec_data->ALU_OP)) );
free(tofree);
mvwprintw(win,starty,startx+20+boxwidth/2-41/2+20,"cycles_left=%d ", simdata->exec_data->cycles_left );
starty+=2;
mvwprintw(win,starty,startx+boxwidth/2-41/2,"COND=%s", (tofree=COND_t_to_string(simdata->exec_data->COND)) );
mvwprintw(win,starty,startx+20+boxwidth/2-41/2,"COND=%s", (tofree=COND_t_to_string(simdata->exec_data->COND)) );
free(tofree);
mvwprintw(win,starty,startx+boxwidth/2-41/2+20,"address=%06X", simdata->exec_data->address);
mvwprintw(win,starty,startx+20+boxwidth/2-41/2+20,"address=%06X", simdata->exec_data->address);
starty+=2;
// Operand boxes
struct exec_op_t *cur;
for(int i=0;i<3;i++){
drawbox(win,startx+boxwidth/2-45/2,starty,startx+boxwidth/2-50/2+45,starty+3);
drawbox(win,startx+20+boxwidth/2-45/2,starty,startx+20+boxwidth/2-50/2+45,starty+3);
wattron(win,A_REVERSE);
switch(i){
case 0:
mvwprintw(win,starty,startx+5," Input operand 1 ");
mvwprintw(win,starty,startx+20+5," Input operand 1 ");
cur=simdata->exec_data->in_op1;
break;
case 1:
mvwprintw(win,starty,startx+5," Input operand 2 ");
exec_arrow_y=starty;
mvwprintw(win,starty,startx+20+5," Input operand 2 ");
cur=simdata->exec_data->in_op2;
break;
case 2:
mvwprintw(win,starty,startx+5," Output operand ");
mvwprintw(win,starty,startx+20+5," Output operand ");
cur=simdata->exec_data->out_op;
break;
}
wattroff(win,A_REVERSE);
starty+=2;
mvwprintw(win,starty,startx+7,"data=%06X OP_ADDR=%s",cur->data , (tofree=OP_ADDR_t_to_string(cur->OP_ADDR)) );
mvwprintw(win,starty,startx+20+7,"data=%06X OP_ADDR=%s",cur->data , (tofree=OP_ADDR_t_to_string(cur->OP_ADDR)) );
free(tofree);
starty+=2;
}
/* Wait for exec arrow */
mvwaddch(win,decode_arrow_exit_y,startx+50,ACS_LTEE);
mvwhline(win,decode_arrow_exit_y,startx+51, 0, 3);
mvwaddch(win,decode_arrow_exit_y,startx+54,ACS_LRCORNER);
mvwvline(win,fetch_arrow_enter_y+1,startx+54, 0,decode_arrow_exit_y-fetch_arrow_enter_y-1);
mvwaddch(win,fetch_arrow_enter_y,startx+54,ACS_URCORNER);
mvwhline(win,fetch_arrow_enter_y,startx+53, 0, 1);
mvwaddch(win,fetch_arrow_enter_y,startx+52,'<');
mvwprintw(win,fetch_arrow_enter_y+(decode_arrow_exit_y-fetch_arrow_enter_y-1)/2-1,startx+55,"Wait");
mvwprintw(win,fetch_arrow_enter_y+(decode_arrow_exit_y-fetch_arrow_enter_y-1)/2 ,startx+55,"For");
mvwprintw(win,fetch_arrow_enter_y+(decode_arrow_exit_y-fetch_arrow_enter_y-1)/2+1,startx+55,"Exec");
mvwaddch(win,decode_arrow_exit_y,startx+20+50,ACS_LTEE);
mvwhline(win,decode_arrow_exit_y,startx+20+51, 0, 3);
mvwaddch(win,decode_arrow_exit_y,startx+20+54,ACS_LRCORNER);
mvwvline(win,fetch_arrow_enter_y+1,startx+20+54, 0,decode_arrow_exit_y-fetch_arrow_enter_y-1);
mvwaddch(win,fetch_arrow_enter_y,startx+20+54,ACS_URCORNER);
mvwhline(win,fetch_arrow_enter_y,startx+20+53, 0, 1);
mvwaddch(win,fetch_arrow_enter_y,startx+20+52,'<');
mvwprintw(win,fetch_arrow_enter_y+(decode_arrow_exit_y-fetch_arrow_enter_y-1)/2-1,startx+20+55,"Wait");
mvwprintw(win,fetch_arrow_enter_y+(decode_arrow_exit_y-fetch_arrow_enter_y-1)/2 ,startx+20+55,"For");
mvwprintw(win,fetch_arrow_enter_y+(decode_arrow_exit_y-fetch_arrow_enter_y-1)/2+1,startx+20+55,"Exec");
/* Decode done arrow */
mvwaddch(win,decode_arrow_exit_y,startx+20,ACS_RTEE);
mvwhline(win,decode_arrow_exit_y,startx+17, 0, 3);
mvwaddch(win,decode_arrow_exit_y,startx+16,ACS_LLCORNER);
mvwvline(win,fetch_arrow_enter_y+1,startx+16, 0,decode_arrow_exit_y-fetch_arrow_enter_y-1);
mvwaddch(win,fetch_arrow_enter_y,startx+16,ACS_ULCORNER);
mvwhline(win,fetch_arrow_enter_y,startx+17, 0, 1);
mvwaddch(win,fetch_arrow_enter_y,startx+18,'>');
mvwprintw(win,fetch_arrow_enter_y+(decode_arrow_exit_y-fetch_arrow_enter_y-1)/2 ,startx+10,"Decode");
mvwprintw(win,fetch_arrow_enter_y+(decode_arrow_exit_y-fetch_arrow_enter_y-1)/2+1,startx+12,"Done");
decode_arrow_exit_y+=2;//a bit of a hack i know
/* Exec done (decode) arrow */
mvwaddch(win,exec_arrow_y,startx+20,ACS_RTEE);
mvwhline(win,exec_arrow_y,startx+17, 0, 3);
mvwaddch(win,exec_arrow_y,startx+16,ACS_LLCORNER);
mvwvline(win,decode_arrow_exit_y+1,startx+16, 0,exec_arrow_y-decode_arrow_exit_y-1);
mvwaddch(win,decode_arrow_exit_y,startx+16,ACS_ULCORNER);
mvwhline(win,decode_arrow_exit_y,startx+17, 0, 1);
mvwaddch(win,decode_arrow_exit_y,startx+18,'>');
mvwprintw(win,decode_arrow_exit_y+(exec_arrow_y-decode_arrow_exit_y-1)/2 ,startx+12,"Exec");
mvwprintw(win,decode_arrow_exit_y+(exec_arrow_y-decode_arrow_exit_y-1)/2+1,startx+12,"Done");
fetch_arrow_enter_y-=2;//a bit of a hack i know
exec_arrow_y+=3;
/* Exec done (fetch) arrow */
mvwaddch(win,exec_arrow_y,startx+20,ACS_RTEE);
mvwhline(win,exec_arrow_y,startx+9, 0, 11);
mvwaddch(win,exec_arrow_y,startx+8,ACS_LLCORNER);
mvwvline(win,fetch_arrow_enter_y+1,startx+8, 0,exec_arrow_y-fetch_arrow_enter_y-1);
mvwaddch(win,fetch_arrow_enter_y,startx+8,ACS_ULCORNER);
mvwhline(win,fetch_arrow_enter_y,startx+9, 0, 9);
mvwaddch(win,fetch_arrow_enter_y,startx+18,'>');
mvwprintw(win,fetch_arrow_enter_y+(exec_arrow_y-fetch_arrow_enter_y-1)/2 ,startx+4,"Exec");
mvwprintw(win,fetch_arrow_enter_y+(exec_arrow_y-fetch_arrow_enter_y-1)/2+1,startx+4,"Done");
break;
default:
mvwprintw(win,starty,startx,"No graph available for this cpu structure");