1 /*
2 * Copyright (c) 1998-2020 Stephen Williams <steve@icarus.com>
3 * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
4 *
5 * This source code is free software; you can redistribute it
6 * and/or modify it in source code form under the terms of the GNU
7 * General Public License as published by the Free Software
8 * Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
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.
15 *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 # include "config.h"
22
23 # include <iostream>
24
25 # include "compiler.h"
26 # include "PExpr.h"
27 # include "PWire.h"
28 # include "Module.h"
29 # include "netmisc.h"
30 # include "util.h"
31 # include <typeinfo>
32
PExpr()33 PExpr::PExpr()
34 {
35 expr_type_ = IVL_VT_NO_TYPE;
36 expr_width_ = 0;
37 min_width_ = 0;
38 signed_flag_ = false;
39 }
40
~PExpr()41 PExpr::~PExpr()
42 {
43 }
44
declare_implicit_nets(LexicalScope *,NetNet::Type)45 void PExpr::declare_implicit_nets(LexicalScope*, NetNet::Type)
46 {
47 }
48
has_aa_term(Design *,NetScope *) const49 bool PExpr::has_aa_term(Design*, NetScope*) const
50 {
51 return false;
52 }
53
is_the_same(const PExpr * that) const54 bool PExpr::is_the_same(const PExpr*that) const
55 {
56 return typeid(this) == typeid(that);
57 }
58
elaborate_lnet(Design *,NetScope *) const59 NetNet* PExpr::elaborate_lnet(Design*, NetScope*) const
60 {
61 cerr << get_fileline() << ": error: "
62 << "expression not valid in assign l-value: "
63 << *this << endl;
64 return 0;
65 }
66
elaborate_bi_net(Design *,NetScope *) const67 NetNet* PExpr::elaborate_bi_net(Design*, NetScope*) const
68 {
69 cerr << get_fileline() << ": error: "
70 << "expression not valid as argument to inout port: "
71 << *this << endl;
72 return 0;
73 }
74
is_collapsible_net(Design *,NetScope *) const75 bool PExpr::is_collapsible_net(Design*, NetScope*) const
76 {
77 return false;
78 }
79
80
width_mode_name(width_mode_t mode)81 const char* PExpr::width_mode_name(width_mode_t mode)
82 {
83 switch (mode) {
84 case PExpr::SIZED:
85 return "sized";
86 case PExpr::UNSIZED:
87 return "unsized";
88 case PExpr::EXPAND:
89 return "expand";
90 case PExpr::LOSSLESS:
91 return "lossless";
92 case PExpr::UPSIZE:
93 return "upsize";
94 default:
95 return "??";
96 }
97 }
98
PEAssignPattern()99 PEAssignPattern::PEAssignPattern()
100 {
101 }
102
PEAssignPattern(const list<PExpr * > & p)103 PEAssignPattern::PEAssignPattern(const list<PExpr*>&p)
104 : parms_(p.size())
105 {
106 size_t idx = 0;
107 for (list<PExpr*>::const_iterator cur = p.begin()
108 ; cur != p.end() ; ++cur) {
109 parms_[idx] = *cur;
110 idx += 1;
111 }
112 }
113
~PEAssignPattern()114 PEAssignPattern::~PEAssignPattern()
115 {
116 }
117
PEBinary(char op,PExpr * l,PExpr * r)118 PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
119 : op_(op), left_(l), right_(r)
120 {
121 }
122
~PEBinary()123 PEBinary::~PEBinary()
124 {
125 }
126
declare_implicit_nets(LexicalScope * scope,NetNet::Type type)127 void PEBinary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
128 {
129 if (left_) left_->declare_implicit_nets(scope, type);
130 if (right_) right_->declare_implicit_nets(scope, type);
131 }
132
has_aa_term(Design * des,NetScope * scope) const133 bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
134 {
135 assert(left_ && right_);
136 return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
137 }
138
PECastSize(PExpr * si,PExpr * b)139 PECastSize::PECastSize(PExpr*si, PExpr*b)
140 : size_(si), base_(b)
141 {
142 }
143
~PECastSize()144 PECastSize::~PECastSize()
145 {
146 }
147
PECastType(data_type_t * t,PExpr * b)148 PECastType::PECastType(data_type_t*t, PExpr*b)
149 : target_(t), base_(b)
150 {
151 }
152
~PECastType()153 PECastType::~PECastType()
154 {
155 }
156
PEBComp(char op,PExpr * l,PExpr * r)157 PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
158 : PEBinary(op, l, r)
159 {
160 l_width_ = 0;
161 r_width_ = 0;
162 }
163
~PEBComp()164 PEBComp::~PEBComp()
165 {
166 }
167
PEBLogic(char op,PExpr * l,PExpr * r)168 PEBLogic::PEBLogic(char op, PExpr*l, PExpr*r)
169 : PEBinary(op, l, r)
170 {
171 assert(op == 'a' || op == 'o' || op == 'q' || op == 'Q');
172 }
173
~PEBLogic()174 PEBLogic::~PEBLogic()
175 {
176 }
177
PEBLeftWidth(char op,PExpr * l,PExpr * r)178 PEBLeftWidth::PEBLeftWidth(char op, PExpr*l, PExpr*r)
179 : PEBinary(op, l, r)
180 {
181 }
182
~PEBLeftWidth()183 PEBLeftWidth::~PEBLeftWidth()
184 {
185 }
186
PEBPower(char op,PExpr * l,PExpr * r)187 PEBPower::PEBPower(char op, PExpr*l, PExpr*r)
188 : PEBLeftWidth(op, l, r)
189 {
190 }
191
~PEBPower()192 PEBPower::~PEBPower()
193 {
194 }
195
PEBShift(char op,PExpr * l,PExpr * r)196 PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
197 : PEBLeftWidth(op, l, r)
198 {
199 }
200
~PEBShift()201 PEBShift::~PEBShift()
202 {
203 }
204
PECallFunction(const pform_name_t & n,const vector<PExpr * > & parms)205 PECallFunction::PECallFunction(const pform_name_t&n, const vector<PExpr *> &parms)
206 : package_(0), path_(n), parms_(parms), is_overridden_(false)
207 {
208 }
209
PECallFunction(PPackage * pkg,const pform_name_t & n,const vector<PExpr * > & parms)210 PECallFunction::PECallFunction(PPackage*pkg, const pform_name_t&n, const vector<PExpr *> &parms)
211 : package_(pkg), path_(n), parms_(parms), is_overridden_(false)
212 {
213 }
214
pn_from_ps(perm_string n)215 static pform_name_t pn_from_ps(perm_string n)
216 {
217 name_component_t tmp_name (n);
218 pform_name_t tmp;
219 tmp.push_back(tmp_name);
220 return tmp;
221 }
222
PECallFunction(PPackage * pkg,perm_string n,const list<PExpr * > & parms)223 PECallFunction::PECallFunction(PPackage*pkg, perm_string n, const list<PExpr *> &parms)
224 : package_(pkg), path_(pn_from_ps(n)), parms_(parms.size()), is_overridden_(false)
225 {
226 int tmp_idx = 0;
227 assert(parms_.size() == parms.size());
228 for (list<PExpr*>::const_iterator idx = parms.begin()
229 ; idx != parms.end() ; ++idx)
230 parms_[tmp_idx++] = *idx;
231 }
232
PECallFunction(perm_string n,const vector<PExpr * > & parms)233 PECallFunction::PECallFunction(perm_string n, const vector<PExpr*>&parms)
234 : package_(0), path_(pn_from_ps(n)), parms_(parms), is_overridden_(false)
235 {
236 }
237
PECallFunction(perm_string n)238 PECallFunction::PECallFunction(perm_string n)
239 : package_(0), path_(pn_from_ps(n)), is_overridden_(false)
240 {
241 }
242
243 // NOTE: Anachronism. Try to work all use of svector out.
PECallFunction(const pform_name_t & n,const list<PExpr * > & parms)244 PECallFunction::PECallFunction(const pform_name_t&n, const list<PExpr *> &parms)
245 : package_(0), path_(n), parms_(parms.size()), is_overridden_(false)
246 {
247 int tmp_idx = 0;
248 assert(parms_.size() == parms.size());
249 for (list<PExpr*>::const_iterator idx = parms.begin()
250 ; idx != parms.end() ; ++idx)
251 parms_[tmp_idx++] = *idx;
252 }
253
PECallFunction(perm_string n,const list<PExpr * > & parms)254 PECallFunction::PECallFunction(perm_string n, const list<PExpr*>&parms)
255 : package_(0), path_(pn_from_ps(n)), parms_(parms.size()), is_overridden_(false)
256 {
257 int tmp_idx = 0;
258 assert(parms_.size() == parms.size());
259 for (list<PExpr*>::const_iterator idx = parms.begin()
260 ; idx != parms.end() ; ++idx)
261 parms_[tmp_idx++] = *idx;
262 }
263
~PECallFunction()264 PECallFunction::~PECallFunction()
265 {
266 }
267
declare_implicit_nets(LexicalScope * scope,NetNet::Type type)268 void PECallFunction::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
269 {
270 for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
271 parms_[idx]->declare_implicit_nets(scope, type);
272 }
273 }
274
has_aa_term(Design * des,NetScope * scope) const275 bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
276 {
277 bool flag = false;
278 for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
279 flag = parms_[idx]->has_aa_term(des, scope) || flag;
280 }
281 return flag;
282 }
283
PEConcat(const list<PExpr * > & p,PExpr * r)284 PEConcat::PEConcat(const list<PExpr*>&p, PExpr*r)
285 : parms_(p.size()), width_modes_(SIZED, p.size()), repeat_(r)
286 {
287 int tmp_idx = 0;
288 assert(parms_.size() == p.size());
289 for (list<PExpr*>::const_iterator idx = p.begin()
290 ; idx != p.end() ; ++idx)
291 parms_[tmp_idx++] = *idx;
292
293 tested_scope_ = 0;
294 repeat_count_ = 1;
295 }
296
~PEConcat()297 PEConcat::~PEConcat()
298 {
299 delete repeat_;
300 }
301
declare_implicit_nets(LexicalScope * scope,NetNet::Type type)302 void PEConcat::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
303 {
304 for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
305 parms_[idx]->declare_implicit_nets(scope, type);
306 }
307 }
308
has_aa_term(Design * des,NetScope * scope) const309 bool PEConcat::has_aa_term(Design*des, NetScope*scope) const
310 {
311 bool flag = false;
312 for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
313 flag = parms_[idx]->has_aa_term(des, scope) || flag;
314 }
315 if (repeat_)
316 flag = repeat_->has_aa_term(des, scope) || flag;
317
318 return flag;
319 }
320
PEEvent(PEEvent::edge_t t,PExpr * e)321 PEEvent::PEEvent(PEEvent::edge_t t, PExpr*e)
322 : type_(t), expr_(e)
323 {
324 }
325
~PEEvent()326 PEEvent::~PEEvent()
327 {
328 }
329
type() const330 PEEvent::edge_t PEEvent::type() const
331 {
332 return type_;
333 }
334
has_aa_term(Design * des,NetScope * scope) const335 bool PEEvent::has_aa_term(Design*des, NetScope*scope) const
336 {
337 assert(expr_);
338 return expr_->has_aa_term(des, scope);
339 }
340
expr() const341 PExpr* PEEvent::expr() const
342 {
343 return expr_;
344 }
345
PENull(void)346 PENull::PENull(void)
347 {
348 }
349
~PENull()350 PENull::~PENull()
351 {
352 }
353
PEFNumber(verireal * v)354 PEFNumber::PEFNumber(verireal*v)
355 : value_(v)
356 {
357 }
358
~PEFNumber()359 PEFNumber::~PEFNumber()
360 {
361 delete value_;
362 }
363
value() const364 const verireal& PEFNumber::value() const
365 {
366 return *value_;
367 }
368
PEIdent(const pform_name_t & that)369 PEIdent::PEIdent(const pform_name_t&that)
370 : package_(0), path_(that), no_implicit_sig_(false)
371 {
372 }
373
PEIdent(perm_string s,bool no_implicit_sig)374 PEIdent::PEIdent(perm_string s, bool no_implicit_sig)
375 : package_(0), no_implicit_sig_(no_implicit_sig)
376 {
377 path_.push_back(name_component_t(s));
378 }
379
PEIdent(PPackage * pkg,const pform_name_t & that)380 PEIdent::PEIdent(PPackage*pkg, const pform_name_t&that)
381 : package_(pkg), path_(that), no_implicit_sig_(true)
382 {
383 }
384
~PEIdent()385 PEIdent::~PEIdent()
386 {
387 }
388
declare_implicit_nets(LexicalScope * scope,NetNet::Type type)389 void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
390 {
391 /* We create an implicit wire if:
392 - this is a simple identifier
393 - an identifier of that name has not already been declared in
394 any enclosing scope.
395 - this is not an implicit named port connection */
396 if (no_implicit_sig_)
397 return;
398 if ((path_.size() == 1) && (path_.front().index.size() == 0)) {
399 perm_string name = path_.front().name;
400 LexicalScope*ss = scope;
401 while (ss) {
402 if (ss->wires.find(name) != ss->wires.end())
403 return;
404 if (ss->localparams.find(name) != ss->localparams.end())
405 return;
406 if (ss->parameters.find(name) != ss->parameters.end())
407 return;
408 if (ss->genvars.find(name) != ss->genvars.end())
409 return;
410 if (ss->events.find(name) != ss->events.end())
411 return;
412 /* Strictly speaking, we should also check for name clashes
413 with tasks, functions, named blocks, module instances,
414 and generate blocks. However, this information is not
415 readily available. As these names would not be legal in
416 this context, we can declare implicit nets here and rely
417 on later checks for name clashes to report the error. */
418
419 ss = ss->parent_scope();
420 }
421 PWire*net = new PWire(name, type, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
422 net->set_file(get_file());
423 net->set_lineno(get_lineno());
424 net->set_range_scalar(SR_NET);
425 scope->wires[name] = net;
426 if (warn_implicit) {
427 cerr << get_fileline() << ": warning: implicit "
428 "definition of wire '" << name << "'." << endl;
429 }
430 }
431 }
432
has_aa_term(Design * des,NetScope * scope) const433 bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
434 {
435 NetNet* net = 0;
436 const NetExpr*par = 0;
437 NetEvent* eve = 0;
438
439 const NetExpr*ex1, *ex2;
440
441 scope = symbol_search(this, des, scope, path_, net, par, eve, ex1, ex2);
442
443 if (scope)
444 return scope->is_auto();
445 else
446 return false;
447 }
448
PENewArray(PExpr * size_expr,PExpr * init_expr)449 PENewArray::PENewArray(PExpr*size_expr, PExpr*init_expr)
450 : size_(size_expr), init_(init_expr)
451 {
452 }
453
~PENewArray()454 PENewArray::~PENewArray()
455 {
456 delete size_;
457 }
458
PENewClass(void)459 PENewClass::PENewClass(void)
460 {
461 }
462
PENewClass(const list<PExpr * > & p)463 PENewClass::PENewClass(const list<PExpr*>&p)
464 : parms_(p.size())
465 {
466 size_t tmp_idx = 0;
467 for (list<PExpr*>::const_iterator cur = p.begin()
468 ; cur != p.end() ; ++ cur) {
469 parms_[tmp_idx++] = *cur;
470 }
471 }
472
~PENewClass()473 PENewClass::~PENewClass()
474 {
475 }
476
PENewCopy(PExpr * src)477 PENewCopy::PENewCopy(PExpr*src)
478 : src_(src)
479 {
480 }
481
~PENewCopy()482 PENewCopy::~PENewCopy()
483 {
484 }
485
PENumber(verinum * vp)486 PENumber::PENumber(verinum*vp)
487 : value_(vp)
488 {
489 assert(vp);
490 }
491
~PENumber()492 PENumber::~PENumber()
493 {
494 delete value_;
495 }
496
value() const497 const verinum& PENumber::value() const
498 {
499 return *value_;
500 }
501
is_the_same(const PExpr * that) const502 bool PENumber::is_the_same(const PExpr*that) const
503 {
504 const PENumber*obj = dynamic_cast<const PENumber*>(that);
505 if (obj == 0)
506 return false;
507
508 return *value_ == *obj->value_;
509 }
510
PEString(char * s)511 PEString::PEString(char*s)
512 : text_(s)
513 {
514 }
515
~PEString()516 PEString::~PEString()
517 {
518 delete[]text_;
519 }
520
value() const521 string PEString::value() const
522 {
523 return text_;
524 }
525
PETernary(PExpr * e,PExpr * t,PExpr * f)526 PETernary::PETernary(PExpr*e, PExpr*t, PExpr*f)
527 : expr_(e), tru_(t), fal_(f)
528 {
529 }
530
~PETernary()531 PETernary::~PETernary()
532 {
533 }
534
declare_implicit_nets(LexicalScope * scope,NetNet::Type type)535 void PETernary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
536 {
537 assert(expr_ && tru_ && fal_);
538 expr_->declare_implicit_nets(scope, type);
539 tru_->declare_implicit_nets(scope, type);
540 fal_->declare_implicit_nets(scope, type);
541 }
542
has_aa_term(Design * des,NetScope * scope) const543 bool PETernary::has_aa_term(Design*des, NetScope*scope) const
544 {
545 assert(expr_ && tru_ && fal_);
546 return expr_->has_aa_term(des, scope)
547 || tru_->has_aa_term(des, scope)
548 || fal_->has_aa_term(des, scope);
549 }
550
PETypename(data_type_t * dt)551 PETypename::PETypename(data_type_t*dt)
552 : data_type_(dt)
553 {
554 }
555
~PETypename()556 PETypename::~PETypename()
557 {
558 }
559
PEUnary(char op,PExpr * ex)560 PEUnary::PEUnary(char op, PExpr*ex)
561 : op_(op), expr_(ex)
562 {
563 }
564
~PEUnary()565 PEUnary::~PEUnary()
566 {
567 }
568
declare_implicit_nets(LexicalScope * scope,NetNet::Type type)569 void PEUnary::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
570 {
571 assert(expr_);
572 expr_->declare_implicit_nets(scope, type);
573 }
574
has_aa_term(Design * des,NetScope * scope) const575 bool PEUnary::has_aa_term(Design*des, NetScope*scope) const
576 {
577 assert(expr_);
578 return expr_->has_aa_term(des, scope);
579 }
580
PEVoid()581 PEVoid::PEVoid()
582 {
583 }
584
~PEVoid()585 PEVoid::~PEVoid()
586 {
587 }
588