Specman - как выполнить множественное расширение подтипа, также для различных типов подтипов
Я хочу добиться следующей функциональности:
расширить пакет RED GREEN BLUE {...}
эта строка приведет к добавлению членов структуры в фигурных скобках ко всем указанным подтипам определенного перечислимого типа. результат будет выглядеть так:
extend RED packet {...} extend BLUE packet {...} extend GREEN packet {...}
расширить БОЛЬШОЙ СРЕДНИЙ КРАСНЫЙ СИНИЙ ЗЕЛЕНЫЙ пакет {...}
эта строка расширит все возможные комбинации элементов из каждого перечислимого типа с элементами 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 {...}
Спасибо,
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):
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;
};
};
'>
Пожалуйста, прокомментируйте, если у вас есть какие-либо вопросы.