trunk/src/emu/netlist/nl_setup.h
| r26295 | r26296 | |
| 16 | 16 | // MACROS / inline netlist definitions |
| 17 | 17 | //============================================================ |
| 18 | 18 | |
| 19 | #define NET_STR(_x) # _x |
| 20 | |
| 19 | 21 | #define NET_ALIAS(_alias, _name) \ |
| 20 | 22 | netlist.register_alias(# _alias, # _name); |
| 21 | 23 | #define NET_NEW(_type , _name) net_create_device_by_classname(NETLIB_NAME_STR(_type), netlist, # _name) |
| r26295 | r26296 | |
| 29 | 31 | #define NET_CONNECT(_name, _input, _output) \ |
| 30 | 32 | netlist.register_link(# _name "." # _input, # _output); |
| 31 | 33 | #define NET_C(_input, _output) \ |
| 32 | | netlist.register_link(# _input , # _output); |
| 34 | netlist.register_link(NET_STR(_input) , NET_STR(_output)); |
| 33 | 35 | #define NETDEV_PARAM(_name, _val) \ |
| 34 | 36 | netlist.find_param(# _name).initial(_val); |
| 35 | 37 | #define NETDEV_PARAMI(_name, _param, _val) \ |
trunk/src/emu/netlist/devices/nld_system.h
| r26295 | r26296 | |
| 34 | 34 | NET_REGISTER_DEV(solver, _name) |
| 35 | 35 | |
| 36 | 36 | // ---------------------------------------------------------------------------------------- |
| 37 | // 2 terminal devices |
| 38 | // ---------------------------------------------------------------------------------------- |
| 39 | |
| 40 | #define NETDEV_R(_name, _R) \ |
| 41 | NET_REGISTER_DEV(R, _name) \ |
| 42 | NETDEV_PARAMI(_name, R, _R) |
| 43 | |
| 44 | #define NETDEV_C(_name, _C) \ |
| 45 | NET_REGISTER_DEV(C, _name) \ |
| 46 | NETDEV_PARAMI(_name, C, _C) |
| 47 | |
| 48 | /* Generic Diode */ |
| 49 | #define NETDEV_D(_name) \ |
| 50 | NET_REGISTER_DEV(D, _name) |
| 51 | |
| 52 | // ---------------------------------------------------------------------------------------- |
| 37 | 53 | // netdev_*_const |
| 38 | 54 | // ---------------------------------------------------------------------------------------- |
| 39 | 55 | |
| r26295 | r26296 | |
| 81 | 97 | netlist_ttl_input_t m_feedback; |
| 82 | 98 | netlist_ttl_output_t m_Q; |
| 83 | 99 | |
| 100 | netlist_param_t m_freq; |
| 101 | |
| 84 | 102 | netlist_time m_inc; |
| 85 | 103 | netlist_time m_last_step; |
| 104 | |
| 86 | 105 | netlist_list_t<netlist_terminal_t *> m_terms; |
| 87 | 106 | netlist_list_t<netlist_terminal_t *> m_inps; |
| 88 | 107 | |
| r26295 | r26296 | |
| 153 | 172 | |
| 154 | 173 | ATTR_HOT ATTR_ALIGN virtual void update_terminals() |
| 155 | 174 | { |
| 175 | m_P.m_g = m_N.m_g = m_g; |
| 156 | 176 | m_N.m_Idr = (m_P.net().Q_Analog() - m_V) * m_g + m_I; |
| 157 | 177 | m_P.m_Idr = (m_N.net().Q_Analog() + m_V) * m_g - m_I; |
| 158 | 178 | //printf("%f %f %f %f\n", m_N.m_Idr, m_P.m_Idr, m_N.net().Q_Analog(), m_P.net().Q_Analog()); |
| r26295 | r26296 | |
| 192 | 212 | virtual void update_param() |
| 193 | 213 | { |
| 194 | 214 | m_g = 1.0 / m_R.Value(); |
| 195 | | m_P.m_g = m_g; |
| 196 | | m_N.m_g = m_g; |
| 197 | 215 | } |
| 198 | 216 | |
| 199 | 217 | private: |
| r26295 | r26296 | |
| 220 | 238 | |
| 221 | 239 | virtual void update_param() |
| 222 | 240 | { |
| 223 | | // set to some very big step time for now |
| 224 | | // ==> large resistance |
| 241 | // set to some very small step time for now |
| 225 | 242 | step_time(1e-9); |
| 226 | 243 | } |
| 227 | 244 | |
| r26295 | r26296 | |
| 233 | 250 | private: |
| 234 | 251 | }; |
| 235 | 252 | |
| 253 | class nld_D : public nld_twoterm |
| 254 | { |
| 255 | public: |
| 256 | nld_D() |
| 257 | : nld_twoterm() |
| 258 | { |
| 259 | } |
| 260 | |
| 261 | netlist_param_t m_Vt; |
| 262 | netlist_param_t m_Is; |
| 263 | netlist_param_t m_Rmin; |
| 264 | |
| 265 | double m_VtInv; |
| 266 | double m_Vcrit; |
| 267 | double m_Vd; |
| 268 | |
| 269 | protected: |
| 270 | void start() |
| 271 | { |
| 272 | register_terminal("A", m_P); |
| 273 | register_terminal("K", m_N); |
| 274 | |
| 275 | register_param("Vt", m_Vt, 0.0258); |
| 276 | register_param("Is", m_Is, 1e-15); |
| 277 | register_param("Rmin", m_Rmin, 1.4); |
| 278 | m_Vd = 0.7; |
| 279 | } |
| 280 | |
| 281 | virtual void update_param() |
| 282 | { |
| 283 | m_Vcrit = m_Vt.Value() * log(m_Vt.Value() / m_Is.Value() / sqrt(2.0)); |
| 284 | m_VtInv = 1.0 / m_Vt.Value(); |
| 285 | NL_VERBOSE_OUT(("VCutoff: %f\n", m_Vcrit)); |
| 286 | } |
| 287 | |
| 288 | ATTR_HOT ATTR_ALIGN virtual void update_terminals() |
| 289 | { |
| 290 | const double nVd = m_P.net().Q_Analog()- m_N.net().Q_Analog(); |
| 291 | |
| 292 | //FIXME: Optimize cutoff case |
| 293 | m_Vd = (nVd > m_Vcrit) ? m_Vd + log((nVd - m_Vd) * m_VtInv + 1.0) * m_Vt.Value() : nVd; |
| 294 | |
| 295 | const double eVDVt = exp(m_Vd * m_VtInv); |
| 296 | const double Id = m_Is.Value() * (eVDVt - 1.0); |
| 297 | |
| 298 | m_g = m_Is.Value() * m_VtInv * eVDVt; |
| 299 | |
| 300 | m_I = (Id - m_Vd * m_g); |
| 301 | //printf("Vd: %f %f %f %f\n", m_Vd, m_g, Id, m_I); |
| 302 | |
| 303 | nld_twoterm::update_terminals(); |
| 304 | } |
| 305 | |
| 306 | private: |
| 307 | }; |
| 308 | |
| 236 | 309 | #endif /* NLD_SYSTEM_H_ */ |
trunk/src/emu/netlist/devices/nld_system.c
| r26295 | r26296 | |
| 85 | 85 | register_output("Q", m_Q); |
| 86 | 86 | //register_input("FB", m_feedback); |
| 87 | 87 | |
| 88 | | m_inc = netlist_time::from_hz(50000); |
| 88 | register_param("FREQ", m_freq, 50000); |
| 89 | m_inc = netlist_time::from_hz(m_freq.Value()); |
| 89 | 90 | |
| 90 | 91 | register_link_internal(m_feedback, m_Q, netlist_input_t::STATE_INP_ACTIVE); |
| 91 | 92 | m_last_step = netlist_time::zero; |
| r26295 | r26296 | |
| 94 | 95 | |
| 95 | 96 | NETLIB_UPDATE_PARAM(solver) |
| 96 | 97 | { |
| 97 | | //m_inc = netlist_time::from_hz(m_freq.Value()*2); |
| 98 | m_inc = netlist_time::from_hz(m_freq.Value()); |
| 98 | 99 | } |
| 99 | 100 | |
| 100 | 101 | NETLIB_FUNC_VOID(solver, post_start, ()) |
| 101 | 102 | { |
| 103 | NL_VERBOSE_OUT(("post start solver ...\n")); |
| 102 | 104 | for (netlist_net_t **pn = m_nets.first(); pn != NULL; pn = m_nets.next(pn)) |
| 103 | 105 | { |
| 106 | NL_VERBOSE_OUT(("setting up net\n")); |
| 104 | 107 | for (netlist_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next) |
| 105 | 108 | { |
| 106 | 109 | switch (p->type()) |
| 107 | 110 | { |
| 108 | 111 | case netlist_terminal_t::TERMINAL: |
| 109 | 112 | m_terms.add(p); |
| 113 | NL_VERBOSE_OUT(("Added terminal\n")); |
| 110 | 114 | break; |
| 111 | 115 | case netlist_terminal_t::INPUT: |
| 112 | 116 | m_inps.add(p); |
| 117 | NL_VERBOSE_OUT(("Added input\n")); |
| 113 | 118 | break; |
| 114 | 119 | default: |
| 115 | 120 | fatalerror("unhandled element found\n"); |
| 116 | 121 | break; |
| 117 | 122 | } |
| 118 | 123 | } |
| 124 | if ((*pn)->m_head == NULL) |
| 125 | { |
| 126 | NL_VERBOSE_OUT(("Deleting net ...\n")); |
| 127 | netlist_net_t *to_delete = *pn; |
| 128 | m_nets.del(to_delete); |
| 129 | delete to_delete; |
| 130 | pn--; |
| 131 | } |
| 119 | 132 | } |
| 120 | 133 | } |
| 121 | 134 | |
| r26295 | r26296 | |
| 142 | 155 | |
| 143 | 156 | for (netlist_terminal_t *p = (*pn)->m_head; p != NULL; p = p->m_update_list_next) |
| 144 | 157 | { |
| 145 | | p->netdev().update_terminals(); |
| 146 | | gtot += p->m_g; |
| 147 | | iIdr += p->m_Idr; |
| 158 | if (p->isType(netlist_terminal_t::TERMINAL)) |
| 159 | { |
| 160 | p->netdev().update_terminals(); |
| 161 | gtot += p->m_g; |
| 162 | iIdr += p->m_Idr; |
| 163 | } |
| 148 | 164 | } |
| 149 | 165 | |
| 150 | 166 | double new_val = iIdr / gtot; |
| r26295 | r26296 | |
| 152 | 168 | resched = true; |
| 153 | 169 | (*pn)->m_cur.Analog = (*pn)->m_new.Analog = new_val; |
| 154 | 170 | |
| 155 | | //printf("New: %d %lld %f %f\n", ts_cnt, netlist().time().as_raw(), netlist().time().as_double(), new_val); |
| 171 | NL_VERBOSE_OUT(("Info: %d\n", (*pn)->m_num_cons)); |
| 172 | NL_VERBOSE_OUT(("New: %lld %f %f\n", netlist().time().as_raw(), netlist().time().as_double(), new_val)); |
| 156 | 173 | } |
| 157 | 174 | if (resched) |
| 158 | 175 | { |
| r26295 | r26296 | |
| 160 | 177 | } |
| 161 | 178 | else |
| 162 | 179 | { |
| 163 | | /* update all inputs connected to this drive */ |
| 180 | /* update all inputs connected */ |
| 164 | 181 | for (netlist_terminal_t **p = m_inps.first(); p != NULL; p = m_inps.next(p)) |
| 165 | 182 | (*p)->netdev().update_dev(); |
| 166 | 183 | /* step circuit */ |
trunk/src/emu/netlist/nl_base.c
| r26295 | r26296 | |
| 79 | 79 | update_time(e.time(), atime); |
| 80 | 80 | |
| 81 | 81 | //if (FATAL_ERROR_AFTER_NS) |
| 82 | | // printf("%s\n", e.object().netdev()->name().cstr()); |
| 82 | // NL_VERBOSE_OUT(("%s\n", e.object().netdev()->name().cstr()); |
| 83 | 83 | |
| 84 | 84 | e.object().update_devs(); |
| 85 | 85 | |
| r26295 | r26296 | |
| 200 | 200 | |
| 201 | 201 | netlist_device_t::~netlist_device_t() |
| 202 | 202 | { |
| 203 | | //printf("~net_device_t\n"); |
| 203 | //NL_VERBOSE_OUT(("~net_device_t\n"); |
| 204 | 204 | } |
| 205 | 205 | |
| 206 | 206 | ATTR_COLD void netlist_device_t::init(netlist_setup_t &setup, const astring &name) |
| r26295 | r26296 | |
| 218 | 218 | |
| 219 | 219 | ATTR_COLD void netlist_device_t::register_output(netlist_core_device_t &dev, const astring &name, netlist_output_t &port) |
| 220 | 220 | { |
| 221 | | m_setup->register_object(*this, dev, name, port, netlist_terminal_t::STATE_NONE); |
| 221 | m_setup->register_object(*this, dev, name, port, netlist_terminal_t::STATE_OUT); |
| 222 | 222 | } |
| 223 | 223 | |
| 224 | 224 | ATTR_COLD void netlist_device_t::register_terminal(const astring &name, netlist_terminal_t &port) |
| 225 | 225 | { |
| 226 | | m_setup->register_object(*this,*this,name, port, netlist_terminal_t::STATE_NONE); |
| 226 | m_setup->register_object(*this,*this,name, port, netlist_terminal_t::STATE_INP_ACTIVE); |
| 227 | 227 | } |
| 228 | 228 | |
| 229 | 229 | ATTR_COLD void netlist_device_t::register_output(const astring &name, netlist_output_t &port) |
| 230 | 230 | { |
| 231 | | m_setup->register_object(*this,*this,name, port, netlist_terminal_t::STATE_NONE); |
| 231 | m_setup->register_object(*this,*this,name, port, netlist_terminal_t::STATE_OUT); |
| 232 | 232 | } |
| 233 | 233 | |
| 234 | 234 | ATTR_COLD void netlist_device_t::register_input(netlist_core_device_t &dev, const astring &name, netlist_input_t &inp, netlist_input_t::state_e type) |
| r26295 | r26296 | |
| 244 | 244 | |
| 245 | 245 | ATTR_COLD void netlist_device_t::register_link_internal(netlist_core_device_t &dev, netlist_input_t &in, netlist_output_t &out, netlist_input_t::state_e aState) |
| 246 | 246 | { |
| 247 | | in.init_terminal(dev); |
| 248 | | in.set_state(aState); |
| 247 | in.init_terminal(dev, aState); |
| 249 | 248 | // ensure we are not yet initialized ... |
| 250 | 249 | if (!out.net().isRailNet()) |
| 251 | 250 | out.init_terminal(dev); |
| r26295 | r26296 | |
| 262 | 261 | { |
| 263 | 262 | param.set_netdev(dev); |
| 264 | 263 | param.initial(initialVal); |
| 265 | | m_setup->register_object(*this, *this, name, param, netlist_terminal_t::STATE_NONE); |
| 264 | m_setup->register_object(*this, *this, name, param, netlist_terminal_t::STATE_NONEX); |
| 266 | 265 | } |
| 267 | 266 | |
| 268 | 267 | ATTR_COLD void netlist_device_t::register_param(const astring &name, netlist_param_t ¶m, double initialVal) |
| r26295 | r26296 | |
| 290 | 289 | |
| 291 | 290 | ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet) |
| 292 | 291 | { |
| 292 | NL_VERBOSE_OUT(("merging nets ...\n")); |
| 293 | 293 | if (othernet == NULL) |
| 294 | 294 | return; // Nothing to do |
| 295 | 295 | |
| r26295 | r26296 | |
| 297 | 297 | fatalerror("Trying to merge to rail nets\n"); |
| 298 | 298 | |
| 299 | 299 | if (othernet->isRailNet()) |
| 300 | { |
| 301 | NL_VERBOSE_OUT(("othernet is railnet\n")); |
| 300 | 302 | othernet->merge_net(this); |
| 303 | } |
| 301 | 304 | else |
| 302 | 305 | { |
| 303 | 306 | netlist_terminal_t *p = othernet->m_head; |
| 304 | | if (p == NULL) |
| 305 | | return; |
| 306 | | if (m_head == NULL) |
| 307 | | { |
| 308 | | m_head = p; |
| 309 | | m_head->set_net(*this); |
| 310 | | p = p->m_update_list_next; |
| 311 | | } |
| 312 | 307 | while (p != NULL) |
| 313 | 308 | { |
| 314 | 309 | netlist_terminal_t *pn = p->m_update_list_next; |
| 315 | | p->m_update_list_next = m_head; |
| 316 | | p->set_net(*this); |
| 317 | | m_head = p; |
| 310 | register_con(*p); |
| 318 | 311 | p = pn; |
| 319 | 312 | } |
| 313 | |
| 320 | 314 | othernet->m_head = NULL; // FIXME: othernet needs to be free'd from memory |
| 321 | 315 | } |
| 322 | 316 | } |
| r26295 | r26296 | |
| 324 | 318 | ATTR_COLD void netlist_net_t::register_con(netlist_terminal_t &terminal) |
| 325 | 319 | { |
| 326 | 320 | terminal.set_net(*this); |
| 327 | | if (m_head == NULL) |
| 328 | | m_head = &terminal; |
| 329 | | else |
| 330 | | { |
| 331 | | terminal.m_update_list_next = m_head; |
| 332 | | m_head = &terminal; |
| 333 | | } |
| 321 | |
| 322 | terminal.m_update_list_next = m_head; |
| 323 | m_head = &terminal; |
| 334 | 324 | m_num_cons++; |
| 335 | 325 | |
| 336 | 326 | if (terminal.state() != netlist_input_t::STATE_INP_PASSIVE) |
| r26295 | r26296 | |
| 387 | 377 | // netlist_terminal_t |
| 388 | 378 | // ---------------------------------------------------------------------------------------- |
| 389 | 379 | |
| 390 | | ATTR_COLD void netlist_terminal_t::init_terminal(netlist_core_device_t &dev) |
| 380 | ATTR_COLD void netlist_terminal_t::init_terminal(netlist_core_device_t &dev, const state_e astate) |
| 391 | 381 | { |
| 392 | 382 | m_netdev = &dev; |
| 383 | set_state(astate); |
| 393 | 384 | init_object(dev.netlist()); |
| 394 | 385 | } |
| 395 | 386 | |
| r26295 | r26296 | |
| 413 | 404 | |
| 414 | 405 | ATTR_COLD void netlist_output_t::init_terminal(netlist_core_device_t &dev) |
| 415 | 406 | { |
| 416 | | netlist_terminal_t::init_terminal(dev); |
| 407 | netlist_terminal_t::init_terminal(dev, STATE_OUT); |
| 417 | 408 | net().init_object(dev.netlist()); |
| 418 | 409 | net().register_railterminal(*this); |
| 419 | 410 | } |
trunk/src/emu/netlist/nl_base.h
| r26295 | r26296 | |
| 287 | 287 | STATE_INP_ACTIVE = 1, |
| 288 | 288 | STATE_INP_HL = 2, |
| 289 | 289 | STATE_INP_LH = 4, |
| 290 | | STATE_NONE = 128 |
| 290 | STATE_OUT = 128, |
| 291 | STATE_NONEX = 256 |
| 291 | 292 | }; |
| 292 | 293 | |
| 293 | 294 | ATTR_COLD netlist_terminal_t(const type_t atype, const family_t afamily) |
| r26295 | r26296 | |
| 297 | 298 | , m_update_list_next(NULL) |
| 298 | 299 | , m_netdev(NULL) |
| 299 | 300 | , m_net(NULL) |
| 300 | | , m_state(STATE_NONE) |
| 301 | , m_state(STATE_NONEX) |
| 301 | 302 | {} |
| 302 | 303 | |
| 303 | 304 | ATTR_COLD netlist_terminal_t() |
| r26295 | r26296 | |
| 306 | 307 | , m_update_list_next(NULL) |
| 307 | 308 | , m_netdev(NULL) |
| 308 | 309 | , m_net(NULL) |
| 309 | | , m_state(STATE_NONE) |
| 310 | , m_state(STATE_NONEX) |
| 310 | 311 | {} |
| 311 | 312 | |
| 312 | | ATTR_COLD virtual void init_terminal(netlist_core_device_t &dev); |
| 313 | ATTR_COLD void init_terminal(netlist_core_device_t &dev, const state_e astate); |
| 313 | 314 | |
| 314 | 315 | ATTR_COLD void set_net(netlist_net_t &anet) { m_net = &anet; } |
| 315 | 316 | ATTR_COLD bool has_net() { return (m_net != NULL); } |
| r26295 | r26296 | |
| 319 | 320 | |
| 320 | 321 | ATTR_HOT inline const bool is_state(const state_e astate) const { return (m_state == astate); } |
| 321 | 322 | ATTR_HOT inline const state_e state() const { return m_state; } |
| 322 | | ATTR_HOT inline void set_state(const state_e astate) { m_state = astate; } |
| 323 | ATTR_HOT inline void set_state(const state_e astate) |
| 324 | { |
| 325 | assert(astate != STATE_NONEX); |
| 326 | m_state = astate; |
| 327 | } |
| 323 | 328 | |
| 324 | 329 | ATTR_HOT inline netlist_core_device_t & RESTRICT netdev() const { return *m_netdev; } |
| 325 | 330 | |
| r26295 | r26296 | |
| 522 | 527 | |
| 523 | 528 | netlist_output_t(const type_t atype, const family_t afamily); |
| 524 | 529 | |
| 525 | | ATTR_COLD virtual void init_terminal(netlist_core_device_t &dev); |
| 530 | ATTR_COLD void init_terminal(netlist_core_device_t &dev); |
| 526 | 531 | |
| 527 | 532 | double m_low_V; |
| 528 | 533 | double m_high_V; |
| r26295 | r26296 | |
| 576 | 581 | : netlist_output_t(OUTPUT, ANALOG) |
| 577 | 582 | { |
| 578 | 583 | net().m_cur.Analog = 0.0; |
| 579 | | net().m_new.Analog = 0.0; |
| 584 | net().m_new.Analog = 99.0; |
| 580 | 585 | } |
| 581 | 586 | |
| 582 | 587 | ATTR_COLD void initial(const double val) |
| 583 | 588 | { |
| 584 | 589 | net().m_cur.Analog = val; |
| 585 | | net().m_new.Analog = val; |
| 590 | net().m_new.Analog = 99.0; |
| 586 | 591 | } |
| 587 | 592 | |
| 588 | 593 | ATTR_HOT inline void set_Q(const double newQ, const netlist_time &delay) |
| r26295 | r26296 | |
| 830 | 835 | protected: |
| 831 | 836 | void start() |
| 832 | 837 | { |
| 833 | | m_I.init_terminal(*this); |
| 838 | m_I.init_terminal(*this, netlist_terminal_t::STATE_INP_ACTIVE); |
| 834 | 839 | |
| 835 | 840 | m_Q.init_terminal(*this); |
| 836 | 841 | m_Q.initial(1); |
| r26295 | r26296 | |
| 842 | 847 | OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1)); |
| 843 | 848 | else if (m_I.Q_Analog() < m_I.m_low_thresh_V) |
| 844 | 849 | OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1)); |
| 850 | else |
| 851 | OUTLOGIC(m_Q, m_Q.net().last_Q(), NLTIME_FROM_NS(1)); |
| 845 | 852 | } |
| 846 | 853 | |
| 847 | 854 | }; |
| r26295 | r26296 | |
| 870 | 877 | protected: |
| 871 | 878 | void start() |
| 872 | 879 | { |
| 873 | | m_I.init_terminal(*this); |
| 880 | m_I.init_terminal(*this, netlist_terminal_t::STATE_INP_ACTIVE); |
| 874 | 881 | m_Q.init_terminal(*this); |
| 875 | 882 | m_Q.initial(0); |
| 876 | 883 | } |
trunk/src/emu/netlist/nl_setup.c
| r26295 | r26296 | |
| 146 | 146 | astring temp = dev.name(); |
| 147 | 147 | temp.cat("."); |
| 148 | 148 | temp.cat(name); |
| 149 | | term.init_terminal(upd_dev); |
| 150 | | term.set_state(state); |
| 149 | if (obj.isType(netlist_terminal_t::OUTPUT)) |
| 150 | dynamic_cast<netlist_output_t &>(term).init_terminal(upd_dev); |
| 151 | else |
| 152 | term.init_terminal(upd_dev, state); |
| 153 | |
| 151 | 154 | if (!(m_terminals.add(temp, &term, false)==TMERR_NONE)) |
| 152 | 155 | fatalerror("Error adding %s %s to terminal list\n", objtype_as_astr(term).cstr(), temp.cstr()); |
| 153 | 156 | NL_VERBOSE_OUT(("%s %s\n", objtype_as_astr(term).cstr(), name.cstr())); |
| r26295 | r26296 | |
| 278 | 281 | { |
| 279 | 282 | if (inp.isFamily(netlist_terminal_t::ANALOG)) |
| 280 | 283 | { |
| 281 | | connect_terminals(term, inp); |
| 284 | connect_terminals(inp, term); |
| 282 | 285 | } |
| 283 | 286 | else if (inp.isFamily(netlist_terminal_t::LOGIC)) |
| 284 | 287 | { |
| 285 | | //printf("here 1\n"); |
| 288 | NL_VERBOSE_OUT(("connect_terminal_input: connecting proxy\n")); |
| 286 | 289 | nld_a_to_d_proxy *proxy = new nld_a_to_d_proxy(inp); |
| 287 | 290 | astring x = ""; |
| 288 | 291 | x.printf("proxy_da_%d", m_proxy_cnt++); |
| r26295 | r26296 | |
| 292 | 295 | connect_terminals(term, proxy->m_I); |
| 293 | 296 | |
| 294 | 297 | if (inp.has_net()) |
| 298 | //fatalerror("logic inputs can only belong to one net!\n"); |
| 295 | 299 | proxy->m_Q.net().merge_net(&inp.net()); |
| 296 | 300 | else |
| 297 | 301 | proxy->m_Q.net().register_con(inp); |
| r26295 | r26296 | |
| 316 | 320 | } |
| 317 | 321 | else if (out.isFamily(netlist_terminal_t::LOGIC)) |
| 318 | 322 | { |
| 319 | | //printf("here 1\n"); |
| 323 | NL_VERBOSE_OUT(("connect_terminal_output: connecting proxy\n")); |
| 320 | 324 | nld_d_to_a_proxy *proxy = new nld_d_to_a_proxy(out); |
| 321 | 325 | astring x = ""; |
| 322 | 326 | x.printf("proxy_da_%d", m_proxy_cnt++); |
| r26295 | r26296 | |
| 336 | 340 | } |
| 337 | 341 | } |
| 338 | 342 | |
| 339 | | void netlist_setup_t::connect_terminals(netlist_terminal_t &in, netlist_terminal_t &out) |
| 343 | void netlist_setup_t::connect_terminals(netlist_terminal_t &t1, netlist_terminal_t &t2) |
| 340 | 344 | { |
| 341 | | assert(in.isType(netlist_terminal_t::TERMINAL)); |
| 342 | | assert(out.isType(netlist_terminal_t::TERMINAL)); |
| 345 | //assert(in.isType(netlist_terminal_t::TERMINAL)); |
| 346 | //assert(out.isType(netlist_terminal_t::TERMINAL)); |
| 343 | 347 | |
| 344 | | if (in.has_net() && out.has_net()) |
| 348 | if (t1.has_net() && t2.has_net()) |
| 345 | 349 | { |
| 346 | | in.net().merge_net(&out.net()); |
| 350 | NL_VERBOSE_OUT(("T2 and T1 have net\n")); |
| 351 | t1.net().merge_net(&t2.net()); |
| 347 | 352 | } |
| 348 | | else if (out.has_net()) |
| 353 | else if (t2.has_net()) |
| 349 | 354 | { |
| 350 | | out.net().register_con(in); |
| 355 | NL_VERBOSE_OUT(("T2 has net\n")); |
| 356 | t2.net().register_con(t1); |
| 351 | 357 | } |
| 352 | | else if (in.has_net()) |
| 358 | else if (t1.has_net()) |
| 353 | 359 | { |
| 354 | | in.net().register_con(out); |
| 360 | NL_VERBOSE_OUT(("T1 has net\n")); |
| 361 | t1.net().register_con(t2); |
| 355 | 362 | } |
| 356 | 363 | else |
| 357 | 364 | { |
| 358 | 365 | NL_VERBOSE_OUT(("adding net ...\n")); |
| 359 | 366 | netlist_net_t *anet = new netlist_net_t(netlist_object_t::NET, netlist_object_t::ANALOG); |
| 360 | | in.set_net(*anet); |
| 367 | t1.set_net(*anet); |
| 361 | 368 | m_netlist.solver()->m_nets.add(anet); |
| 362 | | in.net().init_object(netlist()); |
| 363 | | in.net().register_con(out); |
| 364 | | in.net().register_con(in); |
| 369 | t1.net().init_object(netlist()); |
| 370 | t1.net().register_con(t2); |
| 371 | t1.net().register_con(t1); |
| 365 | 372 | } |
| 366 | 373 | } |
| 367 | 374 | |
| r26295 | r26296 | |
| 390 | 397 | netlist_terminal_t &t1 = find_terminal(t1s); |
| 391 | 398 | netlist_terminal_t &t2 = find_terminal(t2s); |
| 392 | 399 | |
| 400 | NL_VERBOSE_OUT(("Connecting %s to %s\n", t1s.cstr(), t2s.cstr())); |
| 401 | |
| 393 | 402 | // FIXME: amend device design so that warnings can be turned into errors |
| 394 | 403 | // Only variable inputs have this issue |
| 395 | 404 | if (t1.isType(netlist_terminal_t::OUTPUT) && t2.isType(netlist_terminal_t::INPUT)) |