ti99: Improve performance by stopping GROM clock in idle state

This commit is contained in:
Michael Zapf 2016-09-19 14:35:19 +02:00
parent e8c651e343
commit 3cb56626ec
8 changed files with 163 additions and 52 deletions

View File

@ -137,7 +137,16 @@ mainboard8_device::mainboard8_device(const machine_config &mconfig, const char *
m_vaquerro(*this, VAQUERRO_TAG),
m_mofetta(*this, MOFETTA_TAG),
m_amigo(*this, AMIGO_TAG),
m_oso(*this, OSO_TAG)
m_oso(*this, OSO_TAG),
m_video(*owner, VDP_TAG), // subdevice of main class
m_sound(*owner, TISOUNDCHIP_TAG),
m_speech(*owner, SPEECHSYN_TAG),
m_gromport(*owner, GROMPORT_TAG),
m_peb(*owner, PERIBOX_TAG),
m_sgrom_idle(true),
m_tsgrom_idle(true),
m_p8grom_idle(true),
m_p3grom_idle(true)
{
}
@ -252,17 +261,33 @@ WRITE_LINE_MEMBER( mainboard8_device::clock_in )
if (gromclk != m_gromclk) // when it changed, propagate to the GROMs
{
m_gromclk = gromclk;
for (int i=0; i < 8; i++)
// Get some more performance. We only propagate the clock line to
// those GROMs that are not idle.
// Yields about 25% in bench (hoped for more, but well)
if (!m_sgrom_idle)
{
if (i < 3)
{
m_sgrom[i]->gclock_in(gromclk);
m_p3grom[i]->gclock_in(gromclk);
}
m_tsgrom[i]->gclock_in(gromclk);
m_p8grom[i]->gclock_in(gromclk);
for (int i=0; i < 3; i++) m_sgrom[i]->gclock_in(gromclk);
m_gromport->gclock_in(gromclk);
m_sgrom_idle = m_sgrom[0]->idle();
}
if (!m_tsgrom_idle)
{
for (int i=0; i < 8; i++) m_tsgrom[i]->gclock_in(gromclk);
m_tsgrom_idle = m_tsgrom[0]->idle();
}
if (!m_p8grom_idle)
{
for (int i=0; i < 8; i++) m_p8grom[i]->gclock_in(gromclk);
m_p8grom_idle = m_p8grom[0]->idle();
}
if (!m_p3grom_idle)
{
for (int i=0; i < 3; i++) m_p3grom[i]->gclock_in(gromclk);
m_p3grom_idle = m_p3grom[0]->idle();
}
m_gromport->gclock_in(gromclk);
}
// Check video for writing
@ -338,16 +363,23 @@ void mainboard8_device::select_groms()
int lines = (m_dbin_level==ASSERT_LINE)? GROM_M_LINE : 0;
if (m_A14_set) lines |= GROM_MO_LINE;
if (select & SGMSEL) m_sgrom_idle = false;
if (select & TSGSEL) m_tsgrom_idle = false;
if (select & P8GSEL) m_p8grom_idle = false;
if (select & P3GSEL) m_p3grom_idle = false;
for (int i=0; i < 3; i++)
m_sgrom[i]->set_lines(*m_space, lines, select & SGMSEL);
for (int i=0; i < 8; i++)
{
if (i < 3)
{
m_sgrom[i]->set_lines(*m_space, lines, select & SGMSEL);
m_p3grom[i]->set_lines(*m_space, lines, select & P3GSEL);
}
m_tsgrom[i]->set_lines(*m_space, lines, select & TSGSEL);
for (int i=0; i < 8; i++)
m_p8grom[i]->set_lines(*m_space, lines, select & P8GSEL);
}
for (int i=0; i < 3; i++)
m_p3grom[i]->set_lines(*m_space, lines, select & P3GSEL);
// Write to the cartridge port. The GROMs on cartridges are accesses as system GROMs
if (select & SGMSEL) m_gromport->romgq_line(CLEAR_LINE);
m_gromport->set_gromlines(*m_space, lines, select & SGMSEL);
@ -476,6 +508,7 @@ READ8_MEMBER( mainboard8_device::read )
switch (m_vaquerro->gromcs_out())
{
case SGMSEL:
m_sgrom_idle = false;
for (int i=0; i < 3; i++)
{
m_sgrom[i]->readz(space, 0, &value);
@ -486,6 +519,7 @@ READ8_MEMBER( mainboard8_device::read )
goto readdone;
case TSGSEL:
m_tsgrom_idle = false;
for (int i=0; i < 8; i++)
{
m_tsgrom[i]->readz(space, 0, &value);
@ -495,6 +529,7 @@ READ8_MEMBER( mainboard8_device::read )
goto readdone;
case P8GSEL:
m_p8grom_idle = false;
for (int i=0; i < 8; i++)
{
m_p8grom[i]->readz(space, 0, &value);
@ -504,6 +539,7 @@ READ8_MEMBER( mainboard8_device::read )
goto readdone;
case P3GSEL:
m_p3grom_idle = false;
for (int i=0; i < 3; i++)
{
m_p3grom[i]->readz(space, 0, &value);
@ -751,21 +787,6 @@ void mainboard8_device::device_start()
m_p8grom[i] = downcast<tmc0430_device*>(machine().device(glib2[i]));
}
// Link to speech synthesizer
m_speech = downcast<cd2501ecd_device*>(machine().device(SPEECHSYN_TAG));
// Link to sound chip
m_sound = downcast<sn76496_base_device*>(machine().device(TISOUNDCHIP_TAG));
// Link to video
m_video = downcast<tms9118_device*>(machine().device(VDP_TAG));
// Link to cartridge port
m_gromport = downcast<gromport_device*>(machine().device(GROMPORT_TAG));
// Link to PEB
m_peb = downcast<peribox_device*>(machine().device(PERIBOX_TAG));
// Configure RAM and AMIGO
m_sram = std::make_unique<UINT8[]>(SRAM_SIZE);
m_dram = std::make_unique<UINT8[]>(DRAM_SIZE);

View File

@ -505,18 +505,16 @@ private:
required_device<amigo_device> m_amigo;
required_device<oso_device> m_oso;
// More devices
required_device<tms9928a_device> m_video;
required_device<sn76496_base_device> m_sound;
required_device<cd2501ecd_device> m_speech;
required_device<gromport_device> m_gromport;
required_device<peribox_device> m_peb;
// Debugging
line_state m_last_ready;
// Video processor
tms9118_device* m_video;
// Sound generator
sn76496_base_device* m_sound;
// Speech processor
cd2501ecd_device* m_speech;
// System GROM library
tmc0430_device* m_sgrom[3];
@ -529,11 +527,11 @@ private:
// Pascal 3 GROM library
tmc0430_device* m_p3grom[3];
// Gromport (cartridge port)
gromport_device* m_gromport;
// Peripheral box
peribox_device* m_peb;
// Idle flags for GROMs
bool m_sgrom_idle;
bool m_tsgrom_idle;
bool m_p8grom_idle;
bool m_p3grom_idle;
// Memory
std::unique_ptr<UINT8[]> m_sram;

View File

@ -87,7 +87,8 @@ ti99_datamux_device::ti99_datamux_device(const machine_config &mconfig, const ch
m_ram16b(nullptr),
m_use32k(false),
m_base32k(0),
m_console_groms_present(false)
m_console_groms_present(false),
m_grom_idle(true)
{ }
#define TRACE_READY 0
@ -119,6 +120,7 @@ void ti99_datamux_device::read_all(address_space& space, UINT16 addr, UINT8 *val
}
// GROMport (GROMs)
m_gromport->readz(space, addr, value);
m_grom_idle = false;
}
// Video
@ -149,6 +151,7 @@ void ti99_datamux_device::write_all(address_space& space, UINT16 addr, UINT8 val
}
// GROMport
m_gromport->write(space, addr, value);
m_grom_idle = false;
}
// Cartridge port and sound
@ -190,6 +193,8 @@ void ti99_datamux_device::setaddress_all(address_space& space, UINT16 addr)
if (a14==ASSERT_LINE) lines |= 2;
line_state select = isgrom? ASSERT_LINE : CLEAR_LINE;
if (select) m_grom_idle = false;
if (m_console_groms_present)
for (int i=0; i < 3; i++)
m_grom[i]->set_lines(space, lines, select);
@ -519,14 +524,23 @@ WRITE_LINE_MEMBER( ti99_datamux_device::ready_line )
ready_join();
}
/* Called from VDP via console. */
WRITE_LINE_MEMBER( ti99_datamux_device::gromclk_in )
{
// Don't propagate the clock in idle phase
if (m_grom_idle) return;
// Propagate to the GROMs
if (m_console_groms_present)
{
for (int i=0; i < 3; i++) m_grom[i]->gclock_in(state);
m_grom_idle = m_grom[0]->idle();
}
m_gromport->gclock_in(state);
// Only ask the gromport when we don't have GROMs in the console
if (!m_console_groms_present)
m_grom_idle = m_gromport->is_grom_idle();
}
/***************************************************************************

View File

@ -126,6 +126,9 @@ private:
// Console GROMs are available (the HSGPL expects them to be removed)
bool m_console_groms_present;
// GROMs are idle, no need to propagate the clock
bool m_grom_idle;
};
/******************************************************************************/

View File

@ -234,6 +234,18 @@ void gromport_device::cartridge_inserted()
}
}
/*
Find out whether the GROMs in the cartridge are idle. In that case,
cut the clock line.
*/
bool gromport_device::is_grom_idle()
{
if (m_connector != nullptr)
return m_connector->is_grom_idle();
else
return false;
}
void gromport_device::device_config_complete()
{
m_connector = static_cast<ti99_cartridge_connector_device*>(subdevices().first());
@ -347,6 +359,14 @@ WRITE_LINE_MEMBER(single_conn_device::gclock_in)
m_cartridge->gclock_in(state);
}
/*
Check whether the GROMs are idle.
*/
bool single_conn_device::is_grom_idle()
{
return m_cartridge->is_grom_idle();
}
void single_conn_device::device_start()
{
m_cartridge = static_cast<ti99_cartridge_device*>(subdevices().first());
@ -619,6 +639,22 @@ WRITE8_MEMBER(multi_conn_device::cruwrite)
}
}
/*
Check whether the GROMs are idle. Just ask the currently
active cartridge.
*/
bool multi_conn_device::is_grom_idle()
{
/* Sanity check. Higher slots are always empty. */
if (m_active_slot >= NUMBER_OF_CARTRIDGE_SLOTS)
return false;
if (m_cartridge[m_active_slot] != nullptr)
return m_cartridge[m_active_slot]->is_grom_idle();
return false;
}
void multi_conn_device::device_start()
{
m_next_free_slot = 0;
@ -818,6 +854,14 @@ WRITE_LINE_MEMBER(gkracker_device::gclock_in)
if (m_cartridge != nullptr) m_cartridge->gclock_in(state);
}
/*
Check whether the GROMs are idle.
*/
bool gkracker_device::is_grom_idle()
{
return (m_cartridge != nullptr)? m_cartridge->is_grom_idle() : false;
}
READ8Z_MEMBER(gkracker_device::readz)
{
if (m_grom_selected)
@ -1466,6 +1510,11 @@ WRITE_LINE_MEMBER(ti99_cartridge_device::gclock_in)
if (m_pcb != nullptr) m_pcb->gclock_in(state);
}
bool ti99_cartridge_device::is_grom_idle()
{
return (m_pcb != nullptr)? m_pcb->is_grom_idle() : false;
}
void ti99_cartridge_device::device_config_complete()
{
update_names();
@ -1527,6 +1576,7 @@ const device_type TI99CART = &device_creator<ti99_cartridge_device>;
ti99_cartridge_pcb::ti99_cartridge_pcb()
: m_cart(nullptr),
m_grom_idle(false),
m_grom_size(0),
m_rom_size(0),
m_ram_size(0),
@ -1629,13 +1679,25 @@ WRITE_LINE_MEMBER( ti99_cartridge_pcb::romgq_line )
WRITE8_MEMBER(ti99_cartridge_pcb::set_gromlines)
{
for (auto& elem : m_grom)
if (elem != nullptr) elem->set_lines(space, offset, data);
{
if (elem != nullptr)
{
elem->set_lines(space, offset, data);
if (data==ASSERT_LINE) m_grom_idle = false;
}
}
}
WRITE_LINE_MEMBER(ti99_cartridge_pcb::gclock_in)
{
for (auto& elem : m_grom)
if (elem != nullptr) elem->gclock_in(state);
{
if (elem != nullptr)
{
elem->gclock_in(state);
m_grom_idle = elem->idle();
}
}
}

View File

@ -42,6 +42,7 @@ public:
template<class _Object> static devcb_base &static_set_reset_callback(device_t &device, _Object object) { return downcast<gromport_device &>(device).m_console_reset.set_callback(object); }
void cartridge_inserted();
bool is_grom_idle();
protected:
virtual void device_start() override;
@ -100,6 +101,7 @@ public:
bool is_available() { return m_pcb != nullptr; }
void set_slot(int i);
bool is_grom_idle();
protected:
virtual void device_start() override { };
@ -159,8 +161,7 @@ public:
virtual void insert(int index, ti99_cartridge_device* cart) { m_gromport->cartridge_inserted(); };
virtual void remove(int index) { };
// UINT16 grom_base();
// UINT16 grom_mask();
virtual bool is_grom_idle() =0;
protected:
ti99_cartridge_connector_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
@ -186,6 +187,8 @@ public:
DECLARE_WRITE8_MEMBER(set_gromlines) override;
DECLARE_WRITE_LINE_MEMBER(gclock_in) override;
bool is_grom_idle();
protected:
virtual void device_start() override;
virtual void device_reset() override;
@ -221,6 +224,8 @@ public:
void remove(int index) override;
DECLARE_INPUT_CHANGED_MEMBER( switch_changed );
bool is_grom_idle();
protected:
virtual void device_start() override;
virtual void device_reset() override;
@ -258,6 +263,9 @@ public:
void remove(int index) override;
DECLARE_INPUT_CHANGED_MEMBER( gk_changed );
// We may have a cartridge plugged into the GK
bool is_grom_idle();
protected:
virtual void device_start() override;
virtual void device_reset() override;
@ -317,9 +325,11 @@ protected:
void set_cartridge(ti99_cartridge_device *cart);
const char* tag() { return m_tag; }
void set_tag(const char* tag) { m_tag = tag; }
bool is_grom_idle() { return m_grom_idle; }
ti99_cartridge_device* m_cart;
tmc0430_device* m_grom[5];
bool m_grom_idle;
int m_grom_size;
int m_rom_size;
int m_ram_size;

View File

@ -211,7 +211,7 @@ WRITE_LINE_MEMBER( tmc0430_device::gclock_in )
if ((m_current_clock_level==CLEAR_LINE) || (oldlevel==ASSERT_LINE))
return;
if (TRACE_CLOCK) logerror("GROMCLK in, phase=%d, m_add=%d\n", m_phase, m_address);
if (TRACE_CLOCK) logerror("GROMCLK in, phase=%d, m_add=%04x\n", m_phase, m_address);
switch (m_phase)
{

View File

@ -53,6 +53,9 @@ public:
int debug_get_address();
// Allow for checking the state of the GROM so we can turn off the clock
bool idle() { return m_phase == 0; }
protected:
void device_start(void) override;
void device_reset(void) override;