def add_action_node(A: AGraph, G: nx.DiGraph, lambdas, n): """ Add an action node to the CAG. """ output, = A.successors(n) # Only allow LoopVariableNodes in the DBN if output.attr["node_type"] == "LoopVariableNode": oname = output.attr["cag_label"] onode = G.nodes[oname] # Check if it is an initialization function if len(A.predecessors(n)) == 0: onode["init_fn"] = getattr(lambdas, n.attr["lambda_fn"]) # Otherwise append the predecessor function list elif n.attr["label"] == "__decision__": preds = A.predecessors(n) if_var, = [ n for n in preds if list(A.predecessors(n))[0].attr["label"] == "__condition__" ] condition_fn, = A.predecessors(if_var) condition_fn = condition_fn[:condition_fn.rfind("__")] condition_lambda = condition_fn.replace("condition", "lambda") onode["condition_fn"] = getattr(lambdas, condition_lambda) else: onode["pred_fns"].append(getattr(lambdas, n.attr["lambda_fn"])) # If the type of the function is assign, then add an edge in the CAG if n.attr["label"] == "__assign__": for i in A.predecessors(n): iname = i.attr["cag_label"] G.add_edge(iname, oname)
def gen_op_insts(rf_allocs: List[RFallocation], dfg: AGraph, fu: AGraph, input_map: Dict[str, int]) -> List[ATAI]: assembly = [] instructions: List[Instruction] = [] for instruction in fu.nodes(): instructions.append(parse_instruction(instruction)) for instruction in instructions: n = dfg.get_node(instruction.name) nodes = dfg.predecessors(n) input_type0 = inst_input_type(rf_allocs, fu, nodes[0]) if len(nodes) > 1: input_type1 = inst_input_type(rf_allocs, fu, nodes[1]) else: input_type1 = input_type0 # This should never occur but we check for it anyways if input_type0 == OpInput and input_type1 == OpInput: if nodes[0] != nodes[1]: raise DoubleUnidenticalOPInputException # TODO: find scheduling for fetch ops might need to be swapped to fit? if input_type0 == RFInput: # If the data is in the RF we need to generate fetch instructions assembly.append( generate_fetch(rf_allocs, instruction, nodes[0], ATAFetch.REG.REG0)) input0 = RFInput() elif input_type0 == OpInput: input0 = OpInput() else: n = input_map[nodes[0].get_name()] if n is None: raise FUinputException( 'Cannot find FU from which predecessing node originates in map' ) input0 = FUinput(n) if input_type1 == RFInput: assembly.append( generate_fetch(rf_allocs, instruction, nodes[1], ATAFetch.REG.REG1)) input1 = RFInput() elif input_type1 == OpInput: input1 = OpInput() else: n = input_map[nodes[1].get_name()] if n is None: raise FUinputException( 'Cannot find FU from which predecessing node originates in map' ) input1 = FUinput(n) assembly.append(ATAOp(input0, input1, instruction.cycle)) return assembly
def gen_add_input2( dfg: AGraph, fu: AGraph, input_map: Dict[str, int]) -> Tuple[List[Input], List[Output]]: outputs: List[Output] = [] inputs: List[Input] = [] nodes: List[Instruction] = [] for node in fu.nodes(): nodes.append(parse_instruction(node)) nodes.sort() prev_o = 0 for node in nodes: preds = dfg.predecessors(node.name) parent0 = parse_instruction(preds[0]) parent1 = parse_instruction(preds[1]) if parent0.name in input_map: label = dfg.get_node(parent0.name).attr['label'] if 'mul' in label: latency = 2 else: latency = 1 i0 = prev_o + 1 inputs.append( Input(i0, input_map[parent0.name], parent0.cycle + latency)) else: for output in outputs: if output.cycle == parent0.cycle + 1: i0 = output.val break if parent1.name in input_map: label = dfg.get_node(parent1.name).attr['label'] if 'mul' in label: latency = 2 else: latency = 1 i1 = prev_o + 1 inputs.append( Input(i1, input_map[parent1.name], parent1.cycle + latency)) else: for output in outputs: if output.cycle == parent1.cycle + 1: i1 = output.val break expected = i0 + i1 prev_o = expected outputs.append(Output(expected, node.cycle + 1)) inputs.sort() return inputs, outputs
def from_agraph(cls, A: AGraph, lambdas): G = nx.DiGraph() variable_nodes = [ n for n in A.nodes() if n.attr["node_type"] != "ActionNode" ] for n in variable_nodes: name = n.attr["cag_label"] G.add_node(name, value=None, pred_fns=[], agraph_name=n) if n.attr["is_index"] == "True": G.nodes[name]["init_fn"] = lambda: 1 G.nodes[name]["update_fn"] = (lambda **kwargs: int( kwargs.pop(list(kwargs.keys())[0])) + 1) G.add_edge(name, name) function_nodes = [n for n in A.nodes() if n not in variable_nodes] for f in function_nodes: output, = A.successors(f) oname = output.attr["cag_label"] # Check if it is an initialization function if len(A.predecessors(f)) == 0: G.nodes[oname]["init_fn"] = getattr(lambdas, f.attr["lambda_fn"]) # Otherwise append the predecessor function list elif f.attr["label"] == "__decision__": preds = A.predecessors(f) if_var, = [ n for n in preds if list(A.predecessors(n)) [0].attr["label"] == "__condition__" ] condition_fn, = A.predecessors(if_var) cut = condition_fn.rfind("__") condition_fn = condition_fn[:cut] condition_lambda = condition_fn.replace("condition", "lambda") G.nodes[oname]["condition_fn"] = getattr( lambdas, condition_lambda) else: G.nodes[oname]["pred_fns"].append( getattr(lambdas, f.attr["lambda_fn"])) # If the type of the function is assign, then add an edge in the CAG if f.attr["label"] == "__assign__": for i in A.predecessors(f): iname = i.attr["cag_label"] G.add_edge(iname, oname) for n in G.nodes(data=True): n_preds = len(n[1]["pred_fns"]) if n_preds == 0: del n[1]["pred_fns"] elif n_preds == 1: n[1]["update_fn"], = n[1].pop("pred_fns") else: n[1]["choice_fns"] = n[1].pop("pred_fns") def update_fn(n, **kwargs): cond_fn = n[1]["condition_fn"] sig = signature(cond_fn) if cond_fn(**kwargs): return n[1]["choice_fns"][0](**kwargs) else: return n[1]["choice_fns"][1](**kwargs) n[1]["update_fn"] = partial(update_fn, n) isolated_nodes = [ n for n in G.nodes() if len(list(G.predecessors(n))) == len(list(G.successors(n))) == 0 ] for n in isolated_nodes: G.remove_node(n) return cls(G)
def gen_mul_inputs( dfg: AGraph, fu: AGraph, input_map: Dict[str, int]) -> Tuple[List[Input], List[Output]]: outputs: List[Output] = [] inputs: List[Input] = [] nodes: List[Instruction] = [] for node in fu.nodes(): nodes.append(parse_instruction(node)) nodes.sort() prime_idx = 0 for node in nodes: preds = dfg.predecessors(node.name) parent0 = parse_instruction(preds[0]) parent1 = parse_instruction(preds[1]) label0 = dfg.get_node(parent0.name).attr['label'] label1 = dfg.get_node(parent1.name).attr['label'] i0, edge_case0, prime_idx = gen_mul_input(node, parent0, input_map, inputs, outputs, prime_idx, label0) i1, edge_case1, prime_idx = gen_mul_input(node, parent1, input_map, inputs, outputs, prime_idx, label1) if edge_case0 or edge_case1: expected = None else: expected = i0 * i1 # if parent0.name in input_map: # label = dfg.get_node(parent0.name).attr['label'] # if 'mul' in label: # latency = 2 # else: # latency = 1 # # i0 = PRIMES[prime_idx] # prime_idx += 1 # inputs.append(Input(i0, input_map[parent0.name], parent0.cycle + latency)) # else: # for output in outputs: # if output.cycle == parent0.cycle + 2: # i0 = output.val # break # # if parent1.name in input_map: # label = dfg.get_node(parent1.name).attr['label'] # if 'mul' in label: # latency = 2 # else: # latency = 1 # # i1 = PRIMES[prime_idx] # prime_idx += 1 # inputs.append(Input(i1, input_map[parent1.name], parent1.cycle + latency)) # else: # for output in outputs: # if output.cycle == parent1.cycle + 2: # i1 = output.val # break # expected = i0 * i1 outputs.append(Output(expected, node.cycle + 1)) inputs.sort() return inputs, outputs