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

458
cpu.c
View File

@ -8,18 +8,33 @@
struct fetch_data_t *malloc_fetch_data(){ struct fetch_data_t *malloc_fetch_data(){
struct fetch_data_t *ret=malloc(sizeof(struct fetch_data_t)); struct fetch_data_t *ret=malloc(sizeof(struct fetch_data_t));
ret->wait_for_exec=0; ret->wait_for_exec=0;
ret->exec_done=1;
ret->decode_done=1;
ret->fetch_wait=0;
return ret; return ret;
} }
void free_fetch_data(struct fetch_data_t *tofree){ void free_fetch_data(struct fetch_data_t *tofree){
free(tofree); free(tofree);
} }
int fetch(struct simdata_t *simdata){ int fetch(struct simdata_t *simdata){
free_instr_list(&simdata->cpu_gui_hints->fetching_list); free_instr_list(&simdata->cpu_gui_hints->fetching_list);
if(simdata->fetch_data->wait_for_exec!=0){ if(simdata->fetch_data->wait_for_exec!=0){
simdata->fetch_data->fetch_wait=1;
simdata->decode_data->valid=0; simdata->decode_data->valid=0;
simdata->fetch_data->wait_for_exec--; simdata->fetch_data->wait_for_exec=0;
return 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->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->valid=1;
simdata->decode_data->address=simdata->registers->PC; 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)); struct decode_data_t *ret=malloc(sizeof(struct decode_data_t));
if(ret) if(ret)
ret->valid=0; ret->valid=0;
ret->exec_done=1;
return ret; return ret;
} }
void free_decode_data(struct decode_data_t *tofree){ 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){ int decode(struct simdata_t *simdata){
uint16_t opcode,op1,op2,imm; uint16_t opcode,op1,op2,imm;
free_instr_list(&simdata->cpu_gui_hints->decoding_list); 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){ if(simdata->decode_data->valid==0){
simdata->exec_data->valid=0; simdata->exec_data->valid=0;
simdata->fetch_data->decode_done=1;
return 0; return 0;
} }
switch((simdata->decode_data->in_bytecode&0xE0000000)>>29){ switch((simdata->decode_data->in_bytecode&0xE0000000)>>29){
@ -234,6 +255,7 @@ int decode(struct simdata_t *simdata){
default: default:
return 1; return 1;
} }
simdata->fetch_data->decode_done=1;
simdata->exec_data->valid=1; simdata->exec_data->valid=1;
simdata->exec_data->address=simdata->decode_data->address; simdata->exec_data->address=simdata->decode_data->address;
add_to_instr_list(&simdata->cpu_gui_hints->decoding_list,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; return 0;
} }
ret->valid=0; ret->valid=0;
ret->cycles_left=0;
return ret; return ret;
} }
void free_exec_data(struct exec_data_t *tofree){ 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->out_op);
free(tofree); 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){ int exec(struct simdata_t *simdata){
free_instr_list(&simdata->cpu_gui_hints->executing_list); free_instr_list(&simdata->cpu_gui_hints->executing_list);
if(simdata->exec_data->valid==0) if(simdata->exec_data->valid==1){
return 0; simdata->fetch_data->exec_done=0;
int condition=0; simdata->decode_data->exec_done=0;
switch(simdata->exec_data->EXEC_ACTION){ }
case CALL: if(simdata->exec_data->cycles_left==0){
case JUMP: if(simdata->exec_data->valid==0)
switch(simdata->exec_data->COND){ return 0;
case COND_NONE: condition=1; break; int condition=0;
case COND_ZERO: condition=simdata->registers->FLAGS&1; break; switch(simdata->exec_data->EXEC_ACTION){
case COND_NZERO: condition=!(simdata->registers->FLAGS&1); break; case CALL:
case COND_CARRY: condition=simdata->registers->FLAGS&2; break; case JUMP:
case COND_NCARRY: condition=!(simdata->registers->FLAGS&2); break; switch(simdata->exec_data->COND){
} case COND_NONE: condition=1; break;
if(condition){ case COND_ZERO: condition=simdata->registers->FLAGS&1; break;
if(simdata->exec_data->EXEC_ACTION==CALL){ case COND_NZERO: condition=!(simdata->registers->FLAGS&1); break;
*(uint32_t*)(simdata->RAM+simdata->registers->SP)=simdata->registers->PC; case COND_CARRY: condition=simdata->registers->FLAGS&2; break;
simdata->registers->SP+=4; case COND_NCARRY: condition=!(simdata->registers->FLAGS&2); break;
} }
if(simdata->exec_data->out_op->OP_ADDR==IMMEDIATE) switch(simdata->exec_data->COND){
simdata->registers->PC=(uint32_t)(simdata->exec_data->out_op->data); case COND_NONE:
else simdata->exec_data->cycles_left=delay_values[BRNCH_UNCO_INDX];
return 1; break;
} default:
break; if(condition)
case RET: simdata->exec_data->cycles_left=delay_values[BRNCH_TAKN_INDX];
simdata->registers->SP-=4; else
simdata->registers->PC=simdata->RAM[simdata->registers->SP]; simdata->exec_data->cycles_left=delay_values[BRNCH_MISS_INDX];
break; break;
case EXEC_ALU: }
if( simdata->exec_data->in_op1->OP_ADDR==REGISTER && if(condition){
simdata->exec_data->in_op2->OP_ADDR==REGISTER && if(simdata->exec_data->EXEC_ACTION==CALL){
simdata->exec_data->out_op->OP_ADDR==REGISTER ){ *(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; uint32_t result;
switch(simdata->exec_data->ALU_OP){ switch(simdata->exec_data->ALU_OP){
case ALU_ADD: case ALU_ADD:
result = simdata->registers->GPR[simdata->exec_data->in_op1->data] + result = simdata->registers->GPR[simdata->exec_data->in_op1->data] +
simdata->registers->GPR[simdata->exec_data->in_op2->data]; simdata->registers->GPR[simdata->exec_data->in_op2->data];
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)| 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->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; break;
case ALU_SUB: case REGISTERH:
case ALU_CMP: if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE){
result = simdata->registers->GPR[simdata->exec_data->in_op2->data] - 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]; simdata->exec_data->in_op1->data)<<16);
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)| simdata->exec_data->cycles_left=delay_values[IMM_LOAD_INDX];
(simdata->registers->GPR[simdata->exec_data->out_op->data] > simdata->registers->GPR[simdata->exec_data->in_op1->data])<<1; }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; break;
case ALU_SL: case REGISTER: /* This is for special registers like the SP which is 24bits long */
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)| if(simdata->exec_data->out_op->data==0xFF){
((simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x80000000)?2:0); if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE){
result = simdata->registers->GPR[simdata->exec_data->in_op1->data]<<1; 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; break;
case ALU_SR: case REGISTER_IND:
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFD)| if(simdata->exec_data->in_op1->OP_ADDR==REGISTER){
((simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x00000001)?2:0); *(uint32_t*)(simdata->RAM+(simdata->registers->GPR[simdata->exec_data->out_op->data]&0x00FFFFFF))=simdata->registers->GPR[simdata->exec_data->in_op1->data];
result = simdata->registers->GPR[simdata->exec_data->in_op1->data]>>1; if(simdata->registers->GPR[simdata->exec_data->out_op->data]==0x00FFFFFC)
break; if(terminal_output(simdata->registers->GPR[simdata->exec_data->in_op1->data],simdata))
case ALU_FDIV: return 1;
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[MEM_ACCS_INDX];
break; }else
case ALU_FMUL: return 1;
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;
break; break;
default: default:
return 1; return 1;
} }
simdata->registers->FLAGS=(simdata->registers->FLAGS&0xFFFFFFFE)|(result==0); break;
if(simdata->exec_data->ALU_OP!=ALU_CMP) case NOP:
simdata->registers->GPR[simdata->exec_data->out_op->data]=result; simdata->exec_data->cycles_left=1;
}else break;
return 1; case HALT:
break; simdata->exec_data->cycles_left=1;
case MOVE: simdata->cpu_state=CPU_HALTED;
switch(simdata->exec_data->out_op->OP_ADDR){ break;
case REGISTERL: case PUSH:
if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE) simdata->RAM[simdata->registers->SP ]=simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x000000FF;
simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0xFFFF0000)|(0x0000FFFF& simdata->RAM[simdata->registers->SP+1]=(simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x0000FF00)>>8;
simdata->exec_data->in_op1->data); simdata->RAM[simdata->registers->SP+2]=(simdata->registers->GPR[simdata->exec_data->in_op1->data]&0x00FF0000)>>16;
else simdata->RAM[simdata->registers->SP+3]=(simdata->registers->GPR[simdata->exec_data->in_op1->data]&0xFF000000)>>24;
simdata->registers->GPR[simdata->exec_data->out_op->data]=(simdata->registers->GPR[simdata->exec_data->out_op->data]&0xFFFF0000)|(0x0000FFFF& simdata->registers->SP+=4;
simdata->registers->GPR[simdata->exec_data->in_op1->data]); simdata->exec_data->cycles_left=delay_values[MEM_ACCS_INDX];
break; break;
case REGISTERH: case POP:
if(simdata->exec_data->in_op1->OP_ADDR==IMMEDIATE) simdata->registers->SP-=4;
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]=simdata->RAM[simdata->registers->SP];
simdata->exec_data->in_op1->data)<<16); simdata->registers->GPR[simdata->exec_data->in_op1->data]|=simdata->RAM[simdata->registers->SP+1]<<8;
else simdata->registers->GPR[simdata->exec_data->in_op1->data]|=simdata->RAM[simdata->registers->SP+2]<<16;
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]|=simdata->RAM[simdata->registers->SP+3]<<24;
simdata->registers->GPR[simdata->exec_data->in_op1->data])<<16); simdata->exec_data->cycles_left=delay_values[MEM_ACCS_INDX];
break; 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->cycles_left!=0)
if( (simdata->exec_data->in_op1->data&0xFF000000) == 0 ) simdata->exec_data->cycles_left--;
simdata->registers->SP=simdata->exec_data->in_op1->data; else
else return 1;//internal error
return 2; if(simdata->exec_data->cycles_left==0){
}else if( simdata->exec_data->in_op1->OP_ADDR==REGISTER ){ /*for completeion, not valid ( yet )*/ simdata->fetch_data->exec_done=1;
if( (simdata->registers->GPR[simdata->exec_data->in_op1->data]&0xFF000000) == 0 ) simdata->decode_data->exec_done=1;
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;
} }
add_to_instr_list(&simdata->cpu_gui_hints->executing_list,simdata->exec_data->address); add_to_instr_list(&simdata->cpu_gui_hints->executing_list,simdata->exec_data->address);
return 0; return 0;

6
cpu.h
View File

@ -3,11 +3,16 @@
struct fetch_data_t{ struct fetch_data_t{
uint8_t wait_for_exec; uint8_t wait_for_exec;
uint8_t exec_done;
uint8_t decode_done;
int fetch_wait;
}; };
struct decode_data_t{ struct decode_data_t{
uint32_t in_bytecode; uint32_t in_bytecode;
uint32_t address; // used only for the gui hints (for now) uint32_t address; // used only for the gui hints (for now)
uint8_t valid; uint8_t valid;
uint8_t exec_done;
}; };
@ -72,6 +77,7 @@ struct exec_data_t {
struct exec_op_t *out_op; struct exec_op_t *out_op;
uint32_t address; // used only for the gui hints (for now) uint32_t address; // used only for the gui hints (for now)
uint8_t valid; uint8_t valid;
uint8_t cycles_left;
}; };
char* EXEC_ACTION_t_to_string(enum EXEC_ACTION_t in); 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){ switch(simdata->cpu_structure){
case CPU_STRUCTURE_SIMPLE_PIPELINED: case CPU_STRUCTURE_SIMPLE_PIPELINED:
graph_height=42; graph_height=42;
graph_width=59; graph_width=82;
break; break;
default: default:
graph_height=1; graph_height=1;
@ -46,103 +46,147 @@ int update_internals(WINDOW *win,struct simdata_t *simdata){
case CPU_STRUCTURE_SIMPLE_PIPELINED: case CPU_STRUCTURE_SIMPLE_PIPELINED:
int fetch_arrow_enter_y; int fetch_arrow_enter_y;
int decode_arrow_exit_y; int decode_arrow_exit_y;
int exec_arrow_y;
boxwidth=50; boxwidth=50;
/* FETCH BOX */ /* FETCH BOX */
drawbox(win,startx+boxwidth/2-50/2,starty,startx+boxwidth/2-50/2+50,starty+4); drawbox(win,startx+20+boxwidth/2-50/2,starty,startx+20+boxwidth/2-50/2+50,starty+6);
mvwprintw(win,starty,startx+boxwidth/2-4,"[ FETCH ]"); mvwprintw(win,starty,startx+20+boxwidth/2-4,"[ FETCH ]");
starty+=2; 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; fetch_arrow_enter_y=starty;
starty+=2; starty+=2;
/* -------> */ /* -------> */
mvwaddch(win,starty,startx+boxwidth/2,ACS_TTEE); mvwaddch(win,starty,startx+20+boxwidth/2,ACS_TTEE);
starty++; starty++;
mvwvline(win,starty,startx+boxwidth/2, 0, 2); mvwvline(win,starty,startx+20+boxwidth/2, 0, 2);
starty+=2; starty+=2;
mvwaddch(win,starty,startx+boxwidth/2,'V'); mvwaddch(win,starty,startx+20+boxwidth/2,'V');
starty+=1; starty+=1;
starty+=1; starty+=1;
/* DECODE BOX */ /* DECODE BOX */
drawbox(win,startx+boxwidth/2-50/2,starty,startx+boxwidth/2-50/2+50,starty+6); drawbox(win,startx+20+boxwidth/2-50/2,starty,startx+20+boxwidth/2-50/2+50,starty+6);
mvwprintw(win,starty,startx+boxwidth/2-5,"[ DECODE ]"); mvwprintw(win,starty,startx+20+boxwidth/2-5,"[ DECODE ]");
starty+=2; 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; decode_arrow_exit_y=starty;
starty+=2; 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; starty+=2;
/* -------> */ /* -------> */
mvwaddch(win,starty,startx+boxwidth/2,ACS_TTEE); mvwaddch(win,starty,startx+20+boxwidth/2,ACS_TTEE);
starty++; starty++;
mvwvline(win,starty,startx+boxwidth/2, 0, 2); mvwvline(win,starty,startx+20+boxwidth/2, 0, 2);
starty+=2; starty+=2;
mvwaddch(win,starty,startx+boxwidth/2,'V'); mvwaddch(win,starty,startx+20+boxwidth/2,'V');
starty+=1; starty+=1;
starty+=1; starty+=1;
/* EXECUTE BOX */ /* EXECUTE BOX */
drawbox(win,startx+boxwidth/2-50/2,starty,startx+boxwidth/2-50/2+50,starty+21); drawbox(win,startx+20+boxwidth/2-50/2,starty,startx+20+boxwidth/2-50/2+50,starty+21);
mvwprintw(win,starty,startx+boxwidth/2-8,"[ EXECUTE UNIT ]"); mvwprintw(win,starty,startx+20+boxwidth/2-8,"[ EXECUTE UNIT ]");
starty+=2; starty+=2;
char *tofree; 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); free(tofree);
starty+=2; 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); free(tofree);
mvwprintw(win,starty,startx+20+boxwidth/2-41/2+20,"cycles_left=%d ", simdata->exec_data->cycles_left );
starty+=2; 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); 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; starty+=2;
// Operand boxes // Operand boxes
struct exec_op_t *cur; struct exec_op_t *cur;
for(int i=0;i<3;i++){ 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); wattron(win,A_REVERSE);
switch(i){ switch(i){
case 0: 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; cur=simdata->exec_data->in_op1;
break; break;
case 1: 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; cur=simdata->exec_data->in_op2;
break; break;
case 2: case 2:
mvwprintw(win,starty,startx+5," Output operand "); mvwprintw(win,starty,startx+20+5," Output operand ");
cur=simdata->exec_data->out_op; cur=simdata->exec_data->out_op;
break; break;
} }
wattroff(win,A_REVERSE); wattroff(win,A_REVERSE);
starty+=2; 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); free(tofree);
starty+=2; starty+=2;
} }
/* Wait for exec arrow */ /* Wait for exec arrow */
mvwaddch(win,decode_arrow_exit_y,startx+50,ACS_LTEE); mvwaddch(win,decode_arrow_exit_y,startx+20+50,ACS_LTEE);
mvwhline(win,decode_arrow_exit_y,startx+51, 0, 3); mvwhline(win,decode_arrow_exit_y,startx+20+51, 0, 3);
mvwaddch(win,decode_arrow_exit_y,startx+54,ACS_LRCORNER); mvwaddch(win,decode_arrow_exit_y,startx+20+54,ACS_LRCORNER);
mvwvline(win,fetch_arrow_enter_y+1,startx+54, 0,decode_arrow_exit_y-fetch_arrow_enter_y-1); 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+54,ACS_URCORNER); mvwaddch(win,fetch_arrow_enter_y,startx+20+54,ACS_URCORNER);
mvwhline(win,fetch_arrow_enter_y,startx+53, 0, 1); mvwhline(win,fetch_arrow_enter_y,startx+20+53, 0, 1);
mvwaddch(win,fetch_arrow_enter_y,startx+52,'<'); 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+55,"Wait"); 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+55,"For"); 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+55,"Exec"); 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; break;
default: default:
mvwprintw(win,starty,startx,"No graph available for this cpu structure"); mvwprintw(win,starty,startx,"No graph available for this cpu structure");