def Start(dut): dut.start <= 1 yield RisingEdge(dut.clk) dut.start <= 0 yield RisingEdge(dut.clk)
def Z_wavedrom_test(dut): """ Generate a JSON wavedrom diagram of a trace """ log = SimLog("cocotb.%s" % dut._name) cocotb.fork(Clock(dut.clk_i, 100).start()) mockObject = Sha1Model() shaObject = Sha1Driver(dut, None, dut.clk_i) #yield load_data(dut, log, mockObject, 80) args = [ dut.rst_i, dut.dat_i, dut.i, dut.i_mux, # dut.pinput1.i, # dut.pinput1.load_i, # dut.pinput1.test_word_1, # dut.pinput1.test_word_2, # dut.pinput1.test_word_3, # dut.pinput1.test_word_4, # dut.pinput1.test_word_5, # dut.pinput1.valid_o, dut.pbuffer1.i, dut.pbuffer1.rst_i, dut.pbuffer1.load_i, dut.pbuffer1.new_i, dut.pbuffer1.test_word_1, dut.pbuffer1.test_word_2, dut.pbuffer1.test_word_3, dut.pbuffer1.test_word_4, dut.pbuffer1.test_word_5, dut.pbuffer1.valid_o, dut.pbuffer2.i, dut.pbuffer2.rst_i, dut.pbuffer2.load_i, dut.pbuffer2.new_i, dut.pbuffer2.test_word_1, dut.pbuffer2.test_word_2, dut.pbuffer2.test_word_3, dut.pbuffer2.test_word_4, dut.pbuffer2.test_word_5, dut.pbuffer2.valid_o, dut.pbuffer3.i, dut.pbuffer3.rst_i, dut.pbuffer3.load_i, dut.pbuffer3.new_i, dut.pbuffer3.test_word_1, dut.pbuffer3.test_word_2, dut.pbuffer3.test_word_3, dut.pbuffer3.test_word_4, dut.pbuffer3.test_word_5, dut.pbuffer3.valid_o ] with cocotb.wavedrom.trace(*args, clk=dut.clk_i) as waves: yield RisingEdge(dut.clk_i) yield reset(dut) yield load_data(dut, log, mockObject, 16) mockObject.processInput() mockObject.processBuffer() if _debug == True: log.info(convert_hex(dut.pbuffer1.test_word_3).zfill(8)) yield load_data(dut, log, mockObject, 60) if _debug == True: log.info(convert_hex(dut.pbuffer1.test_word_3).zfill(8)) #log.info("{:08x}".format(mockObject.W[78])) #log.info("{:08x}".format(mockObject.W[79])) #log.info("{:08x}".format(mockObject.W[16 - 14])) #log.info("{:08x}".format(mockObject.W[16 - 16])) #log.info("{:08x}".format(mockObject.W[16])) yield load_data(dut, log, mockObject, 90) if _debug == True: log.info(convert_hex(dut.pbuffer1.test_word_3).zfill(8)) log.info(convert_hex(dut.pbuffer1.test_word_4).zfill(8)) #log.info(dut.pinput1.test_word_1.value.hex()) #log.info(dut.pinput1.test_word_2.value.hex()) #log.info(dut.pinput1.test_word_3.value.hex()) #log.info(dut.pinput1.test_word_4.value.hex()) #log.info(dut.pinput1.test_word_5.value.hex()) #log.info(dut.pinput1.test_word_5) #log.info(waves.dumpj(header = {'text':'D_wavedrom_test', 'tick':-2}, config = {'hscale':3})) waves.write('wavedrom.json', header = {'text':'D_wavedrom_test', 'tick':-1}, config = {'hscale':5})
def _monitor_recv(self): """Watch the pins and reconstruct transactions.""" # Avoid spurious object creation by recycling clkedge = RisingEdge(self.clock) rdonly = ReadOnly() pkt = "" in_pkt = False invalid_cyclecount = 0 channel = None def valid(): if hasattr(self.bus, 'ready'): return self.bus.valid.value and self.bus.ready.value return self.bus.valid.value while True: yield clkedge yield rdonly if self.in_reset: continue if valid(): invalid_cyclecount = 0 if self.bus.startofpacket.value: if pkt: raise AvalonProtocolError( "Duplicate start-of-packet received on %s" % str(self.bus.startofpacket)) pkt = "" in_pkt = True if not in_pkt: raise AvalonProtocolError("Data transfer outside of " "packet") # Handle empty and X's in empty / data vec = BinaryValue() if not self.bus.endofpacket.value: vec = self.bus.data.value else: value = self.bus.data.value.get_binstr() if self.config["useEmpty"] and self.bus.empty.value.integer: empty = self.bus.empty.value.integer * self.config[ "dataBitsPerSymbol"] if self.config["firstSymbolInHighOrderBits"]: value = value[:-empty] else: value = value[empty:] vec.assign(value) if not vec.is_resolvable: raise AvalonProtocolError( "After empty masking value is still bad? " "Had empty {:d}, got value {:s}".format( empty, self.bus.data.value.get_binstr())) vec.big_endian = self.config['firstSymbolInHighOrderBits'] pkt += vec.buff if hasattr(self.bus, 'channel'): if channel is None: channel = self.bus.channel.value.integer if channel > self.config["maxChannel"]: raise AvalonProtocolError( "Channel value (%d) is greater than maxChannel (%d)" % (channel, self.config["maxChannel"])) elif self.bus.channel.value.integer != channel: raise AvalonProtocolError( "Channel value changed during packet") if self.bus.endofpacket.value: self.log.info("Received a packet of %d bytes", len(pkt)) self.log.debug(hexdump(str((pkt)))) self.channel = channel if self.report_channel: self._recv({"data": pkt, "channel": channel}) else: self._recv(pkt) pkt = "" in_pkt = False channel = None else: if in_pkt: invalid_cyclecount += 1 if self.config["invalidTimeout"]: if invalid_cyclecount >= self.config["invalidTimeout"]: raise AvalonProtocolError( "In-Packet Timeout. Didn't receive any valid data for %d cycles!" % invalid_cyclecount)
def read(self, address, sync=True): """Issue a request to the bus and block until this comes back. Simulation time still progresses but syntactically it blocks. Args: address (int): The address to read from. sync (bool, optional): Wait for rising edge on clock initially. Defaults to True. Returns: BinaryValue: The read data value. Raises: :any:`TestError`: If master is write-only. """ if not self._can_read: self.log.error("Cannot read - have no read signal") raise TestError("Attempt to read on a write-only AvalonMaster") yield self._acquire_lock() # Apply values for next clock edge if sync: yield RisingEdge(self.clock) self.bus.address <= address self.bus.read <= 1 if hasattr(self.bus, "byteenable"): self.bus.byteenable <= int("1" * len(self.bus.byteenable), 2) if hasattr(self.bus, "cs"): self.bus.cs <= 1 # Wait for waitrequest to be low if hasattr(self.bus, "waitrequest"): yield self._wait_for_nsignal(self.bus.waitrequest) yield RisingEdge(self.clock) # Deassert read self.bus.read <= 0 if hasattr(self.bus, "byteenable"): self.bus.byteenable <= 0 if hasattr(self.bus, "cs"): self.bus.cs <= 0 v = self.bus.address.value v.binstr = "x" * len(self.bus.address) self.bus.address <= v if hasattr(self.bus, "readdatavalid"): while True: yield ReadOnly() if int(self.bus.readdatavalid): break yield RisingEdge(self.clock) else: # Assume readLatency = 1 if no readdatavalid # FIXME need to configure this, # should take a dictionary of Avalon properties. yield ReadOnly() # Get the data data = self.bus.readdata.value self._release_lock() raise ReturnValue(data)
def _send_string(self, string, sync=True, channel=None): """Args: string (str): A string of bytes to send over the bus. channel (int): Channel to send the data on. """ # Avoid spurious object creation by recycling clkedge = RisingEdge(self.clock) firstword = True # FIXME: buses that aren't an integer numbers of bytes bus_width = int(len(self.bus.data) / 8) word = BinaryValue(n_bits=len(self.bus.data), bigEndian=self.config["firstSymbolInHighOrderBits"]) single = BinaryValue(n_bits=1, bigEndian=False) if self.use_empty: empty = BinaryValue(n_bits=len(self.bus.empty), bigEndian=False) # Drive some defaults since we don't know what state we're in if self.use_empty: self.bus.empty <= 0 self.bus.startofpacket <= 0 self.bus.endofpacket <= 0 self.bus.valid <= 0 if hasattr(self.bus, 'error'): self.bus.error <= 0 if hasattr(self.bus, 'channel'): self.bus.channel <= 0 elif channel is not None: raise TestError("%s does not have a channel signal" % self.name) while string: if not firstword or (firstword and sync): yield clkedge # Insert a gap where valid is low if not self.on: self.bus.valid <= 0 for _ in range(self.off): yield clkedge # Grab the next set of on/off values self._next_valids() # Consume a valid cycle if self.on is not True and self.on: self.on -= 1 self.bus.valid <= 1 if hasattr(self.bus, 'channel'): if channel is None: self.bus.channel <= 0 elif channel > self.config['maxChannel'] or channel < 0: raise TestError( "%s: Channel value %d is outside range 0-%d" % (self.name, channel, self.config['maxChannel'])) else: self.bus.channel <= channel if firstword: self.bus.startofpacket <= 1 firstword = False else: self.bus.startofpacket <= 0 nbytes = min(len(string), bus_width) data = string[:nbytes] word.buff = data if len(string) <= bus_width: self.bus.endofpacket <= 1 if self.use_empty: self.bus.empty <= bus_width - len(string) string = "" else: string = string[bus_width:] self.bus.data <= word # If this is a bus with a ready signal, wait for this word to # be acknowledged if hasattr(self.bus, "ready"): yield self._wait_ready() yield clkedge self.bus.valid <= 0 self.bus.endofpacket <= 0 word.binstr = "x" * len(self.bus.data) single.binstr = "x" self.bus.data <= word self.bus.startofpacket <= single self.bus.endofpacket <= single if self.use_empty: empty.binstr = "x" * len(self.bus.empty) self.bus.empty <= empty if hasattr(self.bus, 'channel'): channel_value = BinaryValue(n_bits=len(self.bus.channel), bigEndian=False, value="x" * len(self.bus.channel)) self.bus.channel <= channel_value
def do_test_cached_write_in_readonly(dut): global exited yield RisingEdge(dut.clk) yield ReadOnly() dut.clk <= 0 exited = True
async def send_cycle(self, arg): """ The main sending routine Args: list(WishboneOperations) """ cnt = 0 clkedge = RisingEdge(self.clock) await clkedge if is_sequence(arg): self._op_cnt = len(arg) if self._op_cnt < 1: self.log.error("List contains no operations to carry out") else: result = [] await self._open_cycle() for op in arg: if not isinstance(op, WBOp): raise TestFailure( "Sorry, argument must be a list of WBOp (Wishbone Operation) objects!" ) self._acktimeout = op.acktimeout if op.dat is not None: we = 1 dat = op.dat else: we = 0 dat = 0 await self._drive(we, op.adr, dat, op.sel, op.idle) if op.sel is not None: self.log.debug( "#%3u WE: %s ADR: 0x%08x DAT: 0x%08x SEL: 0x%1x IDLE: %3u" % (cnt, we, op.adr, dat, op.sel, op.idle)) else: self.log.debug( "#%3u WE: %s ADR: 0x%08x DAT: 0x%08x SEL: None IDLE: %3u" % (cnt, we, op.adr, dat, op.idle)) cnt += 1 await self._close_cycle() #do pick and mix from result- and auxiliary buffer so we get all operation and meta info for res, aux in zip(self._res_buf, self._aux_buf): res.datwr = aux.datwr res.sel = aux.sel res.adr = aux.adr res.waitIdle = aux.waitIdle res.waitStall = aux.waitStall res.waitAck -= aux.ts result.append(res) return result else: raise TestFailure( "Sorry, argument must be a list of WBOp (Wishbone Operation) objects!" ) return None
def waitScl(self): while True: if self.scl.read(): break yield RisingEdge(self.clk)
def wait(self,dut): yield RisingEdge(self.dut.clk) yield RisingEdge(self.dut.clk) yield ReadOnly()
def wait_for(clk, cycles): rising_edge = RisingEdge(clk) for _ in range(cycles): yield rising_edge raise ReturnValue(3)
def active_edge(self): yield RisingEdge(self.__clk)
def clock_two(dut): count = 0 while count != 50: yield RisingEdge(dut.clk) yield Timer(10000) count += 1
def run(self): while True: yield FallingEdge(self.clk) if (self.we.value.integer == 1 and self.rdy.value.integer == 1): self.fifo.append(self.data_in) yield RisingEdge(self.clk)
def test(dut): print "------------------------------------------- ONE -------------------------------------------" ADDR_PRETRIGGER = 0 ADDR_NUM_SAMPLES = 1 ADDR_TRIGGER_VALUE = 2 ADDR_TRIGGER_SETTINGS = 3 EDGE_POS = 0 EDGE_NEG = 1 SRC_XX = (0 << 1) SRC_CH1 = (1 << 1) SRC_CH2 = (2 << 1) SRC_EXT = (3 << 1) #dut.num_samples <= 24 # number of samples #dut.pre_trigger <= 8 # number of samples before trigger #dut.trigger_value <= 170 # trigger value ch1_data = dut.ch1_in ch2_data = dut.ch2_in ch1_rdy = dut.adc_ch1_rdy ch2_rdy = dut.adc_ch2_rdy ext_in = dut.ext_in ram_ch1 = RAM_Controller(dut.clk, dut.we, ch1_data, ch1_rdy) ram_ch2 = RAM_Controller(dut.clk, dut.we, ch2_data, ch2_rdy) adc_ch1 = ADC(dut.clk, ch1_data, ch1_rdy) adc_ch2 = ADC(dut.clk, ch2_data, ch2_rdy) tx_protocol = TX_PROTOCOL(dut.clk, dut.rqst_trigger_status, dut.trigger_status_data, dut.trigger_status_rdy, dut.trigger_status_eof, dut.trigger_status_ack) si_reg_master = SI_REG_MASTER(dut.clk, dut.rst, dut.register_data, dut.register_addr, dut.register_rdy) rqst_handler = RQST_HANDLER(dut.clk, dut.start, dut.stop, dut.rqst_trigger_status) si_reg_master.writeReg(ADDR_PRETRIGGER, 8) si_reg_master.writeReg(ADDR_NUM_SAMPLES, 24) si_reg_master.writeReg(ADDR_TRIGGER_VALUE, 170) si_reg_master.writeReg(ADDR_TRIGGER_SETTINGS, SRC_CH1 | EDGE_POS) for t in range(200): x1 = 128 + int(100 * sin(2 * pi * 1e6 * t * 20e-9)) x2 = 128 - int(050 * sin(2 * pi * 1e6 * t * 20e-9)) adc_ch1.write(x1) adc_ch2.write(x2) cocotb.fork(Clock(dut.clk, 10, units='ns').start()) yield Reset(dut) cocotb.fork(ram_ch1.run()) cocotb.fork(ram_ch2.run()) cocotb.fork(adc_ch1.sampling()) cocotb.fork(adc_ch2.sampling()) cocotb.fork(si_reg_master.driver()) # cocotb.fork( () ) # cocotb.fork( () ) # cocotb.fork( () ) # cocotb.fork( () ) # cocotb.fork( () ) for i in range(10): yield RisingEdge(dut.clk) yield rqst_handler.rqst_start() for i in range(500): yield RisingEdge(dut.clk) yield rqst_handler.rqst_stop() yield tx_protocol.request_data() for i in range(500): yield RisingEdge(dut.clk) print "-----------------------------------------" print "LEN fifo Tx_Protocol = " + repr(len(tx_protocol.fifo)) for i in range(len(tx_protocol.fifo)): print "Fifo Read: " + repr(tx_protocol.fifo.pop(0)) print "-----------------------------------------" print "LEN fifo Ram CH1 = " + repr(len(ram_ch1.fifo)) #for i in range(len(ram_ch1.fifo)): # print "Fifo Read: " + repr(ram_ch1.fifo.pop(0)) print "-----------------------------------------" print "LEN fifo Ram CH2 = " + repr(len(ram_ch2.fifo)) #for i in range(len(ram_ch2.fifo)): # print "Fifo Read: " + repr(ram_ch2.fifo.pop(0)) print "I'm at the end"
def read_fifo(dut): """This coroutine performs a read of the FIFO and returns a value""" dut.rd = 1 yield RisingEdge(dut.clk) yield ReadOnly() # Wait until all events have executed for this timestep raise ReturnValue(int(dut.dout.value)) # Read back the value
def trigger(self,dut): yield RisingEdge(self.dut.clk) dut.command_scalar_multiplication.value=1 yield RisingEdge(self.dut.clk) dut.command_scalar_multiplication.value=0 yield ReadOnly()
def test_dsp(dut): cocotb.fork(Clock(dut.clockdsp, 1, units='ns').start()) yield reset(dut) yield Timer(10, units='ns') dut.step_mu <= 4 # 0,1,4,16 N = 1000 dut.rf_enables_module <= 1 fir_output = np.zeros(N, dtype=int) err_output = np.zeros(N, dtype=int) coefs_out = np.zeros((N, 7), dtype=int) fir_input_prbs = np.convolve(np.random.choice([128, -128], (N)), channel[ch_sel], mode='same') fir_input_pulse = np.concatenate((np.ones(50) * 128, np.ones(50) * -128)) for i, val in enumerate(fir_input_prbs.astype('int')): dut.connect_ch_to_dsp <= val yield RisingEdge(dut.clockdsp) fir_output[i] = dut.ffe_inst.o_data.value.signed_integer err_output[i] = dut.error.value.signed_integer for k in range(7): coefs_out[i, k] = dut.ffe_inst.coefs[k].value.signed_integer # test read_values yield Timer(10, units='ns') plt.figure() plt.plot(np.where(fir_input_prbs == 128, 128, -128)) plt.plot(fir_output) plt.figure() plt.plot(err_output) plt.figure() plt.subplot(2, 1, 1) plt.stem(fir_output[0:200]) plt.grid() plt.ylim((np.min(fir_output) - 0.5, np.max(fir_output) + 0.5)) plt.ylabel('Amplitude') plt.xlabel('Samples') plt.title('FFE Output and Error - HW') plt.subplot(2, 1, 2) plt.plot(err_output) plt.grid() plt.ylim((np.min(err_output) - 0.5, np.max(err_output) + 0.5)) plt.ylabel('Amplitude') plt.xlabel('Samples') plt.figure() plt.subplot(3, 1, 1) plt.plot(coefs_out) plt.grid() plt.ylim((min(coefs_out[len(coefs_out) - 1]) - 12, max(coefs_out[len(coefs_out) - 1]) + 12)) plt.ylabel('Amplitude') plt.title('Taps of FFE') plt.subplot(3, 1, 2) plt.stem(coefs_out[len(coefs_out) - 1]) plt.grid() plt.ylim((min(coefs_out[len(coefs_out) - 1]) - 0.5, max(coefs_out[len(coefs_out) - 1]) + 0.5)) plt.ylabel('Amplitude') plt.subplot(3, 1, 3) plt.stem(np.convolve(channel[ch_sel], coefs_out[len(coefs_out) - 1])) plt.grid() plt.ylim((min(coefs_out[len(coefs_out) - 1]) - 0.5, max(coefs_out[len(coefs_out) - 1]) + 0.5)) plt.ylabel('Conv.Ch.Taps') plt.xlabel('Samples') plt.show(block=True) plt.close()
def start(self,dut): yield RisingEdge(self.dut.clk) dut.start_operation.value=1 yield RisingEdge(self.dut.clk) dut.start_operation.value=0 yield ReadOnly()
def do_test_afterdelay_in_readonly(dut, delay): global exited yield RisingEdge(dut.clk) yield ReadOnly() yield Timer(delay) exited = True
def interupt(self,dut): while not dut.interupt_scalar_mul.value: yield RisingEdge(self.dut.clk)
async def _run_pause(self): clock_edge_event = RisingEdge(self.clock) for val in self._pause_generator: self.pause = val await clock_edge_event
def rx_data_to_ad9361( self, i_data, q_data, i_data2=None, q_data2=None, binaryRepresentation=BinaryRepresentation.TWOS_COMPLEMENT): i_bin_val = BinaryValue(bits=12, bigEndian=False, binaryRepresentation=binaryRepresentation) q_bin_val = BinaryValue(bits=12, bigEndian=False, binaryRepresentation=binaryRepresentation) index = 0 if i_data2 is None and q_data2 is None: while True: yield RisingEdge(self.dut.rx_clk_in_p) if self.rx_frame_asserted: self.dut.rx_data_in_p <= i_bin_val[5:0] self.dut.rx_data_in_n <= ~i_bin_val[5:0] self.rx_frame_asserted = False self.dut.rx_frame_in_p <= 0 self.dut.rx_frame_in_n <= 1 else: if index < len(i_data): i_bin_val.set_value(i_data[index]) q_bin_val.set_value(q_data[index]) index += 1 else: return self.dut.rx_data_in_p <= i_bin_val[11:6] self.dut.rx_data_in_n <= ~i_bin_val[11:6] self.rx_frame_asserted = True self.dut.rx_frame_in_p <= 1 self.dut.rx_frame_in_n <= 0 yield RisingEdge(self.dut.rx_clk_in_n) if self.rx_frame_asserted: self.dut.rx_data_in_p <= q_bin_val[11:6] self.dut.rx_data_in_n <= ~q_bin_val[11:6] else: self.dut.rx_data_in_p <= q_bin_val[5:0] self.dut.rx_data_in_n <= ~q_bin_val[5:0] else: I_SEND_HIGH = True Q_SEND_HIGH = True channel = 1 while True: yield RisingEdge(self.dut.rx_clk_in_p) if I_SEND_HIGH: self.dut.rx_data_in_p <= i_bin_val[11:6] self.dut.rx_data_in_n <= ~i_bin_val[11:6] I_SEND_HIGH = False if channel == 1: self.dut.rx_frame_in_p <= 1 self.dut.rx_frame_in_n <= 0 elif channel == 2: self.dut.rx_frame_in_p <= 0 self.dut.rx_frame_in_n <= 1 else: self.dut.rx_data_in_p <= i_bin_val[5:0] self.dut.rx_data_in_n <= ~i_bin_val[5:0] I_SEND_HIGH = True yield RisingEdge(self.dut.rx_clk_in_n) if Q_SEND_HIGH: self.dut.rx_data_in_p <= q_bin_val[5:0] self.dut.rx_data_in_n <= ~q_bin_val[5:0] Q_SEND_HIGH = False else: self.dut.rx_data_in_p <= q_bin_val[11:6] self.dut.rx_data_in_n <= ~q_bin_val[11:6] Q_SEND_HIGH = True if index < len(i_data): if channel == 1: i_bin_val.set_value(i_data[index]) q_bin_val.set_value(q_data[index]) channel = 2 elif channel == 2: i_bin_val.set_value(i_data2[index]) q_bin_val.set_value(q_data2[index]) channel = 1 index += 1 else: return
def _respond(self): """Coroutine to respond to the actual requests.""" edge = RisingEdge(self.clock) while True: yield edge self._do_response() yield ReadOnly() if self._readable and self.bus.read.value: if not self._burstread: self._pad() addr = self.bus.address.value.integer if addr not in self._mem: self.log.warning( "Attempt to read from uninitialized " "address 0x%x", addr) self._responses.append(True) else: self.log.debug("Read from address 0x%x returning 0x%x", addr, self._mem[addr]) self._responses.append(self._mem[addr]) else: addr = self.bus.address.value.integer if addr % self.dataByteSize != 0: self.log.error( "Address must be aligned to data width" + "(addr = " + hex(addr) + ", width = " + str(self._width)) addr = int(addr / self.dataByteSize) burstcount = self.bus.burstcount.value.integer byteenable = self.bus.byteenable.value if byteenable != int("1" * len(self.bus.byteenable), 2): self.log.error("Only full word access is supported " + "for burst read (byteenable must be " + "0b" + "1" * len(self.bus.byteenable) + ")") if burstcount == 0: self.log.error("Burstcount must be 1 at least") # toggle waitrequest # TODO: configure waitrequest time with Avalon properties yield NextTimeStep() # can't write during read-only phase self.bus.waitrequest <= 1 yield edge yield edge self.bus.waitrequest <= 0 # wait for read data for i in range(self._avalon_properties["readLatency"]): yield edge for count in range(burstcount): if (addr + count) * self.dataByteSize not in self._mem: self.log.warning( "Attempt to burst read from uninitialized " "address 0x%x (addr 0x%x count 0x%x)", (addr + count) * self.dataByteSize, addr, count) self._responses.append(True) else: value = 0 for i in range(self.dataByteSize): rvalue = self._mem[(addr + count) * self.dataByteSize + i] value += rvalue << i * 8 self.log.debug( "Read from address 0x%x returning 0x%x", (addr + count) * self.dataByteSize, value) self._responses.append(value) yield edge self._do_response() if self._writeable and self.bus.write.value: if not self._burstwrite: addr = self.bus.address.value.integer data = self.bus.writedata.value.integer if hasattr(self.bus, "byteenable"): byteenable = int(self.bus.byteenable.value) mask = 0 oldmask = 0 olddata = 0 if addr in self._mem: olddata = self._mem[addr] self.log.debug("Old Data : %x", olddata) self.log.debug("Data in : %x", data) self.log.debug("Width : %d", self._width) self.log.debug("Byteenable: %x", byteenable) for i in range(self._width // 8): if byteenable & 2**i: mask |= 0xFF << (8 * i) else: oldmask |= 0xFF << (8 * i) self.log.debug("Data mask : %x", mask) self.log.debug("Old mask : %x", oldmask) data = (data & mask) | (olddata & oldmask) self.log.debug("Data out : %x", data) self.log.debug("Write to address 0x%x -> 0x%x", addr, data) self._mem[addr] = data else: self.log.debug("writing burst") # maintain waitrequest high randomly yield self._waitrequest() addr, byteenable, burstcount = self._write_burst_addr() for count in range(burstcount): while self.bus.write.value == 0: yield NextTimeStep() # self._mem is aligned on 8 bits words yield self._writing_byte_value(addr + count * self.dataByteSize) self.log.debug("writing %016X @ %08X", self.bus.writedata.value.integer, addr + count * self.dataByteSize) yield edge # generate waitrequest randomly yield self._waitrequest() if self._avalon_properties.get("WriteBurstWaitReq", True): self.bus.waitrequest <= 1
def _monitor_recv(self): """Watch the pins and reconstruct transactions.""" yield self._init_done.wait() # Avoid spurious object creation by recycling clkedge = RisingEdge(self.clock) rdonly = ReadOnly() class _dummy(): def __init__(self, value): self.value = value tlast = getattr(self.bus, 'tlast', None) tready = getattr(self.bus, 'tready', _dummy(BinaryValue('1'))) tkeep = getattr(self.bus, 'tkeep', _dummy(BinaryValue("1" * self._n_bytes))) tstrb = getattr(self.bus, 'tstrb', tkeep) tdata = getattr(self.bus, 'tdata', None) tid = getattr(self.bus, 'tid', None) tdest = getattr(self.bus, 'tdest', None) tuser = getattr(self.bus, 'tuser', None) tvalid = self.bus.tvalid packet_buf = {} while True: yield clkedge yield rdonly if self.in_reset: if packet_buf: self.log.warning( "Discarding unfinished packet(s) as the bus is in reset" ) packet_buf = {} continue if int(tvalid) and int(tready): if self._lsb_first: byte_range = range(self._n_bytes - 1, -1, -1) else: byte_range = range(self._n_bytes) filtered_data = [] filtered_user = [] for b in byte_range: byte_type = resolve(tkeep.value.binstr[b] + tstrb.value.binstr[b]) if byte_type == "11": # data byte if tdata: filtered_data.append( int( resolve(tdata.value.binstr[b * 8:(b + 1) * 8]), 2)) if tuser and self._tuser_bytewise: filtered_user.append( int( resolve( tuser.value.binstr[b * self._user_bits: (b + 1) * self._user_bits]), 2)) elif byte_type == "10": # position byte if tdata: filtered_data.append(0) if tuser and self._tuser_bytewise: filtered_user.append(0) elif byte_type == "01": raise AXIS_ProtocolError( "Invald combination of TKEEP and TSTRB byte qualifiers" ) else: # null byte pass stream_id = (int(tid) if tid else None, int(tdest) if tdest else None) if not tlast or int(tlast): recv_pkt = {} try: if tdata: recv_pkt["data"] = b"".join( packet_buf[stream_id]["data"]) + bytes( filtered_data) if tuser: if self._tuser_bytewise: recv_pkt["user"] = packet_buf[stream_id][ "user"] + filtered_user else: recv_pkt["user"] = resolve(tuser.value.binstr) if tid: recv_pkt["tid"] = int(tid) if tdest: recv_pkt["tdest"] = int(tdest) self._recv(recv_pkt) del packet_buf[stream_id] except KeyError: # No buffered data if tdata: recv_pkt["data"] = bytes(filtered_data) if tuser: if self._tuser_bytewise: recv_pkt["user"] = filtered_user else: recv_pkt["user"] = resolve(tuser.value.binstr) if tid: recv_pkt["tid"] = int(tid) if tdest: recv_pkt["tdest"] = int(tdest) else: try: if tdata: packet_buf[stream_id]["data"].append( bytes(filtered_data)) if tuser and self._tuser_bytewise: packet_buf[stream_id]["user"].extend(filtered_user) except KeyError: packet_buf[stream_id] = {} if tdata: packet_buf[stream_id]["data"] = [ bytes(filtered_data) ] if tuser and self._tuser_bytewise: packet_buf[stream_id]["user"] = filtered_user
def socket_test(dut, debug=False): """Testcase that uses a socket to drive the DUT""" host = os.getenv("SIMULATION_HOST", 'localhost') port = os.getenv("SIMULATION_PORT", '12345') if debug: dut._log.setLevel(logging.DEBUG) bus = get_bus()(dut) dut._log.info("Using bus driver : %s" % (type(bus).__name__)) sim_modules = [] sim_modules_data = os.getenv("SIMULATION_MODULES", "") if sim_modules_data: sim_modules_yml = yaml.load(sim_modules_data) for mod in sim_modules_yml: mod_import = import_driver(mod) kargs = dict(sim_modules_yml[mod]) sim_modules.append(mod_import(dut, **kargs)) dut._log.info("Using simulation modules : %s arguments: %s" % (mod, kargs)) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, int(port))) s.listen(1) # start sim_modules for mod in sim_modules: cocotb.fork(mod.run()) yield bus.init() while True: dut._log.info("Waiting for incoming connection on %s:%d" % (host, int(port))) client, sockname = s.accept() dut._log.info("New connection from %s:%d" % (sockname[0], sockname[1])) iface = PickleInterface(client) while True: # uncomment for constantly advancing clock # yield RisingEdge(bus.clock) try: req = iface.try_recv() except EOFError: dut._log.info("Remote client closed the connection") client.close() break if req is None: continue dut._log.debug("Received: %s" % str(req)) # add few clocks for _ in range(10): yield RisingEdge(bus.clock) if isinstance(req, WriteRequest): yield bus.write(req.address, req.data) elif isinstance(req, ReadRequest): result = yield bus.read(req.address, req.size) resp = ReadResponse(result) dut._log.debug("Send: %s" % str(resp)) iface.send(resp) else: raise NotImplementedError("Unsupported request type: %s" % str(type(req))) # add few clocks for _ in range(10): yield RisingEdge(bus.clock) if(os.getenv("SIMULATION_END_ON_DISCONNECT")): break
def _send_bytes(self, bytestr, padZero=False, tid=None, tdest=None, tuser=None): """Send a byte-like object on the AXI stream Args: bytestr (byte-like): data to be sent padZero (boolean): pad the data stream with zero bits instead of 'X' tid: tdest: tuser: """ if padZero: padstr = "00000000" else: padstr = "XXXXXXXX" bytestr = bytes(bytestr) for offset in range(0, len(bytestr), self._n_bytes): if offset + self._n_bytes < len(bytestr): last_word = 0 padbytes = 0 else: last_word = 1 padbytes = offset + self._n_bytes - len(bytestr) if not self.on: self.bus.tdata <= BinaryValue(padstr * self._n_bytes) self.bus.tvalid <= 0 for _ in range(self.off): yield RisingEdge(self.clock) self._next_valids() # Consume a valid cycle if self.on is not True and self.on: self.on -= 1 self.bus.tvalid <= 1 if hasattr(self.bus, 'tlast'): self.bus.tlast <= last_word bytelist = list(bytestr[offset:offset + self._n_bytes]) if self._lsb_first: bytelist.reverse() binstr = ''.join(map(lambda b: "{:08b}".format(b), bytelist)) if padbytes: if self._lsb_first: binstr = padstr * padbytes + binstr keepstr = "0" * padbytes + "1" * (self._n_bytes - padbytes) else: binstr = binstr + padstr * padbytes keepstr = "1" * (self._n_bytes - padbytes) + "0" * padbytes else: keepstr = "1" * self._n_bytes self.bus.tdata <= BinaryValue(binstr) if hasattr(self.bus, 'tkeep'): self.bus.tkeep <= BinaryValue(keepstr) if hasattr(self.bus, 'tstrb'): self.bus.tstrb <= BinaryValue(keepstr) yield RisingEdge(self.clock) if hasattr(self.bus, 'tready'): # other drivers wait for ReadOnly here; I don't understand why while not int(self.bus.tready): yield RisingEdge(self.clock) self._idle_outputs()
def reset(dut): dut.rst_i <= 1 yield RisingEdge(dut.clk_i) dut.rst_i <= 0
def reset_fifo(dut): """This coroutine performs reset to FIFO""" yield RisingEdge(dut.clk) dut.rst = 1 yield RisingEdge(dut.clk) dut.rst = 0
def do_test_readwrite_in_readonly(dut): global exited yield RisingEdge(dut.clk) yield ReadOnly() yield ReadWrite() exited = True
def rqst_trigger_status(self): self.rqst_trigger_status <= 1 yield RisingEdge(self.clk) self.rqst_trigger_status <= 0 yield RisingEdge(self.clk)