docs: def _compile_device_specific_prims(self, debug=False,
                                         stages=None, stagenames=None):
          """Using the data stored in the CommandQueue, Extract and align compatible sequences of Primitives and compile/optimize the Primitives down into a stream of Level 2 device agnostic primitives.
  
          BACKGROUND:
          Device Specific primitives present a special opportunity for
          optimization. Many JTAG systems program one device on the
          chain at a time. But because all devices on a JTAG chain are
          sent information at once, NO-OP instructions are sent to these
          other devices.
  
          When programming multiple devices, Sending these NO-OPS is a
          missed opportunity for optimization. Instead of configuring
          one device at a time, it is more efficient to collect
          instructions for all deices, and align them so multiple
          devices can be configured at the same time.
  
          WAT THIS METHOD DOES:
          This method takes in a list of Primitives, groups the device
          specific primitives by target device, aligns the sequences of
          device instructions, and expands the aligned sequences into a
          flat list of device agnostic primitives.
  
          Args:
              debug: A boolean for if debug information should be generated.
              stages: A list to be edited by this method to store snapshots of the compilation state. Used if debug is True.
              stagenames: A list of strings describing each debug snapshot of the compiilation process. Used if debug is True.
  
          """
          ############### GROUPING BY EXEC BOUNDARIES!################
  
          fences = []
          fence = [self[0]]
          for p in self[1:]:
              if type(fence[0])._layer == type(p)._layer and\
                 isinstance(fence[0], DeviceTarget) == \
                    isinstance(p, DeviceTarget):
                  fence.append(p)
              else:
                  fences.append(fence)
                  fence = [p]
          fences.append(fence)
  
          if debug: #pragma: no cover
              formatted_fences = []
              for fence in fences:
                  formatted_fence = [p.snapshot() for p in fence]
                  formatted_fences.append(formatted_fence)
                  formatted_fences.append([])
              stages.append(formatted_fences[:-1]) #Ignore trailing []
              stagenames.append("Fencing off execution boundaries")
  
          ############## SPLIT GROUPS BY DEVICE TARGET! ##############
  
          split_fences = []
          for fence in fences:
              tmp_chains = {}
              for p in fence:
                  k = p._device_index \
                      if isinstance(p, DeviceTarget) else "chain"
                  subchain = tmp_chains.setdefault(k, []).append(p)
              split_fences.append(list(tmp_chains.values()))
  
          if debug:#pragma: no cover
              formatted_split_fences = []
              for fence in split_fences:
                  for group in fence:
                      formatted_split_fences.append([p.snapshot()
                                                     for p in group])
                  formatted_split_fences.append([])
              stages.append(formatted_split_fences[:-1])
              stagenames.append("Grouping prims of each boundary by "
                                "target device")
  
          ############## ALIGN SEQUENCES AND PAD FRAMES ##############
          #FIRST DEV REQUIRED LINE
          grouped_fences = [
              FrameSequence(self._chain, *fence).finalize()
              for f_i, fence in enumerate(split_fences)
          ]
  
          if debug:#pragma: no cover
              formatted_grouped_fences = []
              for fence in grouped_fences:
                  formatted_grouped_fences += fence.snapshot() + [[]]
              stages.append(formatted_grouped_fences[:-1])
              stagenames.append("Aligning and combining each group dev "
                                "prim stream")
  
          ################## RECOMBINE FRAME GROUPS ##################
  
          ingested_chain = grouped_fences[0]
          for fence in grouped_fences[1:]:
              ingested_chain += fence
  
          if debug:#pragma: no cover
              stages.append(ingested_chain.snapshot())
              stagenames.append("Recombining sanitized exec boundaries")
  
          ###################### POST INGESTION ######################
          ################ Flatten out LV3 Primitives ################
          while(any((f._layer == 3 for f in ingested_chain))):
              ################# COMBINE COMPATIBLE PRIMS #################
              ingested_chain = _merge_prims(ingested_chain)
  
              if debug:#pragma: no cover
                  stages.append(ingested_chain.snapshot())
                  stagenames.append("Combining compatible lv3 prims.")
  
              ################ TRANSLATION TO LOWER LAYER ################
              sm = JTAGStateMachine(self._chain._sm.state)
              expanded_prims = FrameSequence(self._chain)
              for f in ingested_chain:
                  if f._layer == 3:
                      expanded_prims += f.expand_macro(sm)
                  else:
                      expanded_prims.append(f)
              expanded_prims.finalize()
              ingested_chain = expanded_prims
  
              if self._fsm is None:
                  self._fsm = sm
              assert self._fsm == sm, "Target %s != Actual %s"%\
                  (self._fsm.state, sm.state)
  
              if debug:#pragma: no cover
                  stages.append(ingested_chain.snapshot())
                  stagenames.append("Expanding lv3 prims")
  
  
          ############## Flatten out Dev LV2 Primitives ##############
          while(any((isinstance(f._valid_prim, DeviceTarget)
                     for f in ingested_chain))):
              ################# COMBINE COMPATIBLE PRIMS #################
              ingested_chain = _merge_prims(ingested_chain)
  
              if debug:#pragma: no cover
                  stages.append(ingested_chain.snapshot())
                  stagenames.append("Merging Device Specific Prims")
  
              ################ TRANSLATION TO LOWER LAYER ################
  
              sm = JTAGStateMachine(self._chain._sm.state)
              expanded_prims = FrameSequence(self._chain)
              for f in ingested_chain:
                  if issubclass(f._prim_type, DeviceTarget):
                      expanded_prims += f.expand_macro(sm)
                  else:
                      f[0].apply_tap_effect(sm)
                      expanded_prims.append(f)
              expanded_prims.finalize()
              ingested_chain = expanded_prims
              if self._fsm is None:
                  self._fsm = sm
              assert self._fsm == sm, "Target %s != Actual %s"%\
                   (self._fsm.state, sm.state)
  
              if debug:#pragma: no cover
                  stages.append(ingested_chain.snapshot())
                  stagenames.append("Expanding Device Specific Prims")
  
          ############ Convert FrameSequence to flat array ###########
          flattened_prims = [f._valid_prim for f in ingested_chain]
          if debug:#pragma: no cover
              stages.append([[p.snapshot() for p in flattened_prims]])
              stagenames.append("Converting format to single stream.")
  
          return flattened_prims