From c59791e7e266d09070729ad6f7489e28f52fba77 Mon Sep 17 00:00:00 2001 From: "(Tim) Efthimis Kritikos" Date: Wed, 6 Mar 2024 02:37:55 +0000 Subject: [PATCH] CPU: Added support for requiring multiple clock cycles for different instruction in the execution unit and updated the gui/internals tab accordingly --- cpu.c | 458 +++++++++++++++++++++++++++++++----------------- cpu.h | 6 + gui_internals.c | 114 ++++++++---- 3 files changed, 381 insertions(+), 197 deletions(-) diff --git a/cpu.c b/cpu.c index bade53a..f1b0117 100644 --- a/cpu.c +++ b/cpu.c @@ -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,178 +298,289 @@ 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==0) - return 0; - int condition=0; - switch(simdata->exec_data->EXEC_ACTION){ - case CALL: - case JUMP: - switch(simdata->exec_data->COND){ - case COND_NONE: condition=1; break; - case COND_ZERO: condition=simdata->registers->FLAGS&1; break; - case COND_NZERO: condition=!(simdata->registers->FLAGS&1); break; - case COND_CARRY: condition=simdata->registers->FLAGS&2; break; - case COND_NCARRY: condition=!(simdata->registers->FLAGS&2); break; - } - if(condition){ - if(simdata->exec_data->EXEC_ACTION==CALL){ - *(uint32_t*)(simdata->RAM+simdata->registers->SP)=simdata->registers->PC; - simdata->registers->SP+=4; + 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; + switch(simdata->exec_data->EXEC_ACTION){ + case CALL: + case JUMP: + switch(simdata->exec_data->COND){ + case COND_NONE: condition=1; break; + case COND_ZERO: condition=simdata->registers->FLAGS&1; break; + case COND_NZERO: condition=!(simdata->registers->FLAGS&1); break; + case COND_CARRY: condition=simdata->registers->FLAGS&2; break; + case COND_NCARRY: condition=!(simdata->registers->FLAGS&2); break; } - if(simdata->exec_data->out_op->OP_ADDR==IMMEDIATE) - simdata->registers->PC=(uint32_t)(simdata->exec_data->out_op->data); - else - return 1; - } - break; - case RET: - simdata->registers->SP-=4; - simdata->registers->PC=simdata->RAM[simdata->registers->SP]; - break; - case EXEC_ALU: - if( simdata->exec_data->in_op1->OP_ADDR==REGISTER && - simdata->exec_data->in_op2->OP_ADDR==REGISTER && - simdata->exec_data->out_op->OP_ADDR==REGISTER ){ + 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; + simdata->registers->SP+=4; + } + if(simdata->exec_data->out_op->OP_ADDR==IMMEDIATE) + simdata->registers->PC=(uint32_t)(simdata->exec_data->out_op->data); + else + return 1; + } + 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; + case EXEC_ALU: + if( simdata->exec_data->in_op1->OP_ADDR==REGISTER && + simdata->exec_data->in_op2->OP_ADDR==REGISTER && + simdata->exec_data->out_op->OP_ADDR==REGISTER ){ - uint32_t result; - switch(simdata->exec_data->ALU_OP){ - case ALU_ADD: - result = simdata->registers->GPR[simdata->exec_data->in_op1->data] + - 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; + uint32_t result; + switch(simdata->exec_data->ALU_OP){ + case ALU_ADD: + result = simdata->registers->GPR[simdata->exec_data->in_op1->data] + + 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: + result = simdata->registers->GPR[simdata->exec_data->in_op2->data] - + 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; + } + simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFE)|(result==0); + if(simdata->exec_data->ALU_OP!=ALU_CMP) + simdata->registers->GPR[simdata->exec_data->out_op->data]=result; + }else + return 1; + break; + case MOVE: + switch(simdata->exec_data->out_op->OP_ADDR){ + case REGISTERL: + 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); + 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 ALU_SUB: - case ALU_CMP: - result = simdata->registers->GPR[simdata->exec_data->in_op2->data] - - 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; + case REGISTERH: + 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); + 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 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; + case REGISTER: /* This is for special registers like the SP which is 24bits long */ + if(simdata->exec_data->out_op->data==0xFF){ + if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE){ + if( (simdata->exec_data->in_op1->data&0xFF000000) == 0 ) + 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; + 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 ){ + simdata->registers->GPR[simdata->exec_data->out_op->data]=*(uint32_t*)(simdata->RAM+simdata->registers->GPR[simdata->exec_data->in_op1->data]); + 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; - 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; - 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])); - 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])); - 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])); - 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])); - break; - case ALU_FSIN: - result = ieee754_float_to_uint32(sinf(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data]))); - break; - case ALU_FCOS: - result = ieee754_float_to_uint32(cosf(uint32_to_ieee754_float(simdata->registers->GPR[simdata->exec_data->in_op1->data]))); - 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; - 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; + case REGISTER_IND: + if(simdata->exec_data->in_op1->OP_ADDR==REGISTER){ + *(uint32_t*)(simdata->RAM+(simdata->registers->GPR[simdata->exec_data->out_op->data]&0x00FFFFFF))=simdata->registers->GPR[simdata->exec_data->in_op1->data]; + 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; } - simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFE)|(result==0); - if(simdata->exec_data->ALU_OP!=ALU_CMP) - simdata->registers->GPR[simdata->exec_data->out_op->data]=result; - }else - return 1; - break; - case MOVE: - switch(simdata->exec_data->out_op->OP_ADDR){ - case REGISTERL: - 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]); - break; - case REGISTERH: - 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); - break; - case REGISTER: /* This is for special registers like the SP which is 24bits long */ - if(simdata->exec_data->out_op->data==0xFF){ - if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE){ - if( (simdata->exec_data->in_op1->data&0xFF000000) == 0 ) - simdata->registers->SP=simdata->exec_data->in_op1->data; - else - return 2; - }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; - } - }else if(simdata->exec_data->in_op1->OP_ADDR==REGISTER_IND){ - 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 - 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]; - }else - return 1; - break; - case REGISTER_IND: - if(simdata->exec_data->in_op1->OP_ADDR==REGISTER){ - *(uint32_t*)(simdata->RAM+(simdata->registers->GPR[simdata->exec_data->out_op->data]&0x00FFFFFF))=simdata->registers->GPR[simdata->exec_data->in_op1->data]; - 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; - }else - return 1; - break; - default: - return 1; - } - case NOP: break; - case HALT: - simdata->cpu_state=CPU_HALTED; - break; - case PUSH: - simdata->RAM[simdata->registers->SP ]=simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x000000FF; - simdata->RAM[simdata->registers->SP+1]=(simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x0000FF00)>>8; - 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; - break; - case POP: - simdata->registers->SP-=4; - simdata->registers->GPR[simdata->exec_data->in_op1->data]=simdata->RAM[simdata->registers->SP]; - 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; - 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: + simdata->RAM[simdata->registers->SP ]=simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x000000FF; + simdata->RAM[simdata->registers->SP+1]=(simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x0000FF00)>>8; + 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; + simdata->registers->GPR[simdata->exec_data->in_op1->data]=simdata->RAM[simdata->registers->SP]; + 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; diff --git a/cpu.h b/cpu.h index b3b659f..dee908d 100644 --- a/cpu.h +++ b/cpu.h @@ -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); diff --git a/gui_internals.c b/gui_internals.c index db86c61..dc07f7c 100644 --- a/gui_internals.c +++ b/gui_internals.c @@ -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");