From 2ec7bf2338950cec95eb529b2c69fd3116300f5c Mon Sep 17 00:00:00 2001 From: Das Date: Wed, 15 Sep 2021 12:15:30 +0200 Subject: [PATCH 1/9] python scipt for performance comparison --- script/compare.py | 233 ++++++++++++++++++++++++++++++++++++++++ script/requirements.txt | 2 + 2 files changed, 235 insertions(+) create mode 100644 script/compare.py create mode 100644 script/requirements.txt diff --git a/script/compare.py b/script/compare.py new file mode 100644 index 0000000000..09b4865790 --- /dev/null +++ b/script/compare.py @@ -0,0 +1,233 @@ +from itertools import chain, islice +import matplotlib.pyplot as plt +import argparse +import json +import re +from pathlib import Path +from mako.template import Template +from collections import defaultdict +import statistics +import matplotlib +matplotlib.use('Agg') + + +### Template to be published under an issue as a comment ### +ISSUE_TEMPLATE = r''' +**Performance Statistics** + +% for jit_engine_name, old_best_hash, best_hash_link, new_mips, message, best_mips, best_diff in zip_form: + +**Status for the ${jit_engine_name} Just-In-Time Engine** (for commit ${current_hash})**:** ${message} +**Current dhrystone MIPS for ${jit_engine_name} JIT** **:** ${new_mips} +**Previous best for ${jit_engine_name} JIT** (recorded in commit ${old_best_hash})**:** ${best_mips}, difference ${f'{best_diff:.2%}'} + +% endfor + +This comment was created automatically, please do not change! +''' +### Template to be published in Github wiki ### +WIKI_TEMPLATE = r''' +% for jit_engine_name, old_best_hash, best_hash_link, new_mips, message, best_mips, best_diff in zip_form: +**Status for the ${jit_engine_name} Just-In-Time Engine** (for commit ${current_hash_wiki})**:** +${message} +
+**Current dhrystone MIPS for ${jit_engine_name} JIT** **:** ${new_mips} +
+**Previous best for ${jit_engine_name} JIT** (recorded in commit ${best_hash_link})**:** ${best_mips}, difference ${f'{best_diff:.2%}'} +
+
+% endfor +**Graphical Analysis for the last ${commit_history} commits:** +
+
+[[performance_metrics.svg]] +''' +# Declaration of Global Variables: +KEY_TO_COMPARE = "mips" # the key from the input files to compare across engines +MAX_HISTORY = 50 # max amount of past data to keep +TOLERANCE = 0.2 + + +def calculating_performance_metrics(input_files, stats_file, issue_md, wiki_md, graph_file, current_hash, repo_url): + + # truncating hash value to first 8 characters + current_hash = current_hash[:8] + + ### Averaging out the MIPS for the given number of runs:### + + runs = defaultdict(list) + + # get engine name and run no from filename of input + # input files should have the format "run__.json" + for index, fname in enumerate(input_files): + filepath = Path(input_files[index]) + placeholder, engine, run_no = filepath.stem.split( + "_") + match = re.search("^\d+$", run_no) + try: + run_no = match.group(0) + placeholder == "run" + except: + print( + "Filename format not valid. Please follow the format: run__.json !") + run_no = int(run_no) + with open(filepath, 'r') as f: + in_dict = json.load(f) + runs[engine].append(in_dict[KEY_TO_COMPARE]) + + # Averaing out + runs_avg = runs_avg = {key: statistics.mean( + value) for key, value in runs.items()} + + ### Comparing the MIPS value of the current run with previous best MIPS: ### + + # instantiating dictionaries and lists + messages = dict() # to store messages of the performance metric of the corresponding engine + stats = defaultdict(dict) # store output results in a dict of dicts. + diffs = dict() # to store the difference between the current MIPS and the previous best + stats_file = Path(stats_file) # the path of the output file + + if not stats_file.exists(): # first time performance measured + # filling up the stats dictionary with values from the current run + for engine, value in runs_avg.items(): + stats[engine] = { + KEY_TO_COMPARE: [(value, current_hash)], + "best_" + KEY_TO_COMPARE: value, + "best_hash": current_hash, + "regressed_hash": None + } + + else: + with open(stats_file, 'r') as f: # load already existing previous statistics + stats = json.load(f) + + for engine, value in runs_avg.items(): + + if engine not in stats: # adding a new engine + stats[engine] = { + KEY_TO_COMPARE: [(value, current_hash)], + "best_" + KEY_TO_COMPARE: value, + "best_hash": current_hash, + "regressed_hash": None, + } + messages[engine] = "first entry" + + else: + # adding the MIPS from current run + stats[engine][KEY_TO_COMPARE].append((value, current_hash)) + stats[engine][KEY_TO_COMPARE] = stats[engine][KEY_TO_COMPARE][-MAX_HISTORY:] + + best = stats[engine]["best_" + KEY_TO_COMPARE] + + diff = value / best - 1 + diffs[engine] = diff + + # Comparison logic: + if value > best: + stats[engine][f"best_" + KEY_TO_COMPARE] = value + stats[engine][f"best_hash"] = current_hash[:8] + messages[engine] = f'🥇 New best performance!' + + elif diff < -TOLERANCE: + if stats[engine]["regressed_hash"] is None: + stats[engine]["regressed_hash"] = current_hash[:8] + messages[engine] = "Regression introduced" + else: + messages[engine] = "Regressed since commit " + \ + stats[engine]['regressed_hash'] + + else: + if stats[engine]["regressed_hash"] is not None: + stats[engine]["regressed_hash"] = None + messages[engine] = "Regression cleared" + else: + messages[engine] = "No significant performance change" + + # Template rendering for issue and Github Wiki: + issue_template = Template(text=ISSUE_TEMPLATE) + wiki_template = Template(text=WIKI_TEMPLATE) + templates = [issue_template, wiki_template] + + # Instantiating useful lists needed for template rendering: + output_files = [issue_md, wiki_md] + best_hash = [] + best_hash_link = [] + best_value_for_KEY_TO_COMPARE = [] + new_value_for_KEY_TO_COMPARE = [] + jit_engines = [] + message = messages.values() + best_difference = diffs.values() + current_hash_wiki = f"[{current_hash}](https://github.com/{repo_url}/commit/{current_hash})" + + for engine, nested_dict in stats.items(): + jit_engines.append(engine) + best_value_for_KEY_TO_COMPARE.append( + nested_dict["best_"+KEY_TO_COMPARE]) + best_value_for_KEY_TO_COMPARE = [round(num, 2) for num in best_value_for_KEY_TO_COMPARE] + new_value_for_KEY_TO_COMPARE.append(list(chain.from_iterable(islice(item, 0, 1) + for item in nested_dict[KEY_TO_COMPARE]))[-1]) + new_value_for_KEY_TO_COMPARE = [round(num, 2) for num in new_value_for_KEY_TO_COMPARE] + best_hash.append(nested_dict["best_hash"]) + best_hash_ = nested_dict["best_hash"] + best_hash_link.append( + f"[{best_hash_}](https://github.com/{repo_url}/commit/{best_hash_})") + + zip_form = zip(jit_engines, best_hash, best_hash_link, + new_value_for_KEY_TO_COMPARE, message, best_value_for_KEY_TO_COMPARE, best_difference) + zip_list = list(zip_form) + + # Graphical Analysis of Performance Metrics: + fig = plt.figure(figsize=(20, 10)) + + for engine in stats: + commit_history = list(chain.from_iterable(islice(item, 1, 2) + for item in stats[engine][KEY_TO_COMPARE])) + mips_value = list(chain.from_iterable(islice(item, 0, 1) + for item in stats[engine][KEY_TO_COMPARE])) + plt.plot(commit_history, mips_value, + label=f'{KEY_TO_COMPARE}_{engine}') + + plt.xticks(fontsize=15, rotation=45) + plt.yticks(fontsize=20) + plt.title( + f'MIPS values for the last {len(commit_history)} commit(s)', size=50) + plt.xlabel("Commit History", size=30) + plt.ylabel("MIPS", size=30) + plt.legend(loc='center left', bbox_to_anchor=(1, 0.5), prop={'size': 30}) + + # Save figure + fig.savefig(graph_file, bbox_inches='tight', pad_inches=0.5) + + # Save statistics file + with open(stats_file, 'w') as f: + json.dump(stats, f) + + # Render Templates + if repo_url: + + for index, fname in enumerate(output_files): + with open(fname, 'w') as fw: + fw.write(templates[index].render( + current_hash=current_hash, + current_hash_wiki=current_hash_wiki, + zip_form=zip_list, + commit_history=len(commit_history) + ) + ) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("input_files", nargs="+") + parser.add_argument('-o', help='arguments', + dest='stats_file', action='store') + parser.add_argument('-i', '--issue_md') + parser.add_argument('-w', '--wiki_md') + parser.add_argument('-gr', '--graph_file') + parser.add_argument('-g', '--current_hash') + parser.add_argument('-r', '--repo_url') + args = parser.parse_args() + + +calculating_performance_metrics(args.input_files, args.stats_file, args.issue_md, + args.wiki_md, args.graph_file, args.current_hash, args.repo_url) diff --git a/script/requirements.txt b/script/requirements.txt new file mode 100644 index 0000000000..15f21b0c32 --- /dev/null +++ b/script/requirements.txt @@ -0,0 +1,2 @@ +mako +matplotlib \ No newline at end of file From 58d0ef7341b59753b5b011dcc817b832588d58c2 Mon Sep 17 00:00:00 2001 From: Das Date: Wed, 15 Sep 2021 12:16:20 +0200 Subject: [PATCH 2/9] adding dhrystone benchmark --- examples/SW/riscv_dhry/CMakeLists.txt | 13 + examples/SW/riscv_dhry/README.md | 8 + examples/SW/riscv_dhry/dhry.h | 423 ++++++++++++++++++++++++++ examples/SW/riscv_dhry/dhry_1.c | 385 +++++++++++++++++++++++ examples/SW/riscv_dhry/dhry_2.c | 192 ++++++++++++ 5 files changed, 1021 insertions(+) create mode 100644 examples/SW/riscv_dhry/CMakeLists.txt create mode 100644 examples/SW/riscv_dhry/README.md create mode 100644 examples/SW/riscv_dhry/dhry.h create mode 100644 examples/SW/riscv_dhry/dhry_1.c create mode 100644 examples/SW/riscv_dhry/dhry_2.c diff --git a/examples/SW/riscv_dhry/CMakeLists.txt b/examples/SW/riscv_dhry/CMakeLists.txt new file mode 100644 index 0000000000..4ae27f42a8 --- /dev/null +++ b/examples/SW/riscv_dhry/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +SET(CMAKE_TOOLCHAIN_FILE + "../riscv/cmake/pulpino_tumeda/toolchain.cmake" +) +project(etiss_examples) +include(../riscv/cmake/PulpinoTarget.cmake) + +ADD_DEFINITIONS(-DPULPINO_NO_GPIO) + +ADD_DEFINITIONS(-DTIME) +ADD_DEFINITIONS(-DNO_INIT) + +ADD_EXECUTABLE_PULPINO(riscv_example dhry_1.c dhry_2.c) diff --git a/examples/SW/riscv_dhry/README.md b/examples/SW/riscv_dhry/README.md new file mode 100644 index 0000000000..274222378e --- /dev/null +++ b/examples/SW/riscv_dhry/README.md @@ -0,0 +1,8 @@ +# RISC-V Software Compilation for C++ + +This file contains ctr0, linker script, Makefile (originally from pulpino +project) for simple RISC-V software compilation using C++. For instructions and more details, see `../riscv/README.md`. + +### RISC-V target software + +The target software runs some basic C++ specific tests. Binary code and elf file will be located at `./build`. diff --git a/examples/SW/riscv_dhry/dhry.h b/examples/SW/riscv_dhry/dhry.h new file mode 100644 index 0000000000..b556ecc431 --- /dev/null +++ b/examples/SW/riscv_dhry/dhry.h @@ -0,0 +1,423 @@ +/* + **************************************************************************** + * + * "DHRYSTONE" Benchmark Program + * ----------------------------- + * + * Version: C, Version 2.1 + * + * File: dhry.h (part 1 of 3) + * + * Date: May 25, 1988 + * + * Author: Reinhold P. Weicker + * Siemens AG, AUT E 51 + * Postfach 3220 + * 8520 Erlangen + * Germany (West) + * Phone: [+49]-9131-7-20330 + * (8-17 Central European Time) + * Usenet: ..!mcsun!unido!estevax!weicker + * + * Original Version (in Ada) published in + * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984), + * pp. 1013 - 1030, together with the statistics + * on which the distribution of statements etc. is based. + * + * In this C version, the following C library functions are used: + * - strcpy, strcmp (inside the measurement loop) + * - printf, scanf (outside the measurement loop) + * In addition, Berkeley UNIX system calls "times ()" or "time ()" + * are used for execution time measurement. For measurements + * on other systems, these calls have to be changed. + * + * Collection of Results: + * Reinhold Weicker (address see above) and + * + * Rick Richardson + * PC Research. Inc. + * 94 Apple Orchard Drive + * Tinton Falls, NJ 07724 + * Phone: (201) 389-8963 (9-17 EST) + * Usenet: ...!uunet!pcrat!rick + * + * Please send results to Rick Richardson and/or Reinhold Weicker. + * Complete information should be given on hardware and software used. + * Hardware information includes: Machine type, CPU, type and size + * of caches; for microprocessors: clock frequency, memory speed + * (number of wait states). + * Software information includes: Compiler (and runtime library) + * manufacturer and version, compilation switches, OS version. + * The Operating System version may give an indication about the + * compiler; Dhrystone itself performs no OS calls in the measurement loop. + * + * The complete output generated by the program should be mailed + * such that at least some checks for correctness can be made. + * + *************************************************************************** + * + * History: This version C/2.1 has been made for two reasons: + * + * 1) There is an obvious need for a common C version of + * Dhrystone, since C is at present the most popular system + * programming language for the class of processors + * (microcomputers, minicomputers) where Dhrystone is used most. + * There should be, as far as possible, only one C version of + * Dhrystone such that results can be compared without + * restrictions. In the past, the C versions distributed + * by Rick Richardson (Version 1.1) and by Reinhold Weicker + * had small (though not significant) differences. + * + * 2) As far as it is possible without changes to the Dhrystone + * statistics, optimizing compilers should be prevented from + * removing significant statements. + * + * This C version has been developed in cooperation with + * Rick Richardson (Tinton Falls, NJ), it incorporates many + * ideas from the "Version 1.1" distributed previously by + * him over the UNIX network Usenet. + * I also thank Chaim Benedelac (National Semiconductor), + * David Ditzel (SUN), Earl Killian and John Mashey (MIPS), + * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) + * for their help with comments on earlier versions of the + * benchmark. + * + * Changes: In the initialization part, this version follows mostly + * Rick Richardson's version distributed via Usenet, not the + * version distributed earlier via floppy disk by Reinhold Weicker. + * As a concession to older compilers, names have been made + * unique within the first 8 characters. + * Inside the measurement loop, this version follows the + * version previously distributed by Reinhold Weicker. + * + * At several places in the benchmark, code has been added, + * but within the measurement loop only in branches that + * are not executed. The intention is that optimizing compilers + * should be prevented from moving code out of the measurement + * loop, or from removing code altogether. Since the statements + * that are executed within the measurement loop have NOT been + * changed, the numbers defining the "Dhrystone distribution" + * (distribution of statements, operand types and locality) + * still hold. Except for sophisticated optimizing compilers, + * execution times for this version should be the same as + * for previous versions. + * + * Since it has proven difficult to subtract the time for the + * measurement loop overhead in a correct way, the loop check + * has been made a part of the benchmark. This does have + * an impact - though a very minor one - on the distribution + * statistics which have been updated for this version. + * + * All changes within the measurement loop are described + * and discussed in the companion paper "Rationale for + * Dhrystone version 2". + * + * Because of the self-imposed limitation that the order and + * distribution of the executed statements should not be + * changed, there are still cases where optimizing compilers + * may not generate code for some statements. To a certain + * degree, this is unavoidable for small synthetic benchmarks. + * Users of the benchmark are advised to check code listings + * whether code is generated for all statements of Dhrystone. + * + * Version 2.1 is identical to version 2.0 distributed via + * the UNIX network Usenet in March 1988 except that it corrects + * some minor deficiencies that were found by users of version 2.0. + * The only change within the measurement loop is that a + * non-executed "else" part was added to the "if" statement in + * Func_3, and a non-executed "else" part removed from Proc_3. + * + *************************************************************************** + * + * Defines: The following "Defines" are possible: + * -DREG=register (default: Not defined) + * As an approximation to what an average C programmer + * might do, the "register" storage class is applied + * (if enabled by -DREG=register) + * - for local variables, if they are used (dynamically) + * five or more times + * - for parameters if they are used (dynamically) + * six or more times + * Note that an optimal "register" strategy is + * compiler-dependent, and that "register" declarations + * do not necessarily lead to faster execution. + * -DNOSTRUCTASSIGN (default: Not defined) + * Define if the C compiler does not support + * assignment of structures. + * -DNOENUMS (default: Not defined) + * Define if the C compiler does not support + * enumeration types. + * -DTIMES (default) + * -DTIME + * The "times" function of UNIX (returning process times) + * or the "time" function (returning wallclock time) + * is used for measurement. + * For single user machines, "time ()" is adequate. For + * multi-user machines where you cannot get single-user + * access, use the "times ()" function. If you have + * neither, use a stopwatch in the dead of night. + * "printf"s are provided marking the points "Start Timer" + * and "Stop Timer". DO NOT use the UNIX "time(1)" + * command, as this will measure the total time to + * run this program, which will (erroneously) include + * the time to allocate storage (malloc) and to perform + * the initialization. + * -DHZ=nnn + * In Berkeley UNIX, the function "times" returns process + * time in 1/HZ seconds, with HZ = 60 for most systems. + * CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY + * A VALUE. + * + *************************************************************************** + * + * Compilation model and measurement (IMPORTANT): + * + * This C version of Dhrystone consists of three files: + * - dhry.h (this file, containing global definitions and comments) + * - dhry_1.c (containing the code corresponding to Ada package Pack_1) + * - dhry_2.c (containing the code corresponding to Ada package Pack_2) + * + * The following "ground rules" apply for measurements: + * - Separate compilation + * - No procedure merging + * - Otherwise, compiler optimizations are allowed but should be indicated + * - Default results are those without register declarations + * See the companion paper "Rationale for Dhrystone Version 2" for a more + * detailed discussion of these ground rules. + * + * For 16-Bit processors (e.g. 80186, 80286), times for all compilation + * models ("small", "medium", "large" etc.) should be given if possible, + * together with a definition of these models for the compiler system used. + * + ************************************************************************** + * + * Dhrystone (C version) statistics: + * + * [Comment from the first distribution, updated for version 2. + * Note that because of language differences, the numbers are slightly + * different from the Ada version.] + * + * The following program contains statements of a high level programming + * language (here: C) in a distribution considered representative: + * + * assignments 52 (51.0 %) + * control statements 33 (32.4 %) + * procedure, function calls 17 (16.7 %) + * + * 103 statements are dynamically executed. The program is balanced with + * respect to the three aspects: + * + * - statement type + * - operand type + * - operand locality + * operand global, local, parameter, or constant. + * + * The combination of these three aspects is balanced only approximately. + * + * 1. Statement Type: + * ----------------- number + * + * V1 = V2 9 + * (incl. V1 = F(..) + * V = Constant 12 + * Assignment, 7 + * with array element + * Assignment, 6 + * with record component + * -- + * 34 34 + * + * X = Y +|-|"&&"|"|" Z 5 + * X = Y +|-|"==" Constant 6 + * X = X +|- 1 3 + * X = Y *|/ Z 2 + * X = Expression, 1 + * two operators + * X = Expression, 1 + * three operators + * -- + * 18 18 + * + * if .... 14 + * with "else" 7 + * without "else" 7 + * executed 3 + * not executed 4 + * for ... 7 | counted every time + * while ... 4 | the loop condition + * do ... while 1 | is evaluated + * switch ... 1 + * break 1 + * declaration with 1 + * initialization + * -- + * 34 34 + * + * P (...) procedure call 11 + * user procedure 10 + * library procedure 1 + * X = F (...) + * function call 6 + * user function 5 + * library function 1 + * -- + * 17 17 + * --- + * 103 + * + * The average number of parameters in procedure or function calls + * is 1.82 (not counting the function values as implicit parameters). + * + * + * 2. Operators + * ------------ + * number approximate + * percentage + * + * Arithmetic 32 50.8 + * + * + 21 33.3 + * - 7 11.1 + * * 3 4.8 + * / (int div) 1 1.6 + * + * Comparison 27 42.8 + * + * == 9 14.3 + * /= 4 6.3 + * > 1 1.6 + * < 3 4.8 + * >= 1 1.6 + * <= 9 14.3 + * + * Logic 4 6.3 + * + * && (AND-THEN) 1 1.6 + * | (OR) 1 1.6 + * ! (NOT) 2 3.2 + * + * -- ----- + * 63 100.1 + * + * + * 3. Operand Type (counted once per operand reference): + * --------------- + * number approximate + * percentage + * + * Integer 175 72.3 % + * Character 45 18.6 % + * Pointer 12 5.0 % + * String30 6 2.5 % + * Array 2 0.8 % + * Record 2 0.8 % + * --- ------- + * 242 100.0 % + * + * When there is an access path leading to the final operand (e.g. a record + * component), only the final data type on the access path is counted. + * + * + * 4. Operand Locality: + * ------------------- + * number approximate + * percentage + * + * local variable 114 47.1 % + * global variable 22 9.1 % + * parameter 45 18.6 % + * value 23 9.5 % + * reference 22 9.1 % + * function result 6 2.5 % + * constant 55 22.7 % + * --- ------- + * 242 100.0 % + * + * + * The program does not compute anything meaningful, but it is syntactically + * and semantically correct. All variables have a value assigned to them + * before they are used as a source operand. + * + * There has been no explicit effort to account for the effects of a + * cache, or to balance the use of long or short displacements for code or + * data. + * + *************************************************************************** + */ + +/* Compiler and system dependent definitions: */ + +#ifndef TIME +#define TIMES +#endif + /* Use times(2) time function unless */ + /* explicitly defined otherwise */ + +#ifdef TIMES +#include +#include + /* for "times" */ +#endif + +#define Mic_secs_Per_Second 1000000 + /* Berkeley UNIX C returns process times in seconds/HZ */ + +#ifdef NOSTRUCTASSIGN +#define structassign(d, s) memcpy(&(d), &(s), sizeof(d)) +#else +#define structassign(d, s) d = s +#endif + +#ifdef NOENUM +#define Ident_1 0 +#define Ident_2 1 +#define Ident_3 2 +#define Ident_4 3 +#define Ident_5 4 + typedef int Enumeration; +#else + typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5} + Enumeration; +#endif + /* for boolean and enumeration types in Ada, Pascal */ + +/* General definitions: */ + +#include + /* for strcpy, strcmp */ + +#define Null 0 + /* Value of a Null pointer */ +#define true 1 +#define false 0 + +typedef int One_Thirty; +typedef int One_Fifty; +typedef char Capital_Letter; +typedef int Boolean; +typedef char Str_30 [31]; +typedef int Arr_1_Dim [50]; +typedef int Arr_2_Dim [50] [50]; + +typedef struct record + { + struct record *Ptr_Comp; + Enumeration Discr; + union { + struct { + Enumeration Enum_Comp; + int Int_Comp; + char Str_Comp [31]; + } var_1; + struct { + Enumeration E_Comp_2; + char Str_2_Comp [31]; + } var_2; + struct { + char Ch_1_Comp; + char Ch_2_Comp; + } var_3; + } variant; + } Rec_Type, *Rec_Pointer; + + diff --git a/examples/SW/riscv_dhry/dhry_1.c b/examples/SW/riscv_dhry/dhry_1.c new file mode 100644 index 0000000000..0ceae5a6d4 --- /dev/null +++ b/examples/SW/riscv_dhry/dhry_1.c @@ -0,0 +1,385 @@ +/* + **************************************************************************** + * + * "DHRYSTONE" Benchmark Program + * ----------------------------- + * + * Version: C, Version 2.1 + * + * File: dhry_1.c (part 2 of 3) + * + * Date: May 25, 1988 + * + * Author: Reinhold P. Weicker + * + **************************************************************************** + */ + +#include "dhry.h" + +/* Global Variables: */ + +Rec_Pointer Ptr_Glob, + Next_Ptr_Glob; +int Int_Glob; +Boolean Bool_Glob; +char Ch_1_Glob, + Ch_2_Glob; +int Arr_1_Glob [50]; +int Arr_2_Glob [50] [50]; + +extern void *malloc (); +Enumeration Func_1 (); + /* forward declaration necessary since Enumeration may not simply be int */ + +#ifndef REG + Boolean Reg = false; +#define REG + /* REG becomes defined as empty */ + /* i.e. no register variables */ +#else + Boolean Reg = true; +#endif + +/* variables for time measurement: */ + +#ifdef TIMES +struct tms time_info; +extern int times (); + /* see library function "times" */ +#define Too_Small_Time 120 + /* Measurements should last at least about 2 seconds */ +#endif +#ifdef TIME +extern long time(); + /* see library function "time" */ +#define Too_Small_Time 2 + /* Measurements should last at least 2 seconds */ +#endif + +long Begin_Time, + End_Time, + User_Time; +float Microseconds, + Dhrystones_Per_Second; + +/* end of variables for time measurement */ + + +main () +/*****/ + + /* main program, corresponds to procedures */ + /* Main and Proc_0 in the Ada version */ +{ + One_Fifty Int_1_Loc; + REG One_Fifty Int_2_Loc; + One_Fifty Int_3_Loc; + REG char Ch_Index; + Enumeration Enum_Loc; + Str_30 Str_1_Loc; + Str_30 Str_2_Loc; + REG int Run_Index; + REG int Number_Of_Runs; + + /* Initializations */ + + Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); + Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); + + Ptr_Glob->Ptr_Comp = Next_Ptr_Glob; + Ptr_Glob->Discr = Ident_1; + Ptr_Glob->variant.var_1.Enum_Comp = Ident_3; + Ptr_Glob->variant.var_1.Int_Comp = 40; + strcpy (Ptr_Glob->variant.var_1.Str_Comp, + "DHRYSTONE PROGRAM, SOME STRING"); + strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); + + Arr_2_Glob [8][7] = 10; + /* Was missing in published program. Without this statement, */ + /* Arr_2_Glob [8][7] would have an undefined value. */ + /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */ + /* overflow may occur for this array element. */ + + printf ("\n"); + printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n"); + printf ("\n"); + if (Reg) + { + printf ("Program compiled with 'register' attribute\n"); + printf ("\n"); + } + else + { + printf ("Program compiled without 'register' attribute\n"); + printf ("\n"); + } + printf ("Please give the number of runs through the benchmark: "); + { + int n; + /*scanf ("%d", &n);*/ + Number_Of_Runs = 1000000; + } + printf ("\n"); + + printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs); + + /***************/ + /* Start timer */ + /***************/ + +#ifdef TIMES + times (&time_info); + Begin_Time = (long) time_info.tms_utime; +#endif +#ifdef TIME + Begin_Time = time ( (long *) 0); +#endif + + for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) + { + + Proc_5(); + Proc_4(); + /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ + Int_1_Loc = 2; + Int_2_Loc = 3; + strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); + Enum_Loc = Ident_2; + Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc); + /* Bool_Glob == 1 */ + while (Int_1_Loc < Int_2_Loc) /* loop body executed once */ + { + Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; + /* Int_3_Loc == 7 */ + Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); + /* Int_3_Loc == 7 */ + Int_1_Loc += 1; + } /* while */ + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); + /* Int_Glob == 5 */ + Proc_1 (Ptr_Glob); + for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) + /* loop body executed twice */ + { + if (Enum_Loc == Func_1 (Ch_Index, 'C')) + /* then, not executed */ + { + Proc_6 (Ident_1, &Enum_Loc); + strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); + Int_2_Loc = Run_Index; + Int_Glob = Run_Index; + } + } + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Int_2_Loc = Int_2_Loc * Int_1_Loc; + Int_1_Loc = Int_2_Loc / Int_3_Loc; + Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; + /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ + Proc_2 (&Int_1_Loc); + /* Int_1_Loc == 5 */ + + } /* loop "for Run_Index" */ + + /**************/ + /* Stop timer */ + /**************/ + +#ifdef TIMES + times (&time_info); + End_Time = (long) time_info.tms_utime; +#endif +#ifdef TIME + End_Time = time ( (long *) 0); +#endif + + printf ("Execution ends\n"); + printf ("\n"); + printf ("Final values of the variables used in the benchmark:\n"); + printf ("\n"); + printf ("Int_Glob: %d\n", Int_Glob); + printf (" should be: %d\n", 5); + printf ("Bool_Glob: %d\n", Bool_Glob); + printf (" should be: %d\n", 1); + printf ("Ch_1_Glob: %c\n", Ch_1_Glob); + printf (" should be: %c\n", 'A'); + printf ("Ch_2_Glob: %c\n", Ch_2_Glob); + printf (" should be: %c\n", 'B'); + printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]); + printf (" should be: %d\n", 7); + printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]); + printf (" should be: Number_Of_Runs + 10\n"); + printf ("Ptr_Glob->\n"); + printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp); + printf (" should be: (implementation-dependent)\n"); + printf (" Discr: %d\n", Ptr_Glob->Discr); + printf (" should be: %d\n", 0); + printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp); + printf (" should be: %d\n", 2); + printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp); + printf (" should be: %d\n", 17); + printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp); + printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); + printf ("Next_Ptr_Glob->\n"); + printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp); + printf (" should be: (implementation-dependent), same as above\n"); + printf (" Discr: %d\n", Next_Ptr_Glob->Discr); + printf (" should be: %d\n", 0); + printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp); + printf (" should be: %d\n", 1); + printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp); + printf (" should be: %d\n", 18); + printf (" Str_Comp: %s\n", + Next_Ptr_Glob->variant.var_1.Str_Comp); + printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); + printf ("Int_1_Loc: %d\n", Int_1_Loc); + printf (" should be: %d\n", 5); + printf ("Int_2_Loc: %d\n", Int_2_Loc); + printf (" should be: %d\n", 13); + printf ("Int_3_Loc: %d\n", Int_3_Loc); + printf (" should be: %d\n", 7); + printf ("Enum_Loc: %d\n", Enum_Loc); + printf (" should be: %d\n", 1); + printf ("Str_1_Loc: %s\n", Str_1_Loc); + printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n"); + printf ("Str_2_Loc: %s\n", Str_2_Loc); + printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n"); + printf ("\n"); + + User_Time = End_Time - Begin_Time; + + if (User_Time < Too_Small_Time) + { + printf ("Measured time too small to obtain meaningful results\n"); + printf ("Please increase number of runs\n"); + printf ("\n"); + } + else + { +#ifdef TIME + Microseconds = (float) User_Time * Mic_secs_Per_Second + / (float) Number_Of_Runs; + Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time; +#else + Microseconds = (float) User_Time * Mic_secs_Per_Second + / ((float) HZ * ((float) Number_Of_Runs)); + Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs) + / (float) User_Time; +#endif + printf ("Microseconds for one run through Dhrystone: "); + printf ("%6.1f \n", Microseconds); + printf ("Dhrystones per Second: "); + printf ("%6.1f \n", Dhrystones_Per_Second); + printf ("\n"); + } + +} + + +Proc_1 (Ptr_Val_Par) +/******************/ + +REG Rec_Pointer Ptr_Val_Par; + /* executed once */ +{ + REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp; + /* == Ptr_Glob_Next */ + /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */ + /* corresponds to "rename" in Ada, "with" in Pascal */ + + structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); + Ptr_Val_Par->variant.var_1.Int_Comp = 5; + Next_Record->variant.var_1.Int_Comp + = Ptr_Val_Par->variant.var_1.Int_Comp; + Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp; + Proc_3 (&Next_Record->Ptr_Comp); + /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp + == Ptr_Glob->Ptr_Comp */ + if (Next_Record->Discr == Ident_1) + /* then, executed */ + { + Next_Record->variant.var_1.Int_Comp = 6; + Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, + &Next_Record->variant.var_1.Enum_Comp); + Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp; + Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, + &Next_Record->variant.var_1.Int_Comp); + } + else /* not executed */ + structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp); +} /* Proc_1 */ + + +Proc_2 (Int_Par_Ref) +/******************/ + /* executed once */ + /* *Int_Par_Ref == 1, becomes 4 */ + +One_Fifty *Int_Par_Ref; +{ + One_Fifty Int_Loc; + Enumeration Enum_Loc; + + Int_Loc = *Int_Par_Ref + 10; + do /* executed once */ + if (Ch_1_Glob == 'A') + /* then, executed */ + { + Int_Loc -= 1; + *Int_Par_Ref = Int_Loc - Int_Glob; + Enum_Loc = Ident_1; + } /* if */ + while (Enum_Loc != Ident_1); /* true */ +} /* Proc_2 */ + + +Proc_3 (Ptr_Ref_Par) +/******************/ + /* executed once */ + /* Ptr_Ref_Par becomes Ptr_Glob */ + +Rec_Pointer *Ptr_Ref_Par; + +{ + if (Ptr_Glob != Null) + /* then, executed */ + *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp; + Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp); +} /* Proc_3 */ + + +Proc_4 () /* without parameters */ +/*******/ + /* executed once */ +{ + Boolean Bool_Loc; + + Bool_Loc = Ch_1_Glob == 'A'; + Bool_Glob = Bool_Loc | Bool_Glob; + Ch_2_Glob = 'B'; +} /* Proc_4 */ + + +Proc_5 () /* without parameters */ +/*******/ + /* executed once */ +{ + Ch_1_Glob = 'A'; + Bool_Glob = false; +} /* Proc_5 */ + + + /* Procedure for the assignment of structures, */ + /* if the C compiler doesn't support this feature */ +#ifdef NOSTRUCTASSIGN +memcpy (d, s, l) +register char *d; +register char *s; +register int l; +{ + while (l--) *d++ = *s++; +} +#endif + + diff --git a/examples/SW/riscv_dhry/dhry_2.c b/examples/SW/riscv_dhry/dhry_2.c new file mode 100644 index 0000000000..63a3d3ea03 --- /dev/null +++ b/examples/SW/riscv_dhry/dhry_2.c @@ -0,0 +1,192 @@ +/* + **************************************************************************** + * + * "DHRYSTONE" Benchmark Program + * ----------------------------- + * + * Version: C, Version 2.1 + * + * File: dhry_2.c (part 3 of 3) + * + * Date: May 25, 1988 + * + * Author: Reinhold P. Weicker + * + **************************************************************************** + */ + +#include "dhry.h" + +#ifndef REG +#define REG + /* REG becomes defined as empty */ + /* i.e. no register variables */ +#endif + +extern int Int_Glob; +extern char Ch_1_Glob; + + +Proc_6 (Enum_Val_Par, Enum_Ref_Par) +/*********************************/ + /* executed once */ + /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */ + +Enumeration Enum_Val_Par; +Enumeration *Enum_Ref_Par; +{ + *Enum_Ref_Par = Enum_Val_Par; + if (! Func_3 (Enum_Val_Par)) + /* then, not executed */ + *Enum_Ref_Par = Ident_4; + switch (Enum_Val_Par) + { + case Ident_1: + *Enum_Ref_Par = Ident_1; + break; + case Ident_2: + if (Int_Glob > 100) + /* then */ + *Enum_Ref_Par = Ident_1; + else *Enum_Ref_Par = Ident_4; + break; + case Ident_3: /* executed */ + *Enum_Ref_Par = Ident_2; + break; + case Ident_4: break; + case Ident_5: + *Enum_Ref_Par = Ident_3; + break; + } /* switch */ +} /* Proc_6 */ + + +Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref) +/**********************************************/ + /* executed three times */ + /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */ + /* Int_Par_Ref becomes 7 */ + /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */ + /* Int_Par_Ref becomes 17 */ + /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */ + /* Int_Par_Ref becomes 18 */ +One_Fifty Int_1_Par_Val; +One_Fifty Int_2_Par_Val; +One_Fifty *Int_Par_Ref; +{ + One_Fifty Int_Loc; + + Int_Loc = Int_1_Par_Val + 2; + *Int_Par_Ref = Int_2_Par_Val + Int_Loc; +} /* Proc_7 */ + + +Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val) +/*********************************************************************/ + /* executed once */ + /* Int_Par_Val_1 == 3 */ + /* Int_Par_Val_2 == 7 */ +Arr_1_Dim Arr_1_Par_Ref; +Arr_2_Dim Arr_2_Par_Ref; +int Int_1_Par_Val; +int Int_2_Par_Val; +{ + REG One_Fifty Int_Index; + REG One_Fifty Int_Loc; + + Int_Loc = Int_1_Par_Val + 5; + Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val; + Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc]; + Arr_1_Par_Ref [Int_Loc+30] = Int_Loc; + for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index) + Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc; + Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1; + Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc]; + Int_Glob = 5; +} /* Proc_8 */ + + +Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val) +/*************************************************/ + /* executed three times */ + /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */ + /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */ + /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */ + +Capital_Letter Ch_1_Par_Val; +Capital_Letter Ch_2_Par_Val; +{ + Capital_Letter Ch_1_Loc; + Capital_Letter Ch_2_Loc; + + Ch_1_Loc = Ch_1_Par_Val; + Ch_2_Loc = Ch_1_Loc; + if (Ch_2_Loc != Ch_2_Par_Val) + /* then, executed */ + return (Ident_1); + else /* not executed */ + { + Ch_1_Glob = Ch_1_Loc; + return (Ident_2); + } +} /* Func_1 */ + + +Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref) +/*************************************************/ + /* executed once */ + /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */ + /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */ + +Str_30 Str_1_Par_Ref; +Str_30 Str_2_Par_Ref; +{ + REG One_Thirty Int_Loc; + Capital_Letter Ch_Loc; + + Int_Loc = 2; + while (Int_Loc <= 2) /* loop body executed once */ + if (Func_1 (Str_1_Par_Ref[Int_Loc], + Str_2_Par_Ref[Int_Loc+1]) == Ident_1) + /* then, executed */ + { + Ch_Loc = 'A'; + Int_Loc += 1; + } /* if, while */ + if (Ch_Loc >= 'W' && Ch_Loc < 'Z') + /* then, not executed */ + Int_Loc = 7; + if (Ch_Loc == 'R') + /* then, not executed */ + return (true); + else /* executed */ + { + if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0) + /* then, not executed */ + { + Int_Loc += 7; + Int_Glob = Int_Loc; + return (true); + } + else /* executed */ + return (false); + } /* if Ch_Loc */ +} /* Func_2 */ + + +Boolean Func_3 (Enum_Par_Val) +/***************************/ + /* executed once */ + /* Enum_Par_Val == Ident_3 */ +Enumeration Enum_Par_Val; +{ + Enumeration Enum_Loc; + + Enum_Loc = Enum_Par_Val; + if (Enum_Loc == Ident_3) + /* then, executed */ + return (true); + else /* not executed */ + return (false); +} /* Func_3 */ + From 18318cc411d576ed555eb27794d87cb4f6ed1da4 Mon Sep 17 00:00:00 2001 From: Das Date: Wed, 15 Sep 2021 12:17:48 +0200 Subject: [PATCH 3/9] allow etiss to save performance_metrics to json --- examples/SW/CMakeLists.txt | 3 ++ examples/bare_etiss_processor/base.ini | 2 +- examples/bare_etiss_processor/main.cpp | 37 ++++++++++++++++++- .../bare_etiss_processor/run_helper.sh.in | 2 + include/etiss/CPUCore.h | 3 +- src/CPUCore.cpp | 10 ++++- src/ETISS.cpp | 1 + 7 files changed, 52 insertions(+), 6 deletions(-) diff --git a/examples/SW/CMakeLists.txt b/examples/SW/CMakeLists.txt index 66e43d55ce..feceb86baa 100644 --- a/examples/SW/CMakeLists.txt +++ b/examples/SW/CMakeLists.txt @@ -70,3 +70,6 @@ install(FILES riscv/CMakeLists.txt riscv/memsegs.ini install(FILES riscv_cpp/CMakeLists.txt riscv/memsegs.ini DESTINATION examples/SW/riscv_cpp ) +install(FILES riscv_dhry/CMakeLists.txt + DESTINATION examples/SW/riscv_dhry +) \ No newline at end of file diff --git a/examples/bare_etiss_processor/base.ini b/examples/bare_etiss_processor/base.ini index c78fe59bef..d05da02ef1 100644 --- a/examples/bare_etiss_processor/base.ini +++ b/examples/bare_etiss_processor/base.ini @@ -10,7 +10,7 @@ jit.gcc.cleanup=true jit.verify=false etiss.load_integrated_libraries=true jit.debug=false - +testing = false [IntConfigurations] diff --git a/examples/bare_etiss_processor/main.cpp b/examples/bare_etiss_processor/main.cpp index 68e388afdb..1a32f5a3f6 100644 --- a/examples/bare_etiss_processor/main.cpp +++ b/examples/bare_etiss_processor/main.cpp @@ -43,6 +43,7 @@ #include "TracePrinter.h" #include "etiss/SimpleMemSystem.h" #include "etiss/ETISS.h" +void writeFileJson(float cpu_time, float simulation_time, float cpu_cycle, float mips, std::string valid_json_output_path);// Save the information in JSON format int main(int argc, const char *argv[]) { @@ -91,9 +92,12 @@ int main(int argc, const char *argv[]) } } + std::cout << " Setting up CPUCore" << std::endl; // create a cpu core named core0 with the or1k architecture std::string CPUArchName = etiss::cfg().get("arch.cpu", ""); + std::string valid_json_output_path = etiss::cfg().get("vp.stats_file_path", ""); + bool output_json = etiss::cfg().isSet("vp.stats_file_path"); etiss::uint64 sa = etiss::cfg().get("vp.entry_point", dsys.get_startaddr()); std::cout << " CPU start address: 0x" << std::hex << sa << std::dec << std::endl; std::shared_ptr cpu = etiss::CPUCore::create(CPUArchName, "core0"); @@ -125,17 +129,35 @@ int main(int argc, const char *argv[]) if (etiss::cfg().get("etiss.log_pc", false)) { etiss::cfg().set("etiss.max_block_size", 1); cpu->addPlugin(std::shared_ptr(new TracePrinter(0x88888))); - } - + } + std::cout << "=== Setting up plug-ins ===" << std::endl << std::endl; // Simulation start std::cout << std::endl << "=== Simulation start ===" << std::endl; + //float startTime = (float)clock() / CLOCKS_PER_SEC; // TESTING // run cpu with the SimpleMemSystem (in other cases that "system" is most likely a // bus that connects the cpu to memory,periphery,etc) etiss_int32 exception = cpu->execute(dsys); + //float endTime = (float)clock() / CLOCKS_PER_SEC; std::cout << "=== Simulation end ===" << std::endl << std::endl; + //calculations for json file output + + ETISS_CPU *cpu_state = cpu->getState(); + + float cpu_time = cpu_state->cpuTime_ps / 1.0E12; + float simulation_time = cpu->endTime - cpu->startTime; + float cpu_cycle = cpu_state->cpuTime_ps / (float)cpu_state->cpuCycleTime_ps; + float mips = (cpu_state->cpuTime_ps / (float)cpu_state->cpuCycleTime_ps / simulation_time / 1.0E6); + + //print out the simulation calculations via json file + + if(output_json==true) + { + writeFileJson(cpu_time, simulation_time, cpu_cycle, mips, valid_json_output_path); + } + // print the exception code returned by the cpu core std::cout << "CPU0 exited with exception: 0x" << std::hex << exception << std::dec << ": " << etiss::RETURNCODE::getErrorMessages()[exception] << std::endl; @@ -181,3 +203,14 @@ int main(int argc, const char *argv[]) break; } } +void writeFileJson(float cpu_time, float simulation_time, float cpu_cycle, float mips, std::string valid_json_output_path)// Save the information in JSON format +{ + + std::ofstream json_output(valid_json_output_path); + json_output << "{\"mips\": " << mips << ", \"Simulation_Time\": " << simulation_time << ", \"CPU_Time\": " << cpu_time << ", \"CPU_cycle\": " << cpu_cycle << "}" << std::endl; + json_output.close(); + +} + + + diff --git a/examples/bare_etiss_processor/run_helper.sh.in b/examples/bare_etiss_processor/run_helper.sh.in index 87ef8840aa..2084136ca1 100755 --- a/examples/bare_etiss_processor/run_helper.sh.in +++ b/examples/bare_etiss_processor/run_helper.sh.in @@ -63,6 +63,8 @@ do DO_TRACE=1 elif [ "$arg" = "gcc" ]; then JIT="GCCJIT" + elif [ "$arg" = "tcc" ]; then + JIT="TCCJIT" elif [ "$arg" = "llvm" ]; then JIT="LLVMJIT" elif [ "$arg" = "vp" ]; then diff --git a/include/etiss/CPUCore.h b/include/etiss/CPUCore.h index 3e7ceedcd2..0353423758 100644 --- a/include/etiss/CPUCore.h +++ b/include/etiss/CPUCore.h @@ -344,7 +344,8 @@ class CPUCore : public VirtualStructSupport, public etiss::ToString * @brief returns the list of all plugins. */ inline std::list> const *getPlugins() { return &plugins; }; - + float startTime; + float endTime; public: /** * @brief Create a CPUCore instance. diff --git a/src/CPUCore.cpp b/src/CPUCore.cpp index b84e94ac17..fa768b8889 100644 --- a/src/CPUCore.cpp +++ b/src/CPUCore.cpp @@ -54,6 +54,8 @@ using namespace etiss; + + /** @see etiss/CPUArch.h */ @@ -708,7 +710,8 @@ etiss::int32 CPUCore::execute(ETISS_System &_system) // start execution loop - float startTime = (float)clock() / CLOCKS_PER_SEC; // TESTING + + startTime = (float)clock() / CLOCKS_PER_SEC; // TESTING BlockLink *blptr = 0; // pointer to the current block @@ -833,7 +836,8 @@ etiss::int32 CPUCore::execute(ETISS_System &_system) loopexit: - float endTime = (float)clock() / CLOCKS_PER_SEC; + endTime = (float)clock() / CLOCKS_PER_SEC; + // execute coroutines end for (auto &cor_plugin : cor_array) @@ -917,3 +921,5 @@ etiss::int32 CPUCore::execute(ETISS_System &_system) return exception; } + + diff --git a/src/ETISS.cpp b/src/ETISS.cpp index 49b66cfda3..439020600c 100644 --- a/src/ETISS.cpp +++ b/src/ETISS.cpp @@ -741,6 +741,7 @@ void etiss_initialize(const std::vector& args, bool forced = false) ("vp.sw_binary_ram", po::value(), "Path to binary file to be loaded into RAM.") ("vp.sw_binary_rom", po::value(), "Path to binary file to be loaded into ROM.") ("vp.elf_file", po::value(), "Load ELF file.") + ("vp.stats_file_path", po::value(), "Path where the output json file gets stored after bare processor is run.") ("simple_mem_system.print_dbus_access", po::value(), "Traces accesses to the data bus.") ("simple_mem_system.print_ibus_access", po::value(), "Traces accesses to the instruction bus.") ("simple_mem_system.print_dbgbus_access", po::value(), "Traces accesses to the debug bus.") From 231cb4258b9ba1fccc5d55602df5a98c638bd287 Mon Sep 17 00:00:00 2001 From: Das Date: Thu, 16 Sep 2021 07:39:01 +0200 Subject: [PATCH 4/9] modifying the workflow --- .github/workflows/ci.yml | 300 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 294 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e8199ef1c..b5a60b2966 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: matrix: config: - {name: "Linux", os: ubuntu-latest, cmakegen: "", llvm: "linux-gnu-ubuntu-20.04", llvm-ext: ".tar.xz", tc: "linux-ubuntu14", tc-ext: ".tar.gz", unpack: "tar xf"} - - {name: "Windows", os: windows-latest, cmakegen: "-G \"Unix Makefiles\" -DCMAKE_MAKE_PROGRAM=make", llvm: "", llvm-ext: "", tc: "w64-mingw32", tc-ext: ".zip", unpack: "unzip"} + #- {name: "Windows", os: windows-latest, cmakegen: "-G \"Unix Makefiles\" -DCMAKE_MAKE_PROGRAM=make", llvm: "", llvm-ext: "", tc: "w64-mingw32", tc-ext: ".zip", unpack: "unzip"} - {name: "Mac", os: macOS-latest, cmakegen: "", llvm: "apple-darwin", llvm-ext: ".tar.xz", tc: "apple-darwin", tc-ext: ".tar.gz", unpack: "tar xf"} runs-on: ${{ matrix.config.os }} @@ -38,7 +38,6 @@ jobs: if: matrix.config.name == 'Mac' run: | brew install boost coreutils - - name: Requirements (Linux/Mac) if: matrix.config.name == 'Linux' || matrix.config.name == 'Mac' working-directory: ${{runner.workspace}} @@ -48,7 +47,6 @@ jobs: wget https://github.com/llvm/llvm-project/releases/download/llvmorg-11.0.0/$LLVM_NAME${{ matrix.config.llvm-ext }} ${{ matrix.config.unpack }} $LLVM_NAME${{ matrix.config.llvm-ext }} mv $LLVM_NAME llvm-lib - - name: Requirements shell: bash working-directory: ${{runner.workspace}} @@ -57,7 +55,6 @@ jobs: wget https://static.dev.sifive.com/dev-tools/$TC_NAME${{ matrix.config.tc-ext }} ${{ matrix.config.unpack }} $TC_NAME${{ matrix.config.tc-ext }} mv $TC_NAME riscv-tc - - name: Create Build Environment run: cmake -E make_directory ${{runner.workspace}}/build @@ -67,7 +64,6 @@ jobs: run: | export LLVM_DIR=${{runner.workspace}}/llvm-lib cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_INSTALL_PREFIX=../install - - name: Build working-directory: ${{runner.workspace}}/build shell: bash @@ -106,14 +102,51 @@ jobs: cmake .. -DRISCV_ELF_GCC_PREFIX=../../../../../riscv-tc -DRISCV_ELF_GCC_BASENAME=riscv64-unknown-elf -DRISCV_ARCH=rv64gc -DRISCV_ABI=lp64d ${{matrix.config.cmakegen}} cmake --build . --config $BUILD_TYPE cd - + cmake -E make_directory ${{runner.workspace}}/install/examples/SW/riscv_dhry/build + cd SW/riscv_dhry/build + cmake .. -DRISCV_ELF_GCC_PREFIX=../../../../../riscv-tc -DRISCV_ELF_GCC_BASENAME=riscv64-unknown-elf + cmake --build . --config $BUILD_TYPE + cd - cd bare_etiss_processor cd build cmake .. cmake --build . --config $BUILD_TYPE + - name: Compress Compiled System + run: tar -C ${{runner.workspace}} -cvf ${{runner.workspace}}/etiss.tar install + + - name: Upload Compiled System + uses: actions/upload-artifact@v2 + with: + name: etiss-${{matrix.config.name}}.tar + path: ${{runner.workspace}}/etiss.tar + + + + test: + strategy: + matrix: + config: + - {name: "Linux", os: ubuntu-20.04, cmakegen: "", llvm: "linux-gnu-ubuntu-20.04", llvm-ext: ".tar.xz", tc: "linux-ubuntu14", tc-ext: ".tar.gz", unpack: "tar xf"} + #- {name: "Windows", os: windows-latest, cmakegen: "-G \"MinGW Makefiles\"", llvm: "", llvm-ext: "", tc: "w64-mingw32", tc-ext: ".zip", unpack: "unzip"} + - {name: "Mac", os: macOS-latest, cmakegen: "", llvm: "apple-darwin", llvm-ext: ".tar.xz", tc: "apple-darwin", tc-ext: ".tar.gz", unpack: "tar xf"} + + needs: build + runs-on: ${{ matrix.config.os }} + name: ${{ matrix.config.name }} + + steps: + - name: Fetch Compiled System + uses: actions/download-artifact@v2 + with: + name: etiss-${{matrix.config.name}}.tar + path: ${{runner.workspace}} + + - name: Unpack Compiled System + working-directory: ${{runner.workspace}} + run: tar -xf etiss.tar - name: Test (Linux/Mac) working-directory: ${{runner.workspace}}/install/examples/bare_etiss_processor - #if: matrix.config.name == 'Linux' || matrix.config.name == 'Mac' if: matrix.config.name == 'Linux' shell: bash run: | @@ -139,3 +172,258 @@ jobs: ./main.exe --vp.elf_file=../../../SW/riscv_cpp/build/riscv_example.elf --jit.type=LLVMJIT --etiss.loglevel=4 -i../../../SW/riscv_cpp/memsegs.ini -pLogger ./main.exe --vp.elf_file=../../../SW/riscv/build64/riscv_example.elf --jit.type=TCCJIT --etiss.loglevel=4 -i../../../SW/riscv/memsegs.ini -pLogger ./main.exe --vp.elf_file=../../../SW/riscv_cpp/build64/riscv_example.elf --jit.type=TCCJIT --etiss.loglevel=4 -i../../../SW/riscv_cpp/memsegs.ini -pLogger + + + benchmark: + strategy: + matrix: + run-no: [1, 2, 3, 4, 5] + jit-engine: ["tcc", "gcc", "llvm"] + + needs: build + runs-on: ubuntu-latest + + steps: + + - name: Fetch Compiled System + uses: actions/download-artifact@v2 + with: + name: etiss-Linux.tar + path: ${{runner.workspace}} + + - name: Unpack Compiled System + working-directory: ${{runner.workspace}} + run: tar -xf etiss.tar + + - name: create directory to store results + working-directory: ${{runner.workspace}} + run: mkdir ${{runner.workspace}}/results + + - name: Run Benchmarks + working-directory: ${{runner.workspace}}/install/examples/bare_etiss_processor + run: | + ./run_helper.sh ../SW/riscv_dhry/build/riscv_example ${{matrix.jit-engine}} --vp.stats_file_path=${{runner.workspace}}/results/run.json + mv ${{runner.workspace}}/results/run.json ${{runner.workspace}}/results/run_${{matrix.jit-engine}}_${{matrix.run-no}}.json + + - name: Save Benchmark Results + uses: actions/upload-artifact@v2 + with: + name: run_${{matrix.jit-engine}}_${{matrix.run-no}}.json + path: ${{runner.workspace}}/results/run_${{matrix.jit-engine}}_${{matrix.run-no}}.json + + + + + compare_mips: + needs: benchmark + runs-on: ubuntu-latest + + steps: + + - uses: actions/checkout@v2 + + - name: Fetch results + uses: actions/download-artifact@v2 + with: + path: artifacts + + - name: Prepare files + run: | + rm -rf benchmark_results_new + mkdir benchmark_results_new + find artifacts -type f -name '*.json' -exec mv {} benchmark_results_new \; + find artifacts -type f -name '*.tar' -exec mv {} . \; + + - name: install dependencies + run: pip install -r script/requirements.txt + + - name: get old benchmark results + uses: actions/checkout@v2 + with: + ref: benchmark_results + path: benchmark_results_old + + - name: creating a directory results_ for storing wiki text, issue text and the graph + run: | + ls benchmark_results_new + rm -rf results_ + mkdir results_ + + - name: Run comparison (Push) + if: ${{github.event_name == 'push'}} + run: python3 script/compare.py benchmark_results_new/run_*.json -o benchmark_results_old/stats_file.json -i results_/issue.md -w results_/wiki.md -gr results_/performance_metrics.svg -g ${{ github.sha }} -r $GITHUB_REPOSITORY + + - name: Run comparison (PR) + if: ${{github.event_name == 'pull_request'}} + run: python3 script/compare.py benchmark_results_new/run_*.json -o benchmark_results_old/stats_file.json -i results_/issue.md -w results_/wiki.md -gr results_/performance_metrics.svg -g ${{ github.event.pull_request.head.sha }} -r $GITHUB_REPOSITORY + + - name: Deploy results to git + if: ${{github.event_name == 'push'}} + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./benchmark_results_old + publish_branch: benchmark_results + enable_jekyll: true + + - name: uploading benchmark_results + uses: actions/upload-artifact@v2 + with: + name: stats_file.json + + path: benchmark_results_old/stats_file.json + + - name: uploading image + uses: actions/upload-artifact@v2 + with: + name: performance_metrics.svg + path: results_/performance_metrics.svg + + - name: Upload comment text + uses: actions/upload-artifact@v2 + with: + name: issue.md + + path: results_/issue.md + + - name: Upload wiki text + uses: actions/upload-artifact@v2 + with: + name: wiki.md + path: results_/wiki.md + + + + display-push: + needs: compare_mips + runs-on: ubuntu-latest + if: ${{github.event_name == 'push'}} + + steps: + - name: Get comment text + uses: actions/download-artifact@v2 + with: + name: issue.md + + - name: Load comment body + id: get-comment-body + run: | + body=$(cat issue.md) + body="${body//'%'/'%25'}" + body="${body//$'\n'/'%0A'}" + body="${body//$'\r'/'%0D'}" + echo ::set-output name=body::$body + - name: Find Comment + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: 19 + + body-includes: This comment was created automatically, please do not change! + + - name: Create comment + if: ${{ steps.fc.outputs.comment-id == 0 }} + uses: peter-evans/create-or-update-comment@v1 + with: + issue-number: 19 + edit-mode: replace + body: ${{ steps.get-comment-body.outputs.body }} + + - name: Update comment + if: ${{ steps.fc.outputs.comment-id != 0 }} + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + edit-mode: replace + body: ${{ steps.get-comment-body.outputs.body }} + + display-pr: + needs: compare_mips + runs-on: ubuntu-latest + if: ${{github.event_name == 'pull_request'}} + + steps: + - name: Get comment text + uses: actions/download-artifact@v2 + with: + name: issue.md + + - name: Load comment body + id: get-comment-body + run: | + body=$(cat issue.md) + body="${body//'%'/'%25'}" + body="${body//$'\n'/'%0A'}" + body="${body//$'\r'/'%0D'}" + echo ::set-output name=body::$body + - name: Find Comment + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: ${{github.event.number}} + body-includes: This comment was created automatically, please do not change! + + - name: Create comment + if: ${{ steps.fc.outputs.comment-id == 0 }} + uses: peter-evans/create-or-update-comment@v1 + with: + issue-number: ${{github.event.number}} + edit-mode: replace + body: ${{ steps.get-comment-body.outputs.body }} + + - name: Update comment + if: ${{ steps.fc.outputs.comment-id != 0 }} + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + edit-mode: replace + body: ${{ steps.get-comment-body.outputs.body }} + + + + display-wiki: + needs: compare_mips + runs-on: ubuntu-latest + if: ${{github.event_name == 'push'}} + + steps: + - name: Get comment text + uses: actions/download-artifact@v2 + with: + name: wiki.md + + - name: Get performance_metrics.svg + uses: actions/download-artifact@v2 + with: + name: performance_metrics.svg + + - name: Update wiki + run: | + echo "Cloning wiki repo https://github.com/$GITHUB_REPOSITORY.wiki.git" + git clone "https://$GITHUB_ACTOR:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY.wiki.git" "wiki" + cd wiki + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + rm -rf ./performance_metrics.svg + cp ../wiki.md ./Performance_Metrics.md + cp ../performance_metrics.svg ./performance_metrics.svg + git add Performance_Metrics.md performance_metrics.svg + git commit -m "update perf" + git push + + + delete-artifact: + if: always() + needs: [display-wiki, display-push, display-pr] + runs-on: ubuntu-latest + continue-on-error: true + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Delete Artifact + uses: jimschubert/delete-artifacts-action@v1 + with: + min_bytes: '0' + From 3f4c5cfa82d8381fbfc1138d3648131202abd7dd Mon Sep 17 00:00:00 2001 From: Das Date: Tue, 21 Sep 2021 07:26:19 +0200 Subject: [PATCH 5/9] removing explicit .close() --- examples/bare_etiss_processor/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/bare_etiss_processor/main.cpp b/examples/bare_etiss_processor/main.cpp index 1a32f5a3f6..d841655635 100644 --- a/examples/bare_etiss_processor/main.cpp +++ b/examples/bare_etiss_processor/main.cpp @@ -208,7 +208,6 @@ void writeFileJson(float cpu_time, float simulation_time, float cpu_cycle, float std::ofstream json_output(valid_json_output_path); json_output << "{\"mips\": " << mips << ", \"Simulation_Time\": " << simulation_time << ", \"CPU_Time\": " << cpu_time << ", \"CPU_cycle\": " << cpu_cycle << "}" << std::endl; - json_output.close(); } From 0f6eb522b79664668dd3dfa91391e1e716b8adb8 Mon Sep 17 00:00:00 2001 From: Das Date: Sat, 25 Sep 2021 16:04:16 +0200 Subject: [PATCH 6/9] deleting all artifacts issue resolved --- .github/workflows/ci.yml | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5a60b2966..2c1bc4daf3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,11 +11,11 @@ jobs: matrix: config: - {name: "Linux", os: ubuntu-latest, cmakegen: "", llvm: "linux-gnu-ubuntu-20.04", llvm-ext: ".tar.xz", tc: "linux-ubuntu14", tc-ext: ".tar.gz", unpack: "tar xf"} - #- {name: "Windows", os: windows-latest, cmakegen: "-G \"Unix Makefiles\" -DCMAKE_MAKE_PROGRAM=make", llvm: "", llvm-ext: "", tc: "w64-mingw32", tc-ext: ".zip", unpack: "unzip"} - - {name: "Mac", os: macOS-latest, cmakegen: "", llvm: "apple-darwin", llvm-ext: ".tar.xz", tc: "apple-darwin", tc-ext: ".tar.gz", unpack: "tar xf"} + - {name: "Windows", os: windows-latest, cmakegen: "-G \"Unix Makefiles\" -DCMAKE_MAKE_PROGRAM=make", llvm: "", llvm-ext: "", tc: "w64-mingw32", tc-ext: ".zip", unpack: "unzip"} + - {name: "Mac", os: macos-10.15, cmakegen: "", llvm: "apple-darwin", llvm-ext: ".tar.xz", tc: "apple-darwin", tc-ext: ".tar.gz", unpack: "tar xf"} runs-on: ${{ matrix.config.os }} - name: ${{ matrix.config.name }} + name: ${{ matrix.config.name }}_build steps: - uses: actions/checkout@v2 @@ -81,6 +81,7 @@ jobs: cmake -E make_directory ${{runner.workspace}}/install/examples/SW/riscv_cpp/build cmake -E make_directory ${{runner.workspace}}/install/examples/SW/riscv_cpp/build64 cmake -E make_directory ${{runner.workspace}}/install/examples/bare_etiss_processor/build + cmake -E make_directory ${{runner.workspace}}/install/examples/SW/riscv_dhry/build - name: Setup tests working-directory: ${{runner.workspace}}/install/examples @@ -102,15 +103,14 @@ jobs: cmake .. -DRISCV_ELF_GCC_PREFIX=../../../../../riscv-tc -DRISCV_ELF_GCC_BASENAME=riscv64-unknown-elf -DRISCV_ARCH=rv64gc -DRISCV_ABI=lp64d ${{matrix.config.cmakegen}} cmake --build . --config $BUILD_TYPE cd - - cmake -E make_directory ${{runner.workspace}}/install/examples/SW/riscv_dhry/build cd SW/riscv_dhry/build - cmake .. -DRISCV_ELF_GCC_PREFIX=../../../../../riscv-tc -DRISCV_ELF_GCC_BASENAME=riscv64-unknown-elf + cmake .. -DRISCV_ELF_GCC_PREFIX=../../../../../riscv-tc -DRISCV_ELF_GCC_BASENAME=riscv64-unknown-elf ${{matrix.config.cmakegen}} cmake --build . --config $BUILD_TYPE cd - - cd bare_etiss_processor - cd build + cd bare_etiss_processor/build cmake .. cmake --build . --config $BUILD_TYPE + - name: Compress Compiled System run: tar -C ${{runner.workspace}} -cvf ${{runner.workspace}}/etiss.tar install @@ -120,19 +120,17 @@ jobs: name: etiss-${{matrix.config.name}}.tar path: ${{runner.workspace}}/etiss.tar - - test: strategy: matrix: config: - {name: "Linux", os: ubuntu-20.04, cmakegen: "", llvm: "linux-gnu-ubuntu-20.04", llvm-ext: ".tar.xz", tc: "linux-ubuntu14", tc-ext: ".tar.gz", unpack: "tar xf"} - #- {name: "Windows", os: windows-latest, cmakegen: "-G \"MinGW Makefiles\"", llvm: "", llvm-ext: "", tc: "w64-mingw32", tc-ext: ".zip", unpack: "unzip"} - - {name: "Mac", os: macOS-latest, cmakegen: "", llvm: "apple-darwin", llvm-ext: ".tar.xz", tc: "apple-darwin", tc-ext: ".tar.gz", unpack: "tar xf"} + - {name: "Windows", os: windows-latest, cmakegen: "-G \"MinGW Makefiles\"", llvm: "", llvm-ext: "", tc: "w64-mingw32", tc-ext: ".zip", unpack: "unzip"} + - {name: "Mac", os: macos-10.15, cmakegen: "", llvm: "apple-darwin", llvm-ext: ".tar.xz", tc: "apple-darwin", tc-ext: ".tar.gz", unpack: "tar xf"} needs: build runs-on: ${{ matrix.config.os }} - name: ${{ matrix.config.name }} + name: ${{ matrix.config.name }}_test steps: - name: Fetch Compiled System @@ -423,7 +421,8 @@ jobs: uses: actions/checkout@v2 - name: Delete Artifact - uses: jimschubert/delete-artifacts-action@v1 + uses: geekyeggo/delete-artifact@1-glob-support with: - min_bytes: '0' + name: "*" + useGlob: true From 5a4089d65a3886a4ad70a6ad1e2b0b86b042a1ec Mon Sep 17 00:00:00 2001 From: Das Date: Sat, 25 Sep 2021 16:06:06 +0200 Subject: [PATCH 7/9] moving writing JSON functiolaities to the CPUCore file --- examples/SW/riscv_dhry/README.md | 15 +++++++---- examples/bare_etiss_processor/main.cpp | 27 +------------------ src/CPUCore.cpp | 37 +++++++++++++++++++++----- 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/examples/SW/riscv_dhry/README.md b/examples/SW/riscv_dhry/README.md index 274222378e..e194b115fd 100644 --- a/examples/SW/riscv_dhry/README.md +++ b/examples/SW/riscv_dhry/README.md @@ -1,8 +1,13 @@ -# RISC-V Software Compilation for C++ +# Dhrystone benchmark for evaluating RISC-V compilers' performance -This file contains ctr0, linker script, Makefile (originally from pulpino -project) for simple RISC-V software compilation using C++. For instructions and more details, see `../riscv/README.md`. +Header and modules present: -### RISC-V target software + dhry.h + dhry_1.c + dhry_2.c -The target software runs some basic C++ specific tests. Binary code and elf file will be located at `./build`. +See: https://github.com/Keith-S-Thompson/dhrystone/tree/master/v2.1 + +# Compilers whose performances are to be analyzed: + +GCC, TCC and LLVM diff --git a/examples/bare_etiss_processor/main.cpp b/examples/bare_etiss_processor/main.cpp index d841655635..ba60edf0f5 100644 --- a/examples/bare_etiss_processor/main.cpp +++ b/examples/bare_etiss_processor/main.cpp @@ -43,7 +43,7 @@ #include "TracePrinter.h" #include "etiss/SimpleMemSystem.h" #include "etiss/ETISS.h" -void writeFileJson(float cpu_time, float simulation_time, float cpu_cycle, float mips, std::string valid_json_output_path);// Save the information in JSON format + int main(int argc, const char *argv[]) { @@ -96,8 +96,6 @@ int main(int argc, const char *argv[]) std::cout << " Setting up CPUCore" << std::endl; // create a cpu core named core0 with the or1k architecture std::string CPUArchName = etiss::cfg().get("arch.cpu", ""); - std::string valid_json_output_path = etiss::cfg().get("vp.stats_file_path", ""); - bool output_json = etiss::cfg().isSet("vp.stats_file_path"); etiss::uint64 sa = etiss::cfg().get("vp.entry_point", dsys.get_startaddr()); std::cout << " CPU start address: 0x" << std::hex << sa << std::dec << std::endl; std::shared_ptr cpu = etiss::CPUCore::create(CPUArchName, "core0"); @@ -142,21 +140,6 @@ int main(int argc, const char *argv[]) //float endTime = (float)clock() / CLOCKS_PER_SEC; std::cout << "=== Simulation end ===" << std::endl << std::endl; - //calculations for json file output - - ETISS_CPU *cpu_state = cpu->getState(); - - float cpu_time = cpu_state->cpuTime_ps / 1.0E12; - float simulation_time = cpu->endTime - cpu->startTime; - float cpu_cycle = cpu_state->cpuTime_ps / (float)cpu_state->cpuCycleTime_ps; - float mips = (cpu_state->cpuTime_ps / (float)cpu_state->cpuCycleTime_ps / simulation_time / 1.0E6); - - //print out the simulation calculations via json file - - if(output_json==true) - { - writeFileJson(cpu_time, simulation_time, cpu_cycle, mips, valid_json_output_path); - } // print the exception code returned by the cpu core std::cout << "CPU0 exited with exception: 0x" << std::hex << exception << std::dec << ": " @@ -203,13 +186,5 @@ int main(int argc, const char *argv[]) break; } } -void writeFileJson(float cpu_time, float simulation_time, float cpu_cycle, float mips, std::string valid_json_output_path)// Save the information in JSON format -{ - - std::ofstream json_output(valid_json_output_path); - json_output << "{\"mips\": " << mips << ", \"Simulation_Time\": " << simulation_time << ", \"CPU_Time\": " << cpu_time << ", \"CPU_cycle\": " << cpu_cycle << "}" << std::endl; - -} - diff --git a/src/CPUCore.cpp b/src/CPUCore.cpp index fa768b8889..768c9c5c4d 100644 --- a/src/CPUCore.cpp +++ b/src/CPUCore.cpp @@ -54,7 +54,7 @@ using namespace etiss; - +void writeFileJson(float cpu_time, float simulation_time, float cpu_cycle, float mips, std::string valid_json_output_path);// Save the information in JSON format /** @see etiss/CPUArch.h @@ -845,12 +845,27 @@ etiss::int32 CPUCore::execute(ETISS_System &_system) cor_plugin->executionEnd(exception); } - // print some statistics - std::cout << "CPU Time: " << (cpu_->cpuTime_ps / 1.0E12) << "s Simulation Time: " << (endTime - startTime) << "s" + // Defining the statistics of measurement and printing them + double cpu_time = cpu_->cpuTime_ps / 1.0E12; + double simulation_time = endTime - startTime; + double cpu_cycle = cpu_->cpuTime_ps / (float)cpu_->cpuCycleTime_ps; + double mips = cpu_->cpuTime_ps / (float)cpu_->cpuCycleTime_ps / simulation_time / 1.0E6; + std::cout << "CPU Time: " << (cpu_time) << "s Simulation Time: " << (simulation_time) << "s" << std::endl; - std::cout << "CPU Cycles (estimated): " << (cpu_->cpuTime_ps / (float)cpu_->cpuCycleTime_ps) << std::endl; - std::cout << "MIPS (estimated): " - << (cpu_->cpuTime_ps / (float)cpu_->cpuCycleTime_ps / (endTime - startTime) / 1.0E6) << std::endl; + std::cout << "CPU Cycles (estimated): " << (cpu_cycle) << std::endl; + std::cout << "MIPS (estimated): " << (mips) << std::endl; + + + // declaring path of writing the json file contaiing performance metrics and the boolean which approves of writing the json output + std::string valid_json_output_path = etiss::cfg().get("vp.stats_file_path", ""); + bool output_json = etiss::cfg().isSet("vp.stats_file_path"); + + if(output_json==true) + { + writeFileJson(cpu_time, simulation_time, cpu_cycle, mips, valid_json_output_path); + } + + etiss_uint64 max = 0; for (int i = 0; i < ETISS_MAX_RESOURCES; i++) { @@ -923,3 +938,13 @@ etiss::int32 CPUCore::execute(ETISS_System &_system) } +// Function to write the performance metrics of a run into a json file +void writeFileJson(float cpu_time, float simulation_time, float cpu_cycle, float mips, std::string valid_json_output_path)// Save the information in JSON format +{ + + std::ofstream json_output(valid_json_output_path); + json_output << "{\"mips\": " << mips << ", \"Simulation_Time\": " << simulation_time << ", \"CPU_Time\": " << cpu_time << ", \"CPU_cycle\": " << cpu_cycle << "}" << std::endl; + +} + + From 6c41583a66533714f8821778f978243263247a7f Mon Sep 17 00:00:00 2001 From: Das Date: Tue, 28 Sep 2021 10:14:19 +0200 Subject: [PATCH 8/9] resolving last comments --- examples/SW/riscv_dhry/README.md | 2 +- src/CPUCore.cpp | 15 +++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/examples/SW/riscv_dhry/README.md b/examples/SW/riscv_dhry/README.md index e194b115fd..753cad22b4 100644 --- a/examples/SW/riscv_dhry/README.md +++ b/examples/SW/riscv_dhry/README.md @@ -1,4 +1,4 @@ -# Dhrystone benchmark for evaluating RISC-V compilers' performance +# Dhrystone benchmark for evaluating the simulator's performance Header and modules present: diff --git a/src/CPUCore.cpp b/src/CPUCore.cpp index 768c9c5c4d..5f8d9a50ee 100644 --- a/src/CPUCore.cpp +++ b/src/CPUCore.cpp @@ -54,8 +54,6 @@ using namespace etiss; -void writeFileJson(float cpu_time, float simulation_time, float cpu_cycle, float mips, std::string valid_json_output_path);// Save the information in JSON format - /** @see etiss/CPUArch.h */ @@ -858,11 +856,12 @@ etiss::int32 CPUCore::execute(ETISS_System &_system) // declaring path of writing the json file contaiing performance metrics and the boolean which approves of writing the json output std::string valid_json_output_path = etiss::cfg().get("vp.stats_file_path", ""); - bool output_json = etiss::cfg().isSet("vp.stats_file_path"); + bool output_json = etiss::cfg().isSet("vp.stats_file_path"); if(output_json==true) { - writeFileJson(cpu_time, simulation_time, cpu_cycle, mips, valid_json_output_path); + std::ofstream json_output(valid_json_output_path); + json_output << "{\"mips\": " << mips << ", \"Simulation_Time\": " << simulation_time << ", \"CPU_Time\": " << cpu_time << ", \"CPU_cycle\": " << cpu_cycle << "}" << std::endl; } @@ -938,13 +937,5 @@ etiss::int32 CPUCore::execute(ETISS_System &_system) } -// Function to write the performance metrics of a run into a json file -void writeFileJson(float cpu_time, float simulation_time, float cpu_cycle, float mips, std::string valid_json_output_path)// Save the information in JSON format -{ - - std::ofstream json_output(valid_json_output_path); - json_output << "{\"mips\": " << mips << ", \"Simulation_Time\": " << simulation_time << ", \"CPU_Time\": " << cpu_time << ", \"CPU_cycle\": " << cpu_cycle << "}" << std::endl; - -} From 155db0ac83d35740a6bd5036ec0aff6048bd9ed4 Mon Sep 17 00:00:00 2001 From: Das Date: Fri, 22 Oct 2021 18:59:45 +0200 Subject: [PATCH 9/9] startTime and stopTime local variables --- include/etiss/CPUCore.h | 2 -- src/CPUCore.cpp | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/etiss/CPUCore.h b/include/etiss/CPUCore.h index 0353423758..78709d38b4 100644 --- a/include/etiss/CPUCore.h +++ b/include/etiss/CPUCore.h @@ -344,8 +344,6 @@ class CPUCore : public VirtualStructSupport, public etiss::ToString * @brief returns the list of all plugins. */ inline std::list> const *getPlugins() { return &plugins; }; - float startTime; - float endTime; public: /** * @brief Create a CPUCore instance. diff --git a/src/CPUCore.cpp b/src/CPUCore.cpp index 5f8d9a50ee..0b1726f7a0 100644 --- a/src/CPUCore.cpp +++ b/src/CPUCore.cpp @@ -709,7 +709,7 @@ etiss::int32 CPUCore::execute(ETISS_System &_system) // start execution loop - startTime = (float)clock() / CLOCKS_PER_SEC; // TESTING + float startTime = (float)clock() / CLOCKS_PER_SEC; // TESTING BlockLink *blptr = 0; // pointer to the current block @@ -834,7 +834,7 @@ etiss::int32 CPUCore::execute(ETISS_System &_system) loopexit: - endTime = (float)clock() / CLOCKS_PER_SEC; + float endTime = (float)clock() / CLOCKS_PER_SEC; // execute coroutines end