Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for NEURON {RANDOM ranvar1, ranvar2, ...} statement. #1125

Merged
merged 12 commits into from
Feb 8, 2024
Merged
23 changes: 23 additions & 0 deletions src/codegen/codegen_coreneuron_cpp_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,15 @@
}


void CodegenCoreneuronCppVisitor::print_first_random_var_index_getter() {
printer->add_newline(2);
print_device_method_annotation();
printer->push_block("static inline int first_random_var_index()");
printer->fmt_line("return {};", info.first_random_var_index);
printer->pop_block();
}


void CodegenCoreneuronCppVisitor::print_num_variable_getter() {
printer->add_newline(2);
print_device_method_annotation();
Expand Down Expand Up @@ -2293,6 +2302,19 @@
printer->fmt_push_block("static void {}(NrnThread* nt, Memb_list* ml, int type)",
method_name(naming::NRN_PRIVATE_DESTRUCTOR_METHOD));
cast_inst_and_assert_validity();

// delete random streams
if (info.random_variables.size()) {
printer->add_line("int pnodecount = ml->_nodecount_padded;");
printer->add_line("int nodecount = ml->nodecount;");
printer->add_line("Datum* indexes = ml->pdata;");
printer->push_block("for (int id = 0; id < nodecount; id++)");
for (const auto& var: info.random_variables) {
const auto& name = get_variable_name(var->get_name());
printer->fmt_line("nrnran123_deletestream((nrnran123_State*){});", name);

Check warning on line 2314 in src/codegen/codegen_coreneuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_coreneuron_cpp_visitor.cpp#L2308-L2314

Added lines #L2308 - L2314 were not covered by tests
}
printer->pop_block();

Check warning on line 2316 in src/codegen/codegen_coreneuron_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_coreneuron_cpp_visitor.cpp#L2316

Added line #L2316 was not covered by tests
}
print_instance_struct_delete_from_device();
printer->add_multi_line(R"CODE(
delete inst;
Expand Down Expand Up @@ -3561,6 +3583,7 @@

void CodegenCoreneuronCppVisitor::print_common_getters() {
print_first_pointer_var_index_getter();
print_first_random_var_index_getter();
print_net_receive_arg_size_getter();
print_thread_getters();
print_num_variable_getter();
Expand Down
7 changes: 7 additions & 0 deletions src/codegen/codegen_coreneuron_cpp_visitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,13 @@ class CodegenCoreneuronCppVisitor: public CodegenCppVisitor {
void print_first_pointer_var_index_getter();


/**
* Print the getter method for index position of first RANDOM variable
*
*/
void print_first_random_var_index_getter();


/**
* Print the getter methods for float and integer variables count
*
Expand Down
38 changes: 36 additions & 2 deletions src/codegen/codegen_cpp_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "codegen/codegen_helper_visitor.hpp"
#include "codegen/codegen_utils.hpp"
#include "visitors/rename_visitor.hpp"
#include "visitors/visitor_utils.hpp"

namespace nmodl {
namespace codegen {
Expand Down Expand Up @@ -145,7 +146,6 @@
return function && function->has_any_property(properties);
}


int CodegenCppVisitor::float_variables_size() const {
return codegen_float_variables.size();
}
Expand Down Expand Up @@ -235,7 +235,20 @@

void CodegenCppVisitor::print_function_call(const FunctionCall& node) {
const auto& name = node.get_node_name();
auto function_name = name;

// return C++ function name for RANDOM construct function
// e.g. nrnran123_negexp for random_negexp
auto get_renamed_random_function =
[&](const std::string& name) -> std::pair<std::string, bool> {
if (codegen::naming::RANDOM_FUNCTIONS_MAPPING.count(name)) {
return {codegen::naming::RANDOM_FUNCTIONS_MAPPING[name], true};

Check warning on line 244 in src/codegen/codegen_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_cpp_visitor.cpp#L244

Added line #L244 was not covered by tests
}
return {name, false};
};
std::string function_name;
bool is_random_function;
std::tie(function_name, is_random_function) = get_renamed_random_function(name);

if (defined_method(name)) {
function_name = method_name(name);
}
Expand Down Expand Up @@ -265,6 +278,12 @@
}
}

// first argument to random functions need to be type casted
// from void* to nrnran123_State*.
if (is_random_function && !arguments.empty()) {
printer->add_text("(nrnran123_State*)");

Check warning on line 284 in src/codegen/codegen_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_cpp_visitor.cpp#L284

Added line #L284 was not covered by tests
}

print_vector_elements(arguments, ", ");
printer->add_text(')');
}
Expand Down Expand Up @@ -684,6 +703,15 @@
index += size;
}

for (auto& var: info.random_variables) {
if (info.first_random_var_index == -1) {
info.first_random_var_index = index;

Check warning on line 708 in src/codegen/codegen_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_cpp_visitor.cpp#L707-L708

Added lines #L707 - L708 were not covered by tests
}
int size = var->get_length();
info.semantics.emplace_back(index, naming::RANDOM_SEMANTIC, size);
index += size;

Check warning on line 712 in src/codegen/codegen_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_cpp_visitor.cpp#L710-L712

Added lines #L710 - L712 were not covered by tests
}

if (info.diam_used) {
info.semantics.emplace_back(index++, naming::DIAM_VARIABLE, 1);
}
Expand Down Expand Up @@ -863,6 +891,12 @@
}
}

for (const auto& var: info.random_variables) {
auto name = var->get_name();
variables.emplace_back(make_symbol(name), true);
variables.back().symbol->add_properties(NmodlType::random_var);

Check warning on line 897 in src/codegen/codegen_cpp_visitor.cpp

View check run for this annotation

Codecov / codecov/patch

src/codegen/codegen_cpp_visitor.cpp#L895-L897

Added lines #L895 - L897 were not covered by tests
}

if (info.diam_used) {
variables.emplace_back(make_symbol(naming::DIAM_VARIABLE));
}
Expand Down
6 changes: 6 additions & 0 deletions src/codegen/codegen_helper_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ void CodegenHelperVisitor::find_non_range_variables() {
// clang-format on
info.pointer_variables = psymtab->get_variables_with_properties(properties);

/// find RANDOM variables
// clang-format off
properties = NmodlType::random_var;
// clang-format on
info.random_variables = psymtab->get_variables_with_properties(properties);

// find special variables like diam, area
// clang-format off
properties = NmodlType::assigned_definition
Expand Down
6 changes: 6 additions & 0 deletions src/codegen/codegen_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,15 @@ struct CodegenInfo {
/// pointer or bbcore pointer variables
std::vector<SymbolType> pointer_variables;

/// RANDOM variables
std::vector<SymbolType> random_variables;

/// index/offset for first pointer variable if exist
int first_pointer_var_index = -1;

/// index/offset for first RANDOM variable if exist
int first_random_var_index = -1;

/// tqitem index in integer variables
/// note that if tqitem doesn't exist then the default value should be 0
int tqitem_index = 0;
Expand Down
19 changes: 16 additions & 3 deletions src/codegen/codegen_naming.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

#pragma once

#include <map>
#include <string>
#include <unordered_map>


namespace nmodl {
Expand Down Expand Up @@ -119,6 +119,9 @@ static constexpr char POINTER_SEMANTIC[] = "pointer";
/// semantic type for core pointer variable
static constexpr char CORE_POINTER_SEMANTIC[] = "bbcorepointer";

/// semantic type for RANDOM variable
static constexpr char RANDOM_SEMANTIC[] = "random";

/// semantic type for net send call
static constexpr char NET_SEND_SEMANTIC[] = "netsend";

Expand Down Expand Up @@ -174,7 +177,7 @@ static constexpr char NRN_POINTERINDEX[] = "hoc_nrnpointerindex";
/// commonly used variables in verbatim block and how they
/// should be mapped to new code generation backends
// clang-format off
const std::map<std::string, std::string> VERBATIM_VARIABLES_MAPPING{
static const std::unordered_map<std::string, std::string> VERBATIM_VARIABLES_MAPPING{
{"_nt", "nt"},
{"_p", "data"},
{"_ppvar", "indexes"},
Expand All @@ -183,8 +186,18 @@ static constexpr char NRN_POINTERINDEX[] = "hoc_nrnpointerindex";
{"_cntml_padded", "pnodecount"},
{"_cntml", "nodecount"},
{"_tqitem", "tqitem"}};
// clang-format on

// Functions available in NMODL with RANDOM construct and their mapping to
// C++ functions for Random123 interface.
static std::unordered_map<std::string, std::string> RANDOM_FUNCTIONS_MAPPING{
{"random_setseq", "nrnran123_setseq"},
{"random_setids", "nrnran123_setids"},
{"random_uniform", "nrnran123_uniform"},
{"random_negexp", "nrnran123_negexp"},
{"random_normal", "nrnran123_normal"},
{"random_ipick", "nrnran123_ipick"},
{"random_dpick", "nrnran123_dblpick"}};
// clang-format on
} // namespace naming
} // namespace codegen
} // namespace nmodl
2 changes: 2 additions & 0 deletions src/language/code_generator.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ set(AST_GENERATED_SOURCES
${PROJECT_BINARY_DIR}/src/ast/procedure_block.hpp
${PROJECT_BINARY_DIR}/src/ast/program.hpp
${PROJECT_BINARY_DIR}/src/ast/protect_statement.hpp
${PROJECT_BINARY_DIR}/src/ast/random_var.hpp
${PROJECT_BINARY_DIR}/src/ast/random_var_list.hpp
${PROJECT_BINARY_DIR}/src/ast/range.hpp
${PROJECT_BINARY_DIR}/src/ast/range_var.hpp
${PROJECT_BINARY_DIR}/src/ast/react_var_name.hpp
Expand Down
30 changes: 29 additions & 1 deletion src/language/nmodl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,14 @@
type: Name
node_name: true

- RandomVar:
brief: "Single variable of type RANDOM. pointer to a nrnran123_State"
members:
- name:
brief: "Name of the a RANDOM variable"
type: Name
node_name: true

- BbcorePointerVar:
members:
- name:
Expand All @@ -415,7 +423,7 @@
- Block:
brief: "Base class for all block scoped nodes"
description: |
NMODL has different local and global block scoped nodes like
NMODL has different local and globals block scoped nodes like
ast::NeuronBlock, ast::ParamBlock, ast::IfStatement etc. Ast::Block
is base class and defines common interface for these nodes.

Expand Down Expand Up @@ -1731,13 +1739,33 @@
separator: ", "
brief: "Represents GLOBAL statement in NMODL"

- RandomVarList:
brief: "Represents RANDOM statement in NMODL"
nmodl: "RANDOM "
members:
- variables:
brief: "Vector of random variables"
type: RandomVar
vector: true
separator: ", "
description: |
Here is an example of RANDOM statement

\code{.mod}
NEURON {
THREADSAFE
POINT_PROCESS NetStim
RANDOM ranvar
\endcode

- Pointer:
nmodl: "POINTER "
members:
- variables:
brief: "Vector of pointer variables"
type: PointerVar
vector: true
add: true
separator: ", "
brief: "Represents POINTER statement in NMODL"

Expand Down
1 change: 1 addition & 0 deletions src/language/node_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"GlobalVar",
"PointerVar",
"BbcorePointerVar",
"RandomVar",
"ExternVar",
"PrimeName",
"ConstantVar",
Expand Down
2 changes: 2 additions & 0 deletions src/lexer/nmodl_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ SymbolType token_symbol(const std::string& key, PositionType& pos, TokenType typ
return Parser::make_PROCEDURE(token, pos);
case Token::PROTECT:
return Parser::make_PROTECT(token, pos);
case Token::RANDOM:
return Parser::make_RANDOM(token, pos);
case Token::RANGE:
return Parser::make_RANGE(token, pos);
case Token::READ:
Expand Down
1 change: 1 addition & 0 deletions src/lexer/token_mapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ const static std::map<std::string, TokenType> keywords = {
{"CHARGE", Token::VALENCE},
{"GLOBAL", Token::GLOBAL},
{"POINTER", Token::POINTER},
{"RANDOM", Token::RANDOM},
{"BBCOREPOINTER", Token::BBCOREPOINTER},
{"EXTERNAL", Token::EXTERNAL},
{"INCLUDE", Token::INCLUDE1},
Expand Down
24 changes: 24 additions & 0 deletions src/parser/nmodl.yy
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
%token <ModToken> PROCEDURE
%token <ModToken> PROTECT
%token <ModToken> RANGE
%token <ModToken> RANDOM
%token <ModToken> REACT1
%token <ModToken> REACTION
%token <ModToken> READ
Expand Down Expand Up @@ -293,6 +294,7 @@
%type <ast::GlobalVarVector> global_var_list
%type <ast::PointerVarVector> pointer_var_list
%type <ast::BbcorePointerVarVector> bbcore_pointer_var_list
%type <ast::RandomVarVector> random_var_list
%type <ast::ExternVarVector> external_var_list
%type <ast::Valence*> valence
%type <ast::ExpressionStatement*> initial_statement
Expand Down Expand Up @@ -1987,6 +1989,11 @@ neuron_statement :
$1.emplace_back(new ast::BbcorePointer($3));
$$ = $1;
}
| neuron_statement RANDOM random_var_list
{
$1.emplace_back(new ast::RandomVarList($3));
$$ = $1;
}
| neuron_statement EXTERNAL external_var_list
{
$1.emplace_back(new ast::External($3));
Expand Down Expand Up @@ -2195,6 +2202,23 @@ bbcore_pointer_var_list : NAME_PTR
;


random_var_list : NAME_PTR
{
$$ = ast::RandomVarVector();
$$.emplace_back(new ast::RandomVar($1));
}
| random_var_list "," NAME_PTR
{
$1.emplace_back(new ast::RandomVar($3));
$$ = $1;
}
| error
{
error(scanner.loc, "random_var_list");
}
;


external_var_list : NAME_PTR
{
$$ = ast::ExternVarVector();
Expand Down
6 changes: 6 additions & 0 deletions src/symtab/symbol_properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
*/

#include <string>
#include <unordered_map>
#include <vector>

#include "codegen/codegen_naming.hpp"
#include "symtab/symbol_properties.hpp"
#include "utils/string_utils.hpp"

Expand Down Expand Up @@ -159,6 +161,10 @@
properties.emplace_back("codegen_var");
}

if (has_property(obj, NmodlType::random_var)) {
properties.emplace_back("random_var");

Check warning on line 165 in src/symtab/symbol_properties.cpp

View check run for this annotation

Codecov / codecov/patch

src/symtab/symbol_properties.cpp#L165

Added line #L165 was not covered by tests
}

return properties;
}

Expand Down
Loading
Loading