I recently got an e-mail asking about copying objects and decided it would be a great blog post.
Specifically, the question asked about the differences between deep versus shallow copy and when one should choose one technique versus another.
The short answer is there is no right answer. The long answer, well, is a little longer…
In any Object-based system, copying an object is not a trivial exercise. As we talked about in the OOP Connections chapter, your verification system is a mesh of objects. Copying a piece of that mesh is tricky. But even beyond that is the seemingly simple task of copying data.
Suppose you are trying to verify a SOC that moves data to and from some interfaces (RAM, ethernet, PCI, etc). You probably have the classic “generator connected to driver and checker through a channel” model.
Before you have to consider shallow versus deep copy, you have to decide if you want to copy the data. In general, you do want to copy the data, but there is at least one case where you do not. This is the case where the driver and the checker need to communicate some information about the data transaction in the channel. Perhaps its a read completion, or a write status word.
Let’s assume our example should copy the data. So, what then is deep copy ? A deep copy is a recursive replication of the members in the class/struct. For example, if our data between the generator and driver/checker was a list of blocks of lower level random data to be sent, both the list and the blocks would be copied.
A shallow copy, by contrast, would only copy the list. A shallow copy does not recurse beyond the “top level” object (the one being copied). In our example, there would only be one instance of the blocks of lower level data.
If your data only consists of integral types, there is no difference between deep and shallow copy. If there are pointers in your class/struct then you need to think about what you want to happen.
Now, if you data has ANY virtual functions (i.e. not just a clump of data), then you really need to think. My general rule is that you are probably doing something wrong. Go back and rethink why your design needs both virtual data members and needs to copy.
If you really do need to copy a class/struct with virtual methods, you generally end up with a two method scheme. One method “makes/news” the right type of object (because this is a virtual method) and the second method copies the data. Pretty darn horrible.
My general advice is to use pointers for most things in a channel. Then you do not have to worry about copying. But if you do have to copy, make sure you think about all the members, data and methods.