trunk/src/emu/netlist/nl_base.h
| r26078 | r26079 | |
| 84 | 84 | // forward definitions |
| 85 | 85 | // ---------------------------------------------------------------------------------------- |
| 86 | 86 | |
| 87 | class net_net_t; |
| 87 | 88 | class net_output_t; |
| 88 | 89 | class net_param_t; |
| 89 | 90 | class netlist_setup_t; |
| r26078 | r26079 | |
| 111 | 112 | SIGNAL_MASK = 0x10, |
| 112 | 113 | }; |
| 113 | 114 | |
| 114 | | net_object_t(int atype) |
| 115 | net_object_t(const int atype) |
| 115 | 116 | : m_objtype(atype) {} |
| 116 | 117 | |
| 117 | 118 | virtual ~net_object_t() {} |
| 118 | 119 | |
| 120 | ATTR_COLD void init_object(netlist_base_t &nl) |
| 121 | { |
| 122 | m_netlist = &nl; |
| 123 | } |
| 124 | |
| 119 | 125 | ATTR_HOT inline int object_type() const { return m_objtype; } |
| 120 | 126 | ATTR_HOT inline int object_type(const UINT32 mask) const { return m_objtype & mask; } |
| 121 | 127 | |
| 128 | ATTR_HOT inline netlist_base_t * RESTRICT netlist() { return m_netlist; } |
| 129 | ATTR_HOT inline const netlist_base_t * RESTRICT netlist() const { return m_netlist; } |
| 130 | |
| 122 | 131 | private: |
| 123 | | int m_objtype; |
| 132 | const int m_objtype; |
| 133 | netlist_base_t * RESTRICT m_netlist; |
| 124 | 134 | }; |
| 125 | 135 | |
| 126 | 136 | // ---------------------------------------------------------------------------------------- |
| r26078 | r26079 | |
| 134 | 144 | net_terminal_t(const int atype) |
| 135 | 145 | : net_object_t(atype) |
| 136 | 146 | , m_netdev(NULL) |
| 137 | | , m_netlist(NULL) |
| 147 | , m_net(NULL) |
| 138 | 148 | {} |
| 139 | 149 | |
| 140 | | ATTR_COLD void init_terminal(netlist_core_device_t *dev); |
| 141 | | ATTR_HOT inline netlist_core_device_t * RESTRICT netdev() const { return m_netdev; } |
| 142 | | ATTR_HOT inline netlist_base_t * RESTRICT netlist() const { return m_netlist; } |
| 150 | ATTR_COLD virtual void init_terminal(netlist_core_device_t &dev); |
| 143 | 151 | |
| 152 | ATTR_COLD void set_net(net_net_t &anet) { m_net = &anet; } |
| 153 | |
| 154 | ATTR_HOT inline const net_net_t & RESTRICT net() const { return *m_net;} |
| 155 | ATTR_HOT inline net_net_t & RESTRICT net() { return *m_net;} |
| 156 | |
| 157 | ATTR_HOT inline netlist_core_device_t * RESTRICT netdev() const { return m_netdev; } |
| 158 | |
| 144 | 159 | private: |
| 145 | 160 | netlist_core_device_t * RESTRICT m_netdev; |
| 146 | | netlist_base_t * RESTRICT m_netlist; |
| 161 | net_net_t * RESTRICT m_net; |
| 147 | 162 | }; |
| 148 | 163 | |
| 149 | 164 | |
| r26078 | r26079 | |
| 170 | 185 | , m_next(NULL) |
| 171 | 186 | #endif |
| 172 | 187 | , m_state(INP_STATE_ACTIVE) |
| 173 | | , m_output(NULL) |
| 174 | 188 | {} |
| 175 | 189 | |
| 176 | | ATTR_COLD void init_input(netlist_core_device_t *dev, net_input_state astate = INP_STATE_ACTIVE); |
| 190 | ATTR_COLD void init_input(netlist_core_device_t &dev, net_input_state astate = INP_STATE_ACTIVE); |
| 177 | 191 | |
| 178 | | ATTR_HOT inline net_output_t * RESTRICT output() const { return m_output; } |
| 179 | 192 | ATTR_HOT inline const bool is_state(const net_input_state astate) const { return (m_state == astate); } |
| 180 | 193 | ATTR_HOT inline const net_input_state state() const { return m_state; } |
| 181 | 194 | |
| 182 | | ATTR_COLD void set_output(net_output_t &aout) { m_output = &aout; } |
| 183 | 195 | ATTR_HOT inline void inactivate(); |
| 184 | 196 | ATTR_HOT inline void activate(); |
| 185 | 197 | ATTR_HOT inline void activate_hl(); |
| r26078 | r26079 | |
| 194 | 206 | |
| 195 | 207 | private: |
| 196 | 208 | net_input_state m_state; |
| 197 | | net_output_t * RESTRICT m_output; |
| 198 | 209 | }; |
| 199 | 210 | |
| 200 | 211 | // ---------------------------------------------------------------------------------------- |
| r26078 | r26079 | |
| 246 | 257 | //#define INPVAL(_x) (_x).Q() |
| 247 | 258 | |
| 248 | 259 | // ---------------------------------------------------------------------------------------- |
| 249 | | // net_output_t |
| 260 | // net_net_t |
| 250 | 261 | // ---------------------------------------------------------------------------------------- |
| 251 | 262 | |
| 252 | | class NETLIB_NAME(netdev_mainclock); |
| 253 | | |
| 254 | | class net_output_t : public net_terminal_t |
| 263 | class net_net_t : public net_object_t |
| 255 | 264 | { |
| 256 | 265 | public: |
| 257 | 266 | |
| 267 | friend class NETLIB_NAME(netdev_mainclock); |
| 268 | friend class net_output_t; |
| 269 | friend class net_input_t; |
| 270 | friend class logic_output_t; |
| 271 | friend class analog_output_t; |
| 272 | friend class logic_input_t; |
| 273 | friend class analog_input_t; |
| 274 | |
| 258 | 275 | // FIXME: union does not work |
| 259 | 276 | typedef struct |
| 260 | 277 | { |
| r26078 | r26079 | |
| 262 | 279 | double Analog; |
| 263 | 280 | } hybrid_t; |
| 264 | 281 | |
| 265 | | net_output_t(int atype); |
| 282 | ATTR_COLD net_net_t(const int atype); |
| 266 | 283 | |
| 267 | | friend const netlist_sig_t logic_input_t::Q() const; |
| 268 | | friend const double analog_input_t::Q_Analog() const; |
| 269 | | friend const bool analog_input_t::is_highz() const; |
| 270 | | friend class NETLIB_NAME(netdev_mainclock); |
| 284 | ATTR_COLD void register_con(net_input_t &inp); |
| 285 | ATTR_COLD void register_raildev(netlist_core_device_t &mr) |
| 286 | { |
| 287 | assert(m_raildev == NULL); |
| 288 | m_raildev = &mr; |
| 289 | } |
| 271 | 290 | |
| 272 | | ATTR_HOT inline const netlist_sig_t last_Q() const { return m_last.Q; } |
| 273 | | ATTR_HOT inline const netlist_sig_t new_Q() const { return m_new.Q; } |
| 291 | ATTR_HOT inline bool isRailNet() { return m_raildev == NULL; } |
| 274 | 292 | |
| 275 | | ATTR_COLD void register_con(net_input_t &inp); |
| 293 | /* inline not always works out */ |
| 294 | ATTR_HOT /*inline*/ void update_devs(); |
| 276 | 295 | |
| 277 | | /* inline not always works out */ |
| 278 | | ATTR_HOT /*inline*/ void update_devs(); |
| 296 | /* Everything below is used by the logic subsystem */ |
| 279 | 297 | |
| 280 | | ATTR_HOT inline void inc_active(); |
| 281 | | ATTR_HOT inline void dec_active(); |
| 298 | ATTR_HOT inline void inc_active(); |
| 299 | ATTR_HOT inline void dec_active(); |
| 282 | 300 | |
| 283 | | ATTR_HOT inline const int active_count() const { return m_active; } |
| 284 | | ATTR_HOT inline const netlist_time time() const { return m_time; } |
| 285 | | ATTR_HOT inline void set_time(const netlist_time ntime) { m_time = ntime; } |
| 301 | ATTR_HOT inline const int active_count() const { return m_active; } |
| 302 | ATTR_HOT inline const netlist_time time() const { return m_time; } |
| 303 | ATTR_HOT inline void set_time(const netlist_time ntime) { m_time = ntime; } |
| 286 | 304 | |
| 287 | | double m_low_V; |
| 288 | | double m_high_V; |
| 305 | ATTR_HOT inline const netlist_sig_t last_Q() const { return m_last.Q; } |
| 306 | ATTR_HOT inline const netlist_sig_t new_Q() const { return m_new.Q; } |
| 289 | 307 | |
| 308 | ATTR_HOT inline const netlist_core_device_t * RESTRICT raildev() const { return m_raildev; } |
| 309 | ATTR_HOT inline netlist_core_device_t * RESTRICT raildev() { return m_raildev; } |
| 310 | |
| 290 | 311 | protected: |
| 291 | 312 | |
| 292 | | /* prohibit use in device functions |
| 293 | | * current (pending) state can be inquired using new_Q() |
| 294 | | */ |
| 295 | | ATTR_HOT inline const netlist_sig_t Q() const |
| 296 | | { |
| 297 | | assert(object_type(SIGNAL_MASK) == SIGNAL_DIGITAL); |
| 298 | | return m_cur.Q; |
| 299 | | } |
| 300 | | ATTR_HOT inline const double Q_Analog() const |
| 301 | | { |
| 302 | | assert(object_type(SIGNAL_MASK) == SIGNAL_ANALOG); |
| 313 | /* prohibit use in device functions |
| 314 | * current (pending) state can be inquired using new_Q() |
| 315 | */ |
| 316 | ATTR_HOT inline const netlist_sig_t Q() const |
| 317 | { |
| 318 | assert(object_type(SIGNAL_MASK) == SIGNAL_DIGITAL); |
| 319 | return m_cur.Q; |
| 320 | } |
| 321 | ATTR_HOT inline const double Q_Analog() const |
| 322 | { |
| 323 | assert(object_type(SIGNAL_MASK) == SIGNAL_ANALOG); |
| 303 | 324 | return m_cur.Analog; |
| 304 | | } |
| 325 | } |
| 305 | 326 | |
| 306 | | ATTR_HOT inline void push_to_queue(const netlist_time &delay); |
| 307 | 327 | |
| 308 | | hybrid_t m_last; |
| 309 | | hybrid_t m_cur; |
| 310 | | hybrid_t m_new; |
| 328 | ATTR_HOT inline void push_to_queue(const netlist_time &delay); |
| 311 | 329 | |
| 330 | hybrid_t m_last; |
| 331 | hybrid_t m_cur; |
| 332 | hybrid_t m_new; |
| 333 | |
| 312 | 334 | #if USE_LINKED_LIST |
| 313 | | net_input_t *m_head; |
| 335 | net_input_t *m_head; |
| 314 | 336 | #endif |
| 315 | | UINT32 m_num_cons; |
| 337 | UINT32 m_num_cons; |
| 316 | 338 | |
| 317 | 339 | private: |
| 318 | | ATTR_HOT void update_dev(const net_input_t *inp, const UINT32 mask); |
| 340 | ATTR_HOT void update_dev(const net_input_t *inp, const UINT32 mask); |
| 319 | 341 | |
| 320 | | netlist_time m_time; |
| 342 | netlist_time m_time; |
| 343 | INT32 m_active; |
| 344 | UINT32 m_in_queue; /* 0: not in queue, 1: in queue, 2: last was taken */ |
| 321 | 345 | |
| 322 | | INT32 m_active; |
| 323 | | |
| 324 | | UINT32 m_in_queue; /* 0: not in queue, 1: in queue, 2: last was taken */ |
| 325 | | |
| 326 | 346 | #if !USE_LINKED_LIST |
| 327 | | net_input_t * RESTRICT m_cons[OUTPUT_MAX_CONNECTIONS]; |
| 347 | net_input_t * RESTRICT m_cons[OUTPUT_MAX_CONNECTIONS]; |
| 328 | 348 | #endif |
| 349 | netlist_core_device_t * RESTRICT m_raildev; |
| 329 | 350 | }; |
| 330 | 351 | |
| 331 | 352 | |
| 353 | // ---------------------------------------------------------------------------------------- |
| 354 | // net_output_t |
| 355 | // ---------------------------------------------------------------------------------------- |
| 356 | |
| 357 | class NETLIB_NAME(netdev_mainclock); |
| 358 | |
| 359 | class net_output_t : public net_terminal_t |
| 360 | { |
| 361 | public: |
| 362 | |
| 363 | net_output_t(int atype); |
| 364 | |
| 365 | ATTR_COLD virtual void init_terminal(netlist_core_device_t &dev); |
| 366 | |
| 367 | double m_low_V; |
| 368 | double m_high_V; |
| 369 | |
| 370 | protected: |
| 371 | |
| 372 | private: |
| 373 | net_net_t m_my_net; |
| 374 | }; |
| 375 | |
| 376 | |
| 332 | 377 | class logic_output_t : public net_output_t |
| 333 | 378 | { |
| 334 | 379 | public: |
| 335 | 380 | |
| 336 | | logic_output_t() |
| 337 | | : net_output_t(OUTPUT | SIGNAL_DIGITAL) |
| 338 | | { |
| 339 | | // Default to TTL |
| 340 | | m_low_V = 0.1; // these depend on sinked/sourced current. Values should be suitable for typical applications. |
| 341 | | m_high_V = 4.8; |
| 342 | | } |
| 381 | ATTR_COLD logic_output_t(); |
| 343 | 382 | |
| 344 | | ATTR_COLD void initial(const netlist_sig_t val) { m_cur.Q = val; m_new.Q = val; m_last.Q = !val; } |
| 383 | ATTR_COLD void initial(const netlist_sig_t val); |
| 384 | ATTR_COLD void set_levels(const double low, const double high); |
| 345 | 385 | |
| 346 | 386 | ATTR_HOT inline void set_Q(const netlist_sig_t newQ, const netlist_time &delay) |
| 347 | 387 | { |
| 348 | | if (EXPECTED(newQ != m_new.Q)) |
| 388 | net_net_t &anet = net(); |
| 389 | |
| 390 | if (EXPECTED(newQ != anet.m_new.Q)) |
| 349 | 391 | { |
| 350 | | m_new.Q = newQ; |
| 351 | | if (m_num_cons) |
| 352 | | push_to_queue(delay); |
| 392 | anet.m_new.Q = newQ; |
| 393 | if (anet.m_num_cons) |
| 394 | anet.push_to_queue(delay); |
| 353 | 395 | } |
| 354 | 396 | } |
| 355 | | |
| 356 | | ATTR_COLD inline void set_levels(const double low, const double high) |
| 357 | | { |
| 358 | | m_low_V = low; |
| 359 | | m_high_V = high; |
| 360 | | } |
| 361 | 397 | }; |
| 362 | 398 | |
| 363 | 399 | class ttl_output_t : public logic_output_t |
| r26078 | r26079 | |
| 376 | 412 | { |
| 377 | 413 | public: |
| 378 | 414 | |
| 379 | | analog_output_t() |
| 415 | ATTR_COLD analog_output_t() |
| 380 | 416 | : net_output_t(OUTPUT | SIGNAL_ANALOG) |
| 381 | 417 | { |
| 382 | | m_cur.Analog = 0.0; |
| 383 | | m_new.Analog = 0.0; |
| 418 | net().m_cur.Analog = 0.0; |
| 419 | net().m_new.Analog = 0.0; |
| 384 | 420 | } |
| 385 | 421 | |
| 386 | 422 | ATTR_COLD void initial(const double val) |
| 387 | 423 | { |
| 388 | | m_cur.Analog = val; |
| 389 | | m_new.Analog = val; |
| 424 | net().m_cur.Analog = val; |
| 425 | net().m_new.Analog = val; |
| 390 | 426 | } |
| 391 | 427 | |
| 392 | 428 | ATTR_HOT inline void set_Q(const double newQ, const netlist_time &delay) |
| 393 | 429 | { |
| 394 | | if (newQ != m_new.Analog) |
| 430 | if (newQ != net().m_new.Analog) |
| 395 | 431 | { |
| 396 | | m_new.Analog = newQ; |
| 397 | | push_to_queue(delay); |
| 432 | net().m_new.Analog = newQ; |
| 433 | net().push_to_queue(delay); |
| 398 | 434 | } |
| 399 | 435 | } |
| 400 | 436 | |
| r26078 | r26079 | |
| 418 | 454 | |
| 419 | 455 | ATTR_HOT virtual void update_param() {} |
| 420 | 456 | |
| 421 | | ATTR_HOT const netlist_sig_t INPLOGIC_PASSIVE(logic_input_t &inp); |
| 422 | | |
| 423 | 457 | ATTR_HOT inline void update_dev() |
| 424 | 458 | { |
| 425 | 459 | #if USE_DELEGATES |
| r26078 | r26079 | |
| 433 | 467 | #endif |
| 434 | 468 | } |
| 435 | 469 | |
| 470 | ATTR_HOT const netlist_sig_t INPLOGIC_PASSIVE(logic_input_t &inp); |
| 471 | |
| 436 | 472 | ATTR_HOT inline const netlist_sig_t INPLOGIC(const logic_input_t &inp) const |
| 437 | 473 | { |
| 438 | 474 | assert(inp.state() != net_input_t::INP_STATE_PASSIVE); |
| r26078 | r26079 | |
| 461 | 497 | out.set_Q(val, delay); |
| 462 | 498 | } |
| 463 | 499 | |
| 464 | | ATTR_HOT inline netlist_base_t *netlist() const { return m_netlist; } |
| 465 | | |
| 466 | 500 | ATTR_HOT virtual void inc_active() { } |
| 467 | 501 | |
| 468 | 502 | ATTR_HOT virtual void dec_active() { /*printf("DeActivate %s\n", m_name);*/ } |
| r26078 | r26079 | |
| 480 | 514 | ATTR_HOT virtual void update() { } |
| 481 | 515 | ATTR_HOT virtual void start() { } |
| 482 | 516 | |
| 483 | | netlist_base_t * RESTRICT m_netlist; |
| 484 | | |
| 485 | 517 | private: |
| 486 | | |
| 487 | 518 | astring m_name; |
| 488 | 519 | }; |
| 489 | 520 | |
| r26078 | r26079 | |
| 492 | 523 | { |
| 493 | 524 | public: |
| 494 | 525 | |
| 495 | | net_device_t(); |
| 526 | ATTR_COLD net_device_t(); |
| 496 | 527 | |
| 497 | 528 | virtual ~net_device_t(); |
| 498 | 529 | |
| r26078 | r26079 | |
| 518 | 549 | protected: |
| 519 | 550 | |
| 520 | 551 | virtual void update() { } |
| 521 | | ATTR_HOT virtual void start() { } |
| 552 | virtual void start() { } |
| 522 | 553 | |
| 523 | 554 | ATTR_COLD void register_param(const astring &sname, net_param_t ¶m, const double initialVal = 0.0); |
| 524 | 555 | ATTR_COLD void register_param(netlist_core_device_t &dev, const astring &sname, net_param_t ¶m, const double initialVal = 0.0); |
| r26078 | r26079 | |
| 537 | 568 | , m_netdev(NULL) |
| 538 | 569 | { } |
| 539 | 570 | |
| 540 | | inline void setTo(const double param) { m_param = param; m_netdev->update_param(); } |
| 541 | | inline void setTo(const int param) { m_param = param; m_netdev->update_param(); } |
| 571 | ATTR_HOT inline void setTo(const double param) { m_param = param; m_netdev->update_param(); } |
| 572 | ATTR_HOT inline void setTo(const int param) { m_param = param; m_netdev->update_param(); } |
| 542 | 573 | inline void initial(const double val) { m_param = val; } |
| 543 | 574 | inline void initial(const int val) { m_param = val; } |
| 544 | 575 | |
| 545 | | ATTR_HOT inline double Value() const { return m_param; } |
| 546 | | ATTR_HOT inline int ValueInt() const { return (int) m_param; } |
| 576 | ATTR_HOT inline const double Value() const { return m_param; } |
| 577 | ATTR_HOT inline const int ValueInt() const { return (int) m_param; } |
| 547 | 578 | |
| 548 | 579 | ATTR_HOT inline netlist_core_device_t &netdev() const { return *m_netdev; } |
| 549 | | void set_netdev(netlist_core_device_t &dev) { m_netdev = &dev; } |
| 580 | ATTR_COLD void set_netdev(netlist_core_device_t &dev) { m_netdev = &dev; } |
| 550 | 581 | |
| 551 | 582 | private: |
| 552 | 583 | |
| r26078 | r26079 | |
| 566 | 597 | { |
| 567 | 598 | public: |
| 568 | 599 | |
| 569 | | typedef netlist_timed_queue1<net_output_t, netlist_time, 512> queue_t; |
| 600 | typedef netlist_timed_queue1<net_net_t, netlist_time, 512> queue_t; |
| 570 | 601 | |
| 571 | 602 | netlist_base_t(); |
| 572 | 603 | virtual ~netlist_base_t(); |
| 573 | 604 | |
| 574 | 605 | void set_clock_freq(UINT64 clockfreq); |
| 575 | 606 | |
| 576 | | ATTR_HOT inline void push_to_queue(net_output_t &out, const netlist_time &attime) |
| 607 | ATTR_HOT inline void push_to_queue(net_net_t &out, const netlist_time &attime) |
| 577 | 608 | { |
| 578 | 609 | m_queue.push(queue_t::entry_t(attime, out)); |
| 579 | 610 | } |
| r26078 | r26079 | |
| 629 | 660 | protected: |
| 630 | 661 | void start() |
| 631 | 662 | { |
| 632 | | m_I.init_input(this); |
| 663 | m_I.init_input(*this); |
| 633 | 664 | |
| 634 | | m_Q.init_terminal(this); |
| 665 | m_Q.init_terminal(*this); |
| 635 | 666 | m_Q.initial(1); |
| 636 | 667 | } |
| 637 | 668 | |
| r26078 | r26079 | |
| 668 | 699 | protected: |
| 669 | 700 | void start() |
| 670 | 701 | { |
| 671 | | m_I.init_input(this); |
| 672 | | m_Q.init_terminal(this); |
| 702 | m_I.init_input(*this); |
| 703 | m_Q.init_terminal(*this); |
| 673 | 704 | m_Q.initial(0); |
| 674 | 705 | } |
| 675 | 706 | |
| r26078 | r26079 | |
| 693 | 724 | if (m_state != INP_STATE_PASSIVE) |
| 694 | 725 | { |
| 695 | 726 | m_state = INP_STATE_PASSIVE; |
| 696 | | m_output->dec_active(); |
| 727 | net().dec_active(); |
| 697 | 728 | } |
| 698 | 729 | } |
| 699 | 730 | |
| r26078 | r26079 | |
| 701 | 732 | { |
| 702 | 733 | if (m_state == INP_STATE_PASSIVE) |
| 703 | 734 | { |
| 704 | | m_output->inc_active(); |
| 735 | net().inc_active(); |
| 705 | 736 | m_state = INP_STATE_ACTIVE; |
| 706 | 737 | } |
| 707 | 738 | } |
| r26078 | r26079 | |
| 710 | 741 | { |
| 711 | 742 | if (m_state == INP_STATE_PASSIVE) |
| 712 | 743 | { |
| 713 | | m_output->inc_active(); |
| 744 | net().inc_active(); |
| 714 | 745 | m_state = INP_STATE_HL; |
| 715 | 746 | } |
| 716 | 747 | } |
| r26078 | r26079 | |
| 719 | 750 | { |
| 720 | 751 | if (m_state == INP_STATE_PASSIVE) |
| 721 | 752 | { |
| 722 | | m_output->inc_active(); |
| 753 | net().inc_active(); |
| 723 | 754 | m_state = INP_STATE_LH; |
| 724 | 755 | } |
| 725 | 756 | } |
| 726 | 757 | |
| 727 | 758 | |
| 728 | | ATTR_HOT inline void net_output_t::push_to_queue(const netlist_time &delay) |
| 759 | ATTR_HOT inline void net_net_t::push_to_queue(const netlist_time &delay) |
| 729 | 760 | { |
| 730 | 761 | // if (m_in_queue == 1) return; FIXME: check this at some time |
| 731 | 762 | m_time = netlist()->time() + delay; |
| r26078 | r26079 | |
| 737 | 768 | } |
| 738 | 769 | } |
| 739 | 770 | |
| 740 | | ATTR_HOT inline void net_output_t::inc_active() |
| 771 | ATTR_HOT inline void net_net_t::inc_active() |
| 741 | 772 | { |
| 742 | 773 | m_active++; |
| 743 | 774 | |
| r26078 | r26079 | |
| 745 | 776 | if (m_active == 1 && m_in_queue > 0) |
| 746 | 777 | { |
| 747 | 778 | m_last = m_cur; |
| 748 | | netdev()->inc_active(); |
| 779 | raildev()->inc_active(); |
| 749 | 780 | m_cur = m_new; |
| 750 | 781 | } |
| 751 | 782 | #endif |
| r26078 | r26079 | |
| 765 | 796 | } |
| 766 | 797 | } |
| 767 | 798 | |
| 768 | | ATTR_HOT inline void net_output_t::dec_active() |
| 799 | ATTR_HOT inline void net_net_t::dec_active() |
| 769 | 800 | { |
| 770 | 801 | m_active--; |
| 771 | 802 | #if (USE_DEACTIVE_DEVICE) |
| 772 | 803 | if (m_active == 0) |
| 773 | | netdev()->dec_active(); |
| 804 | raildev()->dec_active(); |
| 774 | 805 | #endif |
| 775 | 806 | } |
| 776 | 807 | |
| 777 | 808 | ATTR_HOT inline const netlist_sig_t logic_input_t::Q() const |
| 778 | 809 | { |
| 779 | | return output()->Q(); |
| 810 | return net().Q(); |
| 780 | 811 | } |
| 781 | 812 | |
| 782 | 813 | ATTR_HOT inline const netlist_sig_t logic_input_t::last_Q() const |
| 783 | 814 | { |
| 784 | | return output()->last_Q(); |
| 815 | return net().last_Q(); |
| 785 | 816 | } |
| 786 | 817 | |
| 787 | 818 | ATTR_HOT inline const double analog_input_t::Q_Analog() const |
| 788 | 819 | { |
| 789 | | return output()->Q_Analog(); |
| 820 | return net().Q_Analog(); |
| 790 | 821 | } |
| 791 | 822 | |
| 792 | 823 | ATTR_HOT inline const bool analog_input_t::is_highz() const |
| 793 | 824 | { |
| 794 | | return (output()->Q_Analog() == NETLIST_HIGHIMP_V); |
| 825 | return (net().Q_Analog() == NETLIST_HIGHIMP_V); |
| 795 | 826 | } |
| 796 | 827 | |
| 797 | 828 | // ---------------------------------------------------------------------------------------- |
trunk/src/emu/netlist/nl_base.c
| r26078 | r26079 | |
| 34 | 34 | m_rem = 0; |
| 35 | 35 | m_queue.clear(); |
| 36 | 36 | if (m_mainclock != NULL) |
| 37 | | m_mainclock->m_Q.set_time(netlist_time::zero); |
| 37 | m_mainclock->m_Q.net().set_time(netlist_time::zero); |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | |
| r26078 | r26079 | |
| 73 | 73 | const queue_t::entry_t e = m_queue.pop(); |
| 74 | 74 | update_time(e.time(), atime); |
| 75 | 75 | |
| 76 | | if (FATAL_ERROR_AFTER_NS) |
| 77 | | printf("%s\n", e.object().netdev()->name().cstr()); |
| 76 | //if (FATAL_ERROR_AFTER_NS) |
| 77 | // printf("%s\n", e.object().netdev()->name().cstr()); |
| 78 | 78 | |
| 79 | 79 | e.object().update_devs(); |
| 80 | 80 | |
| r26078 | r26079 | |
| 91 | 91 | atime = 0; |
| 92 | 92 | } |
| 93 | 93 | } else { |
| 94 | | net_output_t &mcQ = m_mainclock->m_Q; |
| 94 | net_net_t &mcQ = m_mainclock->m_Q.net(); |
| 95 | 95 | const netlist_time inc = m_mainclock->m_inc; |
| 96 | 96 | |
| 97 | 97 | while (atime > 0) |
| r26078 | r26079 | |
| 148 | 148 | |
| 149 | 149 | ATTR_COLD void netlist_core_device_t::init(netlist_setup_t &setup, const astring &name) |
| 150 | 150 | { |
| 151 | | m_netlist = &setup.netlist(); |
| 151 | init_object(setup.netlist()); |
| 152 | 152 | m_name = name; |
| 153 | 153 | |
| 154 | 154 | #if USE_DELEGATES |
| r26078 | r26079 | |
| 163 | 163 | |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | | ATTR_COLD void net_device_t::init(netlist_setup_t &setup, const astring &name) |
| 167 | | { |
| 168 | | netlist_core_device_t::init(setup, name); |
| 169 | | m_setup = &setup; |
| 170 | | start(); |
| 171 | | } |
| 172 | | |
| 173 | | |
| 174 | 166 | netlist_core_device_t::~netlist_core_device_t() |
| 175 | 167 | { |
| 176 | 168 | } |
| r26078 | r26079 | |
| 206 | 198 | //printf("~net_device_t\n"); |
| 207 | 199 | } |
| 208 | 200 | |
| 201 | ATTR_COLD void net_device_t::init(netlist_setup_t &setup, const astring &name) |
| 202 | { |
| 203 | netlist_core_device_t::init(setup, name); |
| 204 | m_setup = &setup; |
| 205 | start(); |
| 206 | } |
| 207 | |
| 208 | |
| 209 | 209 | ATTR_COLD void net_device_t::register_sub(netlist_core_device_t &dev, const astring &name) |
| 210 | 210 | { |
| 211 | 211 | dev.init(*m_setup, name); |
| r26078 | r26079 | |
| 233 | 233 | |
| 234 | 234 | void net_device_t::register_link_internal(netlist_core_device_t &dev, net_input_t &in, net_output_t &out, net_input_t::net_input_state aState) |
| 235 | 235 | { |
| 236 | | in.set_output(out); |
| 237 | | in.init_input(&dev, aState); |
| 236 | in.init_input(dev, aState); |
| 237 | out.init_terminal(dev); |
| 238 | 238 | //if (in.state() != net_input_t::INP_STATE_PASSIVE) |
| 239 | | out.register_con(in); |
| 239 | out.net().register_con(in); |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | 242 | void net_device_t::register_link_internal(net_input_t &in, net_output_t &out, net_input_t::net_input_state aState) |
| r26078 | r26079 | |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | 259 | // ---------------------------------------------------------------------------------------- |
| 260 | | // net_terminal_t |
| 260 | // net_net_t |
| 261 | 261 | // ---------------------------------------------------------------------------------------- |
| 262 | 262 | |
| 263 | | ATTR_COLD void net_terminal_t::init_terminal(netlist_core_device_t *dev) |
| 263 | ATTR_COLD net_net_t::net_net_t(const int atype) |
| 264 | : net_object_t(atype) |
| 265 | #if USE_LINKED_LIST |
| 266 | , m_head(NULL) |
| 267 | #endif |
| 268 | , m_num_cons(0) |
| 269 | , m_time(netlist_time::zero) |
| 270 | , m_active(0) |
| 271 | , m_in_queue(2) |
| 272 | , m_raildev(NULL) |
| 264 | 273 | { |
| 265 | | m_netdev = dev; |
| 266 | | m_netlist = dev->netlist(); |
| 267 | | } |
| 274 | m_cur.Q = 0; |
| 275 | m_new.Q = 0; |
| 276 | m_last.Q = 0; |
| 277 | }; |
| 268 | 278 | |
| 269 | | // ---------------------------------------------------------------------------------------- |
| 270 | | // net_input_t |
| 271 | | // ---------------------------------------------------------------------------------------- |
| 272 | | |
| 273 | | ATTR_COLD void net_input_t::init_input(netlist_core_device_t *dev, net_input_state astate) |
| 279 | ATTR_COLD void net_net_t::register_con(net_input_t &input) |
| 274 | 280 | { |
| 275 | | init_terminal(dev); |
| 276 | | m_state = astate; |
| 277 | | } |
| 281 | input.set_net(*this); |
| 282 | #if USE_LINKED_LIST |
| 283 | if (m_head == NULL) |
| 284 | m_head = &input; |
| 285 | else |
| 286 | { |
| 287 | input.m_next = m_head; |
| 288 | m_head = &input; |
| 289 | } |
| 290 | #else |
| 291 | if (m_num_cons >= OUTPUT_MAX_CONNECTIONS) |
| 292 | fatalerror("Connections exceeded for %s\n", netdev()->name().cstr()); |
| 278 | 293 | |
| 279 | | // ---------------------------------------------------------------------------------------- |
| 280 | | // net_output_t |
| 281 | | // ---------------------------------------------------------------------------------------- |
| 294 | #if 0 |
| 295 | int i; |
| 296 | /* keep similar devices together */ |
| 297 | for (i = 0; i < m_num_cons; i++) |
| 298 | if (m_cons[i]->netdev() == input.netdev()) |
| 299 | break; |
| 282 | 300 | |
| 283 | | net_output_t::net_output_t(int atype) |
| 284 | | : net_terminal_t(atype) |
| 285 | | , m_low_V(0.0) |
| 286 | | , m_high_V(0.0) |
| 287 | | //, m_last_Q(0) |
| 288 | | //, m_Q(0) |
| 289 | | //, m_new_Q(0) |
| 290 | | //, m_Q_analog(0.0) |
| 291 | | //, m_new_Q_analog(0.0) |
| 292 | | #if USE_LINKED_LIST |
| 293 | | , m_head(NULL) |
| 301 | for (int j = m_num_cons; j > i; j--) |
| 302 | m_cons[j] = m_cons[j - 1]; |
| 303 | |
| 304 | m_cons[i] = &input; |
| 305 | #else |
| 306 | m_cons[m_num_cons] = &input; |
| 294 | 307 | #endif |
| 295 | | , m_num_cons(0) |
| 296 | | , m_time(netlist_time::zero) |
| 297 | | , m_active(0) |
| 298 | | , m_in_queue(2) |
| 299 | | { |
| 300 | | m_cur.Q = 0; |
| 301 | | m_new.Q = 0; |
| 302 | | m_last.Q = 0; |
| 303 | | //m_cons = global_alloc_array(net_input_t *, OUTPUT_MAX_CONNECTIONS); |
| 308 | #endif |
| 309 | m_num_cons++; |
| 310 | if (input.state() != net_input_t::INP_STATE_PASSIVE) |
| 311 | m_active++; |
| 304 | 312 | } |
| 305 | 313 | |
| 306 | | ATTR_HOT inline void net_output_t::update_dev(const net_input_t *inp, const UINT32 mask) |
| 314 | ATTR_HOT inline void net_net_t::update_dev(const net_input_t *inp, const UINT32 mask) |
| 307 | 315 | { |
| 308 | 316 | if ((inp->state() & mask) != 0) |
| 309 | 317 | { |
| r26078 | r26079 | |
| 315 | 323 | } |
| 316 | 324 | } |
| 317 | 325 | |
| 318 | | ATTR_HOT inline void net_output_t::update_devs() |
| 326 | ATTR_HOT inline void net_net_t::update_devs() |
| 319 | 327 | { |
| 320 | 328 | assert(m_num_cons != 0); |
| 321 | 329 | |
| r26078 | r26079 | |
| 363 | 371 | m_last = m_cur; |
| 364 | 372 | } |
| 365 | 373 | |
| 366 | | ATTR_COLD void net_output_t::register_con(net_input_t &input) |
| 367 | | { |
| 368 | | #if USE_LINKED_LIST |
| 369 | | if (m_head == NULL) |
| 370 | | m_head = &input; |
| 371 | | else |
| 372 | | { |
| 373 | | input.m_next = m_head; |
| 374 | | m_head = &input; |
| 375 | | } |
| 376 | | #else |
| 377 | | if (m_num_cons >= OUTPUT_MAX_CONNECTIONS) |
| 378 | | fatalerror("Connections exceeded for %s\n", netdev()->name().cstr()); |
| 374 | // ---------------------------------------------------------------------------------------- |
| 375 | // net_terminal_t |
| 376 | // ---------------------------------------------------------------------------------------- |
| 379 | 377 | |
| 380 | | #if 0 |
| 381 | | int i; |
| 382 | | /* keep similar devices together */ |
| 383 | | for (i = 0; i < m_num_cons; i++) |
| 384 | | if (m_cons[i]->netdev() == input.netdev()) |
| 385 | | break; |
| 386 | | |
| 387 | | for (int j = m_num_cons; j > i; j--) |
| 388 | | m_cons[j] = m_cons[j - 1]; |
| 389 | | |
| 390 | | m_cons[i] = &input; |
| 391 | | #else |
| 392 | | m_cons[m_num_cons] = &input; |
| 393 | | #endif |
| 394 | | #endif |
| 395 | | m_num_cons++; |
| 396 | | if (input.state() != net_input_t::INP_STATE_PASSIVE) |
| 397 | | m_active++; |
| 378 | ATTR_COLD void net_terminal_t::init_terminal(netlist_core_device_t &dev) |
| 379 | { |
| 380 | m_netdev = &dev; |
| 381 | init_object(*dev.netlist()); |
| 398 | 382 | } |
| 399 | 383 | |
| 400 | 384 | // ---------------------------------------------------------------------------------------- |
| 401 | | // netdev_const |
| 385 | // net_input_t |
| 402 | 386 | // ---------------------------------------------------------------------------------------- |
| 403 | 387 | |
| 404 | | NETLIB_START(netdev_ttl_const) |
| 388 | ATTR_COLD void net_input_t::init_input(netlist_core_device_t &dev, net_input_state astate) |
| 405 | 389 | { |
| 406 | | register_output("Q", m_Q); |
| 407 | | register_param("CONST", m_const, 0.0); |
| 390 | init_terminal(dev); |
| 391 | m_state = astate; |
| 408 | 392 | } |
| 409 | 393 | |
| 410 | | NETLIB_UPDATE(netdev_ttl_const) |
| 411 | | { |
| 412 | | } |
| 394 | // ---------------------------------------------------------------------------------------- |
| 395 | // net_output_t |
| 396 | // ---------------------------------------------------------------------------------------- |
| 413 | 397 | |
| 414 | | NETLIB_UPDATE_PARAM(netdev_ttl_const) |
| 398 | net_output_t::net_output_t(int atype) |
| 399 | : net_terminal_t(atype) |
| 400 | , m_low_V(0.0) |
| 401 | , m_high_V(0.0) |
| 402 | , m_my_net(NET_DIGITAL) |
| 415 | 403 | { |
| 416 | | OUTLOGIC(m_Q, m_const.ValueInt(), NLTIME_IMMEDIATE); |
| 404 | //m_net = new net_net_t(NET_DIGITAL); |
| 405 | this->set_net(m_my_net); |
| 417 | 406 | } |
| 418 | 407 | |
| 419 | | NETLIB_START(netdev_analog_const) |
| 408 | ATTR_COLD void net_output_t::init_terminal(netlist_core_device_t &dev) |
| 420 | 409 | { |
| 421 | | register_output("Q", m_Q); |
| 422 | | register_param("CONST", m_const, 0.0); |
| 410 | net_terminal_t::init_terminal(dev); |
| 411 | net().init_object(*dev.netlist()); |
| 412 | net().register_raildev(dev); |
| 423 | 413 | } |
| 424 | 414 | |
| 425 | | NETLIB_UPDATE(netdev_analog_const) |
| 415 | ATTR_COLD void logic_output_t::initial(const netlist_sig_t val) |
| 426 | 416 | { |
| 417 | net().m_cur.Q = val; |
| 418 | net().m_new.Q = val; |
| 419 | net().m_last.Q = !val; |
| 427 | 420 | } |
| 428 | 421 | |
| 429 | | NETLIB_UPDATE_PARAM(netdev_analog_const) |
| 422 | ATTR_COLD logic_output_t::logic_output_t() |
| 423 | : net_output_t(OUTPUT | SIGNAL_DIGITAL) |
| 430 | 424 | { |
| 431 | | m_Q.initial(m_const.Value()); |
| 425 | // Default to TTL |
| 426 | m_low_V = 0.1; // these depend on sinked/sourced current. Values should be suitable for typical applications. |
| 427 | m_high_V = 4.8; |
| 432 | 428 | } |
| 433 | 429 | |
| 434 | | NETLIB_UPDATE(netdev_analog_callback) |
| 430 | ATTR_COLD void logic_output_t::set_levels(const double low, const double high) |
| 435 | 431 | { |
| 436 | | // FIXME: Remove after device cleanup |
| 437 | | if (!m_callback.isnull()) |
| 438 | | m_callback(INPANALOG(m_in)); |
| 432 | m_low_V = low; |
| 433 | m_high_V = high; |
| 439 | 434 | } |
| 440 | 435 | |
| 436 | |
| 441 | 437 | // ---------------------------------------------------------------------------------------- |
| 442 | 438 | // netdev_mainclock |
| 443 | 439 | // ---------------------------------------------------------------------------------------- |
| 444 | 440 | |
| 445 | | ATTR_HOT inline void NETLIB_NAME(netdev_mainclock)::mc_update(net_output_t &Q, const netlist_time curtime) |
| 441 | ATTR_HOT inline void NETLIB_NAME(netdev_mainclock)::mc_update(net_net_t &net, const netlist_time curtime) |
| 446 | 442 | { |
| 447 | | Q.m_new.Q = !Q.m_new.Q; |
| 448 | | Q.set_time(curtime); |
| 449 | | Q.update_devs(); |
| 443 | net.m_new.Q = !net.m_new.Q; |
| 444 | net.set_time(curtime); |
| 445 | net.update_devs(); |
| 450 | 446 | } |
| 451 | 447 | |
| 452 | 448 | ATTR_COLD NETLIB_START(netdev_mainclock) |
| r26078 | r26079 | |
| 465 | 461 | |
| 466 | 462 | ATTR_HOT NETLIB_UPDATE(netdev_mainclock) |
| 467 | 463 | { |
| 464 | net_net_t &net = m_Q.net(); |
| 468 | 465 | // this is only called during setup ... |
| 469 | | m_Q.m_new.Q = !m_Q.m_new.Q; |
| 470 | | m_Q.set_time(m_netlist->time() + m_inc); |
| 466 | net.m_new.Q = !net.m_new.Q; |
| 467 | net.set_time(netlist()->time() + m_inc); |
| 471 | 468 | } |