0% found this document useful (0 votes)
8 views30 pages

System Verilog Basics Part 2

This document provides an educational overview of SystemVerilog concepts, particularly focusing on Object Oriented Programming (OOP) principles such as inheritance, polymorphism, encapsulation, and abstraction. It includes detailed explanations of classes, methods, properties, and constructors, along with example code and references to GitHub repositories for further exploration. The content is aimed at beginners seeking foundational knowledge in SystemVerilog for design verification.

Uploaded by

yuvaswaraj555
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views30 pages

System Verilog Basics Part 2

This document provides an educational overview of SystemVerilog concepts, particularly focusing on Object Oriented Programming (OOP) principles such as inheritance, polymorphism, encapsulation, and abstraction. It includes detailed explanations of classes, methods, properties, and constructors, along with example code and references to GitHub repositories for further exploration. The content is aimed at beginners seeking foundational knowledge in SystemVerilog for design verification.

Uploaded by

yuvaswaraj555
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 30

System Verilog

Basics
Part II

Daniyal Tahsildar
Disclaimer:
Welcome to this educational document! Here, you'll find a comprehensive
overview of various SystemVerilog concepts, accompanied by example code. Each
topic is conveniently linked to its corresponding code repository on GitHub. Look
for a symbol! Babu’s symbol
Please note that this document is designed solely for educational purposes, aiming
to provide foundational knowledge of SystemVerilog concepts.
All code snippets included have been thoroughly tested using tools such as Mentor
Questa 2021.3 and Synopsys VCS 2021.03, available on EDA Playground.
If you seek a deeper understanding of the topics covered in this document, please
refer the SystemVerilog reference manual. This document primarily serves to
provide a foundational understanding of these concepts.
Your feedback, input, and critique are highly valued! Feel free to connect with me
on LinkedIn or via Email to share your thoughts.

Page | 1
Contents
Object Oriented Programming .............................................................................................. 4
1. Inheritance....................................................................................................................... 4
2. Polymorphism ................................................................................................................. 4
3. Encapsulation .................................................................................................................. 5
4. Abstraction ...................................................................................................................... 5
Introduction to Classes and Methods I ................................................................................. 6
1. Defining a Class .............................................................................................................. 6
2. Creating Class Instances (Objects) ................................................................................. 6
3. Properties ........................................................................................................................ 7
4. Class Inheritance ............................................................................................................. 8
5. Methods........................................................................................................................... 8
5.1. Task .......................................................................................................................... 8
5.2. Function ................................................................................................................... 9
5.3. Static Methods and Properties ............................................................................... 10
6. New Constructor ........................................................................................................... 10
6.1. Default Definition .................................................................................................. 11
6.2. Field Initialization .................................................................................................. 11
6.3. Initialization Using new Arguments ...................................................................... 11
6.4. Initialization with Default Values .......................................................................... 11
7. Polymorphism of Classes.............................................................................................. 12
7.1. Virtual Methods...................................................................................................... 12
8. this, super ...................................................................................................................... 13
9. Class Randomization .................................................................................................... 14
9.1. Rand Mode ............................................................................................................. 15
9.2. Assert for Randomization ...................................................................................... 15
10. Array of Class ............................................................................................................ 16
11. Null Check on Object Handle ................................................................................... 16
12. Variable Scope ........................................................................................................... 16
Introduction to Classes and Methods II .............................................................................. 18

Page | 2
1. Forward Declaration of Classes .................................................................................... 18
2. extern Method ............................................................................................................... 18
3. Constant Class Property ................................................................................................ 19
4. pure virtual Methods ..................................................................................................... 20
5. Abstract Class ............................................................................................................... 20
6. Parameterized Classes................................................................................................... 21
6.1. Parameterized Classes Specialization .................................................................... 22
6.2. Parameterized Classes with Inheritance ................................................................ 23
7. Interface Class............................................................................................................... 24
8. Nested Class .................................................................................................................. 24
9. Object Copying ............................................................................................................. 25
9.1. Copy by Handle ......................................................................................................... 25
9.2. Shallow Copy ............................................................................................................ 26
9.3. Deep Copy ................................................................................................................. 26
9.4. Casting ....................................................................................................................... 28

Page | 3
Object Oriented Programming

Unlike Verilog, SV has constructs implemented for object Oriented Programming


(OOP) that revolves around the concept of objects (instances of a class, building blocks of a
testbench), which can contain data in the form of fields (often called attributes or properties)
and code in the form of methods (known as functions, or tasks). Key principles of OOP include
inheritance, polymorphism, encapsulation, and abstraction.

1. Inheritance
Inheritance is a fundamental concept in programming where a derived class can inherit
properties, methods, and constraints from a base class. This means that all the attributes and
functions defined in the base class are automatically accessible in the derived class when it's
created. In SV, this inheritance relationship is established using the extends keyword.
For example:

2. Polymorphism
Polymorphism in programming is where the behaviour of objects can vary depending
on the specific instance at runtime. It allows a derived class to modify or redefine a method
declared in its base class to suit its particular needs. For polymorphism to work, the method
prototype must remain consistent across both the base class and the derived class.
In SV, the virtual keyword is required to enable polymorphism. When applied to a
method in the base class, it indicates that this method can be overridden by a method with the
same prototype in a derived class.
It's considered a good practice to declare all base class methods as virtual if
polymorphism is desired. Methods that lack the virtual keyword in the base class cannot be
overwritten, thus limiting the flexibility and adaptability of the derived classes. Note that
polymorphism cannot happen without inheritance.
For example:

Page | 4
3. Encapsulation
Encapsulation involves bundling together properties (data) and methods (functions or
tasks) into a cohesive unit known as a class. This means that the data and the operations that
manipulate that data are encapsulated within the same entity.
In essence, encapsulation allows for the organization of data and functionality related to a
specific concept or entity into a single container (class). This container is self-contained and
responsible for managing its own properties and methods.

4. Abstraction
Abstraction involves hiding the complex inner workings of a class and presenting only
the essential features to the outside world. It allows programmers to focus on what an object
does, rather than how it achieves its functionality.
In the context of OOP, abstraction is achieved through data hiding, where the internal
implementation details of a class are concealed from external users. This is done by restricting
access to certain variables or methods of a class, ensuring that they can only be accessed or
modified in specific ways defined by the class itself.
Keywords such as local or protected are often used to control the visibility and accessibility
of class elements, limiting their exposure to the outside world.

Note:
This section offers a brief overview of fundamental OOP concepts. For a deeper
understanding, each concept is explored in detail in the subsequent section of classes and
methods.

Page | 5
Introduction to Classes and Methods I

Classes and methods serve as the foundation of an SV-based testbench, empowering


SystemVerilog with its robustness for design verification. These components are dynamic and
require memory allocation when instantiated. The memory allocated to a class object
comprises the combined sizes of all its properties (or signals). To interact with properties,
methods, or constraints, memory allocation for the object (class instances) is essential. This
section primarily focuses on class properties and methods, with constraints slated for
discussion in a separate section.

1. Defining a Class
Classes are dynamic constructs that facilitate the creation and deletion of objects (class
instances) dynamically. These objects can be passed around using object handles (pointers to
the class instances). The process of defining a class data type typically includes:
1. Identifying the properties needed for the class.
2. Listing down the required methods, determining whether
they should be tasks or functions.
3. Considering if any constraints are necessary for the
properties.
Classes consist of three main elements: properties (data variables/signals), methods (tasks or
functions), and constraints. Objects, or instances of a class, are fundamental to all SV
testbenches.
Methods within a class can be categorized into two types:
Built-in methods: A class inherently possesses four built-in methods: new, randomize, pre-
randomize, and post-randomize.
User-defined methods: These methods are defined by the user to suit specific requirements.

2. Creating Class Instances (Objects)


To create class instances, also known as objects, you first declare a variable of the class
type. Then, you instantiate an object of that class type using the new() keyword.
Here's the syntax: class_name instance_name;
This creates an object handle for the class, but it doesn't allocate memory to it. The new()
keyword is used specifically for memory allocation.
Page | 6
For example:

Once an object is created, its methods can be accessed using the dot operator (`.`).

3. Properties
Properties, also known as fields or signals, are essential components of a testbench,
representing data required by both the Design Under Test (DUT) and the test environment.
Typically, properties are of integral, real, or string types, although they can encompass any SV
data type.
Properties can be categorized as follows:
Local: These properties are accessible only within the methods
and constraints of the same class.
Protected: Accessible within the methods and constraints of the
same class and any inherited classes. Properties marked as
protected cannot be accessed by other classes or modules.
Public: These properties, which are neither local nor protected, are accessible throughout the
test environment or testbench.
Additionally, properties can have the following characteristics:
Static: Memory allocation for these properties occurs at a single location shared by all
instances of the class. This allows for the creation of a commonly shared database for the entire
environment. Static variables can be accessed
using the scope resolution operator (::).
Automatic: Each class instance has dedicated
memory allocation for automatic properties.
Properties can be declared as automatic only
inside procedural blocks. Once the block is
executed, the automatic property memory is
deallocated.
For randomization purposes, properties can be declared as rand or randc. The randomize
method is built-in and can randomize any property declared as rand or
randc. When using randc, cyclic randomization occurs in a specific
order, ensuring that all possible values are generated before repetition
starts. It's important to note that randc should not be used in conjunction

Page | 7
with new() inside loops in the initial block. This is because new() resets the memory used for
previous values, disrupting the cyclic order.
As a best practice, it's advisable to declare every property as protected by default unless
there's a specific need for it to be public. If external access to a protected property is necessary,
it's recommended to declare separate functions to access and modify the property.

4. Class Inheritance
Class inheritance allows for the extension of a base class into a new subclass using the
extends keyword. This process grants the subclass access to all the properties and methods of
the base class. Additionally, the derived class can implement its own unique properties and
methods while retaining access to those inherited from the base class.

5. Methods
A method refers to a procedural block of code that is associated with a class. Methods
encapsulate behaviour and can manipulate the data (properties) of the class. They are similar
to functions or procedures in other programming languages.
SV defines two main types of methods:

5.1. Task
A task represents a procedural block of code that can have zero or more input/output
arguments. It does not return a value. Tasks can execute in zero or more simulation time units.
If an operation needs to take time to execute, using a task is recommended.
The prototype for a task is: task task_name(arguments);
For example: The following code snippet demonstrates how a task is capable of executing in
0 or more simulation time.

Page | 8
5.2. Function
A function is also a procedural block of code that can have zero or more input/output
arguments. Unlike a task, a function returns a value. Functions execute instantaneously,
without consuming simulation time.
The prototype for a function is:
function return_type function_name(arguments);
In SV, all function arguments are considered as input by default. To specify an argument as an
output, it must be explicitly declared.
Example: function void add (a, b, output c);
Following is an example of a function that returns a class instance (object).

A function can also accept the class itself as an input/output argument or return type.
For example, let's consider implementing a compare function within a sample_pkt class:

Page | 9
In this example, the compare function takes another sample_pkt object pkt as an argument. It
compares the properties of the current object (this) with the properties of the provided pkt
object.

5.3. Static Methods and Properties


Static methods exclusively access static properties and cannot access automatic
properties within their method definition. They are integrated into the class definition,
eliminating the necessity for object instantiation to access them. They can be invoked directly
via the class name using the scope resolution operator(::).
Attempting to access automatic properties within a static method can lead to conflicts, as static
methods try to access non-existent properties since automatic properties are instantiated only
with new().
Memory allocation for static methods or properties occurs as soon as the class is defined. They
do not require the use of new().

6. New Constructor
The new constructor is inherent to every class and is responsible for object initialization,
allocating memory for object fields, and assigning default values to them. Users can either
Page | 10
utilize the default definition provided by the language or define their own implementation of
the new constructor. Fields can be accessed using the dot (‘.’) operator.
There are various coding styles for implementing the new constructor:

6.1. Default Definition


No need to explicitly define the new constructor; the
language provides a built-in version.

6.2. Field Initialization


Implement the new constructor and assign specific
values to the fields (using the this keyword is
optional here). This method is suitable when
initializing objects with specific field values.

6.3. Initialization Using new Arguments


Define new() with input arguments to initialize the fields with user-specified values. This
approach is helpful when users want to pass specific values during object creation.
Example:

The example illustrates two distinct approaches to initializing the new() with input arguments.
this.sync refers to the size field defined within the class, while sync represents the input
argument passed to the constructor.

6.4. Initialization with Default Values


Using default values in new() helps prevent errors and simplifies object creation. This
concept applies to all tasks and functions.

Page | 11
Example:

Any data type, including bit, byte, int, arrays, mailbox, events, interfaces, etc., can be passed
as arguments to the new constructor.

7. Polymorphism of Classes
Polymorphism in classes refers to the ability of a derived class to modify the
functionality of a method that has been declared in the base class. However, this feature is only
applicable to methods declared as virtual in the base class.

7.1. Virtual Methods


virtual methods allow derived classes to override the implementation of a method defined in
the base class. For instance, if a base class declares a function as virtual:

Multiple derived classes from this base class can provide different implementations for
the fix_len function. This flexibility allows each derived class to tailor the behaviour of the

Page | 12
method to its specific requirements. It's considered good practice to declare methods in the
base class as virtual, leaving them empty, to enable customization by derived classes.

In SV, polymorphism is dynamic in nature. It enables the use of a variable of the base class
(superclass) type to hold objects of derived classes (subclasses) and to directly access the
methods of these subclasses using the superclass variable.

When a method of a subclass is accessed using a superclass variable, the compiler,


during compile time, is unaware of which specific class will be loaded into the variable.
However, at runtime, the appropriate method is accessed based on the actual class instance
stored in the variable.

8. this, super
In scenarios where both a base class and a derived class contain a property with the
same name, accessing that property directly in the derived class might lead to ambiguity. For
instance, if both classes have a property named count, accessing count in the derived class
would refer to the one defined within the derived class itself. However, if we specifically want
to access the count property from the base class, we can use the super keyword.
super allows users to refer to properties or methods with the same name in both the base
and derived classes as needed. this keyword is utilized to reference class properties or methods
of the current instance, specifically those inherited from the base class. It becomes necessary
to use super when accessing members of a base class that have been overridden in the derived
Page | 13
class. In case of multiple levels of inheritance, super refers to the immediate parent (one level
above class).

From the perspective of the derived class, the syntax would be as follows:
this.count: Refers to the count property in
the derived class (optional to use this here)
super.count: Refers to the count property
in the base class
The choice between super and this
depends on the specific context and
requirements.

Using super.method_name() in a derived class ensures that the functionality available


in the base class is inherited while allowing for polymorphism, enabling users to modify or
extend the functionality as needed. This syntax can be employed in any derived class method
that requires the functionality provided by method_name(). It is required that
super.method_name() is the first line after the method prototype declaration in derived class.
As a best practice, it's recommended to place all common properties and methods in the base
class to promote code reusability and maintainability.

9. Class Randomization
Class randomization differs between objects and non-objects.
Non-objects:
For non-objects, such as integers, bytes, and logic, the randomize() function cannot be utilized.
Instead, $random, $urandom_range, and $urandom functions are used.
Objects:
Page | 14
On the other hand, for objects, which are instances of a class, the randomize() function is used.
The randomize() function returns 0 if randomization fails and 1 if it succeeds.
This function comes with two callback methods:
pre_randomize() and post_randomize(). These callback
methods are automatically invoked when the main
randomize() method is called. Further details on
callbacks will be covered in a separate section.
While inline constraints can accomplish tasks that are performed using
pre_randomize(), users cannot override the randomize() function. However, SV offers users
the option to modify the randomization behaviour by utilizing pre_randomize() and
post_randomize().

9.1. Rand Mode


Rand mode is a feature used to enable or disable
randomization for a property. For instance,
addr.rand_mode(0) disables randomization, while
addr.rand_mode(1) enables it for a property named addr.

9.2. Assert for Randomization


Assert statements provide a compact way of checking conditions, similar to using if
conditions. The syntax for assert is simple: assert(check_condition). If the check condition
evaluates to false, the assert statement triggers an error message. In contrast, if an if statement
is used for checking conditions, the user needs to manually include display statements to
indicate success or failure.
Assert statements can be used anywhere in the code where if statements are valid. When
combined with the randomize() function, assert ensures that an object's fields declared as rand
or randc undergo proper randomization.
Here's an example comparing assert with if
statements for randomization.
We'll discuss assertions in more detail in a later
section.

Page | 15
10. Array of Class
For arrays containing dynamic elements, such as a class, the allocation process involves
two steps: first, allocating memory for the array itself if it’s a dynamic array, and second,
allocating memory for each dynamic element within the array.
Consider the example of a packet class declared as packet pkt_array[]:
pkt_array is allocated memory by doing:
However, this only allocates memory for the array, not the individual packet elements. To
allocate memory for each packet, a loop is used:

Here, memory for each packet is explicitly allocated using new().

11. Null Check on Object Handle


Null check on object handles is crucial for ensuring that memory has been properly
allocated before accessing it. Without this check, attempting to access uninitialized memory
can result in errors such as "Bad handle or reference."
During debugging processes, null checks play a significant role in identifying and resolving
issues. When a simulation fails due to a bad handle or reference error, the simulator provides
the line number and file name where the error occurred, simplifying the debugging process.
Here's an example of how to perform a null check:

12. Variable Scope


Variable scope encompasses three distinct types: global scope, module/class scope, and
method/process scope.
In the global scope, variables, tasks, and functions can be declared freely. To reference
variables within the global scope, utilize the syntax $unit::variable_name. Here, $unit refers
to declarations at the outermost level of the compilation unit. Tasks and functions can also be
declared in global scope, accessible using $unit.

Page | 16
For accessing variables in hierarchies beyond the global scope, use the syntax
$root.module_or_class_name.variable. Here, $root signifies the top-level instance of the
design or test environment.
In referencing a variable or method, precedence is given to the closest declared variable or
method.

Page | 17
Introduction to Classes and Methods II

The previous section provided an introduction to classes, delving into the


implementation of object-oriented concepts, randomization, and method usage, covering the
fundamental aspects of Object-Oriented Programming (OOP) in SystemVerilog. Building
upon this foundation, the current section shifts focus to exploring advanced topics such as
various class types, their applications and object copying techniques.

1. Forward Declaration of Classes


In certain scenarios, it becomes necessary to declare a class variable before the actual
class definition is available. For instance, in the file where a top-level module is present, all
required files for the testbench need to be included. If these files are not included in the correct
order, errors may ensue. Forward declaration of classes serves as a preventive measure against
such errors. It finds use in scenarios requiring a class declaration that has not yet been fully
defined or implemented.
The syntax for forward declaration is as follows:
When employing forward declaration prior to including files, it mitigates errors arising
from incorrect file order. Essentially, it declares the class, and the class obtains its definition
as the compilation progresses to the line that includes the respective file. This approach
prevents potential errors stemming from incorrect file sequencing.

2. extern Method
An extern method refers to a function (or task) prototype specified within a class, with
the actual implementation residing outside the class. They are also called as out-of-block
declarations. The declaration of such
a method outside the class involves
indicating the class to which the
method belongs using a scope
resolution operator. Out of block
declarations using extern enhances
code readability.
For example: Consider a sample_pkt
class as shown here.

Page | 18
It is important to note that when the return type of a method is user-defined and declared
within the class, defining the method externally necessitates specifying the return type with
the class and scope resolution operator. However, since external methods have access to class
properties and declarations, method arguments do not require the use of class scope resolution.
Moreover, it's crucial to declare typedef definitions before the function prototype to prevent
unidentified type errors.
For example:

3. Constant Class Property


A constant class property is a variable declared within a class whose value remains fixed
throughout the simulation. Such properties can be defined as read-only by declaring them as
const. Given the dynamic nature of class objects, there exist two types of read-only variables:
global constants and instance constants.
Global constant class properties are initialized with a fixed value as part of their declaration.
Similar to other const variables, they cannot be assigned a value anywhere other than in their
declaration.
On the other hand, instance constants do not include an initial value in their declaration, only
the const qualifier. However, they can be assigned a value at runtime, but this assignment can
only occur once within the corresponding class constructor (new()).

Page | 19
Example:
For each class instance, the size is specified during object
creation and remains fixed until the end of simulation or
object deletion.

4. pure virtual Methods


Pure virtual methods consist solely of a prototype without an implementation. Their
purpose is to serve as placeholders within a base class, compelling derived classes to
implement them. These methods are denoted with the keyword pure virtual and can only be
used in abstract classes.

5. Abstract Class
In scenarios where a group of classes share properties and methods, a common base
class can be created to encapsulate this shared functionality and structure. However, this base
class cannot be instantiated directly; rather, it serves as a blueprint to be inherited by other

Page | 20
classes. Such classes are called abstract classes. Any class declared as virtual is inherently an
abstract class.
The syntax is:
For example:

It's important to note that declaring a class as virtual doesn't directly relate to
polymorphism. Instead, an abstract class signifies a class to which memory allocation should
not be directly assigned.
Virtual classes cannot be utilized directly; they must be inherited by another class. The
subclasses derived from these virtual classes can then be instantiated if they are not marked as
virtual.
It's crucial to distinguish between virtual classes and virtual methods. While virtual
classes denote abstract classes, virtual methods refer to a different concept. As a best practice,
all tasks and functions within virtual classes should typically be declared as virtual.

6. Parameterized Classes
It's often advantageous to define a generic class that can be instantiated with varying
array sizes or data types. This concept, known as parameterization, facilitates code reuse
across different requirements, fostering flexibility and efficiency.
The syntax for parameterizing classes involves using the # symbol, similar to Verilog. Classes
can be parameterized with any data type available in SV, enabling type parameterization.
Syntax:
While Verilog only supports value parameterization, SV classes offer the flexibility of
parameterization for both data type and value.
For example:

Page | 21
Parameterization significantly enhances code reusability. Depending on specific
requirements, classes can be parameterized with either value or type parameters. For value
parameterization, any data type such as bit, byte, int, or string can be used. For type
parameterization, the keyword type is required. Parameterized classes can also be inherited
and utilized as needed.

6.1. Parameterized Classes Specialization


Specializing a class by passing unique parameter values results in a tailored version of
the class. While the fundamental structure of the class remains unchanged, each specialization
possesses overridden parameters, allowing for customization.
Notably, each specialization of a class maintains its own distinct set of static member
variables. However, to share static member variables across multiple class specializations,
they must be placed within a non-parameterized base class.
Consider the following example:

In this example, each specialization of the class sample_class possesses its own unique
copy of the count variable. Despite sharing the same base class structure, classes with different
specializations are effectively treated as distinct entities. For instance, sample_1 and sample_2
share the same count variable since they have the same specialization while sample_3 has its
own count variable.
To illustrate shared static member variables among multiple class specializations, consider the
following non-parameterized base class:

Here, sample_4 and sample_5[3] share a common memory for the count variable, as it resides
within a non-parameterized class.
Page | 22
6.2. Parameterized Classes with Inheritance
There exist four distinct combinations for parameterization with inheritance, each serving a
specific purpose:
6.2.1. Non-parameterized class extended from a non-parameterized class
o Both the derived and base classes lack parameterization.
o Typically utilized when polymorphism isn't required.

6.2.2. Parameterized class extended from a non-parameterized class


o Useful for sharing a static variable among all class specializations.
o Facilitates the creation of a derived class with required parameters from a base class
with no parameters.

6.2.3. Non-parameterized class extended from a parameterized class


o Employed when further parameterization is unnecessary.

6.2.4. Parameterized class extended from a parameterized class


o Utilized to introduce additional parameters to a parameterized base class without
altering its prototype or functionalities.
o Ensures compatibility by ensuring that the derived class includes both existing and
newly declared parameters from the base class.
Declaration Syntax:

For existing parameters, both read by name and read by position methods are applicable.

Page | 23
7. Interface Class
An interface class is a specialized class that exclusively contains pure virtual
tasks/functions and parameter/type declarations. It does not include any other properties or
methods within its definition, thereby enforcing a contract-like structure for derived classes.
Notably, constraints or properties cannot be implemented within an interface class,
distinguishing it from other class types.
Classes can implement one or more interface classes using the implements keyword
(use comma (,) to separate classes that are inherited from). This approach ensures that the
derived class must compulsorily define the pure virtual methods specified in the interface
class.
For example:

In the provided example, the fifo class implements both the push_in and pop_out
interface classes, obligating it to define the put and get methods as per the interface class
specifications. This promotes adherence to a predefined contract, enhancing code modularity.

8. Nested Class
A nested class refers to a class defined within another class. This nested structure allows
for the organization of classes into hierarchical levels, enabling the creation of multiple layers
of nesting. Much like modules, classes serve as scopes and can be nested within one another.

Page | 24
This nesting feature provides several advantages, including the ability to conceal local names
and allocate resources locally within the nested scope.

9. Object Copying
Object copying encompasses four primary techniques:
1. Copy by Handle
2. Shallow Copy
3. Deep Copy
4. $cast operations

9.1. Copy by Handle


This technique involves copying objects by reference, where the destination object
merely points to the same memory location as the source object. As a result, no new memory
allocation occurs for the destination object, and both objects share the same underlying data.
Consequently, any modifications made to one object will be reflected in the other. This
approach is ideal when the intention is for both objects to reference the same data.
However, it's important to note the drawback: since both objects share the same memory
location, changes made to one object affect the other.
Page | 25
Example:

In this example, s1 and s2 refer to the same memory location, allowing both objects to access
and modify the shared data.

9.2. Shallow Copy


Shallow copy involves the creation of a new memory allocation for the destination
object, wherein all fields of the source object are duplicated into the destination object.
However, only non-object properties are copied to the new memory location.
During a shallow copy, if another object is present inside the source object, only the
object handle is copied, not the internal values, resulting in both objects referencing the same
memory location, similar to copy by handle.
It is done as follows:
For non-object fields, different memory locations are utilized, ensuring independence between
objects. However, for object fields, the same memory is shared between the source and
destination objects after the copy.
It's important to note that shallow copy has
limitations. It's only effective when there are no
objects below the class hierarchy. If there are objects
nested within the class, shallow copy fails as it copies
object handles only, leading to shared memory
between instances even after the shallow copy
operation.
Drawbacks:
Limited applicability when objects are nested within
the class hierarchy.
Objects below the class level are copied by handle,
resulting in shared memory between instances even
after shallow copying.
9.3. Deep Copy
Deep copy involves a user-defined implementation of copying, wherein each field from
the source object is replicated into the destination object. Notably, new memory allocations
are created for objects nested within the class hierarchy.
The copy function can be implemented in various ways, offering flexibility in usage:

Page | 26
1. Using Method Call
source_handle.copy(destination_handle);

2. Using Assignment
destination_handle = source_handle.copy();

Deep copy can also leverage shallow copy techniques. In cases where objects exist
below the class hierarchy, shallow copy is performed for those objects as well to ensure
independent memory allocation.
Example:

Page | 27
In this implementation, the copy function replicates each field (non-object) from the
source object into the destination object. Similarly, for class objects (e.g., sample_2), a shallow
copy is employed allocating memory to object instances.

9.4. Casting
Casting involves converting one variable from one data type into another format. This
process can only be applied to singular variables; arrays or other complex data structures are
not singular.
For example:
Variables subject to casting can be either objects or non-objects. Non-objects, where the
data type is fully known at compile time, are subject to static casting. On the other hand,
objects, where the data type is determined at runtime, are subject to dynamic casting. Objects
can be of any class type (including base or derived classes). Hence, this process is referred to
as dynamic casting.
9.4.1. Static Casting
Static casting involves the syntax datatype '(), allowing for the conversion of data types
at compile time. This type of casting is particularly crucial when dealing with typedef enum
type conversions.
Example:

9.4.2. Dynamic Casting


Dynamic casting involves the transformation of one class into another class using the
$cast operator, a built-in SV method. This process enables the conversion of class_2 into
class_1.
Syntax:
$cast functions similarly to copy by handle, allowing for conversion between class types. Both
the destination and source objects need not be of the same class handles; they can be related
through inheritance.
Furthermore, $cast can behave as both a function and a task depending on its usage.
While a base class object cannot be casted from a derived class objects due to potential type
mismatches, the reverse operation is possible; derived classes can be casted from base classes
Page | 28
since they are related through inheritance. Dynamic casting is successful only if the parent is
previously pointing to the same derived object type.
Example:

Page | 29

You might also like