diff options
| author | Benedikt Tutzer <benedikt.tutzer@gmail.com> | 2019-10-15 10:13:21 +0200 | 
|---|---|---|
| committer | Benedikt Tutzer <benedikt.tutzer@gmail.com> | 2019-10-15 10:13:21 +0200 | 
| commit | f8f572fbfc4e5de3afa7dc05f5fa1feff87aabd3 (patch) | |
| tree | daca10f9ee8149bc7ee13eb9cf89702886275947 | |
| parent | 79be986e2248540854c3e8e1e21f5bf971079690 (diff) | |
| parent | 2daa56859f51631992cc172ccddad55e741b0c3d (diff) | |
| download | yosys-f8f572fbfc4e5de3afa7dc05f5fa1feff87aabd3.tar.gz yosys-f8f572fbfc4e5de3afa7dc05f5fa1feff87aabd3.tar.bz2 yosys-f8f572fbfc4e5de3afa7dc05f5fa1feff87aabd3.zip | |
Merge branch 'master' of https://github.com/YosysHQ/yosys into feature/python_wrappers/globals_and_streams
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -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 | ||||
| -rw-r--r-- | frontends/verilog/verilog_parser.y | 80 | ||||
| -rw-r--r-- | techlibs/ecp5/cells_bb.v | 7 | ||||
| -rw-r--r-- | techlibs/ecp5/cells_ff.vh | 16 | ||||
| -rw-r--r-- | techlibs/ecp5/synth_ecp5.cc | 1 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_sim.v | 11 | ||||
| -rw-r--r-- | techlibs/xilinx/cells_xtra.py | 6 | ||||
| -rw-r--r-- | techlibs/xilinx/xc6s_cells_xtra.v | 10 | ||||
| -rw-r--r-- | techlibs/xilinx/xc6v_cells_xtra.v | 10 | ||||
| -rw-r--r-- | techlibs/xilinx/xc7_cells_xtra.v | 10 | ||||
| -rw-r--r-- | tests/svtypes/.gitignore | 3 | ||||
| -rwxr-xr-x | tests/svtypes/run-test.sh | 20 | ||||
| -rw-r--r-- | tests/svtypes/typedef_memory.sv | 10 | ||||
| -rw-r--r-- | tests/svtypes/typedef_memory.ys | 3 | ||||
| -rw-r--r-- | tests/svtypes/typedef_memory_2.sv | 10 | ||||
| -rw-r--r-- | tests/svtypes/typedef_memory_2.ys | 4 | ||||
| -rw-r--r-- | tests/svtypes/typedef_package.sv | 11 | ||||
| -rw-r--r-- | tests/svtypes/typedef_param.sv | 22 | ||||
| -rw-r--r-- | tests/svtypes/typedef_scopes.sv | 23 | ||||
| -rw-r--r-- | tests/svtypes/typedef_simple.sv | 19 | 
25 files changed, 345 insertions, 61 deletions
| @@ -708,6 +708,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)  	+cd tests/various && bash run-test.sh  	+cd tests/sat && bash run-test.sh  	+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) +	+cd tests/svtypes && bash run-test.sh $(SEEDOPT)  	+cd tests/proc && bash run-test.sh  	+cd tests/opt && bash run-test.sh  	+cd tests/aiger && bash run-test.sh $(ABCOPT) @@ -510,6 +510,8 @@ from SystemVerilog:    into a design with ``read_verilog``, all its packages are available to    SystemVerilog files being read into the same design afterwards. +- typedefs are supported (including inside packages) +  - SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether    ports are inputs or outputs are supported. 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); diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 4afd72b73..77f6d2051 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -155,7 +155,7 @@ struct specify_rise_fall {  %type <ast> range range_or_multirange  non_opt_range non_opt_multirange range_or_signed_int  %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list -%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id +%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id  %type <boolean> opt_signed opt_property unique_case_attr  %type <al> attr case_attr @@ -206,6 +206,7 @@ design:  	task_func_decl design |  	param_decl design |  	localparam_decl design | +	typedef_decl design |  	package design |  	interface design |  	/* empty */; @@ -290,6 +291,9 @@ hierarchical_id:  		$$ = $1;  	}; +hierarchical_type_id: +	'(' hierarchical_id ')' { $$ = $2; }; +  module:  	attr TOK_MODULE TOK_ID {  		do_not_require_port_stubs = false; @@ -324,13 +328,13 @@ single_module_para:  		astbuf1 = new AstNode(AST_PARAMETER);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true));  		append_attr(astbuf1, $1); -	} param_signed param_integer param_range single_param_decl | +	} param_type single_param_decl |  	attr TOK_LOCALPARAM {  		if (astbuf1) delete astbuf1;  		astbuf1 = new AstNode(AST_LOCALPARAM);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true));  		append_attr(astbuf1, $1); -	} param_signed param_integer param_range single_param_decl | +	} param_type single_param_decl |  	single_param_decl;  module_args_opt: @@ -426,6 +430,7 @@ package_body:  	package_body package_body_stmt |;  package_body_stmt: +	typedef_decl |  	localparam_decl;  interface: @@ -452,7 +457,7 @@ interface_body:  	interface_body interface_body_stmt |;  interface_body_stmt: -	param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | +	param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt |  	modport_stmt;  non_opt_delay: @@ -475,8 +480,14 @@ wire_type:  	};  wire_type_token_list: -	wire_type_token | wire_type_token_list wire_type_token | -	wire_type_token_io ; +	wire_type_token | +	wire_type_token_list wire_type_token | +	wire_type_token_io | +	hierarchical_type_id { +		astbuf3->is_custom_type = true; +		astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); +		astbuf3->children.back()->str = *$1; +	};  wire_type_token_io:  	TOK_INPUT { @@ -591,7 +602,7 @@ module_body:  	/* empty */;  module_body_stmt: -	task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | +	task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |  	always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block;  checker_decl: @@ -1149,12 +1160,20 @@ param_range:  		}  	}; +param_type: +	param_signed param_integer param_real param_range | +	hierarchical_type_id { +		astbuf1->is_custom_type = true; +		astbuf1->children.push_back(new AstNode(AST_WIRETYPE)); +		astbuf1->children.back()->str = *$1; +	}; +  param_decl:  	attr TOK_PARAMETER {  		astbuf1 = new AstNode(AST_PARAMETER);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true));  		append_attr(astbuf1, $1); -	} param_signed param_integer param_real param_range param_decl_list ';' { +	} param_type param_decl_list ';' {  		delete astbuf1;  	}; @@ -1163,7 +1182,7 @@ localparam_decl:  		astbuf1 = new AstNode(AST_LOCALPARAM);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true));  		append_attr(astbuf1, $1); -	} param_signed param_integer param_real param_range param_decl_list ';' { +	} param_type param_decl_list ';' {  		delete astbuf1;  	}; @@ -1327,7 +1346,7 @@ wire_name:  		if ($2 != NULL) {  			if (node->is_input || node->is_output)  				frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions."); -			if (!astbuf2) { +			if (!astbuf2 && !node->is_custom_type) {  				AstNode *rng = new AstNode(AST_RANGE);  				rng->children.push_back(AstNode::mkconst_int(0, true));  				rng->children.push_back(AstNode::mkconst_int(0, true)); @@ -1377,6 +1396,45 @@ assign_expr:  		ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3));  	}; +typedef_decl: +	TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' { +		astbuf1 = $2; +		astbuf2 = $3; +		if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { +			if (astbuf2) { +				frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); +			} else { +				astbuf2 = new AstNode(AST_RANGE); +				astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); +				astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true)); +			} +		} +		if (astbuf2 && astbuf2->children.size() != 2) +			frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]"); +		if (astbuf2) +			astbuf1->children.push_back(astbuf2); + +		if ($5 != NULL) { +			if (!astbuf2) { +				AstNode *rng = new AstNode(AST_RANGE); +				rng->children.push_back(AstNode::mkconst_int(0, true)); +				rng->children.push_back(AstNode::mkconst_int(0, true)); +				astbuf1->children.push_back(rng); +			} +			astbuf1->type = AST_MEMORY; +			auto *rangeNode = $5; +			if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { +				// SV array size [n], rewrite as [n-1:0] +				rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); +				rangeNode->children.push_back(AstNode::mkconst_int(0, false)); +			} +			astbuf1->children.push_back(rangeNode); +		} + +		ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); +		ast_stack.back()->children.back()->str = *$4; +	}; +  cell_stmt:  	attr TOK_ID {  		astbuf1 = new AstNode(AST_CELL); @@ -1823,7 +1881,7 @@ simple_behavioral_stmt:  // this production creates the obligatory if-else shift/reduce conflict  behavioral_stmt: -	defattr | assert | wire_decl | param_decl | localparam_decl | +	defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl |  	non_opt_delay behavioral_stmt |  	simple_behavioral_stmt ';' | ';' |  	hierarchical_id attr { diff --git a/techlibs/ecp5/cells_bb.v b/techlibs/ecp5/cells_bb.v index 0a5046db2..ae124e7a3 100644 --- a/techlibs/ecp5/cells_bb.v +++ b/techlibs/ecp5/cells_bb.v @@ -334,6 +334,13 @@ module ECLKSYNCB(  endmodule  (* blackbox *) +module ECLKBRIDGECS( +	input CLK0, CLK1, SEL, +	output ECSOUT +); +endmodule + +(* blackbox *)  module DCCA(  	input CLKI, CE,  	output CLKO diff --git a/techlibs/ecp5/cells_ff.vh b/techlibs/ecp5/cells_ff.vh index 0c9689ebd..501c1b3b2 100644 --- a/techlibs/ecp5/cells_ff.vh +++ b/techlibs/ecp5/cells_ff.vh @@ -23,15 +23,15 @@ module FD1S3JX(input PD, D,     CK, output Q); parameter GSR = "ENABLED"; TRELLI  // module FL1S3AY(); endmodule  // Diamond I/O registers -module IFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module IFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module IFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="input" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule -module OFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3BX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3DX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC"))       _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3IX(input CD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(CD), .CE(SP), .DI(D), .Q(Q)); endmodule +module OFS1P3JX(input PD, D, SP, SCLK, output Q); parameter GSR = "ENABLED"; (* syn_useioff, ioff_dir="output" *) TRELLIS_FF #(.GSR(GSR), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"),   .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(SCLK), .LSR(PD), .CE(SP), .DI(D), .Q(Q)); endmodule  // TODO: Diamond I/O latches  // module IFS1S1B(input PD, D, SCLK, output Q); endmodule diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 80aa1dbc5..a79dee31f 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -297,6 +297,7 @@ struct SynthEcp5Pass : public ScriptPass  			run("simplemap");  			run("ecp5_ffinit");  			run("ecp5_gsr"); +			run("attrmvcp -copy -attr syn_useioff");  			run("opt_clean");  		} diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 28cd208cd..03985b1be 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -38,6 +38,17 @@ module IBUF(    assign O = I;  endmodule +module IBUFG( +    output O, +    (* iopad_external_pin *) +    input I); +  parameter CAPACITANCE = "DONT_CARE"; +  parameter IBUF_DELAY_VALUE = "0"; +  parameter IBUF_LOW_PWR = "TRUE"; +  parameter IOSTANDARD = "DEFAULT"; +  assign O = I; +endmodule +  module OBUF(      (* iopad_external_pin *)      output O, diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py index ee20ae992..9a4747ff3 100644 --- a/techlibs/xilinx/cells_xtra.py +++ b/techlibs/xilinx/cells_xtra.py @@ -53,7 +53,7 @@ XC6S_CELLS = [      # Cell('IBUF', port_attrs={'I': ['iopad_external_pin']}),      Cell('IBUFDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IBUFDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), -    Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}), +    # Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}),      Cell('IBUFGDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IBUFGDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IOBUF', port_attrs={'IO': ['iopad_external_pin']}), @@ -174,7 +174,7 @@ XC6V_CELLS = [      Cell('IBUFDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IBUFDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IBUFDS_GTHE1', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), -    Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}), +    # Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}),      Cell('IBUFGDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IBUFGDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IDELAYCTRL', keep=True, port_attrs={'REFCLK': ['clkbuf_sink']}), @@ -307,7 +307,7 @@ XC7_CELLS = [      Cell('IBUFDS_GTE2', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IBUFDS_IBUFDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IBUFDS_INTERMDISABLE', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}), -    Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}), +    # Cell('IBUFG', port_attrs={'I': ['iopad_external_pin']}),      Cell('IBUFGDS', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IBUFGDS_DIFF_OUT', port_attrs={'I': ['iopad_external_pin'], 'IB': ['iopad_external_pin']}),      Cell('IDELAYCTRL', keep=True, port_attrs={'REFCLK': ['clkbuf_sink']}), diff --git a/techlibs/xilinx/xc6s_cells_xtra.v b/techlibs/xilinx/xc6s_cells_xtra.v index f8dcce81d..7c0462b52 100644 --- a/techlibs/xilinx/xc6s_cells_xtra.v +++ b/techlibs/xilinx/xc6s_cells_xtra.v @@ -1282,16 +1282,6 @@ module IBUFDS_DIFF_OUT (...);      input IB;  endmodule -module IBUFG (...); -    parameter CAPACITANCE = "DONT_CARE"; -    parameter IBUF_DELAY_VALUE = "0"; -    parameter IBUF_LOW_PWR = "TRUE"; -    parameter IOSTANDARD = "DEFAULT"; -    output O; -    (* iopad_external_pin *) -    input I; -endmodule -  module IBUFGDS (...);      parameter CAPACITANCE = "DONT_CARE";      parameter DIFF_TERM = "FALSE"; diff --git a/techlibs/xilinx/xc6v_cells_xtra.v b/techlibs/xilinx/xc6v_cells_xtra.v index d9e06eae2..87656fa49 100644 --- a/techlibs/xilinx/xc6v_cells_xtra.v +++ b/techlibs/xilinx/xc6v_cells_xtra.v @@ -1821,16 +1821,6 @@ module IBUFDS_GTHE1 (...);      input IB;  endmodule -module IBUFG (...); -    parameter CAPACITANCE = "DONT_CARE"; -    parameter IBUF_DELAY_VALUE = "0"; -    parameter IBUF_LOW_PWR = "TRUE"; -    parameter IOSTANDARD = "DEFAULT"; -    output O; -    (* iopad_external_pin *) -    input I; -endmodule -  module IBUFGDS (...);      parameter CAPACITANCE = "DONT_CARE";      parameter DIFF_TERM = "FALSE"; diff --git a/techlibs/xilinx/xc7_cells_xtra.v b/techlibs/xilinx/xc7_cells_xtra.v index f36e4baa2..10eea4a5f 100644 --- a/techlibs/xilinx/xc7_cells_xtra.v +++ b/techlibs/xilinx/xc7_cells_xtra.v @@ -3932,16 +3932,6 @@ module IBUFDS_INTERMDISABLE (...);      input INTERMDISABLE;  endmodule -module IBUFG (...); -    parameter CAPACITANCE = "DONT_CARE"; -    parameter IBUF_DELAY_VALUE = "0"; -    parameter IBUF_LOW_PWR = "TRUE"; -    parameter IOSTANDARD = "DEFAULT"; -    output O; -    (* iopad_external_pin *) -    input I; -endmodule -  module IBUFGDS (...);      parameter CAPACITANCE = "DONT_CARE";      parameter DIFF_TERM = "FALSE"; diff --git a/tests/svtypes/.gitignore b/tests/svtypes/.gitignore new file mode 100644 index 000000000..b48f808a1 --- /dev/null +++ b/tests/svtypes/.gitignore @@ -0,0 +1,3 @@ +/*.log +/*.out +/run-test.mk diff --git a/tests/svtypes/run-test.sh b/tests/svtypes/run-test.sh new file mode 100755 index 000000000..09a30eed1 --- /dev/null +++ b/tests/svtypes/run-test.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -e +{ +echo "all::" +for x in *.ys; do +	echo "all:: run-$x" +	echo "run-$x:" +	echo "	@echo 'Running $x..'" +	echo "	@../../yosys -ql ${x%.ys}.log $x" +done +for x in *.sv; do +	if [ ! -f "${x%.sv}.ys"  ]; then +		echo "all:: check-$x" +		echo "check-$x:" +		echo "	@echo 'Checking $x..'" +		echo "	@../../yosys -ql ${x%.sv}.log -p \"prep -top top; sat -verify -prove-asserts\" $x" +	fi +done +} > run-test.mk +exec ${MAKE:-make} -f run-test.mk diff --git a/tests/svtypes/typedef_memory.sv b/tests/svtypes/typedef_memory.sv new file mode 100644 index 000000000..577e484ad --- /dev/null +++ b/tests/svtypes/typedef_memory.sv @@ -0,0 +1,10 @@ +module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata); +	typedef logic [3:0] ram16x4_t[0:15]; + +	(ram16x4_t) mem; + +	always @(posedge clk) begin +		if (wen) mem[addr] <= wdata; +		rdata <= mem[addr]; +	end +endmodule diff --git a/tests/svtypes/typedef_memory.ys b/tests/svtypes/typedef_memory.ys new file mode 100644 index 000000000..93cf47bbe --- /dev/null +++ b/tests/svtypes/typedef_memory.ys @@ -0,0 +1,3 @@ +read_verilog -sv typedef_memory.sv +prep -top top +select -assert-count 1 t:$mem r:SIZE=16 %i r:WIDTH=4 %i diff --git a/tests/svtypes/typedef_memory_2.sv b/tests/svtypes/typedef_memory_2.sv new file mode 100644 index 000000000..f3089bf55 --- /dev/null +++ b/tests/svtypes/typedef_memory_2.sv @@ -0,0 +1,10 @@ +module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata); +	typedef logic [3:0] nibble; + +	(nibble) mem[0:15]; + +	always @(posedge clk) begin +		if (wen) mem[addr] <= wdata; +		rdata <= mem[addr]; +	end +endmodule diff --git a/tests/svtypes/typedef_memory_2.ys b/tests/svtypes/typedef_memory_2.ys new file mode 100644 index 000000000..854e554f3 --- /dev/null +++ b/tests/svtypes/typedef_memory_2.ys @@ -0,0 +1,4 @@ +read_verilog -sv typedef_memory_2.sv +prep -top top +dump +select -assert-count 1 t:$mem r:SIZE=16 %i r:WIDTH=4 %i diff --git a/tests/svtypes/typedef_package.sv b/tests/svtypes/typedef_package.sv new file mode 100644 index 000000000..a1e16d4b1 --- /dev/null +++ b/tests/svtypes/typedef_package.sv @@ -0,0 +1,11 @@ +package pkg; +	typedef logic [7:0] uint8_t; +endpackage + +module top; + +	(* keep *) (pkg::uint8_t) a = 8'hAA; + +	always @* assert(a == 8'hAA); + +endmodule diff --git a/tests/svtypes/typedef_param.sv b/tests/svtypes/typedef_param.sv new file mode 100644 index 000000000..ddbd471e0 --- /dev/null +++ b/tests/svtypes/typedef_param.sv @@ -0,0 +1,22 @@ +`define STRINGIFY(x) `"x`" +`define STATIC_ASSERT(x) if(!(x)) $error({"assert failed: ", `STRINGIFY(x)}) + +module top; + +	typedef logic [1:0] uint2_t; +	typedef logic signed [3:0] int4_t; +	typedef logic signed [7:0] int8_t; +	typedef (int8_t) char_t; + +	parameter (uint2_t) int2 = 2'b10; +	localparam (int4_t) int4 = -1; +	localparam (int8_t) int8 = int4; +	localparam (char_t) ch = int8; + + +	`STATIC_ASSERT(int2 == 2'b10); +	`STATIC_ASSERT(int4 == 4'b1111); +	`STATIC_ASSERT(int8 == 8'b11111111); +	`STATIC_ASSERT(ch   == 8'b11111111); + +endmodule diff --git a/tests/svtypes/typedef_scopes.sv b/tests/svtypes/typedef_scopes.sv new file mode 100644 index 000000000..faa385bd6 --- /dev/null +++ b/tests/svtypes/typedef_scopes.sv @@ -0,0 +1,23 @@ + +typedef logic [3:0] outer_uint4_t; + +module top; + +	(outer_uint4_t) u4_i = 8'hA5; +	always @(*) assert(u4_i == 4'h5); + +	typedef logic [3:0] inner_type; +	(inner_type) inner_i1 = 8'h5A; +	always @(*) assert(inner_i1 == 4'hA); + +	if (1) begin: genblock +		typedef logic [7:0] inner_type; +		(inner_type) inner_gb_i = 8'hA5; +		always @(*) assert(inner_gb_i == 8'hA5); +	end + +	(inner_type) inner_i2 = 8'h42; +	always @(*) assert(inner_i2 == 4'h2); + + +endmodule diff --git a/tests/svtypes/typedef_simple.sv b/tests/svtypes/typedef_simple.sv new file mode 100644 index 000000000..7e760dee4 --- /dev/null +++ b/tests/svtypes/typedef_simple.sv @@ -0,0 +1,19 @@ +module top; + +	typedef logic [1:0] uint2_t; +	typedef logic signed [3:0] int4_t; +	typedef logic signed [7:0] int8_t; +	typedef (int8_t) char_t; + +	(* keep *) (uint2_t) int2 = 2'b10; +	(* keep *) (int4_t) int4 = -1; +	(* keep *) (int8_t) int8 = int4; +	(* keep *) (char_t) ch = int8; + + +	always @* assert(int2 == 2'b10); +	always @* assert(int4 == 4'b1111); +	always @* assert(int8 == 8'b11111111); +	always @* assert(ch   == 8'b11111111); + +endmodule | 
