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")