.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/extended/plot_flatten.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_extended_plot_flatten.py: ===================================== Flatten A Netlist ===================================== Remove hierarchy from a netlist. The original hierarchy and new hierarchy (after flattening) will be printed. .. GENERATED FROM PYTHON SOURCE LINES 8-190 .. rst-class:: sphx-glr-script-out .. code-block:: none Need to move cells from a0 that references a Need to move cells from b0 that references b Need to move cells from c0 that references c Finished moving cells from c0 Need to move cells from c1 that references c Finished moving cells from c1 Need to move cells from c2 that references c Finished moving cells from c2 Finished moving cells from b0 Need to move cells from b1 that references b Finished moving cells from b1 Need to move cells from b2 that references b Finished moving cells from b2 Finished moving cells from a0 Need to move cells from a1 that references a Finished moving cells from a1 Need to move cells from a2 that references a Finished moving cells from a2 ORIGINAL HIERARCHY top a0 b0 c0 beta_INST_0 c1 beta_INST_0 c2 beta_INST_0 delta_INST_0 b1 c0 beta_INST_0 c1 beta_INST_0 c2 beta_INST_0 delta_INST_0 b2 c0 beta_INST_0 c1 beta_INST_0 c2 beta_INST_0 delta_INST_0 zeta_INST_0 a1 b0 c0 beta_INST_0 c1 beta_INST_0 c2 beta_INST_0 delta_INST_0 b1 c0 beta_INST_0 c1 beta_INST_0 c2 beta_INST_0 delta_INST_0 b2 c0 beta_INST_0 c1 beta_INST_0 c2 beta_INST_0 delta_INST_0 zeta_INST_0 a2 b0 c0 beta_INST_0 c1 beta_INST_0 c2 beta_INST_0 delta_INST_0 b1 c0 beta_INST_0 c1 beta_INST_0 c2 beta_INST_0 delta_INST_0 b2 c0 beta_INST_0 c1 beta_INST_0 c2 beta_INST_0 delta_INST_0 zeta_INST_0 eta_IBUF[0]_inst eta_IBUF[10]_inst eta_IBUF[11]_inst eta_IBUF[12]_inst eta_IBUF[13]_inst eta_IBUF[14]_inst eta_IBUF[15]_inst eta_IBUF[16]_inst eta_IBUF[17]_inst eta_IBUF[18]_inst eta_IBUF[19]_inst eta_IBUF[1]_inst eta_IBUF[20]_inst eta_IBUF[21]_inst eta_IBUF[22]_inst eta_IBUF[23]_inst eta_IBUF[24]_inst eta_IBUF[25]_inst eta_IBUF[26]_inst eta_IBUF[27]_inst eta_IBUF[28]_inst eta_IBUF[29]_inst eta_IBUF[2]_inst eta_IBUF[30]_inst eta_IBUF[31]_inst eta_IBUF[32]_inst eta_IBUF[33]_inst eta_IBUF[34]_inst eta_IBUF[35]_inst eta_IBUF[36]_inst eta_IBUF[37]_inst eta_IBUF[38]_inst eta_IBUF[39]_inst eta_IBUF[3]_inst eta_IBUF[40]_inst eta_IBUF[41]_inst eta_IBUF[42]_inst eta_IBUF[43]_inst eta_IBUF[44]_inst eta_IBUF[45]_inst eta_IBUF[46]_inst eta_IBUF[47]_inst eta_IBUF[48]_inst eta_IBUF[49]_inst eta_IBUF[4]_inst eta_IBUF[50]_inst eta_IBUF[51]_inst eta_IBUF[52]_inst eta_IBUF[53]_inst eta_IBUF[5]_inst eta_IBUF[6]_inst eta_IBUF[7]_inst eta_IBUF[8]_inst eta_IBUF[9]_inst theta_OBUF_inst theta_OBUF_inst_i_1 HIERARCHY AFTER FLATTENING top eta_IBUF[0]_inst eta_IBUF[10]_inst eta_IBUF[11]_inst eta_IBUF[12]_inst eta_IBUF[13]_inst eta_IBUF[14]_inst eta_IBUF[15]_inst eta_IBUF[16]_inst eta_IBUF[17]_inst eta_IBUF[18]_inst eta_IBUF[19]_inst eta_IBUF[1]_inst eta_IBUF[20]_inst eta_IBUF[21]_inst eta_IBUF[22]_inst eta_IBUF[23]_inst eta_IBUF[24]_inst eta_IBUF[25]_inst eta_IBUF[26]_inst eta_IBUF[27]_inst eta_IBUF[28]_inst eta_IBUF[29]_inst eta_IBUF[2]_inst eta_IBUF[30]_inst eta_IBUF[31]_inst eta_IBUF[32]_inst eta_IBUF[33]_inst eta_IBUF[34]_inst eta_IBUF[35]_inst eta_IBUF[36]_inst eta_IBUF[37]_inst eta_IBUF[38]_inst eta_IBUF[39]_inst eta_IBUF[3]_inst eta_IBUF[40]_inst eta_IBUF[41]_inst eta_IBUF[42]_inst eta_IBUF[43]_inst eta_IBUF[44]_inst eta_IBUF[45]_inst eta_IBUF[46]_inst eta_IBUF[47]_inst eta_IBUF[48]_inst eta_IBUF[49]_inst eta_IBUF[4]_inst eta_IBUF[50]_inst eta_IBUF[51]_inst eta_IBUF[52]_inst eta_IBUF[53]_inst eta_IBUF[5]_inst eta_IBUF[6]_inst eta_IBUF[7]_inst eta_IBUF[8]_inst eta_IBUF[9]_inst theta_OBUF_inst theta_OBUF_inst_i_1 a0/b0/c0/beta_INST_0 a0/b0/c1/beta_INST_0 a0/b0/c2/beta_INST_0 a0/b0/delta_INST_0 a0/b1/delta_INST_0 a0/b1/c0/beta_INST_0 a0/b1/c1/beta_INST_0 a0/b1/c2/beta_INST_0 a0/b2/delta_INST_0 a0/b2/c0/beta_INST_0 a0/b2/c1/beta_INST_0 a0/b2/c2/beta_INST_0 a0/zeta_INST_0 a1/zeta_INST_0 a1/b0/c0/beta_INST_0 a1/b0/c1/beta_INST_0 a1/b0/c2/beta_INST_0 a1/b0/delta_INST_0 a1/b1/delta_INST_0 a1/b1/c0/beta_INST_0 a1/b1/c1/beta_INST_0 a1/b1/c2/beta_INST_0 a1/b2/delta_INST_0 a1/b2/c0/beta_INST_0 a1/b2/c1/beta_INST_0 a1/b2/c2/beta_INST_0 a2/zeta_INST_0 a2/b0/c0/beta_INST_0 a2/b0/c1/beta_INST_0 a2/b0/c2/beta_INST_0 a2/b0/delta_INST_0 a2/b1/delta_INST_0 a2/b1/c0/beta_INST_0 a2/b1/c1/beta_INST_0 a2/b1/c2/beta_INST_0 a2/b2/delta_INST_0 a2/b2/c0/beta_INST_0 a2/b2/c1/beta_INST_0 a2/b2/c2/beta_INST_0 | .. code-block:: default import tempfile import spydrnet as sdn from pathlib import Path # Check if given instance is a black box # instance: std.Instance to check # Return True if instance is a black box # (defined by no listed cables or child within child's reference), else return False def is_black_box(instance): definition = instance.reference if len(definition.cables) != 0 or len(definition.children) != 0: return False return True # Creates a copy of a instance # parent_instance: The instance that contains the instance be copy (used to keep hierarchical naming) # instance: The original instance to make the copy of # new_instance: The instance that will be the copy # Returns: None def copy_instance(parent_instance, instance, new_instance): # Copy all the data from instance into new_instance for key, value in instance.data.items(): new_instance[key] = value # Change new_instance EDIF.identifier to represent its hierarchical name new_instance['EDIF.identifier'] = parent_instance['EDIF.identifier'] + \ '_' + new_instance['EDIF.identifier'] # Determine if parent_instance and instance have .NAME in it data # Uses .NAME if available, else used EDIF.identifier to generate # .NAME for new_instance if '.NAME' in parent_instance: if '.NAME' in instance: new_instance['.NAME'] = parent_instance['.NAME'] + '/' \ + instance['.NAME'] else: new_instance['.NAME'] = parent_instance['.NAME'] + '/' \ + instance['EDIF.identifier'] else: if '.NAME' in instance: new_instance['.NAME'] = parent_instance['EDIF.identifier'] + '/' \ + instance['.NAME'] else: new_instance['.NAME'] = parent_instance['EDIF.identifier'] + '/' \ + instance['EDIF.identifier'] # Have new_instance reference the same definition as instance new_instance.reference = instance.reference # Removes a newly created cable in favor of using the cable that connected to the outside of the instance # new_cable: Cable that was connecting the new pins instance's parent # old_cable: Cable that was connecting the old pins in instance # instance: The instance that is being flatten # Return: None def use_outside_cable(new_cable, old_cable, instance): wire = None # Need to find the wire that connects to the outside of the port that old_cable does # Check each pin that old_cable is connected to to find the inside pin for the instance for pin in old_cable.wires[0].pins: if pin in instance.pins: # Get the wire that connects to the outer pin that corresponds to the found inner pin wire = instance.pins[pin].wire break # Loop through each wire in new_cable for new_wire in new_cable.wires: # Loop through is pin the wire connects to for pin in new_wire.pins: # Disconnect the new_wire from the pin and connect wire to that pin instead new_wire.disconnect_pin(pin) wire.connect_pin(pin) # Removes new_cable from the definition that holds it new_cable.definition.remove_cable(new_cable) # Remove instances that have been flatten # instance: std.Instance to be removed # Returns None def clean_up(instance): # Loop through each outside pin and disconnect it from its wire for pin in instance.pins.values(): pin.wire.disconnect_pin(pin) # Remove instances from its parent definition instance.parent.remove_child(instance) # Recursively flatten a given definition # definition: std.Definition to flatten # top_definition: Bool saying the given definition is the top definition of the IR # Returns: list of created instances def flatten_definition(definition, top_definition=False): # Create a copy of the list of children children = definition.children.copy() created = [] # Loop through each pre-existing child of the definition for child in children: leaf_grandchildren = [] child_reference = child.reference # Create a copy of the list of the children for the current child reference grandchildren = child_reference.children.copy() map = {} # Check if progress information should be printed if top_definition and not is_black_box(child): print("Need to move cells from", child['EDIF.identifier'], "that references", child.reference['EDIF.identifier']) # Loop through each grandchild of definition for grandchild in grandchildren: if not is_black_box(grandchild): print("Need to move cells from", grandchild['EDIF.identifier'], "that references", grandchild.reference['EDIF.identifier']) # Flatten any children if they contain non_leaf grandchildren # Keep track of grandchildren that are leaf nodes leaf_grandchildren.extend(flatten_definition(child.reference)) print("Finished moving cells from", grandchild['EDIF.identifier']) else: # Keep track of grandchildren that are leaf nodes leaf_grandchildren.append(grandchild) # Loop though each grandchild that is also a leaf including newly created grandchildren for grandchild in leaf_grandchildren: # Create a new child inside of definition new_instance = definition.create_child() # Copy data from the grandchild into the new instance copy_instance(child, grandchild, new_instance) # Create a key, value relationship between grandchild and new_instance map[grandchild] = new_instance # Add the new_instances to the list of created instances created.append(new_instance) # Create a list of the original cables that the child has cables = child_reference.cables.copy() for cable in cables: name_cable = True new_cable = definition.create_cable() for wire in cable.wires: new_wire = new_cable.create_wire() for pin in wire.pins: # If the pin is connected to a port of the child, we should use an outside cable instead if isinstance(pin, sdn.InnerPin): name_cable = False continue # Connect the new wire to pins on new instances that correspond pins on the original instances new_wire.connect_pin(map[pin.instance].pins[pin.inner_pin]) # Check if we should name the cable or should use the outside cable if name_cable: new_cable['EDIF.identifier'] = child['EDIF.identifier'] + \ '_' + cable['EDIF.identifier'] new_cable.name = new_cable['EDIF.identifier'] else: use_outside_cable(new_cable, cable, child) # Remove any original children that is not a leaf if not is_black_box(child): clean_up(child) # Check if progress information should be printed if top_definition and not is_black_box(child): print("Finished moving cells from", child['EDIF.identifier']) return created #print the hierarchy of a netlist def hierarchy(current_instance,indentation=""): print(indentation,current_instance.name) for child in current_instance.reference.children: hierarchy(child,indentation+" ") example_name1 = "unique_challenge" example_name2 = "three_layer_hierarchy" example_name3 = "unique_different_modules" example_name = example_name1 ir = sdn.load_example_netlist_by_name(example_name) ir_orig = sdn.load_example_netlist_by_name(example_name) #store the original netlist for display later top_def = ir.top_instance.reference flatten_definition(top_def, top_definition=True) with tempfile.TemporaryDirectory() as td: file_name = example_name + '_flat.edf' sdn.compose(ir, Path(td, file_name)) # sdn.composers.compose("test.edf", ir) print() print("ORIGINAL HIERARCHY") hierarchy(ir_orig.top_instance) print("\nHIERARCHY AFTER FLATTENING") hierarchy(ir.top_instance) .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.049 seconds) .. _sphx_glr_download_auto_examples_extended_plot_flatten.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_flatten.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_flatten.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_