From 35974500ca276cf8627a416d0435eb747f3fdfda Mon Sep 17 00:00:00 2001 From: M0stafaRady Date: Thu, 9 May 2024 13:11:27 +0300 Subject: [PATCH] Fix AHB monitor and driver in the cases of hready is not 1 --- base_test.py | 11 ++++--- bus_env/bus_agent/bus_ahb_driver.py | 22 +++++++++---- bus_env/bus_agent/bus_ahb_monitor.py | 48 ++++++++++++++++++---------- bus_env/bus_agent/bus_base_driver.py | 2 +- 4 files changed, 53 insertions(+), 30 deletions(-) diff --git a/base_test.py b/base_test.py index 26581ea..d467209 100644 --- a/base_test.py +++ b/base_test.py @@ -95,11 +95,12 @@ async def reset_phase(self, phase): self, f"{self.__class__.__name__} reset phase drop objection" ) - async def configure_phase(self, phase): - # add background sequences - await super().configure_phase(phase) - bus_seq = delays_bus_bg_seq("delays_bus_bg_seq") - await bus_seq.start(self.bus_sqr) + # remove background sequences as it introduce errors in the cases of ahbl + # async def configure_phase(self, phase): + # # add background sequences + # await super().configure_phase(phase) + # bus_seq = delays_bus_bg_seq("delays_bus_bg_seq") + # await bus_seq.start(self.bus_sqr) @abstractmethod async def main_phase(self, phase): diff --git a/bus_env/bus_agent/bus_ahb_driver.py b/bus_env/bus_agent/bus_ahb_driver.py index 2b9a97b..dfec6f1 100644 --- a/bus_env/bus_agent/bus_ahb_driver.py +++ b/bus_env/bus_agent/bus_ahb_driver.py @@ -1,5 +1,5 @@ -from uvm.macros import uvm_component_utils, uvm_fatal, uvm_info -from cocotb.triggers import Timer, RisingEdge +from uvm.macros import uvm_component_utils, uvm_fatal, uvm_info, uvm_warning +from cocotb.triggers import Timer, RisingEdge, Lock, NextTimeStep from uvm.base.uvm_object_globals import UVM_HIGH, UVM_MEDIUM, UVM_LOW from EF_UVM.bus_env.bus_item import bus_item from EF_UVM.bus_env.bus_agent.bus_base_driver import bus_base_driver @@ -10,6 +10,7 @@ class bus_ahb_driver(bus_base_driver): def __init__(self, name="bus_ahb_driver", parent=None): super().__init__(name, parent) self.tag = name + self.data_phase_lock = Lock() # to get only one in piping async def run_phase(self, phase): uvm_info(self.tag, "run_phase started", UVM_MEDIUM) @@ -33,6 +34,7 @@ async def run_phase(self, phase): self.seq_item_port.item_done() else: await self.address_phase(tr) + await self.data_phase_lock.acquire() await cocotb.start(self.data_phase(tr)) self.seq_item_port.item_done() @@ -49,11 +51,10 @@ async def address_phase(self, tr): self.vif.HADDR.value = tr.addr self.vif.HTRANS.value = 0b10 self.vif.HSEL.value = 0b01 - self.vif.HREADY.value = 1 self.drv_optional_signals_address(tr) # TODO: HSIZE should be existed in the DUT wait until it got added await self.drive_delay() - self.end_of_trans() + # self.end_of_trans() uvm_info( self.tag, f"tr at the end of address phase {tr.convert2string()} sequence id {tr.id}", @@ -72,20 +73,27 @@ async def data_phase(self, tr): if tr.kind == bus_item.WRITE: self.vif.HWDATA.value = tr.data await self.drive_delay() - while self.vif.HREADYOUT == 0: + while self.vif.HREADYOUT.value == 0: await self.drive_delay() else: # for reading just wait until the data is ready await self.drive_delay() - while self.vif.HREADYOUT == 0: + while self.vif.HREADYOUT.value == 0: await self.drive_delay() - tr.data = self.vif.HRDATA.value.integer + try: + tr.data = self.vif.HRDATA.value.integer + except ValueError: + uvm_warning( + self.tag, f"HRDATA is not an integer {self.vif.HRDATA.value.binstr}" + ) + tr.data = self.vif.HRDATA.value.binstr uvm_info( self.tag, f"tr at the end of data phase {tr.convert2string()} sequence id {tr.id}", UVM_HIGH, ) self.seq_item_port.put_response(tr) + self.data_phase_lock.release() def end_of_trans(self): self.vif.HSEL.value = 0b00 diff --git a/bus_env/bus_agent/bus_ahb_monitor.py b/bus_env/bus_agent/bus_ahb_monitor.py index 72a4d70..dcf7df0 100644 --- a/bus_env/bus_agent/bus_ahb_monitor.py +++ b/bus_env/bus_agent/bus_ahb_monitor.py @@ -1,41 +1,52 @@ -from uvm.macros import uvm_component_utils, uvm_fatal, uvm_info, uvm_error +from uvm.macros import uvm_component_utils, uvm_fatal, uvm_info, uvm_error, uvm_warning from uvm.comps.uvm_monitor import UVMMonitor from uvm.tlm1.uvm_analysis_port import UVMAnalysisPort from uvm.base.uvm_config_db import UVMConfigDb -from cocotb.triggers import Timer, RisingEdge, FallingEdge, NextTimeStep +from cocotb.triggers import Timer, RisingEdge, FallingEdge, NextTimeStep, Lock from uvm.base.uvm_object_globals import UVM_HIGH, UVM_LOW from EF_UVM.bus_env.bus_item import bus_item from EF_UVM.bus_env.bus_agent.bus_base_monitor import bus_base_monitor - import cocotb class bus_ahb_monitor(bus_base_monitor): def __init__(self, name="bus_ahb_monitor", parent=None): super().__init__(name, parent) + self.active_reset = False async def run_phase(self, phase): uvm_info(self.tag, "Starting AHB monitor run phase", UVM_LOW) - await cocotb.start(self.watch_reset()) + self.data_phase_lock = Lock() # to get only one in piping + while True: + start_thread = await cocotb.start(self.start()) + await self.assert_reset() + start_thread.kill() + self.active_reset = True + await self.deassert_reset() + self.active_reset = False + + async def start(self): while True: tr = None # wait for a transaction await NextTimeStep() tr = bus_item.type_id.create("tr", self) tr = await self.address_phase(tr) + await self.data_phase_lock.acquire() await cocotb.start(self.data_phase(tr)) - async def watch_reset(self): - while True: - await FallingEdge(self.vif.RESETn) - # send reset tr - tr = bus_item.type_id.create("tr", self) - tr.kind = bus_item.RESET - tr.addr = 0 - self.monitor_port.write(tr) - uvm_info( - self.tag, "sampled reset transaction: " + tr.convert2string(), UVM_HIGH - ) + async def assert_reset(self): + await FallingEdge(self.vif.RESETn) + # send reset tr + tr = bus_item.type_id.create("tr", self) + tr.kind = bus_item.RESET + tr.addr = 0 + self.monitor_port.write(tr) + uvm_info(self.tag, "sampled reset transaction: " + tr.convert2string(), UVM_LOW) + + async def deassert_reset(self): + await RisingEdge(self.vif.RESETn) + uvm_info(self.tag, "deasserted reset", UVM_LOW) async def sample_delay(self): await RisingEdge(self.vif.CLK) @@ -66,12 +77,15 @@ async def data_phase(self, tr): try: tr.data = self.vif.HRDATA.value.integer except ValueError: - uvm_error( + uvm_warning( self.tag, f"HRDATA is not an integer {self.vif.HRDATA.value.binstr}" ) tr.data = self.vif.HRDATA.value.binstr + if self.active_reset: + return self.monitor_port.write(tr) - uvm_info(self.tag, "sampled AHB transaction: " + tr.convert2string(), UVM_HIGH) + uvm_info(self.tag, "sampled AHB transaction: " + tr.convert2string(), UVM_LOW) + self.data_phase_lock.release() return tr diff --git a/bus_env/bus_agent/bus_base_driver.py b/bus_env/bus_agent/bus_base_driver.py index 57eb419..582f971 100644 --- a/bus_env/bus_agent/bus_base_driver.py +++ b/bus_env/bus_agent/bus_base_driver.py @@ -30,10 +30,10 @@ async def run_phase(self, phase): async def reset(self, num_cycles=3): self.vif.RESETn.value = 0 + self.end_of_trans() for _ in range(num_cycles): await self.drive_delay() self.vif.RESETn.value = 1 - self.end_of_trans() async def drive_delay(self): await RisingEdge(self.vif.CLK)