trunk/src/emu/machine/pla.c
| r241887 | r241888 | |
| 2 | 2 | // copyright-holders:Curt Coder |
| 3 | 3 | /********************************************************************** |
| 4 | 4 | |
| 5 | | PLS100 16x48x8 Programmable Logic Array emulation |
| 5 | PLA (Programmable Logic Array) emulation |
| 6 | 6 | |
| 7 | 7 | Copyright MESS Team. |
| 8 | 8 | Visit http://mamedev.org for licensing and usage restrictions. |
| r241887 | r241888 | |
| 10 | 10 | **********************************************************************/ |
| 11 | 11 | |
| 12 | 12 | #include "pla.h" |
| 13 | #include "jedparse.h" |
| 14 | #include "plaparse.h" |
| 13 | 15 | |
| 14 | 16 | |
| 17 | const device_type PLA = &device_creator<pla_device>; |
| 15 | 18 | |
| 16 | | //************************************************************************** |
| 17 | | // DEVICE TYPE DEFINITIONS |
| 18 | | //************************************************************************** |
| 19 | | |
| 20 | | const device_type PLS100 = &device_creator<pls100_device>; |
| 21 | | const device_type MOS8721 = &device_creator<mos8721_device>; |
| 22 | | |
| 23 | | |
| 24 | | |
| 25 | | //************************************************************************** |
| 26 | | // LIVE DEVICE |
| 27 | | //************************************************************************** |
| 28 | | |
| 29 | 19 | //------------------------------------------------- |
| 30 | 20 | // pla_device - constructor |
| 31 | 21 | //------------------------------------------------- |
| 32 | 22 | |
| 33 | | pla_device::pla_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int inputs, int outputs, int terms, UINT32 input_mask, const char *shortname, const char *source) : |
| 34 | | device_t(mconfig, type, name, tag, owner, clock, shortname, source), |
| 35 | | m_inputs(inputs), |
| 36 | | m_outputs(outputs), |
| 37 | | m_terms(terms), |
| 38 | | m_input_mask(((UINT64)input_mask << 32) | input_mask) |
| 23 | pla_device::pla_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 24 | : device_t(mconfig, PLA, "PLA", tag, owner, clock, "pla", __FILE__), |
| 25 | m_format(PLA_FMT_JEDBIN), |
| 26 | m_inputs(0), |
| 27 | m_outputs(0), |
| 28 | m_terms(0), |
| 29 | m_input_mask(0) |
| 39 | 30 | { |
| 40 | 31 | } |
| 41 | 32 | |
| 42 | | pls100_device::pls100_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 43 | | pla_device(mconfig, PLS100, "PLS100", tag, owner, clock, 16, 8, 48, 0xffff, "pls100", __FILE__), |
| 44 | | m_output(*this, "output") |
| 45 | | { |
| 46 | | } |
| 47 | 33 | |
| 48 | | mos8721_device::mos8721_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 49 | | pla_device(mconfig, MOS8721, "MOS8721", tag, owner, clock, 27, 18, 379, 0x7ffffff, "mos8721", __FILE__) // TODO actual number of terms is unknown |
| 50 | | { |
| 51 | | } |
| 52 | | |
| 53 | | |
| 54 | 34 | //------------------------------------------------- |
| 55 | 35 | // device_start - device-specific startup |
| 56 | 36 | //------------------------------------------------- |
| 57 | 37 | |
| 58 | 38 | void pla_device::device_start() |
| 59 | 39 | { |
| 60 | | assert(machine().root_device().memregion(tag()) != NULL); |
| 40 | assert(*region() != NULL); |
| 41 | assert(m_terms < MAX_TERMS); |
| 42 | assert(m_inputs <= 32 && m_outputs <= 32); |
| 61 | 43 | |
| 44 | if (m_input_mask == 0) |
| 45 | m_input_mask = ((UINT64)1 << m_inputs) - 1; |
| 46 | m_input_mask = ((UINT64)m_input_mask << 32) | m_input_mask; |
| 47 | |
| 62 | 48 | // parse fusemap |
| 63 | 49 | parse_fusemap(); |
| 64 | 50 | |
| 65 | | // clear cache |
| 66 | | for (int i = 0; i < CACHE_SIZE; i++) |
| 67 | | { |
| 68 | | m_cache[i] = 0; |
| 69 | | } |
| 51 | // initialize cache |
| 52 | m_cache2_ptr = 0; |
| 53 | for (int i = 0; i < CACHE2_SIZE; i++) |
| 54 | m_cache2[i] = 0; |
| 70 | 55 | |
| 71 | | m_cache_ptr = 0; |
| 56 | m_cache_size = 0; |
| 57 | int csize = 1 << ((m_inputs > MAX_CACHE_BITS) ? MAX_CACHE_BITS : m_inputs); |
| 58 | m_cache.resize(csize); |
| 59 | for (int i = 0; i < csize; i++) |
| 60 | m_cache[i] = read(i); |
| 61 | |
| 62 | m_cache_size = csize; |
| 72 | 63 | } |
| 73 | 64 | |
| 74 | | void pls100_device::device_start() |
| 75 | | { |
| 76 | | pla_device::device_start(); |
| 77 | 65 | |
| 78 | | m_output.allocate(0x10000); |
| 79 | | |
| 80 | | for (UINT32 input = 0; input < 0x10000; input++) |
| 81 | | { |
| 82 | | m_output[input] = pla_device::read(input); |
| 83 | | } |
| 84 | | } |
| 85 | | |
| 86 | | |
| 87 | 66 | //------------------------------------------------- |
| 88 | 67 | // parse_fusemap - |
| 89 | 68 | //------------------------------------------------- |
| 90 | 69 | |
| 91 | 70 | void pla_device::parse_fusemap() |
| 92 | 71 | { |
| 93 | | memory_region *region = machine().root_device().memregion(tag()); |
| 94 | 72 | jed_data jed; |
| 95 | | |
| 96 | | jedbin_parse(region->base(), region->bytes(), &jed); |
| 97 | | |
| 73 | int result = JEDERR_NONE; |
| 74 | |
| 75 | // read pla file |
| 76 | switch (m_format) |
| 77 | { |
| 78 | case PLA_FMT_JEDBIN: |
| 79 | result = jedbin_parse(region()->base(), region()->bytes(), &jed); |
| 80 | break; |
| 81 | |
| 82 | case PLA_FMT_BERKELEY: |
| 83 | result = pla_parse(region()->base(), region()->bytes(), &jed); |
| 84 | break; |
| 85 | } |
| 86 | |
| 87 | if (result != JEDERR_NONE) |
| 88 | fatalerror("%s PLA parse error %d\n", tag(), result); |
| 89 | |
| 90 | // parse it |
| 98 | 91 | UINT32 fusenum = 0; |
| 99 | 92 | |
| 100 | 93 | for (int p = 0; p < m_terms; p++) |
| r241887 | r241888 | |
| 143 | 136 | UINT32 pla_device::read(UINT32 input) |
| 144 | 137 | { |
| 145 | 138 | // try the cache first |
| 146 | | for (int i = 0; i < CACHE_SIZE; ++i) |
| 139 | if (input < m_cache_size) |
| 140 | return m_cache[input]; |
| 141 | |
| 142 | for (int i = 0; i < CACHE2_SIZE; ++i) |
| 147 | 143 | { |
| 148 | | UINT64 cache_entry = m_cache[i]; |
| 144 | UINT64 cache2_entry = m_cache2[i]; |
| 149 | 145 | |
| 150 | | if ((UINT32)cache_entry == input) |
| 146 | if ((UINT32)cache2_entry == input) |
| 151 | 147 | { |
| 152 | | // cache hit |
| 153 | | return cache_entry >> 32; |
| 148 | // cache2 hit |
| 149 | return cache2_entry >> 32; |
| 154 | 150 | } |
| 155 | 151 | } |
| 156 | 152 | |
| r241887 | r241888 | |
| 170 | 166 | |
| 171 | 167 | s ^= m_xor; |
| 172 | 168 | |
| 173 | | // store output in cache |
| 174 | | m_cache[m_cache_ptr] = s | input; |
| 175 | | ++m_cache_ptr &= (CACHE_SIZE - 1); |
| 169 | // store output in cache2 |
| 170 | m_cache2[m_cache2_ptr] = s | input; |
| 171 | ++m_cache2_ptr &= (CACHE2_SIZE - 1); |
| 176 | 172 | |
| 177 | 173 | return s >> 32; |
| 178 | 174 | } |
| 179 | | |
| 180 | | |
| 181 | | //------------------------------------------------- |
| 182 | | // read - |
| 183 | | //------------------------------------------------- |
| 184 | | |
| 185 | | UINT32 pls100_device::read(UINT32 input) |
| 186 | | { |
| 187 | | return m_output[input]; |
| 188 | | } |
trunk/src/emu/machine/pla.h
| r241887 | r241888 | |
| 2 | 2 | // copyright-holders:Curt Coder |
| 3 | 3 | /********************************************************************** |
| 4 | 4 | |
| 5 | | PLS100 16x48x8 Programmable Logic Array emulation |
| 5 | PLA (Programmable Logic Array) emulation |
| 6 | 6 | |
| 7 | 7 | Copyright MESS Team. |
| 8 | 8 | Visit http://mamedev.org for licensing and usage restrictions. |
| 9 | 9 | |
| 10 | | ********************************************************************** |
| 11 | | _____ _____ |
| 12 | | FE 1 |* \_/ | 28 Vcc |
| 13 | | I7 2 | | 27 I8 |
| 14 | | I6 3 | | 26 I9 |
| 15 | | I5 4 | | 25 I10 |
| 16 | | I4 5 | | 24 I11 |
| 17 | | I3 6 | 82S100 | 23 I12 |
| 18 | | I2 7 | 82S101 | 22 I13 |
| 19 | | I1 8 | PLS100 | 21 I14 |
| 20 | | I0 9 | PLS101 | 20 I15 |
| 21 | | F7 10 | | 19 _CE |
| 22 | | F6 11 | | 18 F0 |
| 23 | | F5 12 | | 17 F1 |
| 24 | | F4 13 | | 16 F2 |
| 25 | | GND 14 |_____________| 15 F3 |
| 26 | | |
| 27 | 10 | **********************************************************************/ |
| 28 | 11 | |
| 29 | 12 | #pragma once |
| r241887 | r241888 | |
| 32 | 15 | #define __PLA__ |
| 33 | 16 | |
| 34 | 17 | #include "emu.h" |
| 35 | | #include "jedparse.h" |
| 36 | 18 | |
| 37 | 19 | |
| 38 | 20 | |
| r241887 | r241888 | |
| 41 | 23 | //************************************************************************** |
| 42 | 24 | |
| 43 | 25 | #define MAX_TERMS 512 |
| 44 | | #define CACHE_SIZE 8 |
| 26 | #define MAX_CACHE_BITS 16 |
| 27 | #define CACHE2_SIZE 8 |
| 45 | 28 | |
| 29 | enum |
| 30 | { |
| 31 | PLA_FMT_JEDBIN = 0, |
| 32 | PLA_FMT_BERKELEY |
| 33 | }; |
| 46 | 34 | |
| 47 | 35 | |
| 36 | |
| 48 | 37 | ///************************************************************************* |
| 49 | 38 | // INTERFACE CONFIGURATION MACROS |
| 50 | 39 | ///************************************************************************* |
| 51 | 40 | |
| 41 | #define MCFG_PLA_ADD(_tag, _inputs, _outputs, _terms) \ |
| 42 | MCFG_DEVICE_ADD(_tag, PLA, 0) \ |
| 43 | pla_device::set_num_inputs(*device, _inputs); \ |
| 44 | pla_device::set_num_outputs(*device, _outputs); \ |
| 45 | pla_device::set_num_terms(*device, _terms); |
| 46 | |
| 47 | #define MCFG_PLA_INPUTMASK(_mask) \ |
| 48 | pla_device::set_inputmask(*device, _mask); |
| 49 | |
| 50 | #define MCFG_PLA_FILEFORMAT(_format) \ |
| 51 | pla_device::set_format(*device, _format); |
| 52 | |
| 53 | |
| 54 | // macros for known (and used) devices |
| 55 | |
| 56 | // 82S100, 82S101, PLS100, PLS101 |
| 57 | // 16x48x8 PLA, 28-pin |
| 52 | 58 | #define MCFG_PLS100_ADD(_tag) \ |
| 53 | | MCFG_DEVICE_ADD(_tag, PLS100, 0) |
| 59 | MCFG_PLA_ADD(_tag, 16, 8, 48) |
| 54 | 60 | |
| 61 | // MOS 8721 PLA |
| 62 | // TODO: actual number of terms is unknown |
| 55 | 63 | #define MCFG_MOS8721_ADD(_tag) \ |
| 56 | | MCFG_DEVICE_ADD(_tag, MOS8721, 0) |
| 64 | MCFG_PLA_ADD(_tag, 27, 18, 379) |
| 57 | 65 | |
| 58 | 66 | |
| 67 | |
| 59 | 68 | ///************************************************************************* |
| 60 | 69 | // TYPE DEFINITIONS |
| 61 | 70 | ///************************************************************************* |
| 62 | 71 | |
| 63 | 72 | // ======================> pla_device |
| 64 | 73 | |
| 65 | | class pla_device : public device_t |
| 74 | class pla_device : public device_t |
| 66 | 75 | { |
| 67 | 76 | public: |
| 68 | 77 | // construction/destruction |
| 69 | | pla_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int inputs, int outputs, int terms, UINT32 output_mask, const char *shortname, const char *source); |
| 78 | pla_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 70 | 79 | |
| 71 | | virtual UINT32 read(UINT32 input); |
| 80 | // static configuration helpers |
| 81 | static void set_num_inputs(device_t &device, UINT32 i) { downcast<pla_device &>(device).m_inputs = i; } |
| 82 | static void set_num_outputs(device_t &device, UINT32 o) { downcast<pla_device &>(device).m_outputs = o; } |
| 83 | static void set_num_terms(device_t &device, UINT32 t) { downcast<pla_device &>(device).m_terms = t; } |
| 84 | static void set_inputmask(device_t &device, UINT32 mask) { downcast<pla_device &>(device).m_input_mask = mask; } // UINT32! |
| 85 | static void set_format(device_t &device, int format) { downcast<pla_device &>(device).m_format = format; } |
| 72 | 86 | |
| 87 | UINT32 read(UINT32 input); |
| 88 | |
| 73 | 89 | protected: |
| 74 | 90 | // device-level overrides |
| 75 | 91 | virtual void device_start(); |
| 76 | 92 | |
| 93 | private: |
| 77 | 94 | void parse_fusemap(); |
| 78 | 95 | |
| 79 | | int m_inputs; |
| 80 | | int m_outputs; |
| 81 | | int m_terms; |
| 96 | int m_format; |
| 97 | |
| 98 | UINT32 m_inputs; |
| 99 | UINT32 m_outputs; |
| 100 | UINT32 m_terms; |
| 82 | 101 | UINT64 m_input_mask; |
| 83 | 102 | UINT64 m_xor; |
| 84 | 103 | |
| 104 | int m_cache_size; |
| 105 | dynamic_array<UINT32> m_cache; |
| 106 | UINT64 m_cache2[CACHE2_SIZE]; |
| 107 | UINT8 m_cache2_ptr; |
| 108 | |
| 85 | 109 | struct term |
| 86 | 110 | { |
| 87 | 111 | UINT64 m_and; |
| 88 | 112 | UINT64 m_or; |
| 89 | | }; |
| 90 | | |
| 91 | | term m_term[MAX_TERMS]; |
| 92 | | |
| 93 | | UINT64 m_cache[CACHE_SIZE]; |
| 94 | | UINT8 m_cache_ptr; |
| 113 | } m_term[MAX_TERMS]; |
| 95 | 114 | }; |
| 96 | 115 | |
| 97 | 116 | |
| 98 | | // ======================> pls100_device |
| 99 | | |
| 100 | | class pls100_device : public pla_device |
| 101 | | { |
| 102 | | public: |
| 103 | | pls100_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 104 | | |
| 105 | | // device-level overrides |
| 106 | | virtual void device_start(); |
| 107 | | |
| 108 | | virtual UINT32 read(UINT32 input); |
| 109 | | |
| 110 | | private: |
| 111 | | optional_shared_ptr<UINT8> m_output; |
| 112 | | }; |
| 113 | | |
| 114 | | |
| 115 | | // ======================> mos8721_device |
| 116 | | |
| 117 | | class mos8721_device : public pla_device |
| 118 | | { |
| 119 | | public: |
| 120 | | mos8721_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 121 | | }; |
| 122 | | |
| 123 | | |
| 124 | 117 | // device type definition |
| 125 | | extern const device_type PLS100; |
| 126 | | extern const device_type MOS8721; |
| 118 | extern const device_type PLA; |
| 127 | 119 | |
| 128 | 120 | |
| 129 | | |
| 130 | 121 | #endif |