20 using printer::JSONPrinter;
24 using utils::PerfStat;
36 bool assign_op =
false;
99 throw std::logic_error(
"Binary operator not handled in perf visitor");
109 node.get_lhs()->accept(*
this);
114 node.get_rhs()->accept(*
this);
120 const auto& values = perf.
values();
121 assert(keys.size() == values.size());
123 for (
size_t i = 0;
i < keys.size();
i++) {
136 node.visit_children(*
this);
144 auto symtab =
node.get_symbol_table();
145 if (symtab ==
nullptr) {
146 throw std::runtime_error(
"Perfvisitor : symbol table not setup for " +
147 node.get_node_type_name());
150 auto name = symtab->name();
151 if (
node.is_derivative_block()) {
159 perf.
title =
"Performance Statistics of " +
name;
171 var_set.second.clear();
183 }
else if (
name ==
"log") {
185 }
else if (
name ==
"pow") {
188 node.visit_children(*
this);
191 auto method_property = NmodlType::procedure_block | NmodlType::function_block;
192 if (symbol !=
nullptr && symbol->has_any_property(method_property)) {
205 node.visit_children(*
this);
211 node.visit_children(*
this);
217 node.visit_children(*
this);
224 node.visit_children(*
this);
234 NmodlType property = NmodlType::range_var | NmodlType::assigned_definition |
235 NmodlType::state_var;
238 for (
auto& variable: variables) {
239 if (!variable->has_any_property(NmodlType::global_var)) {
241 if (variable->has_any_property(NmodlType::param_assign)) {
244 if (variable->has_any_status(Status::localized)) {
251 property = NmodlType::state_var;
256 property = NmodlType::pointer_var | NmodlType::bbcore_pointer_var;
261 property = NmodlType::random_var;
269 property = NmodlType::global_var | NmodlType::param_assign | NmodlType::bbcore_pointer_var |
270 NmodlType::pointer_var;
273 for (
auto& variable: variables) {
274 auto is_global = variable->has_any_property(NmodlType::global_var);
275 property = NmodlType::range_var | NmodlType::assigned_definition;
276 if (!variable->has_any_property(property) || is_global) {
278 if (variable->has_any_property(NmodlType::param_assign)) {
281 if (variable->has_any_status(Status::localized)) {
291 stream <<
"#VARIABLES :: ";
305 printer->push_block(
"MemoryInfo");
307 printer->push_block(
"Instance");
323 printer->push_block(
"Pointer");
337 printer->push_block(
"BlockPerf");
340 node.visit_children(*
this);
341 std::string
title =
"Total Performance Statistics";
441 throw std::runtime_error(
"Perfvisitor : symbol table not setup for " +
442 node.get_node_type_name());
448 node.visit_children(*
this);
466 node.visit_children(*
this);
483 throw std::logic_error(
"Unary operator not handled in perf visitor");
486 node.visit_children(*
this);
498 auto is_method = symbol->has_any_property(NmodlType::extern_method | NmodlType::function_block);
503 is_method = symbol->has_any_property(NmodlType::derivative_block | NmodlType::extern_method);
512 bool is_local =
false;
514 auto properties = NmodlType::local_var | NmodlType::argument | NmodlType::function_block;
515 if (symbol->has_any_property(properties)) {
522 bool is_constant =
false;
523 auto properties = NmodlType::param_assign;
524 if (symbol->has_any_property(properties)) {
Auto generated AST classes declaration.
Represents a AFTER block in NMODL.
Represents a block to be executed before or after another block.
Represents a BEFORE block in NMODL.
Represents binary expression in the NMODL.
Represents a BREAKPOINT block in NMODL.
Represents a CONSTRUCTOR block in the NMODL.
Represents DERIVATIVE block in the NMODL.
Represents a DESTRUCTOR block in the NMODL.
Represents a INITIAL block in the NMODL.
Represents LINEAR block in the NMODL.
Represents NONLINEAR block in the NMODL.
Represents a prime variable (for ODE)
Represents top level AST node for whole NMODL input.
Represents block encapsulating list of statements.
Helper class for printing AST in JSON form.
std::vector< std::shared_ptr< Symbol > > get_variables_with_properties(syminfo::NmodlType properties, bool all=false) const
get variables with properties
std::shared_ptr< Symbol > lookup_in_scope(const std::string &name) const
check if symbol with given name exist in the current table (including all parents)
void visit_ba_block(const ast::BABlock &node) override
visit node of type ast::BABlock
std::string global_memw_key
void visit_program(const ast::Program &node) override
visit node of type ast::Program
static bool is_constant_variable(const std::shared_ptr< symtab::Symbol > &symbol)
void compact_json(bool flag)
void visit_initial_block(const ast::InitialBlock &node) override
skip initial block under net_receive block
int num_pointer_variables
count of pointer / bbcorepointer variables
void visit_constructor_block(const ast::ConstructorBlock &node) override
visit node of type ast::ConstructorBlock
int num_random_variables
count of RANDOM variables
int num_localized_global_variables
subset of global variables which are localized
symtab::SymbolTable * current_symtab
symbol table of current block being visited
std::string const_memw_key
std::string global_memr_key
void visit_breakpoint_block(const ast::BreakpointBlock &node) override
visit node of type ast::BreakpointBlock
void update_memory_ops(const std::string &name)
Find symbol in closest scope (up to parent) and update read/write count.
void visit_if_statement(const ast::IfStatement &node) override
visit node of type ast::IfStatement
void visit_name(const ast::Name &node) override
every variable used is of type name, update counters
bool visiting_lhs_expression
true while visiting lhs of binary expression (to count write operations)
utils::PerfStat total_perf
total performance of mod file
void measure_performance(const ast::Ast &node)
Helper function used by all ast nodes : visit all children recursively and performance stats get adde...
void visit_destructor_block(const ast::DestructorBlock &node) override
visit node of type ast::DestructorBlock
void visit_discrete_block(const ast::DiscreteBlock &node) override
visit node of type ast::DiscreteBlock
utils::PerfStat current_block_perf
performance of current block
int num_constant_instance_variables
subset of instance variables which are constant
void visit_derivative_block(const ast::DerivativeBlock &node) override
visit node of type ast::DerivativeBlock
int num_localized_instance_variables
subset of instance variables which are localized
std::string const_memr_key
keys used in map to track var usage
std::stack< utils::PerfStat > blocks_perf
performance stats of all blocks being visited in recursive chain
std::unique_ptr< printer::JSONPrinter > printer
to print to json file
void visit_unary_expression(const ast::UnaryExpression &node) override
visit node of type ast::UnaryExpression
void print_memory_usage()
void visit_prime_name(const ast::PrimeName &node) override
prime name derived from identifier and hence need to be handled here
void visit_function_table_block(const ast::FunctionTableBlock &node) override
visit node of type ast::FunctionTableBlock
std::map< std::string, std::set< std::string > > var_usage
map of variables to count unique read-writes
void add_perf_to_printer(const utils::PerfStat &perf) const
add performance stats to json printer
void visit_statement_block(const ast::StatementBlock &node) override
Blocks like function can have multiple statement blocks and blocks like net receive has nested initia...
void visit_before_block(const ast::BeforeBlock &node) override
visit node of type ast::BeforeBlock
void visit_function_call(const ast::FunctionCall &node) override
count function calls and "most useful" or "commonly used" math functions
void visit_solve_block(const ast::SolveBlock &node) override
solve is not a statement but could have associated block and hence could/should not be skipped comple...
void visit_else_if_statement(const ast::ElseIfStatement &node) override
visit node of type ast::ElseIfStatement
void visit_for_netcon(const ast::ForNetcon &node) override
visit node of type ast::ForNetcon
std::stringstream stream
if not json, all goes to string
void visit_binary_expression(const ast::BinaryExpression &node) override
count math operations from all binary expressions
std::stack< utils::PerfStat > children_blocks_perf
performance of current all childrens
bool under_function_call
whether function call is being visited
void visit_after_block(const ast::AfterBlock &node) override
visit node of type ast::AfterBlock
void visit_net_receive_block(const ast::NetReceiveBlock &node) override
visit node of type ast::NetReceiveBlock
int num_global_variables
count of global variables
void visit_kinetic_block(const ast::KineticBlock &node) override
visit node of type ast::KineticBlock
void visit_linear_block(const ast::LinearBlock &node) override
visit node of type ast::LinearBlock
int num_state_variables
count of state variables
void visit_non_linear_block(const ast::NonLinearBlock &node) override
visit node of type ast::NonLinearBlock
int num_instance_variables
count of per channel instance variables
void visit_procedure_block(const ast::ProcedureBlock &node) override
visit node of type ast::ProcedureBlock
bool under_solve_block
whether solve block is being visited
static bool is_local_variable(const std::shared_ptr< symtab::Symbol > &symbol)
bool under_net_receive_block
whether net receive block is being visited
bool start_measurement
whether to measure performance for current block
void visit_function_block(const ast::FunctionBlock &node) override
visit node of type ast::FunctionBlock
int num_constant_global_variables
subset of global variables which are constant
bool symbol_to_skip(const std::shared_ptr< symtab::Symbol > &symbol) const
Certain statements / symbols needs extra check while measuring read/write operations.
Helper class for printing AST in JSON form.
Status
state during various compiler passes
std::string to_string(const T &obj)
NmodlType
NMODL variable properties.
encapsulates code generation backend implementations
bool is_method(const std::string &name)
Check if given name is an integration method in NMODL.
static Node * node(Object *)
Visitor for measuring performance related information
int find(const int, const int, const int, const int, const int)
Base class for all Abstract Syntax Tree node types.
Helper class to collect performance statistics.
void print(std::stringstream &stream) const
int n_unique_global_write
std::vector< std::string > values() const
int n_int_func_call
mod functions (before/after inlining)
int n_local_read
cheap : typically local variables in mod file means registers
int n_global_read
expensive : typically access to dynamically allocated memory
int n_ext_func_call
could be external math funcs
int n_add
basic ops (<= 1 cycle)
int n_unique_constant_read
int n_unique_constant_write
std::string title
name for pretty-printing
int n_constant_read
could be optimized : access to variables that could be read-only in this case write counts are typica...
static std::vector< std::string > keys()
int n_exp
expensive functions : commonly used functions in mod files