namcos23: Get some speed back (nw)

This commit is contained in:
Olivier Galibert 2014-03-28 17:50:10 +00:00
parent 089ba456f4
commit 2a6dfc5e9b
5 changed files with 220 additions and 75 deletions

View File

@ -41,6 +41,22 @@
#include "debugger.h"
#include "h8.h"
static astring tts(attotime t)
{
char buf[256];
int nsec = t.attoseconds / ATTOSECONDS_PER_NANOSECOND;
sprintf(buf, "%4d.%03d,%03d,%03d", int(t.seconds), nsec/1000000, (nsec/1000)%1000,
nsec % 1000);
return buf;
}
static astring ttsn(running_machine &m)
{
return tts(m.time());
}
h8_device::h8_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, bool mode_a16, address_map_delegate map_delegate) :
cpu_device(mconfig, type, name, tag, owner, clock, shortname, source),
program_config("program", ENDIANNESS_BIG, 16, mode_a16 ? 16 : 24, 0, map_delegate),
@ -178,7 +194,7 @@ void h8_device::recompute_bcount(UINT64 event_time)
void h8_device::execute_run()
{
UINT64 start_cycles = machine().time().as_ticks(clock());
start_cycles = machine().time().as_ticks(clock());
end_cycles = start_cycles + icount;
internal_update(start_cycles);
@ -195,9 +211,9 @@ void h8_device::execute_run()
}
do_exec_full();
}
while(bcount && icount <= bcount)
int pic = icount;
while(bcount && icount && icount <= bcount)
internal_update(end_cycles - bcount);
do_exec_partial();
}
end_cycles = 0;

View File

@ -214,7 +214,7 @@ protected:
int inst_state, inst_substate;
int icount, bcount;
UINT64 end_cycles;
UINT64 start_cycles, end_cycles;
int irq_vector, taken_irq_vector;
int irq_level, taken_irq_level;
bool irq_required, irq_nmi;

View File

@ -3,12 +3,29 @@
const device_type H8_SCI = &device_creator<h8_sci_device>;
static astring tts(attotime t)
{
char buf[256];
int nsec = t.attoseconds / ATTOSECONDS_PER_NANOSECOND;
sprintf(buf, "%4d.%03d,%03d,%03d", int(t.seconds), nsec/1000000, (nsec/1000)%1000,
nsec % 1000);
return buf;
}
static astring ttsn(running_machine &m)
{
return tts(m.time());
}
const char *const h8_sci_device::state_names[] = { "idle", "start", "bit", "parity", "stop", "last-tick" };
h8_sci_device::h8_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, H8_SCI, "H8 Serial Communications Interface", tag, owner, clock, "h8_sci", __FILE__),
cpu(*this, DEVICE_SELF_OWNER),
tx_cb(*this),
clk_cb(*this)
{
external_clock_period = attotime::never;
}
void h8_sci_device::set_info(const char *_intc_tag,int eri, int rxi, int txi, int tei)
@ -20,6 +37,11 @@ void h8_sci_device::set_info(const char *_intc_tag,int eri, int rxi, int txi, in
tei_int = tei;
}
void h8_sci_device::set_external_clock_period(attotime period)
{
external_clock_period = period;
}
WRITE8_MEMBER(h8_sci_device::smr_w)
{
smr = data;
@ -166,19 +188,28 @@ void h8_sci_device::clock_update()
switch(clock_mode) {
case CLKM_INTERNAL_ASYNC:
logerror("%s: clock internal at %d Hz, async, bitrate %d bps\n", tag(), int(cpu->clock() / (divider*2)), int(cpu->clock() / (divider*16)));
logerror("%s: clock internal at %d Hz, async, bitrate %d bps\n", tag(), int(cpu->clock() / divider), int(cpu->clock() / (divider*16)));
break;
case CLKM_INTERNAL_ASYNC_OUT:
logerror("%s: clock internal at %d Hz, async, bitrate %d bps, output\n", tag(), int(cpu->clock() / (divider*2)), int(cpu->clock() / (divider*16)));
logerror("%s: clock internal at %d Hz, async, bitrate %d bps, output\n", tag(), int(cpu->clock() / divider), int(cpu->clock() / (divider*16)));
break;
case CLKM_EXTERNAL_ASYNC:
logerror("%s: clock external, async\n", tag());
if(!external_clock_period.is_never()) {
clock_mode = CLKM_EXTERNAL_RATE_ASYNC;
logerror("%s: clock external at %d Hz, async, bitrate %d bps\n", tag(), int(cpu->clock()*internal_to_external_ratio), int(cpu->clock()*internal_to_external_ratio/16));
} else
logerror("%s: clock external, async\n", tag());
break;
case CLKM_INTERNAL_SYNC_OUT:
logerror("%s: clock internal at %d Hz, sync, output\n", tag(), int(cpu->clock() / (divider*2)));
break;
case CLKM_EXTERNAL_SYNC:
logerror("%s: clock external, sync\n", tag());
if(!external_clock_period.is_never()) {
clock_mode = CLKM_EXTERNAL_RATE_ASYNC;
logerror("%s: clock external at %d Hz, sync\n", tag(), int(cpu->clock()*internal_to_external_ratio));
} else
logerror("%s: clock external, sync\n", tag());
break;
}
}
@ -188,6 +219,16 @@ void h8_sci_device::device_start()
tx_cb.resolve_safe();
clk_cb.resolve_safe();
sync_timer = timer_alloc(0);
if(external_clock_period.is_never()) {
internal_to_external_ratio = 0;
external_to_internal_ratio = 0;
} else {
external_to_internal_ratio = (external_clock_period*cpu->clock()).as_double();
internal_to_external_ratio = 1/external_to_internal_ratio;
}
intc = siblingdevice<h8_intc_device>(intc_tag);
save_item(NAME(rdr));
save_item(NAME(tdr));
@ -208,6 +249,7 @@ void h8_sci_device::device_start()
save_item(NAME(divider));
save_item(NAME(ext_clock_value));
save_item(NAME(ext_clock_counter));
save_item(NAME(cur_sync_time));
}
void h8_sci_device::device_reset()
@ -233,6 +275,12 @@ void h8_sci_device::device_reset()
ext_clock_counter = 0;
rx_value = true;
clk_cb(clock_value);
cur_sync_time = attotime::never;
}
void h8_sci_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
// Used only to force system-wide syncs
}
WRITE_LINE_MEMBER(h8_sci_device::rx_w)
@ -248,7 +296,6 @@ WRITE_LINE_MEMBER(h8_sci_device::clk_w)
if(ext_clock_value != state) {
ext_clock_value = state;
if(clock_state) {
logerror("%s: clki=%d\n", tag(), state);
switch(clock_mode) {
case CLKM_EXTERNAL_ASYNC:
if(ext_clock_value) {
@ -275,69 +322,133 @@ WRITE_LINE_MEMBER(h8_sci_device::clk_w)
UINT64 h8_sci_device::internal_update(UINT64 current_time)
{
UINT64 event = 0;
switch(clock_mode) {
case CLKM_INTERNAL_SYNC_OUT:
if(clock_state || !clock_value) {
UINT64 fp = divider*2;
UINT64 delta = current_time - clock_base;
if(delta >= fp) {
delta -= fp;
clock_base += fp;
}
assert(delta < fp);
bool new_clock = delta >= divider;
if(new_clock != clock_value) {
if((!new_clock) && (clock_state & CLK_TX))
tx_dropped_edge();
if(current_time >= clock_base) {
UINT64 delta = current_time - clock_base;
if(delta >= fp) {
delta -= fp;
clock_base += fp;
}
assert(delta < fp);
else if(new_clock && (clock_state & CLK_RX))
rx_raised_edge();
if(clock_state || !clock_value) {
bool new_clock = delta >= divider;
if(new_clock != clock_value) {
cpu->synchronize();
if((!new_clock) && (clock_state & CLK_TX))
tx_dropped_edge();
else if(new_clock && (clock_state & CLK_RX))
rx_raised_edge();
clock_value = new_clock;
clk_cb(clock_value);
if(clock_state || clock_value)
clk_cb(clock_value);
}
}
return clock_base + (clock_value ? fp : divider);
} else
return 0;
event = clock_base + (clock_value ? fp : divider);
}
break;
case CLKM_INTERNAL_ASYNC:
case CLKM_INTERNAL_ASYNC_OUT:
if(clock_state || !clock_value) {
UINT64 fp = divider*16;
UINT64 delta = current_time - clock_base;
if(delta >= fp) {
delta -= fp;
clock_base += fp;
}
assert(delta < fp);
bool new_clock = delta >= divider*8;
if(new_clock != clock_value) {
if((!new_clock) && (clock_state & CLK_TX))
tx_dropped_edge();
else if(new_clock && (clock_state & CLK_RX))
rx_raised_edge();
if(clock_state || !clock_value) {
if(current_time >= clock_base) {
UINT64 delta = current_time - clock_base;
if(delta >= fp) {
delta -= fp;
clock_base += fp;
}
assert(delta < fp);
bool new_clock = delta >= divider*8;
if(new_clock != clock_value) {
cpu->synchronize();
logerror("%s: internal clock edge %s\n", tag(), ttsn(machine()).cstr());
if((!new_clock) && (clock_state & CLK_TX))
tx_dropped_edge();
else if(new_clock && (clock_state & CLK_RX))
rx_raised_edge();
clock_value = new_clock;
if(clock_mode == CLKM_INTERNAL_ASYNC_OUT)
if(clock_mode == CLKM_INTERNAL_ASYNC_OUT && (clock_state || !clock_value))
clk_cb(clock_value);
}
}
return clock_base + (clock_value ? fp : divider*16);
} else
return 0;
logerror("%s: %lld -> %lld (%lld, %lld, %d, %d)\n", tag(), current_time, clock_base + (clock_value ? fp : divider*8), clock_base, divider*8, clock_value, clock_state);
event = clock_base + (clock_value ? fp : divider*8);
}
break;
case CLKM_EXTERNAL_RATE_SYNC:
if(clock_state || !clock_value) {
UINT64 ctime = UINT64(current_time*internal_to_external_ratio*2);
if(ctime >= clock_base) {
UINT64 delta = ctime - clock_base;
clock_base += delta & ~1;
delta &= 1;
bool new_clock = delta >= 1;
if(new_clock != clock_value) {
cpu->synchronize();
if((!new_clock) && (clock_state & CLK_TX))
tx_dropped_edge();
else if(new_clock && (clock_state & CLK_RX))
rx_raised_edge();
clock_value = new_clock;
}
}
event = UINT64((clock_base + (clock_value ? 2 : 1))*external_to_internal_ratio)+1;
}
break;
case CLKM_EXTERNAL_RATE_ASYNC:
if(clock_state || !clock_value) {
UINT64 ctime = UINT64(current_time*internal_to_external_ratio);
if(ctime >= clock_base) {
UINT64 delta = ctime - clock_base;
clock_base += delta & ~15;
delta &= 15;
bool new_clock = delta >= 8;
if(new_clock != clock_value) {
cpu->synchronize();
logerror("%s: external clock edge %s / %lld\n", tag(), ttsn(machine()).cstr(), current_time);
if((!new_clock) && (clock_state & CLK_TX))
tx_dropped_edge();
else if(new_clock && (clock_state & CLK_RX))
rx_raised_edge();
clock_value = new_clock;
}
}
event = UINT64((clock_base + (clock_value ? 16 : 8))*external_to_internal_ratio)+1;
}
break;
case CLKM_EXTERNAL_ASYNC:
case CLKM_EXTERNAL_SYNC:
return 0;
break;;
}
return 0;
if(event) {
attotime ctime = machine().time();
attotime sync_time = attotime::from_ticks(event-10, cpu->clock());
if(cur_sync_time != sync_time && sync_time > ctime) {
logerror("%s: adjust to %s (%lld) from %s\n", tag(), tts(sync_time).cstr(), event-10, tts(ctime).cstr());
sync_timer->adjust(sync_time - ctime);
cur_sync_time = sync_time;
}
}
return event;
}
void h8_sci_device::clock_start(int mode)
@ -347,6 +458,7 @@ void h8_sci_device::clock_start(int mode)
return;
if(!clock_state) {
cpu->synchronize();
clock_state = mode;
switch(clock_mode) {
case CLKM_INTERNAL_ASYNC:
@ -357,6 +469,18 @@ void h8_sci_device::clock_start(int mode)
cpu->internal_update();
break;
case CLKM_EXTERNAL_RATE_ASYNC:
logerror("%s: Simulating external clock async\n", tag());
clock_base = UINT64(cpu->get_cycle()*internal_to_external_ratio);
cpu->internal_update();
break;
case CLKM_EXTERNAL_RATE_SYNC:
logerror("%s: Simulating external clock sync\n", tag());
clock_base = UINT64(cpu->get_cycle()*2*internal_to_external_ratio);
cpu->internal_update();
break;
case CLKM_EXTERNAL_ASYNC:
logerror("%s: Waiting for external clock async\n", tag());
ext_clock_counter = 15;
@ -396,7 +520,7 @@ void h8_sci_device::tx_start()
void h8_sci_device::tx_dropped_edge()
{
logerror("%s: tx_dropped_edge state=%d bit=%d\n", tag(), tx_state, tx_bit);
logerror("%s: tx_dropped_edge state=%s bit=%d\n", tag(), state_names[tx_state], tx_bit);
switch(tx_state) {
case ST_START:
tx_cb(false);
@ -460,7 +584,7 @@ void h8_sci_device::tx_dropped_edge()
default:
abort();
}
logerror("%s: -> state=%d bit=%d\n", tag(), tx_state, tx_bit);
logerror("%s: -> state=%s bit=%d\n", tag(), state_names[tx_state], tx_bit);
}
void h8_sci_device::rx_start()
@ -512,7 +636,7 @@ void h8_sci_device::rx_done()
void h8_sci_device::rx_raised_edge()
{
logerror("%s: rx_raised_edge state=%d bit=%d\n", tag(), rx_state, rx_value);
logerror("%s: rx_raised_edge state=%s bit=%d\n", tag(), state_names[rx_state], rx_bit);
switch(rx_state) {
case ST_START:
if(rx_value) {
@ -563,6 +687,6 @@ void h8_sci_device::rx_raised_edge()
default:
abort();
}
logerror("%s: -> state=%d\n", tag(), rx_state);
logerror("%s: -> state=%s, bit=%d\n", tag(), state_names[rx_state], rx_bit);
}

View File

@ -47,6 +47,9 @@
MCFG_DEVICE_ADD( _tag, H8_SCI, 0 ) \
downcast<h8_sci_device *>(device)->set_info(intc, eri, rxi, txi, tei);
#define MCFG_H8_SCI_SET_EXTERNAL_CLOCK_PERIOD(_period) \
downcast<h8_sci_device *>(device)->set_external_clock_period(_period);
#define MCFG_H8_SCI_TX_CALLBACK(_devcb) \
devcb = &h8_sci_device::set_tx_cb(*device, DEVCB2_##_devcb);
@ -58,6 +61,7 @@ public:
h8_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
void set_info(const char *intc, int eri, int rxi, int txi, int tei);
void set_external_clock_period(attotime _period);
DECLARE_WRITE8_MEMBER(smr_w);
DECLARE_READ8_MEMBER(smr_r);
@ -86,6 +90,8 @@ protected:
ST_IDLE, ST_START, ST_BIT, ST_PARITY, ST_STOP, ST_LAST_TICK,
};
static const char *const state_names[];
enum {
CLK_TX = 1,
CLK_RX = 2
@ -95,8 +101,10 @@ protected:
CLKM_INTERNAL_ASYNC,
CLKM_INTERNAL_ASYNC_OUT,
CLKM_EXTERNAL_ASYNC,
CLKM_EXTERNAL_RATE_ASYNC,
CLKM_INTERNAL_SYNC_OUT,
CLKM_EXTERNAL_SYNC
CLKM_EXTERNAL_SYNC,
CLKM_EXTERNAL_RATE_SYNC
};
enum {
@ -129,8 +137,12 @@ protected:
};
required_device<h8_device> cpu;
devcb2_write_line tx_cb, clk_cb;
h8_intc_device *intc;
const char *intc_tag;
attotime external_clock_period, cur_sync_time;
double external_to_internal_ratio, internal_to_external_ratio;
emu_timer *sync_timer;
int eri_int, rxi_int, txi_int, tei_int;
@ -140,10 +152,10 @@ protected:
UINT8 rdr, tdr, smr, scr, ssr, brr, rsr, tsr;
UINT64 clock_base, divider;
devcb2_write_line tx_cb, clk_cb;
virtual void device_start();
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
void clock_start(int mode);
void clock_stop(int mode);

View File

@ -1351,7 +1351,6 @@ public:
m_maincpu(*this, "maincpu"),
m_subcpu(*this, "subcpu"),
m_adc(*this, "subcpu:adc"),
m_sci0(*this, "subcpu:sci0"),
m_iocpu(*this, "iocpu"),
m_rtc(*this, "rtc"),
m_settings(*this, "namco_settings"),
@ -1375,7 +1374,6 @@ public:
required_device<cpu_device> m_maincpu;
required_device<h83002_device> m_subcpu;
required_device<h8_adc_device> m_adc;
required_device<h8_sci_device> m_sci0;
optional_device<h83334_device> m_iocpu;
required_device<rtc4543_device> m_rtc;
required_device<namco_settings_device> m_settings;
@ -1440,7 +1438,6 @@ public:
int m_s23_porta;
int m_s23_lastpb;
UINT8 m_s23_tssio_port_4;
bool jvs_timer_state;
void update_main_interrupts(UINT32 cause);
void update_mixer();
@ -1499,7 +1496,6 @@ public:
UINT32 screen_update_s23(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(s23_interrupt);
TIMER_CALLBACK_MEMBER(c361_timer_cb);
TIMER_DEVICE_CALLBACK_MEMBER(jvs_timer);
void namcos23_sub_irq(screen_device &screen, bool state);
UINT8 nthbyte(const UINT32 *pSource, int offs);
UINT16 nthword(const UINT32 *pSource, int offs);
@ -3198,16 +3194,9 @@ void namcos23_state::machine_start()
void namcos23_state::machine_reset()
{
jvs_timer_state = false;
m_subcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
}
TIMER_DEVICE_CALLBACK_MEMBER(namcos23_state::jvs_timer)
{
jvs_timer_state = !jvs_timer_state;
m_sci0->clk_w(jvs_timer_state);
}
MACHINE_RESET_MEMBER(namcos23_state,gmen)
{
machine_reset();
@ -3310,8 +3299,9 @@ static MACHINE_CONFIG_START( gorgon, namcos23_state )
MCFG_CPU_PROGRAM_MAP( s23h8rwmap )
MCFG_CPU_IO_MAP( s23h8iomap )
// Timer at 115200*16 for the jvs serial clock, extra *2 to have both edges
MCFG_TIMER_DRIVER_ADD_PERIODIC("jvs_timer", namcos23_state, jvs_timer, attotime::from_hz(S23_JVSCLOCK/8*2))
// Timer at 115200*16 for the jvs serial clock
MCFG_DEVICE_MODIFY(":subcpu:sci0")
MCFG_H8_SCI_SET_EXTERNAL_CLOCK_PERIOD(attotime::from_hz(S23_JVSCLOCK/8))
MCFG_CPU_ADD("iocpu", H83334, S23_JVSCLOCK )
MCFG_CPU_PROGRAM_MAP( s23iobrdmap )
@ -3322,7 +3312,7 @@ static MACHINE_CONFIG_START( gorgon, namcos23_state )
MCFG_DEVICE_MODIFY("subcpu:sci0")
MCFG_H8_SCI_TX_CALLBACK(DEVWRITELINE(":iocpu:sci0", h8_sci_device, rx_w))
MCFG_QUANTUM_TIME(attotime::from_hz(60000))
MCFG_QUANTUM_TIME(attotime::from_hz(2*115200))
MCFG_NAMCO_SETTINGS_ADD("namco_settings")
@ -3377,7 +3367,9 @@ static MACHINE_CONFIG_START( s23, namcos23_state )
MCFG_CPU_PROGRAM_MAP( s23h8rwmap )
MCFG_CPU_IO_MAP( s23h8iomap )
MCFG_TIMER_DRIVER_ADD_PERIODIC("jvs_timer", namcos23_state, jvs_timer, attotime::from_hz(S23_JVSCLOCK/8*2))
// Timer at 115200*16 for the jvs serial clock
MCFG_DEVICE_MODIFY(":subcpu:sci0")
MCFG_H8_SCI_SET_EXTERNAL_CLOCK_PERIOD(attotime::from_hz(S23_JVSCLOCK/8))
MCFG_CPU_ADD("iocpu", H83334, S23_JVSCLOCK )
MCFG_CPU_PROGRAM_MAP( s23iobrdmap )
@ -3388,7 +3380,7 @@ static MACHINE_CONFIG_START( s23, namcos23_state )
MCFG_DEVICE_MODIFY("subcpu:sci0")
MCFG_H8_SCI_TX_CALLBACK(DEVWRITELINE(":iocpu:sci0", h8_sci_device, rx_w))
MCFG_QUANTUM_TIME(attotime::from_hz(60000))
MCFG_QUANTUM_TIME(attotime::from_hz(2*115200))
MCFG_NAMCO_SETTINGS_ADD("namco_settings")
@ -3463,9 +3455,11 @@ static MACHINE_CONFIG_START( ss23, namcos23_state )
MCFG_CPU_PROGRAM_MAP( s23h8rwmap )
MCFG_CPU_IO_MAP( s23h8iomap )
MCFG_TIMER_DRIVER_ADD_PERIODIC("jvs_timer", namcos23_state, jvs_timer, attotime::from_hz(S23_JVSCLOCK/8*2))
// Timer at 115200*16 for the jvs serial clock
MCFG_DEVICE_MODIFY(":subcpu:sci0")
MCFG_H8_SCI_SET_EXTERNAL_CLOCK_PERIOD(attotime::from_hz(S23_JVSCLOCK/8))
MCFG_QUANTUM_TIME(attotime::from_hz(60000))
MCFG_QUANTUM_TIME(attotime::from_hz(2*115200))
MCFG_NAMCO_SETTINGS_ADD("namco_settings")
@ -3508,7 +3502,6 @@ static MACHINE_CONFIG_START( ss23, namcos23_state )
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( timecrs2v4a, ss23 )
/* basic machine hardware */
MCFG_CPU_ADD("iocpu", H83334, S23_JVSCLOCK )
MCFG_CPU_PROGRAM_MAP( timecrs2iobrdmap )