From 5211a003a57a9ca5bb4b117499f313fd8fca4d32 Mon Sep 17 00:00:00 2001 From: Ville Linde Date: Thu, 17 Jun 2021 17:59:35 +0300 Subject: [PATCH] sharc: Cycle-based DMA. Added support for write stalling. --- src/devices/cpu/sharc/sharc.cpp | 45 ++++++++-- src/devices/cpu/sharc/sharc.h | 5 ++ src/devices/cpu/sharc/sharcdma.hxx | 138 ++++++++++++++++++++++++----- src/mame/drivers/gticlub.cpp | 2 + src/mame/drivers/hornet.cpp | 6 +- src/mame/drivers/nwk-tr.cpp | 6 +- 6 files changed, 172 insertions(+), 30 deletions(-) diff --git a/src/devices/cpu/sharc/sharc.cpp b/src/devices/cpu/sharc/sharc.cpp index ded941af415..391520f688b 100644 --- a/src/devices/cpu/sharc/sharc.cpp +++ b/src/devices/cpu/sharc/sharc.cpp @@ -343,7 +343,10 @@ void adsp21062_device::iop_w(offs_t offset, uint32_t data) case 0x1c: { m_core->dma[6].control = data; - sharc_iop_delayed_w(0x1c, data, 1); + if (data & 0x1) + { + sharc_iop_delayed_w(0x1c, data, 1); + } break; } @@ -360,9 +363,12 @@ void adsp21062_device::iop_w(offs_t offset, uint32_t data) // DMA 7 case 0x1d: - { + { m_core->dma[7].control = data; - sharc_iop_delayed_w(0x1d, data, 30); + if (data & 0x1) + { + sharc_iop_delayed_w(0x1d, data, 30); + } 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 first internal RAM location, before they are used by the DMA controller. */ - + switch ((m_core->dma[6].control >> 6) & 0x3) { 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() { int i; @@ -1028,8 +1039,24 @@ void adsp21062_device::execute_run() } else { + if (m_core->write_stalled) + eat_cycles(m_core->icount); + 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; debugger_instruction_hook(m_core->daddr); } @@ -1037,9 +1064,9 @@ void adsp21062_device::execute_run() { check_interrupts(); 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->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; }; } diff --git a/src/devices/cpu/sharc/sharc.h b/src/devices/cpu/sharc/sharc.h index 6c9292c5193..f7d2d8701cd 100644 --- a/src/devices/cpu/sharc/sharc.h +++ b/src/devices/cpu/sharc/sharc.h @@ -103,6 +103,8 @@ public: TIMER_CALLBACK_MEMBER(sharc_iop_delayed_write_callback); TIMER_CALLBACK_MEMBER(sharc_dma_callback); + WRITE_LINE_MEMBER(write_stall); + void sharc_cfunc_unimplemented(); void sharc_cfunc_read_iop(); void sharc_cfunc_write_iop(); @@ -270,6 +272,7 @@ private: int32_t chained_direction; emu_timer *timer; bool active; + bool chained; }; @@ -379,6 +382,7 @@ private: SHARC_DMA_OP dma_op[12]; uint32_t dma_status; + bool write_stalled; 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 dma_op(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); inline void swap_register(uint32_t *a, uint32_t *b); void systemreg_write_latency_effect(); diff --git a/src/devices/cpu/sharc/sharcdma.hxx b/src/devices/cpu/sharc/sharcdma.hxx index fdbf7a0f635..63ea0b85c38 100644 --- a/src/devices/cpu/sharc/sharcdma.hxx +++ b/src/devices/cpu/sharc/sharcdma.hxx @@ -10,7 +10,7 @@ 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_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].chained_direction = chained_direction; + m_core->dma_op[channel].chained = true; m_core->dma_op[channel].active = true; - int cycles = m_core->dma_op[channel].src_count / 4; - m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel); + if (m_enable_drc) + { + 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 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].chain_ptr = 0; + m_core->dma_op[channel].chained = false; m_core->dma_op[channel].active = true; - int cycles = src_count / 4; - m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel); + if (m_enable_drc) + { + int cycles = src_count / 4; + m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel); + } // enable busy flag 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) { int i; @@ -94,7 +190,7 @@ void adsp21062_device::dma_op(int channel) //int dst_count = m_core->dma_op[channel].dst_count; 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) { @@ -191,36 +287,36 @@ void adsp21062_device::sharc_dma_exec(int channel) { 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 { if (tran) // Transmit to external { - dst = m_core->dma[channel].ext_index; - dst_modifier = m_core->dma[channel].ext_modifier; - dst_count = m_core->dma[channel].ext_count; - src = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000; - src_modifier = m_core->dma[channel].int_modifier; - src_count = m_core->dma[channel].int_count; + dst = m_core->dma[channel].ext_index; + dst_modifier = m_core->dma[channel].ext_modifier; + dst_count = m_core->dma[channel].ext_count; + src = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000; + src_modifier = m_core->dma[channel].int_modifier; + src_count = m_core->dma[channel].int_count; } else // Receive from external { - src = m_core->dma[channel].ext_index; - src_modifier = m_core->dma[channel].ext_modifier; - src_count = m_core->dma[channel].ext_count; - dst = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000; - dst_modifier = m_core->dma[channel].int_modifier; - dst_count = m_core->dma[channel].int_count; + src = m_core->dma[channel].ext_index; + src_modifier = m_core->dma[channel].ext_modifier; + src_count = m_core->dma[channel].ext_count; + dst = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000; + dst_modifier = m_core->dma[channel].int_modifier; + dst_count = m_core->dma[channel].int_count; } if (dtype) - //if (src_count != dst_count) + //if (src_count != dst_count) { 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); } } diff --git a/src/mame/drivers/gticlub.cpp b/src/mame/drivers/gticlub.cpp index b1a0a12b00d..2f48600b04c 100644 --- a/src/mame/drivers/gticlub.cpp +++ b/src/mame/drivers/gticlub.cpp @@ -963,6 +963,7 @@ void gticlub_state::hangplt(machine_config &config) m_voodoo[0]->set_screen_tag("lscreen"); m_voodoo[0]->set_cpu_tag(m_dsp[0]); 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); 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_cpu_tag(m_dsp[1]); 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_2", 0, m_voodoo[1]); diff --git a/src/mame/drivers/hornet.cpp b/src/mame/drivers/hornet.cpp index f09bd70d4bf..4aa91fc24a3 100644 --- a/src/mame/drivers/hornet.cpp +++ b/src/mame/drivers/hornet.cpp @@ -1122,6 +1122,7 @@ void hornet_state::hornet(machine_config &config) m_voodoo[0]->set_screen_tag("screen"); m_voodoo[0]->set_cpu_tag(m_dsp[0]); 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]); @@ -1201,6 +1202,7 @@ void hornet_state::sscope(machine_config &config) m_voodoo[1]->set_screen_tag("rscreen"); m_voodoo[1]->set_cpu_tag(m_dsp[1]); 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]); @@ -1235,6 +1237,7 @@ void hornet_state::sscope2(machine_config &config) m_voodoo[0]->set_screen_tag("lscreen"); m_voodoo[0]->set_cpu_tag(m_dsp[0]); 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); 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_cpu_tag(m_dsp[1]); 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"); 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_dsp[0]->enable_recompiler(); + //m_dsp[0]->enable_recompiler(); } void hornet_state::init_sscope() diff --git a/src/mame/drivers/nwk-tr.cpp b/src/mame/drivers/nwk-tr.cpp index 6bd567d1732..1e7356bfc07 100644 --- a/src/mame/drivers/nwk-tr.cpp +++ b/src/mame/drivers/nwk-tr.cpp @@ -404,7 +404,7 @@ uint8_t nwktr_state::sysreg_r(offs_t offset) case 4: r = m_dsw->read(); break; - default: + default: 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(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(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(0x3500000, 0x35000ff).rw(m_konppc, FUNC(konppc_device::K033906_1_r), FUNC(konppc_device::K033906_1_w)); 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_cpu_tag(m_dsp[0]); 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)); 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_cpu_tag(m_dsp[1]); 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)); // default 24KHz parameter in both 001604 and voodoo, input clock correct? (58~Hz Vsync, 50MHz/3 or 64MHz/4?)