예제 #1
0
/*
 * For converting param specs for Regions and LinkPolicies
 */
ValueMap toValueMap(const char *yamlstring,
                    Collection<ParameterSpec> &parameters,
                    const std::string &nodeType,
                    const std::string &regionName) {

  ValueMap vm;

  // special value that applies to all regions.
  ParameterSpec dim_spec("Buffer dimensions for region's global dimensions. "
                    "Syntax: {dim: [2,3]}",  // description
	                  NTA_BasicType_UInt32,
							      0,                         // elementCount (an array of unknown size)
							      "",                        // constraints
							      "",                        // defaultValue
							      ParameterSpec::ReadWriteAccess);


  std::string paddedstring(yamlstring);
  // TODO: strip white space to determine if empty
  bool empty = (paddedstring.size() == 0);

  // TODO: utf-8 compatible?
  const YAML::Node doc = YAML::Load(paddedstring);
  if(!empty) {
    // A ValueMap is specified as a dictionary
    if (doc.Type() != YAML::NodeType::Map) {
      std::string ys(yamlstring);
      if (ys.size() > 30) {
        ys = ys.substr(0, 30) + "...";
      }
      NTA_THROW
          << "YAML string '" << ys
          << "' does not not specify a dictionary of key-value pairs. "
          << "Region and Link parameters must be specified as a dictionary";
    }
  }
  // Grab each value out of the YAML dictionary and put into the ValueMap
  // if it is allowed by the nodespec.
  for (auto i = doc.begin(); i != doc.end(); i++)
  {
    ParameterSpec ps;

    const auto key = i->first.as<std::string>();
    if (key == "dim")
      ps = dim_spec;
    else {
      if (!parameters.contains(key))
      {
        std::stringstream ss;
        for (UInt j = 0; j < parameters.getCount(); j++){
          ss << "   " << parameters.getByIndex(j).first << "\n";
        }

        if (nodeType == std::string("")) {
          NTA_THROW << "Unknown parameter '" << key << "'\n"
                    << "Valid parameters are:\n" << ss.str();
        } else {
          NTA_CHECK(regionName != std::string(""));
          NTA_THROW << "Unknown parameter '" << key << "' for region '"
                    << regionName << "' of type '" << nodeType << "'\n"
                    << "Valid parameters are:\n"
                    << ss.str();
        }
      }
      ps = parameters.getByName(key); // makes a copy of ParameterSpec
    }
    if (vm.contains(key))
        NTA_THROW << "Parameter '" << key << "' specified more than once in YAML document";
    try
    {
      if (ps.accessMode == ParameterSpec::ReadOnlyAccess) {
        NTA_THROW << "Parameter '" << key << "'. This is ReadOnly access. Cannot be set.";
      }
      Value v = toValue(i->second, ps.dataType);
      if (v.isScalar() && ps.count != 1)
      {
        NTA_THROW << "Parameter '" << key << "'. Bad value in runtime parameters. Expected array value but got scalar value";
      }
      if (!v.isScalar() && ps.count == 1)
      {
        NTA_THROW << "Parameter '" << key << "'. Bad value in runtime parameters. Expected scalar value but got array value";
      }
      vm.add(key, v);
    } catch (std::runtime_error &e) {
      NTA_THROW << "Unable to set parameter '" << key << "'. " << e.what();
    }
  } //end for

  // Populate ValueMap with default values if they were not specified in the YAML dictionary.
  for (size_t i = 0; i < parameters.getCount(); i++)
  {
    const std::pair<std::string, ParameterSpec>& item = parameters.getByIndex(i);
    if (!vm.contains(item.first))
    {
      const ParameterSpec & ps = item.second;
      if (ps.defaultValue != "")
      {
        // TODO: This check should be uncommented after dropping NuPIC 1.x nodes (which don't comply) //FIXME try this
        // if (ps.accessMode != ParameterSpec::CreateAccess)
        // {
        //   NTA_THROW << "Default value for non-create parameter: " << item.first;
        // }

        try {
#ifdef YAMLDEBUG
          NTA_DEBUG << "Adding default value '" << ps.defaultValue
                    << "' to parameter " << item.first << " of type "
                    << BasicType::getName(ps.dataType) << " count " << ps.count;
#endif
          // NOTE: this can handle both scalers and arrays
          //       Arrays MUST be in Yaml sequence format even if one element.
          //       i.e.  [1,2,3]
          Value v = toValue(ps.defaultValue, ps.dataType);
          if (v.isScalar() && ps.count != 1)
          {
            NTA_THROW << "Parameter '" << item.first << "'. Bad default value in spec. Expected array value but got scalar value";
          }
          if (!v.isScalar() && ps.count == 1)
          {
            NTA_THROW << "Parameter '" << item.first << "'. Bad default value in spec. Expected scalar value but got array value";
          }
          vm.add(item.first, v);
        } catch (...) {
          NTA_THROW << "Unable to set default value for item '" << item.first
                    << "' of datatype " << BasicType::getName(ps.dataType)
                    << " with value '" << ps.defaultValue << "'";
        }
      }
    }
  }

  return vm;
}
    void SSValgrind::run(DTO& dto)
    {
        PragmaCustomCompilerPhase::run(dto);

        // Now look for all function calls that we know are CSS functions

        ScopeLink sl = dto["scope_link"];
        AST_t a = dto["translation_unit"];

        ObjectList<AST_t> all_function_calls = a.depth_subtrees(PredicateAttr(LANG_IS_FUNCTION_CALL));

        for (ObjectList<AST_t>::iterator it = all_function_calls.begin();
                it != all_function_calls.end();
                it++)
        {
            Expression function_call(*it, sl);

            Expression function_called_expresion = function_call.get_called_expression();
            ObjectList<Expression> arguments = function_call.get_argument_list();
            if (!function_called_expresion.is_id_expression())
                // We do not handle indirect calls (through variables)
                continue;

            Scope sc = sl.get_scope(*it);

            AugmentedSymbol symbol = function_called_expresion.get_id_expression().get_computed_symbol();

            // This is a CSS task
            if (!symbol.is_valid() 
                    || !symbol.is_task())
                continue;

            AST_t decl_tree = symbol.get_point_of_declaration();

            ObjectList<ParameterDeclaration> parameter_decls;
            if (FunctionDefinition::predicate(decl_tree))
            {
                FunctionDefinition function_def(decl_tree, sl);
                DeclaredEntity entity = function_def.get_declared_entity();
                parameter_decls = entity.get_parameter_declarations();
            }
            else
            {
                Declaration declaration(decl_tree, sl);
                DeclaredEntity entity ( declaration.get_declared_entities()[0] );
                parameter_decls = entity.get_parameter_declarations();
            }

            int i = 0;
            ReplaceSrcIdExpression replace_parameters(sl);
            for (ObjectList<ParameterDeclaration>::iterator param_decl_it = parameter_decls.begin();
                    param_decl_it != parameter_decls.end();
                    param_decl_it++, i++)
            {
                replace_parameters.add_replacement(param_decl_it->get_name().get_symbol(),
                        "(" + arguments[i].prettyprint() + ")");
            }

            Source new_code, data_info;

            new_code
                << "{"
                << "int temp_sp_ssvalgrind;"
                << "start_task_valgrind(&temp_sp_ssvalgrind, \"" << symbol.get_name() << "\");"
                << data_info
                << function_call.prettyprint() << ";"
                << "end_task_valgrind();"
                << "}"
                ;

            ObjectList<Type> parameters = symbol.get_type().nonadjusted_parameters();
            RefPtr<ParameterRegionList> parameter_region_list = symbol.get_parameter_region_list();

            ObjectList<ParameterDeclaration>::iterator param_decl_it2 = parameter_decls.begin();
            i = 0;
            for (ObjectList<RegionList>::iterator region_list_it = parameter_region_list->begin();
                    region_list_it != parameter_region_list->end();
                    region_list_it++, i++, param_decl_it2++)
            {
                Type base_type = parameters[i];

                Source array_factor; 

                if (base_type.is_pointer())
                {
                    base_type = base_type.points_to();
                }
                else if (base_type.is_reference())
                {
                    base_type = base_type.references_to();
                }
                else if (base_type.is_array())
                {
                    while (base_type.is_array())
                    {
                        Source expr;
                        expr << "(" << base_type.array_get_size().prettyprint() << ")";
                        array_factor << "*" << expr;

                        base_type = base_type.array_element();
                    }
                }

                DEBUG_CODE()
                {
                    std::cerr << "SS-VALGRIND: base_type: " << base_type.get_declaration(function_call.get_scope(), "") << std::endl;
                }

                for (ObjectList<Region>::iterator reg_it = region_list_it->begin();
                        reg_it != region_list_it->end();
                        reg_it++)
                {
                    Region &region(*reg_it);
                    Source register_data, addr, base_type_size, span, called_function, decl_name;

                    register_data
                        << called_function << "(\n" << decl_name << "\n," << addr << ", " << base_type_size << "," << span << ");"
                        ;
                    decl_name << "\"" << param_decl_it2->get_name() << "\"";

                    switch ((int)reg_it->get_direction())
                    {
                        case Region::INPUT_DIR:
                            {
                                called_function << "task_input_valgrind";
                                break;
                            }
                        case Region::OUTPUT_DIR:
                            {
                                called_function << "task_output_valgrind";
                                break;
                            }
                        case Region::INOUT_DIR:
                            {
                                called_function << "task_inout_valgrind";
                                break;
                            }
                        case Region::UNSPECIFIED_DIR:
                            {
                                called_function << "task_unspecified_dir_valgrind";
                                break;
                            }
                        case Region::UNKNOWN_DIR:
                            {
                                internal_error("Invalid directionality", 0);
                            }
                    }

                    if (region.get_dimension_count() == 0)
                    {
                        // Two cases: a scalar or a pointer if it is a scalar there is
                        // no need to state anything
                        if (parameters[i].is_pointer()
                                || parameters[i].is_array())
                        {
                            addr << arguments[i];
                            base_type_size
                                << "sizeof(" << base_type.get_declaration(sc, "") << ")" << array_factor;
                        }
                        else if (parameters[i].is_reference())
                        {
                            addr << "&" << arguments[i];
                            base_type_size
                                << "sizeof(" << base_type.get_declaration(sc, "") << ")";
                        }
                        else
                        {
                            // This is an awkward case
                            called_function = Source("task_input_value_valgrind");
                            addr << "0";
                            base_type_size
                                << "sizeof(" << base_type.get_declaration(sc, "") << ")";
                        }
                        span << 1;
                    }
                    else
                    {
                        Source dim_spec_src;
                        for (unsigned int j = 1;
                                j <= region.get_dimension_count();
                                j++)
                        {
                            // This list is reversed
                            Region::DimensionSpecifier &dim_spec(region[region.get_dimension_count() - j]);

                            DEBUG_CODE()
                            {
                                std::cerr
                                    << "SS-VALGRIND: Region: #" << j << std::endl
                                    << "SS-VALGRIND:  dimension_start: "  << dim_spec.get_dimension_start() << std::endl
                                    << "SS-VALGRIND:  accessed_length: "  << dim_spec.get_accessed_length() << std::endl
                                    << "SS-VALGRIND:  dimension_length: " << dim_spec.get_dimension_length() << std::endl;
                            }

                            dim_spec_src << "[" << replace_parameters.replace(dim_spec.get_dimension_start()) << "]";
                            span.append_with_separator(
                                    replace_parameters.replace(dim_spec.get_accessed_length()),
                                    "*");
                        }
                        base_type_size
                            << "sizeof(" << base_type.get_declaration(sc, "") << ")";
                        addr << "&((" << arguments[i] << ")" << dim_spec_src << ")";
                    }

                    data_info
                        << register_data
                        ;
                }
            }

            Statement enclosing_statement = function_call.get_enclosing_statement();

            AST_t new_tree = new_code.parse_statement(function_call.get_ast(), function_call.get_scope_link());
            enclosing_statement.get_ast().replace(new_tree);
        }
    }