mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
alpha: implement srom interface (nw)
* alpha: added icache and srom interface * xc1700e: implemented oe/reset line * jensen: connect the cpu to the srom
This commit is contained in:
parent
e17ff486db
commit
ac63bffecc
@ -4,7 +4,7 @@
|
||||
/*
|
||||
* An implementation of the Digital Alpha CPU family.
|
||||
*
|
||||
* Sources
|
||||
* Sources:
|
||||
*
|
||||
* http://bitsavers.org/pdf/dec/alpha/21064-aa-RISC%20Microprocessor%20Preliminary%20Data%20Sheet-apr92.pdf
|
||||
* http://bitsavers.org/pdf/dec/alpha/Sites_AlphaAXPArchitectureReferenceManual_2ed_1995.pdf
|
||||
@ -52,6 +52,7 @@ alpha_ev4_device::alpha_ev4_device(const machine_config &mconfig, device_type ty
|
||||
|
||||
alpha_device::alpha_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
|
||||
: cpu_device(mconfig, type, tag, owner, clock)
|
||||
, m_dasm_type(alpha_disassembler::dasm_type::TYPE_UNKNOWN)
|
||||
, m_as_config
|
||||
{
|
||||
address_space_config("0", ENDIANNESS_LITTLE, 64, 32, 0),
|
||||
@ -59,7 +60,8 @@ alpha_device::alpha_device(const machine_config &mconfig, device_type type, cons
|
||||
address_space_config("2", ENDIANNESS_LITTLE, 64, 32, 0),
|
||||
address_space_config("3", ENDIANNESS_LITTLE, 64, 32, 0)
|
||||
}
|
||||
, m_dasm_type(alpha_disassembler::dasm_type::TYPE_UNKNOWN)
|
||||
, m_srom_oe_cb(*this)
|
||||
, m_srom_data_cb(*this)
|
||||
, m_icount(0)
|
||||
{
|
||||
}
|
||||
@ -86,6 +88,9 @@ void alpha_device::device_start()
|
||||
// floating point registers
|
||||
for (unsigned i = 0; i < 32; i++)
|
||||
state_add(i + 32, util::string_format("F%d", i).c_str(), m_f[i]);
|
||||
|
||||
m_srom_oe_cb.resolve_safe();
|
||||
m_srom_data_cb.resolve_safe(0);
|
||||
}
|
||||
|
||||
void alpha_device::device_reset()
|
||||
@ -129,8 +134,8 @@ device_memory_interface::space_config_vector alpha_device::memory_space_config()
|
||||
* the top two bits to select one of four memory spaces with the other 32
|
||||
* bits giving the offset within each space. This approach works out quite
|
||||
* well for the jensen hardware, which uses the first space for memory, and
|
||||
* the others for a variety of I/O memory mapping.
|
||||
*
|
||||
* the others for a variety of I/O memory mapping.
|
||||
*
|
||||
* Note: space numbers are multiplied by two to avoid the special handling
|
||||
* applied to the decrypted opcode space (number 3).
|
||||
*/
|
||||
@ -700,9 +705,20 @@ template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::va
|
||||
|
||||
void alpha_device::fetch(u64 address, std::function<void(u32)> &&apply)
|
||||
{
|
||||
unsigned const s = (address >> 31) & 6;
|
||||
cpu_translate(address, TRANSLATE_FETCH);
|
||||
|
||||
apply(space(s).read_dword(address));
|
||||
apply(icache_fetch(address));
|
||||
}
|
||||
|
||||
u32 alpha_device::read_srom(unsigned const bits)
|
||||
{
|
||||
u32 data = 0;
|
||||
|
||||
for (unsigned i = 0; i < bits; i++)
|
||||
if (m_srom_data_cb())
|
||||
data |= (1U << i);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void alpha_ev4_device::device_start()
|
||||
@ -925,5 +941,55 @@ void alpha_ev4_device::abx_set(u8 reg, u64 data)
|
||||
logerror("invalid mtpr/a register %d (%s)\n", reg, machine().describe_context());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void dec_21064_device::device_reset()
|
||||
{
|
||||
alpha_ev4_device::device_reset();
|
||||
|
||||
m_srom_oe_cb(0);
|
||||
|
||||
// load icache from srom
|
||||
for (icache_block &block : m_icache)
|
||||
{
|
||||
block.lw[0] = read_srom(32);
|
||||
block.lw[2] = read_srom(32);
|
||||
block.lw[4] = read_srom(32);
|
||||
block.lw[6] = read_srom(32);
|
||||
|
||||
block.tag = read_srom(21);
|
||||
block.aav = read_srom(8);
|
||||
|
||||
block.lw[1] = read_srom(32);
|
||||
block.lw[3] = read_srom(32);
|
||||
block.lw[5] = read_srom(32);
|
||||
block.lw[7] = read_srom(32);
|
||||
|
||||
block.bht = read_srom(8);
|
||||
}
|
||||
|
||||
m_srom_oe_cb(1);
|
||||
}
|
||||
|
||||
u32 dec_21064_device::icache_fetch(u64 const address)
|
||||
{
|
||||
icache_block &block = m_icache[(address >> 5) & 0xff];
|
||||
|
||||
// check tag, valid, and asm or asn
|
||||
if ((block.tag != (address >> 13)) || !(block.aav & AAV_V) || (!(block.aav & AAV_ASM) && ((block.aav & AAV_ASN) != (((m_ibx[IBX_ICCSR] & IBX_ICCSR_R_ASN) >> 28)))))
|
||||
{
|
||||
// fetch a new block
|
||||
block.tag = address >> 13;
|
||||
block.aav = AAV_V | ((m_ibx[IBX_ICCSR] & IBX_ICCSR_R_ASN) >> 28); // TODO: set ASM depending on PTE
|
||||
|
||||
// always set ASM if istream superpage mapping is enabled
|
||||
if (m_ibx[IBX_ICCSR] & IBX_ICCSR_R_MAP)
|
||||
block.aav |= AAV_ASM;
|
||||
|
||||
address_space &s = space((address >> 31) & 6);
|
||||
for (unsigned i = 0; i < 8; i++)
|
||||
block.lw[i] = s.read_dword(address | (i << 2));
|
||||
}
|
||||
|
||||
return block.lw[(address >> 2) & 7];
|
||||
}
|
||||
|
@ -13,6 +13,10 @@ class alpha_device : public cpu_device
|
||||
public:
|
||||
void set_dasm_type(alpha_disassembler::dasm_type type) { m_dasm_type = type; }
|
||||
|
||||
// input/output lines
|
||||
auto srom_oe_w() { return m_srom_oe_cb.bind(); }
|
||||
auto srom_data_r() { return m_srom_data_cb.bind(); }
|
||||
|
||||
protected:
|
||||
alpha_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
@ -48,9 +52,15 @@ protected:
|
||||
template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> store(u64 address, U data, T mem_mask = ~T(0));
|
||||
void fetch(u64 address, std::function<void(u32)> &&apply);
|
||||
|
||||
// cache helpers
|
||||
u32 read_srom(unsigned const bits);
|
||||
virtual u32 icache_fetch(u64 const address) = 0;
|
||||
|
||||
// configuration
|
||||
address_space_config m_as_config[4];
|
||||
alpha_disassembler::dasm_type m_dasm_type;
|
||||
address_space_config m_as_config[4];
|
||||
devcb_write_line m_srom_oe_cb;
|
||||
devcb_read_line m_srom_data_cb;
|
||||
|
||||
// emulation state
|
||||
int m_icount;
|
||||
@ -68,7 +78,7 @@ class alpha_ev4_device : public alpha_device
|
||||
public:
|
||||
alpha_ev4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
private:
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
@ -103,6 +113,22 @@ private:
|
||||
IBX_SL_XMIT = 22, // w
|
||||
};
|
||||
|
||||
enum ibx_itb_pte_mask : u64
|
||||
{
|
||||
IBX_ITB_PTE_W_ASM = 0x00000000'00000010, // address space match
|
||||
IBX_ITB_PTE_W_KRE = 0x00000000'00000100, // kernel read-enable
|
||||
IBX_ITB_PTE_W_ERE = 0x00000000'00000200, // executive read-enable
|
||||
IBX_ITB_PTE_W_SRE = 0x00000000'00000400, // supervisor read-enable
|
||||
IBX_ITB_PTE_W_URE = 0x00000000'00000800, // user read-enable
|
||||
IBX_ITB_PTE_W_PFN = 0x001fffff'00000000, // page frame number
|
||||
|
||||
IBX_ITB_PTE_R_KRE = 0x00000000'00000200, // kernel read-enable
|
||||
IBX_ITB_PTE_R_ERE = 0x00000000'00000400, // executive read-enable
|
||||
IBX_ITB_PTE_R_SRE = 0x00000000'00000800, // supervisor read-enable
|
||||
IBX_ITB_PTE_R_URE = 0x00000000'00001000, // user read-enable
|
||||
IBX_ITB_PTE_R_PFN = 0x00000003'ffffe000, // page frame number
|
||||
IBX_ITB_PTE_R_ASM = 0x00000004'00000000, // address space match
|
||||
};
|
||||
enum ibx_iccsr_mask : u64
|
||||
{
|
||||
IBX_ICCSR_W_PC1 = 0x00000000'00000001, // performance counter 1 interrupt enable
|
||||
@ -228,6 +254,29 @@ class dec_21064_device : public alpha_ev4_device
|
||||
{
|
||||
public:
|
||||
dec_21064_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
protected:
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual u32 icache_fetch(u64 const address) override;
|
||||
|
||||
private:
|
||||
struct icache_block
|
||||
{
|
||||
u32 lw[8]; // instruction longwords
|
||||
u32 tag; // cache tag
|
||||
u8 aav; // asn, asm and v fields
|
||||
u8 bht; // branch history table
|
||||
};
|
||||
|
||||
enum aav_mask : u8
|
||||
{
|
||||
AAV_ASN = 0x3f, // address space number
|
||||
AAV_ASM = 0x40, // address space match
|
||||
AAV_V = 0x80, // valid
|
||||
};
|
||||
|
||||
icache_block m_icache[256];
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(DEC_21064, dec_21064_device)
|
||||
|
@ -17,8 +17,7 @@
|
||||
* XC1704L 4,194,304
|
||||
*
|
||||
* The input C̅E̅ and CLK lines have not been explicitly implemented; these are
|
||||
* assumed to be asserted as expected before/during data read. Similarly, the
|
||||
* RESET/O̅E̅ or OE/R̅E̅S̅E̅T̅ is implicitly handled by device_reset(). The effect of
|
||||
* assumed to be asserted as expected before/during data read. The effect of
|
||||
* C̅E̅O̅ can be obtained by connecting the cascade_r callback to the data_r of
|
||||
* the cascaded device and resetting all devices when needed.
|
||||
*
|
||||
@ -53,6 +52,8 @@ base_xc1700e_device::base_xc1700e_device(const machine_config &mconfig, device_t
|
||||
, m_capacity(capacity)
|
||||
, m_region(*this, DEVICE_SELF)
|
||||
, m_cascade_cb(*this)
|
||||
, m_reset(true)
|
||||
, m_address(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -60,16 +61,23 @@ void base_xc1700e_device::device_start()
|
||||
{
|
||||
m_cascade_cb.resolve_safe(1);
|
||||
|
||||
save_item(NAME(m_reset));
|
||||
save_item(NAME(m_address));
|
||||
}
|
||||
|
||||
void base_xc1700e_device::device_reset()
|
||||
void base_xc1700e_device::reset_w(int state)
|
||||
{
|
||||
m_address = 0;
|
||||
if (state)
|
||||
m_address = 0;
|
||||
|
||||
m_reset = bool(state);
|
||||
}
|
||||
|
||||
int base_xc1700e_device::data_r()
|
||||
{
|
||||
if (m_reset)
|
||||
return 1;
|
||||
|
||||
if (m_address < m_capacity)
|
||||
{
|
||||
int const data = BIT(m_region->as_u8(m_address >> 3), m_address & 7);
|
||||
|
@ -12,7 +12,8 @@ public:
|
||||
// configuration
|
||||
auto cascade_r() { return m_cascade_cb.bind(); }
|
||||
|
||||
// output line
|
||||
// input/output lines
|
||||
void reset_w(int state);
|
||||
int data_r();
|
||||
|
||||
protected:
|
||||
@ -20,7 +21,6 @@ protected:
|
||||
|
||||
// device_t overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
// device configuration
|
||||
@ -30,6 +30,7 @@ private:
|
||||
devcb_read_line m_cascade_cb;
|
||||
|
||||
// device state
|
||||
bool m_reset;
|
||||
unsigned m_address;
|
||||
};
|
||||
|
||||
|
@ -38,66 +38,6 @@ void jensen_state::machine_start()
|
||||
|
||||
void jensen_state::machine_reset()
|
||||
{
|
||||
unpack_srom();
|
||||
}
|
||||
|
||||
u32 jensen_state::get_srom(unsigned const bits)
|
||||
{
|
||||
u32 data = 0;
|
||||
|
||||
for (unsigned i = 0; i < bits; i++)
|
||||
if (m_srom->data_r())
|
||||
data |= (1U << i);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void jensen_state::unpack_srom()
|
||||
{
|
||||
/*
|
||||
* Read the packed data fields from the srom dump and turn them into
|
||||
* executable code. This should actually be done by the Alpha itself,
|
||||
* with the data being written into the primary instruction cache.
|
||||
*/
|
||||
|
||||
unsigned ram_offset = 0;
|
||||
u32 lw_data[8];
|
||||
|
||||
m_srom->reset();
|
||||
|
||||
// there are up to 256 blocks of 293 bits each
|
||||
for (unsigned block = 0; block < 256; block++)
|
||||
{
|
||||
// lw0 lw2 lw4 lw6
|
||||
lw_data[0] = get_srom(32);
|
||||
lw_data[2] = get_srom(32);
|
||||
lw_data[4] = get_srom(32);
|
||||
lw_data[6] = get_srom(32);
|
||||
|
||||
get_srom(21); // tag
|
||||
get_srom(6); // asn
|
||||
get_srom(1); // asm
|
||||
get_srom(1); // v
|
||||
|
||||
// lw1 lw3 lw5 lw7
|
||||
lw_data[1] = get_srom(32);
|
||||
lw_data[3] = get_srom(32);
|
||||
lw_data[5] = get_srom(32);
|
||||
lw_data[7] = get_srom(32);
|
||||
|
||||
get_srom(8); // bht
|
||||
|
||||
// copy each instruction longword to ram
|
||||
for (u32 const lw : lw_data)
|
||||
{
|
||||
m_ram->write(BYTE4_XOR_LE(ram_offset + 0), lw >> 0);
|
||||
m_ram->write(BYTE4_XOR_LE(ram_offset + 1), lw >> 8);
|
||||
m_ram->write(BYTE4_XOR_LE(ram_offset + 2), lw >> 16);
|
||||
m_ram->write(BYTE4_XOR_LE(ram_offset + 3), lw >> 24);
|
||||
|
||||
ram_offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void jensen_state::init_common()
|
||||
@ -164,6 +104,8 @@ void jensen_state::jensen(machine_config &config)
|
||||
m_cpu->set_addrmap(2, &jensen_state::local_io);
|
||||
m_cpu->set_addrmap(4, &jensen_state::eisa_memory);
|
||||
m_cpu->set_addrmap(6, &jensen_state::eisa_io);
|
||||
m_cpu->srom_oe_w().set(m_srom, FUNC(xc1765e_device::reset_w));
|
||||
m_cpu->srom_data_r().set(m_srom, FUNC(xc1765e_device::data_r));
|
||||
|
||||
RAM(config, m_ram);
|
||||
m_ram->set_default_size("16M");
|
||||
|
@ -48,9 +48,6 @@ protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void unpack_srom();
|
||||
u32 get_srom(unsigned const bits);
|
||||
|
||||
// address maps
|
||||
void local_memory(address_map &map);
|
||||
void local_io(address_map &map);
|
||||
|
Loading…
Reference in New Issue
Block a user