######################################################################################## # This library creates the task needed to establish a circuit switched transmission and # the configuration data that these task need to send ######################################################################################## import math import os import random import numpy as np import svgwrite from lib_vhdl_gen import * def bit_length(n): if n == 1: return 1 elif n > 1: return math.ceil(math.log(n) / math.log(2)) def int2binary(w, z): return bin(w)[2:].zfill(z) #function to count the number of ports of a router with dimensions as input def port_num_def(port,x_dim,y_dim,z_dim): port_num=7 if port[1]==y_dim-1: port_num-=1 if port[2]==x_dim-1: port_num-=1 if port[1]==0: port_num-=1 if port[2]==0: port_num-=1 if port[0]==z_dim-1: port_num-=1 if port[0]==0: port_num-=1 return(port_num) # Function to add zeros to the beginning of a string def zeros(str,n): for i in range(n): str='0'+str return(str) #calculates the coordinates from the router number def int_to_coordinates(router_num, x_dim=4, y_dim=4, z_dim=3): coordinateZYX = [0, 0, 0] coordinateZ = math.floor(router_num / (x_dim * y_dim)) coordinateY = math.floor((router_num - coordinateZ * x_dim * y_dim) / x_dim) coordinateX = router_num - coordinateZ * x_dim * y_dim - coordinateY * x_dim coordinateZYX[0] = coordinateZ coordinateZYX[1] = coordinateY coordinateZYX[2] = coordinateX return coordinateZYX def coordinates_to_int(coordinateZYX, x_dim=4, y_dim=4, z_dim=3): coordinateZ, coordinateY, coordinateX = coordinateZYX router_num = coordinateZ * x_dim * y_dim + coordinateY * x_dim + coordinateX return router_num #doing XYZ routing takin the source and destination router in int form as input def xyz_routing(src_router, dest_router, x_dim=4, y_dim=4, z_dim=3): # Convert router numbers to coordinates src_coord = int_to_coordinates(src_router, x_dim, y_dim, z_dim) dest_coord = int_to_coordinates(dest_router, x_dim, y_dim, z_dim) # Initialize the route list with the source coordinate route=list() route.append(src_coord[:]) # XYZ Routing Logic [0]=Z [1]=Y [2]=X while src_coord != dest_coord: if src_coord[2] < dest_coord[2]: src_coord[2] += 1 elif src_coord[2] > dest_coord[2]: src_coord[2] -= 1 elif src_coord[1] < dest_coord[1]: src_coord[1] += 1 elif src_coord[1] > dest_coord[1]: src_coord[1] -= 1 elif src_coord[0] < dest_coord[0]: src_coord[0] += 1 elif src_coord[0] > dest_coord[0]: src_coord[0] -= 1 route.append(src_coord[:]) return route # requirements not needed as this will always be a start task config_task_template=""" """ config_map_template=""" """ from collections import Counter def count_consecutive_pairs(data): # Initialize a Counter to track occurrences of pairs pair_counts = Counter() pair_counter=0 # Iterate through each sublist in the data for sublist in data: # Extract consecutive pairs from the sublist for i in range(len(sublist) - 1): pair = (sublist[i], sublist[i + 1]) pair_counts[pair] += 1 pair_counter+=1 # Print results for pairs that occur multiple times filename = "/home/sfischer/Documents/projects/wk_hybridNoC_VHDL/Python/gen_vhdl_from_task/simlog.txt" write_to_file(filename, f"Paths {data}") for pair, count in pair_counts.items(): if count > 1: write_to_file(filename, f"Hop {pair} occurs {count} times") write_to_file(filename, f"Total number of hops {pair_counter}") def count_consecutive_pairs_no_file(data): # Initialize a Counter to track occurrences of pairs pair_counts = Counter() pair_list=[] # Iterate through each sublist in the data for idx,sublist in enumerate(data): # Extract consecutive pairs from the sublist for i in range(len(sublist) - 1): pair = (sublist[i], sublist[i + 1]) pair_counts[pair] += 1 # if pair_counts[pair]>1: # print(idx,i,pair) # write_to_file(filename, f"Paths {data}") for pair, count in pair_counts.items(): if count > 1: # print(f"Hop {pair} occurs {count} times") pair_list.append(pair) # print(pair_list) return(pair_list) def find_pair_indices(pair, lists): indices = [] for i, sublist in enumerate(lists): for j in range(len(sublist) - 1): if sublist[j] == pair[0] and sublist[j + 1] == pair[1]: indices.append(i) break # No need to check further in this sublist return indices def cs_tasks( source_destination = [], start_task=21, start_PE=30, x_dim = 4, #async noc dimensions y_dim = 4, z_dim = 3 ): """ Generates configuration and data for tasks in a 3D asynchronous NoC (Network-on-Chip). This function creates configuration tasks, mapping tasks, and data for routing packets in a 3D asynchronous NoC. It calculates routing paths, determines input/output ports, and generates XML-like data for tasks and mappings. Args: source_destination (list): A list of tuples where each tuple contains source and destination coordinates for routing tasks. start_task (int): The starting task ID for generating unique task IDs. start_PE (int): The starting processing element (PE) ID for mapping tasks. x_dim (int): The X dimension of the NoC. y_dim (int): The Y dimension of the NoC. z_dim (int): The Z dimension of the NoC. Returns: tuple: A tuple containing: - data_xml (str): The generated data for routing tasks in XML-like format. - task_xml (str): The configuration tasks in XML-like format. - map_xml (str): The mapping tasks in XML-like format. - dest_address_list_int (list): A list of destination addresses as integers. """ # ----------------------------------------------header--------------------------------------------------- # | | | | | | | | | | | # |config Flag| Flit_num | Packet_id | Z_src | Y_src | X_src | Z_dest | Y_dest | X_dest | Packet_length | # | 1b | 2b | 13b | 2b | 2b | 2b | 2b | 2b | 2b | 5b | # | | | | | | | | | | | # ------------------------------------------------------------------------------------------------------- # -------------------------data---------------------------- # | | | | | | # |config Flag| Flit_num | Filler | write_clk | direction | # | 1b | 2b | 2b | 7b | 21b | # | | | | | | # --------------------------------------------------------- max_x_dim = 4 # starting from 1 // Must be the same in both files + VHDL files max_y_dim = 4 # starting from 1 // Must be the same in both files + VHDL files max_z_dim = 4 # starting from 1 // Must be the same in both files + VHDL files flit_width = 32 # Must be the same in both files + VHDL files max_packet_len = 31 # (number of flits + header_included) in a packet // Must be the same in both files + VHDL files normal 31 max_tasks_per_pe=50 # start_task=21 # the max task of the normal file so that we can create more tasks with unique IDs start_task_temp=start_task # start_PE=30 # as we can have a max of 50 tasks per PE, we need to split the config task on multiple PEs dest_address_list_coord=list() for i in range(len(source_destination)): dest_address_list_coord.append(xyz_routing(source_destination[i][0],source_destination[i][1])) dest_address_list_int=list() for i, liste in enumerate(dest_address_list_coord): dest_address_list_int.append([]) for n, coord in enumerate(liste): dest_address_list_int[i].append(coordinates_to_int(coord)) count_consecutive_pairs_no_file(dest_address_list_int) # print(dest_address_list_int) task_xml="" map_xml="" counter_PE=0 for m in dest_address_list_int: for idx,k in enumerate(m): task_xml += config_task_template.format(id=start_task, dest=k) map_xml += config_map_template.format(id=start_task, PE=start_PE) counter_PE+=1 start_task+=1 if counter_PE==max_tasks_per_pe: counter_PE=0 start_PE+=1 # Define source address in the synchronous NoC # src_address = (0, 2, 1) # Dimensions of asynchronous NoC # Port constants local = 0 north = 1 east = 2 south = 3 west = 4 up = 5 down = 6 # print(int_to_coordinates(17)) #convert the adress list with the router as int to the adress list with the routes as coordinated counter=0 dest_address_list=list() for i in dest_address_list_int: dest_address_list.append([]) for n in i: dest_address_list[counter].append(int_to_coordinates(n)) counter+=1 input_port=0 output_port=0 packet_id=0 packet_len=2 #packet length without header data_xml="" task_num_counter=0 # print(dest_address_list) for j in range(len(dest_address_list)): for i in range(len(dest_address_list[j])): dest_address = dest_address_list[j][i] ######################################################################### # calculate port numbers of async noc ######################################################################### #what direction is what port north=math.nan east=math.nan south=math.nan west=math.nan up=math.nan down=math.nan port_index=0 if (dest_address[1]==y_dim-1): #north doesnt exist north=math.nan else: port_index+=1 north=port_index if (dest_address[2]==x_dim-1): #east doesnt exist east=math.nan else: port_index+=1 east=port_index if (dest_address[1]==0): #south doesnt exist south=math.nan else: port_index+=1 south=port_index if (dest_address[2]==0): #west doesnt exist west=math.nan else: port_index+=1 west=port_index if (dest_address[0]==z_dim-1): #up doesnt exist up=math.nan else: port_index+=1 up=port_index if (dest_address[0]==0): #down doesnt exist down=math.nan else: port_index+=1 down=port_index ############################################################################### #what number is input port and output port if i==0: #first router always has local as input port input_port=0 else: if dest_address_list[j][i][0] comming from up input_port=up if dest_address_list[j][i][0] >dest_address_list[j][i-1][0]: #Z of previous router is lower ->comming from down input_port=down if dest_address_list[j][i][1] comming from north input_port=north if dest_address_list[j][i][1] >dest_address_list[j][i-1][1]: #Y of previous router is lower ->comming from south input_port=south if dest_address_list[j][i][2] comming from east input_port=east if dest_address_list[j][i][2] >dest_address_list[j][i-1][2]: #X of previous router is lower ->comming from west input_port=west if i==len(dest_address_list[j])-1: #last router alway has local as output port output_port=0 else: if dest_address_list[j][i][0] going to up output_port=up if dest_address_list[j][i][0] >dest_address_list[j][i+1][0]: #Z of next router is lower ->going to down output_port=down if dest_address_list[j][i][1] going to north output_port=north if dest_address_list[j][i][1] >dest_address_list[j][i+1][1]: #Y of next router is lower ->going to south output_port=south if dest_address_list[j][i][2] going to east output_port=east if dest_address_list[j][i][2] >dest_address_list[j][i+1][2]: #X of next router is lower ->going to west output_port=west ######################################################################### # create header and data - Not using the header. It gets created in vhdl ######################################################################### flit_num=0 flit_num+=1 packet_id+=1 ######################direction data output############## data_output='' data_output=zeros(data_output,bit_length(port_num_def(dest_address,x_dim,y_dim,z_dim))*output_port) #how many bits do we need for one direction signal* outputport num (zeros until the right direction must be set) data_output= int2binary(input_port,bit_length(port_num_def(dest_address,x_dim,y_dim,z_dim)))+ data_output data_output=zeros(data_output,flit_width-len(data_output)-11) #write_clk data_output=zeros(data_output,output_port) data_output='1' +data_output #write_clk data_output=zeros(data_output,6-output_port) #filler data_output=zeros(data_output,1) #flit number in packet data_output=int2binary(flit_num,2) +data_output #config flag data_output='1'+data_output task_num=0 fixed_length = 10 # if j>0: # # task_num=len(dest_address_list[j-1])*j+start_task_temp+i # task_num=start_task_temp+task_num_counter # print(f"start_task_temp {start_task_temp}") # print(f"len(dest_address_list[j-1])) {len(dest_address_list[j-1])}") # print(f"j {j}") # print(f"i {i}") # print(f"task_num {task_num}") # task_num_counter+=1 # else: # task_num=start_task_temp+task_num_counter # # task_num=start_task_temp+i # task_num_counter+=1 # # print(task_num) task_num=start_task_temp+task_num_counter task_num_counter+=1 # print(task_num) task_num=format(task_num, f'0{fixed_length}b') data_output=task_num+data_output + "\n" data_xml=data_xml+data_output flit_num+=1 ##################direction data input######################## data_input='' data_input=zeros(data_input,bit_length(port_num_def(dest_address,x_dim,y_dim,z_dim))*input_port) data_input= int2binary(output_port,bit_length(port_num_def(dest_address,x_dim,y_dim,z_dim)))+ data_input data_input=zeros(data_input,flit_width-len(data_input)-11) #write clk data_input=zeros(data_input,input_port) data_input='1' +data_input data_input=zeros(data_input,6-input_port) #fillter data_input=zeros(data_input,1) #flit number in packet data_input=int2binary(flit_num,2) +data_input #config flag data_input='1'+data_input data_input=task_num+data_input + "\n" data_xml=data_xml+data_input # print(data_xml) # print(task_xml) # print(map_xml) return (data_xml,task_xml,map_xml,dest_address_list_int) # cs_tasks()