update to the new driver system
Follows most of the changes made to the gint driver system. * Replace test gint/switch with a new test gint/drivers which shows driver metadata, flags, and world states. * Enable the DMA Control test on SH4-based fx-9860G. * Enable the Memory Speed test on SH4-based fx-9860G. * Enable the Memory Speed test on SH3-based fx-9860G although there's barely anything useful for that platform. * Update all tests to the GINT_CALL API when useful. * Use public world buffers and public driver state structures to show world states without having to coordinate the gint and gintctl code.
|
@ -22,6 +22,7 @@ set(SOURCES
|
|||
src/gint/bopti.c
|
||||
src/gint/cpumem.c
|
||||
src/gint/dma.c
|
||||
src/gint/drivers.c
|
||||
src/gint/dsp.c
|
||||
src/gint/dsp.s
|
||||
src/gint/dump.c
|
||||
|
@ -31,7 +32,6 @@ set(SOURCES
|
|||
src/gint/ram.c
|
||||
src/gint/rtc.c
|
||||
src/gint/spuram.c
|
||||
src/gint/switch.c
|
||||
src/gint/timer.c
|
||||
src/gint/timer_callbacks.c
|
||||
src/gint/tlb.c
|
||||
|
@ -70,6 +70,8 @@ set(ASSETS_fx
|
|||
assets-fx/img/opt_dump.png
|
||||
assets-fx/img/opt_gint_bopti.png
|
||||
assets-fx/img/opt_gint_cpumem.png
|
||||
assets-fx/img/opt_gint_dma.png
|
||||
assets-fx/img/opt_gint_drivers.png
|
||||
assets-fx/img/opt_gint_gray.png
|
||||
assets-fx/img/opt_gint_keyboard.png
|
||||
assets-fx/img/opt_gint_kmalloc.png
|
||||
|
@ -84,10 +86,9 @@ set(ASSETS_fx
|
|||
assets-fx/img/opt_main.png
|
||||
assets-fx/img/opt_mem.png
|
||||
assets-fx/img/opt_perf_libprof.png
|
||||
assets-fx/img/opt_perf_memory.png
|
||||
assets-fx/img/opt_perf_memory_sh3.png
|
||||
assets-fx/img/opt_perf_render.png
|
||||
assets-fx/img/opt_switch_ctx.png
|
||||
assets-fx/img/opt_switch_ctx_sh3.png
|
||||
assets-fx/img/opt_switch.png
|
||||
assets-fx/img/profile_gray_alpha.png
|
||||
assets-fx/img/profile_gray.png
|
||||
assets-fx/img/profile_mono_alpha.png
|
||||
|
|
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.0 KiB |
|
@ -25,6 +25,7 @@ extern bopti_image_t
|
|||
img_opt_dump,
|
||||
img_opt_gint_bopti,
|
||||
img_opt_gint_cpumem,
|
||||
img_opt_gint_drivers,
|
||||
img_opt_gint_gray,
|
||||
img_opt_gint_keyboard,
|
||||
img_opt_gint_kmalloc,
|
||||
|
@ -39,10 +40,9 @@ extern bopti_image_t
|
|||
img_opt_main,
|
||||
img_opt_mem,
|
||||
img_opt_perf_libprof,
|
||||
img_opt_perf_memory,
|
||||
img_opt_perf_memory_sh3,
|
||||
img_opt_perf_render,
|
||||
img_opt_switch_ctx,
|
||||
img_opt_switch_ctx_sh3,
|
||||
img_opt_switch,
|
||||
img_profile_gray_alpha,
|
||||
img_profile_gray,
|
||||
img_profile_mono_alpha,
|
||||
|
|
|
@ -20,8 +20,8 @@ void gintctl_gint_spuram(void);
|
|||
/* gintctl_gint_dump(): Dump memory to filesystem */
|
||||
void gintctl_gint_dump(void);
|
||||
|
||||
/* gintctl_gint_switch(): Test the gint switch-in-out procedures */
|
||||
void gintctl_gint_switch(void);
|
||||
/* gintctl_gint_drivers(): Test the gint driver logic and world switch */
|
||||
void gintctl_gint_drivers(void);
|
||||
|
||||
/* gintctl_gint_tlb(): TLB miss handler and TLB management */
|
||||
void gintctl_gint_tlb(void);
|
||||
|
@ -35,6 +35,9 @@ void gintctl_gint_timer(void);
|
|||
/* gintctl_gint_timer_callbacks(): Stunts in the environment of callbacks */
|
||||
void gintctl_gint_timer_callbacks(void);
|
||||
|
||||
/* gintctl_gint_dma(): Test the Direct Access Memory Controller */
|
||||
void gintctl_gint_dma(void);
|
||||
|
||||
/* gintctl_gint_rtc(): Configure RTC and check timer speed */
|
||||
void gintctl_gint_rtc(void);
|
||||
|
||||
|
@ -50,13 +53,6 @@ void gintctl_gint_kmalloc(void);
|
|||
/* gintctl_gint_usb(): USB communication */
|
||||
void gintctl_gint_usb(void);
|
||||
|
||||
#ifdef FXCG50
|
||||
|
||||
/* gintctl_gint_dma(): Test the Direct Access Memory Controller */
|
||||
void gintctl_gint_dma(void);
|
||||
|
||||
#endif /* FXCG50 */
|
||||
|
||||
#ifdef FX9860G
|
||||
|
||||
/* gintctl_gint_gray(): Gray engine tuning */
|
||||
|
|
|
@ -3,28 +3,26 @@
|
|||
#include <gint/mpu/dma.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/mmu.h>
|
||||
|
||||
#include <gintctl/util.h>
|
||||
#include <gintctl/gint.h>
|
||||
|
||||
#ifdef FXCG50
|
||||
|
||||
#define DMA SH7305_DMA
|
||||
#define dprint(x, y, ...) dprint(x, y, C_BLACK, __VA_ARGS__)
|
||||
|
||||
void show_dma(int x, int y, int channel, sh7305_dma_channel_t *dma)
|
||||
void show_dma(int x, int y, GUNUSED int channel, sh7305_dma_channel_t *dma)
|
||||
{
|
||||
#ifdef FX9860G
|
||||
dma->SAR = 0x12345678;
|
||||
dma->DAR = 0x9abcdef0;
|
||||
dma->TCR = 0x12481248;
|
||||
|
||||
int dx=60, dy=8;
|
||||
dprint(x, y, "DMA%d:", channel);
|
||||
dprint(x, y+1*dy, "%08X", (uint32_t)dma);
|
||||
dprint(x, y, "SAR:");
|
||||
dprint(x, y+1*dy, "DAR:");
|
||||
dprint(x, y+2*dy, "TCR:");
|
||||
dprint(x, y+3*dy, "CHCR:");
|
||||
dprint(x+dx, y, "%08X", dma->SAR);
|
||||
dprint(x+dx, y+1*dy, "%08X", dma->DAR);
|
||||
dprint(x, y+2*dy, "%08X", dma->TCR);
|
||||
dprint(x+dx, y+2*dy, "%08X", dma->CHCR);
|
||||
dprint(x+dx, y+2*dy, "%08X", dma->TCR);
|
||||
dprint(x+dx, y+3*dy, "%08X", dma->CHCR);
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
|
@ -44,28 +42,30 @@ void show_dma(int x, int y, int channel, sh7305_dma_channel_t *dma)
|
|||
/* gintctl_gint_dma(): Test the Direct Access Memory Controller */
|
||||
void gintctl_gint_dma(void)
|
||||
{
|
||||
/* Here we'll display the DMA status at "full speed", only limited by
|
||||
the dupdate() time. */
|
||||
int key = 0, timeout = 1;
|
||||
|
||||
/* Test channel, interrupts, and source */
|
||||
int channel = 0, interrupts = 0, source = 0;
|
||||
/* Number of successful attempts */
|
||||
int successes = 0;
|
||||
/* We'll display the DMA status at "full speed", without sleeping. */
|
||||
int key=0, timeout=1;
|
||||
/* Test channel, interrupts, and source; successful attempts */
|
||||
int channel=0, interrupts=0, source=0, successes=0;
|
||||
|
||||
/* Get the physical VRAM address */
|
||||
void *vram_address = gint_vram;
|
||||
#ifdef FX9860G
|
||||
/* Currently visible channel */
|
||||
int view = 0;
|
||||
uint32_t virt_page = (uint32_t)vram_address & 0xfffff000;
|
||||
uint32_t phys_page = 0x80000000 + mmu_translate(virt_page, NULL);
|
||||
vram_address = (void *)phys_page + (vram_address - (void *)virt_page);
|
||||
#endif
|
||||
|
||||
sh7305_dma_channel_t *addr[6] = {
|
||||
&DMA.DMA0, &DMA.DMA1, &DMA.DMA2, &DMA.DMA3, &DMA.DMA4, &DMA.DMA5,
|
||||
};
|
||||
|
||||
while(key != KEY_EXIT)
|
||||
{
|
||||
dclear(C_WHITE);
|
||||
|
||||
#ifdef FX9860G
|
||||
show_dma(1, 1, view);
|
||||
|
||||
dprint(1, 32, "Channel %d", channel);
|
||||
show_dma(1, 0, channel, addr[channel]);
|
||||
dprint(1, 32, "Channel DMA%d", channel);
|
||||
dprint(1, 40, "Interrupts %s", interrupts ? "Yes" : "No");
|
||||
dprint(1, 48, "Source %s", source ? "IL" : "RAM");
|
||||
dprint(103, 40, "%d", successes);
|
||||
|
@ -75,11 +75,6 @@ void gintctl_gint_dma(void)
|
|||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
sh7305_dma_channel_t *addr[6] = {
|
||||
&DMA.DMA0, &DMA.DMA1, &DMA.DMA2,
|
||||
&DMA.DMA3, &DMA.DMA4, &DMA.DMA5,
|
||||
};
|
||||
|
||||
row_title("Direct Memory Access status");
|
||||
|
||||
show_dma(6, 24, 0, addr[0]);
|
||||
|
@ -105,11 +100,11 @@ void gintctl_gint_dma(void)
|
|||
dupdate();
|
||||
key = getkey_opt(GETKEY_DEFAULT, &timeout).key;
|
||||
|
||||
/* On F1, start a DMA transfer and see what happens */
|
||||
/* On F1, start a 1024-byte DMA transfer and see what happens */
|
||||
if(key == KEY_F1)
|
||||
{
|
||||
void *src = (void *)(source ? 0xe5200000 : 0x88000000);
|
||||
void *dst = gint_vram;
|
||||
void *dst = vram_address;
|
||||
int blocks = 256;
|
||||
|
||||
if(interrupts)
|
||||
|
@ -124,16 +119,8 @@ void gintctl_gint_dma(void)
|
|||
successes++;
|
||||
}
|
||||
|
||||
#ifdef FX9860G
|
||||
/* On F2, switch the visible channel */
|
||||
if(key == KEY_F2) view = (view + 1) % 6;
|
||||
#endif
|
||||
|
||||
/* On F4, F5 and F6, change parameters */
|
||||
if(key == KEY_F4) channel = (channel + 1) % 6;
|
||||
if(key == KEY_F5) interrupts = !interrupts;
|
||||
if(key == KEY_F6) source = !source;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FXCG50 */
|
||||
|
|
|
@ -0,0 +1,328 @@
|
|||
#include <gint/gint.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/drivers.h>
|
||||
#include <gint/drivers/states.h>
|
||||
#include <gint/clock.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/mpu/tmu.h>
|
||||
#include <gint/mpu/dma.h>
|
||||
#include <gint/std/string.h>
|
||||
|
||||
#include <gintctl/gint.h>
|
||||
#include <gintctl/util.h>
|
||||
#include <gintctl/assets.h>
|
||||
|
||||
//---
|
||||
// Driver list and information
|
||||
//---
|
||||
|
||||
static void draw_list(int offset, int maximum)
|
||||
{
|
||||
#ifdef FXCG50
|
||||
row_print(1, 2, "Id");
|
||||
row_print(1, 5, "Name");
|
||||
row_print(1, 13, "Size");
|
||||
row_print(1, 18, "Flags");
|
||||
#endif
|
||||
|
||||
font_t const *old_font = dfont(_(&font_mini, dfont_default()));
|
||||
|
||||
for(int i=offset; i < (int)gint_driver_count() && i < offset+maximum; i++)
|
||||
{
|
||||
gint_driver_t *d = &gint_drivers[i];
|
||||
uint8_t flags = gint_driver_flags[i];
|
||||
int y = _(10+6*(i-offset), row_y(i-offset+2));
|
||||
|
||||
dprint(_( 2,row_x(2)), y, C_BLACK, "%d", i);
|
||||
dprint(_(12,row_x(5)), y, C_BLACK, "%s", d->name);
|
||||
dprint(_(36,row_x(13)), y, C_BLACK, "%d", d->state_size);
|
||||
dprint(_(52,row_x(18)), y, C_BLACK, "%s%s%s",
|
||||
(flags & GINT_DRV_CLEAN) ? "CLEAN " : "",
|
||||
(flags & GINT_DRV_FOREIGN_POWERED) ? _("FP ","FOREIGN_POW. ") : "",
|
||||
(flags & GINT_DRV_SHARED) ? "SHARED " : ""
|
||||
);
|
||||
}
|
||||
|
||||
dfont(old_font);
|
||||
|
||||
if((int)gint_driver_count() > maximum) scrollbar_px(_(8,50), _(55,200), 0,
|
||||
gint_driver_count(), offset, maximum);
|
||||
}
|
||||
|
||||
//---
|
||||
// State management
|
||||
//---
|
||||
|
||||
static void draw_state(gint_world_t world, int i)
|
||||
{
|
||||
font_t const *old_font = dfont(_(&font_mini, dfont_default()));
|
||||
|
||||
if(i > 0)
|
||||
dprint(_(86,10), _(57,row_y(1)), C_BLACK, "<");
|
||||
if(i < (int)gint_driver_count() - 1)
|
||||
dprint(DWIDTH - _(4,16), _(57,row_y(1)), C_BLACK, ">");
|
||||
|
||||
dprint_opt(_(106, DWIDTH / 2), _(57, row_y(1)), C_BLACK, C_NONE,
|
||||
DTEXT_CENTER, DTEXT_TOP, "%s", gint_drivers[i].name);
|
||||
|
||||
if(gint_driver_flags[i] & GINT_DRV_SHARED)
|
||||
{
|
||||
dprint_opt(DWIDTH / 2, DHEIGHT / 2, C_BLACK, C_NONE, DTEXT_CENTER,
|
||||
DTEXT_MIDDLE, "Device is shared");
|
||||
return;
|
||||
}
|
||||
if(world == gint_world_addin && (gint_driver_flags[i] & GINT_DRV_CLEAN))
|
||||
{
|
||||
dprint_opt(DWIDTH / 2, DHEIGHT / 2, C_BLACK, C_NONE, DTEXT_CENTER,
|
||||
DTEXT_MIDDLE, "Device is clean");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strcmp(gint_drivers[i].name, "CPG"))
|
||||
{
|
||||
cpg_state_t const *s = world[i];
|
||||
if(isSH3()) row_print(_(1,3), 1, "No state");
|
||||
else row_print(_(1,3), 1, "SSCGCR: %08X", s->SSCGCR);
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "CPU"))
|
||||
{
|
||||
cpu_state_t const *s = world[i];
|
||||
row_print(_(1,3), 1, "SR: %08X", s->SR);
|
||||
row_print(_(2,4), 1, "VBR: %08X", s->VBR);
|
||||
row_print(_(3,5), 1, "CPUOPM: %08X", s->CPUOPM);
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "DMA"))
|
||||
{
|
||||
dma_state_t const *s = world[i];
|
||||
|
||||
#ifdef FX9860G
|
||||
for(int i = 0; i < 6; i++) {
|
||||
dprint(1, 1+6*i, C_BLACK, "%d: %08X->%08X %08X",
|
||||
i, s->ch[i].SAR, s->ch[i].DAR, s->ch[i].CHCR);
|
||||
}
|
||||
dprint(1, 43, C_BLACK, "OR: %08X", s->OR);
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
for(int i = 0; i < 6; i++) {
|
||||
int y=3+5*(i/3), x=1+16*(i%3);
|
||||
row_print(y, x, "%d:", i);
|
||||
row_print(y, x+2, "SAR");
|
||||
row_print(y, x+7, "%08X", s->ch[i].SAR);
|
||||
row_print(y+1, x+2, "DAR");
|
||||
row_print(y+1, x+7, "%08X", s->ch[i].DAR);
|
||||
row_print(y+2, x+2, "TCR");
|
||||
row_print(y+2, x+7, "%08X", s->ch[i].TCR);
|
||||
row_print(y+3, x+2, "CHCR");
|
||||
row_print(y+3, x+7, "%08X", s->ch[i].CHCR);
|
||||
}
|
||||
row_print(13, 1, "OR: %08X\n", s->OR);
|
||||
#endif
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "INTC"))
|
||||
{
|
||||
intc_state_t const *s = world[i];
|
||||
|
||||
#ifdef FX9860G
|
||||
for(int i = 0; i < 12; i++) {
|
||||
dprint(1+32*(i%4),1+6*(i/4), C_BLACK, "%c:%04X", 'A'+i, s->IPR[i]);
|
||||
}
|
||||
for(int i = 0; i < 13; i++) {
|
||||
dprint(1+32*(i%4),25+6*(i/4), C_BLACK, "%d:%02X", i, s->MSK[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
for(int i = 0; i < 12; i++) {
|
||||
row_print(3+i/4, 1+11*(i%4), "IPR%c:", 'A'+i);
|
||||
row_print(3+i/4, 6+11*(i%4), "%04X", s->IPR[i]);
|
||||
}
|
||||
for(int i = 0; i < 13; i++) {
|
||||
row_print(7+i/4, 1+11*(i%4), "IMR%d:", i);
|
||||
row_print(7+i/4, 7+11*(i%4), "%02X", s->MSK[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "KEYSC"))
|
||||
{
|
||||
row_print(_(1,3), 1, "No state");
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "MMU"))
|
||||
{
|
||||
mmu_state_t const *s = world[i];
|
||||
row_print(_(1,3), 1, "PASCR: %08X", s->PASCR);
|
||||
row_print(_(2,4), 1, "IRMCR: %08X", s->IRMCR);
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "R61524"))
|
||||
{
|
||||
r61524_state_t const *s = world[i];
|
||||
row_print(3, 1, "HSA..HEA: %d..%d", s->HSA, s->HEA);
|
||||
row_print(4, 1, "VSA..VEA: %d..%d", s->VSA, s->VEA);
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "RTC"))
|
||||
{
|
||||
rtc_state_t const *s = world[i];
|
||||
row_print(_(1,3), 1, "RCR1: %02X RCR2: %02X", s->RCR1, s->RCR2);
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "SPU"))
|
||||
{
|
||||
spu_state_t const *s = world[i];
|
||||
|
||||
#ifdef FX9860G
|
||||
dprint(1, 1, C_BLACK, "PBANKC0: %08X", s->PBANKC0);
|
||||
dprint(1, 7, C_BLACK, "PBANKC1: %08X", s->PBANKC1);
|
||||
dprint(1, 13, C_BLACK, "XBANKC0: %08X", s->XBANKC0);
|
||||
dprint(1, 19, C_BLACK, "XBANKC1: %08X", s->XBANKC1);
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
row_print(3,1, "PBANKC0: %08X PBANKC1: %08X", s->PBANKC0, s->PBANKC1);
|
||||
row_print(4,1, "XBANKC0: %08X XBANKC1: %08X", s->XBANKC0, s->XBANKC1);
|
||||
#endif
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "T6K11"))
|
||||
{
|
||||
t6k11_state_t const *s = world[i];
|
||||
dprint(1, 1, C_BLACK, "STRD: %02X", s->STRD);
|
||||
dprint(1, 7, C_BLACK, "RESET:%d", (s->STRD & 0x08) != 0);
|
||||
dprint(1, 13, C_BLACK, "N/F:%d", (s->STRD & 0x04) != 0);
|
||||
dprint(1, 19, C_BLACK, "X/Y:%d", (s->STRD & 0x02) != 0);
|
||||
dprint(1, 25, C_BLACK, "U/D:%d", (s->STRD & 0x01) != 0);
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "TMU"))
|
||||
{
|
||||
tmu_state_t const *s = world[i];
|
||||
|
||||
for(int k = 0; k < 9; k++) {
|
||||
#ifdef FX9860G
|
||||
if(k < 3) dprint(1, 6*k, C_BLACK, "TMU%d: CNT:%08X TCR:%04X %s",
|
||||
k, s->t[k].TCNT, s->t[k].TCR, (s->TSTR & (1<<k) ? "STR" : ""));
|
||||
else dprint(1, 6*k, C_BLACK, "E%d: TCNT:%08X TCR:%02X TSTR:%02X",
|
||||
k-3, s->t[k].TCNT, s->t[k].TCR, s->t[k].TSTR);
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
row_print(k+3, 1, "%sTMU%d:", (k<3 ? "" : "E"), (k<3 ? k : k-3));
|
||||
if(k < 3) row_print(k+3, 8, "%08X/%08X TCR:%04X",
|
||||
s->t[k].TCNT, s->t[k].TCOR, s->t[k].TCR);
|
||||
else row_print(k+3, 8,"%08X/%08X TCR:%02X TSTR:%02X",
|
||||
s->t[k].TCNT, s->t[k].TCOR, s->t[k].TCR, s->t[k].TSTR);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(!strcmp(gint_drivers[i].name, "USB"))
|
||||
{
|
||||
row_print(_(1,3), 1, "In USB test");
|
||||
}
|
||||
|
||||
dfont(old_font);
|
||||
}
|
||||
|
||||
//---
|
||||
// Manual switches with performance statistics
|
||||
//---
|
||||
|
||||
struct switch_stats {
|
||||
/* Number of empty world switches */
|
||||
int world_switch_count;
|
||||
/* Number of return-to-menu */
|
||||
int return_to_menu_count;
|
||||
/* TODO: Performance statistics for each driver */
|
||||
};
|
||||
|
||||
static void draw_manual(struct switch_stats *stats)
|
||||
{
|
||||
#ifdef FX9860G
|
||||
row_print(2, 1, "World switches: %d", stats->world_switch_count);
|
||||
row_print(3, 1, "Return-to-menu: %d", stats->return_to_menu_count);
|
||||
// row_print(4, 1, "Switch time: %d µs", stats->world_switch_time);
|
||||
row_print(5, 1, "[1]: World switch");
|
||||
row_print(6, 1, "[2]: Return-to-menu");
|
||||
row_print(7, 1, "[3]: Measure perf");
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
row_print(1, 1, "World switches performed: %d",
|
||||
stats->world_switch_count);
|
||||
row_print(2, 1, "Return-to-menu performed: %d",
|
||||
stats->return_to_menu_count);
|
||||
|
||||
row_print(11, 1, "[1]: Standard world switch");
|
||||
row_print(12, 1, "[2]: Return-to-menu with gint_osmenu()");
|
||||
row_print(13, 1, "[3]: World switch with shared libprof (TODO)");
|
||||
#endif
|
||||
}
|
||||
|
||||
//---
|
||||
// Main test
|
||||
//---
|
||||
|
||||
/* gintctl_gint_drivers(): Test the gint driver logic and world switch */
|
||||
void gintctl_gint_drivers(void)
|
||||
{
|
||||
int key=0, tab=0, list_scroll=0, list_max=_(7,12), selected_driver=0;
|
||||
struct switch_stats stats = { 0 };
|
||||
|
||||
while(key != KEY_EXIT)
|
||||
{
|
||||
dclear(C_WHITE);
|
||||
|
||||
#ifdef FX9860G
|
||||
if(tab == 0 || tab == 3) row_print(1, 1, "Drivers and worlds");
|
||||
dimage(0, 56, &img_opt_gint_drivers);
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
row_title("Drivers and world switches");
|
||||
fkey_menu(1, "DRIVERS");
|
||||
fkey_menu(2, "OS");
|
||||
fkey_menu(3, "ADDIN");
|
||||
fkey_menu(4, "MANUAL");
|
||||
#endif
|
||||
|
||||
if(tab == 0) draw_list(list_scroll, list_max);
|
||||
if(tab == 1) draw_state(gint_world_os, selected_driver);
|
||||
if(tab == 2) draw_state(gint_world_addin, selected_driver);
|
||||
if(tab == 3) draw_manual(&stats);
|
||||
dupdate();
|
||||
|
||||
key = getkey().key;
|
||||
if(key == KEY_F1) tab = 0;
|
||||
if(key == KEY_F2) tab = 1;
|
||||
if(key == KEY_F3) tab = 2;
|
||||
if(key == KEY_F4) tab = 3;
|
||||
|
||||
/* Action for list tab */
|
||||
if(tab == 0 && key == KEY_UP && list_scroll > 0)
|
||||
list_scroll--;
|
||||
if(tab == 0 && key == KEY_DOWN && list_scroll <
|
||||
(int)gint_driver_count() - list_max)
|
||||
list_scroll++;
|
||||
|
||||
/* Actions for OS state tab */
|
||||
if((tab == 1 || tab == 2) && key == KEY_LEFT && selected_driver > 0)
|
||||
selected_driver--;
|
||||
if((tab == 1 || tab == 2) && key == KEY_RIGHT
|
||||
&& selected_driver < (int)gint_driver_count()-1)
|
||||
selected_driver++;
|
||||
|
||||
/* Actions for the manual tab */
|
||||
if(tab == 3 && key == KEY_1)
|
||||
gint_world_switch(GINT_CALL_INC(&stats.world_switch_count));
|
||||
if(tab == 3 && key == KEY_2)
|
||||
{
|
||||
/* TODO: Should render next frame in advance for seamless return */
|
||||
stats.return_to_menu_count++;
|
||||
dupdate();
|
||||
|
||||
gint_osmenu();
|
||||
/* Wait for KEY_2 to be released before calling next getkey() */
|
||||
while(keydown(KEY_2)) waitevent(NULL);
|
||||
}
|
||||
if(tab == 3 && key == KEY_3)
|
||||
{
|
||||
/* TODO: World switch with performance statistics */
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,13 +15,6 @@ struct region {
|
|||
int segment_count;
|
||||
};
|
||||
|
||||
struct {
|
||||
int region;
|
||||
int segment;
|
||||
char filename[30];
|
||||
int retcode;
|
||||
} dump;
|
||||
|
||||
static struct region const regs[] = {
|
||||
#ifdef FX9860G
|
||||
{ "ROM", 0x80000000, 0x807fffff, 8 },
|
||||
|
@ -36,15 +29,15 @@ static struct region const regs[] = {
|
|||
#endif
|
||||
};
|
||||
|
||||
static void switch_dump(void)
|
||||
static void switch_dump(int region, int segment, char *filename, int *retcode)
|
||||
{
|
||||
uint32_t start = regs[dump.region].start;
|
||||
int size = regs[dump.region].end + 1 - start;
|
||||
uint32_t start = regs[region].start;
|
||||
int size = regs[region].end + 1 - start;
|
||||
|
||||
/* For segmented regions, use blocks of 1M */
|
||||
if(regs[dump.region].segment_count > 1)
|
||||
if(regs[region].segment_count > 1)
|
||||
{
|
||||
start += dump.segment << 20;
|
||||
start += segment << 20;
|
||||
size = 1 << 20;
|
||||
}
|
||||
|
||||
|
@ -52,35 +45,34 @@ static void switch_dump(void)
|
|||
size &= ~1;
|
||||
|
||||
uint16_t file[30] = { 0 };
|
||||
for(int i = 0; i < 30; i++) file[i] = dump.filename[i];
|
||||
for(int i = 0; i < 30; i++) file[i] = filename[i];
|
||||
|
||||
dump.retcode = 1;
|
||||
*retcode = 1;
|
||||
|
||||
int x = BFile_Remove(file);
|
||||
if(x < 0 && x != -1) { dump.retcode = x; return; }
|
||||
if(x < 0 && x != -1) { *retcode = x; return; }
|
||||
|
||||
x = BFile_Create(file, BFile_File, &size);
|
||||
if(x < 0) { dump.retcode = x; return; }
|
||||
if(x < 0) { *retcode = x; return; }
|
||||
|
||||
int fd = BFile_Open(file, BFile_WriteOnly);
|
||||
if(fd < 0) { dump.retcode = fd; return; }
|
||||
if(fd < 0) { *retcode = fd; return; }
|
||||
|
||||
x = BFile_Write(fd, (void *)start, size);
|
||||
if(x < 0) { dump.retcode = x; return; }
|
||||
if(x < 0) { *retcode = x; return; }
|
||||
|
||||
BFile_Close(fd);
|
||||
}
|
||||
|
||||
static int do_dump(int region, int segment)
|
||||
{
|
||||
/* Pass around parameters through the global variable */
|
||||
dump.region = region;
|
||||
dump.segment = segment;
|
||||
sprintf(dump.filename, "\\\\fls0\\%s%02x.bin", regs[region].name,
|
||||
segment);
|
||||
char filename[30];
|
||||
int retcode = 0;
|
||||
|
||||
gint_switch(switch_dump);
|
||||
return dump.retcode;
|
||||
sprintf(filename, "\\\\fls0\\%s%02x.bin", regs[region].name, segment);
|
||||
gint_world_switch(GINT_CALL(switch_dump,region,segment,filename,&retcode));
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/* gintctl_gint_dump(): Dump memory to filesystem */
|
||||
|
|
|
@ -1,276 +0,0 @@
|
|||
#include <gint/gint.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/drivers.h>
|
||||
#include <gint/clock.h>
|
||||
#include <gint/hardware.h>
|
||||
#include <gint/mpu/tmu.h>
|
||||
#include <gint/mpu/dma.h>
|
||||
#include <gint/std/string.h>
|
||||
|
||||
#include <gintctl/gint.h>
|
||||
#include <gintctl/util.h>
|
||||
|
||||
static int switches = 0;
|
||||
static int menus = 0;
|
||||
|
||||
static void switch_function(void)
|
||||
{
|
||||
switches++;
|
||||
}
|
||||
|
||||
//---
|
||||
// Saved system context visualizer
|
||||
//---
|
||||
|
||||
void *driver_ctx(char const *name)
|
||||
{
|
||||
extern gint_driver_t bdrv, edrv;
|
||||
for(gint_driver_t *drv = &bdrv; drv < &edrv; drv++)
|
||||
{
|
||||
if(!strcmp(drv->name, name)) return drv->sys_ctx;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef FX9860G
|
||||
static void ctx_tmu()
|
||||
{
|
||||
tmu_t *t = driver_ctx("TMU");
|
||||
uint8_t *TSTR = (void *)t + 3 * sizeof(tmu_t) + 6 * sizeof(etmu_t);
|
||||
|
||||
for(int i = 0; i < 3; i++, t++)
|
||||
{
|
||||
row_print(2*i+1, 1, "TMU%d=%d CNT:%08x", i,
|
||||
(*TSTR & (1 << i)) != 0, t->TCNT);
|
||||
row_print(2*i+2, 1, "TCR:%04x COR:%08x", t->TCR.word, t->TCOR);
|
||||
}
|
||||
}
|
||||
static void ctx_dd()
|
||||
{
|
||||
uint8_t *STRD = driver_ctx("T6K11");
|
||||
|
||||
row_print(1, 1, "STRD:%02x", *STRD);
|
||||
row_print(2, 2, "RESET:%d", (*STRD & 0x08) != 0);
|
||||
row_print(3, 2, "N/F:%d", (*STRD & 0x04) != 0);
|
||||
row_print(4, 2, "X/Y:%d", (*STRD & 0x02) != 0);
|
||||
row_print(5, 2, "U/D:%d", (*STRD & 0x01) != 0);
|
||||
}
|
||||
static void ctx_rtc()
|
||||
{
|
||||
uint8_t *ctx = driver_ctx("RTC");
|
||||
if(!ctx) return;
|
||||
|
||||
uint8_t RCR1=ctx[0], RCR2=ctx[1];
|
||||
row_print(1, 1, "RCR1:%02x", RCR1);
|
||||
row_print(2, 1, "RCR2:%02x", RCR2);
|
||||
}
|
||||
static void show_etmu(int line, int id, etmu_t *t)
|
||||
{
|
||||
row_print(line, 1, "ETMU%d=%-3dCNT:%08x", id, t->TSTR, t->TCNT);
|
||||
row_print(line+1, 1, "TCR:%02x COR:%08x", t->TCR.byte, t->TCOR);
|
||||
}
|
||||
static void ctx_etmu(int start)
|
||||
{
|
||||
etmu_t *t = driver_ctx("TMU") + 3 * sizeof(tmu_t);
|
||||
int length = 3;
|
||||
|
||||
if(isSH3()) length=1, start=0;
|
||||
|
||||
t += start;
|
||||
for(int i = 0; i < length; i++, t++)
|
||||
{
|
||||
show_etmu(2*i+1, i+start, t);
|
||||
}
|
||||
}
|
||||
static void ctx_intc()
|
||||
{
|
||||
uint16_t *IPR = driver_ctx("INTC");
|
||||
|
||||
if(isSH3())
|
||||
{
|
||||
row_print(1,1, "A:%04x B:%04x C:%04x", IPR[0], IPR[1], IPR[2]);
|
||||
row_print(2,1, "D:%04x E:%04x F:%04x", IPR[3], IPR[4], IPR[5]);
|
||||
row_print(3,1, "G:%04x H:%04x", IPR[6], IPR[7]);
|
||||
}
|
||||
else
|
||||
{
|
||||
row_print(1,1, "A:%04x B:%04x C:%04x", IPR[0], IPR[1], IPR[2]);
|
||||
row_print(2,1, "D:%04x E:%04x F:%04x", IPR[3], IPR[4], IPR[5]);
|
||||
row_print(3,1, "G:%04x H:%04x I:%04x", IPR[6], IPR[7], IPR[8]);
|
||||
row_print(4,1, "J:%04x K:%04x L:%04x", IPR[9],IPR[10],IPR[11]);
|
||||
}
|
||||
}
|
||||
#endif /* FX9860G */
|
||||
|
||||
#ifdef FXCG50
|
||||
static void ctx_tmu()
|
||||
{
|
||||
tmu_t *t = driver_ctx("TMU");
|
||||
etmu_t *e = (void *)(t + 3);
|
||||
uint8_t *TSTR = (void *)(e + 6);
|
||||
|
||||
int const x[] = { 6, 138, 270, 6, 138, 270, 6, 138, 270 };
|
||||
int const y[] = { 24, 24, 24, 84, 84, 84, 144, 144, 144 };
|
||||
|
||||
tmu_print(x[0], y[0], "TMU0", t+0, *TSTR & 0x1);
|
||||
tmu_print(x[1], y[1], "TMU1", t+1, *TSTR & 0x2);
|
||||
tmu_print(x[2], y[2], "TMU2", t+2, *TSTR & 0x4);
|
||||
|
||||
etmu_print(x[3], y[3], "ETMU0", e+0);
|
||||
etmu_print(x[4], y[4], "ETMU1", e+1);
|
||||
etmu_print(x[5], y[5], "ETMU2", e+2);
|
||||
|
||||
etmu_print(x[6], y[6], "ETMU3", e+3);
|
||||
etmu_print(x[7], y[7], "ETMU4", e+4);
|
||||
etmu_print(x[8], y[8], "ETMU5", e+5);
|
||||
}
|
||||
static void ctx_dd()
|
||||
{
|
||||
uint16_t *win = driver_ctx("R61524");
|
||||
uint16_t HSA = win[0], HEA = win[1], VSA = win[2], VEA = win[3];
|
||||
|
||||
row_print(1, 1, "Horizontal range: %d..%d", HSA, HEA);
|
||||
row_print(2, 1, "Vertical range: %d..%d", VSA, VEA);
|
||||
}
|
||||
static void ctx_rtc()
|
||||
{
|
||||
uint8_t *ctx = driver_ctx("RTC");
|
||||
if(!ctx) return;
|
||||
|
||||
uint8_t RCR1=ctx[0], RCR2=ctx[1];
|
||||
row_print(1, 1, "RCR1:%02x", RCR1);
|
||||
row_print(2, 1, "RCR2:%02x", RCR2);
|
||||
}
|
||||
static void ctx_dma()
|
||||
{
|
||||
sh7305_dma_channel_t *ch = driver_ctx("DMA0");
|
||||
int *clock = (void *)(ch + 6);
|
||||
uint16_t *OR = (void *)(clock + 1);
|
||||
|
||||
show_dma(6, 24, 0, ch+0);
|
||||
show_dma(138, 24, 1, ch+1);
|
||||
show_dma(270, 24, 2, ch+2);
|
||||
|
||||
show_dma(6, 104, 3, ch+3);
|
||||
show_dma(138, 104, 4, ch+4);
|
||||
show_dma(270, 104, 5, ch+5);
|
||||
|
||||
dprint(6, 184, C_BLACK, "DMAOR: %08X", *OR);
|
||||
dprint(198, 184, C_BLACK, "Clock enabled: %s",(*clock ? "No" : "Yes"));
|
||||
}
|
||||
#endif /* FXCG50 */
|
||||
|
||||
static void system_contexts(void)
|
||||
{
|
||||
int key=0, tab=0;
|
||||
|
||||
while(key != KEY_EXIT)
|
||||
{
|
||||
dclear(C_WHITE);
|
||||
|
||||
#ifdef FX9860G
|
||||
extern bopti_image_t img_opt_switch_ctx_sh3;
|
||||
extern bopti_image_t img_opt_switch_ctx;
|
||||
|
||||
if(isSH3())
|
||||
dimage(0, 56, &img_opt_switch_ctx_sh3);
|
||||
else
|
||||
dimage(0, 56, &img_opt_switch_ctx);
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
row_title("System context visualizer");
|
||||
fkey_button(1, "TMU");
|
||||
fkey_button(2, "R61524");
|
||||
fkey_button(3, "RTC");
|
||||
fkey_button(4, "DMA");
|
||||
#endif
|
||||
|
||||
if(tab == 0) ctx_tmu();
|
||||
if(tab == 1) ctx_dd();
|
||||
if(tab == 2) ctx_rtc();
|
||||
|
||||
#ifdef FX9860G
|
||||
if(tab == 3) ctx_etmu(0);
|
||||
if(tab == 4) ctx_etmu(3);
|
||||
if(tab == 5) ctx_intc();
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
if(tab == 3) ctx_dma();
|
||||
#endif
|
||||
|
||||
dupdate();
|
||||
|
||||
key = getkey().key;
|
||||
if(key == KEY_F1) tab = 0;
|
||||
if(key == KEY_F2) tab = 1;
|
||||
if(key == KEY_F3) tab = 2;
|
||||
if(key == KEY_F4) tab = 3;
|
||||
if(key == KEY_F6) tab = 5;
|
||||
|
||||
#ifdef FX9860G
|
||||
if(key == KEY_F5 && isSH3()) tab = 4;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//---
|
||||
// Interactive in-out switching
|
||||
//---
|
||||
|
||||
/* Render VRAM for this screen, used when returning to menu */
|
||||
void render(void)
|
||||
{
|
||||
dclear(C_WHITE);
|
||||
|
||||
#ifdef FX9860G
|
||||
extern bopti_image_t img_opt_switch;
|
||||
row_print(1, 1, "Switch to OS");
|
||||
row_print(3, 1, "Switches done: %d", switches);
|
||||
row_print(4, 1, "Menus done: %d", menus);
|
||||
|
||||
dimage(0, 56, &img_opt_switch);
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
row_title("Hot switching between gint and OS");
|
||||
row_print(2, 1, "Switches done: %d", switches);
|
||||
row_print(3, 1, "Menus done: %d", menus);
|
||||
fkey_button(1, "SWITCH");
|
||||
fkey_button(2, "MENU");
|
||||
fkey_action(6, "SYSTEM");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* gintctl_gint_switch(): Test the gint switch-in-out procedures */
|
||||
void gintctl_gint_switch(void)
|
||||
{
|
||||
int key = 0;
|
||||
|
||||
while(key != KEY_EXIT)
|
||||
{
|
||||
render();
|
||||
dupdate();
|
||||
|
||||
key = getkey().key;
|
||||
if(key == KEY_F1) gint_switch(switch_function);
|
||||
/* Wait for F2 to be released before calling next getkey() */
|
||||
if(key == KEY_F2)
|
||||
{
|
||||
/* Render next frame in advance. When we return from
|
||||
the main menu, our VRAM will be displayed but
|
||||
GetKeyWait() will not give control back until a key
|
||||
is pressed. This will make it look like we render a
|
||||
new frame right away. */
|
||||
menus++;
|
||||
render();
|
||||
dupdate();
|
||||
|
||||
gint_osmenu();
|
||||
while(keydown(KEY_F2)) waitevent(NULL);
|
||||
}
|
||||
if(key == KEY_F6) system_contexts();
|
||||
}
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
#include <gint/mpu/usb.h>
|
||||
#include <gint/usb.h>
|
||||
#include <gint/usb-ff-bulk.h>
|
||||
#include <gint/drivers.h>
|
||||
#include <gint/drivers/states.h>
|
||||
#include <gint/intc.h>
|
||||
#include <gint/mpu/power.h>
|
||||
#include <gint/mpu/cpg.h>
|
||||
|
@ -18,17 +20,6 @@
|
|||
|
||||
#define USB SH7305_USB
|
||||
|
||||
/* Copy of the context structure from the driver (edgy style but heck) */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t SYSCFG, DVSTCTR, TESTMODE, REG_C2;
|
||||
uint16_t CFIFOSEL, D0FIFOSEL, D1FIFOSEL;
|
||||
uint16_t INTENB0, BRDYENB, NRDYENB, BEMPENB, SOFCFG;
|
||||
uint16_t DCPCFG, DCPMAXP, DCPCTR;
|
||||
uint16_t PIPECFG[9], PIPEBUF[9], PIPEMAXP[9], PIPEPERI[9];
|
||||
uint16_t PIPEnCTR[9], PIPEnTRE[5], PIPEnTRN[5];
|
||||
} ctx_t;
|
||||
|
||||
/* USB log buffer */
|
||||
#define LOG_SIZE _(1023, 16383)
|
||||
static char log_buffer[LOG_SIZE+1];
|
||||
|
@ -155,25 +146,28 @@ static void draw_registers(GUNUSED int scroll)
|
|||
|
||||
static void draw_context(void)
|
||||
{
|
||||
extern void *driver_ctx(char const *name);
|
||||
ctx_t *ctx = driver_ctx("USB");
|
||||
GUNUSED int scroll = 0;
|
||||
usb_state_t *s = NULL;
|
||||
for(int i = 0; i < gint_driver_count(); i++) {
|
||||
if(!strcmp(gint_drivers[i].name, "USB")) s = gint_world_os[i];
|
||||
}
|
||||
if(!s) return;
|
||||
|
||||
val( 0, "SYSCFG", ctx->SYSCFG);
|
||||
val( 1, "DVSTCTR", ctx->DVSTCTR);
|
||||
val( 2, "TESTMODE", ctx->TESTMODE);
|
||||
val( 3, "REG_C2", ctx->REG_C2);
|
||||
val( 4, "CFIFOSEL", ctx->CFIFOSEL);
|
||||
val( 5, "D0FIFOSEL", ctx->D0FIFOSEL);
|
||||
val( 6, "D1FIFOSEL", ctx->D1FIFOSEL);
|
||||
val( 7, "INTENB0", ctx->INTENB0);
|
||||
val( 8, "BRDYENB", ctx->BRDYENB);
|
||||
val( 9, "NRDYENB", ctx->NRDYENB);
|
||||
val(10, "BEMPENB", ctx->BEMPENB);
|
||||
val(11, "SOFCFG", ctx->SOFCFG);
|
||||
val(12, "DCPCFG", ctx->DCPCFG);
|
||||
val(13, "DCPMAXP", ctx->DCPMAXP);
|
||||
val(14, "DCPCTR", ctx->DCPCTR);
|
||||
GUNUSED int scroll = 0;
|
||||
val( 0, "SYSCFG", s->SYSCFG);
|
||||
val( 1, "DVSTCTR", s->DVSTCTR);
|
||||
val( 2, "TESTMODE", s->TESTMODE);
|
||||
val( 3, "REG_C2", s->REG_C2);
|
||||
val( 4, "CFIFOSEL", s->CFIFOSEL);
|
||||
val( 5, "D0FIFOSEL", s->D0FIFOSEL);
|
||||
val( 6, "D1FIFOSEL", s->D1FIFOSEL);
|
||||
val( 7, "INTENB0", s->INTENB0);
|
||||
val( 8, "BRDYENB", s->BRDYENB);
|
||||
val( 9, "NRDYENB", s->NRDYENB);
|
||||
val(10, "BEMPENB", s->BEMPENB);
|
||||
val(11, "SOFCFG", s->SOFCFG);
|
||||
val(12, "DCPCFG", s->DCPCFG);
|
||||
val(13, "DCPMAXP", s->DCPMAXP);
|
||||
val(14, "DCPCTR", s->DCPCTR);
|
||||
|
||||
// uint16_t PIPECFG[9], PIPEBUF[9], PIPEMAXP[9], PIPEPERI[9];
|
||||
// uint16_t PIPEnCTR[9], PIPEnTRE[5], PIPEnTRN[5];
|
||||
|
@ -305,7 +299,8 @@ void gintctl_gint_usb(void)
|
|||
if(key == KEY_F3) tab = 2;
|
||||
if(key == KEY_F4) tab = 3;
|
||||
|
||||
if(tab == 2 && key == KEY_F5) gint_switch(save_logger);
|
||||
if(tab == 2 && key == KEY_F5)
|
||||
gint_world_switch(GINT_CALL(save_logger));
|
||||
|
||||
if(key == KEY_F6)
|
||||
{
|
||||
|
@ -313,7 +308,7 @@ void gintctl_gint_usb(void)
|
|||
else
|
||||
{
|
||||
usb_interface_t const *interfaces[] = { &usb_ff_bulk, NULL };
|
||||
int rc = usb_open(interfaces, GINT_CB(open_callback));
|
||||
int rc = usb_open(interfaces, GINT_CALL(open_callback));
|
||||
open = (rc == 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,29 +27,27 @@
|
|||
struct menu menu_gint = {
|
||||
_("gint tests", "gint features and driver tests"), .entries = {
|
||||
|
||||
{ "CPU and memory", gintctl_gint_cpumem, 0 },
|
||||
{ "RAM discovery", gintctl_gint_ram, MENU_SH4_ONLY },
|
||||
{ "CPU and memory", gintctl_gint_cpumem, 0 },
|
||||
{ "RAM discovery", gintctl_gint_ram, MENU_SH4_ONLY },
|
||||
#ifdef FXCG50
|
||||
{ "DSP processors", gintctl_gint_dsp, 0 },
|
||||
{ "DSP processors", gintctl_gint_dsp, 0 },
|
||||
#endif
|
||||
{ "SPU memory", gintctl_gint_spuram, MENU_SH4_ONLY },
|
||||
{ "Memory dump", gintctl_gint_dump, 0 },
|
||||
{ "Switching to OS", gintctl_gint_switch, 0 },
|
||||
{ "TLB management", gintctl_gint_tlb, 0 },
|
||||
{ "Memory allocation",gintctl_gint_kmalloc, 0 },
|
||||
{ "Keyboard", gintctl_gint_keyboard, 0 },
|
||||
{ "Timers", gintctl_gint_timer, 0 },
|
||||
{ "Timer callbacks", gintctl_gint_timer_callbacks, 0 },
|
||||
#ifdef FXCG50
|
||||
{ "DMA control", gintctl_gint_dma, 0 },
|
||||
#endif
|
||||
{ "Real-time clock", gintctl_gint_rtc, 0 },
|
||||
{ "USB communication",gintctl_gint_usb, MENU_SH4_ONLY },
|
||||
{ "Image rendering", gintctl_gint_bopti, 0 },
|
||||
{ "Text rendering", gintctl_gint_topti, 0 },
|
||||
{ "SPU memory", gintctl_gint_spuram, MENU_SH4_ONLY },
|
||||
{ "Memory dump", gintctl_gint_dump, 0 },
|
||||
{ "Drivers and worlds", gintctl_gint_drivers, 0 },
|
||||
{ "TLB management", gintctl_gint_tlb, 0 },
|
||||
{ "Memory allocation", gintctl_gint_kmalloc, 0 },
|
||||
{ "Keyboard", gintctl_gint_keyboard, 0 },
|
||||
{ "Timers", gintctl_gint_timer, 0 },
|
||||
{ "Timer callbacks", gintctl_gint_timer_callbacks, 0 },
|
||||
{ "DMA control", gintctl_gint_dma, MENU_SH4_ONLY },
|
||||
{ "Real-time clock", gintctl_gint_rtc, 0 },
|
||||
{ "USB communication", gintctl_gint_usb, MENU_SH4_ONLY },
|
||||
{ "Image rendering", gintctl_gint_bopti, 0 },
|
||||
{ "Text rendering", gintctl_gint_topti, 0 },
|
||||
#ifdef FX9860G
|
||||
{ "Gray engine", gintctl_gint_gray, 0 },
|
||||
{ "Gray rendering", gintctl_gint_grayrender, 0 },
|
||||
{ "Gray engine", gintctl_gint_gray, 0 },
|
||||
{ "Gray rendering", gintctl_gint_grayrender, 0 },
|
||||
#endif
|
||||
{ NULL, NULL, 0 },
|
||||
}};
|
||||
|
@ -61,9 +59,7 @@ struct menu menu_perf = {
|
|||
{ "libprof basics", gintctl_perf_libprof, 0 },
|
||||
{ "CPU and cache", gintctl_perf_cpucache, 0 },
|
||||
{ "Interrupt stress", gintctl_perf_interrupts, 0 },
|
||||
#ifdef FXCG50
|
||||
{ "Memory access speed", gintctl_perf_memory, 0 },
|
||||
#endif
|
||||
{ "Rendering functions", gintctl_perf_render, 0 },
|
||||
|
||||
/* TODO: Comparison with MonochromeLib */
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
#include <gint/hardware.h>
|
||||
#include <gint/dma.h>
|
||||
#include <gint/std/string.h>
|
||||
#include <gint/mmu.h>
|
||||
|
||||
#include <gintctl/perf.h>
|
||||
#include <gintctl/util.h>
|
||||
#include <gintctl/assets.h>
|
||||
|
||||
#include <libprof.h>
|
||||
|
||||
|
@ -104,17 +106,13 @@ static void test(struct results *r, void *address, uint32_t size, int rounds)
|
|||
});
|
||||
|
||||
r->dma_memset_time = prof_exec({
|
||||
#ifdef FXCG50
|
||||
for(int i = 0; i < rounds; i++)
|
||||
dma_memset(address, 0, size);
|
||||
#endif
|
||||
if(isSH4()) dma_memset(address, 0, size);
|
||||
});
|
||||
|
||||
r->dma_memcpy_time = 2 * prof_exec({
|
||||
#ifdef FXCG50
|
||||
for(int i = 0; i < rounds; i++)
|
||||
dma_memcpy(address + size / 2, address, size / 2);
|
||||
#endif
|
||||
if(isSH4()) dma_memcpy(address + size / 2, address, size / 2);
|
||||
});
|
||||
|
||||
if(address == &xram_buffer)
|
||||
|
@ -122,14 +120,14 @@ static void test(struct results *r, void *address, uint32_t size, int rounds)
|
|||
/* Since the buffers are small, repeat 16 times */
|
||||
r->dsp_xram_memset_time = prof_exec({
|
||||
for(int i = 0; i < rounds; i++)
|
||||
memory_dsp_xram_memset(address, size);
|
||||
if(isSH4()) memory_dsp_xram_memset(address, size);
|
||||
});
|
||||
}
|
||||
if(address == &yram_buffer)
|
||||
{
|
||||
r->dsp_yram_memset_time = prof_exec({
|
||||
for(int i = 0; i < rounds; i++)
|
||||
memory_dsp_yram_memset(address, size);
|
||||
if(isSH4()) memory_dsp_yram_memset(address, size);
|
||||
});
|
||||
}
|
||||
if(address == &xram_buffer)
|
||||
|
@ -140,7 +138,7 @@ static void test(struct results *r, void *address, uint32_t size, int rounds)
|
|||
/* Since the buffers are small, repeat 16 times */
|
||||
r->dsp_xyram_memcpy_time = prof_exec({
|
||||
for(int i = 0; i < rounds; i++)
|
||||
memory_dsp_xyram_memcpy(y, x, size);
|
||||
if(isSH4()) memory_dsp_xyram_memcpy(y, x, size);
|
||||
});
|
||||
}
|
||||
if(address == &yram_buffer)
|
||||
|
@ -150,7 +148,7 @@ static void test(struct results *r, void *address, uint32_t size, int rounds)
|
|||
|
||||
r->dsp_xyram_memcpy_time = prof_exec({
|
||||
for(int i = 0; i < rounds; i++)
|
||||
memory_dsp_xyram_memcpy(x, y, size);
|
||||
if(isSH4()) memory_dsp_xyram_memcpy(x, y, size);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -171,25 +169,76 @@ static void test(struct results *r, void *address, uint32_t size, int rounds)
|
|||
|
||||
static void results_line(int row, uint32_t time, uint32_t speed)
|
||||
{
|
||||
dprint_opt(260, row_y(row), C_BLACK, C_NONE, DTEXT_RIGHT, DTEXT_TOP,
|
||||
int y = _(8+6*row, row_y(row));
|
||||
dprint_opt(_(80,260), y, C_BLACK, C_NONE, DTEXT_RIGHT, DTEXT_TOP,
|
||||
"%d us", time);
|
||||
dprint_opt(370, row_y(row), C_BLACK, C_NONE, DTEXT_RIGHT, DTEXT_TOP,
|
||||
"%3.3j MB/s", speed);
|
||||
dprint_opt(_(125,370), y, C_BLACK, C_NONE, DTEXT_RIGHT, DTEXT_TOP,
|
||||
_("%3.1j MB/s", "%3.3j MB/s"), _(speed/100, speed));
|
||||
}
|
||||
|
||||
/* gintctl_perf_memory(): Memory primitives and reading/writing speed */
|
||||
void gintctl_perf_memory(void)
|
||||
{
|
||||
/* TODO: Memory performance on SH3 */
|
||||
if(isSH3()) return;
|
||||
|
||||
int key = 0;
|
||||
struct results r = { 0 };
|
||||
|
||||
/* Get the physical VRAM address */
|
||||
void *vram_address = gint_vram;
|
||||
#ifdef FX9860G
|
||||
uint32_t virt_page = (uint32_t)vram_address & 0xfffff000;
|
||||
uint32_t phys_page = 0x80000000 + mmu_translate(virt_page, NULL);
|
||||
vram_address = (void *)phys_page + (vram_address - (void *)virt_page);
|
||||
#endif
|
||||
|
||||
while(key != KEY_EXIT)
|
||||
{
|
||||
dclear(C_WHITE);
|
||||
row_title("Memory access speed");
|
||||
font_t const *old_font = dfont(_(&font_mini, dfont_default()));
|
||||
|
||||
#ifdef FX9860G
|
||||
/* Due to less space, focus on the non-trivial methods */
|
||||
dprint(1, 14, C_BLACK, "gint memcpy:");
|
||||
dprint(1, 20, C_BLACK, "gint memset:");
|
||||
if(isSH4()) {
|
||||
dprint(1, 26, C_BLACK, "dma_memcpy:");
|
||||
dprint(1, 32, C_BLACK, "dma_memset:");
|
||||
|
||||
if(r.address == &xram_buffer)
|
||||
dprint(1, 38, C_BLACK, "DSP memset:");
|
||||
if(r.address == &yram_buffer)
|
||||
dprint(1, 38, C_BLACK, "DSP memset:");
|
||||
if(r.address == &xram_buffer || r.address == &yram_buffer)
|
||||
dprint(1, 44, C_BLACK, "DSP memcpy:");
|
||||
}
|
||||
|
||||
if(!r.address) dprint(1, 8, C_BLACK, "No test yet");
|
||||
else
|
||||
{
|
||||
dprint(1, 8, C_BLACK, "Area: %08X (%d B, %d round%s)",
|
||||
(uint32_t)r.address, r.size, r.rounds, (r.rounds>1)?"s":"");
|
||||
results_line(1, r.memcpy_time, r.memcpy_speed);
|
||||
results_line(2, r.memset_time, r.memset_speed);
|
||||
if(isSH4()) {
|
||||
results_line(3, r.dma_memcpy_time, r.dma_memcpy_speed);
|
||||
results_line(4, r.dma_memset_time, r.dma_memset_speed);
|
||||
if(r.address == &xram_buffer)
|
||||
results_line(5, r.dsp_xram_memset_time,
|
||||
r.dsp_xram_memset_speed);
|
||||
if(r.address == &yram_buffer)
|
||||
results_line(5, r.dsp_yram_memset_time,
|
||||
r.dsp_yram_memset_speed);
|
||||
if(r.address==&xram_buffer || r.address==&yram_buffer)
|
||||
results_line(6, r.dsp_xyram_memcpy_time,
|
||||
r.dsp_xyram_memcpy_speed);
|
||||
}
|
||||
}
|
||||
|
||||
if(isSH3())
|
||||
dimage(0, 56, &img_opt_perf_memory_sh3);
|
||||
else
|
||||
dimage(0, 56, &img_opt_perf_memory);
|
||||
#endif
|
||||
|
||||
#ifdef FXCG50
|
||||
row_print( 3, 1, "Naive C-loop u8 read:");
|
||||
|
@ -208,10 +257,7 @@ void gintctl_perf_memory(void)
|
|||
if(r.address == &xram_buffer || r.address == &yram_buffer)
|
||||
row_print(12, 1, "DSP XRAM->YRAM memcpy():");
|
||||
|
||||
if(!r.address)
|
||||
{
|
||||
row_print(1, 1, "No test yet");
|
||||
}
|
||||
if(!r.address) row_print(1, 1, "No test yet");
|
||||
else
|
||||
{
|
||||
row_print(1, 1, "Results for area %08x (%d bytes, %d "
|
||||
|
@ -227,20 +273,14 @@ void gintctl_perf_memory(void)
|
|||
results_line(10,r.dma_memset_time, r.dma_memset_speed);
|
||||
|
||||
if(r.address == &xram_buffer)
|
||||
{
|
||||
results_line(11, r.dsp_xram_memset_time,
|
||||
r.dsp_xram_memset_speed);
|
||||
}
|
||||
if(r.address == &yram_buffer)
|
||||
{
|
||||
results_line(11, r.dsp_yram_memset_time,
|
||||
r.dsp_yram_memset_speed);
|
||||
}
|
||||
if(r.address==&xram_buffer || r.address==&yram_buffer)
|
||||
{
|
||||
results_line(12, r.dsp_xyram_memcpy_time,
|
||||
r.dsp_xyram_memcpy_speed);
|
||||
}
|
||||
}
|
||||
|
||||
fkey_button(1, "RAM");
|
||||
|
@ -249,12 +289,15 @@ void gintctl_perf_memory(void)
|
|||
fkey_button(4, "YRAM");
|
||||
#endif
|
||||
|
||||
dfont(old_font);
|
||||
dupdate();
|
||||
key = getkey().key;
|
||||
|
||||
if(key == KEY_F1) test(&r, gint_vram, _(0x400,0x8000), 1);
|
||||
if(key == KEY_F2) test(&r, &ilram_buffer, 0x800, 64);
|
||||
if(key == KEY_F3) test(&r, &xram_buffer, 0x800, 64);
|
||||
if(key == KEY_F4) test(&r, &yram_buffer, 0x800, 64);
|
||||
if(key == KEY_F1) test(&r, vram_address, _(0x400,0x8000), _(32,1));
|
||||
if(isSH4()) {
|
||||
if(key == KEY_F2) test(&r, &ilram_buffer, 0x800, 64);
|
||||
if(key == KEY_F3) test(&r, &xram_buffer, 0x800, 64);
|
||||
if(key == KEY_F4) test(&r, &yram_buffer, 0x800, 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,9 +218,7 @@ void fkey_menu(int position, char const *text)
|
|||
// Screenshot saving
|
||||
//---
|
||||
|
||||
static uint16_t const *path;
|
||||
|
||||
void switch_screen_mono(void)
|
||||
void switch_screen_mono(uint16_t const *path)
|
||||
{
|
||||
int size = 1024;
|
||||
|
||||
|
@ -235,6 +233,5 @@ void switch_screen_mono(void)
|
|||
/* screen_mono(): Take a screenshot of the mono VRAM */
|
||||
void screen_mono(uint16_t const *filepath)
|
||||
{
|
||||
path = filepath;
|
||||
gint_switch(switch_screen_mono);
|
||||
gint_world_switch(GINT_CALL(switch_screen_mono, filepath));
|
||||
}
|
||||
|
|