1 /*
2  * Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
3  *
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.
9  *
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.
14  *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 # include "config.h"
21 
22 # include  <iostream>
23 
24 # include  <cstring>
25 # include  "t-dll.h"
26 # include  "netlist.h"
27 # include  "netclass.h"
28 # include  <cassert>
29 # include  <cstdlib>
30 # include  "ivl_alloc.h"
31 # include  "ivl_assert.h"
32 
33 /*
34  * This is a little convenience function for converting a NetExpr
35  * expression type to the expression type used by ivl_expr_t objects.
36  */
get_expr_type(const NetExpr * net)37 static ivl_variable_type_t get_expr_type(const NetExpr*net)
38 {
39       return net->expr_type();
40 }
41 
42 /*
43  * These methods implement the expression scan that generates the
44  * ivl_expr_t representing the expression. Each method leaves the
45  * expr_ member filled with the ivl_expr_t that represents it. Each
46  * method expects that the expr_ member empty (0) when it starts.
47  */
48 
49 /*
50  * This function takes an expression in the expr_ member that is
51  * already built up, and adds a subtraction of the given constant.
52  */
sub_off_from_expr_(long off)53 void dll_target::sub_off_from_expr_(long off)
54 {
55       assert(expr_ != 0);
56 
57       char*bits;
58       ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
59       tmpc->type_   = IVL_EX_NUMBER;
60       tmpc->value_  = IVL_VT_VECTOR;
61       tmpc->net_type= 0;
62       tmpc->width_  = expr_->width_;
63       tmpc->signed_ = expr_->signed_;
64       tmpc->sized_  = 1;
65       tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
66       for (unsigned idx = 0 ;  idx < tmpc->width_ ;  idx += 1) {
67 	    bits[idx] = (off & 1)? '1' : '0';
68 	    off >>= 1;
69       }
70 
71 	/* Now make the subtracter (x-4 in the above example)
72 	   that has as input A the index expression and input B
73 	   the constant to subtract. */
74       ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
75       tmps->type_  = IVL_EX_BINARY;
76       tmps->value_ = IVL_VT_VECTOR;
77       tmps->net_type= 0;
78       tmps->width_ = tmpc->width_;
79       tmps->signed_ = tmpc->signed_;
80       tmps->sized_ = 1;
81       tmps->u_.binary_.op_  = '-';
82       tmps->u_.binary_.lef_ = expr_;
83       tmps->u_.binary_.rig_ = tmpc;
84 
85 	/* Replace (x) with (x-off) */
86       expr_ = tmps;
87 }
88 
mul_expr_by_const_(long val)89 void dll_target::mul_expr_by_const_(long val)
90 {
91       assert(expr_ != 0);
92 
93       char*bits;
94       ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
95       tmpc->type_   = IVL_EX_NUMBER;
96       tmpc->value_  = IVL_VT_VECTOR;
97       tmpc->net_type= 0;
98       tmpc->width_  = expr_->width_;
99       tmpc->signed_ = expr_->signed_;
100       tmpc->sized_  = 1;
101       tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
102       for (unsigned idx = 0 ;  idx < tmpc->width_ ;  idx += 1) {
103 	    bits[idx] = (val & 1)? '1' : '0';
104 	    val >>= 1;
105       }
106 
107 	/* Now make the subtracter (x-4 in the above example)
108 	   that has as input A the index expression and input B
109 	   the constant to subtract. */
110       ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
111       tmps->type_  = IVL_EX_BINARY;
112       tmps->value_ = IVL_VT_VECTOR;
113       tmpc->net_type= 0;
114       tmps->width_ = tmpc->width_;
115       tmps->signed_ = tmpc->signed_;
116       tmps->sized_ = 1;
117       tmps->u_.binary_.op_  = '*';
118       tmps->u_.binary_.lef_ = expr_;
119       tmps->u_.binary_.rig_ = tmpc;
120 
121 	/* Replace (x) with (x*valf) */
122       expr_ = tmps;
123 }
124 
expr_from_value_(const verinum & val)125 ivl_expr_t dll_target::expr_from_value_(const verinum&val)
126 {
127       ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
128 
129       unsigned idx;
130       char*bits;
131       expr->type_ = IVL_EX_NUMBER;
132       expr->value_= IVL_VT_VECTOR;
133       expr->net_type=0;
134       expr->width_= val.len();
135       expr->signed_ = val.has_sign()? 1 : 0;
136       expr->sized_= 1;
137       expr->u_.number_.bits_ = bits = (char*)malloc(expr->width_ + 1);
138       for (idx = 0 ;  idx < expr->width_ ;  idx += 1)
139 	    switch (val.get(idx)) {
140 		case verinum::V0:
141 		  bits[idx] = '0';
142 		  break;
143 		case verinum::V1:
144 		  bits[idx] = '1';
145 		  break;
146 		case verinum::Vx:
147 		  bits[idx] = 'x';
148 		  break;
149 		case verinum::Vz:
150 		  bits[idx] = 'z';
151 		  break;
152 		default:
153 		  assert(0);
154 	    }
155 
156       bits[expr->width_] = 0;
157 
158       return expr;
159 }
160 
expr_access_func(const NetEAccess * net)161 void dll_target::expr_access_func(const NetEAccess*net)
162 {
163       assert(expr_ == 0);
164 	// Make a stub Branch Access Function expression node.
165       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
166       expr_->type_  = IVL_EX_BACCESS;
167       expr_->value_ = IVL_VT_REAL;
168       expr_->net_type=0;
169       expr_->width_ = 1;
170       expr_->signed_= 1;
171       expr_->sized_ = 1;
172       FILE_NAME(expr_, net);
173 
174       expr_->u_.branch_.branch = net->get_branch()->target_obj();
175       expr_->u_.branch_.nature = net->get_nature();
176 }
177 
expr_array_pattern(const NetEArrayPattern * net)178 void dll_target::expr_array_pattern(const NetEArrayPattern*net)
179 {
180       assert(expr_ == 0);
181       ivl_expr_t expr_tmp = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
182       expr_tmp->type_ = IVL_EX_ARRAY_PATTERN;
183       expr_tmp->value_= net->expr_type();
184       expr_tmp->net_type = net->net_type();
185       expr_tmp->width_   = 1;
186       expr_tmp->signed_  = 0;
187       expr_tmp->sized_   = 0;
188       FILE_NAME(expr_tmp, net);
189 
190       expr_tmp->u_.array_pattern_.parms = net->item_size();
191       expr_tmp->u_.array_pattern_.parm = new ivl_expr_t [net->item_size()];
192 
193       for (size_t idx = 0 ; idx < net->item_size() ; idx += 1) {
194 	    const NetExpr*tmp = net->item(idx);
195 	    tmp->expr_scan(this);
196 	    expr_tmp->u_.array_pattern_.parm[idx] = expr_;
197 	    expr_ = 0;
198       }
199 
200       expr_ = expr_tmp;
201 }
202 
expr_binary(const NetEBinary * net)203 void dll_target::expr_binary(const NetEBinary*net)
204 {
205       assert(expr_ == 0);
206 
207       net->left()->expr_scan(this);
208       ivl_expr_t left = expr_;
209 
210       expr_ = 0;
211       net->right()->expr_scan(this);
212       ivl_expr_t rght = expr_;
213 
214       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
215 
216       expr_->type_ = IVL_EX_BINARY;
217       expr_->value_= get_expr_type(net);
218       expr_->net_type=0;
219       expr_->width_= net->expr_width();
220       expr_->signed_ = net->has_sign()? 1 : 0;
221       expr_->sized_= 1;
222       FILE_NAME(expr_, net);
223 
224       expr_->u_.binary_.op_ = net->op();
225       expr_->u_.binary_.lef_ = left;
226       expr_->u_.binary_.rig_ = rght;
227 }
228 
expr_concat(const NetEConcat * net)229 void dll_target::expr_concat(const NetEConcat*net)
230 {
231       assert(expr_ == 0);
232 
233       ivl_expr_t cur = new struct ivl_expr_s;
234       assert(cur);
235 
236       cur->type_  = IVL_EX_CONCAT;
237       cur->value_ = net->expr_type();
238       cur->net_type=0;
239       cur->width_ = net->expr_width();
240       cur->signed_ = net->has_sign() ? 1 : 0;
241       cur->sized_ = 1;
242       FILE_NAME(cur, net);
243 
244       cur->u_.concat_.rept  = net->repeat();
245       cur->u_.concat_.parms = net->nparms();
246       cur->u_.concat_.parm  = new ivl_expr_t [net->nparms()];
247 
248       for (unsigned idx = 0 ;  idx < net->nparms() ;  idx += 1) {
249 	    expr_ = 0;
250 	    net->parm(idx)->expr_scan(this);
251 	    assert(expr_);
252 	    cur->u_.concat_.parm[idx] = expr_;
253       }
254 
255       expr_ = cur;
256 }
257 
expr_const(const NetEConst * net)258 void dll_target::expr_const(const NetEConst*net)
259 {
260       assert(expr_ == 0);
261 
262       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
263       expr_->value_= net->expr_type();
264       expr_->net_type=0;
265       FILE_NAME(expr_, net);
266 
267       if (net->value().is_string()) {
268 	    expr_->type_ = IVL_EX_STRING;
269 	    expr_->width_= net->expr_width();
270 	    expr_->u_.string_.value_ =strdup(net->value().as_string().c_str());
271 
272       } else {
273 	    verinum val = net->value();
274 	    unsigned idx;
275 	    char*bits;
276 	    expr_->type_ = IVL_EX_NUMBER;
277 	    expr_->width_= net->expr_width();
278 	    expr_->signed_ = net->has_sign()? 1 : 0;
279 	    expr_->sized_= net->has_width()? 1 : 0;
280 	    expr_->u_.number_.bits_ = bits = (char*)malloc(expr_->width_);
281 	    for (idx = 0 ;  idx < expr_->width_ ;  idx += 1)
282 		  switch (val.get(idx)) {
283 		      case verinum::V0:
284 			bits[idx] = '0';
285 			break;
286 		      case verinum::V1:
287 			bits[idx] = '1';
288 			break;
289 		      case verinum::Vx:
290 			bits[idx] = 'x';
291 			break;
292 		      case verinum::Vz:
293 			bits[idx] = 'z';
294 			break;
295 		      default:
296 			assert(0);
297 		  }
298 
299       }
300 }
301 
expr_param(const NetEConstParam * net)302 void dll_target::expr_param(const NetEConstParam*net)
303 {
304       ivl_scope_t scop = find_scope(des_, net->scope());
305       ivl_parameter_t par = scope_find_param(scop, net->name());
306 
307       if (par == 0) {
308 	    cerr << net->get_fileline() << ": internal error: "
309 		 << "Parameter " << net->name() << " missing from "
310 		 << ivl_scope_name(scop) << endl;
311       }
312       assert(par);
313       expr_const(net);
314       expr_->u_.string_.parameter = par;
315 }
316 
expr_rparam(const NetECRealParam * net)317 void dll_target::expr_rparam(const NetECRealParam*net)
318 {
319       ivl_scope_t scop = find_scope(des_, net->scope());
320       ivl_parameter_t par = scope_find_param(scop, net->name());
321 
322       if (par == 0) {
323 	    cerr << net->get_fileline() << ": internal error: "
324 		 << "Parameter " << net->name() << " missing from "
325 		 << ivl_scope_name(scop) << endl;
326       }
327       assert(par);
328       assert(par->value);
329       expr_ = par->value;
330 }
331 
expr_creal(const NetECReal * net)332 void dll_target::expr_creal(const NetECReal*net)
333 {
334       assert(expr_ == 0);
335       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
336       expr_->width_  = net->expr_width();
337       expr_->signed_ = 1;
338       expr_->sized_  = 1;
339       expr_->type_ = IVL_EX_REALNUM;
340       FILE_NAME(expr_, net);
341       expr_->value_= IVL_VT_REAL;
342       expr_->net_type=0;
343       expr_->u_.real_.value = net->value().as_double();
344 }
345 
expr_last(const NetELast * net)346 void dll_target::expr_last(const NetELast*net)
347 {
348       assert(expr_ == 0);
349       ivl_expr_t expr = new struct ivl_expr_s;
350       expr->type_   = IVL_EX_SFUNC;
351       expr->value_  = IVL_VT_LOGIC;
352       expr->width_  = 32;
353       expr->signed_ = 1;
354       expr->sized_  = 1;
355       expr->net_type  = 0;
356       FILE_NAME(expr, net);
357 
358       expr->u_.sfunc_.name_ = "$high";
359 
360       ivl_signal_t sig = find_signal(des_, net->sig());
361 
362       ivl_expr_t esig = new struct ivl_expr_s;
363       esig->type_   = IVL_EX_SIGNAL;
364       esig->value_  = IVL_VT_DARRAY;
365       esig->net_type= sig->net_type;
366       esig->width_  = 1;
367       esig->signed_ = sig->net_type->get_signed()? 1 : 0;
368       FILE_NAME(esig, net);
369       esig->u_.signal_.word = 0;
370       esig->u_.signal_.sig = sig;
371 
372       expr->u_.sfunc_.parms = 1;
373       expr->u_.sfunc_.parm = new ivl_expr_t[1];
374       expr->u_.sfunc_.parm[0] = esig;
375 
376       expr_ = expr;
377 }
378 
expr_new(const NetENew * net)379 void dll_target::expr_new(const NetENew*net)
380 {
381       ivl_expr_t size = 0;
382       ivl_expr_t init_val = 0;
383 
384       if (net->size_expr()) {
385 	    net->size_expr()->expr_scan(this);
386 	    size = expr_;
387 	    expr_ = 0;
388       }
389 
390       if (net->init_expr()) {
391 	    net->init_expr()->expr_scan(this);
392 	    init_val = expr_;
393 	    expr_ = 0;
394       }
395 
396       assert(expr_ == 0);
397       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
398       expr_->width_  = net->expr_width();
399       expr_->signed_ = 0;
400       expr_->sized_  = 1;
401       expr_->type_   = IVL_EX_NEW;
402       FILE_NAME(expr_, net);
403       expr_->value_  = net->expr_type(); // May be IVL_VT_DARRAY or _CLASS
404       expr_->net_type= net->get_type();
405       expr_->u_.new_.size = size;
406       expr_->u_.new_.init_val = init_val;
407 }
408 
expr_null(const NetENull * net)409 void dll_target::expr_null(const NetENull*net)
410 {
411       assert(expr_ == 0);
412       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
413       expr_->width_  = net->expr_width();
414       expr_->signed_ = 0;
415       expr_->sized_  = 1;
416       expr_->type_   = IVL_EX_NULL;
417       FILE_NAME(expr_, net);
418       expr_->value_  = IVL_VT_CLASS;
419       expr_->net_type= 0;
420 }
421 
expr_property(const NetEProperty * net)422 void dll_target::expr_property(const NetEProperty*net)
423 {
424       ivl_expr_t index = 0;
425       if (const NetExpr*index_expr = net->get_index()) {
426 	    index_expr->expr_scan(this);
427 	    index = expr_;
428 	    expr_ = 0;
429       }
430       assert(expr_ == 0);
431       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
432       expr_->width_  = net->expr_width();
433       expr_->signed_ = net->has_sign();
434       expr_->sized_  = 1;
435       expr_->type_   = IVL_EX_PROPERTY;
436       FILE_NAME(expr_, net);
437       expr_->value_  = net->expr_type();
438       expr_->net_type= net->net_type();
439       expr_->u_.property_.sig = find_signal(des_, net->get_sig());
440       expr_->u_.property_.prop_idx = net->property_idx();
441       expr_->u_.property_.index = index;
442 }
443 
expr_event(const NetEEvent * net)444 void dll_target::expr_event(const NetEEvent*net)
445 {
446       assert(expr_ == 0);
447 
448       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
449 
450       expr_->type_ = IVL_EX_EVENT;
451       FILE_NAME(expr_, net);
452       expr_->value_= IVL_VT_VOID;
453       expr_->net_type=0;
454 
455         /* Locate the event by name. Save the ivl_event_t in the
456            expression so that the generator can find it easily. */
457       const NetEvent*ev = net->event();
458       ivl_scope_t ev_scope = lookup_scope_(ev->scope());
459 
460       for (unsigned idx = 0 ;  idx < ev_scope->nevent_ ;  idx += 1) {
461             const char*ename = ivl_event_basename(ev_scope->event_[idx]);
462             if (strcmp(ev->name(), ename) == 0) {
463                   expr_->u_.event_.event = ev_scope->event_[idx];
464                   break;
465             }
466       }
467 }
468 
expr_scope(const NetEScope * net)469 void dll_target::expr_scope(const NetEScope*net)
470 {
471       assert(expr_ == 0);
472 
473       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
474 
475       expr_->type_ = IVL_EX_SCOPE;
476       FILE_NAME(expr_, net);
477       expr_->value_= IVL_VT_VOID;
478       expr_->net_type=0;
479       expr_->u_.scope_.scope = lookup_scope_(net->scope());
480 }
481 
expr_scopy(const NetEShallowCopy * net)482 void dll_target::expr_scopy(const NetEShallowCopy*net)
483 {
484       assert(expr_ == 0);
485 
486       net->expr_scan_oper1(this);
487       ivl_expr_t expr1 = expr_;
488       expr_ = 0;
489 
490       net->expr_scan_oper2(this);
491       ivl_expr_t expr2 = expr_;
492       expr_ = 0;
493 
494       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
495       expr_->type_ = IVL_EX_SHALLOWCOPY;
496       FILE_NAME(expr_, net);
497       expr_->value_ = net->expr_type();
498       expr_->net_type = net->net_type();
499 
500       expr_->u_.shallow_.dest = expr1;
501       expr_->u_.shallow_.src  = expr2;
502 }
503 
expr_netenum(const NetENetenum * net)504 void dll_target::expr_netenum(const NetENetenum*net)
505 {
506       assert(expr_ == 0);
507 
508       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
509 
510       expr_->type_ = IVL_EX_ENUMTYPE;
511       FILE_NAME(expr_, net);
512       expr_->value_= IVL_VT_VOID;
513       expr_->net_type=0;
514       expr_->u_.enumtype_.type = net->netenum();
515 }
516 
expr_select(const NetESelect * net)517 void dll_target::expr_select(const NetESelect*net)
518 {
519       assert(expr_ == 0);
520 
521       net->sub_expr()->expr_scan(this);
522       ivl_expr_t expr = expr_;
523 
524       expr_ = 0;
525       if (net->select())
526 	    net->select()->expr_scan(this);
527 
528       ivl_expr_t base = expr_;
529 
530       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
531 
532       expr_->type_ = IVL_EX_SELECT;
533       expr_->value_= net->expr_type();
534       expr_->net_type=0;
535       expr_->width_= net->expr_width();
536       expr_->signed_ = net->has_sign()? 1 : 0;
537       expr_->sized_= 1;
538       FILE_NAME(expr_, net);
539 
540       expr_->u_.select_.sel_type_ = net->select_type();
541       expr_->u_.select_.expr_ = expr;
542       expr_->u_.select_.base_ = base;
543 }
544 
expr_sfunc(const NetESFunc * net)545 void dll_target::expr_sfunc(const NetESFunc*net)
546 {
547       assert(expr_ == 0);
548 
549       ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
550 
551       expr->type_ = IVL_EX_SFUNC;
552       expr->value_= net->expr_type();
553       expr->net_type=net->net_type();
554       expr->width_= net->expr_width();
555       expr->signed_ = net->has_sign()? 1 : 0;
556       expr->sized_= 1;
557       FILE_NAME(expr, net);
558 	/* system function names are lex_strings strings. */
559       expr->u_.sfunc_.name_ = net->name();
560 
561       unsigned cnt = net->nparms();
562       expr->u_.sfunc_.parms = cnt;
563       expr->u_.sfunc_.parm = new ivl_expr_t[cnt];
564 
565 	/* make up the parameter expressions. */
566       for (unsigned idx = 0 ;  idx < cnt ;  idx += 1) {
567 	    net->parm(idx)->expr_scan(this);
568 	    assert(expr_);
569 	    expr->u_.sfunc_.parm[idx] = expr_;
570 	    expr_ = 0;
571       }
572 
573       expr_ = expr;
574 }
575 
expr_ternary(const NetETernary * net)576 void dll_target::expr_ternary(const NetETernary*net)
577 {
578       assert(expr_ == 0);
579 
580       ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
581 
582       expr->type_  = IVL_EX_TERNARY;
583       expr->value_= net->expr_type();
584       expr->net_type=0;
585       expr->width_ = net->expr_width();
586       expr->signed_ = net->has_sign()? 1 : 0;
587       expr->sized_ = 1;
588       FILE_NAME(expr, net);
589 
590       net->cond_expr()->expr_scan(this);
591       assert(expr_);
592       expr->u_.ternary_.cond = expr_;
593       expr_ = 0;
594 
595       net->true_expr()->expr_scan(this);
596       assert(expr_);
597       expr->u_.ternary_.true_e = expr_;
598       expr_ = 0;
599 
600       net->false_expr()->expr_scan(this);
601       assert(expr_);
602       expr->u_.ternary_.false_e = expr_;
603 
604       expr_ = expr;
605 }
606 
expr_signal(const NetESignal * net)607 void dll_target::expr_signal(const NetESignal*net)
608 {
609       ivl_signal_t sig = find_signal(des_, net->sig());
610 
611       assert(expr_ == 0);
612 
613 	/* If there is a word expression, generate it. */
614       ivl_expr_t word_expr = 0;
615       if (const NetExpr*word = net->word_index()) {
616 	    word->expr_scan(this);
617 	    assert(expr_);
618 	    word_expr = expr_;
619 	    expr_ = 0;
620       }
621 
622       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
623 
624       expr_->type_ = IVL_EX_SIGNAL;
625       expr_->value_= net->expr_type();
626       expr_->net_type=0;
627       expr_->width_= net->expr_width();
628       expr_->signed_ = net->has_sign()? 1 : 0;
629       expr_->sized_= 1;
630       FILE_NAME(expr_, net);
631       expr_->u_.signal_.word = word_expr;
632       expr_->u_.signal_.sig = sig;
633 
634 	/* Make account for the special case that this is a reference
635 	   to an array as a whole. We detect this case by noting that
636 	   this is an array (more than 0 array dimensions) and that
637 	   there is no word select expression. For this case, we have
638 	   an IVL_EX_ARRAY expression instead of a SIGNAL expression. */
639       if (sig->array_dimensions_ > 0 && word_expr == 0) {
640 	    expr_->type_ = IVL_EX_ARRAY;
641 	    expr_->width_ = 0; // Doesn't make much sense for arrays.
642       }
643 }
644 
645 
expr_ufunc(const NetEUFunc * net)646 void dll_target::expr_ufunc(const NetEUFunc*net)
647 {
648       assert(expr_ == 0);
649 
650       ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
651 
652       expr->type_ = IVL_EX_UFUNC;
653       expr->value_= net->expr_type();
654       expr->net_type=0;
655       expr->width_= net->expr_width();
656       expr->signed_ = net->has_sign()? 1 : 0;
657       expr->sized_= 1;
658       FILE_NAME(expr, net);
659 
660       expr->u_.ufunc_.def = lookup_scope_(net->func());
661       if (expr->u_.ufunc_.def == 0) {
662 	    cerr << net->get_fileline() << ": internal error: "
663 		 << "dll_target::expr_ufunc: "
664 		 << "Unable to match scope " << scope_path(net->func()) << endl;
665       }
666       ivl_assert(*net, expr->u_.ufunc_.def);
667       ivl_assert(*net, expr->u_.ufunc_.def->type_ == IVL_SCT_FUNCTION);
668 
669       unsigned cnt = net->parm_count();
670       expr->u_.ufunc_.parms = cnt;
671       expr->u_.ufunc_.parm = new ivl_expr_t[cnt];
672 
673 	/* make up the parameter expressions. */
674       for (unsigned idx = 0 ;  idx < cnt ;  idx += 1) {
675 	    net->parm(idx)->expr_scan(this);
676 	    assert(expr_);
677 	    expr->u_.ufunc_.parm[idx] = expr_;
678 	    expr_ = 0;
679       }
680 
681       expr_ = expr;
682 }
683 
expr_unary(const NetEUnary * net)684 void dll_target::expr_unary(const NetEUnary*net)
685 {
686       assert(expr_ == 0);
687 
688       net->expr()->expr_scan(this);
689       assert(expr_);
690 
691       ivl_expr_t sub = expr_;
692 
693       expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
694       expr_->type_ = IVL_EX_UNARY;
695       expr_->value_= net->expr_type();
696       expr_->net_type=0;
697       expr_->width_ = net->expr_width();
698       expr_->signed_ = net->has_sign()? 1 : 0;
699       expr_->sized_ = 1;
700       FILE_NAME(expr_, net);
701       expr_->u_.unary_.op_ = net->op();
702       expr_->u_.unary_.sub_ = sub;
703 }
704