Efficient Generator Clones¶
kratos has provided an efficient way to clone generators and modify the clones. Similar to the “copy-on-write”, the Python front-end allows users to create explicit copies and allow them to be initialized later for further editing.
Design Philosophy on CoW¶
The CoW mechanism is still work-in-progress, so the interface may subject to change.
- We want each clones have unique generator information. Since kratos is embedded into the Python language, we can leveraging the Object-Oriented-Programming in Python. This requires every non-verilog information has to be properly initialized during the clone process.
- Since kratos is the generator of generators, we allow user to edit cloned generators. This requires the circuit definition to be initialized prior to the editing, hence the “copy” part.
Implement Generator Clones with create
¶
To avoid excessive computation in kratos’ CoW mechanism, your generators have to meet the following requirements:
Every argument to the
Generator
has to be hashable. For custom classes, you need to override__hash__
function.Your custom generator
__init__
function takesis_clone
as an argument and passes it to the base class generatorinit
call. For instance, you need something like:class Mod(Generator): def __init__(self, width, is_clone=False): super().__init__(f"mod_{width}", is_clone=is_clone)
You have to call
[Generator_Name].create()
for every generator instantiation, where[Generator_Name]
is your generator class name. You have to use named arguments for all your__init__
arguments. For instance, to create an instance of theMod
class, we can callmod1 = Mod.create(width=1) mod2 = Mod.create(width=1)
mod1
andmod2
will share the same generator definition.If you want to make edits to the generators, you need to call
initialize_clone
on that particular instance. This function call ensures the full-instantiation of the generator definition, i.e. the “copy” part in CoW. You can do the following before editing the generator:if mod1.is_cloned: mod1.initialize_clone()
kratos also provides you the pointer reference to the generator that
a clone is referring to. You can access it through
[gen].def_instance
. This is useful if you want to modify the entire
generator definition along with all the clones.
A more efficient yet shallow clone using clone
¶
If you don’t care about the Python variable initialization but care much
about performance, kratos provides a mechanism that copies the IO and
parameter definitions over, using clone(**kargs)
function calls.
The invocation is the same as create(**kargs)
, and doesn’t require
you to have is_clone
in __init__
. However, you are not able to
modify or initialize the cloned instance. In addition, the type of the
cloned instance will be the generic Generator
. You can still access
the original instance though def_instance
though. Here is a table
of summary of the differences between create
and clone
.
Properties | create |
clone |
---|---|---|
Correct type() |
✓ | ✗ |
Most efficient | ✗ | ✓ |
Able to initialize and edit | ✓ | ✗ |
Has def_instance reference |
✓ | ✓ |
Need to have is_clone argument in __init__ |
✓ | ✗ |
A general rule is that if you’re building some basic building blocks that
will be used very often yet doesn’t care about the embedded information,
you should use clone
, otherwise create
is recommended.