1 #ifndef IVL_netmisc_H
2 #define IVL_netmisc_H
3 /*
4  * Copyright (c) 1999-2019 Stephen Williams (steve@icarus.com)
5  *
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)
10  *    any later version.
11  *
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.
16  *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 # include  "netlist.h"
23 
24 class netsarray_t;
25 
26 /*
27  * Search for a symbol using the "start" scope as the starting
28  * point. If the path includes a scope part, then locate the
29  * scope first.
30  *
31  * The return value is the scope where the symbol was found.
32  * If the symbol was not found, return 0. The output arguments
33  * get 0 except for the pointer to the object that represents
34  * the located symbol.
35  *
36  * The ex1 and ex2 output arguments are extended results. If the
37  * symbol is a parameter (par!=0) then ex1 is the msb expression and
38  * ex2 is the lsb expression for the range. If there is no range, then
39  * these values are set to 0.
40  */
41 extern NetScope* symbol_search(const LineInfo*li,
42                                Design*des,
43 			       NetScope*start,
44                                pform_name_t path,
45 			       NetNet*&net,       /* net/reg */
46 			       const NetExpr*&par,/* parameter/expr */
47 			       NetEvent*&eve,     /* named event */
48 			       const NetExpr*&ex1, const NetExpr*&ex2);
49 
symbol_search(const LineInfo * li,Design * des,NetScope * start,const pform_name_t & path,NetNet * & net,const NetExpr * & par,NetEvent * & eve)50 inline NetScope* symbol_search(const LineInfo*li,
51                                Design*des,
52 			       NetScope*start,
53                                const pform_name_t&path,
54 			       NetNet*&net,       /* net/reg */
55 			       const NetExpr*&par,/* parameter/expr */
56 			       NetEvent*&eve      /* named event */)
57 {
58       const NetExpr*ex1, *ex2;
59       return symbol_search(li, des, start, path, net, par, eve, ex1, ex2);
60 }
61 
62 /*
63  * This function transforms an expression by either zero or sign extending
64  * the high bits until the expression has the desired width. This may mean
65  * not transforming the expression at all, if it is already wide enough.
66  * The extension method and the returned expression type is determined by
67  * signed_flag.
68  */
69 extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
70 			    const LineInfo&info);
71 /*
72  * This version determines the extension method from the base expression type.
73  */
pad_to_width(NetExpr * expr,unsigned wid,const LineInfo & info)74 inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
75 {
76       return pad_to_width(expr, wid, expr->has_sign(), info);
77 }
78 
79 /*
80  * This function transforms an expression by either zero or sign extending
81  * or discarding the high bits until the expression has the desired width.
82  * This may mean not transforming the expression at all, if it is already
83  * the correct width. The extension method (if needed) and the returned
84  * expression type is determined by signed_flag.
85  */
86 extern NetExpr*cast_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
87 			     const LineInfo&info);
88 
89 extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w,
90                            const LineInfo&info);
91 
92 extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w,
93                                   const LineInfo&info);
94 
95 /*
96  * Generate the nodes necessary to cast an expression (a net) to a
97  * real value.
98  */
99 extern NetNet*cast_to_int4(Design*des, NetScope*scope, NetNet*src, unsigned wid);
100 extern NetNet*cast_to_int2(Design*des, NetScope*scope, NetNet*src, unsigned wid);
101 extern NetNet*cast_to_real(Design*des, NetScope*scope, NetNet*src);
102 
103 extern NetExpr*cast_to_int4(NetExpr*expr, unsigned width);
104 extern NetExpr*cast_to_int2(NetExpr*expr, unsigned width);
105 extern NetExpr*cast_to_real(NetExpr*expr);
106 
107 /*
108  * Take the input expression and return a variation that assures that
109  * the expression is 1-bit wide and logical. This reflects the needs
110  * of conditions i.e. for "if" statements or logical operators.
111  */
112 extern NetExpr*condition_reduce(NetExpr*expr);
113 
114 /*
115  * This function transforms an expression by cropping the high bits
116  * off with a part select. The result has the width w passed in. This
117  * function does not pad, use pad_to_width if padding is desired.
118  */
119 extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
120 
121 extern bool calculate_part(const LineInfo*li, Design*des, NetScope*scope,
122 			   const index_component_t&index,
123 			   long&off, unsigned long&wid);
124 
125 /*
126  * These functions generate an equation to normalize an expression using
127  * the provided vector/array information.
128  */
129 extern NetExpr*normalize_variable_base(NetExpr *base, long msb, long lsb,
130                                        unsigned long wid, bool is_up,
131 				       long slice_off =0);
132 extern NetExpr*normalize_variable_base(NetExpr *base,
133 				       const list<netrange_t>&dims,
134 				       unsigned long wid, bool is_up);
135 
136 /*
137  * Calculate a canonicalizing expression for a bit select, when the
138  * base expression is the last index of an otherwise complete bit
139  * select. For example:
140  *   reg [3:0][7:0] foo;
141  *   ... foo[1][x] ...
142  * base is (x) and the generated expression will be (x+8).
143  */
144 extern NetExpr*normalize_variable_bit_base(const list<long>&indices, NetExpr *base,
145 					   const NetNet*reg);
146 
147 /*
148  * This is similar to normalize_variable_bit_base, but the tail index
149  * it a base and width, instead of a bit. This is used for handling
150  * indexed part selects:
151  *   reg [3:0][7:0] foo;
152  *   ... foo[1][x +: 2]
153  * base is (x), wid input is (2), and is_up is (true). The output
154  * expression is (x+8).
155  */
156 extern NetExpr *normalize_variable_part_base(const list<long>&indices, NetExpr*base,
157 					     const NetNet*reg,
158 					     unsigned long wid, bool is_up);
159 /*
160  * Calculate a canonicalizing expression for a slice select. The
161  * indices array is less than needed to fully address a bit, so the
162  * result is a slice of the packed array. The return value is an
163  * expression that gets to the base of the slice, and (lwid) becomes
164  * the width of the slice, in bits. For example:
165  *   reg [4:1][7:0] foo
166  *   ...foo[x]...
167  * base is (x) and the generated expression will be (x*8 - 8), with
168  * lwid set to (8).
169  */
170 extern NetExpr*normalize_variable_slice_base(const list<long>&indices, NetExpr *base,
171 					     const NetNet*reg, unsigned long&lwid);
172 
173 /*
174  * The as_indices() manipulator is a convenient way to emit a list of
175  * index values in the form [<>][<>]....
176  */
177 template <class TYPE> struct __IndicesManip {
__IndicesManip__IndicesManip178       explicit inline __IndicesManip(const std::list<TYPE>&v) : val(v) { }
179       const std::list<TYPE>&val;
180 };
as_indices(const std::list<TYPE> & indices)181 template <class TYPE> inline __IndicesManip<TYPE> as_indices(const std::list<TYPE>&indices)
182 { return __IndicesManip<TYPE>(indices); }
183 
184 extern ostream& operator << (ostream&o, __IndicesManip<long>);
185 extern ostream& operator << (ostream&o, __IndicesManip<NetExpr*>);
186 
187 /*
188  * Given a list of index expressions, generate elaborated expressions
189  * and constant values, if possible.
190  */
191 struct indices_flags {
192       bool invalid;    // at least one index failed elaboration
193       bool variable;   // at least one index is a dynamic value
194       bool undefined;  // at least one index is an undefined value
195 };
196 extern void indices_to_expressions(Design*des, NetScope*scope,
197 				     // loc is for error messages.
198 				   const LineInfo*loc,
199 				     // src is the index list, and count is
200 				     // the number of items in the list to use.
201 				   const list<index_component_t>&src, unsigned count,
202 				     // True if the expression MUST be constant.
203 				   bool need_const,
204 				     // These are the outputs.
205 				   indices_flags&flags,
206 				   list<NetExpr*>&indices,list<long>&indices_const);
207 
208 extern NetExpr*normalize_variable_unpacked(const NetNet*net, list<long>&indices);
209 extern NetExpr*normalize_variable_unpacked(const netsarray_t*net, list<long>&indices);
210 
211 extern NetExpr*normalize_variable_unpacked(const NetNet*net, list<NetExpr*>&indices);
212 extern NetExpr*normalize_variable_unpacked(const LineInfo&loc, const netsarray_t*net, list<NetExpr*>&indices);
213 
214 extern NetExpr*make_canonical_index(Design*des, NetScope*scope,
215 				      // loc for error messages
216 				    const LineInfo*loc,
217 				      // src is the index list
218 				    const std::list<index_component_t>&src,
219 				      // This is the reference type
220 				    const netsarray_t*stype,
221 				      // True if the expression MUST be constant.
222 				    bool need_const);
223 
224 /*
225  * This function takes as input a NetNet signal and adds a constant
226  * value to it. If the val is 0, then simply return sig. Otherwise,
227  * return a new NetNet value that is the output of an addition.
228  *
229  * Not currently used.
230  */
231 #if 0
232 extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
233 #endif
234 extern NetNet*sub_net_from(Design*des, NetScope*scope, long val, NetNet*sig);
235 
236 /*
237  * Make a NetEConst object that contains only X bits.
238  */
239 extern NetEConst*make_const_x(unsigned long wid);
240 extern NetEConst*make_const_0(unsigned long wid);
241 extern NetEConst*make_const_val(unsigned long val);
242 extern NetEConst*make_const_val_s(long val);
243 
244 /*
245  * Make A const net
246  */
247 extern NetNet* make_const_x(Design*des, NetScope*scope, unsigned long wid);
248 extern NetNet* make_const_z(Design*des, NetScope*scope, unsigned long wid);
249 
250 /*
251  * In some cases the lval is accessible as a pointer to the head of
252  * a list of NetAssign_ objects. This function returns the width of
253  * the l-value represented by this list.
254  */
255 extern unsigned count_lval_width(const class NetAssign_*first);
256 
257 /*
258  * This function elaborates an expression, and tries to evaluate it
259  * right away. If the expression can be evaluated, this returns a
260  * constant expression. If it cannot be evaluated, it returns whatever
261  * it can. If the expression cannot be elaborated, return 0.
262  *
263  * The context_width is the width of the context where the expression is
264  * being elaborated, or -1 if the expression is self-determined, or -2
265  * if the expression is lossless self-determined (this last option is
266  * treated as standard self-determined if the gn_strict_expr_width flag
267  * is set).
268  *
269  * cast_type allows the expression to be cast to a different type
270  * (before it is evaluated). If cast to a vector type, the vector
271  * width will be set to the context_width. The default value of
272  * IVL_VT_NO_TYPE causes the expression to retain its self-determined
273  * type.
274  */
275 class PExpr;
276 
277 extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
278 			      PExpr*pe, int context_width,
279                               bool need_const =false,
280                               bool annotatable =false,
281 			      ivl_variable_type_t cast_type =IVL_VT_NO_TYPE,
282 			      bool force_unsigned =false);
283 
284 extern NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope,
285 			      PExpr*pe, int context_width,
286                               bool need_const =false,
287                               bool annotatable =false,
288 			      ivl_variable_type_t cast_type =IVL_VT_NO_TYPE);
289 
290 /*
291  * This form of elab_and_eval uses the ivl_type_t to carry type
292  * information instead of the piecemeal form. We should transition to
293  * this form as we reasonably can.
294  */
295 extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
296 			      PExpr*expr, ivl_type_t lv_net_type,
297 			      bool need_const);
298 
299 /*
300  * This function is a variant of elab_and_eval that elaborates and
301  * evaluates the arguments of a system task.
302  */
303 extern NetExpr* elab_sys_task_arg(Design*des, NetScope*scope,
304                                   perm_string name, unsigned arg_idx,
305                                   PExpr*pe, bool need_const =false);
306 /*
307  * This function elaborates an expression as if it is for the r-value
308  * of an assignment, The lv_type and lv_width are the type and width
309  * of the l-value, and the expr is the expression to elaborate. The
310  * result is the NetExpr elaborated and evaluated. (See elab_expr.cc)
311  *
312  * I would rather that all calls to elaborate_rval_expr use the
313  * lv_net_type argument to express the l-value type, but, for now,
314  * that it not possible. Those cases will be indicated by the
315  * lv_net_type being set to nil.
316  */
317 extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
318 				    ivl_type_t lv_net_type,
319 				    ivl_variable_type_t lv_type,
320 				    unsigned lv_width, PExpr*expr,
321 				    bool need_const =false,
322 				    bool force_unsigned =false);
323 
324 extern bool evaluate_range(Design*des, NetScope*scope, const LineInfo*li,
325                            const pform_range_t&range,
326                            long&index_l, long&index_r);
327 
328 extern bool evaluate_ranges(Design*des, NetScope*scope, const LineInfo*li,
329 			    std::vector<netrange_t>&llist,
330 			    const std::list<pform_range_t>&rlist);
331 /*
332  * This procedure evaluates an expression and if the evaluation is
333  * successful the original expression is replaced with the new one.
334  */
335 void eval_expr(NetExpr*&expr, int context_width =-1);
336 
337 /*
338  * Get the long integer value for the passed in expression, if
339  * possible. If it is not possible (the expression is not evaluated
340  * down to a constant) then return false and leave value unchanged.
341  */
342 bool eval_as_long(long&value, const NetExpr*expr);
343 bool eval_as_double(double&value, NetExpr*expr);
344 
345 /*
346  * Evaluate an entire scope path in the context of the given scope.
347  */
348 extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
349 					  const pform_name_t&path);
350 extern hname_t eval_path_component(Design*des, NetScope*scope,
351 				   const name_component_t&comp,
352 				   bool&error_flag);
353 
354 /*
355  * If this scope is contained within a class scope (i.e. a method of a
356  * class) then return the class definition that contains it.
357  */
358 extern const netclass_t*find_class_containing_scope(const LineInfo&loc,const NetScope*scope);
359 extern NetScope* find_method_containing_scope(const LineInfo&log, NetScope*scope);
360 
361 /*
362  * Return true if the data type is a type that is normally available
363  * in vector for. IVL_VT_BOOL and IVL_VT_LOGIC are vectorable,
364  * IVL_VT_REAL is not.
365  */
366 extern bool type_is_vectorable(ivl_variable_type_t type);
367 
368 /*
369  * Return a human readable version of the operator.
370  */
371 const char *human_readable_op(const char op, bool unary = false);
372 
373 /*
374  * Is the expression a constant value and if so what is its logical
375  * value.
376  *
377  * C_NON - the expression is not a constant value.
378  * C_0   - the expression is constant and it has a false value.
379  * C_1   - the expression is constant and it has a true value.
380  * C_X   - the expression is constant and it has an 'bX value.
381  */
382 enum const_bool { C_NON, C_0, C_1, C_X };
383 const_bool const_logical(const NetExpr*expr);
384 
385 /*
386  * When scaling a real value to a time we need to do some standard
387  * processing.
388  */
389 extern uint64_t get_scaled_time_from_real(Design*des,
390                                           NetScope*scope,
391                                           NetECReal*val);
392 
393 extern void collapse_partselect_pv_to_concat(Design*des, NetNet*sig);
394 
395 extern bool evaluate_index_prefix(Design*des, NetScope*scope,
396 				  list<long>&prefix_indices,
397 				  const list<index_component_t>&indices);
398 
399 extern NetExpr*collapse_array_indices(Design*des, NetScope*scope, NetNet*net,
400 				      const std::list<index_component_t>&indices);
401 
402 extern NetExpr*collapse_array_exprs(Design*des, NetScope*scope,
403 				    const LineInfo*loc, NetNet*net,
404 				    const list<index_component_t>&indices);
405 
406 extern void assign_unpacked_with_bufz(Design*des, NetScope*scope,
407 				      const LineInfo*loc,
408 				      NetNet*lval, NetNet*rval);
409 
410 extern NetPartSelect* detect_partselect_lval(Link&pin);
411 
412 /*
413  * Print a warning if we find a mixture of default and explicit timescale
414  * based delays in the design, since this is likely an error.
415  */
416 extern void check_for_inconsistent_delays(NetScope*scope);
417 
418 #endif /* IVL_netmisc_H */
419