From 2dbf993ebe3bfeaa0c98b044865c7eff325cd9f4 Mon Sep 17 00:00:00 2001 From: Anderson Ignacio Date: Sun, 12 Nov 2023 15:09:14 +0000 Subject: [PATCH] fix #2 - Update on slave error response Signed-off-by: Anderson Ignacio --- cocotbext/ahb/ahb_master.py | 78 +++++++++++++++++++++++++----------- cocotbext/ahb/ahb_monitor.py | 9 +++-- cocotbext/ahb/ahb_slave.py | 17 ++++++-- cocotbext/ahb/version.py | 2 +- 4 files changed, 76 insertions(+), 30 deletions(-) diff --git a/cocotbext/ahb/ahb_master.py b/cocotbext/ahb/ahb_master.py index c01c0d6..832eff1 100644 --- a/cocotbext/ahb/ahb_master.py +++ b/cocotbext/ahb/ahb_master.py @@ -4,7 +4,7 @@ # License : MIT license # Author : Anderson I. da Silva (aignacio) # Date : 08.10.2023 -# Last Modified Date: 29.10.2023 +# Last Modified Date: 12.11.2023 import cocotb import logging @@ -146,9 +146,17 @@ async def _send_txn( response = [] first_txn = True - for index, (txn_addr, txn_data, txn_size, txn_mode, txn_trans) in enumerate( - zip(address, value, size, mode, trans) - ): + index = 0 + restart = False + + while index < len(address): + txn_addr, txn_data, txn_size, txn_mode, txn_trans = ( + address[index], + value[index], + size[index], + mode[index], + trans[index], + ) if index == len(address) - 1: self._init_bus() else: @@ -168,26 +176,46 @@ async def _send_txn( self.bus.hready_in.value = 1 await RisingEdge(self.clk) - timeout_counter = 0 - if self.bus.hready.value.is_resolvable is False: - while self.bus.hready.value.is_resolvable is False: - timeout_counter += 1 - if timeout_counter == self.timeout: - raise Exception( - f"Timeout value of {timeout_counter}" - f" clock cycles has been reached!" - ) - await RisingEdge(self.clk) - else: - while self.bus.hready.value != 1: - timeout_counter += 1 - if timeout_counter == self.timeout: - raise Exception( - f"Timeout value of {timeout_counter}" - f" clock cycles has been reached!" - ) - await RisingEdge(self.clk) + # First check if the slave signals are resolvable + timeout_counter = 0 + while any( + [ + not self.bus.hready.value.is_resolvable, + not self.bus.hresp.value.is_resolvable, + not self.bus.hrdata.value.is_resolvable, + ] + ): + timeout_counter += 1 + if timeout_counter == self.timeout: + raise Exception( + f"Timeout value of {timeout_counter}" + f" clock cycles has been reached because AHB.SLAVE" + f"signals are not resolvable!\n" + f"hready: {self.bus.hready.value.is_resolvable}\n" + f"hrdata: {self.bus.hrdata.value.is_resolvable}\n" + f"hresp: {self.bus.hresp.value.is_resolvable}\n" + ) + await RisingEdge(self.clk) + + index += 1 + # Wait till a response is available from the slave + while self.bus.hready.value != 1: + if self.bus.hresp == AHBResp.ERROR: + if self.bus.htrans.value.is_resolvable: + if self.bus.htrans.value == AHBTrans.NONSEQ: + index -= 1 # Redo the txn + self.bus.htrans.value = ( + AHBTrans.IDLE + ) # Withdrawn the req. in case of error + restart = True + timeout_counter += 1 + if timeout_counter == self.timeout: + raise Exception( + f"Timeout value of {timeout_counter}" + f" clock cycles has been reached!" + ) + await RisingEdge(self.clk) if first_txn: first_txn = False @@ -202,6 +230,10 @@ async def _send_txn( "data": hex(self.bus.hrdata.value), } ] + if restart: # As we withdrawn the last txn, let's restart + first_txn = True + restart = False + self._init_bus() return response diff --git a/cocotbext/ahb/ahb_monitor.py b/cocotbext/ahb/ahb_monitor.py index e5c1c93..f5360d5 100644 --- a/cocotbext/ahb/ahb_monitor.py +++ b/cocotbext/ahb/ahb_monitor.py @@ -165,6 +165,9 @@ def _check_signals(self, stable): if current[signal].value.is_resolvable is not True: raise AssertionError(f"Signal master.{signal} is not resolvable!") if current[signal].value != stable[signal]: - raise AssertionError( - f"AHB PROTOCOL VIOLATION: Master.{signal} signal should not change before slave.hready == 1" - ) + if (signal == "htrans") and (self.bus.hresp.value == AHBResp.ERROR): + pass + else: + raise AssertionError( + f"AHB PROTOCOL VIOLATION: Master.{signal} signal should not change before slave.hready == 1" + ) diff --git a/cocotbext/ahb/ahb_slave.py b/cocotbext/ahb/ahb_slave.py index 7465908..67e1b33 100644 --- a/cocotbext/ahb/ahb_slave.py +++ b/cocotbext/ahb/ahb_slave.py @@ -4,7 +4,7 @@ # License : MIT license # Author : Anderson I. da Silva (aignacio) # Date : 16.10.2023 -# Last Modified Date: 27.10.2023 +# Last Modified Date: 12.11.2023 import cocotb import logging @@ -80,6 +80,7 @@ async def _proc_txn(self): await RisingEdge(self.clk) cur_hready = copy.deepcopy(self.bus.hready.value) + cur_hresp = copy.deepcopy(self.bus.hresp.value) # Default values in case there is no txn self.bus.hready.value = self._get_def(1) @@ -93,7 +94,12 @@ async def _proc_txn(self): if ready: self.bus.hready.value = 1 - if error: + if error and (cur_hresp == AHBResp.OKAY): # First cycle of error response + self.bus.hready.value = 0 + self.bus.hresp.value = AHBResp.ERROR + elif error and ( + cur_hresp == AHBResp.ERROR + ): # Second cycle of error response self.bus.hready.value = 1 self.bus.hresp.value = AHBResp.ERROR error = False @@ -110,7 +116,12 @@ async def _proc_txn(self): self.bus.hresp.value = AHBResp.OKAY # Check for new txn - if cur_hready == 1 and self._check_inputs() and self._check_valid_txn(): + if ( + (cur_hready == 1) + and (cur_hresp != AHBResp.ERROR) + and self._check_inputs() + and self._check_valid_txn() + ): txn_addr = self.bus.haddr.value txn_size = AHBSize(self.bus.hsize.value) txn_type = AHBWrite(self.bus.hwrite.value) diff --git a/cocotbext/ahb/version.py b/cocotbext/ahb/version.py index 0a8da88..f1380ee 100644 --- a/cocotbext/ahb/version.py +++ b/cocotbext/ahb/version.py @@ -1 +1 @@ -__version__ = "0.1.6" +__version__ = "0.1.7"