Esempio n. 1
0
class Testbench(object):
    def __init__(self, dut):
        self.dut = dut
        self.stopped = False
        elements = dut.ELEMENTS.value
        self.lru = LeastRecentlyUsedDict(size_limit=elements)

        # initial state of LRU list
        for keyin in range(elements - 1, -1, -1):
            self.lru[keyin] = 1

        init_val = elements - 1

        self.input_drv = InputDriver(dut)
        self.output_mon = OutputMonitor(dut)

        # Create a scoreboard on the outputs
        self.expected_output = [init_val]
        self.scoreboard = Scoreboard(dut)
        self.scoreboard.add_interface(self.output_mon, self.expected_output)

        # Reconstruct the input transactions from the pins
        # and send them to our 'model'
        self.input_mon = InputMonitor(dut, callback=self.model)

    def model(self, transaction):
        '''Model the DUT based on the input transaction.'''
        insert, free, keyin = transaction
        #print "=== model called with stopped=%r, Insert=%d, Free=%d, KeyIn=%d" % (self.stopped, insert, free, keyin)
        if not self.stopped:
            if insert == 1:
                self.lru[keyin] = 1
            elif free == 1:
                self.lru.moveLRU(keyin)

            #print "=== model: lru=%s" % self.lru.items()
            keyout = self.lru.iterkeys().next()
            #print "=== model: KeyOut=%d" % keyout
            self.expected_output.append(keyout)

    def stop(self):
        """
		Stop generation of expected output transactions.
		One more clock cycle must be executed afterwards, so that, output of
		D-FF can be checked.
		"""
        self.stopped = True
Esempio n. 2
0
class Testbench(object):
	def __init__(self, dut):
		self.dut = dut
		self.stopped = False
		elements = dut.ELEMENTS.value;
		self.lru = LeastRecentlyUsedDict(size_limit=elements)

		# initial state of LRU list
		for keyin in range(elements-1, -1, -1):
			self.lru[keyin] = 1

		init_val = elements-1

		self.input_drv = InputDriver(dut)
		self.output_mon = OutputMonitor(dut)

		# Create a scoreboard on the outputs
		self.expected_output = [ init_val ]
		self.scoreboard = Scoreboard(dut)
		self.scoreboard.add_interface(self.output_mon, self.expected_output)

		# Reconstruct the input transactions from the pins
		# and send them to our 'model'
		self.input_mon = InputMonitor(dut, callback=self.model)

	def model(self, transaction):
		'''Model the DUT based on the input transaction.'''
		insert, free, keyin = transaction
		#print "=== model called with stopped=%r, Insert=%d, Free=%d, KeyIn=%d" % (self.stopped, insert, free, keyin)
		if not self.stopped:
			if insert == 1:
				self.lru[keyin] = 1
			elif free == 1:
				self.lru.moveLRU(keyin)

			#print "=== model: lru=%s" % self.lru.items()
			keyout = self.lru.iterkeys().next()
			#print "=== model: KeyOut=%d" % keyout
			self.expected_output.append(keyout)

	def stop(self):
		"""
		Stop generation of expected output transactions.
		One more clock cycle must be executed afterwards, so that, output of
		D-FF can be checked.
		"""
		self.stopped = True
Esempio n. 3
0
    def __init__(self, dut, init_val):
        self.dut = dut
        self.stopped = False
        elements = dut.ELEMENTS.value
        self.lru = LeastRecentlyUsedDict(size_limit=elements)

        if elements != 16:
            raise TestFailure("Unsupported number of elements.")

        self.input_drv = InputDriver(dut)
        self.output_mon = OutputMonitor(dut)

        # Create a scoreboard on the outputs
        self.expected_output = [init_val]
        self.scoreboard = Testbench.MyScoreboard(dut)
        self.scoreboard.add_interface(self.output_mon, self.expected_output)

        # Reconstruct the input transactions from the pins
        # and send them to our 'model'
        self.input_mon = InputMonitor(dut, callback=self.model)
Esempio n. 4
0
def random_input_gen(tb,n=100000):
	"""
	Generate random input data to be applied by InputDriver.
	Returns up to n instances of InputTransaction.
	tb must an instance of the Testbench class.
	"""
	address_high  = 2**tb.address_bits-1
	data_high = 2**tb.data_bits-1

	# it is forbidden to replace a cache line when the new address is already within the cache
	# we cannot directly access the content of the LRU list in the testbench because this function is called asynchronously
	lru_tags = tuple([LeastRecentlyUsedDict(size_limit=tb.associativity) for _ in range(tb.cache_sets)])

	for i in range(n):
		if DEBUG and (i % 1000 == 0): print("Generating transaction #{0} ...".format(i))

		command = random.randint(1,60)
		request, readWrite, invalidate, replace = 0, 0, 0, 0
		# 10% for each possible command
		if   command > 50: request = 1; readWrite = 0; invalidate = 0
		elif command > 40: request = 1; readWrite = 1; invalidate = 0
		elif command > 30: request = 1; readWrite = 0; invalidate = 1
		elif command > 20: request = 1; readWrite = 1; invalidate = 1
		elif command > 10: replace = 1

		# Upon request, check if address is in LRU list.
		while True:
			address = random.randint(0,address_high)
			index = address & tb.index_mask
			tag = (address >> tb.index_bits) &  tb.tag_mask
			#print "while loop: %d, %d, %d" % (address, index, tag)
			if (replace == 0) or (tag not in lru_tags[index]): break

		# Update LRU list
		if request == 1:
			if tag in lru_tags[index]:
				if invalidate == 1:
					del lru_tags[index][tag] # free cache line
				else:
					lru_tags[index][tag] = 1 # tag access
		elif replace == 1:
			lru_tags[index][tag] = 1 # allocate cache line

			#replace step 1:
			yield InputTransaction(tb, request, 0, invalidate, replace, address, random.randint(0,data_high))

			#replace step 2:
			readWrite = 1		# ... and continue below

		if DEBUG >= 2: print("=== random_input_gen: request={0}, readWrite={1}, invalidate={2}, replace={3}, address={4}".format(request, readWrite, invalidate, replace, address))
		if DEBUG >= 2: print("=== random_input_gen: lru_tags[{0}]={1!s}".format(index, lru_tags[index].items()))

		yield InputTransaction(tb, request, readWrite, invalidate, replace, address, random.randint(0,data_high))
Esempio n. 5
0
    def __init__(self, dut):
        self.dut = dut
        self.stopped = False
        elements = dut.ELEMENTS.value
        self.lru = LeastRecentlyUsedDict(size_limit=elements)

        # initial state of LRU list
        for keyin in range(elements - 1, -1, -1):
            self.lru[keyin] = 1

        init_val = elements - 1

        self.input_drv = InputDriver(dut)
        self.output_mon = OutputMonitor(dut)

        # Create a scoreboard on the outputs
        self.expected_output = [init_val]
        self.scoreboard = Scoreboard(dut)
        self.scoreboard.add_interface(self.output_mon, self.expected_output)

        # Reconstruct the input transactions from the pins
        # and send them to our 'model'
        self.input_mon = InputMonitor(dut, callback=self.model)
Esempio n. 6
0
    def __init__(self, dut):
        self.dut = dut
        self.stopped = False
        self.address_bits = dut.ADDRESS_BITS.value
        self.data_bits = dut.DATA_BITS.value

        cache_lines = dut.CACHE_LINES.value  # total number of cache lines
        self.associativity = dut.ASSOCIATIVITY.value
        self.cache_sets = cache_lines / self.associativity  # number of cache sets

        self.index_bits = log2ceil(self.cache_sets)
        tag_bits = self.address_bits - self.index_bits

        self.index_mask = 2**self.index_bits - 1
        self.tag_mask = 2**tag_bits - 1

        if DEBUG:
            print("Testbench: {0}, {1}, {2}".format(self.index_bits,
                                                    self.index_mask,
                                                    self.tag_mask))

        replacement_policy = dut.REPLACEMENT_POLICY.value
        if replacement_policy != "LRU":
            raise TestFailure(
                "Unsupported configuration: REPLACEMENT_POLICY=%s" %
                replacement_policy)

        # TODO: create LRU dictionary for each cache set
        self.lrus = tuple([
            LeastRecentlyUsedDict(size_limit=self.associativity)
            for _ in range(self.cache_sets)
        ])

        init_val = OutputTransaction(self)

        self.input_drv = InputDriver(dut)
        self.output_mon = OutputMonitor(dut, self)

        # Create a scoreboard on the outputs
        self.expected_output = [init_val]
        self.scoreboard = Testbench.MyScoreboard(dut)
        self.scoreboard.add_interface(self.output_mon, self.expected_output)

        # Reconstruct the input transactions from the pins
        # and send them to our 'model'
        self.input_mon = InputMonitor(dut, callback=self.model)
Esempio n. 7
0
	def __init__(self, dut, init_val):
		self.dut = dut
		self.stopped = False
		elements = dut.ELEMENTS.value;
		self.lru = LeastRecentlyUsedDict(size_limit=elements)

		if elements != 16:
			raise TestFailure("Unsupported number of elements.")

		self.input_drv = InputDriver(dut)
		self.output_mon = OutputMonitor(dut)

		# Create a scoreboard on the outputs
		self.expected_output = [ init_val ]
		self.scoreboard = Testbench.MyScoreboard(dut)
		self.scoreboard.add_interface(self.output_mon, self.expected_output)

		# Reconstruct the input transactions from the pins
		# and send them to our 'model'
		self.input_mon = InputMonitor(dut, callback=self.model)
Esempio n. 8
0
	def __init__(self, dut):
		self.dut = dut
		self.stopped = False
		elements = dut.ELEMENTS.value;
		self.lru = LeastRecentlyUsedDict(size_limit=elements)

		# initial state of LRU list
		for keyin in range(elements-1, -1, -1):
			self.lru[keyin] = 1

		init_val = elements-1

		self.input_drv = InputDriver(dut)
		self.output_mon = OutputMonitor(dut)

		# Create a scoreboard on the outputs
		self.expected_output = [ init_val ]
		self.scoreboard = Scoreboard(dut)
		self.scoreboard.add_interface(self.output_mon, self.expected_output)

		# Reconstruct the input transactions from the pins
		# and send them to our 'model'
		self.input_mon = InputMonitor(dut, callback=self.model)
Esempio n. 9
0
class Testbench(object):
	class MyScoreboard(Scoreboard):
		def compare(self, got, exp, log, **_):
			"""Compare Valid before DataOut."""
			got_valid, got_elem = got
			exp_valid, exp_elem = exp

			if got_valid != exp_valid:
				self.errors += 1
				log.error("Received transaction differed from expected output.")
				log.warning("Expected: Valid=%d.\nReceived: Valid=%d." % (exp_valid, got_valid))
				if self._imm:
					raise TestFailure("Received transaction differed from expected transaction.")

			elif got_valid == 1:
				if got_elem != exp_elem: 
					self.errors += 1
					log.error("Received transaction differed from expected output.")
					log.warning("Expected: Valid=%d, DataOut=%d.\n"
											"Received: Valid=%d, DataOut=%d." %
											(exp_valid, exp_elem, got_valid, got_elem))
					if self._imm:
						raise TestFailure("Received transaction differed from expected transaction.")


	def __init__(self, dut, init_val):
		self.dut = dut
		self.stopped = False
		elements = dut.ELEMENTS.value;
		self.lru = LeastRecentlyUsedDict(size_limit=elements)

		if elements != 16:
			raise TestFailure("Unsupported number of elements.")

		self.input_drv = InputDriver(dut)
		self.output_mon = OutputMonitor(dut)

		# Create a scoreboard on the outputs
		self.expected_output = [ init_val ]
		self.scoreboard = Testbench.MyScoreboard(dut)
		self.scoreboard.add_interface(self.output_mon, self.expected_output)

		# Reconstruct the input transactions from the pins
		# and send them to our 'model'
		self.input_mon = InputMonitor(dut, callback=self.model)

	def model(self, transaction):
		'''Model the DUT based on the input transaction.'''
		insert, remove, datain = transaction
		keyin = datain & 0x0f
		#print "=== model called with stopped=%r, Insert=%d, Remove=%d, KeyIn=%d, DataIn=%d" % (self.stopped, insert, remove, keyin, datain)
		if not self.stopped:
			if insert == 1:
				self.lru[keyin] = datain
			#elif free == 1:
			#	self.lru.moveLRU(keyin, datain)
			elif remove == 1:
				if keyin in self.lru: del self.lru[keyin]

			#print "=== model: lru=%s" % self.lru.items()
			if len(self.lru) < 1:
				#print "=== model: to few elements, yet."
				self.expected_output.append( (0, 0) )
			else:
				dataout = self.lru.itervalues().next()
				#print "=== model: LRU element=%d" % dataout
				self.expected_output.append( (1, dataout) )

	def stop(self):
		"""
		Stop generation of expected output transactions.
		One more clock cycle must be executed afterwards, so that, output of
		D-FF can be checked.
		"""
		self.stopped = True
Esempio n. 10
0
class Testbench(object):
    class MyScoreboard(Scoreboard):
        def compare(self, got, exp, log, **_):
            """Compare Valid before DataOut."""
            got_valid, got_elem = got
            exp_valid, exp_elem = exp

            if got_valid != exp_valid:
                self.errors += 1
                log.error(
                    "Received transaction differed from expected output.")
                log.warning("Expected: Valid=%d.\nReceived: Valid=%d." %
                            (exp_valid, got_valid))
                if self._imm:
                    raise TestFailure(
                        "Received transaction differed from expected transaction."
                    )

            elif got_valid == 1:
                if got_elem != exp_elem:
                    self.errors += 1
                    log.error(
                        "Received transaction differed from expected output.")
                    log.warning("Expected: Valid=%d, DataOut=%d.\n"
                                "Received: Valid=%d, DataOut=%d." %
                                (exp_valid, exp_elem, got_valid, got_elem))
                    if self._imm:
                        raise TestFailure(
                            "Received transaction differed from expected transaction."
                        )

    def __init__(self, dut, init_val):
        self.dut = dut
        self.stopped = False
        elements = dut.ELEMENTS.value
        self.lru = LeastRecentlyUsedDict(size_limit=elements)

        if elements != 16:
            raise TestFailure("Unsupported number of elements.")

        self.input_drv = InputDriver(dut)
        self.output_mon = OutputMonitor(dut)

        # Create a scoreboard on the outputs
        self.expected_output = [init_val]
        self.scoreboard = Testbench.MyScoreboard(dut)
        self.scoreboard.add_interface(self.output_mon, self.expected_output)

        # Reconstruct the input transactions from the pins
        # and send them to our 'model'
        self.input_mon = InputMonitor(dut, callback=self.model)

    def model(self, transaction):
        '''Model the DUT based on the input transaction.'''
        insert, remove, datain = transaction
        keyin = datain & 0x0f
        #print "=== model called with stopped=%r, Insert=%d, Remove=%d, KeyIn=%d, DataIn=%d" % (self.stopped, insert, remove, keyin, datain)
        if not self.stopped:
            if insert == 1:
                self.lru[keyin] = datain
            #elif free == 1:
            #	self.lru.moveLRU(keyin, datain)
            elif remove == 1:
                if keyin in self.lru: del self.lru[keyin]

            #print "=== model: lru=%s" % self.lru.items()
            if len(self.lru) < 1:
                #print "=== model: to few elements, yet."
                self.expected_output.append((0, 0))
            else:
                dataout = self.lru.itervalues().next()
                #print "=== model: LRU element=%d" % dataout
                self.expected_output.append((1, dataout))

    def stop(self):
        """
		Stop generation of expected output transactions.
		One more clock cycle must be executed afterwards, so that, output of
		D-FF can be checked.
		"""
        self.stopped = True