Specman - как выполнить мультирасширение подтипа, также для разных видов подтипов

Я хочу добиться следующей функциональности:

  1. расширить КРАСНЫЙ ЗЕЛЕНЫЙ СИНИЙ пакет {...}

    эта строка приведет к тому, что элементы структуры в фигурных скобках будут добавлены ко всем указанным подтипам определенного перечисляемого типа. результат будет выглядеть так:

    extend RED packet {...}
    extend BLUE packet {...}
    extend GREEN packet {...}
    
  2. расширить БОЛЬШОЙ СРЕДНИЙ КРАСНЫЙ СИНИЙ ЗЕЛЕНЫЙ пакет {...}

    эта строка будет расширять все возможные комбинации элементов каждого перечисляемого типа с элементами структуры, указанными в фигурных скобках. результат будет выглядеть так:

    extend MEDIUM RED packet {...}
    extend MEDIUM BLUE packet {...}
    extend MEDIUM GREEN packet {...}
    extend BIG RED packet {...}
    extend BIG BLUE packet {...}
    extend BIG GREEN packet {...}
    

Спасибо,


person user3444042    schedule 29.04.2014    source источник


Ответы (1)


Этот макрос решает эту проблему, но есть небольшое ограничение. Поскольку этот макрос «определить как вычисляемый», структура, к которой вы собираетесь его применить, должна быть определена в файле, отличном от файла, в котором используется макрос. Здесь показан простой пример использования: (предположим, что этот макрос находится в файле с именем dac.e):

define <multi_when'statement>  "ext_s \[<detr'name>,...\] <base'type>  \{<sm'exp>,...\}" as computed {
var our_struct:rf_struct=rf_manager.get_type_by_name(<base'type>).as_a(rf_struct);
var fields:list of rf_field = our_struct.as_a(rf_struct).get_declared_fields();
var rf_type_list:list of rf_type;
var list_of_0_index:list of uint;
var field_names:list of string;
var list_of_enums:list of rf_enum;
var temp_index:uint=0;
var used_types_list:list of rf_type;
var enumerations:list of string;
var indices:list of uint;
var num_of_each_enum:list of uint;
var  size_of_final_list_of_enumerations_to_be_used:uint=1;
var enum_items_list:list of rf_enum_item;
var final_list_of_enumerations_to_be_used: list of string;
var multiplication_list_algrtm1:list of uint;
var multiplication_list_algrtm2:list of uint;
var multiplication_uint_algrtm:uint=1;
if (<detr'names>.is_empty()){
    error("you did not supply any when subtypes");
};
for each (field) in fields{
    rf_type_list.add(field.get_type());
    field_names.add(field.get_name());
};
for each (typ) in rf_type_list{
    if (rf_type_list[index] is not a rf_enum){
        rf_type_list.delete(index);
        field_names.delete(index);
    };
};
if (rf_type_list.is_empty()){
    error("the type ",<base'type>," does not have any enumerated type fields.");
};
for each (typ) using index (typ_index) in rf_type_list {
    num_of_each_enum.add(0);
    if(indices.is_empty()){
        indices.add(0);
    }else {
        indices.add(indices[typ_index-1])
    };
    enum_items_list = typ.as_a(rf_enum).get_items();
      for each (enum_item) in <detr'names> {
          if (enum_items_list.has(it.get_name()==enum_item)){
            out(enum_item, " is found in ",typ.get_name());
            enumerations.add(append(enum_item,"'",field_names[typ_index]));
              indices[typ_index]+=1;
              num_of_each_enum[typ_index]+=1;
          };
      };
};
for each in num_of_each_enum do { // avoid enums that are not used - to
    if (it==0){
        list_of_0_index.add(index);
    };
};
if (!list_of_0_index.is_empty()){
    list_of_0_index=list_of_0_index.reverse();
    for each in list_of_0_index {
       num_of_each_enum.delete(it);
        indices.delete(it);
        field_names.delete(it);
    }

};
enumerations=enumerations.unique(it);
if (enumerations.is_empty()){
    error("no legal enumerated values were used in the ext_s macro, please check that the arguments in square brackets are in the form of [<enum_item1>,<enum_item2>,...]");
};
//remove the last index (not relevant - and add 0 in the indices[0]
indices.add0(0);
indices.delete(indices.size()-1);
for each in num_of_each_enum do {
    size_of_final_list_of_enumerations_to_be_used*=it;
 };
for each in num_of_each_enum do {
    multiplication_uint_algrtm*=it;
    multiplication_list_algrtm1.add(size_of_final_list_of_enumerations_to_be_used/multiplication_uint_algrtm);
    multiplication_list_algrtm2.add(size_of_final_list_of_enumerations_to_be_used/multiplication_list_algrtm1[index]);
};
//build the final list of string to be used in the extend statement:   
for i from 1 to size_of_final_list_of_enumerations_to_be_used{
    final_list_of_enumerations_to_be_used.add("");
};

for k from 0 to indices.size()-1 do {
    temp_index=0;
    for j from 0 to multiplication_list_algrtm2[k]-1 do {
        for i from 0 to multiplication_list_algrtm1[k]-1 do {
            final_list_of_enumerations_to_be_used[temp_index]=append(final_list_of_enumerations_to_be_used[temp_index]," ",enumerations[indices[k]+j%num_of_each_enum[k]]);
            temp_index+=1;
        };
    };
};
for each in final_list_of_enumerations_to_be_used  do {
    result = appendf("%s extend %s %s {",result,it, <base'type> );
    for each in <sm'exps> do {
        result= appendf("%s %s;",result,it);
    };
    result = append(result , "};");
};
            print result;
};

Обратите внимание, что этот макрос решает интересную проблему: Предположим, у вас есть список из множества элементов определенных типов (например: {a1,a2,b1,b2,c1,c2,c3…}), и вы предварительно не знаете сколько типов в этом списке (в этом примере 3 типа - a,b,c - но их может быть больше или меньше). Итак, вопрос в том, как создать список всех возможных комбинаций всех элементов всех типов (например: 0. a1-b1-c1 1.a1-b1-c2…..11.a2-b2-c3), не зная, сколько типов в списке? Вы можете следовать коду и выяснить алгоритм для этого (используя список индексов, сколько элементов каждого типа и т. д.). Файл, который должен быть загружен до макроса (dac.e):

Структура д:

<'
type t1:[A1,A2,A3,A4,A5];
type t2:[B1,B2,B3];
type t3:[C1,C2,C3];

struct s{
    a:uint(bits:4);
    t_1:t1;
    t_2:t2;
    t_3:t3;
};
'>

И тестовый файл:

<'
Import dac.e;
import struct.e;
//use the macro
ext_s [A1,A2,B1,B2] s {x:int,keep x==6,y:int,keep y==10};
    extend sys{
    s1:A1 B1 s;
    s2:A2 B1 s;
    s3:A1 s;
    run() is also{  
        print s1;
        print s2;
        print s3;
    };
};
'>

Пожалуйста, прокомментируйте, если у вас есть какие-либо вопросы.

person yuvalg    schedule 29.04.2014