* i came up with this sketch: ``` class _JTAGCommand(enum.Enum): ShiftTMS = 0 ... class JTAGComponent(wiring.Component): ctrl: wiring.Signature({ "i": In(stream.Signature(8)), "o": Out(stream.Signature(8)) }) def __init__(self, ports, frequency): self._ports = ports self._frequency = frequency super().__init__() def elaborate(self, platform): m = Module() m.submodules.tck_buffer = tck_buffer = io.Buffer("o", self._ports.tck) ... class JTAGInterface: def __init__(self, fifo): self._fifo = fifo async def shift_tms(self, tms): await self._fifo.write([_JTAGCommand.ShiftTMS, tms]) ... class JTAGApplet: # these annotations stand in for a configuration schema that could be used for defining # CLI options or used programmatically pin_tck: Pin(1, bank="JTAG") pin_tms: Pin(1) frequency: float def __init__(self, orchi, pin_tck, pin_tms, frequency): # allocate physical pins and get io.PortLikes out of them ports = orchi.get_ports(tck=pin_tck, tms=pin_tms) # adds the gateware to the set of all gateware to include component = orchi.add_component(JTAGComponent(ports, frequency)) # creates an inactive FIFO handle that wouldn't do anything until a `perform()` call self.iface = JTAGInterface(orchi.get_fifo(component.ctrl)) # create a design for this run orchi = GlasgowOrchestrator() applet = JTAGApplet(orchi) # build and load a bitstream orchi.perform() # interact with the applet applet.iface.shift_tms(0b11111) ```