avl-spi 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
avl_spi-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [2025] [avl@projectapheleia.net]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
avl_spi-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.4
2
+ Name: avl-spi
3
+ Version: 0.1.0
4
+ Summary: Apheleia Verification Library - Serial Peripheral Interface verification component.
5
+ License: MIT License
6
+
7
+ Copyright (c) [2025] [avl@projectapheleia.net]
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+ License-File: LICENSE
27
+ Author: avl
28
+ Author-email: avl@projectapheleia.net
29
+ Maintainer: avl
30
+ Maintainer-email: avl@projectapheleia.net
31
+ Requires-Python: >=3.10
32
+ Classifier: Development Status :: 4 - Beta
33
+ Classifier: Programming Language :: Python
34
+ Provides-Extra: dev
35
+ Requires-Dist: avl-core (>=1.1.0)
36
+ Requires-Dist: black (>=22.3.0) ; extra == "dev"
37
+ Requires-Dist: cocotb (>=2.1.0)
38
+ Requires-Dist: matplotlib (>=3.10.0)
39
+ Requires-Dist: mypy (>=0.910) ; extra == "dev"
40
+ Requires-Dist: pytest (>=7.0) ; extra == "dev"
41
+ Requires-Dist: ruff (>=0.11.0) ; extra == "dev"
42
+ Requires-Dist: sphinx (>=8.1.3) ; extra == "dev"
43
+ Requires-Dist: sphinx_rtd_theme (>=3.0.2) ; extra == "dev"
44
+ Description-Content-Type: text/markdown
45
+
46
+ # AVL-SPI - Apheleia Verification Library SPI Verification Component
47
+
48
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
49
+ [![Python](https://img.shields.io/badge/Python-3.10%2B-blue)](https://www.python.org/)
50
+
51
+
52
+ AVL-SPI has been developed by experienced, industry professional verification engineers to provide a simple, \
53
+ extensible verification component for the [Serial Peripheral Interface](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface) \
54
+ developed in [Python](https://www.python.org/) and the [AVL](https://avl-core.readthedocs.io/en/latest/index.html) library.
55
+
56
+ AVL is built on the [CocoTB](https://docs.cocotb.org/en/stable/) framework, but aims to combine the best elements of \
57
+ [UVM](https://accellera.org/community/uvm) in a more engineer friendly and efficient way.
58
+
59
+ ## CocoTB 2.0
60
+
61
+ AVL-SPI supports [CocoTB 2.0](https://docs.cocotb.org/en/development/upgrade-2.0.html) and requires CocoTB 2.1 or later.
62
+
63
+ ## Protocol Features
64
+
65
+ | Signal Name | Description | Driven By |
66
+ |-------------|-------------|-----------|
67
+ | SCLK | Serial clock. Idles at CPOL. | Master |
68
+ | CS | Chip select; one per slave. Polarity configurable per slave. | Master |
69
+ | MOSI | Master out, slave in serial data. | Master |
70
+ | MISO | Master in, slave out serial data. | Slave |
71
+
72
+ > **Note:** At present only single bit, uni-directional SPI is supported. Each SCLK cycle transfers one bit on MOSI (master to slave) and one bit on MISO (slave to master). Bi-directional (3-wire), dual, quad and QPI modes are not supported.
73
+
74
+ ## Component Features
75
+
76
+ - Simple RTL interface to interact with HDL and define parameter and configuration options
77
+ - Multiple chip selects with individual polarity
78
+ - Clock polarity and individual drive and sample edges for master and slave (all 4 SPI modes and beyond)
79
+ - Variable transfer length, MSB or LSB first
80
+ - Chip select onehot0, setup, hold and inter-frame gap checks in the RTL interface
81
+ - Master sequence, sequencer and driver with rate limiter, SCLK frequency and chip select timing control
82
+ - Slave sequence, sequencer and driver with vanilla, random and memory response patterns
83
+ - Monitor
84
+ - Bandwidth monitor generating bus activity plots over user defined windows during simulation
85
+ - Functional coverage
86
+ - Searchable trace file generation
87
+
88
+ ---
89
+
90
+ ## 📦 Installation
91
+
92
+ ### Using `pip`
93
+ ```sh
94
+ # Standard build
95
+ pip install avl-spi
96
+
97
+ # Development build
98
+ pip install avl-spi[dev]
99
+ ```
100
+
101
+ ### Install from Source
102
+ ```sh
103
+ git clone https://github.com/projectapheleia/avl-spi.git
104
+ cd avl-spi
105
+
106
+ # Standard build
107
+ pip install .
108
+
109
+ # Development build
110
+ pip install .[dev]
111
+ ```
112
+
113
+ Alternatively if you want to create a [virtual environment](https://docs.python.org/3/library/venv.html) rather than install globally a script is provided. This will install, with edit privileges to local virtual environment.
114
+
115
+ This script assumes you have [Graphviz](https://graphviz.org/download/) and appropriate simulator installed, so all examples and documentation will build out of the box.
116
+
117
+
118
+ ```sh
119
+ git clone https://github.com/projectapheleia/avl-spi.git
120
+ cd avl-spi
121
+ source avl-spi.sh
122
+ ```
123
+
124
+ ## 📖 Documentation
125
+
126
+ In order to build the documentation you must have installed the development build.
127
+
128
+ ### Build from Source
129
+ ```sh
130
+ cd doc
131
+ make html
132
+ <browser> build/html/index.html
133
+ ```
134
+ ## 🏃 Examples
135
+
136
+ In order to run all the examples you must have installed the development build.
137
+
138
+ To run all examples:
139
+
140
+ ```sh
141
+ cd examples
142
+
143
+ # To run
144
+ make -j 8 sim
145
+
146
+ # To clean
147
+ make -j 8 clean
148
+ ```
149
+
150
+ To run an individual example:
151
+
152
+ ```sh
153
+ cd examples/THE EXAMPLE YOU WANT
154
+
155
+ # To run
156
+ make sim
157
+
158
+ # To clean
159
+ make clean
160
+ ```
161
+
162
+ The examples use the [CocoTB Makefile](https://docs.cocotb.org/en/stable/building.html) and default to [Verilator](https://www.veripool.org/verilator/) with all waveforms generated. This can be modified using the standard CocoTB build system.
163
+
164
+ ---
165
+
166
+
167
+ ## 🧹 Code Style & Linting
168
+
169
+ This project uses [**Ruff**](https://docs.astral.sh/ruff/) for linting and formatting.
170
+
171
+ Check code for issues:
172
+
173
+ ```sh
174
+ ruff check .
175
+ ```
176
+
177
+ Automatically fix common issues:
178
+
179
+ ```sh
180
+ ruff check . --fix
181
+ ```
182
+
183
+
184
+
185
+ ## 📧 Contact
186
+
187
+ - Email: avl@projectapheleia.net
188
+ - GitHub: [projectapheleia](https://github.com/projectapheleia)
189
+
@@ -0,0 +1,143 @@
1
+ # AVL-SPI - Apheleia Verification Library SPI Verification Component
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
+ [![Python](https://img.shields.io/badge/Python-3.10%2B-blue)](https://www.python.org/)
5
+
6
+
7
+ AVL-SPI has been developed by experienced, industry professional verification engineers to provide a simple, \
8
+ extensible verification component for the [Serial Peripheral Interface](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface) \
9
+ developed in [Python](https://www.python.org/) and the [AVL](https://avl-core.readthedocs.io/en/latest/index.html) library.
10
+
11
+ AVL is built on the [CocoTB](https://docs.cocotb.org/en/stable/) framework, but aims to combine the best elements of \
12
+ [UVM](https://accellera.org/community/uvm) in a more engineer friendly and efficient way.
13
+
14
+ ## CocoTB 2.0
15
+
16
+ AVL-SPI supports [CocoTB 2.0](https://docs.cocotb.org/en/development/upgrade-2.0.html) and requires CocoTB 2.1 or later.
17
+
18
+ ## Protocol Features
19
+
20
+ | Signal Name | Description | Driven By |
21
+ |-------------|-------------|-----------|
22
+ | SCLK | Serial clock. Idles at CPOL. | Master |
23
+ | CS | Chip select; one per slave. Polarity configurable per slave. | Master |
24
+ | MOSI | Master out, slave in serial data. | Master |
25
+ | MISO | Master in, slave out serial data. | Slave |
26
+
27
+ > **Note:** At present only single bit, uni-directional SPI is supported. Each SCLK cycle transfers one bit on MOSI (master to slave) and one bit on MISO (slave to master). Bi-directional (3-wire), dual, quad and QPI modes are not supported.
28
+
29
+ ## Component Features
30
+
31
+ - Simple RTL interface to interact with HDL and define parameter and configuration options
32
+ - Multiple chip selects with individual polarity
33
+ - Clock polarity and individual drive and sample edges for master and slave (all 4 SPI modes and beyond)
34
+ - Variable transfer length, MSB or LSB first
35
+ - Chip select onehot0, setup, hold and inter-frame gap checks in the RTL interface
36
+ - Master sequence, sequencer and driver with rate limiter, SCLK frequency and chip select timing control
37
+ - Slave sequence, sequencer and driver with vanilla, random and memory response patterns
38
+ - Monitor
39
+ - Bandwidth monitor generating bus activity plots over user defined windows during simulation
40
+ - Functional coverage
41
+ - Searchable trace file generation
42
+
43
+ ---
44
+
45
+ ## 📦 Installation
46
+
47
+ ### Using `pip`
48
+ ```sh
49
+ # Standard build
50
+ pip install avl-spi
51
+
52
+ # Development build
53
+ pip install avl-spi[dev]
54
+ ```
55
+
56
+ ### Install from Source
57
+ ```sh
58
+ git clone https://github.com/projectapheleia/avl-spi.git
59
+ cd avl-spi
60
+
61
+ # Standard build
62
+ pip install .
63
+
64
+ # Development build
65
+ pip install .[dev]
66
+ ```
67
+
68
+ Alternatively if you want to create a [virtual environment](https://docs.python.org/3/library/venv.html) rather than install globally a script is provided. This will install, with edit privileges to local virtual environment.
69
+
70
+ This script assumes you have [Graphviz](https://graphviz.org/download/) and appropriate simulator installed, so all examples and documentation will build out of the box.
71
+
72
+
73
+ ```sh
74
+ git clone https://github.com/projectapheleia/avl-spi.git
75
+ cd avl-spi
76
+ source avl-spi.sh
77
+ ```
78
+
79
+ ## 📖 Documentation
80
+
81
+ In order to build the documentation you must have installed the development build.
82
+
83
+ ### Build from Source
84
+ ```sh
85
+ cd doc
86
+ make html
87
+ <browser> build/html/index.html
88
+ ```
89
+ ## 🏃 Examples
90
+
91
+ In order to run all the examples you must have installed the development build.
92
+
93
+ To run all examples:
94
+
95
+ ```sh
96
+ cd examples
97
+
98
+ # To run
99
+ make -j 8 sim
100
+
101
+ # To clean
102
+ make -j 8 clean
103
+ ```
104
+
105
+ To run an individual example:
106
+
107
+ ```sh
108
+ cd examples/THE EXAMPLE YOU WANT
109
+
110
+ # To run
111
+ make sim
112
+
113
+ # To clean
114
+ make clean
115
+ ```
116
+
117
+ The examples use the [CocoTB Makefile](https://docs.cocotb.org/en/stable/building.html) and default to [Verilator](https://www.veripool.org/verilator/) with all waveforms generated. This can be modified using the standard CocoTB build system.
118
+
119
+ ---
120
+
121
+
122
+ ## 🧹 Code Style & Linting
123
+
124
+ This project uses [**Ruff**](https://docs.astral.sh/ruff/) for linting and formatting.
125
+
126
+ Check code for issues:
127
+
128
+ ```sh
129
+ ruff check .
130
+ ```
131
+
132
+ Automatically fix common issues:
133
+
134
+ ```sh
135
+ ruff check . --fix
136
+ ```
137
+
138
+
139
+
140
+ ## 📧 Contact
141
+
142
+ - Email: avl@projectapheleia.net
143
+ - GitHub: [projectapheleia](https://github.com/projectapheleia)
@@ -0,0 +1,29 @@
1
+ from ._agent import Agent
2
+ from ._agent_cfg import AgentCfg
3
+ from ._bandwidth import Bandwidth
4
+ from ._coverage import Coverage
5
+ from ._item import SequenceItem
6
+ from ._mdriver import MstDriver
7
+ from ._monitor import Monitor
8
+ from ._msequence import MstMemorySequence, MstSequence
9
+ from ._sdriver import SlvDriver, SlvMemoryDriver, SlvRandomDriver
10
+ from ._ssequence import SlvSequence
11
+
12
+ # Add version
13
+ __version__: str = "0.1.0"
14
+
15
+ __all__ = [
16
+ "Agent",
17
+ "AgentCfg",
18
+ "Bandwidth",
19
+ "Coverage",
20
+ "SequenceItem",
21
+ "Monitor",
22
+ "MstDriver",
23
+ "MstSequence",
24
+ "MstMemorySequence",
25
+ "SlvDriver",
26
+ "SlvRandomDriver",
27
+ "SlvMemoryDriver",
28
+ "SlvSequence",
29
+ ]
@@ -0,0 +1,119 @@
1
+ # Copyright 2026 Apheleia
2
+ #
3
+ # Description:
4
+ # Apheleia Verification Library Agent
5
+
6
+ import avl
7
+ import cocotb
8
+ from cocotb.handle import HierarchyObject
9
+ from cocotb.triggers import NextTimeStep, RisingEdge
10
+
11
+ from ._agent_cfg import AgentCfg
12
+ from ._bandwidth import Bandwidth
13
+ from ._coverage import Coverage
14
+ from ._interface import Interface
15
+ from ._mdriver import MstDriver
16
+ from ._monitor import Monitor
17
+ from ._msequence import MstSequence
18
+ from ._sdriver import SlvDriver
19
+ from ._ssequence import SlvSequence
20
+
21
+
22
+ class Agent(avl.Agent):
23
+ def __init__(self, name: str, parent: avl.Component) -> None:
24
+ """
25
+ Initialize the avl-spi Agent
26
+
27
+ :param name: Name of the agent instance
28
+ :type name: str
29
+ :param parent: Parent component
30
+ :type parent: Component
31
+ """
32
+ super().__init__(name, parent)
33
+
34
+ # Create configuration and export to children
35
+ self.cfg = avl.Factory.get_variable(f"{self.get_full_name()}.cfg", AgentCfg("cfg", self))
36
+ avl.Factory.set_variable(f"{self.get_full_name()}.*.cfg", self.cfg)
37
+
38
+ # Bind HDL to establish parameters and configuration
39
+ self._bind_(avl.Factory.get_variable(f"{self.get_full_name()}.hdl", None))
40
+
41
+ # Create sequencer and driver if master is enabled
42
+ if self.cfg.has_master:
43
+ self.msqr = avl.Sequencer("msqr", self)
44
+ self.mseq = MstSequence("mseq", self.msqr)
45
+ self.mdrv = MstDriver("mdrv", self)
46
+ self.msqr.seq_item_export.connect(self.mdrv.seq_item_port)
47
+
48
+ # Create sequencer, sequence and driver for each slave
49
+ if self.cfg.num_slave > 1:
50
+ self.ssqr, self.sseq, self.sdrv = [], [], []
51
+ for i in range(self.cfg.num_slave):
52
+ avl.Factory.set_variable(f"{self.get_full_name()}.sdrv_{i}.idx", i)
53
+ self.ssqr.append(avl.Sequencer(f"ssqr_{i}", self))
54
+ self.sseq.append(SlvSequence("sseq", self.ssqr[i]))
55
+ self.sdrv.append(SlvDriver(f"sdrv_{i}", self))
56
+ self.ssqr[i].seq_item_export.connect(self.sdrv[i].seq_item_port)
57
+ elif self.cfg.num_slave == 1:
58
+ self.ssqr = avl.Sequencer("ssqr", self)
59
+ self.sseq = SlvSequence("sseq", self.ssqr)
60
+ self.sdrv = SlvDriver("sdrv", self)
61
+ self.ssqr.seq_item_export.connect(self.sdrv.seq_item_port)
62
+
63
+ # Create monitor if enabled
64
+ if self.cfg.has_monitor:
65
+ self.monitor = Monitor("monitor", self)
66
+
67
+ if self.cfg.has_coverage:
68
+ self.coverage = Coverage("coverage", self)
69
+ self.monitor.item_export.connect(self.coverage.item_port)
70
+
71
+ if self.cfg.has_bandwidth:
72
+ self.bandwidth = Bandwidth("bandwidth", self)
73
+ self.monitor.item_export.connect(self.bandwidth.item_port)
74
+
75
+ if self.cfg.has_trace:
76
+ self.trace = avl.Trace("trace", self)
77
+ self.monitor.item_export.connect(self.trace.item_port)
78
+
79
+ def _bind_(self, hdl) -> None:
80
+ """
81
+ Bind the agent to a hardware description language (HDL) interface.
82
+ This method is used to associate the agent with a specific HDL interface,
83
+ allowing it to interact with the hardware model.
84
+
85
+ :param hdl: The HDL interface to bind to the agent
86
+ :type hdl: HierarchyObject
87
+ :raises TypeError: If `hdl` is not an instance of HierarchyObject
88
+ """
89
+ if not isinstance(hdl, HierarchyObject):
90
+ raise TypeError(f"Expected HierarchyObject, got {type(hdl)}")
91
+
92
+ # Assign Interface
93
+ self.i_f = Interface(hdl)
94
+ avl.Factory.set_variable(f"{self.get_full_name()}.*.i_f", self.i_f)
95
+
96
+ async def run_phase(self) -> None:
97
+ """
98
+ Run the agent's phase. This method is called to start the agent's operation.
99
+ It starts the slave sequences, and the master sequence if the master is enabled.
100
+ Slave sequences are not awaited, as they depend on transfers from the master.
101
+ """
102
+
103
+ self.raise_objection()
104
+ await NextTimeStep()
105
+
106
+ if self.cfg.num_slave > 0:
107
+ for s in (self.sseq if isinstance(self.sseq, list) else [self.sseq]):
108
+ cocotb.start_soon(s.start())
109
+
110
+ if self.cfg.has_master:
111
+ await self.mseq.start()
112
+
113
+ # Run-off
114
+ for _ in range(10):
115
+ await RisingEdge(self.i_f.clk)
116
+
117
+ self.drop_objection()
118
+
119
+ __all__ = ["Agent"]
@@ -0,0 +1,36 @@
1
+ # Copyright 2026 Apheleia
2
+ #
3
+ # Description:
4
+ # Apheleia Verification Library Agent Configuration
5
+
6
+ import avl
7
+
8
+
9
+ class AgentCfg(avl.Object):
10
+
11
+ def __init__(self, name: str, parent: avl.Component) -> None:
12
+ """
13
+ Initialize the avl-spi Agent Configuration
14
+
15
+ :param name: Name of the agent instance
16
+ :type name: str
17
+ :param parent: Parent component
18
+ :type parent: Component
19
+ """
20
+ super().__init__(name, parent)
21
+
22
+ # Agent Attributes
23
+ self.has_master = avl.Factory.get_variable(f"{self.get_full_name()}.has_master", False)
24
+ """Has Master Driver"""
25
+ self.num_slave = avl.Factory.get_variable(f"{self.get_full_name()}.num_slave", 0)
26
+ """Number of Slave Drivers"""
27
+ self.has_monitor = avl.Factory.get_variable(f"{self.get_full_name()}.has_monitor", False)
28
+ """Has Monitor"""
29
+ self.has_coverage = avl.Factory.get_variable(f"{self.get_full_name()}.has_coverage", False)
30
+ """Has Functional Coverage"""
31
+ self.has_bandwidth = avl.Factory.get_variable(f"{self.get_full_name()}.has_bandwidth", False)
32
+ """Has Bandwidth Monitor"""
33
+ self.has_trace = avl.Factory.get_variable(f"{self.get_full_name()}.has_trace", False)
34
+ """Has Trace Generator"""
35
+
36
+ __all__ = ["AgentCfg"]
@@ -0,0 +1,91 @@
1
+ # Copyright 2026 Apheleia
2
+ #
3
+ # Description:
4
+ # Apheleia Verification Library Bandwidth Monitor
5
+
6
+ import avl
7
+ import cocotb
8
+ from avl._core._lazy import lazy_import
9
+ from cocotb.triggers import Timer
10
+ from cocotb.utils import get_sim_time
11
+
12
+ # Deferred until the report phase
13
+ plt = lazy_import("matplotlib.pyplot")
14
+ np = lazy_import("numpy")
15
+
16
+
17
+ class Bandwidth(avl.Component):
18
+
19
+ def __init__(self, name: str, parent: avl.Component) -> None:
20
+ """
21
+ Initialize Bandwidth Monitor
22
+
23
+ Class contains variable window_ns which defines the time window in nanoseconds. This
24
+ is configurable via the factory.
25
+
26
+ :param name: Name of the bandwidth monitor.
27
+ :type name: str
28
+ :param parent: Parent component.
29
+ :type parent: Component
30
+ """
31
+ super().__init__(name, parent)
32
+ self.i_f = avl.Factory.get_variable(f"{self.get_full_name()}.i_f", None)
33
+
34
+ self.window_ns = avl.Factory.get_variable(f"{self.get_full_name()}.window_ns", 1000)
35
+ """ Rolling time window in nanoseconds for bandwidth calculation. Default is 1000 ns. """
36
+
37
+ self.item_port = avl.List()
38
+ self.bandwidth = {}
39
+
40
+ async def run_phase(self) -> None:
41
+ """
42
+ Run phase for the bandwidth component.
43
+
44
+ """
45
+ async def counter():
46
+ while True:
47
+ self.item = await self.item_port.blocking_get()
48
+ self.bandwidth[t] += int(self.item.get("length"))
49
+
50
+ cocotb.start_soon(counter())
51
+
52
+ while True:
53
+ t = get_sim_time(unit="ns")
54
+ self.bandwidth[t] = 0
55
+
56
+ self.raise_objection()
57
+ await Timer(self.window_ns, unit="ns")
58
+ self.drop_objection()
59
+
60
+ async def report_phase(self) -> None:
61
+ """
62
+ Report phase for the bandwidth component.
63
+
64
+ Generate plot of bits on bus over time windows
65
+
66
+ """
67
+ times = list(self.bandwidth.keys())
68
+ counts = list(self.bandwidth.values())
69
+
70
+ if len(times) > 1:
71
+ # For unevenly spaced data, calculate individual widths
72
+ # This uses the minimum spacing to avoid overlapping bars
73
+ spacings = np.diff(times)
74
+ bar_width = np.min(spacings)
75
+ else:
76
+ # For single bar, use a default width
77
+ bar_width = 1
78
+
79
+ # Create plot
80
+ plt.figure(figsize=(8, 4))
81
+ plt.bar(times, counts, width=bar_width, align='center')
82
+ plt.title("Bus Bandwidth (Bits over Time)")
83
+ plt.xlabel("Time (ns)")
84
+ plt.ylabel("Bit Count")
85
+ plt.grid(True)
86
+
87
+ # Export to PNG
88
+ plt.savefig(f"{self.get_full_name()}.png")
89
+ plt.close()
90
+
91
+ __all__ = ["Bandwidth"]