sharc: Cycle-based DMA. Added support for write stalling.

This commit is contained in:
Ville Linde 2021-06-17 17:59:35 +03:00
parent 16a85237c7
commit 5211a003a5
6 changed files with 172 additions and 30 deletions

View File

@ -343,7 +343,10 @@ void adsp21062_device::iop_w(offs_t offset, uint32_t data)
case 0x1c: case 0x1c:
{ {
m_core->dma[6].control = data; m_core->dma[6].control = data;
sharc_iop_delayed_w(0x1c, data, 1); if (data & 0x1)
{
sharc_iop_delayed_w(0x1c, data, 1);
}
break; break;
} }
@ -360,9 +363,12 @@ void adsp21062_device::iop_w(offs_t offset, uint32_t data)
// DMA 7 // DMA 7
case 0x1d: case 0x1d:
{ {
m_core->dma[7].control = data; m_core->dma[7].control = data;
sharc_iop_delayed_w(0x1d, data, 30); if (data & 0x1)
{
sharc_iop_delayed_w(0x1d, data, 30);
}
break; break;
} }
@ -442,7 +448,7 @@ void adsp21062_device::external_dma_write(uint32_t address, uint64_t data)
All addresses in the 17-bit index registers are offset by 0x0002 0000, the All addresses in the 17-bit index registers are offset by 0x0002 0000, the
first internal RAM location, before they are used by the DMA controller. first internal RAM location, before they are used by the DMA controller.
*/ */
switch ((m_core->dma[6].control >> 6) & 0x3) switch ((m_core->dma[6].control >> 6) & 0x3)
{ {
case 2: // 16/48 packing case 2: // 16/48 packing
@ -972,6 +978,11 @@ void adsp21062_device::set_flag_input(int flag_num, int state)
} }
} }
WRITE_LINE_MEMBER(adsp21062_device::write_stall)
{
m_core->write_stalled = (state == 0) ? false : true;
}
void adsp21062_device::check_interrupts() void adsp21062_device::check_interrupts()
{ {
int i; int i;
@ -1028,8 +1039,24 @@ void adsp21062_device::execute_run()
} }
else else
{ {
if (m_core->write_stalled)
eat_cycles(m_core->icount);
if (m_core->idle && m_core->irq_pending == 0) if (m_core->idle && m_core->irq_pending == 0)
{ {
int dma_count = m_core->icount;
// run active DMAs even while idling
while (dma_count > 0 && m_core->dma_status & ((1 << 6) | (1 << 7)))
{
if (!m_core->write_stalled)
{
dma_run_cycle(6);
dma_run_cycle(7);
}
dma_count--;
}
m_core->icount = 0; m_core->icount = 0;
debugger_instruction_hook(m_core->daddr); debugger_instruction_hook(m_core->daddr);
} }
@ -1037,9 +1064,9 @@ void adsp21062_device::execute_run()
{ {
check_interrupts(); check_interrupts();
m_core->idle = 0; m_core->idle = 0;
} }
while (m_core->icount > 0 && !m_core->idle) while (m_core->icount > 0 && !m_core->idle && !m_core->write_stalled)
{ {
m_core->pc = m_core->daddr; m_core->pc = m_core->daddr;
m_core->daddr = m_core->faddr; m_core->daddr = m_core->faddr;
@ -1126,6 +1153,12 @@ void adsp21062_device::execute_run()
} }
} }
if (!m_core->write_stalled)
{
dma_run_cycle(6);
dma_run_cycle(7);
}
--m_core->icount; --m_core->icount;
}; };
} }

View File

@ -103,6 +103,8 @@ public:
TIMER_CALLBACK_MEMBER(sharc_iop_delayed_write_callback); TIMER_CALLBACK_MEMBER(sharc_iop_delayed_write_callback);
TIMER_CALLBACK_MEMBER(sharc_dma_callback); TIMER_CALLBACK_MEMBER(sharc_dma_callback);
WRITE_LINE_MEMBER(write_stall);
void sharc_cfunc_unimplemented(); void sharc_cfunc_unimplemented();
void sharc_cfunc_read_iop(); void sharc_cfunc_read_iop();
void sharc_cfunc_write_iop(); void sharc_cfunc_write_iop();
@ -270,6 +272,7 @@ private:
int32_t chained_direction; int32_t chained_direction;
emu_timer *timer; emu_timer *timer;
bool active; bool active;
bool chained;
}; };
@ -379,6 +382,7 @@ private:
SHARC_DMA_OP dma_op[12]; SHARC_DMA_OP dma_op[12];
uint32_t dma_status; uint32_t dma_status;
bool write_stalled;
int32_t interrupt_active; int32_t interrupt_active;
@ -475,6 +479,7 @@ private:
void schedule_dma_op(int channel, uint32_t src, uint32_t dst, int src_modifier, int dst_modifier, int src_count, int dst_count, int pmode); void schedule_dma_op(int channel, uint32_t src, uint32_t dst, int src_modifier, int dst_modifier, int src_count, int dst_count, int pmode);
void dma_op(int channel); void dma_op(int channel);
void sharc_dma_exec(int channel); void sharc_dma_exec(int channel);
void dma_run_cycle(int channel);
void add_systemreg_write_latency_effect(int sysreg, uint32_t data, uint32_t prev_data); void add_systemreg_write_latency_effect(int sysreg, uint32_t data, uint32_t prev_data);
inline void swap_register(uint32_t *a, uint32_t *b); inline void swap_register(uint32_t *a, uint32_t *b);
void systemreg_write_latency_effect(); void systemreg_write_latency_effect();

View File

@ -10,7 +10,7 @@
void adsp21062_device::schedule_chained_dma_op(int channel, uint32_t dma_chain_ptr, int chained_direction) void adsp21062_device::schedule_chained_dma_op(int channel, uint32_t dma_chain_ptr, int chained_direction)
{ {
uint32_t op_ptr = 0x20000 + dma_chain_ptr; uint32_t op_ptr = 0x20000 + (dma_chain_ptr & 0x1ffff);
uint32_t int_index = dm_read32(op_ptr - 0); uint32_t int_index = dm_read32(op_ptr - 0);
uint32_t int_modifier = dm_read32(op_ptr - 1); uint32_t int_modifier = dm_read32(op_ptr - 1);
@ -49,10 +49,14 @@ void adsp21062_device::schedule_chained_dma_op(int channel, uint32_t dma_chain_p
m_core->dma_op[channel].chain_ptr = chain_ptr; m_core->dma_op[channel].chain_ptr = chain_ptr;
m_core->dma_op[channel].chained_direction = chained_direction; m_core->dma_op[channel].chained_direction = chained_direction;
m_core->dma_op[channel].chained = true;
m_core->dma_op[channel].active = true; m_core->dma_op[channel].active = true;
int cycles = m_core->dma_op[channel].src_count / 4; if (m_enable_drc)
m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel); {
int cycles = m_core->dma_op[channel].src_count / 4;
m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel);
}
// enable busy flag // enable busy flag
m_core->dma_status |= (1 << channel); m_core->dma_status |= (1 << channel);
@ -74,15 +78,107 @@ void adsp21062_device::schedule_dma_op(int channel, uint32_t src, uint32_t dst,
m_core->dma_op[channel].pmode = pmode; m_core->dma_op[channel].pmode = pmode;
m_core->dma_op[channel].chain_ptr = 0; m_core->dma_op[channel].chain_ptr = 0;
m_core->dma_op[channel].chained = false;
m_core->dma_op[channel].active = true; m_core->dma_op[channel].active = true;
int cycles = src_count / 4; if (m_enable_drc)
m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel); {
int cycles = src_count / 4;
m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel);
}
// enable busy flag // enable busy flag
m_core->dma_status |= (1 << channel); m_core->dma_status |= (1 << channel);
} }
void adsp21062_device::dma_run_cycle(int channel)
{
if (m_core->dma_status & (1 << channel))
{
uint32_t src = m_core->dma_op[channel].src;
uint32_t dst = m_core->dma_op[channel].dst;
int src_modifier = m_core->dma_op[channel].src_modifier;
int dst_modifier = m_core->dma_op[channel].dst_modifier;
int src_count = m_core->dma_op[channel].src_count;
//int dst_count = m_core->dma_op[channel].dst_count;
int pmode = m_core->dma_op[channel].pmode;
switch (pmode)
{
case DMA_PMODE_NO_PACKING:
{
uint32_t data = dm_read32(src);
dm_write32(dst, data);
src += src_modifier;
dst += dst_modifier;
src_count--;
break;
}
case DMA_PMODE_16_32:
{
uint32_t data = ((dm_read32(src + 0) & 0xffff) << 16) | (dm_read32(src + 1) & 0xffff);
dm_write32(dst, data);
src += src_modifier * 2;
dst += dst_modifier;
src_count -= 2;
break;
}
case DMA_PMODE_8_48:
{
uint64_t data = ((uint64_t)(dm_read32(src + 0) & 0xff) << 0) |
((uint64_t)(dm_read32(src + 1) & 0xff) << 8) |
((uint64_t)(dm_read32(src + 2) & 0xff) << 16) |
((uint64_t)(dm_read32(src + 3) & 0xff) << 24) |
((uint64_t)(dm_read32(src + 4) & 0xff) << 32) |
((uint64_t)(dm_read32(src + 5) & 0xff) << 40);
pm_write48(dst, data);
src += src_modifier * 6;
dst += dst_modifier;
src_count -= 6;
break;
}
default:
{
fatalerror("SHARC: dma_op: unimplemented packing mode %d\n", pmode);
}
}
m_core->dma_op[channel].src_count = src_count;
m_core->dma_op[channel].src = src;
m_core->dma_op[channel].dst = dst;
if (src_count <= 0)
{
// clear busy flag
m_core->dma_status &= ~(1 << channel);
m_core->dma_op[channel].active = false;
// raise interrupt if
// * non-chained DMA
// * chained-DMA with PCI set in the next chain pointer
if (!m_core->dma_op[channel].chained || (m_core->dma_op[channel].chained && (m_core->dma_op[channel].chain_ptr & 0x20000)))
{
m_core->irptl |= (1 << (channel + 10));
// DMA interrupt
if (m_core->imask & (1 << (channel + 10)))
{
m_core->irq_pending |= 1 << (channel + 10);
}
}
// schedule chained op if chaining
if ((m_core->dma_op[channel].chain_ptr & 0x1ffff) != 0)
{
schedule_chained_dma_op(channel, m_core->dma_op[channel].chain_ptr, m_core->dma_op[channel].chained_direction);
}
}
}
}
void adsp21062_device::dma_op(int channel) void adsp21062_device::dma_op(int channel)
{ {
int i; int i;
@ -94,7 +190,7 @@ void adsp21062_device::dma_op(int channel)
//int dst_count = m_core->dma_op[channel].dst_count; //int dst_count = m_core->dma_op[channel].dst_count;
int pmode = m_core->dma_op[channel].pmode; int pmode = m_core->dma_op[channel].pmode;
//printf("dma_op: %08X, %08X, %08X, %08X, %08X, %d\n", src, dst, src_modifier, dst_modifier, src_count, pmode); //printf("dma_op: ch %d: %08X, %08X, %08X, %08X, %08X, %d at %08X\n", channel, src, dst, src_modifier, dst_modifier, src_count, pmode, m_core->pc);
switch (pmode) switch (pmode)
{ {
@ -191,36 +287,36 @@ void adsp21062_device::sharc_dma_exec(int channel)
{ {
uint32_t dma_chain_ptr = m_core->dma[channel].chain_ptr & 0x1ffff; uint32_t dma_chain_ptr = m_core->dma[channel].chain_ptr & 0x1ffff;
schedule_chained_dma_op(channel, dma_chain_ptr, tran); schedule_chained_dma_op(channel, dma_chain_ptr, tran);
} }
else else
{ {
if (tran) // Transmit to external if (tran) // Transmit to external
{ {
dst = m_core->dma[channel].ext_index; dst = m_core->dma[channel].ext_index;
dst_modifier = m_core->dma[channel].ext_modifier; dst_modifier = m_core->dma[channel].ext_modifier;
dst_count = m_core->dma[channel].ext_count; dst_count = m_core->dma[channel].ext_count;
src = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000; src = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
src_modifier = m_core->dma[channel].int_modifier; src_modifier = m_core->dma[channel].int_modifier;
src_count = m_core->dma[channel].int_count; src_count = m_core->dma[channel].int_count;
} }
else // Receive from external else // Receive from external
{ {
src = m_core->dma[channel].ext_index; src = m_core->dma[channel].ext_index;
src_modifier = m_core->dma[channel].ext_modifier; src_modifier = m_core->dma[channel].ext_modifier;
src_count = m_core->dma[channel].ext_count; src_count = m_core->dma[channel].ext_count;
dst = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000; dst = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
dst_modifier = m_core->dma[channel].int_modifier; dst_modifier = m_core->dma[channel].int_modifier;
dst_count = m_core->dma[channel].int_count; dst_count = m_core->dma[channel].int_count;
} }
if (dtype) if (dtype)
//if (src_count != dst_count) //if (src_count != dst_count)
{ {
pmode = DMA_PMODE_8_48; pmode = DMA_PMODE_8_48;
} }
schedule_dma_op(channel, src, dst, src_modifier, dst_modifier, src_count, dst_count, pmode); schedule_dma_op(channel, src, dst, src_modifier, dst_modifier, src_count, dst_count, pmode);
} }
} }

View File

@ -963,6 +963,7 @@ void gticlub_state::hangplt(machine_config &config)
m_voodoo[0]->set_screen_tag("lscreen"); m_voodoo[0]->set_screen_tag("lscreen");
m_voodoo[0]->set_cpu_tag(m_dsp[0]); m_voodoo[0]->set_cpu_tag(m_dsp[0]);
m_voodoo[0]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); m_voodoo[0]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_voodoo[0]->stall_callback().set(m_dsp[0], FUNC(adsp21062_device::write_stall));
VOODOO_1(config, m_voodoo[1], STD_VOODOO_1_CLOCK); VOODOO_1(config, m_voodoo[1], STD_VOODOO_1_CLOCK);
m_voodoo[1]->set_fbmem(2); m_voodoo[1]->set_fbmem(2);
@ -970,6 +971,7 @@ void gticlub_state::hangplt(machine_config &config)
m_voodoo[1]->set_screen_tag("rscreen"); m_voodoo[1]->set_screen_tag("rscreen");
m_voodoo[1]->set_cpu_tag(m_dsp[1]); m_voodoo[1]->set_cpu_tag(m_dsp[1]);
m_voodoo[1]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ1); m_voodoo[1]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ1);
m_voodoo[1]->stall_callback().set(m_dsp[1], FUNC(adsp21062_device::write_stall));
K033906(config, "k033906_1", 0, m_voodoo[0]); K033906(config, "k033906_1", 0, m_voodoo[0]);
K033906(config, "k033906_2", 0, m_voodoo[1]); K033906(config, "k033906_2", 0, m_voodoo[1]);

View File

@ -1122,6 +1122,7 @@ void hornet_state::hornet(machine_config &config)
m_voodoo[0]->set_screen_tag("screen"); m_voodoo[0]->set_screen_tag("screen");
m_voodoo[0]->set_cpu_tag(m_dsp[0]); m_voodoo[0]->set_cpu_tag(m_dsp[0]);
m_voodoo[0]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); m_voodoo[0]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_voodoo[0]->stall_callback().set(m_dsp[0], FUNC(adsp21062_device::write_stall));
K033906(config, "k033906_1", 0, m_voodoo[0]); K033906(config, "k033906_1", 0, m_voodoo[0]);
@ -1201,6 +1202,7 @@ void hornet_state::sscope(machine_config &config)
m_voodoo[1]->set_screen_tag("rscreen"); m_voodoo[1]->set_screen_tag("rscreen");
m_voodoo[1]->set_cpu_tag(m_dsp[1]); m_voodoo[1]->set_cpu_tag(m_dsp[1]);
m_voodoo[1]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ1); m_voodoo[1]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ1);
m_voodoo[1]->stall_callback().set(m_dsp[1], FUNC(adsp21062_device::write_stall));
K033906(config, "k033906_2", 0, m_voodoo[1]); K033906(config, "k033906_2", 0, m_voodoo[1]);
@ -1235,6 +1237,7 @@ void hornet_state::sscope2(machine_config &config)
m_voodoo[0]->set_screen_tag("lscreen"); m_voodoo[0]->set_screen_tag("lscreen");
m_voodoo[0]->set_cpu_tag(m_dsp[0]); m_voodoo[0]->set_cpu_tag(m_dsp[0]);
m_voodoo[0]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); m_voodoo[0]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_voodoo[0]->stall_callback().set(m_dsp[0], FUNC(adsp21062_device::write_stall));
VOODOO_2(config.replace(), m_voodoo[1], STD_VOODOO_2_CLOCK); VOODOO_2(config.replace(), m_voodoo[1], STD_VOODOO_2_CLOCK);
m_voodoo[1]->set_fbmem(2); m_voodoo[1]->set_fbmem(2);
@ -1242,6 +1245,7 @@ void hornet_state::sscope2(machine_config &config)
m_voodoo[1]->set_screen_tag("rscreen"); m_voodoo[1]->set_screen_tag("rscreen");
m_voodoo[1]->set_cpu_tag(m_dsp[1]); m_voodoo[1]->set_cpu_tag(m_dsp[1]);
m_voodoo[1]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ1); m_voodoo[1]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ1);
m_voodoo[1]->stall_callback().set(m_dsp[1], FUNC(adsp21062_device::write_stall));
DS2401(config, "lan_serial_id"); DS2401(config, "lan_serial_id");
EEPROM_93C46_16BIT(config, "lan_eeprom"); EEPROM_93C46_16BIT(config, "lan_eeprom");
@ -1394,7 +1398,7 @@ void hornet_state::init_hornet()
m_maincpu->ppc4xx_spu_set_tx_handler(write8smo_delegate(*this, FUNC(hornet_state::jamma_jvs_w))); m_maincpu->ppc4xx_spu_set_tx_handler(write8smo_delegate(*this, FUNC(hornet_state::jamma_jvs_w)));
m_dsp[0]->enable_recompiler(); //m_dsp[0]->enable_recompiler();
} }
void hornet_state::init_sscope() void hornet_state::init_sscope()

View File

@ -404,7 +404,7 @@ uint8_t nwktr_state::sysreg_r(offs_t offset)
case 4: case 4:
r = m_dsw->read(); r = m_dsw->read();
break; break;
default: default:
break; break;
} }
@ -548,7 +548,7 @@ void nwktr_state::sharc1_map(address_map &map)
map(0x0400000, 0x041ffff).rw(m_konppc, FUNC(konppc_device::cgboard_1_shared_sharc_r), FUNC(konppc_device::cgboard_1_shared_sharc_w)); map(0x0400000, 0x041ffff).rw(m_konppc, FUNC(konppc_device::cgboard_1_shared_sharc_r), FUNC(konppc_device::cgboard_1_shared_sharc_w));
map(0x0500000, 0x05fffff).ram().share(m_sharc_dataram[1]).lr32(NAME([this](offs_t offset) { return m_sharc_dataram[1][offset] & 0xffff; })); map(0x0500000, 0x05fffff).ram().share(m_sharc_dataram[1]).lr32(NAME([this](offs_t offset) { return m_sharc_dataram[1][offset] & 0xffff; }));
map(0x1400000, 0x14fffff).ram(); map(0x1400000, 0x14fffff).ram();
map(0x2400000, 0x27fffff).rw(m_konppc, FUNC(konppc_device::nwk_voodoo_0_r), FUNC(konppc_device::nwk_voodoo_0_w)); map(0x2400000, 0x27fffff).rw(m_konppc, FUNC(konppc_device::nwk_voodoo_1_r), FUNC(konppc_device::nwk_voodoo_1_w));
map(0x3400000, 0x34000ff).rw(m_konppc, FUNC(konppc_device::cgboard_1_comm_sharc_r), FUNC(konppc_device::cgboard_1_comm_sharc_w)); map(0x3400000, 0x34000ff).rw(m_konppc, FUNC(konppc_device::cgboard_1_comm_sharc_r), FUNC(konppc_device::cgboard_1_comm_sharc_w));
map(0x3500000, 0x35000ff).rw(m_konppc, FUNC(konppc_device::K033906_1_r), FUNC(konppc_device::K033906_1_w)); map(0x3500000, 0x35000ff).rw(m_konppc, FUNC(konppc_device::K033906_1_r), FUNC(konppc_device::K033906_1_w));
map(0x3600000, 0x37fffff).bankr("slave_cgboard_bank"); map(0x3600000, 0x37fffff).bankr("slave_cgboard_bank");
@ -675,6 +675,7 @@ void nwktr_state::nwktr(machine_config &config)
m_voodoo[0]->set_screen_tag("lscreen"); m_voodoo[0]->set_screen_tag("lscreen");
m_voodoo[0]->set_cpu_tag(m_dsp[0]); m_voodoo[0]->set_cpu_tag(m_dsp[0]);
m_voodoo[0]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); m_voodoo[0]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_voodoo[0]->stall_callback().set(m_dsp[0], FUNC(adsp21062_device::write_stall));
VOODOO_1(config, m_voodoo[1], XTAL(50'000'000)); VOODOO_1(config, m_voodoo[1], XTAL(50'000'000));
m_voodoo[1]->set_fbmem(2); m_voodoo[1]->set_fbmem(2);
@ -682,6 +683,7 @@ void nwktr_state::nwktr(machine_config &config)
m_voodoo[1]->set_screen_tag("rscreen"); m_voodoo[1]->set_screen_tag("rscreen");
m_voodoo[1]->set_cpu_tag(m_dsp[1]); m_voodoo[1]->set_cpu_tag(m_dsp[1]);
m_voodoo[1]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ1); m_voodoo[1]->vblank_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ1);
m_voodoo[1]->stall_callback().set(m_dsp[1], FUNC(adsp21062_device::write_stall));
screen_device &lscreen(SCREEN(config, "lscreen", SCREEN_TYPE_RASTER)); screen_device &lscreen(SCREEN(config, "lscreen", SCREEN_TYPE_RASTER));
// default 24KHz parameter in both 001604 and voodoo, input clock correct? (58~Hz Vsync, 50MHz/3 or 64MHz/4?) // default 24KHz parameter in both 001604 and voodoo, input clock correct? (58~Hz Vsync, 50MHz/3 or 64MHz/4?)