def __init__(self, bus, clock, reset=None, reset_active_level=True, *args, **kwargs): self.bus = bus self.clock = clock self.reset = reset self.log = logging.getLogger(f"cocotb.{bus._entity._name}.{bus._name}") super().__init__(*args, **kwargs) self.active = False self.queue = Queue() self.dequeue_event = Event() self.idle_event = Event() self.idle_event.set() self.active_event = Event() self.ready = None self.valid = None if self._ready_signal is not None and hasattr(self.bus, self._ready_signal): self.ready = getattr(self.bus, self._ready_signal) if self._ready_init is not None: self.ready.setimmediatevalue(self._ready_init) if self._valid_signal is not None and hasattr(self.bus, self._valid_signal): self.valid = getattr(self.bus, self._valid_signal) if self._valid_init is not None: self.valid.setimmediatevalue(self._valid_init) for sig in self._signals+self._optional_signals: if hasattr(self.bus, sig): if sig in self._signal_widths: assert len(getattr(self.bus, sig)) == self._signal_widths[sig] if self._init_x and sig not in (self._valid_signal, self._ready_signal): v = getattr(self.bus, sig).value v.binstr = 'x'*len(v) getattr(self.bus, sig).setimmediatevalue(v) self._run_cr = None self._init_reset(reset, reset_active_level)
def __init__(self, bus, clock, reset=None, reset_active_level=True, max_burst_len=256): self.log = logging.getLogger(f"cocotb.{bus.ar._entity._name}.{bus.ar._name}") self.log.info("AXI master (read)") self.log.info("cocotbext-axi version %s", __version__) self.log.info("Copyright (c) 2020 Alex Forencich") self.log.info("https://github.com/alexforencich/cocotbext-axi") self.ar_channel = AxiARSource(bus.ar, clock, reset, reset_active_level) self.ar_channel.queue_occupancy_limit = 2 self.r_channel = AxiRSink(bus.r, clock, reset, reset_active_level) self.r_channel.queue_occupancy_limit = 2 self.read_command_queue = Queue() self.current_read_command = None self.id_count = 2**len(self.ar_channel.bus.arid) self.cur_id = 0 self.active_id = Counter() self.int_read_resp_command_queue = [Queue() for k in range(self.id_count)] self.current_read_resp_command = [None for k in range(self.id_count)] self.int_read_resp_queue_list = [Queue() for k in range(self.id_count)] self.in_flight_operations = 0 self._idle = Event() self._idle.set() self.width = len(self.r_channel.bus.rdata) self.byte_size = 8 self.byte_width = self.width // self.byte_size self.max_burst_len = max(min(max_burst_len, 256), 1) self.max_burst_size = (self.byte_width-1).bit_length() self.log.info("AXI master configuration:") self.log.info(" Address width: %d bits", len(self.ar_channel.bus.araddr)) self.log.info(" ID width: %d bits", len(self.ar_channel.bus.arid)) self.log.info(" Byte size: %d bits", self.byte_size) self.log.info(" Data width: %d bits (%d bytes)", self.width, self.byte_width) self.log.info(" Max burst size: %d (%d bytes)", self.max_burst_size, 2**self.max_burst_size) self.log.info(" Max burst length: %d cycles (%d bytes)", self.max_burst_len, self.max_burst_len*self.byte_width) assert self.byte_width * self.byte_size == self.width assert len(self.r_channel.bus.rid) == len(self.ar_channel.bus.arid) self._process_read_cr = None self._process_read_resp_cr = None self._process_read_resp_id_cr = None self._init_reset(reset, reset_active_level)
def __init__(self, dut, rx_channels=1, tx_channels=1, tx_clock_half_period=16276, rx_clock_half_period=16276, loopback_queue_maxlen=16): self.dut = dut self.tx_clock_half_period = tx_clock_half_period self.rx_clock_half_period = rx_clock_half_period self.rx_frame_asserted = False self.tx_frame_asserted = False self.lbqi = deque() self.lbqq = deque() cocotb.fork(self._rx_clock()) self.got_tx = Event("Got tx event")
def __init__(self): """Constructor for a driver instance.""" # self._busy = Lock() self._pending = Event(name="Driver._pending") self._sendQ = deque() # Subclasses may already set up logging if not hasattr(self, "log"): self.log = SimLog("cocotb.driver.%s" % (self.__class__.__name__)) # Create an independent coroutine which can send stuff self._thread = cocotb.scheduler.add(self._send_thread())
def init_read(self, address, length, arid=None, burst=AxiBurstType.INCR, size=None, lock=AxiLockType.NORMAL, cache=0b0011, prot=AxiProt.NONSECURE, qos=0, region=0, user=0, event=None): if event is None: event = Event() if not isinstance(event, Event): raise ValueError("Expected event object") if length < 0: raise ValueError("Read length must be positive") if arid is None or arid < 0: arid = None elif arid > self.id_count: raise ValueError("Requested ID exceeds maximum ID allowed for ID signal width") burst = AxiBurstType(burst) if size is None or size < 0: size = self.max_burst_size elif size > self.max_burst_size: raise ValueError("Requested burst size exceeds maximum burst size allowed for bus width") lock = AxiLockType(lock) prot = AxiProt(prot) if not self.arlock_present and lock != AxiLockType.NORMAL: raise ValueError("arlock sideband signal value specified, but signal is not connected") if not self.arcache_present and cache != 0b0011: raise ValueError("arcache sideband signal value specified, but signal is not connected") if not self.arprot_present and prot != AxiProt.NONSECURE: raise ValueError("arprot sideband signal value specified, but signal is not connected") if not self.arqos_present and qos != 0: raise ValueError("arqos sideband signal value specified, but signal is not connected") if not self.arregion_present and region != 0: raise ValueError("arregion sideband signal value specified, but signal is not connected") if not self.aruser_present and user != 0: raise ValueError("aruser sideband signal value specified, but signal is not connected") self.in_flight_operations += 1 self._idle.clear() cmd = AxiReadCmd(address, length, arid, burst, size, lock, cache, prot, qos, region, user, event) self.read_command_queue.put_nowait(cmd) return event
async def run_arb_test(dut): tb = TB(dut) byte_lanes = tb.source[0].byte_lanes id_count = 2**len(tb.source[0].bus.tid) cur_id = 1 await tb.reset() test_frames = [] length = byte_lanes * 16 test_data = bytearray(itertools.islice(itertools.cycle(range(256)), length)) for k in range(5): test_frame = AxiStreamFrame(test_data, tx_complete=Event()) test_frame.tid = cur_id test_frame.tdest = 0 src_ind = 0 if k == 0: src_ind = 0 elif k == 4: await test_frames[1].tx_complete.wait() for j in range(8): await RisingEdge(dut.clk) src_ind = 0 else: src_ind = 1 test_frames.append(test_frame) await tb.source[src_ind].send(test_frame) cur_id = (cur_id + 1) % id_count for k in [0, 1, 2, 4, 3]: test_frame = test_frames[k] rx_frame = await tb.sink[0].recv() assert rx_frame.tdata == test_frame.tdata assert rx_frame.tid == test_frame.tid assert rx_frame.tdest == test_frame.tdest assert not rx_frame.tuser assert all(s.empty() for s in tb.sink) await RisingEdge(dut.clk) await RisingEdge(dut.clk)
def __init__(self, entity, name, clock): BusDriver.__init__(self, entity, name, clock) self.bus.cmd_coco_dir.setimmediatevalue(0) self.bus.data_coco_dir.setimmediatevalue(0x00) self.bus.data_coco_out.setimmediatevalue(0xff) self.bus.cmd_coco_out.setimmediatevalue(1) self.bus_width = 1 # Locks implemented with cocotb Events, normal threading.Lock guys don't work self.cmd_bus_busy_event = Event("cmd_bus_busy") self.cmd_bus_busy = False self.data_write_aborted = False self.data_read_aborted = False
def init_write(self, address, data, prot=AxiProt.NONSECURE, event=None): if event is None: event = Event() if not isinstance(event, Event): raise ValueError("Expected event object") self.in_flight_operations += 1 self._idle.clear() self.write_command_queue.put_nowait(AxiLiteWriteCmd(address, bytearray(data), prot, event)) return event
def init_read(self, address, length, prot=AxiProt.NONSECURE, event=None): if event is None: event = Event() if not isinstance(event, Event): raise ValueError("Expected event object") self.in_flight_operations += 1 self._idle.clear() self.read_command_queue.put_nowait(AxiLiteReadCmd(address, length, prot, event)) return event
def __init__(self, interface, param_namespace, name=""): ''' Constructor. interface = The interface associated with the driver should contain the cocotb handles to all the resets that need to be driven. param_namespace = A namespace with parameters associated with each clock in interface. name = String identifier needed for logging. ''' self.__param_namespace = param_namespace self.__event = Event() self.__log = SimLog("cocotb.rsts.{}".format(name)) Driver.__init__(self, interface)
def __init__(self, entity, name, clock, reset=None): self.log = logging.getLogger(f"cocotb.{entity._name}.{name}") self.log.info("AXI lite master (read)") self.log.info("cocotbext-axi version %s", __version__) self.log.info("Copyright (c) 2020 Alex Forencich") self.log.info("https://github.com/alexforencich/cocotbext-axi") self.reset = reset self.ar_channel = AxiLiteARSource(entity, name, clock, reset) self.r_channel = AxiLiteRSink(entity, name, clock, reset) self.read_command_queue = deque() self.read_command_sync = Event() self.read_data_queue = deque() self.read_data_sync = Event() self.read_data_set = set() self.int_read_resp_command_queue = deque() self.int_read_resp_command_sync = Event() self.in_flight_operations = 0 self.width = len(self.r_channel.bus.rdata) self.byte_size = 8 self.byte_width = self.width // self.byte_size self.log.info("AXI lite master configuration:") self.log.info(" Address width: %d bits", len(self.ar_channel.bus.araddr)) self.log.info(" Byte size: %d bits", self.byte_size) self.log.info(" Data width: %d bits (%d bytes)", self.width, self.byte_width) assert self.byte_width * self.byte_size == self.width cocotb.fork(self._process_read()) cocotb.fork(self._process_read_resp())
def __init__(self, entity, name, clock, **kwargs): AvalonMM.__init__(self, entity, name, clock, **kwargs) self.log.debug("AvalonMaster created") self.busy_event = Event("%s_busy" % name) self.busy = False config = kwargs.pop('config', {}) self.config = AvalonMaster._default_config.copy() for configoption, value in config.items(): self.config[configoption] = value self.log.debug("Setting config option %s to %s" % (configoption, str(value)))
def __init__(self, entity, name, clock, reset=None): self.log = SimLog("cocotb.%s.%s" % (entity._name, name)) self.reset = reset self.ar_channel = AxiARSource(entity, name, clock, reset) self.r_channel = AxiRSink(entity, name, clock, reset) self.active_tokens = set() self.read_command_queue = deque() self.read_command_sync = Event() self.read_data_queue = deque() self.read_data_sync = Event() self.read_data_set = set() self.id_queue = deque(range(2**len(self.ar_channel.bus.arid))) self.id_sync = Event() self.int_read_resp_command_queue = deque() self.int_read_resp_command_sync = Event() self.int_read_resp_queue_list = {} self.in_flight_operations = 0 self.width = len(self.r_channel.bus.rdata) self.byte_size = 8 self.byte_width = self.width // self.byte_size self.max_burst_len = 256 self.max_burst_size = (self.byte_width - 1).bit_length() assert self.byte_width * self.byte_size == self.width assert len(self.r_channel.bus.rid) == len(self.ar_channel.bus.arid) cocotb.fork(self._process_read()) cocotb.fork(self._process_read_resp())
def __init__(self, entity, name, clock, timeout=None, width=32, **kwargs): sTo = ", no cycle timeout" if timeout is not None: sTo = ", cycle timeout is %u clockcycles" % timeout self.busy_event = Event("%s_busy" % name) self._timeout = timeout self.busy = False self._acked_ops = 0 self._res_buf = [] self._aux_buf = [] self._op_cnt = 0 self._clk_cycle_count = 0 Wishbone.__init__(self, entity, name, clock, width, **kwargs) self.log.info("Wishbone Master created%s" % sTo)
def __init__(self, entity, name, clock, reset=None): self.log = SimLog("cocotb.%s.%s" % (entity._name, name)) self.log.info("AXI lite master model") self.log.info("cocotbext-axi version %s", __version__) self.log.info("Copyright (c) 2020 Alex Forencich") self.log.info("https://github.com/alexforencich/cocotbext-axi") self.reset = reset self.aw_channel = AxiLiteAWSource(entity, name, clock, reset) self.w_channel = AxiLiteWSource(entity, name, clock, reset) self.b_channel = AxiLiteBSink(entity, name, clock, reset) self.active_tokens = set() self.write_command_queue = deque() self.write_command_sync = Event() self.write_resp_queue = deque() self.write_resp_sync = Event() self.write_resp_set = set() self.int_write_resp_command_queue = deque() self.int_write_resp_command_sync = Event() self.in_flight_operations = 0 self.width = len(self.w_channel.bus.wdata) self.byte_size = 8 self.byte_width = self.width // self.byte_size self.strb_mask = 2**self.byte_width-1 assert self.byte_width == len(self.w_channel.bus.wstrb) assert self.byte_width * self.byte_size == self.width cocotb.fork(self._process_write()) cocotb.fork(self._process_write_resp())
def __init__(self, bus, clock, reset=None, *args, **kwargs): super().__init__(bus, clock, reset, *args, **kwargs) self.sample_obj = None self.sample_sync = Event() self.queue_occupancy_limit_bytes = -1 self.queue_occupancy_limit_frames = -1 self.bus.tready.setimmediatevalue(0) self._init() cocotb.fork(self._run_sink()) cocotb.fork(self._run())
def __init__(self, tracer_bfm, mem_size=1024, halt_addr=0x80000004, max_instr=1000000): self.instr_count = 0 self.test_done_ev = Event() self.halt_addr = halt_addr self.max_instr = max_instr self.complete = False self.tracer_bfm = tracer_bfm self.mem = [0] * mem_size self.trace_instr = "trace_instr" in cocotb.plusargs self.trace_memwrite = "trace_memwrite" in cocotb.plusargs
def __init__(self, entity, name, clock): BusDriver.__init__(self, entity, name, clock) self.bus.cmd_coco_dir.setimmediatevalue( 1) # SPI mode - direction of CMD pin is always host->slave (1) self.bus.cmd_coco_out.setimmediatevalue(1) self.bus.data_coco_dir.setimmediatevalue( 0x08) # D[3] (chip select) is always asserted host->slave self.bus.data_coco_out.setimmediatevalue(0x08) self.bus_width = 1 # Locks implemented with cocotb Events, normal threading.Lock guys don't work self.cmd_bus_busy_event = Event("cmd_bus_busy") self.cmd_bus_busy = False self.data_write_aborted = False self.data_read_aborted = False
def __init__(self, callback=None, event=None): self._event = event self._wait_event = Event() self._recvQ = deque() self._callbacks = [] self.stats = MonitorStatistics() # Sub-classes may already set up logging if not hasattr(self, "log"): self.log = SimLog("cocotb.monitor.%s" % (type(self).__qualname__)) if callback is not None: self.add_callback(callback) # Create an independent coroutine which can receive stuff self._thread = cocotb.scheduler.add(self._monitor_recv())
def __init__(self, entity, name, clock, reset=None, *args, **kwargs): super().__init__(entity, name, clock, reset, *args, **kwargs) self.drive_obj = None self.drive_sync = Event() self.bus.tdata.setimmediatevalue(0) self.bus.tvalid.setimmediatevalue(0) self.bus.tlast.setimmediatevalue(0) self.bus.tkeep.setimmediatevalue(0) self.bus.tuser.setimmediatevalue(0) self._init() cocotb.fork(self._run_source()) cocotb.fork(self._run())
def reset(self, wakeup=False): """ Resets the event to its off state. If `wakeup` is set, then all processes currently waiting for the event are activated before the reset. No self.callbacks are called during a reset. Args: wakeup (bool): """ if wakeup: self.m_event.set() self.m_event = Event() self.num_waiters = 0 self.set_value("on", False) self.trigger_time = 0
def init_read(self, address, length, prot=AxiProt.NONSECURE, event=None): if event is None: event = Event() if not isinstance(event, Event): raise ValueError("Expected event object") if address < 0 or address >= 2**self.address_width: raise ValueError("Address out of range") if not self.arprot_present and prot != AxiProt.NONSECURE: raise ValueError("arprot sideband signal value specified, but signal is not connected") cocotb.start_soon(self._read_wrapper(address, length, prot, event)) return event
async def read(self, address, length, prot=AxiProt.NONSECURE): if address < 0 or address >= 2**self.address_width: raise ValueError("Address out of range") if not self.arprot_present and prot != AxiProt.NONSECURE: raise ValueError("arprot sideband signal value specified, but signal is not connected") event = Event() self.in_flight_operations += 1 self._idle.clear() await self.read_command_queue.put(AxiLiteReadCmd(address, length, prot, event)) await event.wait() return event.data
def send_input_events(self, input_testvectors, n_to_send=-1, l0id_request=-1, event_delays=False): n_input_files = len(input_testvectors) if n_input_files != self.n_input_ports: raise ValueError( f"Number of input event tables (={n_input_files}) is not equal to number of B2B input ports (={self.n_input_ports})" ) hooks = [] for port_num, testvector_file in enumerate(input_testvectors): driver, io, active = self.input_ports[port_num] input_events = events.load_events_from_file( filename=testvector_file, n_to_load=n_to_send, l0id_request=l0id_request) cocotb.log.info( f"Sending {len(input_events)} events to input (port_num, port_name) = ({io.value}, {io.name}) from testvector {testvector_file}" ) hook = None for ievent, event in enumerate(input_events): words = list(event) for iword, word in enumerate(words): flow_kwargs = {} # delays are entered at event boundaries # if word.is_start_of_event(): # flow_kwargs.update( # b2b_flow.event_rate_delay( # io, event, pass_through=not event_delays # ) # ) hook = ( Event() ) # used to tell outside world that all events have been queued to be sent into the fifos driver.append(word.get_binary(), event=hook, **flow_kwargs) if hook: hooks.append(hook.wait()) return hooks
def __init__(self, entity, name, clock, reset=None, *args, **kwargs): self.log = SimLog("cocotb.%s.%s" % (entity._name, name)) self.entity = entity self.clock = clock self.reset = reset self.bus = Bus(self.entity, name, self._signals, optional_signals=self._optional_signals, **kwargs) self.log.info("AXI stream sink") self.log.info("cocotbext-axi version %s", __version__) self.log.info("Copyright (c) 2020 Alex Forencich") self.log.info("https://github.com/alexforencich/cocotbext-axi") super().__init__(*args, **kwargs) self.active = False self.queue = deque() self.sync = Event() self.read_queue = [] self.pause = False self._pause_generator = None self._pause_cr = None self.queue_occupancy_bytes = 0 self.queue_occupancy_frames = 0 self.queue_occupancy_limit_bytes = None self.queue_occupancy_limit_frames = None self.width = len(self.bus.tdata) self.byte_width = 1 self.reset = reset if hasattr(self.bus, "tready"): self.bus.tready.setimmediatevalue(0) if hasattr(self.bus, "tkeep"): self.byte_width = len(self.bus.tkeep) self.byte_size = self.width // self.byte_width self.byte_mask = 2**self.byte_size - 1 cocotb.fork(self._run())
async def read(self, address, length, arid=None, burst=AxiBurstType.INCR, size=None, lock=AxiLockType.NORMAL, cache=0b0011, prot=AxiProt.NONSECURE, qos=0, region=0, user=0): event = Event() self.init_read(address, length, arid, burst, size, lock, cache, prot, qos, region, user, event) await event.wait() return event.data
def __init__(self, data, ctrl, clock, reset=None, enable=None, reset_active_level=True, *args, **kwargs): self.log = logging.getLogger(f"cocotb.{data._path}") self.data = data self.ctrl = ctrl self.clock = clock self.reset = reset self.enable = enable self.log.info("XGMII sink") self.log.info("cocotbext-eth version %s", __version__) self.log.info("Copyright (c) 2020 Alex Forencich") self.log.info("https://github.com/alexforencich/cocotbext-eth") super().__init__(*args, **kwargs) self.active = False self.queue = Queue() self.active_event = Event() self.queue_occupancy_bytes = 0 self.queue_occupancy_frames = 0 self.width = len(self.data) self.byte_size = 8 self.byte_lanes = len(self.ctrl) assert self.width == self.byte_lanes * self.byte_size self.log.info("XGMII sink model configuration") self.log.info(" Byte size: %d bits", self.byte_size) self.log.info(" Data width: %d bits (%d bytes)", self.width, self.byte_lanes) self._run_cr = None self._init_reset(reset, reset_active_level)
def __init__(self, data, header, clock, enable=None, scramble=True, reverse=False, *args, **kwargs): self.log = logging.getLogger(f"cocotb.{data._path}") self.data = data self.header = header self.clock = clock self.enable = enable self.scramble = scramble self.reverse = reverse self.log.info("BASE-R serdes sink") self.log.info("Copyright (c) 2021 Alex Forencich") self.log.info("https://github.com/alexforencich/verilog-ethernet") super().__init__(*args, **kwargs) self.active = False self.queue = Queue() self.active_event = Event() self.queue_occupancy_bytes = 0 self.queue_occupancy_frames = 0 self.width = len(self.data) self.byte_size = 8 self.byte_lanes = 8 assert self.width == self.byte_lanes * self.byte_size self.log.info("BASE-R serdes sink model configuration") self.log.info(" Byte size: %d bits", self.byte_size) self.log.info(" Data width: %d bits (%d bytes)", self.width, self.byte_lanes) self.log.info(" Enable scrambler: %s", self.scramble) self.log.info(" Bit reverse: %s", self.reverse) self._run_cr = cocotb.fork(self._run())
def __init__(self, data, er, dv, clock, reset=None, enable=None, reset_active_level=True, *args, **kwargs): self.log = logging.getLogger(f"cocotb.{data._path}") self.data = data self.er = er self.dv = dv self.clock = clock self.reset = reset self.enable = enable self.log.info("MII sink") self.log.info("cocotbext-eth version %s", __version__) self.log.info("Copyright (c) 2020 Alex Forencich") self.log.info("https://github.com/alexforencich/cocotbext-eth") super().__init__(*args, **kwargs) self.active = False self.queue = Queue() self.active_event = Event() self.queue_occupancy_bytes = 0 self.queue_occupancy_frames = 0 self.width = 4 self.byte_width = 1 assert len(self.data) == 4 if self.er is not None: assert len(self.er) == 1 if self.dv is not None: assert len(self.dv) == 1 self._run_cr = None self._init_reset(reset, reset_active_level)
def __init__(self, bus, clock, reset=None, *args, **kwargs): super().__init__(bus, clock, reset, *args, **kwargs) self.drive_obj = None self.drive_sync = Event() self.queue_occupancy_limit_bytes = -1 self.queue_occupancy_limit_frames = -1 self.bus.tdata.setimmediatevalue(0) self.bus.tvalid.setimmediatevalue(0) self.bus.tlast.setimmediatevalue(0) self.bus.tkeep.setimmediatevalue(0) self.bus.tuser.setimmediatevalue(0) self._init() cocotb.fork(self._run_source()) cocotb.fork(self._run())