def set_response(self, ep, response): if (EndpointType.epdir(ep) == EndpointType.IN and response == EndpointResponse.ACK): yield self.write(self.csrs['usb_in_ctrl'], EndpointType.epnum(ep)) elif (EndpointType.epdir(ep) == EndpointType.OUT and response == EndpointResponse.ACK): yield self.write(self.csrs['usb_out_ctrl'], 0x10 | EndpointType.epnum(ep))
def transaction_data_in(self, addr, ep, data, chunk_size=None): epnum = EndpointType.epnum(ep) datax = PID.DATA1 sent_data = 0 if chunk_size is None: chunk_size = self.max_packet_size for i, chunk in enumerate(grouper_tofit(chunk_size, data)): # Do we still have time? current = get_sim_time("us") if current > self.request_deadline: raise TestFailure("Failed to get all data in time") self.dut._log.debug("Expecting chunk {}".format(i)) self.packet_deadline = current + 5e2 # 500 ms sent_data = 1 self.dut._log.debug( "Actual data we're expecting: {}".format(chunk)) recv = cocotb.fork(self.host_recv(datax, addr, epnum, chunk)) yield recv.join() if datax == PID.DATA0: datax = PID.DATA1 else: datax = PID.DATA0 if not sent_data: recv = cocotb.fork(self.host_recv(datax, addr, epnum, [])) yield recv.join()
def transaction_data_in(self, addr, ep, data, chunk_size=64, datax=PID.DATA1): epnum = EndpointType.epnum(ep) sent_data = 0 for i, chunk in enumerate(grouper_tofit(chunk_size, data)): # Do we still have time? current = get_sim_time("us") if current > self.request_deadline: raise TestFailure("Failed to get all data in time") self.dut._log.debug("Expecting chunk {}".format(i)) self.packet_deadline = current + 5e2 # 500 ms sent_data = 1 self.dut._log.debug( "Actual data we're expecting: {}".format(chunk)) for b in chunk: yield self.write(self.csrs['usb_in_data'], b) yield self.write(self.csrs['usb_in_ctrl'], epnum) recv = cocotb.fork(self.host_recv(datax, addr, epnum, chunk)) yield recv.join() if datax == PID.DATA0: datax = PID.DATA1 else: datax = PID.DATA0 if not sent_data: yield self.write(self.csrs['usb_in_ctrl'], epnum) recv = cocotb.fork(self.host_recv(datax, addr, epnum, [])) yield self.send_data(datax, epnum, data) yield recv.join()
def transaction_data_out(self, addr, ep, data, chunk_size=64, expected=PID.ACK, datax=PID.DATA1): epnum = EndpointType.epnum(ep) # # Set it up so we ACK the final IN packet # yield self.write(self.csrs['usb_in_ctrl'], 0) for _i, chunk in enumerate(grouper_tofit(chunk_size, data)): self.dut._log.warning("Sending {} bytes to host".format( len(chunk))) self.packet_deadline = get_sim_time("us") + super().MAX_PACKET_TIME # Enable receiving data yield self.set_response(ep, EndpointResponse.ACK) xmit = cocotb.fork( self.host_send(datax, addr, epnum, chunk, expected)) yield self.expect_data(epnum, list(chunk), expected) yield xmit.join() if datax == PID.DATA0: datax = PID.DATA1 else: datax = PID.DATA0
def pending(self, ep): if EndpointType.epdir(ep) == EndpointType.IN: val = yield self.read(self.csrs['usb_in_status']) raise ReturnValue(val & (1 << 4)) else: val = yield self.read(self.csrs['usb_out_status']) raise ReturnValue((val & (1 << 5) | (1 << 4)) and (EndpointType.epnum(ep) == (val & 0x0f)))
def test_in_transfer(dut): harness = get_harness(dut) yield harness.reset() yield harness.connect() addr = 0 epaddr = EndpointType.epaddr(1, EndpointType.IN) yield harness.write(harness.csrs['usb_address'], addr) d = [0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8] yield harness.clear_pending(epaddr) yield RisingEdge(harness.dut.clk12) yield RisingEdge(harness.dut.clk12) yield harness.set_response(epaddr, EndpointResponse.NAK) yield harness.set_data(epaddr, d[:4]) yield harness.set_response(epaddr, EndpointResponse.ACK) yield harness.host_send_token_packet(PID.IN, addr, EndpointType.epnum(epaddr)) yield harness.host_expect_data_packet(PID.DATA0, d[:4]) yield harness.host_send_ack() pending = yield harness.pending(epaddr) if pending: raise TestFailure("data was still pending") # need to wait 3 clk12 cycles after packet received for # rx packet machine to reset yield RisingEdge(harness.dut.clk12) yield RisingEdge(harness.dut.clk12) yield RisingEdge(harness.dut.clk12) yield harness.set_data(epaddr, d[4:]) yield harness.set_response(epaddr, EndpointResponse.ACK) yield harness.host_send_token_packet(PID.IN, addr, EndpointType.epnum(epaddr)) yield harness.host_expect_data_packet(PID.DATA1, d[4:]) yield harness.host_send_ack()
def test_sof_is_ignored(dut): harness = get_harness(dut) harness.max_packet_size = model.deviceDescriptor.bMaxPacketSize0 yield harness.reset() yield harness.wait(1e3, units="us") yield harness.port_reset(10e3) yield harness.connect() yield harness.wait(1e3, units="us") # After waiting (bus inactivity) let's start with SOF yield harness.host_send_sof(0x01) DEVICE_ADDRESS = 0x20 epaddr_out = EndpointType.epaddr(0, EndpointType.OUT) yield harness.set_device_address(DEVICE_ADDRESS) data = getDescriptorRequest(descriptor_type=Descriptor.Types.STRING, descriptor_index=0, lang_id=0, length=10) # Send SOF packet yield harness.host_send_sof(2) # Setup stage # ------------------------------------------ # Send SETUP packet yield harness.host_send_token_packet(PID.SETUP, DEVICE_ADDRESS, EndpointType.epnum(epaddr_out)) harness.request_deadline = get_sim_time("us") + harness.MAX_REQUEST_TIME # Send another SOF packet yield harness.host_send_sof(3) # Data stage # ------------------------------------------ # Send DATA packet harness.packet_deadline = get_sim_time("us") + harness.MAX_PACKET_TIME yield harness.host_send_data_packet(PID.DATA1, data) yield harness.host_expect_ack() # Send another SOF packet yield harness.host_send_sof(4) # # Status stage # # ------------------------------------------ harness.packet_deadline = get_sim_time("us") + harness.MAX_PACKET_TIME yield harness.transaction_status_out(DEVICE_ADDRESS, epaddr_out)
def send_setup_and_sof(): # Send SOF packet yield harness.host_send_sof(2) # Setup stage # ------------------------------------------ # Send SETUP packet yield harness.host_send_token_packet(PID.SETUP, addr, EndpointType.epnum(epaddr_out)) # Send another SOF packet yield harness.host_send_sof(3) # Data stage # ------------------------------------------ # Send DATA packet yield harness.host_send_data_packet(PID.DATA1, data) yield harness.host_expect_ack() # Send another SOF packet yield harness.host_send_sof(4)
def transaction_status_out(self, addr, ep): epnum = EndpointType.epnum(ep) assert EndpointType.epdir(ep) == EndpointType.OUT xmit = cocotb.fork(self.host_send(PID.DATA1, addr, epnum, [])) yield xmit.join()
def print_ep(self, epaddr, msg, *args): self.dut._log.info("ep(%i, %s): %s" % (EndpointType.epnum(epaddr), EndpointType.epdir(epaddr).name, msg) % args)
def send_data(self, token, ep, data): for b in data: yield self.write(self.csrs['usb_in_data'], b) yield self.write(self.csrs['usb_in_ctrl'], EndpointType.epnum(ep) & 0x0f)