/* * For converting param specs for Regions and LinkPolicies */ ValueMap toValueMap(const char *yamlstring, Collection<ParameterSpec> ¶meters, const std::string &nodeType, const std::string ®ionName) { 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 ®ion(*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); } }