GUI: Added a new Display tab that only updates when the cpu finished producing a new frame and made massive performance improvements with the help of the new profiler

This commit is contained in:
(Tim) Efthimis Kritikos 2024-02-26 22:11:30 +00:00
parent 201ac2d401
commit 316d4952fa
2 changed files with 125 additions and 48 deletions

View File

@ -52,6 +52,7 @@ callgrind.out:first ${MAIN_ROM}
${QUIET_VALGRIND} ${QUIET_VALGRIND}
${Q}if ldd first |grep asan > /dev/null;\ ${Q}if ldd first |grep asan > /dev/null;\
then\ then\
rm -f "$@";\
echo ERROR: Binary build with libasan, please rebuild without address sanitiser;\ echo ERROR: Binary build with libasan, please rebuild without address sanitiser;\
else\ else\
valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes --collect-jumps=yes --callgrind-out-file=callgrind.out ./first -i programs/3d_renderer.rom;\ valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes --collect-jumps=yes --callgrind-out-file=callgrind.out ./first -i programs/3d_renderer.rom;\

172
gui.c
View File

@ -49,6 +49,8 @@ WINDOW *pipeline_disas;
WINDOW *debug_simdata; WINDOW *debug_simdata;
WINDOW *display_terminal_output;
int monochrome; int monochrome;
int get_terminal_size(){ int get_terminal_size(){
@ -61,7 +63,7 @@ int get_terminal_size(){
} }
char *tab_name[]={"Overview","Memory","Pipeline","Debug"}; char *tab_name[]={"Overview","Memory","Pipeline","Debug","Display"};
unsigned int CURRENT_TAB=1; unsigned int CURRENT_TAB=1;
@ -92,12 +94,16 @@ int gui_ncurses_refresh(){
}else if(CURRENT_TAB==4){ }else if(CURRENT_TAB==4){
if(wrefresh(debug_simdata)==ERR) if(wrefresh(debug_simdata)==ERR)
return 1; return 1;
}else if(CURRENT_TAB==5){
if(wrefresh(display_terminal_output)==ERR)
return 1;
} }
return 0; return 0;
} }
enum GUI_CPU_STATE_t GUI_CPU_STATE=GUI_CPU_SINGLE_STEPPING; enum GUI_CPU_STATE_t GUI_CPU_STATE=GUI_CPU_SINGLE_STEPPING;
void update_tabs(){ void update_tabs(){
wattron(tabs,A_BOLD); wattron(tabs,A_BOLD);
wattron(tabs,COLOR_PAIR(2)); wattron(tabs,COLOR_PAIR(2));
@ -225,6 +231,8 @@ int start_gui(){
pipeline_pipeline=newwin(terminal_height-1-border*2,terminal_width-border*3-GENERAL_DISAS_WIDTH,1+border,border); pipeline_pipeline=newwin(terminal_height-1-border*2,terminal_width-border*3-GENERAL_DISAS_WIDTH,1+border,border);
pipeline_disas=newwin(terminal_height-1-border*2,GENERAL_DISAS_WIDTH,1+border,border+terminal_width-border*3-GENERAL_DISAS_WIDTH); pipeline_disas=newwin(terminal_height-1-border*2,GENERAL_DISAS_WIDTH,1+border,border+terminal_width-border*3-GENERAL_DISAS_WIDTH);
display_terminal_output=newwin(terminal_height-1,terminal_width,1,0);
gui_settings=malloc(sizeof(struct gui_settings_t)); gui_settings=malloc(sizeof(struct gui_settings_t));
gui_settings->cycles_per_frame=100; gui_settings->cycles_per_frame=100;
@ -604,7 +612,7 @@ L'⢀',L'⢁',L'⢂',L'⢃',L'⢄',L'⢅',L'⢆',L'⢇',L'⢈',L'⢉',L'⢊',L'
L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'', L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',L'',
}; };
int print_braille_frame_buffer(WINDOW* win,uint8_t *buffer,int width,int height){ int print_braille_frame_buffer(WINDOW* win,uint8_t *buffer,int width,int height,int fullscreen){
for(int h=0;h<height/4;h++){ for(int h=0;h<height/4;h++){
for(int w=0;w<width/2;w++){ for(int w=0;w<width/2;w++){
uint8_t select=0; uint8_t select=0;
@ -624,7 +632,10 @@ int print_braille_frame_buffer(WINDOW* win,uint8_t *buffer,int width,int height)
select|=0x20; select|=0x20;
if(buffer[w*2+1 +width*(h*4+3 )]) if(buffer[w*2+1 +width*(h*4+3 )])
select|=0x80; select|=0x80;
mvwprintw(win,h+1,w+1,"%lc",braille_lookup[select]); if(fullscreen)
mvwprintw(win,h,w,"%lc",braille_lookup[select]);
else
mvwprintw(win,h+1,w+1,"%lc",braille_lookup[select]);
} }
} }
return 0; return 0;
@ -648,24 +659,31 @@ void braille_frame_buffer_line(uint8_t *buffer,int buffer_width,int buffer_heigh
} }
} }
int update_terminal_output(WINDOW *win, struct simdata_t *simdata,uint8_t fullscreen){
int update_general_terminal_output(struct simdata_t *simdata){
int width,height; int width,height;
werase(general_terminal_output); werase(win);
getmaxyx(general_terminal_output,height,width); getmaxyx(win,height,width);
term_curs_x=0; term_curs_x=0;
term_curs_y=0; term_curs_y=0;
uint8_t* vector_working_frame_buffer=malloc((height*4)*(width*2));
uint8_t* vector_display_frame_buffer=malloc((height*4)*(width*2));
memset(vector_working_frame_buffer,0,(height*4)*(width*2));
memset(vector_display_frame_buffer,0,(height*4)*(width*2));
int vector=0; int vector=0;
int vstate=0; int vstate=0;
int vfb_width=(width-2)*2; int vfb_width, vfb_height;
int vfb_height=(height-2)*4; if(fullscreen){
vfb_width=(width)*2;
vfb_height=(height)*4;
}else{
vfb_width=(width-2)*2;
vfb_height=(height-2)*4;
}
uint8_t* vector_working_frame_buffer=malloc(vfb_height*vfb_width);
uint8_t* vector_display_frame_buffer=malloc(vfb_height*vfb_width);
memset(vector_working_frame_buffer,0,vfb_height*vfb_width);
memset(vector_display_frame_buffer,0,vfb_height*vfb_width);
float x0,y0,x1,y1; float x0,y0,x1,y1;
for(uint64_t i=0;i < simdata->terminal_output_size/4;i++){ for(uint64_t i=0;i < simdata->terminal_output_size/4;i++){
uint32_t c=simdata->terminal_output[i]; uint32_t c=simdata->terminal_output[i];
@ -675,9 +693,9 @@ int update_general_terminal_output(struct simdata_t *simdata){
if(c==0x00000001) if(c==0x00000001)
vector=0; vector=0;
else if(c==0x00000002) else if(c==0x00000002)
memset(vector_working_frame_buffer,0,(height*4)*(width*2)); memset(vector_working_frame_buffer,0,vfb_height*vfb_width);
else if(c==0x00000003) else if(c==0x00000003)
memcpy(vector_display_frame_buffer,vector_working_frame_buffer,(height*4)*(width*2)); memcpy(vector_display_frame_buffer,vector_working_frame_buffer,vfb_height*vfb_width);
else else
vstate++; vstate++;
break; break;
@ -709,17 +727,17 @@ int update_general_terminal_output(struct simdata_t *simdata){
} }
}else{ }else{
if(c>=' '&&c<='~'){ if(c>=' '&&c<='~'){
mvwprintw(general_terminal_output,term_curs_y+1,term_curs_x+1,"%c",c); mvwprintw(win,term_curs_y+1,term_curs_x+1,"%c",c);
term_curs_x++; term_curs_x++;
if(term_curs_x>=width-2){ if(term_curs_x>=width){
term_curs_x=0; term_curs_x=0;
term_curs_y++; term_curs_y++;
} }
if(term_curs_y>=height-2){ if(term_curs_y>=height){
wscrl(general_terminal_output,1); wscrl(win,1);
term_curs_y--; term_curs_y--;
for(int i=0;i<width;i++){ for(int i=0;i<width;i++){
mvwprintw(general_terminal_output,term_curs_y+1,i," "); mvwprintw(win,term_curs_y+1,i," ");
} }
} }
}else{ }else{
@ -730,37 +748,49 @@ int update_general_terminal_output(struct simdata_t *simdata){
case 0x0a: case 0x0a:
term_curs_x=0; term_curs_x=0;
term_curs_y++; term_curs_y++;
if(term_curs_y>=height-2){ if(term_curs_y>=vfb_height){
wscrl(general_terminal_output,1); wscrl(win,1);
term_curs_y--; term_curs_y--;
box(general_terminal_output, 0 , 0); box(win, 0 , 0);
mvwprintw(general_terminal_output,0,width/2-7,"[ TERM OUTPUT ]"); mvwprintw(win,0,width/2-7,"[ TERM OUTPUT ]");
} }
break; break;
default: default:
werase(general_terminal_output); werase(win);
box(general_terminal_output, 0 , 0); box(win, 0 , 0);
mvwprintw(general_terminal_output,0,width/2-7,"[ TERM OUTPUT ]"); mvwprintw(win,0,width/2-7,"[ TERM OUTPUT ]");
mvwprintw(general_terminal_output,1,1,"Invalid output"); mvwprintw(win,1,1,"Invalid output");
return 0; return 0;
} }
} }
} }
} }
box(general_terminal_output, 0 , 0); if(!fullscreen){
if(!vector){ box(win, 0 , 0);
mvwchgat(general_terminal_output,term_curs_y+1,term_curs_x+1, 1, A_REVERSE, 0, NULL); if(!vector){
mvwprintw(general_terminal_output,0,width/2-7,"[ TERM OUTPUT ]"); mvwchgat(win,term_curs_y+1,term_curs_x+1, 1, A_REVERSE, 0, NULL);
}else{ mvwprintw(win,0,width/2-7,"[ TERM OUTPUT ]");
print_braille_frame_buffer(general_terminal_output,vector_display_frame_buffer,(width-2)*2,(height-2)*4); }else{
mvwprintw(general_terminal_output,0,width/2-9,"[ VECTOR DISPLAY ]"); print_braille_frame_buffer(win,vector_display_frame_buffer,vfb_width,vfb_height,0);
} mvwprintw(win,0,width/2-9,"[ VECTOR DISPLAY ]");
}
}else
if(vector)
print_braille_frame_buffer(win,vector_display_frame_buffer,vfb_width,vfb_height,1);
free(vector_working_frame_buffer); free(vector_working_frame_buffer);
free(vector_display_frame_buffer); free(vector_display_frame_buffer);
return 0; return 0;
} }
int update_general_terminal_output(WINDOW *win, struct simdata_t *simdata){
return update_terminal_output(win,simdata,0);
}
int update_display_terminal_output(WINDOW *win, struct simdata_t *simdata){
return update_terminal_output(win,simdata,1);
}
int update_debug_simdata(struct simdata_t *simdata){ int update_debug_simdata(struct simdata_t *simdata){
int width,height; int width,height;
werase(debug_simdata); werase(debug_simdata);
@ -856,18 +886,34 @@ int update_pipeline(WINDOW *win,struct simdata_t *simdata){
return 0; return 0;
} }
int force_disp_terminal_output_update(struct simdata_t *simdata){
if(update_display_terminal_output(display_terminal_output,simdata))
return 1;
if(gui_ncurses_refresh())
return 1;
if(simdata)
return 0;
else return 0;
}
int clear_back_window=1; int clear_back_window=1;
int write_tabs=1;
int update_gui(struct simdata_t *simdata){ int update_gui(struct simdata_t *simdata){
if(simdata->cpu_state==CPU_HALTED) if(simdata->cpu_state==CPU_HALTED){
GUI_CPU_STATE=GUI_CPU_STOPPED; GUI_CPU_STATE=GUI_CPU_STOPPED;
if(CURRENT_TAB==5)
force_disp_terminal_output_update(simdata);
}
if(clear_back_window){ if(clear_back_window){
clear(); clear();
clear_back_window=0; clear_back_window=0;
} }
if((simdata->current_clock)%(gui_settings->cycles_per_frame)==0 || GUI_CPU_STATE!=GUI_CPU_RUNNING ){ if(write_tabs){
update_tabs(); update_tabs();
write_tabs=0;
}
if((simdata->current_clock)%(gui_settings->cycles_per_frame)==0 || GUI_CPU_STATE!=GUI_CPU_RUNNING ){
if(CURRENT_TAB==1){ if(CURRENT_TAB==1){
if(update_general_memdump(simdata)) if(update_general_memdump(simdata))
return 1; return 1;
@ -877,7 +923,7 @@ int update_gui(struct simdata_t *simdata){
return 1; return 1;
if(update_general_registers(simdata)) if(update_general_registers(simdata))
return 1; return 1;
if(update_general_terminal_output(simdata)) if(update_general_terminal_output(general_terminal_output,simdata))
return 1; return 1;
}else if(CURRENT_TAB==2){ }else if(CURRENT_TAB==2){
if(update_memory_memdump(simdata)) if(update_memory_memdump(simdata))
@ -890,10 +936,15 @@ int update_gui(struct simdata_t *simdata){
}else if(CURRENT_TAB==4){ }else if(CURRENT_TAB==4){
if(update_debug_simdata(simdata)) if(update_debug_simdata(simdata))
return 1; return 1;
}else if(CURRENT_TAB==5){
if(GUI_CPU_STATE!=GUI_CPU_RUNNING)
force_disp_terminal_output_update(simdata);
} }
if(CURRENT_TAB!=5)
if(gui_ncurses_refresh())
return 1;
} }
if(gui_ncurses_refresh())
return 1;
return 0; return 0;
} }
@ -901,18 +952,23 @@ int gui_continue_request(struct simdata_t *simdata){
int inch; int inch;
int release=0; int release=0;
while(release==0){ while(release==0){
if(((inch=getch())==ERR)){ inch=ERR;
if(GUI_CPU_STATE==GUI_CPU_SINGLE_STEPPING) if(((simdata->current_clock)%(gui_settings->cycles_per_frame))==0 || GUI_CPU_STATE!=GUI_CPU_RUNNING ){
return 1; if(((inch=getch())==ERR)){
else if(GUI_CPU_STATE==GUI_CPU_SINGLE_STEPPING)
release=1; return 1;
} else
release=1;
}
}else
release=1;
switch(inch){ switch(inch){
case 'r': case 'r':
if(simdata->cpu_state!=CPU_HALTED){ if(simdata->cpu_state!=CPU_HALTED){
if(GUI_CPU_STATE==GUI_CPU_RUNNING){ if(GUI_CPU_STATE==GUI_CPU_RUNNING){
GUI_CPU_STATE=GUI_CPU_SINGLE_STEPPING; GUI_CPU_STATE=GUI_CPU_SINGLE_STEPPING;
update_gui(simdata); if(CURRENT_TAB!=5)
update_gui(simdata);
nodelay(stdscr, FALSE); nodelay(stdscr, FALSE);
}else{ }else{
GUI_CPU_STATE=GUI_CPU_RUNNING; GUI_CPU_STATE=GUI_CPU_RUNNING;
@ -929,6 +985,7 @@ int gui_continue_request(struct simdata_t *simdata){
if(CURRENT_TAB!=1){ if(CURRENT_TAB!=1){
CURRENT_TAB=1; CURRENT_TAB=1;
clear(); clear();
update_tabs();
update_gui(simdata); update_gui(simdata);
} }
break; break;
@ -936,6 +993,7 @@ int gui_continue_request(struct simdata_t *simdata){
if(CURRENT_TAB!=2){ if(CURRENT_TAB!=2){
CURRENT_TAB=2; CURRENT_TAB=2;
clear(); clear();
update_tabs();
update_gui(simdata); update_gui(simdata);
} }
break; break;
@ -943,6 +1001,7 @@ int gui_continue_request(struct simdata_t *simdata){
if(CURRENT_TAB!=3){ if(CURRENT_TAB!=3){
CURRENT_TAB=3; CURRENT_TAB=3;
clear(); clear();
update_tabs();
update_gui(simdata); update_gui(simdata);
} }
break; break;
@ -950,9 +1009,18 @@ int gui_continue_request(struct simdata_t *simdata){
if(CURRENT_TAB!=4){ if(CURRENT_TAB!=4){
CURRENT_TAB=4; CURRENT_TAB=4;
clear(); clear();
update_tabs();
update_gui(simdata); update_gui(simdata);
} }
break; break;
case '5':
if(CURRENT_TAB!=5){
CURRENT_TAB=5;
clear();
update_tabs();
force_disp_terminal_output_update(simdata);
}
break;
case 'j': case 'j':
if(CURRENT_TAB==2){ if(CURRENT_TAB==2){
memory_window_address++; memory_window_address++;
@ -976,6 +1044,7 @@ int gui_continue_request(struct simdata_t *simdata){
return 0; return 0;
} }
uint32_t highest_disps=0;//XXX: remember that if we create a clear screen command it should zero this out too
int clean_cpu_output(struct simdata_t *simdata){ int clean_cpu_output(struct simdata_t *simdata){
uint32_t last_vect_disp=0; uint32_t last_vect_disp=0;
uint32_t second_last_vect_disp=simdata->terminal_output_size/4;//TODO: I shouldn't have to initialise this. GCC gives a warning erroneously uint32_t second_last_vect_disp=simdata->terminal_output_size/4;//TODO: I shouldn't have to initialise this. GCC gives a warning erroneously
@ -1015,12 +1084,19 @@ int clean_cpu_output(struct simdata_t *simdata){
} }
} }
} }
if(highest_disps<disps_found){
highest_disps=disps_found;
if(CURRENT_TAB==5)
force_disp_terminal_output_update(simdata);
}
if(disps_found>=2){ if(disps_found>=2){
int final_data_size=simdata->terminal_output_size-(second_last_vect_disp+4); int final_data_size=simdata->terminal_output_size-(second_last_vect_disp+4);
memmove((uint8_t*)simdata->terminal_output+4,(uint8_t*)simdata->terminal_output+simdata->terminal_output_size-final_data_size,final_data_size); memmove((uint8_t*)simdata->terminal_output+4,(uint8_t*)simdata->terminal_output+simdata->terminal_output_size-final_data_size,final_data_size);
simdata->terminal_output[0]=0xFFFFFFFF; simdata->terminal_output[0]=0xFFFFFFFF;
simdata->terminal_output=realloc(simdata->terminal_output,final_data_size+4); simdata->terminal_output=realloc(simdata->terminal_output,final_data_size+4);
simdata->terminal_output_size=final_data_size+4; simdata->terminal_output_size=final_data_size+4;
if(CURRENT_TAB==5)
force_disp_terminal_output_update(simdata);
} }
return 0; return 0;
} }