Skip to content

Commit

Permalink
Fix AHB monitor and driver in the cases of hready is not 1
Browse files Browse the repository at this point in the history
  • Loading branch information
M0stafaRady committed May 9, 2024
1 parent 32d50bf commit 3597450
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 30 deletions.
11 changes: 6 additions & 5 deletions base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
22 changes: 15 additions & 7 deletions bus_env/bus_agent/bus_ahb_driver.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)
Expand All @@ -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()

Expand All @@ -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}",
Expand All @@ -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
Expand Down
48 changes: 31 additions & 17 deletions bus_env/bus_agent/bus_ahb_monitor.py
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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


Expand Down
2 changes: 1 addition & 1 deletion bus_env/bus_agent/bus_base_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 3597450

Please sign in to comment.