diff --git a/calyx-opt/src/passes/profiler_instrumentation.rs b/calyx-opt/src/passes/profiler_instrumentation.rs index d377a8fc0..c6254cd23 100644 --- a/calyx-opt/src/passes/profiler_instrumentation.rs +++ b/calyx-opt/src/passes/profiler_instrumentation.rs @@ -40,6 +40,7 @@ impl Visitor for ProfilerInstrumentation { sigs: &ir::LibrarySignatures, _comps: &[ir::Component], ) -> VisResult { + let delimiter = "___"; let mut acc = 0; let comp_name = comp.name; let mut structural_enable_map: HashMap< @@ -142,7 +143,10 @@ impl Visitor for ProfilerInstrumentation { // FIXME: probably best to remove the code clone by extracting this out into a different function? for group_name in group_names.into_iter() { // store group and component name (differentiate between groups of the same name under different components) - let name = format!("{}__{}_group_probe", group_name, comp_name); + let name = format!( + "{}{}{}_group_probe", + group_name, delimiter, comp_name + ); let probe_cell = builder.add_primitive(name, "std_wire", &[1]); let probe_asgn: ir::Assignment = builder .build_assignment( @@ -162,8 +166,12 @@ impl Visitor for ProfilerInstrumentation { for (group, primitive_invs) in primitive_invoke_map.iter() { for (primitive_cell_name, guard) in primitive_invs.iter() { let probe_cell_name = format!( - "{}__{}__{}_primitive_probe", - primitive_cell_name, group, comp_name + "{}{}{}{}{}_primitive_probe", + primitive_cell_name, + delimiter, + group, + delimiter, + comp_name ); let probe_cell = builder.add_primitive( probe_cell_name, @@ -190,8 +198,12 @@ impl Visitor for ProfilerInstrumentation { { for (parent_group, guard) in parent_groups.iter() { let probe_cell_name = format!( - "{}__{}__{}_se_probe", - invoked_group_name, parent_group, comp_name + "{}{}{}{}{}_se_probe", + invoked_group_name, + delimiter, + parent_group, + delimiter, + comp_name ); let probe_cell = builder.add_primitive( probe_cell_name, @@ -220,8 +232,12 @@ impl Visitor for ProfilerInstrumentation { for (invoker_group, invoked_cells) in cell_invoke_map.iter() { for invoked_cell in invoked_cells { let probe_cell_name = format!( - "{}__{}__{}_cell_probe", - invoked_cell, invoker_group, comp_name + "{}{}{}{}{}_cell_probe", + invoked_cell, + delimiter, + invoker_group, + delimiter, + comp_name ); let probe_cell = builder.add_primitive( probe_cell_name, diff --git a/fud2/scripts/profiler.rhai b/fud2/scripts/profiler.rhai index 41e1a6602..2e7c9c78b 100644 --- a/fud2/scripts/profiler.rhai +++ b/fud2/scripts/profiler.rhai @@ -23,11 +23,11 @@ fn profiling_setup(e) { // script to process vcd and produce folded representation of flame graph e.var_("parse-vcd-script", "$calyx-base/tools/profiler/profiler-process.py"); - e.rule("parse-vcd", "python3 $parse-vcd-script $in $cells dot-out $out flame-out"); + e.rule("parse-vcd", "python3 $parse-vcd-script $in $cells profiler-out $out"); e.config_var("flamegraph-script", "flamegraph.script"); - e.var_("flamegraph-utility-script", "$calyx-base/tools/profiler/convert-all-flames.sh"); - e.rule("produce-flame-graph", "bash $flamegraph-utility-script $flamegraph-script flame-out $in $out"); + e.var_("flamegraph-utility-script", "$calyx-base/tools/profiler/create-visuals.sh"); + e.rule("produce-flame-graph", "bash $flamegraph-utility-script $flamegraph-script profiler-out $in $out"); // Standalone Verilog testbench. copied from testbench e.rsrc("tb.sv"); diff --git a/tools/profiler/convert-all-flames.sh b/tools/profiler/create-visuals.sh similarity index 64% rename from tools/profiler/convert-all-flames.sh rename to tools/profiler/create-visuals.sh index 478d18215..279c7d0b9 100644 --- a/tools/profiler/convert-all-flames.sh +++ b/tools/profiler/create-visuals.sh @@ -1,18 +1,23 @@ # Utility script for fud2 to produce flame graphs from produced .folded files if [ $# -lt 4 ]; then - echo "USAGE: bash $0 FLAME_GRAPH_SCRIPT FOLDED_DIR REPR_IN" + echo "USAGE: bash $0 FLAME_GRAPH_SCRIPT DATA_DIR REPR_IN REPR_OUT" # the last two arguments are mainly for fud2's need for a defined input and output. exit fi SCRIPT_DIR=$( cd $( dirname $0 ) && pwd ) FLAME_GRAPH_SCRIPT=$1 -FOLDED_DIR=$2 +DATA_DIR=$2 REPR_IN=$3 REPR_OUT=$4 -for folded in $( ls ${FOLDED_DIR}/*.folded ); do +TREES_PDF_DIR=${DATA_DIR}-png +for f in $( ls ${DATA_DIR} | grep dot$ ); do + dot -Tpng ${DATA_DIR}/${f} > ${DATA_DIR}/${f}.png +done + +for folded in $( ls ${DATA_DIR}/*.folded ); do base_name=$( echo "${folded}" | rev | cut -d. -f2- | rev ) if [[ "${base_name}" == *"scaled"* ]]; then ${FLAME_GRAPH_SCRIPT} --countname="cycles" ${folded} > ${base_name}-original.svg diff --git a/tools/profiler/finagle-with-svg.py b/tools/profiler/finagle-with-svg.py index ad9aca18b..f3845a2cb 100644 --- a/tools/profiler/finagle-with-svg.py +++ b/tools/profiler/finagle-with-svg.py @@ -13,7 +13,7 @@ def main(svg_in): if line_split[i] == "cycles,": target_idx = i-1 new_number = int(line_split[target_idx].split("(")[1].replace(",", "")) / 1000 - print(" ".join(line_split[0:target_idx]) + " (" + str(new_number) + " " + " ".join(line_split[target_idx+1:])) + print(" ".join(line_split[0:target_idx]) + " (" + "{:,}".format(new_number) + " " + " ".join(line_split[target_idx+1:])) else: print(line.strip()) diff --git a/tools/profiler/new-profiler-approach.sh b/tools/profiler/new-profiler-approach.sh index c57301633..98f8d3978 100644 --- a/tools/profiler/new-profiler-approach.sh +++ b/tools/profiler/new-profiler-approach.sh @@ -21,8 +21,6 @@ FSM_JSON=${TMP_DIR}/fsm.json CELLS_JSON=${TMP_DIR}/cells.json GROUPS_JSON=${TMP_DIR}/groups.json OUT_DIR=${TMP_DIR}/out -FLAME_OUT_DIR=${TMP_DIR}/flame-out -rm -rf ${TREES_OUT_DIR} OUT_JSON=${TMP_DIR}/dump.json TIMELINE_VIEW_JSON=${TMP_DIR}/timeline.json FSM_TIMELINE_VIEW_JSON=${TMP_DIR}/fsm-timeline.json @@ -80,18 +78,16 @@ fi echo "[${SCRIPT_NAME}] Using FSM info and VCD file to obtain cycle level counts" ( set -o xtrace - time python3 ${SCRIPT_DIR}/new-profiler-process.py ${VCD_FILE} ${CELLS_JSON} ${OUT_DIR} ${OUT_DIR}/flame.folded ${FLAME_OUT_DIR} + time python3 ${SCRIPT_DIR}/profiler-process.py ${VCD_FILE} ${CELLS_JSON} ${OUT_DIR} ${OUT_DIR}/flame.folded set +o xtrace ) &> ${LOGS_DIR}/gol-process # Convert all dot files to png -TREES_PDF_DIR=${OUT_DIR}-png -mkdir -p ${TREES_PDF_DIR} for f in $( ls ${OUT_DIR} | grep dot$ ); do - dot -Tpng ${OUT_DIR}/${f} > ${TREES_PDF_DIR}/${f}.png + dot -Tpng ${OUT_DIR}/${f} > ${OUT_DIR}/${f}.png done -for folded in $( ls ${FLAME_OUT_DIR}/*.folded ); do +for folded in $( ls ${OUT_DIR}/*.folded ); do echo "Writing flame graph for ${folded}" base_name=$( echo ${folded} | rev | cut -d. -f2- | rev ) if [[ "${base_name}" == *"scaled"* ]]; then @@ -101,3 +97,5 @@ for folded in $( ls ${FLAME_OUT_DIR}/*.folded ); do ${FLAMEGRAPH_DIR}/flamegraph.pl --countname="cycles" ${folded} > ${base_name}.svg fi done + +${FLAMEGRAPH_DIR}/flamegraph.pl --countname="cycles" ${OUT_DIR}/flame.folded > ${OUT_DIR}/flame.svg diff --git a/tools/profiler/profiler-process.py b/tools/profiler/profiler-process.py index abb351dbf..a2437e8b0 100644 --- a/tools/profiler/profiler-process.py +++ b/tools/profiler/profiler-process.py @@ -5,7 +5,7 @@ import sys import vcdvcd -DELIMITER = "__" +DELIMITER = "___" INVISIBLE = "gray" TREE_PICTURE_LIMIT=300 SCALED_FLAME_MULTIPLIER=1000 @@ -516,7 +516,7 @@ def create_slideshow_dot(timeline_map, dot_out_dir, flame_out_file, flames_out_d f.write(f'\t{edge} [color="{INVISIBLE}"]; \n') f.write("}") -def main(vcd_filename, cells_json_file, dot_out_dir, flame_out, flames_out_dir): +def main(vcd_filename, cells_json_file, out_dir, flame_out): print(f"Start time: {datetime.now()}") main_component, cells_to_components = read_component_cell_names_json(cells_json_file) print(f"Start reading VCD: {datetime.now()}") @@ -536,20 +536,18 @@ def main(vcd_filename, cells_json_file, dot_out_dir, flame_out, flames_out_dir): tree_dict, path_dict = create_tree(converter.trace) path_to_edges, all_edges = create_edge_dict(path_dict) - create_aggregate_tree(converter.trace, dot_out_dir, tree_dict, path_dict) - create_tree_rankings(converter.trace, tree_dict, path_dict, path_to_edges, all_edges, dot_out_dir) - create_flame_groups(converter.trace, flame_out, flames_out_dir) + create_aggregate_tree(converter.trace, out_dir, tree_dict, path_dict) + create_tree_rankings(converter.trace, tree_dict, path_dict, path_to_edges, all_edges, out_dir) + create_flame_groups(converter.trace, flame_out, out_dir) print(f"End time: {datetime.now()}") - if __name__ == "__main__": - if len(sys.argv) > 5: + if len(sys.argv) > 4: vcd_filename = sys.argv[1] cells_json = sys.argv[2] - dot_out_dir = sys.argv[3] + out_dir = sys.argv[3] flame_out = sys.argv[4] - flames_out_dir = sys.argv[5] # tmp folder until I figure out how to get multiple outputs from fud2 - main(vcd_filename, cells_json, dot_out_dir, flame_out, flames_out_dir) + main(vcd_filename, cells_json, out_dir, flame_out) else: args_desc = [ "VCD_FILE",