frontends/ast/simplify.cc
// annotate the names of all wires and other named objects in a generate block
annotate the names of all wires and other named objects in a generate block
annotate the names of all wires and other named objects in a generate block
void AstNode::expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map, bool original_scope)
{
	if (!index_var.empty() && type == AST_IDENTIFIER && str == index_var) {
		if (children.empty()) {
			current_scope[index_var]->children[0]->cloneInto(this);
		} else {
			AstNode *p = new AstNode(AST_LOCALPARAM, current_scope[index_var]->children[0]->clone());
			p->str = stringf("$genval$%d", autoidx++);
			current_ast_mod->children.push_back(p);
			str = p->str;
			id2ast = p;
		}
	}
	if (type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) {
		if (name_map.count(str) > 0) {
			str = name_map[str];
		} else {
			size_t pos = str.rfind('.');
			if (pos != std::string::npos) {
				std::string existing_prefix = str.substr(0, pos);
				if (name_map.count(existing_prefix) > 0) {
					str = name_map[existing_prefix] + str.substr(pos);
				}
			}
		}
	}
	std::map<std::string, std::string> backup_name_map;
	auto prefix_node = [&](AstNode* child) {
		if (backup_name_map.size() == 0)
			backup_name_map = name_map;
		if (!original_scope) {
			name_map[child->str] = child->str;
			return;
		}
		std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix;
		size_t pos = child->str.rfind('.');
		if (pos == std::string::npos)
			pos = child->str[0] == '\\' && prefix[0] == '\\' ? 1 : 0;
		else
			pos = pos + 1;
		new_name = child->str.substr(0, pos) + new_name + child->str.substr(pos);
		if (new_name[0] != '$' && new_name[0] != '\\')
			new_name = prefix[0] + new_name;
		name_map[child->str] = new_name;
		if (child->type == AST_FUNCTION)
			replace_result_wire_name_in_function(child, child->str, new_name);
		else
			child->str = new_name;
		current_scope[new_name] = child;
	};
	for (size_t i = 0; i < children.size(); i++) {
		AstNode *child = children[i];
		switch (child->type) {
		case AST_WIRE:
		case AST_MEMORY:
		case AST_PARAMETER:
		case AST_LOCALPARAM:
		case AST_FUNCTION:
		case AST_TASK:
		case AST_CELL:
		case AST_TYPEDEF:
		case AST_ENUM_ITEM:
		case AST_GENVAR:
			prefix_node(child);
			break;
		case AST_BLOCK:
		case AST_GENBLOCK:
			if (!child->str.empty())
				prefix_node(child);
			break;
		case AST_ENUM:
			current_scope[child->str] = child;
			for (auto enode : child->children){
				log_assert(enode->type == AST_ENUM_ITEM);
				prefix_node(enode);
			}
			break;
		default:
			break;
		}
	}
	for (size_t i = 0; i < children.size(); i++) {
		AstNode *child = children[i];
		if (type == AST_PREFIX && i == 1 && child->type == AST_IDENTIFIER)
			continue;
		if (child->type == AST_FUNCTION || child->type == AST_TASK)
			child->expand_genblock(index_var, prefix, name_map, false);
		else if (child->type == AST_GENBLOCK || child->type == AST_BLOCK)
			child->expand_genblock(index_var, prefix, name_map, original_scope && child->str.empty());
		else
			child->expand_genblock(index_var, prefix, name_map, original_scope);
	}
	if (backup_name_map.size() > 0)
		name_map.swap(backup_name_map);
}
void AstNode :: expand_genblock ( std :: string index_var , std :: string prefix , std :: map < std :: string , std :: string > & name_map , bool original_scope ) { if ( ! index_var . empty ( ) && type == AST_IDENTIFIER && str == index_var ) { if ( children . empty ( ) ) { current_scope [ index_var ] -> children [ 0 ] -> cloneInto ( this ) ; } else { AstNode * p = new AstNode ( AST_LOCALPARAM , current_scope [ index_var ] -> children [ 0 ] -> clone ( ) ) ; p -> str = stringf ( " " , autoidx ++ ) ; current_ast_mod -> children . push_back ( p ) ; str = p -> str ; id2ast = p ; } } if ( type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE ) { if ( name_map . count ( str ) > 0 ) { str = name_map [ str ] ; } else { size_t pos = str . rfind ( ' ' ) ; if ( pos != std :: string :: npos ) { std :: string existing_prefix = str . substr ( 0 , pos ) ; if ( name_map . count ( existing_prefix ) > 0 ) { str = name_map [ existing_prefix ] + str . substr ( pos ) ; } } } } std :: map < std :: string , std :: string > backup_name_map ; auto prefix_node = [ & ] ( AstNode * child ) { if ( backup_name_map . size ( ) == 0 ) backup_name_map = name_map ; if ( ! original_scope ) { name_map [ child -> str ] = child -> str ; return ; } std :: string new_name = prefix [ 0 ] == ' \\ ' ? prefix . substr ( 1 ) : prefix ; size_t pos = child -> str . rfind ( ' ' ) ; if ( pos == std :: string :: npos ) pos = child -> str [ 0 ] == ' \\ ' && prefix [ 0 ] == ' \\ ' ? 1 : 0 ; else pos = pos + 1 ; new_name = child -> str . substr ( 0 , pos ) + new_name + child -> str . substr ( pos ) ; if ( new_name [ 0 ] != ' ' && new_name [ 0 ] != ' \\ ' ) new_name = prefix [ 0 ] + new_name ; name_map [ child -> str ] = new_name ; if ( child -> type == AST_FUNCTION ) replace_result_wire_name_in_function ( child , child -> str , new_name ) ; else child -> str = new_name ; current_scope [ new_name ] = child ; } ; for ( size_t i = 0 ; i < children . size ( ) ; i ++ ) { AstNode * child = children [ i ] ; switch ( child -> type ) { case AST_WIRE : case AST_MEMORY : case AST_PARAMETER : case AST_LOCALPARAM : case AST_FUNCTION : case AST_TASK : case AST_CELL : case AST_TYPEDEF : case AST_ENUM_ITEM : case AST_GENVAR : prefix_node ( child ) ; break ; case AST_BLOCK : case AST_GENBLOCK : if ( ! child -> str . empty ( ) ) prefix_node ( child ) ; break ; case AST_ENUM : current_scope [ child -> str ] = child ; for ( auto enode : child -> children ) { log_assert ( enode -> type == AST_ENUM_ITEM ) ; prefix_node ( enode ) ; } break ; default : break ; } } for ( size_t i = 0 ; i < children . size ( ) ; i ++ ) { AstNode * child = children [ i ] ; if ( type == AST_PREFIX && i == 1 && child -> type == AST_IDENTIFIER ) continue ; if ( child -> type == AST_FUNCTION || child -> type == AST_TASK ) child -> expand_genblock ( index_var , prefix , name_map , false ) ; else if ( child -> type == AST_GENBLOCK || child -> type == AST_BLOCK ) child -> expand_genblock ( index_var , prefix , name_map , original_scope && child -> str . empty ( ) ) ; else child -> expand_genblock ( index_var , prefix , name_map , original_scope ) ; } if ( backup_name_map . size ( ) > 0 ) name_map . swap ( backup_name_map ) ; }
annotate the names of all wires and other named objects in a generate block
annotate the names of all wires and other named objects in a generate block
// `original_scope` defaults to false, and is used to prevent the premature // prefixing of items in named sub-blocks // remap the prefix of this ident if it is a local generate scope // if within a nested scope // this declaration shadows anything in the parent scope(s) // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX // still needs to recursed-into // functions/tasks may reference wires, constants, etc. in this scope // continue prefixing if this child block is anonymous