This is first in a series of three blog posts that are going to present some powerful enhancements that were added to Specman 12.2 in order to ease the modeling of a multi-instance coverage environment. In this blog we're going to focus on the first enhancement, while the other two enhancements will be described in the following coverage blogs.
Starting with Specman 12.2, one can define the coverage options per subtype. Using per-instance, Specman checks the subtypes of each instance, and applies only the relevant subtype options. We will demonstrate the power of this in both "per unit instance" and "per subtype instance."
- I. Utilizing when extensions for modeling per subtype instances
One intuitive use of extensions of covergroups under "when" subtypes relates to covergroups which are collected per subtype using the per_instance item option:
type packet_size_t: [SMALL, LARGE];
struct packet{
size: packet_size_t;
length: uint(bits:4);
event sent;
cover sent is{
item size using per_instance;
item length;
};
};
The results of the above covergroup are collected per each value of the size item, so in practice this covergroup is collected separately per each "size" subtype.
Let's assume that small packets can only have length < 8, and big packets can only have length >= 8. The following code was needed in pre 12.2 releases for refining the irrelevant values of each subtype:
extend packet{
cover sent(size==SMALL) is also{
item length using also ignore=(length >= 8);
};
cover sent(size==BIG) is also{
item length using also ignore=(length < 8);
};
};
This code can now be replaced with a native "when" subtype extension:
extend packet{
when SMALL packet{
cover sent is also{
item length using also ignore=(length >= 8);
};
};
when BIG packet{
cover sent is also{
item length using also ignore=(length < 8);
};
};
};
- II. Utilizing when extensions for modeling per unit instances
Extension of covergroups under "when" subtypes can also be used to model the different instances of a covergroup that are collected per-unit instance, according to the exact subtype of the containing instance.
Let's see a code example that illustrates the power of this capability. In this code we model a packet generator unit that generates packets of different sizes. The packet generator unit has a field which describes the maximal size of a packet that a packet_generator instance can generate:
type packet_size_t: [SMALL, MEDIUM,LARGE,HUGE];
struct packet{
size: packet_size_t;
};
unit packet_generator{
max_packet_size: packet_size_t;
event packet_generated;
cur_packet: packet;
generate_packet() is{
gen cur_packet keeping {it.size.as_a(int) <= max_packet_size.as_a(int)};
emit packet_generated;
};
};
extend sys{
packet_gen1: packet_generator is instance;
keep packet_gen1.max_packet_size == LARGE;
packet_gen2: packet_generator is instance;
keep packet_gen2.max_packet_size == MEDIUM;
packet_gen3: packet_generator is instance;
keep packet_gen3.max_packet_size == HUGE;
};
Oh, right, there's that coverage thing we need to define in order to check that each valid packet size was generated in each instance of the packet_generator :
extend packet_generator{
cover packet_generated using per_unit_instance is{
item p_size: packet_size_t = cur_packet.size;
};
};
OK, so the above code enables the coverage collection of p_size separately for each instance of packet_generator. Let's generate 100 packets in each packet generator instance. Surely we'll get 100% coverage?
Well, we won't. When launching Incisive Metric Center (IMC), three of the coverage instances are not fully covered. For example the grade of the instance under sys.packet_gen1 is only 75%:
The reason for that is the constraint that prevents the generation of HUGE size packets in instance sys.packet_gen1, so no matter how many packets are generated in that instance, the ‘HUGE' bucket (bin) will never be covered.
We need to refine the valid buckets according to the generatable packet size in each instance. We can use the instance specific covergroups extensions for that:
extend packet_generator{
cover packet_generated(e_path==sys.packet_gen1) is also{
item p_size using also ignore = p_size.as_a(int) >
packet_size_t'LARGE.as_a(int);
};
cover packet_generated(e_path==sys.packet_gen2) is also{
item p_size using also ignore = p_size.as_a(int) >
packet_size_t'MEDIUM.as_a(int);
};
cover packet_generated(e_path==sys.packet_gen3) is also{
item p_size using also ignore = p_size.as_a(int) >
packet_size_t'HUGE.as_a(int);
};
};
Now we can achieve 100% grade for each instance:
But in 12.2 we can use the following subtype extensions instead:
extend packet_generator{
when SMALL'max_packet_size packet_generator{
cover packet_generated is also{
item p_size using also ignore = p_size.as_a(int) >
packet_size_t'SMALL.as_a(int);
};
};
when MEDIUM'max_packet_size packet_generator{
cover packet_generated is also{
item p_size using also ignore = p_size.as_a(int) >
packet_size_t'MEDIUM.as_a(int);
};
};
when LARGE'max_packet_size packet_generator{
cover packet_generated is also{
item p_size using also ignore = p_size.as_a(int) >
packet_size_t'LARGE.as_a(int);
};
};
when HUGE'max_packet_size packet_generator{
cover packet_generated is also{// for extend packet_type_t: [GIGANTIC]; ...
item p_size using also ignore = p_size.as_a(int) >
packet_size_t'HUGE.as_a(int);
};
};
};
At first look, the later solution doesn't look more efficient than the former one. It includes 4 extensions of the covergroup instead of 3 extensions that were needed before. But what would have happened if instead of only 3 packet_generator instances we would have 100 instances? If we extend each instance by itself, as we've done in the first solution, we will need to extend each one of the 100 covergroup instances.
While using the "when subtype extension" solution, the 4 extensions above satisfy the requirement for any number of instances.
Even more important, the solution which uses "when subtype extension" is reusable, since it doesn't use the full path of the covergroup instances. So it is much more suitable for verification IPs and for module verification environments which are later integrated into system level verification.
But before you run and start extending your covergroups under subtypes, I'd like to mention that there is another newly supported option in the e language which is even a better suited for that exact scenario which is described above - -it is called the "instance_ignore" item option.
- What is this "instance_ignore" option?
- Why it is better suited for the above scenario?
- For which scenarios is the ‘extension under when subtypes' better suited?
Answers for all of the above questions (and more) will be found in the next Specman coverage blog -- "Using Instance Based Coverage Options for Coverage Parameterization"
Team Specman