2 * Copyright (c) 2000-2008 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)
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
25 # include <stdio.h> // sprintf()
26 # include "compiler.h"
34 #if defined(__WIN32__)
36 inline ivl_dll_t
ivl_dlopen(const char *name
)
38 ivl_dll_t res
= (ivl_dll_t
) LoadLibrary(name
);
43 inline void * ivl_dlsym(ivl_dll_t dll
, const char *nm
)
46 return (void*)GetProcAddress((HMODULE
)dll
, nm
);
49 inline void ivl_dlclose(ivl_dll_t dll
)
51 FreeLibrary((HMODULE
)dll
);
54 const char *dlerror(void)
57 unsigned long err
= GetLastError();
59 FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
,
62 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), // Default language
69 #elif defined(HAVE_DLFCN_H)
70 inline ivl_dll_t
ivl_dlopen(const char*name
)
71 { return dlopen(name
,RTLD_LAZY
); }
73 inline void* ivl_dlsym(ivl_dll_t dll
, const char*nm
)
75 void*sym
= dlsym(dll
, nm
);
76 /* Not found? try without the leading _ */
77 if (sym
== 0 && nm
[0] == '_')
78 sym
= dlsym(dll
, nm
+1);
82 inline void ivl_dlclose(ivl_dll_t dll
)
85 #elif defined(HAVE_DL_H)
86 inline ivl_dll_t
ivl_dlopen(const char*name
)
87 { return shl_load(name
, BIND_IMMEDIATE
, 0); }
89 inline void* ivl_dlsym(ivl_dll_t dll
, const char*nm
)
92 int rc
= shl_findsym(&dll
, nm
, TYPE_PROCEDURE
, &sym
);
93 return (rc
== 0) ? sym
: 0;
96 inline void ivl_dlclose(ivl_dll_t dll
)
99 inline const char*dlerror(void)
100 { return strerror( errno
); }
104 * The custom new operator for the ivl_nexus_s type allows us to
105 * allocate nexus objects in blocks. There are generally lots of them
106 * permanently allocated, and allocating them in blocks reduces the
107 * allocation overhead.
109 static struct ivl_nexus_s
* nexus_pool_ptr
= 0;
110 static int nexus_pool_remaining
= 0;
111 static const size_t NEXUS_POOL_SIZE
= 4096;
113 void* ivl_nexus_s::operator new(size_t s
)
115 assert(s
== sizeof(struct ivl_nexus_s
));
116 if (nexus_pool_remaining
<= 0) {
117 nexus_pool_ptr
= new struct ivl_nexus_s
[NEXUS_POOL_SIZE
];
118 nexus_pool_remaining
= NEXUS_POOL_SIZE
;
121 struct ivl_nexus_s
*tmp
= nexus_pool_ptr
;
123 nexus_pool_remaining
-= 1;
128 inline static const char *basename(ivl_scope_t scope
, const char *inst
)
130 inst
+= strlen(ivl_scope_name(scope
));
131 assert(*inst
== '.');
135 static perm_string
make_scope_name(const hname_t
&name
)
137 if (! name
.has_number())
138 return name
.peek_name();
141 snprintf(buf
, sizeof buf
, "%s[%d]",
142 name
.peek_name().str(), name
.peek_number());
143 return lex_strings
.make(buf
);
146 static struct dll_target dll_target_obj
;
148 static void drive_from_link(const Link
&lnk
, ivl_drive_t
&drv0
, ivl_drive_t
&drv1
)
150 switch (lnk
.drive0()) {
161 drv0
= IVL_DR_STRONG
;
164 drv0
= IVL_DR_SUPPLY
;
168 switch (lnk
.drive1()) {
179 drv1
= IVL_DR_STRONG
;
182 drv1
= IVL_DR_SUPPLY
;
187 ivl_attribute_s
* dll_target::fill_in_attributes(const Attrib
*net
)
189 ivl_attribute_s
*attr
;
190 unsigned nattr
= net
->attr_cnt();
195 attr
= new struct ivl_attribute_s
[nattr
];
197 for (unsigned idx
= 0 ; idx
< nattr
; idx
+= 1) {
198 verinum tmp
= net
->attr_value(idx
);
199 attr
[idx
].key
= net
->attr_key(idx
);
200 if (tmp
.is_string()) {
201 attr
[idx
].type
= IVL_ATT_STR
;
202 attr
[idx
].val
.str
= strings_
.add(tmp
.as_string().c_str());
204 } else if (tmp
== verinum()) {
205 attr
[idx
].type
= IVL_ATT_VOID
;
208 attr
[idx
].type
= IVL_ATT_NUM
;
209 attr
[idx
].val
.num
= tmp
.as_long();
217 * This function locates an ivl_scope_t object that matches the
218 * NetScope object. The search works by looking for the parent scope,
219 * then scanning the parent scope for the NetScope object.
221 static ivl_scope_t
find_scope_from_root(ivl_scope_t root
, const NetScope
*cur
)
223 ivl_scope_t parent
, tmp
;
224 perm_string cur_name
= make_scope_name(cur
->fullname());
226 if (const NetScope
*par
= cur
->parent()) {
227 parent
= find_scope_from_root(root
, par
);
231 for (tmp
= parent
->child_
; tmp
; tmp
= tmp
->sibling_
)
232 if (strcmp(tmp
->name_
, cur_name
) == 0)
236 if (strcmp(root
->name_
, cur_name
) == 0)
243 ivl_scope_t
dll_target::find_scope(ivl_design_s
&des
, const NetScope
*cur
)
247 ivl_scope_t scope
= 0;
248 for (unsigned i
= 0; i
< des
.nroots_
&& scope
== 0; i
+= 1) {
249 assert(des
.roots_
[i
]);
250 scope
= find_scope_from_root(des
.roots_
[i
], cur
);
255 ivl_scope_t
dll_target::lookup_scope_(const NetScope
*cur
)
257 return find_scope(des_
, cur
);
261 * This is a convenience function to locate an ivl_signal_t object
262 * given the NetESignal that has the signal name.
264 ivl_signal_t
dll_target::find_signal(ivl_design_s
&des
, const NetNet
*net
)
266 ivl_scope_t scope
= find_scope(des
, net
->scope());
269 perm_string nname
= net
->name();
271 for (unsigned idx
= 0 ; idx
< scope
->nsigs_
; idx
+= 1) {
272 if (strcmp(scope
->sigs_
[idx
]->name_
, nname
) == 0)
273 return scope
->sigs_
[idx
];
280 static ivl_nexus_t
nexus_sig_make(ivl_signal_t net
, unsigned pin
)
282 ivl_nexus_t tmp
= new struct ivl_nexus_s
;
283 tmp
->private_data
= 0;
285 tmp
->ptrs_
= (struct ivl_nexus_ptr_s
*)
286 malloc(sizeof(struct ivl_nexus_ptr_s
));
287 tmp
->ptrs_
[0].pin_
= pin
;
288 tmp
->ptrs_
[0].type_
= __NEXUS_PTR_SIG
;
289 tmp
->ptrs_
[0].l
.sig
= net
;
291 ivl_drive_t drive
= IVL_DR_HiZ
;
292 switch (ivl_signal_type(net
)) {
294 drive
= IVL_DR_STRONG
;
299 tmp
->ptrs_
[0].drive0
= drive
;
300 tmp
->ptrs_
[0].drive1
= drive
;
305 static void nexus_sig_add(ivl_nexus_t nex
, ivl_signal_t net
, unsigned pin
)
307 unsigned top
= nex
->nptr_
+ 1;
308 nex
->ptrs_
= (struct ivl_nexus_ptr_s
*)
309 realloc(nex
->ptrs_
, top
* sizeof(struct ivl_nexus_ptr_s
));
312 ivl_drive_t drive
= IVL_DR_HiZ
;
313 switch (ivl_signal_type(net
)) {
315 drive
= IVL_DR_STRONG
;
321 nex
->ptrs_
[top
-1].type_
= __NEXUS_PTR_SIG
;
322 nex
->ptrs_
[top
-1].drive0
= drive
;
323 nex
->ptrs_
[top
-1].drive1
= drive
;
324 nex
->ptrs_
[top
-1].pin_
= pin
;
325 nex
->ptrs_
[top
-1].l
.sig
= net
;
329 * Add the pin of the logic object to the nexus, and return the nexus
330 * pointer used for the pin.
332 * NOTE: This pointer is only valid until another pin is added to the
335 static ivl_nexus_ptr_t
nexus_log_add(ivl_nexus_t nex
,
339 unsigned top
= nex
->nptr_
+ 1;
340 nex
->ptrs_
= (struct ivl_nexus_ptr_s
*)
341 realloc(nex
->ptrs_
, top
* sizeof(struct ivl_nexus_ptr_s
));
344 nex
->ptrs_
[top
-1].type_
= __NEXUS_PTR_LOG
;
345 nex
->ptrs_
[top
-1].drive0
= (pin
== 0)? IVL_DR_STRONG
: IVL_DR_HiZ
;
346 nex
->ptrs_
[top
-1].drive1
= (pin
== 0)? IVL_DR_STRONG
: IVL_DR_HiZ
;
347 nex
->ptrs_
[top
-1].pin_
= pin
;
348 nex
->ptrs_
[top
-1].l
.log
= net
;
350 return nex
->ptrs_
+ top
- 1;
353 static void nexus_con_add(ivl_nexus_t nex
, ivl_net_const_t net
, unsigned pin
,
354 ivl_drive_t drive0
, ivl_drive_t drive1
)
356 unsigned top
= nex
->nptr_
+ 1;
357 nex
->ptrs_
= (struct ivl_nexus_ptr_s
*)
358 realloc(nex
->ptrs_
, top
* sizeof(struct ivl_nexus_ptr_s
));
361 nex
->ptrs_
[top
-1].type_
= __NEXUS_PTR_CON
;
362 nex
->ptrs_
[top
-1].drive0
= drive0
;
363 nex
->ptrs_
[top
-1].drive1
= drive1
;
364 nex
->ptrs_
[top
-1].pin_
= pin
;
365 nex
->ptrs_
[top
-1].l
.con
= net
;
368 static void nexus_lpm_add(ivl_nexus_t nex
, ivl_lpm_t net
, unsigned pin
,
369 ivl_drive_t drive0
, ivl_drive_t drive1
)
371 unsigned top
= nex
->nptr_
+ 1;
372 nex
->ptrs_
= (struct ivl_nexus_ptr_s
*)
373 realloc(nex
->ptrs_
, top
* sizeof(struct ivl_nexus_ptr_s
));
376 nex
->ptrs_
[top
-1].type_
= __NEXUS_PTR_LPM
;
377 nex
->ptrs_
[top
-1].drive0
= drive0
;
378 nex
->ptrs_
[top
-1].drive1
= drive0
;
379 nex
->ptrs_
[top
-1].pin_
= pin
;
380 nex
->ptrs_
[top
-1].l
.lpm
= net
;
384 void scope_add_logic(ivl_scope_t scope
, ivl_net_logic_t net
)
386 if (scope
->nlog_
== 0) {
388 scope
->log_
= (ivl_net_logic_t
*)malloc(sizeof(ivl_net_logic_t
));
389 scope
->log_
[0] = net
;
393 scope
->log_
= (ivl_net_logic_t
*)
394 realloc(scope
->log_
, scope
->nlog_
*sizeof(ivl_net_logic_t
));
395 scope
->log_
[scope
->nlog_
-1] = net
;
400 void scope_add_event(ivl_scope_t scope
, ivl_event_t net
)
402 if (scope
->nevent_
== 0) {
404 scope
->event_
= (ivl_event_t
*)malloc(sizeof(ivl_event_t
));
405 scope
->event_
[0] = net
;
409 scope
->event_
= (ivl_event_t
*)
410 realloc(scope
->event_
, scope
->nevent_
*sizeof(ivl_event_t
));
411 scope
->event_
[scope
->nevent_
-1] = net
;
416 static void scope_add_lpm(ivl_scope_t scope
, ivl_lpm_t net
)
418 if (scope
->nlpm_
== 0) {
419 assert(scope
->lpm_
== 0);
421 scope
->lpm_
= (ivl_lpm_t
*)malloc(sizeof(ivl_lpm_t
));
422 scope
->lpm_
[0] = net
;
427 scope
->lpm_
= (ivl_lpm_t
*)
429 scope
->nlpm_
*sizeof(ivl_lpm_t
));
430 scope
->lpm_
[scope
->nlpm_
-1] = net
;
434 ivl_parameter_t
dll_target::scope_find_param(ivl_scope_t scope
,
438 while (idx
< scope
->nparam_
) {
439 if (strcmp(name
, scope
->param_
[idx
].basename
) == 0)
440 return scope
->param_
+ idx
;
449 * This method scans the parameters of the scope, and makes
450 * ivl_parameter_t objects. This involves saving the name and scanning
451 * the expression value.
453 void dll_target::make_scope_parameters(ivl_scope_t scope
, const NetScope
*net
)
455 scope
->nparam_
= net
->parameters
.size() + net
->localparams
.size();
456 if (scope
->nparam_
== 0) {
461 scope
->param_
= new struct ivl_parameter_s
[scope
->nparam_
];
464 typedef map
<perm_string
,NetScope::param_expr_t
>::const_iterator pit_t
;
466 for (pit_t cur_pit
= net
->parameters
.begin()
467 ; cur_pit
!= net
->parameters
.end() ; cur_pit
++) {
469 assert(idx
< scope
->nparam_
);
470 ivl_parameter_t cur_par
= scope
->param_
+ idx
;
471 cur_par
->basename
= (*cur_pit
).first
;
472 cur_par
->scope
= scope
;
473 cur_par
->file
= (*cur_pit
).second
.file
;
474 cur_par
->lineno
= (*cur_pit
).second
.lineno
;
476 NetExpr
*etmp
= (*cur_pit
).second
.expr
;
477 make_scope_param_expr(cur_par
, etmp
);
480 for (pit_t cur_pit
= net
->localparams
.begin()
481 ; cur_pit
!= net
->localparams
.end() ; cur_pit
++) {
483 assert(idx
< scope
->nparam_
);
484 ivl_parameter_t cur_par
= scope
->param_
+ idx
;
485 cur_par
->basename
= (*cur_pit
).first
;
486 cur_par
->scope
= scope
;
487 cur_par
->file
= (*cur_pit
).second
.file
;
488 cur_par
->lineno
= (*cur_pit
).second
.lineno
;
490 NetExpr
*etmp
= (*cur_pit
).second
.expr
;
491 make_scope_param_expr(cur_par
, etmp
);
496 void dll_target::make_scope_param_expr(ivl_parameter_t cur_par
, NetExpr
*etmp
)
498 if (const NetEConst
*e
= dynamic_cast<const NetEConst
*>(etmp
)) {
503 switch (expr_
->type_
) {
505 expr_
->u_
.string_
.parameter
= cur_par
;
508 expr_
->u_
.number_
.parameter
= cur_par
;
514 } else if (const NetECReal
*e
= dynamic_cast<const NetECReal
*>(etmp
)) {
518 assert(expr_
->type_
== IVL_EX_REALNUM
);
519 expr_
->u_
.real_
.parameter
= cur_par
;
523 cur_par
->value
= expr_
;
527 void dll_target::add_root(ivl_design_s
&des_
, const NetScope
*s
)
529 ivl_scope_t root_
= new struct ivl_scope_s
;
530 perm_string name
= s
->basename();
545 make_scope_parameters(root_
, s
);
546 root_
->type_
= IVL_SCT_MODULE
;
547 root_
->tname_
= root_
->name_
;
548 root_
->time_precision
= s
->time_precision();
549 root_
->time_units
= s
->time_unit();
550 root_
->nattr
= s
->attr_cnt();
551 root_
->attr
= fill_in_attributes(s
);
555 des_
.roots_
= (ivl_scope_t
*)realloc(des_
.roots_
, des_
.nroots_
* sizeof(ivl_scope_t
));
557 des_
.roots_
= (ivl_scope_t
*)malloc(des_
.nroots_
* sizeof(ivl_scope_t
));
558 des_
.roots_
[des_
.nroots_
- 1] = root_
;
561 bool dll_target::start_design(const Design
*des
)
563 list
<NetScope
*> root_scopes
;
564 const char*dll_path_
= des
->get_flag("DLL");
566 dll_
= ivl_dlopen(dll_path_
);
568 if ((dll_
== 0) && (dll_path_
[0] != '/')) {
569 size_t len
= strlen(basedir
) + 1 + strlen(dll_path_
) + 1;
570 char*tmp
= new char[len
];
571 sprintf(tmp
, "%s/%s", basedir
, dll_path_
);
572 dll_
= ivl_dlopen(tmp
);
577 cerr
<< "error: " << dll_path_
<< " failed to load." << endl
;
578 cerr
<< dll_path_
<< ": " << dlerror() << endl
;
584 // Initialize the design object.
586 des_
.time_precision
= des
->get_precision();
590 root_scopes
= des
->find_root_scopes();
591 for (list
<NetScope
*>::const_iterator scope
= root_scopes
.begin();
592 scope
!= root_scopes
.end(); scope
++)
593 add_root(des_
, *scope
);
595 des_
.consts
= (ivl_net_const_t
*)
596 malloc(sizeof(ivl_net_const_t
));
599 target_
= (target_design_f
)ivl_dlsym(dll_
, LU
"target_design" TU
);
601 cerr
<< dll_path_
<< ": error: target_design entry "
602 "point is missing." << endl
;
610 * Here ivl is telling us that the design is scanned completely, and
611 * here is where we call the API to process the constructed design.
613 int dll_target::end_design(const Design
*)
616 cout
<< " ... invoking target_design" << endl
;
619 int rc
= (target_
)(&des_
);
624 void dll_target::logic_attributes(struct ivl_net_logic_s
*obj
,
627 obj
->nattr
= net
->attr_cnt();
628 obj
->attr
= fill_in_attributes(net
);
631 void dll_target::make_logic_delays_(struct ivl_net_logic_s
*obj
,
638 /* Translate delay expressions to ivl_target form. Try to
639 preserve pointer equality, not as a rule but to save on
641 if (net
->rise_time()) {
643 net
->rise_time()->expr_scan(this);
644 obj
->delay
[0] = expr_
;
647 if (net
->fall_time()) {
648 if (net
->fall_time() == net
->rise_time()) {
649 obj
->delay
[1] = obj
->delay
[0];
652 net
->fall_time()->expr_scan(this);
653 obj
->delay
[1] = expr_
;
657 if (net
->decay_time()) {
658 if (net
->decay_time() == net
->rise_time()) {
659 obj
->delay
[2] = obj
->delay
[0];
662 net
->decay_time()->expr_scan(this);
663 obj
->delay
[2] = expr_
;
669 void dll_target::make_lpm_delays_(struct ivl_lpm_s
*obj
,
676 /* Translate delay expressions to ivl_target form. Try to
677 preserve pointer equality, not as a rule but to save on
679 if (net
->rise_time()) {
681 net
->rise_time()->expr_scan(this);
682 obj
->delay
[0] = expr_
;
685 if (net
->fall_time()) {
686 if (net
->fall_time() == net
->rise_time()) {
687 obj
->delay
[1] = obj
->delay
[0];
690 net
->fall_time()->expr_scan(this);
691 obj
->delay
[1] = expr_
;
695 if (net
->decay_time()) {
696 if (net
->decay_time() == net
->rise_time()) {
697 obj
->delay
[2] = obj
->delay
[0];
700 net
->decay_time()->expr_scan(this);
701 obj
->delay
[2] = expr_
;
707 void dll_target::make_const_delays_(struct ivl_net_const_s
*obj
,
714 /* Translate delay expressions to ivl_target form. Try to
715 preserve pointer equality, not as a rule but to save on
717 if (net
->rise_time()) {
719 net
->rise_time()->expr_scan(this);
720 obj
->delay
[0] = expr_
;
723 if (net
->fall_time()) {
724 if (net
->fall_time() == net
->rise_time()) {
725 obj
->delay
[1] = obj
->delay
[0];
728 net
->fall_time()->expr_scan(this);
729 obj
->delay
[1] = expr_
;
733 if (net
->decay_time()) {
734 if (net
->decay_time() == net
->rise_time()) {
735 obj
->delay
[2] = obj
->delay
[0];
738 net
->decay_time()->expr_scan(this);
739 obj
->delay
[2] = expr_
;
746 * Add a bufz object to the scope that contains it.
748 * Note that in the ivl_target API a BUFZ device is a special kind of
749 * ivl_net_logic_t device, so create an ivl_net_logic_t cookie to
752 bool dll_target::bufz(const NetBUFZ
*net
)
754 struct ivl_net_logic_s
*obj
= new struct ivl_net_logic_s
;
756 assert(net
->pin_count() == 2);
758 obj
->type_
= IVL_LO_BUFZ
;
759 obj
->width_
= net
->width();
761 obj
->pins_
= new ivl_nexus_t
[2];
763 /* Get the ivl_nexus_t objects connected to the two pins.
765 (We know a priori that the ivl_nexus_t objects have been
766 allocated, because the signals have been scanned before
767 me. This saves me the trouble of allocating them.) */
769 assert(net
->pin(0).nexus()->t_cookie());
770 obj
->pins_
[0] = net
->pin(0).nexus()->t_cookie();
771 ivl_nexus_ptr_t out_ptr
= nexus_log_add(obj
->pins_
[0], obj
, 0);
774 switch (net
->pin(0).drive0()) {
776 out_ptr
->drive0
= IVL_DR_HiZ
;
779 out_ptr
->drive0
= IVL_DR_WEAK
;
782 out_ptr
->drive0
= IVL_DR_PULL
;
785 out_ptr
->drive0
= IVL_DR_STRONG
;
788 out_ptr
->drive0
= IVL_DR_SUPPLY
;
792 switch (net
->pin(0).drive1()) {
794 out_ptr
->drive1
= IVL_DR_HiZ
;
797 out_ptr
->drive1
= IVL_DR_WEAK
;
800 out_ptr
->drive1
= IVL_DR_PULL
;
803 out_ptr
->drive1
= IVL_DR_STRONG
;
806 out_ptr
->drive1
= IVL_DR_SUPPLY
;
810 assert(net
->pin(1).nexus()->t_cookie());
811 obj
->pins_
[1] = net
->pin(1).nexus()->t_cookie();
812 nexus_log_add(obj
->pins_
[1], obj
, 1);
814 /* Attach the logic device to the scope that contains it. */
816 assert(net
->scope());
817 ivl_scope_t scope
= find_scope(des_
, net
->scope());
822 obj
->name_
= net
->name();
823 logic_attributes(obj
, net
);
825 make_logic_delays_(obj
, net
);
827 scope_add_logic(scope
, obj
);
832 void dll_target::event(const NetEvent
*net
)
834 struct ivl_event_s
*obj
= new struct ivl_event_s
;
836 ivl_scope_t scope
= find_scope(des_
, net
->scope());
837 obj
->name
= net
->name();
839 scope_add_event(scope
, obj
);
845 if (net
->nprobe() >= 1) {
847 for (unsigned idx
= 0 ; idx
< net
->nprobe() ; idx
+= 1) {
848 const NetEvProbe
*pr
= net
->probe(idx
);
849 switch (pr
->edge()) {
850 case NetEvProbe::ANYEDGE
:
851 obj
->nany
+= pr
->pin_count();
853 case NetEvProbe::NEGEDGE
:
854 obj
->nneg
+= pr
->pin_count();
856 case NetEvProbe::POSEDGE
:
857 obj
->npos
+= pr
->pin_count();
862 unsigned npins
= obj
->nany
+ obj
->nneg
+ obj
->npos
;
863 obj
->pins
= (ivl_nexus_t
*)calloc(npins
, sizeof(ivl_nexus_t
));
871 void dll_target::logic(const NetLogic
*net
)
873 struct ivl_net_logic_s
*obj
= new struct ivl_net_logic_s
;
875 obj
->width_
= net
->width();
877 switch (net
->type()) {
879 obj
->type_
= IVL_LO_AND
;
882 obj
->type_
= IVL_LO_BUF
;
884 case NetLogic::BUFIF0
:
885 obj
->type_
= IVL_LO_BUFIF0
;
887 case NetLogic::BUFIF1
:
888 obj
->type_
= IVL_LO_BUFIF1
;
891 obj
->type_
= IVL_LO_CMOS
;
894 obj
->type_
= IVL_LO_NAND
;
897 obj
->type_
= IVL_LO_NMOS
;
900 obj
->type_
= IVL_LO_NOR
;
903 obj
->type_
= IVL_LO_NOT
;
905 case NetLogic::NOTIF0
:
906 obj
->type_
= IVL_LO_NOTIF0
;
908 case NetLogic::NOTIF1
:
909 obj
->type_
= IVL_LO_NOTIF1
;
912 obj
->type_
= IVL_LO_OR
;
914 case NetLogic::PULLDOWN
:
915 obj
->type_
= IVL_LO_PULLDOWN
;
917 case NetLogic::PULLUP
:
918 obj
->type_
= IVL_LO_PULLUP
;
920 case NetLogic::RCMOS
:
921 obj
->type_
= IVL_LO_RCMOS
;
923 case NetLogic::RNMOS
:
924 obj
->type_
= IVL_LO_RNMOS
;
926 case NetLogic::RPMOS
:
927 obj
->type_
= IVL_LO_RPMOS
;
930 obj
->type_
= IVL_LO_PMOS
;
933 obj
->type_
= IVL_LO_XNOR
;
936 obj
->type_
= IVL_LO_XOR
;
940 obj
->type_
= IVL_LO_NONE
;
944 /* Connect all the ivl_nexus_t objects to the pins of the
947 obj
->npins_
= net
->pin_count();
948 obj
->pins_
= new ivl_nexus_t
[obj
->npins_
];
950 ivl_nexus_ptr_t out_ptr
= 0;
952 for (unsigned idx
= 0 ; idx
< obj
->npins_
; idx
+= 1) {
953 const Nexus
*nex
= net
->pin(idx
).nexus();
954 assert(nex
->t_cookie());
955 obj
->pins_
[idx
] = nex
->t_cookie();
956 ivl_nexus_ptr_t tmp
= nexus_log_add(obj
->pins_
[idx
], obj
, idx
);
961 switch (net
->pin(0).drive0()) {
963 out_ptr
->drive0
= IVL_DR_HiZ
;
966 out_ptr
->drive0
= IVL_DR_WEAK
;
969 out_ptr
->drive0
= IVL_DR_PULL
;
972 out_ptr
->drive0
= IVL_DR_STRONG
;
975 out_ptr
->drive0
= IVL_DR_SUPPLY
;
979 switch (net
->pin(0).drive1()) {
981 out_ptr
->drive1
= IVL_DR_HiZ
;
984 out_ptr
->drive1
= IVL_DR_WEAK
;
987 out_ptr
->drive1
= IVL_DR_PULL
;
990 out_ptr
->drive1
= IVL_DR_STRONG
;
993 out_ptr
->drive1
= IVL_DR_SUPPLY
;
997 assert(net
->scope());
998 ivl_scope_t scope
= find_scope(des_
, net
->scope());
1002 obj
->name_
= net
->name();
1004 logic_attributes(obj
, net
);
1006 make_logic_delays_(obj
, net
);
1008 scope_add_logic(scope
, obj
);
1011 bool dll_target::sign_extend(const NetSignExtend
*net
)
1013 struct ivl_lpm_s
*obj
= new struct ivl_lpm_s
;
1014 obj
->type
= IVL_LPM_SIGN_EXT
;
1015 obj
->width
= net
->width();
1016 obj
->name
= net
->name();
1017 obj
->scope
= find_scope(des_
, net
->scope());
1022 nex
= net
->pin(0).nexus();
1023 assert(nex
->t_cookie());
1025 obj
->u_
.reduce
.q
= nex
->t_cookie();
1026 nexus_lpm_add(obj
->u_
.reduce
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1028 nex
= net
->pin(1).nexus();
1029 assert(nex
->t_cookie());
1031 obj
->u_
.reduce
.a
= nex
->t_cookie();
1032 nexus_lpm_add(obj
->u_
.reduce
.a
, obj
, 1, IVL_DR_HiZ
, IVL_DR_HiZ
);
1034 make_lpm_delays_(obj
, net
);
1036 scope_add_lpm(obj
->scope
, obj
);
1041 bool dll_target::ureduce(const NetUReduce
*net
)
1043 struct ivl_lpm_s
*obj
= new struct ivl_lpm_s
;
1044 switch (net
->type()) {
1045 case NetUReduce::NONE
:
1048 case NetUReduce::AND
:
1049 obj
->type
= IVL_LPM_RE_AND
;
1051 case NetUReduce::OR
:
1052 obj
->type
= IVL_LPM_RE_OR
;
1054 case NetUReduce::XOR
:
1055 obj
->type
= IVL_LPM_RE_XOR
;
1057 case NetUReduce::NAND
:
1058 obj
->type
= IVL_LPM_RE_NAND
;
1060 case NetUReduce::NOR
:
1061 obj
->type
= IVL_LPM_RE_NOR
;
1063 case NetUReduce::XNOR
:
1064 obj
->type
= IVL_LPM_RE_XNOR
;
1068 obj
->name
= net
->name();
1069 obj
->scope
= find_scope(des_
, net
->scope());
1072 obj
->width
= net
->width();
1076 nex
= net
->pin(0).nexus();
1077 assert(nex
->t_cookie());
1079 obj
->u_
.reduce
.q
= nex
->t_cookie();
1080 nexus_lpm_add(obj
->u_
.reduce
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1082 nex
= net
->pin(1).nexus();
1083 assert(nex
->t_cookie());
1085 obj
->u_
.reduce
.a
= nex
->t_cookie();
1086 nexus_lpm_add(obj
->u_
.reduce
.a
, obj
, 1, IVL_DR_HiZ
, IVL_DR_HiZ
);
1088 make_lpm_delays_(obj
, net
);
1090 scope_add_lpm(obj
->scope
, obj
);
1095 void dll_target::net_case_cmp(const NetCaseCmp
*net
)
1097 struct ivl_lpm_s
*obj
= new struct ivl_lpm_s
;
1098 obj
->type
= net
->eeq()? IVL_LPM_CMP_EEQ
: IVL_LPM_CMP_NEE
;
1099 obj
->name
= net
->name();
1100 obj
->scope
= find_scope(des_
, net
->scope());
1103 obj
->width
= net
->width();
1104 obj
->u_
.arith
.signed_flag
= 0;
1108 nex
= net
->pin(1).nexus();
1109 assert(nex
->t_cookie());
1111 obj
->u_
.arith
.a
= nex
->t_cookie();
1112 nexus_lpm_add(obj
->u_
.arith
.a
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1114 nex
= net
->pin(2).nexus();
1115 assert(nex
->t_cookie());
1117 obj
->u_
.arith
.b
= nex
->t_cookie();
1118 nexus_lpm_add(obj
->u_
.arith
.b
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1120 nex
= net
->pin(0).nexus();
1121 assert(nex
->t_cookie());
1123 obj
->u_
.arith
.q
= nex
->t_cookie();
1124 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1126 make_lpm_delays_(obj
, net
);
1128 scope_add_lpm(obj
->scope
, obj
);
1131 bool dll_target::net_sysfunction(const NetSysFunc
*net
)
1136 struct ivl_lpm_s
*obj
= new struct ivl_lpm_s
;
1137 obj
->type
= IVL_LPM_SFUNC
;
1138 FILE_NAME(obj
, net
);
1139 obj
->name
= net
->name();
1140 obj
->scope
= find_scope(des_
, net
->scope());
1143 obj
->u_
.sfunc
.ports
= net
->pin_count();
1145 assert(net
->pin_count() >= 1);
1146 obj
->width
= net
->vector_width();
1148 obj
->u_
.sfunc
.fun_name
= net
->func_name();
1150 obj
->u_
.sfunc
.pins
= new ivl_nexus_t
[net
->pin_count()];
1152 nex
= net
->pin(0).nexus();
1153 assert(nex
->t_cookie());
1155 obj
->u_
.sfunc
.pins
[0] = nex
->t_cookie();
1156 nexus_lpm_add(obj
->u_
.sfunc
.pins
[0], obj
, 0,
1157 IVL_DR_STRONG
, IVL_DR_STRONG
);
1159 for (idx
= 1 ; idx
< net
->pin_count() ; idx
+= 1) {
1160 nex
= net
->pin(idx
).nexus();
1161 assert(nex
->t_cookie());
1163 obj
->u_
.sfunc
.pins
[idx
] = nex
->t_cookie();
1164 nexus_lpm_add(obj
->u_
.sfunc
.pins
[idx
], obj
, 0,
1165 IVL_DR_HiZ
, IVL_DR_HiZ
);
1168 make_lpm_delays_(obj
, net
);
1170 scope_add_lpm(obj
->scope
, obj
);
1175 * An IVL_LPM_UFUNC represents a node in a combinational expression
1176 * that calls a user defined function. I create an LPM object that has
1177 * the right connections, and refers to the ivl_scope_t of the
1180 bool dll_target::net_function(const NetUserFunc
*net
)
1182 struct ivl_lpm_s
*obj
= new struct ivl_lpm_s
;
1183 obj
->type
= IVL_LPM_UFUNC
;
1184 obj
->name
= net
->name();
1185 obj
->scope
= find_scope(des_
, net
->scope());
1188 /* Get the definition of the function and save it. */
1189 const NetScope
*def
= net
->def();
1192 obj
->u_
.ufunc
.def
= lookup_scope_(def
);
1194 /* Save information about the ports in the ivl_lpm_s
1195 structure. Note that port 0 is the return value. */
1196 obj
->u_
.ufunc
.ports
= net
->pin_count();
1198 assert(net
->pin_count() >= 1);
1199 obj
->width
= net
->port_width(0);
1201 /* Now collect all the pins and connect them to the nexa of
1202 the net. The output pins have strong drive, and the
1203 remaining input pins are HiZ. */
1205 obj
->u_
.ufunc
.pins
= new ivl_nexus_t
[net
->pin_count()];
1207 for (unsigned idx
= 0 ; idx
< net
->pin_count() ; idx
+= 1) {
1208 const Nexus
*nex
= net
->pin(idx
).nexus();
1209 assert(nex
->t_cookie());
1210 ivl_nexus_t nn
= nex
->t_cookie();
1213 obj
->u_
.ufunc
.pins
[idx
] = nn
;
1214 ivl_drive_t drive
= idx
== 0 ? IVL_DR_STRONG
: IVL_DR_HiZ
;
1215 nexus_lpm_add(obj
->u_
.ufunc
.pins
[idx
], obj
, idx
, drive
, drive
);
1218 make_lpm_delays_(obj
, net
);
1220 /* All done. Add this LPM to the scope. */
1221 scope_add_lpm(obj
->scope
, obj
);
1226 void dll_target::udp(const NetUDP
*net
)
1228 struct ivl_net_logic_s
*obj
= new struct ivl_net_logic_s
;
1230 obj
->type_
= IVL_LO_UDP
;
1232 /* The NetUDP class hasn't learned about width yet, so we
1233 assume a width of 1. */
1236 static map
<perm_string
,ivl_udp_t
> udps
;
1239 if (udps
.find(net
->udp_name()) != udps
.end())
1241 u
= udps
[net
->udp_name()];
1245 u
= new struct ivl_udp_s
;
1246 u
->nrows
= net
->rows();
1247 u
->table
= (ivl_udp_s::ccharp_t
*)malloc((u
->nrows
+1)*sizeof(char*));
1249 u
->table
[u
->nrows
] = 0x0;
1250 u
->nin
= net
->nin();
1251 u
->sequ
= net
->is_sequential();
1253 u
->init
= net
->get_initial();
1256 u
->name
= net
->udp_name();
1260 if (net
->first(inp
, out
))
1263 string tt
= inp
+out
;
1264 u
->table
[i
++] = strings_
.add(tt
.c_str());
1265 } while (net
->next(inp
, out
));
1266 assert(i
==u
->nrows
);
1268 udps
[net
->udp_name()] = u
;
1273 // Some duplication of code here, see: dll_target::logic()
1275 /* Connect all the ivl_nexus_t objects to the pins of the
1278 obj
->npins_
= net
->pin_count();
1279 obj
->pins_
= new ivl_nexus_t
[obj
->npins_
];
1280 for (unsigned idx
= 0 ; idx
< obj
->npins_
; idx
+= 1) {
1281 const Nexus
*nex
= net
->pin(idx
).nexus();
1283 /* Skip unconnected input pins. These will take on HiZ
1284 values by the code generators. */
1285 if (nex
->t_cookie() == 0) {
1286 obj
->pins_
[idx
] = 0;
1290 assert(nex
->t_cookie());
1291 obj
->pins_
[idx
] = nex
->t_cookie();
1292 nexus_log_add(obj
->pins_
[idx
], obj
, idx
);
1295 assert(net
->scope());
1296 ivl_scope_t scope
= find_scope(des_
, net
->scope());
1300 obj
->name_
= net
->name();
1302 make_logic_delays_(obj
, net
);
1307 scope_add_logic(scope
, obj
);
1310 void dll_target::lpm_add_sub(const NetAddSub
*net
)
1312 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1313 if (net
->attribute(perm_string::literal("LPM_Direction")) == verinum("SUB"))
1314 obj
->type
= IVL_LPM_SUB
;
1316 obj
->type
= IVL_LPM_ADD
;
1317 obj
->name
= net
->name(); // NetAddSub names are permallocated.
1318 assert(net
->scope());
1319 obj
->scope
= find_scope(des_
, net
->scope());
1322 obj
->u_
.arith
.signed_flag
= 0;
1324 /* Choose the width of the adder. If the carry bit is
1325 connected, then widen the adder by one and plan on leaving
1326 the fake inputs unconnected. */
1327 obj
->width
= net
->width();
1328 if (net
->pin_Cout().is_linked()) {
1335 nex
= net
->pin_Result().nexus();
1336 assert(nex
->t_cookie());
1338 obj
->u_
.arith
.q
= nex
->t_cookie();
1339 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1341 nex
= net
->pin_DataA().nexus();
1342 assert(nex
->t_cookie());
1344 obj
->u_
.arith
.a
= nex
->t_cookie();
1345 nexus_lpm_add(obj
->u_
.arith
.a
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1347 nex
= net
->pin_DataB().nexus();
1348 assert(nex
->t_cookie());
1350 obj
->u_
.arith
.b
= nex
->t_cookie();
1351 nexus_lpm_add(obj
->u_
.arith
.b
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1353 /* If the carry output is connected, then connect the extra Q
1354 pin to the carry nexus and zero the a and b inputs. */
1355 if (net
->pin_Cout().is_linked()) {
1356 cerr
<< "XXXX: t-dll.cc: Forgot how to connect cout." << endl
;
1359 make_lpm_delays_(obj
, net
);
1361 scope_add_lpm(obj
->scope
, obj
);
1364 bool dll_target::lpm_array_dq(const NetArrayDq
*net
)
1366 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1367 obj
->type
= IVL_LPM_ARRAY
;
1368 obj
->name
= net
->name();
1369 obj
->u_
.array
.sig
= find_signal(des_
, net
->mem());
1370 assert(obj
->u_
.array
.sig
);
1371 obj
->scope
= find_scope(des_
, net
->scope());
1373 obj
->width
= net
->width();
1374 obj
->u_
.array
.swid
= net
->awidth();
1376 make_lpm_delays_(obj
, net
);
1378 scope_add_lpm(obj
->scope
, obj
);
1382 nex
= net
->pin_Address().nexus();
1383 assert(nex
->t_cookie());
1384 obj
->u_
.array
.a
= nex
->t_cookie();
1385 nexus_lpm_add(obj
->u_
.array
.a
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1387 nex
= net
->pin_Result().nexus();
1388 assert(nex
->t_cookie());
1389 obj
->u_
.array
.q
= nex
->t_cookie();
1390 nexus_lpm_add(obj
->u_
.array
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1396 * The lpm_clshift device represents both left and right shifts,
1397 * depending on what is connected to the Direction pin. We convert
1398 * this device into SHIFTL or SHIFTR devices.
1400 void dll_target::lpm_clshift(const NetCLShift
*net
)
1402 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1403 obj
->type
= IVL_LPM_SHIFTL
;
1404 obj
->name
= net
->name();
1405 assert(net
->scope());
1406 obj
->scope
= find_scope(des_
, net
->scope());
1409 /* Look at the direction input of the device, and select the
1410 shift direction accordingly. */
1411 if (net
->right_flag())
1412 obj
->type
= IVL_LPM_SHIFTR
;
1413 if (net
->signed_flag())
1414 obj
->u_
.shift
.signed_flag
= 1;
1416 obj
->u_
.shift
.signed_flag
= 0;
1418 obj
->width
= net
->width();
1419 obj
->u_
.shift
.select
= net
->width_dist();
1423 nex
= net
->pin_Result().nexus();
1424 assert(nex
->t_cookie());
1426 obj
->u_
.shift
.q
= nex
->t_cookie();
1427 nexus_lpm_add(obj
->u_
.shift
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1429 nex
= net
->pin_Data().nexus();
1430 assert(nex
->t_cookie());
1432 obj
->u_
.shift
.d
= nex
->t_cookie();
1433 nexus_lpm_add(obj
->u_
.shift
.d
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1435 nex
= net
->pin_Distance().nexus();
1436 assert(nex
->t_cookie());
1438 obj
->u_
.shift
.s
= nex
->t_cookie();
1439 nexus_lpm_add(obj
->u_
.shift
.s
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1441 make_lpm_delays_(obj
, net
);
1443 scope_add_lpm(obj
->scope
, obj
);
1447 * Make out of the NetCompare object an ivl_lpm_s object. The
1448 * comparators in ivl_target do not support < or <=, but they can be
1449 * trivially converted to > and >= by swapping the operands.
1451 void dll_target::lpm_compare(const NetCompare
*net
)
1453 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1454 obj
->name
= net
->name(); // NetCompare names are permallocated
1455 assert(net
->scope());
1456 obj
->scope
= find_scope(des_
, net
->scope());
1459 bool swap_operands
= false;
1461 obj
->width
= net
->width();
1462 obj
->u_
.arith
.signed_flag
= net
->get_signed()? 1 : 0;
1466 nex
= net
->pin_DataA().nexus();
1467 assert(nex
->t_cookie());
1469 obj
->u_
.arith
.a
= nex
->t_cookie();
1471 nex
= net
->pin_DataB().nexus();
1472 assert(nex
->t_cookie());
1474 obj
->u_
.arith
.b
= nex
->t_cookie();
1477 if (net
->pin_AGEB().is_linked()) {
1478 nex
= net
->pin_AGEB().nexus();
1479 obj
->type
= IVL_LPM_CMP_GE
;
1481 assert(nex
->t_cookie());
1482 obj
->u_
.arith
.q
= nex
->t_cookie();
1483 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0,
1484 IVL_DR_STRONG
, IVL_DR_STRONG
);
1486 } else if (net
->pin_AGB().is_linked()) {
1487 nex
= net
->pin_AGB().nexus();
1488 obj
->type
= IVL_LPM_CMP_GT
;
1490 assert(nex
->t_cookie());
1491 obj
->u_
.arith
.q
= nex
->t_cookie();
1492 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0,
1493 IVL_DR_STRONG
, IVL_DR_STRONG
);
1495 } else if (net
->pin_ALEB().is_linked()) {
1496 nex
= net
->pin_ALEB().nexus();
1497 obj
->type
= IVL_LPM_CMP_GE
;
1499 assert(nex
->t_cookie());
1500 obj
->u_
.arith
.q
= nex
->t_cookie();
1501 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0,
1502 IVL_DR_STRONG
, IVL_DR_STRONG
);
1504 swap_operands
= true;
1506 } else if (net
->pin_ALB().is_linked()) {
1507 nex
= net
->pin_ALB().nexus();
1508 obj
->type
= IVL_LPM_CMP_GT
;
1510 assert(nex
->t_cookie());
1511 obj
->u_
.arith
.q
= nex
->t_cookie();
1512 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0,
1513 IVL_DR_STRONG
, IVL_DR_STRONG
);
1515 swap_operands
= true;
1517 } else if (net
->pin_AEB().is_linked()) {
1518 nex
= net
->pin_AEB().nexus();
1519 obj
->type
= IVL_LPM_CMP_EQ
;
1521 assert(nex
->t_cookie());
1522 obj
->u_
.arith
.q
= nex
->t_cookie();
1523 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0,
1524 IVL_DR_STRONG
, IVL_DR_STRONG
);
1526 } else if (net
->pin_ANEB().is_linked()) {
1527 nex
= net
->pin_ANEB().nexus();
1528 obj
->type
= IVL_LPM_CMP_NE
;
1530 assert(nex
->t_cookie());
1531 obj
->u_
.arith
.q
= nex
->t_cookie();
1532 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0,
1533 IVL_DR_STRONG
, IVL_DR_STRONG
);
1539 if (swap_operands
) {
1540 ivl_nexus_t tmp
= obj
->u_
.arith
.a
;
1541 obj
->u_
.arith
.a
= obj
->u_
.arith
.b
;
1542 obj
->u_
.arith
.b
= tmp
;
1545 nexus_lpm_add(obj
->u_
.arith
.a
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1546 nexus_lpm_add(obj
->u_
.arith
.b
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1548 make_lpm_delays_(obj
, net
);
1550 scope_add_lpm(obj
->scope
, obj
);
1553 void dll_target::lpm_divide(const NetDivide
*net
)
1555 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1556 obj
->type
= IVL_LPM_DIVIDE
;
1557 obj
->name
= net
->name();
1558 assert(net
->scope());
1559 obj
->scope
= find_scope(des_
, net
->scope());
1562 unsigned wid
= net
->width_r();
1565 obj
->u_
.arith
.signed_flag
= net
->get_signed()? 1 : 0;
1569 nex
= net
->pin_Result().nexus();
1570 assert(nex
->t_cookie());
1572 obj
->u_
.arith
.q
= nex
->t_cookie();
1573 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1575 nex
= net
->pin_DataA().nexus();
1576 assert(nex
->t_cookie());
1578 obj
->u_
.arith
.a
= nex
->t_cookie();
1579 nexus_lpm_add(obj
->u_
.arith
.a
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1581 nex
= net
->pin_DataB().nexus();
1582 assert(nex
->t_cookie());
1584 obj
->u_
.arith
.b
= nex
->t_cookie();
1585 nexus_lpm_add(obj
->u_
.arith
.b
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1587 make_lpm_delays_(obj
, net
);
1589 scope_add_lpm(obj
->scope
, obj
);
1592 void dll_target::lpm_modulo(const NetModulo
*net
)
1594 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1595 obj
->type
= IVL_LPM_MOD
;
1596 obj
->name
= net
->name();
1597 assert(net
->scope());
1598 obj
->scope
= find_scope(des_
, net
->scope());
1601 unsigned wid
= net
->width_r();
1604 obj
->u_
.arith
.signed_flag
= 0;
1608 nex
= net
->pin_Result().nexus();
1609 assert(nex
->t_cookie());
1611 obj
->u_
.arith
.q
= nex
->t_cookie();
1612 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1614 nex
= net
->pin_DataA().nexus();
1615 assert(nex
->t_cookie());
1617 obj
->u_
.arith
.a
= nex
->t_cookie();
1618 nexus_lpm_add(obj
->u_
.arith
.a
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1620 nex
= net
->pin_DataB().nexus();
1621 assert(nex
->t_cookie());
1623 obj
->u_
.arith
.b
= nex
->t_cookie();
1624 nexus_lpm_add(obj
->u_
.arith
.b
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1626 make_lpm_delays_(obj
, net
);
1628 scope_add_lpm(obj
->scope
, obj
);
1631 void dll_target::lpm_ff(const NetFF
*net
)
1633 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1634 obj
->type
= IVL_LPM_FF
;
1635 obj
->name
= net
->name();
1636 obj
->scope
= find_scope(des_
, net
->scope());
1639 obj
->width
= net
->width();
1641 scope_add_lpm(obj
->scope
, obj
);
1645 /* Set the clk signal to point to the nexus, and the nexus to
1646 point back to this device. */
1647 nex
= net
->pin_Clock().nexus();
1648 assert(nex
->t_cookie());
1649 obj
->u_
.ff
.clk
= nex
->t_cookie();
1650 assert(obj
->u_
.ff
.clk
);
1651 nexus_lpm_add(obj
->u_
.ff
.clk
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1653 /* If there is a clock enable, then connect it up to the FF
1655 if (net
->pin_Enable().is_linked()) {
1656 nex
= net
->pin_Enable().nexus();
1657 assert(nex
->t_cookie());
1658 obj
->u_
.ff
.we
= nex
->t_cookie();
1659 assert(obj
->u_
.ff
.we
);
1660 nexus_lpm_add(obj
->u_
.ff
.we
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1665 if (net
->pin_Aclr().is_linked()) {
1666 nex
= net
->pin_Aclr().nexus();
1667 assert(nex
->t_cookie());
1668 obj
->u_
.ff
.aclr
= nex
->t_cookie();
1669 assert(obj
->u_
.ff
.aclr
);
1670 nexus_lpm_add(obj
->u_
.ff
.aclr
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1672 obj
->u_
.ff
.aclr
= 0;
1675 if (net
->pin_Aset().is_linked()) {
1676 nex
= net
->pin_Aset().nexus();
1677 assert(nex
->t_cookie());
1678 obj
->u_
.ff
.aset
= nex
->t_cookie();
1679 assert(obj
->u_
.ff
.aset
);
1680 nexus_lpm_add(obj
->u_
.ff
.aset
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1682 verinum tmp
= net
->aset_value();
1683 obj
->u_
.ff
.aset_value
= expr_from_value_(tmp
);
1686 obj
->u_
.ff
.aset
= 0;
1687 obj
->u_
.ff
.aset_value
= 0;
1690 if (net
->pin_Sclr().is_linked()) {
1691 nex
= net
->pin_Sclr().nexus();
1692 assert(nex
->t_cookie());
1693 obj
->u_
.ff
.sclr
= nex
->t_cookie();
1694 assert(obj
->u_
.ff
.sclr
);
1695 nexus_lpm_add(obj
->u_
.ff
.sclr
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1697 obj
->u_
.ff
.sclr
= 0;
1700 if (net
->pin_Sset().is_linked()) {
1701 nex
= net
->pin_Sset().nexus();
1702 assert(nex
->t_cookie());
1703 obj
->u_
.ff
.sset
= nex
->t_cookie();
1704 assert(obj
->u_
.ff
.sset
);
1705 nexus_lpm_add(obj
->u_
.ff
.sset
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1707 verinum tmp
= net
->sset_value();
1708 obj
->u_
.ff
.sset_value
= expr_from_value_(tmp
);
1711 obj
->u_
.ff
.sset
= 0;
1712 obj
->u_
.ff
.sset_value
= 0;
1715 nex
= net
->pin_Q().nexus();
1716 assert(nex
->t_cookie());
1717 obj
->u_
.ff
.q
.pin
= nex
->t_cookie();
1718 nexus_lpm_add(obj
->u_
.ff
.q
.pin
, obj
, 0,
1719 IVL_DR_STRONG
, IVL_DR_STRONG
);
1721 nex
= net
->pin_Data().nexus();
1722 assert(nex
->t_cookie());
1723 obj
->u_
.ff
.d
.pin
= nex
->t_cookie();
1724 nexus_lpm_add(obj
->u_
.ff
.d
.pin
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1729 * Make the NetMult object into an IVL_LPM_MULT node.
1731 void dll_target::lpm_mult(const NetMult
*net
)
1733 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1734 obj
->type
= IVL_LPM_MULT
;
1735 obj
->name
= net
->name();
1736 assert(net
->scope());
1737 obj
->scope
= find_scope(des_
, net
->scope());
1740 unsigned wid
= net
->width_r();
1746 nex
= net
->pin_Result().nexus();
1747 assert(nex
->t_cookie());
1749 obj
->u_
.arith
.q
= nex
->t_cookie();
1750 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1752 nex
= net
->pin_DataA().nexus();
1753 assert(nex
->t_cookie());
1755 obj
->u_
.arith
.a
= nex
->t_cookie();
1756 nexus_lpm_add(obj
->u_
.arith
.a
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1758 nex
= net
->pin_DataB().nexus();
1759 assert(nex
->t_cookie());
1761 obj
->u_
.arith
.b
= nex
->t_cookie();
1762 nexus_lpm_add(obj
->u_
.arith
.b
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1764 make_lpm_delays_(obj
, net
);
1766 scope_add_lpm(obj
->scope
, obj
);
1770 * Hook up the mux devices so that the select expression selects the
1771 * correct sub-expression with the ivl_lpm_data2 function.
1773 void dll_target::lpm_mux(const NetMux
*net
)
1775 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1776 obj
->type
= IVL_LPM_MUX
;
1777 obj
->name
= net
->name(); // The NetMux perallocates its name.
1778 obj
->scope
= find_scope(des_
, net
->scope());
1781 obj
->width
= net
->width();
1782 obj
->u_
.mux
.size
= net
->size();
1783 obj
->u_
.mux
.swid
= net
->sel_width();
1785 make_lpm_delays_(obj
, net
);
1787 scope_add_lpm(obj
->scope
, obj
);
1791 /* Connect the output bits. */
1792 nex
= net
->pin_Result().nexus();
1793 assert(nex
->t_cookie());
1794 obj
->u_
.mux
.q
= nex
->t_cookie();
1795 nexus_lpm_add(obj
->u_
.mux
.q
, obj
, 0,
1796 IVL_DR_STRONG
, IVL_DR_STRONG
);
1798 /* Connect the select bits. */
1799 nex
= net
->pin_Sel().nexus();
1800 assert(nex
->t_cookie());
1801 obj
->u_
.mux
.s
= nex
->t_cookie();
1802 nexus_lpm_add(obj
->u_
.mux
.s
, obj
, 0,
1803 IVL_DR_HiZ
, IVL_DR_HiZ
);
1805 unsigned selects
= obj
->u_
.mux
.size
;
1807 obj
->u_
.mux
.d
= new ivl_nexus_t
[selects
];
1809 for (unsigned sdx
= 0 ; sdx
< selects
; sdx
+= 1) {
1810 nex
= net
->pin_Data(sdx
).nexus();
1811 ivl_nexus_t tmp
= nex
->t_cookie();
1812 obj
->u_
.mux
.d
[sdx
] = tmp
;
1813 nexus_lpm_add(tmp
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1819 * Make the NetPow object into an IVL_LPM_POW node.
1821 void dll_target::lpm_pow(const NetPow
*net
)
1823 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1824 obj
->type
= IVL_LPM_POW
;
1825 FILE_NAME(obj
, net
);
1826 obj
->name
= net
->name();
1827 assert(net
->scope());
1828 obj
->scope
= find_scope(des_
, net
->scope());
1831 unsigned wid
= net
->width_r();
1832 obj
->u_
.arith
.signed_flag
= net
->get_signed()? 1 : 0;
1838 nex
= net
->pin_Result().nexus();
1839 assert(nex
->t_cookie());
1841 obj
->u_
.arith
.q
= nex
->t_cookie();
1842 nexus_lpm_add(obj
->u_
.arith
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1844 nex
= net
->pin_DataA().nexus();
1845 assert(nex
->t_cookie());
1847 obj
->u_
.arith
.a
= nex
->t_cookie();
1848 nexus_lpm_add(obj
->u_
.arith
.a
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1850 nex
= net
->pin_DataB().nexus();
1851 assert(nex
->t_cookie());
1853 obj
->u_
.arith
.b
= nex
->t_cookie();
1854 nexus_lpm_add(obj
->u_
.arith
.b
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1856 make_lpm_delays_(obj
, net
);
1858 scope_add_lpm(obj
->scope
, obj
);
1861 bool dll_target::concat(const NetConcat
*net
)
1863 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1864 obj
->type
= IVL_LPM_CONCAT
;
1865 obj
->name
= net
->name(); // NetConcat names are permallocated
1866 assert(net
->scope());
1867 obj
->scope
= find_scope(des_
, net
->scope());
1870 obj
->width
= net
->width();
1872 obj
->u_
.concat
.inputs
= net
->pin_count() - 1;
1873 obj
->u_
.concat
.pins
= new ivl_nexus_t
[obj
->u_
.concat
.inputs
+1];
1875 for (unsigned idx
= 0 ; idx
< obj
->u_
.concat
.inputs
+1 ; idx
+= 1) {
1876 ivl_drive_t dr
= idx
== 0? IVL_DR_STRONG
: IVL_DR_HiZ
;
1877 const Nexus
*nex
= net
->pin(idx
).nexus();
1878 assert(nex
->t_cookie());
1880 obj
->u_
.concat
.pins
[idx
] = nex
->t_cookie();
1881 nexus_lpm_add(obj
->u_
.concat
.pins
[idx
], obj
, 0, dr
, dr
);
1884 make_lpm_delays_(obj
, net
);
1886 scope_add_lpm(obj
->scope
, obj
);
1891 bool dll_target::part_select(const NetPartSelect
*net
)
1893 ivl_lpm_t obj
= new struct ivl_lpm_s
;
1894 switch (net
->dir()) {
1895 case NetPartSelect::VP
:
1896 obj
->type
= IVL_LPM_PART_VP
;
1898 case NetPartSelect::PV
:
1899 obj
->type
= IVL_LPM_PART_PV
;
1901 case NetPartSelect::BI
:
1902 obj
->type
= IVL_LPM_PART_BI
;
1905 obj
->name
= net
->name(); // NetPartSelect names are permallocated.
1906 assert(net
->scope());
1907 obj
->scope
= find_scope(des_
, net
->scope());
1910 /* Part selects are always unsigned. */
1911 obj
->u_
.part
.signed_flag
= 0;
1913 /* Choose the width of the part select. */
1914 obj
->width
= net
->width();
1915 obj
->u_
.part
.base
= net
->base();
1920 switch (obj
->type
) {
1921 case IVL_LPM_PART_VP
:
1922 /* NetPartSelect:pin(0) is the output pin. */
1923 nex
= net
->pin(0).nexus();
1924 assert(nex
->t_cookie());
1926 obj
->u_
.part
.q
= nex
->t_cookie();
1928 /* NetPartSelect:pin(1) is the input pin. */
1929 nex
= net
->pin(1).nexus();
1930 assert(nex
->t_cookie());
1932 obj
->u_
.part
.a
= nex
->t_cookie();
1934 /* If the part select has an additional pin, that pin is
1935 a variable select base. */
1936 if (net
->pin_count() >= 3) {
1937 nex
= net
->pin(2).nexus();
1938 assert(nex
->t_cookie());
1939 obj
->u_
.part
.s
= nex
->t_cookie();
1943 case IVL_LPM_PART_PV
:
1944 /* NetPartSelect:pin(1) is the output pin. */
1945 nex
= net
->pin(1).nexus();
1946 assert(nex
->t_cookie());
1948 obj
->u_
.part
.q
= nex
->t_cookie();
1950 /* NetPartSelect:pin(0) is the input pin. */
1951 nex
= net
->pin(0).nexus();
1952 assert(nex
->t_cookie());
1954 obj
->u_
.part
.a
= nex
->t_cookie();
1957 case IVL_LPM_PART_BI
:
1958 /* For now, handle this exactly the same as a PV */
1960 /* NetPartSelect:pin(0) is the output pin. */
1961 nex
= net
->pin(0).nexus();
1962 assert(nex
->t_cookie());
1964 obj
->u_
.part
.q
= nex
->t_cookie();
1966 /* NetPartSelect:pin(1) is the input pin. */
1967 nex
= net
->pin(1).nexus();
1968 assert(nex
->t_cookie());
1970 obj
->u_
.part
.a
= nex
->t_cookie();
1977 nexus_lpm_add(obj
->u_
.part
.q
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1979 /* If the device is a PART_BI, then the "input" is also a
1980 strength aware output, so attach it to the nexus with
1982 if (obj
->type
== IVL_LPM_PART_BI
)
1983 nexus_lpm_add(obj
->u_
.part
.a
, obj
, 0, IVL_DR_STRONG
, IVL_DR_STRONG
);
1985 nexus_lpm_add(obj
->u_
.part
.a
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1987 /* The select input is optional. */
1989 nexus_lpm_add(obj
->u_
.part
.s
, obj
, 0, IVL_DR_HiZ
, IVL_DR_HiZ
);
1991 make_lpm_delays_(obj
, net
);
1993 scope_add_lpm(obj
->scope
, obj
);
1998 bool dll_target::replicate(const NetReplicate
*net
)
2000 ivl_lpm_t obj
= new struct ivl_lpm_s
;
2001 obj
->type
= IVL_LPM_REPEAT
;
2002 obj
->name
= net
->name();
2003 assert(net
->scope());
2004 obj
->scope
= find_scope(des_
, net
->scope());
2007 obj
->width
= net
->width();
2008 obj
->u_
.repeat
.count
= net
->repeat();
2010 ivl_drive_t dr
= IVL_DR_STRONG
;
2011 const Nexus
*nex
= net
->pin(0).nexus();
2012 assert(nex
->t_cookie());
2014 obj
->u_
.repeat
.q
= nex
->t_cookie();
2015 nexus_lpm_add(obj
->u_
.repeat
.q
, obj
, 0, dr
, dr
);
2018 nex
= net
->pin(1).nexus();
2019 assert(nex
->t_cookie());
2021 obj
->u_
.repeat
.a
= nex
->t_cookie();
2022 nexus_lpm_add(obj
->u_
.repeat
.a
, obj
, 0, dr
, dr
);
2024 make_lpm_delays_(obj
, net
);
2026 scope_add_lpm(obj
->scope
, obj
);
2032 * The assignment l-values are captured by the assignment statements
2033 * themselves in the process handling.
2035 void dll_target::net_assign(const NetAssign_
*)
2039 bool dll_target::net_const(const NetConst
*net
)
2044 struct ivl_net_const_s
*obj
= new struct ivl_net_const_s
;
2046 obj
->type
= IVL_VT_LOGIC
;
2048 /* constants have a single vector output. */
2049 assert(net
->pin_count() == 1);
2051 obj
->width_
= net
->width();
2052 if (obj
->width_
<= sizeof(obj
->b
.bit_
)) {
2056 obj
->b
.bits_
= (char*)malloc(obj
->width_
);
2057 bits
= obj
->b
.bits_
;
2060 for (idx
= 0 ; idx
< obj
->width_
; idx
+= 1)
2061 switch (net
->value(idx
)) {
2076 /* Connect to all the nexus objects. Note that the one-bit
2077 case can be handled more efficiently without allocating
2080 ivl_drive_t drv0
, drv1
;
2081 drive_from_link(net
->pin(0), drv0
, drv1
);
2082 const Nexus
*nex
= net
->pin(0).nexus();
2083 assert(nex
->t_cookie());
2084 obj
->pin_
= nex
->t_cookie();
2085 nexus_con_add(obj
->pin_
, obj
, 0, drv0
, drv1
);
2089 des_
.consts
= (ivl_net_const_t
*)
2090 realloc(des_
.consts
, des_
.nconsts
* sizeof(ivl_net_const_t
));
2091 des_
.consts
[des_
.nconsts
-1] = obj
;
2093 make_const_delays_(obj
, net
);
2098 bool dll_target::net_literal(const NetLiteral
*net
)
2101 struct ivl_net_const_s
*obj
= new struct ivl_net_const_s
;
2103 obj
->type
= IVL_VT_REAL
;
2106 obj
->b
.real_value
= net
->value_real().as_double();
2108 /* Connect to all the nexus objects. Note that the one-bit
2109 case can be handled more efficiently without allocating
2112 ivl_drive_t drv0
, drv1
;
2113 drive_from_link(net
->pin(0), drv0
, drv1
);
2114 const Nexus
*nex
= net
->pin(0).nexus();
2115 assert(nex
->t_cookie());
2116 obj
->pin_
= nex
->t_cookie();
2117 nexus_con_add(obj
->pin_
, obj
, 0, drv0
, drv1
);
2120 des_
.consts
= (ivl_net_const_t
*)
2121 realloc(des_
.consts
, des_
.nconsts
* sizeof(ivl_net_const_t
));
2122 des_
.consts
[des_
.nconsts
-1] = obj
;
2124 make_const_delays_(obj
, net
);
2129 void dll_target::net_probe(const NetEvProbe
*net
)
2133 void dll_target::scope(const NetScope
*net
)
2137 if (net
->parent() == 0) {
2140 for (i
= 0; i
< des_
.nroots_
&& scope
== NULL
; i
++) {
2141 if (strcmp(des_
.roots_
[i
]->name_
, net
->basename()) == 0)
2142 scope
= des_
.roots_
[i
];
2147 perm_string sname
= make_scope_name(net
->fullname());
2148 scope
= new struct ivl_scope_s
;
2149 scope
->name_
= sname
;
2150 FILE_NAME(scope
, net
);
2152 scope
->sibling_
= 0;
2153 scope
->parent
= find_scope(des_
, net
->parent());
2154 assert(scope
->parent
);
2164 make_scope_parameters(scope
, net
);
2165 scope
->time_precision
= net
->time_precision();
2166 scope
->time_units
= net
->time_unit();
2167 scope
->nattr
= net
->attr_cnt();
2168 scope
->attr
= fill_in_attributes(net
);
2170 switch (net
->type()) {
2171 case NetScope::MODULE
:
2172 scope
->type_
= IVL_SCT_MODULE
;
2173 scope
->tname_
= net
->module_name();
2175 case NetScope::TASK
: {
2176 const NetTaskDef
*def
= net
->task_def();
2178 cerr
<< "?:?" << ": internal error: "
2179 << "task " << scope
->name_
2180 << " has no definition." << endl
;
2183 scope
->type_
= IVL_SCT_TASK
;
2184 scope
->tname_
= def
->scope()->basename();
2187 case NetScope::FUNC
:
2188 scope
->type_
= IVL_SCT_FUNCTION
;
2189 scope
->tname_
= net
->func_def()->scope()->basename();
2191 case NetScope::BEGIN_END
:
2192 scope
->type_
= IVL_SCT_BEGIN
;
2193 scope
->tname_
= scope
->name_
;
2195 case NetScope::FORK_JOIN
:
2196 scope
->type_
= IVL_SCT_FORK
;
2197 scope
->tname_
= scope
->name_
;
2199 case NetScope::GENBLOCK
:
2200 scope
->type_
= IVL_SCT_GENERATE
;
2201 scope
->tname_
= scope
->name_
;
2205 assert(scope
->parent
!= 0);
2207 scope
->sibling_
= scope
->parent
->child_
;
2208 scope
->parent
->child_
= scope
;
2212 void dll_target::signal(const NetNet
*net
)
2214 ivl_signal_t obj
= new struct ivl_signal_s
;
2216 obj
->name_
= net
->name();
2218 /* Attach the signal to the ivl_scope_t object that contains
2219 it. This involves growing the sigs_ array in the scope
2220 object, or creating the sigs_ array if this is the first
2222 obj
->scope_
= find_scope(des_
, net
->scope());
2223 obj
->file
= perm_string::literal("N/A");
2225 assert(obj
->scope_
);
2227 if (obj
->scope_
->nsigs_
== 0) {
2228 assert(obj
->scope_
->sigs_
== 0);
2229 obj
->scope_
->nsigs_
= 1;
2230 obj
->scope_
->sigs_
= (ivl_signal_t
*)malloc(sizeof(ivl_signal_t
));
2233 assert(obj
->scope_
->sigs_
);
2234 obj
->scope_
->nsigs_
+= 1;
2235 obj
->scope_
->sigs_
= (ivl_signal_t
*)
2236 realloc(obj
->scope_
->sigs_
,
2237 obj
->scope_
->nsigs_
*sizeof(ivl_signal_t
));
2240 obj
->scope_
->sigs_
[obj
->scope_
->nsigs_
-1] = obj
;
2243 /* Save the primitive properties of the signal in the
2244 ivl_signal_t object. */
2246 obj
->width_
= net
->vector_width();
2247 obj
->signed_
= net
->get_signed()? 1 : 0;
2248 obj
->lsb_index
= net
->lsb();
2249 obj
->lsb_dist
= net
->msb() >= net
->lsb() ? 1 : -1;
2250 obj
->isint_
= false;
2251 obj
->local_
= net
->local_flag()? 1 : 0;
2253 obj
->array_dimensions_
= net
->array_dimensions();
2255 switch (net
->port_type()) {
2257 case NetNet::PINPUT
:
2258 obj
->port_
= IVL_SIP_INPUT
;
2261 case NetNet::POUTPUT
:
2262 obj
->port_
= IVL_SIP_OUTPUT
;
2265 case NetNet::PINOUT
:
2266 obj
->port_
= IVL_SIP_INOUT
;
2270 obj
->port_
= IVL_SIP_NONE
;
2274 switch (net
->type()) {
2277 obj
->type_
= IVL_SIT_REG
;
2278 obj
->isint_
= net
->get_isint();
2281 /* The SUPPLY0/1 net types are replaced with pulldown/up
2282 by elaborate. They should not make it here. */
2283 case NetNet::SUPPLY0
:
2286 case NetNet::SUPPLY1
:
2292 case NetNet::IMPLICIT
:
2293 obj
->type_
= IVL_SIT_TRI
;
2297 obj
->type_
= IVL_SIT_TRI0
;
2301 obj
->type_
= IVL_SIT_TRI1
;
2304 case NetNet::TRIAND
:
2306 obj
->type_
= IVL_SIT_TRIAND
;
2311 obj
->type_
= IVL_SIT_TRIOR
;
2315 obj
->type_
= IVL_SIT_NONE
;
2319 /* Initialize the path fields to be filled in later. */
2323 obj
->data_type
= net
->data_type();
2324 obj
->nattr
= net
->attr_cnt();
2325 obj
->attr
= fill_in_attributes(net
);
2328 /* Get the nexus objects for all the pins of the signal. If
2329 the signal has only one pin, then write the single
2330 ivl_nexus_t object into n.pin_. Otherwise, make an array of
2331 ivl_nexus_t cookies.
2333 When I create an ivl_nexus_t object, store it in the
2334 t_cookie of the Nexus object so that I find it again when I
2335 next encounter the nexus. */
2337 obj
->array_base
= net
->array_first();
2338 obj
->array_words
= net
->array_count();
2339 if (obj
->array_words
> 1)
2340 obj
->pins
= new ivl_nexus_t
[obj
->array_words
];
2342 for (unsigned idx
= 0 ; idx
< obj
->array_words
; idx
+= 1) {
2344 const Nexus
*nex
= net
->pin(idx
).nexus();
2345 if (nex
->t_cookie()) {
2346 if (obj
->array_words
> 1) {
2347 obj
->pins
[idx
] = nex
->t_cookie();
2348 nexus_sig_add(obj
->pins
[idx
], obj
, idx
);
2350 obj
->pin
= nex
->t_cookie();
2351 nexus_sig_add(obj
->pin
, obj
, idx
);
2354 ivl_nexus_t tmp
= nexus_sig_make(obj
, idx
);
2358 if (obj
->array_words
> 1)
2359 obj
->pins
[idx
] = tmp
;
2366 bool dll_target::signal_paths(const NetNet
*net
)
2368 /* Nothing to do if there are no paths for this signal. */
2369 if (net
->delay_paths() == 0)
2372 ivl_signal_t obj
= find_signal(des_
, net
);
2375 /* We cannot have already set up the paths for this signal. */
2376 assert(obj
->npath
== 0);
2377 assert(obj
->path
== 0);
2379 /* Figure out how many paths there really are. */
2380 for (unsigned idx
= 0 ; idx
< net
->delay_paths() ; idx
+= 1) {
2381 const NetDelaySrc
*src
= net
->delay_path(idx
);
2382 obj
->npath
+= src
->src_count();
2385 obj
->path
= new struct ivl_delaypath_s
[obj
->npath
];
2388 for (unsigned idx
= 0 ; idx
< net
->delay_paths() ; idx
+= 1) {
2389 const NetDelaySrc
*src
= net
->delay_path(idx
);
2391 /* If this path has a condition, then hook it up. */
2392 ivl_nexus_t path_condit
= 0;
2393 if (src
->has_condit()) {
2394 const Nexus
*nt
= src
->condit_pin().nexus();
2395 path_condit
= nt
->t_cookie();
2398 for (unsigned pin
= 0; pin
< src
->src_count(); pin
+= 1) {
2399 const Nexus
*nex
= src
->src_pin(pin
).nexus();
2400 if (! nex
->t_cookie()) {
2401 cerr
<< src
->get_fileline() << ": internal error: "
2402 << "No signal connected to pin " << pin
2403 << " of delay path to " << net
->name()
2406 assert(nex
->t_cookie());
2407 obj
->path
[ptr
].scope
= lookup_scope_(src
->scope());
2408 obj
->path
[ptr
].src
= nex
->t_cookie();
2409 obj
->path
[ptr
].condit
= path_condit
;
2410 obj
->path
[ptr
].conditional
= src
->is_condit();
2411 obj
->path
[ptr
].posedge
= src
->is_posedge();
2412 obj
->path
[ptr
].negedge
= src
->is_negedge();
2413 for (unsigned pe
= 0 ; pe
< 12 ; pe
+= 1) {
2414 obj
->path
[ptr
].delay
[pe
] = src
->get_delay(pe
);
2425 extern const struct target tgt_dll
= { "dll", &dll_target_obj
};