Specman - 如何执行子类型多扩展,也适用于不同种类的子类型

时间:2014-04-29 14:31:24

标签: verification specman

我想实现以下功能:

  1. 延长RED GREEN BLUE包{...}

    此行将导致大括号中的struct成员, 要添加到某个枚举类型的所有指定子类型。 结果将如下所示:

    extend RED packet {...}
    extend BLUE packet {...}
    extend GREEN packet {...}
    
  2. 延长BIG MEDIUM RED BLUE GREEN包{...}

    这一行将扩展所有可能的组合 具有struct成员的每个枚举类型的项目 出现在花括号中。 结果将如下所示:

    extend MEDIUM RED packet {...}
    extend MEDIUM BLUE packet {...}
    extend MEDIUM GREEN packet {...}
    extend BIG RED packet {...}
    extend BIG BLUE packet {...}
    extend BIG GREEN packet {...}
    
  3. 谢谢,

1 个答案:

答案 0 :(得分:2)

这个宏解决了这个问题,但是存在一个小的限制。 由于此宏是“定义为计算”,因此应将其应用于的结构应定义在与使用宏的文件不同的文件中。 这里显示了一个简单的用例:(假设此宏位于名为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)之前加载的文件是:

Struct.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;
    };
};
'>

如果您有任何疑问,请发表评论。