$finish() now stops at the end of the time step not immediately.
[iverilog.git] / t-dll-proc.cc
blob1632aadd8e862e634eee23b5f77dc50a567ac950
1 /*
2 * Copyright (c) 2000 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.will need a Picture Elements Binary Software
9 * License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 #ifdef HAVE_CVS_IDENT
21 #ident "$Id: t-dll-proc.cc,v 1.71 2007/06/02 03:42:13 steve Exp $"
22 #endif
24 # include "config.h"
26 # include <iostream>
28 # include "target.h"
29 # include "ivl_target.h"
30 # include "compiler.h"
31 # include "t-dll.h"
32 #ifdef HAVE_MALLOC_H
33 # include <malloc.h>
34 #endif
35 # include <stdlib.h>
38 bool dll_target::process(const NetProcTop*net)
40 ivl_process_t obj = (struct ivl_process_s*)
41 calloc(1, sizeof(struct ivl_process_s));
43 switch (net->type()) {
44 case NetProcTop::KINITIAL:
45 obj->type_ = IVL_PR_INITIAL;
46 break;
47 case NetProcTop::KALWAYS:
48 obj->type_ = IVL_PR_ALWAYS;
49 break;
50 default:
51 assert(0);
54 /* Save the scope of the process. */
55 obj->scope_ = lookup_scope_(net->scope());
57 obj->nattr = net->attr_cnt();
58 obj->attr = fill_in_attributes(net);
60 /* This little bit causes the process to be completely
61 generated so that it can be passed to the DLL. The
62 stmt_cur_ member us used to hold a pointer to the current
63 statement in progress, and the emit_proc() method fills in
64 that object.
66 We know a few things about the current statement: we are
67 not in the middle of one, and when we are done, we have our
68 statement back. The asserts check these conditions. */
70 assert(stmt_cur_ == 0);
71 stmt_cur_ = (struct ivl_statement_s*)calloc(1, sizeof*stmt_cur_);
72 assert(stmt_cur_);
73 net->statement()->emit_proc(this);
75 assert(stmt_cur_);
76 obj->stmt_ = stmt_cur_;
77 stmt_cur_ = 0;
79 /* Save the process in the design. */
80 obj->next_ = des_.threads_;
81 des_.threads_ = obj;
83 return true;
86 void dll_target::task_def(const NetScope*net)
88 ivl_scope_t scope = lookup_scope_(net);
89 const NetTaskDef*def = net->task_def();
91 assert(stmt_cur_ == 0);
92 stmt_cur_ = (struct ivl_statement_s*)calloc(1, sizeof*stmt_cur_);
93 assert(stmt_cur_);
94 def->proc()->emit_proc(this);
96 assert(stmt_cur_);
97 scope->def = stmt_cur_;
98 stmt_cur_ = 0;
102 bool dll_target::func_def(const NetScope*net)
104 ivl_scope_t scope = lookup_scope_(net);
105 const NetFuncDef*def = net->func_def();
107 assert(stmt_cur_ == 0);
108 stmt_cur_ = (struct ivl_statement_s*)calloc(1, sizeof*stmt_cur_);
109 assert(stmt_cur_);
110 def->proc()->emit_proc(this);
112 assert(stmt_cur_);
113 scope->def = stmt_cur_;
114 stmt_cur_ = 0;
116 scope->ports = def->port_count() + 1;
117 if (scope->ports > 0) {
118 scope->port = new ivl_signal_t[scope->ports];
119 for (unsigned idx = 1 ; idx < scope->ports ; idx += 1)
120 scope->port[idx] = find_signal(des_, def->port(idx-1));
123 /* FIXME: the ivl_target API expects port-0 to be the output
124 port. This assumes that the return value is a signal, which
125 is *not* correct. Someday, I'm going to have to change
126 this, but that will break code generators that use this
127 result. */
128 if (const NetNet*ret_sig = def->return_sig()) {
129 scope->port[0] = find_signal(des_, ret_sig);
130 return true;
133 cerr << "?:0" << ": internal error: "
134 << "Function " << net->basename() << " has a return type"
135 << " that I do not understand." << endl;
137 return false;
141 * This private function makes the assignment lvals for the various
142 * kinds of assignment statements.
144 void dll_target::make_assign_lvals_(const NetAssignBase*net)
146 assert(stmt_cur_);
148 unsigned cnt = net->l_val_count();
150 stmt_cur_->u_.assign_.lvals_ = cnt;
151 stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
152 stmt_cur_->u_.assign_.delay = 0;
154 for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
155 struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx;
156 const NetAssign_*asn = net->l_val(idx);
157 const NetExpr*loff = asn->get_base();
159 if (loff == 0) {
160 cur->loff = 0;
161 } else {
162 loff->expr_scan(this);
163 cur->loff = expr_;
164 expr_ = 0;
167 cur->width_ = asn->lwidth();
169 if (asn->sig()) {
170 cur->type_ = IVL_LVAL_REG;
171 cur->n.sig = find_signal(des_, asn->sig());
173 cur->idx = 0;
174 // If there is a word select expression, it is
175 // really an array index. Note that the word index
176 // expression is already converted to canonical
177 // form by elaboration.
178 if (asn->word()) {
179 assert(expr_ == 0);
180 asn->word()->expr_scan(this);
181 // lsb_dist is the distance for this
182 // index. If this is >1, then this may be an
183 // array of arrays, so we need to multiply
184 // to get the canonical index.
185 if (cur->n.sig->lsb_dist != 1)
186 mul_expr_by_const_(cur->n.sig->lsb_dist);
188 cur->type_ = IVL_LVAL_ARR;
189 cur->idx = expr_;
190 expr_ = 0;
192 } else {
193 assert(0);
200 void dll_target::proc_assign(const NetAssign*net)
202 assert(stmt_cur_);
203 assert(stmt_cur_->type_ == IVL_ST_NONE);
205 stmt_cur_->type_ = IVL_ST_ASSIGN;
207 stmt_cur_->u_.assign_.delay = 0;
209 /* Make the lval fields. */
210 make_assign_lvals_(net);
212 assert(expr_ == 0);
213 net->rval()->expr_scan(this);
214 stmt_cur_->u_.assign_.rval_ = expr_;
215 expr_ = 0;
217 const NetExpr*del = net->get_delay();
218 if (del) {
219 del->expr_scan(this);
220 stmt_cur_->u_.assign_.delay = expr_;
221 expr_ = 0;
226 void dll_target::proc_assign_nb(const NetAssignNB*net)
228 const NetExpr* delay_exp = net->get_delay();
229 assert(stmt_cur_);
230 assert(stmt_cur_->type_ == IVL_ST_NONE);
232 stmt_cur_->type_ = IVL_ST_ASSIGN_NB;
233 stmt_cur_->u_.assign_.delay = 0;
235 /* Make the lval fields. */
236 make_assign_lvals_(net);
238 /* Make the rval field. */
239 assert(expr_ == 0);
240 net->rval()->expr_scan(this);
241 stmt_cur_->u_.assign_.rval_ = expr_;
242 expr_ = 0;
244 if (const NetEConst*delay_num = dynamic_cast<const NetEConst*>(delay_exp)) {
245 verinum val = delay_num->value();
246 ivl_expr_t de = new struct ivl_expr_s;
247 de->type_ = IVL_EX_ULONG;
248 de->width_ = 8 * sizeof(unsigned long);
249 de->signed_ = 0;
250 de->u_.ulong_.value = val.as_ulong();
251 stmt_cur_->u_.assign_.delay = de;
253 } else if (delay_exp != 0) {
254 delay_exp->expr_scan(this);
255 stmt_cur_->u_.assign_.delay = expr_;
256 expr_ = 0;
260 bool dll_target::proc_block(const NetBlock*net)
262 assert(stmt_cur_);
263 assert(stmt_cur_->type_ == IVL_ST_NONE);
265 /* First, count the statements in the block. */
266 unsigned count = 0;
267 for (const NetProc*cur = net->proc_first()
268 ; cur ; cur = net->proc_next(cur))
269 count += 1;
271 /* If the block has no statements, then turn it into a no-op */
272 if (count == 0) {
273 stmt_cur_->type_ = IVL_ST_NOOP;
274 return true;
277 /* If there is exactly one statement, there is no need for the
278 block wrapper, generate the contained statement instead. */
279 if ((count == 1) && (net->subscope() == 0)) {
280 return net->proc_first()->emit_proc(this);
284 /* Handle the general case. The block has some statements in
285 it, so fill in the block fields of the existing statement,
286 and generate the contents for the statement array. */
288 stmt_cur_->type_ = (net->type() == NetBlock::SEQU)
289 ? IVL_ST_BLOCK
290 : IVL_ST_FORK;
291 stmt_cur_->u_.block_.nstmt_ = count;
292 stmt_cur_->u_.block_.stmt_ = (struct ivl_statement_s*)
293 calloc(count, sizeof(struct ivl_statement_s));
295 if (net->subscope())
296 stmt_cur_->u_.block_.scope = lookup_scope_(net->subscope());
297 else
298 stmt_cur_->u_.block_.scope = 0;
300 struct ivl_statement_s*save_cur_ = stmt_cur_;
301 unsigned idx = 0;
302 bool flag = true;
304 for (const NetProc*cur = net->proc_first()
305 ; cur ; cur = net->proc_next(cur), idx += 1) {
306 assert(idx < count);
307 stmt_cur_ = save_cur_->u_.block_.stmt_ + idx;
308 bool rc = cur->emit_proc(this);
309 flag = flag && rc;
311 assert(idx == count);
313 stmt_cur_ = save_cur_;
315 return flag;
319 * A case statement is in turn an array of statements with gate
320 * expressions. This builds arrays of the right size and builds the
321 * ivl_expr_t and ivl_statement_s arrays for the substatements.
323 void dll_target::proc_case(const NetCase*net)
325 assert(stmt_cur_);
326 assert(stmt_cur_->type_ == IVL_ST_NONE);
328 switch (net->type()) {
329 case NetCase::EQ:
330 stmt_cur_->type_ = IVL_ST_CASE;
331 break;
332 case NetCase::EQX:
333 stmt_cur_->type_ = IVL_ST_CASEX;
334 break;
335 case NetCase::EQZ:
336 stmt_cur_->type_ = IVL_ST_CASEZ;
337 break;
339 assert(stmt_cur_->type_ != IVL_ST_NONE);
341 assert(expr_ == 0);
342 assert(net->expr());
343 net->expr()->expr_scan(this);
344 stmt_cur_->u_.case_.cond = expr_;
345 expr_ = 0;
347 /* If the condition expression is a real valued expression,
348 then change the case statement to a CASER statement. */
349 if (stmt_cur_->u_.case_.cond->value_ == IVL_VT_REAL)
350 stmt_cur_->type_ = IVL_ST_CASER;
352 unsigned ncase = net->nitems();
353 stmt_cur_->u_.case_.ncase = ncase;
355 stmt_cur_->u_.case_.case_ex = new ivl_expr_t[ncase];
356 stmt_cur_->u_.case_.case_st = new struct ivl_statement_s[ncase];
358 ivl_statement_t save_cur = stmt_cur_;
360 for (unsigned idx = 0 ; idx < ncase ; idx += 1) {
361 const NetExpr*ex = net->expr(idx);
362 if (ex) {
363 ex->expr_scan(this);
364 save_cur->u_.case_.case_ex[idx] = expr_;
365 expr_ = 0;
366 } else {
367 save_cur->u_.case_.case_ex[idx] = 0;
370 stmt_cur_ = save_cur->u_.case_.case_st + idx;
371 stmt_cur_->type_ = IVL_ST_NONE;
372 if (net->stat(idx) == 0) {
373 stmt_cur_->type_ = IVL_ST_NOOP;
374 } else {
375 net->stat(idx)->emit_proc(this);
379 stmt_cur_ = save_cur;
382 bool dll_target::proc_cassign(const NetCAssign*net)
385 assert(stmt_cur_);
386 assert(stmt_cur_->type_ == IVL_ST_NONE);
388 stmt_cur_->type_ = IVL_ST_CASSIGN;
390 /* Make the l-value fields. */
391 make_assign_lvals_(net);
393 assert(expr_ == 0);
394 net->rval()->expr_scan(this);
395 stmt_cur_->u_.assign_.rval_ = expr_;
396 expr_ = 0;
398 return true;
401 bool dll_target::proc_condit(const NetCondit*net)
403 assert(stmt_cur_);
404 assert(stmt_cur_->type_ == IVL_ST_NONE);
406 stmt_cur_->type_ = IVL_ST_CONDIT;
407 stmt_cur_->u_.condit_.stmt_ = (struct ivl_statement_s*)
408 calloc(2, sizeof(struct ivl_statement_s));
410 assert(expr_ == 0);
411 net->expr()->expr_scan(this);
412 stmt_cur_->u_.condit_.cond_ = expr_;
413 expr_ = 0;
415 ivl_statement_t save_cur_ = stmt_cur_;
417 stmt_cur_ = save_cur_->u_.condit_.stmt_+0;
418 bool flag = net->emit_recurse_if(this);
420 stmt_cur_ = save_cur_->u_.condit_.stmt_+1;
421 flag = flag && net->emit_recurse_else(this);
423 stmt_cur_ = save_cur_;
424 return flag;
427 bool dll_target::proc_deassign(const NetDeassign*net)
429 assert(stmt_cur_);
430 assert(stmt_cur_->type_ == IVL_ST_NONE);
432 stmt_cur_->type_ = IVL_ST_DEASSIGN;
434 /* Make the l-value fields. */
435 make_assign_lvals_(net);
437 return true;
440 bool dll_target::proc_delay(const NetPDelay*net)
442 assert(stmt_cur_);
443 assert(stmt_cur_->type_ == IVL_ST_NONE);
445 ivl_statement_t tmp = (struct ivl_statement_s*)
446 calloc(1, sizeof(struct ivl_statement_s));
448 if (const NetExpr*expr = net->expr()) {
450 stmt_cur_->type_ = IVL_ST_DELAYX;
451 assert(expr_ == 0);
452 expr->expr_scan(this);
453 stmt_cur_->u_.delayx_.expr = expr_;
454 expr_ = 0;
456 stmt_cur_->u_.delayx_.stmt_ = tmp;
458 } else {
459 stmt_cur_->type_ = IVL_ST_DELAY;
460 stmt_cur_->u_.delay_.stmt_ = tmp;
461 stmt_cur_->u_.delay_.delay_ = net->delay();
464 ivl_statement_t save_cur_ = stmt_cur_;
465 stmt_cur_ = tmp;
466 bool flag = net->emit_proc_recurse(this);
468 /* If the recurse doesn't turn this new item into something,
469 then either it failed or there is no statement
470 there. Either way, draw a no-op into the statement. */
471 if (stmt_cur_->type_ == IVL_ST_NONE) {
472 stmt_cur_->type_ = IVL_ST_NOOP;
475 stmt_cur_ = save_cur_;
477 return flag;
480 bool dll_target::proc_disable(const NetDisable*net)
482 assert(stmt_cur_);
483 assert(stmt_cur_->type_ == IVL_ST_NONE);
485 stmt_cur_->type_ = IVL_ST_DISABLE;
486 stmt_cur_->u_.disable_.scope = lookup_scope_(net->target());
487 return true;
490 bool dll_target::proc_force(const NetForce*net)
493 assert(stmt_cur_);
494 assert(stmt_cur_->type_ == IVL_ST_NONE);
496 stmt_cur_->type_ = IVL_ST_FORCE;
498 /* Make the l-value fields. */
499 make_assign_lvals_(net);
501 assert(expr_ == 0);
502 net->rval()->expr_scan(this);
503 stmt_cur_->u_.assign_.rval_ = expr_;
504 expr_ = 0;
506 return true;
509 void dll_target::proc_forever(const NetForever*net)
511 assert(stmt_cur_);
512 assert(stmt_cur_->type_ == IVL_ST_NONE);
514 stmt_cur_->type_ = IVL_ST_FOREVER;
516 ivl_statement_t tmp = (struct ivl_statement_s*)
517 calloc(1, sizeof(struct ivl_statement_s));
519 ivl_statement_t save_cur_ = stmt_cur_;
520 stmt_cur_ = tmp;
522 net->emit_recurse(this);
524 save_cur_->u_.forever_.stmt_ = stmt_cur_;
525 stmt_cur_ = save_cur_;
528 bool dll_target::proc_release(const NetRelease*net)
530 assert(stmt_cur_);
531 assert(stmt_cur_->type_ == IVL_ST_NONE);
533 stmt_cur_->type_ = IVL_ST_RELEASE;
535 /* Make the l-value fields. */
536 make_assign_lvals_(net);
538 return true;
541 void dll_target::proc_repeat(const NetRepeat*net)
543 assert(stmt_cur_);
544 assert(stmt_cur_->type_ == IVL_ST_NONE);
546 stmt_cur_->type_ = IVL_ST_REPEAT;
548 assert(expr_ == 0);
549 net->expr()->expr_scan(this);
550 stmt_cur_->u_.while_.cond_ = expr_;
551 expr_ = 0;
553 ivl_statement_t tmp = (struct ivl_statement_s*)
554 calloc(1, sizeof(struct ivl_statement_s));
556 ivl_statement_t save_cur_ = stmt_cur_;
557 stmt_cur_ = tmp;
559 net->emit_recurse(this);
561 save_cur_->u_.while_.stmt_ = stmt_cur_;
562 stmt_cur_ = save_cur_;
565 void dll_target::proc_stask(const NetSTask*net)
567 unsigned nparms = net->nparms();
568 assert(stmt_cur_);
569 assert(stmt_cur_->type_ == IVL_ST_NONE);
571 stmt_cur_->type_ = IVL_ST_STASK;
572 /* System task names are lex_strings strings. */
573 stmt_cur_->u_.stask_.name_ = net->name();
574 stmt_cur_->u_.stask_.nparm_= nparms;
575 stmt_cur_->u_.stask_.parms_= (ivl_expr_t*)
576 calloc(nparms, sizeof(ivl_expr_t));
578 for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
579 if (net->parm(idx))
580 net->parm(idx)->expr_scan(this);
581 stmt_cur_->u_.stask_.parms_[idx] = expr_;
582 expr_ = 0;
587 bool dll_target::proc_trigger(const NetEvTrig*net)
589 assert(stmt_cur_);
590 assert(stmt_cur_->type_ == IVL_ST_NONE);
592 stmt_cur_->type_ = IVL_ST_TRIGGER;
593 stmt_cur_->u_.wait_.nevent = 1;
595 /* Locate the event by name. Save the ivl_event_t in the
596 statement so that the generator can find it easily. */
597 const NetEvent*ev = net->event();
598 ivl_scope_t ev_scope = lookup_scope_(ev->scope());
600 for (unsigned idx = 0 ; idx < ev_scope->nevent_ ; idx += 1) {
601 const char*ename = ivl_event_basename(ev_scope->event_[idx]);
602 if (strcmp(ev->name(), ename) == 0) {
603 stmt_cur_->u_.wait_.event = ev_scope->event_[idx];
604 break;
609 return true;
612 void dll_target::proc_utask(const NetUTask*net)
614 assert(stmt_cur_);
615 assert(stmt_cur_->type_ == IVL_ST_NONE);
617 stmt_cur_->type_ = IVL_ST_UTASK;
618 stmt_cur_->u_.utask_.def = lookup_scope_(net->task());
621 bool dll_target::proc_wait(const NetEvWait*net)
623 assert(stmt_cur_);
624 assert(stmt_cur_->type_ == IVL_ST_NONE);
626 stmt_cur_->type_ = IVL_ST_WAIT;
627 stmt_cur_->u_.wait_.stmt_ = (struct ivl_statement_s*)
628 calloc(1, sizeof(struct ivl_statement_s));
630 stmt_cur_->u_.wait_.nevent = net->nevents();
631 if (net->nevents() > 1) {
632 stmt_cur_->u_.wait_.events = (ivl_event_t*)
633 calloc(net->nevents(), sizeof(ivl_event_t*));
636 for (unsigned edx = 0 ; edx < net->nevents() ; edx += 1) {
638 /* Locate the event by name. Save the ivl_event_t in the
639 statement so that the generator can find it easily. */
640 const NetEvent*ev = net->event(edx);
641 ivl_scope_t ev_scope = lookup_scope_(ev->scope());
642 ivl_event_t ev_tmp=0;
644 assert(ev_scope);
645 assert(ev_scope->nevent_ > 0);
646 for (unsigned idx = 0 ; idx < ev_scope->nevent_ ; idx += 1) {
647 const char*ename = ivl_event_basename(ev_scope->event_[idx]);
648 if (strcmp(ev->name(), ename) == 0) {
649 ev_tmp = ev_scope->event_[idx];
650 break;
653 // XXX should we assert(ev_tmp)?
655 if (net->nevents() == 1)
656 stmt_cur_->u_.wait_.event = ev_tmp;
657 else
658 stmt_cur_->u_.wait_.events[edx] = ev_tmp;
660 /* If this is an event with a probe, then connect up the
661 pins. This wasn't done during the ::event method because
662 the signals weren't scanned yet. */
664 if (ev->nprobe() >= 1) {
665 unsigned iany = 0;
666 unsigned ineg = ev_tmp->nany;
667 unsigned ipos = ineg + ev_tmp->nneg;
669 for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
670 const NetEvProbe*pr = ev->probe(idx);
671 unsigned base = 0;
673 switch (pr->edge()) {
674 case NetEvProbe::ANYEDGE:
675 base = iany;
676 iany += pr->pin_count();
677 break;
678 case NetEvProbe::NEGEDGE:
679 base = ineg;
680 ineg += pr->pin_count();
681 break;
682 case NetEvProbe::POSEDGE:
683 base = ipos;
684 ipos += pr->pin_count();
685 break;
688 for (unsigned bit = 0
689 ; bit < pr->pin_count()
690 ; bit += 1) {
691 ivl_nexus_t nex = (ivl_nexus_t)
692 pr->pin(bit).nexus()->t_cookie();
693 assert(nex);
694 ev_tmp->pins[base+bit] = nex;
700 /* The ivl_statement_t for the wait statement is not complete
701 until we calculate the sub-statement. */
703 ivl_statement_t save_cur_ = stmt_cur_;
704 stmt_cur_ = stmt_cur_->u_.wait_.stmt_;
705 bool flag = net->emit_recurse(this);
706 if (flag && (stmt_cur_->type_ == IVL_ST_NONE))
707 stmt_cur_->type_ = IVL_ST_NOOP;
709 stmt_cur_ = save_cur_;
711 return flag;
714 void dll_target::proc_while(const NetWhile*net)
716 assert(stmt_cur_);
717 assert(stmt_cur_->type_ == IVL_ST_NONE);
719 stmt_cur_->type_ = IVL_ST_WHILE;
720 stmt_cur_->u_.while_.stmt_ = (struct ivl_statement_s*)
721 calloc(1, sizeof(struct ivl_statement_s));
723 assert(expr_ == 0);
724 net->expr()->expr_scan(this);
725 stmt_cur_->u_.while_.cond_ = expr_;
726 expr_ = 0;
728 /* Now generate the statement of the while loop. We know it is
729 a single statement, and we know that the
730 emit_proc_recurse() will call emit_proc() for it. */
732 ivl_statement_t save_cur_ = stmt_cur_;
733 stmt_cur_ = save_cur_->u_.while_.stmt_;
734 net->emit_proc_recurse(this);
735 stmt_cur_ = save_cur_;
739 * $Log: t-dll-proc.cc,v $
740 * Revision 1.71 2007/06/02 03:42:13 steve
741 * Properly evaluate scope path expressions.
743 * Revision 1.70 2007/04/04 01:50:38 steve
744 * t-dll should not canonicalize word addresses, elaboration already does it.
746 * Revision 1.69 2007/01/16 05:44:15 steve
747 * Major rework of array handling. Memories are replaced with the
748 * more general concept of arrays. The NetMemory and NetEMemory
749 * classes are removed from the ivl core program, and the IVL_LPM_RAM
750 * lpm type is removed from the ivl_target API.
752 * Revision 1.68 2006/02/02 02:43:59 steve
753 * Allow part selects of memory words in l-values.
755 * Revision 1.67 2005/07/11 16:56:51 steve
756 * Remove NetVariable and ivl_variable_t structures.
758 * Revision 1.66 2004/12/11 02:31:28 steve
759 * Rework of internals to carry vectors through nexus instead
760 * of single bits. Make the ivl, tgt-vvp and vvp initial changes
761 * down this path.
763 * Revision 1.65 2004/10/04 01:10:55 steve
764 * Clean up spurious trailing white space.
766 * Revision 1.64 2004/05/31 23:34:39 steve
767 * Rewire/generalize parsing an elaboration of
768 * function return values to allow for better
769 * speed and more type support.
771 * Revision 1.63 2004/05/19 03:18:40 steve
772 * Add ivl_target support for non-blocking assign of real.
774 * Revision 1.62 2003/12/19 01:27:10 steve
775 * Fix various unsigned compare warnings.
777 * Revision 1.61 2003/12/03 02:46:24 steve
778 * Add support for wait on list of named events.
780 * Revision 1.60 2003/06/24 01:38:03 steve
781 * Various warnings fixed.
783 * Revision 1.59 2003/05/14 05:26:41 steve
784 * Support real expressions in case statements.
786 * Revision 1.58 2003/05/07 19:56:20 steve
787 * Improve internal error message.
789 * Revision 1.57 2003/03/01 06:25:30 steve
790 * Add the lex_strings string handler, and put
791 * scope names and system task/function names
792 * into this table. Also, permallocate event
793 * names from the beginning.
795 * Revision 1.56 2003/01/30 16:23:08 steve
796 * Spelling fixes.
798 * Revision 1.55 2003/01/26 21:15:59 steve
799 * Rework expression parsing and elaboration to
800 * accommodate real/realtime values and expressions.
802 * Revision 1.54 2002/08/19 00:06:12 steve
803 * Allow release to handle removal of target net.
805 * Revision 1.53 2002/08/13 05:35:00 steve
806 * Do not elide named blocks.
808 * Revision 1.52 2002/08/12 01:35:00 steve
809 * conditional ident string using autoconfig.
811 * Revision 1.51 2002/08/07 00:54:39 steve
812 * Add force to nets.
814 * Revision 1.50 2002/08/04 18:28:15 steve
815 * Do not use hierarchical names of memories to
816 * generate vvp labels. -tdll target does not
817 * used hierarchical name string to look up the
818 * memory objects in the design.
820 * Revision 1.49 2002/06/16 20:39:12 steve
821 * Normalize run-time index expressions for bit selects
823 * Revision 1.48 2002/06/16 19:19:16 steve
824 * Generate runtime code to normalize indices.
826 * Revision 1.47 2002/06/05 03:44:25 steve
827 * Add support for memory words in l-value of
828 * non-blocking assignments, and remove the special
829 * NetAssignMem_ and NetAssignMemNB classes.
831 * Revision 1.46 2002/06/04 05:38:44 steve
832 * Add support for memory words in l-value of
833 * blocking assignments, and remove the special
834 * NetAssignMem class.
836 * Revision 1.45 2002/05/29 22:05:55 steve
837 * Offset lvalue index expressions.
839 * Revision 1.44 2002/05/27 00:08:45 steve
840 * Support carrying the scope of named begin-end
841 * blocks down to the code generator, and have
842 * the vvp code generator use that to support disable.
844 * Revision 1.43 2002/05/26 01:39:03 steve
845 * Carry Verilog 2001 attributes with processes,
846 * all the way through to the ivl_target API.
848 * Divide signal reference counts between rval
849 * and lval references.
851 * Revision 1.42 2002/04/21 22:31:02 steve
852 * Redo handling of assignment internal delays.
853 * Leave it possible for them to be calculated
854 * at run time.
856 * Revision 1.41 2002/01/19 19:02:08 steve
857 * Pass back target errors processing conditionals.
859 * Revision 1.40 2001/11/14 03:28:49 steve
860 * DLL target support for force and release.
862 * Revision 1.39 2001/11/01 04:25:31 steve
863 * ivl_target support for cassign.
865 * Revision 1.38 2001/10/31 05:24:52 steve
866 * ivl_target support for assign/deassign.
868 * Revision 1.37 2001/10/30 02:52:07 steve
869 * Stubs for assign/deassign for t-dll.
871 * Revision 1.36 2001/10/19 21:53:24 steve
872 * Support multiple root modules (Philip Blundell)
874 * Revision 1.35 2001/09/15 18:27:04 steve
875 * Make configure detect malloc.h
877 * Revision 1.34 2001/08/25 23:50:03 steve
878 * Change the NetAssign_ class to refer to the signal
879 * instead of link into the netlist. This is faster
880 * and uses less space. Make the NetAssignNB carry
881 * the delays instead of the NetAssign_ lval objects.
883 * Change the vvp code generator to support multiple
884 * l-values, i.e. concatenations of part selects.
886 * Revision 1.33 2001/07/27 02:41:56 steve
887 * Fix binding of dangling function ports. do not elide them.
889 * Revision 1.32 2001/07/25 03:10:49 steve
890 * Create a config.h.in file to hold all the config
891 * junk, and support gcc 3.0. (Stephan Boettcher)
893 * Revision 1.31 2001/07/19 04:55:06 steve
894 * Support calculated delays in vvp.tgt.
896 * Revision 1.30 2001/06/21 23:23:14 steve
897 * Initialize stmt_cur_ substatements during dll case building.
899 * Revision 1.29 2001/05/08 23:59:33 steve
900 * Add ivl and vvp.tgt support for memories in
901 * expressions and l-values. (Stephan Boettcher)
903 * Revision 1.28 2001/04/15 03:19:44 steve
904 * Oops, excessive test assert neets to be removed.
906 * Revision 1.27 2001/04/15 03:14:31 steve
907 * Handle noop as case statements.
909 * Revision 1.26 2001/04/15 02:58:11 steve
910 * vvp support for <= with internal delay.
912 * Revision 1.25 2001/04/07 19:26:32 steve
913 * Add the disable statemnent.
915 * Revision 1.24 2001/04/06 02:28:02 steve
916 * Generate vvp code for functions with ports.
918 * Revision 1.23 2001/04/05 03:20:57 steve
919 * Generate vvp code for the repeat statement.
921 * Revision 1.22 2001/04/04 04:50:35 steve
922 * Support forever loops in the tgt-vvp target.
924 * Revision 1.21 2001/04/03 04:50:37 steve
925 * Support non-blocking assignments.
927 * Revision 1.20 2001/04/02 02:28:12 steve
928 * Generate code for task calls.
930 * Revision 1.19 2001/04/01 06:52:28 steve
931 * support the NetWhile statement.
933 * Revision 1.18 2001/04/01 01:48:21 steve
934 * Redesign event information to support arbitrary edge combining.
936 * Revision 1.17 2001/03/31 17:36:39 steve
937 * Generate vvp code for case statements.
939 * Revision 1.16 2001/03/30 23:24:02 steve
940 * Make empty event sub-expression a noop.
942 * Revision 1.15 2001/03/30 05:49:52 steve
943 * Generate code for fork/join statements.
945 * Revision 1.14 2001/03/29 03:47:38 steve
946 * Behavioral trigger statements.
948 * Revision 1.13 2001/03/28 06:07:39 steve
949 * Add the ivl_event_t to ivl_target, and use that to generate
950 * .event statements in vvp way ahead of the thread that uses it.
952 * Revision 1.12 2001/03/27 06:27:40 steve
953 * Generate code for simple @ statements.
955 * Revision 1.11 2001/03/20 01:44:14 steve
956 * Put processes in the proper scope.
958 * Revision 1.10 2000/10/18 20:04:39 steve
959 * Add ivl_lval_t and support for assignment l-values.
961 * Revision 1.9 2000/10/08 04:01:54 steve
962 * Back pointers in the nexus objects into the devices
963 * that point to it.
965 * Collect threads into a list in the design.
967 * Revision 1.8 2000/10/06 23:46:50 steve
968 * ivl_target updates, including more complete
969 * handling of ivl_nexus_t objects. Much reduced
970 * dependencies on pointers to netlist objects.
972 * Revision 1.7 2000/10/05 05:03:01 steve
973 * xor and constant devices.
975 * Revision 1.6 2000/09/30 02:18:15 steve
976 * ivl_expr_t support for binary operators,
977 * Create a proper ivl_scope_t object.
979 * Revision 1.5 2000/09/26 00:30:07 steve
980 * Add EX_NUMBER and ST_TRIGGER to dll-api.
982 * Revision 1.4 2000/09/23 05:15:07 steve
983 * Add enough tgt-verilog code to support hello world.
985 * Revision 1.3 2000/09/22 03:58:30 steve
986 * Access to the name of a system task call.
988 * Revision 1.2 2000/09/19 04:15:27 steve
989 * Introduce the means to get statement types.
991 * Revision 1.1 2000/09/18 01:24:32 steve
992 * Get the structure for ivl_statement_t worked out.