AVL Factory
Overview
The AVL factory provides the same functionality as the UVM factory without the complexity of the class::type_id::create() syntax as the factory is native to the avl.Object class.
All classes that exend the avl.Object class can be overridden by the factory.
Override by Type
# Copyright 2024 Apheleia
#
# Description:
# Apheleia factory example
import avl
import cocotb
class example_env(avl.Env):
def __init__(self, name, parent):
super().__init__(name, parent)
self.s = sub_comp_A("s", self)
class sub_comp_A(avl.Component):
def __init__(self, name, parent):
super().__init__(name, parent)
self.error("sub_comp_A should have been overriden by sub_comp_B")
class sub_comp_B(avl.Component):
def __init__(self, name, parent):
super().__init__(name, parent)
self.info("sub_comp_B successfully overriden sub_comp_A")
@cocotb.test
async def test(dut):
avl.Factory.set_override_by_type(sub_comp_A, sub_comp_B)
e = example_env("env", None)
await e.start()
Override by Instance
There is no override by name in AVL. Instead, the factory can be used to override by instance. As wildcards (see below) are supported names can always be found.
# Copyright 2024 Apheleia
#
# Description:
# Apheleia factory example
import avl
import cocotb
class example_env(avl.Env):
def __init__(self, name, parent):
super().__init__(name, parent)
self.s = sub_comp_A("s", self)
self.o = object_A("o", self)
class sub_comp_A(avl.Component):
def __init__(self, name, parent):
super().__init__(name, parent)
self.error("sub_comp_A should have been overriden by sub_comp_B")
class sub_comp_B(avl.Component):
def __init__(self, name, parent):
super().__init__(name, parent)
self.info("sub_comp_B successfully overriden sub_comp_A")
class object_A(avl.Object):
def __init__(self, name, parent):
super().__init__(name, parent)
self.error("object_A should have been overriden by object_B")
class object_B(avl.Object):
def __init__(self, name, parent):
super().__init__(name, parent)
self.info("object_B successfully overriden object_A")
@cocotb.test
async def test(dut):
avl.Factory.set_override_by_instance("env.s", sub_comp_B)
avl.Factory.set_override_by_instance("env.o", object_B)
e = example_env("env", None)
await e.start()
Wildcards are also supported. These are implemented using the Python fnmatch module. If multiple matches are found, the most specific match is used Factory.specificity.
# Copyright 2024 Apheleia
#
# Description:
# Apheleia factory example
import avl
import cocotb
class example_env(avl.Env):
def __init__(self, name, parent):
super().__init__(name, parent)
self.s = sub_comp_A("super_long_name", self)
class sub_comp_A(avl.Component):
def __init__(self, name, parent):
super().__init__(name, parent)
self.error("sub_comp_A should have been overriden by sub_comp_B")
class sub_comp_B(avl.Component):
def __init__(self, name, parent):
super().__init__(name, parent)
self.info("sub_comp_B successfully overriden sub_comp_A")
@cocotb.test
async def test0(dut):
avl.Factory.set_override_by_instance("env.super_long_name", sub_comp_B)
avl.Factory.set_override_by_instance("env.*", sub_comp_A) # Shouldn't be used as not the closest match
e = example_env("env", None)
await e.start()
@cocotb.test
async def test1(dut):
avl.Factory.set_override_by_instance("env.super_*", sub_comp_B)
avl.Factory.set_override_by_instance("*.super_l*", sub_comp_A) # Shouldn't be used as not the closest match
e = example_env("env", None)
await e.start()
@cocotb.test
async def test2(dut):
avl.Factory.set_override_by_instance("env.super_*", sub_comp_B)
avl.Factory.set_override_by_instance("env.super_??*", sub_comp_A) # Shouldn't be used as not the closest match
e = example_env("env", None)
await e.start()
@cocotb.test
async def test3(dut):
avl.Factory.set_override_by_instance("env.super_long_nam?", sub_comp_B)
avl.Factory.set_override_by_instance("env.super_long_nam*", sub_comp_A) # Shouldn't be used as not the closest match
e = example_env("env", None)
await e.start()
@cocotb.test
async def test4(dut):
avl.Factory.set_override_by_instance("env.super_[a-z]", sub_comp_B)
avl.Factory.set_override_by_instance("env.super_*", sub_comp_A) # Shouldn't be used as not the closest match
e = example_env("env", None)
await e.start()
@cocotb.test
async def test5(dut):
avl.Factory.set_override_by_instance("en*.super_[a-z]", sub_comp_B)
avl.Factory.set_override_by_instance("[a-z].super_*", sub_comp_A) # Shouldn't be used as not the closest match
e = example_env("env", None)
await e.start()
Variables
Similar to the UVM config_db / resource_db variables can be set and retrieved from the factory. No copying is done automatically, classes are passed by reference and literals by value.
This means avl.Var objects can be easily shared, as can cocotb hdl handles.
The same wildcards as for the override by instance are supported Factory.specificity.
# Copyright 2024 Apheleia
#
# Description:
# Apheleia factory example
import avl
import cocotb
class example_env(avl.Env):
def __init__(self, name, parent):
super().__init__(name, parent)
self.a = avl.Factory.get_variable(f"{self.get_full_name()}.a", 0)
if self.a != 100:
self.error(f"Expected a to be 100, got {self.a}")
@cocotb.test
async def test(dut):
avl.Factory.set_variable("env.a", 100)
e = example_env("env", None)
await e.start()