diff --git a/sam/onyx/hw_nodes/buffet_node.py b/sam/onyx/hw_nodes/buffet_node.py index e2473e9d..828f1337 100644 --- a/sam/onyx/hw_nodes/buffet_node.py +++ b/sam/onyx/hw_nodes/buffet_node.py @@ -124,8 +124,16 @@ def configure(self, attributes): cap0 = kratos.clog2(capacity_0) - fetch_width_log cap1 = kratos.clog2(capacity_1) - fetch_width_log + if 'vector_reduce_mode' in attributes: + is_in_vr_mode = attributes['vector_reduce_mode'].strip('"') + if is_in_vr_mode == "true": + vr_mode = 1 + else: + vr_mode = 0 + cfg_kwargs = { 'capacity_0': cap0, - 'capacity_1': cap1 + 'capacity_1': cap1, + 'vr_mode': vr_mode } - return (capacity_0, capacity_1), cfg_kwargs + return (capacity_0, capacity_1, vr_mode), cfg_kwargs diff --git a/sam/onyx/hw_nodes/compute_node.py b/sam/onyx/hw_nodes/compute_node.py index 2482f399..560aa4db 100644 --- a/sam/onyx/hw_nodes/compute_node.py +++ b/sam/onyx/hw_nodes/compute_node.py @@ -62,12 +62,16 @@ def connect(self, other, edge, kwargs=None): pe = self.get_name() # isect_conn = other.get_num_inputs() - if 'tensor' not in edge.get_attributes(): - # Taking some liberties here - but technically this is the combo val - # isect_conn = other.get_connection_from_tensor('B') - isect_conn = other.get_connection_from_tensor('C') + if 'vector_reduce_mode' in edge.get_attributes(): + if edge.get_attributes()['vector_reduce_mode'] == True: + isect_conn = 0 else: - isect_conn = other.get_connection_from_tensor(edge.get_tensor()) + if 'tensor' not in edge.get_attributes(): + # Taking some liberties here - but technically this is the combo val + # isect_conn = other.get_connection_from_tensor('B') + isect_conn = other.get_connection_from_tensor('C') + else: + isect_conn = other.get_connection_from_tensor(edge.get_tensor()) new_conns = { f'pe_to_isect_{in_str}_{isect_conn}': [ diff --git a/sam/onyx/hw_nodes/fiberaccess_node.py b/sam/onyx/hw_nodes/fiberaccess_node.py index 89b12e6e..63e7c85f 100644 --- a/sam/onyx/hw_nodes/fiberaccess_node.py +++ b/sam/onyx/hw_nodes/fiberaccess_node.py @@ -228,9 +228,12 @@ def configure(self, attributes, flavor): cfg_tuple, cfg_kwargs = self.get_flavor(flavor=flavor).configure(attributes) cfg_kwargs['flavor'] = flavor + print("THESE ARE MY CONFIG KWARGS") + print(cfg_kwargs) + #breakpoint() - vr_mode = 0 - cfg_tuple += (vr_mode,) - cfg_kwargs["vr_mode"] = vr_mode + #vr_mode = 0 + #cfg_tuple += (vr_mode,) + #cfg_kwargs["vr_mode"] = vr_mode return cfg_tuple, cfg_kwargs diff --git a/sam/onyx/hw_nodes/hw_node.py b/sam/onyx/hw_nodes/hw_node.py index 5991a225..9b7d8847 100644 --- a/sam/onyx/hw_nodes/hw_node.py +++ b/sam/onyx/hw_nodes/hw_node.py @@ -16,7 +16,7 @@ class HWNodeType(Enum): Broadcast = 12 RepSigGen = 13 CrdHold = 14 - SpAccumulator = 15 + VectorReducer = 15 FiberAccess = 16 diff --git a/sam/onyx/hw_nodes/intersect_node.py b/sam/onyx/hw_nodes/intersect_node.py index 18e20d9e..5f4617d4 100644 --- a/sam/onyx/hw_nodes/intersect_node.py +++ b/sam/onyx/hw_nodes/intersect_node.py @@ -180,6 +180,7 @@ def connect(self, other, edge, kwargs=None): print(edge.get_attributes()) edge_comment = edge.get_attributes()['comment'].strip('"') tensor = edge_comment.split('-')[1] + print(self.tensor_to_conn) out_conn = self.tensor_to_conn[tensor] compute_conn = compute.get_num_inputs() new_conns = { @@ -248,6 +249,15 @@ def configure(self, attributes): cmrg_enable = 0 cmrg_stop_lvl = 0 type_op = attributes['type'].strip('"') + + + if 'vector_reduce_mode' in attributes: + is_in_vr_mode = attributes['vector_reduce_mode'].strip('"') + if is_in_vr_mode == "true": + vr_mode = 1 + else: + vr_mode = 0 + if type_op == "intersect": op = JoinerOp.INTERSECT.value elif type_op == "union": @@ -258,6 +268,6 @@ def configure(self, attributes): 'cmrg_enable': cmrg_enable, 'cmrg_stop_lvl': cmrg_stop_lvl, 'op': op, - 'vr_mode': 0 + 'vr_mode': vr_mode } - return (cmrg_enable, cmrg_stop_lvl, op, 0), cfg_kwargs + return (cmrg_enable, cmrg_stop_lvl, op, vr_mode), cfg_kwargs diff --git a/sam/onyx/hw_nodes/merge_node.py b/sam/onyx/hw_nodes/merge_node.py index c0b3d158..5dccdb88 100644 --- a/sam/onyx/hw_nodes/merge_node.py +++ b/sam/onyx/hw_nodes/merge_node.py @@ -62,7 +62,16 @@ def connect(self, other, edge, kwargs=None): return new_conns elif other_type == IntersectNode: - raise NotImplementedError(f'Cannot connect MergeNode to {other_type}') + isect = other.get_name() + print("MERGE TO UNION FOR VECTOR REDUCE") + new_conns = { + f'merge_to_union_inner': [ + ([(merge, f"cmrg_coord_out_{0}"), (isect, f"coord_in_{0}")], 17), + ] + } + + return new_conns + #raise NotImplementedError(f'Cannot connect MergeNode to {other_type}') elif other_type == ReduceNode: # raise NotImplementedError(f'Cannot connect MergeNode to {other_type}') other_red = other.get_name() diff --git a/sam/onyx/hw_nodes/read_scanner_node.py b/sam/onyx/hw_nodes/read_scanner_node.py index 63e8023f..64c4cad0 100644 --- a/sam/onyx/hw_nodes/read_scanner_node.py +++ b/sam/onyx/hw_nodes/read_scanner_node.py @@ -90,6 +90,9 @@ def connect(self, other, edge, kwargs=None): edge_attr = edge.get_attributes() if 'use_alt_out_port' in edge_attr: out_conn = 'block_rd_out' + elif ('vector_reduce_mode' in edge_attr): + if (edge_attr['vector_reduce_mode'] == True): + out_conn = 'pos_out' else: out_conn = 'coord_out' @@ -102,7 +105,13 @@ def connect(self, other, edge, kwargs=None): elif other_type == IntersectNode: # Send both.... isect = other.get_name() - isect_conn = other.get_connection_from_tensor(self.get_tensor()) + if 'vector_reduce_mode' in edge.get_attributes(): + if edge.get_attributes()['vector_reduce_mode'] == True: + isect_conn = 1 + elif 'special' in edge.get_attributes(): + isect_conn = 0 + else: + isect_conn = other.get_connection_from_tensor(self.get_tensor()) e_attr = edge.get_attributes() # isect_conn = 0 @@ -247,12 +256,12 @@ def configure(self, attributes): dim_size = 1 stop_lvl = 0 - if 'spacc' in attributes: - spacc_mode = 1 - assert 'stop_lvl' in attributes - stop_lvl = int(attributes['stop_lvl'].strip('"')) - else: - spacc_mode = 0 + #if 'spacc' in attributes: + # spacc_mode = 1 + # assert 'stop_lvl' in attributes + # stop_lvl = int(attributes['stop_lvl'].strip('"')) + #else: + # spacc_mode = 0 # This is a fiberwrite's opposing read scanner for comms with GLB if attributes['type'].strip('"') == 'fiberwrite': @@ -283,6 +292,15 @@ def configure(self, attributes): lookup = 0 block_mode = int(attributes['type'].strip('"') == 'fiberwrite') + + if 'vector_reduce_mode' in attributes: + is_in_vr_mode = attributes['vector_reduce_mode'].strip('"') + if is_in_vr_mode == "true": + vr_mode = 1 + else: + vr_mode = 0 + + cfg_kwargs = { 'dense': dense, 'dim_size': dim_size, @@ -294,11 +312,12 @@ def configure(self, attributes): 'do_repeat': do_repeat, 'repeat_outer': repeat_outer, 'repeat_factor': repeat_factor, - 'stop_lvl': stop_lvl, + #'stop_lvl': stop_lvl, 'block_mode': block_mode, 'lookup': lookup, - 'spacc_mode': spacc_mode + #'spacc_mode': spacc_mode + 'vr_mode': vr_mode } return (inner_offset, max_outer_dim, strides, ranges, is_root, do_repeat, - repeat_outer, repeat_factor, stop_lvl, block_mode, lookup, spacc_mode), cfg_kwargs + repeat_outer, repeat_factor, block_mode, lookup, vr_mode), cfg_kwargs diff --git a/sam/onyx/hw_nodes/write_scanner_node.py b/sam/onyx/hw_nodes/write_scanner_node.py index a61a2172..4ac63f81 100644 --- a/sam/onyx/hw_nodes/write_scanner_node.py +++ b/sam/onyx/hw_nodes/write_scanner_node.py @@ -79,6 +79,7 @@ def connect(self, other, edge, kwargs=None): def configure(self, attributes): stop_lvl = 0 + init_blank = 0 # compressed = int(attributes['format'] == 'compressed') if 'format' in attributes and 'vals' in attributes['format'].strip('"'): @@ -89,14 +90,14 @@ def configure(self, attributes): else: compressed = 1 - if 'spacc' in attributes: - spacc_mode = 1 - init_blank = 1 - assert 'stop_lvl' in attributes - stop_lvl = int(attributes['stop_lvl'].strip('"')) - else: - spacc_mode = 0 - init_blank = 0 + #if 'spacc' in attributes: + # spacc_mode = 1 + # init_blank = 1 + # assert 'stop_lvl' in attributes + # stop_lvl = int(attributes['stop_lvl'].strip('"')) + #else: + # spacc_mode = 0 + # init_blank = 0 # compressed = int(attributes['format'] == 'compressed') if attributes['type'].strip('"') == 'arrayvals': @@ -111,17 +112,25 @@ def configure(self, attributes): block_mode = 1 else: block_mode = 0 + + if 'vector_reduce_mode' in attributes: + is_in_vr_mode = attributes['vector_reduce_mode'].strip('"') + if is_in_vr_mode == "true": + vr_mode = 1 + else: + vr_mode = 0 # block_mode = int(attributes['type'].strip('"') == 'fiberlookup') # cfg_tuple = (inner_offset, compressed, lowest_level, stop_lvl, block_mode) - cfg_tuple = (compressed, lowest_level, stop_lvl, block_mode, init_blank, spacc_mode) + cfg_tuple = (compressed, lowest_level, stop_lvl, block_mode, vr_mode, init_blank) cfg_kwargs = { # 'inner_offset': inner_offset, 'compressed': compressed, 'lowest_level': lowest_level, 'stop_lvl': stop_lvl, 'block_mode': block_mode, - 'init_blank': init_blank, - 'spacc_mode': spacc_mode + 'vr_mode': vr_mode, + 'init_blank': init_blank + #'spacc_mode': spacc_mode } return cfg_tuple, cfg_kwargs diff --git a/sam/onyx/parse_dot.py b/sam/onyx/parse_dot.py index 7fae6744..b21f553d 100644 --- a/sam/onyx/parse_dot.py +++ b/sam/onyx/parse_dot.py @@ -37,7 +37,7 @@ def __init__(self, filename=None, local_mems=True, use_fork=False, # Rewrite each 3-input joiners to 3 2-input joiners self.rewrite_tri_to_binary() - self.rewrite_spacc_1() + self.rewrite_VectorReducer() # Passes to lower to CGRA self.rewrite_lookup() @@ -111,8 +111,8 @@ def map_nodes(self): hw_nt = f"HWNodeType.Merge" elif n_type == "crdhold": hw_nt = f"HWNodeType.CrdHold" - elif n_type == "spaccumulator": - hw_nt = f"HWNodeType.SpAccumulator" + elif n_type == "vectorreducer": + hw_nt = f"HWNodeType.VectorReducer " else: print(n_type) raise SAMDotGraphLoweringError(f"Node is of type {n_type}") @@ -130,32 +130,32 @@ def find_node_by_name(self, name): return node assert False - def rewrite_spacc_1(self): + def rewrite_VectorReducer(self): - # Get the spacc node and the resulting fiberwrites + # Get the vr node and the resulting fiberwrites nodes_to_proc = [] for node in self.graph.get_nodes(): node_type = node.get_attributes()['type'].strip('"') - if 'spaccumulator' in node_type and '1' in node.get_attributes()['order'].strip('"'): + if 'vectorreducer' in node_type: # nodes_to_proc.append(node.get_name()) nodes_to_proc.append(node) - for spacc_node in nodes_to_proc: + for vr_node in nodes_to_proc: - attrs = spacc_node.get_attributes() + attrs = vr_node.get_attributes() og_label = attrs['label'].strip('"') del attrs['label'] # TODO: Get redux crd - output_crd = attrs['in0'].strip('"') - input_crd = None + output_crd = attrs['accum_index'].strip('"') + #input_crd = None - incoming_edges = [edge for edge in self.graph.get_edges() if edge.get_destination() == spacc_node.get_name()] - outgoing_edges = [edge for edge in self.graph.get_edges() if edge.get_source() == spacc_node.get_name()] + incoming_edges = [edge for edge in self.graph.get_edges() if edge.get_destination() == vr_node.get_name()] + outgoing_edges = [edge for edge in self.graph.get_edges() if edge.get_source() == vr_node.get_name()] in_val_node = None - in_output_node = None - in_input_node = None + in_crd_node = None + #in_input_node = None # Keep these for the edges in_edge_attrs = {} @@ -167,14 +167,14 @@ def rewrite_spacc_1(self): in_val_node = incoming_edge_.get_source() in_edge_attrs[in_val_node] = edge_attr elif edge_attr['type'].strip('"') == 'crd': - edge_comment = edge_attr['comment'].strip('"') - if output_crd in edge_comment: - in_output_node = incoming_edge_.get_source() - in_edge_attrs[in_output_node] = edge_attr - else: - input_crd = edge_comment - in_input_node = incoming_edge_.get_source() - in_edge_attrs[in_input_node] = edge_attr + #edge_comment = edge_attr['comment'].strip('"') + #if output_crd in edge_comment: + in_crd_node = incoming_edge_.get_source() + in_edge_attrs[in_crd_node] = edge_attr + #else: + # input_crd = edge_comment + # in_input_node = incoming_edge_.get_source() + # in_edge_attrs[in_input_node] = edge_attr self.graph.del_edge(incoming_edge_.get_source(), incoming_edge_.get_destination()) # Delete the outgoing edges/attached nodes @@ -190,95 +190,99 @@ def rewrite_spacc_1(self): og_type = attrs['type'] del attrs['type'] - rsg = pydot.Node(f"spacc1_rsg_{self.get_next_seq()}", - **attrs, label=f"{og_label}_rsg", hwnode=f"{HWNodeType.RepSigGen}", - type=og_type) + #rsg = pydot.Node(f"vr_rsg_{self.get_next_seq()}", + # **attrs, label=f"{og_label}_rsg", hwnode=f"{HWNodeType.RepSigGen}", + # type=og_type) - repeat = pydot.Node(f"spacc1_repeat_{self.get_next_seq()}", - **attrs, label=f"{og_label}_repeat", hwnode=f"{HWNodeType.Repeat}", - root="true", type=og_type, spacc="true") + #repeat = pydot.Node(f"vr_repeat_{self.get_next_seq()}", + # **attrs, label=f"{og_label}_repeat", hwnode=f"{HWNodeType.Repeat}", + # root="true", type=og_type, spacc="true") - union = pydot.Node(f"spacc1_union_{self.get_next_seq()}", - **attrs, label=f"{og_label}_union", hwnode=f"{HWNodeType.Intersect}", - type="union") + union = pydot.Node(f"vr_union_{self.get_next_seq()}", label=f"{og_label}_union", hwnode=f"{HWNodeType.Intersect}", + type="union", vector_reduce_mode="true", comment=f"type=union,index={output_crd}", index=output_crd) - add = pydot.Node(f"spacc1_add_{self.get_next_seq()}", - **attrs, label=f"{og_label}_add", hwnode=f"{HWNodeType.Compute}", - type=og_type) + add = pydot.Node(f"vr_add_{self.get_next_seq()}", label=f"{og_label}_Add", hwnode=f"{HWNodeType.Compute}", + type="add", sub="0", comment="type=add,sub=0") - crd_buffet = pydot.Node(f"spacc1_crd_buffet_{self.get_next_seq()}", - **attrs, label=f"{og_label}_crd_buffet", hwnode=f"{HWNodeType.Buffet}", - type=og_type, fa_color=self.fa_color) + crd_buffet = pydot.Node(f"vr_crd_buffet_{self.get_next_seq()}", + label=f"{og_label}_crd_buffet", hwnode=f"{HWNodeType.Buffet}", + type="buffet", vector_reduce_mode="true", fa_color=self.fa_color, comment="crd_buffet") - crd_rd_scanner = pydot.Node(f"spacc1_crd_rd_scanner_{self.get_next_seq()}", - **attrs, label=f"{og_label}_crd_rd_scanner", hwnode=f"{HWNodeType.ReadScanner}", - tensor="x", type=og_type, root="false", format="compressed", - mode="0", index=f"{output_crd}", spacc="true", stop_lvl="0", - fa_color=self.fa_color) + crd_rd_scanner = pydot.Node(f"vr_crd_rd_scanner_{self.get_next_seq()}", + label=f"{og_label}_crd_rd_scanner", hwnode=f"{HWNodeType.ReadScanner}", + tensor="X", type="fiberlookup", root="false", format="compressed", + mode="0", index=f"{output_crd}", vector_reduce_mode="true", fa_color=self.fa_color, comment="crd_rd_scanner") - crd_wr_scanner = pydot.Node(f"spacc1_crd_wr_scanner_{self.get_next_seq()}", - **attrs, label=f"{og_label}_crd_wr_scanner", hwnode=f"{HWNodeType.WriteScanner}", - type=og_type, mode="0", format="compressed", spacc="true", stop_lvl="0", - fa_color=self.fa_color) + crd_wr_scanner = pydot.Node(f"vr_crd_wr_scanner_{self.get_next_seq()}", + label=f"{og_label}_crd_wr_scanner", hwnode=f"{HWNodeType.WriteScanner}", + type="fiberwrite", mode="0", format="compressed", vector_reduce_mode="true", fa_color=self.fa_color, comment="crd_wr_scanner") self.fa_color += 1 - # glb_crd = pydot.Node(f"spacc1_crd_glb_{self.get_next_seq()}", **attrs, + # glb_crd = pydot.Node(f"vr_crd_glb_{self.get_next_seq()}", **attrs, # label=f"{og_label}_glb_crd_read", hwnode=f"{HWNodeType.GLB}", # tensor="x", mode="0", format="compressed", type=og_type) - vals_buffet = pydot.Node(f"spacc1_vals_buffet_{self.get_next_seq()}", - **attrs, label=f"{og_label}_vals_buffet", hwnode=f"{HWNodeType.Buffet}", - type=og_type, fa_color=self.fa_color) - - vals_rd_scanner = pydot.Node(f"spacc1_vals_rd_scanner_{self.get_next_seq()}", - **attrs, label=f"{og_label}_vals_rd_scanner", hwnode=f"{HWNodeType.ReadScanner}", - tensor="x", type=og_type, root="false", format="vals", - mode="vals", spacc="true", stop_lvl="0", fa_color=self.fa_color) - - vals_wr_scanner = pydot.Node(f"spacc1_vals_wr_scanner_{self.get_next_seq()}", - **attrs, label=f"{og_label}_vals_wr_scanner", hwnode=f"{HWNodeType.WriteScanner}", - type=og_type, mode="vals", format="compressed", spacc="true", - stop_lvl="0", fa_color=self.fa_color) - - # glb_vals = pydot.Node(f"spacc1_crd_vals_{self.get_next_seq()}", **attrs, + vals_buffet = pydot.Node(f"vr_vals_buffet_{self.get_next_seq()}", + label=f"{og_label}_vals_buffet", hwnode=f"{HWNodeType.Buffet}", + type="buffet", vector_reduce_mode="true", fa_color=self.fa_color, comment="vals_buffet") + + #vals_rd_scanner = pydot.Node(f"vr_vals_rd_scanner_{self.get_next_seq()}", + # label=f"{og_label}_vals_rd_scanner", hwnode=f"{HWNodeType.ReadScanner}", + # tensor="X", type="arrayvals", root="false", format="vals", + # mode="vals", vector_reduce_mode="true", fa_color=self.fa_color, comment="vals_rd_scanner") + + vals_rd_scanner = pydot.Node(f"vr_vals_rd_scanner_{self.get_next_seq()}", + label=f"{og_label}_vals_rd_scanner", hwnode=f"{HWNodeType.ReadScanner}", + tensor="X", type="fiberlookup", root="false", format="compressed", + mode="1", vector_reduce_mode="true", fa_color=self.fa_color, comment="vals_rd_scanner") + + #vals_wr_scanner = pydot.Node(f"vr_vals_wr_scanner_{self.get_next_seq()}", + # label=f"{og_label}_vals_wr_scanner", hwnode=f"{HWNodeType.WriteScanner}", + # type="fiberwrite", mode="vals", vector_reduce_mode="true", fa_color=self.fa_color, comment="vals_wr_scanner") + + + vals_wr_scanner = pydot.Node(f"vr_vals_wr_scanner_{self.get_next_seq()}", + label=f"{og_label}_vals_wr_scanner", hwnode=f"{HWNodeType.WriteScanner}", + type="fiberwrite", mode="1", format="compressed", vector_reduce_mode="true", fa_color=self.fa_color, comment="vals_wr_scanner") + + + # glb_vals = pydot.Node(f"vr_crd_vals_{self.get_next_seq()}", **attrs, # label=f"{og_label}_glb_vals_read", hwnode=f"{HWNodeType.GLB}", # tensor="x", mode="vals", format="vals", type=og_type) self.fa_color += 1 - self.graph.add_node(rsg) - self.graph.add_node(repeat) + self.graph.add_node(union) self.graph.add_node(add) self.graph.add_node(crd_buffet) self.graph.add_node(crd_rd_scanner) self.graph.add_node(crd_wr_scanner) - # self.graph.add_node(glb_crd) self.graph.add_node(vals_buffet) self.graph.add_node(vals_rd_scanner) self.graph.add_node(vals_wr_scanner) - # self.graph.add_node(glb_vals) - print(in_edge_attrs[in_input_node]) - print(in_edge_attrs[in_output_node]) + #print(in_edge_attrs[in_input_node]) + print(in_edge_attrs[in_crd_node]) print(in_edge_attrs[in_val_node]) - del in_edge_attrs[in_output_node]['comment'] + del in_edge_attrs[in_crd_node]['comment'] del in_edge_attrs[in_val_node]['type'] + del in_edge_attrs[in_crd_node]['type'] # Edges - input_to_rsg_edge = pydot.Edge(src=in_input_node, dst=rsg, **in_edge_attrs[in_input_node]) - rsg_to_repeat = pydot.Edge(src=rsg, dst=repeat) - repeat_to_crd_rd_scan = pydot.Edge(src=repeat, dst=crd_rd_scanner) - crd_rd_scan_to_val_rd_scan = pydot.Edge(src=crd_rd_scanner, dst=vals_rd_scanner) - output_to_union_edge = pydot.Edge(src=in_output_node, dst=union, - **in_edge_attrs[in_output_node], comment=f"in-B") - val_to_union = pydot.Edge(src=in_val_node, dst=union, **in_edge_attrs[in_val_node], - type="ref", comment=f"in-B", val="true") + #input_to_rsg_edge = pydot.Edge(src=in_input_node, dst=rsg, **in_edge_attrs[in_input_node]) + #rsg_to_repeat = pydot.Edge(src=rsg, dst=repeat) + #repeat_to_crd_rd_scan = pydot.Edge(src=repeat, dst=crd_rd_scanner) + #crd_rd_scan_to_val_rd_scan = pydot.Edge(src=crd_rd_scanner, dst=vals_rd_scanner) + in_crd_to_union = pydot.Edge(src=in_crd_node, dst=union, + **in_edge_attrs[in_crd_node], type="crd", comment=f"in-B") + in_val_to_union = pydot.Edge(src=in_val_node, dst=union, **in_edge_attrs[in_val_node], + type="ref", comment=f"in-B", val="true", vector_reduce_mode=True) # type="ref", comment=f"in-C", val="true") - crd_rd_scan_to_union = pydot.Edge(src=crd_rd_scanner, dst=union, type="crd", comment="in-x") - val_rd_scan_to_union = pydot.Edge(src=vals_rd_scanner, dst=union, type="ref", comment="in-x", val="true") + crd_rd_scan_to_union = pydot.Edge(src=crd_rd_scanner, dst=union, type="crd", comment="in-x", vector_reduce_mode=True) + val_rd_scan_to_union = pydot.Edge(src=vals_rd_scanner, dst=union, type="ref", comment="in-x", val="true", vector_reduce_mode=True) union_crd_to_crd_wr_scan = pydot.Edge(src=union, dst=crd_wr_scanner, type="crd") union_val0_to_alu = pydot.Edge(src=union, dst=add, comment='out-B') # union_val0_to_alu = pydot.Edge(src=union, dst=add, comment='out-C') @@ -307,15 +311,22 @@ def rewrite_spacc_1(self): self.graph.del_edge(crd_edge.get_source(), crd_edge.get_destination()) self.graph.del_edge(val_edge.get_source(), val_edge.get_destination()) - crd_rd_scan_to_glb = pydot.Edge(src=crd_rd_scanner, dst=dst_crd, **crd_edge_attr, use_alt_out_port="1") - val_rd_scan_to_glb = pydot.Edge(src=vals_rd_scanner, dst=dst_vals, **val_edge_attr, use_alt_out_port="1") + print(crd_edge_attr) + print(val_edge_attr) + del crd_edge_attr['comment'] + + #crd_rd_scan_to_glb = pydot.Edge(src=crd_rd_scanner, dst=dst_crd, **crd_edge_attr, use_alt_out_port="1") + #val_rd_scan_to_glb = pydot.Edge(src=vals_rd_scanner, dst=dst_vals, **val_edge_attr, use_alt_out_port="1") + + crd_rd_scan_to_ds = pydot.Edge(src=crd_rd_scanner, dst=dst_crd, **crd_edge_attr, comment="final-crd", vector_reduce_mode=True) + val_rd_scan_to_ds = pydot.Edge(src=vals_rd_scanner, dst=dst_vals, **val_edge_attr, comment="final-val", vector_reduce_mode=True) - self.graph.add_edge(input_to_rsg_edge) - self.graph.add_edge(rsg_to_repeat) - self.graph.add_edge(repeat_to_crd_rd_scan) - self.graph.add_edge(crd_rd_scan_to_val_rd_scan) - self.graph.add_edge(output_to_union_edge) - self.graph.add_edge(val_to_union) + #self.graph.add_edge(input_to_rsg_edge) + #self.graph.add_edge(rsg_to_repeat) + #self.graph.add_edge(repeat_to_crd_rd_scan) + #self.graph.add_edge(crd_rd_scan_to_val_rd_scan) + self.graph.add_edge(in_crd_to_union) + self.graph.add_edge(in_val_to_union) self.graph.add_edge(crd_rd_scan_to_union) self.graph.add_edge(val_rd_scan_to_union) self.graph.add_edge(union_crd_to_crd_wr_scan) @@ -326,10 +337,10 @@ def rewrite_spacc_1(self): self.graph.add_edge(val_wr_scan_to_buffet) self.graph.add_edge(crd_rd_scan_to_buffet) self.graph.add_edge(vals_rd_scan_to_buffet) - self.graph.add_edge(crd_rd_scan_to_glb) - self.graph.add_edge(val_rd_scan_to_glb) + self.graph.add_edge(crd_rd_scan_to_ds) + self.graph.add_edge(val_rd_scan_to_ds) - self.graph.del_node(spacc_node) + self.graph.del_node(vr_node) def rewrite_tri_to_binary(self): ''' diff --git a/sam/sim/src/accumulator.py b/sam/sim/src/accumulator.py index a3500369..3dd264b2 100644 --- a/sam/sim/src/accumulator.py +++ b/sam/sim/src/accumulator.py @@ -1,5 +1,6 @@ +import enum + from .base import * -from .crd_manager import CrdPtConverter class Reduce(Primitive): @@ -65,7 +66,7 @@ def update(self): if (self.backpressure_en and self.check_backpressure()) or not self.backpressure_en: if self.backpressure_en: self.data_valid = True - if (len(self.in_val) > 0): + if len(self.in_val) > 0: self.block_start = False curr_in_val = "" @@ -152,262 +153,33 @@ def return_statistics(self): return stats_dict -class SparseCrdPtAccumulator1(Primitive): - def __init__(self, maxdim=100, valtype=float, fifos=None, **kwargs): +# NEW VERSION: Accumulation into a vector +class SparseAccumulator1(Primitive): + def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, depth=1, **kwargs): super().__init__(**kwargs) - - self.outer_crdpt = [] - self.inner_crdpt = [] - self.in_val = [] - - self.curr_in_val = None - self.curr_in_inner_crdpt = None - self.curr_in_outer_crdpt = None - - self.emit_output = [] - self.curr_inner_crdpt = '' - self.curr_outer_crdpt = '' - self.curr_val = '' - - # Maximum possible dimension for this index level + self.kwargs = kwargs self.maxdim = maxdim - self.order = 1 - - self.seen_done = False - # Accumulation scratchpad storage - self.storage = dict() self.valtype = valtype + self.last_level = last_level + # Boolean flag for whether to output stop tokens on the output val stream + self.val_stkn = val_stkn - if fifos is not None and len(fifos) == 3: - self.outer_crdpt = fifos[0] - self.inner_crdpt = fifos[1] - self.in_val = fifos[2] - - if self.get_stats: - self.hits_tracker = {} - self.stop_token_out = 0 - self.drop_token_out = 0 - self.valid_token_out = 0 - self.zero_out = 0 - self.nonzero_out = 0 - self.out_crd_fifo = 0 - self.in_crd_fifo = 0 - self.in_val_fifo = 0 - - def return_fifo(self): - return self.outer_crdpt, self.inner_crdpt, self.in_val - - def update(self): - self.update_done() - if self.debug: - if self.seen_done or self.done: - print(self.seen_done, self.done) - print("@@@", self.outer_crdpt, self.inner_crdpt, self.in_val, self.emit_output, - self.curr_in_outer_crdpt, self.curr_in_inner_crdpt, self.curr_val) - self.print_debug() - if len(self.in_val) > 0 and self.in_val[0] == "D": - print("val", self.outer_crdpt, self.inner_crdpt, self.in_val, self.emit_output, - self.curr_in_outer_crdpt, self.curr_in_inner_crdpt, self.curr_val) - self.print_debug() - if len(self.inner_crdpt) > 0 and self.inner_crdpt[0] == "D": - print("innercrd", self.outer_crdpt, self.inner_crdpt, self.in_val, self.emit_output, - self.curr_in_outer_crdpt, self.curr_in_inner_crdpt, self.curr_val) - self.print_debug() - if len(self.outer_crdpt) > 0 and self.outer_crdpt[0] == "D": - print("outercrd", self.outer_crdpt, self.inner_crdpt, self.in_val, self.emit_output, - self.curr_in_outer_crdpt, self.curr_in_inner_crdpt, self.curr_val) - self.print_debug() - - if len(self.outer_crdpt) > 0 or len(self.inner_crdpt) > 0: - self.block_start = False - - if self.get_stats: - self.out_crd_fifo = max(self.out_crd_fifo, len(self.outer_crdpt)) - self.in_crd_fifo = max(self.in_crd_fifo, len(self.inner_crdpt)) - self.in_val_fifo = max(self.in_val_fifo, len(self.in_val)) - - if self.done: - self.curr_outer_crdpt = '' - self.curr_inner_crdpt = '' - self.curr_val = '' - if self.get_stats: - self.drop_token_out += 1 - return - - if len(self.in_val) > 0 and len(self.outer_crdpt) > 0 and len(self.inner_crdpt) > 0 and not self.seen_done: - self.curr_in_val = self.in_val.pop(0) - self.curr_in_inner_crdpt = self.inner_crdpt.pop(0) - - ocrd = self.outer_crdpt.pop(0) - # if self.curr_in_val == 'D': - # print(self.curr_in_val, self.curr_in_inner_crdpt, ocrd) - # assert self.curr_in_val == "D" and self.curr_in_inner_crdpt == "D" and ocrd == "D" - # print("######", ocrd, self.curr_in_outer_crdpt, self.curr_in_inner_crdpt, self.emit_output) - # print(self.in_val, self.outer_crdpt, self.inner_crdpt, ocrd - # self.curr_in_outer_crdpt, self.curr_in_inner_crdpt, self.curr_in_val) - emit_output = ocrd != self.curr_in_outer_crdpt and self.curr_in_outer_crdpt is not None and \ - self.curr_in_outer_crdpt != "D" - if emit_output: - self.emit_output.append([self.curr_in_outer_crdpt, -1]) - # print("@@@@@", self.curr_in_outer_crdpt) - self.curr_in_outer_crdpt = ocrd - if self.curr_in_outer_crdpt in self.storage.keys(): - inner_dict = self.storage[self.curr_in_outer_crdpt] - if self.get_stats: - for k in inner_dict.keys(): - self.hits_tracker[k] = 1 - if self.curr_in_inner_crdpt in inner_dict.keys(): - if self.get_stats: - self.hits_tracker[self.curr_in_inner_crdpt] += 1 - inner_dict[self.curr_in_inner_crdpt] += self.valtype(self.curr_in_val) - else: - if self.get_stats: - self.hits_tracker[self.curr_in_inner_crdpt] = 1 - inner_dict[self.curr_in_inner_crdpt] = self.valtype(self.curr_in_val) - # If a done token is seen, cannot emit done until all coordinates have been written out - elif self.curr_in_outer_crdpt == 'D': - assert self.curr_in_inner_crdpt == 'D' and self.curr_in_val == 'D', \ - "If one item is a 'D' token, then all inputs must be" - self.seen_done = True - else: - self.storage[self.curr_in_outer_crdpt] = {self.curr_in_inner_crdpt: self.valtype(self.curr_in_val)} - # if self.curr_in_outer_crdpt == "D": - # print("__________", self.emit_output, self.seen_done) - - if len(self.emit_output) > 0: - fiber = self.emit_output[0] - - self.curr_outer_crdpt = fiber[0] - # print("===, ", self.storage) - # print(fiber) - # print(self.emit_output) - # print(self.storage[self.curr_outer_crdpt].keys(), fiber[1]) - self.curr_inner_crdpt = min( - [item for item in self.storage[self.curr_outer_crdpt].keys() if item > fiber[1]]) - self.curr_val = self.storage[self.curr_outer_crdpt][self.curr_inner_crdpt] - - if not [item for item in self.storage[self.curr_outer_crdpt].keys() if item > self.curr_inner_crdpt]: - self.emit_output.pop(0) - else: - self.emit_output[0][1] = self.curr_inner_crdpt - elif self.seen_done: - self.done = True - self.seen_done = False - self.curr_outer_crdpt = 'D' - self.curr_inner_crdpt = 'D' - self.curr_val = 'D' - else: - self.curr_outer_crdpt = '' - self.curr_inner_crdpt = '' - self.curr_val = '' - if self.get_stats: - if self.curr_val == "": - self.drop_token_out += 1 - elif is_stkn(self.curr_val): - self.stop_token_out += 1 - else: - if (isinstance(self.curr_val, float) or isinstance(self.curr_val, int)) and self.curr_val == 0: - self.zero_out += 1 - else: - self.nonzero_out += 1 - self.valid_token_out += 1 - - if self.debug: - print("Done ptaccum:", self.out_done(), self.done, - "\n Curr in ocrd: ", self.curr_in_outer_crdpt, "\t Curr in icrd", self.curr_in_inner_crdpt, - "\t Curr in val", self.curr_in_val, - "\n Curr out ocrd: ", self.curr_outer_crdpt, "\t Curr out icrd: ", self.curr_inner_crdpt, - "\t Curr out val: ", self.curr_val, - "\n Emit crds: ", self.emit_output, - "\n Storage: ", self.storage, - "\n f: ", self.outer_crdpt, self.inner_crdpt, self.in_val) - - def print_debug(self): - print("Crdptaccum_debug Done:", self.out_done(), self.done, - "\n Curr in ocrd: ", self.curr_in_outer_crdpt, "\t Curr in icrd", self.curr_in_inner_crdpt, - "\t Curr in val", self.curr_in_val, - "\n Curr out ocrd: ", self.curr_outer_crdpt, "\t Curr out icrd: ", self.curr_inner_crdpt, - "\t Curr out val: ", self.curr_val, - "\n Emit crds: ", self.emit_output, - "\n Storage: ", self.storage, - "\n Fifos: ", self.outer_crdpt, self.inner_crdpt, self.in_val) - - def set_inner_crdpt(self, crdpt): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.inner_crdpt.append(crdpt) - - def set_outer_crdpt(self, crdpt): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.outer_crdpt.append(crdpt) - - def set_val(self, val): - assert not is_stkn(val), 'Values associated with points should not have stop tokens' - if val != '' and val is not None: - self.in_val.append(val) - - def out_outer_crdpt(self): - return self.curr_outer_crdpt - - def out_inner_crdpt(self): - return self.curr_inner_crdpt - - def out_val(self): - return self.curr_val - - def return_statistics(self): - if self.get_stats: - stats_dict = {"stkn_outs": self.stop_token_out, - "drop_outs": self.drop_token_out, "valid_outs": self.valid_token_out, - "zero_outs": self.zero_out, "nonzero_outs": self.nonzero_out} - stats_dict.update(super().return_statistics()) - else: - stats_dict = {} - return stats_dict - - def return_hits(self): - i = 0 - cnt_gt_zero = 0 - cnt_total = 0 - total_sum = 0 - if self.get_stats: - for k in self.hits_tracker.keys(): - if self.hits_tracker[k] > i: - i = self.hits_tracker[k] - if self.hits_tracker[k] > 1: - cnt_gt_zero += 1 - total_sum += self.hits_tracker[k] - cnt_total += 1 - return i, cnt_gt_zero, cnt_total, total_sum - - -# Accumulation into a vector -class SparseAccumulator1(Primitive): - def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, depth=1, **kwargs): - super().__init__(**kwargs) - self.in_outer_crdpt = [] - self.in_inner_crdpt = [] + self.in_crd1 = [] + self.in_crd0 = [] self.in_val = [] - self.crdpt_spacc = SparseCrdPtAccumulator1(maxdim=maxdim, valtype=valtype, debug=self.debug, - statisics=self.get_stats, name="", back_en=False) - self.crdpt_converter = CrdPtConverter(last_level=last_level, debug=self.debug, - statisics=self.get_stats, name="", back_en=False) - self.crdpt_spacc_out_val = [] + self.storage = {} - self.curr_outer_crd = None - self.curr_inner_crd = None + self.curr_crd1 = None + self.curr_crd0 = None self.curr_val = None - self.outer_crdpt = [] - self.inner_crdpt = [] - - self.val_stkn = val_stkn + self.curr_in_crd0 = None + self.curr_in_val = None if self.get_stats: - self.in_outer_crd_pt_fifo = 0 - self.in_inner_crd_pt_fifo = 0 + self.in_crd0_fifo = 0 + self.in_crd1_fifo = 0 self.in_val_fifo = 0 if self.backpressure_en: @@ -418,9 +190,14 @@ def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, d self.fifo_avail_outer = True self.fifo_avail_val = True - self.temp_maxdim = maxdim - self.temp_valtype = valtype - self.temp_last_level = last_level + self.states = enum.Enum('States', ['READY', 'ACC', 'WR', 'DONE']) + self.curr_state = self.states.READY + self.next_state = self.states.READY + self.writeout = False + self.writeout_storage = [] + + self.seen_done = False + self.crd1_stkn = None def check_backpressure(self): if self.backpressure_en: @@ -455,169 +232,185 @@ def add_child(self, child=None, branch=""): def update_ready(self): if self.backpressure_en: - if len(self.in_inner_crdpt) > self.depth: - self.fifo_avail_inner = False + self.fifo_avail_outer = not (len(self.in_crd1) > self.depth) + self.fifo_avail_inner = not (len(self.in_crd0) > self.depth) + self.fifo_avail_val = not (len(self.in_val) > self.depth) + + def ACC_body(self): + self.curr_in_crd0 = self.in_crd0.pop(0) + self.curr_in_val = self.in_val.pop(0) + # In accumulation, accumulate into memory + if is_nc_tkn(self.curr_in_val, self.valtype): + assert is_nc_tkn(self.curr_in_crd0, int), "The inner coordinate must be a non-control token" + if self.curr_in_crd0 in self.storage.keys(): + # Coordinate is in storage, so accumulate + self.storage[self.curr_in_crd0] += self.curr_in_val else: - self.fifo_avail_inner = True - if len(self.in_outer_crdpt) > self.depth: - self.fifo_avail_outer = False - else: - self.fifo_avail_outer = True - if len(self.in_val) > self.depth: - self.fifo_avail_val = False - else: - self.fifo_avail_val = True + # Coordinate is not in storage, so add it in + self.storage[self.curr_in_crd0] = self.curr_in_val + self.next_state = self.states.ACC + # In accumulation, if you see a stop token in the inner level, go back to start + elif is_stkn(self.curr_in_crd0): + assert is_stkn(self.curr_in_val) and stkn_order(self.curr_in_crd0) == stkn_order(self.curr_in_val), \ + "Stop tokens must match for inner crd: " + str(self.curr_in_crd0) + " and val: " + str(self.curr_in_val) + self.next_state = self.states.READY + elif is_dtkn(self.curr_in_crd0): + assert False, "Shouldn't have done token for coordinates if in accumulate (ACC) state" + # Do nothing + else: + self.next_state = self.states.ACC def update(self): self.update_done() self.update_ready() + + # Print out debugging statements + if self.debug: + print("========== " + self.name + " SPACC1 (NEW) ==========") + print("Inputs: ", self.in_crd1, self.in_crd0, self.in_val) + print("Temps: ", self.curr_crd1, self.crd1_stkn, self.curr_in_crd0, self.curr_in_val) + print("Store/Wr: ", self.storage, self.writeout_storage, self.writeout) + print("Outputs: ", self.curr_crd0, self.curr_val) + print("State: ", self.curr_state) + if self.backpressure_en: self.data_valid = False if (self.backpressure_en and self.check_backpressure()) or not self.backpressure_en: - if self.backpressure_en: - self.data_valid = True - if self.debug: - print(self.in_outer_crdpt, self.in_inner_crdpt, self.in_val) - print(self.crdpt_spacc.print_debug()) - print(self.crdpt_converter.print_debug()) - if self.done: - f1, f2, f3 = self.crdpt_spacc.return_fifo() - f4, f5 = self.crdpt_converter.return_fifo() - self.crdpt_spacc = SparseCrdPtAccumulator1(maxdim=self.temp_maxdim, - valtype=self.temp_valtype, fifos=[f1, f2, f3]) - self.crdpt_converter = CrdPtConverter(last_level=self.temp_last_level, fifos=[f4, f5]) + # Update state of state machine to next state + self.curr_state = self.next_state # FIXME: (owhsu) self.data_ready not defined in init if self.backpressure_en: + self.data_valid = True self.data_ready = True - if len(self.in_outer_crdpt) > 0 or len(self.in_inner_crdpt) > 0: + + if self.done: + # Reset things + # fch1, fch2 = self.crdhold_01.return_fifo() + # fs1, fs2, fs3 = self.spacc1_no_crdhold.return_fifo() + # fsd1 = self.stkndrop_crd1.return_fifo() + # fsd2 = self.stkndrop_crd0.return_fifo() + # fsd3 = self.stkndrop_val.return_fifo() + # self.crdhold_01 = CrdHold(fifos=[fch1, fch2], **self.kwargs) + # + # self.spacc1_no_crdhold = SpAcc1NoCrdHold(maxdim=self.maxdim, valtype=self.valtype, + # name=self.name + "_no_crdhold", + # fifos=[fs1, fs2, fs3], **self.kwargs) + # self.stkndrop_crd1 = StknDrop(fifos=[fsd1], **self.kwargs) + # self.stkndrop_crd0 = StknDrop(fifos=[fsd2], **self.kwargs) + # self.stkndrop_val = StknDrop(fifos=[fsd3], **self.kwargs) + pass + + # Set when block counts should start + if len(self.in_crd1) > 0 or len(self.in_crd0) > 0 or len(self.in_val) > 0: self.block_start = False - # What to do for drop tokens? + # Store block statistics if asked to be reported if self.get_stats: - self.in_outer_crd_pt_fifo = max(self.in_outer_crd_pt_fifo, len(self.in_outer_crdpt)) - self.in_inner_crd_pt_fifo = max(self.in_inner_crd_pt_fifo, len(self.in_inner_crdpt)) - self.in_val_fifo = max(self.in_val_fifo, len(self.in_val)) - - if len(self.in_outer_crdpt) > 0: - self.crdpt_spacc.set_outer_crdpt(self.in_outer_crdpt.pop(0)) - - if len(self.in_inner_crdpt) > 0: - self.crdpt_spacc.set_inner_crdpt(self.in_inner_crdpt.pop(0)) - - if len(self.in_val) > 0: - self.crdpt_spacc.set_val(self.in_val.pop(0)) - - self.crdpt_spacc.update() - print(">>>>>>>>>>>>SPACC:", self.crdpt_spacc.out_outer_crdpt(), self.crdpt_spacc.out_inner_crdpt()) - self.crdpt_converter.set_outer_crdpt(self.crdpt_spacc.out_outer_crdpt()) - self.crdpt_converter.set_inner_crdpt(self.crdpt_spacc.out_inner_crdpt()) - - if self.crdpt_spacc.out_val() != '': - self.crdpt_spacc_out_val.append(self.crdpt_spacc.out_val()) - - self.crdpt_converter.update() - self.curr_outer_crd = self.crdpt_converter.out_crd_outer() - self.curr_inner_crd = self.crdpt_converter.out_crd_inner() - - if self.val_stkn: - self.curr_val = self.crdpt_spacc_out_val.pop(0) if isinstance(self.curr_inner_crd, int) and \ - len(self.crdpt_spacc_out_val) > 0 else self.curr_inner_crd + # What to do for drop tokens? + pass + + # Begin state machine computation + if self.curr_state == self.states.READY: + if len(self.in_crd1) > 0: + self.curr_crd1 = self.in_crd1.pop(0) + if is_nc_tkn(self.curr_crd1): + if len(self.in_crd0) > 0 and len(self.in_val) > 0: + self.ACC_body() + else: + self.next_state = self.states.ACC + elif is_stkn(self.curr_crd1): + # TODO: what to do when we want to writeout but writeout isn't done + + # Set writeout to be true, move over storage, and clear it. + self.crd1_stkn = self.curr_crd1 + self.writeout = True + self.writeout_storage = [item for item in sorted(self.storage.items())] + self.storage = {} + self.next_state = self.states.READY + elif is_dtkn(self.curr_crd1): + self.seen_done = True + if self.writeout: + self.next_state = self.states.WR + else: + self.next_state = self.states.DONE + else: + assert False, "Cannot have a coordinate token of this type: " + str(self.curr_crd1) + # Handle accumulation into storage + elif self.curr_state == self.states.ACC: + if len(self.in_crd0) > 0 and len(self.in_val) > 0: + self.ACC_body() + # Finish writeout and then be done. + elif self.curr_state == self.states.WR: + if not self.writeout: + self.next_state = self.states.DONE + else: + self.next_state = self.states.WR + # See a done signal AND writeout is done + # Stay done until reset + elif self.curr_state == self.states.DONE: + self.done = True + self.next_state = self.states.DONE + # Default to the current state else: - self.curr_val = self.crdpt_spacc_out_val.pop(0) if len(self.crdpt_spacc_out_val) > 0 else '' - - if self.debug: - print(self.in_val) + self.next_state = self.curr_state + + # Writeout is true, so writeout the current values for storage + if self.writeout: + # Writeout is done when there are no elements left + if len(self.writeout_storage) == 0: + self.writeout = False + assert self.crd1_stkn is not None, "The current writeout stop token should not be None" + self.curr_crd0 = self.crd1_stkn + self.curr_val = self.crd1_stkn + else: + curr_writeout_elem = self.writeout_storage.pop(0) + self.curr_val = curr_writeout_elem[1] + self.curr_crd0 = curr_writeout_elem[0] + elif self.done: + self.curr_val = 'D' + self.curr_crd0 = 'D' + else: + self.curr_val = "" + self.curr_crd0 = "" - self.done = self.crdpt_spacc.out_done() and self.crdpt_converter.out_done() + # Update the current state + self.curr_state = self.next_state if self.debug: - print("Vals: ", self.in_val, "\n Done:", self.done, - "\n SpCrdPt Accum Done:", self.crdpt_spacc.out_done(), - "\t CrdPtConverter Done:", self.crdpt_converter.out_done() - ) - - def set_inner_crdpt(self, crdpt, parent=None): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.in_inner_crdpt.append(crdpt) - if self.backpressure_en: - parent.set_backpressure(self.fifo_avail_inner) - - def set_outer_crdpt(self, crdpt, parent=None): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.in_outer_crdpt.append(crdpt) - if self.backpressure_en: - parent.set_backpressure(self.fifo_avail_outer) + print(self.in_crd1, self.in_crd0, self.in_val) + print(self.curr_crd1, self.curr_crd0, self.curr_val) - def crd_in_inner(self, crdpt, parent=None): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.in_inner_crdpt.append(crdpt) + def set_in_crd0(self, crd, parent=None): + if crd != '' and crd is not None: + self.in_crd0.append(crd) if self.backpressure_en: parent.set_backpressure(self.fifo_avail_inner) - def crd_in_outer(self, crdpt, parent=None): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.in_outer_crdpt.append(crdpt) - if self.backpressure_en: - parent.set_backpressure(self.fifo_avail_outer) - - def set_crd_inner(self, crdpt, parent=None): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.in_inner_crdpt.append(crdpt) - if self.backpressure_en: - parent.set_backpressure(self.fifo_avail_inner) - - def set_crd_outer(self, crdpt, parent=None): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.in_outer_crdpt.append(crdpt) + def set_in_crd1(self, crd, parent=None): + if crd != '' and crd is not None: + self.in_crd1.append(crd) if self.backpressure_en: parent.set_backpressure(self.fifo_avail_outer) def set_val(self, val, parent=None): - assert not is_stkn(val), 'Values associated with points should not have stop tokens' if val != '' and val is not None: self.in_val.append(val) if self.backpressure_en: parent.set_backpressure(self.fifo_avail_val) - def out_outer_crd(self): + def out_crd0(self): if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_outer_crd - - def out_inner_crd(self): - if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_inner_crd + return self.curr_crd0 def out_val(self): if (self.backpressure_en and self.data_valid) or not self.backpressure_en: return self.curr_val - def out_crd_outer(self): - if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_outer_crd - - def out_crd_inner(self): - if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_inner_crd - def return_statistics(self): if self.get_stats: stats_dict = {} - stats_dict["in_outer_fifo"] = self.in_outer_crd_pt_fifo - stats_dict["in_inner_fifo"] = self.in_inner_crd_pt_fifo - stats_dict["in_val_fifo"] = self.in_val_fifo - hits_info = self.crdpt_spacc.return_hits() - stats_dict["max_hits"] = hits_info[0] - stats_dict["hits_gt_one"] = hits_info[1] - stats_dict["total_elems"] = hits_info[2] - stats_dict["rmw_ops"] = hits_info[3] - stats_dict.update(self.crdpt_spacc.return_statistics()) + # TODO: Finish adding in other statistics stats_dict.update(super().return_statistics()) else: stats_dict = {} @@ -627,221 +420,57 @@ def print_fifos(self): print("Spaccumulator: None available") -class SparseCrdPtAccumulator2(Primitive): - def __init__(self, maxdim=100, valtype=float, **kwargs): +# NEW VERSION: Accumulation into a matrix +class SparseAccumulator2(Primitive): + def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, depth=1, **kwargs): super().__init__(**kwargs) - self.in_crdpt0 = [] - self.in_crdpt1 = [] - self.in_val = [] - - self.curr_in_val = None - self.curr_in0_crdpt = None - self.curr_in1_crdpt = None - - self.emit_output = [] - self.curr_crdpt0 = '' - self.curr_crdpt1 = '' - self.curr_val = '' - - # Maximum possible dimension for this index level + self.kwargs = kwargs self.maxdim = maxdim - self.order = 1 - - self.seen_done = False - # Accumulation scratchpad storage - self.storage = dict() self.valtype = valtype + self.last_level = last_level + # Boolean flag for whether to output stop tokens on the output val stream + self.val_stkn = val_stkn - if self.get_stats: - self.hits_tracker = {} - self.stop_token_out = 0 - self.drop_token_out = 0 - self.valid_token_out = 0 - self.zero_out = 0 - self.nonzero_out = 0 - - def return_fifo(self): - return self.in_crdpt0, self.in_crdpt1, self.in_val - - def update(self): - self.update_done() - if len(self.in_crdpt0) > 0 or len(self.in_crdpt0) > 0 or len(self.in_val) > 0: - self.block_start = False - - if self.done: - self.curr_crdpt0 = '' - self.curr_crdpt1 = '' - self.curr_val = '' - if self.get_stats: - self.drop_token_out += 1 - return - - if len(self.in_val) > 0 and len(self.in_crdpt1) > 0 and len(self.in_crdpt0) > 0: - self.curr_in_val = self.in_val.pop(0) - self.curr_in0_crdpt = self.in_crdpt0.pop(0) - self.curr_in1_crdpt = self.in_crdpt1.pop(0) - - emit_output = self.curr_in1_crdpt == 'D' - if emit_output: - self.emit_output.append([-1, -1]) - assert self.curr_in1_crdpt == 'D' and self.curr_in0_crdpt == 'D' and self.curr_in_val == 'D', \ - "If one item is a 'D' token, then all inputs must be" - self.seen_done = True - else: - if self.curr_in1_crdpt in self.storage.keys(): - inner_dict = self.storage[self.curr_in1_crdpt] - if self.get_stats: - for k in inner_dict.keys(): - self.hits_tracker[k] = 1 - if self.curr_in0_crdpt in inner_dict.keys(): - if self.get_stats: - self.hits_tracker[self.curr_in0_crdpt] += 1 - inner_dict[self.curr_in0_crdpt] += self.valtype(self.curr_in_val) - else: - if self.get_stats: - self.hits_tracker[self.curr_in0_crdpt] = 1 - inner_dict[self.curr_in0_crdpt] = self.valtype(self.curr_in_val) - else: - self.storage[self.curr_in1_crdpt] = {self.curr_in0_crdpt: self.valtype(self.curr_in_val)} - - if len(self.emit_output) > 0: - fiber = self.emit_output.pop(0) - # - key1 = min( - [item for item in self.storage.keys() if item > fiber[0]]) - key0 = min( - [item for item in self.storage[key1].keys() if item > fiber[1]]) - - self.curr_crdpt1 = key1 - self.curr_crdpt0 = key0 - self.curr_val = self.storage[key1][key0] - - # Finished inner coordinates, increment outer coordinate - if not [item for item in self.storage[key1].keys() if item > key0]: - # Do not increment outer coordinate if it's the last one - if [item for item in self.storage.keys() if item > key1]: - self.emit_output.append([key1, -1]) - # Do inner coordinates - else: - self.emit_output.append([fiber[0], key0]) - - elif self.seen_done: - self.done = True - self.seen_done = False - self.curr_crdpt0 = 'D' - self.curr_crdpt1 = 'D' - self.curr_val = 'D' - else: - self.curr_crdpt0 = '' - self.curr_crdpt1 = '' - self.curr_val = '' - - if self.get_stats: - if self.curr_val == "": - self.drop_token_out += 1 - elif is_stkn(self.curr_val): - self.stop_token_out += 1 - else: - if (isinstance(self.curr_val, float) or isinstance(self.curr_val, int)) and self.curr_val == 0: - self.zero_out += 1 - else: - self.nonzero_out += 1 - self.valid_token_out += 1 - - if self.debug: - print("Done:", self.out_done(), - "\n Curr in crd1: ", self.curr_in1_crdpt, - "\t Curr in crd0", self.curr_in0_crdpt, - "\t Curr in val", self.curr_in_val, - "\n Curr out crd1: ", self.curr_crdpt1, - "\t Curr out crd0: ", self.curr_crdpt0, - "\t Curr out val: ", self.curr_val, - "\n Emit crds: ", self.emit_output, - "\n Storage: ", self.storage) - - def set_inner_crdpt(self, crdpt): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.in_crdpt0.append(crdpt) - - def set_outer_crdpt(self, crdpt): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.in_crdpt1.append(crdpt) - - def set_val(self, val): - assert not is_stkn(val), 'Values associated with points should not have stop tokens' - if val != '' and val is not None: - self.in_val.append(val) - - def out_outer_crdpt(self): - return self.curr_crdpt1 - - def out_inner_crdpt(self): - return self.curr_crdpt0 - - def out_val(self): - return self.curr_val - - def return_hits(self): - i = 0 - cnt_gt_zero = 0 - cnt_total = 0 - for k in self.hits_tracker.keys(): - if self.hits_tracker[k] > i: - i = self.hits_tracker[k] - if self.hits_tracker[k] > 1: - cnt_gt_zero += 1 - cnt_total += 1 - return i, cnt_gt_zero, cnt_total - - def return_statistics(self): - if self.get_stats: - stats_dict = {"stkn_outs": self.stop_token_out, - "drop_outs": self.drop_token_out, "valid_outs": self.valid_token_out, - "zero_outs": self.zero_out, "nonzero_outs": self.nonzero_out} - stats_dict.update(super().return_statistics()) - else: - stats_dict = {} - return stats_dict - - -# Accumulation into a matrix (2D) -class SparseAccumulator2(Primitive): - def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, depth=1, **kwargs): - super().__init__(**kwargs) - self.in1_crdpt = [] - self.in0_crdpt = [] + self.in_crd2 = [] + self.in_crd1 = [] + self.in_crd0 = [] self.in_val = [] - self.crdpt_spacc = SparseCrdPtAccumulator2(maxdim=maxdim, valtype=valtype, **kwargs) - self.crdpt_converter = CrdPtConverter(last_level=True, **kwargs) - - self.crdpt_spacc_out_val = [] + self.storage = {} - self.curr_1_crd = None - self.curr_0_crd = None + self.curr_crd2 = None + self.curr_crd1 = None + self.curr_crd0 = None self.curr_val = None - self.outer_crdpt = [] - self.inner_crdpt = [] + self.curr_in_crd1 = None + self.curr_in_crd0 = None + self.curr_in_val = None + + self.states = enum.Enum('States', ['READY', 'ACC1', 'ACC0', 'WR', 'DONE']) + self.curr_state = self.states.READY + self.next_state = self.states.READY + self.writeout0 = False + self.writeout1 = False + self.writeout_storage1 = [] + self.writeout_storage0 = [] + + self.seen_done = False + self.crd2_stkn = None - self.val_stkn = val_stkn if self.get_stats: - self.in1_fifo = 0 - self.in0_fifo = 0 - self.inval_fifo = 0 + self.in_crd0_fifo = 0 + self.in_crd1_fifo = 0 + self.in_val_fifo = 0 if self.backpressure_en: self.ready_backpressure = True self.data_valid = True self.depth = depth - self.fifo_avail_inner = True - self.fifo_avail_outer = True + self.fifo_avail_2 = True + self.fifo_avail_1 = True + self.fifo_avail_0 = True self.fifo_avail_val = True - self.temp_maxdim = maxdim - self.temp_valtype = valtype - self.temp_last_level = last_level def check_backpressure(self): if self.backpressure_en: @@ -854,6 +483,20 @@ def set_backpressure(self, backpressure): if not backpressure: self.ready_backpressure = False + # FIXME: (owhsu) This code is unreachable + def fifo_available(self, br=""): + assert False + if self.backpressure_en: + if br == "inner": + # and len(self.in_inner_crdpt) > self.depth: + return self.fifo_avail_inner + if br == "outer": # and len(self.in_outer_crdpt) > self.depth: + return self.fifo_avail_outer # return False + if br == "val": # and len(self.in_val) > self.depth: + return self.fifo_avail_val # return False + # return True + return True + def add_child(self, child=None, branch=""): if self.backpressure_en: if child is not None: @@ -862,110 +505,261 @@ def add_child(self, child=None, branch=""): def update_ready(self): if self.backpressure_en: - if len(self.in0_crdpt) > self.depth: - self.fifo_avail_inner = False - else: - self.fifo_avail_inner = True - if len(self.in1_crdpt) > self.depth: - self.fifo_avail_outer = False + self.fifo_avail_outer = not (len(self.in_crd1) > self.depth) + self.fifo_avail_inner = not (len(self.in_crd0) > self.depth) + self.fifo_avail_val = not (len(self.in_val) > self.depth) + + def print_debug(self): + print("========== " + self.name + " SPACC2 (NEW) ==========") + print("Inputs: ", self.in_crd2, self.in_crd1, self.in_crd0, self.in_val) + print("Temps: ", self.curr_crd2, self.crd2_stkn, self.curr_in_crd1, self.curr_in_crd0, self.curr_in_val) + print("Store/Wr: ", self.storage, self.writeout_storage1, self.writeout_storage0, self.writeout1, + self.writeout0) + print("Outputs: ", self.curr_crd1, self.curr_crd0, self.curr_val) + print("State: ", self.curr_state, self.next_state) + + def get_writout(self): + return self.writeout0 or self.writeout1 + + def build_writeout(self): + result = [] + for crd1 in sorted(self.storage.keys()): + for crd0, val in self.storage[crd1].items(): + result.append((crd0, val)) + result.append(('S0', 'S0')) + # Remove last stop token + return result[:-1] + + def update_storage(self, crd1, crd0, val): + if crd1 not in self.storage.keys(): + self.storage[crd1] = {crd0: val} + else: + assert isinstance(self.storage[crd1], dict), "Storage must be a dictionary of dictionaries" + if crd0 not in self.storage[crd1].keys(): + self.storage[crd1][crd0] = val else: - self.fifo_avail_outer = True - if len(self.in_val) > self.depth: - self.fifo_avail_val = False + self.storage[crd1][crd0] += val + + def ACC1_body(self): + # In accumulation, accumulate into memory + self.curr_in_crd1 = self.in_crd1.pop(0) + + # All elements are ready + if is_nc_tkn(self.curr_in_crd1): + if len(self.in_crd0) > 0 and len(self.in_val) > 0: + self.ACC0_body() else: - self.fifo_avail_val = True + self.next_state = self.states.ACC0 + elif is_stkn(self.curr_in_crd1): + self.next_state = self.states.READY + elif is_dtkn(self.curr_in_crd1): + assert False, "Shouldn't have done token for coordinates if in accumulate (ACC) state" + else: + assert False, "Cannot have a coordinate token of this type: " + str(self.curr_in_crd1) + + def ACC0_body(self): + self.curr_in_crd0 = self.in_crd0.pop(0) + self.curr_in_val = self.in_val.pop(0) + + if is_nc_tkn(self.curr_in_val, self.valtype): + assert is_nc_tkn(self.curr_in_crd0, int), "The inner coordinate must be a non-control token" + self.update_storage(self.curr_in_crd1, self.curr_in_crd0, self.curr_in_val) + self.next_state = self.states.ACC0 + # In accumulation, if you see a stop token in the inner level, go back to start + elif is_stkn(self.curr_in_crd0): + assert is_stkn(self.curr_in_val) and stkn_order(self.curr_in_crd0) == stkn_order(self.curr_in_val), \ + "Stop tokens must match for inner crd: " + str(self.curr_in_crd0) + " and val: " + str(self.curr_in_val) + self.next_state = self.states.ACC1 + elif is_dtkn(self.curr_in_crd0): + assert False, "Shouldn't have done token for coordinates if in accumulate (ACC) state" + # Do nothing + else: + assert False, "Cannot have a coordinate token of this type: " + str(self.curr_in_crd0) def update(self): self.update_done() self.update_ready() + + # Print out debugging statements + if self.debug: + self.print_debug() + if self.backpressure_en: self.data_valid = False if (self.backpressure_en and self.check_backpressure()) or not self.backpressure_en: - if self.done: - f1, f2, f3 = self.crdpt_spacc.return_fifo() - f4, f5 = self.crdpt_converter.return_fifo() - self.crdpt_spacc = SparseCrdPtAccumulator2(maxdim=self.temp_maxdim, valtype=self.temp_valtype, - fifos=[f1, f2, f3]) - self.crdpt_converter = CrdPtConverter(last_level=self.temp_last_level, fifos=[f4, f5]) + # Update state of state machine to next state + self.curr_state = self.next_state + + # FIXME: (owhsu) self.data_ready not defined in init if self.backpressure_en: self.data_valid = True - if (len(self.in1_crdpt) > 0 or len(self.in0_crdpt) > 0 or len(self.in_val) > 0): + self.data_ready = True + + if self.done: + # Reset things + # fch1, fch2 = self.crdhold_01.return_fifo() + # fs1, fs2, fs3 = self.spacc1_no_crdhold.return_fifo() + # fsd1 = self.stkndrop_crd1.return_fifo() + # fsd2 = self.stkndrop_crd0.return_fifo() + # fsd3 = self.stkndrop_val.return_fifo() + # self.crdhold_01 = CrdHold(fifos=[fch1, fch2], **self.kwargs) + # + # self.spacc1_no_crdhold = SpAcc1NoCrdHold(maxdim=self.maxdim, valtype=self.valtype, + # name=self.name + "_no_crdhold", + # fifos=[fs1, fs2, fs3], **self.kwargs) + # self.stkndrop_crd1 = StknDrop(fifos=[fsd1], **self.kwargs) + # self.stkndrop_crd0 = StknDrop(fifos=[fsd2], **self.kwargs) + # self.stkndrop_val = StknDrop(fifos=[fsd3], **self.kwargs) + pass + + # Set when block counts should start + if len(self.in_crd1) > 0 or len(self.in_crd0) > 0 or len(self.in_val) > 0: self.block_start = False + # Store block statistics if asked to be reported if self.get_stats: - self.compute_fifo() - - if len(self.in1_crdpt) > 0: - self.crdpt_spacc.set_outer_crdpt(self.in1_crdpt.pop(0)) - - if len(self.in0_crdpt) > 0: - self.crdpt_spacc.set_inner_crdpt(self.in0_crdpt.pop(0)) - - if len(self.in_val) > 0: - self.crdpt_spacc.set_val(self.in_val.pop(0)) - - self.crdpt_spacc.update() - - self.crdpt_converter.set_inner_crdpt(self.crdpt_spacc.out_inner_crdpt()) - self.crdpt_converter.set_outer_crdpt(self.crdpt_spacc.out_outer_crdpt()) - self.crdpt_converter.update() - - if self.crdpt_spacc.out_val() != '': - self.crdpt_spacc_out_val.append(self.crdpt_spacc.out_val()) + # What to do for drop tokens? + pass + + # Begin state machine computation + # READY State + # Accepts crd2 token + if self.curr_state == self.states.READY: + if len(self.in_crd2) > 0: + self.curr_crd2 = self.in_crd2.pop(0) + if is_nc_tkn(self.curr_crd2): + if len(self.in_crd1) > 0: + self.ACC1_body() + else: + self.next_state = self.states.ACC1 + elif is_stkn(self.curr_crd2) and not self.get_writout(): + # Set writeout to be true, move over storage, and clear it. + self.crd2_stkn = self.curr_crd2 + self.writeout1 = True + self.writeout0 = True + self.writeout_storage1 = [k for k in sorted(self.storage.keys())] + self.writeout_storage0 = self.build_writeout() + self.storage = {} + self.next_state = self.states.READY + elif is_stkn(self.curr_crd2): + # Wait for previous writeout to be done + self.next_state = self.states.WR + elif is_dtkn(self.curr_crd2): + self.seen_done = True + if self.get_writout(): + self.next_state = self.states.WR + else: + self.next_state = self.states.DONE + else: + assert False, "Cannot have a coordinate token of this type: " + str(self.curr_crd2) + # Handle accumulation into storage + # Accepts crd1 token + elif self.curr_state == self.states.ACC1: + if len(self.in_crd1) > 0: + self.ACC1_body() + else: + self.next_state = self.states.ACC1 + elif self.curr_state == self.states.ACC0: + if len(self.in_crd0) > 0 and len(self.in_val) > 0: + self.ACC0_body() + else: + self.next_state = self.states.ACC0 + # Finish writeout and then be done or go back to ready state + elif self.curr_state == self.states.WR: + if not self.get_writout() and self.seen_done: + self.next_state = self.states.DONE + elif not self.get_writout(): + self.next_state = self.states.READY + else: + self.next_state = self.states.WR + # See a done signal AND writeout is done + # Stay done until reset + elif self.curr_state == self.states.DONE: + self.done = True + self.next_state = self.states.DONE + # Default to the current state + else: + self.next_state = self.curr_state + + # Writeout is true, so writeout the current values for storage + if self.get_writout(): + # Writeout is done when there are no elements left + # Writeout outer (crd1) level coordinates + if self.writeout1: + if len(self.writeout_storage1) == 0: + self.writeout1 = False + assert self.crd2_stkn is not None, "The current writeout stop token should not be None" + self.curr_crd1 = self.crd2_stkn + else: + curr_writeout_elem1 = self.writeout_storage1.pop(0) + self.curr_crd1 = curr_writeout_elem1 + else: + self.curr_crd1 = "" - self.curr_1_crd = self.crdpt_converter.out_crd_outer() - self.curr_0_crd = self.crdpt_converter.out_crd_inner() + # Writeout inner (crd0) level coordinates + if self.writeout0: + if len(self.writeout_storage0) == 0: + self.writeout0 = False + assert self.crd2_stkn is not None, "The current writeout stop token should not be None" + self.curr_crd0 = increment_stkn(self.crd2_stkn) - if self.val_stkn: - self.curr_val = self.crdpt_spacc_out_val.pop(0) if isinstance(self.curr_0_crd, int) and \ - len(self.crdpt_spacc_out_val) > 0 else self.curr_0_crd + self.curr_val = increment_stkn(self.crd2_stkn) + else: + curr_writeout_elem0 = self.writeout_storage0.pop(0) + self.curr_crd0 = curr_writeout_elem0[0] + self.curr_val = curr_writeout_elem0[1] else: - self.curr_val = self.crdpt_spacc_out_val.pop(0) if len(self.crdpt_spacc_out_val) > 0 else '' + self.curr_crd0 = "" + self.curr_val = "" - if self.debug: - print(self.in_val) + elif self.done: + self.curr_val = 'D' + self.curr_crd0 = 'D' + self.curr_crd1 = 'D' + else: + self.curr_val = "" + self.curr_crd0 = "" + self.curr_crd1 = "" - self.done = self.crdpt_spacc.out_done() and self.crdpt_converter.out_done() + # Update the current state + self.curr_state = self.next_state if self.debug: - print("Done:", self.done, - "\n SpCrdPt Accum Done:", self.crdpt_spacc.out_done(), - "\t CrdPtConv 01 Done:", self.crdpt_converter.out_done() - ) - - def compute_fifo(self): - self.in1_fifo = max(self.in1_fifo, len(self.in1_crdpt)) - self.in0_fifo = max(self.in0_fifo, len(self.in0_crdpt)) - self.inval_fifo = max(self.inval_fifo, len(self.in_val)) - - def set_crd_inner(self, crdpt, parent=None): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.in0_crdpt.append(crdpt) + print(self.in_crd1, self.in_crd0, self.in_val) + print(self.curr_crd1, self.curr_crd0, self.curr_val) + print("====== SPACC2 END =======") + + def set_in_crd0(self, crd, parent=None): + if super().valid_token(crd, int): + self.in_crd0.append(crd) if self.backpressure_en: - parent.set_backpressure(self.fifo_avail_inner) + parent.set_backpressure(self.fifo_avail_0) - def set_crd_outer(self, crdpt, parent=None): - assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' - if crdpt != '' and crdpt is not None: - self.in1_crdpt.append(crdpt) + def set_in_crd1(self, crd, parent=None): + if super().valid_token(crd, int): + self.in_crd1.append(crd) if self.backpressure_en: - parent.set_backpressure(self.fifo_avail_outer) + parent.set_backpressure(self.fifo_avail_1) + + def set_in_crd2(self, crd, parent=None): + if super().valid_token(crd, int): + self.in_crd2.append(crd) + if self.backpressure_en: + parent.set_backpressure(self.fifo_avail_2) def set_val(self, val, parent=None): - assert not is_stkn(val), 'Values associated with points should not have stop tokens' if val != '' and val is not None: self.in_val.append(val) if self.backpressure_en: parent.set_backpressure(self.fifo_avail_val) - def out_crd_outer(self): + def out_crd1(self): if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_1_crd + return self.curr_crd1 - def out_crd_inner(self): + def out_crd0(self): if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_0_crd + return self.curr_crd0 def out_val(self): if (self.backpressure_en and self.data_valid) or not self.backpressure_en: @@ -973,12 +767,12 @@ def out_val(self): def return_statistics(self): if self.get_stats: - hits_info = self.crdpt_spacc.return_hits() - stats_dict = {"in1_fifo": self.in1_fifo, "in0_fifo": self.in0_fifo, - "inval_fifo": self.inval_fifo, "max_hits": hits_info[0], "gt_one": hits_info[1], - "total_elems": hits_info[2]} - stats_dict.update(self.crdpt_spacc.return_statistics()) + stats_dict = {} + # TODO: Finish adding in other statistics stats_dict.update(super().return_statistics()) else: stats_dict = {} return stats_dict + + def print_fifos(self): + print("Spaccumulator: None available")