Reference Documentation¶
Module coverage
¶
Functional Coverage features.
Classes:
CoverageDB
- singleton containing coverage database.CoverItem
- base class for coverage, corresponds to a covergroup, created automatically.CoverPoint
- a cover point with bins.CoverCross
- a cover cross of cover points.CoverCheck
- a cover point which checks only a pass/fail condition.
Functions:
coverage_section()
- allows for convenient definition of multiple coverage items and combines them into a single decorator.merge_coverage()
- merges coverage files in XML or YAML format.
- class cocotb_coverage.coverage.CoverageDB(*args, **kwargs)[source]¶
Bases:
dict
Class (singleton) containing coverage database.
This is the coverage prefix tree (trie) containing all coverage objects with name string as a key (using dot as a stage separator). Coverage primitives may be accessed by string identificator. Example coverage trie is shown below:
Examples:
>>> CoverageDB()["top"] #access whole coverage under ``top`` >>> CoverageDB()["top.b"] #access whole covergroup >>> CoverageDB()["top.b.cp1"] #access specific coverpoint
- report_coverage(logger, bins=False, node='')[source]¶
Print sorted coverage with optional bins details.
- cocotb_coverage.coverage.coverage_db = {}¶
Instance of the
CoverageDB
.
- class cocotb_coverage.coverage.CoverItem(name)[source]¶
Bases:
object
Class used to describe coverage groups.
CoverItem
objects are created automatically. This is a base class for all coverage primitives (CoverPoint
,CoverCross
orCoverCheck
). It may be used as a base class for other, user-defined coverage types.- add_threshold_callback(callback, threshold)[source]¶
Add a threshold callback to the
CoverItem
or any its derived class.A callback is called (once) when the threshold is crossed, so that coverage level of this particular cover group (or other object) exceeds defined % value.
- Parameters:
callback (func) – a callback function.
threshold (int) – a callback call threshold (% coverage).
Examples:
>>> def notify_threshold(): >>> print("reached 50% coverage!") >>> >>> # add callback to the cover group >>> coverage_db["top.covergroup1"].add_threshold_callback( >>> notify_threshold, 50 >>> ) >>> # add callback to the cover point >>> coverage_db["top.covergroup1.coverpoint4"].add_threshold_callback( >>> notify_threshold, 50 >>> )
- add_bins_callback(callback, bins)[source]¶
Add a bins callback to the derived class of the
CoverItem
.A callback is called (once) when a specific bin is covered.
- Parameters:
callback (func) – a callback function.
bins – a particular bin (type depends on bins type).
Examples:
>>> def notify_bins(): >>> print("covered bin 'special case'") >>> >>> coverage_db["top.covergroup1.coverpoint5"].add_bins_callback( >>> notify_bins, 'special case' >>> )
- property size¶
Return size of the coverage primitive.
Size of the cover group (or other coverage primitive) is returned. This is a total number of bins associated with assigned weights.
- Returns:
size of the coverage primitive.
- Return type:
- property coverage¶
Return size of the covered bins in the coverage primitive.
Number of the covered bins in cover group (or other coverage primitive) is returned. This is a number of covered bins associated with assigned weights.
- Returns:
size of the covered bins.
- Return type:
- property cover_percentage¶
Return coverage level of the coverage primitive.
Percent of the covered bins in cover group (or other coverage primitive) is returned. This is basically a
coverage()
divided bysize()
in %.- Returns:
percent of the coverage.
- Return type:
- property detailed_coverage¶
Return detailed coverage - full list of bins associated with number of hits. If labels are assigned to bins, labels are returned instead of bins values.
A dictionary (bins) -> (number of hits) is returned.
- Returns:
dictionary associating number of hits with a particular bins.
- Return type:
- property new_hits¶
Return bins hit at last sampling event. Works only for objects deriving from
CoverItem
.- Returns:
list of the new bins (which have not been already covered) sampled at last sampling event.
- Return type:
- class cocotb_coverage.coverage.CoverPoint(name, vname=None, xf=None, rel=None, bins=[], bins_labels=None, weight=1, at_least=1, inj=False)[source]¶
Bases:
CoverItem
Class used to create coverage points as decorators.
This decorator samples members of the decorated function (its signature). Sampling matches predefined bins according to the rule:
rel(xf(args), bin) == True
- Parameters:
name (str) – a
CoverPoint
path and name, defining its position in a coverage trie.vname (str, optional) – a name of the variable to be covered (use this only when covering a single variable in the decorated function signature).
xf (func, optional) – a transformation function which transforms arguments of the decorated function. If
vname
andxf
are not defined, matched is a single input argument (if only one exists) or a tuple (if multiple exist). Note that theself
argument is always removed from the argument list.bins (list) – a list of bins objects to be matched. Note that for non-trivial types, a
rel
must always be defined (or the equality operator must be overloaded).bins_labels (list, optional) – a list of labels (str) associated with defined bins. Both lists lengths must match.
rel (func, optional) – a relation function which defines the bins matching relation (by default, the equality operator
==
).weight (int, optional) – a
CoverPoint
weight (by default1
).at_least (int, optional) – the number of hits per bins to be considered as covered (by default
1
).inj (bool, optional) – “injection” feature, defines that only one bin can be matched at single sampling (default
True
).
Example:
>>> @coverage.CoverPoint( # cover (arg/2) < 1 ... 4 (4 bins) ... name = "top.parent.coverpoint1", ... xf = lambda x : x/2, ... rel = lambda x, y : x < y, ... bins = list(range(5)) ... ) >>> @coverage.CoverPoint( # cover (arg) == 1 ... 4 (4 bins) ... name = "top.parent.coverpoint2", ... vname = "arg", ... bins = list(range(5)) ... ) >>> def decorated_func1(self, arg): ... ...
>>> @coverage.CoverPoint( # cover (arg1, arg2) == (1, 1) or (0, 0) (2 bins) ... name = "top.parent.coverpoint3", ... bins = [(1, 1), (0, 0)] ... ) >>> def decorated_func1(self, arg1, arg2): ... ...
- property coverage¶
Return size of the covered bins in the coverage primitive.
Number of the covered bins in cover group (or other coverage primitive) is returned. This is a number of covered bins associated with assigned weights.
- Returns:
size of the covered bins.
- Return type:
- property detailed_coverage¶
Return detailed coverage - full list of bins associated with number of hits. If labels are assigned to bins, labels are returned instead of bins values.
A dictionary (bins) -> (number of hits) is returned.
- Returns:
dictionary associating number of hits with a particular bins.
- Return type:
- class cocotb_coverage.coverage.CoverCross(name, items=[], ign_bins=[], weight=1, at_least=1)[source]¶
Bases:
CoverItem
Class used to create coverage crosses as decorators.
This decorator samples members of the decorated function (its signature). It matches tuples cross-bins which are Cartesian products of bins defined in
CoverPoints
(items).- Parameters:
name (str) – a
CoverCross
path and name, defining its position in a coverage trie.items (list) – a list of
CoverPoints
by names, to create a Cartesian product of cross-bins.ign_bins (list, optional) – a list of bins to be ignored.
weight (int, optional) – a
CoverCross
weight (by default1
).at_least (int, optional) – the number of hits per bin to be considered as covered (by default
1
).
Example:
>>> @coverage.CoverPoint( ... name = "top.parent.coverpoint1", ... xf = lambda x, y: x, ... bins = list(range(5)) # 4 bins in total ... ) >>> @coverage.CoverPoint( ... name = "top.parent.coverpoint2", ... xf = lambda x, y: y, ... bins = list(range(5)) # 4 bins in total ... ) >>> @coverage.CoverCross( ... name = "top.parent.covercross", ... items = ["top.parent.coverpoint1", "top.parent.coverpoint2"], ... ign_bins = [(1, 1), (4, 4)], # 4x4 - 2 = 14 bins in total ... ) >>> def decorated_func(self, arg_a, arg_b): >>> # bin from the bins list [(1, 2), (1, 3)...(4, 3)] will be matched >>> # when a tuple (x=arg_a, y=arg_b) was sampled at this function call. ... ...
- property coverage¶
Return size of the covered bins in the coverage primitive.
Number of the covered bins in cover group (or other coverage primitive) is returned. This is a number of covered bins associated with assigned weights.
- Returns:
size of the covered bins.
- Return type:
- property detailed_coverage¶
Return detailed coverage - full list of bins associated with number of hits. If labels are assigned to bins, labels are returned instead of bins values.
A dictionary (bins) -> (number of hits) is returned.
- Returns:
dictionary associating number of hits with a particular bins.
- Return type:
- class cocotb_coverage.coverage.CoverCheck(name, f_fail, f_pass=None, weight=1, at_least=1)[source]¶
Bases:
CoverItem
Class used to create coverage checks as decorators.
It is a simplified
CoverPoint
with defined 2 bins: PASS and FAIL andf_pass()
andf_fail()
functions.- Parameters:
name (str) – a
CoverCheck
path and name, defining its position in a coverage trie.f_fail – a failure condition function - if it returns
True
, the coverage level is set to0
permanently.f_pass – a pass condition function - if it returns
True
, the coverage level is set toweight
afterat_least
hits.weight (int, optional) – a
CoverCheck
weight (by default1
).at_least (int, optional) – the number of hits of the
f_pass
function to consider a particularCoverCheck
as covered.
Example:
>>> @coverage.CoverCheck( ... name = "top.parent.check", ... f_fail = lambda x : x == 0, ... f_pass = lambda x : x < 5) >>> def decorated_fun(self, arg): >>> # CoverCheck is 100% covered when (arg < 5) and never (arg == 0) was >>> # sampled. CoverCheck is set to 0 unconditionally when at least once >>> # (arg == 0) was sampled. ... ...
- property coverage¶
Return size of the covered bins in the coverage primitive.
Number of the covered bins in cover group (or other coverage primitive) is returned. This is a number of covered bins associated with assigned weights.
- Returns:
size of the covered bins.
- Return type:
- property detailed_coverage¶
Return detailed coverage - full list of bins associated with number of hits. If labels are assigned to bins, labels are returned instead of bins values.
A dictionary (bins) -> (number of hits) is returned.
- Returns:
dictionary associating number of hits with a particular bins.
- Return type:
- cocotb_coverage.coverage.coverage_section(*coverItems)[source]¶
Combine multiple coverage items into a single decorator.
- Parameters:
*coverItems ((multiple)
CoverItem
) – coverage primitives to be combined.
Example:
>>> my_coverage = coverage.coverage_section( ... coverage.CoverPoint("x", ...), ... coverage.CoverPoint("y", ...), ... coverage.CoverCross("z", ...), ... ... ... ) >>> >>> @my_coverage >>> def decorated_fun(self, arg): ... ...
Module crv
(Constrained Random Verification)¶
Constrained-random verification features.
Classes:
Randomized
- base class for randoimzed types.
- class cocotb_coverage.crv.Randomized[source]¶
Bases:
object
Base class for randomized types.
The final class should contain defined random variables using the
add_rand()
method.Constraints may be added and deleted using the
add_constraint()
anddel_constraint()
methods respectively.A constraint is an arbitrary function and may either return a
True
/False
value (hard constraints) or a numeric value, which may be interpreted as soft constraints or distribution functions.Constraint function arguments (names) must match final class attributes (random or not). Constraints may have multiple random arguments which corresponds to multi-dimensional distributions.
The function
randomize()
performs a randomization for all random variables meeting all defined constraints.The function
randomize_with()
performs a randomization using additional constraint functions given in an argument.The functions
pre_randomize()
andpost_randomize()
are called before and afterrandomize()
and should be overloaded in a final class if necessary.If hard constraint cannot be resolved, an exception is thrown. If a soft constraint cannot be resolved (all acceptable solutions have zero probability), then the variable value is not being randomized.
Example:
>>> class FinalRandomized(Randomized): >>> def __init__(self, x): >>> Randomized.__init__(self) >>> self.x = x >>> self.y = 0 >>> self.z = 0 >>> >>> # define y as a random variable taking values from 0 to 9 >>> add_rand("y", list(range(10))) >>> >>> # define z as a random variable taking values from 0 to 4 >>> add_rand("z", list(range(5))) >>> >>> # hard constraint >>> add_constraint(lambda x, y: x !=y) >>> # multi-dimensional distribution >>> add_constraint(lambda y, z: y + z) >>> >>> # create randomized object instance (default values at this point) >>> obj_ = FinalRandomized(5) >>> # randomize object with additional contraint >>> obj_.randomize_with(lambda z : z > 3)
As generating constrained random objects may involve a lot of computations, it is recommended to limit random variables domains and use
pre_randomize()
/post_randomize()
methods where possible.- add_rand(var, domain=None)[source]¶
Add a random variable to the solver.
All random variables must be defined before adding any constraint with
add_constraint()
. Therefore it is highly recommended to calladd_rand
in the__init__
method of your final class.- Parameters:
Examples:
>>> add_rand("data", list(range(1024))) >>> add_rand("delay", ["small", "medium", "high"])
- add_constraint(cstr)[source]¶
Add a constraint function to the solver.
A constraint may return
True
/False
or a numeric value. Constraint function arguments must be valid class member names (random or not). Arguments must be listed in alphabetical order.Due to calculation complexity, it is recommended to create as few constraints as possible and implement
pre_randomize()
/post_randomize()
methods, or use thesolve_order()
function.Each constraint is associated with its arguments being random variables,which means for each random variable combination only one constraint of the
True
/False
type and one numeric may be defined. The latter will overwrite the existing one.For example, when class has two random variables
(x, y)
, six constraint functions may be defined: boolean and numeric constraints ofx
,y
and a pair(x, y)
.- Parameters:
cstr (func) – a constraint function.
- Returns:
an overwritten constraint or
None
if no overwrite happened.- Return type:
func or None
Examples:
>>> def highdelay_cstr(delay): >>> return delay == "high" >>> >>> add_constraint(highdelay_cstr) # hard constraint >>> add_constraint(lambda data : data < 128) # hard constraint >>> >>> # distribution (highest probability density at the boundaries): >>> add_constraint(lambda data : abs(64 - data)) >>> >>> # hard constraint of multiple variables (some of them may be >>> # non-random): >>> add_constraint(lambda x,y,z : x + y + z == 0) >>> >>> # soft constraint created by applying low probability density for >>> # some solutions: >>> add_constraint( >>> lambda delay, size : 0.01 if (size < 5 & delay == "medium") else 1 >>> ) >>> # constraint that overwrites the previously defined one >>> # (data < 128) >>> add_constraint(lambda data : data < 256)
- solve_order(*orderedVars)[source]¶
Define an order of the constraints resolving.
Constraints are being resolved in a given order, which means that randomization is called in separated steps, where at each next step some constraints are already resolved. Number of arguments defines number of the randomization steps. If this funcion is specified multiple times for a given object, only the last one remains valid.
- Parameters:
*orderedVars (multiple str or list) – Variables that are requested to be resolved in an specific order.
Example:
>>> add_rand("x", list(range(0,10))) >>> add_rand("y", list(range(0,10))) >>> add_rand("z", list(range(0,10))) >>> add_rand("w", list(range(0,10))) >>> add_constraint(lambda x, y : x + y = 9) >>> add_constraint(lambda z : z < 5) >>> add_constraint(lambda w : w > 5) >>> >>> solve_order(["x", "z"], "y") >>> # In a first step, "z", "x" and "w" will be resolved, which means >>> # only the second and third constraint will be applied. In a second >>> # step, the first constraint will be resolved as it was requested >>> # to solve "y" after "x" and "z". "x" will be interpreted as a >>> # constant in this case.
- del_constraint(cstr)[source]¶
Delete a constraint function.
- Parameters:
cstr (func) – a constraint function.
Example:
>>> del_constraint(highdelay_cstr)
- pre_randomize()[source]¶
A function that is called before
randomize()
/randomize_with()
.To be overridden in a final class if used.
- post_randomize()[source]¶
A function that is called after
randomize()
/randomize_with()
.To be overridden in a final class if used.