diff options
Diffstat (limited to 'frontends')
| -rw-r--r-- | frontends/ast/ast.h | 3 | ||||
| -rw-r--r-- | frontends/ast/genrtlil.cc | 6 | ||||
| -rw-r--r-- | frontends/ast/simplify.cc | 67 | 
3 files changed, 74 insertions, 2 deletions
| diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 08f91c9c3..8b185ff51 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -214,6 +214,8 @@ namespace AST  			MEM2REG_FL_SET_ASYNC = 0x00000800,  			MEM2REG_FL_EQ2       = 0x00001000,  			MEM2REG_FL_CMPLX_LHS = 0x00002000, +			MEM2REG_FL_CONST_LHS = 0x00004000, +			MEM2REG_FL_VAR_LHS   = 0x00008000,  			/* proc flags */  			MEM2REG_FL_EQ1       = 0x01000000, @@ -237,6 +239,7 @@ namespace AST  		bool has_const_only_constructs(bool &recommend_const_eval);  		void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);  		AstNode *eval_const_function(AstNode *fcall); +		bool is_simple_const_expr();  		// create a human-readable text representation of the AST (for debugging)  		void dumpAst(FILE *f, std::string indent) const; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 2d591b29d..13383845a 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -544,7 +544,11 @@ struct AST_INTERNAL::ProcessGenerator  			break;  		case AST_WIRE: -			log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n"); +			log_file_error(ast->filename, ast->linenum, "Found reg declaration in block without label!\n"); +			break; + +		case AST_ASSIGN: +			log_file_error(ast->filename, ast->linenum, "Found continous assignment in always/initial block!\n");  			break;  		case AST_PARAMETER: diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 46013544b..7160c6c0f 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -113,6 +113,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  				if (memflags & AstNode::MEM2REG_FL_CMPLX_LHS)  					goto verbose_activate; +				if ((memflags & AstNode::MEM2REG_FL_CONST_LHS) && !(memflags & AstNode::MEM2REG_FL_VAR_LHS)) +					goto verbose_activate; +  				// log("Note: Not replacing memory %s with list of registers (flags=0x%08lx).\n", mem->str.c_str(), long(memflags));  				continue; @@ -325,6 +328,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		for (size_t i = 0; i < children.size(); i++) {  			AstNode *node = children[i];  			if (node->type == AST_WIRE) { +				if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { +					for (auto c : node->children[0]->children) { +						if (!c->is_simple_const_expr()) { +							if (attributes.count("\\dynports")) +								delete attributes.at("\\dynports"); +							attributes["\\dynports"] = AstNode::mkconst_int(1, true); +						} +					} +				}  				if (this_wire_scope.count(node->str) > 0) {  					AstNode *first_node = this_wire_scope[node->str];  					if (first_node->is_input && node->is_reg) @@ -938,7 +950,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			}  		}  		if (current_scope.count(str) == 0) { -			if (flag_autowire) { +			if (flag_autowire || str == "\\$global_clock") {  				AstNode *auto_wire = new AstNode(AST_AUTOWIRE);  				auto_wire->str = str;  				current_ast_mod->children.push_back(auto_wire); @@ -2169,6 +2181,8 @@ skip_dynamic_range_lvalue_expansion:;  				}  				newNode = readmem(str == "\\$readmemh", node_filename->bitsAsConst().decode_string(), node_memory->id2ast, start_addr, finish_addr, unconditional_init); +				delete node_filename; +				delete node_memory;  				goto apply_newNode;  			} @@ -2936,6 +2950,14 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg  				proc_flags[mem] |= AstNode::MEM2REG_FL_EQ1;  			} +			// remember if this is a constant index or not +			if (children[0]->children.size() && children[0]->children[0]->type == AST_RANGE && children[0]->children[0]->children.size()) { +				if (children[0]->children[0]->children[0]->type == AST_CONSTANT) +					mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_CONST_LHS; +				else +					mem2reg_candidates[mem] |= AstNode::MEM2REG_FL_VAR_LHS; +			} +  			// remember where this is  			if (flags & MEM2REG_FL_INIT) {  				if (!(mem2reg_candidates[mem] & AstNode::MEM2REG_FL_SET_INIT)) @@ -3048,6 +3070,39 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,  	if (type == AST_FUNCTION || type == AST_TASK)  		return false; +	if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast)) +	{ +		log_assert(children[0]->type == AST_CONSTANT); +		log_assert(children[1]->type == AST_CONSTANT); +		log_assert(children[2]->type == AST_CONSTANT); + +		int cursor = children[0]->asInt(false); +		Const data = children[1]->bitsAsConst(); +		int length = children[2]->asInt(false); + +		if (length != 0) +		{ +			AstNode *block = new AstNode(AST_INITIAL, new AstNode(AST_BLOCK)); +			mod->children.push_back(block); +			block = block->children[0]; + +			int wordsz = GetSize(data) / length; + +			for (int i = 0; i < length; i++) { +				block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false))), mkconst_bits(data.extract(i*wordsz, wordsz).bits, false))); +				block->children.back()->children[0]->str = str; +				block->children.back()->children[0]->id2ast = id2ast; +				block->children.back()->children[0]->was_checked = true; +			} +		} + +		AstNode *newNode = new AstNode(AST_NONE); +		newNode->cloneInto(this); +		delete newNode; + +		did_something = true; +	} +  	if (type == AST_ASSIGN && block == NULL && children[0]->mem2reg_check(mem2reg_set))  	{  		if (async_block == NULL) { @@ -3277,6 +3332,16 @@ bool AstNode::has_const_only_constructs(bool &recommend_const_eval)  	return false;  } +bool AstNode::is_simple_const_expr() +{ +	if (type == AST_IDENTIFIER) +		return false; +	for (auto child : children) +		if (!child->is_simple_const_expr()) +			return false; +	return true; +} +  // helper function for AstNode::eval_const_function()  void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &variables, AstNode *fcall)  { | 
