From 80176cd79093ad7b649bdf3faf3ffb2dff1690b5 Mon Sep 17 00:00:00 2001
From: Elizabeth <hashim.sharif91@gmail.com>
Date: Tue, 8 Oct 2019 16:33:27 -0500
Subject: [PATCH] Implemented table outputter function

---
 .../build_pldi/table_generator.py             | 95 ++++++++++++++-----
 1 file changed, 70 insertions(+), 25 deletions(-)

diff --git a/llvm/projects/hpvm-tensor-rt/build_pldi/table_generator.py b/llvm/projects/hpvm-tensor-rt/build_pldi/table_generator.py
index e944de7d37..71f88fed3e 100644
--- a/llvm/projects/hpvm-tensor-rt/build_pldi/table_generator.py
+++ b/llvm/projects/hpvm-tensor-rt/build_pldi/table_generator.py
@@ -79,13 +79,16 @@ class TableGenerator:
         return op_name[ : underscore_ind], op_name[underscore_ind + 1 : ]
 
     def generate_table(self):
-        table = self.__build_nested_default_dict()
+        self.__table = self.__build_nested_default_dict()
+        self.__build_internal_table()
+        self.__output_table()
 
+
+    def __build_internal_table(self):
         for results_file_name in os.listdir(self.__results_dir_name):
             print(results_file_name, self.__network_name)
-            # Ignore if it's the output file or if it's not a results file
-            if results_file_name == table_filename or \
-                    not results_file_name.startswith(self.__network_name):
+            # Ignore if it's not a results file
+            if results_file_name.startswith(self.__network_name):
                 continue
 
             approx_type = self.__get_approximation_type(results_file_name)
@@ -103,39 +106,81 @@ class TableGenerator:
                     orig_op_name, conversion_type = self.__get_original_operation_name(op_name)
                     print("f2h/h2f", orig_op_name, conversion_type)
                     # Error bc original op name should ALWAYS be in the table
-                    if orig_op_name not in table: 
+                    if orig_op_name not in self.__table: 
                         print("ERROR: Conversion found but original %s is not in the table" % orig_op_name)
                         exit(1)
-                    table[orig_op_name][conversion_type]["time"] = total_time
-                    table[orig_op_name][conversion_type]["energy"] = total_energy 
+                    self.__table[orig_op_name][conversion_type]["time"] = total_time
+                    self.__table[orig_op_name][conversion_type]["energy"] = total_energy 
 
                 # Create a new row in the dictionary
                 else:
-                    table[op_name][approx_type]["time"] = total_time
-                    table[op_name][approx_type]["energy"] = total_energy
+                    self.__table[op_name][approx_type]["time"] = total_time
+                    self.__table[op_name][approx_type]["energy"] = total_energy
 
             results_file.close()
-        # Then output everything
 
+    def __output_table(self):
         # Copy ops file to results directory to use as empty table 
         table_filename = "%s_tensors.txt" % self.__network_name
         table_file_path = os.path.join(self.__results_dir_name, table_filename)
         # TODO un hard code this 
-        soc_operations_file_name = os.path.join("/home/nvidia/soc_simulator", \
-                        "%s_cifar10" % self.__network_name, "%s_ops.txt" % self.__network_name)
-        #shutil.copyfile(soc_operations_file_name, table_file_path)
-
-		# Output in the order of everything in the file
-		# Conv1,1 = leave the same
-		# Next line: Conv1 --> find it  
-		# don't need to copy the file over --> can use the original file as a reference
-		soc_operations_file = open(soc_operations_file_name, "r")
-		table_file = open(table_filename, "w")
-		for line in soc_operations_file:
-			if line.startswith("#"): # TODO variable
-				table_file.write(line) # Copy to table file 
-				# Then write the new header for 
-				
+        soc_operations_file_name = os.path.join("/home/nvidia/soc_simulator", "%s_cifar10" % self.__network_name, "%s_ops.txt" % self.__network_name)
+
+		# Don't need to copy the file over --> can use the original file as a reference
+        soc_operations_file = open(soc_operations_file_name, "r")
+        table_file = open(table_filename, "w")
+
+        # Read header line to get layer name and # operations in layer
+        # Get ops in each layer using the dict
+        # TODO possible for operations in the same layer to not have the same # of cols? 
+        # Need to store a list of all 2nd level dict keys we go through!
+        # at the very end --> then generate the header and write everything in 
+
+        curr_line = soc_operations_file.readline().strip()
+
+        while curr_line:
+            # First line is always the layers line (#layer_name,num_ops)
+            layer_name, num_ops = self.__parse_layer_info_line(curr_line)
+            
+            # Get each operation in the layer
+            ops_in_layer = []
+            header = []
+            
+            for op_in_layer_count in range(num_ops): 
+                # Each line consists of operation name  
+                curr_line = soc_operations_file.readline().strip()
+
+                curr_op = [curr_line] # Join into a string later
+                operation_data = self.__table[curr_line]
+                # Iterate through time/energy data for each approx type
+                for approx_type in operation_data:
+                    curr_op.append(operation_data[approx_type]["time"]) 
+                    curr_op.append(operation_data[approx_type]["time"])
+
+                    # CRITICAL ASSUMPTION: All ops within a layer have the same # cols
+                    # Only fill out the header once for the layer
+                    if op_in_layer_count == 0:
+                        header.append(approx_type)    
+
+                ops_in_layer.append(' '.join(curr_op))
+            # Getting all operation rows and then writing everything because
+            # calls to write() are slow (memory vs time tradeoff)
+            print("%s" % ' '.join(header))
+            print("%s" % '\n'.join(ops_in_layer))
+            table_file.write("%s\n" % ' '.join(header))
+            table_file.write("%s\n" % '\n'.join(ops_in_layer))
+
+            curr_line = soc_operations_file.readline().strip()
+
+    def __parse_layer_info_line(self, layer_info_line): #layer_name,num_ops
+        comma_ind = layer_info_line.find(",")
+        return layer_info_line[layer_info_line.find("#") : comma_ind], int(layer_info_line[comma_ind + 1 : ])
+
+    def __generate_header(self, table):
+        # <approx type time/energy> <conversion type at very end> 
+        # should the header be per tensor op or per layer?
+        # Try doing this per layer first
+        pass            
 
 binary_dir_name = "/home/nvidia/Gitlab/hpvm/llvm/projects/hpvm-tensor-rt/build_pldi/mobilenet"
 num_iters = 1 
-- 
GitLab