def __init__(self, id: int, cacheSz: int, blockSz: int, a: int, bus: Bus,
                 processor: Processor):
        """ Constructor for the class

        ...
        Parameters
        ----------
        id: int
            id of the processor
        cacheSz: int
             size of the cache
        blockSz: int
            size of the block
        a: int
            Associativity
        bus: Bus
            bus object
        processor: Processor
            processor object

        """
        self.id = id
        self.num_entries = int(cacheSz / blockSz)
        self.entries = [CacheEntry() for i in range(self.num_entries)]
        self.cacheSz = cacheSz
        self.blockSz = blockSz
        self.num_sets = self.num_entries // a
        self.num_entries_per_set = self.num_entries // self.num_sets
        self.a = a
        self.bus = bus
        self.processor = processor
        self.currentRequestAddr = None
        self.currentRequestType = None
        self.currentRequestId = None

        # Stats related fields
        self.cacheAccesses = 0
        self.cacheHits = 0
        self.cacheMisses = 0
        self.numMemBusTransaction = 0
        self.numCacheBusTransaction = 0
    def snoopBus(self, clock: int):
        """Snoops the bus and updates accordingly
    
        .....
        Parameters
        ----------
        clock: int
            the clock tick number
        Returns
        -------
        str
            Action performed by cache on Snooping
        """
        if self.bus.currentData != None:
            request = deepcopy(self.bus.currentData)
            print(request.addr, request.coreId, request.msg, self.id,
                  request.response)
            # entry_id = self.containsEntry(request.addr)

            if request.response or request.msg == 'Flush':
                # This is a response to some data request
                if request.addr != None and request.id == self.currentRequestId and request.coreId == self.id and request.addr == self.currentRequestAddr:
                    entry_id = self.containsEntry(request.addr)
                    if request.responseTime == 0:
                        self.numCacheBusTransaction += 1
                    if request.responseTime > 0 or request.msg == 'Flush':
                        self.numMemBusTransaction += 1
                    if request.response:
                        self.bus.currentData = None
                    if entry_id != -1:
                        if self.currentRequestType != 'READ':
                            self.entries[entry_id].state == 'M'
                        else:
                            # print(f"Setting the state as E or s for index {entry_id}")
                            self.entries[
                                entry_id].state = 'E' if request.responseTime > 0 else 'S'

                        self.entries[
                            entry_id].access = clock  # Relying on python's mutable objects
                    else:
                        newEntry = CacheEntry()
                        if request.entry != None:
                            newEntry = request.entry
                        else:
                            newEntry.access = clock
                            newEntry.valid, newEntry.tag, newEntry.index = True, (
                                request.addr // self.blockSz
                            ) // self.num_sets, (request.addr //
                                                 self.blockSz) % self.num_sets
                        if self.currentRequestType != 'READ':
                            # print("M must be added")
                            newEntry.state = 'M'
                        else:
                            # print("E or S must be added")
                            newEntry.state = 'E' if request.responseTime > 0 else 'S'
                        # print("Adding a new ENTRY!!!!!!!!!!!!!!!!!!!!!!")
                        self.addEntry(newEntry)

                    return 'RECV_DATA'

            else:
                entry_id = self.containsEntry(request.addr)
                if entry_id != -1:
                    entry = self.entries[entry_id]
                    # State must be M or S
                    if request.msg == 'BusRd':
                        if entry.state == 'S' or entry.state == 'E':
                            entry.access = clock
                            entry.state = 'S'
                            request.response = True
                            self.bus.reply = request
                            self.bus.reply.entry = entry
                            self.entries[entry_id] = entry
                        elif entry.state == 'M':
                            # writeBackRequest = Request(request.addr, 'Flush', self.id)
                            self.bus.reply = request
                            self.bus.reply.msg = 'Flush'
                            self.bus.reply.responseTime = 0
                            entry.access = clock
                            entry.state = 'S'
                        else:
                            print("snoopBus: Incorrect state while snooping")
                            exit()

                        print(
                            f'Cache {self.id} performed bus request for msg {request.msg}'
                        )
                        return 'BusRd'

                    elif request.msg == 'BusRdX' and request.coreId != self.id:
                        # State is either 'M' or 'S or 'E'
                        entry.valid = False
                        # print(self.bus.currentData.response)
                        request.response = True
                        # print(self.bus.currentData.response)
                        self.bus.reply = request
                        self.entries[entry_id] = entry
                        print(
                            f'Cache {self.id} performed bus request for msg {request.msg}'
                        )
                        return 'BusRdX'

                    elif request.msg in ['BusRdX'
                                         ] and request.coreId == self.id:
                        pass

                    elif request.msg == 'BusUpgr' and request.coreId != self.id:
                        entry.valid = False
                        request.response = True
                        self.bus.reply = request
                        self.entries[entry_id] = entry
                        print(
                            f'Cache {self.id} performed bus request for msg {request.msg}'
                        )
                        return 'BusUpgr'

                    elif request.msg == 'BusUpgr' and request.coreId == self.id:
                        # print(self.bus.currentData.response)
                        request.response = True
                        # print(self.bus.currentData.response)
                        self.bus.reply = request
                        return 'BusUpgr'

                    else:
                        print(
                            f'Wrong msg {request.msg}, {request.coreId} detected in the bus while snooping by cache {self.id}'
                        )
        return 'UNUSED'