1

Are there built-in methods in Specman that give me the value of the first, last, and next value of an enumerated variable? For example:

type color_e: [blue, green, red, yellow, orange];`
        var color: color_e;

color = <want to assign first value of color_e>;  //blue
       …
        color = <next value>;     //which is green

3 Answers3

3

you can use the all_values() method, which returns a list of all value of the enumerated type. You can then play with the list as you want.

example:

 type color : [RED, BLUE, GREEN];
    extend color : [BLACK, CYAN];

    extend sys {
       run() is also {
         var x : color;
         foreach in all_values(color) {
            x = it;
            print x;
         };
     };
    };


Running the test ...
  x = RED
  x = BLUE
  x = GREEN
  x = BLACK
  x = CYAN
Semadar
  • 105
  • 6
1

I got the following reflection solution, but woner if there is an easier way.

<'

 ----------------------------------------------------------------------
 -- Define an enumerated type and populate
 ----------------------------------------------------------------------
  type color_e : [blue, green, red, yellow, orange];


  ----------------------------------------------------------------------
  -- Extend sys
  ----------------------------------------------------------------------
  extend sys {

  ----------------------------------------------------------------------
  -- Use the reflection facility to get the number of labels in an
  -- enumerated type
  ----------------------------------------------------------------------
  get_num_labels(enum_item: string) : int is {

    var size : int; -- number of labels defined in the enumerated type

    -- Find the type if defined
    for each (t) in rf_manager.get_user_types() { 
       if t is a rf_enum and t.get_name() == enum_item {
          -- return the size of the list
         result = t.as_a(rf_enum).get_items().size();
       }; // if t is a rf_en...
    }; // for each (t) in...
 }; // get_num_labels( ...

 ----------------------------------------------------------------------
 -- Use the reflection facility to return the value of the
 -- label defined in an enumerated type at a particular index
 ----------------------------------------------------------------------
   get_enum_label_value(enum_item: string, idx: int) : int is {

    var size : int; -- number of labels defined in the enumerated type

    -- Find the type if defined
    for each (t) in rf_manager.get_user_types() { 
       if t is a rf_enum and t.get_name() == enum_item {

          -- get the size of the list
          size = get_num_labels(enum_item);

          -- return the value of the item in the list at the specified index if legal
          if (idx < size) {
            result = t.as_a(rf_enum).get_items()[idx].get_value();
          } else {
            dut_errorf("Index requested is greater than the number of labels in the enumerated type %s\n",enum_item);
          };

       }; // if t is a rf_en...
    }; // for each (t) in...
 }; // get_enum_label_value( ...


 ----------------------------------------------------------------------
 -- Extend the run phase
 ----------------------------------------------------------------------
   run() is also {

     var color : color_e;
     var size  : int;

     size = get_num_labels("color_e");
     messagef (NONE, "Enumerated type color_e has %d labels, and they are...\n", size);

     for i from 0 to (size-1) {
        color = get_enum_label_value("color_e",i).as_a(color_e);
        messagef (NONE, "%s\n", color);
     }; -- for

   }; // run is also

 }; // extend sys

'>
  • To get a specific type in reflection by name, there is no need to loop over get_user_types(). There is an existing reflection method for that: rf_manager.get_type_by_name(). So, you could simply do: if rf_manager.get_type_by_name(the_name) is a rf_enum (rfe) then { result = rfe.get_items().size() }; or something like that. Also, even when we do need to loop over all enumerated types, we can do it like this: for each rf_enum in rf_manager.get_user_types() { ... } so there is no need to explicitly check whether each one "is a rf_enum", and no need in the explicit as_a(ef_enum). – Yuri Tsoglin Aug 04 '14 at 09:38
1

Another possible solution (in addition to all_values()) is with reflection. Given a rf_enum, we can call its get_items() method to get a list of all enum items.

However, there are some differences between the refleciton soluition and all_values(), which are important to know. One difference is that if some enum items are given explicit numeric values, not necessarily in increasing order, then all_values() will return the values in increasing order, but rf_enum.get_items() will return the items in the order of declaration. For example, if we have:

type foo: [A=5, B, C=1, D];

then all_values(foo) will return C, D, A, B (in this order - according to the respective numeric values 1, 2, 5, 6), but rf_manager.get_type_by_name("foo").as_a(rf_enum).get_items() will return A, B, C, D. If you want to get the reflection result sorted by the numeric values, you can do, for example, rf_manager.get_type_by_name("foo").as_a(rf_enum).get_items().sort(it.get_value()).

Another difference is that when we have several enumerated types based on each other, with different generative sub-ranges, then all_values() for a specific type will return only values that belong to that types's generative range, but rf_enum.get_items() will return all items. For example:

type t1: [A, B, C, D];
type t2: t1[A..B];
type t3: t2;
extend t2: [E];

With this example, rf_enum.get_items() will return A, B, C, D, E for any of t1, t2, or t3. But all_values() will give different results, according to the generative range of each type. all_values(t1) will return A, B, C, D; all_values(t2) will return A, B, E; and all_values(t3) will return A, B.

Yuri Tsoglin
  • 963
  • 4
  • 7