def __init__(self, sim: HdlSimulator, intf: "Spi", allowNoReset=False): AgentBase.__init__(self, sim, intf) self.txData = deque() self.rxData = deque() self.chipSelects = deque() self._txBitBuff = deque() self._rxBitBuff = deque() self.csMask = mask(intf.cs._dtype.bit_length()) self.slaveEn = False # resolve clk and rstn self.clk = self.intf._getAssociatedClk()._sigInside self.rst, self.rstOffIn = self._discoverReset( intf, allowNoReset=allowNoReset) # read on rising edge write on falling self.monitorRx = OnRisingCallbackLoop(self.sim, self.clk, self.monitorRx, self.getEnable) self.monitorTx = OnFallingCallbackLoop(self.sim, self.clk, self.monitorTx, self.getEnable) self.driverRx = OnFallingCallbackLoop(self.sim, self.clk, self.driverRx, self.getEnable) self.driverTx = OnRisingCallbackLoop(self.sim, self.clk, self.driverTx, self.getEnable)
def getDrivers(self): self.dataWriter = OnRisingCallbackLoop(self.sim, self.clk, self.dataWriter, self.getEnable) return ([self.driver_init()] + super(FifoReaderAgent, self).getDrivers() + [self.dataWriter()])
def getMonitors(self): self.dataReader = OnRisingCallbackLoop(self.sim, self.clk, self.dataReader, self.getEnable) return ([self.monitor_init()] + super(FifoReaderAgent, self).getMonitors() + [self.dataReader()])
def get_sync_sig_monitor(sim: HdlSimulator, sig, clk, rst, result): def monitorWithClk(): # if clock is specified this function is periodically called every # clk tick yield WaitCombRead() if not rst.read(): result.append((sim.now, int(sig.read()))) return OnRisingCallbackLoop(sim, clk, monitorWithClk, lambda: True)()
def getMonitors(self): sim = self.sim scl = self.intf[0] self.scl = TristateClkAgent( sim, scl, (self.rst, self.rstOffIn), ) self.monitor = OnRisingCallbackLoop( sim, scl.i, self.monitor, self.getEnable) self.startListener = OnFallingCallbackLoop( sim, scl.i, self.startListener, self.getEnable) return ( self.monitor(), self.startListener(), *self.sda.getMonitors(), *self.scl.getMonitors() )
def get_sync_pull_up_driver_with_reset(sim: HdlSimulator, sig, clk, rst): # init yield WaitWriteOnly() sig.write(0) assert sim.now == 0 def pull_up_after(): exp_t = sim.now yield WaitCombRead() assert sim.now == exp_t if not rst.read(): yield WaitWriteOnly() sig.write(1) assert sim.now == exp_t yield OnRisingCallbackLoop(sim, clk, pull_up_after, lambda: True)()
def getDrivers(self): sim = self.sim scl = self.intf[0] driver = self.driver self.scl = TristateClkAgent( sim, scl, (self.rst, self.rstOffIn), ) self.driver = OnRisingCallbackLoop( sim, scl.i, self.driver, self.getEnable) self.startSender = OnFallingCallbackLoop( sim, scl.i, self.startSender, self.getEnable) self.scl.setEnable(False, None) return ( driver(), # initialization of the interface self.driver(), self.startSender(), *self.sda.getDrivers(), *self.scl.getDrivers() )
def __init__(self, sim: HdlSimulator, intf, allowNoReset=False, wrap_monitor_and_driver_in_edge_callback=True): super(MdioAgent, self).__init__(sim, intf, allowNoReset=allowNoReset, wrap_monitor_and_driver_in_edge_callback=False) self.intf.io._initSimAgent(sim) if wrap_monitor_and_driver_in_edge_callback: self.rx_bits = OnRisingCallbackLoop(sim, intf.c, self.rx_bits, lambda: True) self.tx_bits = OnFallingCallbackLoop(sim, intf.c, self.tx_bits, lambda: True) self.rx_bits_tmp = deque() self.tx_bits_tmp = deque() self.reset_state() self.data = {}
class FifoReaderAgent(SyncAgentBase): """ Simulation agent for FifoReader interface """ def __init__(self, sim, intf, allowNoReset=False): super(FifoReaderAgent, self).__init__(sim, intf, allowNoReset) self.data = deque() self.readPending = False self.lastData = None # flags to keep data coherent when enable state changes self.lastData_invalidate = False self.readPending_invalidate = False def setEnable_asDriver(self, en): lastEn = self._enabled super(FifoReaderAgent, self).setEnable_asDriver(en) self.intf.wait.write(not en) self.lastData_invalidate = not en if not lastEn: self.dataWriter.setEnable(en) def setEnable_asMonitor(self, en): lastEn = self._enabled super(FifoReaderAgent, self).setEnable_asMonitor(en) self.intf.en.write(en) self.readPending_invalidate = not en if not lastEn: self.dataReader.setEnable(en) # else dataReader will disable itself def driver_init(self): yield WaitWriteOnly() self.intf.wait.write(not self._enabled) def monitor_init(self): yield WaitWriteOnly() self.intf.en.write(self._enabled) def get_data(self): return self.intf.data.read() def dataReader(self): yield Timer(1) if self.readPending: yield WaitCombRead() d = self.get_data() self.data.append(d) if self.readPending_invalidate: self.readPending = False if not self.readPending and not self._enabled: self.dataWriter.setEnable(False) def getMonitors(self): self.dataReader = OnRisingCallbackLoop(self.sim, self.clk, self.dataReader, self.getEnable) return ([self.monitor_init()] + super(FifoReaderAgent, self).getMonitors() + [self.dataReader()]) def monitor(self): """ Initialize data reading if wait is 0 """ intf = self.intf yield WaitCombRead() if self.notReset(): # wait until wait signal is stable wait_last = None while True: yield WaitCombRead() wait = intf.wait.read() try: wait = int(wait) except ValueError: raise AssertionError(self.sim.now, intf, "wait signal in invalid state") if wait is wait_last: break else: wait_last = wait yield WaitWriteOnly() rd = not wait else: rd = False yield WaitWriteOnly() intf.en.write(rd) self.readPending = rd def getDrivers(self): self.dataWriter = OnRisingCallbackLoop(self.sim, self.clk, self.dataWriter, self.getEnable) return ([self.driver_init()] + super(FifoReaderAgent, self).getDrivers() + [self.dataWriter()]) def set_data(self, d): self.intf.data.write(d) def dataWriter(self): # delay data litle bit to have nicer wave # otherwise wirte happens before next clk period # and it means in 0 time and we will not be able to see it in wave yield Timer(1) yield WaitWriteOnly() self.set_data(self.lastData) if self.lastData_invalidate: self.lastData = None if not self._enabled: self.dataWriter.setEnable(False) def driver(self): # now we are before clock event # * set wait signal # * set last data (done in separate process) # * if en == 1, pop next data for next clk intf = self.intf yield WaitCombRead() rst_n = self.notReset() # speculative write if rst_n and self.data: wait = 0 else: wait = 1 yield WaitWriteOnly() intf.wait.write(wait) if rst_n: # wait for potential update of en # check if write can be performed and if it possible do real write yield WaitTimeslotEnd() en = intf.en.read() try: en = int(en) except ValueError: raise AssertionError(self.sim.now, intf, "en signal in invalid state") if en: assert self.data, (self.sim.now, intf, "underflow") self.lastData = self.data.popleft()
class SpiAgent(SyncAgentBase): """ Simulation agent for SPI interface :ivar ~.txData: data to transceiver container :ivar ~.rxData: received data :ivar ~.chipSelects: values of chip select chipSelects, rxData and txData are lists of integers """ BITS_IN_WORD = 8 def __init__(self, sim: HdlSimulator, intf: "Spi", allowNoReset=False): AgentBase.__init__(self, sim, intf) self.txData = deque() self.rxData = deque() self.chipSelects = deque() self._txBitBuff = deque() self._rxBitBuff = deque() self.csMask = mask(intf.cs._dtype.bit_length()) self.slaveEn = False # resolve clk and rstn self.clk = self.intf._getAssociatedClk()._sigInside self.rst, self.rstOffIn = self._discoverReset( intf, allowNoReset=allowNoReset) # read on rising edge write on falling self.monitorRx = OnRisingCallbackLoop(self.sim, self.clk, self.monitorRx, self.getEnable) self.monitorTx = OnFallingCallbackLoop(self.sim, self.clk, self.monitorTx, self.getEnable) self.driverRx = OnFallingCallbackLoop(self.sim, self.clk, self.driverRx, self.getEnable) self.driverTx = OnRisingCallbackLoop(self.sim, self.clk, self.driverTx, self.getEnable) def setEnable(self, en): self._enabled = en self.monitorRx.setEnable(en) self.monitorTx.setEnable(en) self.driverRx.setEnable(en) self.driverTx.setEnable(en) def splitBits(self, v): return deque( [get_bit(v, i) for i in range(self.BITS_IN_WORD - 1, -1, -1)]) def mergeBits(self, bits): t = Bits(self.BITS_IN_WORD, False) val = 0 vld_mask = 0 for v in bits: val <<= 1 val |= v.val vld_mask <<= 1 vld_mask |= v.vld_mask return t.getValueCls()(t, val, vld_mask) def readRxSig(self, sig): d = sig.read() bits = self._rxBitBuff bits.append(d) if len(bits) == self.BITS_IN_WORD: self.rxData.append(self.mergeBits(bits)) self._rxBitBuff = [] def writeTxSig(self, sig): bits = self._txBitBuff if not bits: if not self.txData: return d = self.txData.popleft() bits = self._txBitBuff = self.splitBits(d) sig.write(bits.popleft()) def monitorRx(self): yield WaitCombRead() if self.notReset(): cs = self.intf.cs.read() cs = int(cs) if cs != self.csMask: # if any slave is enabled if not self._rxBitBuff: self.chipSelects.append(cs) self.readRxSig(self.intf.mosi) # def monitorTx_pre_set(self): # yield WaitWriteOnly() # self.writeTxSig(self.intf.miso) def monitorTx(self): yield WaitCombRead() if self.notReset(): cs = self.intf.cs.read() cs = int(cs) if cs != self.csMask: yield Timer(1) yield WaitWriteOnly() self.writeTxSig(self.intf.miso) def driverRx(self): yield WaitCombRead() if self.notReset() and self.slaveEn: self.readRxSig(self.intf.miso) def driverTx(self): yield WaitCombRead() if self.notReset(): if not self._txBitBuff: try: cs = self.chipSelects.popleft() except IndexError: self.slaveEn = False yield WaitWriteOnly() self.intf.cs.write(self.csMask) return self.slaveEn = True yield WaitWriteOnly() self.intf.cs.write(cs) yield WaitWriteOnly() self.writeTxSig(self.intf.mosi) def getDrivers(self): return [self.driverRx(), self.driverTx()] def getMonitors(self): return [ self.monitorRx(), # self.monitorTx_pre_set(), self.monitorTx() ]