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:
Patrick Mackinlay 2019-02-20 19:37:41 +07:00
parent e17ff486db
commit ac63bffecc
6 changed files with 141 additions and 78 deletions

View File

@ -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];
}

View File

@ -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)

View File

@ -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);

View File

@ -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;
};

View File

@ -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");

View File

@ -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);