trunk/src/emu/machine/pla.c
| r18535 | r18536 | |
| 12 | 12 | |
| 13 | 13 | |
| 14 | 14 | //************************************************************************** |
| 15 | | // DEVICE TYPE DEFINITION |
| 15 | // DEVICE TYPE DEFINITIONS |
| 16 | 16 | //************************************************************************** |
| 17 | 17 | |
| 18 | 18 | const device_type PLS100 = &device_creator<pls100_device>; |
| r18535 | r18536 | |
| 21 | 21 | |
| 22 | 22 | |
| 23 | 23 | //************************************************************************** |
| 24 | | // INLINE HELPERS |
| 24 | // LIVE DEVICE |
| 25 | 25 | //************************************************************************** |
| 26 | 26 | |
| 27 | 27 | //------------------------------------------------- |
| 28 | // pla_device - constructor |
| 29 | //------------------------------------------------- |
| 30 | |
| 31 | 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) |
| 32 | : device_t(mconfig, type, name, tag, owner, clock), |
| 33 | m_inputs(inputs), |
| 34 | m_outputs(outputs), |
| 35 | m_terms(terms), |
| 36 | m_input_mask(((UINT64)input_mask << 32) | input_mask) |
| 37 | { |
| 38 | } |
| 39 | |
| 40 | pls100_device::pls100_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 41 | : pla_device(mconfig, PLS100, "PLS100", tag, owner, clock, 16, 8, 48, 0xffff) |
| 42 | { |
| 43 | } |
| 44 | |
| 45 | mos8721_device::mos8721_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 46 | : pla_device(mconfig, MOS8721, "MOS8721", tag, owner, clock, 27, 18, 379, 0x7ffffff) // TODO actual number of terms is unknown |
| 47 | { |
| 48 | } |
| 49 | |
| 50 | |
| 51 | //------------------------------------------------- |
| 52 | // device_start - device-specific startup |
| 53 | //------------------------------------------------- |
| 54 | |
| 55 | void pla_device::device_start() |
| 56 | { |
| 57 | assert(machine().root_device().memregion(tag()) != NULL); |
| 58 | |
| 59 | // parse fusemap |
| 60 | parse_fusemap(); |
| 61 | |
| 62 | // clear cache |
| 63 | for (int i = 0; i < CACHE_SIZE; i++) |
| 64 | { |
| 65 | m_cache[i] = 0; |
| 66 | } |
| 67 | |
| 68 | m_cache_ptr = 0; |
| 69 | } |
| 70 | |
| 71 | |
| 72 | //------------------------------------------------- |
| 28 | 73 | // parse_fusemap - |
| 29 | 74 | //------------------------------------------------- |
| 30 | 75 | |
| 31 | | inline void pla_device::parse_fusemap() |
| 76 | void pla_device::parse_fusemap() |
| 32 | 77 | { |
| 33 | 78 | memory_region *region = machine().root_device().memregion(tag()); |
| 34 | 79 | jed_data jed; |
| 35 | 80 | |
| 36 | 81 | jedbin_parse(region->base(), region->bytes(), &jed); |
| 37 | 82 | |
| 38 | | //logerror("PLA '%s' %u fuses\n", tag(), jed.numfuses); |
| 39 | | |
| 40 | 83 | UINT32 fusenum = 0; |
| 41 | | m_xor = 0; |
| 42 | 84 | |
| 43 | | for (int term = 0; term < m_terms; term++) |
| 85 | for (int p = 0; p < m_terms; p++) |
| 44 | 86 | { |
| 45 | | m_and_comp[term] = 0; |
| 46 | | m_and_true[term] = 0; |
| 47 | | m_or[term] = 0; |
| 87 | term *term = &m_term[p]; |
| 48 | 88 | |
| 89 | // AND mask |
| 90 | term->m_and = 0; |
| 91 | |
| 49 | 92 | for (int i = 0; i < m_inputs; i++) |
| 50 | 93 | { |
| 51 | | m_and_comp[term] |= jed_get_fuse(&jed, fusenum++) << i; |
| 52 | | m_and_true[term] |= jed_get_fuse(&jed, fusenum++) << i; |
| 94 | // complement |
| 95 | term->m_and |= (UINT64)jed_get_fuse(&jed, fusenum++) << (i + 32); |
| 96 | |
| 97 | // true |
| 98 | term->m_and |= (UINT64)jed_get_fuse(&jed, fusenum++) << i; |
| 53 | 99 | } |
| 54 | 100 | |
| 101 | // OR mask |
| 102 | term->m_or = 0; |
| 103 | |
| 55 | 104 | for (int f = 0; f < m_outputs; f++) |
| 56 | 105 | { |
| 57 | | m_or[term] |= !jed_get_fuse(&jed, fusenum++) << f; |
| 106 | term->m_or |= !jed_get_fuse(&jed, fusenum++) << f; |
| 58 | 107 | } |
| 59 | 108 | |
| 60 | | //logerror("PLA '%s' %3u COMP %08x TRUE %08x OR %08x\n", tag(), term, m_and_comp[term], m_and_true[term], m_or[term]); |
| 109 | term->m_or <<= 32; |
| 61 | 110 | } |
| 62 | 111 | |
| 112 | // XOR mask |
| 113 | m_xor = 0; |
| 114 | |
| 63 | 115 | for (int f = 0; f < m_outputs; f++) |
| 64 | 116 | { |
| 65 | 117 | m_xor |= jed_get_fuse(&jed, fusenum++) << f; |
| 66 | 118 | } |
| 67 | 119 | |
| 68 | | //logerror("PLA '%s' XOR %08x\n", tag(), m_xor); |
| 120 | m_xor <<= 32; |
| 69 | 121 | } |
| 70 | 122 | |
| 71 | 123 | |
| 72 | 124 | //------------------------------------------------- |
| 73 | | // get_product - |
| 125 | // read - |
| 74 | 126 | //------------------------------------------------- |
| 75 | 127 | |
| 76 | | inline bool pla_device::get_product(int term) |
| 128 | UINT32 pla_device::read(UINT32 input) |
| 77 | 129 | { |
| 78 | | UINT32 input_comp = m_and_comp[term] | ~m_i; |
| 79 | | UINT32 input_true = m_and_true[term] | m_i; |
| 130 | // try the cache first |
| 131 | for (int i = 0; i < CACHE_SIZE; ++i) |
| 132 | { |
| 133 | UINT64 cache_entry = m_cache[i]; |
| 80 | 134 | |
| 81 | | //logerror("PLA '%s' %3u COMP %08x TRUE %08x OR %08x : %u\n", tag(), term, ~input_comp & m_output_mask, ~input_true & m_output_mask, m_or[term], (((input_comp & input_true) & m_output_mask) == m_output_mask)); |
| 135 | if ((UINT32)cache_entry == input) |
| 136 | { |
| 137 | // cache hit |
| 138 | return cache_entry >> 32; |
| 139 | } |
| 140 | } |
| 82 | 141 | |
| 83 | | return ((input_comp & input_true) & m_output_mask) == m_output_mask; |
| 84 | | } |
| 142 | // cache miss, process terms |
| 143 | UINT64 inputs = ((~(UINT64)input << 32) | input) & m_input_mask; |
| 144 | UINT64 s = 0; |
| 85 | 145 | |
| 146 | for (int i = 0; i < m_terms; ++i) |
| 147 | { |
| 148 | term term = m_term[i]; |
| 86 | 149 | |
| 87 | | //------------------------------------------------- |
| 88 | | // update_outputs - |
| 89 | | //------------------------------------------------- |
| 90 | | |
| 91 | | inline void pla_device::update_outputs() |
| 92 | | { |
| 93 | | m_s = 0; |
| 94 | | |
| 95 | | for (int term = 0; term < m_terms; term++) |
| 96 | | { |
| 97 | | if (get_product(term)) |
| 150 | if ((term.m_and | inputs) == m_input_mask) |
| 98 | 151 | { |
| 99 | | m_s |= m_or[term]; |
| 152 | s |= term.m_or; |
| 100 | 153 | } |
| 101 | 154 | } |
| 102 | | } |
| 103 | 155 | |
| 156 | s ^= m_xor; |
| 104 | 157 | |
| 158 | // store output in cache |
| 159 | m_cache[m_cache_ptr] = s | input; |
| 160 | ++m_cache_ptr &= (CACHE_SIZE - 1); |
| 105 | 161 | |
| 106 | | //************************************************************************** |
| 107 | | // LIVE DEVICE |
| 108 | | //************************************************************************** |
| 109 | | |
| 110 | | //------------------------------------------------- |
| 111 | | // pla_device - constructor |
| 112 | | //------------------------------------------------- |
| 113 | | |
| 114 | | 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 output_mask) |
| 115 | | : device_t(mconfig, type, name, tag, owner, clock), |
| 116 | | m_inputs(inputs), |
| 117 | | m_outputs(outputs), |
| 118 | | m_terms(terms), |
| 119 | | m_output_mask(output_mask) |
| 120 | | { |
| 162 | return s >> 32; |
| 121 | 163 | } |
| 122 | | |
| 123 | | pls100_device::pls100_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 124 | | : pla_device(mconfig, PLS100, "PLS100", tag, owner, clock, 16, 8, 48, 0xffff) |
| 125 | | { |
| 126 | | } |
| 127 | | |
| 128 | | mos8721_device::mos8721_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 129 | | : pla_device(mconfig, MOS8721, "MOS8721", tag, owner, clock, 27, 18, 379, 0x7ffffff) // TODO actual number of terms is unknown |
| 130 | | { |
| 131 | | } |
| 132 | | |
| 133 | | |
| 134 | | //------------------------------------------------- |
| 135 | | // device_start - device-specific startup |
| 136 | | //------------------------------------------------- |
| 137 | | |
| 138 | | void pla_device::device_start() |
| 139 | | { |
| 140 | | // parse fusemap |
| 141 | | assert(machine().root_device().memregion(tag()) != NULL); |
| 142 | | parse_fusemap(); |
| 143 | | |
| 144 | | // register for state saving |
| 145 | | save_item(NAME(m_i)); |
| 146 | | save_item(NAME(m_s)); |
| 147 | | } |
| 148 | | |
| 149 | | |
| 150 | | //------------------------------------------------- |
| 151 | | // read - |
| 152 | | //------------------------------------------------- |
| 153 | | |
| 154 | | UINT32 pla_device::read(UINT32 input) |
| 155 | | { |
| 156 | | m_i = input; |
| 157 | | |
| 158 | | update_outputs(); |
| 159 | | |
| 160 | | return m_s ^ m_xor; |
| 161 | | } |