diff options
Diffstat (limited to 'o3d/compiler/puritan/knobs.cc')
-rw-r--r-- | o3d/compiler/puritan/knobs.cc | 783 |
1 files changed, 783 insertions, 0 deletions
diff --git a/o3d/compiler/puritan/knobs.cc b/o3d/compiler/puritan/knobs.cc new file mode 100644 index 0000000..d36a89e --- /dev/null +++ b/o3d/compiler/puritan/knobs.cc @@ -0,0 +1,783 @@ +/* + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "knobs.h" +#include <sstream> +#include <iomanip> +#include <iostream> +#include "rand.h" + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +// Knobs control the behavior of Puritan and keep track of what's happened. + +namespace Salem +{ +namespace Puritan +{ +static Knob *link; + +Knobs::Knobs (void) + : + top_level_statements +("--top-level-statements", + "\t\tNumber of statements at the top level\n", + 1, + 3), + + for_count + ("--for-count", + "\t\tNumber of for loops in code\n", + 0, + 2), + + while_count + ("--while-count", + "\t\tNumber of while loops in code\n", + 0, + 2), + + do_count + ("--do-count", + "\t\tNumber of do loops in code\n", + 0, + 1), + + if_count + ("--if-count", + "\t\tNumber of ifs in code\n", + 0, + 5), + + block_count + ("--block-count", + "\t\tNumber of blocks in code\n", + 0, + 3), + + code_limit + ("--code-limit", + "\t\tMaximum number of code nodes\n", + 200), + + exp_limit + ("--exp-limit", + "\t\tMaximum number of expression nodes\n", + 100), + + exp_count + ("--exp-count", + "\t\tNumber of expressions in code\n", + 6, + 16), + + func_count + ("--func-count", + "\t\tNumber of functions in code\n", + 1, + 9), + + func_trim + ("--func-trim", + "\t\tSize factor to apply to callee functions\n", + 0.7), + + arg_in_chance + ("--args-in-chance", + "\t\tChance argument may be just input\n", + 0.4), + + arg_out_chance + ("--args-out-chance", + "\t\tAfter input, chance argument may be just output\n", + 0.4), + + for_nesting + ("--for-nest", + "\t\tNumber of for loops inside for loops\n", + 0, + 9), + + while_nesting + ("--while-nest", + "\t\tNumber of while loops inside while loops\n", + 0, + 4), + + block_nesting + ("--block-nest", + "\t\tNumber of blocks inside blocks\n", + 0, + 1), + + do_nesting + ("--do-nest", + "\t\tNumber of do loops inside do loops\n", + 0, + 4), + + if_nesting + ("--if-nest", + "\t\tNumber of ifs inside ifs\n", + 0, + 9), + + block_length + ("--block-length", + "\t\tNumber of statements in a block.\n", + 2, + 7), + + expression_depth + ("--exp-depth", + "\t\tRange of expression complexity\n", + 1, + 7), + + special_chance + ("--special-chance", + "\t\tProbability at each expression point of a special phrase.\n", + 0.2), + + float4_chance + ("--float4-chance", + "\t\tProbability that an expression will have a float4 constructor.\n", + .03), + + float4_struct_member_chance + ("--float4-struct-member-chance", + "\t\tProbability that an element of the output struct will be float4.\n", + .90), + + float2_chance + ("--float2-chance", + "\t\tProbability that an expression will have a float2 constructor.\n", + 0.03), + + func_chance + ("--func-chance", + "\t\tAfter special, probability of an intrinsic function.\n", + 0.1), + + term_chance + ("--terminal-chance", + "\t\tAfter func, probability a terminal.\n", + 0.2), + + unary_chance + ("--unary-chance", + "\t\tAfter terminal, probabaility of a unary op.\n", + 0.05), + + swizzle_chance + ("--swizzle-chance", + "\t\tAfter unrary, chance that term will be a swizzle.\n", + 0.35), + + fcall_chance + ("--fcall-chance", + "\t\tAfter swizzle, probability of a function call.\n", + 0.25), + + copy_swizzle_chance + ("--copy-swizzle-chance", + "\t\tChance a simple non converting copy will be a swizzle.\n", + 0.3), + + noinline_chance + ("--fnoinline-chance", + "\t\tProbability a function will be declared noinline.\n", + 0.25), + + lhs_swizzle_chance + ("--lhs-swizzle-chance", + "\t\tProbabaility of a swizzle as an lval.\n", + 1.0), + + assop_chance + ("--assop-chance", + "\t\tProbability of a fancy assignment operator as assignment.\n", + 0.1), + + selfmod_chance + ("--selfmod-chance", + "\t\tProbability that an assignment will really be a selfmodify.\n", + 0.1), + + trifunc_chance + ("--trifunc-chance", + "\t\tProbability of a trinary intrinsic.\n", + 0.2), + + binfunc_chance + ("--binary-chance", + "\t\tAfter trinary, probabaility of a binary intrinsic instead of unary.\n", + 0.8), + + relop_chance + ("--relop-chance", + "\t\tIf there's going to be a binop," + "probability that it will be a relation.\n", + 0.1), + + relop_cond_chance + ("--relop-cond-chance", + "\t\tNear the end of an expression in a test, " + "chance that the op will be a compare\n", + 0.9), + + type_change_chance + ("--type-change-chance", + "\t\tProbability that the type of a subexpression will be different " + "to the expression.\n", + 0.01), + + type_float4_chance + ("--type-float4-chance", + "\t\tProbability that a subexpression type will be float4.\n", + 0.9), + + type_float2_chance + ("--type-float2-chance", + "\t\tAfter float4," + "probability that a subexpression type will be float2 instead of float.\n", + 0.9), + + sampler_count + ("--sampler-count", + "\t\tNumber of samplers used\n", + 0, + 9), + + sampler_chance + ("--sampler-chance", + "\t\tProbability that an expression will use a sampler\n", + .4), + + uniform_count + ("--uniform-count", + "\t\tNumber of unforms used\n", + 0, + 9), + + uniform_chance + ("--unform-chance", + "\t\tProbability that an expression will use a uniform\n", + .4), + + arg_count + ("--arg-count", + "\t\tNumber of arguments to functions\n", + 1, + 3), + + static_initializer_depth + ("--static-initializer-depth", + "\t\tRange of static initializer expression complexity\n", + 1, + 2), + + standalone + ("--standalone", + "\t\tIf the output should work outside the framework\n", + false), + + seed + ("--seed", + "\t\tSeed for the random number generator\n", + 0), + + variable_reuse + ("--variable-reuse", + "\t\tRatio of variables reused to created in expressions\n", + 0.90), + + array_use + ("--array-use", + "\t\tRatio of array terms in terms in expressions\n", + 0.2), + + array_reuse + ("--array-reuse", + "\t\tRatio of array terms reused to created in expressions\n", + 0.95), + + array_constness + ("--array-constness", + "\t\tProportion of array refs which are references to const arrays\n", + 1.), + + array_index_const + ("--array-index-const", + "\t\tProportion of array references which have a constant index\n", + 1.), + + array_in_for_use + ("--array-in-for", + "\t\tProportion of array references which use a loop index, lhs only.\n", + 0.), + + if_elses + ("--if-elses", + "\t\tProportion of ifs which have elses.\n", + 0.30), + + loop_breaks + ("--loop-breaks", + "\t\tProportion of loops which have breaks.\n", + 0.80), + + multiple_stmt + ("--multiple-stmt", + "\t\tRatio of single statements to blocks.\n", + 0.30), + + constant_use + ("--constant-use", + "\t\tRatio of constants to variables in expressions.\n", + 0.30), + + constant_small + ("--constant-small", + "\t\tChance a constant will be between 0 and 1.\n", + 0.90), + +// random_names +// ("--random-names", +// "\t\tShould names be random or easy on the eyes\n", +// false), + + int_variables + ("--int-variables", + "\t\tDeclare integer variables and use them in expressions\n", + false), + + allow_two_negs + ("--allow-two-negs", + "\t\tAllow two negs in an expression\n", + false), + first (link) +{ + link = 0; +} + +RangeKnob::RangeKnob (const char *_name, + const char *_help, + int _from, int _to) + :Knob (_name, _help), + from (_from), to (_to) +{ +} + +IntKnob::IntKnob (const char *_name, + const char *_help, + int _val) + :Knob (_name, _help), val (_val) +{ +} + +BoolKnob::BoolKnob (const char *_name, + const char *_help, + bool _x) + :Knob (_name, _help), val (_x) +{ +} + +ProbKnob::ProbKnob (const char *_name, + const char *_help, + double _x) + :Knob (_name, _help), prob (_x) +{ +} + +void RangeKnob::set (int a, int b) +{ + from = a; + to = b; +} + +// link together the members so we can iterate simply through the struct +// elements. + + +Knob::~Knob () +{ +} + +Knob::Knob (const char *_name, const char *_help) + :prev (link), + name (_name), help (_help) +{ + link = this; +} + + +void RangeKnob::to_stream (std::ostream & out) const +{ + out << name << "=" << from; + if (from != to) + out << "," << to; +} + +void IntKnob::to_stream (std::ostream & out) const +{ + out << name << "=" << val; +} + +void BoolKnob::to_stream (std::ostream & out) const +{ + out << name << "=" << (val ? "t" : "f") ; +} + +void BoolKnob::usage (std::ostream & out) const +{ + out << (name) << "=" << "[t|f] "; + out << (val ? "{t}" : "{f}") << "\n" << help; +} + +void ProbKnob::usage (std::ostream & out) const +{ + char t[1000]; + sprintf (t, "%s = <0.0 <= x <= 1.0> {%g}\n%s", name, prob, help); + out << t; +} + +void IntKnob::usage (std::ostream & out) const +{ + out << (name) << "=" << "<int>"; + out << " {" << val << "}\n" << help; +} + +void RangeKnob::usage (std::ostream & out) const +{ + out << (name) << "=" << "<int>,<int>"; + out << " {" << from; + if (from != to) + out << "," << to; + out << "}\n" << help; +} + +bool BoolKnob::set_from_argument (const char *arg) +{ + if (arg[0] == 't' || arg[0] == '1') + { + val = true; + return true; + } + if (arg[0] == 'f' || arg[0] == '0') + { + val = false; + return true; + } + return false; +} + +bool ProbKnob::set_from_argument (const char *arg) +{ + char *finish; + prob = strtod (arg, &finish); + return (arg != finish); +} + +bool IntKnob::set_from_argument (const char *arg) +{ + char *finish; + val = strtol (arg, &finish, 0); + return (arg != finish); +} + +int IntKnob::get () const +{ + return val; +} + +unsigned IntKnob::uget () const +{ + return val; +} + +bool RangeKnob::set_from_argument (const char *val) +{ + long int a, b; + char *next; + a = strtol (val, &next, 0); + + if (next == val) + { + return false; + } + + if (*next == 0) + { + from = a; + to = a; + return true; + } + + if (*next != ',') + { + return false; + } + + char *next_2; + next++; + b = strtol (next, &next_2, 0); + if (next_2 == next || *next_2 != 0) + return false; + + from = a; + to = b; + return true; +} + +bool Knobs::parse_argument (const char *arg) +{ + for (Knob * l = first; l; l = l->prev) + { + if (strncmp (l->name, arg, strlen (l->name)) == 0) + { + const char *val = strchr (arg, '='); + if (val) + return l->set_from_argument (val + 1); + } + } + return false; +} + +std::ostream & operator << (std::ostream &out, const Knobs& x) +{ + unsigned j = 0; + for (Knob * l = x.first; l; l = l->prev) + { + std::ostringstream tmp; + l->to_stream (tmp); + out << std::setw(30) << tmp.str(); + j++; + if (j == 3) + { + out << "\n"; + j = 0; + } + } + + return out; +} + +std::string Knobs::usage () +{ + std::ostringstream tmp; + Knobs dummy = Knobs (); + + for (Knob * l = dummy.first; l; l = l->prev) + { + l->usage (tmp); + tmp << "\n"; + } + + return tmp.str (); +} + +bool BoolKnob::operator () () const +{ + return val; +} + +void BoolKnob::set (bool x) +{ + val = x; +} + +bool ProbKnob::operator () (Rand * r) const +{ + double rnd = r->rnd_flt (); + return prob > rnd; +} + +void ProbKnob::to_stream (std::ostream & out) const +{ + char t[1000]; + sprintf (t, "%s=%g", name, prob); + out << t; +} + +double ProbKnob::get () const +{ + return prob; +} + +int RangeKnob::operator () (Rand * r) const +{ + return r->range (from, to); +} + +unsigned RangeKnob::random_uint (Rand * r) const +{ + return r->range (from, to); +} + +////////////////////////////////////////////////////////////////////// +// +// Coverage +// Used for random selections and maintaining stats. + +// pointer to head of choice list, so we can look through choices later and +// generate stats. +Coverage * Coverage::head = 0; + +Coverage::Coverage (std::string _title) + :title (_title), + prev (head) +{ + head = this; +} + +Coverage:: ~ Coverage () +{ +} + +void Coverage::increment (size_t idx) +{ + if (idx >= count.size ()) + { + count.resize (idx + 1); + + } + count[idx]++; +} + +std::ostream &operator<<(std::ostream &out, const Coverage &thing) +{ + thing.output_worker (out); + return out; +} + +StrCoverage:: StrCoverage (const char *_title, + const char **_selections):Coverage (_title) +{ + while (*_selections) + { + width = std::max (width, strlen (*_selections)); + selections.push_back (*_selections); + count.push_back (0); + _selections++; + } +// round to tab size + width = (width + 7) & -8; +} + +std::string StrCoverage::choose (class Rand * r) +{ + size_t idx = r->srange (0, count.size ()); + increment (idx); + return selections[idx]; +} + +void StrCoverage::output_worker (std::ostream & out) const +{ + unsigned items = 0; + out << title << "\n"; + size_t online = 0; + for (unsigned i = 0; i < count.size (); i++) + { + out << " |"; + out.fill (' '); + out.width (static_cast<int>(width)); + out << selections[i]; + out.fill (' '); + out.width (6); + out << count[i]; + out.width (0); + online += width + 6; + items++; + if (items > 4 || online > 60) + { + out << " |\n"; + items = 0; + online = 0; + } + } + if (online) + { + out << " |\n"; + } + if (prev) + { + prev->output_worker (out); + } +} + +IntCoverage::IntCoverage (const char *_title):Coverage (_title) +{ +} + +void IntCoverage::output_worker (std::ostream & out) const +{ + unsigned items = 0; + out << title << "\n"; + + for (unsigned i = 0; i < count.size (); i++) + { + out << "|"; + out << std::setw(4) << i ; + + if (count[i]) + { + out << std::setw(6) << count[i]; + } + else + { + out << std::setw(6) << "****"; + } + items++; + if (items > 4) + { + out << "\n"; + items = 0; + } + } + + if (items) + { + out << "\n"; + } + + if (prev) + { + prev->output_worker (out); + } +} + + +} +} |