Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed the issue of missing wires when multiple blocks are connected to other multiple blocks through a single block (port) #339

Merged
merged 1 commit into from
Oct 17, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 118 additions & 67 deletions backend/synthesis/synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ def syntheize_modules(data: dict, zipfile: InMemoryZip) -> Tuple[InMemoryZip, Di
Blocks, parameters and the connections (wires) between the blocks stored in a
JSON file.
'''
# Initialize an empty dictionary for tracking dependencies, blocks, parameters, synhronize_frequency, optional_files
dependencies = {}
blocks = {}
parameters = {}
Expand Down Expand Up @@ -157,103 +156,155 @@ def process_dependency(dep, zipfile, synhronize_frequency, optional_files, dep_n
# Add the wire to the valid_wires list
valid_wires.append(wire)

# Function to process wires and handle absent blocks
def process_wires(valid_wires):
# Initialize dictionaries to track source and target ports
wire_check_source = {}
wire_check_target = {}

# Initialize a counter for iteration
count = 0
# Set a flag to detect changes
changes_detected = True
def process_wires(valid_wires):
count = 0 # Initialize a counter for processing iterations
changes_detected = True # Boolean flag to track if changes were made in the current iteration

# Continue processing while changes are detected
# Loop until no changes are detected
while changes_detected:
changes_detected = False
wire_check_source = {} # Dictionary to store wires' source info where 'ob' is absent
wire_check_target = {}
changes_detected = False # Reset changes_detected to False before processing wires

new_wires = [] # List to store newly created wires

# Iterate over valid wires in reverse order
# Iterate through valid_wires in reverse order
for i in range(len(valid_wires) - 1, -1, -1):
wire = valid_wires[i]
remove_wire = False # Flag to determine if the wire should be removed
count += 1 # Increment the counter
wire = valid_wires[i] # Access the current wire from valid_wires
remove_wire = False # Flag to mark whether the current wire should be removed

count += 1 # Increment the processing counter

# Check if the source port is 'input-out'
if wire['source']['port'] == 'input-out':
port_name = wire['source']['block']
# Check if the target is marked 'absent'
port_name = wire['source']['block'] # Get the block name of the source port

# If the target has 'ob' and it's 'absent', track it for processing later
if 'ob' in wire['target'] and wire['target']['ob'] == 'absent':
# Add target details to wire_check_source with 'input-out' port
wire_check_source[port_name] = wire['target'].copy()
wire_check_source[port_name]['port'] = port_name
if port_name not in wire_check_source:
wire_check_source[port_name] = [] # Initialize list if it's not present
wire_check_source[port_name].append(wire['target'].copy()) # Append a copy of the target
wire_check_source[port_name][-1]['port'] = port_name # Set the port name for the new entry
else:
# Add target details to wire_check_source
wire_check_source[port_name] = wire['target']
# Mark the wire for removal
remove_wire = True
# Otherwise, add the target to wire_check_source and mark for removal
if port_name not in wire_check_source:
wire_check_source[port_name] = []
wire_check_source[port_name].append(wire['target']) # Add target to the dictionary
remove_wire = True # Mark the wire for removal later

# Check if the target port is 'output-in'
if wire['target']['port'] == 'output-in':
port_name = wire['target']['block']
# Check if the source is marked 'absent'
port_name = wire['target']['block'] # Get the block name of the target port

# If the source has 'ob' and it's 'absent', track it for processing later
if 'ob' in wire['source'] and wire['source']['ob'] == 'absent':
# Add source details to wire_check_target with 'output-in' port
wire_check_target[port_name] = wire['source'].copy()
wire_check_target[port_name]['port'] = port_name
if port_name not in wire_check_target:
wire_check_target[port_name] = [] # Initialize list if it's not present
wire_check_target[port_name].append(wire['source'].copy()) # Append a copy of the source
wire_check_target[port_name][-1]['port'] = port_name # Set the port name for the new entry
else:
# Add source details to wire_check_target
wire_check_target[port_name] = wire['source']
# Mark the wire for removal
remove_wire = True
# Otherwise, add the source to wire_check_target and mark for removal
if port_name not in wire_check_target:
wire_check_target[port_name] = []
wire_check_target[port_name].append(wire['source']) # Add source to the dictionary
remove_wire = True # Mark the wire for removal later

# Remove the wire from valid_wires if marked for removal
# Remove the wire if it was marked for removal
if remove_wire:
del valid_wires[i]
changes_detected = True # Set flag to true since changes were made
del valid_wires[i] # Remove the wire from valid_wires
changes_detected = True # Set changes_detected to True as wires were modified

i = 0 # Initialize counter for iterating through valid_wires
new_wires = [] # Reset the list to store any newly created wires

# Iterate through valid_wires starting from the beginning
while i < len(valid_wires):
wire = valid_wires[i] # Access the current wire

# Iterate over the valid wires to update ports
for i, wire in enumerate(valid_wires):
# Check if the source port name has 36 characters
# Check if the source port is exactly 36 characters (for specific port length)
if len(wire['source'].get('port', '')) == 36:
port_name = wire['source']['port']
# Update source with wire_check_target details if present
if port_name in wire_check_target:
valid_wires[i]['source'] = wire_check_target[port_name]
# Update port name if 'absent' flag is present
if 'ob' in valid_wires[i]['source']:
port_name = wire['source']['port'] # Get the port name of the source

# If the port name exists in wire_check_target, process the sources
if port_name in wire_check_target and wire_check_target[port_name]:
new_sources = wire_check_target[port_name] # Get the list of sources for the port

# Replace the source of the current wire with the first new source
valid_wires[i]['source'] = new_sources[0]
if 'ob' in valid_wires[i]['source']: # If 'ob' exists, set the port name
valid_wires[i]['source']['port'] = port_name

# Check if the target port name has 36 characters

# For remaining sources, create new wires
for new_source in new_sources[1:]:
new_wire = wire.copy() # Copy the current wire
new_wire['source'] = new_source # Set the new source for the copied wire
if 'ob' in new_wire['source']: # If 'ob' exists, set the port name
new_wire['source']['port'] = port_name
new_wires.append(new_wire) # Add the new wire to new_wires

# Check if the target port is exactly 36 characters (for specific port length)
if len(wire['target'].get('port', '')) == 36:
port_name = wire['target']['port']
# Update target with wire_check_source details if present
if port_name in wire_check_source:
valid_wires[i]['target'] = wire_check_source[port_name]
# Update port name if 'absent' flag is present
if 'ob' in valid_wires[i]['target']:
port_name = wire['target']['port'] # Get the port name of the target

# If the port name exists in wire_check_source, process the targets
if port_name in wire_check_source and wire_check_source[port_name]:
new_targets = wire_check_source[port_name] # Get the list of targets for the port

# Replace the target of the current wire with the first new target
valid_wires[i]['target'] = new_targets[0]
if 'ob' in valid_wires[i]['target']: # If 'ob' exists, set the port name
valid_wires[i]['target']['port'] = port_name

# For remaining targets, create new wires
for new_target in new_targets[1:]:
new_wire = wire.copy() # Copy the current wire
new_wire['target'] = new_target # Set the new target for the copied wire
if 'ob' in new_wire['target']: # If 'ob' exists, set the port name
new_wire['target']['port'] = port_name
new_wires.append(new_wire) # Add the new wire to new_wires

i += 1 # Move to the next wire in the valid_wires list

# Append newly created wires to the valid_wires list
valid_wires.extend(new_wires)

# Remove duplicate wires by checking for uniqueness
unique_wires = [] # List to store unique wires
seen_wires = set() # Set to track already seen wires

# Iterate over valid_wires to remove duplicates
for wire in valid_wires:
# Convert the wire dictionary to a frozenset for hashability (so it can be added to a set)
wire_tuple = frozenset((key, frozenset(value.items())) if isinstance(value, dict) else (key, value) for key, value in wire.items())

# Only add unique wires to unique_wires
if wire_tuple not in seen_wires:
seen_wires.add(wire_tuple) # Add the wire to the set of seen wires
unique_wires.append(wire) # Append the wire to unique_wires

valid_wires = unique_wires # Assign the unique wires back to valid_wires

# Return the processed list of valid wires
return valid_wires
return valid_wires # Return the processed valid_wires

# Process the wires to handle 'absent' blocks

# Call the process_wires function to process the wires
processed_wires = process_wires(valid_wires)

# Create a final data dictionary with blocks, parameters, frequencies, and wires
# Package processed data into a JSON file for saving or further use
data = {
'blocks': blocks,
'parameters': parameters,
'synchronize_frequency': synhronize_frequency,
'wires': processed_wires
'blocks': blocks, # Block-related data
'parameters': parameters, # Parameter-related data
'synchronize_frequency': synhronize_frequency, # Synchronization frequency information
'wires': processed_wires # The processed wire data
}
# Add the data dictionary as a JSON file in the zipfile
zipfile.append('data.json', json.dumps(data))

# Return the updated zipfile and optional files dictionary
# Add data to a zipfile (the zipfile object must be defined elsewhere in the code)
zipfile.append('data.json', json.dumps(data)) # Append the JSON data to the zipfile


return zipfile, optional_files


def synthesize_executioner(zipfile: InMemoryZip, optional_files: Dict[str, bool]) -> InMemoryZip:
'''Synthesize python code necessary to run the blocks.
All these files are present in django static directory.
Expand Down
Loading