diff options
| author | Miodrag Milanović <mmicko@gmail.com> | 2019-10-18 10:53:56 +0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-10-18 10:53:56 +0200 | 
| commit | 66fca65b58bfb944cad45da5836613726498e4b7 (patch) | |
| tree | a78b5d92952ea9f95623bb3daf8028d2402d023b /frontends/ast | |
| parent | 46af9a0ff7727c2d47b1dc12501e3328cba1f2e9 (diff) | |
| parent | 5ffb0053ec7d53ffc5c57e3277bfbab5d3fddb54 (diff) | |
| download | yosys-66fca65b58bfb944cad45da5836613726498e4b7.tar.gz yosys-66fca65b58bfb944cad45da5836613726498e4b7.tar.bz2 yosys-66fca65b58bfb944cad45da5836613726498e4b7.zip | |
Merge branch 'master' into mmicko/anlogic
Diffstat (limited to 'frontends/ast')
| -rw-r--r-- | frontends/ast/ast.cc | 3 | ||||
| -rw-r--r-- | frontends/ast/ast.h | 7 | ||||
| -rw-r--r-- | frontends/ast/genrtlil.cc | 1 | ||||
| -rw-r--r-- | frontends/ast/simplify.cc | 116 | 
4 files changed, 118 insertions, 9 deletions
| diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 37a69d8bf..5bbea0faf 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -164,6 +164,8 @@ std::string AST::type2str(AstNodeType type)  	X(AST_MODPORT)  	X(AST_MODPORTMEMBER)  	X(AST_PACKAGE) +	X(AST_WIRETYPE) +	X(AST_TYPEDEF)  #undef X  	default:  		log_abort(); @@ -206,6 +208,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch  	was_checked = false;  	range_valid = false;  	range_swapped = false; +	is_custom_type = false;  	port_id = 0;  	range_left = -1;  	range_right = 0; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 0ec249ab9..918d178c7 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -148,7 +148,10 @@ namespace AST  		AST_INTERFACEPORTTYPE,  		AST_MODPORT,  		AST_MODPORTMEMBER, -		AST_PACKAGE +		AST_PACKAGE, + +		AST_WIRETYPE, +		AST_TYPEDEF  	};  	// convert an node type to a string (e.g. for debug output) @@ -174,7 +177,7 @@ namespace AST  		// node content - most of it is unused in most node types  		std::string str;  		std::vector<RTLIL::State> bits; -		bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized; +		bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized, is_custom_type;  		int port_id, range_left, range_right;  		uint32_t integer;  		double realvalue; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 407a34472..94f5c0a04 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -863,6 +863,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  	case AST_PACKAGE:  	case AST_MODPORT:  	case AST_MODPORTMEMBER: +	case AST_TYPEDEF:  		break;  	case AST_INTERFACEPORT: {  		// If a port in a module with unknown type is found, mark it with the attribute 'is_interface' diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index b1ee22f42..44fd32cdc 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -318,7 +318,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  	}  	// activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.) -	if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX) +	if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF)  		const_fold = true;  	if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM))  		const_fold = true; @@ -336,6 +336,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		std::map<std::string, AstNode*> this_wire_scope;  		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) { @@ -405,14 +406,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  				this_wire_scope[node->str] = node;  			}  			if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR || -					node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL) { +					node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL || +					node->type == AST_TYPEDEF) {  				backup_scope[node->str] = current_scope[node->str];  				current_scope[node->str] = node;  			}  		}  		for (size_t i = 0; i < children.size(); i++) {  			AstNode *node = children[i]; -			if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY) +			if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF)  				while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM))  					did_something = true;  		} @@ -780,6 +782,99 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		delete_children();  	} +	// resolve typedefs +	if (type == AST_TYPEDEF) { +		log_assert(children.size() == 1); +		log_assert(children[0]->type == AST_WIRE || children[0]->type == AST_MEMORY); +		while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) +			did_something = true; +		log_assert(!children[0]->is_custom_type); +	} + +	// resolve types of wires +	if (type == AST_WIRE || type == AST_MEMORY) { +		if (is_custom_type) { +			log_assert(children.size() >= 1); +			log_assert(children[0]->type == AST_WIRETYPE); +			if (!current_scope.count(children[0]->str)) +				log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str()); +			AstNode *resolved_type = current_scope.at(children[0]->str); +			if (resolved_type->type != AST_TYPEDEF) +				log_file_error(filename, linenum, "`%s' does not name a type\n", children[0]->str.c_str()); +			log_assert(resolved_type->children.size() == 1); +			AstNode *templ = resolved_type->children[0]; +			// Remove type reference +			delete children[0]; +			children.erase(children.begin()); + +			// Ensure typedef itself is fully simplified +			while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + +			if (type == AST_WIRE) +				type = templ->type; +			is_reg = templ->is_reg; +			is_logic = templ->is_logic; +			is_signed = templ->is_signed; +			is_string = templ->is_string; +			is_custom_type = templ->is_custom_type; + +			range_valid = templ->range_valid; +			range_swapped = templ->range_swapped; +			range_left = templ->range_left; +			range_right = templ->range_right; + +			// Insert clones children from template at beginning +			for (int i  = 0; i < GetSize(templ->children); i++) +				children.insert(children.begin() + i, templ->children[i]->clone()); +			 +			if (type == AST_MEMORY && GetSize(children) == 1) { +				// Single-bit memories must have [0:0] range +				AstNode *rng = new AstNode(AST_RANGE); +				rng->children.push_back(AstNode::mkconst_int(0, true)); +				rng->children.push_back(AstNode::mkconst_int(0, true)); +				children.insert(children.begin(), rng); +			} + +			did_something = true; +		} +		log_assert(!is_custom_type); +	} + +	// resolve types of parameters +	if (type == AST_LOCALPARAM || type == AST_PARAMETER) { +		if (is_custom_type) { +			log_assert(children.size() == 2); +			log_assert(children[1]->type == AST_WIRETYPE); +			if (!current_scope.count(children[1]->str)) +				log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str()); +			AstNode *resolved_type = current_scope.at(children[1]->str); +			if (resolved_type->type != AST_TYPEDEF) +				log_file_error(filename, linenum, "`%s' does not name a type\n", children[1]->str.c_str()); +			log_assert(resolved_type->children.size() == 1); +			AstNode *templ = resolved_type->children[0]; +			delete children[1]; +			children.pop_back(); + +			// Ensure typedef itself is fully simplified +			while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; + +			if (templ->type == AST_MEMORY) +				log_file_error(filename, linenum, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str()); +			is_signed = templ->is_signed; +			is_string = templ->is_string; +			is_custom_type = templ->is_custom_type; + +			range_valid = templ->range_valid; +			range_swapped = templ->range_swapped; +			range_left = templ->range_left; +			range_right = templ->range_right; +			for (auto template_child : templ->children) +				children.push_back(template_child->clone()); +			did_something = true; +		} +		log_assert(!is_custom_type); +	}	 +  	// resolve constant prefixes  	if (type == AST_PREFIX) {  		if (children[0]->type != AST_CONSTANT) { @@ -1194,7 +1289,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  	if (type == AST_BLOCK && str.empty())  	{  		for (size_t i = 0; i < children.size(); i++) -			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) +			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF)  				log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");  	} @@ -1206,7 +1301,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		std::vector<AstNode*> new_children;  		for (size_t i = 0; i < children.size(); i++) -			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) { +			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) {  				children[i]->simplify(false, false, false, stage, -1, false, false);  				current_ast_mod->children.push_back(children[i]);  				current_scope[children[i]->str] = children[i]; @@ -2906,7 +3001,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma  		}  	} -	if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0) +	if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) && name_map.count(str) > 0)  		str = name_map[str];  	std::map<std::string, std::string> backup_name_map; @@ -2914,7 +3009,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma  	for (size_t i = 0; i < children.size(); i++) {  		AstNode *child = children[i];  		if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || -				child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL) { +				child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) {  			if (backup_name_map.size() == 0)  				backup_name_map = name_map;  			std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix; @@ -2945,6 +3040,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma  			child->expand_genblock(index_var, prefix, name_map);  	} +  	if (backup_name_map.size() > 0)  		name_map.swap(backup_name_map);  } @@ -2998,6 +3094,9 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg  	uint32_t children_flags = 0;  	int lhs_children_counter = 0; +	if (type == AST_TYPEDEF) +		return; // don't touch content of typedefs +  	if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)  	{  		// mark all memories that are used in a complex expression on the left side of an assignment @@ -3155,6 +3254,9 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,  	if (type == AST_FUNCTION || type == AST_TASK)  		return false; +	if (type == AST_TYPEDEF) +		return false; +  	if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast))  	{  		log_assert(children[0]->type == AST_CONSTANT); | 
