0% found this document useful (0 votes)
91 views9 pages

OOP in Verification

This document discusses the limitations of using object-oriented programming (OOP) for hardware verification. Specifically, it examines an issue called "layering" where verification tasks require combining models at different levels of abstraction in a way that does not map cleanly to OOP constructs. While OOP is commonly used, verification often requires additional design patterns and techniques. The document argues hardware verification languages should support constructs beyond OOP to better enable reuse in verification which differs from software domains.

Uploaded by

Swift super
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
91 views9 pages

OOP in Verification

This document discusses the limitations of using object-oriented programming (OOP) for hardware verification. Specifically, it examines an issue called "layering" where verification tasks require combining models at different levels of abstraction in a way that does not map cleanly to OOP constructs. While OOP is commonly used, verification often requires additional design patterns and techniques. The document argues hardware verification languages should support constructs beyond OOP to better enable reuse in verification which differs from software domains.

Uploaded by

Swift super
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 9

Where OOP Falls Short

of Hardware Verification Needs


Matan Vax
Cadence Design Systems, Inc.
8 Hamelacha St., Rosh Ha'ain, 48091, Israel
matan@cadence.com
and stimuli spaces. As the discipline matures, reuse of
ABSTRACT libraries and verification IPs becomes ubiquitous and crucial
Functional verification requires, among other things,
for the success of projects.
dedicated programming constructs and mechanisms. Such are
accessible to a wide community of verification engineers With the adoption of coverage-driven methods existing
today more than in the past thanks to the SystemVerilog programming languages were no longer sufficient for
language. Along with many verification specific constructs it testbench development, as they lacked the means to express
features object-oriented programming (OOP) framework. constraints on stimuli generation and functional coverage
OOP has been extremely successful in facilitating reuse in definitions. So languages dedicated for the task emerged –
many software application domains. This observation hardware verification languages (HVLs). The most widely
suggests that it should serve just as well for reuse in the used public domain HVLs today are e [6], SystemVerilog
verification domain. The present paper critically examines [7], and SystemC/SCV [13].2 All three languages support a
this supposition. It demonstrates issues with the naive rich set of verification specific constructs to express
application of object-oriented mechanisms, and how they are constraints, coverage points, temporal properties, hardware
partially overcome by more sophisticated design techniques. interfaces, and more. However, they differ in the basic
Still these techniques don't scale well and increase code modularization mechanisms they provide.
complexity. The same needs are shown to be met more
naturally with modularization mechanisms that go beyond Developing testbenches for hardware devices is in many
strict OOP. This analysis leads to an interesting observation senses a software engineering task. In order to exercise the
on the nature of reuse in verification. It turns out to differ design under test (DUT) and check its behavior the testbench
substantially from that of classical software application needs to emulate the behavior of the environment in which
domains. If hardware verification languages are to address the device is embedded, as well as the device's own
the challenges of creating reusable verification code, they operation, at various levels of abstraction. This essentially
must accommodate for its unique character. involves models, algorithms, and data structures naturally
expressed in high-level programming languages. Advanced
Categories and Subject Descriptors testbenches are, in this sense, large scale software systems.
B.6.3 [Logic Design]: Design Aids—Verification; D.3.3 Much of the code of a testbench, if built well, may live for
[Programming Languages]: Language Constructs and years and be reused across the hardware project's
Features – Classes and Objects, Patterns. proliferations, various different projects, and even different
companies. A different and more elementary dimension of
General Terms reuse in verification is that between the numerous tests in a
Languages, Verification. single project's test suite [5]. This kind of reuse has no
obvious counterpart in general software systems, but is
Keywords somewhat reminiscent of the variability found in software
Object-Oriented Design, Hardware Verification Languages. product lines. In any case, verification engineers nowadays
must draw upon state-of-the-art software engineering
1. INTRODUCTION methods to meet the challenge of effective code reuse.
Simulation-based functional verification of hardware The dominant programming paradigm in the industrial
designs1 has established itself in recent years as an software world is object-oriented programming. OOP makes
engineering discipline in its own right. It has its own use of the notion of class as the primary unit of
dedicated languages, tool set, methodologies, library eco-
systems, and body of knowledge. The turning point in the
evolution of the discipline was the adoption of coverage- 2 These languages are not exclusively used for verification.
driven methods in conjunction with constrained-random
SystemVerilog is also a hardware design language, and
stimuli generation [11, 16]. Replacing traditional approaches
SystemC is primarily used for hardware modeling.
that were either strictly directed or fully randomized, it deals
SystemC is referred to as a language, although it is actually
more systematically with the explosion of simulation state
a C++ library compiled with standard C++ compilers. Vera
and OpenVera are still used in the industry, but are
proclaimed to be superseded by SystemVerilog. There are
1 Henceforth I shall use the unqualified term 'verification' in many proprietary verification languages and language
this sense. extensions mostly developed in-house by chip makers.
modularization, and relies on class inheritance as its main addr. The verification environment should provide the signal
abstraction mechanism. In so far as verification is ultimately level logic for actually driving a packet into the DUT, as in:
about writing software, it is only natural to expect that OOP
would serve just as well for verification needs. Indeed this class packet_env;
expectation is echoed in all three leading languages. ...
task drive_packet(packet p);
However, in practice even with object-oriented mechanisms
// write packet onto DUT signals
in place the design of testbenches does not resemble all that
endtask
much mainstream software design. This is manifested in the endclass
extensive use of certain design patterns and auxiliary design
constructions. Similar techniques are applied in other Consider a very simple test on top of this environment that
domains, but never in such sweeping manner. This drives 20 packets having lower-end addresses into the DUT.
phenomenon was observed before but the present paper Here is its code:
proposes a generalized analysis for it under the title – the
layering problem. The main contribution of the paper is in class low_addr_packet extends packet;
suggesting what it is about the task of verification that does constraint low_addr { addr <= 'hFF; }
not lend itself naturally to classic object-oriented design. The endclass
answer has to do with the unique form that code reuse must
take in this domain. program test1;
packet_env env;
The remainder of the paper is organized as follows: Section 2
presents a design situation encountered regularly in
initial begin
verification, known as "layering", and explains why it does
env = new();
not map directly to object-oriented constructs. Section 3
random_scenario();
surveys and evaluates techniques to address layering within end
OOP. Section 4 shows how the required relationship can be
captured directly with a different set of language constructs. task random_scenario();
Section 5 builds on previous observations and tries to address int i;
the main question framed above. Work related to this kind for (i = 0; i < 20; i++) begin
analysis is surveyed in section 6, and section 7 concludes. low_addr_packet p = new();
assert(p.randomize());
2. THE LAYERING PROBLEM env.drive_packet(p);
The constrained-random verification flow is essentially about end
running a multitude of tests, each focusing on some specific endtask
feature, condition, or aspect of the DUT. There may be endprogram
hundreds or even thousands of such tests in a regression
suite, and each test is executed multiple times with different Now imagine another test that drives 20 upper-end address
random seeds. The verification environment is the common packets into the DUT, and yet another that drives random
infrastructure for test execution for a given DUT, or simply packets with addresses distributed in some other way. These
put, the code that is shared between all tests. tests share the base packet definition and the driving logic.
However, they have in common also the scenario code that
2.1. Layering Constraints generates 20 packets, with the sole difference being the
It would be instructive to open the exposition of the problem additional constraint. Unfortunately this code cannot be
through an example. Let us consider a testbench for a shared between them because the new operator considers
switching device that interfaces through some packet only the static type of its operand. If the code of task
protocol. Here is a simplistic definition of packet data type in random_scenrio above had used class packet instead of
SystemVerilog:3 low_addr_packet randomization would have ignored
lower_addr constraint. Note that using inline constraints (the
class packet; randomize with operator) may obviate the subclasses of
rand bit[15:0] addr; packet, but the recurrence of generation code in all three tests
rand bit[7:0] data[]; would still remain.
constraint addr_range {addr >= 'h10;} In this trivial example the loop that generates and drives
endclass packets is obviously not worth the trouble of factoring out
This class has two randomized member variables (fields): a and reusing. But it so happens that the structure of legitimate
16 bit address and an array of data bytes. It also has one transaction streams may involve some of the most intricate
member constraint restricting the range of values for variable logic of the protocol. Ideally most tests would reuse this logic
and entirely abstract from it. When constructing a testbench
for a device that interacts through a USB port, for example,
3 For simplicity, all code examples in this section and the the environment may wish to hide the complex packet
next are in SystemVerilog. The same issues arise in handshaking flows while letting the test merely affect the
SystemC/C++ and e so far as standard object-oriented data packets delivered. But this is rendered impossible using
inheritance is used. the language's constructs in this naive manner.
2.2. Layering Behavior The main tasks of the environment are decomposed into
The above situation is often referred to as the layering separate objects classified by their function. Different
problem – the test writer needs to layer some property on top methodologies differ in details and terminology, but are alike
of the environment's data type. This problem is by no means in spirit with respect to this classification. They name entities
restricted to constraints. To illustrate, imagine that in the such as monitors, drivers, sequencers, collectors, loggers,
above testbench some legality check is implemented for generators, etc. These are composed together to form agents
packets and is invoked after a packet has been read off the or transactors, and multiple agents are further grouped in
DUT interface. Here is this aspect of the environment: module and system environments. All these objects function
as software components in the sense that they are created and
class packet; configured during environment setup and live throughout the
... simulation. Other kinds of components, such as scoreboards,
virtual function void check_length(); abstract scenario libraries, register file models, and
// perform check behavioral "golden" models, may also be instantiated in the
endfunction same environment and interconnected.
endclass The architecture of a large scale testbench may become
rather complex. Fortunately, it remains constant (perhaps
class packet_env; with minor variations) for the entire test suite since it
... corresponds to the structure of the DUT. It is unrealistic to
task monitor(); expect that a test would construct and configure the entire
packet p; component hierarchy for itself just to be able to control the
forever begin actual type of some specific monitor or driver. After all, this
collect_packet(p); structure is exactly the kind of non-trivial definition that
p.check_length(); should be abstracted from and reused. So for purposes of test
... writing, inheritance of component classes in its simple form
end is out of the question.
endtask
Finally it should be stressed that the layering problem is not
task collect_packet(output packet p); restricted to tests. Standalone module-level environments can
p = new(); be reused as verification IPs by integrating them into
// read packet off DUT signals different system environments. The large scale environment
endtask will typically need to customize the verification IP and adapt
endclass it to its needs. This is done in much the same way as tests
would, since the IP logic that needs to be reused involves
If a test writer needs to refine the check in some way, she instantiation of its own object model. Packaged IP code is
cannot expect to achieve this just by overriding function usually not open for integrators to edit even if they wanted,
check_length in a derived class. This is again because task and they rarely do.
collect_packet allocates packets by new-ing the base type.
Editing the code of class packet_env may not be an option, as
the source code for this part of the environment is not
3. DESIGN PATTERNS FOR
necessarily available (as in the case of commercial IPs, for LAYERING
example). But even if it were, the decoupling of test and 3.1. Layering with Factories
environment would be sacrificed. Inheriting packet_env and In object-oriented languages virtual method calls are bound
overriding collect_packet is impractical for reasons that shall dynamically, that is, dispatched based on the actual type of
be discussed next. Note also that non trivial behavioral the receiver object. The new operator, on the other hand,
extensions often require auxiliary member variables and
determines the type of the object in the first place and so
functions and may affect more than one class.
must be bound statically with some class. The way to work
around this is seemingly straightforward – use another object
2.3. Layering on top of Components for the instantiation and leverage its polymorphic behavior.
So far we focused on layering properties or behavior on top This auxiliary class is known as a factory. In this way objects
of data item classes provided by the verification can be created in multiple places using an abstract factory
environment. However, most checks and coverage points are interface, while the actual class being thus instantiated is
defined outside the data model, and so are some aspects of determined by the type of a concrete factory object. This is
stimuli such as timing and error injection. Here too actually an old technique that was named a design pattern in
individual tests may need to intervene with the environment's the famous Gang-of-Four book [3].
operation in certain respects to hit corner cases or observe
specific DUT behavior correctly. The naive object-oriented If we apply the pattern to the example in section 2.1 above,
approach would be again to subclass the environment's we would need to replace all explicit uses of the new
classes that handle these tasks and make the required operator with calls to a virtual method create() of an abstract
adaptations. But in itself this move is futile, because just like factory class. The test would then only have to instantiate a
in the case of the data model, instantiation of these classes is concrete factory once, and it in turn will affect the behavior
something the test cannot take over. Here is why. of the entire environment. Leaving out much of the detail, the
environment code may now look thus:
class packet_factory; Imagine a test with another variant of packet, call it
virtual function packet create(); round_addr_packet, which gives more weight to 4-byte
// by default create a packet aligned addresses. It may make sense to apply this property
create = new(); also in conjunction with the low_addr property defined
endfunction above to create a third test. But since a different class is used
endclass to define each of the variants and both derive from packet
they cannot be applied together to the same instances.
class packet_env; Conversely, if round_addr_packet explicitly derives from
packet_factory pfact; low_addr_packet it cannot be applied separately.
...
packet p = pfact.create(); With multiple inheritance, as in SystemC (C++), this kind of
... reuse can be achieved by deriving a third class from both
packet p = pfact.create(); subclasses of packet. This way each test could choose
... between the base class, one of the two subclasses, or the third
endclass class that combines the two. However, this still requires
explicit definition of the combination as a separate class. So
This way layering additional properties or refined behavior the two definitions are not truly pluggable independently in a
on top of the basic packet definition does not require any test. The situation gets worse with more independent
intrusive editing of the environment code. A test can simply properties, of which arbitrary subsets may be used in
define a factory subclass and register its instance with the different tests. The number of explicit classes that need to be
environment class, as follows: created and maintained grows exponentially with the number
of such independent properties.
class test1_packet_factory
extends packet_factory; A related requirement on the part of test writers has to do
virtual function packet create(); with leveraging existing abstractions of the data model. Tests
low_addr_packet p = new(); may need to layer a property on top of an abstract class so as
return p; to affect all its subclasses equally. Consider a protocol that
endfunction defines several variants of its basic data item which have
endclass some properties in common and others not. For example, in
an environment for USB interface it would be natural to
program test1; define data packet, token packet, and handshake packet, as
packet_env env; separate classes, all deriving from an abstract packet class.
Now some tests may need to layer an additional constraint on
initial begin; top of all three subclasses. Ideally the new property would be
// factory registration associated with the common base class, rather than
test1_packet_factory pf; duplicated for each concrete class. The test writer in this case
pf = new(); need not even be aware of the subclasses. But even if
env.pfact = pf; factories have been used to instantiate these classes
... throughout the environment, deriving a new class from the
end base class would not help. The new class does not "blend in"
endprogram with any of the existing.
A utility library can reduce the coding overhead of the Here too multiple inheritance can be used to overcome the
abstract factory pattern for both environment developer and reuse issue. But this is, again, a very lean sense of reuse. It is
test writer. The OVM-SV library, for example, includes a achieved at the price of explicitly crossing the new property
very sophisticated version of the Abstract Factory pattern with every existing subclass. The number of synthetic classes
[10]. It involves global type registry and bookkeeping code generated by this cross may be large, causing significant
encapsulated in base classes and in preprocessor macros. So coding and maintenance overhead. Moreover, the test writer
the environment developer needs to derive from a common cannot remain agnostic of the concrete data model.
base class, and use a factory method for creation supplied by
the library rather then new. The test writer simply needs to 3.3. Behavioral Extensions with Callbacks
call a library function to "override" all allocations of some We turn now to discuss another well known object-oriented
class with that of a subclass. Neither test nor environment technique to tackle the layering problem. It involves using
need to explicitly define or instantiate a factory class. "listeners" or callback objects, and is akin to Command and
Observer design patterns [3]. We shall use the term 'callback',
3.2. Limitations of Factories as it is more commonly used in this context.
The use of factories solves the layering problem in its simple The principle is simple. The environment declares an abstract
form. However, often when tests are defined as refinement class with one or more virtual functions that are called at
layers on top of an existing object model, useful tests may be
designated points in the execution. The classic observer is
obtained by composing two or more such refinements. This
intended to monitor state changes within some model, but
cannot be done with the Abstract Factory pattern, at least not any kind of occurrence can be monitored just as well. The
in a single inheritance language such as SystemVerilog. key here is that a single occurrence may trigger the
notification of multiple callbacks. In its simplest form, the 3.4. Advantages and Limitation of
idea may be implemented in the environment thus:
Callbacks
class env_callback; First it should be noted that callback objects can only
virtual task execute(); implement behavioral extensions. If structural properties
endtask // does nothing by default need to be added to an existing class, such as constraints,
endclass fields, or new methods, other techniques must be applied,
such as factories.4
class packet_env; Callbacks require upfront design of extension points and are
// callback queue only as good as the preparation they have in the environment
env_callback pre_drive_cbs[$]; code. Unlike factories, they cannot be used to apply
unanticipated modifications to a class. In particular, callbacks
task drive_packet(packet p); cannot completely override existing functionality, unless
// invoke all registered callbacks explicit preparation for this has been made. It could be
for (int i = 0; argued that this restriction is actually an advantage, as it
i < pre_drive_cbs.size(); i++) enforces more disciplined usage. Perhaps this position is
pre_drive_cbs[i].execute(); valid in other domains, but often turns out to be too rigid for
real life situations in verification (see a case for this claim in
... // do the actual driving [12]). A related issue with callbacks is the fact that they
endtask encapsulate the extension code in a separate class, while it is
endclass
often tightly coupled with the extended class.
Here the environment triggers all callbacks registered in On the other hand, callbacks are much more flexible with
pre_driver_cbs queue right before actually driving a packet respect to layer composition. Any number of independent
into the DUT. A test that needs to modify the driving callback objects can be registered to monitor the same event,
behavior in this sense can simply define its own callback as long as it has the required preparation. In fact, callbacks
object and register it. The following test utilizes the above are independent in a way that does not allow one to affect
preparation to force random delay before each packet: another, even when this is needed. Further techniques can be
applied to implement more sophisticated notification
class my_delay_cb extends env_callback; semantics. In particular, Chain of Responsibility pattern [3]
virtual task execute(); can be used to enable control flow variability between the
int unsigned delay; calls. With more flexibility comes more complication of
delay = $urandom_range(10); flow, which impedes readability and understandability of the
#(delay); // wait 0..10 time units code.
endtask
endclass
4. FROM DESIGN PATTERNS TO
program test1; NATIVE CONSTRUCTS
packet_env env; Limitations of specific design patterns can usually be
my_delay_cb my_cb; overcome with yet more sophisticated techniques. But the
one inherent down side of design patterns is their very
initial begin existence in the code. They put both cognitive and coding
// ... overhead on the programmer, even when reduced to the
minimum using utility libraries, and have negative impact on
// regiester callback with the env traceability and understandability of the code [2]. The
my_cb = new(); compiler and other development tools remain ignorant of the
env.pre_drive_cbs.push_back(my_cb); design intent expressed in these terms. The pain grows with
end density and variety of patterns applied. It seems that with
endprogram advanced object-oriented verification methodologies this
becomes a serious issue.
Different observer classes (and queues) may be used to
encapsulate different function signatures. Conversely, several Gamma et al. readily admitted that design patterns are a
callback functions may be grouped together in a single matter of point of view – "One person's pattern can be
abstract callback class to encapsulate the handling of related another person's primitive building block" [3]. The difference
events. between two such persons may simply be the programming
Just like in the case the Abstract Factory pattern, it is
worthwhile to encapsulate pattern related services in a utility 4 It should be s,//tressed that neither this section, nor the rest
library. The Verification Methodology Manual (VMM), for
of the paper, attempts a comparison of OVM and VMM.
example, recommends a very wide application of callbacks,
Both include more concepts and services that bear on the
and provides related services encapsulated in library base
considerations raised here. The intention is merely to
classes and macros [1, 15]. These handle registration,
evaluate the two design techniques per se with respect to
unregistration, and the actual invocation of callback objects.
the needs outlined previously.
language they use. Bosch writes "... design patterns are part 4.2. Applying Class Extensions in Layering
of the software engineer’s paradigm and it is the task of the The constraint layering example from section 2.1 above
programming language to represent the concepts in the could be rewritten in e such that a generic random scenario is
paradigm as accurate as possible" [2]. Gil and Lorentz call defined in the environment using the new operator directly.
design patters "puppy language features" and argue that in The e equivalent of the environment's definition for class
many cases they compensate in one language for capabilities packet would be:
that already exist in other languages [4]. This is evident, for
example, with aspect-oriented languages such as AspectJ that
struct packet {
have the Observer collaboration (as in the callback pattern)
addr: uint(bits:16);
as their prototypical application [9].
data: list of byte;
The e language has unconventional features with direct keep addr_range is { addr >= 0x10; }
bearing on the design requirements described above. This };
should come as no surprise, as they were devised from the
The code of test1 would consist simply of an extension to
outset to tackle exactly these challenges. They are
class packet with the additional constraint thus:
inheritance-like mechanisms on top of the standard single
inheritance – class extensions and "when" subtyping. Both
have been presented previously in [6]. Their affinity to key extend packet {
keep addr < 0xFF;
aspect-oriented concepts, namely advice and introductions,
has been analyzed in [12, 14]. In this chapter we shall explain };
very briefly these two mechanisms, leaving details out, and The reader can appreciate the way the extend construct
demonstrate their application to the layering problem. The expresses the intention of the test in a concise and intuitive
main purpose of this is to substantiate the claim that design way without the need for auxiliary definitions. If defining the
techniques discussed above indeed compensate for limited same class in multiple locations should seem strange at first
expressive power of strict object-oriented languages.5 glance, it may be just because we disregard the fact that this
is in fact what we try to achieve here, and what the patterns
4.1. Class Extensions discussed above try to emulate.
In e a class is initially declared with the struct or unit
keyword,6 optionally deriving from another class in the Moreover, the limitations listed in section 3.2 do not plague
standard object-oriented sense. Within the scope of the class' this mechanism. Consider another property defined in some
initial definition new members can be defined, and existing other test, for example:
members can be overridden.
extend packet {
Having been initially defined in this way, a class may be keep data.size() in [2,4,8];
extended elsewhere using the keyword extend. In the scope };
of this construct the class may be further defined in exactly
the same manner – new members can be added and existing The two properties thus defined could be loaded together in
members can be overridden "in-place" so to speak. New the same session and would then apply equally to all
members and new definitions to existing members affect all generated packets, be it within the environment code or
instances of that class, including classes inherited from it, outside. Note that this would have been true even if packet
just as if they were part of its initial definition. This is was an abstract class in the environment and only subclasses
regardless of where the instantiation of (or inheritance from) of it were actually generated.
the class occurs in the code. Now consider the example from section 3.3. The same
Overriding existing definition in the strict sense is often not approach would apply here just as well. The test only needs
required. Subclasses inherited in the standard way, and more to extend class packet_env and refine time-consuming
so in-place class extensions, often need to augment existing method drive_packet (e's equivalent of SystemVerilog's
definitions rather than replace them altogether. For this member task):
purpose e makes available two additive modes of member
overriding, or more aptly – refinement. They place the new extend packet_env {
definitions after or before the exiting definitions, and are drive_packet() @clock is first {
denoted by the key phrases is also and is first var delay: int[0..10]
respectively. The standard object-oriented replacement gen delay;
semantics is denoted by is only. wait [delay];
};
};
5 If a number of refinements for the same method are compiled
This is not to claim that e's are the only conceivable
mechanisms for that purpose, nor even that they are the or loaded in the same session they all get executed upon
best ones. every call. The order of execution is determined according to
6
dependency between the modules (source files). The effect
The difference between the two corresponds to a distinction thus achieved is similar to that of the use of callbacks. But no
made previously between data types and components. For up-front preparation in the base environment is required and
present purposes both keywords prefix class definitions. the coding overhead is gone.
4.3. Taking it Further with When Subtypes configuring components, such as buttons, panes, menus etc.
A when subtype is simply a class under some condition. These are placed within a window, and behavior is associated
Assume that class packet has a field (member variable) with events reported by them. The library provides a pure
named kind of an enumerated type, whose possible values are object model for these components while instantiation is left
token, data, and handshake. In e these values imply the exclusively to the application.
existence of 3 subtypes of packet, namely token packet, data What in verification is analogous to this classic relation
packet, and handshake packet. An instance of class packet between library and end-application? Where does the main
with field kind equals to token is actually an instance of the "reuse divide" pass? In a single verification project much of
type token packet. The phrase token packet represents a logic is common to all tests in a regression suite. Its
type for all purposes – declaring variables, casting, etc. When complexity is typically greater than that of any specific test,
subtypes may be extended just like any other class type, and so is the effort that goes into its development. But a
making the definitions in the extension scope conditional. verification environment is very different in nature from a
They apply to an object in as far as it is an instance of that class library, just as tests are very different from GUI
subtype, that is, it is an instance of the base class and its applications.
corresponding field is of the right value at that time.
Section 2 above already outlined what a verification
When subtypes are ideal for data modeling where different environment should consist of. It is not merely a set of
values of a field correspond to structural differences of the abstract building blocks for writing test. Rather, it is a
data item in which it is embedded. This is often the case in concrete and fully operational model simulating in great
hardware protocols and processor instruction sets. More details relevant aspects of the environment in which the
importantly, with when subtypes it is possible to constrain device is embedded. If built properly a verification
and randomize the type of data items. environment could, at least in principle, execute as-is (or
In the context of the present discussion when subtypes are a almost as-is) achieving real coverage and possibly
way to introduce independent sub-classifications of objects uncovering bugs.7 It obviously makes no sense to expect
and thus gain finer control over extensions. A constraint may something of the sort from the average class library.
be put on data packet without affecting other kinds of Similarly, individual tests, when distilled to their essentials,
packets. Imagine another field of packet indicating whether it don't resemble standalone applications in any way. Tests may
is legal or corrupt. This field would expand a sub- need to configure some properties of the environment,
classification on an orthogonal dimension. So under corrupt perhaps make slight adaptations to its behavior. But most
packet there could be a refined implementation of some commonly tests use constraints and procedural code to guide
method, and it would apply to all corrupt packets, regardless random stimuli into the scenario's areas of interest. In this
of whether they are data packets or of other kinds. sense tests are merely variations on the environment's
This use for when subtypes is very common also in definitions. If fact, test may involve a number of independent
customizing components. Bus agents, for example, are variations combined together, where variations themselves
typically classified into masters and slaves, a classification may be shared across some (but not all) tests. Interestingly,
that may affect both their structure and behavior. From the this mode of reuse is not restricted to tests. It is often
testbench point of view some may be active in the sense that manifested also when integrating verification IPs in system-
they actually inject synthetic traffic, while others passive, level environments.
that is, merely monitoring traffic. These classifications are At the heart of what we identified as the layering problem
naturally captured as when subtype extensions to class agent. lies the fact that the model defined by the environment is
Any given agent is either a master or a slave, and concrete. Unlike the case with class libraries, the verification
independently either active or passive. In all four cases all environment does much, if not all, of the actual instantiation
and only the relevant definitions apply. of classes it defines. Generation of data item streams for
stimulating the DUT obviously requires instantiation, and so
5. DISCUSSION: THE REUSE MODEL does collection of DUT responses for checking. The
IN VERIFICATION construction of environment's component architecture, which
The object-oriented programming paradigm emerged in the may become fairly complex, also involves instantiation of
1970's with the development of Smalltalk. One of its first and objects.
most distinctive applications was in the design of a graphical There are two basic tasks that a software system needs to
user interface (GUI) framework [8]. The language handle – the definition of a model and its instantiation. The
mechanisms forged for this purpose, most notably class object-oriented paradigm focuses on modularization of the
inheritance and polymorphism, were extremely successful in model's definition prior to its instantiation, and indeed this is
capturing the commonalities between library entities, and in where potential for reuse lies in many application domains.
supplying useful abstractions to the end application. But in verification the balance between the two tasks is
Let us consider the mode of reuse in the context of this different from a reuse point of view. Much of the logic of a
classical application for OOP. Reuse here means first and
foremost factoring the code-intense definitions of graphical
7
elements into a library so that they can easily be shared In fact, some commercial verification IPs do just that and
between many different applications. Applications define even claim to cover significant portions of the verification
their custom GUI by specializing, instantiating, and goals relative to a given plan.
verification environment involves instantiation, while the constructs. It may well need a suitable programming
tests typically just need refine some aspect of the model. This paradigm to supply the right toolbox for modularization,
mode of reuse constitutes a different programming paradigm. abstraction, and reuse.
As quoted previously, it is the task of the programming
language to represent the concepts in the paradigm as 8. ACKNOWLEDGEMENTS
accurate as possible. I wish to thank Brett Lammers, Shlomi Uziel, and Zeev
Kirshenbaum of Cadence, and JL Gray of Verilab, who
6. RELATED WORK provided valuable feedback on earlier drafts of this paper.
Hollander et al. [5] survey the unique mechanisms for
separation of concerns of the e language, and their relation to 9. REFERENCES
the specific challenges encountered in verification. The 1. Bergeron, J., Cerny, E., Hunter, A., and Nightingale, A.
present paper is very much following the lead of hints in their 2005 Verification Methodology Manual for
work, in particular in its focus on the special relation between Systemverilog. Springer-Verlag New York, Inc.
a verification environments and individual tests in a test
suite. However, in their paper Hollander et al. do not discuss 2. Bosch, J. 1998. Design Patterns as Language Constructs.
possible solutions within the bounds of object-oriented In Journal of Object-Oriented Programming, vol 11, 18-
programming, and their limitations. The present paper 32.
attempts exactly this analysis. Here e's mechanisms are 3. Gamma, E., Helm, R., Johnson, R., and Vlissides, J. 1995
mentioned mostly to substantiate the criticism of object- Design Patterns: Elements of Reusable Object-Oriented
oriented languages in this respect. Software. Addison-Wesley Longman Publishing Co., Inc.
Robinson's book [12] is strongly related to issues discussed 4. Gil, J. and Lorenz, D. H., 1998, Design patterns vs.
in the present paper. Apart from being a valuable book for language design. In Proceedings of the 11 th European
practitioners, it contains some insights on the very idea of Conference on Object-Oriented Programming, Lecture
aspects and AOP. Unlike the present paper, it stresses the Notes in Computer Science, vol. 1241, 9-13.
general problem of crosscutting concerns and how AOP
promotes better modularization of them. Robinson is surely 5. Hollander, Y., Morley, M., and Noy, A. 2001. The e
right in that, being large software systems, testbenches have language: A fresh separation of concerns. In Proceedings
crosscutting concerns. He does not stress enough, though, the of the International Conference on Technology of Object-
special traits of the verification domain that make these Oriented Languages and Systems (TOOLS 2001 Europe
AOP-like mechanisms indispensable. Unlike Robinson, the Conference, Zurich, Switzerland).
present paper focuses on problems of reuse in verification 6. IEEE Standard for the Functional Verification Language
that are not germane to most other domains. 'e', IEEE Computer Society, IEEE, New York, NY, IEEE
Std 1647—2006
7. CONCLUSION
This paper presented a software design situation that is 7. IEEE Standard For System Verilog - Unified Hardware
ubiquitous when building reusable verification environments. Design, Specification and Verification Language, IEEE
It concerns layering properties and behavior on top of a Computer Society, IEEE, New York, NY, IEEE Std
model without owning its instantiation. This design situation 1800—2005
does not map naturally to native object-oriented constructs.
8. Kay, A. C. 1993. The early history of Smalltalk. In the
Design patterns and techniques are applied across the board
Second ACM SIGPLAN Conference on History of
by verification methodologies to overcome this shortcoming,
Programming Languages (Cambridge, Massachusetts,
but these techniques are inherently cumbersome and not
United States, April 20 - 23, 1993). HOPL-II. ACM, New
wholly satisfactory. Language mechanisms that go beyond
York, NY, 69-95.
the strict object-oriented paradigm do a much better job in
capturing the same design intent. In fact, the object-oriented 9. Kiczales, G., Hilsdale, E., Hugunin, J., Kersten, M., Palm,
techniques seem to emulate these very mechanisms. J., and Griswold, W. G. 2001. An Overview of AspectJ.
In Proceedings of the 15th European Conference on
What makes the programming paradigm that works so well
Object-Oriented Programming (June 18 - 22, 2001). J. L.
for most complex software systems not right for verification?
Knudsen, Ed. Lecture Notes In Computer Science, vol.
Some insight can be gained by comparing the mode of reuse
2072. Springer-Verlag, London, 327-353.
in classical object-oriented application domains and that of
verification environments. In a nutshell, object models make 10. OVM web site. http://ovmworld.org
very good candidates for reuse, but construction and
generation logic does not. The latter is extremely important 11. Piziali, A. 2007 Functional Verification Coverage
in verification, and less so in other domains. Measurement and Analysis. 1st. Springer Publishing
Company, Incorporated.
The upshot of this discussion is twofold. It reinforces the
claim that simulation-based verification is a unique kind of 12. Robinson, D. 2007, Aspect-Oriented Programming with
challenge, not reducible in its methods to other engineering the e Verification Language: A Pragmatic Guide for
disciplines. From the point of view of language design, there Testbench Developers. Elsevier Inc.
is a lesson to be learned too. A domain specific language is 13. SystemC web site. http://www.systemc.org
not all about domain specific types, operators, or even
14. Vax, M. 2007. Conservative aspect-orientated 15. VMM web site. http://vmm-sv.org
programming with the e language. In Proceedings of the
6th international Conference on Aspect-Oriented 16. Wile, B., Goss, J., and Roesner, W. 2005 Comprehensive
Software Development (Vancouver, British Columbia, Functional Verification: the Complete Industry Cycle
Canada, March 12 - 16, 2007). AOSD '07, vol. 208. (Systems on Silicon). Morgan Kaufmann Publishers Inc.

You might also like