4 * Copyright (c) 1998-2000 Stephen Williams <steve@icarus.com>
6 * This source code is free software; you can redistribute it
7 * and/or modify it in source code form under the terms of the GNU
8 * General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
26 # include "LineInfo.h"
27 # include "pform_types.h"
36 * The PExpr class hierarchy supports the description of
37 * expressions. The parser can generate expression objects from the
38 * source, possibly reducing things that it knows how to reduce.
40 * The elaborate_net method is used by structural elaboration to build
41 * up a netlist interpretation of the expression.
44 class PExpr
: public LineInfo
{
50 virtual void dump(ostream
&) const;
52 // This method tests the width that the expression wants to
53 // be. It is used by elaboration of assignments to figure out
54 // the width of the expression.
56 // The "min" is the width of the local context, so it the
57 // minimum width that this function should return. Initially
58 // this is the same as the lval width.
60 // The "lval" is the width of the destination where this
61 // result is going to go. This can be used to constrain the
62 // amount that an expression can reasonably expand. For
63 // example, there is no point expanding an addition to beyond
64 // the lval. This extra bit of information allows the
65 // expression to optimize itself a bit. If the lval==0, then
66 // the subexpression should not make l-value related
69 // The unsigned_flag is set to true if the expression is
70 // unsized and therefore expandable. This happens if a
71 // sub-expression is an unsized literal. Some expressions make
72 // special use of that.
73 virtual unsigned test_width(Design
*des
, NetScope
*scope
,
74 unsigned min
, unsigned lval
,
75 bool&unsized_flag
) const;
77 // Procedural elaboration of the expression. The expr_width is
78 // the width of the context of the expression (i.e. the
79 // l-value width of an assignment),
81 // ... or -1 if the expression is self-determined. or
82 // ... or -2 if the expression is losslessly
83 // self-determined. This can happen in situations where the
84 // result is going to a pseudo-infinitely wide context.
86 // The sys_task_arg flag is true if expressions are allowed to
88 virtual NetExpr
*elaborate_expr(Design
*des
, NetScope
*scope
,
89 int expr_width
, bool sys_task_arg
) const;
91 // Elaborate expressions that are the r-value of parameter
92 // assignments. This elaboration follows the restrictions of
93 // constant expressions and supports later overriding and
94 // evaluation of parameters.
95 virtual NetExpr
*elaborate_pexpr(Design
*des
, NetScope
*sc
) const;
97 // This method elaborate the expression as gates, for use in a
98 // continuous assign or other wholly structural context.
99 virtual NetNet
* elaborate_net(Design
*des
, NetScope
*scope
,
103 const NetExpr
* decay
,
104 Link::strength_t drive0
=Link::STRONG
,
105 Link::strength_t drive1
=Link::STRONG
)
108 // This method elaborates the expression as gates, but
109 // restricted for use as l-values of continuous assignments.
110 virtual NetNet
* elaborate_lnet(Design
*des
, NetScope
*scope
,
111 bool implicit_net_ok
=false) const;
113 // This is similar to elaborate_lnet, except that the
114 // expression is evaluated to be bi-directional. This is
115 // useful for arguments to inout ports of module instances and
116 // ports of tran primitives.
117 virtual NetNet
* elaborate_bi_net(Design
*des
, NetScope
*scope
) const;
119 // Expressions that can be in the l-value of procedural
120 // assignments can be elaborated with this method. If the
121 // is_force flag is true, then the set of valid l-value types
122 // is slightly modified to accomodate the Verilog force
124 virtual NetAssign_
* elaborate_lval(Design
*des
,
126 bool is_force
) const;
128 // This attempts to evaluate a constant expression, and return
129 // a verinum as a result. If the expression cannot be
130 // evaluated, return 0.
131 virtual verinum
* eval_const(Design
*des
, NetScope
*sc
) const;
133 // This method returns true if that expression is the same as
134 // this expression. This method is used for comparing
135 // expressions that must be structurally "identical".
136 virtual bool is_the_same(const PExpr
*that
) const;
138 // Return true if this expression is a valid constant
139 // expression. the Module pointer is needed to find parameter
140 // identifiers and any other module specific interpretations
142 virtual bool is_constant(Module
*) const;
144 private: // not implemented
146 PExpr
& operator= (const PExpr
&);
149 ostream
& operator << (ostream
&, const PExpr
&);
151 class PEConcat
: public PExpr
{
154 PEConcat(const svector
<PExpr
*>&p
, PExpr
*r
=0);
157 virtual verinum
* eval_const(Design
*des
, NetScope
*sc
) const;
158 virtual void dump(ostream
&) const;
160 virtual NetNet
* elaborate_lnet(Design
*des
, NetScope
*scope
,
161 bool implicit_net_ok
=false) const;
162 virtual NetNet
* elaborate_bi_net(Design
*des
, NetScope
*scope
) const;
163 virtual NetNet
* elaborate_net(Design
*des
, NetScope
*scope
,
167 const NetExpr
* decay
,
168 Link::strength_t drive0
,
169 Link::strength_t drive1
) const;
170 virtual NetExpr
*elaborate_expr(Design
*des
, NetScope
*,
171 int expr_width
, bool sys_task_arg
) const;
172 virtual NetEConcat
*elaborate_pexpr(Design
*des
, NetScope
*) const;
173 virtual NetAssign_
* elaborate_lval(Design
*des
,
175 bool is_force
) const;
176 virtual bool is_constant(Module
*) const;
179 NetNet
* elaborate_lnet_common_(Design
*des
, NetScope
*scope
,
180 bool implicit_net_ok
,
181 bool bidirectional_flag
) const;
183 svector
<PExpr
*>parms_
;
188 * Event expressions are expressions that can be combined with the
189 * event "or" operator. These include "posedge foo" and similar, and
190 * also include named events. "edge" events are associated with an
191 * expression, whereas named events simply have a name, which
192 * represents an event variable.
194 class PEEvent
: public PExpr
{
197 enum edge_t
{ANYEDGE
, POSEDGE
, NEGEDGE
, POSITIVE
};
199 // Use this constructor to create events based on edges or levels.
200 PEEvent(edge_t t
, PExpr
*e
);
207 virtual void dump(ostream
&) const;
215 * This holds a floating point constant in the source.
217 class PEFNumber
: public PExpr
{
220 explicit PEFNumber(verireal
*vp
);
223 const verireal
& value() const;
225 /* The eval_const method as applied to a floating point number
226 gets the *integer* value of the number. This accounts for
227 any rounding that is needed to get the value. */
228 virtual verinum
* eval_const(Design
*des
, NetScope
*sc
) const;
230 /* A PEFNumber is a constant, so this returns true. */
231 virtual bool is_constant(Module
*) const;
233 virtual NetExpr
*elaborate_expr(Design
*des
, NetScope
*,
234 int expr_width
, bool sys_task_arg
) const;
235 virtual NetExpr
*elaborate_pexpr(Design
*des
, NetScope
*sc
) const;
237 virtual NetNet
* elaborate_net(Design
*des
, NetScope
*scope
,
241 const NetExpr
* decay
,
242 Link::strength_t drive0
,
243 Link::strength_t drive1
) const;
245 virtual void dump(ostream
&) const;
251 class PEIdent
: public PExpr
{
254 explicit PEIdent(perm_string
);
255 explicit PEIdent(const pform_name_t
&);
258 // Add another name to the string of heirarchy that is the
259 // current identifier.
260 void append_name(perm_string
);
262 virtual void dump(ostream
&) const;
263 virtual unsigned test_width(Design
*des
, NetScope
*scope
,
264 unsigned min
, unsigned lval
,
265 bool&unsized_flag
) const;
267 // Identifiers are allowed (with restrictions) is assign l-values.
268 virtual NetNet
* elaborate_lnet(Design
*des
, NetScope
*scope
,
269 bool implicit_net_ok
=false) const;
271 virtual NetNet
* elaborate_bi_net(Design
*des
, NetScope
*scope
) const;
273 // Identifiers are also allowed as procedural assignment l-values.
274 virtual NetAssign_
* elaborate_lval(Design
*des
,
276 bool is_force
) const;
278 // Structural r-values are OK.
279 virtual NetNet
* elaborate_net(Design
*des
, NetScope
*scope
,
283 const NetExpr
* decay
,
284 Link::strength_t drive0
,
285 Link::strength_t drive1
) const;
287 virtual NetExpr
*elaborate_expr(Design
*des
, NetScope
*,
288 int expr_width
, bool sys_task_arg
) const;
289 virtual NetExpr
*elaborate_pexpr(Design
*des
, NetScope
*sc
) const;
291 // Elaborate the PEIdent as a port to a module. This method
292 // only applies to Ident expressions.
293 NetNet
* elaborate_port(Design
*des
, NetScope
*sc
) const;
295 virtual bool is_constant(Module
*) const;
296 verinum
* eval_const(Design
*des
, NetScope
*sc
) const;
298 const pform_name_t
& path() const { return path_
; }
304 // Common functions to calculate parts of part/bit selects.
305 bool calculate_parts_(Design
*, NetScope
*, long&msb
, long&lsb
) const;
306 bool calculate_up_do_width_(Design
*, NetScope
*, unsigned long&wid
) const;
309 NetAssign_
*elaborate_lval_net_word_(Design
*, NetScope
*, NetNet
*) const;
310 bool elaborate_lval_net_part_(Design
*, NetScope
*, NetAssign_
*) const;
311 bool elaborate_lval_net_idx_(Design
*, NetScope
*, NetAssign_
*,
312 index_component_t::ctype_t
) const;
315 NetExpr
*elaborate_expr_param(Design
*des
,
319 const NetExpr
*par_msb
,
320 const NetExpr
*par_lsb
) const;
321 NetExpr
*elaborate_expr_net(Design
*des
,
325 bool sys_task_arg
) const;
326 NetExpr
*elaborate_expr_net_word_(Design
*des
,
330 bool sys_task_arg
) const;
331 NetExpr
*elaborate_expr_net_part_(Design
*des
,
334 NetScope
*found
) const;
335 NetExpr
*elaborate_expr_net_idx_up_(Design
*des
,
338 NetScope
*found
) const;
339 NetExpr
*elaborate_expr_net_idx_do_(Design
*des
,
342 NetScope
*found
) const;
343 NetExpr
*elaborate_expr_net_bit_(Design
*des
,
346 NetScope
*found
) const;
350 NetNet
* elaborate_net_array_(Design
*des
, NetScope
*scope
,
351 NetNet
*sig
, unsigned lwidth
,
354 const NetExpr
* decay
,
355 Link::strength_t drive0
,
356 Link::strength_t drive1
) const;
358 NetNet
* elaborate_net_net_(Design
*des
, NetScope
*scope
,
359 NetNet
*sig
, unsigned lwidth
,
362 const NetExpr
* decay
,
363 Link::strength_t drive0
,
364 Link::strength_t drive1
) const;
365 NetNet
* elaborate_net_net_idx_up_(Design
*des
, NetScope
*scope
,
366 NetNet
*sig
, unsigned lwidth
,
369 const NetExpr
* decay
,
370 Link::strength_t drive0
,
371 Link::strength_t drive1
) const;
372 NetNet
* elaborate_net_bitmux_(Design
*des
, NetScope
*scope
,
376 const NetExpr
* decay
,
377 Link::strength_t drive0
,
378 Link::strength_t drive1
) const;
381 NetNet
* elaborate_lnet_common_(Design
*des
, NetScope
*scope
,
382 bool implicit_net_ok
,
383 bool bidirectional_flag
) const;
385 NetNet
*make_implicit_net_(Design
*des
, NetScope
*scope
) const;
387 bool eval_part_select_(Design
*des
, NetScope
*scope
, NetNet
*sig
,
388 unsigned&midx
, unsigned&lidx
) const;
389 NetNet
*process_select_(Design
*des
, NetScope
*scope
, NetNet
*sig
) const;
393 class PENumber
: public PExpr
{
396 explicit PENumber(verinum
*vp
);
399 const verinum
& value() const;
401 virtual void dump(ostream
&) const;
402 virtual unsigned test_width(Design
*des
, NetScope
*scope
,
403 unsigned min
, unsigned lval
,
404 bool&unsized_flag
) const;
406 virtual NetNet
* elaborate_net(Design
*des
, NetScope
*scope
,
410 const NetExpr
* decay
,
411 Link::strength_t drive0
,
412 Link::strength_t drive1
) const;
413 virtual NetEConst
*elaborate_expr(Design
*des
, NetScope
*,
414 int expr_width
, bool) const;
415 virtual NetExpr
*elaborate_pexpr(Design
*des
, NetScope
*sc
) const;
416 virtual NetAssign_
* elaborate_lval(Design
*des
,
418 bool is_force
) const;
420 virtual verinum
* eval_const(Design
*des
, NetScope
*sc
) const;
422 virtual bool is_the_same(const PExpr
*that
) const;
423 virtual bool is_constant(Module
*) const;
426 verinum
*const value_
;
430 * This represents a string constant in an expression.
432 * The s parameter to the PEString constructor is a C string that this
433 * class instance will take for its own. The caller should not delete
434 * the string, the destructor will do it.
436 class PEString
: public PExpr
{
439 explicit PEString(char*s
);
442 string
value() const;
443 virtual void dump(ostream
&) const;
445 virtual unsigned test_width(Design
*des
, NetScope
*scope
,
446 unsigned min
, unsigned lval
,
447 bool&unsized_flag
) const;
449 virtual NetNet
* elaborate_net(Design
*des
, NetScope
*scope
,
453 const NetExpr
* decay
,
454 Link::strength_t drive0
,
455 Link::strength_t drive1
) const;
456 virtual NetEConst
*elaborate_expr(Design
*des
, NetScope
*,
457 int expr_width
, bool) const;
458 virtual NetEConst
*elaborate_pexpr(Design
*des
, NetScope
*sc
) const;
459 verinum
* eval_const(Design
*, NetScope
*) const;
461 virtual bool is_constant(Module
*) const;
467 class PEUnary
: public PExpr
{
470 explicit PEUnary(char op
, PExpr
*ex
);
473 virtual void dump(ostream
&out
) const;
475 virtual NetNet
* elaborate_net(Design
*des
, NetScope
*scope
,
479 const NetExpr
* decay
,
480 Link::strength_t drive0
,
481 Link::strength_t drive1
) const;
482 virtual NetExpr
*elaborate_expr(Design
*des
, NetScope
*,
483 int expr_width
, bool sys_task_arg
) const;
484 virtual NetExpr
*elaborate_pexpr(Design
*des
, NetScope
*sc
) const;
485 virtual verinum
* eval_const(Design
*des
, NetScope
*sc
) const;
487 virtual bool is_constant(Module
*) const;
494 class PEBinary
: public PExpr
{
497 explicit PEBinary(char op
, PExpr
*l
, PExpr
*r
);
500 virtual bool is_constant(Module
*) const;
502 virtual void dump(ostream
&out
) const;
504 virtual unsigned test_width(Design
*des
, NetScope
*scope
,
505 unsigned min
, unsigned lval
,
506 bool&unsized_flag
) const;
508 virtual NetNet
* elaborate_net(Design
*des
, NetScope
*scope
,
512 const NetExpr
* decay
,
513 Link::strength_t drive0
,
514 Link::strength_t drive1
) const;
515 virtual NetEBinary
*elaborate_expr(Design
*des
, NetScope
*,
516 int expr_width
, bool sys_task_arg
) const;
517 virtual NetExpr
*elaborate_pexpr(Design
*des
, NetScope
*sc
) const;
518 virtual verinum
* eval_const(Design
*des
, NetScope
*sc
) const;
525 NetEBinary
*elaborate_expr_base_(Design
*, NetExpr
*lp
, NetExpr
*rp
, int use_wid
) const;
526 NetEBinary
*elaborate_eval_expr_base_(Design
*, NetExpr
*lp
, NetExpr
*rp
, int use_wid
) const;
529 NetNet
* elaborate_net_add_(Design
*des
, NetScope
*scope
,
533 const NetExpr
* decay
) const;
534 NetNet
* elaborate_net_bit_(Design
*des
, NetScope
*scope
,
538 const NetExpr
* decay
) const;
539 NetNet
* elaborate_net_cmp_(Design
*des
, NetScope
*scope
,
543 const NetExpr
* decay
) const;
544 NetNet
* elaborate_net_div_(Design
*des
, NetScope
*scope
,
548 const NetExpr
* decay
) const;
549 NetNet
* elaborate_net_mod_(Design
*des
, NetScope
*scope
,
553 const NetExpr
* decay
) const;
554 NetNet
* elaborate_net_log_(Design
*des
, NetScope
*scope
,
558 const NetExpr
* decay
) const;
559 NetNet
* elaborate_net_mul_(Design
*des
, NetScope
*scope
,
563 const NetExpr
* decay
) const;
564 NetNet
* elaborate_net_shift_(Design
*des
, NetScope
*scope
,
568 const NetExpr
* decay
) const;
572 * Here are a few specilized classes for handling specific binary
575 class PEBComp
: public PEBinary
{
578 explicit PEBComp(char op
, PExpr
*l
, PExpr
*r
);
581 virtual unsigned test_width(Design
*des
, NetScope
*scope
,
582 unsigned min
, unsigned lval
,
585 NetEBinary
* elaborate_expr(Design
*des
, NetScope
*scope
,
586 int expr_width
, bool sys_task_arg
) const;
589 class PEBShift
: public PEBinary
{
592 explicit PEBShift(char op
, PExpr
*l
, PExpr
*r
);
595 virtual unsigned test_width(Design
*des
, NetScope
*scope
,
596 unsigned min
, unsigned lval
, bool&flag
) const;
600 * This class supports the ternary (?:) operator. The operator takes
601 * three expressions, the test, the true result and the false result.
603 class PETernary
: public PExpr
{
606 explicit PETernary(PExpr
*e
, PExpr
*t
, PExpr
*f
);
609 virtual bool is_constant(Module
*) const;
611 virtual void dump(ostream
&out
) const;
612 virtual unsigned test_width(Design
*des
, NetScope
*scope
,
613 unsigned min
, unsigned lval
,
614 bool&unsized_flag
) const;
616 virtual NetNet
* elaborate_net(Design
*des
, NetScope
*scope
,
620 const NetExpr
* decay
,
621 Link::strength_t drive0
,
622 Link::strength_t drive1
) const;
623 virtual NetETernary
*elaborate_expr(Design
*des
, NetScope
*,
624 int expr_width
, bool sys_task_arg
) const;
625 virtual NetETernary
*elaborate_pexpr(Design
*des
, NetScope
*sc
) const;
626 virtual verinum
* eval_const(Design
*des
, NetScope
*sc
) const;
635 * This class represents a parsed call to a function, including calls
636 * to system functions. The parameters in the parms list are the
637 * expressions that are passed as input to the ports of the function.
639 class PECallFunction
: public PExpr
{
641 explicit PECallFunction(const pform_name_t
&n
, const svector
<PExpr
*> &parms
);
642 // Call of system function (name is not heirarchical)
643 explicit PECallFunction(perm_string n
, const svector
<PExpr
*> &parms
);
644 explicit PECallFunction(perm_string n
);
647 virtual void dump(ostream
&) const;
649 virtual NetNet
* elaborate_net(Design
*des
, NetScope
*scope
,
653 const NetExpr
* decay
,
654 Link::strength_t drive0
,
655 Link::strength_t drive1
) const;
656 virtual NetExpr
*elaborate_expr(Design
*des
, NetScope
*scope
,
657 int expr_wid
, bool sys_task_arg
) const;
659 virtual unsigned test_width(Design
*des
, NetScope
*scope
,
660 unsigned min
, unsigned lval
,
661 bool&unsized_flag
) const;
665 svector
<PExpr
*> parms_
;
667 bool check_call_matches_definition_(Design
*des
, NetScope
*dscope
) const;
669 NetExpr
* elaborate_sfunc_(Design
*des
, NetScope
*scope
, int expr_wid
) const;
670 NetNet
* elaborate_net_sfunc_(Design
*des
, NetScope
*scope
,
674 const NetExpr
* decay
,
675 Link::strength_t drive0
,
676 Link::strength_t drive1
) const;
677 unsigned test_width_sfunc_(Design
*des
, NetScope
*scope
,
678 unsigned min
, unsigned lval
,
679 bool&unsized_flag
) const;