1 /*
2  * Copyright (c) 2000-2015 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  "netlist.h"
23 # include  "netclass.h"
24 # include  "netdarray.h"
25 # include  "netenum.h"
26 # include  "ivl_assert.h"
27 
28 /*
29  * NetAssign
30  */
31 
count_lval_width(const NetAssign_ * idx)32 unsigned count_lval_width(const NetAssign_*idx)
33 {
34       unsigned wid = 0;
35       while (idx) {
36 	    wid += idx->lwidth();
37 	    idx = idx->more;
38       }
39       return wid;
40 }
41 
NetAssign_(NetAssign_ * n)42 NetAssign_::NetAssign_(NetAssign_*n)
43 : nest_(n), sig_(0), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
44 {
45       lwid_ = 0;
46       more = 0;
47       signed_ = false;
48       turn_sig_to_wire_on_release_ = false;
49 }
50 
NetAssign_(NetNet * s)51 NetAssign_::NetAssign_(NetNet*s)
52 : nest_(0), sig_(s), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
53 {
54       lwid_ = sig_->vector_width();
55       sig_->incr_lref();
56       more = 0;
57       signed_ = false;
58       turn_sig_to_wire_on_release_ = false;
59 }
60 
~NetAssign_()61 NetAssign_::~NetAssign_()
62 {
63       if (sig_) {
64 	    sig_->decr_lref();
65 	    if (turn_sig_to_wire_on_release_ && sig_->peek_lref() == 0)
66 		  sig_->type(NetNet::WIRE);
67       }
68 
69       assert( more == 0 );
70       delete word_;
71 }
72 
get_fileline() const73 string NetAssign_::get_fileline() const
74 {
75       if (sig_) return sig_->get_fileline();
76       else return nest_->get_fileline();
77 }
78 
scope() const79 NetScope*NetAssign_::scope() const
80 {
81       if (sig_) return sig_->scope();
82       else return nest_->scope();
83 }
84 
set_word(NetExpr * r)85 void NetAssign_::set_word(NetExpr*r)
86 {
87       assert(word_ == 0);
88       word_ = r;
89 }
90 
word()91 NetExpr* NetAssign_::word()
92 {
93       return word_;
94 }
95 
word() const96 const NetExpr* NetAssign_::word() const
97 {
98       return word_;
99 }
100 
get_base() const101 const NetExpr* NetAssign_::get_base() const
102 {
103       return base_;
104 }
105 
select_type() const106 ivl_select_type_t NetAssign_::select_type() const
107 {
108       return sel_type_;
109 }
110 
lwidth() const111 unsigned NetAssign_::lwidth() const
112 {
113 	// This gets me the type of the l-value expression, down to
114 	// the type of the member. If this returns nil, then resort to
115 	// the lwid_ value.
116       ivl_type_t ntype = net_type();
117       if (ntype == 0)
118 	    return lwid_;
119 
120 	// If the type is a darray, and there is a word index, then we
121 	// actually want the width of the elements.
122       if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (ntype)) {
123 	    if (word_ == 0)
124 		  return 1;
125 	    else
126 		  return darray->element_width();
127       }
128 
129       return ntype->packed_width();
130 }
131 
expr_type() const132 ivl_variable_type_t NetAssign_::expr_type() const
133 {
134       ivl_type_t ntype = net_type();
135       if (const netdarray_t*darray = dynamic_cast<const netdarray_t*>(ntype)) {
136 	    if (word_ == 0)
137 		  return IVL_VT_DARRAY;
138 	    else
139 		  return darray->element_base_type();
140       }
141 
142       if (sig_ && sig_->data_type()==IVL_VT_STRING && base_!=0)
143 	    return IVL_VT_BOOL;
144 
145       if (ntype) return ntype->base_type();
146 
147       ivl_assert(*this, sig_);
148       return sig_->data_type();
149 }
150 
net_type() const151 const ivl_type_s* NetAssign_::net_type() const
152 {
153       if (nest_) {
154 	    const ivl_type_s*ntype = nest_->net_type();
155 	    if (member_.nil())
156 		  return ntype;
157 
158 	    if (const netclass_t*class_type = dynamic_cast<const netclass_t*>(ntype)) {
159 		  int pidx = class_type->property_idx_from_name(member_);
160 		  ivl_assert(*this, pidx >= 0);
161 		  ivl_type_t tmp = class_type->get_prop_type(pidx);
162 		  return tmp;
163 	    }
164 
165 	    if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (ntype)) {
166 		  if (word_ == 0)
167 			return ntype;
168 		  else
169 			return darray->element_type();
170 	    }
171 
172 	    return 0;
173       }
174 
175       if (const netclass_t*class_type = sig_->class_type()) {
176 	    if (member_.nil())
177 		  return sig_->net_type();
178 
179 	    int pidx = class_type->property_idx_from_name(member_);
180 	    ivl_assert(*sig_, pidx >= 0);
181 	    ivl_type_t tmp = class_type->get_prop_type(pidx);
182 	    return tmp;
183       }
184 
185       if (const netdarray_t*darray = dynamic_cast<const netdarray_t*> (sig_->net_type())) {
186 	    if (word_ == 0)
187 		  return sig_->net_type();
188 	    else
189 		  return darray->element_type();
190       }
191 
192       return 0;
193 }
194 
enumeration() const195 const netenum_t*NetAssign_::enumeration() const
196 {
197       const netenum_t*tmp = 0;
198       ivl_type_t ntype = net_type();
199       if (ntype == 0) {
200 
201 	    ivl_assert(*this, sig_);
202 
203 	      // If the base signal is not an enumeration, return nil.
204 	    if ( (tmp = sig_->enumeration()) == 0 )
205 		  return 0;
206 
207       } else {
208 	    tmp = dynamic_cast<const netenum_t*>(ntype);
209 	    if (tmp == 0)
210 		  return 0;
211       }
212 
213 	// Part select of an enumeration is not an enumeration.
214       if (base_ != 0)
215 	    return 0;
216 
217 	// Concatenation of enumerations is not an enumeration.
218       if (more != 0)
219 	    return 0;
220 
221       return tmp;
222 }
223 
name() const224 perm_string NetAssign_::name() const
225 {
226       if (sig_) {
227 	    return sig_->name();
228       } else {
229 	    return perm_string::literal("");
230       }
231 }
232 
sig() const233 NetNet* NetAssign_::sig() const
234 {
235       assert(sig_? nest_==0 : nest_!=0);
236       return sig_;
237 }
238 
set_part(NetExpr * base,unsigned wid,ivl_select_type_t sel_type)239 void NetAssign_::set_part(NetExpr*base, unsigned wid,
240                           ivl_select_type_t sel_type)
241 {
242       base_ = base;
243       lwid_ = wid;
244       sel_type_ = sel_type;
245 }
246 
set_property(const perm_string & mname)247 void NetAssign_::set_property(const perm_string&mname)
248 {
249 	//ivl_assert(*sig_, sig_->class_type());
250       member_ = mname;
251 }
252 
253 /*
254  */
turn_sig_to_wire_on_release()255 void NetAssign_::turn_sig_to_wire_on_release()
256 {
257       turn_sig_to_wire_on_release_ = true;
258 }
259 
NetAssignBase(NetAssign_ * lv,NetExpr * rv)260 NetAssignBase::NetAssignBase(NetAssign_*lv, NetExpr*rv)
261 : lval_(lv), rval_(rv), delay_(0)
262 {
263 }
264 
~NetAssignBase()265 NetAssignBase::~NetAssignBase()
266 {
267       delete rval_;
268       while (lval_) {
269 	    NetAssign_*tmp = lval_;
270 	    lval_ = tmp->more;
271 	    tmp->more = 0;
272 	    delete tmp;
273       }
274 }
275 
rval()276 NetExpr* NetAssignBase::rval()
277 {
278       return rval_;
279 }
280 
rval() const281 const NetExpr* NetAssignBase::rval() const
282 {
283       return rval_;
284 }
285 
set_rval(NetExpr * r)286 void NetAssignBase::set_rval(NetExpr*r)
287 {
288       delete rval_;
289       rval_ = r;
290 }
291 
l_val(unsigned idx)292 NetAssign_* NetAssignBase::l_val(unsigned idx)
293 {
294       NetAssign_*cur = lval_;
295       while (idx > 0) {
296 	    if (cur == 0)
297 		  return cur;
298 
299 	    cur = cur->more;
300 	    idx -= 1;
301       }
302 
303       assert(idx == 0);
304       return cur;
305 }
306 
l_val(unsigned idx) const307 const NetAssign_* NetAssignBase::l_val(unsigned idx) const
308 {
309       const NetAssign_*cur = lval_;
310       while (idx > 0) {
311 	    if (cur == 0)
312 		  return cur;
313 
314 	    cur = cur->more;
315 	    idx -= 1;
316       }
317 
318       assert(idx == 0);
319       return cur;
320 }
321 
l_val_count() const322 unsigned NetAssignBase::l_val_count() const
323 {
324       const NetAssign_*cur = lval_;
325       unsigned cnt = 0;
326       while (cur) {
327 	    cnt += 1;
328 	    cur = cur->more;
329       }
330 
331       return cnt;
332 }
333 
lwidth() const334 unsigned NetAssignBase::lwidth() const
335 {
336       unsigned sum = 0;
337       for (NetAssign_*cur = lval_ ;  cur ;  cur = cur->more)
338 	    sum += cur->lwidth();
339       return sum;
340 }
341 
set_delay(NetExpr * expr)342 void NetAssignBase::set_delay(NetExpr*expr)
343 {
344       delay_ = expr;
345 }
346 
get_delay() const347 const NetExpr* NetAssignBase::get_delay() const
348 {
349       return delay_;
350 }
351 
NetAssign(NetAssign_ * lv,NetExpr * rv)352 NetAssign::NetAssign(NetAssign_*lv, NetExpr*rv)
353 : NetAssignBase(lv, rv), op_(0)
354 {
355 }
356 
NetAssign(NetAssign_ * lv,char op,NetExpr * rv)357 NetAssign::NetAssign(NetAssign_*lv, char op, NetExpr*rv)
358 : NetAssignBase(lv, rv), op_(op)
359 {
360 }
361 
~NetAssign()362 NetAssign::~NetAssign()
363 {
364 }
365 
NetAssignNB(NetAssign_ * lv,NetExpr * rv,NetEvWait * ev,NetExpr * cnt)366 NetAssignNB::NetAssignNB(NetAssign_*lv, NetExpr*rv, NetEvWait*ev, NetExpr*cnt)
367 : NetAssignBase(lv, rv)
368 {
369       event_ = ev;
370       count_ = cnt;
371 }
372 
~NetAssignNB()373 NetAssignNB::~NetAssignNB()
374 {
375 }
376 
nevents() const377 unsigned NetAssignNB::nevents() const
378 {
379       if (event_) return event_->nevents();
380       return 0;
381 }
382 
event(unsigned idx) const383 const NetEvent*NetAssignNB::event(unsigned idx) const
384 {
385       if (event_) return event_->event(idx);
386       return 0;
387 }
388 
get_count() const389 const NetExpr*NetAssignNB::get_count() const
390 {
391       return count_;
392 }
393 
NetCAssign(NetAssign_ * lv,NetExpr * rv)394 NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
395 : NetAssignBase(lv, rv)
396 {
397 }
398 
~NetCAssign()399 NetCAssign::~NetCAssign()
400 {
401 }
402 
NetDeassign(NetAssign_ * l)403 NetDeassign::NetDeassign(NetAssign_*l)
404 : NetAssignBase(l, 0)
405 {
406 }
407 
~NetDeassign()408 NetDeassign::~NetDeassign()
409 {
410 }
411 
NetForce(NetAssign_ * lv,NetExpr * rv)412 NetForce::NetForce(NetAssign_*lv, NetExpr*rv)
413 : NetAssignBase(lv, rv)
414 {
415 }
416 
~NetForce()417 NetForce::~NetForce()
418 {
419 }
420 
NetRelease(NetAssign_ * l)421 NetRelease::NetRelease(NetAssign_*l)
422 : NetAssignBase(l, 0)
423 {
424 }
425 
~NetRelease()426 NetRelease::~NetRelease()
427 {
428 }
429