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
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
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 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))
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 __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)
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 __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)
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
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