1 /* attributes
2 
3    Copyright (C) 1994-1997 University of Dortmund
4    Department of Electrical Engineering, AG SIV
5 
6    VAUL is free software; you can redistribute it and/or modify it
7    under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10 
11    VAUL is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General
14    Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public
17    License along with VAUL; see the file COPYING.LIB.  If not, write
18    to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19    Boston, MA 02111-1307 USA.
20 
21 
22 */
23 
24 #include <freehdl/vaul-parser.h>
25 #include <freehdl/vaul-chunk.h>
26 #include <freehdl/vaul-dunit.h>
27 #include <freehdl/vaul-util.h>
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <assert.h>
32 
33 #define psr vaul_parser
34 
35 enum attr_id {
36 
37     // type prefix
38     ai_BASE, ai_IMAGE, ai_VALUE, ai_POS, ai_VAL, ai_SUCC, ai_PRED,
39     ai_LEFTOF, ai_RIGHTOF,
40 
41     // type or array prefix
42     ai_LEFT, ai_RIGHT, ai_HIGH, ai_LOW, ai_ASCENDING,
43     ai_RANGE, ai_REVERSE_RANGE, ai_LENGTH,
44 
45     // signal prefix
46     ai_DELAYED, ai_STABLE, ai_QUIET, ai_TRANSACTION, ai_EVENT,
47     ai_ACTIVE, ai_LAST_EVENT, ai_LAST_ACTIVE, ai_LAST_VALUE,
48     ai_DRIVING, ai_DRIVING_VALUE,
49 
50     // named entity prefix
51     ai_SIMPLE_NAME, ai_INSTANCE_NAME, ai_PATH_NAME,
52 
53     ai_MAX
54 };
55 
56 #define AI_FIRST_TYPE   ai_BASE
57 #define AI_LAST_TYPE    ai_RIGHTOF
58 #define AI_FIRST_T_OR_A ai_LEFT
59 #define AI_LAST_T_OR_A  ai_LENGTH
60 #define AI_FIRST_TA     AI_FIRST_TYPE
61 #define AI_LAST_TA      AI_LAST_T_OR_A
62 #define AI_FIRST_SIGNAL ai_DELAYED
63 #define AI_LAST_SIGNAL  ai_DRIVING_VALUE
64 #define AI_FIRST_ENTITY ai_SIMPLE_NAME
65 #define AI_LAST_ENTITY  ai_PATH_NAME
66 
67 static const char *attr_name[] = {
68     "BASE", "IMAGE", "VALUE", "POS", "VAL", "SUCC", "PRED",
69     "LEFTOF", "RIGHTOF",
70 
71     "LEFT", "RIGHT", "HIGH", "LOW", "ASCENDING",
72 
73     "RANGE", "REVERSE_RANGE", "LENGTH",
74 
75     "DELAYED", "STABLE", "QUIET", "TRANSACTION", "EVENT",
76     "ACTIVE", "LAST_EVENT", "LAST_ACTIVE", "LAST_VALUE",
77     "DRIVING", "DRIVING_VALUE",
78 
79     "SIMPLE_NAME", "INSTANCE_NAME", "PATH_NAME"
80 };
81 
82 
83 pIIR
build_AttrNode(pVAUL_Name n,vaul_decl_set * set,IR_Kind basic_k)84 psr::build_AttrNode (pVAUL_Name n, vaul_decl_set *set, IR_Kind basic_k)
85 {
86   if (n->is(VAUL_ATTRIBUTE_NAME))
87     return build_AttrNode (pVAUL_AttributeName(n), set, basic_k);
88 
89   if(n == set->name && tree_is (basic_k, IR_TYPE_DECLARATION))
90     {
91       pIIR_Declaration d = set->single_decl ();
92       delete set;
93       assert (d->is(IR_TYPE_DECLARATION));
94       return pIIR_TypeDeclaration(d)->type;
95     }
96 
97   return build_Expr (n, set, basic_k);
98 }
99 
100 pIIR
build_AttrNode(pVAUL_AttributeName n,vaul_decl_set * set,IR_Kind basic_k)101 psr::build_AttrNode (pVAUL_AttributeName n, vaul_decl_set *set, IR_Kind basic_k)
102 {
103   pIIR_Expression p = NULL;
104   bool too_many = false;
105   if (n->first_actual)
106     {
107       if (n->first_actual->next)
108 	too_many = true;
109       if (n->first_actual->formal)
110 	error ("%:attribute arguments do not have names", n);
111       p = n->first_actual->actual;
112     }
113 
114   attr_id ai = ai_MAX;
115   for (int i = 0; i < ai_MAX; i++)
116     if(vaul_name_eq(n->attribute, attr_name[i]))
117       {
118 	ai = attr_id(i);
119 	break;
120       }
121 
122   pIIR res = NULL;
123 
124   if (ai >= AI_FIRST_TA && ai <= AI_LAST_TA)
125     {
126       pIIR pfx = build_AttrNode (n->prefix, set, basic_k);
127       if (pfx == NULL)
128 	return NULL;
129 
130       // T is the type we are talking about.
131       // BT is the base type of T
132       // E is an expression denoting the original prefix, or NULL
133       // when the prefix was T itself.
134 
135       pIIR_Type t = NULL, base_t = NULL;
136       pIIR_Expression e = NULL;
137 
138       if (pfx->is(IR_EXPRESSION))
139 	{
140 	  e = pIIR_Expression(pfx);
141 	  overload_resolution (e, NULL, IR_TYPE, false, false);
142 	  e = make_appropriate (e);
143 	  if (e == NULL)
144 	    return NULL;
145 	  t = expr_type (e);
146 	  if (t == NULL)
147 	    return NULL;
148 	}
149       else if (pfx->is(IR_TYPE))
150 	{
151 	  t = pIIR_Type(pfx);
152 	}
153       else
154 	{
155 	  error ("%:prefix of '%s must be a type or object",
156 		 n->prefix, attr_name[ai]);
157 	  return NULL;
158 	}
159 
160       base_t = vaul_get_base (t);
161 
162       if(ai >= AI_FIRST_TYPE && ai <= AI_LAST_TYPE) {
163 	if(ai >= ai_IMAGE && ai <= ai_VALUE) {
164 	  if(!base_t->is(IR_SCALAR_TYPE)) {
165 	    error("%:prefix of '%s must be a scalar type", n->prefix,
166 		  attr_name[ai]);
167 	    return NULL;
168 	  }
169 	} else if(ai >= ai_POS && ai <= ai_RIGHTOF) {
170 	  if(!is_discrete_type(base_t)
171 	     && !base_t->is(IR_PHYSICAL_TYPE)) {
172 	    error("%:prefix of '%s must be a discrete or"
173 		  " physical type", n->prefix, attr_name[ai]);
174 	    return NULL;
175 	  }
176 	}
177 
178 	switch(ai) {
179 	case ai_BASE: {
180 	  res = base_t;
181 	} break;
182 
183 	case ai_IMAGE: {
184 	  overload_resolution (p, t);
185 	  res = mIIR_Attr_IMAGE (n->pos, std->predef_STRING, t, p);
186 	  p = NULL;
187 	} break;
188 
189 	case ai_VALUE: {
190 	  overload_resolution (p, std->predef_STRING);
191 	  res = mIIR_Attr_VALUE (n->pos, t, t, p);
192 	  p = NULL;
193 	} break;
194 
195 	case ai_POS: {
196 	  overload_resolution (p, t);
197 	  res = mIIR_Attr_POS (n->pos, std->universal_integer, t, p);
198 	  p = NULL;
199 	} break;
200 
201 	case ai_VAL: {
202 	  overload_resolution (p, IR_INTEGER_TYPE);
203 	  res = mIIR_Attr_VAL (n->pos, t, t, p);
204 	  p = NULL;
205 	} break;
206 
207 	case ai_SUCC: {
208 	  overload_resolution (p, t);
209 	  res = mIIR_Attr_SUCC (n->pos, t, t, p);
210 	  p = NULL;
211 	} break;
212 
213 	case ai_PRED: {
214 	  overload_resolution (p, t);
215 	  res = mIIR_Attr_PRED (n->pos, t, t, p);
216 	  p = NULL;
217 	} break;
218 
219 	case ai_LEFTOF: {
220 	  overload_resolution (p, t);
221 	  res = mIIR_Attr_LEFTOF (n->pos, t, t, p);
222 	  p = NULL;
223 	} break;
224 
225 	case ai_RIGHTOF: {
226 	  overload_resolution (p, t);
227 	  res = mIIR_Attr_RIGHTOF (n->pos, t, t, p);
228 	  p = NULL;
229 	} break;
230 
231 	default: // should be complete.
232 	  info("%:XXX - unimplemented type attribute %n",
233 	       n, n->attribute);
234 	  return NULL;
235 	}
236 
237       } else if (ai >= AI_FIRST_T_OR_A && ai <= AI_LAST_T_OR_A) {
238 	int index;
239 	pIIR_Expression arg = p;
240 	p = NULL;
241 	if (base_t->is(IR_ARRAY_TYPE))
242 	  {
243 	    if (arg)
244 	      {
245 		overload_resolution (arg, IR_INTEGER_TYPE);
246 		if (arg == NULL)
247 		  return NULL;
248 	      }
249 
250 	    pIIR_Type it = find_array_attr_index_type (pIIR_ArrayType(base_t),
251 						       arg, index);
252 	    if (it == NULL)
253 	      return NULL;
254 
255 	    switch (ai)
256 	      {
257 	      case ai_LEFT:
258 		res = mIIR_Attr_ArrayLEFT (n->pos, it, e, t, index);
259 		break;
260 	      case ai_RIGHT:
261 		res = mIIR_Attr_ArrayRIGHT (n->pos, it, e, t, index);
262 		break;
263 	      case ai_HIGH:
264 		res = mIIR_Attr_ArrayHIGH (n->pos, it, e, t, index);
265 		break;
266 	      case ai_LOW:
267 		res = mIIR_Attr_ArrayLOW (n->pos, it, e, t, index);
268 		break;
269 	      case ai_ASCENDING:
270 		res = mIIR_Attr_ArrayASCENDING (n->pos,
271 						std->predef_BOOLEAN,
272 						e, t, index);
273 		break;
274 	      case ai_RANGE:
275 		res = mIIR_Attr_ArrayRANGE (n->pos, it, e, t, arg);
276 		break;
277 	      case ai_REVERSE_RANGE:
278 		res = mIIR_Attr_ArrayREVERSE_RANGE (n->pos, it, e, t, arg);
279 		break;
280 	      case ai_LENGTH:
281 		res = mIIR_Attr_ArrayLENGTH (n->pos,
282 					     std->universal_integer, e, t,
283 					     index);
284 		break;
285 	      default:
286 		assert (false);
287 	      }
288 	  }
289 	else if (t)
290 	  {
291 	    switch (ai)
292 	      {
293 	      case ai_LEFT:
294 		res = mIIR_Attr_LEFT (n->pos, t, t, arg);
295 		break;
296 	      case ai_RIGHT:
297 		res = mIIR_Attr_RIGHT (n->pos, t, t, arg);
298 		break;
299 	      case ai_HIGH:
300 		res = mIIR_Attr_HIGH (n->pos, t, t, arg);
301 		break;
302 	      case ai_LOW:
303 		res = mIIR_Attr_LOW (n->pos, t, t, arg);
304 		break;
305 	      case ai_ASCENDING:
306 		res = mIIR_Attr_ASCENDING (n->pos, std->predef_BOOLEAN,
307 					   t, arg);
308 		break;
309 	      case ai_RANGE:
310 	      case ai_REVERSE_RANGE:
311 	      case ai_LENGTH:
312 		error ("prefix of '%s must be an array or array type",
313 		       attr_name[ai]);
314 		res = NULL;
315 		break;
316 	      default:
317 		assert (false);
318 	      }
319 	  }
320 	else
321 	  {
322 	    error ("%:prefix of '%s must be a type or array",
323 		   n->prefix, attr_name[ai]);
324 	    return NULL;
325 	  }
326       }
327 
328     } else if(ai >= AI_FIRST_SIGNAL && ai <= AI_LAST_SIGNAL) {
329 
330       pIIR b = build_Expr (n->prefix, set, basic_k);
331       if (b == NULL)
332 	return NULL;
333       if (!b->is(IR_OBJECT_REFERENCE) || !is_signal (pIIR_ObjectReference(b)))
334 	{
335 	  error ("%:prefix of '%s must be a signal",
336 		 n->prefix, attr_name[ai]);
337 	  return NULL;
338 	}
339 
340       pIIR_ObjectReference r = pIIR_ObjectReference(b);
341 
342       switch(ai)
343 	{
344 	case ai_DELAYED:
345 	  overload_resolution (p, std->predef_TIME);
346 	  res = mIIR_Attr_DELAYED (n->pos, vaul_get_type (r), r, p);
347 	  p = NULL;
348 	  break;
349 
350 	case ai_STABLE:
351 	  overload_resolution (p, std->predef_TIME);
352 	  res = mIIR_Attr_STABLE (n->pos, std->predef_BOOLEAN, r, p);
353 	  p = NULL;
354 	  break;
355 
356 	case ai_QUIET:
357 	  overload_resolution (p, std->predef_TIME);
358 	  res = mIIR_Attr_QUIET (n->pos, std->predef_BOOLEAN, r, p);
359 	  p = NULL;
360 	  break;
361 
362 	case ai_TRANSACTION:
363 	  res = mIIR_Attr_TRANSACTION (n->pos, std->predef_BIT, r);
364 	  break;
365 
366 	case ai_EVENT:
367 	  res = mIIR_Attr_EVENT (n->pos, std->predef_BOOLEAN, r);
368 	  break;
369 
370 	case ai_ACTIVE:
371 	  res = mIIR_Attr_ACTIVE (n->pos, std->predef_BOOLEAN, r);
372 	  break;
373 
374 	case ai_LAST_EVENT:
375 	  res = mIIR_Attr_LAST_EVENT (n->pos, std->predef_TIME, r);
376 	  break;
377 
378 	case ai_LAST_ACTIVE:
379 	  res = mIIR_Attr_LAST_ACTIVE (n->pos, std->predef_TIME, r);
380 	  break;
381 
382 	case ai_LAST_VALUE:
383 	  res = mIIR_Attr_LAST_VALUE (n->pos, vaul_get_type(r), r);
384 	  break;
385 
386 	case ai_DRIVING:
387 	  res = mIIR_Attr_DRIVING (n->pos, std->predef_BOOLEAN, r);
388 	  break;
389 
390 	case ai_DRIVING_VALUE:
391 	  res = mIIR_Attr_DRIVING_VALUE (n->pos, vaul_get_type(r), r);
392 	  break;
393 
394 	default:
395 	  // should be complete
396 	  info ("%:XXX - unimplemented signal attribute %n", n, n->attribute);
397 
398 	}
399 
400     } else if(ai >= AI_FIRST_ENTITY && ai <= AI_LAST_ENTITY) {
401       info ("XXX - unimplemented entity attribute %n", n, n->attribute);
402       delete set;
403       res = NULL;
404     } else {
405       // user defined attributes
406       info("%:XXX - no user defined attributes", n);
407       delete set;
408       res = NULL;
409     }
410 
411   if(p || too_many)
412     error ("%:too many arguments for attribute %s", n, attr_name[ai]);
413 
414   return res;
415 }
416 
417 pIIR_Type
find_array_attr_index_type(pIIR_ArrayType t,pIIR_Expression p,int & index)418 psr::find_array_attr_index_type (pIIR_ArrayType t, pIIR_Expression p, int &index)
419 {
420   if (p == NULL)
421     index = 1;
422   else if (!evaluate_locally_static_universal_integer(p, index))
423     return NULL;
424 
425   //info ("+++ - folded %n to %d", p, index);
426 
427   if (index <= 0)
428     {
429       error ("%:indices must be positive", p);
430       return NULL;
431     }
432 
433   pIIR_TypeList it = pIIR_ArrayType(t)->index_types;
434   int dims = 0;
435   while(it && index != ++dims)
436     it = it->rest;
437   if (it == NULL)
438     {
439       error("%:%n has only %d dimensions, not %d", p, t,
440 	    dims, index);
441       return NULL;
442     }
443   return it->first;
444 }
445 
446 #if 0 // not used
447 
448 static pIIR_Declaration
449 find_in_decl_part (nScope part, Id id)
450 {
451   for (nDeclaration d = part->first_decl; d; d = d->next_decl) {
452     if (d->id && vaul_name_eq (d->id, id))
453       return d;
454   }
455   return NULL;
456 }
457 
458 #endif
459 
460 void
bind_attrspec(pVAUL_AttributeSpec s)461 psr::bind_attrspec (pVAUL_AttributeSpec s)
462 {
463   if (s == NULL || s->entities == NULL)
464     return;
465 
466   pVAUL_SimpleName attr_name = mVAUL_SimpleName (s->pos, s->attr_desig);
467   pIIR_AttributeDeclaration a =
468     pIIR_AttributeDeclaration (find_single_decl (attr_name,
469 						 IR_ATTRIBUTE_DECLARATION,
470 						 "attribute"));
471   if (a == NULL)
472     return;
473 
474   overload_resolution (s->value, a->subtype);
475   if (s->value == NULL)
476     return;
477 
478   pVAUL_EntityNameList el = s->entities->names;
479   if (el->is(VAUL_ENTITY_NAME_LIST_IDS))
480     {
481       IR_Kind eclass = s->entities->entity_class;
482       const char *ename = tree_kind_name (eclass);
483 
484       for (pVAUL_DesigList il = pVAUL_EntityNameList_Ids(el)->ids;
485 	   il; il = il->link)
486 	{
487 	  pIIR_Declaration d =
488 	    find_single_decl (mVAUL_SimpleName(il->pos,
489 					       il->desig),
490 			      IR_DECLARATION, NULL);
491 	  if (d == NULL)
492 	    continue;
493 
494 	  if (d->declarative_region != cur_scope
495 	      && d != cur_du->get_tree())
496 	    {
497 	      error ("%:only declarations in the current design unit "
498 		     "can be attributed", il);
499 	    }
500 	  else
501 	    {
502 	      pIIR_AttributeValue av = mIIR_AttributeValue (il->pos,
503 							    s->value,
504 							    a);
505 	      d->attributes =
506 		mIIR_AttributeValueList (av->pos, av, d->attributes);
507 	    }
508 	}
509     }
510   else if(el->is(VAUL_ENTITY_NAME_LIST_ALL))
511     {
512       info("%:XXX - no ALL attributions yet", el);
513     }
514   else if(el->is(VAUL_ENTITY_NAME_LIST_OTHERS))
515     {
516       info("%:XXX - no OTHERS attributions yet", el);
517     }
518   else
519     assert(false);
520 }
521