From 9f2b7d65532f3d69878cb37dfe6a503646eae9cd Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 9 Feb 2014 08:59:51 -0800 Subject: [PATCH] Rearrange counters to me more realistic Instead of counting gate types, convert to gate count estimates and some other interesting statistics. Also handling the descent into child scopes. --- tgt-sizer/scan_logs.cc | 8 ++- tgt-sizer/scan_lpms.cc | 23 ++++++++- tgt-sizer/sizer.cc | 107 +++++++++++++++++++++++++++++++++-------- tgt-sizer/sizer_priv.h | 17 ++++--- 4 files changed, 123 insertions(+), 32 deletions(-) diff --git a/tgt-sizer/scan_logs.cc b/tgt-sizer/scan_logs.cc index e70a2ffb8..82a4df0d9 100644 --- a/tgt-sizer/scan_logs.cc +++ b/tgt-sizer/scan_logs.cc @@ -20,7 +20,7 @@ # include "sizer_priv.h" -void scan_logs_gates(ivl_scope_t scope, ivl_net_logic_t log, struct sizer_statistics&stats) +void scan_logs_gates(ivl_scope_t, ivl_net_logic_t log, struct sizer_statistics&stats) { unsigned wid = ivl_logic_width(log); @@ -35,11 +35,15 @@ void scan_logs(ivl_scope_t scope, struct sizer_statistics&stats) case IVL_LO_AND: case IVL_LO_OR: case IVL_LO_XOR: + case IVL_LO_NAND: + case IVL_LO_NOR: case IVL_LO_XNOR: + case IVL_LO_BUF: + case IVL_LO_NOT: scan_logs_gates(scope, log, stats); break; default: - stats.log_unknown += 1; + stats.log_bytype[ivl_logic_type(log)] += 1; break; } } diff --git a/tgt-sizer/scan_lpms.cc b/tgt-sizer/scan_lpms.cc index ddd382504..4d23a8f40 100644 --- a/tgt-sizer/scan_lpms.cc +++ b/tgt-sizer/scan_lpms.cc @@ -19,6 +19,12 @@ # include "sizer_priv.h" +using namespace std; + +/* + * Count each bit of flip-flops. It is clear and obvious how these + * come out, so no need to make alternate counts as well. + */ static void scan_lpms_ff(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats) { ivl_nexus_t out = ivl_lpm_q(lpm); @@ -27,6 +33,19 @@ static void scan_lpms_ff(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&sta stats.flop_count += wid; } +/* + * Count adders as 2m gates. + * Also keep a count of adders by width, just out of curiosity. + */ +static void scans_lpms_add(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats) +{ + unsigned wid = ivl_lpm_width(lpm); + + stats.adder_count[wid] += 1; + + stats.gate_count += 2*wid; +} + void scan_lpms(ivl_scope_t scope, struct sizer_statistics&stats) { for (unsigned idx = 0 ; idx < ivl_scope_lpms(scope) ; idx += 1) { @@ -43,7 +62,7 @@ void scan_lpms(ivl_scope_t scope, struct sizer_statistics&stats) break; case IVL_LPM_ADD: - stats.adder_count += 1; + scans_lpms_add(scope, lpm, stats); break; // D-Type flip-flops. @@ -52,7 +71,7 @@ void scan_lpms(ivl_scope_t scope, struct sizer_statistics&stats) break; default: - stats.lpm_unknown += 1; + stats.lpm_bytype[ivl_lpm_type(lpm)] += 1; break; } } diff --git a/tgt-sizer/sizer.cc b/tgt-sizer/sizer.cc index 2009ea558..5eb17f343 100644 --- a/tgt-sizer/sizer.cc +++ b/tgt-sizer/sizer.cc @@ -25,6 +25,8 @@ # include # include +using namespace std; + /* * This is a null target module. It does nothing. */ @@ -53,8 +55,24 @@ int sizer_errors = 0; FILE*sizer_out = 0; static int process_scan_fun(ivl_process_t net, void*raw); -static void emit_sizer_root(ivl_design_t des, ivl_scope_t model); +static void emit_sizer_scope(ivl_design_t des, ivl_scope_t model, struct sizer_statistics&stats); +static void show_stats(struct sizer_statistics&stats); +/* + * This is called by the ivl core to get version information from the + * loadable code generator. + */ +const char* target_query(const char*key) +{ + if (strcmp(key,"version") == 0) + return version_string; + + return 0; +} + +/* + * This is the main entry point from the IVL core. + */ int target_design(ivl_design_t des) { const char*sizer_path = ivl_design_flag(des, "-o"); @@ -65,11 +83,14 @@ int target_design(ivl_design_t des) // Detect processes and dispatch them. ivl_design_process(des, &process_scan_fun, 0); - // Locate the root scope for the design. + // Locate the root scopes for the design. ivl_scope_t*roots; unsigned nroots; ivl_design_roots(des, &roots, &nroots); + // Process all the root scopes. It is possible that there are + // multiple root scopes, we will give isolated numbers for + // each and keep then separate. for (unsigned idx = 0 ; idx < nroots ; idx += 1) { if (ivl_scope_type(roots[idx]) != IVL_SCT_MODULE) { fprintf(stderr, "SIZER: The root scope %s must be a module.\n", ivl_scope_basename(roots[idx])); @@ -77,21 +98,22 @@ int target_design(ivl_design_t des) continue; } - emit_sizer_root(des, roots[idx]); + struct sizer_statistics stats; + emit_sizer_scope(des, roots[idx], stats); + + fprintf(sizer_out, "**** TOTALS\n"); + show_stats(stats); } return sizer_errors; } -const char* target_query(const char*key) -{ - if (strcmp(key,"version") == 0) - return version_string; - - return 0; -} - +/* + * Processes are not collected into scopes, but we should not have any + * left anyhow. Give error messages for all the processes that we find + * to be remaining. + */ static int process_scan_fun(ivl_process_t net, void* /*raw*/) { fprintf(stderr, "%s:%u: SIZER: Processes not synthesized for statistics.\n", @@ -100,20 +122,43 @@ static int process_scan_fun(ivl_process_t net, void* /*raw*/) return 0; } -static void emit_sizer_root(ivl_design_t des, ivl_scope_t model) +static void emit_sizer_scope(ivl_design_t des, ivl_scope_t scope, struct sizer_statistics&stats) { - fprintf(sizer_out, "**** Root module: %s\n", ivl_scope_name(model)); - fprintf(sizer_out, " Logic gates: %u (ivl_net_logic_t nodes))\n", ivl_scope_logs(model)); - fprintf(sizer_out, " LPM nodes : %u (ivl_lpm_t nodes)\n", ivl_scope_lpms(model)); + fprintf(sizer_out, "**** module/scope: %s\n", ivl_scope_name(scope)); - struct sizer_statistics stats; - scan_logs(model, stats); - scan_lpms(model, stats); + scan_logs(scope, stats); + scan_lpms(scope, stats); + show_stats(stats); + + for (size_t idx = 0 ; idx < ivl_scope_childs(scope) ; idx += 1) { + ivl_scope_t child = ivl_scope_child(scope,idx); + struct sizer_statistics child_stats; + emit_sizer_scope(des, child, child_stats); + stats += child_stats; + } +} + +static void show_stats(struct sizer_statistics&stats) +{ fprintf(sizer_out, " Flip-Flops : %u\n", stats.flop_count); fprintf(sizer_out, " Logic Gates : %u\n", stats.gate_count); - fprintf(sizer_out, " LPM Unknown : %u\n", stats.lpm_unknown); - fprintf(sizer_out, " Logic Unknown: %u\n", stats.log_unknown); + + for (map::const_iterator cur = stats.adder_count.begin() + ; cur != stats.adder_count.end() ; ++ cur) { + fprintf(sizer_out, " ADDER[%u]: %u\n", cur->first, cur->second); + } + + // These are diagnostic outputs for when more detail is needed. + for (map::const_iterator cur = stats.lpm_bytype.begin() + ; cur != stats.lpm_bytype.end() ; ++ cur) { + fprintf(sizer_out, " LPM[%d]: %u unaccounted\n", cur->first, cur->second); + } + + for (map::const_iterator cur = stats.log_bytype.begin() + ; cur != stats.log_bytype.end() ; ++ cur) { + fprintf(sizer_out, " LOG[%d]: %u unaccounted\n", cur->first, cur->second); + } } unsigned get_nexus_width(ivl_nexus_t nex) @@ -130,3 +175,25 @@ unsigned get_nexus_width(ivl_nexus_t nex) sizer_errors += 1; return 0; } + +struct sizer_statistics& sizer_statistics::operator += (const sizer_statistics&that) +{ + flop_count += that.flop_count; + gate_count += that.gate_count; + + for (map::const_iterator cur = that.adder_count.begin() + ; cur != that.adder_count.end() ; ++ cur) + adder_count[cur->first] += cur->second; + + + for (map::const_iterator cur = that.lpm_bytype.begin() + ; cur != that.lpm_bytype.end() ; ++ cur) + lpm_bytype[cur->first] += cur->second; + + + for (map::const_iterator cur = that.log_bytype.begin() + ; cur != that.log_bytype.end() ; ++ cur) + log_bytype[cur->first] += cur->second; + + return *this; +} diff --git a/tgt-sizer/sizer_priv.h b/tgt-sizer/sizer_priv.h index f036d91b9..3732e3174 100644 --- a/tgt-sizer/sizer_priv.h +++ b/tgt-sizer/sizer_priv.h @@ -22,25 +22,26 @@ # include "config.h" # include "ivl_target.h" +# include # include struct sizer_statistics { + // These are the accumulated global statistics unsigned flop_count; unsigned gate_count; - unsigned adder_count; - - unsigned lpm_unknown; - unsigned log_unknown; + // Count adders of various dimension + std::map adder_count; + // Different kinds of nodes that we have not accounted for + std::map lpm_bytype; + std::map log_bytype; inline sizer_statistics() { flop_count = 0; gate_count = 0; - adder_count = 0; - - lpm_unknown = 0; - log_unknown = 0; } + + struct sizer_statistics& operator += (const struct sizer_statistics&that); }; extern int sizer_errors;