From 1fa53b05937b092c4a8c4ee33759942a7802eba6 Mon Sep 17 00:00:00 2001 From: Olivia Hsu Date: Tue, 21 Feb 2023 13:18:06 -0800 Subject: [PATCH 1/9] Update gitignore --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index bd907aea..4cfac793 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ __pycache__/ *.swo *.txt *.out +*.log # Files for MacOS and IDEs .DS_store @@ -34,6 +35,7 @@ results-cpu/ suitesparse-bench/ sam-outputs/ compiler/benchmark/ +sam/sim/test/apps/ # Generated SAM simulator tests */sim/test/apps/test_*.py @@ -50,3 +52,7 @@ tensor_*_mode_* # Tensor files *.mtx *.tns + +# From instaling as pip package +sam.egg-info/ + From 7bdeb4ba2453793515b7ac9c96a72fb652313c54 Mon Sep 17 00:00:00 2001 From: Olivia Hsu Date: Tue, 21 Feb 2023 13:32:33 -0800 Subject: [PATCH 2/9] Fix gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7bfea7a6..0b16e795 100644 --- a/.gitignore +++ b/.gitignore @@ -58,7 +58,6 @@ tmp_mat*/ tensor_*_mode_* # Tensor files -<<<<<<< HEAD *.mtx *.tns From 4fb082edc47cb5fccfc2d64458c5ad9bd03daad3 Mon Sep 17 00:00:00 2001 From: Olivia Hsu Date: Tue, 21 Feb 2023 14:48:45 -0800 Subject: [PATCH 3/9] Add in fixes to test_generating_code script and sparse accumulator code --- sam/sim/src/accumulator.py | 15 - .../test/unit-apps/test_unit_matmul_ikj.py | 36 +- sam/util.py | 4 +- scripts/test_generating_code.py | 791 +++++++++--------- 4 files changed, 412 insertions(+), 434 deletions(-) diff --git a/sam/sim/src/accumulator.py b/sam/sim/src/accumulator.py index a3500369..43944829 100644 --- a/sam/sim/src/accumulator.py +++ b/sam/sim/src/accumulator.py @@ -509,7 +509,6 @@ def update(self): 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()) @@ -551,20 +550,6 @@ def set_outer_crdpt(self, crdpt, parent=None): if self.backpressure_en: parent.set_backpressure(self.fifo_avail_outer) - 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) - 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: diff --git a/sam/sim/test/unit-apps/test_unit_matmul_ikj.py b/sam/sim/test/unit-apps/test_unit_matmul_ikj.py index b58c0d29..cfb90ce2 100644 --- a/sam/sim/test/unit-apps/test_unit_matmul_ikj.py +++ b/sam/sim/test/unit-apps/test_unit_matmul_ikj.py @@ -24,39 +24,39 @@ reason='CI lacks datasets', ) @pytest.mark.suitesparse -def test_matmul_ikj(samBench, ssname, check_gold, debug_sim, fill=0): - B_dirname = os.path.join(formatted_dir, ssname, "orig", "ss01") - B_shape_filename = os.path.join(B_dirname, "B_shape.txt") +def test_matmul_ikj(samBench, ssname, check_gold, debug_sim, cast, fill=0): + B_dirname = os.path.join(formatted_dir, ssname, "matmul_ikj") + B_shape_filename = os.path.join(B_dirname, "tensor_B_mode_shape") B_shape = read_inputs(B_shape_filename) - B0_seg_filename = os.path.join(B_dirname, "B0_seg.txt") + B0_seg_filename = os.path.join(B_dirname, "tensor_B_mode_0_seg") B_seg0 = read_inputs(B0_seg_filename) - B0_crd_filename = os.path.join(B_dirname, "B0_crd.txt") + B0_crd_filename = os.path.join(B_dirname, "tensor_B_mode_0_crd") B_crd0 = read_inputs(B0_crd_filename) - B1_seg_filename = os.path.join(B_dirname, "B1_seg.txt") + B1_seg_filename = os.path.join(B_dirname, "tensor_B_mode_1_seg") B_seg1 = read_inputs(B1_seg_filename) - B1_crd_filename = os.path.join(B_dirname, "B1_crd.txt") + B1_crd_filename = os.path.join(B_dirname, "tensor_B_mode_1_crd") B_crd1 = read_inputs(B1_crd_filename) - B_vals_filename = os.path.join(B_dirname, "B_vals.txt") + B_vals_filename = os.path.join(B_dirname, "tensor_B_mode_vals") B_vals = read_inputs(B_vals_filename, float) - C_dirname = os.path.join(formatted_dir, ssname, "shift-trans", "ss01") - C_shape_filename = os.path.join(C_dirname, "C_shape.txt") + C_dirname = B_dirname + C_shape_filename = os.path.join(C_dirname, "tensor_C_mode_shape") C_shape = read_inputs(C_shape_filename) - C0_seg_filename = os.path.join(C_dirname, "C0_seg.txt") + C0_seg_filename = os.path.join(C_dirname, "tensor_C_mode_0_seg") C_seg0 = read_inputs(C0_seg_filename) - C0_crd_filename = os.path.join(C_dirname, "C0_crd.txt") + C0_crd_filename = os.path.join(C_dirname, "tensor_C_mode_0_crd") C_crd0 = read_inputs(C0_crd_filename) - C1_seg_filename = os.path.join(C_dirname, "C1_seg.txt") + C1_seg_filename = os.path.join(C_dirname, "tensor_C_mode_1_seg") C_seg1 = read_inputs(C1_seg_filename) - C1_crd_filename = os.path.join(C_dirname, "C1_crd.txt") + C1_crd_filename = os.path.join(C_dirname, "tensor_C_mode_1_crd") C_crd1 = read_inputs(C1_crd_filename) - C_vals_filename = os.path.join(C_dirname, "C_vals.txt") + C_vals_filename = os.path.join(C_dirname, "tensor_C_mode_vals") C_vals = read_inputs(C_vals_filename, float) fiberlookup_Bi_17 = CompressedCrdRdScan(crd_arr=B_crd0, seg_arr=B_seg0, debug=debug_sim) @@ -149,9 +149,9 @@ def test_matmul_ikj(samBench, ssname, check_gold, debug_sim, fill=0): spaccumulator1_3_drop_val.update() spaccumulator1_3_drop_crd_in_inner.update() - spaccumulator1_3.crd_in_outer(spaccumulator1_3_drop_crd_in_outer.out_val()) + spaccumulator1_3.set_crd_outer(spaccumulator1_3_drop_crd_in_outer.out_val()) spaccumulator1_3.set_val(spaccumulator1_3_drop_val.out_val()) - spaccumulator1_3.crd_in_inner(spaccumulator1_3_drop_crd_in_inner.out_val()) + spaccumulator1_3.set_crd_inner(spaccumulator1_3_drop_crd_in_inner.out_val()) spaccumulator1_3.update() fiberwrite_Xvals_0.set_input(spaccumulator1_3.out_val()) @@ -217,5 +217,5 @@ def bench(): if check_gold: print("Checking gold...") - check_gold_matmul(ssname, debug_sim, out_crds, out_segs, out_vals) + check_gold_matmul(ssname, debug_sim, cast, out_crds, out_segs, out_vals) samBench(bench, extra_info) diff --git a/sam/util.py b/sam/util.py index 96cc15c5..7044e94d 100644 --- a/sam/util.py +++ b/sam/util.py @@ -7,7 +7,7 @@ import shutil import numpy as np import math -import pydata +import sparse from pathlib import Path from dataclasses import dataclass @@ -601,7 +601,7 @@ def safeCastPydataTensorToInts(tensor): # else: # data[i] = int(tensor.data[i]) data[i] = round_sparse(tensor.data[i]) - return pydata.sparse.COO(tensor.coords, data, tensor.shape) + return sparse.COO(tensor.coords, data, tensor.shape) def parse_taco_format(infilename, outdir, tensorname, format_str): diff --git a/scripts/test_generating_code.py b/scripts/test_generating_code.py index d92b39b9..36ae7869 100755 --- a/scripts/test_generating_code.py +++ b/scripts/test_generating_code.py @@ -537,422 +537,415 @@ def get_all_files(directory_path): parser = argparse.ArgumentParser("Generate sam apps/") parser.add_argument("--input_dir", type=str, default="./compiler/sam-outputs/dot") +parser.add_argument("--name", type=str, default="all") args = parser.parse_args() file_paths, out_name = get_all_files(args.input_dir) -num = 0 -for apath in file_paths: - # apath = "../compiler/sam-outputs/dot/matmul_ijk.gv" - # out_name[0] = "matmul_ijk" - # apath = os.path.join(directory, ".gv") - graphs = pydot.graph_from_dot_file(apath) - graph = graphs[0] - networkx_graph = nx.nx_pydot.from_pydot(graph) - - tensor_format_parse = TensorFormat() - tensor_format_parse.set_all_tensors(apath) - f = open(out_name[num] + ".py", "w") - generate_header(f, out_name[num]) - # nx.draw(networkx_graph, with_labels=True) - # plt.savefig("Graph.png", format="PNG") - # plt.show() - networkx_graph = remove_broadcast_nodes(networkx_graph) - # Node Dataset present - d = {} - invalid_flag = 0 - root_nodes = [] - output_nodes = {} - tensor_information = {} - nodes_updating_list = [] - - for u in list(nx.topological_sort(networkx_graph)): - node_info = breakup_node_info(networkx_graph.nodes[u]["comment"]) - if node_info["type"] == "fiberlookup": - if node_info["tensor"] not in tensor_information: - tensor_information[node_info["tensor"]] = 0 - if node_info["format"] == "compressed": - tensor_information[node_info["tensor"]] += 1 * (2 ** int(node_info["mode"])) - tens_fmt = {} - count = 0 - data_formats = gen_data_formats(len(tensor_format_parse.return_all_tensors()), out_name[num], apath) - ct = 0 - for k in tensor_format_parse.return_all_tensors(): - if ct != 0: - tens_fmt[k] = {} - tens_fmt[k]["information"] = data_formats[ct - 1] - ct += 1 - generate_datasets_code(f, tens_fmt, 1, tensor_information, tensor_format_parse, out_name[num]) - f.write("\n") - for u in list(nx.topological_sort(networkx_graph)): - node_info = breakup_node_info(networkx_graph.nodes[u]["comment"]) - d[u] = node_info - if (node_info["type"] == "fiberlookup" or node_info["type"] == "repeat") and node_info["root"] == "true": - root_nodes.append(node_info["tensor"]) - if node_info["type"] == "fiberlookup": - if node_info["format"] == "dense": - f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + - node_info["index"] + "_" + str(u) + " = UncompressCrdRdScan(dim=" + node_info["tensor"] + - "_shape[" + node_info["mode"] + "]" + ", debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["index"] + "_" + str(u) +for num, apath in enumerate(file_paths): + if args.name in apath or args.name == "all": + graphs = pydot.graph_from_dot_file(apath) + graph = graphs[0] + + networkx_graph = nx.nx_pydot.from_pydot(graph) + + tensor_format_parse = TensorFormat() + tensor_format_parse.set_all_tensors(apath) + f = open(out_name[num] + ".py", "w") + generate_header(f, out_name[num]) + + networkx_graph = remove_broadcast_nodes(networkx_graph) + # Node Dataset present + d = {} + invalid_flag = 0 + root_nodes = [] + output_nodes = {} + tensor_information = {} + nodes_updating_list = [] + + for u in list(nx.topological_sort(networkx_graph)): + node_info = breakup_node_info(networkx_graph.nodes[u]["comment"]) + if node_info["type"] == "fiberlookup": + if node_info["tensor"] not in tensor_information: + tensor_information[node_info["tensor"]] = 0 + if node_info["format"] == "compressed": + tensor_information[node_info["tensor"]] += 1 * (2 ** int(node_info["mode"])) + tens_fmt = {} + count = 0 + data_formats = gen_data_formats(len(tensor_format_parse.return_all_tensors()), out_name[num], apath) + ct = 0 + for k in tensor_format_parse.return_all_tensors(): + if ct != 0: + tens_fmt[k] = {} + tens_fmt[k]["information"] = data_formats[ct - 1] + ct += 1 + generate_datasets_code(f, tens_fmt, 1, tensor_information, tensor_format_parse, out_name[num]) + f.write("\n") + + for u in list(nx.topological_sort(networkx_graph)): + node_info = breakup_node_info(networkx_graph.nodes[u]["comment"]) + d[u] = node_info + if (node_info["type"] == "fiberlookup" or node_info["type"] == "repeat") and node_info["root"] == "true": + root_nodes.append(node_info["tensor"]) + if node_info["type"] == "fiberlookup": + if node_info["format"] == "dense": + f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + + node_info["index"] + "_" + str(u) + " = UncompressCrdRdScan(dim=" + node_info["tensor"] + + "_shape[" + node_info["mode"] + "]" + ", debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["index"] + "_" + str(u) + + if node_info["format"] == "compressed": + f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + node_info["index"] + + "_" + str(u) + " = CompressedCrdRdScan(crd_arr=" + node_info["tensor"] + + "_crd" + node_info["mode"] + ", seg_arr=" + node_info["tensor"] + + "_seg" + node_info["mode"] + ", debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["index"] + "_" + str(u) + + elif node_info["type"] == "arrayvals": + f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + "_" + str(u) + " = Array(init_arr=" + + node_info["tensor"] + "_vals, " + "debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + "_" + str(u) + + elif "broadcast" in networkx_graph.nodes[u]['comment']: + continue + + elif node_info["type"] == "repsiggen": + f.write(tab(1) + node_info["type"] + "_" + node_info["index"] + "_" + str(u) + + " = RepeatSigGen(debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + node_info["index"] + "_" + str(u) - if node_info["format"] == "compressed": - f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + node_info["index"] + - "_" + str(u) + " = CompressedCrdRdScan(crd_arr=" + node_info["tensor"] + - "_crd" + node_info["mode"] + ", seg_arr=" + node_info["tensor"] + - "_seg" + node_info["mode"] + ", debug=debug_sim, statistics=report_stats)\n") + elif node_info["type"] == "repeat": + f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + node_info["index"] + "_" + str(u) + + " = Repeat(debug=debug_sim, statistics=report_stats)\n") d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["index"] + "_" + str(u) + elif node_info["type"] == "intersect": + f.write(tab(1) + node_info["type"] + node_info["index"] + "_" + str(u) + " = Intersect2(debug=debug_sim, " + + "statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + node_info["index"] + "_" + str(u) + elif node_info["type"] == "union": + f.write(tab(1) + node_info["type"] + node_info["index"] + "_" + str(u) + " = Union2(debug=debug_sim, " + + "statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + node_info["index"] + "_" + str(u) + # invalid_flag = 1 + elif node_info["type"] == "spaccumulator" and node_info["order"] == "1": + f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( + u) + " = SparseAccumulator1(debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + node_info["order"] + "_" + str(u) + f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( + u) + "_drop_crd_inner" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") + f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( + u) + "_drop_crd_outer" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") + f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( + u) + "_drop_val" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") + elif node_info["type"] == "spaccumulator" and node_info["order"] == "2": + f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( + u) + " = SparseAccumulator2(debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + node_info["order"] + "_" + str(u) + f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( + u) + "_drop_crd_inner" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") + f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( + u) + "_drop_crd_outer" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") + # f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( + # u) + "_drop_crd_in_2" + " = StknDrop(debug=debug_sim)\n") + f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( + u) + "_drop_val" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") + elif node_info["type"] == "crddrop": + f.write( + tab(1) + node_info["type"] + "_" + str(u) + " = CrdDrop(debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + str(u) + elif node_info["type"] == "crdhold": + f.write( + tab(1) + node_info["type"] + "_" + str(u) + " = CrdHold(debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + str(u) + elif node_info["type"] == "mul": + f.write( + tab(1) + node_info["type"] + "_" + str(u) + " = Multiply2(debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + str(u) + elif node_info["type"] == "add": + f.write(tab(1) + node_info["type"] + "_" + str(u) + " = Add2(debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + str(u) + elif node_info["type"] == "reduce": + f.write(tab(1) + node_info["type"] + "_" + str(u) + " = Reduce(debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + str(u) + elif node_info["type"] == "fiberwrite": + if node_info["mode"] == "vals": + f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + node_info["mode"] + "_" + str(u) + + " = ValsWrScan(size=" + array_size_computation(node_info["size"]) + + ", fill=fill, debug=debug_sim, statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["mode"] + "_" + str(u) + elif node_info["format"] == "compressed": + f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + node_info["mode"] + "_" + str(u) + + " = CompressWrScan(seg_size=" + array_size_computation(node_info["segsize"]) + ", size=" + + array_size_computation(node_info["crdsize"]) + ", fill=fill," + " debug=debug_sim, " + + "statistics=report_stats)\n") + d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["mode"] + "_" + str(u) + else: + d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["mode"] + "_" + str(u) + continue + if node_info["sink"] == "true": + output_nodes[d[u]["object"]] = node_info["mode"] + else: + invalid_flag = 1 + print("Error invalid node detected", node_info["type"], "\n") + if invalid_flag == 1: + os.system("rm " + out_name[num] + ".py") + print(out_name[num] + " failed\n") + num += 1 + continue + output_check_nodes(f, root_nodes) + f.write("\n") + f.write(tab(1) + "while not done and time_cnt < TIMEOUT:\n") + + intersect_dataset = defaultdict(dict) + data = CodeGenerationdatasets() + data.build_datasets(networkx_graph) + for u in networkx_graph.nodes(): + if d[u]["type"] == "fiberlookup" and u not in data.get_if_done(): + if d[u]["root"] == "true": + f.write(tab(2) + "if len(in_ref_" + d[u]["tensor"] + ") > 0:\n") + f.write(tab(3) + d[u]["object"] + ".set_in_ref(in_ref_" + d[u]["tensor"] + ".pop(0))\n") + nodes_updating_list.append(tab(2) + d[u]["object"] + ".update()\n\n") + data.add_done(u) + + # FIXME: RENAME VARIABLE FROM i. Also figure out why this in range(10) is there... + for i in range(10): + for u, v, _ in list(nx.edge_bfs(networkx_graph)): # .edges(data=True), networkx_graph.nodes())): + a = networkx_graph.get_edge_data(u, v)[0] + if d[v]["type"] == "fiberlookup" and data.get_if_node_done(v) == 0 and parents_done(networkx_graph, + data.get_if_done(), v): + for i in range(len(data.get_parents()[v])): + u_ = data.get_parents()[v][i] + if "intersect" in d[u_]["object"] or "union" in d[u_]["object"]: + f.write(tab(2) + d[v]["object"] + ".set_in_ref(" + d[u_]["object"] + ".out_ref" + + str(intersect_dataset[d[u_]["object"]][d[v]["tensor"]]) + "())\n") + else: + f.write(tab(2) + d[v]["object"] + ".set_in_ref(" + + d[u_]["object"] + ".out_" + + str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + "())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) + + if d[v]["type"] == "repsiggen" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + for u_ in data.get_parents()[v]: + f.write(tab(2) + d[v]["object"] + ".set_istream(" + str(d[u_]["object"]).strip('"') + + ".out_" + str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + "())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) - elif node_info["type"] == "arrayvals": - f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + "_" + str(u) + " = Array(init_arr=" + - node_info["tensor"] + "_vals, " + "debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + "_" + str(u) + if d[v]["type"] == "repeat" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + if d[v]["root"] == "true": + f.write(tab(2) + "if len(in_ref_" + d[v]["tensor"] + ") > 0:\n") + f.write(tab(3) + d[v]["object"] + + ".set_in_ref(in_ref_" + d[v]["tensor"] + ".pop(0))\n") + for u_ in data.get_parents()[v]: + if "intersect" in d[u_]["object"] or "union" in d[u_]["object"]: + f.write(tab(2) + d[v]["object"] + ".set_in_ref(" + + d[u_]["object"] + ".out_ref" + + str(intersect_dataset[d[u_]["object"]][d[v]["tensor"]]) + "())\n") + else: + f.write(tab(2) + d[v]["object"] + ".set_in_" + + str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + + "(" + d[u_]["object"] + ".out_" + + str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + "())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) - elif "broadcast" in networkx_graph.nodes[u]['comment']: - continue + if d[v]["type"] == "arrayvals" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + for u_ in data.get_parents()[v]: + if "intersect" in d[u_]["object"] or "union" in d[u_]["object"]: + f.write(tab(2) + d[v]["object"] + ".set_load(" + d[u_]["object"] + ".out_ref" + + str(intersect_dataset[d[u_]["object"]][d[v]["tensor"]]) + "())\n") + else: + f.write(tab(2) + d[v]["object"] + ".set_load(" + d[u_]["object"] + ".out_ref" + "())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) - elif node_info["type"] == "repsiggen": - f.write(tab(1) + node_info["type"] + "_" + node_info["index"] + "_" + str(u) + - " = RepeatSigGen(debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + node_info["index"] + "_" + str(u) - - elif node_info["type"] == "repeat": - f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + node_info["index"] + "_" + str(u) + - " = Repeat(debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["index"] + "_" + str(u) - elif node_info["type"] == "intersect": - f.write(tab(1) + node_info["type"] + node_info["index"] + "_" + str(u) + " = Intersect2(debug=debug_sim, " + - "statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + node_info["index"] + "_" + str(u) - elif node_info["type"] == "union": - f.write(tab(1) + node_info["type"] + node_info["index"] + "_" + str(u) + " = Union2(debug=debug_sim, " + - "statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + node_info["index"] + "_" + str(u) - # invalid_flag = 1 - elif node_info["type"] == "spaccumulator" and node_info["order"] == "1": - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + " = SparseAccumulator1(debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + node_info["order"] + "_" + str(u) - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_crd_inner" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_crd_outer" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_val" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") - elif node_info["type"] == "spaccumulator" and node_info["order"] == "2": - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + " = SparseAccumulator2(debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + node_info["order"] + "_" + str(u) - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_crd_inner" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_crd_outer" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") - # f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - # u) + "_drop_crd_in_2" + " = StknDrop(debug=debug_sim)\n") - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_val" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") - elif node_info["type"] == "crddrop": - f.write( - tab(1) + node_info["type"] + "_" + str(u) + " = CrdDrop(debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + str(u) - elif node_info["type"] == "crdhold": - f.write( - tab(1) + node_info["type"] + "_" + str(u) + " = CrdHold(debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + str(u) - elif node_info["type"] == "mul": - f.write( - tab(1) + node_info["type"] + "_" + str(u) + " = Multiply2(debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + str(u) - elif node_info["type"] == "add": - f.write(tab(1) + node_info["type"] + "_" + str(u) + " = Add2(debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + str(u) - elif node_info["type"] == "reduce": - f.write(tab(1) + node_info["type"] + "_" + str(u) + " = Reduce(debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + str(u) - elif node_info["type"] == "fiberwrite": - if node_info["mode"] == "vals": - f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + node_info["mode"] + "_" + str(u) + - " = ValsWrScan(size=" + array_size_computation(node_info["size"]) + - ", fill=fill, debug=debug_sim, statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["mode"] + "_" + str(u) - elif node_info["format"] == "compressed": - f.write(tab(1) + node_info["type"] + "_" + node_info["tensor"] + node_info["mode"] + "_" + str(u) + - " = CompressWrScan(seg_size=" + array_size_computation(node_info["segsize"]) + ", size=" + - array_size_computation(node_info["crdsize"]) + ", fill=fill," + " debug=debug_sim, " + - "statistics=report_stats)\n") - d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["mode"] + "_" + str(u) - else: - d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["mode"] + "_" + str(u) - continue - if node_info["sink"] == "true": - output_nodes[d[u]["object"]] = node_info["mode"] - else: - invalid_flag = 1 - print("Error invalid node detected", node_info["type"], "\n") - if invalid_flag == 1: - os.system("rm " + out_name[num] + ".py") - print(out_name[num] + " failed\n") - num += 1 - continue - output_check_nodes(f, root_nodes) - f.write("\n") - f.write(tab(1) + "while not done and time_cnt < TIMEOUT:\n") + if d[v]["type"] == "intersect" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + for i in range(len(data.get_parents()[v])): + if i % 2 == 1: + continue + u_ = data.get_parents()[v][i] + f.write(tab(2) + d[v]["object"] + ".set_in" + str((i) // 2 + 1) + "(" + + d[u_]["object"] + ".out_ref(), " + d[u_]["object"] + ".out_crd())\n") + intersect_dataset[d[v]["object"]][d[u_]["tensor"]] = i // 2 + 1 + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) - intersect_dataset = defaultdict(dict) - data = CodeGenerationdatasets() - data.build_datasets(networkx_graph) - for u in networkx_graph.nodes(): - if d[u]["type"] == "fiberlookup" and u not in data.get_if_done(): - if d[u]["root"] == "true": - f.write(tab(2) + "if len(in_ref_" + d[u]["tensor"] + ") > 0:\n") - f.write(tab(3) + d[u]["object"] + ".set_in_ref(in_ref_" + d[u]["tensor"] + ".pop(0))\n") - nodes_updating_list.append(tab(2) + d[u]["object"] + ".update()\n\n") - data.add_done(u) - - # FIXME: RENAME VARIABLE FROM i. Also figure out why this in range(10) is there... - for i in range(10): - for u, v, _ in list(nx.edge_bfs(networkx_graph)): # .edges(data=True), networkx_graph.nodes())): - a = networkx_graph.get_edge_data(u, v)[0] - if d[v]["type"] == "fiberlookup" and data.get_if_node_done(v) == 0 and parents_done(networkx_graph, - data.get_if_done(), v): - for i in range(len(data.get_parents()[v])): - u_ = data.get_parents()[v][i] - if "intersect" in d[u_]["object"] or "union" in d[u_]["object"]: - f.write(tab(2) + d[v]["object"] + ".set_in_ref(" + d[u_]["object"] + ".out_ref" + - str(intersect_dataset[d[u_]["object"]][d[v]["tensor"]]) + "())\n") - else: - f.write(tab(2) + d[v]["object"] + ".set_in_ref(" + - d[u_]["object"] + ".out_" + - str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + "())\n") + if d[v]["type"] == "union" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + for i in range(len(data.get_parents()[v])): + if i % 2 == 1: + continue + u_ = data.get_parents()[v][i] + f.write(tab(2) + d[v]["object"] + ".set_in" + str((i) // 2 + 1) + "(" + + d[u_]["object"] + ".out_ref(), " + d[u_]["object"] + ".out_crd())\n") + intersect_dataset[d[v]["object"]][d[u_]["tensor"]] = i // 2 + 1 nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") # f.write(tab(2) + d[v]["object"] + ".update()\n\n") data.add_done(v) - if d[v]["type"] == "repsiggen" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - for u_ in data.get_parents()[v]: - f.write(tab(2) + d[v]["object"] + ".set_istream(" + str(d[u_]["object"]).strip('"') + - ".out_" + str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + "())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "repeat" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - if d[v]["root"] == "true": - f.write(tab(2) + "if len(in_ref_" + d[v]["tensor"] + ") > 0:\n") - f.write(tab(3) + d[v]["object"] + - ".set_in_ref(in_ref_" + d[v]["tensor"] + ".pop(0))\n") - for u_ in data.get_parents()[v]: - if "intersect" in d[u_]["object"] or "union" in d[u_]["object"]: - f.write(tab(2) + d[v]["object"] + ".set_in_ref(" + - d[u_]["object"] + ".out_ref" + - str(intersect_dataset[d[u_]["object"]][d[v]["tensor"]]) + "())\n") - else: - f.write(tab(2) + d[v]["object"] + ".set_in_" + - str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + - "(" + d[u_]["object"] + ".out_" + - str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + "())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "arrayvals" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - for u_ in data.get_parents()[v]: - if "intersect" in d[u_]["object"] or "union" in d[u_]["object"]: - f.write(tab(2) + d[v]["object"] + ".set_load(" + d[u_]["object"] + ".out_ref" + - str(intersect_dataset[d[u_]["object"]][d[v]["tensor"]]) + "())\n") - else: - f.write(tab(2) + d[v]["object"] + ".set_load(" + d[u_]["object"] + ".out_ref" + "())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "intersect" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - for i in range(len(data.get_parents()[v])): - if i % 2 == 1: - continue - u_ = data.get_parents()[v][i] - f.write(tab(2) + d[v]["object"] + ".set_in" + str((i) // 2 + 1) + "(" + - d[u_]["object"] + ".out_ref(), " + d[u_]["object"] + ".out_crd())\n") - intersect_dataset[d[v]["object"]][d[u_]["tensor"]] = i // 2 + 1 - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "union" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - for i in range(len(data.get_parents()[v])): - if i % 2 == 1: - continue - u_ = data.get_parents()[v][i] - f.write(tab(2) + d[v]["object"] + ".set_in" + str((i) // 2 + 1) + "(" + - d[u_]["object"] + ".out_ref(), " + d[u_]["object"] + ".out_crd())\n") - intersect_dataset[d[v]["object"]][d[u_]["tensor"]] = i // 2 + 1 - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "crddrop" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - for u_ in data.get_parents()[v]: - index_value = data.get_edge_data()[v][data.get_parents()[v].index(u_)][-1] - if index_value == d[v]["inner"]: - f.write(tab(2) + d[v]["object"] + ".set_inner_crd" + "(" + d[u_]["object"] + ".out_crd())\n") - if index_value == d[v]["outer"]: - f.write(tab(2) + d[v]["object"] + ".set_outer_crd" + "(" + d[u_]["object"] + ".out_crd())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "crdhold" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - for i in range(len(data.get_parents()[v])): - u_ = data.get_parents()[v][i] - index_value = data.get_edge_data()[v][i][-1] - local_edge = data.get_edge_data()[v][i][:-2] - if index_value == d[v]["inner"]: - f.write(tab(2) + d[v]["object"] + ".set_inner_crd" + "(" + d[u_]["object"] + - ".out_" + local_edge + "())\n") - if index_value == d[v]["outer"]: - f.write(tab(2) + d[v]["object"] + ".set_outer_crd" + "(" + d[u_]["object"] + - ".out_" + local_edge + "())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n") - data.add_done(v) - - if d[v]["type"] == "spaccumulator" and d[v]["order"] == "1" and parents_done(networkx_graph, - data.get_if_done(), v) \ - and data.get_if_node_done(v) == 0: - for i in range(len(data.get_parents()[v])): - u_ = data.get_parents()[v][i] - local_edge = "" - if "crd" in data.get_edge_data()[v][i]: - local_edge = data.get_edge_data()[v][i][:-2] - f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + - d[u_]["object"] + ".out_" + local_edge + "())\n") - else: - local_edge = data.get_edge_data()[v][i] - f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + - d[u_]["object"] + ".out_val())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") - # f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") - - for i in range(len(data.get_parents()[v])): - u_ = data.get_parents()[v][i] - local_edge = "" - if "crd" in data.get_edge_data()[v][i]: - local_edge = data.get_edge_data()[v][i][:-2] - f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + - d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") - else: - local_edge = data.get_edge_data()[v][i] - f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + - d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "spaccumulator" and d[v]["order"] == "2" and parents_done(networkx_graph, - data.get_if_done(), v) \ - and data.get_if_node_done(v) == 0: - for i in range(len(data.get_parents()[v])): - u_ = data.get_parents()[v][i] - local_edge = "" - if "crd" in data.get_edge_data()[v][i]: - local_edge = data.get_edge_data()[v][i][:-2] - f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + - d[u_]["object"] + ".out_" + local_edge + "())\n") - else: - local_edge = data.get_edge_data()[v][i] - f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + - d[u_]["object"] + ".out_val())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") - # f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") - - for i in range(len(data.get_parents()[v])): - u_ = data.get_parents()[v][i] - local_edge = "" - if "crd" in data.get_edge_data()[v][i]: + if d[v]["type"] == "crddrop" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + for u_ in data.get_parents()[v]: + index_value = data.get_edge_data()[v][data.get_parents()[v].index(u_)][-1] + if index_value == d[v]["inner"]: + f.write(tab(2) + d[v]["object"] + ".set_inner_crd" + "(" + d[u_]["object"] + ".out_crd())\n") + if index_value == d[v]["outer"]: + f.write(tab(2) + d[v]["object"] + ".set_outer_crd" + "(" + d[u_]["object"] + ".out_crd())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) + + if d[v]["type"] == "crdhold" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + for i in range(len(data.get_parents()[v])): + u_ = data.get_parents()[v][i] + index_value = data.get_edge_data()[v][i][-1] local_edge = data.get_edge_data()[v][i][:-2] - f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + - d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") - else: - local_edge = data.get_edge_data()[v][i] - f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + - d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "mul" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - for i in range(len(data.get_parents()[v])): - u_ = data.get_parents()[v][i] - f.write(tab(2) + d[v]["object"] + ".set_in" + str(data.get_parents()[v].index(u_) + 1) + "(" + - d[u_]["object"] + ".out_" + str(data.get_edge_info(v, i)) + "())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "add" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - for u_ in data.get_parents()[v]: - f.write(tab(2) + d[v]["object"] + ".set_in" + str(data.get_parents()[v].index(u_) + 1) + "(" + - d[u_]["object"] + ".out_" + str(data.get_edge_info(v, i)) + "())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "reduce" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - for u_ in data.get_parents()[v]: - f.write(tab(2) + d[v]["object"] + ".set_in_" + - str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + "(" + d[u_]["object"] + - ".out_" + str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + "())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - # f.write(tab(2) + d[v]["object"] + ".update()\n\n") - data.add_done(v) - - if d[v]["type"] == "fiberwrite" and parents_done(networkx_graph, data.get_if_done(), v) and \ - data.get_if_node_done(v) == 0: - for i in range(len(data.get_parents()[v])): - u_ = data.get_parents()[v][i] - if "val" not in data.get_edge_data()[v][i] and "spaccumulator" \ - in d[u_]["object"]: - local_index = data.get_edge_data()[v][i][-1] - print(d[u_], " ", local_index, " ", apath) - if d[u_]["in0"] == local_index: - local_cord = "_inner" + if index_value == d[v]["inner"]: + f.write(tab(2) + d[v]["object"] + ".set_inner_crd" + "(" + d[u_]["object"] + + ".out_" + local_edge + "())\n") + if index_value == d[v]["outer"]: + f.write(tab(2) + d[v]["object"] + ".set_outer_crd" + "(" + d[u_]["object"] + + ".out_" + local_edge + "())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n") + data.add_done(v) + + if d[v]["type"] == "spaccumulator" and d[v]["order"] == "1" and parents_done(networkx_graph, + data.get_if_done(), v) \ + and data.get_if_node_done(v) == 0: + for i in range(len(data.get_parents()[v])): + u_ = data.get_parents()[v][i] + print("HELLO----", u_, d[u_]) + local_edge = "" + if "crd" in data.get_edge_data()[v][i]: + local_edge = data.get_edge_data()[v][i][:-2] + f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + + d[u_]["object"] + ".out_" + local_edge + "())\n") else: - local_cord = "_outer" - data.set_edge_data(v, i, "crd" + local_cord) - if d[v]["mode"] == "vals": - f.write(tab(2) + d[v]["object"] + ".set_input(" + d[u_]["object"] + ".out_" + - str(data.get_edge_info(v, i)) + "())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - else: - f.write(tab(2) + d[v]["object"] + ".set_input(" + d[u_]["object"] + ".out_" + - str(data.get_edge_info(v, i)) + "())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - data.add_done(v) + local_edge = data.get_edge_data()[v][i] + f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + + d[u_]["object"] + ".out_val())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") + # f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") + + for i in range(len(data.get_parents()[v])): + u_ = data.get_parents()[v][i] + local_edge = "" + if "crd" in data.get_edge_data()[v][i]: + local_edge = data.get_edge_data()[v][i][:-2] + f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + + d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") + else: + local_edge = data.get_edge_data()[v][i] + f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + + d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) - output_tensor = "" - ct = 0 - for k in tensor_format_parse.return_all_tensors(): - if ct == 0: - output_tensor = k - ct += 1 + if d[v]["type"] == "spaccumulator" and d[v]["order"] == "2" and parents_done(networkx_graph, + data.get_if_done(), v) \ + and data.get_if_node_done(v) == 0: + for i in range(len(data.get_parents()[v])): + u_ = data.get_parents()[v][i] + local_edge = "" + if "crd" in data.get_edge_data()[v][i]: + local_edge = data.get_edge_data()[v][i][:-2] + f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + + d[u_]["object"] + ".out_" + local_edge + "())\n") + else: + local_edge = data.get_edge_data()[v][i] + f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + + d[u_]["object"] + ".out_val())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") + # f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") + + for i in range(len(data.get_parents()[v])): + u_ = data.get_parents()[v][i] + local_edge = "" + if "crd" in data.get_edge_data()[v][i]: + local_edge = data.get_edge_data()[v][i][:-2] + f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + + d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") + else: + local_edge = data.get_edge_data()[v][i] + f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + + d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) + + if d[v]["type"] == "mul" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + for i in range(len(data.get_parents()[v])): + u_ = data.get_parents()[v][i] + f.write(tab(2) + d[v]["object"] + ".set_in" + str(data.get_parents()[v].index(u_) + 1) + "(" + + d[u_]["object"] + ".out_" + str(data.get_edge_info(v, i)) + "())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) + + if d[v]["type"] == "add" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + for u_ in data.get_parents()[v]: + f.write(tab(2) + d[v]["object"] + ".set_in" + str(data.get_parents()[v].index(u_) + 1) + "(" + + d[u_]["object"] + ".out_" + str(data.get_edge_info(v, i)) + "())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) + + if d[v]["type"] == "reduce" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + for u_ in data.get_parents()[v]: + f.write(tab(2) + d[v]["object"] + ".set_in_" + + str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + "(" + d[u_]["object"] + + ".out_" + str(data.get_edge_data()[v][data.get_parents()[v].index(u_)]) + "())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # f.write(tab(2) + d[v]["object"] + ".update()\n\n") + data.add_done(v) + + if d[v]["type"] == "fiberwrite" and parents_done(networkx_graph, data.get_if_done(), v) and \ + data.get_if_node_done(v) == 0: + for i in range(len(data.get_parents()[v])): + u_ = data.get_parents()[v][i] + if "val" not in data.get_edge_data()[v][i] and "spaccumulator" \ + in d[u_]["object"]: + local_index = data.get_edge_data()[v][i][-1] + print(d[u_], " ", local_index, " ", apath) + if d[u_]["in0"] == local_index: + local_cord = "_inner" + else: + local_cord = "_outer" + data.set_edge_data(v, i, "crd" + local_cord) + if d[v]["mode"] == "vals": + f.write(tab(2) + d[v]["object"] + ".set_input(" + d[u_]["object"] + ".out_" + + str(data.get_edge_info(v, i)) + "())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + else: + f.write(tab(2) + d[v]["object"] + ".set_input(" + d[u_]["object"] + ".out_" + + str(data.get_edge_info(v, i)) + "())\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + data.add_done(v) + + output_tensor = list(tensor_format_parse.return_all_tensors())[0] - sorted_nodes = sort_output_nodes(output_nodes, tensor_format_parse.get_format(output_tensor)) - output_list = finish_outputs(f, sorted_nodes, nodes_updating_list) + sorted_nodes = sort_output_nodes(output_nodes, tensor_format_parse.get_format(output_tensor)) + output_list = finish_outputs(f, sorted_nodes, nodes_updating_list) - generate_benchmarking_code(f, tensor_format_parse, out_name[num]) - generate_check_against_gold_code(f, tensor_format_parse, out_name[num]) + generate_benchmarking_code(f, tensor_format_parse, out_name[num]) + generate_check_against_gold_code(f, tensor_format_parse, out_name[num]) - f.close() - os.system("cp " + out_name[num] + ".py ./sam/sim/test/apps/test_" + out_name[num] + ".py") - os.system("rm " + out_name[num] + ".py") - num += 1 + f.close() + os.system("cp " + out_name[num] + ".py ./sam/sim/test/apps/test_" + out_name[num] + ".py") + os.system("rm " + out_name[num] + ".py") \ No newline at end of file From 79607968d5887ac0e5cd64e23575b3cc0b09124c Mon Sep 17 00:00:00 2001 From: Olivia Hsu Date: Fri, 5 May 2023 20:49:42 -0700 Subject: [PATCH 4/9] Add in update to CrdHold and sparse accumulator --- compiler/taco | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/taco b/compiler/taco index cf8f007b..d9472db8 160000 --- a/compiler/taco +++ b/compiler/taco @@ -1 +1 @@ -Subproject commit cf8f007bab940527c48fb0479236b3928b32c1b0 +Subproject commit d9472db8669eca5e067f00fd250f319203dea513 From 16ca499f94c7f96e907fc8a0da200ba27b2cf3cb Mon Sep 17 00:00:00 2001 From: Olivia Hsu Date: Sun, 28 May 2023 11:32:39 -0700 Subject: [PATCH 5/9] Add in some fixes for sparse accumulator --- sam/sim/src/accumulator.py | 1126 ++++++++++------- sam/sim/src/accumulator_helpers.py | 809 ++++++++++++ sam/sim/src/base.py | 15 +- sam/sim/src/crd_manager.py | 31 +- sam/sim/src/token.py | 38 +- .../test/final-apps/test_matmul_ikj_FINAL.py | 221 ++++ sam/sim/test/primitives/test_spacc.py | 284 ++++- sam/sim/test/primitives/test_spacc_helpers.py | 128 ++ scripts/test_generating_code.py | 202 +-- 9 files changed, 2220 insertions(+), 634 deletions(-) create mode 100644 sam/sim/src/accumulator_helpers.py create mode 100644 sam/sim/test/final-apps/test_matmul_ikj_FINAL.py create mode 100644 sam/sim/test/primitives/test_spacc_helpers.py diff --git a/sam/sim/src/accumulator.py b/sam/sim/src/accumulator.py index 43944829..d7069fca 100644 --- a/sam/sim/src/accumulator.py +++ b/sam/sim/src/accumulator.py @@ -1,5 +1,11 @@ +import enum + from .base import * from .crd_manager import CrdPtConverter +from .accumulator_helpers import SparseCrdPtAccumulator2, SparseCrdPtAccumulator1, \ + SpAcc2NoCrdHold, SpAcc1NoCrdHold +from .crd_manager import CrdHold +from .token import StknDrop class Reduce(Primitive): @@ -65,7 +71,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 +158,46 @@ def return_statistics(self): return stats_dict -class SparseCrdPtAccumulator1(Primitive): - def __init__(self, maxdim=100, valtype=float, fifos=None, **kwargs): +# 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 of whether or not 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) + self.in_crd1 = [] + self.in_crd0 = [] + self.in_val = [] - def out_outer_crdpt(self): - return self.curr_outer_crdpt + self.crdhold_01 = CrdHold(**kwargs) - def out_inner_crdpt(self): - return self.curr_inner_crdpt + self.crdhold_out1 = [] + self.crdhold_out0 = [] - def out_val(self): - return self.curr_val + self.spacc1_no_crdhold = SpAcc1NoCrdHold(maxdim=maxdim, valtype=valtype, + name=self.name + "_no_crdhold", + last_level=last_level, val_stkn=val_stkn, + **kwargs) - 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_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.sd_out1 = [] + self.sd_out0 = [] + self.sd_out_val = [] - self.crdpt_spacc_out_val = [] + self.stkndrop_crd1 = StknDrop(**kwargs) + self.stkndrop_crd0 = StknDrop(**kwargs) + self.stkndrop_val = StknDrop(**kwargs) - 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 - 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 +208,6 @@ 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 def check_backpressure(self): if self.backpressure_en: @@ -455,154 +242,133 @@ 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 - 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 + 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 update(self): self.update_done() self.update_ready() + 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()) + print(self.in_crd1, self.in_crd0, self.in_val) + print(self.crdhold_out1, self.crdhold_out0) + print(self.curr_crd1, self.curr_crd0, self.curr_val) 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]) + 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) # FIXME: (owhsu) self.data_ready not defined in init if self.backpressure_en: self.data_ready = True - if len(self.in_outer_crdpt) > 0 or len(self.in_inner_crdpt) > 0: + + # 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? 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)) + pass - if len(self.in_outer_crdpt) > 0: - self.crdpt_spacc.set_outer_crdpt(self.in_outer_crdpt.pop(0)) + if len(self.in_crd0) > 0: + self.crdhold_01.set_inner_crd(self.in_crd0.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_crd1) > 0: + self.crdhold_01.set_outer_crd(self.in_crd1.pop(0)) - if len(self.in_val) > 0: - self.crdpt_spacc.set_val(self.in_val.pop(0)) + self.crdhold_01.update() - self.crdpt_spacc.update() - self.crdpt_converter.set_outer_crdpt(self.crdpt_spacc.out_outer_crdpt()) - self.crdpt_converter.set_inner_crdpt(self.crdpt_spacc.out_inner_crdpt()) + self.crdhold_out1.append(self.crdhold_01.out_crd_outer()) + self.crdhold_out0.append(self.crdhold_01.out_crd_inner()) - if self.crdpt_spacc.out_val() != '': - self.crdpt_spacc_out_val.append(self.crdpt_spacc.out_val()) + self.stkndrop_crd1.set_in_val(self.crdhold_01.out_crd_outer()) + self.stkndrop_crd0.set_in_val(self.crdhold_01.out_crd_inner()) + if len(self.in_val) > 0: + self.stkndrop_val.set_in_val(self.in_val.pop(0)) - self.crdpt_converter.update() - self.curr_outer_crd = self.crdpt_converter.out_crd_outer() - self.curr_inner_crd = self.crdpt_converter.out_crd_inner() + self.stkndrop_crd1.update() + self.stkndrop_crd0.update() + self.stkndrop_val.update() - 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 - else: - self.curr_val = self.crdpt_spacc_out_val.pop(0) if len(self.crdpt_spacc_out_val) > 0 else '' + self.sd_out1.append(self.stkndrop_crd1.out_val()) + self.sd_out0.append(self.stkndrop_crd0.out_val()) + self.sd_out_val.append(self.stkndrop_val.out_val()) - if self.debug: - print(self.in_val) + self.spacc1_no_crdhold.set_in_crd1(self.stkndrop_crd1.out_val()) + self.spacc1_no_crdhold.set_in_crd0(self.stkndrop_crd0.out_val()) + self.spacc1_no_crdhold.set_val(self.stkndrop_val.out_val()) - self.done = self.crdpt_spacc.out_done() and self.crdpt_converter.out_done() + self.spacc1_no_crdhold.update() - 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() - ) + self.curr_crd1 = self.spacc1_no_crdhold.out_crd1() + self.curr_crd0 = self.spacc1_no_crdhold.out_crd0() + self.curr_val = self.spacc1_no_crdhold.out_val() - 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) + print(self.spacc1_no_crdhold.out_done(), self.stkndrop_crd1.out_done(), + self.stkndrop_crd0.out_done(), self.stkndrop_val.out_done(), self.crdhold_01.out_done()) + self.done = self.crdhold_01.out_done() and self.spacc1_no_crdhold.out_done() and \ + self.stkndrop_crd1.out_done() and self.stkndrop_crd0.out_done() and self.stkndrop_val.out_done() - 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) + if self.debug: + print(self.in_crd1, self.in_crd0, self.in_val) + print(self.crdhold_out1, self.crdhold_out0) + print(self.curr_crd1, self.curr_crd0, self.curr_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.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 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_crd1(self): if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_outer_crd + return self.curr_crd1 - def out_inner_crd(self): + def out_crd0(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(self.spacc1_no_crdhold.return_statistics()) + stats_dict.update(self.crdhold_01.return_statistics()) + stats_dict.update(self.stkndrop_crd1.return_statistics()) + stats_dict.update(self.stkndrop_crd0.return_statistics()) + stats_dict.update(self.stkndrop_val.return_statistics()) stats_dict.update(super().return_statistics()) else: stats_dict = {} @@ -612,184 +378,273 @@ def print_fifos(self): print("Spaccumulator: None available") -class SparseCrdPtAccumulator2(Primitive): - def __init__(self, maxdim=100, valtype=float, **kwargs): +# NEW VERSION: Accumulation into a vector +class SpAcc1New(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.kwargs = kwargs + self.maxdim = maxdim + 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 + + self.in_crd1 = [] + self.in_crd0 = [] self.in_val = [] + self.storage = {} + + self.curr_crd1 = None + self.curr_crd0 = None + self.curr_val = None + + self.curr_in_crd0 = None 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 = '' + if self.get_stats: + self.in_crd0_fifo = 0 + self.in_crd1_fifo = 0 + self.in_val_fifo = 0 - # Maximum possible dimension for this index level - self.maxdim = maxdim - self.order = 1 + 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_val = True + + 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 - # Accumulation scratchpad storage - self.storage = dict() - self.valtype = valtype + self.crd1_stkn = None - 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 check_backpressure(self): + if self.backpressure_en: + copy_backpressure = self.ready_backpressure + self.ready_backpressure = True + return copy_backpressure + return True - def return_fifo(self): - return self.in_crdpt0, self.in_crdpt1, self.in_val + 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: + self.backpressure.append(child) + self.branch.append(branch) + + def update_ready(self): + if self.backpressure_en: + 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: + # 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() - if len(self.in_crdpt0) > 0 or len(self.in_crdpt0) > 0 or len(self.in_val) > 0: - self.block_start = False + 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: + # 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 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 - if self.done: - self.curr_crdpt0 = '' - self.curr_crdpt1 = '' - self.curr_val = '' + # Store block statistics if asked to be reported 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) + # 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: - if self.get_stats: - self.hits_tracker[self.curr_in0_crdpt] = 1 - inner_dict[self.curr_in0_crdpt] = self.valtype(self.curr_in_val) + 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.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 + 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.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.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_crdpt0 = '' - self.curr_crdpt1 = '' - self.curr_val = '' + self.curr_val = "" + self.curr_crd0 = "" - 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 + # Update the current state + self.curr_state = self.next_state 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) + print(self.in_crd1, self.in_crd0, self.in_val) + print(self.curr_crd1, self.curr_crd0, self.curr_val) - 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_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 set_val(self, val): - assert not is_stkn(val), 'Values associated with points should not have stop tokens' + 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): 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_crdpt(self): - return self.curr_crdpt1 - - def out_inner_crdpt(self): - return self.curr_crdpt0 + def out_crd0(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_crd0 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 + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + 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 = {} + # 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") + # Accumulation into a matrix (2D) class SparseAccumulator2(Primitive): @@ -903,7 +758,7 @@ def update(self): 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 + len(self.crdpt_spacc_out_val) > 0 else self.curr_0_crd else: self.curr_val = self.crdpt_spacc_out_val.pop(0) if len(self.crdpt_spacc_out_val) > 0 else '' @@ -967,3 +822,312 @@ def return_statistics(self): else: stats_dict = {} return stats_dict + +# NEW VERSION: Accumulation into a matrix +class SpAcc2New(Primitive): + def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, depth=1, **kwargs): + super().__init__(**kwargs) + self.kwargs = kwargs + self.maxdim = maxdim + 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 + + self.in_crd2 = [] + self.in_crd1 = [] + self.in_crd0 = [] + self.in_val = [] + + self.storage = {} + + self.curr_crd2 = None + self.curr_crd1 = None + self.curr_crd0 = None + self.curr_val = None + + + 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.writeout = False + self.writeout_storage = [] + + self.seen_done = False + self.crd2_stkn = None + + if self.get_stats: + 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_2 = True + self.fifo_avail_1 = True + self.fifo_avail_0 = True + self.fifo_avail_val = True + def check_backpressure(self): + if self.backpressure_en: + copy_backpressure = self.ready_backpressure + self.ready_backpressure = True + return copy_backpressure + return True + + 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: + self.backpressure.append(child) + self.branch.append(branch) + + def update_ready(self): + if self.backpressure_en: + 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 ACC1_body(self): + # In accumulation, accumulate into memory + self.curr_in_crd1 = self.in_crd1.pop(0) + + # All elements are ready + if len(self.in_crd) > 0 and len(self.in_val) > 0: + self.ACC0_body() + else: + self.next_state = self.states.ACC1 + + def build_writeout(self): + result = [] + for crd1 in self.storage.keys(): + for crd0, val in self.storage[crd1]: + 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.storage[crd1][crd0] += val + + 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_crd0, 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: + self.next_state = self.states.ACC1 + + def update(self): + self.update_done() + self.update_ready() + + # Print out debugging statements + if self.debug: + 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_storage, self.writeout) + print("Outputs: ", self.curr_crd1, 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: + # 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 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: + # What to do for drop tokens? + pass + + # Begin state machine computation + 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_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_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_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.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.crd2_stkn is not None, "The current writeout stop token should not be None" + self.curr_crd1 = self.crd2_stkn + self.curr_val = decrement_stkn(self.crd2_stkn) + + self.curr_val = decrement_stkn(self.crd2_stkn) + else: + curr_writeout_elem1 = self.writeout_storage1.pop(0) + curr_writeout_elem0 = self.writeout_storage0.pop(0) + self.curr_crd1 = curr_writeout_elem1[1] + self.curr_crd0 = curr_writeout_elem0[0] + self.curr_val = curr_writeout_elem0[1] + elif self.done: + self.curr_val = 'D' + self.curr_crd0 = 'D' + else: + self.curr_val = "" + self.curr_crd0 = "" + + # Update the current state + self.curr_state = self.next_state + + if self.debug: + print(self.in_crd1, self.in_crd0, self.in_val) + print(self.curr_crd1, self.curr_crd0, self.curr_val) + + 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_0) + + 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_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): + 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_crd1(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_crd1 + def out_crd0(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + 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 return_statistics(self): + if self.get_stats: + 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") diff --git a/sam/sim/src/accumulator_helpers.py b/sam/sim/src/accumulator_helpers.py new file mode 100644 index 00000000..b16a8aae --- /dev/null +++ b/sam/sim/src/accumulator_helpers.py @@ -0,0 +1,809 @@ +from .base import * +from .crd_manager import CrdPtConverter + + +# Accumulation into a vector +class SpAcc1NoCrdHold(Primitive): + def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, depth=1, fifos=None, **kwargs): + super().__init__(**kwargs) + self.in_outer_crdpt = [] + self.in_inner_crdpt = [] + 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.curr_outer_crd = None + self.curr_inner_crd = None + self.curr_val = None + + self.outer_crdpt = [] + self.inner_crdpt = [] + + self.val_stkn = val_stkn + + if self.get_stats: + self.in_outer_crd_pt_fifo = 0 + self.in_inner_crd_pt_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_val = True + + self.temp_maxdim = maxdim + self.temp_valtype = valtype + self.temp_last_level = last_level + + if fifos is not None: + self.in_outer_crdpt = fifos[0] + self.in_inner_crdpt = fifos[1] + self.in_val = fifos[2] + + def check_backpressure(self): + if self.backpressure_en: + copy_backpressure = self.ready_backpressure + self.ready_backpressure = True + return copy_backpressure + return True + + 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 return_fifo(self): + return self.in_outer_crdpt, self.in_inner_crdpt, self.in_val + + def add_child(self, child=None, branch=""): + if self.backpressure_en: + if child is not None: + self.backpressure.append(child) + self.branch.append(branch) + + def update_ready(self): + if self.backpressure_en: + if len(self.in_inner_crdpt) > self.depth: + self.fifo_avail_inner = False + 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 + + def update(self): + self.update_done() + self.update_ready() + 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]) + + # FIXME: (owhsu) self.data_ready not defined in init + if self.backpressure_en: + self.data_ready = True + + if len(self.in_outer_crdpt) > 0 or len(self.in_inner_crdpt) > 0: + self.block_start = False + + # What to do for drop tokens? + 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() + 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 + 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.done = self.crdpt_spacc.out_done() and self.crdpt_converter.out_done() + + 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_in_crd0(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_in_crd1(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_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_crd1(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_outer_crd + + def out_crd0(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_inner_crd + + def out_val(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_val + + 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()) + stats_dict.update(super().return_statistics()) + else: + stats_dict = {} + return stats_dict + + def print_fifos(self): + print("Spaccumulator: None available") + + +# Accumulation into a matrix (2D) +class SpAcc2NoCrdHold(Primitive): + def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, depth=1, **kwargs): + super().__init__(**kwargs) + self.in2_crdpt = [] + self.in1_crdpt = [] + self.in0_crdpt = [] + 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.curr_2_crd = None + self.curr_1_crd = None + self.curr_0_crd = None + self.curr_val = None + + self.outer_crdpt = [] + self.inner_crdpt = [] + + self.val_stkn = val_stkn + if self.get_stats: + self.in1_fifo = 0 + self.in0_fifo = 0 + self.inval_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_val = True + self.temp_maxdim = maxdim + self.temp_valtype = valtype + self.temp_last_level = last_level + + def check_backpressure(self): + if self.backpressure_en: + copy_backpressure = self.ready_backpressure + self.ready_backpressure = True + return copy_backpressure + return True + + def set_backpressure(self, backpressure): + if not backpressure: + self.ready_backpressure = False + + def add_child(self, child=None, branch=""): + if self.backpressure_en: + if child is not None: + self.backpressure.append(child) + self.branch.append(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 + else: + self.fifo_avail_outer = True + if len(self.in_val) > self.depth: + self.fifo_avail_val = False + else: + self.fifo_avail_val = True + + def update(self): + self.update_done() + self.update_ready() + 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]) + 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.block_start = False + + 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()) + + self.curr_1_crd = self.crdpt_converter.out_crd_outer() + self.curr_0_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_0_crd, int) and \ + len(self.crdpt_spacc_out_val) > 0 else self.curr_0_crd + 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.done = self.crdpt_spacc.out_done() and self.crdpt_converter.out_done() + + 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_in_crd0(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) + if self.backpressure_en: + parent.set_backpressure(self.fifo_avail_inner) + + def set_in_crd1(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) + if self.backpressure_en: + parent.set_backpressure(self.fifo_avail_outer) + + def set_in_crd2(self, crdpt, parent=None): + assert not is_stkn(crdpt), 'Coordinate points should not have stop tokens' + if crdpt != '' and crdpt is not None: + self.in2_crdpt.append(crdpt) + 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_crd2(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_2_crd + + def out_crd1(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_1_crd + + def out_crd0(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_0_crd + + def out_val(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_val + + 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.update(super().return_statistics()) + else: + stats_dict = {} + return stats_dict + + +class SparseCrdPtAccumulator1(Primitive): + def __init__(self, maxdim=100, valtype=float, fifos=None, **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.maxdim = maxdim + self.order = 1 + + self.seen_done = False + # Accumulation scratchpad storage + self.storage = dict() + self.valtype = valtype + + 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("SparseAccumulatorNoCrdHold1", 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) + + 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]) + + 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 len(self.emit_output) > 0: + fiber = self.emit_output[0] + + self.curr_outer_crdpt = fiber[0] + print(self.storage) + 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 + + +class SparseCrdPtAccumulator2(Primitive): + def __init__(self, maxdim=100, valtype=float, **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.maxdim = maxdim + self.order = 1 + + self.seen_done = False + # Accumulation scratchpad storage + self.storage = dict() + self.valtype = valtype + + 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 diff --git a/sam/sim/src/base.py b/sam/sim/src/base.py index 38eaa778..f7cadf13 100644 --- a/sam/sim/src/base.py +++ b/sam/sim/src/base.py @@ -1,6 +1,5 @@ from abc import ABC, abstractmethod - def gen_stkns(dim=10): return ['S' + str(i) for i in range(dim)] @@ -32,6 +31,9 @@ def is_valid_val(elem, dim=10): def is_0tkn(elem): return elem == 'N' +# Checks if a token is a non-control (numerical) token +def is_nc_tkn(elem, datatype=int): + return isinstance(elem, datatype) def is_stkn(elem): if isinstance(elem, str): @@ -39,6 +41,12 @@ def is_stkn(elem): return False +def is_dtkn(elem): + if isinstance(elem, str): + return elem == 'D' + return False + + def stkn_order(elem): assert is_stkn(elem) return int(elem[1]) @@ -89,6 +97,11 @@ def is_debug(self): def update(self): pass + # Check the input token of something + def valid_token(self, element, datatype=int): + return element != "" and element is not None and \ + (is_dtkn(element) or is_stkn(element) or is_nc_tkn(element, datatype) or is_0tkn(element)) + def reset(self): self.done = False diff --git a/sam/sim/src/crd_manager.py b/sam/sim/src/crd_manager.py index 7006f336..6021b189 100644 --- a/sam/sim/src/crd_manager.py +++ b/sam/sim/src/crd_manager.py @@ -187,7 +187,7 @@ def return_statistics(self): # Converts coordinate streams to point streams class CrdHold(Primitive): - def __init__(self, depth=1, **kwargs): + def __init__(self, depth=1, fifos=None, **kwargs): super().__init__(**kwargs) self.outer_crd = [] @@ -207,6 +207,10 @@ def __init__(self, depth=1, **kwargs): self.fifo_avail_inner = True self.fifo_avail_outer = True + if fifos is not None: + self.outer_crd = fifos[0] + self.inner_crd = fifos[1] + def set_backpressure(self, backpressure): if not backpressure: self.ready_backpressure = False @@ -232,6 +236,9 @@ def fifo_available(self, br=""): # return False return True + def return_fifo(self): + return self.outer_crd, self.inner_crd + def update_ready(self): if self.backpressure_en: if len(self.inner_crd) > self.depth: @@ -251,30 +258,23 @@ 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.outer_crd) > 0 or len(self.inner_crd) > 0): + + # Denotes the start of the block (when nonempty tokens are input) + if len(self.outer_crd) > 0 or len(self.inner_crd) > 0: self.block_start = False + # If the done signal is set, the block is done if self.done: self.curr_crd = '' - # self.done = False - # return - # print("-") - # print(self.RSG.print_debug()) - # print(self.repeat.print_debug()) - # print(self.RSG.done, self.repeat.done) - # print("-") - # self.RSG = RepeatSigGen(debug=self.debug, fifo=) - # self.repeat = Repeat(debug=self.debug) - # return + # If the block is not done and if len(self.inner_crd) > 0: icrd = self.inner_crd.pop(0) self.RSG.set_istream(icrd) self.curr_inner_crd = icrd else: self.curr_inner_crd = '' - if self.debug: - print("crdManager:") + self.repsig.append(self.RSG.out_repeat()) if len(self.outer_crd) > 0: ocrd = self.outer_crd.pop(0) @@ -285,8 +285,6 @@ def update(self): self.RSG.update() self.repeat.update() - if self.debug: - print("+++++++") self.curr_crd = self.repeat.out_ref() self.done = self.RSG.done and self.repeat.done @@ -336,6 +334,7 @@ def __init__(self, last_level=False, fifos=None, **kwargs): self.waiting_next = False self.inner_last_level = last_level + if fifos is not None: self.outer_crdpt = fifos[0] self.inner_crdpt = fifos[1] diff --git a/sam/sim/src/token.py b/sam/sim/src/token.py index 6b631991..91320d32 100644 --- a/sam/sim/src/token.py +++ b/sam/sim/src/token.py @@ -3,10 +3,10 @@ # Drops tokens class StknDrop(Primitive): - def __init__(self, depth=1, **kwargs): + def __init__(self, depth=1, fifos=None, **kwargs): super().__init__(**kwargs) - self.in_stream = [] + self.in_val = [] self.curr_out = '' if self.backpressure_en: @@ -15,6 +15,9 @@ def __init__(self, depth=1, **kwargs): self.fifo_avail = True self.ready_backpressure = True + if fifos is not None: + self.in_val = fifos[0] + def set_backpressure(self, backpressure): if not backpressure: self.ready_backpressure = False @@ -26,9 +29,12 @@ def check_backpressure(self): return copy_backpressure return True + def return_fifo(self): + return self.in_val + def update_ready(self): if self.backpressure_en: - if len(self.in_stream) > self.depth: + if len(self.in_val) > self.depth: self.fifo_avail = False else: self.fifo_avail = True @@ -37,20 +43,22 @@ def update(self): self.update_done() self.update_ready() self.data_valid = False + ival = '' + 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_stream) > 0: + if len(self.in_val) > 0: self.block_start = False - ival = '' + if self.done: self.curr_out = '' # return - if len(self.in_stream) > 0: - ival = self.in_stream.pop(0) + if len(self.in_val) > 0: + ival = self.in_val.pop(0) if ival == 'D': self.done = True self.curr_out = 'D' @@ -62,9 +70,9 @@ def update(self): if self.debug: print("Curr InnerCrd:", ival, "\t Curr OutputCrd:", self.curr_out) - def set_in_stream(self, val, parent=None): + def set_in_val(self, val, parent=None): if val != '' and val is not None: - self.in_stream.append(val) + self.in_val.append(val) if self.backpressure_en: parent.set_backpressure(self.fifo_avail) @@ -77,7 +85,7 @@ class EmptyFiberStknDrop(Primitive): def __init__(self, depth=4, **kwargs): super().__init__(**kwargs) - self.in_stream = [] + self.in_val = [] self.largest_stkn = None self.prev_stkn = False @@ -114,7 +122,7 @@ def update_ready(self): def update(self): self.update_done() self.update_ready() - if len(self.in_stream) > 0: + if len(self.in_val) > 0: self.block_start = False if self.backpressure_en: self.data_valid = False @@ -138,8 +146,8 @@ def update(self): self.leading_stkn = False return - if len(self.in_stream) > 0: - ival = self.in_stream.pop(0) + if len(self.in_val) > 0: + ival = self.in_val.pop(0) if is_stkn(ival) and not self.leading_stkn: self.largest_stkn = ival if self.largest_stkn is None else larger_stkn(self.largest_stkn, ival) self.curr_out = '' @@ -169,9 +177,9 @@ def update(self): print("Curr InnerCrd:", ival, "\t Curr OutputCrd:", self.curr_out) # This can be both val or crd - def set_in_stream(self, val, parent=None): + def set_in_val(self, val, parent=None): if val != '' and val is not None: - self.in_stream.append(val) + self.in_val.append(val) if self.backpressure_en: parent.set_backpressure(self.fifo_avail) diff --git a/sam/sim/test/final-apps/test_matmul_ikj_FINAL.py b/sam/sim/test/final-apps/test_matmul_ikj_FINAL.py new file mode 100644 index 00000000..8620fa7a --- /dev/null +++ b/sam/sim/test/final-apps/test_matmul_ikj_FINAL.py @@ -0,0 +1,221 @@ +import pytest +import time +import scipy.sparse +from sam.sim.src.rd_scanner import UncompressCrdRdScan, CompressedCrdRdScan +from sam.sim.src.wr_scanner import ValsWrScan +from sam.sim.src.joiner import Intersect2, Union2 +from sam.sim.src.compute import Multiply2 +from sam.sim.src.crd_manager import CrdDrop, CrdHold +from sam.sim.src.repeater import Repeat, RepeatSigGen +from sam.sim.src.accumulator import Reduce +from sam.sim.src.accumulator_helpers import SpAcc1NoCrdHold +from sam.sim.src.token import * +from sam.sim.test.test import * +from sam.sim.test.gold import * +import os +import csv +cwd = os.getcwd() +formatted_dir = os.getenv('SUITESPARSE_FORMATTED_PATH', default=os.path.join(cwd, 'mode-formats')) + + +# FIXME: Figureout formats +@pytest.mark.skipif( + os.getenv('CI', 'false') == 'true', + reason='CI lacks datasets', +) +@pytest.mark.suitesparse +def test_matmul_ikj_FINAL(samBench, ssname, check_gold, debug_sim, cast, fill=0): + B_dirname = os.path.join(formatted_dir, ssname, "matmul_ikj") + B_shape_filename = os.path.join(B_dirname, "tensor_B_mode_shape") + B_shape = read_inputs(B_shape_filename) + + B0_seg_filename = os.path.join(B_dirname, "tensor_B_mode_0_seg") + B_seg0 = read_inputs(B0_seg_filename) + B0_crd_filename = os.path.join(B_dirname, "tensor_B_mode_0_crd") + B_crd0 = read_inputs(B0_crd_filename) + + B1_seg_filename = os.path.join(B_dirname, "tensor_B_mode_1_seg") + B_seg1 = read_inputs(B1_seg_filename) + B1_crd_filename = os.path.join(B_dirname, "tensor_B_mode_1_crd") + B_crd1 = read_inputs(B1_crd_filename) + + B_vals_filename = os.path.join(B_dirname, "tensor_B_mode_vals") + B_vals = read_inputs(B_vals_filename, float) + + C_dirname = os.path.join(formatted_dir, ssname, "matmul_ikj") + + C_shape_filename = os.path.join(C_dirname, "tensor_C_mode_shape") + C_shape = read_inputs(C_shape_filename) + + C0_seg_filename = os.path.join(C_dirname, "tensor_C_mode_0_seg") + C_seg0 = read_inputs(C0_seg_filename) + C0_crd_filename = os.path.join(C_dirname, "tensor_C_mode_0_crd") + C_crd0 = read_inputs(C0_crd_filename) + + C1_seg_filename = os.path.join(C_dirname, "tensor_C_mode_1_seg") + C_seg1 = read_inputs(C1_seg_filename) + C1_crd_filename = os.path.join(C_dirname, "tensor_C_mode_1_crd") + C_crd1 = read_inputs(C1_crd_filename) + + C_vals_filename = os.path.join(C_dirname, "tensor_C_mode_vals") + C_vals = read_inputs(C_vals_filename, float) + + fiberlookup_Bi_17 = CompressedCrdRdScan(crd_arr=B_crd0, seg_arr=B_seg0, debug=debug_sim) + fiberlookup_Bk_12 = CompressedCrdRdScan(crd_arr=B_crd1, seg_arr=B_seg1, debug=debug_sim) + fiberwrite_X0_2 = CompressWrScan(seg_size=2, size=B_shape[0], fill=fill, debug=debug_sim) + repsiggen_i_15 = RepeatSigGen(debug=debug_sim) + repeat_Ci_14 = Repeat(debug=debug_sim) + fiberlookup_Ck_13 = CompressedCrdRdScan(crd_arr=C_crd0, seg_arr=C_seg0, debug=debug_sim) + intersectk_11 = Intersect2(debug=debug_sim) + fiberlookup_Cj_10 = CompressedCrdRdScan(crd_arr=C_crd1, seg_arr=C_seg1, debug=debug_sim) + arrayvals_C_6 = Array(init_arr=C_vals, debug=debug_sim) + repsiggen_j_8 = RepeatSigGen(debug=debug_sim) + repeat_Bj_7 = Repeat(debug=debug_sim) + arrayvals_B_5 = Array(init_arr=B_vals, debug=debug_sim) + mul_4 = Multiply2(debug=debug_sim) + spaccumulator1_3 = SpAcc1NoCrdHold(debug=debug_sim) + spaccumulator1_3_drop_crd_in_inner = StknDrop(debug=debug_sim) + spaccumulator1_3_drop_crd_in_outer = StknDrop(debug=debug_sim) + + spaccumulator1_3_crd_hold_in_ik = CrdHold(debug=debug_sim) + spaccumulator1_3_crd_hold_in_ij = CrdHold(debug=debug_sim) + + spaccumulator1_3_drop_val = StknDrop(debug=debug_sim) + fiberwrite_Xvals_0 = ValsWrScan(size=1 * B_shape[0] * C_shape[1], fill=fill, debug=debug_sim) + fiberwrite_X1_1 = CompressWrScan(seg_size=B_shape[0] + 1, size=B_shape[0] * C_shape[1], fill=fill, debug=debug_sim) + in_ref_B = [0, 'D'] + in_ref_C = [0, 'D'] + done = False + time_cnt = 0 + + while not done and time_cnt < TIMEOUT: + if len(in_ref_B) > 0: + fiberlookup_Bi_17.set_in_ref(in_ref_B.pop(0)) + + fiberlookup_Bk_12.set_in_ref(fiberlookup_Bi_17.out_ref()) + + fiberwrite_X0_2.set_input(fiberlookup_Bi_17.out_crd()) + + repsiggen_i_15.set_istream(fiberlookup_Bi_17.out_crd()) + + if len(in_ref_C) > 0: + repeat_Ci_14.set_in_ref(in_ref_C.pop(0)) + repeat_Ci_14.set_in_repsig(repsiggen_i_15.out_repsig()) + + fiberlookup_Ck_13.set_in_ref(repeat_Ci_14.out_ref()) + + intersectk_11.set_in1(fiberlookup_Ck_13.out_ref(), fiberlookup_Ck_13.out_crd()) + intersectk_11.set_in2(fiberlookup_Bk_12.out_ref(), fiberlookup_Bk_12.out_crd()) + + fiberlookup_Cj_10.set_in_ref(intersectk_11.out_ref1()) + + arrayvals_C_6.set_load(fiberlookup_Cj_10.out_ref()) + + repsiggen_j_8.set_istream(fiberlookup_Cj_10.out_crd()) + + repeat_Bj_7.set_in_ref(intersectk_11.out_ref2()) + repeat_Bj_7.set_in_repsig(repsiggen_j_8.out_repsig()) + + arrayvals_B_5.set_load(repeat_Bj_7.out_ref()) + + mul_4.set_in1(arrayvals_B_5.out_load()) + mul_4.set_in2(arrayvals_C_6.out_load()) + + spaccumulator1_3_crd_hold_in_ik.set_outer_crd(fiberlookup_Bi_17.out_crd()) + spaccumulator1_3_crd_hold_in_ik.set_inner_crd(intersectk_11.out_crd()) + + spaccumulator1_3_crd_hold_in_ij.set_outer_crd(spaccumulator1_3_crd_hold_in_ik.out_crd_outer()) + spaccumulator1_3_crd_hold_in_ij.set_inner_crd(fiberlookup_Cj_10.out_crd()) + + spaccumulator1_3_drop_crd_in_outer.set_in_val(spaccumulator1_3_crd_hold_in_ij.out_crd_outer()) + spaccumulator1_3_drop_val.set_in_val(mul_4.out_val()) + spaccumulator1_3_drop_crd_in_inner.set_in_val(fiberlookup_Cj_10.out_crd()) + + spaccumulator1_3.set_in_crd1(spaccumulator1_3_drop_crd_in_outer.out_val()) + spaccumulator1_3.set_val(spaccumulator1_3_drop_val.out_val()) + spaccumulator1_3.set_in_crd0(spaccumulator1_3_drop_crd_in_inner.out_val()) + + fiberwrite_Xvals_0.set_input(spaccumulator1_3.out_val()) + fiberwrite_X1_1.set_input(spaccumulator1_3.out_crd0()) + + fiberlookup_Bi_17.update() + fiberlookup_Bk_12.update() + fiberwrite_X0_2.update() + repsiggen_i_15.update() + repeat_Ci_14.update() + fiberlookup_Ck_13.update() + intersectk_11.update() + fiberlookup_Cj_10.update() + arrayvals_C_6.update() + repsiggen_j_8.update() + repeat_Bj_7.update() + arrayvals_B_5.update() + mul_4.update() + spaccumulator1_3_crd_hold_in_ik.update() + spaccumulator1_3_crd_hold_in_ij.update() + spaccumulator1_3_drop_crd_in_outer.update() + spaccumulator1_3_drop_val.update() + spaccumulator1_3_drop_crd_in_inner.update() + spaccumulator1_3.update() + fiberwrite_Xvals_0.update() + fiberwrite_X1_1.update() + + done = fiberwrite_X0_2.out_done() and fiberwrite_Xvals_0.out_done() and fiberwrite_X1_1.out_done() + time_cnt += 1 + + fiberwrite_X0_2.autosize() + fiberwrite_Xvals_0.autosize() + fiberwrite_X1_1.autosize() + + out_crds = [fiberwrite_X0_2.get_arr(), fiberwrite_X1_1.get_arr()] + out_segs = [fiberwrite_X0_2.get_seg_arr(), fiberwrite_X1_1.get_seg_arr()] + out_vals = fiberwrite_Xvals_0.get_arr() + + def bench(): + time.sleep(0.01) + + extra_info = dict() + extra_info["dataset"] = ssname + extra_info["cycles"] = time_cnt + extra_info["tensor_B_shape"] = B_shape + extra_info["tensor_C_shape"] = C_shape + sample_dict = fiberwrite_X0_2.return_statistics() + for k in sample_dict.keys(): + extra_info["fiberwrite_X0_2" + "_" + k] = sample_dict[k] + + sample_dict = repeat_Ci_14.return_statistics() + for k in sample_dict.keys(): + extra_info["repeat_Ci_14" + "_" + k] = sample_dict[k] + + sample_dict = intersectk_11.return_statistics() + for k in sample_dict.keys(): + extra_info["intersectk_11" + "_" + k] = sample_dict[k] + + sample_dict = spaccumulator1_3.return_statistics() + for k in sample_dict.keys(): + extra_info["spaccumulator1_3" + "_" + k] = sample_dict[k] + + sample_dict = fiberwrite_Xvals_0.return_statistics() + for k in sample_dict.keys(): + extra_info["fiberwrite_Xvals_0" + "_" + k] = sample_dict[k] + + sample_dict = fiberwrite_X1_1.return_statistics() + for k in sample_dict.keys(): + extra_info["fiberwrite_X1_1" + "_" + k] = sample_dict[k] + + sample_dict = repeat_Bj_7.return_statistics() + for k in sample_dict.keys(): + extra_info["repeat_Bj_7" + "_" + k] = sample_dict[k] + + sample_dict = arrayvals_B_5.return_statistics() + for k in sample_dict.keys(): + extra_info["arrayvals_B_5" + "_" + k] = sample_dict[k] + + sample_dict = arrayvals_C_6.return_statistics() + for k in sample_dict.keys(): + extra_info["arrayvals_C_6" + "_" + k] = sample_dict[k] + + if check_gold: + print("Checking gold...") + check_gold_matmul(ssname, debug_sim, cast, out_crds, out_segs, out_vals) + samBench(bench, extra_info) diff --git a/sam/sim/test/primitives/test_spacc.py b/sam/sim/test/primitives/test_spacc.py index 39b08960..caecee14 100644 --- a/sam/sim/test/primitives/test_spacc.py +++ b/sam/sim/test/primitives/test_spacc.py @@ -1,19 +1,92 @@ import copy import pytest +import random +import numpy as np -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SparseAccumulator1, SpAcc1New +from sam.sim.src.rd_scanner import CompressedCrdRdScan +from sam.sim.src.array import Array +from sam.sim.src.wr_scanner import ValsWrScan, CompressWrScan from sam.sim.src.base import remove_emptystr -from sam.sim.test.test import TIMEOUT +from sam.sim.test.test import TIMEOUT, gen_n_comp_arrs, gen_val_arr, get_point_list, \ + convert_point_tuple, convert_ndarr_point_tuple, convert_point_tuple_ndarr, check_point_tuple -arrs_dict1 = {'ocrd_in': [0, 0, 0, 2, 2, 2, 2, 2, 2, 'D'], - 'icrd_in': [0, 2, 3, 0, 2, 3, 0, 2, 3, 'D'], - 'val_in': [50, 5, 10, 40, 4, 8, -40, 33, 36, 'D'], +# Old sparse accumulator +arrs_dict1 = {'ocrd_in': [0, 2, 'S0', 2, 'S1', 'D'], + 'icrd_in': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 0, 2, 3, 'S2', 'D'], + 'val_in': [50, 5, 10, 'S0', 40, 4, 8, 'S1', -40, 33, 36, 'S2', 'D'], 'ocrd_gold': [0, 2, 'S0', 'D'], 'icrd_gold': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], 'val_gold': [50, 5, 10, 'S0', 0, 37, 44, 'S1', 'D']} +arrs_dict2 = { + 'ocrd_in': [0, 'S0', 1, 'S0', 2, 'S0', 3, 'S0', 4, 'S0', 5, 'S0', 6, 'S0', 7, 'S0', 8, 'S0', 9, 'S0', 10, 'S0', + 11, 'S0', 12, 'S0', 13, 'S0', 14, 'S0', 15, 'S0', 16, 'S0', 17, 'S0', 18, 'S0', 19, 'S0', 20, 'S0', + 21, 'S0', 22, 'S0', 23, 'S0', 24, 'S0', 25, 'S0', 26, 'S0', 27, 'S0', 28, 'S0', 29, 'S0', 30, 'S0', + 31, 'S0', 32, 'S0', 33, 'S0', 34, 'S0', 35, 'S0', 36, 'S0', 37, 'S0', 38, 'S0', 39, 'S0', 40, 'S0', + 41, 'S0', 42, 'S0', 43, 'S0', 44, 'S0', 45, 'S0', 46, 'S0', 47, 'S0', 48, 'S0', 49, 'S0', 50, 'S0', + 51, 'S0', 52, 'S0', 53, 'S0', 54, 'S0', 55, 'S0', 56, 'S0', 57, 'S0', 58, 'S0', 59, 'S0', 60, 'S0', + 61, 'S0', 62, 'S0', 63, 'S0', 64, 'S0', 65, 'S1', 'D'], + 'icrd_in': [65, 'S1', 0, 'S1', 1, 'S1', 2, 'S1', 3, 'S1', 4, 'S1', 5, 'S1', 6, 'S1', 7, 'S1', 8, 'S1', 9, 'S1', + 10, 'S1', 11, 'S1', 12, 'S1', 13, 'S1', 14, 'S1', 15, 'S1', 16, 'S1', 17, 'S1', 18, 'S1', 19, 'S1', + 20, 'S1', 21, 'S1', 22, 'S1', 23, 'S1', 24, 'S1', 25, 'S1', 26, 'S1', 27, 'S1', 28, 'S1', 29, 'S1', 30, + 'S1', 31, 'S1', 32, 'S1', 33, 'S1', 34, 'S1', 35, 'S1', 36, 'S1', 37, 'S1', 38, 'S1', 39, 'S1', 40, + 'S1', 41, 'S1', 42, 'S1', 43, 'S1', 44, 'S1', 45, 'S1', 46, 'S1', 47, 'S1', 48, 'S1', 49, 'S1', 50, + 'S1', 51, 'S1', 52, 'S1', 53, 'S1', 54, 'S1', 55, 'S1', 56, 'S1', 57, 'S1', 58, 'S1', 59, 'S1', 60, + 'S1', 61, 'S1', 62, 'S1', 63, 'S1', 64, 'S2', 'D'], + 'val_in': [0.18427716102, 'S1', 0.18427716102, 'S1', 0.18427716102, 'S1', 0.275991475966, 'S1', 0.275991475966, + 'S1', 0.275991475966, 'S1', 0.275991475966, 'S1', 0.275991475966, 'S1', 0.275991475966, 'S1', + 0.18427716102, 'S1', 0.18427716102, 'S1', 0.18427716102, 'S1', 0.34565714691, 'S1', 0.34565714691, 'S1', + 0.34565714691, 'S1', 0.1704767152044, 'S1', 0.1704767152044, 'S1', 0.1704767152044, 'S1', + 0.1704767152044, 'S1', 0.1704767152044, 'S1', 0.1704767152044, 'S1', 0.34565714691, 'S1', 0.34565714691, + 'S1', 0.34565714691, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', + 0.282616682952, 'S1', 0.282616682952, 'S1', 0.282616682952, 'S1', 0.282616682952, 'S1', 0.282616682952, + 'S1', 0.282616682952, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', + 0.250853276904, 'S1', 0.250853276904, 'S1', 0.250853276904, 'S1', 0.1066417854742, 'S1', 0.1066417854742, + 'S1', 0.1066417854742, 'S1', 0.1066417854742, 'S1', 0.1066417854742, 'S1', 0.1066417854742, 'S1', + 0.250853276904, 'S1', 0.250853276904, 'S1', 0.250853276904, 'S1', 0.0463412200974, 'S1', 0.0463412200974, + 'S1', 0.0463412200974, 'S1', 0.061186376815, 'S1', 0.061186376815, 'S1', 0.061186376815, 'S1', + 0.1297137398738, 'S1', 0.1297137398738, 'S1', 0.1297137398738, 'S1', 0.1297137398738, 'S1', + 0.1297137398738, 'S1', 0.1297137398738, 'S1', 0.061186376815, 'S1', 0.061186376815, 'S1', 0.061186376815, + 'S1', 0.03949387733, 'S1', 0.03949387733, 'S1', 0.03949387733, 'S2', 'D'], + 'ocrd_gold': list(range(0, 66)) + ['S0', 'D'], + 'icrd_gold': [0, 'S0', 1, 'S0', 2, 'S0', 3, 'S0', 4, 'S0', 5, 'S0', 6, 'S0', 7, 'S0', 8, 'S0', 9, 'S0', 10, 'S0', + 11, 'S0', 12, 'S0', 13, 'S0', 14, 'S0', 15, 'S0', 16, 'S0', 17, 'S0', 18, 'S0', 19, 'S0', 20, 'S0', + 21, 'S0', 22, 'S0', 23, 'S0', 24, 'S0', 25, 'S0', 26, 'S0', 27, 'S0', 28, 'S0', 29, 'S0', 30, 'S0', + 31, 'S0', 32, 'S0', 33, 'S0', 34, 'S0', 35, 'S0', 36, 'S0', 37, 'S0', 38, 'S0', 39, 'S0', 40, 'S0', + 41, 'S0', 42, 'S0', 43, 'S0', 44, 'S0', 45, 'S0', 46, 'S0', 47, 'S0', 48, 'S0', 49, 'S0', 50, 'S0', + 51, 'S0', 52, 'S0', 53, 'S0', 54, 'S0', 55, 'S0', 56, 'S0', 57, 'S0', 58, 'S0', 59, 'S0', 60, 'S0', + 61, 'S0', 62, 'S0', 63, 'S0', 64, 'S0', 65, 'S1', 'D'], + 'val_gold': [0.18427716102, 'S0', 0.18427716102, 'S0', 0.275991475966, 'S0', 0.275991475966, 'S0', 0.275991475966, + 'S0', + 0.275991475966, 'S0', 0.275991475966, 'S0', 0.275991475966, 'S0', 0.18427716102, 'S0', 0.18427716102, + 'S0', + 0.18427716102, 'S0', 0.34565714691, 'S0', 0.34565714691, 'S0', 0.34565714691, 'S0', 0.1704767152044, + 'S0', 0.1704767152044, + 'S0', 0.1704767152044, 'S0', 0.1704767152044, 'S0', 0.1704767152044, 'S0', 0.1704767152044, 'S0', + 0.34565714691, 'S0', + 0.34565714691, 'S0', 0.34565714691, 'S0', 0.1234664378214, 'S0', 0.1234664378214, 'S0', + 0.1234664378214, + 'S0', 0.282616682952, 'S0', 0.282616682952, 'S0', 0.282616682952, 'S0', 0.282616682952, 'S0', + 0.282616682952, + 'S0', 0.282616682952, 'S0', 0.1234664378214, 'S0', 0.1234664378214, 'S0', 0.1234664378214, 'S0', + 0.250853276904, + 'S0', 0.250853276904, 'S0', 0.250853276904, 'S0', 0.1066417854742, 'S0', 0.1066417854742, 'S0', + 0.1066417854742, + 'S0', 0.1066417854742, 'S0', 0.1066417854742, 'S0', 0.1066417854742, 'S0', 0.250853276904, 'S0', + 0.250853276904, + 'S0', 0.250853276904, 'S0', 0.0463412200974, 'S0', 0.0463412200974, 'S0', 0.0463412200974, 'S0', + 0.061186376815, + 'S0', 0.061186376815, 'S0', 0.061186376815, 'S0', 0.1297137398738, 'S0', 0.1297137398738, 'S0', + 0.1297137398738, + 'S0', 0.1297137398738, 'S0', 0.1297137398738, 'S0', 0.1297137398738, 'S0', 0.061186376815, 'S0', + 0.061186376815, + 'S0', 0.061186376815, 'S0', 0.03949387733, 'S0', 0.03949387733, 'S0', 0.03949387733, 'S0', + 0.18427716102, 'S1', 'D'] +} -@pytest.mark.parametrize("arrs", [arrs_dict1]) +@pytest.mark.skip("Old sparse accumulator 1 test") +@pytest.mark.parametrize("arrs", [arrs_dict1, arrs_dict2]) def test_spacc1_direct(arrs, debug_sim): icrd = copy.deepcopy(arrs['icrd_in']) ocrd = copy.deepcopy(arrs['ocrd_in']) @@ -32,16 +105,16 @@ def test_spacc1_direct(arrs, debug_sim): out_val = [] while not done and time < TIMEOUT: if len(icrd) > 0: - sa.set_inner_crdpt(icrd.pop(0)) + sa.set_in_crd0(icrd.pop(0)) if len(ocrd) > 0: - sa.set_outer_crdpt(ocrd.pop(0)) + sa.set_in_crd1(ocrd.pop(0)) if len(val) > 0: sa.set_val(val.pop(0)) sa.update() - out_ocrd.append(sa.out_outer_crd()) - out_icrd.append(sa.out_inner_crd()) + out_ocrd.append(sa.out_crd1()) + out_icrd.append(sa.out_crd0()) out_val.append(sa.out_val()) print("Timestep", time, "\t Done:", sa.out_done()) @@ -63,23 +136,161 @@ def test_spacc1_direct(arrs, debug_sim): assert (out_val == gold_val) -arrs_dict1 = {'crd1_in': [0, 2, 3, 0, 0, 2, 2, 2, 3, 3, 3, 3, 3, 0, 'D'], - 'crd0_in': [0, 2, 3, 0, 2, 0, 0, 3, 0, 2, 3, 0, 2, 0, 'D'], - 'val_in': [50, 5, 10, 40, 4, 8, -40, 33, 36, 1, 2, 3, 4, 5, 'D'], - 'crd1_gold': [0, 2, 3, 'S0', 'D'], - 'crd0_gold': [0, 2, 'S0', 0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], - 'val_gold': [95.0, 4.0, 'S0', -32.0, 5.0, 33.0, 'S0', 39.0, 5.0, 12.0, 'S1', 'D']} +arrs_dict1 = {'ocrd_in': [0, 2, 'S0', 2, 'S1', 'D'], + 'icrd_in': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 0, 2, 3, 'S2', 'D'], + 'val_in': [50, 5, 10, 'S0', 40, 4, 8, 'S1', -40, 33, 36, 'S2', 'D'], + 'icrd_gold': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], + 'val_gold': [90, 9, 18, 'S0', -40, 33, 36, 'S1', 'D']} -arrs_dict2 = {'crd1_in': [0, 0, 0, 1, 1, 1, 1, 0, 0, 'D'], - 'crd0_in': [0, 2, 3, 0, 2, 3, 4, 2, 3, 'D'], - 'val_in': [50, 5, 10, 40, 4, 8, -40, 33, 36, 'D'], - 'crd1_gold': [0, 1, 'S0', 'D'], - 'crd0_gold': [0, 2, 3, 'S0', 0, 2, 3, 4, 'S1', 'D'], - 'val_gold': [50, 38, 46, 'S0', 40, 4, 8, -40, 'S1', 'D']} +# New sparse accumulator +@pytest.mark.parametrize("arrs", [arrs_dict1]) +def test_spacc1new_direct(arrs, debug_sim): + icrd = copy.deepcopy(arrs['icrd_in']) + ocrd = copy.deepcopy(arrs['ocrd_in']) + val = copy.deepcopy(arrs['val_in']) -@pytest.mark.parametrize("arrs", [arrs_dict1, arrs_dict2]) -def test_spacc2_direct(arrs, debug_sim): + gold_icrd = copy.deepcopy(arrs['icrd_gold']) + gold_val = copy.deepcopy(arrs['val_gold']) + + sa = SpAcc1New(valtype=int, val_stkn=True, debug=debug_sim) + + done = False + time = 0 + out_icrd = [] + out_val = [] + while not done and time < TIMEOUT: + if len(icrd) > 0: + sa.set_in_crd0(icrd.pop(0)) + if len(ocrd) > 0: + sa.set_in_crd1(ocrd.pop(0)) + if len(val) > 0: + sa.set_val(val.pop(0)) + + sa.update() + + out_icrd.append(sa.out_crd0()) + out_val.append(sa.out_val()) + + print("Timestep", time, "\t Done:", sa.out_done()) + + done = sa.out_done() + time += 1 + + out_icrd = remove_emptystr(out_icrd) + out_val = remove_emptystr(out_val) + + if debug_sim: + print("Inner Crd: ", out_icrd) + print("Vals: ", out_val) + + assert (out_icrd == gold_icrd) + assert (out_val == gold_val) + + +@pytest.mark.parametrize("dim", [2 ** x for x in range(2, 11, 2)]) +def test_spacc1new_rand(dim, debug_sim, max_val=1000, fill=0): + in_mat_crds1, in_mat_segs1 = gen_n_comp_arrs(2, dim) + in_mat_vals1 = gen_val_arr(len(in_mat_crds1[-1]), max_val, -max_val) + + in1_tup = convert_point_tuple(get_point_list(in_mat_crds1, in_mat_segs1, in_mat_vals1)) + + nd1 = convert_point_tuple_ndarr(in1_tup, dim) + gold_nd = np.sum(nd1, 0) + gold_tup = convert_ndarr_point_tuple(gold_nd) + + rdscan_B1 = CompressedCrdRdScan(crd_arr=in_mat_crds1[0], seg_arr=in_mat_segs1[0], debug=debug_sim) + rdscan_B2 = CompressedCrdRdScan(crd_arr=in_mat_crds1[1], seg_arr=in_mat_segs1[1], debug=debug_sim) + + val_B = Array(init_arr=in_mat_vals1, debug=debug_sim) + sa = SpAcc1New(valtype=int, val_stkn=True, debug=debug_sim) + + vals_X = ValsWrScan(size=dim * dim, fill=fill, debug=debug_sim) + wrscan_X1 = CompressWrScan(seg_size=2, size=dim, fill=fill, debug=debug_sim) + + done = False + time = 0 + in_ref_B = [0, 'D'] + out_rdscan_B1 = [] + out_rdscan_B2 = [] + out_val_B = [] + while not done and time < TIMEOUT: + if len(in_ref_B) > 0: + rdscan_B1.set_in_ref(in_ref_B.pop(0)) + + rdscan_B2.set_in_ref(rdscan_B1.out_ref()) + val_B.set_load(rdscan_B2.out_ref()) + + # Inject random empty strings + out_rdscan_B1.append(rdscan_B1.out_crd()) + out_rdscan_B2.append(rdscan_B2.out_crd()) + out_val_B.append(val_B.out_load()) + if random.random() < 0.2: + out_rdscan_B1.append("") + if random.random() < 0.2: + out_rdscan_B2.append("") + if random.random() < 0.2: + out_val_B.append("") + + sa.set_in_crd1(out_rdscan_B1.pop(0)) + sa.set_in_crd0(out_rdscan_B2.pop(0)) + sa.set_val(out_val_B.pop(0)) + vals_X.set_input(sa.out_val()) + wrscan_X1.set_input(sa.out_crd0()) + + rdscan_B1.update() + rdscan_B2.update() + val_B.update() + sa.update() + vals_X.update() + wrscan_X1.update() + + print("Timestep", time, "\t Done --", + "\tRdScan B1:", rdscan_B1.out_done(), + "\tSpAcc1New:", sa.out_done(), + "\tArr:", val_B.out_done(), + "\tWrScan:", vals_X.out_done(), + "\tWrScan X1:", wrscan_X1.out_done(), + ) + + done = wrscan_X1.out_done() + time += 1 + + wrscan_X1.autosize() + vals_X.autosize() + + out_crds = [wrscan_X1.get_arr()] + out_segs = [wrscan_X1.get_seg_arr()] + out_val = vals_X.get_arr() + + if debug_sim: + print("Input", in_mat_segs1, in_mat_crds1, in_mat_vals1) + print("X seg", out_segs) + print("X crd", out_crds) + print("X val", out_val) + print("Gold np", gold_nd) + print("Gold Tuple", gold_tup) + + if not out_val: + assert out_val == gold_tup + else: + out_tup = convert_point_tuple(get_point_list(out_crds, out_segs, out_val)) + assert (check_point_tuple(out_tup, gold_tup)) + + +arrs_dict1 = {'crd2_in': [0, 1, 'S0', 'D'], + 'crd1_in': [0, 2, 'S0', 2, 'S1', 'D'], + 'crd0_in': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 0, 2, 3, 'S2', 'D'], + 'val_in': [50, 5, 10, 'S0', 40, 4, 8, 'S1', -40, 33, 36, 'S2', 'D'], + 'crd1_gold': [0, 2, 'S0', 'D'], + 'crd0_gold': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], + 'val_gold': [50, 5, 10, 'S0', 0, 37, 44, 'S1', 'D']} + + +# New sparse accumulator +@pytest.mark.parametrize("arrs", [arrs_dict1]) +def test_spacc2new_direct(arrs, debug_sim): + crd2 = copy.deepcopy(arrs['crd2_in']) crd1 = copy.deepcopy(arrs['crd1_in']) crd0 = copy.deepcopy(arrs['crd0_in']) val = copy.deepcopy(arrs['val_in']) @@ -88,25 +299,25 @@ def test_spacc2_direct(arrs, debug_sim): gold_crd0 = copy.deepcopy(arrs['crd0_gold']) gold_val = copy.deepcopy(arrs['val_gold']) - sa = SparseAccumulator2(val_stkn=True, debug=debug_sim) + sa = SpAcc2New(valtype=int, val_stkn=True, debug=debug_sim) done = False time = 0 - out_crd1 = [] - out_crd0 = [] + out_icrd = [] out_val = [] while not done and time < TIMEOUT: if len(crd0) > 0: - sa.set_crd_inner(crd0.pop(0)) + sa.set_in_crd0(crd0.pop(0)) if len(crd1) > 0: - sa.set_crd_outer(crd1.pop(0)) + sa.set_in_crd1(crd1.pop(0)) + if len(crd2) > 0: + sa.set_in_crd2(crd2.pop(0)) if len(val) > 0: sa.set_val(val.pop(0)) sa.update() - out_crd1.append(sa.out_crd_outer()) - out_crd0.append(sa.out_crd_inner()) + out_icrd.append(sa.out_crd0()) out_val.append(sa.out_val()) print("Timestep", time, "\t Done:", sa.out_done()) @@ -114,15 +325,12 @@ def test_spacc2_direct(arrs, debug_sim): done = sa.out_done() time += 1 - out_crd1 = remove_emptystr(out_crd1) - out_crd0 = remove_emptystr(out_crd0) + out_icrd = remove_emptystr(out_icrd) out_val = remove_emptystr(out_val) if debug_sim: - print("Crd1: ", out_crd1) - print("Crd0: ", out_crd0) + print("Inner Crd: ", out_icrd) print("Vals: ", out_val) - assert (out_crd1 == gold_crd1) - assert (out_crd0 == gold_crd0) - assert (out_val == gold_val) + assert (out_icrd == gold_icrd) + assert (out_val == gold_val) \ No newline at end of file diff --git a/sam/sim/test/primitives/test_spacc_helpers.py b/sam/sim/test/primitives/test_spacc_helpers.py new file mode 100644 index 00000000..c85c2e14 --- /dev/null +++ b/sam/sim/test/primitives/test_spacc_helpers.py @@ -0,0 +1,128 @@ +import copy +import pytest + +from sam.sim.src.accumulator_helpers import SpAcc1NoCrdHold, SpAcc2NoCrdHold +from sam.sim.src.base import remove_emptystr +from sam.sim.test.test import TIMEOUT + +arrs_dict1 = {'ocrd_in': [0, 2, 2, 2, 2, 2, 2, 'D'], + 'icrd_in': [0, 2, 3, 0, 2, 3, 0, 2, 3, 'D'], + 'val_in': [50, 5, 10, 40, 4, 8, -40, 33, 36, 'D'], + 'ocrd_gold': [0, 2, 'S0', 'D'], + 'icrd_gold': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], + 'val_gold': [50, 5, 10, 'S0', 0, 37, 44, 'S1', 'D']} + + +@pytest.mark.parametrize("arrs", [arrs_dict1]) +def test_spacc1_no_crdhold_direct(arrs, debug_sim): + icrd = copy.deepcopy(arrs['icrd_in']) + ocrd = copy.deepcopy(arrs['ocrd_in']) + val = copy.deepcopy(arrs['val_in']) + + gold_ocrd = copy.deepcopy(arrs['ocrd_gold']) + gold_icrd = copy.deepcopy(arrs['icrd_gold']) + gold_val = copy.deepcopy(arrs['val_gold']) + + sa = SpAcc1NoCrdHold(val_stkn=True, debug=debug_sim) + + done = False + time = 0 + out_ocrd = [] + out_icrd = [] + out_val = [] + while not done and time < TIMEOUT: + if len(icrd) > 0: + sa.set_in_crd0(icrd.pop(0)) + if len(ocrd) > 0: + sa.set_in_crd1(ocrd.pop(0)) + if len(val) > 0: + sa.set_val(val.pop(0)) + + sa.update() + + out_ocrd.append(sa.out_crd1()) + out_icrd.append(sa.out_crd0()) + out_val.append(sa.out_val()) + + print("Timestep", time, "\t Done:", sa.out_done()) + + done = sa.out_done() + time += 1 + + out_ocrd = remove_emptystr(out_ocrd) + out_icrd = remove_emptystr(out_icrd) + out_val = remove_emptystr(out_val) + + if debug_sim: + print("Outer Crd: ", out_ocrd) + print("Inner Crd: ", out_icrd) + print("Vals: ", out_val) + + assert (out_ocrd == gold_ocrd) + assert (out_icrd == gold_icrd) + assert (out_val == gold_val) + + +arrs_dict1 = {'crd1_in': [0, 2, 3, 0, 0, 2, 2, 2, 3, 3, 3, 3, 3, 0, 'D'], + 'crd0_in': [0, 2, 3, 0, 2, 0, 0, 3, 0, 2, 3, 0, 2, 0, 'D'], + 'val_in': [50, 5, 10, 40, 4, 8, -40, 33, 36, 1, 2, 3, 4, 5, 'D'], + 'crd1_gold': [0, 2, 3, 'S0', 'D'], + 'crd0_gold': [0, 2, 'S0', 0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], + 'val_gold': [95.0, 4.0, 'S0', -32.0, 5.0, 33.0, 'S0', 39.0, 5.0, 12.0, 'S1', 'D']} + +arrs_dict2 = {'crd1_in': [0, 0, 0, 1, 1, 1, 1, 0, 0, 'D'], + 'crd0_in': [0, 2, 3, 0, 2, 3, 4, 2, 3, 'D'], + 'val_in': [50, 5, 10, 40, 4, 8, -40, 33, 36, 'D'], + 'crd1_gold': [0, 1, 'S0', 'D'], + 'crd0_gold': [0, 2, 3, 'S0', 0, 2, 3, 4, 'S1', 'D'], + 'val_gold': [50, 38, 46, 'S0', 40, 4, 8, -40, 'S1', 'D']} + + +@pytest.mark.parametrize("arrs", [arrs_dict1, arrs_dict2]) +def test_spacc2_no_crdhold_direct(arrs, debug_sim): + crd1 = copy.deepcopy(arrs['crd1_in']) + crd0 = copy.deepcopy(arrs['crd0_in']) + val = copy.deepcopy(arrs['val_in']) + + gold_crd1 = copy.deepcopy(arrs['crd1_gold']) + gold_crd0 = copy.deepcopy(arrs['crd0_gold']) + gold_val = copy.deepcopy(arrs['val_gold']) + + sa = SpAcc2NoCrdHold(val_stkn=True, debug=debug_sim) + + done = False + time = 0 + out_crd1 = [] + out_crd0 = [] + out_val = [] + while not done and time < TIMEOUT: + if len(crd0) > 0: + sa.set_in_crd0(crd0.pop(0)) + if len(crd1) > 0: + sa.set_in_crd1(crd1.pop(0)) + if len(val) > 0: + sa.set_val(val.pop(0)) + + sa.update() + + out_crd1.append(sa.out_crd1()) + out_crd0.append(sa.out_crd0()) + out_val.append(sa.out_val()) + + print("Timestep", time, "\t Done:", sa.out_done()) + + done = sa.out_done() + time += 1 + + out_crd1 = remove_emptystr(out_crd1) + out_crd0 = remove_emptystr(out_crd0) + out_val = remove_emptystr(out_val) + + if debug_sim: + print("Crd1: ", out_crd1) + print("Crd0: ", out_crd0) + print("Vals: ", out_val) + + assert (out_crd1 == gold_crd1) + assert (out_crd0 == gold_crd0) + assert (out_val == gold_val) diff --git a/scripts/test_generating_code.py b/scripts/test_generating_code.py index 36ae7869..e823d5e6 100755 --- a/scripts/test_generating_code.py +++ b/scripts/test_generating_code.py @@ -2,6 +2,7 @@ import os import argparse import networkx as nx +import copy from collections import defaultdict @@ -55,7 +56,16 @@ def get_location(self, ten): return 1 -class CodeGenerationdatasets: +def strip_quotes_dict(dd): + return_dict = {} + for kk, vv in dd.items(): + assert(isinstance(vv, str)) + element = vv.replace('"', '') + return_dict[kk] = element + return return_dict + + +class CodeGenerationDatasets: def __init__(self): # Rememebers [parents of a node self.stream_join_elements = {} @@ -64,16 +74,24 @@ def __init__(self): # Not used required since intersection has special structure need to know which reference is which coordinate self.intersect_dataset = defaultdict(dict) self.done_all = {} + self.edge_data_map = {} def build_datasets(self, networkx_graph): for u, v, a in networkx_graph.edges(data=True): + print(u, v, a) if v not in self.done_all: self.done_all[v] = 0 if v not in self.stream_join_elements: self.stream_join_elements[v] = [u] + clean_map = strip_quotes_dict(a) + print(clean_map) + self.set_edge_data_map(u, v, clean_map) self.edge_data[v] = [str((a["label"]).strip('"'))] else: self.stream_join_elements[v].append(u) + clean_map = strip_quotes_dict(a) + print(clean_map) + self.set_edge_data_map(u, v, clean_map) self.edge_data[v].append(str((a["label"]).strip('"'))) def get_edge_data(self): @@ -82,6 +100,7 @@ def get_edge_data(self): def get_edge_info(self, v, i): if self.edge_data[v][i] is None and len(self.edge_data[v][i]) == 0: return "" + # FIXME: This can't handle any index variable... Only 'ijk' what about 'lmn...' if "-i" in self.edge_data[v][i] or "-j" in self.edge_data[v][i] or "-k" in self.edge_data[v][i]: return str(self.edge_data[v][i])[:-2] return str(self.edge_data[v][i]) @@ -101,6 +120,14 @@ def set_edge_data(self, v, i, string): def get_if_node_done(self, v): return self.done_all[v] + def get_edge_data_map(self): + return self.edge_data_map + + def set_edge_data_map(self, in_node_id, out_node_id, node_attr_map): + if in_node_id in self.edge_data_map.keys(): + self.edge_data_map[in_node_id][out_node_id] = node_attr_map + else: + self.edge_data_map[in_node_id] = {out_node_id: node_attr_map} def tab(a): ans = "" @@ -209,73 +236,73 @@ def generate_datasets_code(f, tensor_formats, scope_lvl, tensor_info, tensor_for if tensor_format_parse.get_format(ten) == "ds01": f.write( tab(scope_lvl) + ten + "1_seg_filename = os.path.join(" + ten + "_dirname" + ", \"tensor_" + ten + - "_mode_1_seg\" )\n") + "_mode_1_seg\")\n") f.write(tab(scope_lvl) + ten + "_seg1" + " = read_inputs(" + ten + "1_seg_filename)\n") f.write( tab(scope_lvl) + ten + "1_crd_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_dirname" + "tensor_" + ten + "_mode_1_crd\" )\n") + "_dirname" + "tensor_" + ten + "_mode_1_crd\")\n") f.write(tab(scope_lvl) + ten + "_crd1" + " = read_inputs(" + ten + "1_crd_filename)\n\n") elif tensor_format_parse.get_format(ten) == "ds10": f.write( tab(scope_lvl) + ten + "0_seg_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_0_seg\" )\n") + "_mode_0_seg\")\n") f.write(tab(scope_lvl) + ten + "_seg0" + " = read_inputs(" + ten + "0_seg_filename)\n") f.write( tab(scope_lvl) + ten + "0_crd_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_0_crd\" )\n") + "_mode_0_crd\")\n") f.write(tab(scope_lvl) + ten + "_crd0" + " = read_inputs(" + ten + "0_crd_filename)\n\n") # f.write(tab(scope_lvl) + ten + "_seg1" + " = read_inputs(" + ten + "1_crd_filename)") elif tensor_format_parse.get_format(ten) == "ss01": f.write( tab(scope_lvl) + ten + "0_seg_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_0_seg\" )\n") + "_mode_0_seg\")\n") f.write(tab(scope_lvl) + ten + "_seg0" + " = read_inputs(" + ten + "0_seg_filename)\n") f.write( tab(scope_lvl) + ten + "0_crd_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_0_crd\" )\n") + "_mode_0_crd\")\n") f.write(tab(scope_lvl) + ten + "_crd0" + " = read_inputs(" + ten + "0_crd_filename)\n\n") f.write( tab(scope_lvl) + ten + "1_seg_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_1_seg\" )\n") + "_mode_1_seg\")\n") f.write(tab(scope_lvl) + ten + "_seg1" + " = read_inputs(" + ten + "1_seg_filename)\n") f.write( tab(scope_lvl) + ten + "1_crd_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_1_crd\" )\n") + "_mode_1_crd\")\n") f.write(tab(scope_lvl) + ten + "_crd1" + " = read_inputs(" + ten + "1_crd_filename)\n\n") elif tensor_format_parse.get_format(ten) == "ss10": f.write( tab(scope_lvl) + ten + "0_seg_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_0_seg\" )\n") + "_mode_0_seg\")\n") f.write(tab(scope_lvl) + ten + "_seg0" + " = read_inputs(" + ten + "0_seg_filename)\n") f.write( tab(scope_lvl) + ten + "0_crd_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_0_crd\" )\n") + "_mode_0_crd\")\n") f.write(tab(scope_lvl) + ten + "_crd0" + " = read_inputs(" + ten + "0_crd_filename)\n\n") f.write( tab(scope_lvl) + ten + "1_seg_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_1_seg\" )\n") + "_mode_1_seg\")\n") f.write(tab(scope_lvl) + ten + "_seg1" + " = read_inputs(" + ten + "1_seg_filename)\n") f.write( tab(scope_lvl) + ten + "1_crd_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_1_crd\" )\n") + "_mode_1_crd\")\n") f.write(tab(scope_lvl) + ten + "_crd1" + " = read_inputs(" + ten + "1_crd_filename)\n\n") elif tensor_format_parse.get_format(ten) == "dss012": f.write( tab(scope_lvl) + ten + "1_seg_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_1_seg\" )\n") + "_mode_1_seg\")\n") f.write(tab(scope_lvl) + ten + "_seg1" + " = read_inputs(" + ten + "1_seg_filename)\n") f.write( tab(scope_lvl) + ten + "1_crd_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_1_crd\" )\n") + "_mode_1_crd\")\n") f.write(tab(scope_lvl) + ten + "_crd1" + " = read_inputs(" + ten + "1_crd_filename)\n\n") f.write( tab(scope_lvl) + ten + "2_seg_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_2_seg\" )\n") + "_mode_2_seg\")\n") f.write(tab(scope_lvl) + ten + "_seg2" + " = read_inputs(" + ten + "2_seg_filename)\n") f.write( tab(scope_lvl) + ten + "2_crd_filename = os.path.join(" + ten + "_dirname, \"tensor_" + ten + - "_mode_2_crd\" )\n") + "_mode_2_crd\")\n") f.write(tab(scope_lvl) + ten + "_crd2" + " = read_inputs(" + ten + "2_crd_filename)\n\n") else: ct = 0 @@ -295,6 +322,13 @@ def generate_datasets_code(f, tensor_formats, scope_lvl, tensor_info, tensor_for f.write(tab(scope_lvl) + ten + "_vals" + " = read_inputs(" + ten + "_vals_filename, float)\n\n") +# Gets the input number for a sparse accumulator block given the index string +def get_spacc_input(node, index): + for k, v in node.items(): + if v == index: + return k + + def gen_data_formats(size, app_name, path): ans_list = [] if size - 1 == 1: @@ -619,8 +653,9 @@ def get_all_files(directory_path): " = Repeat(debug=debug_sim, statistics=report_stats)\n") d[u]["object"] = node_info["type"] + "_" + node_info["tensor"] + node_info["index"] + "_" + str(u) elif node_info["type"] == "intersect": - f.write(tab(1) + node_info["type"] + node_info["index"] + "_" + str(u) + " = Intersect2(debug=debug_sim, " + - "statistics=report_stats)\n") + f.write( + tab(1) + node_info["type"] + node_info["index"] + "_" + str(u) + " = Intersect2(debug=debug_sim, " + + "statistics=report_stats)\n") d[u]["object"] = node_info["type"] + node_info["index"] + "_" + str(u) elif node_info["type"] == "union": f.write(tab(1) + node_info["type"] + node_info["index"] + "_" + str(u) + " = Union2(debug=debug_sim, " + @@ -631,41 +666,32 @@ def get_all_files(directory_path): f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( u) + " = SparseAccumulator1(debug=debug_sim, statistics=report_stats)\n") d[u]["object"] = node_info["type"] + node_info["order"] + "_" + str(u) - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_crd_inner" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_crd_outer" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_val" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") elif node_info["type"] == "spaccumulator" and node_info["order"] == "2": f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( u) + " = SparseAccumulator2(debug=debug_sim, statistics=report_stats)\n") d[u]["object"] = node_info["type"] + node_info["order"] + "_" + str(u) - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_crd_inner" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_crd_outer" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") - # f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - # u) + "_drop_crd_in_2" + " = StknDrop(debug=debug_sim)\n") - f.write(tab(1) + node_info["type"] + node_info["order"] + "_" + str( - u) + "_drop_val" + " = StknDrop(debug=debug_sim, statistics=report_stats)\n") elif node_info["type"] == "crddrop": f.write( - tab(1) + node_info["type"] + "_" + str(u) + " = CrdDrop(debug=debug_sim, statistics=report_stats)\n") + tab(1) + node_info["type"] + "_" + str( + u) + " = CrdDrop(debug=debug_sim, statistics=report_stats)\n") d[u]["object"] = node_info["type"] + "_" + str(u) elif node_info["type"] == "crdhold": f.write( - tab(1) + node_info["type"] + "_" + str(u) + " = CrdHold(debug=debug_sim, statistics=report_stats)\n") + tab(1) + node_info["type"] + "_" + str( + u) + " = CrdHold(debug=debug_sim, statistics=report_stats)\n") d[u]["object"] = node_info["type"] + "_" + str(u) elif node_info["type"] == "mul": f.write( - tab(1) + node_info["type"] + "_" + str(u) + " = Multiply2(debug=debug_sim, statistics=report_stats)\n") + tab(1) + node_info["type"] + "_" + str( + u) + " = Multiply2(debug=debug_sim, statistics=report_stats)\n") d[u]["object"] = node_info["type"] + "_" + str(u) elif node_info["type"] == "add": - f.write(tab(1) + node_info["type"] + "_" + str(u) + " = Add2(debug=debug_sim, statistics=report_stats)\n") + f.write( + tab(1) + node_info["type"] + "_" + str(u) + " = Add2(debug=debug_sim, statistics=report_stats)\n") d[u]["object"] = node_info["type"] + "_" + str(u) elif node_info["type"] == "reduce": - f.write(tab(1) + node_info["type"] + "_" + str(u) + " = Reduce(debug=debug_sim, statistics=report_stats)\n") + f.write( + tab(1) + node_info["type"] + "_" + str(u) + " = Reduce(debug=debug_sim, statistics=report_stats)\n") d[u]["object"] = node_info["type"] + "_" + str(u) elif node_info["type"] == "fiberwrite": if node_info["mode"] == "vals": @@ -697,7 +723,7 @@ def get_all_files(directory_path): f.write(tab(1) + "while not done and time_cnt < TIMEOUT:\n") intersect_dataset = defaultdict(dict) - data = CodeGenerationdatasets() + data = CodeGenerationDatasets() data.build_datasets(networkx_graph) for u in networkx_graph.nodes(): if d[u]["type"] == "fiberlookup" and u not in data.get_if_done(): @@ -712,7 +738,8 @@ def get_all_files(directory_path): for u, v, _ in list(nx.edge_bfs(networkx_graph)): # .edges(data=True), networkx_graph.nodes())): a = networkx_graph.get_edge_data(u, v)[0] if d[v]["type"] == "fiberlookup" and data.get_if_node_done(v) == 0 and parents_done(networkx_graph, - data.get_if_done(), v): + data.get_if_done(), + v): for i in range(len(data.get_parents()[v])): u_ = data.get_parents()[v][i] if "intersect" in d[u_]["object"] or "union" in d[u_]["object"]: @@ -798,9 +825,11 @@ def get_all_files(directory_path): for u_ in data.get_parents()[v]: index_value = data.get_edge_data()[v][data.get_parents()[v].index(u_)][-1] if index_value == d[v]["inner"]: - f.write(tab(2) + d[v]["object"] + ".set_inner_crd" + "(" + d[u_]["object"] + ".out_crd())\n") + f.write( + tab(2) + d[v]["object"] + ".set_inner_crd" + "(" + d[u_]["object"] + ".out_crd())\n") if index_value == d[v]["outer"]: - f.write(tab(2) + d[v]["object"] + ".set_outer_crd" + "(" + d[u_]["object"] + ".out_crd())\n") + f.write( + tab(2) + d[v]["object"] + ".set_outer_crd" + "(" + d[u_]["object"] + ".out_crd())\n") nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") # f.write(tab(2) + d[v]["object"] + ".update()\n\n") data.add_done(v) @@ -826,31 +855,37 @@ def get_all_files(directory_path): and data.get_if_node_done(v) == 0: for i in range(len(data.get_parents()[v])): u_ = data.get_parents()[v][i] - print("HELLO----", u_, d[u_]) local_edge = "" + node_data = d[v] if "crd" in data.get_edge_data()[v][i]: local_edge = data.get_edge_data()[v][i][:-2] - f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + + + # Get the index of the edge + local_index = data.get_edge_data_map()[u_][v]["index"] + + # Get that edge's input number based on the spacc index to number map + local_input_num = get_spacc_input(d[v], local_index)[-1] + local_edge_type = data.get_edge_data() + f.write(tab(2) + d[v]["object"] + ".set_in_crd" + local_input_num + "(" + d[u_]["object"] + ".out_" + local_edge + "())\n") else: local_edge = data.get_edge_data()[v][i] - f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + + f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + d[u_]["object"] + ".out_val())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") - # f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - for i in range(len(data.get_parents()[v])): - u_ = data.get_parents()[v][i] - local_edge = "" - if "crd" in data.get_edge_data()[v][i]: - local_edge = data.get_edge_data()[v][i][:-2] - f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + - d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") - else: - local_edge = data.get_edge_data()[v][i] - f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + - d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # for i in range(len(data.get_parents()[v])): + # u_ = data.get_parents()[v][i] + # local_edge = "" + # if "crd" in data.get_edge_data()[v][i]: + # local_edge = data.get_edge_data()[v][i][:-2] + # f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + + # d[v]["object"] + ".out_val())\n") + # else: + # local_edge = data.get_edge_data()[v][i] + # f.write(tab(2) + d[v]["object"] + ".set_in_" + local_edge + "(" + + # d[v]["object"] + ".out_val())\n") + # nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") # f.write(tab(2) + d[v]["object"] + ".update()\n\n") data.add_done(v) @@ -862,27 +897,26 @@ def get_all_files(directory_path): local_edge = "" if "crd" in data.get_edge_data()[v][i]: local_edge = data.get_edge_data()[v][i][:-2] - f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + + f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + d[u_]["object"] + ".out_" + local_edge + "())\n") else: local_edge = data.get_edge_data()[v][i] - f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".set_in_stream(" + + f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + d[u_]["object"] + ".out_val())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") - # f.write(tab(2) + d[v]["object"] + "_drop_" + local_edge + ".update()\n") + nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") - for i in range(len(data.get_parents()[v])): - u_ = data.get_parents()[v][i] - local_edge = "" - if "crd" in data.get_edge_data()[v][i]: - local_edge = data.get_edge_data()[v][i][:-2] - f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + - d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") - else: - local_edge = data.get_edge_data()[v][i] - f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + - d[v]["object"] + "_drop_" + local_edge + ".out_val())\n") - nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") + # for i in range(len(data.get_parents()[v])): + # u_ = data.get_parents()[v][i] + # local_edge = "" + # if "crd" in data.get_edge_data()[v][i]: + # local_edge = data.get_edge_data()[v][i][:-2] + # f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + + # d[v]["object"] + ".out_val())\n") + # else: + # local_edge = data.get_edge_data()[v][i] + # f.write(tab(2) + d[v]["object"] + ".set_" + local_edge + "(" + + # d[v]["object"] + ".out_val())\n") + # nodes_updating_list.append(tab(2) + d[v]["object"] + ".update()\n") # f.write(tab(2) + d[v]["object"] + ".update()\n\n") data.add_done(v) @@ -921,13 +955,15 @@ def get_all_files(directory_path): u_ = data.get_parents()[v][i] if "val" not in data.get_edge_data()[v][i] and "spaccumulator" \ in d[u_]["object"]: - local_index = data.get_edge_data()[v][i][-1] - print(d[u_], " ", local_index, " ", apath) - if d[u_]["in0"] == local_index: - local_cord = "_inner" - else: - local_cord = "_outer" - data.set_edge_data(v, i, "crd" + local_cord) + + # Get the index of the edge + local_index = data.get_edge_data_map()[u_][v]["index"] + + # Get that edge's input number based on the spacc index to number map + local_input_num = get_spacc_input(d[u_], local_index)[-1] + print(local_index, local_input_num, v, u_, d[v]) + + data.set_edge_data(v, i, "crd" + local_input_num) if d[v]["mode"] == "vals": f.write(tab(2) + d[v]["object"] + ".set_input(" + d[u_]["object"] + ".out_" + str(data.get_edge_info(v, i)) + "())\n") @@ -948,4 +984,4 @@ def get_all_files(directory_path): f.close() os.system("cp " + out_name[num] + ".py ./sam/sim/test/apps/test_" + out_name[num] + ".py") - os.system("rm " + out_name[num] + ".py") \ No newline at end of file + os.system("rm " + out_name[num] + ".py") From 9dcbefcc2c82cdbca2e529adff98ad6bc04bfc2c Mon Sep 17 00:00:00 2001 From: Olivia Hsu Date: Wed, 31 May 2023 18:13:58 -0700 Subject: [PATCH 6/9] Fix apps to use new sparse accumulator and move old one to OLD --- compiler/taco | 2 +- sam/sim/src/accumulator.py | 550 +++--------------- sam/sim/src/accumulator_OLD.py | 403 +++++++++++++ .../final-apps/test_mat_elemadd3_FINAL.py | 2 +- .../test/final-apps/test_mat_elemadd_FINAL.py | 2 +- .../final-apps/test_mat_identity_FINAL.py | 2 +- .../final-apps/test_mat_mattransmul_FINAL.py | 2 +- .../final-apps/test_mat_residual_FINAL.py | 2 +- .../test/final-apps/test_mat_sddmm_FINAL.py | 2 +- .../test/final-apps/test_mat_vecmul_FINAL.py | 2 +- .../test/final-apps/test_matmul_kij_FINAL.py | 2 +- .../final-apps/test_tensor3_elemadd_FINAL.py | 2 +- .../test_tensor3_innerprod_FINAL.py | 2 +- .../final-apps/test_tensor3_mttkrp_FINAL.py | 2 +- .../test/final-apps/test_tensor3_ttm_FINAL.py | 2 +- .../test/final-apps/test_tensor3_ttv_FINAL.py | 2 +- sam/sim/test/primitives/test_spacc.py | 288 ++++----- sam/sim/test/primitives/test_spacc_OLD.py | 132 +++++ .../reorder-study/test_reorder_matmul_ijk.py | 2 +- .../reorder-study/test_reorder_matmul_ikj.py | 2 +- .../reorder-study/test_reorder_matmul_jik.py | 2 +- .../reorder-study/test_reorder_matmul_jki.py | 2 +- .../reorder-study/test_reorder_matmul_kij.py | 2 +- .../reorder-study/test_reorder_matmul_kji.py | 2 +- .../unit-apps/test_unit_mat_mattransmul.py | 1 - .../test/unit-apps/test_unit_mat_residual.py | 2 - .../test/unit-apps/test_unit_matmul_ikj.py | 2 +- 27 files changed, 801 insertions(+), 617 deletions(-) create mode 100644 sam/sim/src/accumulator_OLD.py create mode 100644 sam/sim/test/primitives/test_spacc_OLD.py diff --git a/compiler/taco b/compiler/taco index d9472db8..6570336a 160000 --- a/compiler/taco +++ b/compiler/taco @@ -1 +1 @@ -Subproject commit d9472db8669eca5e067f00fd250f319203dea513 +Subproject commit 6570336af5fe4568c1c555b17e1da5b99b61749e diff --git a/sam/sim/src/accumulator.py b/sam/sim/src/accumulator.py index d7069fca..9efe9e15 100644 --- a/sam/sim/src/accumulator.py +++ b/sam/sim/src/accumulator.py @@ -1,11 +1,6 @@ import enum from .base import * -from .crd_manager import CrdPtConverter -from .accumulator_helpers import SparseCrdPtAccumulator2, SparseCrdPtAccumulator1, \ - SpAcc2NoCrdHold, SpAcc1NoCrdHold -from .crd_manager import CrdHold -from .token import StknDrop class Reduce(Primitive): @@ -158,228 +153,8 @@ def return_statistics(self): return stats_dict -# 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.kwargs = kwargs - self.maxdim = maxdim - self.valtype = valtype - self.last_level = last_level - # Boolean flag of whether or not to output stop tokens on the output val stream - self.val_stkn = val_stkn - - self.in_crd1 = [] - self.in_crd0 = [] - self.in_val = [] - - self.crdhold_01 = CrdHold(**kwargs) - - self.crdhold_out1 = [] - self.crdhold_out0 = [] - - self.spacc1_no_crdhold = SpAcc1NoCrdHold(maxdim=maxdim, valtype=valtype, - name=self.name + "_no_crdhold", - last_level=last_level, val_stkn=val_stkn, - **kwargs) - - self.sd_out1 = [] - self.sd_out0 = [] - self.sd_out_val = [] - - self.stkndrop_crd1 = StknDrop(**kwargs) - self.stkndrop_crd0 = StknDrop(**kwargs) - self.stkndrop_val = StknDrop(**kwargs) - - self.curr_crd1 = None - self.curr_crd0 = None - self.curr_val = None - - if self.get_stats: - 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_val = True - - - def check_backpressure(self): - if self.backpressure_en: - copy_backpressure = self.ready_backpressure - self.ready_backpressure = True - return copy_backpressure - return True - - 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: - self.backpressure.append(child) - self.branch.append(branch) - - def update_ready(self): - if self.backpressure_en: - 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 update(self): - self.update_done() - self.update_ready() - - 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_crd1, self.in_crd0, self.in_val) - print(self.crdhold_out1, self.crdhold_out0) - print(self.curr_crd1, self.curr_crd0, self.curr_val) - if self.done: - 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) - - # FIXME: (owhsu) self.data_ready not defined in init - if self.backpressure_en: - self.data_ready = True - - # 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? - if self.get_stats: - pass - - if len(self.in_crd0) > 0: - self.crdhold_01.set_inner_crd(self.in_crd0.pop(0)) - - if len(self.in_crd1) > 0: - self.crdhold_01.set_outer_crd(self.in_crd1.pop(0)) - - self.crdhold_01.update() - - self.crdhold_out1.append(self.crdhold_01.out_crd_outer()) - self.crdhold_out0.append(self.crdhold_01.out_crd_inner()) - - self.stkndrop_crd1.set_in_val(self.crdhold_01.out_crd_outer()) - self.stkndrop_crd0.set_in_val(self.crdhold_01.out_crd_inner()) - if len(self.in_val) > 0: - self.stkndrop_val.set_in_val(self.in_val.pop(0)) - - self.stkndrop_crd1.update() - self.stkndrop_crd0.update() - self.stkndrop_val.update() - - self.sd_out1.append(self.stkndrop_crd1.out_val()) - self.sd_out0.append(self.stkndrop_crd0.out_val()) - self.sd_out_val.append(self.stkndrop_val.out_val()) - - self.spacc1_no_crdhold.set_in_crd1(self.stkndrop_crd1.out_val()) - self.spacc1_no_crdhold.set_in_crd0(self.stkndrop_crd0.out_val()) - self.spacc1_no_crdhold.set_val(self.stkndrop_val.out_val()) - - self.spacc1_no_crdhold.update() - - self.curr_crd1 = self.spacc1_no_crdhold.out_crd1() - self.curr_crd0 = self.spacc1_no_crdhold.out_crd0() - self.curr_val = self.spacc1_no_crdhold.out_val() - - print(self.spacc1_no_crdhold.out_done(), self.stkndrop_crd1.out_done(), - self.stkndrop_crd0.out_done(), self.stkndrop_val.out_done(), self.crdhold_01.out_done()) - self.done = self.crdhold_01.out_done() and self.spacc1_no_crdhold.out_done() and \ - self.stkndrop_crd1.out_done() and self.stkndrop_crd0.out_done() and self.stkndrop_val.out_done() - - if self.debug: - print(self.in_crd1, self.in_crd0, self.in_val) - print(self.crdhold_out1, self.crdhold_out0) - print(self.curr_crd1, self.curr_crd0, self.curr_val) - - 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 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): - 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_crd1(self): - if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_crd1 - - def out_crd0(self): - if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - 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 return_statistics(self): - if self.get_stats: - stats_dict = {} - # TODO: Finish adding in other statistics - stats_dict.update(self.spacc1_no_crdhold.return_statistics()) - stats_dict.update(self.crdhold_01.return_statistics()) - stats_dict.update(self.stkndrop_crd1.return_statistics()) - stats_dict.update(self.stkndrop_crd0.return_statistics()) - stats_dict.update(self.stkndrop_val.return_statistics()) - stats_dict.update(super().return_statistics()) - else: - stats_dict = {} - return stats_dict - - def print_fifos(self): - print("Spaccumulator: None available") - - # NEW VERSION: Accumulation into a vector -class SpAcc1New(Primitive): +class SpAcc1(Primitive): def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, depth=1, **kwargs): super().__init__(**kwargs) self.kwargs = kwargs @@ -646,185 +421,8 @@ def print_fifos(self): print("Spaccumulator: None available") -# 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_val = [] - - self.crdpt_spacc = SparseCrdPtAccumulator2(maxdim=maxdim, valtype=valtype, **kwargs) - self.crdpt_converter = CrdPtConverter(last_level=True, **kwargs) - - self.crdpt_spacc_out_val = [] - - self.curr_1_crd = None - self.curr_0_crd = None - self.curr_val = None - - self.outer_crdpt = [] - self.inner_crdpt = [] - - self.val_stkn = val_stkn - if self.get_stats: - self.in1_fifo = 0 - self.in0_fifo = 0 - self.inval_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_val = True - self.temp_maxdim = maxdim - self.temp_valtype = valtype - self.temp_last_level = last_level - - def check_backpressure(self): - if self.backpressure_en: - copy_backpressure = self.ready_backpressure - self.ready_backpressure = True - return copy_backpressure - return True - - def set_backpressure(self, backpressure): - if not backpressure: - self.ready_backpressure = False - - def add_child(self, child=None, branch=""): - if self.backpressure_en: - if child is not None: - self.backpressure.append(child) - self.branch.append(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 - else: - self.fifo_avail_outer = True - if len(self.in_val) > self.depth: - self.fifo_avail_val = False - else: - self.fifo_avail_val = True - - def update(self): - self.update_done() - self.update_ready() - 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]) - 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.block_start = False - - 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()) - - self.curr_1_crd = self.crdpt_converter.out_crd_outer() - self.curr_0_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_0_crd, int) and \ - len(self.crdpt_spacc_out_val) > 0 else self.curr_0_crd - 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.done = self.crdpt_spacc.out_done() and self.crdpt_converter.out_done() - - 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) - 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.in1_crdpt.append(crdpt) - 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_crd_outer(self): - if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_1_crd - - def out_crd_inner(self): - if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_0_crd - - def out_val(self): - if (self.backpressure_en and self.data_valid) or not self.backpressure_en: - return self.curr_val - - 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.update(super().return_statistics()) - else: - stats_dict = {} - return stats_dict - # NEW VERSION: Accumulation into a matrix -class SpAcc2New(Primitive): +class SpAcc2(Primitive): def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, depth=1, **kwargs): super().__init__(**kwargs) self.kwargs = kwargs @@ -846,7 +444,6 @@ def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, d self.curr_crd0 = None self.curr_val = None - self.curr_in_crd1 = None self.curr_in_crd0 = None self.curr_in_val = None @@ -854,8 +451,10 @@ def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, d self.states = enum.Enum('States', ['READY', 'ACC1', 'ACC0', 'WR', 'DONE']) self.curr_state = self.states.READY self.next_state = self.states.READY - self.writeout = False - self.writeout_storage = [] + self.writeout0 = False + self.writeout1 = False + self.writeout_storage1 = [] + self.writeout_storage0 = [] self.seen_done = False self.crd2_stkn = None @@ -910,24 +509,26 @@ def update_ready(self): self.fifo_avail_inner = not (len(self.in_crd0) > self.depth) self.fifo_avail_val = not (len(self.in_val) > self.depth) - def ACC1_body(self): - # In accumulation, accumulate into memory - self.curr_in_crd1 = self.in_crd1.pop(0) + 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) - # All elements are ready - if len(self.in_crd) > 0 and len(self.in_val) > 0: - self.ACC0_body() - else: - self.next_state = self.states.ACC1 + def get_writout(self): + return self.writeout0 or self.writeout1 def build_writeout(self): result = [] - for crd1 in self.storage.keys(): - for crd0, val in self.storage[crd1]: - result.append((crd0,val)) - result.append(('S0','S0')) + for crd1 in sorted(self.storage.keys()): + print("storage:", self.storage[crd1]) + for crd0, val in self.storage[crd1].items(): + result.append((crd0, val)) + result.append(('S0', 'S0')) # Remove last stop token - return result[-1] + return result[:-1] def update_storage(self, crd1, crd0, val): if crd1 not in self.storage.keys(): @@ -939,13 +540,30 @@ def update_storage(self, crd1, crd0, val): else: 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.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_crd0, self.curr_in_crd0, self.curr_in_val) + 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): @@ -956,7 +574,7 @@ def ACC0_body(self): assert False, "Shouldn't have done token for coordinates if in accumulate (ACC) state" # Do nothing else: - self.next_state = self.states.ACC1 + assert False, "Cannot have a coordinate token of this type: " + str(self.curr_in_crd0) def update(self): self.update_done() @@ -964,12 +582,7 @@ def update(self): # Print out debugging statements if self.debug: - 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_storage, self.writeout) - print("Outputs: ", self.curr_crd1, self.curr_crd0, self.curr_val) - print("State: ", self.curr_state) + self.print_debug() if self.backpressure_en: self.data_valid = False @@ -999,7 +612,6 @@ def update(self): # 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 @@ -1010,6 +622,8 @@ def update(self): 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) @@ -1018,32 +632,44 @@ def update(self): self.ACC1_body() else: self.next_state = self.states.ACC1 - elif is_stkn(self.curr_crd1): - # TODO: what to do when we want to writeout but writeout isn't done - + elif is_stkn(self.curr_crd2) and not self.get_writout(): # Set writeout to be true, move over storage, and clear it. - self.crd1_stkn = self.curr_crd1 - self.writeout = True + 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_dtkn(self.curr_crd1): + 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.writeout: + 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_crd1) + assert False, "Cannot have a coordinate token of this type: " + str(self.curr_crd2) # Handle accumulation into storage - elif self.curr_state == self.states.ACC: + # 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.ACC_body() - # Finish writeout and then be done. + 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.writeout: + 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 @@ -1056,27 +682,44 @@ def update(self): self.next_state = self.curr_state # Writeout is true, so writeout the current values for storage - if self.writeout: + if self.get_writout(): # Writeout is done when there are no elements left - if len(self.writeout_storage) == 0: - self.writeout = False - assert self.crd2_stkn is not None, "The current writeout stop token should not be None" - self.curr_crd1 = self.crd2_stkn - self.curr_val = decrement_stkn(self.crd2_stkn) + # 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 = "" + + # 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) - self.curr_val = decrement_stkn(self.crd2_stkn) + 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: - curr_writeout_elem1 = self.writeout_storage1.pop(0) - curr_writeout_elem0 = self.writeout_storage0.pop(0) - self.curr_crd1 = curr_writeout_elem1[1] - self.curr_crd0 = curr_writeout_elem0[0] - self.curr_val = curr_writeout_elem0[1] + self.curr_crd0 = "" + self.curr_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 = "" # Update the current state self.curr_state = self.next_state @@ -1084,6 +727,7 @@ def update(self): if self.debug: 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): diff --git a/sam/sim/src/accumulator_OLD.py b/sam/sim/src/accumulator_OLD.py new file mode 100644 index 00000000..d4d15dae --- /dev/null +++ b/sam/sim/src/accumulator_OLD.py @@ -0,0 +1,403 @@ +from .base import * +from .crd_manager import CrdPtConverter +from .accumulator_helpers import SparseCrdPtAccumulator2, SpAcc1NoCrdHold +from .crd_manager import CrdHold +from .token import StknDrop + + +# 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.kwargs = kwargs + self.maxdim = maxdim + self.valtype = valtype + self.last_level = last_level + # Boolean flag of whether or not to output stop tokens on the output val stream + self.val_stkn = val_stkn + + self.in_crd1 = [] + self.in_crd0 = [] + self.in_val = [] + + self.crdhold_01 = CrdHold(**kwargs) + + self.crdhold_out1 = [] + self.crdhold_out0 = [] + + self.spacc1_no_crdhold = SpAcc1NoCrdHold(maxdim=maxdim, valtype=valtype, + name=self.name + "_no_crdhold", + last_level=last_level, val_stkn=val_stkn, + **kwargs) + + self.sd_out1 = [] + self.sd_out0 = [] + self.sd_out_val = [] + + self.stkndrop_crd1 = StknDrop(**kwargs) + self.stkndrop_crd0 = StknDrop(**kwargs) + self.stkndrop_val = StknDrop(**kwargs) + + self.curr_crd1 = None + self.curr_crd0 = None + self.curr_val = None + + if self.get_stats: + 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_val = True + + + def check_backpressure(self): + if self.backpressure_en: + copy_backpressure = self.ready_backpressure + self.ready_backpressure = True + return copy_backpressure + return True + + 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: + self.backpressure.append(child) + self.branch.append(branch) + + def update_ready(self): + if self.backpressure_en: + 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 update(self): + self.update_done() + self.update_ready() + + 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_crd1, self.in_crd0, self.in_val) + print(self.crdhold_out1, self.crdhold_out0) + print(self.curr_crd1, self.curr_crd0, self.curr_val) + if self.done: + 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) + + # FIXME: (owhsu) self.data_ready not defined in init + if self.backpressure_en: + self.data_ready = True + + # 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? + if self.get_stats: + pass + + if len(self.in_crd0) > 0: + self.crdhold_01.set_inner_crd(self.in_crd0.pop(0)) + + if len(self.in_crd1) > 0: + self.crdhold_01.set_outer_crd(self.in_crd1.pop(0)) + + self.crdhold_01.update() + + self.crdhold_out1.append(self.crdhold_01.out_crd_outer()) + self.crdhold_out0.append(self.crdhold_01.out_crd_inner()) + + self.stkndrop_crd1.set_in_val(self.crdhold_01.out_crd_outer()) + self.stkndrop_crd0.set_in_val(self.crdhold_01.out_crd_inner()) + if len(self.in_val) > 0: + self.stkndrop_val.set_in_val(self.in_val.pop(0)) + + self.stkndrop_crd1.update() + self.stkndrop_crd0.update() + self.stkndrop_val.update() + + self.sd_out1.append(self.stkndrop_crd1.out_val()) + self.sd_out0.append(self.stkndrop_crd0.out_val()) + self.sd_out_val.append(self.stkndrop_val.out_val()) + + self.spacc1_no_crdhold.set_in_crd1(self.stkndrop_crd1.out_val()) + self.spacc1_no_crdhold.set_in_crd0(self.stkndrop_crd0.out_val()) + self.spacc1_no_crdhold.set_val(self.stkndrop_val.out_val()) + + self.spacc1_no_crdhold.update() + + self.curr_crd1 = self.spacc1_no_crdhold.out_crd1() + self.curr_crd0 = self.spacc1_no_crdhold.out_crd0() + self.curr_val = self.spacc1_no_crdhold.out_val() + + print(self.spacc1_no_crdhold.out_done(), self.stkndrop_crd1.out_done(), + self.stkndrop_crd0.out_done(), self.stkndrop_val.out_done(), self.crdhold_01.out_done()) + self.done = self.crdhold_01.out_done() and self.spacc1_no_crdhold.out_done() and \ + self.stkndrop_crd1.out_done() and self.stkndrop_crd0.out_done() and self.stkndrop_val.out_done() + + if self.debug: + print(self.in_crd1, self.in_crd0, self.in_val) + print(self.crdhold_out1, self.crdhold_out0) + print(self.curr_crd1, self.curr_crd0, self.curr_val) + + 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 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): + 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_crd1(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_crd1 + + def out_crd0(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + 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 return_statistics(self): + if self.get_stats: + stats_dict = {} + # TODO: Finish adding in other statistics + stats_dict.update(self.spacc1_no_crdhold.return_statistics()) + stats_dict.update(self.crdhold_01.return_statistics()) + stats_dict.update(self.stkndrop_crd1.return_statistics()) + stats_dict.update(self.stkndrop_crd0.return_statistics()) + stats_dict.update(self.stkndrop_val.return_statistics()) + stats_dict.update(super().return_statistics()) + else: + stats_dict = {} + return stats_dict + + def print_fifos(self): + print("Spaccumulator: None available") + + +# 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_val = [] + + self.crdpt_spacc = SparseCrdPtAccumulator2(maxdim=maxdim, valtype=valtype, **kwargs) + self.crdpt_converter = CrdPtConverter(last_level=True, **kwargs) + + self.crdpt_spacc_out_val = [] + + self.curr_1_crd = None + self.curr_0_crd = None + self.curr_val = None + + self.outer_crdpt = [] + self.inner_crdpt = [] + + self.val_stkn = val_stkn + if self.get_stats: + self.in1_fifo = 0 + self.in0_fifo = 0 + self.inval_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_val = True + self.temp_maxdim = maxdim + self.temp_valtype = valtype + self.temp_last_level = last_level + + def check_backpressure(self): + if self.backpressure_en: + copy_backpressure = self.ready_backpressure + self.ready_backpressure = True + return copy_backpressure + return True + + def set_backpressure(self, backpressure): + if not backpressure: + self.ready_backpressure = False + + def add_child(self, child=None, branch=""): + if self.backpressure_en: + if child is not None: + self.backpressure.append(child) + self.branch.append(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 + else: + self.fifo_avail_outer = True + if len(self.in_val) > self.depth: + self.fifo_avail_val = False + else: + self.fifo_avail_val = True + + def update(self): + self.update_done() + self.update_ready() + 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]) + 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.block_start = False + + 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()) + + self.curr_1_crd = self.crdpt_converter.out_crd_outer() + self.curr_0_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_0_crd, int) and \ + len(self.crdpt_spacc_out_val) > 0 else self.curr_0_crd + 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.done = self.crdpt_spacc.out_done() and self.crdpt_converter.out_done() + + 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) + 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.in1_crdpt.append(crdpt) + 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_crd_outer(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_1_crd + + def out_crd_inner(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_0_crd + + def out_val(self): + if (self.backpressure_en and self.data_valid) or not self.backpressure_en: + return self.curr_val + + 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.update(super().return_statistics()) + else: + stats_dict = {} + return stats_dict \ No newline at end of file diff --git a/sam/sim/test/final-apps/test_mat_elemadd3_FINAL.py b/sam/sim/test/final-apps/test_mat_elemadd3_FINAL.py index 901fe4a9..c254b5a8 100644 --- a/sam/sim/test/final-apps/test_mat_elemadd3_FINAL.py +++ b/sam/sim/test/final-apps/test_mat_elemadd3_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_mat_elemadd_FINAL.py b/sam/sim/test/final-apps/test_mat_elemadd_FINAL.py index e230d329..ee3f772c 100644 --- a/sam/sim/test/final-apps/test_mat_elemadd_FINAL.py +++ b/sam/sim/test/final-apps/test_mat_elemadd_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_mat_identity_FINAL.py b/sam/sim/test/final-apps/test_mat_identity_FINAL.py index 36e64986..eb60dc6e 100644 --- a/sam/sim/test/final-apps/test_mat_identity_FINAL.py +++ b/sam/sim/test/final-apps/test_mat_identity_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_mat_mattransmul_FINAL.py b/sam/sim/test/final-apps/test_mat_mattransmul_FINAL.py index 79a5edff..c68fda18 100644 --- a/sam/sim/test/final-apps/test_mat_mattransmul_FINAL.py +++ b/sam/sim/test/final-apps/test_mat_mattransmul_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_mat_residual_FINAL.py b/sam/sim/test/final-apps/test_mat_residual_FINAL.py index 2831ad01..db5d1f3c 100644 --- a/sam/sim/test/final-apps/test_mat_residual_FINAL.py +++ b/sam/sim/test/final-apps/test_mat_residual_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_mat_sddmm_FINAL.py b/sam/sim/test/final-apps/test_mat_sddmm_FINAL.py index f2222e69..a82e84ed 100644 --- a/sam/sim/test/final-apps/test_mat_sddmm_FINAL.py +++ b/sam/sim/test/final-apps/test_mat_sddmm_FINAL.py @@ -10,7 +10,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_mat_vecmul_FINAL.py b/sam/sim/test/final-apps/test_mat_vecmul_FINAL.py index cb91e752..845ee9bb 100644 --- a/sam/sim/test/final-apps/test_mat_vecmul_FINAL.py +++ b/sam/sim/test/final-apps/test_mat_vecmul_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator_OLD import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_matmul_kij_FINAL.py b/sam/sim/test/final-apps/test_matmul_kij_FINAL.py index c1f0d212..733ea13b 100644 --- a/sam/sim/test/final-apps/test_matmul_kij_FINAL.py +++ b/sam/sim/test/final-apps/test_matmul_kij_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator_OLD import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_tensor3_elemadd_FINAL.py b/sam/sim/test/final-apps/test_tensor3_elemadd_FINAL.py index a9c9fbca..31070d2e 100644 --- a/sam/sim/test/final-apps/test_tensor3_elemadd_FINAL.py +++ b/sam/sim/test/final-apps/test_tensor3_elemadd_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_tensor3_innerprod_FINAL.py b/sam/sim/test/final-apps/test_tensor3_innerprod_FINAL.py index 9a3d257a..f2c1ca0b 100644 --- a/sam/sim/test/final-apps/test_tensor3_innerprod_FINAL.py +++ b/sam/sim/test/final-apps/test_tensor3_innerprod_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_tensor3_mttkrp_FINAL.py b/sam/sim/test/final-apps/test_tensor3_mttkrp_FINAL.py index b8d92149..a5bc830d 100644 --- a/sam/sim/test/final-apps/test_tensor3_mttkrp_FINAL.py +++ b/sam/sim/test/final-apps/test_tensor3_mttkrp_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_tensor3_ttm_FINAL.py b/sam/sim/test/final-apps/test_tensor3_ttm_FINAL.py index b2033c29..f704f661 100644 --- a/sam/sim/test/final-apps/test_tensor3_ttm_FINAL.py +++ b/sam/sim/test/final-apps/test_tensor3_ttm_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/final-apps/test_tensor3_ttv_FINAL.py b/sam/sim/test/final-apps/test_tensor3_ttv_FINAL.py index bf86f70b..70853831 100644 --- a/sam/sim/test/final-apps/test_tensor3_ttv_FINAL.py +++ b/sam/sim/test/final-apps/test_tensor3_ttv_FINAL.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/primitives/test_spacc.py b/sam/sim/test/primitives/test_spacc.py index caecee14..ae95181e 100644 --- a/sam/sim/test/primitives/test_spacc.py +++ b/sam/sim/test/primitives/test_spacc.py @@ -3,7 +3,7 @@ import random import numpy as np -from sam.sim.src.accumulator import SparseAccumulator1, SpAcc1New +from sam.sim.src.accumulator import SpAcc1, SpAcc2 from sam.sim.src.rd_scanner import CompressedCrdRdScan from sam.sim.src.array import Array from sam.sim.src.wr_scanner import ValsWrScan, CompressWrScan @@ -11,131 +11,6 @@ from sam.sim.test.test import TIMEOUT, gen_n_comp_arrs, gen_val_arr, get_point_list, \ convert_point_tuple, convert_ndarr_point_tuple, convert_point_tuple_ndarr, check_point_tuple -# Old sparse accumulator -arrs_dict1 = {'ocrd_in': [0, 2, 'S0', 2, 'S1', 'D'], - 'icrd_in': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 0, 2, 3, 'S2', 'D'], - 'val_in': [50, 5, 10, 'S0', 40, 4, 8, 'S1', -40, 33, 36, 'S2', 'D'], - 'ocrd_gold': [0, 2, 'S0', 'D'], - 'icrd_gold': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], - 'val_gold': [50, 5, 10, 'S0', 0, 37, 44, 'S1', 'D']} - -arrs_dict2 = { - 'ocrd_in': [0, 'S0', 1, 'S0', 2, 'S0', 3, 'S0', 4, 'S0', 5, 'S0', 6, 'S0', 7, 'S0', 8, 'S0', 9, 'S0', 10, 'S0', - 11, 'S0', 12, 'S0', 13, 'S0', 14, 'S0', 15, 'S0', 16, 'S0', 17, 'S0', 18, 'S0', 19, 'S0', 20, 'S0', - 21, 'S0', 22, 'S0', 23, 'S0', 24, 'S0', 25, 'S0', 26, 'S0', 27, 'S0', 28, 'S0', 29, 'S0', 30, 'S0', - 31, 'S0', 32, 'S0', 33, 'S0', 34, 'S0', 35, 'S0', 36, 'S0', 37, 'S0', 38, 'S0', 39, 'S0', 40, 'S0', - 41, 'S0', 42, 'S0', 43, 'S0', 44, 'S0', 45, 'S0', 46, 'S0', 47, 'S0', 48, 'S0', 49, 'S0', 50, 'S0', - 51, 'S0', 52, 'S0', 53, 'S0', 54, 'S0', 55, 'S0', 56, 'S0', 57, 'S0', 58, 'S0', 59, 'S0', 60, 'S0', - 61, 'S0', 62, 'S0', 63, 'S0', 64, 'S0', 65, 'S1', 'D'], - 'icrd_in': [65, 'S1', 0, 'S1', 1, 'S1', 2, 'S1', 3, 'S1', 4, 'S1', 5, 'S1', 6, 'S1', 7, 'S1', 8, 'S1', 9, 'S1', - 10, 'S1', 11, 'S1', 12, 'S1', 13, 'S1', 14, 'S1', 15, 'S1', 16, 'S1', 17, 'S1', 18, 'S1', 19, 'S1', - 20, 'S1', 21, 'S1', 22, 'S1', 23, 'S1', 24, 'S1', 25, 'S1', 26, 'S1', 27, 'S1', 28, 'S1', 29, 'S1', 30, - 'S1', 31, 'S1', 32, 'S1', 33, 'S1', 34, 'S1', 35, 'S1', 36, 'S1', 37, 'S1', 38, 'S1', 39, 'S1', 40, - 'S1', 41, 'S1', 42, 'S1', 43, 'S1', 44, 'S1', 45, 'S1', 46, 'S1', 47, 'S1', 48, 'S1', 49, 'S1', 50, - 'S1', 51, 'S1', 52, 'S1', 53, 'S1', 54, 'S1', 55, 'S1', 56, 'S1', 57, 'S1', 58, 'S1', 59, 'S1', 60, - 'S1', 61, 'S1', 62, 'S1', 63, 'S1', 64, 'S2', 'D'], - 'val_in': [0.18427716102, 'S1', 0.18427716102, 'S1', 0.18427716102, 'S1', 0.275991475966, 'S1', 0.275991475966, - 'S1', 0.275991475966, 'S1', 0.275991475966, 'S1', 0.275991475966, 'S1', 0.275991475966, 'S1', - 0.18427716102, 'S1', 0.18427716102, 'S1', 0.18427716102, 'S1', 0.34565714691, 'S1', 0.34565714691, 'S1', - 0.34565714691, 'S1', 0.1704767152044, 'S1', 0.1704767152044, 'S1', 0.1704767152044, 'S1', - 0.1704767152044, 'S1', 0.1704767152044, 'S1', 0.1704767152044, 'S1', 0.34565714691, 'S1', 0.34565714691, - 'S1', 0.34565714691, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', - 0.282616682952, 'S1', 0.282616682952, 'S1', 0.282616682952, 'S1', 0.282616682952, 'S1', 0.282616682952, - 'S1', 0.282616682952, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', - 0.250853276904, 'S1', 0.250853276904, 'S1', 0.250853276904, 'S1', 0.1066417854742, 'S1', 0.1066417854742, - 'S1', 0.1066417854742, 'S1', 0.1066417854742, 'S1', 0.1066417854742, 'S1', 0.1066417854742, 'S1', - 0.250853276904, 'S1', 0.250853276904, 'S1', 0.250853276904, 'S1', 0.0463412200974, 'S1', 0.0463412200974, - 'S1', 0.0463412200974, 'S1', 0.061186376815, 'S1', 0.061186376815, 'S1', 0.061186376815, 'S1', - 0.1297137398738, 'S1', 0.1297137398738, 'S1', 0.1297137398738, 'S1', 0.1297137398738, 'S1', - 0.1297137398738, 'S1', 0.1297137398738, 'S1', 0.061186376815, 'S1', 0.061186376815, 'S1', 0.061186376815, - 'S1', 0.03949387733, 'S1', 0.03949387733, 'S1', 0.03949387733, 'S2', 'D'], - 'ocrd_gold': list(range(0, 66)) + ['S0', 'D'], - 'icrd_gold': [0, 'S0', 1, 'S0', 2, 'S0', 3, 'S0', 4, 'S0', 5, 'S0', 6, 'S0', 7, 'S0', 8, 'S0', 9, 'S0', 10, 'S0', - 11, 'S0', 12, 'S0', 13, 'S0', 14, 'S0', 15, 'S0', 16, 'S0', 17, 'S0', 18, 'S0', 19, 'S0', 20, 'S0', - 21, 'S0', 22, 'S0', 23, 'S0', 24, 'S0', 25, 'S0', 26, 'S0', 27, 'S0', 28, 'S0', 29, 'S0', 30, 'S0', - 31, 'S0', 32, 'S0', 33, 'S0', 34, 'S0', 35, 'S0', 36, 'S0', 37, 'S0', 38, 'S0', 39, 'S0', 40, 'S0', - 41, 'S0', 42, 'S0', 43, 'S0', 44, 'S0', 45, 'S0', 46, 'S0', 47, 'S0', 48, 'S0', 49, 'S0', 50, 'S0', - 51, 'S0', 52, 'S0', 53, 'S0', 54, 'S0', 55, 'S0', 56, 'S0', 57, 'S0', 58, 'S0', 59, 'S0', 60, 'S0', - 61, 'S0', 62, 'S0', 63, 'S0', 64, 'S0', 65, 'S1', 'D'], - 'val_gold': [0.18427716102, 'S0', 0.18427716102, 'S0', 0.275991475966, 'S0', 0.275991475966, 'S0', 0.275991475966, - 'S0', - 0.275991475966, 'S0', 0.275991475966, 'S0', 0.275991475966, 'S0', 0.18427716102, 'S0', 0.18427716102, - 'S0', - 0.18427716102, 'S0', 0.34565714691, 'S0', 0.34565714691, 'S0', 0.34565714691, 'S0', 0.1704767152044, - 'S0', 0.1704767152044, - 'S0', 0.1704767152044, 'S0', 0.1704767152044, 'S0', 0.1704767152044, 'S0', 0.1704767152044, 'S0', - 0.34565714691, 'S0', - 0.34565714691, 'S0', 0.34565714691, 'S0', 0.1234664378214, 'S0', 0.1234664378214, 'S0', - 0.1234664378214, - 'S0', 0.282616682952, 'S0', 0.282616682952, 'S0', 0.282616682952, 'S0', 0.282616682952, 'S0', - 0.282616682952, - 'S0', 0.282616682952, 'S0', 0.1234664378214, 'S0', 0.1234664378214, 'S0', 0.1234664378214, 'S0', - 0.250853276904, - 'S0', 0.250853276904, 'S0', 0.250853276904, 'S0', 0.1066417854742, 'S0', 0.1066417854742, 'S0', - 0.1066417854742, - 'S0', 0.1066417854742, 'S0', 0.1066417854742, 'S0', 0.1066417854742, 'S0', 0.250853276904, 'S0', - 0.250853276904, - 'S0', 0.250853276904, 'S0', 0.0463412200974, 'S0', 0.0463412200974, 'S0', 0.0463412200974, 'S0', - 0.061186376815, - 'S0', 0.061186376815, 'S0', 0.061186376815, 'S0', 0.1297137398738, 'S0', 0.1297137398738, 'S0', - 0.1297137398738, - 'S0', 0.1297137398738, 'S0', 0.1297137398738, 'S0', 0.1297137398738, 'S0', 0.061186376815, 'S0', - 0.061186376815, - 'S0', 0.061186376815, 'S0', 0.03949387733, 'S0', 0.03949387733, 'S0', 0.03949387733, 'S0', - 0.18427716102, 'S1', 'D'] -} - -@pytest.mark.skip("Old sparse accumulator 1 test") -@pytest.mark.parametrize("arrs", [arrs_dict1, arrs_dict2]) -def test_spacc1_direct(arrs, debug_sim): - icrd = copy.deepcopy(arrs['icrd_in']) - ocrd = copy.deepcopy(arrs['ocrd_in']) - val = copy.deepcopy(arrs['val_in']) - - gold_ocrd = copy.deepcopy(arrs['ocrd_gold']) - gold_icrd = copy.deepcopy(arrs['icrd_gold']) - gold_val = copy.deepcopy(arrs['val_gold']) - - sa = SparseAccumulator1(val_stkn=True, debug=debug_sim) - - done = False - time = 0 - out_ocrd = [] - out_icrd = [] - out_val = [] - while not done and time < TIMEOUT: - if len(icrd) > 0: - sa.set_in_crd0(icrd.pop(0)) - if len(ocrd) > 0: - sa.set_in_crd1(ocrd.pop(0)) - if len(val) > 0: - sa.set_val(val.pop(0)) - - sa.update() - - out_ocrd.append(sa.out_crd1()) - out_icrd.append(sa.out_crd0()) - out_val.append(sa.out_val()) - - print("Timestep", time, "\t Done:", sa.out_done()) - - done = sa.out_done() - time += 1 - - out_ocrd = remove_emptystr(out_ocrd) - out_icrd = remove_emptystr(out_icrd) - out_val = remove_emptystr(out_val) - - if debug_sim: - print("Outer Crd: ", out_ocrd) - print("Inner Crd: ", out_icrd) - print("Vals: ", out_val) - - assert (out_ocrd == gold_ocrd) - assert (out_icrd == gold_icrd) - assert (out_val == gold_val) - - arrs_dict1 = {'ocrd_in': [0, 2, 'S0', 2, 'S1', 'D'], 'icrd_in': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 0, 2, 3, 'S2', 'D'], 'val_in': [50, 5, 10, 'S0', 40, 4, 8, 'S1', -40, 33, 36, 'S2', 'D'], @@ -153,7 +28,7 @@ def test_spacc1new_direct(arrs, debug_sim): gold_icrd = copy.deepcopy(arrs['icrd_gold']) gold_val = copy.deepcopy(arrs['val_gold']) - sa = SpAcc1New(valtype=int, val_stkn=True, debug=debug_sim) + sa = SpAcc1(valtype=int, val_stkn=True, debug=debug_sim) done = False time = 0 @@ -203,7 +78,7 @@ def test_spacc1new_rand(dim, debug_sim, max_val=1000, fill=0): rdscan_B2 = CompressedCrdRdScan(crd_arr=in_mat_crds1[1], seg_arr=in_mat_segs1[1], debug=debug_sim) val_B = Array(init_arr=in_mat_vals1, debug=debug_sim) - sa = SpAcc1New(valtype=int, val_stkn=True, debug=debug_sim) + sa = SpAcc1(valtype=int, val_stkn=True, debug=debug_sim) vals_X = ValsWrScan(size=dim * dim, fill=fill, debug=debug_sim) wrscan_X1 = CompressWrScan(seg_size=2, size=dim, fill=fill, debug=debug_sim) @@ -286,9 +161,27 @@ def test_spacc1new_rand(dim, debug_sim, max_val=1000, fill=0): 'crd0_gold': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], 'val_gold': [50, 5, 10, 'S0', 0, 37, 44, 'S1', 'D']} +# [[0, 1], [0, 4], [0, 2, 3, 4, 5]] [[0], [0, 1, 2, 3], [0, 2, 3, 1, 3]] [-60, 85, 314, 241, -887] +arrs_dict2 = {'crd2_in': [0, 'S0', 'D'], + 'crd1_in': [0, 1, 2, 3, 'S1', 'D'], + 'crd0_in': [0, 2, 'S0', 3, 'S0', 1, 'S0', 3, 'S2', 'D'], + 'val_in': [-60, 85, 'S0', 314, 'S0', 241, 'S0', -887, 'S2', 'D'], + 'crd1_gold': [0, 1, 2, 3, 'S0', 'D'], + 'crd0_gold': [0, 2, 'S0', 3, 'S0', 1, 'S0', 3, 'S1', 'D'], + 'val_gold': [-60, 85, 'S0', 314, 'S0', 241, 'S0', -887, 'S1', 'D']} + +# [[0, 1], [0, 3], [0, 4, 6, 8]] [[1], [0, 1, 2], [0, 1, 2, 3, 1, 3, 0, 2]] [637, 210, -847, 358, 162, 687, 95, -91] +arrs_dict3 = {'crd2_in': [1, 'S0', 'D'], + 'crd1_in': [0, 1, 2, 'S1', 'D'], + 'crd0_in': [0, 1, 2, 3, 'S0', 1, 3, 'S0', 0, 2, 'S2', 'D'], + 'val_in': [637, 210, -847, 358, 'S0', 162, 687, 'S0', 95, -91, 'S2', 'D'], + 'crd1_gold': [0, 1, 2, 'S0', 'D'], + 'crd0_gold': [0, 1, 2, 3, 'S0', 1, 3, 'S0', 0, 2, 'S1', 'D'], + 'val_gold': [637, 210, -847, 358, 'S0', 162, 687, 'S0', 95, -91, 'S1', 'D']} + # New sparse accumulator -@pytest.mark.parametrize("arrs", [arrs_dict1]) +@pytest.mark.parametrize("arrs", [arrs_dict1, arrs_dict2, arrs_dict3]) def test_spacc2new_direct(arrs, debug_sim): crd2 = copy.deepcopy(arrs['crd2_in']) crd1 = copy.deepcopy(arrs['crd1_in']) @@ -299,25 +192,27 @@ def test_spacc2new_direct(arrs, debug_sim): gold_crd0 = copy.deepcopy(arrs['crd0_gold']) gold_val = copy.deepcopy(arrs['val_gold']) - sa = SpAcc2New(valtype=int, val_stkn=True, debug=debug_sim) + sa = SpAcc2(valtype=int, val_stkn=True, debug=debug_sim) done = False time = 0 - out_icrd = [] + out_crd1 = [] + out_crd0 = [] out_val = [] while not done and time < TIMEOUT: - if len(crd0) > 0: - sa.set_in_crd0(crd0.pop(0)) - if len(crd1) > 0: - sa.set_in_crd1(crd1.pop(0)) if len(crd2) > 0: sa.set_in_crd2(crd2.pop(0)) + if len(crd1) > 0: + sa.set_in_crd1(crd1.pop(0)) + if len(crd0) > 0: + sa.set_in_crd0(crd0.pop(0)) if len(val) > 0: sa.set_val(val.pop(0)) sa.update() - out_icrd.append(sa.out_crd0()) + out_crd1.append(sa.out_crd1()) + out_crd0.append(sa.out_crd0()) out_val.append(sa.out_val()) print("Timestep", time, "\t Done:", sa.out_done()) @@ -325,12 +220,125 @@ def test_spacc2new_direct(arrs, debug_sim): done = sa.out_done() time += 1 - out_icrd = remove_emptystr(out_icrd) + out_crd1 = remove_emptystr(out_crd1) + out_crd0 = remove_emptystr(out_crd0) out_val = remove_emptystr(out_val) if debug_sim: - print("Inner Crd: ", out_icrd) + print("Crd1: ", out_crd1) + print("Crd0: ", out_crd0) print("Vals: ", out_val) - assert (out_icrd == gold_icrd) - assert (out_val == gold_val) \ No newline at end of file + assert (out_crd1 == gold_crd1) + assert (out_crd0 == gold_crd0) + assert (out_val == gold_val) + + +@pytest.mark.parametrize("dim", [2 ** x for x in range(1, 5, 1)]) +def test_spacc2new_rand(dim, debug_sim, max_val=1000, fill=0): + np.random.seed(0) + random.seed(0) + + in_mat_crds1, in_mat_segs1 = gen_n_comp_arrs(3, dim) + in_mat_vals1 = gen_val_arr(len(in_mat_crds1[-1]), max_val, -max_val) + + in1_tup = convert_point_tuple(get_point_list(in_mat_crds1, in_mat_segs1, in_mat_vals1)) + + nd1 = convert_point_tuple_ndarr(in1_tup, dim) + gold_nd = np.sum(nd1, 0) + gold_tup = convert_ndarr_point_tuple(gold_nd) + + rdscan_B1 = CompressedCrdRdScan(crd_arr=in_mat_crds1[0], seg_arr=in_mat_segs1[0], debug=debug_sim) + rdscan_B2 = CompressedCrdRdScan(crd_arr=in_mat_crds1[1], seg_arr=in_mat_segs1[1], debug=debug_sim) + rdscan_B3 = CompressedCrdRdScan(crd_arr=in_mat_crds1[2], seg_arr=in_mat_segs1[2], debug=debug_sim) + + val_B = Array(init_arr=in_mat_vals1, debug=debug_sim) + sa = SpAcc2(valtype=int, val_stkn=True, debug=debug_sim) + + vals_X = ValsWrScan(size=dim * dim, fill=fill, debug=debug_sim) + wrscan_X1 = CompressWrScan(seg_size=2, size=dim, fill=fill, debug=debug_sim) + wrscan_X2 = CompressWrScan(seg_size=dim+1, size=dim*dim, fill=fill, debug=debug_sim) + + done = False + time = 0 + in_ref_B = [0, 'D'] + out_rdscan_B1 = [] + out_rdscan_B2 = [] + out_rdscan_B3 = [] + out_val_B = [] + while not done and time < TIMEOUT: + if len(in_ref_B) > 0: + rdscan_B1.set_in_ref(in_ref_B.pop(0)) + + rdscan_B2.set_in_ref(rdscan_B1.out_ref()) + rdscan_B3.set_in_ref(rdscan_B2.out_ref()) + val_B.set_load(rdscan_B3.out_ref()) + + # Inject random empty strings + out_rdscan_B1.append(rdscan_B1.out_crd()) + out_rdscan_B2.append(rdscan_B2.out_crd()) + out_rdscan_B3.append(rdscan_B3.out_crd()) + out_val_B.append(val_B.out_load()) + + # Inject random delay + if random.random() < 0.2: + out_rdscan_B1.append("") + if random.random() < 0.2: + out_rdscan_B2.append("") + if random.random() < 0.2: + out_val_B.append("") + + sa.set_in_crd2(out_rdscan_B1.pop(0)) + sa.set_in_crd1(out_rdscan_B2.pop(0)) + sa.set_in_crd0(out_rdscan_B3.pop(0)) + sa.set_val(out_val_B.pop(0)) + + vals_X.set_input(sa.out_val()) + wrscan_X1.set_input(sa.out_crd1()) + wrscan_X2.set_input(sa.out_crd0()) + + rdscan_B1.update() + rdscan_B2.update() + rdscan_B3.update() + val_B.update() + sa.update() + vals_X.update() + wrscan_X1.update() + wrscan_X2.update() + + print("Timestep", time, "\t Done --", + "\tRdScan B1:", rdscan_B1.out_done(), + "\tRdScan B2:", rdscan_B2.out_done(), + "\tRdScan B3:", rdscan_B3.out_done(), + "\tSpAcc1New:", sa.out_done(), + "\tArr:", val_B.out_done(), + "\tWrScan:", vals_X.out_done(), + "\tWrScan X1:", wrscan_X1.out_done(), + "\tWrScan X2:", wrscan_X2.out_done(), + ) + + done = wrscan_X2.out_done() and wrscan_X1.out_done() and vals_X.out_done() + time += 1 + + wrscan_X1.autosize() + wrscan_X2.autosize() + vals_X.autosize() + + out_crds = [wrscan_X1.get_arr(), wrscan_X2.get_arr()] + out_segs = [wrscan_X1.get_seg_arr(), wrscan_X2.get_seg_arr()] + out_val = vals_X.get_arr() + + if debug_sim: + print("Input", in_mat_segs1, in_mat_crds1, in_mat_vals1) + print(nd1) + print("X seg", out_segs) + print("X crd", out_crds) + print("X val", out_val) + print("Gold np", gold_nd) + print("Gold Tuple", gold_tup) + + if not out_val: + assert out_val == gold_tup + else: + out_tup = convert_point_tuple(get_point_list(out_crds, out_segs, out_val)) + assert (check_point_tuple(out_tup, gold_tup)) \ No newline at end of file diff --git a/sam/sim/test/primitives/test_spacc_OLD.py b/sam/sim/test/primitives/test_spacc_OLD.py new file mode 100644 index 00000000..29475174 --- /dev/null +++ b/sam/sim/test/primitives/test_spacc_OLD.py @@ -0,0 +1,132 @@ +import copy +import pytest +import random +import numpy as np + +from sam.sim.src.accumulator_OLD import SparseAccumulator1 +from sam.sim.src.base import remove_emptystr +from sam.sim.test.test import TIMEOUT + +# Old sparse accumulator +arrs_dict1 = {'ocrd_in': [0, 2, 'S0', 2, 'S1', 'D'], + 'icrd_in': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 0, 2, 3, 'S2', 'D'], + 'val_in': [50, 5, 10, 'S0', 40, 4, 8, 'S1', -40, 33, 36, 'S2', 'D'], + 'ocrd_gold': [0, 2, 'S0', 'D'], + 'icrd_gold': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], + 'val_gold': [50, 5, 10, 'S0', 0, 37, 44, 'S1', 'D']} + +arrs_dict2 = { + 'ocrd_in': [0, 'S0', 1, 'S0', 2, 'S0', 3, 'S0', 4, 'S0', 5, 'S0', 6, 'S0', 7, 'S0', 8, 'S0', 9, 'S0', 10, 'S0', + 11, 'S0', 12, 'S0', 13, 'S0', 14, 'S0', 15, 'S0', 16, 'S0', 17, 'S0', 18, 'S0', 19, 'S0', 20, 'S0', + 21, 'S0', 22, 'S0', 23, 'S0', 24, 'S0', 25, 'S0', 26, 'S0', 27, 'S0', 28, 'S0', 29, 'S0', 30, 'S0', + 31, 'S0', 32, 'S0', 33, 'S0', 34, 'S0', 35, 'S0', 36, 'S0', 37, 'S0', 38, 'S0', 39, 'S0', 40, 'S0', + 41, 'S0', 42, 'S0', 43, 'S0', 44, 'S0', 45, 'S0', 46, 'S0', 47, 'S0', 48, 'S0', 49, 'S0', 50, 'S0', + 51, 'S0', 52, 'S0', 53, 'S0', 54, 'S0', 55, 'S0', 56, 'S0', 57, 'S0', 58, 'S0', 59, 'S0', 60, 'S0', + 61, 'S0', 62, 'S0', 63, 'S0', 64, 'S0', 65, 'S1', 'D'], + 'icrd_in': [65, 'S1', 0, 'S1', 1, 'S1', 2, 'S1', 3, 'S1', 4, 'S1', 5, 'S1', 6, 'S1', 7, 'S1', 8, 'S1', 9, 'S1', + 10, 'S1', 11, 'S1', 12, 'S1', 13, 'S1', 14, 'S1', 15, 'S1', 16, 'S1', 17, 'S1', 18, 'S1', 19, 'S1', + 20, 'S1', 21, 'S1', 22, 'S1', 23, 'S1', 24, 'S1', 25, 'S1', 26, 'S1', 27, 'S1', 28, 'S1', 29, 'S1', 30, + 'S1', 31, 'S1', 32, 'S1', 33, 'S1', 34, 'S1', 35, 'S1', 36, 'S1', 37, 'S1', 38, 'S1', 39, 'S1', 40, + 'S1', 41, 'S1', 42, 'S1', 43, 'S1', 44, 'S1', 45, 'S1', 46, 'S1', 47, 'S1', 48, 'S1', 49, 'S1', 50, + 'S1', 51, 'S1', 52, 'S1', 53, 'S1', 54, 'S1', 55, 'S1', 56, 'S1', 57, 'S1', 58, 'S1', 59, 'S1', 60, + 'S1', 61, 'S1', 62, 'S1', 63, 'S1', 64, 'S2', 'D'], + 'val_in': [0.18427716102, 'S1', 0.18427716102, 'S1', 0.18427716102, 'S1', 0.275991475966, 'S1', 0.275991475966, + 'S1', 0.275991475966, 'S1', 0.275991475966, 'S1', 0.275991475966, 'S1', 0.275991475966, 'S1', + 0.18427716102, 'S1', 0.18427716102, 'S1', 0.18427716102, 'S1', 0.34565714691, 'S1', 0.34565714691, 'S1', + 0.34565714691, 'S1', 0.1704767152044, 'S1', 0.1704767152044, 'S1', 0.1704767152044, 'S1', + 0.1704767152044, 'S1', 0.1704767152044, 'S1', 0.1704767152044, 'S1', 0.34565714691, 'S1', 0.34565714691, + 'S1', 0.34565714691, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', + 0.282616682952, 'S1', 0.282616682952, 'S1', 0.282616682952, 'S1', 0.282616682952, 'S1', 0.282616682952, + 'S1', 0.282616682952, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', 0.1234664378214, 'S1', + 0.250853276904, 'S1', 0.250853276904, 'S1', 0.250853276904, 'S1', 0.1066417854742, 'S1', 0.1066417854742, + 'S1', 0.1066417854742, 'S1', 0.1066417854742, 'S1', 0.1066417854742, 'S1', 0.1066417854742, 'S1', + 0.250853276904, 'S1', 0.250853276904, 'S1', 0.250853276904, 'S1', 0.0463412200974, 'S1', 0.0463412200974, + 'S1', 0.0463412200974, 'S1', 0.061186376815, 'S1', 0.061186376815, 'S1', 0.061186376815, 'S1', + 0.1297137398738, 'S1', 0.1297137398738, 'S1', 0.1297137398738, 'S1', 0.1297137398738, 'S1', + 0.1297137398738, 'S1', 0.1297137398738, 'S1', 0.061186376815, 'S1', 0.061186376815, 'S1', 0.061186376815, + 'S1', 0.03949387733, 'S1', 0.03949387733, 'S1', 0.03949387733, 'S2', 'D'], + 'ocrd_gold': list(range(0, 66)) + ['S0', 'D'], + 'icrd_gold': [0, 'S0', 1, 'S0', 2, 'S0', 3, 'S0', 4, 'S0', 5, 'S0', 6, 'S0', 7, 'S0', 8, 'S0', 9, 'S0', 10, 'S0', + 11, 'S0', 12, 'S0', 13, 'S0', 14, 'S0', 15, 'S0', 16, 'S0', 17, 'S0', 18, 'S0', 19, 'S0', 20, 'S0', + 21, 'S0', 22, 'S0', 23, 'S0', 24, 'S0', 25, 'S0', 26, 'S0', 27, 'S0', 28, 'S0', 29, 'S0', 30, 'S0', + 31, 'S0', 32, 'S0', 33, 'S0', 34, 'S0', 35, 'S0', 36, 'S0', 37, 'S0', 38, 'S0', 39, 'S0', 40, 'S0', + 41, 'S0', 42, 'S0', 43, 'S0', 44, 'S0', 45, 'S0', 46, 'S0', 47, 'S0', 48, 'S0', 49, 'S0', 50, 'S0', + 51, 'S0', 52, 'S0', 53, 'S0', 54, 'S0', 55, 'S0', 56, 'S0', 57, 'S0', 58, 'S0', 59, 'S0', 60, 'S0', + 61, 'S0', 62, 'S0', 63, 'S0', 64, 'S0', 65, 'S1', 'D'], + 'val_gold': [0.18427716102, 'S0', 0.18427716102, 'S0', 0.275991475966, 'S0', 0.275991475966, 'S0', 0.275991475966, + 'S0', + 0.275991475966, 'S0', 0.275991475966, 'S0', 0.275991475966, 'S0', 0.18427716102, 'S0', 0.18427716102, + 'S0', + 0.18427716102, 'S0', 0.34565714691, 'S0', 0.34565714691, 'S0', 0.34565714691, 'S0', 0.1704767152044, + 'S0', 0.1704767152044, + 'S0', 0.1704767152044, 'S0', 0.1704767152044, 'S0', 0.1704767152044, 'S0', 0.1704767152044, 'S0', + 0.34565714691, 'S0', + 0.34565714691, 'S0', 0.34565714691, 'S0', 0.1234664378214, 'S0', 0.1234664378214, 'S0', + 0.1234664378214, + 'S0', 0.282616682952, 'S0', 0.282616682952, 'S0', 0.282616682952, 'S0', 0.282616682952, 'S0', + 0.282616682952, + 'S0', 0.282616682952, 'S0', 0.1234664378214, 'S0', 0.1234664378214, 'S0', 0.1234664378214, 'S0', + 0.250853276904, + 'S0', 0.250853276904, 'S0', 0.250853276904, 'S0', 0.1066417854742, 'S0', 0.1066417854742, 'S0', + 0.1066417854742, + 'S0', 0.1066417854742, 'S0', 0.1066417854742, 'S0', 0.1066417854742, 'S0', 0.250853276904, 'S0', + 0.250853276904, + 'S0', 0.250853276904, 'S0', 0.0463412200974, 'S0', 0.0463412200974, 'S0', 0.0463412200974, 'S0', + 0.061186376815, + 'S0', 0.061186376815, 'S0', 0.061186376815, 'S0', 0.1297137398738, 'S0', 0.1297137398738, 'S0', + 0.1297137398738, + 'S0', 0.1297137398738, 'S0', 0.1297137398738, 'S0', 0.1297137398738, 'S0', 0.061186376815, 'S0', + 0.061186376815, + 'S0', 0.061186376815, 'S0', 0.03949387733, 'S0', 0.03949387733, 'S0', 0.03949387733, 'S0', + 0.18427716102, 'S1', 'D'] +} + +@pytest.mark.skip("Old sparse accumulator 1 test") +@pytest.mark.parametrize("arrs", [arrs_dict1, arrs_dict2]) +def test_spacc1_direct(arrs, debug_sim): + icrd = copy.deepcopy(arrs['icrd_in']) + ocrd = copy.deepcopy(arrs['ocrd_in']) + val = copy.deepcopy(arrs['val_in']) + + gold_ocrd = copy.deepcopy(arrs['ocrd_gold']) + gold_icrd = copy.deepcopy(arrs['icrd_gold']) + gold_val = copy.deepcopy(arrs['val_gold']) + + sa = SparseAccumulator1(val_stkn=True, debug=debug_sim) + + done = False + time = 0 + out_ocrd = [] + out_icrd = [] + out_val = [] + while not done and time < TIMEOUT: + if len(icrd) > 0: + sa.set_in_crd0(icrd.pop(0)) + if len(ocrd) > 0: + sa.set_in_crd1(ocrd.pop(0)) + if len(val) > 0: + sa.set_val(val.pop(0)) + + sa.update() + + out_ocrd.append(sa.out_crd1()) + out_icrd.append(sa.out_crd0()) + out_val.append(sa.out_val()) + + print("Timestep", time, "\t Done:", sa.out_done()) + + done = sa.out_done() + time += 1 + + out_ocrd = remove_emptystr(out_ocrd) + out_icrd = remove_emptystr(out_icrd) + out_val = remove_emptystr(out_val) + + if debug_sim: + print("Outer Crd: ", out_ocrd) + print("Inner Crd: ", out_icrd) + print("Vals: ", out_val) + + assert (out_ocrd == gold_ocrd) + assert (out_icrd == gold_icrd) + assert (out_val == gold_val) diff --git a/sam/sim/test/reorder-study/test_reorder_matmul_ijk.py b/sam/sim/test/reorder-study/test_reorder_matmul_ijk.py index cc269c6b..81dedfd7 100644 --- a/sam/sim/test/reorder-study/test_reorder_matmul_ijk.py +++ b/sam/sim/test/reorder-study/test_reorder_matmul_ijk.py @@ -10,7 +10,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator_OLD import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/reorder-study/test_reorder_matmul_ikj.py b/sam/sim/test/reorder-study/test_reorder_matmul_ikj.py index af03c87a..3d518569 100644 --- a/sam/sim/test/reorder-study/test_reorder_matmul_ikj.py +++ b/sam/sim/test/reorder-study/test_reorder_matmul_ikj.py @@ -9,7 +9,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator_OLD import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/reorder-study/test_reorder_matmul_jik.py b/sam/sim/test/reorder-study/test_reorder_matmul_jik.py index 0b7e4388..c7b674ee 100644 --- a/sam/sim/test/reorder-study/test_reorder_matmul_jik.py +++ b/sam/sim/test/reorder-study/test_reorder_matmul_jik.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator_OLD import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/reorder-study/test_reorder_matmul_jki.py b/sam/sim/test/reorder-study/test_reorder_matmul_jki.py index 6511ddc6..6b69cb9a 100644 --- a/sam/sim/test/reorder-study/test_reorder_matmul_jki.py +++ b/sam/sim/test/reorder-study/test_reorder_matmul_jki.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator_OLD import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/reorder-study/test_reorder_matmul_kij.py b/sam/sim/test/reorder-study/test_reorder_matmul_kij.py index c16f522a..cf68c44f 100644 --- a/sam/sim/test/reorder-study/test_reorder_matmul_kij.py +++ b/sam/sim/test/reorder-study/test_reorder_matmul_kij.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator_OLD import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/reorder-study/test_reorder_matmul_kji.py b/sam/sim/test/reorder-study/test_reorder_matmul_kji.py index 184ca2c4..fbdfa1c0 100644 --- a/sam/sim/test/reorder-study/test_reorder_matmul_kji.py +++ b/sam/sim/test/reorder-study/test_reorder_matmul_kji.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator_OLD import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/unit-apps/test_unit_mat_mattransmul.py b/sam/sim/test/unit-apps/test_unit_mat_mattransmul.py index 32519ed1..5f23b21f 100644 --- a/sam/sim/test/unit-apps/test_unit_mat_mattransmul.py +++ b/sam/sim/test/unit-apps/test_unit_mat_mattransmul.py @@ -8,7 +8,6 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/unit-apps/test_unit_mat_residual.py b/sam/sim/test/unit-apps/test_unit_mat_residual.py index 05d9225c..58ccd737 100644 --- a/sam/sim/test/unit-apps/test_unit_mat_residual.py +++ b/sam/sim/test/unit-apps/test_unit_mat_residual.py @@ -7,10 +7,8 @@ from sam.sim.src.wr_scanner import ValsWrScan from sam.sim.src.joiner import Intersect2, Union2 from sam.sim.src.compute import Multiply2, Add2 -from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * diff --git a/sam/sim/test/unit-apps/test_unit_matmul_ikj.py b/sam/sim/test/unit-apps/test_unit_matmul_ikj.py index cfb90ce2..2a76c501 100644 --- a/sam/sim/test/unit-apps/test_unit_matmul_ikj.py +++ b/sam/sim/test/unit-apps/test_unit_matmul_ikj.py @@ -8,7 +8,7 @@ from sam.sim.src.crd_manager import CrdDrop, CrdHold from sam.sim.src.repeater import Repeat, RepeatSigGen from sam.sim.src.accumulator import Reduce -from sam.sim.src.accumulator import SparseAccumulator1, SparseAccumulator2 +from sam.sim.src.accumulator_OLD import SparseAccumulator1, SparseAccumulator2 from sam.sim.src.token import * from sam.sim.test.test import * from sam.sim.test.gold import * From 0b3f6c8fef78cda469b31d06f31d22ee159df876 Mon Sep 17 00:00:00 2001 From: Olivia Hsu Date: Fri, 2 Jun 2023 09:09:51 -0700 Subject: [PATCH 7/9] Add in new SpAcc2 --- sam/sim/src/accumulator.py | 7 +- sam/sim/src/accumulator_helpers.py | 7 +- sam/sim/src/bitvector.py | 4 +- sam/sim/test/conftest.py | 1 + .../test/primitives/test_empty_stkn_drop.py | 2 +- sam/sim/test/primitives/test_memory_block.py | 3 + sam/sim/test/primitives/test_spacc.py | 167 ++++++++++++++++-- ...c_helpers.py => test_spacc_helpers_OLD.py} | 6 +- ...tor.py => test_spcrdpt_accumulator_OLD.py} | 2 +- sam/sim/test/primitives/test_stkn_drop.py | 2 +- sam/sim/test/test.py | 5 +- 11 files changed, 172 insertions(+), 34 deletions(-) rename sam/sim/test/primitives/{test_spacc_helpers.py => test_spacc_helpers_OLD.py} (95%) rename sam/sim/test/primitives/{test_spcrdpt_accumulator.py => test_spcrdpt_accumulator_OLD.py} (97%) diff --git a/sam/sim/src/accumulator.py b/sam/sim/src/accumulator.py index 9efe9e15..5164b637 100644 --- a/sam/sim/src/accumulator.py +++ b/sam/sim/src/accumulator.py @@ -301,7 +301,6 @@ def update(self): # 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 @@ -472,6 +471,7 @@ def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, d self.fifo_avail_1 = True self.fifo_avail_0 = True self.fifo_avail_val = True + def check_backpressure(self): if self.backpressure_en: copy_backpressure = self.ready_backpressure @@ -513,7 +513,8 @@ 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("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) @@ -523,7 +524,6 @@ def get_writout(self): def build_writeout(self): result = [] for crd1 in sorted(self.storage.keys()): - print("storage:", self.storage[crd1]) for crd0, val in self.storage[crd1].items(): result.append((crd0, val)) result.append(('S0', 'S0')) @@ -756,6 +756,7 @@ def set_val(self, val, parent=None): def out_crd1(self): if (self.backpressure_en and self.data_valid) or not self.backpressure_en: return self.curr_crd1 + def out_crd0(self): if (self.backpressure_en and self.data_valid) or not self.backpressure_en: return self.curr_crd0 diff --git a/sam/sim/src/accumulator_helpers.py b/sam/sim/src/accumulator_helpers.py index b16a8aae..33eb7cba 100644 --- a/sam/sim/src/accumulator_helpers.py +++ b/sam/sim/src/accumulator_helpers.py @@ -150,7 +150,8 @@ def update(self): 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 + len(self.crdpt_spacc_out_val) > 0 else \ + self.curr_inner_crd else: self.curr_val = self.crdpt_spacc_out_val.pop(0) if len(self.crdpt_spacc_out_val) > 0 else '' @@ -520,7 +521,8 @@ def update(self): # 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" + "If one item is a 'D' token, then all inputs must be: " + str(self.curr_in_inner_crdpt) + ", " + \ + str(self.curr_in_val) self.seen_done = True else: self.storage[self.curr_in_outer_crdpt] = {self.curr_in_inner_crdpt: self.valtype(self.curr_in_val)} @@ -529,7 +531,6 @@ def update(self): fiber = self.emit_output[0] self.curr_outer_crdpt = fiber[0] - print(self.storage) 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] diff --git a/sam/sim/src/bitvector.py b/sam/sim/src/bitvector.py index 80e2e2b4..2a87136d 100644 --- a/sam/sim/src/bitvector.py +++ b/sam/sim/src/bitvector.py @@ -383,11 +383,11 @@ def update(self): if len(self.inner_bv) > 0: ibv = self.inner_bv.pop(0) self.bv_drop.set_inner_bv(ibv) - self.inner_stkn_drop.set_in_stream(ibv) + self.inner_stkn_drop.set_in_val(ibv) self.bv_drop.update() - self.outer_stkn_drop.set_in_stream(self.bv_drop.out_bv_outer()) + self.outer_stkn_drop.set_in_val(self.bv_drop.out_bv_outer()) self.outer_stkn_drop.update() self.inner_stkn_drop.update() diff --git a/sam/sim/test/conftest.py b/sam/sim/test/conftest.py index 8339e3f5..27c9a8aa 100644 --- a/sam/sim/test/conftest.py +++ b/sam/sim/test/conftest.py @@ -159,3 +159,4 @@ def f(func, extra_info=None, save_ret_val=False): benchmark.pedantic(func, rounds=1, iterations=1, warmup_rounds=0) return f + diff --git a/sam/sim/test/primitives/test_empty_stkn_drop.py b/sam/sim/test/primitives/test_empty_stkn_drop.py index 0983f86c..5f6e99e0 100644 --- a/sam/sim/test/primitives/test_empty_stkn_drop.py +++ b/sam/sim/test/primitives/test_empty_stkn_drop.py @@ -49,7 +49,7 @@ def test_empty_stkn_drop(arrs, debug_sim): out = [] while not done and time < TIMEOUT: if len(ival) > 0: - td.set_in_stream(ival.pop(0)) + td.set_in_val(ival.pop(0)) td.update() diff --git a/sam/sim/test/primitives/test_memory_block.py b/sam/sim/test/primitives/test_memory_block.py index de732d8e..bbcca2b3 100644 --- a/sam/sim/test/primitives/test_memory_block.py +++ b/sam/sim/test/primitives/test_memory_block.py @@ -9,6 +9,7 @@ import csv import pickle import yaml + cwd = os.getcwd() formatted_dir = os.getenv('TILED_SUITESPARSE_FORMATTED_PATH', default=os.path.join(cwd, 'mode-formats')) sam_home = os.getenv('SAM_HOME') @@ -30,6 +31,7 @@ "out_crd": [28, 'S1', 'S1', 28, 'S1', 'D'], "out_ref": [0, 'S1', 'S1', 0, 'S1', 'D']} +@pytest.mark.skipif(sam_home is None, reason="Skipping because SAM_HOME not set") @pytest.mark.parametrize("arrs", [arr_dict1, arr_dict2, arr_dict3, arr_dict4, arr_dict5]) def test_memory_block_nbuffer(arrs, debug_sim, skip_empty, yaml_name, report_stats, nbuffer): nbuffer = True @@ -98,6 +100,7 @@ def test_memory_block_nbuffer(arrs, debug_sim, skip_empty, yaml_name, report_sta assert out_gold == out +@pytest.mark.skipif(sam_home is None, reason="Skipping because SAM_HOME not set") @pytest.mark.parametrize("arrs", [arr_dict1, arr_dict2, arr_dict3, arr_dict4, arr_dict5]) def test_memory_block(arrs, debug_sim, skip_empty, yaml_name, report_stats, nbuffer): nbuffer = False diff --git a/sam/sim/test/primitives/test_spacc.py b/sam/sim/test/primitives/test_spacc.py index ae95181e..57ad0898 100644 --- a/sam/sim/test/primitives/test_spacc.py +++ b/sam/sim/test/primitives/test_spacc.py @@ -9,7 +9,7 @@ from sam.sim.src.wr_scanner import ValsWrScan, CompressWrScan from sam.sim.src.base import remove_emptystr from sam.sim.test.test import TIMEOUT, gen_n_comp_arrs, gen_val_arr, get_point_list, \ - convert_point_tuple, convert_ndarr_point_tuple, convert_point_tuple_ndarr, check_point_tuple + convert_point_tuple, convert_ndarr_point_tuple, convert_point_tuple_ndarr, check_point_tuple, remove_zeros arrs_dict1 = {'ocrd_in': [0, 2, 'S0', 2, 'S1', 'D'], 'icrd_in': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 0, 2, 3, 'S2', 'D'], @@ -150,6 +150,7 @@ def test_spacc1new_rand(dim, debug_sim, max_val=1000, fill=0): assert out_val == gold_tup else: out_tup = convert_point_tuple(get_point_list(out_crds, out_segs, out_val)) + out_tup = remove_zeros(out_tup) assert (check_point_tuple(out_tup, gold_tup)) @@ -182,7 +183,7 @@ def test_spacc1new_rand(dim, debug_sim, max_val=1000, fill=0): # New sparse accumulator @pytest.mark.parametrize("arrs", [arrs_dict1, arrs_dict2, arrs_dict3]) -def test_spacc2new_direct(arrs, debug_sim): +def test_spacc2new_stream_direct(arrs, debug_sim): crd2 = copy.deepcopy(arrs['crd2_in']) crd1 = copy.deepcopy(arrs['crd1_in']) crd0 = copy.deepcopy(arrs['crd0_in']) @@ -234,11 +235,138 @@ def test_spacc2new_direct(arrs, debug_sim): assert (out_val == gold_val) -@pytest.mark.parametrize("dim", [2 ** x for x in range(1, 5, 1)]) -def test_spacc2new_rand(dim, debug_sim, max_val=1000, fill=0): - np.random.seed(0) - random.seed(0) +# Segs: [[0, 11], [0, 8, 18, 25, 31, 36, 44, 50, 61, 68, 78, 86], [0, 10, 18, 26, 35, 45, 53, 61, 69, 76, 84, 93, 99, 107, 114, 124, 134, 145, 154, 160, 168, 176, 188, 198, 208, 214, 223, 232, 242, 251, 261, 271, 280, 288, 294, 301, 308, 315, 323, 328, 339, 348, 357, 367, 378, 385, 391, 399, 408, 417, 425, 435, 440, 446, 453, 463, 467, 477, 489, 494, 502, 508, 516, 523, 531, 537, 541, 550, 557, 569, 576, 586, 593, 600, 608, 614, 623, 631, 640, 647, 656, 665, 675, 681, 689, 699, 703]] +# Crds: [[0, 2, 3, 4, 5, 8, 9, 10, 11, 14, 15], [0, 1, 2, 5, 6, 7, 9, 14, 3, 4, 5, 6, 7, 8, 10, 11, 13, 15, 4, 7, 8, 11, 12, 13, 14, 1, 5, 8, 10, 13, 14, 0, 3, 4, 7, 15, 1, 7, 9, 10, 12, 13, 14, 15, 1, 4, 8, 10, 11, 12, 1, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 0, 2, 4, 5, 8, 14, 15, 0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 1, 2, 3, 6, 7, 8, 10, 12], [1, 2, 3, 8, 9, 10, 11, 13, 14, 15, 2, 3, 5, 8, 9, 10, 11, 14, 1, 4, 6, 7, 9, 10, 11, 12, 0, 1, 4, 9, 10, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 0, 1, 2, 6, 7, 9, 10, 15, 0, 1, 2, 8, 9, 12, 13, 15, 0, 1, 4, 6, 8, 9, 13, 15, 2, 4, 5, 7, 10, 13, 15, 2, 5, 7, 10, 11, 13, 14, 15, 0, 1, 2, 3, 9, 10, 12, 13, 15, 0, 5, 6, 11, 13, 15, 0, 5, 6, 9, 11, 12, 13, 14, 2, 3, 5, 6, 8, 10, 15, 0, 1, 2, 3, 5, 9, 11, 12, 13, 15, 1, 2, 4, 6, 8, 9, 10, 11, 14, 15, 0, 2, 3, 4, 7, 8, 9, 10, 11, 13, 15, 0, 3, 4, 5, 9, 10, 12, 14, 15, 1, 5, 6, 9, 12, 14, 0, 1, 4, 7, 10, 11, 12, 14, 1, 2, 6, 8, 10, 12, 13, 15, 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 14, 15, 0, 2, 3, 4, 6, 9, 10, 11, 13, 15, 1, 3, 4, 5, 6, 7, 8, 11, 13, 14, 0, 3, 6, 8, 11, 12, 0, 2, 5, 6, 7, 8, 9, 14, 15, 1, 3, 6, 9, 11, 12, 13, 14, 15, 0, 3, 4, 5, 6, 9, 10, 12, 13, 14, 2, 4, 5, 6, 7, 9, 10, 13, 15, 0, 4, 6, 7, 8, 9, 12, 13, 14, 15, 0, 1, 2, 3, 5, 7, 8, 10, 13, 15, 2, 3, 4, 5, 6, 10, 12, 13, 15, 2, 3, 6, 7, 8, 12, 14, 15, 0, 4, 5, 10, 12, 15, 4, 5, 6, 7, 9, 10, 15, 0, 1, 5, 8, 10, 12, 14, 1, 5, 8, 9, 11, 12, 15, 0, 1, 4, 5, 6, 7, 8, 12, 0, 2, 5, 9, 11, 0, 2, 3, 4, 5, 6, 9, 10, 12, 13, 14, 1, 2, 4, 7, 10, 12, 13, 14, 15, 0, 3, 4, 5, 7, 11, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 9, 12, 15, 0, 1, 3, 4, 7, 8, 15, 1, 4, 6, 9, 10, 11, 0, 2, 3, 4, 7, 9, 12, 14, 0, 2, 4, 5, 8, 10, 12, 14, 15, 0, 3, 4, 6, 9, 10, 11, 12, 13, 1, 2, 6, 8, 9, 10, 12, 13, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 1, 2, 3, 10, 15, 2, 5, 7, 9, 13, 15, 0, 2, 5, 6, 10, 11, 13, 0, 3, 4, 5, 6, 7, 10, 13, 14, 15, 2, 8, 10, 15, 0, 1, 2, 4, 6, 9, 10, 11, 12, 15, 0, 1, 2, 3, 5, 6, 7, 9, 10, 13, 14, 15, 0, 1, 7, 11, 12, 1, 2, 3, 4, 9, 11, 12, 14, 0, 2, 5, 6, 8, 10, 1, 3, 5, 7, 9, 12, 13, 14, 2, 4, 5, 7, 9, 11, 14, 0, 4, 5, 6, 7, 8, 11, 14, 0, 3, 4, 5, 7, 12, 5, 9, 12, 13, 0, 3, 4, 6, 7, 8, 9, 11, 13, 2, 3, 5, 6, 7, 9, 14, 0, 1, 2, 3, 5, 6, 7, 8, 9, 12, 13, 15, 2, 5, 6, 8, 12, 13, 15, 0, 2, 4, 5, 6, 7, 8, 12, 14, 15, 1, 2, 3, 5, 9, 12, 15, 0, 1, 5, 8, 12, 13, 14, 1, 3, 6, 8, 9, 11, 12, 13, 3, 4, 5, 9, 11, 13, 1, 2, 4, 6, 7, 8, 9, 12, 15, 1, 4, 5, 7, 12, 13, 14, 15, 0, 2, 3, 5, 7, 8, 9, 11, 12, 3, 6, 7, 9, 11, 13, 15, 1, 2, 3, 6, 8, 9, 11, 13, 14, 0, 2, 3, 4, 5, 7, 8, 11, 14, 0, 1, 2, 4, 5, 9, 12, 13, 14, 15, 5, 7, 11, 12, 13, 15, 0, 2, 3, 4, 7, 8, 10, 13, 1, 2, 3, 4, 5, 6, 7, 9, 12, 13, 4, 8, 11, 14]] +# Vals: [-275, 130, -863, 147, 180, 534, 563, 41, -124, -359, -481, -40, 158, 413, -110, 421, -441, 978, 443, 295, 743, 955, -57, 765, -901, -143, -471, -476, -820, -405, 7, -413, 566, 477, -92, -791, -672, -733, 958, -773, 265, -42, -895, 139, -262, 337, 602, -5, 424, 478, 489, 614, -744, 854, -604, 393, -693, 769, 605, -357, -970, -304, -87, 363, -919, 166, 179, -313, 151, -734, 992, -158, -603, -453, 260, -731, -135, -945, 885, -649, -917, -371, -483, -874, -761, 918, -704, 401, 985, 5, 902, -946, -218, -504, 857, 943, 273, 622, 692, 364, 61, -109, 540, -733, -826, 43, -303, 185, -938, -269, -951, -117, -279, -388, -57, 288, 562, -34, 562, -856, 481, 307, -584, 153, 600, -527, 50, 374, 887, 705, 742, -482, -52, -280, 14, -582, 387, -910, -11, -823, -974, 765, 569, -106, 754, 27, -678, 297, -248, 642, -383, -984, 119, 276, -635, -843, 558, -833, 831, 910, 148, -222, -878, -881, 576, -3, -772, 660, 718, -266, 24, -96, 125, -94, 144, -490, 14, 713, 765, -527, -925, 109, 542, -567, -368, 951, -610, -594, -482, -740, 995, 993, -487, -178, -51, 91, -517, 102, 68, -291, -558, 201, -465, -673, 112, 484, 327, 931, -988, -786, -942, 935, 961, -891, -143, 255, -823, 628, 775, -290, -163, -183, 354, -342, -465, 137, 902, 870, -466, -324, 207, 896, -308, 637, 717, -537, 395, -746, 351, 523, -960, -458, 505, 869, -580, -502, 664, 171, 320, 877, 497, 461, -226, 130, -743, 98, 826, 427, 92, -223, -822, 952, -565, 920, 569, 539, 372, -248, 592, 405, -832, -692, 673, 22, 978, -327, 935, -10, 191, -558, -430, -874, -147, -133, -850, 268, 380, 828, -519, 414, 289, -11, -407, -844, -54, 660, -9, 537, -25, -614, -985, 238, -52, -437, 763, 792, 212, -892, -527, 658, 944, 416, -910, -82, -262, 634, -380, 672, -667, 662, 331, 928, -893, 141, 715, -590, -762, 124, -116, -736, -652, 812, -919, 952, 5, -801, -189, 315, 778, 762, 269, -594, -215, 492, 650, 938, 203, 443, 546, -976, 404, 917, 377, 729, 194, -759, -12, -253, 395, -152, -142, 136, -768, 525, -20, -761, 171, -793, 174, 845, 377, 354, -424, 941, 213, -732, 836, 191, 314, -275, -390, 520, 595, -466, -639, -888, 775, 672, 299, 762, 735, -329, -566, 137, 423, -774, -548, 307, -297, -332, -497, -633, -242, -297, -648, 239, -828, -2, -577, -643, 236, 849, -792, -513, -521, -470, -212, 148, -897, 497, 627, 834, -720, -914, 245, 550, 99, -410, 550, 537, 784, -716, 646, 213, -387, 914, 976, 388, 534, -543, 588, -453, -54, -819, -792, 885, 89, -834, 832, -427, -906, -630, -79, -354, 605, 651, -96, 261, 96, -726, -832, 550, -327, 519, -561, -928, -47, -352, 186, -103, 3, -563, 247, -416, 289, -54, 815, -216, 859, 909, -540, 38, -759, 541, -132, -466, 685, -354, -746, -956, -826, 431, -343, 67, 823, -732, 946, -611, 592, 541, 198, -28, 518, 433, 348, 264, -620, 935, 700, 594, -144, -14, 15, -101, -730, 706, -200, 713, 951, 348, -62, -935, 419, 511, -358, -734, 561, -329, 685, 948, 554, 256, -615, -666, -473, 295, -688, 508, 917, -269, 363, 484, 775, 807, 408, -519, 388, -205, 443, -959, 344, 107, -600, -403, 254, 778, 518, 320, 415, -976, 339, -36, -723, -980, 846, 66, -405, 956, 932, 747, -111, -804, -495, -821, 538, 366, -866, 614, -349, -145, 426, 256, 662, 533, -549, -381, -668, 531, 954, -343, -645, 823, -611, -382, -846, 474, 503, -673, 841, -549, 263, 966, 632, 574, 719, -219, -396, -98, 374, 700, -567, 84, 951, 294, -260, 334, -532, -828, -867, -399, 575, -9, 342, 913, 736, -882, -993, 232, -627, -655, -451, 606, 571, 289, -690, -161, 864, 608, -695, 806, -620, -844, 719, 353, 834, -915, 371, -151, -239, 355, 379, 405, -48, -565, 592, -531, -850, -800, 424, -384, -663, -982, 225, 294, -557, -97, 883, -674, -42, -436, -100, 548, 466, -54, -337, -222, -11, 112, 893, 372, -950, 418, 80, -24, 391, 659, 741, 25, -321, 367, -488, 106, 361, 41, 301, 650, -672, 105, -715, 401, -989, 804, 858] +arrs_dict1 = { "segs": [[0, 11], [0, 8, 18, 25, 31, 36, 44, 50, 61, 68, 78, 86], [0, 10, 18, 26, 35, 45, 53, 61, 69, 76, + 84, 93, 99, 107, 114, 124, 134, 145, + 154, 160, 168, 176, 188, 198, 208, + 214, 223, 232, 242, 251, 261, 271, + 280, 288, 294, 301, 308, 315, 323, 328, 339, 348, 357, 367, 378, 385, 391, 399, 408, 417, 425, 435, 440, 446, 453, 463, 467, 477, 489, 494, 502, 508, 516, 523, 531, 537, 541, 550, 557, 569, 576, 586, 593, 600, 608, 614, 623, 631, 640, 647, 656, 665, 675, 681, 689, 699, 703]], + "crds": [[0, 2, 3, 4, 5, 8, 9, 10, 11, 14, 15], [0, 1, 2, 5, 6, 7, 9, 14, 3, 4, 5, 6, 7, 8, 10, 11, 13, + 15, 4, 7, 8, 11, 12, 13, 14, 1, 5, 8, 10, 13, 14, 0, 3, 4, 7, 15, 1, 7, 9, 10, 12, 13, 14, 15, 1, 4, 8, 10, 11, 12, 1, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 0, 2, 4, 5, 8, 14, 15, 0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 1, 2, 3, 6, 7, 8, 10, 12], [1, 2, 3, 8, 9, 10, 11, 13, 14, 15, 2, 3, 5, 8, 9, 10, 11, 14, 1, 4, 6, 7, 9, 10, 11, 12, 0, 1, 4, 9, 10, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 0, 1, 2, 6, 7, 9, 10, 15, 0, 1, 2, 8, 9, 12, 13, 15, 0, 1, 4, 6, 8, 9, 13, 15, 2, 4, 5, 7, 10, 13, 15, 2, 5, 7, 10, 11, 13, 14, 15, 0, 1, 2, 3, 9, 10, 12, 13, 15, 0, 5, 6, 11, 13, 15, 0, 5, 6, 9, 11, 12, 13, 14, 2, 3, 5, 6, 8, 10, 15, 0, 1, 2, 3, 5, 9, 11, 12, 13, 15, 1, 2, 4, 6, 8, 9, 10, 11, 14, 15, 0, 2, 3, 4, 7, 8, 9, 10, 11, 13, 15, 0, 3, 4, 5, 9, 10, 12, 14, 15, 1, 5, 6, 9, 12, 14, 0, 1, 4, 7, 10, 11, 12, 14, 1, 2, 6, 8, 10, 12, 13, 15, 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 14, 15, 0, 2, 3, 4, 6, 9, 10, 11, 13, 15, 1, 3, 4, 5, 6, 7, 8, 11, 13, 14, 0, 3, 6, 8, 11, 12, 0, 2, 5, 6, 7, 8, 9, 14, 15, 1, 3, 6, 9, 11, 12, 13, 14, 15, 0, 3, 4, 5, 6, 9, 10, 12, 13, 14, 2, 4, 5, 6, 7, 9, 10, 13, 15, 0, 4, 6, 7, 8, 9, 12, 13, 14, 15, 0, 1, 2, 3, 5, 7, 8, 10, 13, 15, 2, 3, 4, 5, 6, 10, 12, 13, 15, 2, 3, 6, 7, 8, 12, 14, 15, 0, 4, 5, 10, 12, 15, 4, 5, 6, 7, 9, 10, 15, 0, 1, 5, 8, 10, 12, 14, 1, 5, 8, 9, 11, 12, 15, 0, 1, 4, 5, 6, 7, 8, 12, 0, 2, 5, 9, 11, 0, 2, 3, 4, 5, 6, 9, 10, 12, 13, 14, 1, 2, 4, 7, 10, 12, 13, 14, 15, 0, 3, 4, 5, 7, 11, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 9, 12, 15, 0, 1, 3, 4, 7, 8, 15, 1, 4, 6, 9, 10, 11, 0, 2, 3, 4, 7, 9, 12, 14, 0, 2, 4, 5, 8, 10, 12, 14, 15, 0, 3, 4, 6, 9, 10, 11, 12, 13, 1, 2, 6, 8, 9, 10, 12, 13, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 1, 2, 3, 10, 15, 2, 5, 7, 9, 13, 15, 0, 2, 5, 6, 10, 11, 13, 0, 3, 4, 5, 6, 7, 10, 13, 14, 15, 2, 8, 10, 15, 0, 1, 2, 4, 6, 9, 10, 11, 12, 15, 0, 1, 2, 3, 5, 6, 7, 9, 10, 13, 14, 15, 0, 1, 7, 11, 12, 1, 2, 3, 4, 9, 11, 12, 14, 0, 2, 5, 6, 8, 10, 1, 3, 5, 7, 9, 12, 13, 14, 2, 4, 5, 7, 9, 11, 14, 0, 4, 5, 6, 7, 8, 11, 14, 0, 3, 4, 5, 7, 12, 5, 9, 12, 13, 0, 3, 4, 6, 7, 8, 9, 11, 13, 2, 3, 5, 6, 7, 9, 14, 0, 1, 2, 3, 5, 6, 7, 8, 9, 12, 13, 15, 2, 5, 6, 8, 12, 13, 15, 0, 2, 4, 5, 6, 7, 8, 12, 14, 15, 1, 2, 3, 5, 9, 12, 15, 0, 1, 5, 8, 12, 13, 14, 1, 3, 6, 8, 9, 11, 12, 13, 3, 4, 5, 9, 11, 13, 1, 2, 4, 6, 7, 8, 9, 12, 15, 1, 4, 5, 7, 12, 13, 14, 15, 0, 2, 3, 5, 7, 8, 9, 11, 12, 3, 6, 7, 9, 11, 13, 15, 1, 2, 3, 6, 8, 9, 11, 13, 14, 0, 2, 3, 4, 5, 7, 8, 11, 14, 0, 1, 2, 4, 5, 9, 12, 13, 14, 15, 5, 7, 11, 12, 13, 15, 0, 2, 3, 4, 7, 8, 10, 13, 1, 2, 3, 4, 5, 6, 7, 9, 12, 13, 4, 8, 11, 14]], + "vals": [-275, 130, -863, 147, 180, 534, 563, 41, -124, -359, -481, -40, 158, 413, -110, 421, -441, 978, + 443, 295, 743, 955, -57, 765, -901, -143, -471, -476, -820, -405, 7, -413, 566, 477, -92, -791, -672, -733, 958, -773, 265, -42, -895, 139, -262, 337, 602, -5, 424, 478, 489, 614, -744, 854, -604, 393, -693, 769, 605, -357, -970, -304, -87, 363, -919, 166, 179, -313, 151, -734, 992, -158, -603, -453, 260, -731, -135, -945, 885, -649, -917, -371, -483, -874, -761, 918, -704, 401, 985, 5, 902, -946, -218, -504, 857, 943, 273, 622, 692, 364, 61, -109, 540, -733, -826, 43, -303, 185, -938, -269, -951, -117, -279, -388, -57, 288, 562, -34, 562, -856, 481, 307, -584, 153, 600, -527, 50, 374, 887, 705, 742, -482, -52, -280, 14, -582, 387, -910, -11, -823, -974, 765, 569, -106, 754, 27, -678, 297, -248, 642, -383, -984, 119, 276, -635, -843, 558, -833, 831, 910, 148, -222, -878, -881, 576, -3, -772, 660, 718, -266, 24, -96, 125, -94, 144, -490, 14, 713, 765, -527, -925, 109, 542, -567, -368, 951, -610, -594, -482, -740, 995, 993, -487, -178, -51, 91, -517, 102, 68, -291, -558, 201, -465, -673, 112, 484, 327, 931, -988, -786, -942, 935, 961, -891, -143, 255, -823, 628, 775, -290, -163, -183, 354, -342, -465, 137, 902, 870, -466, -324, 207, 896, -308, 637, 717, -537, 395, -746, 351, 523, -960, -458, 505, 869, -580, -502, 664, 171, 320, 877, 497, 461, -226, 130, -743, 98, 826, 427, 92, -223, -822, 952, -565, 920, 569, 539, 372, -248, 592, 405, -832, -692, 673, 22, 978, -327, 935, -10, 191, -558, -430, -874, -147, -133, -850, 268, 380, 828, -519, 414, 289, -11, -407, -844, -54, 660, -9, 537, -25, -614, -985, 238, -52, -437, 763, 792, 212, -892, -527, 658, 944, 416, -910, -82, -262, 634, -380, 672, -667, 662, 331, 928, -893, 141, 715, -590, -762, 124, -116, -736, -652, 812, -919, 952, 5, -801, -189, 315, 778, 762, 269, -594, -215, 492, 650, 938, 203, 443, 546, -976, 404, 917, 377, 729, 194, -759, -12, -253, 395, -152, -142, 136, -768, 525, -20, -761, 171, -793, 174, 845, 377, 354, -424, 941, 213, -732, 836, 191, 314, -275, -390, 520, 595, -466, -639, -888, 775, 672, 299, 762, 735, -329, -566, 137, 423, -774, -548, 307, -297, -332, -497, -633, -242, -297, -648, 239, -828, -2, -577, -643, 236, 849, -792, -513, -521, -470, -212, 148, -897, 497, 627, 834, -720, -914, 245, 550, 99, -410, 550, 537, 784, -716, 646, 213, -387, 914, 976, 388, 534, -543, 588, -453, -54, -819, -792, 885, 89, -834, 832, -427, -906, -630, -79, -354, 605, 651, -96, 261, 96, -726, -832, 550, -327, 519, -561, -928, -47, -352, 186, -103, 3, -563, 247, -416, 289, -54, 815, -216, 859, 909, -540, 38, -759, 541, -132, -466, 685, -354, -746, -956, -826, 431, -343, 67, 823, -732, 946, -611, 592, 541, 198, -28, 518, 433, 348, 264, -620, 935, 700, 594, -144, -14, 15, -101, -730, 706, -200, 713, 951, 348, -62, -935, 419, 511, -358, -734, 561, -329, 685, 948, 554, 256, -615, -666, -473, 295, -688, 508, 917, -269, 363, 484, 775, 807, 408, -519, 388, -205, 443, -959, 344, 107, -600, -403, 254, 778, 518, 320, 415, -976, 339, -36, -723, -980, 846, 66, -405, 956, 932, 747, -111, -804, -495, -821, 538, 366, -866, 614, -349, -145, 426, 256, 662, 533, -549, -381, -668, 531, 954, -343, -645, 823, -611, -382, -846, 474, 503, -673, 841, -549, 263, 966, 632, 574, 719, -219, -396, -98, 374, 700, -567, 84, 951, 294, -260, 334, -532, -828, -867, -399, 575, -9, 342, 913, 736, -882, -993, 232, -627, -655, -451, 606, 571, 289, -690, -161, 864, 608, -695, 806, -620, -844, 719, 353, 834, -915, 371, -151, -239, 355, 379, 405, -48, -565, 592, -531, -850, -800, 424, -384, -663, -982, 225, 294, -557, -97, 883, -674, -42, -436, -100, 548, 466, -54, -337, -222, -11, 112, 893, 372, -950, 418, 80, -24, 391, 659, 741, 25, -321, 367, -488, 106, 361, 41, 301, 650, -672, 105, -715, 401, -989, 804, 858], + "dim": 16 +} + +# Segs: [[0, 8], [0, 10, 21, 30, 40, 52, 61, 68, 76], [0, 8, 18, 28, 35, 48, 57, 62, 73, 83, 94, 99, 111, 121, 129, 137, 144, 152, 159, 166, 176, 184, 191, 197, 204, 214, 221, 233, 240, 246, 255, 264, 268, 275, 282, 291, 300, 308, 313, 320, 328, 338, 346, 356, 365, 376, 383, 391, 401, 407, 419, 426, 430, 439, 448, 457, 462, 468, 473, 480, 486, 494, 501, 508, 517, 526, 533, 543, 551, 559, 567, 577, 586, 592, 598, 608, 614]] +# Crds: [[0, 1, 2, 4, 7, 10, 12, 13], [0, 2, 5, 7, 8, 10, 11, 13, 14, 15, 0, 1, 2, 3, 4, 5, 7, 10, 12, 14, 15, 0, 1, 2, 3, 4, 5, 9, 14, 15, 0, 1, 2, 3, 6, 8, 9, 10, 11, 14, 0, 1, 2, 3, 4, 6, 7, 8, 11, 12, 14, 15, 0, 2, 3, 4, 7, 8, 11, 13, 14, 5, 6, 9, 10, 11, 14, 15, 2, 3, 5, 6, 10, 11, 12, 15], [0, 1, 3, 5, 7, 8, 11, 12, 0, 1, 2, 3, 6, 7, 9, 11, 14, 15, 0, 1, 2, 4, 6, 7, 11, 13, 14, 15, 2, 3, 4, 6, 10, 14, 15, 0, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 1, 2, 4, 5, 6, 9, 10, 11, 15, 4, 5, 6, 8, 13, 0, 1, 2, 4, 6, 9, 10, 11, 13, 14, 15, 1, 4, 6, 7, 8, 9, 12, 13, 14, 15, 1, 3, 4, 6, 8, 9, 10, 11, 12, 13, 15, 4, 6, 8, 9, 15, 0, 1, 2, 5, 6, 7, 8, 11, 12, 13, 14, 15, 1, 2, 5, 6, 8, 9, 11, 12, 13, 15, 3, 5, 6, 9, 10, 11, 12, 15, 0, 1, 2, 6, 7, 12, 14, 15, 2, 6, 7, 9, 10, 11, 15, 0, 4, 6, 7, 8, 10, 11, 13, 0, 5, 6, 8, 13, 14, 15, 3, 7, 9, 10, 11, 13, 15, 0, 3, 4, 6, 7, 8, 9, 11, 14, 15, 1, 2, 3, 4, 5, 9, 10, 14, 2, 3, 5, 8, 10, 12, 15, 0, 2, 8, 9, 11, 12, 0, 1, 3, 4, 10, 13, 15, 0, 1, 4, 5, 6, 7, 8, 11, 12, 13, 1, 2, 3, 6, 10, 11, 13, 1, 2, 3, 4, 5, 8, 9, 11, 12, 13, 14, 15, 2, 4, 5, 6, 9, 13, 14, 0, 5, 6, 9, 11, 15, 0, 1, 2, 4, 6, 8, 12, 13, 15, 0, 1, 2, 4, 5, 6, 8, 9, 11, 4, 6, 8, 13, 1, 2, 3, 6, 10, 13, 15, 0, 1, 2, 8, 13, 14, 15, 0, 2, 3, 4, 7, 9, 10, 12, 15, 0, 2, 4, 5, 7, 8, 10, 11, 15, 2, 4, 5, 7, 8, 10, 12, 15, 2, 8, 10, 13, 14, 0, 6, 9, 10, 12, 14, 15, 3, 4, 6, 7, 9, 10, 11, 14, 0, 3, 6, 7, 10, 11, 12, 13, 14, 15, 0, 2, 7, 8, 9, 11, 14, 15, 0, 1, 3, 5, 7, 8, 9, 12, 14, 15, 0, 3, 4, 5, 7, 8, 10, 11, 12, 0, 1, 2, 5, 6, 8, 9, 10, 11, 12, 14, 1, 2, 4, 5, 7, 8, 15, 1, 5, 8, 9, 10, 12, 13, 14, 0, 1, 2, 7, 8, 9, 10, 11, 12, 15, 0, 1, 6, 7, 10, 15, 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 13, 15, 0, 1, 2, 3, 9, 11, 14, 0, 4, 8, 10, 0, 1, 2, 4, 8, 11, 12, 14, 15, 0, 1, 2, 5, 8, 9, 12, 13, 14, 1, 3, 4, 5, 8, 9, 11, 12, 15, 1, 5, 10, 11, 14, 0, 5, 6, 9, 14, 15, 1, 2, 13, 14, 15, 4, 5, 6, 7, 8, 11, 12, 0, 2, 6, 10, 12, 15, 1, 3, 5, 6, 8, 9, 12, 15, 0, 3, 4, 7, 11, 12, 15, 1, 2, 4, 7, 9, 10, 11, 0, 3, 5, 7, 8, 9, 11, 12, 14, 0, 2, 3, 5, 6, 10, 11, 13, 14, 0, 2, 4, 7, 10, 12, 13, 0, 3, 4, 5, 6, 7, 9, 10, 13, 14, 1, 4, 6, 7, 8, 9, 11, 15, 0, 1, 2, 4, 7, 8, 13, 14, 0, 2, 4, 5, 10, 11, 12, 13, 0, 2, 3, 6, 8, 9, 10, 11, 12, 15, 0, 1, 2, 4, 5, 6, 9, 11, 12, 0, 1, 5, 13, 14, 15, 0, 2, 3, 7, 11, 12, 0, 1, 2, 3, 6, 8, 9, 10, 12, 13, 1, 5, 7, 9, 14, 15]] +# Vals: [-250, 363, -637, 105, -364, -874, 861, -490, -222, 321, -667, -537, -151, -746, -36, 71, -32, -998, 438, 604, 436, -383, 27, -107, -106, -109, -707, 226, 953, 707, -210, -155, 377, -780, 102, -186, -798, 171, -467, 982, -397, 387, -395, 456, -864, -836, -271, -27, -99, -159, -815, 885, -662, -14, -951, 462, 617, -442, 433, 395, 82, 819, -938, 877, -57, -349, -993, -812, -541, -269, -284, -60, -242, -744, 62, -829, -976, 403, 621, -87, -548, 731, -643, -137, -264, -38, 613, 643, 882, 410, -124, -688, 86, 365, 632, 657, -955, 279, -80, -409, 357, 181, 527, 537, 340, -683, -434, 203, 68, 480, 452, 981, 890, 700, -559, 792, 241, -528, 275, 45, 211, -765, 511, 931, -560, -897, 836, -816, -881, 44, 726, -858, -322, 847, 247, -336, -276, -835, 732, 961, -30, -570, 924, -605, -399, 80, 952, 747, 546, 25, -743, -687, -981, 454, 579, -634, 924, 156, -708, 716, -447, -234, -370, -746, -864, -87, 633, -176, 839, -868, -26, 32, 896, 593, 298, -668, -225, -213, 516, -300, -98, 417, -549, 168, 978, -902, -79, -192, 789, 488, 188, 814, -1000, 205, 186, 494, -319, 613, -460, -645, -723, -692, -333, -953, -211, -291, -957, 797, 607, -30, 611, 931, -725, -809, 583, 672, 262, 620, 711, 774, 563, 157, 395, 60, -456, -130, 268, 999, 705, 989, -812, 223, 501, 920, -495, -371, 816, 671, -183, 205, 910, -553, 465, -316, 712, 410, -804, -744, -369, -665, 619, -617, 256, -823, 640, 75, -758, -710, -697, -659, 990, -858, -235, 476, -236, 248, -47, 259, 271, -163, -889, -216, 692, -418, -14, 614, -829, -670, 381, -385, 928, -797, 670, 246, 395, 474, 917, -717, 700, -214, 162, -517, 389, 437, 278, -45, 219, -805, 617, 533, -772, 255, -25, 978, -46, -873, 262, -978, -13, -289, 812, -988, 626, -442, 223, -272, 933, 180, 182, 35, -176, -770, -86, 547, 590, -551, -627, -463, -361, 267, 859, -147, 979, -437, 735, -112, -348, -395, -745, -328, -974, -602, -820, -4, -600, -273, 458, 634, 591, 975, -116, -432, -689, -916, 523, -227, -203, 719, 527, 992, -475, -103, 28, -229, 680, -62, -83, -105, -394, 606, 15, 919, -546, 803, 5, -52, -817, 647, -436, 858, -51, -987, -923, 835, -2, 88, 873, -444, -509, -185, -988, -951, -863, -523, -969, -373, -817, -629, -999, 467, 148, -168, 512, -446, -386, -582, 810, 326, 505, -707, -339, 155, -27, -104, -603, -207, -740, -138, -107, 998, -252, 160, 689, -585, -140, 396, 453, 42, -325, 782, -638, 973, -343, 942, 968, 979, 879, -745, 245, 917, -532, -278, -194, 912, -299, 248, -849, -565, -100, -779, -658, -110, -257, -39, -766, 885, -704, -4, 533, 77, -27, -704, 497, -934, 299, 528, 149, 583, -697, -107, -48, 299, 759, 377, -798, -825, -893, -299, -178, 183, 39, -367, -862, -660, -157, -93, -89, 36, 563, 547, 392, -977, -864, 376, 4, 19, -416, 485, -637, 156, -20, -714, 116, -383, -182, -771, -851, -973, -282, 716, -243, -899, -267, 792, 668, -921, 10, -612, 96, 354, -23, 415, 233, 934, -193, 619, 5, 281, -660, -299, 50, 105, -469, -141, 347, 440, 758, -620, 620, -460, 673, 16, -905, -468, 565, -416, -3, -248, 57, 870, -895, 890, 847, -127, -490, -881, -901, 455, 235, 260, -703, -255, -541, -238, -215, 886, 429, -350, -357, 828, 646, 448, -860, -894, -934, -314, 922, -640, 506, 117, 525, -606, -701, -582, 356, 172, -218, -780, -540, 272, -768, 397, -41, -795, -619, -568, 268, 691, 669, -452, -851, -218, -432, -767, -300, 178, 769, -191, -272, 349, 573, -291, 429, -236] +@pytest.mark.parametrize("arrs", [arrs_dict1]) +def test_spacc2new_tensor_direct(arrs, debug_sim, fill=0): + in_mat_crds1 = arrs["crds"] + in_mat_segs1 = arrs["segs"] + in_mat_vals1 = arrs["vals"] + dim = arrs["dim"] + + in1_tup = convert_point_tuple(get_point_list(in_mat_crds1, in_mat_segs1, in_mat_vals1)) + + nd1 = convert_point_tuple_ndarr(in1_tup, dim) + gold_nd = np.sum(nd1, 0) + gold_tup = convert_ndarr_point_tuple(gold_nd) + + rdscan_B1 = CompressedCrdRdScan(crd_arr=in_mat_crds1[0], seg_arr=in_mat_segs1[0], debug=debug_sim) + rdscan_B2 = CompressedCrdRdScan(crd_arr=in_mat_crds1[1], seg_arr=in_mat_segs1[1], debug=debug_sim) + rdscan_B3 = CompressedCrdRdScan(crd_arr=in_mat_crds1[2], seg_arr=in_mat_segs1[2], debug=debug_sim) + + val_B = Array(init_arr=in_mat_vals1, debug=debug_sim) + sa = SpAcc2(valtype=int, val_stkn=True, debug=debug_sim) + + vals_X = ValsWrScan(size=dim * dim, fill=fill, debug=debug_sim) + wrscan_X1 = CompressWrScan(seg_size=2, size=dim, fill=fill, debug=debug_sim) + wrscan_X2 = CompressWrScan(seg_size=dim + 1, size=dim * dim, fill=fill, debug=debug_sim) + + done = False + time = 0 + in_ref_B = [0, 'D'] + out_rdscan_B1 = [] + out_rdscan_B2 = [] + out_rdscan_B3 = [] + out_val_B = [] + while not done and time < TIMEOUT: + if len(in_ref_B) > 0: + rdscan_B1.set_in_ref(in_ref_B.pop(0)) + rdscan_B2.set_in_ref(rdscan_B1.out_ref()) + rdscan_B3.set_in_ref(rdscan_B2.out_ref()) + val_B.set_load(rdscan_B3.out_ref()) + + # Inject random empty strings + out_rdscan_B1.append(rdscan_B1.out_crd()) + out_rdscan_B2.append(rdscan_B2.out_crd()) + out_rdscan_B3.append(rdscan_B3.out_crd()) + out_val_B.append(val_B.out_load()) + + # Inject random delay + if random.random() < 0.2: + out_rdscan_B1.append("") + if random.random() < 0.2: + out_rdscan_B2.append("") + if random.random() < 0.2: + out_val_B.append("") + + sa.set_in_crd2(out_rdscan_B1.pop(0)) + sa.set_in_crd1(out_rdscan_B2.pop(0)) + sa.set_in_crd0(out_rdscan_B3.pop(0)) + sa.set_val(out_val_B.pop(0)) + + vals_X.set_input(sa.out_val()) + wrscan_X1.set_input(sa.out_crd1()) + wrscan_X2.set_input(sa.out_crd0()) + + rdscan_B1.update() + rdscan_B2.update() + rdscan_B3.update() + val_B.update() + sa.update() + vals_X.update() + wrscan_X1.update() + wrscan_X2.update() + + if time % 100 == 0: + print("Timestep", time, "\t Done --", + "\tRdScan B1:", rdscan_B1.out_done(), + "\tRdScan B2:", rdscan_B2.out_done(), + "\tRdScan B3:", rdscan_B3.out_done(), + "\tSpAcc1New:", sa.out_done(), + "\tArr:", val_B.out_done(), + "\tWrScan:", vals_X.out_done(), + "\tWrScan X1:", wrscan_X1.out_done(), + "\tWrScan X2:", wrscan_X2.out_done(), + ) + + done = wrscan_X2.out_done() and wrscan_X1.out_done() and vals_X.out_done() + time += 1 + + wrscan_X1.autosize() + wrscan_X2.autosize() + vals_X.autosize() + + out_crds = [wrscan_X1.get_arr(), wrscan_X2.get_arr()] + out_segs = [wrscan_X1.get_seg_arr(), wrscan_X2.get_seg_arr()] + out_val = vals_X.get_arr() + + if debug_sim: + print("Input", in_mat_segs1, in_mat_crds1, in_mat_vals1) + print(nd1) + print("X seg", out_segs) + print("X crd", out_crds) + print("X val", out_val) + print("Gold np", gold_nd) + print("Gold Tuple", gold_tup) + + if not out_val: + assert out_val == gold_tup + else: + out_tup = convert_point_tuple(get_point_list(out_crds, out_segs, out_val)) + out_tup = remove_zeros(out_tup) + print("\nSegs: " + str(in_mat_segs1) + "\nCrds: " + str(in_mat_crds1) + \ + "\nVals: " + str(in_mat_vals1)) + assert check_point_tuple(out_tup, gold_tup) + +@pytest.mark.parametrize("dim", [2 ** x for x in range(1, 5, 1)]) +def test_spacc2new_tensor_rand(dim, debug_sim, max_val=1000, fill=0): in_mat_crds1, in_mat_segs1 = gen_n_comp_arrs(3, dim) in_mat_vals1 = gen_val_arr(len(in_mat_crds1[-1]), max_val, -max_val) @@ -257,7 +385,7 @@ def test_spacc2new_rand(dim, debug_sim, max_val=1000, fill=0): vals_X = ValsWrScan(size=dim * dim, fill=fill, debug=debug_sim) wrscan_X1 = CompressWrScan(seg_size=2, size=dim, fill=fill, debug=debug_sim) - wrscan_X2 = CompressWrScan(seg_size=dim+1, size=dim*dim, fill=fill, debug=debug_sim) + wrscan_X2 = CompressWrScan(seg_size=dim + 1, size=dim * dim, fill=fill, debug=debug_sim) done = False time = 0 @@ -306,16 +434,17 @@ def test_spacc2new_rand(dim, debug_sim, max_val=1000, fill=0): wrscan_X1.update() wrscan_X2.update() - print("Timestep", time, "\t Done --", - "\tRdScan B1:", rdscan_B1.out_done(), - "\tRdScan B2:", rdscan_B2.out_done(), - "\tRdScan B3:", rdscan_B3.out_done(), - "\tSpAcc1New:", sa.out_done(), - "\tArr:", val_B.out_done(), - "\tWrScan:", vals_X.out_done(), - "\tWrScan X1:", wrscan_X1.out_done(), - "\tWrScan X2:", wrscan_X2.out_done(), - ) + if time % 100 == 0: + print("Timestep", time, "\t Done --", + "\tRdScan B1:", rdscan_B1.out_done(), + "\tRdScan B2:", rdscan_B2.out_done(), + "\tRdScan B3:", rdscan_B3.out_done(), + "\tSpAcc1New:", sa.out_done(), + "\tArr:", val_B.out_done(), + "\tWrScan:", vals_X.out_done(), + "\tWrScan X1:", wrscan_X1.out_done(), + "\tWrScan X2:", wrscan_X2.out_done(), + ) done = wrscan_X2.out_done() and wrscan_X1.out_done() and vals_X.out_done() time += 1 @@ -341,4 +470,6 @@ def test_spacc2new_rand(dim, debug_sim, max_val=1000, fill=0): assert out_val == gold_tup else: out_tup = convert_point_tuple(get_point_list(out_crds, out_segs, out_val)) - assert (check_point_tuple(out_tup, gold_tup)) \ No newline at end of file + print("\nSegs: " + str(in_mat_segs1) + "\nCrds: " + str(in_mat_crds1) + \ + "\nVals: " + str(in_mat_vals1)) + assert check_point_tuple(out_tup, gold_tup) diff --git a/sam/sim/test/primitives/test_spacc_helpers.py b/sam/sim/test/primitives/test_spacc_helpers_OLD.py similarity index 95% rename from sam/sim/test/primitives/test_spacc_helpers.py rename to sam/sim/test/primitives/test_spacc_helpers_OLD.py index c85c2e14..7da8905a 100644 --- a/sam/sim/test/primitives/test_spacc_helpers.py +++ b/sam/sim/test/primitives/test_spacc_helpers_OLD.py @@ -5,12 +5,12 @@ from sam.sim.src.base import remove_emptystr from sam.sim.test.test import TIMEOUT -arrs_dict1 = {'ocrd_in': [0, 2, 2, 2, 2, 2, 2, 'D'], +arrs_dict1 = {'ocrd_in': [0, 2, 2, 2, 2, 2, 2, 2, 2, 'D'], 'icrd_in': [0, 2, 3, 0, 2, 3, 0, 2, 3, 'D'], 'val_in': [50, 5, 10, 40, 4, 8, -40, 33, 36, 'D'], 'ocrd_gold': [0, 2, 'S0', 'D'], - 'icrd_gold': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], - 'val_gold': [50, 5, 10, 'S0', 0, 37, 44, 'S1', 'D']} + 'icrd_gold': [0, 'S0', 0, 2, 3, 'S1', 'D'], + 'val_gold': [50, 'S0', 0, 42, 54, 'S1', 'D']} @pytest.mark.parametrize("arrs", [arrs_dict1]) diff --git a/sam/sim/test/primitives/test_spcrdpt_accumulator.py b/sam/sim/test/primitives/test_spcrdpt_accumulator_OLD.py similarity index 97% rename from sam/sim/test/primitives/test_spcrdpt_accumulator.py rename to sam/sim/test/primitives/test_spcrdpt_accumulator_OLD.py index 67b36087..087a4644 100644 --- a/sam/sim/test/primitives/test_spcrdpt_accumulator.py +++ b/sam/sim/test/primitives/test_spcrdpt_accumulator_OLD.py @@ -1,7 +1,7 @@ import copy import pytest -from sam.sim.src.accumulator import SparseCrdPtAccumulator1, SparseCrdPtAccumulator2 +from sam.sim.src.accumulator_helpers import SparseCrdPtAccumulator1, SparseCrdPtAccumulator2 from sam.sim.src.base import remove_emptystr from sam.sim.test.test import TIMEOUT diff --git a/sam/sim/test/primitives/test_stkn_drop.py b/sam/sim/test/primitives/test_stkn_drop.py index eb667ddb..3863083d 100644 --- a/sam/sim/test/primitives/test_stkn_drop.py +++ b/sam/sim/test/primitives/test_stkn_drop.py @@ -28,7 +28,7 @@ def test_tkn_drop(arrs, debug_sim): out = [] while not done and time < TIMEOUT: if len(ival) > 0: - td.set_in_stream(ival.pop(0)) + td.set_in_val(ival.pop(0)) td.update() diff --git a/sam/sim/test/test.py b/sam/sim/test/test.py index 2d45e58e..3d63ed1a 100644 --- a/sam/sim/test/test.py +++ b/sam/sim/test/test.py @@ -186,14 +186,15 @@ def remove_zeros(pt_tup): def check_point_tuple(pt_tup1, pt_tup2, err=1e-12): tup1 = sorted(pt_tup1) tup2 = sorted(pt_tup2) - assert len(tup1) == len(tup2), "Pts1 length (" + str(len(tup1)) + " != Pts2 length (" + str(len(tup2)) + ")" assert len(tup1[0]) == len(tup2[0]), str(len(tup1[0])) + " != " + str(len(tup2[0])) for i in range(len(tup1)): if tup1[i] != tup2[i]: if abs(tup1[i][-1] - tup2[i][-1]) > max(abs(tup1[i][-1]) * err, err): - print(str(i) + ":", tup1[i], "!=", ) + print(str(i) + ": " + str(tup1[i]) + "," + str(tup1[i+1]) + " != " + str(tup2[i])) return False + + assert len(tup1) == len(tup2), "Pts1 length (" + str(len(tup1)) + " != Pts2 length (" + str(len(tup2)) + ")" return True From ce48880ebe4e71bbe4d8b848d6d0332b4558d0d3 Mon Sep 17 00:00:00 2001 From: Olivia Hsu Date: Mon, 22 Jan 2024 10:11:44 -0800 Subject: [PATCH 8/9] Update sam-kernels to include unfused mttkrp --- compiler/sam-kernels.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/sam-kernels.sh b/compiler/sam-kernels.sh index 44db88c2..0449b1ef 100755 --- a/compiler/sam-kernels.sh +++ b/compiler/sam-kernels.sh @@ -37,6 +37,8 @@ GEN_KERNEL_NAMES=( mat_residual mat_elemadd3 tensor3_mttkrp + tensor3_mttkrp_unfused1 + tensor3_mttkrp_unfused2 vec_spacc_simple mat_spacc_simple vec_sd_compression_WRONG @@ -79,6 +81,8 @@ TACO_ARGS=( "x(i)=b(i)-C(i,j)*d(j) -f=x:s -f=C:ss -f=b:s -f=d:s" "X(i,j)=B(i,j)+C(i,j)+D(i,j) -f=X:ss -f=B:ss -f=C:ss -f=D:ss" "X(i,j)=B(i,k,l)*C(j,k)*D(j,l) -f=X:ss -f=B:sss -f=C:ss -f=D:ss" + "T(j,k,l)=C(j,k)*D(j,l) -f=T:sss -f=C:ss -f=D:ss" + "X(i,j)=B(i,k,l)*T(j,k,l) -f=X:ss -f=B:sss -f=T:sss" "x(j)=B(i,j) -f=x:s -f=B:ss" "X(j,k)=B(i,j,k) -f=X:ss -f=B:sss" "x(i)=b(i) -f=b:s -f=x:d" From 4ca552c5f80c759b74d0001a4afb5c14e7792dec Mon Sep 17 00:00:00 2001 From: Olivia Hsu Date: Thu, 6 Jun 2024 14:37:19 -0700 Subject: [PATCH 9/9] Some fixes to sparse accumulator --- compiler/sam-kernels.sh | 2 +- sam/sim/src/accumulator.py | 183 ++++++++++++++++---------- sam/sim/test/primitives/test_spacc.py | 143 ++++++++++++++++---- 3 files changed, 231 insertions(+), 97 deletions(-) diff --git a/compiler/sam-kernels.sh b/compiler/sam-kernels.sh index 0449b1ef..254336b3 100755 --- a/compiler/sam-kernels.sh +++ b/compiler/sam-kernels.sh @@ -73,7 +73,7 @@ TACO_ARGS=( "X(i,j,k)=B(i,j,k) -f=X:sss -f=B:sss" "X(i,j,k)=B(i,j,k) -f=X:ddd -f=B:ddd" "X(i,j,k)=B(i,j,k)+C(i,j,k) -f=X:sss -f=B:sss -f=C:sss" - "x=B(i,j,k)*C(i,j,k) -f=B:sss -f=C:sss" + "x=B(i,j,k)*C(i,j,k) -f=B:sss -f=C:sss -s=reorder(i,j,k)" "X(i,j)=B(i,j,k)*c(k) -f=X:ss -f=B:sss -f=c:s" "X(i,j,k)=B(i,j,l)*C(k,l) -f=X:sss -f=B:sss -f=C:ss" "X(i,j)=B(i,j)*C(i,k)*D(k,j) -f=X:ss -f=B:ss -f=C:dd -f=D:dd:1,0 -s=reorder(i,j,k)" diff --git a/sam/sim/src/accumulator.py b/sam/sim/src/accumulator.py index 5164b637..0a1f7eca 100644 --- a/sam/sim/src/accumulator.py +++ b/sam/sim/src/accumulator.py @@ -164,13 +164,13 @@ def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, d # Boolean flag for whether to output stop tokens on the output val stream self.val_stkn = val_stkn - self.in_crd1 = [] + # self.in_crd1 = [] self.in_crd0 = [] self.in_val = [] self.storage = {} - self.curr_crd1 = None + # self.curr_crd1 = None self.curr_crd0 = None self.curr_val = None @@ -179,7 +179,7 @@ def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, d if self.get_stats: self.in_crd0_fifo = 0 - self.in_crd1_fifo = 0 + # self.in_crd1_fifo = 0 self.in_val_fifo = 0 if self.backpressure_en: @@ -197,7 +197,7 @@ def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, d self.writeout_storage = [] self.seen_done = False - self.crd1_stkn = None + self.wr_stkn = None def check_backpressure(self): if self.backpressure_en: @@ -232,16 +232,19 @@ def add_child(self, child=None, branch=""): def update_ready(self): if self.backpressure_en: - self.fifo_avail_outer = not (len(self.in_crd1) > self.depth) + # 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) + def ACC_body(self, pop_ins=False): + if pop_ins: + 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" + assert is_nc_tkn(self.curr_in_crd0, int), ("The inner coordinate (" + str(self.curr_in_crd0) + + ") 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 @@ -250,10 +253,17 @@ def ACC_body(self): 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): + elif is_stkn(self.curr_in_crd0) and stkn_order(self.curr_in_crd0) == 0: 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 + # In accumulation, if you see a stop token of any other level, start writing out + elif is_stkn(self.curr_in_crd0): + self.wr_stkn = self.curr_in_crd0 + 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_in_crd0): assert False, "Shouldn't have done token for coordinates if in accumulate (ACC) state" # Do nothing @@ -267,8 +277,8 @@ def update(self): # 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("Inputs: ", self.in_crd0, self.in_val) + print("Temps: ", self.wr_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) @@ -302,7 +312,7 @@ def update(self): 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: + if len(self.in_crd0) > 0 or len(self.in_val) > 0: self.block_start = False # Store block statistics if asked to be reported @@ -312,34 +322,34 @@ def update(self): # 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): + if len(self.in_crd0) > 0 and len(self.in_val) > 0: + 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_crd0): + assert is_nc_tkn(self.curr_in_val), ("The inner value (" + str(self.curr_in_val) + + ") must be a non-control token") + self.ACC_body() + elif is_stkn(self.curr_in_crd0) and stkn_order(self.curr_in_crd0) > 0: # 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.wr_stkn = self.curr_crd0 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): + elif is_dtkn(self.curr_in_crd0): 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) + assert False, "Cannot have a coordinate token of this type: " + str(self.curr_crd0) # 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() + self.ACC_body(True) # Finish writeout and then be done. elif self.curr_state == self.states.WR: if not self.writeout: @@ -360,9 +370,9 @@ def update(self): # 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 + assert self.wr_stkn is not None, "The current writeout stop token should not be None" + self.curr_crd0 = decrement_stkn(self.wr_stkn) + self.curr_val = decrement_stkn(self.wr_stkn) else: curr_writeout_elem = self.writeout_storage.pop(0) self.curr_val = curr_writeout_elem[1] @@ -378,8 +388,8 @@ def update(self): self.curr_state = self.next_state if self.debug: - print(self.in_crd1, self.in_crd0, self.in_val) - print(self.curr_crd1, self.curr_crd0, self.curr_val) + print(self.in_crd0, self.in_val) + print(self.curr_crd0, self.curr_val) def set_in_crd0(self, crd, parent=None): if crd != '' and crd is not None: @@ -387,11 +397,11 @@ def set_in_crd0(self, crd, parent=None): if self.backpressure_en: parent.set_backpressure(self.fifo_avail_inner) - 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_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): if val != '' and val is not None: @@ -431,14 +441,14 @@ def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, d # Boolean flag for whether to output stop tokens on the output val stream self.val_stkn = val_stkn - self.in_crd2 = [] + # self.in_crd2 = [] self.in_crd1 = [] self.in_crd0 = [] self.in_val = [] self.storage = {} - self.curr_crd2 = None + # self.curr_crd2 = None self.curr_crd1 = None self.curr_crd0 = None self.curr_val = None @@ -447,7 +457,8 @@ def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, d self.curr_in_crd0 = None self.curr_in_val = None - self.states = enum.Enum('States', ['READY', 'ACC1', 'ACC0', 'WR', 'DONE']) + self.states = enum.Enum('States', ['READY', 'ACC1', 'WAIT_ACC1', + 'ACC0', 'WR', 'DONE']) self.curr_state = self.states.READY self.next_state = self.states.READY self.writeout0 = False @@ -456,7 +467,8 @@ def __init__(self, maxdim=100, valtype=float, last_level=True, val_stkn=False, d self.writeout_storage0 = [] self.seen_done = False - self.crd2_stkn = None + self.wr_stkn = None + self.wait_crd1 = False if self.get_stats: self.in_crd0_fifo = 0 @@ -505,14 +517,14 @@ def add_child(self, child=None, branch=""): def update_ready(self): if self.backpressure_en: - 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_1 = not (len(self.in_crd1) > self.depth) + self.fifo_avail_0 = 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("Inputs: ", self.in_crd1, self.in_crd0, self.in_val) + print("Temps: ", self.wr_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) @@ -540,9 +552,10 @@ def update_storage(self, crd1, crd0, val): else: self.storage[crd1][crd0] += val - def ACC1_body(self): + def ACC1_body(self, pop_crd1=False): # In accumulation, accumulate into memory - self.curr_in_crd1 = self.in_crd1.pop(0) + if pop_crd1: + self.curr_in_crd1 = self.in_crd1.pop(0) # All elements are ready if is_nc_tkn(self.curr_in_crd1): @@ -550,7 +563,16 @@ def ACC1_body(self): self.ACC0_body() else: self.next_state = self.states.ACC0 + elif is_stkn(self.curr_in_crd1) and stkn_order(self.curr_in_crd1) == 0: + self.next_state = self.states.ACC0 + # In accumulation, if you see a stop token of any other level, start writing out elif is_stkn(self.curr_in_crd1): + self.wr_stkn = self.curr_in_crd1 + 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_dtkn(self.curr_in_crd1): assert False, "Shouldn't have done token for coordinates if in accumulate (ACC) state" @@ -566,16 +588,39 @@ def ACC0_body(self): 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): + elif is_stkn(self.curr_in_crd0) and stkn_order(self.curr_in_crd0) == 0: 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_stkn(self.curr_in_crd0): + self.check_crd1() + # If you see a stop token go back to ready + # elif is_stkn(self.curr_in_crd0): + # 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: assert False, "Cannot have a coordinate token of this type: " + str(self.curr_in_crd0) + def check_crd1(self): + if len(self.in_crd1) > 0: + self.curr_in_crd1 = self.in_crd1.pop(0) + assert (is_stkn(self.curr_in_crd1) and stkn_order(self.curr_in_crd1) == + stkn_order(self.curr_in_crd0) - 1), ("Stop tokens must match for crd1: " + str(self.curr_in_crd1) + + " and crd0: " + str(self.curr_in_crd0)) + if stkn_order(self.curr_in_crd1) > 0: + self.wr_stkn = self.curr_in_crd1 + 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 + else: + self.next_state = self.states.READY + else: + self.next_state = self.states.WAIT_ACC1 def update(self): self.update_done() self.update_ready() @@ -623,40 +668,42 @@ def update(self): # Begin state machine computation # READY State - # Accepts crd2 token + # Accepts crd1 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: + if len(self.in_crd1) > 0: + self.curr_in_crd1 = self.in_crd1.pop(0) + if is_nc_tkn(self.curr_in_crd1): + if len(self.in_crd0) > 0 and len(self.in_val) > 0: self.ACC1_body() else: - self.next_state = self.states.ACC1 - elif is_stkn(self.curr_crd2) and not self.get_writout(): + self.next_state = self.states.ACC0 + elif is_stkn(self.curr_in_crd1) and stkn_order(self.curr_in_crd1) > 0 and not self.get_writout(): # Set writeout to be true, move over storage, and clear it. - self.crd2_stkn = self.curr_crd2 + self.wr_stkn = self.curr_in_crd1 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): + elif is_stkn(self.curr_in_crd1) and stkn_order(self.curr_in_crd1) > 0: # Wait for previous writeout to be done self.next_state = self.states.WR - elif is_dtkn(self.curr_crd2): + elif is_dtkn(self.curr_in_crd1): 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) + assert False, "Cannot have a coordinate token of this type: " + str(self.curr_in_crd1) + elif self.curr_state == self.states.WAIT_ACC1: + self.check_crd1() # Handle accumulation into storage # Accepts crd1 token elif self.curr_state == self.states.ACC1: if len(self.in_crd1) > 0: - self.ACC1_body() + self.ACC1_body(True) else: self.next_state = self.states.ACC1 elif self.curr_state == self.states.ACC0: @@ -688,8 +735,8 @@ def update(self): 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 + assert self.wr_stkn is not None, "The current writeout stop token should not be None" + self.curr_crd1 = decrement_stkn(self.wr_stkn) else: curr_writeout_elem1 = self.writeout_storage1.pop(0) self.curr_crd1 = curr_writeout_elem1 @@ -700,10 +747,10 @@ def update(self): 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) + assert self.wr_stkn is not None, "The current writeout stop token should not be None" + self.curr_crd0 = self.wr_stkn - self.curr_val = increment_stkn(self.crd2_stkn) + self.curr_val = self.wr_stkn else: curr_writeout_elem0 = self.writeout_storage0.pop(0) self.curr_crd0 = curr_writeout_elem0[0] @@ -741,11 +788,11 @@ def set_in_crd1(self, crd, parent=None): if self.backpressure_en: 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_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): if val != '' and val is not None: diff --git a/sam/sim/test/primitives/test_spacc.py b/sam/sim/test/primitives/test_spacc.py index 57ad0898..39baf17d 100644 --- a/sam/sim/test/primitives/test_spacc.py +++ b/sam/sim/test/primitives/test_spacc.py @@ -11,18 +11,18 @@ from sam.sim.test.test import TIMEOUT, gen_n_comp_arrs, gen_val_arr, get_point_list, \ convert_point_tuple, convert_ndarr_point_tuple, convert_point_tuple_ndarr, check_point_tuple, remove_zeros -arrs_dict1 = {'ocrd_in': [0, 2, 'S0', 2, 'S1', 'D'], - 'icrd_in': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 0, 2, 3, 'S2', 'D'], - 'val_in': [50, 5, 10, 'S0', 40, 4, 8, 'S1', -40, 33, 36, 'S2', 'D'], - 'icrd_gold': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], - 'val_gold': [90, 9, 18, 'S0', -40, 33, 36, 'S1', 'D']} +arrs_dict1 = { # 'ocrd_in': [0, 2, 'S0', 2, 'S1', 'D'], + 'icrd_in': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 0, 2, 3, 'S2', 'D'], + 'val_in': [50, 5, 10, 'S0', 40, 4, 8, 'S1', -40, 33, 36, 'S2', 'D'], + 'icrd_gold': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 'D'], + 'val_gold': [90, 9, 18, 'S0', -40, 33, 36, 'S1', 'D']} # New sparse accumulator @pytest.mark.parametrize("arrs", [arrs_dict1]) def test_spacc1new_direct(arrs, debug_sim): icrd = copy.deepcopy(arrs['icrd_in']) - ocrd = copy.deepcopy(arrs['ocrd_in']) + # ocrd = copy.deepcopy(arrs['ocrd_in']) val = copy.deepcopy(arrs['val_in']) gold_icrd = copy.deepcopy(arrs['icrd_gold']) @@ -37,8 +37,8 @@ def test_spacc1new_direct(arrs, debug_sim): while not done and time < TIMEOUT: if len(icrd) > 0: sa.set_in_crd0(icrd.pop(0)) - if len(ocrd) > 0: - sa.set_in_crd1(ocrd.pop(0)) + # if len(ocrd) > 0: + # sa.set_in_crd1(ocrd.pop(0)) if len(val) > 0: sa.set_val(val.pop(0)) @@ -107,7 +107,7 @@ def test_spacc1new_rand(dim, debug_sim, max_val=1000, fill=0): if random.random() < 0.2: out_val_B.append("") - sa.set_in_crd1(out_rdscan_B1.pop(0)) + # sa.set_in_crd1(out_rdscan_B1.pop(0)) sa.set_in_crd0(out_rdscan_B2.pop(0)) sa.set_val(out_val_B.pop(0)) vals_X.set_input(sa.out_val()) @@ -154,7 +154,7 @@ def test_spacc1new_rand(dim, debug_sim, max_val=1000, fill=0): assert (check_point_tuple(out_tup, gold_tup)) -arrs_dict1 = {'crd2_in': [0, 1, 'S0', 'D'], +arrs_dict1 = { # 'crd2_in': [0, 1, 'S0', 'D'], 'crd1_in': [0, 2, 'S0', 2, 'S1', 'D'], 'crd0_in': [0, 2, 3, 'S0', 0, 2, 3, 'S1', 0, 2, 3, 'S2', 'D'], 'val_in': [50, 5, 10, 'S0', 40, 4, 8, 'S1', -40, 33, 36, 'S2', 'D'], @@ -163,7 +163,7 @@ def test_spacc1new_rand(dim, debug_sim, max_val=1000, fill=0): 'val_gold': [50, 5, 10, 'S0', 0, 37, 44, 'S1', 'D']} # [[0, 1], [0, 4], [0, 2, 3, 4, 5]] [[0], [0, 1, 2, 3], [0, 2, 3, 1, 3]] [-60, 85, 314, 241, -887] -arrs_dict2 = {'crd2_in': [0, 'S0', 'D'], +arrs_dict2 = { # 'crd2_in': [0, 'S0', 'D'], 'crd1_in': [0, 1, 2, 3, 'S1', 'D'], 'crd0_in': [0, 2, 'S0', 3, 'S0', 1, 'S0', 3, 'S2', 'D'], 'val_in': [-60, 85, 'S0', 314, 'S0', 241, 'S0', -887, 'S2', 'D'], @@ -172,7 +172,7 @@ def test_spacc1new_rand(dim, debug_sim, max_val=1000, fill=0): 'val_gold': [-60, 85, 'S0', 314, 'S0', 241, 'S0', -887, 'S1', 'D']} # [[0, 1], [0, 3], [0, 4, 6, 8]] [[1], [0, 1, 2], [0, 1, 2, 3, 1, 3, 0, 2]] [637, 210, -847, 358, 162, 687, 95, -91] -arrs_dict3 = {'crd2_in': [1, 'S0', 'D'], +arrs_dict3 = { # 'crd2_in': [1, 'S0', 'D'], 'crd1_in': [0, 1, 2, 'S1', 'D'], 'crd0_in': [0, 1, 2, 3, 'S0', 1, 3, 'S0', 0, 2, 'S2', 'D'], 'val_in': [637, 210, -847, 358, 'S0', 162, 687, 'S0', 95, -91, 'S2', 'D'], @@ -184,7 +184,7 @@ def test_spacc1new_rand(dim, debug_sim, max_val=1000, fill=0): # New sparse accumulator @pytest.mark.parametrize("arrs", [arrs_dict1, arrs_dict2, arrs_dict3]) def test_spacc2new_stream_direct(arrs, debug_sim): - crd2 = copy.deepcopy(arrs['crd2_in']) + # crd2 = copy.deepcopy(arrs['crd2_in']) crd1 = copy.deepcopy(arrs['crd1_in']) crd0 = copy.deepcopy(arrs['crd0_in']) val = copy.deepcopy(arrs['val_in']) @@ -201,8 +201,8 @@ def test_spacc2new_stream_direct(arrs, debug_sim): out_crd0 = [] out_val = [] while not done and time < TIMEOUT: - if len(crd2) > 0: - sa.set_in_crd2(crd2.pop(0)) + # if len(crd2) > 0: + # sa.set_in_crd2(crd2.pop(0)) if len(crd1) > 0: sa.set_in_crd1(crd1.pop(0)) if len(crd0) > 0: @@ -238,22 +238,108 @@ def test_spacc2new_stream_direct(arrs, debug_sim): # Segs: [[0, 11], [0, 8, 18, 25, 31, 36, 44, 50, 61, 68, 78, 86], [0, 10, 18, 26, 35, 45, 53, 61, 69, 76, 84, 93, 99, 107, 114, 124, 134, 145, 154, 160, 168, 176, 188, 198, 208, 214, 223, 232, 242, 251, 261, 271, 280, 288, 294, 301, 308, 315, 323, 328, 339, 348, 357, 367, 378, 385, 391, 399, 408, 417, 425, 435, 440, 446, 453, 463, 467, 477, 489, 494, 502, 508, 516, 523, 531, 537, 541, 550, 557, 569, 576, 586, 593, 600, 608, 614, 623, 631, 640, 647, 656, 665, 675, 681, 689, 699, 703]] # Crds: [[0, 2, 3, 4, 5, 8, 9, 10, 11, 14, 15], [0, 1, 2, 5, 6, 7, 9, 14, 3, 4, 5, 6, 7, 8, 10, 11, 13, 15, 4, 7, 8, 11, 12, 13, 14, 1, 5, 8, 10, 13, 14, 0, 3, 4, 7, 15, 1, 7, 9, 10, 12, 13, 14, 15, 1, 4, 8, 10, 11, 12, 1, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 0, 2, 4, 5, 8, 14, 15, 0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 1, 2, 3, 6, 7, 8, 10, 12], [1, 2, 3, 8, 9, 10, 11, 13, 14, 15, 2, 3, 5, 8, 9, 10, 11, 14, 1, 4, 6, 7, 9, 10, 11, 12, 0, 1, 4, 9, 10, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 0, 1, 2, 6, 7, 9, 10, 15, 0, 1, 2, 8, 9, 12, 13, 15, 0, 1, 4, 6, 8, 9, 13, 15, 2, 4, 5, 7, 10, 13, 15, 2, 5, 7, 10, 11, 13, 14, 15, 0, 1, 2, 3, 9, 10, 12, 13, 15, 0, 5, 6, 11, 13, 15, 0, 5, 6, 9, 11, 12, 13, 14, 2, 3, 5, 6, 8, 10, 15, 0, 1, 2, 3, 5, 9, 11, 12, 13, 15, 1, 2, 4, 6, 8, 9, 10, 11, 14, 15, 0, 2, 3, 4, 7, 8, 9, 10, 11, 13, 15, 0, 3, 4, 5, 9, 10, 12, 14, 15, 1, 5, 6, 9, 12, 14, 0, 1, 4, 7, 10, 11, 12, 14, 1, 2, 6, 8, 10, 12, 13, 15, 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 14, 15, 0, 2, 3, 4, 6, 9, 10, 11, 13, 15, 1, 3, 4, 5, 6, 7, 8, 11, 13, 14, 0, 3, 6, 8, 11, 12, 0, 2, 5, 6, 7, 8, 9, 14, 15, 1, 3, 6, 9, 11, 12, 13, 14, 15, 0, 3, 4, 5, 6, 9, 10, 12, 13, 14, 2, 4, 5, 6, 7, 9, 10, 13, 15, 0, 4, 6, 7, 8, 9, 12, 13, 14, 15, 0, 1, 2, 3, 5, 7, 8, 10, 13, 15, 2, 3, 4, 5, 6, 10, 12, 13, 15, 2, 3, 6, 7, 8, 12, 14, 15, 0, 4, 5, 10, 12, 15, 4, 5, 6, 7, 9, 10, 15, 0, 1, 5, 8, 10, 12, 14, 1, 5, 8, 9, 11, 12, 15, 0, 1, 4, 5, 6, 7, 8, 12, 0, 2, 5, 9, 11, 0, 2, 3, 4, 5, 6, 9, 10, 12, 13, 14, 1, 2, 4, 7, 10, 12, 13, 14, 15, 0, 3, 4, 5, 7, 11, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 9, 12, 15, 0, 1, 3, 4, 7, 8, 15, 1, 4, 6, 9, 10, 11, 0, 2, 3, 4, 7, 9, 12, 14, 0, 2, 4, 5, 8, 10, 12, 14, 15, 0, 3, 4, 6, 9, 10, 11, 12, 13, 1, 2, 6, 8, 9, 10, 12, 13, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 1, 2, 3, 10, 15, 2, 5, 7, 9, 13, 15, 0, 2, 5, 6, 10, 11, 13, 0, 3, 4, 5, 6, 7, 10, 13, 14, 15, 2, 8, 10, 15, 0, 1, 2, 4, 6, 9, 10, 11, 12, 15, 0, 1, 2, 3, 5, 6, 7, 9, 10, 13, 14, 15, 0, 1, 7, 11, 12, 1, 2, 3, 4, 9, 11, 12, 14, 0, 2, 5, 6, 8, 10, 1, 3, 5, 7, 9, 12, 13, 14, 2, 4, 5, 7, 9, 11, 14, 0, 4, 5, 6, 7, 8, 11, 14, 0, 3, 4, 5, 7, 12, 5, 9, 12, 13, 0, 3, 4, 6, 7, 8, 9, 11, 13, 2, 3, 5, 6, 7, 9, 14, 0, 1, 2, 3, 5, 6, 7, 8, 9, 12, 13, 15, 2, 5, 6, 8, 12, 13, 15, 0, 2, 4, 5, 6, 7, 8, 12, 14, 15, 1, 2, 3, 5, 9, 12, 15, 0, 1, 5, 8, 12, 13, 14, 1, 3, 6, 8, 9, 11, 12, 13, 3, 4, 5, 9, 11, 13, 1, 2, 4, 6, 7, 8, 9, 12, 15, 1, 4, 5, 7, 12, 13, 14, 15, 0, 2, 3, 5, 7, 8, 9, 11, 12, 3, 6, 7, 9, 11, 13, 15, 1, 2, 3, 6, 8, 9, 11, 13, 14, 0, 2, 3, 4, 5, 7, 8, 11, 14, 0, 1, 2, 4, 5, 9, 12, 13, 14, 15, 5, 7, 11, 12, 13, 15, 0, 2, 3, 4, 7, 8, 10, 13, 1, 2, 3, 4, 5, 6, 7, 9, 12, 13, 4, 8, 11, 14]] # Vals: [-275, 130, -863, 147, 180, 534, 563, 41, -124, -359, -481, -40, 158, 413, -110, 421, -441, 978, 443, 295, 743, 955, -57, 765, -901, -143, -471, -476, -820, -405, 7, -413, 566, 477, -92, -791, -672, -733, 958, -773, 265, -42, -895, 139, -262, 337, 602, -5, 424, 478, 489, 614, -744, 854, -604, 393, -693, 769, 605, -357, -970, -304, -87, 363, -919, 166, 179, -313, 151, -734, 992, -158, -603, -453, 260, -731, -135, -945, 885, -649, -917, -371, -483, -874, -761, 918, -704, 401, 985, 5, 902, -946, -218, -504, 857, 943, 273, 622, 692, 364, 61, -109, 540, -733, -826, 43, -303, 185, -938, -269, -951, -117, -279, -388, -57, 288, 562, -34, 562, -856, 481, 307, -584, 153, 600, -527, 50, 374, 887, 705, 742, -482, -52, -280, 14, -582, 387, -910, -11, -823, -974, 765, 569, -106, 754, 27, -678, 297, -248, 642, -383, -984, 119, 276, -635, -843, 558, -833, 831, 910, 148, -222, -878, -881, 576, -3, -772, 660, 718, -266, 24, -96, 125, -94, 144, -490, 14, 713, 765, -527, -925, 109, 542, -567, -368, 951, -610, -594, -482, -740, 995, 993, -487, -178, -51, 91, -517, 102, 68, -291, -558, 201, -465, -673, 112, 484, 327, 931, -988, -786, -942, 935, 961, -891, -143, 255, -823, 628, 775, -290, -163, -183, 354, -342, -465, 137, 902, 870, -466, -324, 207, 896, -308, 637, 717, -537, 395, -746, 351, 523, -960, -458, 505, 869, -580, -502, 664, 171, 320, 877, 497, 461, -226, 130, -743, 98, 826, 427, 92, -223, -822, 952, -565, 920, 569, 539, 372, -248, 592, 405, -832, -692, 673, 22, 978, -327, 935, -10, 191, -558, -430, -874, -147, -133, -850, 268, 380, 828, -519, 414, 289, -11, -407, -844, -54, 660, -9, 537, -25, -614, -985, 238, -52, -437, 763, 792, 212, -892, -527, 658, 944, 416, -910, -82, -262, 634, -380, 672, -667, 662, 331, 928, -893, 141, 715, -590, -762, 124, -116, -736, -652, 812, -919, 952, 5, -801, -189, 315, 778, 762, 269, -594, -215, 492, 650, 938, 203, 443, 546, -976, 404, 917, 377, 729, 194, -759, -12, -253, 395, -152, -142, 136, -768, 525, -20, -761, 171, -793, 174, 845, 377, 354, -424, 941, 213, -732, 836, 191, 314, -275, -390, 520, 595, -466, -639, -888, 775, 672, 299, 762, 735, -329, -566, 137, 423, -774, -548, 307, -297, -332, -497, -633, -242, -297, -648, 239, -828, -2, -577, -643, 236, 849, -792, -513, -521, -470, -212, 148, -897, 497, 627, 834, -720, -914, 245, 550, 99, -410, 550, 537, 784, -716, 646, 213, -387, 914, 976, 388, 534, -543, 588, -453, -54, -819, -792, 885, 89, -834, 832, -427, -906, -630, -79, -354, 605, 651, -96, 261, 96, -726, -832, 550, -327, 519, -561, -928, -47, -352, 186, -103, 3, -563, 247, -416, 289, -54, 815, -216, 859, 909, -540, 38, -759, 541, -132, -466, 685, -354, -746, -956, -826, 431, -343, 67, 823, -732, 946, -611, 592, 541, 198, -28, 518, 433, 348, 264, -620, 935, 700, 594, -144, -14, 15, -101, -730, 706, -200, 713, 951, 348, -62, -935, 419, 511, -358, -734, 561, -329, 685, 948, 554, 256, -615, -666, -473, 295, -688, 508, 917, -269, 363, 484, 775, 807, 408, -519, 388, -205, 443, -959, 344, 107, -600, -403, 254, 778, 518, 320, 415, -976, 339, -36, -723, -980, 846, 66, -405, 956, 932, 747, -111, -804, -495, -821, 538, 366, -866, 614, -349, -145, 426, 256, 662, 533, -549, -381, -668, 531, 954, -343, -645, 823, -611, -382, -846, 474, 503, -673, 841, -549, 263, 966, 632, 574, 719, -219, -396, -98, 374, 700, -567, 84, 951, 294, -260, 334, -532, -828, -867, -399, 575, -9, 342, 913, 736, -882, -993, 232, -627, -655, -451, 606, 571, 289, -690, -161, 864, 608, -695, 806, -620, -844, 719, 353, 834, -915, 371, -151, -239, 355, 379, 405, -48, -565, 592, -531, -850, -800, 424, -384, -663, -982, 225, 294, -557, -97, 883, -674, -42, -436, -100, 548, 466, -54, -337, -222, -11, 112, 893, 372, -950, 418, 80, -24, 391, 659, 741, 25, -321, 367, -488, 106, 361, 41, 301, 650, -672, 105, -715, 401, -989, 804, 858] -arrs_dict1 = { "segs": [[0, 11], [0, 8, 18, 25, 31, 36, 44, 50, 61, 68, 78, 86], [0, 10, 18, 26, 35, 45, 53, 61, 69, 76, - 84, 93, 99, 107, 114, 124, 134, 145, - 154, 160, 168, 176, 188, 198, 208, - 214, 223, 232, 242, 251, 261, 271, - 280, 288, 294, 301, 308, 315, 323, 328, 339, 348, 357, 367, 378, 385, 391, 399, 408, 417, 425, 435, 440, 446, 453, 463, 467, 477, 489, 494, 502, 508, 516, 523, 531, 537, 541, 550, 557, 569, 576, 586, 593, 600, 608, 614, 623, 631, 640, 647, 656, 665, 675, 681, 689, 699, 703]], - "crds": [[0, 2, 3, 4, 5, 8, 9, 10, 11, 14, 15], [0, 1, 2, 5, 6, 7, 9, 14, 3, 4, 5, 6, 7, 8, 10, 11, 13, - 15, 4, 7, 8, 11, 12, 13, 14, 1, 5, 8, 10, 13, 14, 0, 3, 4, 7, 15, 1, 7, 9, 10, 12, 13, 14, 15, 1, 4, 8, 10, 11, 12, 1, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 0, 2, 4, 5, 8, 14, 15, 0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 1, 2, 3, 6, 7, 8, 10, 12], [1, 2, 3, 8, 9, 10, 11, 13, 14, 15, 2, 3, 5, 8, 9, 10, 11, 14, 1, 4, 6, 7, 9, 10, 11, 12, 0, 1, 4, 9, 10, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 9, 13, 0, 1, 2, 6, 7, 9, 10, 15, 0, 1, 2, 8, 9, 12, 13, 15, 0, 1, 4, 6, 8, 9, 13, 15, 2, 4, 5, 7, 10, 13, 15, 2, 5, 7, 10, 11, 13, 14, 15, 0, 1, 2, 3, 9, 10, 12, 13, 15, 0, 5, 6, 11, 13, 15, 0, 5, 6, 9, 11, 12, 13, 14, 2, 3, 5, 6, 8, 10, 15, 0, 1, 2, 3, 5, 9, 11, 12, 13, 15, 1, 2, 4, 6, 8, 9, 10, 11, 14, 15, 0, 2, 3, 4, 7, 8, 9, 10, 11, 13, 15, 0, 3, 4, 5, 9, 10, 12, 14, 15, 1, 5, 6, 9, 12, 14, 0, 1, 4, 7, 10, 11, 12, 14, 1, 2, 6, 8, 10, 12, 13, 15, 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 14, 15, 0, 2, 3, 4, 6, 9, 10, 11, 13, 15, 1, 3, 4, 5, 6, 7, 8, 11, 13, 14, 0, 3, 6, 8, 11, 12, 0, 2, 5, 6, 7, 8, 9, 14, 15, 1, 3, 6, 9, 11, 12, 13, 14, 15, 0, 3, 4, 5, 6, 9, 10, 12, 13, 14, 2, 4, 5, 6, 7, 9, 10, 13, 15, 0, 4, 6, 7, 8, 9, 12, 13, 14, 15, 0, 1, 2, 3, 5, 7, 8, 10, 13, 15, 2, 3, 4, 5, 6, 10, 12, 13, 15, 2, 3, 6, 7, 8, 12, 14, 15, 0, 4, 5, 10, 12, 15, 4, 5, 6, 7, 9, 10, 15, 0, 1, 5, 8, 10, 12, 14, 1, 5, 8, 9, 11, 12, 15, 0, 1, 4, 5, 6, 7, 8, 12, 0, 2, 5, 9, 11, 0, 2, 3, 4, 5, 6, 9, 10, 12, 13, 14, 1, 2, 4, 7, 10, 12, 13, 14, 15, 0, 3, 4, 5, 7, 11, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 9, 12, 15, 0, 1, 3, 4, 7, 8, 15, 1, 4, 6, 9, 10, 11, 0, 2, 3, 4, 7, 9, 12, 14, 0, 2, 4, 5, 8, 10, 12, 14, 15, 0, 3, 4, 6, 9, 10, 11, 12, 13, 1, 2, 6, 8, 9, 10, 12, 13, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 1, 2, 3, 10, 15, 2, 5, 7, 9, 13, 15, 0, 2, 5, 6, 10, 11, 13, 0, 3, 4, 5, 6, 7, 10, 13, 14, 15, 2, 8, 10, 15, 0, 1, 2, 4, 6, 9, 10, 11, 12, 15, 0, 1, 2, 3, 5, 6, 7, 9, 10, 13, 14, 15, 0, 1, 7, 11, 12, 1, 2, 3, 4, 9, 11, 12, 14, 0, 2, 5, 6, 8, 10, 1, 3, 5, 7, 9, 12, 13, 14, 2, 4, 5, 7, 9, 11, 14, 0, 4, 5, 6, 7, 8, 11, 14, 0, 3, 4, 5, 7, 12, 5, 9, 12, 13, 0, 3, 4, 6, 7, 8, 9, 11, 13, 2, 3, 5, 6, 7, 9, 14, 0, 1, 2, 3, 5, 6, 7, 8, 9, 12, 13, 15, 2, 5, 6, 8, 12, 13, 15, 0, 2, 4, 5, 6, 7, 8, 12, 14, 15, 1, 2, 3, 5, 9, 12, 15, 0, 1, 5, 8, 12, 13, 14, 1, 3, 6, 8, 9, 11, 12, 13, 3, 4, 5, 9, 11, 13, 1, 2, 4, 6, 7, 8, 9, 12, 15, 1, 4, 5, 7, 12, 13, 14, 15, 0, 2, 3, 5, 7, 8, 9, 11, 12, 3, 6, 7, 9, 11, 13, 15, 1, 2, 3, 6, 8, 9, 11, 13, 14, 0, 2, 3, 4, 5, 7, 8, 11, 14, 0, 1, 2, 4, 5, 9, 12, 13, 14, 15, 5, 7, 11, 12, 13, 15, 0, 2, 3, 4, 7, 8, 10, 13, 1, 2, 3, 4, 5, 6, 7, 9, 12, 13, 4, 8, 11, 14]], - "vals": [-275, 130, -863, 147, 180, 534, 563, 41, -124, -359, -481, -40, 158, 413, -110, 421, -441, 978, - 443, 295, 743, 955, -57, 765, -901, -143, -471, -476, -820, -405, 7, -413, 566, 477, -92, -791, -672, -733, 958, -773, 265, -42, -895, 139, -262, 337, 602, -5, 424, 478, 489, 614, -744, 854, -604, 393, -693, 769, 605, -357, -970, -304, -87, 363, -919, 166, 179, -313, 151, -734, 992, -158, -603, -453, 260, -731, -135, -945, 885, -649, -917, -371, -483, -874, -761, 918, -704, 401, 985, 5, 902, -946, -218, -504, 857, 943, 273, 622, 692, 364, 61, -109, 540, -733, -826, 43, -303, 185, -938, -269, -951, -117, -279, -388, -57, 288, 562, -34, 562, -856, 481, 307, -584, 153, 600, -527, 50, 374, 887, 705, 742, -482, -52, -280, 14, -582, 387, -910, -11, -823, -974, 765, 569, -106, 754, 27, -678, 297, -248, 642, -383, -984, 119, 276, -635, -843, 558, -833, 831, 910, 148, -222, -878, -881, 576, -3, -772, 660, 718, -266, 24, -96, 125, -94, 144, -490, 14, 713, 765, -527, -925, 109, 542, -567, -368, 951, -610, -594, -482, -740, 995, 993, -487, -178, -51, 91, -517, 102, 68, -291, -558, 201, -465, -673, 112, 484, 327, 931, -988, -786, -942, 935, 961, -891, -143, 255, -823, 628, 775, -290, -163, -183, 354, -342, -465, 137, 902, 870, -466, -324, 207, 896, -308, 637, 717, -537, 395, -746, 351, 523, -960, -458, 505, 869, -580, -502, 664, 171, 320, 877, 497, 461, -226, 130, -743, 98, 826, 427, 92, -223, -822, 952, -565, 920, 569, 539, 372, -248, 592, 405, -832, -692, 673, 22, 978, -327, 935, -10, 191, -558, -430, -874, -147, -133, -850, 268, 380, 828, -519, 414, 289, -11, -407, -844, -54, 660, -9, 537, -25, -614, -985, 238, -52, -437, 763, 792, 212, -892, -527, 658, 944, 416, -910, -82, -262, 634, -380, 672, -667, 662, 331, 928, -893, 141, 715, -590, -762, 124, -116, -736, -652, 812, -919, 952, 5, -801, -189, 315, 778, 762, 269, -594, -215, 492, 650, 938, 203, 443, 546, -976, 404, 917, 377, 729, 194, -759, -12, -253, 395, -152, -142, 136, -768, 525, -20, -761, 171, -793, 174, 845, 377, 354, -424, 941, 213, -732, 836, 191, 314, -275, -390, 520, 595, -466, -639, -888, 775, 672, 299, 762, 735, -329, -566, 137, 423, -774, -548, 307, -297, -332, -497, -633, -242, -297, -648, 239, -828, -2, -577, -643, 236, 849, -792, -513, -521, -470, -212, 148, -897, 497, 627, 834, -720, -914, 245, 550, 99, -410, 550, 537, 784, -716, 646, 213, -387, 914, 976, 388, 534, -543, 588, -453, -54, -819, -792, 885, 89, -834, 832, -427, -906, -630, -79, -354, 605, 651, -96, 261, 96, -726, -832, 550, -327, 519, -561, -928, -47, -352, 186, -103, 3, -563, 247, -416, 289, -54, 815, -216, 859, 909, -540, 38, -759, 541, -132, -466, 685, -354, -746, -956, -826, 431, -343, 67, 823, -732, 946, -611, 592, 541, 198, -28, 518, 433, 348, 264, -620, 935, 700, 594, -144, -14, 15, -101, -730, 706, -200, 713, 951, 348, -62, -935, 419, 511, -358, -734, 561, -329, 685, 948, 554, 256, -615, -666, -473, 295, -688, 508, 917, -269, 363, 484, 775, 807, 408, -519, 388, -205, 443, -959, 344, 107, -600, -403, 254, 778, 518, 320, 415, -976, 339, -36, -723, -980, 846, 66, -405, 956, 932, 747, -111, -804, -495, -821, 538, 366, -866, 614, -349, -145, 426, 256, 662, 533, -549, -381, -668, 531, 954, -343, -645, 823, -611, -382, -846, 474, 503, -673, 841, -549, 263, 966, 632, 574, 719, -219, -396, -98, 374, 700, -567, 84, 951, 294, -260, 334, -532, -828, -867, -399, 575, -9, 342, 913, 736, -882, -993, 232, -627, -655, -451, 606, 571, 289, -690, -161, 864, 608, -695, 806, -620, -844, 719, 353, 834, -915, 371, -151, -239, 355, 379, 405, -48, -565, 592, -531, -850, -800, 424, -384, -663, -982, 225, 294, -557, -97, 883, -674, -42, -436, -100, 548, 466, -54, -337, -222, -11, 112, 893, 372, -950, 418, 80, -24, 391, 659, 741, 25, -321, 367, -488, 106, 361, 41, 301, 650, -672, 105, -715, 401, -989, 804, 858], +arrs_dict1 = {"segs": [[0, 11], [0, 8, 18, 25, 31, 36, 44, 50, 61, 68, 78, 86], [0, 10, 18, 26, 35, 45, 53, 61, 69, 76, + 84, 93, 99, 107, 114, 124, 134, 145, + 154, 160, 168, 176, 188, 198, 208, + 214, 223, 232, 242, 251, 261, 271, + 280, 288, 294, 301, 308, 315, 323, 328, + 339, 348, 357, 367, 378, 385, 391, 399, + 408, 417, 425, 435, 440, 446, 453, 463, + 467, 477, 489, 494, 502, 508, 516, 523, + 531, 537, 541, 550, 557, 569, 576, 586, + 593, 600, 608, 614, 623, 631, 640, 647, + 656, 665, 675, 681, 689, 699, 703]], + "crds": [[0, 2, 3, 4, 5, 8, 9, 10, 11, 14, 15], + [0, 1, 2, 5, 6, 7, 9, 14, + 3, 4, 5, 6, 7, 8, 10, 11, 13, 15, + 4, 7, 8, 11, 12, 13, 14, + 1, 5, 8, 10, 13, 14, + 0, 3, 4, 7, 15, + 1, 7, 9, 10, 12, 13, 14, 15, 1, 4, 8, 10, 11, + 12, 1, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 0, 2, 4, 5, 8, + 14, 15, 0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 1, 2, 3, 6, 7, + 8, 10, 12], + [1, 2, 3, 8, 9, 10, 11, 13, 14, 15, + 2, 3, 5, 8, 9, 10, 11, 14, + 1, 4, 6, 7, 9, 10, 11, 12, 0, + 1, 4, 9, 10, 12, 13, 14, 15, 0, 1, + 2, 3, 4, 5, 6, 7, 9, 13, 0, 1, 2, 6, 7, 9, 10, 15, 0, 1, 2, 8, + 9, 12, 13, 15, 0, 1, 4, 6, 8, 9, 13, 15, 2, 4, 5, 7, 10, 13, 15, 2, 5, 7, 10, 11, 13, 14, 15, 0, + 1, 2, 3, 9, 10, 12, 13, 15, 0, 5, 6, 11, 13, 15, 0, 5, 6, 9, 11, 12, 13, 14, 2, 3, 5, 6, 8, 10, + 15, 0, 1, 2, 3, 5, 9, 11, 12, 13, 15, 1, 2, 4, 6, 8, 9, 10, 11, 14, 15, 0, 2, 3, 4, 7, 8, 9, 10, + 11, 13, 15, 0, 3, 4, 5, 9, 10, 12, 14, 15, 1, 5, 6, 9, 12, 14, 0, 1, 4, 7, 10, 11, 12, 14, 1, 2, + 6, 8, 10, 12, 13, 15, 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 14, 15, 0, 2, 3, 4, 6, 9, 10, 11, 13, 15, + 1, 3, 4, 5, 6, 7, 8, 11, 13, 14, 0, 3, 6, 8, 11, 12, 0, 2, 5, 6, 7, 8, 9, 14, 15, 1, 3, 6, 9, + 11, 12, 13, 14, 15, 0, 3, 4, 5, 6, 9, 10, 12, 13, 14, 2, 4, 5, 6, 7, 9, 10, 13, 15, 0, 4, 6, 7, + 8, 9, 12, 13, 14, 15, 0, 1, 2, 3, 5, 7, 8, 10, 13, 15, 2, 3, 4, 5, 6, 10, 12, 13, 15, 2, 3, 6, + 7, 8, 12, 14, 15, 0, 4, 5, 10, 12, 15, 4, 5, 6, 7, 9, 10, 15, 0, 1, 5, 8, 10, 12, 14, 1, 5, 8, + 9, 11, 12, 15, 0, 1, 4, 5, 6, 7, 8, 12, 0, 2, 5, 9, 11, 0, 2, 3, 4, 5, 6, 9, 10, 12, 13, 14, 1, + 2, 4, 7, 10, 12, 13, 14, 15, 0, 3, 4, 5, 7, 11, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 0, + 1, 2, 3, 4, 5, 6, 7, 9, 12, 15, 0, 1, 3, 4, 7, 8, 15, 1, 4, 6, 9, 10, 11, 0, 2, 3, 4, 7, 9, 12, + 14, 0, 2, 4, 5, 8, 10, 12, 14, 15, 0, 3, 4, 6, 9, 10, 11, 12, 13, 1, 2, 6, 8, 9, 10, 12, 13, 4, + 5, 6, 8, 9, 10, 11, 12, 14, 15, 1, 2, 3, 10, 15, 2, 5, 7, 9, 13, 15, 0, 2, 5, 6, 10, 11, 13, 0, + 3, 4, 5, 6, 7, 10, 13, 14, 15, 2, 8, 10, 15, 0, 1, 2, 4, 6, 9, 10, 11, 12, 15, 0, 1, 2, 3, 5, 6, + 7, 9, 10, 13, 14, 15, 0, 1, 7, 11, 12, 1, 2, 3, 4, 9, 11, 12, 14, 0, 2, 5, 6, 8, 10, 1, 3, 5, 7, + 9, 12, 13, 14, 2, 4, 5, 7, 9, 11, 14, 0, 4, 5, 6, 7, 8, 11, 14, 0, 3, 4, 5, 7, 12, 5, 9, 12, 13, + 0, 3, 4, 6, 7, 8, 9, 11, 13, 2, 3, 5, 6, 7, 9, 14, 0, 1, 2, 3, 5, 6, 7, 8, 9, 12, 13, 15, 2, 5, + 6, 8, 12, 13, 15, 0, 2, 4, 5, 6, 7, 8, 12, 14, 15, 1, 2, 3, 5, 9, 12, 15, 0, 1, 5, 8, 12, 13, + 14, 1, 3, 6, 8, 9, 11, 12, 13, 3, 4, 5, 9, 11, 13, 1, 2, 4, 6, 7, 8, 9, 12, 15, 1, 4, 5, 7, 12, + 13, 14, 15, 0, 2, 3, 5, 7, 8, 9, 11, 12, 3, 6, 7, 9, 11, 13, 15, 1, 2, 3, 6, 8, 9, 11, 13, 14, + 0, 2, 3, 4, 5, 7, 8, 11, 14, 0, 1, 2, 4, 5, 9, 12, 13, 14, 15, 5, 7, 11, 12, 13, 15, 0, 2, 3, 4, + 7, 8, 10, 13, 1, 2, 3, 4, 5, 6, 7, 9, 12, 13, 4, 8, 11, 14]], + "vals": [-275, 130, -863, 147, 180, 534, 563, 41, -124, -359, + -481, -40, 158, 413, -110, 421, -441, 978, + 443, 295, 743, 955, -57, 765, -901, -143, -471, -476, -820, -405, 7, -413, 566, 477, -92, -791, + -672, -733, 958, -773, 265, -42, -895, 139, -262, 337, 602, -5, 424, 478, 489, 614, -744, 854, + -604, 393, -693, 769, 605, -357, -970, -304, -87, 363, -919, 166, 179, -313, 151, -734, 992, + -158, -603, -453, 260, -731, -135, -945, 885, -649, -917, -371, -483, -874, -761, 918, -704, 401, + 985, 5, 902, -946, -218, -504, 857, 943, 273, 622, 692, 364, 61, -109, 540, -733, -826, 43, -303, + 185, -938, -269, -951, -117, -279, -388, -57, 288, 562, -34, 562, -856, 481, 307, -584, 153, 600, + -527, 50, 374, 887, 705, 742, -482, -52, -280, 14, -582, 387, -910, -11, -823, -974, 765, 569, + -106, 754, 27, -678, 297, -248, 642, -383, -984, 119, 276, -635, -843, 558, -833, 831, 910, 148, + -222, -878, -881, 576, -3, -772, 660, 718, -266, 24, -96, 125, -94, 144, -490, 14, 713, 765, + -527, -925, 109, 542, -567, -368, 951, -610, -594, -482, -740, 995, 993, -487, -178, -51, 91, + -517, 102, 68, -291, -558, 201, -465, -673, 112, 484, 327, 931, -988, -786, -942, 935, 961, -891, + -143, 255, -823, 628, 775, -290, -163, -183, 354, -342, -465, 137, 902, 870, -466, -324, 207, + 896, -308, 637, 717, -537, 395, -746, 351, 523, -960, -458, 505, 869, -580, -502, 664, 171, 320, + 877, 497, 461, -226, 130, -743, 98, 826, 427, 92, -223, -822, 952, -565, 920, 569, 539, 372, + -248, 592, 405, -832, -692, 673, 22, 978, -327, 935, -10, 191, -558, -430, -874, -147, -133, + -850, 268, 380, 828, -519, 414, 289, -11, -407, -844, -54, 660, -9, 537, -25, -614, -985, 238, + -52, -437, 763, 792, 212, -892, -527, 658, 944, 416, -910, -82, -262, 634, -380, 672, -667, 662, + 331, 928, -893, 141, 715, -590, -762, 124, -116, -736, -652, 812, -919, 952, 5, -801, -189, 315, + 778, 762, 269, -594, -215, 492, 650, 938, 203, 443, 546, -976, 404, 917, 377, 729, 194, -759, + -12, -253, 395, -152, -142, 136, -768, 525, -20, -761, 171, -793, 174, 845, 377, 354, -424, 941, + 213, -732, 836, 191, 314, -275, -390, 520, 595, -466, -639, -888, 775, 672, 299, 762, 735, -329, + -566, 137, 423, -774, -548, 307, -297, -332, -497, -633, -242, -297, -648, 239, -828, -2, -577, + -643, 236, 849, -792, -513, -521, -470, -212, 148, -897, 497, 627, 834, -720, -914, 245, 550, 99, + -410, 550, 537, 784, -716, 646, 213, -387, 914, 976, 388, 534, -543, 588, -453, -54, -819, -792, + 885, 89, -834, 832, -427, -906, -630, -79, -354, 605, 651, -96, 261, 96, -726, -832, 550, -327, + 519, -561, -928, -47, -352, 186, -103, 3, -563, 247, -416, 289, -54, 815, -216, 859, 909, -540, + 38, -759, 541, -132, -466, 685, -354, -746, -956, -826, 431, -343, 67, 823, -732, 946, -611, 592, + 541, 198, -28, 518, 433, 348, 264, -620, 935, 700, 594, -144, -14, 15, -101, -730, 706, -200, + 713, 951, 348, -62, -935, 419, 511, -358, -734, 561, -329, 685, 948, 554, 256, -615, -666, -473, + 295, -688, 508, 917, -269, 363, 484, 775, 807, 408, -519, 388, -205, 443, -959, 344, 107, -600, + -403, 254, 778, 518, 320, 415, -976, 339, -36, -723, -980, 846, 66, -405, 956, 932, 747, -111, + -804, -495, -821, 538, 366, -866, 614, -349, -145, 426, 256, 662, 533, -549, -381, -668, 531, + 954, -343, -645, 823, -611, -382, -846, 474, 503, -673, 841, -549, 263, 966, 632, 574, 719, -219, + -396, -98, 374, 700, -567, 84, 951, 294, -260, 334, -532, -828, -867, -399, 575, -9, 342, 913, + 736, -882, -993, 232, -627, -655, -451, 606, 571, 289, -690, -161, 864, 608, -695, 806, -620, + -844, 719, 353, 834, -915, 371, -151, -239, 355, 379, 405, -48, -565, 592, -531, -850, -800, 424, + -384, -663, -982, 225, 294, -557, -97, 883, -674, -42, -436, -100, 548, 466, -54, -337, -222, + -11, 112, 893, 372, -950, 418, 80, -24, 391, 659, 741, 25, -321, 367, -488, 106, 361, 41, 301, + 650, -672, 105, -715, 401, -989, 804, 858], "dim": 16 -} + } + +arrs_dict2 = {"segs": [[0, 2], [0, 2, 4], [0, 3, 6, 9, 12]], + "crds": [[0, 1], [0, 1, 3, 4], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]], + "vals": [100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111], + "dim": 16} # Segs: [[0, 8], [0, 10, 21, 30, 40, 52, 61, 68, 76], [0, 8, 18, 28, 35, 48, 57, 62, 73, 83, 94, 99, 111, 121, 129, 137, 144, 152, 159, 166, 176, 184, 191, 197, 204, 214, 221, 233, 240, 246, 255, 264, 268, 275, 282, 291, 300, 308, 313, 320, 328, 338, 346, 356, 365, 376, 383, 391, 401, 407, 419, 426, 430, 439, 448, 457, 462, 468, 473, 480, 486, 494, 501, 508, 517, 526, 533, 543, 551, 559, 567, 577, 586, 592, 598, 608, 614]] # Crds: [[0, 1, 2, 4, 7, 10, 12, 13], [0, 2, 5, 7, 8, 10, 11, 13, 14, 15, 0, 1, 2, 3, 4, 5, 7, 10, 12, 14, 15, 0, 1, 2, 3, 4, 5, 9, 14, 15, 0, 1, 2, 3, 6, 8, 9, 10, 11, 14, 0, 1, 2, 3, 4, 6, 7, 8, 11, 12, 14, 15, 0, 2, 3, 4, 7, 8, 11, 13, 14, 5, 6, 9, 10, 11, 14, 15, 2, 3, 5, 6, 10, 11, 12, 15], [0, 1, 3, 5, 7, 8, 11, 12, 0, 1, 2, 3, 6, 7, 9, 11, 14, 15, 0, 1, 2, 4, 6, 7, 11, 13, 14, 15, 2, 3, 4, 6, 10, 14, 15, 0, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 1, 2, 4, 5, 6, 9, 10, 11, 15, 4, 5, 6, 8, 13, 0, 1, 2, 4, 6, 9, 10, 11, 13, 14, 15, 1, 4, 6, 7, 8, 9, 12, 13, 14, 15, 1, 3, 4, 6, 8, 9, 10, 11, 12, 13, 15, 4, 6, 8, 9, 15, 0, 1, 2, 5, 6, 7, 8, 11, 12, 13, 14, 15, 1, 2, 5, 6, 8, 9, 11, 12, 13, 15, 3, 5, 6, 9, 10, 11, 12, 15, 0, 1, 2, 6, 7, 12, 14, 15, 2, 6, 7, 9, 10, 11, 15, 0, 4, 6, 7, 8, 10, 11, 13, 0, 5, 6, 8, 13, 14, 15, 3, 7, 9, 10, 11, 13, 15, 0, 3, 4, 6, 7, 8, 9, 11, 14, 15, 1, 2, 3, 4, 5, 9, 10, 14, 2, 3, 5, 8, 10, 12, 15, 0, 2, 8, 9, 11, 12, 0, 1, 3, 4, 10, 13, 15, 0, 1, 4, 5, 6, 7, 8, 11, 12, 13, 1, 2, 3, 6, 10, 11, 13, 1, 2, 3, 4, 5, 8, 9, 11, 12, 13, 14, 15, 2, 4, 5, 6, 9, 13, 14, 0, 5, 6, 9, 11, 15, 0, 1, 2, 4, 6, 8, 12, 13, 15, 0, 1, 2, 4, 5, 6, 8, 9, 11, 4, 6, 8, 13, 1, 2, 3, 6, 10, 13, 15, 0, 1, 2, 8, 13, 14, 15, 0, 2, 3, 4, 7, 9, 10, 12, 15, 0, 2, 4, 5, 7, 8, 10, 11, 15, 2, 4, 5, 7, 8, 10, 12, 15, 2, 8, 10, 13, 14, 0, 6, 9, 10, 12, 14, 15, 3, 4, 6, 7, 9, 10, 11, 14, 0, 3, 6, 7, 10, 11, 12, 13, 14, 15, 0, 2, 7, 8, 9, 11, 14, 15, 0, 1, 3, 5, 7, 8, 9, 12, 14, 15, 0, 3, 4, 5, 7, 8, 10, 11, 12, 0, 1, 2, 5, 6, 8, 9, 10, 11, 12, 14, 1, 2, 4, 5, 7, 8, 15, 1, 5, 8, 9, 10, 12, 13, 14, 0, 1, 2, 7, 8, 9, 10, 11, 12, 15, 0, 1, 6, 7, 10, 15, 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 13, 15, 0, 1, 2, 3, 9, 11, 14, 0, 4, 8, 10, 0, 1, 2, 4, 8, 11, 12, 14, 15, 0, 1, 2, 5, 8, 9, 12, 13, 14, 1, 3, 4, 5, 8, 9, 11, 12, 15, 1, 5, 10, 11, 14, 0, 5, 6, 9, 14, 15, 1, 2, 13, 14, 15, 4, 5, 6, 7, 8, 11, 12, 0, 2, 6, 10, 12, 15, 1, 3, 5, 6, 8, 9, 12, 15, 0, 3, 4, 7, 11, 12, 15, 1, 2, 4, 7, 9, 10, 11, 0, 3, 5, 7, 8, 9, 11, 12, 14, 0, 2, 3, 5, 6, 10, 11, 13, 14, 0, 2, 4, 7, 10, 12, 13, 0, 3, 4, 5, 6, 7, 9, 10, 13, 14, 1, 4, 6, 7, 8, 9, 11, 15, 0, 1, 2, 4, 7, 8, 13, 14, 0, 2, 4, 5, 10, 11, 12, 13, 0, 2, 3, 6, 8, 9, 10, 11, 12, 15, 0, 1, 2, 4, 5, 6, 9, 11, 12, 0, 1, 5, 13, 14, 15, 0, 2, 3, 7, 11, 12, 0, 1, 2, 3, 6, 8, 9, 10, 12, 13, 1, 5, 7, 9, 14, 15]] # Vals: [-250, 363, -637, 105, -364, -874, 861, -490, -222, 321, -667, -537, -151, -746, -36, 71, -32, -998, 438, 604, 436, -383, 27, -107, -106, -109, -707, 226, 953, 707, -210, -155, 377, -780, 102, -186, -798, 171, -467, 982, -397, 387, -395, 456, -864, -836, -271, -27, -99, -159, -815, 885, -662, -14, -951, 462, 617, -442, 433, 395, 82, 819, -938, 877, -57, -349, -993, -812, -541, -269, -284, -60, -242, -744, 62, -829, -976, 403, 621, -87, -548, 731, -643, -137, -264, -38, 613, 643, 882, 410, -124, -688, 86, 365, 632, 657, -955, 279, -80, -409, 357, 181, 527, 537, 340, -683, -434, 203, 68, 480, 452, 981, 890, 700, -559, 792, 241, -528, 275, 45, 211, -765, 511, 931, -560, -897, 836, -816, -881, 44, 726, -858, -322, 847, 247, -336, -276, -835, 732, 961, -30, -570, 924, -605, -399, 80, 952, 747, 546, 25, -743, -687, -981, 454, 579, -634, 924, 156, -708, 716, -447, -234, -370, -746, -864, -87, 633, -176, 839, -868, -26, 32, 896, 593, 298, -668, -225, -213, 516, -300, -98, 417, -549, 168, 978, -902, -79, -192, 789, 488, 188, 814, -1000, 205, 186, 494, -319, 613, -460, -645, -723, -692, -333, -953, -211, -291, -957, 797, 607, -30, 611, 931, -725, -809, 583, 672, 262, 620, 711, 774, 563, 157, 395, 60, -456, -130, 268, 999, 705, 989, -812, 223, 501, 920, -495, -371, 816, 671, -183, 205, 910, -553, 465, -316, 712, 410, -804, -744, -369, -665, 619, -617, 256, -823, 640, 75, -758, -710, -697, -659, 990, -858, -235, 476, -236, 248, -47, 259, 271, -163, -889, -216, 692, -418, -14, 614, -829, -670, 381, -385, 928, -797, 670, 246, 395, 474, 917, -717, 700, -214, 162, -517, 389, 437, 278, -45, 219, -805, 617, 533, -772, 255, -25, 978, -46, -873, 262, -978, -13, -289, 812, -988, 626, -442, 223, -272, 933, 180, 182, 35, -176, -770, -86, 547, 590, -551, -627, -463, -361, 267, 859, -147, 979, -437, 735, -112, -348, -395, -745, -328, -974, -602, -820, -4, -600, -273, 458, 634, 591, 975, -116, -432, -689, -916, 523, -227, -203, 719, 527, 992, -475, -103, 28, -229, 680, -62, -83, -105, -394, 606, 15, 919, -546, 803, 5, -52, -817, 647, -436, 858, -51, -987, -923, 835, -2, 88, 873, -444, -509, -185, -988, -951, -863, -523, -969, -373, -817, -629, -999, 467, 148, -168, 512, -446, -386, -582, 810, 326, 505, -707, -339, 155, -27, -104, -603, -207, -740, -138, -107, 998, -252, 160, 689, -585, -140, 396, 453, 42, -325, 782, -638, 973, -343, 942, 968, 979, 879, -745, 245, 917, -532, -278, -194, 912, -299, 248, -849, -565, -100, -779, -658, -110, -257, -39, -766, 885, -704, -4, 533, 77, -27, -704, 497, -934, 299, 528, 149, 583, -697, -107, -48, 299, 759, 377, -798, -825, -893, -299, -178, 183, 39, -367, -862, -660, -157, -93, -89, 36, 563, 547, 392, -977, -864, 376, 4, 19, -416, 485, -637, 156, -20, -714, 116, -383, -182, -771, -851, -973, -282, 716, -243, -899, -267, 792, 668, -921, 10, -612, 96, 354, -23, 415, 233, 934, -193, 619, 5, 281, -660, -299, 50, 105, -469, -141, 347, 440, 758, -620, 620, -460, 673, 16, -905, -468, 565, -416, -3, -248, 57, 870, -895, 890, 847, -127, -490, -881, -901, 455, 235, 260, -703, -255, -541, -238, -215, 886, 429, -350, -357, 828, 646, 448, -860, -894, -934, -314, 922, -640, 506, 117, 525, -606, -701, -582, 356, 172, -218, -780, -540, 272, -768, 397, -41, -795, -619, -568, 268, 691, 669, -452, -851, -218, -432, -767, -300, 178, 769, -191, -272, 349, 573, -291, 429, -236] -@pytest.mark.parametrize("arrs", [arrs_dict1]) +@pytest.mark.parametrize("arrs", [arrs_dict1, arrs_dict2]) def test_spacc2new_tensor_direct(arrs, debug_sim, fill=0): in_mat_crds1 = arrs["crds"] in_mat_segs1 = arrs["segs"] @@ -306,7 +392,7 @@ def test_spacc2new_tensor_direct(arrs, debug_sim, fill=0): if random.random() < 0.2: out_val_B.append("") - sa.set_in_crd2(out_rdscan_B1.pop(0)) + # sa.set_in_crd2(out_rdscan_B1.pop(0)) sa.set_in_crd1(out_rdscan_B2.pop(0)) sa.set_in_crd0(out_rdscan_B3.pop(0)) sa.set_val(out_val_B.pop(0)) @@ -365,6 +451,7 @@ def test_spacc2new_tensor_direct(arrs, debug_sim, fill=0): "\nVals: " + str(in_mat_vals1)) assert check_point_tuple(out_tup, gold_tup) + @pytest.mark.parametrize("dim", [2 ** x for x in range(1, 5, 1)]) def test_spacc2new_tensor_rand(dim, debug_sim, max_val=1000, fill=0): in_mat_crds1, in_mat_segs1 = gen_n_comp_arrs(3, dim) @@ -416,7 +503,7 @@ def test_spacc2new_tensor_rand(dim, debug_sim, max_val=1000, fill=0): if random.random() < 0.2: out_val_B.append("") - sa.set_in_crd2(out_rdscan_B1.pop(0)) + # sa.set_in_crd2(out_rdscan_B1.pop(0)) sa.set_in_crd1(out_rdscan_B2.pop(0)) sa.set_in_crd0(out_rdscan_B3.pop(0)) sa.set_val(out_val_B.pop(0))