diff options
Diffstat (limited to 'src/devices/machine/pla.cpp')
-rw-r--r-- | src/devices/machine/pla.cpp | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/devices/machine/pla.cpp b/src/devices/machine/pla.cpp new file mode 100644 index 00000000000..e8ca43d448f --- /dev/null +++ b/src/devices/machine/pla.cpp @@ -0,0 +1,181 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder, hap +/********************************************************************** + + PLA (Programmable Logic Array) emulation + +**********************************************************************/ + +#include "pla.h" +#include "jedparse.h" +#include "plaparse.h" + + +const device_type PLA = &device_creator<pla_device>; + +//------------------------------------------------- +// pla_device - constructor +//------------------------------------------------- + +pla_device::pla_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, PLA, "PLA", tag, owner, clock, "pla", __FILE__), + m_format(PLA_FMT_JEDBIN), + m_inputs(0), + m_outputs(0), + m_terms(0), + m_input_mask(0), + m_xor(0) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void pla_device::device_start() +{ + assert(region() != NULL); + assert(m_terms < MAX_TERMS); + assert(m_inputs < 32 && m_outputs <= 32); + + if (m_input_mask == 0) + m_input_mask = ((UINT64)1 << m_inputs) - 1; + m_input_mask = ((UINT64)m_input_mask << 32) | m_input_mask; + + // parse fusemap + parse_fusemap(); + + // initialize cache + m_cache2_ptr = 0; + for (int i = 0; i < CACHE2_SIZE; i++) + m_cache2[i] = 0x80000000; + + m_cache_size = 0; + int csize = 1 << ((m_inputs > MAX_CACHE_BITS) ? MAX_CACHE_BITS : m_inputs); + m_cache.resize(csize); + for (int i = 0; i < csize; i++) + m_cache[i] = read(i); + + m_cache_size = csize; +} + + +//------------------------------------------------- +// parse_fusemap - +//------------------------------------------------- + +void pla_device::parse_fusemap() +{ + jed_data jed; + int result = JEDERR_NONE; + + // read pla file + switch (m_format) + { + case PLA_FMT_JEDBIN: + result = jedbin_parse(region()->base(), region()->bytes(), &jed); + break; + + case PLA_FMT_BERKELEY: + result = pla_parse(region()->base(), region()->bytes(), &jed); + break; + } + + if (result != JEDERR_NONE) + { + for (int p = 0; p < m_terms; p++) + { + m_term[p].and_mask = 0; + m_term[p].or_mask = 0; + } + + logerror("%s PLA parse error %d!\n", tag(), result); + return; + } + + // parse it + UINT32 fusenum = 0; + + for (int p = 0; p < m_terms; p++) + { + term *term = &m_term[p]; + + // AND mask + term->and_mask = 0; + + for (int i = 0; i < m_inputs; i++) + { + // complement + term->and_mask |= (UINT64)jed_get_fuse(&jed, fusenum++) << (i + 32); + + // true + term->and_mask |= (UINT64)jed_get_fuse(&jed, fusenum++) << i; + } + + // OR mask + term->or_mask = 0; + + for (int f = 0; f < m_outputs; f++) + { + term->or_mask |= !jed_get_fuse(&jed, fusenum++) << f; + } + + term->or_mask <<= 32; + } + + // XOR mask + m_xor = 0; + + for (int f = 0; f < m_outputs; f++) + { + m_xor |= jed_get_fuse(&jed, fusenum++) << f; + } + + m_xor <<= 32; +} + + +//------------------------------------------------- +// read - +//------------------------------------------------- + +UINT32 pla_device::read(UINT32 input) +{ + // try the cache first + if (input < m_cache_size) + return m_cache[input]; + + for (int i = 0; i < CACHE2_SIZE; ++i) + { + UINT64 cache2_entry = m_cache2[i]; + + if ((UINT32)cache2_entry == input) + { + // cache2 hit + return cache2_entry >> 32; + } + } + + // cache miss, process terms + UINT64 inputs = ((~(UINT64)input << 32) | input) & m_input_mask; + UINT64 s = 0; + + for (int i = 0; i < m_terms; ++i) + { + term* term = &m_term[i]; + + if ((term->and_mask | inputs) == m_input_mask) + { + s |= term->or_mask; + } + } + + s ^= m_xor; + + // store output in cache2 + m_cache2[m_cache2_ptr] = s | input; + ++m_cache2_ptr &= (CACHE2_SIZE - 1); + + return s >> 32; +} |