trunk/src/emu/netlist/devices/nld_signal.h
| r31048 | r31049 | |
| 26 | 26 | // net_signal_t |
| 27 | 27 | // ---------------------------------------------------------------------------------------- |
| 28 | 28 | |
| 29 | | template <int _numdev> |
| 30 | | class net_signal_base_t : public netlist_device_t |
| 31 | | { |
| 32 | | public: |
| 33 | | net_signal_base_t() |
| 34 | | : netlist_device_t(), m_active(1) { } |
| 35 | | |
| 36 | | ATTR_COLD void start() |
| 37 | | { |
| 38 | | const char *sIN[8] = { "I1", "I2", "I3", "I4", "I5", "I6", "I7", "I8" }; |
| 39 | | |
| 40 | | register_output("Q", m_Q); |
| 41 | | for (int i=0; i < _numdev; i++) |
| 42 | | { |
| 43 | | register_input(sIN[i], m_i[i], netlist_input_t::STATE_INP_ACTIVE); |
| 44 | | } |
| 45 | | save(NAME(m_active)); |
| 46 | | } |
| 47 | | |
| 48 | | ATTR_COLD void reset() |
| 49 | | { |
| 50 | | m_Q.initial(1); |
| 51 | | m_active = 1; |
| 52 | | } |
| 53 | | |
| 54 | | #if (USE_DEACTIVE_DEVICE) |
| 55 | | ATTR_HOT void inc_active() |
| 56 | | { |
| 57 | | if (++m_active == 1) |
| 58 | | { |
| 59 | | update(); |
| 60 | | } |
| 61 | | } |
| 62 | | |
| 63 | | ATTR_HOT void dec_active() |
| 64 | | { |
| 65 | | if (--m_active == 0) |
| 66 | | { |
| 67 | | for (int i = 0; i< _numdev; i++) |
| 68 | | m_i[i].inactivate(); |
| 69 | | } |
| 70 | | } |
| 71 | | #endif |
| 72 | | |
| 73 | | public: |
| 74 | | netlist_ttl_input_t m_i[_numdev]; |
| 75 | | netlist_ttl_output_t m_Q; |
| 76 | | INT32 m_active; |
| 77 | | }; |
| 78 | | |
| 79 | | |
| 80 | 29 | template <int _numdev, int _check, int _invert> |
| 81 | 30 | class net_signal_t : public netlist_device_t |
| 82 | 31 | { |
| r31048 | r31049 | |
| 207 | 156 | |
| 208 | 157 | m_i[0].activate(); |
| 209 | 158 | m_i[1].activate(); |
| 210 | | #if 0 |
| 211 | | UINT8 res = _invert ^ 1 ^_check; |
| 212 | | if (INPLOGIC(m_i[0]) ^ _check) |
| 213 | | { |
| 214 | | if (INPLOGIC(m_i[1]) ^ _check) |
| 215 | | { |
| 216 | | res = _invert ^ _check; |
| 217 | | } |
| 218 | | else |
| 219 | | m_i[0].inactivate(); |
| 220 | | } else { |
| 221 | | if (INPLOGIC(m_i[1]) ^ _check) |
| 222 | | m_i[1].inactivate(); |
| 223 | | } |
| 224 | | OUTLOGIC(m_Q, res, times[res & 1]);// ? 22000 : 15000); |
| 225 | | #else |
| 159 | |
| 226 | 160 | const UINT8 val = (INPLOGIC(m_i[0]) ^ _check) | ((INPLOGIC(m_i[1]) ^ _check) << 1); |
| 227 | 161 | UINT8 res = _invert ^ 1 ^_check; |
| 228 | 162 | switch (val) |
| r31048 | r31049 | |
| 238 | 172 | break; |
| 239 | 173 | } |
| 240 | 174 | OUTLOGIC(m_Q, res, times[res]);// ? 22000 : 15000); |
| 241 | | #endif |
| 242 | 175 | } |
| 243 | 176 | |
| 244 | 177 | public: |
| r31048 | r31049 | |
| 248 | 181 | |
| 249 | 182 | }; |
| 250 | 183 | |
| 251 | | // The following did not improve performance |
| 252 | | #if 0 |
| 253 | | |
| 254 | | template <UINT8 _check, UINT8 _invert> |
| 255 | | class net_signal_t<3, _check, _invert> : public netlist_device_t |
| 256 | | { |
| 257 | | public: |
| 258 | | net_signal_t() : netlist_device_t(), m_active(1) { } |
| 259 | | |
| 260 | | ATTR_COLD void start() |
| 261 | | { |
| 262 | | const char *sIN[3] = { "I1", "I2", "I3" }; |
| 263 | | |
| 264 | | register_output("Q", m_Q); |
| 265 | | for (int i=0; i < 3; i++) |
| 266 | | { |
| 267 | | register_input(sIN[i], m_i[i], netlist_input_t::STATE_INP_ACTIVE); |
| 268 | | } |
| 269 | | //m_Q.initial(1); |
| 270 | | } |
| 271 | | |
| 272 | | ATTR_HOT ATTR_ALIGN void update() |
| 273 | | { |
| 274 | | const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) }; |
| 275 | | //const UINT8 res_tab[4] = {1, 1, 1, 0 }; |
| 276 | | //const UINT8 ai1[4] = {0, 1, 0, 0 }; |
| 277 | | //const UINT8 ai2[4] = {1, 0, 1, 0 }; |
| 278 | | |
| 279 | | UINT8 res = _invert ^ 1 ^_check; |
| 280 | | m_i[0].activate(); |
| 281 | | if (INPLOGIC(m_i[0]) ^ _check) |
| 282 | | { |
| 283 | | m_i[1].activate(); |
| 284 | | if (INPLOGIC(m_i[1]) ^ _check) |
| 285 | | { |
| 286 | | m_i[2].activate(); |
| 287 | | if (INPLOGIC(m_i[2]) ^ _check) |
| 288 | | { |
| 289 | | res = _invert ^ _check; |
| 290 | | } |
| 291 | | else |
| 292 | | m_i[1].inactivate(); |
| 293 | | } |
| 294 | | else |
| 295 | | { |
| 296 | | if (INPLOGIC(m_i[2]) ^ _check) |
| 297 | | m_i[2].inactivate(); |
| 298 | | m_i[0].inactivate(); |
| 299 | | } |
| 300 | | } else { |
| 301 | | if (INPLOGIC(m_i[1]) ^ _check) |
| 302 | | m_i[1].inactivate(); |
| 303 | | } |
| 304 | | OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000); |
| 305 | | } |
| 306 | | public: |
| 307 | | netlist_ttl_input_t m_i[3]; |
| 308 | | netlist_ttl_output_t m_Q; |
| 309 | | INT8 m_active; |
| 310 | | |
| 311 | | }; |
| 312 | | |
| 313 | | #endif |
| 314 | | |
| 315 | | |
| 316 | 184 | template <int _check, int _invert> |
| 317 | 185 | class net_signal_t<2, _check, _invert> : public net_signal_2inp_t<_check, _invert> |
| 318 | 186 | { |
trunk/src/emu/netlist/devices/nld_74ls629.c
| r31048 | r31049 | |
| 51 | 51 | |
| 52 | 52 | save(NAME(m_enableq)); |
| 53 | 53 | save(NAME(m_inc)); |
| 54 | save(NAME(m_out)); |
| 54 | 55 | } |
| 55 | 56 | |
| 56 | 57 | NETLIB_RESET(SN74LS629clk) |
| r31048 | r31049 | |
| 63 | 64 | { |
| 64 | 65 | if (!m_enableq) |
| 65 | 66 | { |
| 66 | | OUTLOGIC(m_Y, !m_Y.net().as_logic().new_Q(), m_inc); |
| 67 | m_out = m_out ^ 1; |
| 68 | OUTLOGIC(m_Y, m_out, m_inc); |
| 67 | 69 | } |
| 68 | 70 | else |
| 69 | 71 | { |
| r31048 | r31049 | |
| 146 | 148 | if (!m_clock.m_enableq && INPLOGIC(m_ENQ)) |
| 147 | 149 | { |
| 148 | 150 | m_clock.m_enableq = 1; |
| 149 | | OUTLOGIC(m_clock.m_Y, !m_clock.m_Y.net().as_logic().last_Q(), netlist_time::from_nsec(1)); |
| 151 | m_clock.m_out = m_clock.m_out ^ 1; |
| 152 | OUTLOGIC(m_clock.m_Y, m_clock.m_out, netlist_time::from_nsec(1)); |
| 150 | 153 | } |
| 151 | 154 | else if (m_clock.m_enableq && !INPLOGIC(m_ENQ)) |
| 152 | 155 | { |
| 153 | 156 | m_clock.m_enableq = 0; |
| 154 | | OUTLOGIC(m_clock.m_Y, !m_clock.m_Y.net().as_logic().last_Q(), netlist_time::from_nsec(1)); |
| 157 | m_clock.m_out = m_clock.m_out ^ 1; |
| 158 | OUTLOGIC(m_clock.m_Y, m_clock.m_out, netlist_time::from_nsec(1)); |
| 155 | 159 | } |
| 156 | 160 | } |
| 157 | 161 | |
trunk/src/emu/netlist/devices/nld_truthtable.h
| r0 | r31049 | |
| 1 | /* |
| 2 | * nld_truthtable.h |
| 3 | * |
| 4 | * Created on: 19 Jun 2014 |
| 5 | * Author: andre |
| 6 | */ |
| 7 | |
| 8 | #ifndef NLD_TRUTHTABLE_H_ |
| 9 | #define NLD_TRUTHTABLE_H_ |
| 10 | |
| 11 | #include "../nl_base.h" |
| 12 | |
| 13 | template<int m_NI, int m_NO> |
| 14 | class nld_truthtable_t : public netlist_device_t |
| 15 | { |
| 16 | public: |
| 17 | |
| 18 | static const int m_size = (1 << (2 * m_NI + m_NO)); |
| 19 | |
| 20 | nld_truthtable_t() |
| 21 | : netlist_device_t(), m_active(1) |
| 22 | { |
| 23 | } |
| 24 | |
| 25 | ATTR_COLD virtual void start() |
| 26 | { |
| 27 | } |
| 28 | |
| 29 | ATTR_COLD void help(UINT32 outs[], int cur, nl_util::pstring_list list, UINT64 state, UINT64 ignore, UINT16 val) |
| 30 | { |
| 31 | pstring elem = list[cur]; |
| 32 | int start = 0; |
| 33 | int end = 0; |
| 34 | int ign = 0; |
| 35 | |
| 36 | if (elem.equals("0")) |
| 37 | { |
| 38 | start = 0; |
| 39 | end = 0; |
| 40 | } |
| 41 | else if (elem.equals("1")) |
| 42 | { |
| 43 | start = 1; |
| 44 | end = 1; |
| 45 | } |
| 46 | else if (elem.equals("X")) |
| 47 | { |
| 48 | start = 0; |
| 49 | end = 1; |
| 50 | ign = 1; |
| 51 | } |
| 52 | for (int i = start; i <= end; i++) |
| 53 | { |
| 54 | const UINT64 nstate = state | (i << cur); |
| 55 | const UINT64 nignore = ignore | (ign << cur); |
| 56 | |
| 57 | if (cur < list.count() - 1) |
| 58 | { |
| 59 | help(outs, cur + 1, list, nstate, nignore, val); |
| 60 | } |
| 61 | else |
| 62 | { |
| 63 | // cutoff previous inputs and outputs for ignore |
| 64 | outs[nstate] = val | ((nignore & ((1 << m_NI)-1)) << m_NO); |
| 65 | } |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | ATTR_COLD void setup_tt(const char **truthtable, UINT32 outs[]) |
| 70 | { |
| 71 | pstring ttline = pstring(truthtable[0]); |
| 72 | truthtable++; |
| 73 | { |
| 74 | nl_util::pstring_list io = nl_util::split(ttline,"|"); |
| 75 | // checks |
| 76 | assert(io.count() == 2); |
| 77 | nl_util::pstring_list inout = nl_util::split(io[0], ","); |
| 78 | assert(inout.count() == 2 * m_NI + m_NO); |
| 79 | nl_util::pstring_list out = nl_util::split(io[1], ","); |
| 80 | assert(out.count() == m_NO); |
| 81 | |
| 82 | for (int i=0; i < m_NI; i++) |
| 83 | { |
| 84 | register_input(inout[i], m_i[i]); |
| 85 | } |
| 86 | for (int i=0; i < m_NO; i++) |
| 87 | { |
| 88 | register_output(out[i], m_Q[i]); |
| 89 | } |
| 90 | //save(NAME(m_active)); |
| 91 | ttline = pstring(truthtable[0]); |
| 92 | truthtable++; |
| 93 | } |
| 94 | |
| 95 | for (int j=0; j < m_size; j++) |
| 96 | outs[j] = -1; |
| 97 | |
| 98 | while (!ttline.equals("")) |
| 99 | { |
| 100 | nl_util::pstring_list io = nl_util::split(ttline,"|"); |
| 101 | // checks |
| 102 | assert(io.count() == 2); |
| 103 | nl_util::pstring_list inout = nl_util::split(io[0], ","); |
| 104 | assert(inout.count() == 2 * m_NI + m_NO); |
| 105 | nl_util::pstring_list out = nl_util::split(io[1], ","); |
| 106 | assert(out.count() == m_NO); |
| 107 | |
| 108 | UINT16 val = 0; |
| 109 | for (int j=0; j<m_NO; j++) |
| 110 | if (out[j].equals("1")) |
| 111 | val = val | (1 << j); |
| 112 | |
| 113 | help(outs, 0, inout, 0 , 0 , val); |
| 114 | ttline = pstring(truthtable[0]); |
| 115 | truthtable++; |
| 116 | } |
| 117 | for (int j=0; j < m_size; j++) |
| 118 | printf("%05x %04x %04x\n", j, outs[j] & ((1 << m_NO)-1), outs[j] >> m_NO); |
| 119 | m_ttp = outs; |
| 120 | } |
| 121 | |
| 122 | ATTR_COLD void reset() |
| 123 | { |
| 124 | //m_Q.initial(1); |
| 125 | m_active = 1; |
| 126 | m_last_state = 0; |
| 127 | } |
| 128 | |
| 129 | ATTR_HOT ATTR_ALIGN void update() |
| 130 | { |
| 131 | const netlist_time times[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22)}; |
| 132 | |
| 133 | // FIXME: this check is needed because update is called during startup as well |
| 134 | if (UNEXPECTED(USE_DEACTIVE_DEVICE && m_active == 0)) |
| 135 | return; |
| 136 | |
| 137 | UINT32 state = 0; |
| 138 | for (int i=0; i< m_NI; i++) |
| 139 | { |
| 140 | m_i[i].activate(); |
| 141 | state = state | (INPLOGIC(m_i[i]) << i); |
| 142 | } |
| 143 | |
| 144 | const UINT32 nstate = state | (m_last_state << m_NI); |
| 145 | const UINT32 out = m_ttp[nstate] & ((1 << m_NO) - 1); |
| 146 | const UINT32 ign = m_ttp[nstate] >> m_NO; |
| 147 | |
| 148 | for (int i=0; i< m_NI; i++) |
| 149 | if (ign & (1 << i)) |
| 150 | m_i[i].inactivate(); |
| 151 | |
| 152 | for (int i=0; i<m_NO; i++) |
| 153 | OUTLOGIC(m_Q[i], (out >> i) & 1, times[(out >> i) & 1]);// ? 22000 : 15000); |
| 154 | m_last_state = (state << m_NO) | out; |
| 155 | |
| 156 | } |
| 157 | |
| 158 | |
| 159 | #if (USE_DEACTIVE_DEVICE) |
| 160 | ATTR_HOT void inc_active() |
| 161 | { |
| 162 | if (++m_active == 1) |
| 163 | { |
| 164 | update(); |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | ATTR_HOT void dec_active() |
| 169 | { |
| 170 | if (--m_active == 0) |
| 171 | { |
| 172 | for (int i = 0; i< m_NI; i++) |
| 173 | m_i[i].inactivate(); |
| 174 | } |
| 175 | } |
| 176 | #endif |
| 177 | |
| 178 | public: |
| 179 | netlist_ttl_input_t m_i[m_NI]; |
| 180 | netlist_ttl_output_t m_Q[m_NO]; |
| 181 | |
| 182 | UINT32 *m_ttp; |
| 183 | INT32 m_active; |
| 184 | UINT32 m_last_state; |
| 185 | }; |
| 186 | |
| 187 | #endif /* NLD_TRUTHTABLE_H_ */ |
trunk/src/emu/netlist/nl_base.c
| r31048 | r31049 | |
| 455 | 455 | : netlist_object_t(NET, afamily) |
| 456 | 456 | , m_new_Q(0) |
| 457 | 457 | , m_cur_Q (0) |
| 458 | | , m_last_Q(0) |
| 459 | 458 | , m_railterminal(NULL) |
| 460 | 459 | , m_time(netlist_time::zero) |
| 461 | 460 | , m_active(0) |
| r31048 | r31049 | |
| 486 | 485 | { |
| 487 | 486 | if (m_active == 1 && m_in_queue > 0) |
| 488 | 487 | { |
| 489 | | m_last_Q = m_cur_Q; |
| 490 | 488 | railterminal().netdev().inc_active(); |
| 491 | 489 | m_cur_Q = m_new_Q; |
| 492 | 490 | } |
| r31048 | r31049 | |
| 501 | 499 | } |
| 502 | 500 | else |
| 503 | 501 | { |
| 504 | | m_cur_Q = m_last_Q = m_new_Q; |
| 502 | m_cur_Q = m_new_Q; |
| 505 | 503 | m_in_queue = 2; |
| 506 | 504 | } |
| 507 | 505 | } |
| r31048 | r31049 | |
| 541 | 539 | save(NAME(m_active)); |
| 542 | 540 | save(NAME(m_in_queue)); |
| 543 | 541 | save(NAME(m_cur_Analog)); |
| 544 | | save(NAME(m_last_Q)); |
| 545 | 542 | save(NAME(m_cur_Q)); |
| 546 | 543 | save(NAME(m_new_Q)); |
| 547 | 544 | netlist_object_t::save_register(); |
| r31048 | r31049 | |
| 565 | 562 | assert(this->isRailNet()); |
| 566 | 563 | |
| 567 | 564 | const UINT32 masks[4] = { 1, 5, 3, 1 }; |
| 568 | | const UINT32 mask = masks[ (m_last_Q << 1) | m_new_Q ]; |
| 565 | const UINT32 mask = masks[ (m_cur_Q << 1) | m_new_Q ]; |
| 569 | 566 | netlist_core_terminal_t *p = m_list_active.first(); |
| 570 | 567 | |
| 571 | 568 | m_in_queue = 2; /* mark as taken ... */ |
| 572 | 569 | m_cur_Q = m_new_Q; |
| 573 | 570 | |
| 574 | | switch (m_active) |
| 571 | switch (m_active) |
| 575 | 572 | { |
| 576 | 573 | case 2: |
| 577 | 574 | update_dev(p, mask); |
| r31048 | r31049 | |
| 588 | 585 | } |
| 589 | 586 | break; |
| 590 | 587 | } |
| 591 | | m_last_Q = m_cur_Q; |
| 588 | |
| 592 | 589 | } |
| 593 | 590 | |
| 594 | 591 | ATTR_COLD void netlist_net_t::reset() |
| r31048 | r31049 | |
| 597 | 594 | m_active = 0; |
| 598 | 595 | m_in_queue = 2; |
| 599 | 596 | |
| 600 | | m_last_Q = 0; |
| 601 | 597 | m_new_Q = 0; |
| 602 | 598 | m_cur_Q = 0; |
| 603 | 599 | m_cur_Analog = 0.0; |
trunk/src/emu/netlist/nl_base.h
| r31048 | r31049 | |
| 629 | 629 | |
| 630 | 630 | netlist_sig_t m_new_Q; |
| 631 | 631 | netlist_sig_t m_cur_Q; |
| 632 | | netlist_sig_t m_last_Q; |
| 633 | 632 | |
| 634 | 633 | private: |
| 635 | 634 | |
| r31048 | r31049 | |
| 663 | 662 | return m_cur_Q; |
| 664 | 663 | } |
| 665 | 664 | |
| 666 | | ATTR_HOT inline const netlist_sig_t last_Q() const |
| 667 | | { |
| 668 | | return m_last_Q; |
| 669 | | } |
| 670 | | |
| 671 | 665 | ATTR_HOT inline const netlist_sig_t new_Q() const |
| 672 | 666 | { |
| 673 | 667 | return m_new_Q; |
| r31048 | r31049 | |
| 691 | 685 | { |
| 692 | 686 | m_cur_Q = val; |
| 693 | 687 | m_new_Q = val; |
| 694 | | m_last_Q = val; |
| 695 | 688 | } |
| 696 | 689 | |
| 697 | 690 | /* internal state support |
| r31048 | r31049 | |
| 986 | 979 | out.set_Q(val, delay); |
| 987 | 980 | } |
| 988 | 981 | |
| 989 | | ATTR_HOT inline bool INP_CHANGED(const netlist_logic_input_t &inp) const |
| 990 | | { |
| 991 | | return (inp.last_Q() != inp.Q()); |
| 992 | | } |
| 993 | | |
| 994 | | ATTR_HOT inline bool INP_HL(const netlist_logic_input_t &inp) const |
| 995 | | { |
| 996 | | return ((inp.last_Q() & !inp.Q()) == 1); |
| 997 | | } |
| 998 | | |
| 999 | | ATTR_HOT inline bool INP_LH(const netlist_logic_input_t &inp) const |
| 1000 | | { |
| 1001 | | return ((!inp.last_Q() & inp.Q()) == 1); |
| 1002 | | } |
| 1003 | | |
| 1004 | 982 | ATTR_HOT inline const double INPANALOG(const netlist_analog_input_t &inp) const { return inp.Q_Analog(); } |
| 1005 | 983 | |
| 1006 | 984 | ATTR_HOT inline const double TERMANALOG(const netlist_terminal_t &term) const { return term.net().as_analog().Q_Analog(); } |
| r31048 | r31049 | |
| 1358 | 1336 | return net().as_logic().Q(); |
| 1359 | 1337 | } |
| 1360 | 1338 | |
| 1361 | | ATTR_HOT inline const netlist_sig_t netlist_logic_input_t::last_Q() const |
| 1362 | | { |
| 1363 | | return net().as_logic().last_Q(); |
| 1364 | | } |
| 1365 | | |
| 1366 | 1339 | ATTR_HOT inline const double netlist_analog_input_t::Q_Analog() const |
| 1367 | 1340 | { |
| 1368 | 1341 | return net().as_analog().Q_Analog(); |