trunk/src/emu/netlist/devices/nld_system.h
| r26234 | r26235 | |
| 11 | 11 | |
| 12 | 12 | #include "../nl_setup.h" |
| 13 | 13 | #include "../nl_base.h" |
| 14 | | #include "../nl_lists.h" |
| 15 | 14 | |
| 16 | 15 | // ---------------------------------------------------------------------------------------- |
| 17 | 16 | // Macros |
| r26234 | r26235 | |
| 83 | 82 | netlist_ttl_output_t m_Q; |
| 84 | 83 | |
| 85 | 84 | netlist_time m_inc; |
| 85 | netlist_time m_last_step; |
| 86 | netlist_list_t<netlist_terminal_t *> m_terms; |
| 87 | netlist_list_t<netlist_terminal_t *> m_inps; |
| 88 | |
| 86 | 89 | public: |
| 87 | 90 | netlist_list_t<netlist_net_t *> m_nets; |
| 88 | 91 | |
| 89 | 92 | ATTR_HOT inline void schedule(); |
| 93 | |
| 94 | ATTR_COLD void post_start(); |
| 90 | 95 | ); |
| 91 | 96 | |
| 92 | 97 | inline void NETLIB_NAME(solver)::schedule() |
| 93 | 98 | { |
| 94 | 99 | // FIXME: time should be parameter; |
| 95 | | if (!m_Q.net().is_queued()) |
| 100 | if (!m_Q.net().is_queued()) { |
| 96 | 101 | m_Q.net().push_to_queue(NLTIME_FROM_NS(10)); |
| 102 | } |
| 97 | 103 | } |
| 98 | 104 | |
| 99 | 105 | // ---------------------------------------------------------------------------------------- |
| r26234 | r26235 | |
| 154 | 160 | |
| 155 | 161 | ATTR_HOT ATTR_ALIGN virtual void update() |
| 156 | 162 | { |
| 157 | | netlist().solver().schedule(); |
| 158 | | #if 0 |
| 159 | | if (!m_N.net().is_queued() && !m_N.net().isRailNet()) |
| 160 | | m_N.net().push_to_queue(NLTIME_FROM_NS(10)); |
| 161 | | if (!m_P.net().is_queued() && !m_P.net().isRailNet() ) |
| 162 | | m_P.net().push_to_queue(NLTIME_FROM_NS(10)); |
| 163 | | #endif |
| 163 | /* only called if connected to a rail net ==> notify the solver to recalculate */ |
| 164 | netlist().solver()->schedule(); |
| 164 | 165 | } |
| 165 | 166 | |
| 166 | 167 | double m_g; // conductance |
| r26234 | r26235 | |
| 198 | 199 | private: |
| 199 | 200 | }; |
| 200 | 201 | |
| 202 | class nld_C : public nld_twoterm |
| 203 | { |
| 204 | public: |
| 205 | nld_C() |
| 206 | : nld_twoterm() |
| 207 | { |
| 208 | } |
| 209 | |
| 210 | netlist_param_t m_C; |
| 211 | |
| 212 | protected: |
| 213 | void start() |
| 214 | { |
| 215 | register_terminal("1", m_P); |
| 216 | register_terminal("2", m_N); |
| 217 | |
| 218 | register_param("C", m_C, NETLIST_GMIN); |
| 219 | } |
| 220 | |
| 221 | virtual void update_param() |
| 222 | { |
| 223 | // set to some very big step time for now |
| 224 | // ==> large resistance |
| 225 | step_time(1e-9); |
| 226 | } |
| 227 | |
| 228 | ATTR_HOT virtual void step_time(const double st) |
| 229 | { |
| 230 | m_g = m_P.m_g = m_N.m_g = m_C.Value() / st; |
| 231 | m_I = -m_g * (m_P.net().Q_Analog()- m_N.net().Q_Analog()); |
| 232 | } |
| 233 | private: |
| 234 | }; |
| 235 | |
| 201 | 236 | #endif /* NLD_SYSTEM_H_ */ |
trunk/src/emu/netlist/devices/nld_system.c
| r26234 | r26235 | |
| 85 | 85 | register_output("Q", m_Q); |
| 86 | 86 | //register_input("FB", m_feedback); |
| 87 | 87 | |
| 88 | | m_inc = netlist_time::from_hz(48000); |
| 88 | m_inc = netlist_time::from_hz(50000); |
| 89 | 89 | |
| 90 | 90 | register_link_internal(m_feedback, m_Q, netlist_input_t::STATE_INP_ACTIVE); |
| 91 | m_last_step = netlist_time::zero; |
| 91 | 92 | |
| 92 | 93 | } |
| 93 | 94 | |
| r26234 | r26235 | |
| 96 | 97 | //m_inc = netlist_time::from_hz(m_freq.Value()*2); |
| 97 | 98 | } |
| 98 | 99 | |
| 100 | NETLIB_FUNC_VOID(solver, post_start, ()) |
| 101 | { |
| 102 | for (netlist_net_t **pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn)) |
| 103 | { |
| 104 | for (netlist_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next) |
| 105 | { |
| 106 | switch (p->type()) |
| 107 | { |
| 108 | case netlist_terminal_t::TERMINAL: |
| 109 | m_terms.add(p); |
| 110 | break; |
| 111 | case netlist_terminal_t::INPUT: |
| 112 | m_inps.add(p); |
| 113 | break; |
| 114 | default: |
| 115 | fatalerror("unhandled element found\n"); |
| 116 | break; |
| 117 | } |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | |
| 99 | 122 | NETLIB_UPDATE(solver) |
| 100 | 123 | { |
| 101 | 124 | //m_Q.setToNoCheck(!m_Q.new_Q(), m_inc ); |
| 102 | 125 | //OUTLOGIC(m_Q, !m_Q.net().new_Q(), m_inc ); |
| 103 | 126 | |
| 104 | | netlist_net_t **pn = m_nets.first(); |
| 105 | 127 | bool resched = false; |
| 128 | netlist_time now = netlist().time(); |
| 129 | netlist_time delta = now - m_last_step; |
| 106 | 130 | |
| 107 | | while (pn <= m_nets.last()) |
| 131 | if (delta >= m_inc) |
| 108 | 132 | { |
| 133 | /* update all terminals for new time step */ |
| 134 | m_last_step = now; |
| 135 | for (netlist_terminal_t **p = m_terms.first(); p != NULL; p = m_terms.next(p)) |
| 136 | (*p)->netdev().step_time(delta.as_double()); |
| 137 | } |
| 138 | for (netlist_net_t **pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn)) |
| 139 | { |
| 109 | 140 | double gtot = 0; |
| 110 | 141 | double iIdr = 0; |
| 111 | 142 | |
| 112 | | netlist_terminal_t *p = (*pn)->m_head; |
| 113 | | do |
| 143 | for (netlist_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next) |
| 114 | 144 | { |
| 115 | 145 | p->netdev().update_terminals(); |
| 116 | 146 | gtot += p->m_g; |
| 117 | 147 | iIdr += p->m_Idr; |
| 148 | } |
| 118 | 149 | |
| 119 | | p = p->m_update_list_next; |
| 120 | | } while (p != NULL); |
| 121 | | (*pn)->m_new.Analog = iIdr / gtot; |
| 122 | | if (fabs((*pn)->m_new.Analog - (*pn)->m_cur.Analog) > 1e-4) |
| 150 | double new_val = iIdr / gtot; |
| 151 | if (fabs(new_val - (*pn)->m_cur.Analog) > 1e-4) |
| 123 | 152 | resched = true; |
| 124 | | (*pn)->m_cur.Analog = (*pn)->m_new.Analog; |
| 153 | (*pn)->m_cur.Analog = (*pn)->m_new.Analog = new_val; |
| 125 | 154 | |
| 126 | | //printf("New: %f\n", (*pn)->m_new.Analog); |
| 127 | | pn++; |
| 155 | //printf("New: %d %lld %f %f\n", ts_cnt, netlist().time().as_raw(), netlist().time().as_double(), new_val); |
| 128 | 156 | } |
| 129 | 157 | if (resched) |
| 158 | { |
| 130 | 159 | schedule(); |
| 160 | } |
| 131 | 161 | else |
| 132 | | m_Q.net().push_to_queue(m_inc); // step circuit |
| 162 | { |
| 163 | /* update all inputs connected to this drive */ |
| 164 | for (netlist_terminal_t **p = m_inps.first(); p != NULL; p = m_inps.next(p)) |
| 165 | (*p)->netdev().update_dev(); |
| 166 | /* step circuit */ |
| 167 | if (!m_Q.net().is_queued()) |
| 168 | { |
| 169 | m_Q.net().push_to_queue(m_inc); |
| 170 | } |
| 171 | } |
| 133 | 172 | |
| 134 | 173 | /* only inputs and terminals connected |
| 135 | 174 | * approach: |
trunk/src/emu/netlist/nl_base.h
| r26234 | r26235 | |
| 168 | 168 | // : net_device_t(setup, name) |
| 169 | 169 | |
| 170 | 170 | #define NETLIB_UPDATE_PARAM(_chip) ATTR_HOT ATTR_ALIGN void NETLIB_NAME(_chip) :: update_param(void) |
| 171 | | #define NETLIB_FUNC_VOID(_chip, _name, _params) ATTR_HOT ATTR_ALIGN inline void NETLIB_NAME(_chip) :: _name _params |
| 171 | #define NETLIB_FUNC_VOID(_chip, _name, _params) ATTR_HOT ATTR_ALIGN void NETLIB_NAME(_chip) :: _name _params |
| 172 | 172 | |
| 173 | 173 | #define NETLIB_DEVICE_BASE(_name, _pclass, _extra, _priv) \ |
| 174 | 174 | class _name : public _pclass \ |
| r26234 | r26235 | |
| 661 | 661 | |
| 662 | 662 | ATTR_HOT virtual void dec_active() { /*printf("DeActivate %s\n", m_name);*/ } |
| 663 | 663 | |
| 664 | ATTR_HOT virtual void step_time(const double st) { } |
| 664 | 665 | ATTR_HOT virtual void update_terminals() { } |
| 665 | 666 | |
| 666 | 667 | /* stats */ |
| r26234 | r26235 | |
| 774 | 775 | m_queue.push(queue_t::entry_t(attime, out)); |
| 775 | 776 | } |
| 776 | 777 | |
| 777 | | ATTR_HOT NETLIB_NAME(solver) &solver() { return *m_solver; } |
| 778 | ATTR_HOT NETLIB_NAME(solver) *solver() { return m_solver; } |
| 778 | 779 | |
| 779 | 780 | ATTR_HOT void process_queue(INT32 &atime); |
| 780 | 781 | |
trunk/src/emu/netlist/nl_setup.c
| r26234 | r26235 | |
| 41 | 41 | netlist_setup_t::~netlist_setup_t() |
| 42 | 42 | { |
| 43 | 43 | tagmap_free_entries<tagmap_devices_t>(m_devices); |
| 44 | | tagmap_free_entries<tagmap_astring_t>(m_links); |
| 44 | tagmap_free_entries<tagmap_link_t>(m_links); |
| 45 | 45 | tagmap_free_entries<tagmap_astring_t>(m_alias); |
| 46 | 46 | m_params.reset(); |
| 47 | 47 | m_terminals.reset(); |
| r26234 | r26235 | |
| 82 | 82 | //remove_start_with<tagmap_input_t>(m_inputs, temp); |
| 83 | 83 | remove_start_with<tagmap_terminal_t>(m_terminals, temp); |
| 84 | 84 | remove_start_with<tagmap_param_t>(m_params, temp); |
| 85 | | remove_start_with<tagmap_astring_t>(m_links, temp); |
| 85 | |
| 86 | tagmap_link_t::entry_t *p = m_links.first(); |
| 87 | while (p != NULL) |
| 88 | { |
| 89 | tagmap_link_t::entry_t *n = m_links.next(p); |
| 90 | if (temp.cmpsubstr(p->object()->e1,0,temp.len()) == 0 || temp.cmpsubstr(p->object()->e2,0,temp.len()) == 0) |
| 91 | m_links.remove(p->object()); |
| 92 | p = n; |
| 93 | } |
| 86 | 94 | m_devices.remove(name); |
| 87 | 95 | } |
| 88 | 96 | |
| r26234 | r26235 | |
| 141 | 149 | term.init_terminal(upd_dev); |
| 142 | 150 | term.set_state(state); |
| 143 | 151 | if (!(m_terminals.add(temp, &term, false)==TMERR_NONE)) |
| 144 | | fatalerror("Error adding %s %s to terminal list\n", objtype_as_astr(term).cstr(), name.cstr()); |
| 152 | fatalerror("Error adding %s %s to terminal list\n", objtype_as_astr(term).cstr(), temp.cstr()); |
| 145 | 153 | NL_VERBOSE_OUT(("%s %s\n", objtype_as_astr(term).cstr(), name.cstr())); |
| 146 | 154 | } |
| 147 | 155 | break; |
| r26234 | r26235 | |
| 164 | 172 | |
| 165 | 173 | void netlist_setup_t::register_link(const astring &sin, const astring &sout) |
| 166 | 174 | { |
| 167 | | const astring *temp = new astring(sout); |
| 175 | link_t *temp = new link_t(sin, sout); |
| 168 | 176 | NL_VERBOSE_OUT(("link %s <== %s\n", sin.cstr(), sout.cstr())); |
| 169 | | if (!(m_links.add(sin, temp, false)==TMERR_NONE)) |
| 177 | if (!(m_links.add(sin + "." + sout, temp, false)==TMERR_NONE)) |
| 170 | 178 | fatalerror("Error adding link %s<==%s to link list\n", sin.cstr(), sout.cstr()); |
| 171 | 179 | } |
| 172 | 180 | |
| r26234 | r26235 | |
| 266 | 274 | } |
| 267 | 275 | } |
| 268 | 276 | |
| 277 | void netlist_setup_t::connect_terminal_input(netlist_terminal_t &term, netlist_input_t &inp) |
| 278 | { |
| 279 | if (inp.isFamily(netlist_terminal_t::ANALOG)) |
| 280 | { |
| 281 | connect_terminals(term, inp); |
| 282 | } |
| 283 | else if (inp.isFamily(netlist_terminal_t::LOGIC)) |
| 284 | { |
| 285 | //printf("here 1\n"); |
| 286 | nld_a_to_d_proxy *proxy = new nld_a_to_d_proxy(inp); |
| 287 | astring x = ""; |
| 288 | x.printf("proxy_da_%d", m_proxy_cnt++); |
| 289 | proxy->init(*this, x.cstr()); |
| 290 | register_dev(proxy); |
| 291 | |
| 292 | connect_terminals(term, proxy->m_I); |
| 293 | |
| 294 | if (inp.has_net()) |
| 295 | proxy->m_Q.net().merge_net(&inp.net()); |
| 296 | else |
| 297 | proxy->m_Q.net().register_con(inp); |
| 298 | } |
| 299 | else |
| 300 | { |
| 301 | fatalerror("Netlist: Severe Error"); |
| 302 | } |
| 303 | } |
| 304 | |
| 269 | 305 | // FIXME: optimize code ... |
| 270 | 306 | void netlist_setup_t::connect_terminal_output(netlist_terminal_t &in, netlist_output_t &out) |
| 271 | 307 | { |
| r26234 | r26235 | |
| 322 | 358 | NL_VERBOSE_OUT(("adding net ...\n")); |
| 323 | 359 | netlist_net_t *anet = new netlist_net_t(netlist_object_t::NET, netlist_object_t::ANALOG); |
| 324 | 360 | in.set_net(*anet); |
| 325 | | m_netlist.solver().m_nets.add(anet); |
| 361 | m_netlist.solver()->m_nets.add(anet); |
| 326 | 362 | in.net().init_object(netlist()); |
| 327 | 363 | in.net().register_con(out); |
| 328 | 364 | in.net().register_con(in); |
| r26234 | r26235 | |
| 347 | 383 | } |
| 348 | 384 | |
| 349 | 385 | NL_VERBOSE_OUT(("Resolving ...\n")); |
| 350 | | for (tagmap_astring_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry)) |
| 386 | for (tagmap_link_t::entry_t *entry = m_links.first(); entry != NULL; entry = m_links.next(entry)) |
| 351 | 387 | { |
| 352 | | const astring t1s = *entry->object(); |
| 353 | | const astring t2s = entry->tag(); |
| 388 | const astring t1s = entry->object()->e1; |
| 389 | const astring t2s = entry->object()->e2; |
| 354 | 390 | netlist_terminal_t &t1 = find_terminal(t1s); |
| 355 | 391 | netlist_terminal_t &t2 = find_terminal(t2s); |
| 356 | 392 | |
| r26234 | r26235 | |
| 376 | 412 | { |
| 377 | 413 | connect_terminal_output(dynamic_cast<netlist_terminal_t &>(t1), dynamic_cast<netlist_output_t &>(t2)); |
| 378 | 414 | } |
| 415 | else if (t1.isType(netlist_terminal_t::INPUT) && t2.isType(netlist_terminal_t::TERMINAL)) |
| 416 | { |
| 417 | connect_terminal_input(dynamic_cast<netlist_terminal_t &>(t2), dynamic_cast<netlist_input_t &>(t1)); |
| 418 | } |
| 419 | else if (t1.isType(netlist_terminal_t::TERMINAL) && t2.isType(netlist_terminal_t::INPUT)) |
| 420 | { |
| 421 | connect_terminal_input(dynamic_cast<netlist_terminal_t &>(t1), dynamic_cast<netlist_input_t &>(t2)); |
| 422 | } |
| 379 | 423 | else if (t1.isType(netlist_terminal_t::TERMINAL) && t2.isType(netlist_terminal_t::TERMINAL)) |
| 380 | 424 | { |
| 381 | 425 | connect_terminals(dynamic_cast<netlist_terminal_t &>(t1), dynamic_cast<netlist_terminal_t &>(t2)); |
| r26234 | r26235 | |
| 392 | 436 | //VERBOSE_OUT(("%s %d\n", out->netdev()->name(), *out->Q_ptr())); |
| 393 | 437 | } |
| 394 | 438 | |
| 439 | if (m_netlist.solver() != NULL) |
| 440 | m_netlist.solver()->post_start(); |
| 395 | 441 | |
| 442 | |
| 396 | 443 | } |
| 397 | 444 | |
| 398 | 445 | void netlist_setup_t::step_devices_once(void) |
trunk/src/emu/netlist/nl_setup.h
| r26234 | r26235 | |
| 63 | 63 | { |
| 64 | 64 | public: |
| 65 | 65 | |
| 66 | struct link_t |
| 67 | { |
| 68 | link_t(const astring &ae1, const astring &ae2) |
| 69 | { |
| 70 | e1 = ae1; |
| 71 | e2 = ae2; |
| 72 | } |
| 73 | astring e1; |
| 74 | astring e2; |
| 75 | }; |
| 76 | |
| 66 | 77 | typedef tagmap_t<netlist_device_t *, 393> tagmap_devices_t; |
| 78 | typedef tagmap_t<link_t *, 393> tagmap_link_t; |
| 67 | 79 | typedef tagmap_t<const astring *, 393> tagmap_astring_t; |
| 68 | 80 | typedef tagmap_t<netlist_param_t *, 393> tagmap_param_t; |
| 69 | 81 | typedef tagmap_t<netlist_terminal_t *, 393> tagmap_terminal_t; |
| r26234 | r26235 | |
| 108 | 120 | tagmap_devices_t m_devices; |
| 109 | 121 | tagmap_astring_t m_alias; |
| 110 | 122 | tagmap_param_t m_params; |
| 111 | | tagmap_astring_t m_links; |
| 123 | tagmap_link_t m_links; |
| 112 | 124 | |
| 113 | 125 | int m_proxy_cnt; |
| 114 | 126 | |
| 115 | 127 | void connect_terminals(netlist_terminal_t &in, netlist_terminal_t &out); |
| 116 | 128 | void connect_input_output(netlist_input_t &in, netlist_output_t &out); |
| 117 | 129 | void connect_terminal_output(netlist_terminal_t &in, netlist_output_t &out); |
| 130 | void connect_terminal_input(netlist_terminal_t &term, netlist_input_t &inp); |
| 118 | 131 | |
| 119 | 132 | // helpers |
| 120 | 133 | astring objtype_as_astr(netlist_object_t &in); |