Add -D to iverilog-vpi and update documentation.
[iverilog.git] / elab_sig.cc
blob6a68517bacad1a5a30ab8ceb4d397995178b1dbe
1 /*
2 * Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: elab_sig.cc,v 1.52 2007/06/02 03:42:12 steve Exp $"
21 #endif
23 # include "config.h"
25 # include <iostream>
27 # include "Module.h"
28 # include "PExpr.h"
29 # include "PGate.h"
30 # include "PGenerate.h"
31 # include "PTask.h"
32 # include "PWire.h"
33 # include "compiler.h"
34 # include "netlist.h"
35 # include "netmisc.h"
36 # include "util.h"
37 # include "ivl_assert.h"
40 * This local function checks if a named signal is connected to a
41 * port. It looks in the array of ports passed, for NetEIdent objects
42 * within the port_t that have a matching name.
44 static bool signal_is_in_port(const svector<Module::port_t*>&ports,
45 NetNet*sig)
47 perm_string name = sig->name();
49 for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
51 Module::port_t*pp = ports[idx];
52 // Skip internally unconnected ports.
53 if (pp == 0)
54 continue;
56 // This port has an internal connection. In this case,
57 // the port has 0 or more NetEIdent objects concatenated
58 // together that form the port.
60 // Note that module ports should not have any heirarchy
61 // in their names: they are in the root of the module
62 // scope by definition.
64 for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
65 perm_string pname = peek_tail_name(pp->expr[cc]->path());
66 assert(pp->expr[cc]);
67 if (pname == name)
68 return true;
72 return false;
75 #if 0
76 static NetNet*find_signal_in_scope(NetScope*scope, const hname_t&path)
78 NetScope*cur = scope;
79 unsigned idx = 0;
81 while (path.peek_name(idx+1)) {
82 cur = cur->child(path.peek_name(idx));
83 if (cur == 0)
84 return 0;
86 idx += 1;
89 return cur->find_signal(path.peek_name(idx));
91 #endif
93 bool Module::elaborate_sig(Design*des, NetScope*scope) const
95 bool flag = true;
97 // Scan all the ports of the module, and make sure that each
98 // is connected to wires that have port declarations.
99 for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
100 Module::port_t*pp = ports[idx];
101 if (pp == 0)
102 continue;
104 map<pform_name_t,PWire*>::const_iterator wt;
105 for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
106 pform_name_t port_path (pp->expr[cc]->path());
107 wt = wires_.find(port_path);
109 if (wt == wires_.end()) {
110 cerr << get_line() << ": error: "
111 << "Port " << pp->expr[cc]->path() << " ("
112 << (idx+1) << ") of module " << name_
113 << " is not declared within module." << endl;
114 des->errors += 1;
115 continue;
118 if ((*wt).second->get_port_type() == NetNet::NOT_A_PORT) {
119 cerr << get_line() << ": error: "
120 << "Port " << pp->expr[cc]->path() << " ("
121 << (idx+1) << ") of module " << name_
122 << " has no direction declaration."
123 << endl;
124 des->errors += 1;
129 for (map<pform_name_t,PWire*>::const_iterator wt = wires_.begin()
130 ; wt != wires_.end() ; wt ++ ) {
132 PWire*cur = (*wt).second;
133 NetNet*sig = cur->elaborate_sig(des, scope);
135 // If this wire is a signal of the module (as opposed to
136 // a port of a function) and is a port, then check that
137 // the module knows about it. We know that the signal is
138 // the name of a signal within a subscope of a module
139 // (a task, a function, etc.) if the name for the PWire
140 // has hierarchy.
142 if (sig && (sig->scope() == scope)
143 && (cur->get_port_type() != NetNet::NOT_A_PORT)) {
145 if (! signal_is_in_port(ports, sig)) {
147 cerr << cur->get_line() << ": error: Signal "
148 << sig->name() << " has a declared direction "
149 << "but is not a port." << endl;
150 des->errors += 1;
155 /* If the signal is an input and is also declared as a
156 reg, then report an error. */
158 if (sig && (sig->scope() == scope)
159 && (sig->port_type() == NetNet::PINPUT)
160 && (sig->type() == NetNet::REG)) {
162 cerr << cur->get_line() << ": error: "
163 << cur->path() << " in module "
164 << scope->module_name()
165 << " declared as input and as a reg type." << endl;
166 des->errors += 1;
169 if (sig && (sig->scope() == scope)
170 && (sig->port_type() == NetNet::PINOUT)
171 && (sig->type() == NetNet::REG)) {
173 cerr << cur->get_line() << ": error: "
174 << cur->path() << " in module "
175 << scope->module_name()
176 << " declared as inout and as a reg type." << endl;
177 des->errors += 1;
182 // Run through all the generate schemes to enaborate the
183 // signals that they hold. Note that the generate schemes hold
184 // the scopes that they instantiated, so we don't pass any
185 // scope in.
186 typedef list<PGenerate*>::const_iterator generate_it_t;
187 for (generate_it_t cur = generate_schemes.begin()
188 ; cur != generate_schemes.end() ; cur ++ ) {
189 (*cur) -> elaborate_sig(des, scope);
192 // Get all the gates of the module and elaborate them by
193 // connecting them to the signals. The gate may be simple or
194 // complex. What we are looking for is gates that are modules
195 // that can create scopes and signals.
197 const list<PGate*>&gl = get_gates();
199 for (list<PGate*>::const_iterator gt = gl.begin()
200 ; gt != gl.end()
201 ; gt ++ ) {
203 flag &= (*gt)->elaborate_sig(des, scope);
207 typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
209 for (mfunc_it_t cur = funcs_.begin()
210 ; cur != funcs_.end() ; cur ++) {
212 hname_t use_name ( (*cur).first );
213 NetScope*fscope = scope->child(use_name);
214 if (scope == 0) {
215 cerr << (*cur).second->get_line() << ": internal error: "
216 << "Child scope for function " << (*cur).first
217 << " missing in " << scope_path(scope) << "." << endl;
218 des->errors += 1;
219 continue;
222 (*cur).second->elaborate_sig(des, fscope);
226 // After all the wires are elaborated, we are free to
227 // elaborate the ports of the tasks defined within this
228 // module. Run through them now.
230 typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
232 for (mtask_it_t cur = tasks_.begin()
233 ; cur != tasks_.end() ; cur ++) {
234 NetScope*tscope = scope->child( hname_t((*cur).first) );
235 assert(tscope);
236 (*cur).second->elaborate_sig(des, tscope);
239 return flag;
242 bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
243 Module*rmod) const
245 bool flag = true;
247 NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
249 for (unsigned idx = 0 ; idx < instance.count() ; idx += 1) {
250 // I know a priori that the elaborate_scope created the scope
251 // already, so just look it up as a child of the current scope.
252 NetScope*my_scope = instance[idx];
253 assert(my_scope);
255 if (my_scope->parent() != scope) {
256 cerr << get_line() << ": internal error: "
257 << "Instance " << scope_path(my_scope)
258 << " is in parent " << scope_path(my_scope->parent())
259 << " instead of " << scope_path(scope)
260 << endl;
262 assert(my_scope->parent() == scope);
264 if (! rmod->elaborate_sig(des, my_scope))
265 flag = false;
269 return flag;
272 bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
274 bool flag = true;
276 typedef list<NetScope*>::const_iterator scope_list_it_t;
277 for (scope_list_it_t cur = scope_list_.begin()
278 ; cur != scope_list_.end() ; cur ++ ) {
280 NetScope*scope = *cur;
282 if (scope->parent() != container)
283 continue;
285 if (debug_elaborate)
286 cerr << get_line() << ": debug: Elaborate nets in "
287 << "scope " << scope_path(*cur)
288 << " in generate " << id_number << endl;
289 flag = elaborate_sig_(des, *cur) & flag;
292 return flag;
295 bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
297 // Scan the declared PWires to elaborate the obvious signals
298 // in the current scope.
299 typedef map<pform_name_t,PWire*>::const_iterator wires_it_t;
300 for (wires_it_t wt = wires.begin()
301 ; wt != wires.end() ; wt ++ ) {
303 PWire*cur = (*wt).second;
305 if (debug_elaborate)
306 cerr << get_line() << ": debug: Elaborate PWire "
307 << cur->path() << " in scope " << scope_path(scope) << endl;
309 cur->elaborate_sig(des, scope);
312 typedef list<PGenerate*>::const_iterator generate_it_t;
313 for (generate_it_t cur = generates.begin()
314 ; cur != generates.end() ; cur ++ ) {
315 (*cur) -> elaborate_sig(des, scope);
318 typedef list<PGate*>::const_iterator pgate_list_it_t;
319 for (pgate_list_it_t cur = gates.begin()
320 ; cur != gates.end() ; cur ++) {
321 (*cur) ->elaborate_sig(des, scope);
324 return true;
329 * A function definition exists within an elaborated module. This
330 * matters when elaborating signals, as the ports of the function are
331 * created as signals/variables for each instance of the
332 * function. That is why PFunction has an elaborate_sig method.
334 void PFunction::elaborate_sig(Design*des, NetScope*scope) const
336 perm_string fname = scope->basename();
337 assert(scope->type() == NetScope::FUNC);
339 /* Make sure the function has at least one input port. If it
340 fails this test, print an error message. Keep going so we
341 can find more errors. */
342 if (ports_ == 0) {
343 cerr << get_line() << ": error: Function " << fname
344 << " has no ports." << endl;
345 cerr << get_line() << ": : Functions must have"
346 << " at least one input port." << endl;
347 des->errors += 1;
350 NetNet*ret_sig = 0;
352 /* Create the signals/variables of the return value and write
353 them into the function scope. */
354 switch (return_type_.type) {
356 case PTF_REG:
357 case PTF_REG_S:
358 if (return_type_.range) {
359 NetExpr*me = elab_and_eval(des, scope,
360 (*return_type_.range)[0], -1);
361 assert(me);
362 NetExpr*le = elab_and_eval(des, scope,
363 (*return_type_.range)[1], -1);
364 assert(le);
366 long mnum = 0, lnum = 0;
367 if (NetEConst*tmp = dynamic_cast<NetEConst*>(me)) {
368 mnum = tmp->value().as_long();
369 } else {
370 cerr << me->get_line() << ": error: "
371 "Unable to evaluate constant expression "
372 << *me << "." << endl;
373 des->errors += 1;
376 if (NetEConst*tmp = dynamic_cast<NetEConst*>(le)) {
377 lnum = tmp->value().as_long();
378 } else {
379 cerr << le->get_line() << ": error: "
380 "Unable to evaluate constant expression "
381 << *le << "." << endl;
382 des->errors += 1;
385 ret_sig = new NetNet(scope, fname, NetNet::REG, mnum, lnum);
387 } else {
388 ret_sig = new NetNet(scope, fname, NetNet::REG);
390 ret_sig->set_line(*this);
391 ret_sig->set_signed(return_type_.type == PTF_REG_S);
392 ret_sig->port_type(NetNet::POUTPUT);
393 ret_sig->data_type(IVL_VT_LOGIC);
394 break;
396 case PTF_INTEGER:
397 ret_sig = new NetNet(scope, fname, NetNet::REG, integer_width);
398 ret_sig->set_line(*this);
399 ret_sig->set_signed(true);
400 ret_sig->set_isint(true);
401 ret_sig->port_type(NetNet::POUTPUT);
402 ret_sig->data_type(IVL_VT_LOGIC);
403 break;
405 case PTF_TIME:
406 ret_sig = new NetNet(scope, fname, NetNet::REG, 64);
407 ret_sig->set_line(*this);
408 ret_sig->set_signed(false);
409 ret_sig->set_isint(false);
410 ret_sig->port_type(NetNet::POUTPUT);
411 ret_sig->data_type(IVL_VT_LOGIC);
412 break;
414 case PTF_REAL:
415 case PTF_REALTIME:
416 ret_sig = new NetNet(scope, fname, NetNet::REG, 1);
417 ret_sig->set_line(*this);
418 ret_sig->set_signed(true);
419 ret_sig->set_isint(false);
420 ret_sig->port_type(NetNet::POUTPUT);
421 ret_sig->data_type(IVL_VT_REAL);
422 break;
424 default:
425 cerr << get_line() << ": internal error: I don't know how "
426 << "to deal with return type of function "
427 << scope->basename() << "." << endl;
430 svector<NetNet*>ports (ports_? ports_->count() : 0);
432 if (ports_)
433 for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
435 /* Parse the port name into the task name and the reg
436 name. We know by design that the port name is given
437 as two components: <func>.<port>. */
439 pform_name_t path = (*ports_)[idx]->path();
440 ivl_assert(*this, path.size() == 2);
442 perm_string pname = peek_tail_name(path);
443 perm_string ppath = peek_head_name(path);
445 if (ppath != scope->basename()) {
446 cerr << get_line() << ": internal error: function "
447 << "port " << (*ports_)[idx]->path()
448 << " has wrong name for function "
449 << scope_path(scope) << "." << endl;
450 des->errors += 1;
453 NetNet*tmp = scope->find_signal(pname);
454 if (tmp == 0) {
455 cerr << get_line() << ": internal error: function "
456 << scope_path(scope) << " is missing port "
457 << pname << "." << endl;
458 scope->dump(cerr);
459 cerr << get_line() << ": Continuing..." << endl;
460 des->errors += 1;
463 ports[idx] = tmp;
467 NetFuncDef*def = 0;
468 if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
470 assert(def);
471 scope->set_func_def(def);
475 * A task definition is a scope within an elaborated module. When we
476 * are elaborating signals, the scopes have already been created, as
477 * have the reg objects that are the parameters of this task. The
478 * elaborate_sig method of PTask is therefore left to connect the
479 * signals to the ports of the NetTaskDef definition. We know for
480 * certain that signals exist (They are in my scope!) so the port
481 * binding is sure to work.
483 void PTask::elaborate_sig(Design*des, NetScope*scope) const
485 assert(scope->type() == NetScope::TASK);
487 svector<NetNet*>ports (ports_? ports_->count() : 0);
488 for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
490 /* Parse the port name into the task name and the reg
491 name. We know by design that the port name is given
492 as two components: <task>.<port>. */
494 pform_name_t path = (*ports_)[idx]->path();
495 ivl_assert(*this, path.size() == 2);
497 perm_string scope_name = peek_head_name(path);
498 perm_string port_name = peek_tail_name(path);
500 /* check that the current scope really does have the
501 name of the first component of the task port name. Do
502 this by looking up the task scope in the parent of
503 the current scope. */
504 ivl_assert(*this, scope->basename() == scope_name);
506 /* Find the signal for the port. We know by definition
507 that it is in the scope of the task, so look only in
508 the scope. */
509 NetNet*tmp = scope->find_signal(port_name);
511 if (tmp == 0) {
512 cerr << get_line() << ": internal error: "
513 << "Could not find port " << port_name
514 << " in scope " << scope_path(scope) << endl;
515 scope->dump(cerr);
518 ports[idx] = tmp;
521 NetTaskDef*def = new NetTaskDef(scope, ports);
522 scope->set_task_def(def);
525 bool PGate::elaborate_sig(Design*des, NetScope*scope) const
527 return true;
531 * Elaborate a source wire. The "wire" is the declaration of wires,
532 * registers, ports and memories. The parser has already merged the
533 * multiple properties of a wire (i.e., "input wire") so come the
534 * elaboration this creates an object in the design that represent the
535 * defined item.
537 NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
540 /* The parser may produce hierarchical names for wires. I here
541 follow the scopes down to the base where I actually want to
542 elaborate the NetNet object. */
543 { pform_name_t tmp_path = hname_;
544 tmp_path.pop_back();
545 while (! tmp_path.empty()) {
546 name_component_t cur = tmp_path.front();
547 tmp_path.pop_front();
549 scope = scope->child( hname_t(cur.name) );
551 if (scope == 0) {
552 cerr << get_line() << ": internal error: "
553 << "Bad scope component for name "
554 << hname_ << endl;
555 assert(scope);
560 NetNet::Type wtype = type_;
561 if (wtype == NetNet::IMPLICIT)
562 wtype = NetNet::WIRE;
563 if (wtype == NetNet::IMPLICIT_REG)
564 wtype = NetNet::REG;
566 unsigned wid = 1;
567 long lsb = 0, msb = 0;
569 des->errors += error_cnt_;
571 if (port_set_ || net_set_) {
572 long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0;
573 /* If they exist get the port definition MSB and LSB */
574 if (port_set_ && port_msb_ != 0) {
575 NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
577 if (! eval_as_long(pmsb, texpr)) {
578 cerr << port_msb_->get_line() << ": error: "
579 "Unable to evaluate MSB constant expression ``"
580 << *port_msb_ << "''." << endl;
581 des->errors += 1;
582 return 0;
585 delete texpr;
587 texpr = elab_and_eval(des, scope, port_lsb_, -1);
589 if (! eval_as_long(plsb, texpr)) {
590 cerr << port_lsb_->get_line() << ": error: "
591 "Unable to evaluate LSB constant expression ``"
592 << *port_lsb_ << "''." << endl;
593 des->errors += 1;
594 return 0;
597 delete texpr;
598 nmsb = pmsb;
599 nlsb = plsb;
601 if (!port_set_) assert(port_msb_ == 0 && port_lsb_ == 0);
602 if (port_msb_ == 0) assert(port_lsb_ == 0);
603 if (port_lsb_ == 0) assert(port_msb_ == 0);
605 /* If they exist get the net/etc. definition MSB and LSB */
606 if (net_set_ && net_msb_ != 0) {
607 NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
609 if (! eval_as_long(nmsb, texpr)) {
610 cerr << net_msb_->get_line() << ": error: "
611 "Unable to evaluate MSB constant expression ``"
612 << *net_msb_ << "''." << endl;
613 des->errors += 1;
614 return 0;
617 delete texpr;
619 texpr = elab_and_eval(des, scope, net_lsb_, -1);
621 if (! eval_as_long(nlsb, texpr)) {
622 cerr << net_lsb_->get_line() << ": error: "
623 "Unable to evaluate LSB constant expression ``"
624 << *net_lsb_ << "''." << endl;
625 des->errors += 1;
626 return 0;
629 delete texpr;
631 if (!net_set_) assert(net_msb_ == 0 && net_lsb_ == 0);
632 if (net_msb_ == 0) assert(net_lsb_ == 0);
633 if (net_lsb_ == 0) assert(net_msb_ == 0);
635 /* We have a port size error */
636 if (port_set_ && net_set_ && (pmsb != nmsb || plsb != nlsb)) {
638 /* Scalar port with a vector net/etc. definition */
639 if (port_msb_ == 0) {
640 if (!gn_io_range_error_flag) {
641 cerr << get_line()
642 << ": warning: Scalar port ``" << hname_
643 << "'' has a vectored net declaration ["
644 << nmsb << ":" << nlsb << "]." << endl;
645 } else {
646 cerr << get_line()
647 << ": error: Scalar port ``" << hname_
648 << "'' has a vectored net declaration ["
649 << nmsb << ":" << nlsb << "]." << endl;
650 des->errors += 1;
651 return 0;
655 /* Vectored port with a scalar net/etc. definition */
656 if (net_msb_ == 0) {
657 cerr << port_msb_->get_line()
658 << ": error: Vectored port ``"
659 << hname_ << "'' [" << pmsb << ":" << plsb
660 << "] has a scalar net declaration at "
661 << get_line() << "." << endl;
662 des->errors += 1;
663 return 0;
666 /* Both vectored, but they have different ranges. */
667 if (port_msb_ != 0 && net_msb_ != 0) {
668 cerr << port_msb_->get_line()
669 << ": error: Vectored port ``"
670 << hname_ << "'' [" << pmsb << ":" << plsb
671 << "] has a net declaration [" << nmsb << ":"
672 << nlsb << "] at " << net_msb_->get_line()
673 << " that does not match." << endl;
674 des->errors += 1;
675 return 0;
679 lsb = nlsb;
680 msb = nmsb;
681 if (nmsb > nlsb)
682 wid = nmsb - nlsb + 1;
683 else
684 wid = nlsb - nmsb + 1;
689 unsigned nattrib = 0;
690 attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
691 des, scope);
693 long array_s0 = 0;
694 long array_e0 = 0;
695 unsigned array_dimensions = 0;
697 /* If the ident has idx expressions, then this is a
698 memory. It can only have the idx registers after the msb
699 and lsb expressions are filled. And, if it has one index,
700 it has both. */
701 if (lidx_ || ridx_) {
702 assert(lidx_ && ridx_);
704 NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
705 NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
707 if ((lexp == 0) || (rexp == 0)) {
708 cerr << get_line() << ": internal error: There is "
709 << "a problem evaluating indices for ``"
710 << hname_ << "''." << endl;
711 des->errors += 1;
712 return 0;
715 NetEConst*lcon = dynamic_cast<NetEConst*> (lexp);
716 NetEConst*rcon = dynamic_cast<NetEConst*> (rexp);
718 if ((lcon == 0) || (rcon == 0)) {
719 cerr << get_line() << ": internal error: The indices "
720 << "are not constant for array ``"
721 << hname_ << "''." << endl;
722 des->errors += 1;
723 return 0;
726 verinum lval = lcon->value();
727 verinum rval = rcon->value();
729 delete lexp;
730 delete rexp;
732 array_dimensions = 1;
733 array_s0 = lval.as_long();
734 array_e0 = rval.as_long();
737 /* If the net type is supply0 or supply1, replace it
738 with a simple wire with a pulldown/pullup with supply
739 strength. In other words, transform:
741 supply0 foo;
745 wire foo;
746 pulldown #(supply0) (foo);
748 This reduces the backend burden, and behaves exactly
749 the same. */
751 NetLogic*pull = 0;
752 if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
753 NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
754 ? NetLogic::PULLUP
755 : NetLogic::PULLDOWN;
756 pull = new NetLogic(scope, scope->local_symbol(),
757 1, pull_type, wid);
758 pull->set_line(*this);
759 pull->pin(0).drive0(Link::SUPPLY);
760 pull->pin(0).drive1(Link::SUPPLY);
761 des->add_node(pull);
762 wtype = NetNet::WIRE;
764 if (debug_elaborate) {
765 cerr << get_line() << ": debug: "
766 << "Generate a SUPPLY pulldown for the "
767 << "supply0 net." << endl;
771 perm_string name = peek_tail_name(hname_);
772 if (debug_elaborate) {
773 cerr << get_line() << ": debug: Create signal "
774 << wtype << " ["<<msb<<":"<<lsb<<"] " << name
775 << " in scope " << scope_path(scope) << endl;
779 NetNet*sig = array_dimensions > 0
780 ? new NetNet(scope, name, wtype, msb, lsb, array_s0, array_e0)
781 : new NetNet(scope, name, wtype, msb, lsb);
783 ivl_variable_type_t use_data_type = data_type_;
784 if (use_data_type == IVL_VT_NO_TYPE) {
785 use_data_type = IVL_VT_LOGIC;
786 if (debug_elaborate) {
787 cerr << get_line() << ": debug: "
788 << "Signal " << name
789 << " in scope " << scope_path(scope)
790 << " defaults to data type " << use_data_type << endl;
794 sig->data_type(use_data_type);
795 sig->set_line(*this);
796 sig->port_type(port_type_);
797 sig->set_signed(get_signed());
798 sig->set_isint(get_isint());
800 if (pull)
801 connect(sig->pin(0), pull->pin(0));
803 for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
804 sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
806 return sig;