def visit_Constant(self, node: Constant): node_vals = self.graph[node.name] # self.inputs.append( # f"input [{node_vals[0] + node_vals[1] - 1}:0] {node.name}") self.constants.append( f"\t`MAKE_CONST_REAL({node.value}, {node.name});\n") Visitor.generic_visit(self, node)
def generic_visit(self, node: DagNode): Visitor.generic_visit(self, node) if node.node_name == "global.IO" or node.node_name == "global.BitIO": if "write" in node.iname: new_node = Output(type=IO_Output_t, iname=node.iname) new_children = [] for child in node.children(): if node.node_name == "global.IO": new_reg_sink = RegisterSink(self.node_map[child], iname=node.iname+"$reg"+str(self.added_regs)) new_reg_source = RegisterSource(iname=node.iname+"$reg"+str(self.added_regs)) else: new_reg_sink = BitRegisterSink(self.node_map[child], iname=node.iname+"$reg"+str(self.added_regs)) new_reg_source = BitRegisterSource(iname=node.iname+"$reg"+str(self.added_regs)) self.dag_sources.append(new_reg_source) self.dag_sinks.append(new_reg_sink) self.node_map[new_reg_source] = new_reg_source self.node_map[new_reg_sink] = new_reg_sink self.added_regs += 1 new_children.append(new_reg_source) new_node.set_children(*new_children) self.outputs.append(new_node) else: new_node = Input(type=IO_Input_t, iname=node.iname) self.inputs.append(new_node) self.node_map[node] = new_node else: if not(node.node_name == "Input" or "Input" in [child.node_name for child in node.children()]): new_children = [self.node_map[child] for child in node.children()] new_node = node.copy() if node not in self.node_map: new_node.set_children(*new_children) self.node_map[node] = new_node
def generic_visit(self, node: DagNode): Visitor.generic_visit(self, node) if node.node_name not in self.inst_info: raise ValueError(f"Need info for {node.node_name}") id = f"{self.inst_info[node.node_name]}{self.i}" self.node_to_id[node.iname] = id self.i += 1
def visit_Input(self, node: Input): node_vals = self.graph[node.name] self.inputs.append(f"\n\t`INPUT_REAL({node.name})") self.in_decl.append(f"\n\t`DECL_REAL({node.name})") # self.inputs.append( # f"input [{node_vals[0] + node_vals[1] - 1}:0] {node.name}") Visitor.generic_visit(self, node)
def generic_visit(self, node: DagNode): Visitor.generic_visit(self, node) new_children = [self.node_map[child] for child in node.children()] new_node = node.copy() new_node.set_children(*new_children) self.node_to_opaths[node] = {(): new_node} self.node_map[node] = new_node
def visit_Output(self, node: Output): Visitor.generic_visit(self, node) child_bid = self.node_to_bid[node.child] if node.child.type == Bit: port = 'f2io_1' else: port = 'f2io_16' self.netlist[child_bid].append((node, port))
def visit_Select(self, node: Select): Visitor.generic_visit(self, node) self.handleIB(node) input_signal = self.getChildren(node) if self.train_MNIST: self.errors[node.name] = self.errors[input_signal.name][node.index]
def visit_BitShift(self, node: BitShift): Visitor.generic_visit(self, node) self.handleIB(node) lhs, rhs = self.getChildren(node) if self.calculate_IB: self.errors[node.name] = self.errors[lhs.name].mul( self.errors[rhs.name], node.name)
def generic_visit(self, node): Visitor.generic_visit(self, node) def n2s(node): return f"{str(node)}_{str(node.iname)}_{str(node.node_name)}" if self.no_unbound and not is_unbound_const(node): self.graph.node(n2s(node)) for i, child in enumerate(node.children()): if self.no_unbound and not is_unbound_const(child): self.graph.edge(n2s(child), n2s(node), label=str(i))
def visit_Select(self, node): Visitor.generic_visit(self, node) child = list(node.children())[0] child_bid = self.node_to_bid[child] assert isinstance(child_bid, dict) assert node.field in child_bid bid = child_bid[node.field] self.node_to_bid[node] = bid self.netlist[bid].append((child, node.field))
def generic_visit(self, node: DagNode): Visitor.generic_visit(self, node) child_values = [self.node_values[child] for child in node.children()] eval_name = f"eval_{node.kind()[0]}" assert hasattr(self, eval_name) node_val = getattr(self, eval_name)(*child_values, node=node) assert node_val is not None self.node_values[node] = node_val
def visit_Reduce(self, node: Reduce): Visitor.generic_visit(self, node) self.handleIB(node) input_vector = self.getChildren(node) if self.train_MNIST: self.errors[node.name] = PrecisionNode.reduce( self.errors[input_vector.name], node.name)
def visit_Combine(self, node: Combine): Visitor.generic_visit(self, node) child_bids = [self.node_to_bid[child] for child in node.children()] input_t = node.type bids = {} for field, child_bid in zip(input_t.field_dict.keys(), child_bids): if child_bid is None: continue bids[field] = child_bid self.node_to_bid[node] = bids
def visit_RegisterSink(self, node): Visitor.generic_visit(self, node) if node.type == Bit: id = f"r{self.i}" elif node.type == BitVector[16]: id = f"r{self.i}" else: raise NotImplementedError(f"{node}, {node.type}") self.node_to_id[node.iname] = id self.i += 1
def generic_visit(self, node: DagNode): Visitor.generic_visit(self, node) if node.node_name not in self.inst_info: raise ValueError(f"Need info for {node.node_name}") adt = self.inst_info[node.node_name] for instr_child in node.children(): if isinstance(instr_child, Constant): break assert isinstance(instr_child, Constant), f"{node.node_name} {node.iname} {instr_child.node_name}" self.node_to_instr[node.iname] = instr_child.value
def visit_Concat(self, node: Concat): Visitor.generic_visit(self, node) self.handleIB(node) inputs = self.getChildren(node) if self.train_MNIST: precisions = [] for i in inputs: precisions.append(copy.deepcopy(self.errors[i.name])) self.errors[node.name] = precisions
def visit_Combine(self, node: Combine): Visitor.generic_visit(self, node) adt = node.type assert issubclass(adt, (Product, Tuple)) paths = {} for k, child in zip(adt.field_dict.keys(), node.children()): child_paths = self.node_to_opaths[child] for child_path, new_child in child_paths.items(): new_path = (k, *child_path) paths[new_path] = new_child self.node_to_opaths[node] = paths
def visit_Select(self, node): Visitor.generic_visit(self, node) child = list(node.children())[0] if isinstance(child, Input): if node.type == Bit: id = f"i{self.i}" elif node.type == BitVector[16]: id = f"I{self.i}" else: raise NotImplementedError(f"{node}, {node.type}") self.i += 1 self.node_to_id[child.iname] = id
def generic_visit(self, node: DagNode): Visitor.generic_visit(self, node) if node.node_name == "Input" or node.node_name == "Output": self.num_ios += 1 elif node.node_name == "global.PE": self.num_pes += 1 elif node.node_name == "global.MEM": self.num_mems += 1 elif node.node_name == "global.Pond": self.num_ponds += 1 elif node.node_name == "Register": self.num_regs += 1
def visit_Mul(self, node: Mul): Visitor.generic_visit(self, node) self.handleIB(node) lhs, rhs = self.getChildren(node) if self.calculate_IB or self.train_MNIST: self.errors[node.name] = self.errors[lhs.name].mul( self.errors[rhs.name], node.name) if self.calculate_IB: self.area_fn += f"+1 * ({self.IBs[lhs.name]} + {lhs.name})*({self.IBs[rhs.name]} + {rhs.name})" else: self.area_fn += f"+1 * ({lhs.name}_ib + {lhs.name})*({rhs.name}_ib + {rhs.name})"
def generic_visit(self, node): Visitor.generic_visit(self, node) child_bids = [self.node_to_bid[child] for child in node.children()] if node.node_name not in self.inst_info: raise ValueError(f"Missing {node.node_name} in info") input_t = self.inst_info[node.node_name] for field, child_bid in zip(input_t.field_dict.keys(), child_bids): if child_bid is None: continue assert child_bid in self.netlist self.netlist[child_bid].append((node, field)) if not isinstance(node, Sink): bid = self.create_buses(node.type) self.node_to_bid[node] = bid
def visit_Output(self, node: Output): Visitor.generic_visit(self, node) child = list(node.children())[0] #assert isinstance(child, Combine) #c_children = list(child.children()) if "io16" in node.iname: is_bit = False else: is_bit = True if is_bit: id = f"i{self.i}" #print(node) else: id = f"I{self.i}" self.i += 1 self.node_to_id[node.iname] = id
def visit_Output(self, node: Output): Visitor.generic_visit(self, node) for field, child in zip(node.type.field_dict, node.children()): child_paths = self.node_to_opaths[child] for child_path, new_child in child_paths.items(): new_path = (field, *child_path) assert new_path in self.opath_to_type child_t = self.opath_to_type[new_path] if child_t == Bit: combine_children = [Constant(type=BitVector[16], value=Unbound), new_child] else: combine_children = [new_child, Constant(type=Bit, value=Unbound)] cnode = Combine(*combine_children, type=IO_Output_t) # Bad hack, read_en signals aren't actually connected to anything, this should be checked if "read_en" not in field: self.outputs[new_path] = Output(cnode, type=IO_Output_t, iname="_".join(str(field) for field in new_path))
def visit_LookupTable(self, node: LookupTable): Visitor.generic_visit(self, node) self.handleIB(node) input_signal = self.getChildren(node) node.child = input_signal if self.calculate_IB: if node.precision >= 0.: self.area_fn += f"+1 * (2 ** ({self.IBs[input_signal.name]} + {input_signal.name})) * ({node.precision} + {self.IBs[node.name]})" else: self.area_fn += f"+1 * (2 ** ({self.IBs[input_signal.name]} + {input_signal.name})) * ({node.name} + {self.IBs[node.name]})" self.errors[node.name] = PrecisionNode(sin( self.errors[input_signal.name].val), node.name, self.errors[input_signal.name].error) else: if node.precision >= 0.: # TODO: the 5. here shouldn't be hardcoded! self.area_fn += f"+1 * (2 ** ({input_signal.name} + {input_signal.name}_ib)) * ({node.precision} + 8.)" else: self.area_fn += f"+1 * (2 ** ({input_signal.name} + {input_signal.name}_ib)) * ({node.name} + {node.name}_ib)"
def generic_visit(self, node): Visitor.generic_visit(self, node) def n2s(node): op = node.iname.split("_")[0] return f"{str(node)}_{node._id_}\n{op}" def find_child(node): if len(node.children()) == 0: return for child in node.children(): if str(child) in self.plotted_nodes: self.child_list.append(child) else: child_f = find_child(child) if str(node) in self.plotted_nodes: find_child(node) for child in self.child_list: self.graph.edge(n2s(child), n2s(node)) self.child_list = []
def visit_Select(self, node: DagNode): Visitor.generic_visit(self, node) if not ("hw_output" in [child.iname for child in node.children()] or "self" in [child.iname for child in node.children()]): new_children = [self.node_map[child] for child in node.children()] io_child = new_children[0] pipeline = os.getenv('PIPELINED') if "io16in" in io_child.iname: new_node = new_children[0].select("io2f_16") if pipeline: self.create_register_tree(io_child, new_node, node, self.sinks[node], False, 4) elif "io1in" in io_child.iname: new_node = new_children[0].select("io2f_1") if pipeline: self.create_register_tree(io_child, new_node, node, self.sinks[node], True, 4) else: new_node = node.copy() if node not in self.node_map: new_node.set_children(*new_children) self.node_map[node] = new_node
def visit_Select(self, node: Select): def get_input_node(node, path=()): if isinstance(node, Input): assert path in self.inputs return self.inputs[path] elif isinstance(node, Select): child = list(node.children())[0] return get_input_node(child, (node.field, *path)) else: return None input_node = get_input_node(node) if input_node is not None: self.node_map[node] = input_node return Visitor.generic_visit(self, node) new_children = [self.node_map[child] for child in node.children()] new_node = node.copy() new_node.set_children(*new_children) self.node_to_opaths[node] = {(): new_node} self.node_map[node] = new_node
def visit_Mul(self, node: Mul): self.codeForOperation(node, ' * ') Visitor.generic_visit(self, node)
def visit_Add(self, node: Add): self.codeForOperation(node, ' + ') Visitor.generic_visit(self, node)
def generic_visit(self, node: DagNode): Visitor.generic_visit(self, node)