class SdramTester(Infrastructure): def __init__(self,name,parent,cmd,rsp,clk,reset): Infrastructure.__init__(self, name, parent) StreamDriverMaster(cmd, self.genCmd, clk, reset) self.nonZeroRspCounter = 0 self.cmdRandomizer = BoolRandomizer() self.writeRandomizer = BoolRandomizer() self.burstRandomizer = BoolRandomizer() self.lastAddr = 0 self.closeIt = False self.ram = bytearray(b'\x00' * (1 << (9+2+2+1))) self.scorboard = ScorboardInOrder("scoreboard", self) StreamDriverSlave(rsp, clk, reset) # rsp.ready <= 1 StreamMonitor(rsp, self.scorboard.uutPush, clk, reset) def canPhaseProgress(self, phase): return self.nonZeroRspCounter > 4000 def startPhase(self, phase): Infrastructure.startPhase(self, phase) if phase == PHASE_WAIT_TASKS_END: self.closeIt = True def genCmd(self): if self.closeIt or not self.cmdRandomizer.get(): return None trans = Transaction() if not self.burstRandomizer.get(): trans.address = randBits(9+2+2) else: trans.address = self.lastAddr + 1 trans.address = trans.address & ((1 << 13)-1) trans.write = self.writeRandomizer.get() and self.writeRandomizer.get() trans.mask = randBits(2) trans.data = randBits(16) trans.context = randBits(8) self.lastAddr = trans.address if trans.write == 0: rsp = Transaction() rsp.data = self.ram[trans.address*2] + (self.ram[trans.address*2+1] << 8) rsp.context = trans.context self.scorboard.refPush(rsp) if rsp.data != 0: self.nonZeroRspCounter += 1 if self.nonZeroRspCounter % 50 == 0: print("self.nonZeroRspCounter=" + str(self.nonZeroRspCounter)) else: for i in xrange(2): if (trans.mask >> i) & 1 == 1: self.ram[trans.address * 2 + i] = (trans.data >> (i*8)) & 0xFF return trans
class SharedMasterDriver(WriteOnlyMasterDriver, ReadOnlyMasterDriver): def __init__(self,name,parent,idBase,axi,dut): WriteOnlyMasterDriver.__init__(self,name,parent, idBase, axi, dut) ReadOnlyMasterDriver.__init__(self,name,parent, idBase, axi, dut) self.readOrWriteRand = BoolRandomizer() def createInfrastructure(self): StreamDriverMaster(self.axi.arw, self.genSharedCmd, self.dut.clk, self.dut.reset) StreamDriverMaster(self.axi.w, self.genWriteData, self.dut.clk, self.dut.reset) StreamDriverSlave(self.axi.b, self.dut.clk, self.dut.reset) StreamDriverSlave(self.axi.r, self.dut.clk, self.dut.reset) return self def genSharedCmd(self): if self.readOrWriteRand.get(): trans = self.genWriteCmd() if trans: trans.write = 1 else: trans = self.genReadCmd() if trans: trans.write = 0 return trans def updateDoFinish(self): if self.readCounter > 100 and self.writeCounter > 100: self.closeIt = False def isCompleted(self): return WriteOnlyMasterDriver.isCompleted(self) and ReadOnlyMasterDriver.isCompleted(self)
class SharedMasterDriver(WriteOnlyMasterDriver, ReadOnlyMasterDriver): def __init__(self, name, parent, idBase, axi, dut): WriteOnlyMasterDriver.__init__(self, name, parent, idBase, axi, dut) ReadOnlyMasterDriver.__init__(self, name, parent, idBase, axi, dut) self.readOrWriteRand = BoolRandomizer() def createInfrastructure(self): StreamDriverMaster(self.axi.arw, self.genSharedCmd, self.dut.clk, self.dut.reset) StreamDriverMaster(self.axi.w, self.genWriteData, self.dut.clk, self.dut.reset) StreamDriverSlave(self.axi.b, self.dut.clk, self.dut.reset) StreamDriverSlave(self.axi.r, self.dut.clk, self.dut.reset) return self def genSharedCmd(self): if self.readOrWriteRand.get(): trans = self.genWriteCmd() if trans: trans.write = 1 else: trans = self.genReadCmd() if trans: trans.write = 0 return trans def updateDoFinish(self): if self.readCounter > 100 and self.writeCounter > 100: self.closeIt = False def isCompleted(self): return WriteOnlyMasterDriver.isCompleted( self) and ReadOnlyMasterDriver.isCompleted(self)
def stim(self): randomizer = BoolRandomizer() self.ahb.HREADY <= 1 self.ahb.HSEL <= 1 while True: yield RisingEdge(self.clk) self.randomHREADY = randomizer.get() self.doComb()
def cmd(dut,queue): validRandomizer = BoolRandomizer() dut.io_slave0_valid <= 0 while True: yield RisingEdge(dut.io_clkA) if int(dut.io_slave0_valid) == 1 and int(dut.io_slave0_ready) == 1: queue.put(Packet(int(dut.io_slave0_payload_a),int(dut.io_slave0_payload_b))) dut.io_slave0_valid <= validRandomizer.get() randSignal(dut.io_slave0_payload_a) randSignal(dut.io_slave0_payload_b)
def cmd(dut,queue): validRandomizer = BoolRandomizer() dut.io_slave0_valid <= 0 while True: yield RisingEdge(dut.io_clkA) if int(dut.io_slave0_valid) == 1 and int(dut.io_slave0_ready) == 1: queue.put(Packet(int(dut.io_slave0_payload_a),int(dut.io_slave0_payload_b))) dut.io_slave0_valid <= validRandomizer.get() randSignal(dut.io_slave0_payload_a) randSignal(dut.io_slave0_payload_b)
def push(self): dut = self.dut queue = self.queue validRandomizer = BoolRandomizer() dut.io_slave0_valid <= 0 while True: yield RisingEdge(dut.clk) if int(dut.io_slave0_valid) == 1 and int(dut.io_slave0_ready) == 1: queue.put(FifoPacket(int(dut.io_slave0_payload_a), int(dut.io_slave0_payload_b))) dut.io_slave0_valid <= validRandomizer.get() randSignal(dut.io_slave0_payload_a) randSignal(dut.io_slave0_payload_b)
def rsp(dut,queue): readyRandomizer = BoolRandomizer() dut.io_master0_ready <= 0 for i in range(0,1000): while True: yield RisingEdge(dut.io_clkB) dut.io_master0_ready <= readyRandomizer.get() if int(dut.io_master0_valid) == 1 and int(dut.io_master0_ready) == 1: break pop = queue.get() assertEquals(pop.a, dut.io_master0_payload_a,"io_master0_payload_a") assertEquals(pop.b, dut.io_master0_payload_b, "io_master0_payload_b")
def rsp(dut,queue): readyRandomizer = BoolRandomizer() dut.io_master0_ready <= 0 for i in range(0,1000): while True: yield RisingEdge(dut.io_clkB) dut.io_master0_ready <= readyRandomizer.get() if int(dut.io_master0_valid) == 1 and int(dut.io_master0_ready) == 1: break pop = queue.get() assertEquals(pop.a, dut.io_master0_payload_a,"io_master0_payload_a") assertEquals(pop.b, dut.io_master0_payload_b, "io_master0_payload_b")
def push(self): dut = self.dut queue = self.queue validRandomizer = BoolRandomizer() dut.io_slave0_valid <= 0 while True: yield RisingEdge(dut.clk) if int(dut.io_slave0_valid) == 1 and int(dut.io_slave0_ready) == 1: queue.put(FifoPacket(int(dut.io_slave0_payload_a), int(dut.io_slave0_payload_b))) dut.io_slave0_valid <= validRandomizer.get() randSignal(dut.io_slave0_payload_a) randSignal(dut.io_slave0_payload_b)
def pop(self): dut = self.dut queue = self.queue readyRandomizer = BoolRandomizer() dut.io_master0_ready <= 0 for i in range(0,1000): while True: yield RisingEdge(dut.clk) dut.io_master0_ready <= readyRandomizer.get() if int(dut.io_master0_valid) == 1 and int(dut.io_master0_ready) == 1: break pop = queue.get() assertEquals(pop.a, dut.io_master0_payload_a,"io_master0_payload_a") assertEquals(pop.b, dut.io_master0_payload_b, "io_master0_payload_b")
def pop(self): dut = self.dut queue = self.queue readyRandomizer = BoolRandomizer() dut.io_master0_ready <= 0 for i in range(0,1000): while True: yield RisingEdge(dut.clk) dut.io_master0_ready <= readyRandomizer.get() if int(dut.io_master0_valid) == 1 and int(dut.io_master0_ready) == 1: break pop = queue.get() assertEquals(pop.a, dut.io_master0_payload_a,"io_master0_payload_a") assertEquals(pop.b, dut.io_master0_payload_b, "io_master0_payload_b")
class StreamDriverSlave: def __init__(self, stream, clk, reset): self.stream = stream self.clk = clk self.reset = reset self.randomizer = BoolRandomizer() cocotb.fork(self.stim()) @cocotb.coroutine def stim(self): stream = self.stream stream.ready <= 1 while True: yield RisingEdge(self.clk) stream.ready <= self.randomizer.get()
def stimReady(self): randomizer = BoolRandomizer() self.ahb.HREADYOUT <= 1 busy = False while True: yield RisingEdge(self.clk) if int(self.ahb.HREADY) == 1: busyNew = int(self.ahb.HTRANS) >= 2 else: busyNew = busy if (busy or busyNew) and int(self.ahb.HREADYOUT) == 0 and int( self.ahb.HREADY) == 1: raise TestFailure("HREADYOUT == 0 but HREADY == 1 ??? " + self.ahb.HREADY._name) busy = busyNew self.ahb.HREADYOUT <= randomizer.get()
class ReadOnlySlaveDriver: def __init__(self, axi, base, size, dut): self.axi = axi self.size = size self.base = base self.dut = dut self.readRspRand = BoolRandomizer() self.readRspQueues = [Queue() for i in range(256)] self.nonEmptyReadRspQueues = [] axi.r.payload.hid <= 0 def createInfrastructure(self): StreamDriverSlave(self.axi.ar, self.dut.clk, self.dut.reset) StreamMonitor(self.axi.ar, self.onReadCmd, self.dut.clk, self.dut.reset) StreamDriverMaster(self.axi.r, self.genReadRsp, self.dut.clk, self.dut.reset) return self def onReadCmd(self, trans): if trans.addr < self.base or trans.addr >= self.base + self.size: raise TestFailure("WRONG ADDRESS addr=%d base=%d size=%d" % (trans.addr, self.base, self.size)) for i in range(trans.len + 1): rsp = Transaction() rsp.data = trans.addr + i rsp.resp = 0 rsp.hid = trans.hid if i == trans.len: rsp.last = 1 else: rsp.last = 0 queue = self.readRspQueues[trans.hid] if queue.empty(): self.nonEmptyReadRspQueues.append(queue) queue.put(rsp) def genReadRsp(self): if len(self.nonEmptyReadRspQueues) == 0: return None if not self.readRspRand.get(): return None queue = random.choice(self.nonEmptyReadRspQueues) trans = queue.get() if queue.empty(): self.nonEmptyReadRspQueues.remove(queue) return trans
class ReadOnlySlaveDriver: def __init__(self,axi,base,size,dut): self.axi = axi self.size = size self.base = base self.dut = dut self.readRspRand = BoolRandomizer() self.readRspQueues = [Queue() for i in xrange(256)] self.nonEmptyReadRspQueues = [] axi.r.payload.hid <= 0 def createInfrastructure(self): StreamDriverSlave(self.axi.ar, self.dut.clk, self.dut.reset) StreamMonitor(self.axi.ar, self.onReadCmd, self.dut.clk, self.dut.reset) StreamDriverMaster(self.axi.r, self.genReadRsp, self.dut.clk, self.dut.reset) return self def onReadCmd(self,trans): if trans.addr < self.base or trans.addr >= self.base + self.size: raise TestFailure("WRONG ADDRESS addr=%d base=%d size=%d" %(trans.addr,self.base,self.size)) for i in xrange(trans.len+1): rsp = Transaction() rsp.data = trans.addr + i rsp.resp = 0 rsp.hid = trans.hid if i == trans.len: rsp.last = 1 else: rsp.last = 0 queue = self.readRspQueues[trans.hid] if queue.empty(): self.nonEmptyReadRspQueues.append(queue) queue.put(rsp) def genReadRsp(self): if len(self.nonEmptyReadRspQueues) == 0: return None if not self.readRspRand.get(): return None queue = random.choice(self.nonEmptyReadRspQueues) trans = queue.get() if queue.empty(): self.nonEmptyReadRspQueues.remove(queue) return trans
def clockProcess(dut): randomizer = BoolRandomizer() dut.io_clkA <= 0 dut.io_clkB <= 0 dut.io_resetB <= 1 dut.io_resetA <= 1 yield Timer(1000) dut.io_resetA <= 0 dut.io_resetB <= 0 while True: dut.io_clkA <= 0 dut.io_clkB <= 0 yield Timer(500) if randomizer.get(): dut.io_clkA <= 1 else: dut.io_clkB <= 1 yield Timer(500)
def clockProcess(dut): randomizer = BoolRandomizer() dut.io_clkA <= 0 dut.io_clkB <= 0 dut.io_resetB <= 1 dut.io_resetA <= 1 yield Timer(1000) dut.io_resetA <= 0 dut.io_resetB <= 0 while True: dut.io_clkA <= 0 dut.io_clkB <= 0 yield Timer(500) if randomizer.get(): dut.io_clkA <= 1 else: dut.io_clkB <= 1 yield Timer(500)
class ReadOnlyMasterDriver(Infrastructure): def __init__(self, name, parent, idBase, axi, dut): Infrastructure.__init__(self, name, parent) self.idBase = idBase self.axi = axi self.dut = dut self.closeIt = False self.readCmdIdleRand = BoolRandomizer() def startPhase(self, phase): Infrastructure.startPhase(self, phase) if phase == PHASE_WAIT_TASKS_END: self.closeIt = True def createInfrastructure(self): StreamDriverMaster(self.axi.ar, self.genReadCmd, self.dut.clk, self.dut.reset) StreamDriverSlave(self.axi.r, self.dut.clk, self.dut.reset) return self def genRandomReadAddress(self): if random.random() < 0.1: # Random assertion of decoding error return 1 << 14 return randBits(12) + random.choice([0, 1, 2]) * 0x1000 def genReadCmd(self): if self.closeIt: return None if not self.readCmdIdleRand.get(): return None idOffset = randBits(2) trans = Transaction() trans.addr = self.genRandomReadAddress() trans.hid = self.idBase * 4 + idOffset #Each master can use 4 id trans.region = randBits(4) trans.len = randBits(4) trans.size = randBits(3) trans.burst = randBits(2) trans.lock = randBits(1) trans.cache = randBits(4) trans.qos = randBits(4) trans.prot = randBits(3) return trans
class ReadOnlyMasterDriver(Infrastructure): def __init__(self,name,parent,idBase,axi,dut): Infrastructure.__init__(self,name,parent) self.idBase = idBase self.axi = axi self.dut = dut self.closeIt = False self.readCmdIdleRand = BoolRandomizer() def startPhase(self, phase): Infrastructure.startPhase(self, phase) if phase == PHASE_WAIT_TASKS_END: self.closeIt = True def createInfrastructure(self): StreamDriverMaster(self.axi.ar, self.genReadCmd, self.dut.clk, self.dut.reset) StreamDriverSlave(self.axi.r, self.dut.clk, self.dut.reset) return self def genRandomReadAddress(self): if random.random() < 0.1: # Random assertion of decoding error return 1 << 14 return randBits(12) + random.choice([0,1,2])*0x1000 def genReadCmd(self): if self.closeIt: return None if not self.readCmdIdleRand.get(): return None idOffset = randBits(2) trans = Transaction() trans.addr = self.genRandomReadAddress() trans.hid = self.idBase*4 + idOffset #Each master can use 4 id trans.region = randBits(4) trans.len = randBits(4) trans.size = randBits(3) trans.burst = randBits(2) trans.lock = randBits(1) trans.cache = randBits(4) trans.qos = randBits(4) trans.prot = randBits(3) return trans
class StreamFifoTester(Infrastructure): def __init__(self, name, parent, pushStream, popStream, transactionGenerator, dutCounterTarget, clk, reset): Infrastructure.__init__(self, name, parent) self.pushStream = pushStream self.popStream = popStream self.clk = clk self.reset = reset self.dutCounter = 0 self.closeIt = False self.transactionGenerator = transactionGenerator self.dutCounterTarget = dutCounterTarget self.pushRandomizer = BoolRandomizer() self.scoreboard = ScorboardInOrder("scoreboard", self) def createInfrastructure(self): StreamDriverMaster(self.pushStream, self.genPush, self.clk, self.reset) StreamDriverSlave(self.popStream, self.clk, self.reset) StreamMonitor(self.popStream, self.onUut, self.clk, self.reset) StreamMonitor(self.pushStream, self.onRef, self.clk, self.reset) def startPhase(self, phase): Infrastructure.startPhase(self, phase) if phase == PHASE_WAIT_TASKS_END: self.closeIt = True def genPush(self): if not self.closeIt and self.pushRandomizer.get(): return self.transactionGenerator() def onUut(self, uut): self.dutCounter += 1 self.scoreboard.uutPush(uut) def onRef(self, uut): self.scoreboard.refPush(uut) def canPhaseProgress(self, phase): return self.dutCounter > self.dutCounterTarget
class Axi4SharedMemoryChecker(Infrastructure): def __init__(self, name, parent, axi, addressWidth, clk, reset): Infrastructure.__init__(self, name, parent) self.axi = axi if hasattr(axi.arw.payload, "hid"): self.idWidth = len(axi.arw.payload.hid) self.addressWidth = addressWidth self.dataWidth = len(axi.w.payload.data) self.maxDataBytes = int(log2Up(self.dataWidth) / 8) self.ram = bytearray(b'\x00' * ((1 << addressWidth) * self.maxDataBytes)) self.doReadWriteCmdRand = BoolRandomizer() self.readWriteRand = BoolRandomizer() self.writeDataRand = BoolRandomizer() self.writeRspScoreboard = ScorboardOutOfOrder("writeRspScoreboard", self) self.readRspScoreboard = ScorboardOutOfOrder("readRspScoreboard", self) self.writeRspScoreboard.addListener(self.freeReservatedAddresses) self.readRspScoreboard.addListener(self.freeReservatedAddresses) self.cmdTasks = Queue() self.writeTasks = Queue() self.nonZeroReadRspCounter = 0 self.nonZeroReadRspCounterTarget = 1000 self.reservedAddresses = {} StreamDriverSlave(axi.r, clk, reset) StreamDriverSlave(axi.b, clk, reset) StreamDriverMaster(axi.arw, self.genReadWriteCmd, clk, reset) StreamDriverMaster(axi.w, self.genWriteData, clk, reset) StreamMonitor(axi.r, self.onReadRsp, clk, reset) StreamMonitor(axi.b, self.onWriteRsp, clk, reset) axi.w.payload.last <= 0 axi.r.payload.last <= 0 def freeReservatedAddresses(self, uut, ref, equal): self.reservedAddresses.pop(ref, None) def isAddressRangeBusy(self, start, end): for r in self.reservedAddresses.values(): if start < r[1] and end > r[0]: return True return False def genRandomeAddress(self): return randBits(self.addressWidth) def genNewCmd(self): cmd = Transaction() cmd.hid = randBits(self.idWidth) # Each master can use 4 id cmd.region = randBits(4) cmd.len = randBits(4) cmd.size = random.randint(0, self.maxDataBytes) cmd.burst = random.randint(0, 2) if cmd.burst == 2: cmd.len = random.choice([2, 4, 8, 16]) - 1 else: cmd.len = randBits(4) + (16 if random.random() < 0.1 else 0) + (32 if random.random() < 0.02 else 0) cmd.lock = randBits(1) cmd.cache = randBits(4) cmd.qos = randBits(4) cmd.prot = randBits(3) byteCount = (1 << cmd.size) * (cmd.len + 1) while (True): cmd.addr = self.genRandomeAddress() & ~((1 << cmd.size) - 1) if cmd.burst == 1: if cmd.addr + byteCount >= (1 << self.addressWidth): continue if cmd.burst == 0: start = cmd.addr end = start + cmd.size if cmd.burst == 1: start = cmd.addr end = start + byteCount if cmd.burst == 2: start = cmd.addr & ~(byteCount - 1) end = start + byteCount if self.isAddressRangeBusy(start, end): continue break if self.readWriteRand.get(): cmd.write = 1 beatAddr = cmd.addr for i in range(cmd.len + 1): dataTrans = Transaction() dataTrans.data = randBits(self.dataWidth) dataTrans.strb = randBits(self.maxDataBytes) dataTrans.last = 1 if cmd.len == i else 0 self.writeTasks.put(dataTrans) for s in range(self.maxDataBytes): if (dataTrans.strb >> s) & 1 == 1: self.ram[(beatAddr & ~(self.maxDataBytes - 1)) + s] = (dataTrans.data >> (s * 8)) & 0xFF beatAddr = Axi4AddrIncr(beatAddr, cmd.burst, cmd.len, cmd.size) writeRsp = Transaction() writeRsp.resp = 0 writeRsp.hid = cmd.hid self.reservedAddresses[writeRsp] = [start, end] self.writeRspScoreboard.refPush(writeRsp, writeRsp.hid) else: cmd.write = 0 beatAddr = cmd.addr for s in range(cmd.len + 1): readRsp = Transaction() addrBase = beatAddr & ~(self.maxDataBytes - 1) readRsp.data = 0 for i in range(self.maxDataBytes): readRsp.data |= self.ram[addrBase + i] << (i * 8) readRsp.resp = 0 readRsp.last = 1 if cmd.len == s else 0 readRsp.hid = cmd.hid if readRsp.last == 1: self.reservedAddresses[readRsp] = [start, end] self.readRspScoreboard.refPush(readRsp, readRsp.hid) beatAddr = Axi4AddrIncr(beatAddr, cmd.burst, cmd.len, cmd.size) self.cmdTasks.put(cmd) # print(str(len(self.cmdTasks.queue)) + " " + str(len(self.writeTasks.queue))) def genReadWriteCmd(self): if self.doReadWriteCmdRand.get(): while self.cmdTasks.empty(): if self.getPhase() != PHASE_SIM: return None self.genNewCmd() return self.cmdTasks.get() def genWriteData(self): if self.writeDataRand.get(): while self.writeTasks.empty(): if self.getPhase() != PHASE_SIM: return None self.genNewCmd() return self.writeTasks.get() def onWriteRsp(self, trans): if hasattr(trans, "hid"): self.writeRspScoreboard.uutPush(trans, trans.hid) def onReadRsp(self, trans): if hasattr(trans, "hid"): self.readRspScoreboard.uutPush(trans, trans.hid) if trans.data != 0: self.nonZeroReadRspCounter += 1 if self.nonZeroReadRspCounter % 50 == 0: print("progress=" + str(self.nonZeroReadRspCounter)) # override def hasEnoughSim(self): return self.nonZeroReadRspCounter > self.nonZeroReadRspCounterTarget
class MasterHandle: def __init__(self, id, idToWrites): self.hid = id self.readCounter = 0 self.writeCounter = 0 self.doFinish = False self.readMonitorQueues = [Queue() for i in range(4) ] # One queue for each transaction id self.writeCmdQueue = Queue() self.writeDataQueue = Queue() self.idToWrites = idToWrites self.readCmdIdleRand = BoolRandomizer() self.writeCmdIdleRand = BoolRandomizer() self.writeDataIdleRand = BoolRandomizer() def isCompleted(self): if not self.doFinish: return False for q in self.readMonitorQueues: if not q.empty(): return False if not self.writeDataQueue.empty(): return False if not self.writeCmdQueue.empty(): return False return True def genWrite(self): idOffset = randBits(2) writeCmd = Transaction() writeCmd.addr = self.genRandomAddress() if random.random() < 0.1: # Random assertion of decoding error writeCmd.addr = 1 << 12 writeCmd.hid = self.hid * 4 + idOffset #Each master can use 4 id writeCmd.region = randBits(4) writeCmd.len = randBits(4) writeCmd.size = randBits(3) writeCmd.burst = randBits(2) writeCmd.lock = randBits(1) writeCmd.cache = randBits(4) writeCmd.qos = randBits(4) writeCmd.prot = randBits(3) self.writeCmdQueue.put(writeCmd) writeCmd.linkedDatas = [] for i in range(writeCmd.len + 1): writeData = Transaction() writeData.data = randBits(32) writeData.strb = randBits(4) writeData.last = 1 if i == writeCmd.len else 0 self.writeDataQueue.put(writeData) writeCmd.linkedDatas.append(writeData) self.idToWrites[writeCmd.hid].append(writeCmd) def getNextWriteCmdTrans(self): if (self.writeCmdQueue.empty()): if self.doFinish: return None self.genWrite() return self.writeCmdQueue.get() def getNextWriteDataTrans(self): if (self.writeDataQueue.empty()): if self.doFinish: return None self.genWrite() return self.writeDataQueue.get() def genRandomAddress(self): while True: value = randBits(12) if (value >> 10) != self.hid and ((value >> 8) & 0x3) == self.hid: return value def genReadCmd(self): if self.doFinish: return None if not self.readCmdIdleRand.get(): return None idOffset = randBits(2) trans = Transaction() trans.addr = self.genRandomAddress() if random.random() < 0.1: # Random assertion of decoding error trans.addr = 1 << 12 trans.hid = self.hid * 4 + idOffset #Each master can use 4 id trans.region = randBits(4) trans.len = randBits(4) trans.size = randBits(3) trans.burst = randBits(2) trans.lock = randBits(1) trans.cache = randBits(4) trans.qos = randBits(4) trans.prot = randBits(3) trans.progress = 0 self.readMonitorQueues[idOffset].put(trans) # print("Master START %d %x" % (trans.hid, trans.addr)) return trans def onReadRsp(self, trans): queue = self.readMonitorQueues[trans.hid - self.hid * 4] task = queue.queue[0] if task.addr != 1 << 12: assertEquals(trans.data, task.addr + task.progress, "Readed value is wrong") else: assertEquals(trans.resp, 3, "yep") task.progress += 1 if task.progress == task.len + 1: # print("Master FINISH %d %x" % (task.hid,task.addr)) assertEquals(trans.last, 1, "Should be last read") queue.get() self.readCounter += 1 self.updateDoFinish() def genWriteCmd(self): if not self.writeCmdIdleRand.get(): return None return self.getNextWriteCmdTrans() def genWriteData(self): if not self.writeDataIdleRand.get(): return None return self.getNextWriteDataTrans() def onWriteRsp(self, trans): self.writeCounter = self.writeCounter + 1 if trans.resp == 3: write = self.idToWrites[trans.hid][0] assertEquals(write.addr, (1 << 12), "ERROR ?") self.idToWrites[trans.hid].remove(write) self.updateDoFinish() def updateDoFinish(self): if self.readCounter > 100 and self.writeCounter > 100: self.doFinish = True
class SlaveHandle: def __init__(self, id, idToWrites): self.tasksQueues = [Queue() ] * 64 # One queue of task for each transaction id self.hid = id self.writeCmds = [] self.writeDatas = [] self.idToWrites = idToWrites self.readRspIdleRand = BoolRandomizer() self.writeRspIdleRand = BoolRandomizer() def getRandTaskList(self): tasksQueuesFiltred = [ tasksList for tasksList in self.tasksQueues if not tasksList.empty() ] if len(tasksQueuesFiltred) == 0: return None return random.choice(tasksQueuesFiltred) def genReadRsp(self): tasksQueue = self.getRandTaskList() if tasksQueue: if self.readRspIdleRand.get(): task = tasksQueue.queue[0] trans = Transaction() trans.data = task.addr + task.progress trans.resp = 0 trans.hid = task.hid task.progress += 1 if task.progress == task.len + 1: trans.last = 1 tasksQueue.get() else: trans.last = 0 return trans def onReadCmd(self, trans): trans.progress = 0 assertEquals(trans.addr >> 10, self.hid, ":(") self.tasksQueues[trans.hid].put(trans) def onWriteCmd(self, trans): assertEquals(trans.addr >> 10, self.hid, ":(") self.writeCmds.append(trans) def onWriteData(self, trans): self.writeDatas.append(trans) def genWriteRsp(self): if len(self.writeCmds) != 0: if not self.writeRspIdleRand.get(): return None cmd = self.writeCmds[0] beatCount = cmd.len + 1 if len(self.writeDatas) >= beatCount: datas = self.writeDatas[0:beatCount - 1] #Check it masterWrite = next(write for write in self.idToWrites[cmd.hid & 0xF] if write.addr >> 10 == self.hid) assertEquals(cmd.addr, masterWrite.addr, "write cmd missmatch") assertEquals(cmd.len, masterWrite.len, "write cmd missmatch") for data, dataRef in zip(datas, masterWrite.linkedDatas): assertEquals(data.data, dataRef.data, "write data missmatch") #Clean self.writeCmds = self.writeCmds[1:] self.writeDatas = self.writeDatas[beatCount:] self.idToWrites[cmd.hid & 0xF].remove(masterWrite) #Answer trans = Transaction() trans.hid = cmd.hid trans.resp = 0 return trans return None
class SdramTester(Infrastructure): def __init__(self, name, parent, cmd, rsp, clk, reset): Infrastructure.__init__(self, name, parent) StreamDriverMaster(cmd, self.genCmd, clk, reset) self.nonZeroRspCounter = 0 self.cmdRandomizer = BoolRandomizer() self.writeRandomizer = BoolRandomizer() self.burstRandomizer = BoolRandomizer() self.lastAddr = 0 self.closeIt = False self.ram = bytearray(b'\x00' * (1 << (9 + 2 + 2 + 1))) self.scorboard = ScorboardInOrder("scoreboard", self) StreamDriverSlave(rsp, clk, reset) # rsp.ready <= 1 StreamMonitor(rsp, self.scorboard.uutPush, clk, reset) def canPhaseProgress(self, phase): return self.nonZeroRspCounter > 4000 def startPhase(self, phase): Infrastructure.startPhase(self, phase) if phase == PHASE_WAIT_TASKS_END: self.closeIt = True def genCmd(self): if self.closeIt or not self.cmdRandomizer.get(): return None trans = Transaction() if not self.burstRandomizer.get(): trans.address = randBits(9 + 2 + 2) else: trans.address = self.lastAddr + 1 trans.address = trans.address & ((1 << 13) - 1) trans.write = self.writeRandomizer.get() and self.writeRandomizer.get() trans.mask = randBits(2) trans.data = randBits(16) trans.context = randBits(8) self.lastAddr = trans.address if trans.write == 0: rsp = Transaction() rsp.data = self.ram[trans.address * 2] + (self.ram[trans.address * 2 + 1] << 8) rsp.context = trans.context self.scorboard.refPush(rsp) if rsp.data != 0: self.nonZeroRspCounter += 1 if self.nonZeroRspCounter % 50 == 0: print(("self.nonZeroRspCounter=" + str(self.nonZeroRspCounter))) else: for i in range(2): if (trans.mask >> i) & 1 == 1: self.ram[trans.address * 2 + i] = (trans.data >> (i * 8)) & 0xFF return trans
class WriteOnlyMasterDriver(Infrastructure): def __init__(self, name, parent, idBase, axi, dut): Infrastructure.__init__(self, name, parent) self.dut = dut self.axi = axi self.idBase = idBase self.writeCmdQueue = Queue() self.writeDataQueue = Queue() self.writeCmdIdleRand = BoolRandomizer() self.writeDataIdleRand = BoolRandomizer() self.closeIt = False def startPhase(self, phase): Infrastructure.startPhase(self, phase) if phase == PHASE_WAIT_TASKS_END: self.closeIt = True def createInfrastructure(self): StreamDriverMaster(self.axi.aw, self.genWriteCmd, self.dut.clk, self.dut.reset) StreamDriverMaster(self.axi.w, self.genWriteData, self.dut.clk, self.dut.reset) StreamDriverSlave(self.axi.b, self.dut.clk, self.dut.reset) return self def genRandomWriteAddress(self): if random.random() < 0.1: # Random assertion of decoding error return 1 << 14 return randBits(12) + random.choice([0, 1, 3]) * 0x1000 def genWrite(self): idOffset = randBits(2) writeCmd = Transaction() writeCmd.addr = self.genRandomWriteAddress() writeCmd.hid = self.idBase + idOffset #Each master can use 4 id writeCmd.region = randBits(4) writeCmd.len = randBits(4) writeCmd.size = randBits(3) writeCmd.burst = randBits(2) writeCmd.lock = randBits(1) writeCmd.cache = randBits(4) writeCmd.qos = randBits(4) writeCmd.prot = randBits(3) self.writeCmdQueue.put(writeCmd) for i in range(writeCmd.len + 1): writeData = Transaction() writeData.data = writeCmd.addr + i writeData.strb = (writeCmd.addr + i) & 0xF writeData.last = 1 if i == writeCmd.len else 0 self.writeDataQueue.put(writeData) def getNextWriteCmdTrans(self): if (self.writeCmdQueue.empty()): if self.closeIt: return None self.genWrite() return self.writeCmdQueue.get() def getNextWriteDataTrans(self): if (self.writeDataQueue.empty()): if self.closeIt: return None self.genWrite() return self.writeDataQueue.get() def genWriteCmd(self): if not self.writeCmdIdleRand.get(): return None return self.getNextWriteCmdTrans() def genWriteData(self): if not self.writeDataIdleRand.get(): return None return self.getNextWriteDataTrans()
class WriteOnlyMasterDriver(Infrastructure): def __init__(self,name,parent,idBase,axi,dut): Infrastructure.__init__(self,name,parent) self.dut = dut self.axi = axi self.idBase = idBase self.writeCmdQueue = Queue() self.writeDataQueue = Queue() self.writeCmdIdleRand = BoolRandomizer() self.writeDataIdleRand = BoolRandomizer() self.closeIt = False def startPhase(self, phase): Infrastructure.startPhase(self, phase) if phase == PHASE_WAIT_TASKS_END: self.closeIt = True def createInfrastructure(self): StreamDriverMaster(self.axi.aw, self.genWriteCmd, self.dut.clk, self.dut.reset) StreamDriverMaster(self.axi.w, self.genWriteData, self.dut.clk, self.dut.reset) StreamDriverSlave(self.axi.b, self.dut.clk, self.dut.reset) return self def genRandomWriteAddress(self): if random.random() < 0.1: # Random assertion of decoding error return 1 << 14 return randBits(12) + random.choice([0,1,3])*0x1000 def genWrite(self): idOffset = randBits(2) writeCmd = Transaction() writeCmd.addr = self.genRandomWriteAddress() writeCmd.hid = self.idBase + idOffset #Each master can use 4 id writeCmd.region = randBits(4) writeCmd.len = randBits(4) writeCmd.size = randBits(3) writeCmd.burst = randBits(2) writeCmd.lock = randBits(1) writeCmd.cache = randBits(4) writeCmd.qos = randBits(4) writeCmd.prot = randBits(3) self.writeCmdQueue.put(writeCmd) for i in xrange(writeCmd.len + 1): writeData = Transaction() writeData.data = writeCmd.addr + i writeData.strb = (writeCmd.addr + i) & 0xF writeData.last = 1 if i == writeCmd.len else 0 self.writeDataQueue.put(writeData) def getNextWriteCmdTrans(self): if(self.writeCmdQueue.empty()): if self.closeIt: return None self.genWrite() return self.writeCmdQueue.get() def getNextWriteDataTrans(self): if(self.writeDataQueue.empty()): if self.closeIt: return None self.genWrite() return self.writeDataQueue.get() def genWriteCmd(self): if not self.writeCmdIdleRand.get(): return None return self.getNextWriteCmdTrans() def genWriteData(self): if not self.writeDataIdleRand.get(): return None return self.getNextWriteDataTrans()
class WriteOnlySlaveDriver: def __init__(self,axi,base,size,dut): self.axi = axi self.size = size self.base = base self.dut = dut self.writeRspRand = BoolRandomizer() self.writeCmds = [] self.writeDatas = [] self.writeRspQueues = [Queue() for i in xrange(256)] self.nonEmptyWriteRspQueues = [] axi.b.payload.hid <= 0 def createInfrastructure(self): StreamDriverSlave(self.axi.aw, self.dut.clk, self.dut.reset) StreamDriverSlave(self.axi.w, self.dut.clk, self.dut.reset) StreamMonitor(self.axi.aw, self.onWriteCmd, self.dut.clk, self.dut.reset) StreamMonitor(self.axi.w, self.onWriteData, self.dut.clk, self.dut.reset) StreamDriverMaster(self.axi.b, self.genWriteRsp, self.dut.clk, self.dut.reset) return self def onWriteCmd(self,trans): if trans.addr < self.base or trans.addr >= self.base + self.size: raise TestFailure("WRONG ADDRESS addr=%d base=%d size=%d" %(trans.addr,self.base,self.size)) self.writeCmds.append(trans) self.managePendingWrites() def onWriteData(self, trans): self.writeDatas.append(trans) self.managePendingWrites() def managePendingWrites(self): if len(self.writeCmds) != 0: cmd = self.writeCmds[0] beatCount = cmd.len + 1 if len(self.writeDatas) >= beatCount: datas = self.writeDatas[0:beatCount - 1] # Clean self.writeCmds = self.writeCmds[1:] self.writeDatas = self.writeDatas[beatCount:] # Rsp rsp = Transaction() rsp.hid = cmd.hid rsp.resp = 0 queue = self.writeRspQueues[cmd.hid] if queue.empty(): self.nonEmptyWriteRspQueues.append(queue) queue.put(rsp) def genWriteRsp(self): if len(self.nonEmptyWriteRspQueues) == 0: return None if not self.writeRspRand.get(): return None queue = random.choice(self.nonEmptyWriteRspQueues) trans = queue.get() if queue.empty(): self.nonEmptyWriteRspQueues.remove(queue) return trans
class WriteOnlySlaveDriver: def __init__(self, axi, base, size, dut): self.axi = axi self.size = size self.base = base self.dut = dut self.writeRspRand = BoolRandomizer() self.writeCmds = [] self.writeDatas = [] self.writeRspQueues = [Queue() for i in range(256)] self.nonEmptyWriteRspQueues = [] axi.b.payload.hid <= 0 def createInfrastructure(self): StreamDriverSlave(self.axi.aw, self.dut.clk, self.dut.reset) StreamDriverSlave(self.axi.w, self.dut.clk, self.dut.reset) StreamMonitor(self.axi.aw, self.onWriteCmd, self.dut.clk, self.dut.reset) StreamMonitor(self.axi.w, self.onWriteData, self.dut.clk, self.dut.reset) StreamDriverMaster(self.axi.b, self.genWriteRsp, self.dut.clk, self.dut.reset) return self def onWriteCmd(self, trans): if trans.addr < self.base or trans.addr >= self.base + self.size: raise TestFailure("WRONG ADDRESS addr=%d base=%d size=%d" % (trans.addr, self.base, self.size)) self.writeCmds.append(trans) self.managePendingWrites() def onWriteData(self, trans): self.writeDatas.append(trans) self.managePendingWrites() def managePendingWrites(self): if len(self.writeCmds) != 0: cmd = self.writeCmds[0] beatCount = cmd.len + 1 if len(self.writeDatas) >= beatCount: datas = self.writeDatas[0:beatCount - 1] # Clean self.writeCmds = self.writeCmds[1:] self.writeDatas = self.writeDatas[beatCount:] # Rsp rsp = Transaction() rsp.hid = cmd.hid rsp.resp = 0 queue = self.writeRspQueues[cmd.hid] if queue.empty(): self.nonEmptyWriteRspQueues.append(queue) queue.put(rsp) def genWriteRsp(self): if len(self.nonEmptyWriteRspQueues) == 0: return None if not self.writeRspRand.get(): return None queue = random.choice(self.nonEmptyWriteRspQueues) trans = queue.get() if queue.empty(): self.nonEmptyWriteRspQueues.remove(queue) return trans