diff options
Diffstat (limited to 'frontends')
| -rw-r--r-- | frontends/ast/ast.cc | 292 | ||||
| -rw-r--r-- | frontends/ast/ast.h | 13 | ||||
| -rw-r--r-- | frontends/ast/genrtlil.cc | 158 | ||||
| -rw-r--r-- | frontends/ast/simplify.cc | 109 | ||||
| -rw-r--r-- | frontends/ilang/ilang_parser.y | 16 | ||||
| -rw-r--r-- | frontends/liberty/liberty.cc | 13 | ||||
| -rw-r--r-- | frontends/verific/verific.cc | 312 | ||||
| -rw-r--r-- | frontends/verific/verific.h | 1 | ||||
| -rw-r--r-- | frontends/verilog/verilog_lexer.l | 11 | ||||
| -rw-r--r-- | frontends/verilog/verilog_parser.y | 169 | 
10 files changed, 775 insertions, 319 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index e79be953a..2c1561552 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -2,6 +2,7 @@   *  yosys -- Yosys Open SYnthesis Suite   *   *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> + *  Copyright (C) 2018  Ruben Undheim <ruben.undheim@gmail.com>   *   *  Permission to use, copy, modify, and/or distribute this software for any   *  purpose with or without fee is hereby granted, provided that the above @@ -171,8 +172,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)  	AstNode *attr = attributes.at(id);  	if (attr->type != AST_CONSTANT) -		log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", -			       id.c_str()); +		log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n", id.c_str());  	return attr->integer != 0;  } @@ -903,9 +903,9 @@ RTLIL::Const AstNode::realAsConst(int width)  }  // create a new AstModule from an AST_MODULE AST node -static AstModule* process_module(AstNode *ast, bool defer) +static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL)  { -	log_assert(ast->type == AST_MODULE); +	log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);  	if (defer)  		log("Storing AST representation for module `%s'.\n", ast->str.c_str()); @@ -916,9 +916,14 @@ static AstModule* process_module(AstNode *ast, bool defer)  	current_module->ast = NULL;  	current_module->name = ast->str;  	current_module->attributes["\\src"] = stringf("%s:%d", ast->filename.c_str(), ast->linenum); +	current_module->set_bool_attribute("\\cells_not_processed");  	current_ast_mod = ast; -	AstNode *ast_before_simplify = ast->clone(); +	AstNode *ast_before_simplify; +	if (original_ast != NULL) +		ast_before_simplify = original_ast; +	else +		ast_before_simplify = ast->clone();  	if (flag_dump_ast1) {  		log("Dumping Verilog AST before simplification:\n"); @@ -963,8 +968,7 @@ static AstModule* process_module(AstNode *ast, bool defer)  		for (auto &attr : ast->attributes) {  			if (attr.second->type != AST_CONSTANT) -				log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", -					       attr.first.c_str()); +				log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());  			current_module->attributes[attr.first] = attr.second->asAttrConst();  		}  		for (size_t i = 0; i < ast->children.size(); i++) { @@ -989,6 +993,8 @@ static AstModule* process_module(AstNode *ast, bool defer)  		ignoreThisSignalsInInitial = RTLIL::SigSpec();  	} +	if (ast->type == AST_INTERFACE) +		current_module->set_bool_attribute("\\is_interface");  	current_module->ast = ast_before_simplify;  	current_module->nolatches = flag_nolatches;  	current_module->nomeminit = flag_nomeminit; @@ -1031,7 +1037,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump  	log_assert(current_ast->type == AST_DESIGN);  	for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++)  	{ -		if ((*it)->type == AST_MODULE) +		if ((*it)->type == AST_MODULE || (*it)->type == AST_INTERFACE)  		{  			for (auto n : design->verilog_globals)  				(*it)->children.push_back(n->clone()); @@ -1053,8 +1059,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump  			if (design->has((*it)->str)) {  				RTLIL::Module *existing_mod = design->module((*it)->str);  				if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) { -					log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", -						       (*it)->str.c_str()); +					log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n", (*it)->str.c_str());  				} else if (nooverwrite) {  					log("Ignoring re-definition of module `%s' at %s:%d.\n",  							(*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum); @@ -1083,8 +1088,264 @@ AstModule::~AstModule()  		delete ast;  } + +// An interface port with modport is specified like this: +//    <interface_name>.<modport_name> +// This function splits the interface_name from the modport_name, and fails if it is not a valid combination +std::pair<std::string,std::string> AST::split_modport_from_type(std::string name_type) +{ +	std::string interface_type = ""; +	std::string interface_modport = ""; +	size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); +	// Separate the interface instance name from any modports: +	if (ndots == 0) { // Does not have modport +		interface_type = name_type; +	} +	else { +		std::stringstream name_type_stream(name_type); +		std::string segment; +		std::vector<std::string> seglist; +		while(std::getline(name_type_stream, segment, '.')) { +			seglist.push_back(segment); +		} +		if (ndots == 1) { // Has modport +			interface_type = seglist[0]; +			interface_modport = seglist[1]; +		} +		else { // Erroneous port type +			log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); +		} +	} +	return std::pair<std::string,std::string>(interface_type, interface_modport); + +} + +AstNode * AST::find_modport(AstNode *intf, std::string name) +{ +	for (auto &ch : intf->children) +		if (ch->type == AST_MODPORT) +			if (ch->str == name) // Modport found +				return ch; +	return NULL; +} + +// Iterate over all wires in an interface and add them as wires in the AST module: +void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport) +{ +	for (auto &wire_it : intfmodule->wires_){ +		AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); +		std::string origname = log_id(wire_it.first); +		std::string newname = intfname + "." + origname; +		wire->str = newname; +		if (modport != NULL) { +			bool found_in_modport = false; +			// Search for the current wire in the wire list for the current modport +			for (auto &ch : modport->children) { +				if (ch->type == AST_MODPORTMEMBER) { +					std::string compare_name = "\\" + origname; +					if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output +						found_in_modport = true; +						wire->is_input = ch->is_input; +						wire->is_output = ch->is_output; +						break; +					} +				} +			} +			if (found_in_modport) { +				module_ast->children.push_back(wire); +			} +			else { // If not found in modport, do not create port +				delete wire; +			} +		} +		else { // If no modport, set inout +			wire->is_input = true; +			wire->is_output = true; +			module_ast->children.push_back(wire); +		} +	} +} + +// When an interface instance is found in a module, the whole RTLIL for the module will be rederived again +// from AST. The interface members are copied into the AST module with the prefix of the interface. +void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module*> local_interfaces) +{ +	bool is_top = false; +	AstNode *new_ast = ast->clone(); +	for (auto &intf : local_interfaces) { +		std::string intfname = intf.first.str(); +		RTLIL::Module *intfmodule = intf.second; +		for (auto &wire_it : intfmodule->wires_){ +			AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); +			std::string newname = log_id(wire_it.first); +			newname = intfname + "." + newname; +			wire->str = newname; +			new_ast->children.push_back(wire); +		} +	} + +	AstNode *ast_before_replacing_interface_ports = new_ast->clone(); + +	// Explode all interface ports. Note this will only have an effect on 'top +	// level' modules. Other sub-modules will have their interface ports +	// exploded via the derive(..) function +	for (size_t i =0; i<new_ast->children.size(); i++) +	{ +		AstNode *ch2 = new_ast->children[i]; +		if (ch2->type == AST_INTERFACEPORT) { // Is an interface port +			std::string name_port = ch2->str; // Name of the interface port +			if (ch2->children.size() > 0) { +				for(size_t j=0; j<ch2->children.size();j++) { +					AstNode *ch = ch2->children[j]; +					if(ch->type == AST_INTERFACEPORTTYPE) { // Found the AST node containing the type of the interface +						std::pair<std::string,std::string> res = split_modport_from_type(ch->str); +						std::string interface_type = res.first; +						std::string interface_modport = res.second; // Is "", if no modport +						if (design->modules_.count(interface_type) > 0) { +							// Add a cell to the module corresponding to the interface port such that +							// it can further propagated down if needed: +							AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE); +							celltype_for_intf->str = interface_type; +							AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf); +							cell_for_intf->str = name_port + "_inst_from_top_dummy"; +							new_ast->children.push_back(cell_for_intf); + +							// Get all members of this non-overridden dummy interface instance: +							RTLIL::Module *intfmodule = design->modules_[interface_type]; // All interfaces should at this point in time (assuming +							                                                              // reprocess_module is called from the hierarchy pass) be +							                                                              // present in design->modules_ +							AstModule *ast_module_of_interface = (AstModule*)intfmodule; +							std::string interface_modport_compare_str = "\\" + interface_modport; +							AstNode *modport = find_modport(ast_module_of_interface->ast, interface_modport_compare_str); // modport == NULL if no modport +							// Iterate over all wires in the interface and add them to the module: +							explode_interface_port(new_ast, intfmodule, name_port, modport); +						} +						break; +					} +				} +			} +		} +	} + +	// The old module will be deleted. Rename and mark for deletion: +	std::string original_name = this->name.str(); +	std::string changed_name = original_name + "_before_replacing_local_interfaces"; +	design->rename(this, changed_name); +	this->set_bool_attribute("\\to_delete"); + +	// Check if the module was the top module. If it was, we need to remove the top attribute and put it on the +	// new module. +	if (this->get_bool_attribute("\\initial_top")) { +		this->attributes.erase("\\initial_top"); +		is_top = true; +	} + +	// Generate RTLIL from AST for the new module and add to the design: +	AstModule *newmod = process_module(new_ast, false, ast_before_replacing_interface_ports); +	delete(new_ast); +	design->add(newmod); +	RTLIL::Module* mod = design->module(original_name); +	if (is_top) +		mod->set_bool_attribute("\\top"); + +	// Set the attribute "interfaces_replaced_in_module" so that it does not happen again. +	mod->set_bool_attribute("\\interfaces_replaced_in_module"); +} + +// create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces +// This method is used to explode the interface when the interface is a port of the module (not instantiated inside) +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) +{ +	AstNode *new_ast = NULL; +	std::string modname = derive_common(design, parameters, &new_ast, mayfail); + +	// Since interfaces themselves may be instantiated with different parameters, +	// "modname" must also take those into account, so that unique modules +	// are derived for any variant of interface connections: +	std::string interf_info = ""; + +	bool has_interfaces = false; +	for(auto &intf : interfaces) { +		interf_info += log_id(intf.second->name); +		has_interfaces = true; +	} + +	if (has_interfaces) +		modname += "$interfaces$" + interf_info; + + +	if (!design->has(modname)) { +		new_ast->str = modname; + +		// Iterate over all interfaces which are ports in this module: +		for(auto &intf : interfaces) { +			RTLIL::Module * intfmodule = intf.second; +			std::string intfname = intf.first.str(); +			// Check if a modport applies for the interface port: +			AstNode *modport = NULL; +			if (modports.count(intfname) > 0) { +				std::string interface_modport = modports.at(intfname).str(); +				AstModule *ast_module_of_interface = (AstModule*)intfmodule; +				AstNode *ast_node_of_interface = ast_module_of_interface->ast; +				modport = find_modport(ast_node_of_interface, interface_modport); +			} +			// Iterate over all wires in the interface and add them to the module: +			explode_interface_port(new_ast, intfmodule, intfname, modport); +		} + +		design->add(process_module(new_ast, false)); +		design->module(modname)->check(); + +		RTLIL::Module* mod = design->module(modname); + +		// Now that the interfaces have been exploded, we can delete the dummy port related to every interface. +		for(auto &intf : interfaces) { +			if(mod->wires_.count(intf.first)) { +				mod->wires_.erase(intf.first); +				mod->fixup_ports(); +				// We copy the cell of the interface to the sub-module such that it can further be found if it is propagated +				// down to sub-sub-modules etc. +				RTLIL::Cell * new_subcell = mod->addCell(intf.first, intf.second->name); +				new_subcell->set_bool_attribute("\\is_interface"); +			} +			else { +				log_error("No port with matching name found (%s) in %s. Stopping\n", log_id(intf.first), modname.c_str()); +			} +		} + +		// If any interfaces were replaced, set the attribute 'interfaces_replaced_in_module': +		if (interfaces.size() > 0) { +			mod->set_bool_attribute("\\interfaces_replaced_in_module"); +		} + +	} else { +		log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); +	} + +	delete new_ast; +	return modname; +} + +// create a new parametric module (when needed) and return the name of the generated module - without support for interfaces +RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) +{ +	AstNode *new_ast = NULL; +	std::string modname = derive_common(design, parameters, &new_ast, mayfail); + +	if (!design->has(modname)) { +		new_ast->str = modname; +		design->add(process_module(new_ast, false)); +		design->module(modname)->check(); +	} else { +		log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); +	} + +	delete new_ast; +	return modname; +} +  // create a new parametric module (when needed) and return the name of the generated module -RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool) +std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool)  {  	std::string stripped_name = name.str(); @@ -1156,15 +1417,8 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R  	else  		modname = "$paramod" + stripped_name + para_info; -	if (!design->has(modname)) { -		new_ast->str = modname; -		design->add(process_module(new_ast, false)); -		design->module(modname)->check(); -	} else { -		log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); -	} -	delete new_ast; +	(*new_ast_out) = new_ast;  	return modname;  } diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 7e97bdb3b..08f91c9c3 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -142,6 +142,11 @@ namespace AST  		AST_NEGEDGE,  		AST_EDGE, +		AST_INTERFACE, +		AST_INTERFACEPORT, +		AST_INTERFACEPORTTYPE, +		AST_MODPORT, +		AST_MODPORTMEMBER,  		AST_PACKAGE  	}; @@ -284,6 +289,9 @@ namespace AST  		bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire;  		~AstModule() YS_OVERRIDE;  		RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE; +		RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE; +		std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool mayfail); +		void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE;  		RTLIL::Module *clone() const YS_OVERRIDE;  	}; @@ -300,6 +308,11 @@ namespace AST  	// call a DPI function  	AstNode *dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<AstNode*> &args); + +	// Helper functions related to handling SystemVerilog interfaces +	std::pair<std::string,std::string> split_modport_from_type(std::string name_type); +	AstNode * find_modport(AstNode *intf, std::string name); +	void explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport);  }  namespace AST_INTERNAL diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index c9345ff08..9531dd356 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -55,8 +55,7 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi  	if (gen_attributes)  		for (auto &attr : that->attributes) {  			if (attr.second->type != AST_CONSTANT) -				log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", -					       attr.first.c_str()); +				log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());  			cell->attributes[attr.first] = attr.second->asAttrConst();  		} @@ -89,8 +88,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s  	if (that != NULL)  		for (auto &attr : that->attributes) {  			if (attr.second->type != AST_CONSTANT) -				log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", -					       attr.first.c_str()); +				log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());  			cell->attributes[attr.first] = attr.second->asAttrConst();  		} @@ -117,8 +115,7 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi  	for (auto &attr : that->attributes) {  		if (attr.second->type != AST_CONSTANT) -			log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", -				       attr.first.c_str()); +			log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());  		cell->attributes[attr.first] = attr.second->asAttrConst();  	} @@ -152,8 +149,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const  	for (auto &attr : that->attributes) {  		if (attr.second->type != AST_CONSTANT) -			log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", -				       attr.first.c_str()); +			log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());  		cell->attributes[attr.first] = attr.second->asAttrConst();  	} @@ -480,8 +476,7 @@ struct AST_INTERNAL::ProcessGenerator  				for (auto &attr : ast->attributes) {  					if (attr.second->type != AST_CONSTANT) -						log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", -							       attr.first.c_str()); +						log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());  					sw->attributes[attr.first] = attr.second->asAttrConst();  				} @@ -648,8 +643,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun  				while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }  				while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }  				if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) -					log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", -						       str.c_str()); +					log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());  				this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;  				delete left_at_zero_ast;  				delete right_at_zero_ast; @@ -778,7 +772,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun  				while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }  				if (children[0]->type != AST_CONSTANT)  					log_file_error(filename, linenum, "System function %s called with non-const argument!\n", -						       RTLIL::unescape_id(str).c_str()); +							RTLIL::unescape_id(str).c_str());  				width_hint = max(width_hint, int(children[0]->asInt(true)));  			}  			break; @@ -799,8 +793,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun  	default:  		for (auto f : log_files)  			current_ast->dumpAst(f, "verilog-ast> "); -		log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", -			       type2str(type).c_str()); +		log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str());  	}  	if (*found_real) @@ -853,6 +846,35 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  	case AST_GENIF:  	case AST_GENCASE:  	case AST_PACKAGE: +	case AST_MODPORT: +	case AST_MODPORTMEMBER: +		break; +	case AST_INTERFACEPORT: { +		// If a port in a module with unknown type is found, mark it with the attribute 'is_interface' +		// This is used by the hierarchy pass to know when it can replace interface connection with the individual +		// signals. +		RTLIL::Wire *wire = current_module->addWire(str, 1); +		wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); +		wire->start_offset = 0; +		wire->port_id = port_id; +		wire->port_input = true; +		wire->port_output = true; +		wire->set_bool_attribute("\\is_interface"); +		if (children.size() > 0) { +			for(size_t i=0; i<children.size();i++) { +				if(children[i]->type == AST_INTERFACEPORTTYPE) { +					std::pair<std::string,std::string> res = AST::split_modport_from_type(children[i]->str); +					wire->attributes["\\interface_type"] = res.first; +					if (res.second != "") +						wire->attributes["\\interface_modport"] = res.second; +					break; +				} +			} +		} +		wire->upto = 0; +		} +		break; +	case AST_INTERFACEPORTTYPE:  		break;  	// remember the parameter, needed for example in techmap @@ -863,11 +885,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  	// create an RTLIL::Wire for an AST_WIRE node  	case AST_WIRE: {  			if (current_module->wires_.count(str) != 0) -				log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", -					       str.c_str()); +				log_file_error(filename, linenum, "Re-definition of signal `%s'!\n", str.c_str());  			if (!range_valid) -				log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", -					       str.c_str()); +				log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n", str.c_str());  			log_assert(range_left >= range_right || (range_left == -1 && range_right == 0)); @@ -881,8 +901,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  			for (auto &attr : attributes) {  				if (attr.second->type != AST_CONSTANT) -					log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", -						       attr.first.c_str()); +					log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());  				wire->attributes[attr.first] = attr.second->asAttrConst();  			}  		} @@ -891,16 +910,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  	// create an RTLIL::Memory for an AST_MEMORY node  	case AST_MEMORY: {  			if (current_module->memories.count(str) != 0) -				log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", -					       str.c_str()); +				log_file_error(filename, linenum, "Re-definition of memory `%s'!\n", str.c_str());  			log_assert(children.size() >= 2);  			log_assert(children[0]->type == AST_RANGE);  			log_assert(children[1]->type == AST_RANGE);  			if (!children[0]->range_valid || !children[1]->range_valid) -				log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", -					       str.c_str()); +				log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n", str.c_str());  			RTLIL::Memory *memory = new RTLIL::Memory;  			memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -917,8 +934,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  			for (auto &attr : attributes) {  				if (attr.second->type != AST_CONSTANT) -					log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", -						       attr.first.c_str()); +					log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());  				memory->attributes[attr.first] = attr.second->asAttrConst();  			}  		} @@ -937,8 +953,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  	case AST_REALVALUE:  		{  			RTLIL::SigSpec sig = realAsConst(width_hint); -			log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", -					 realvalue, log_signal(sig)); +			log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));  			return sig;  		} @@ -949,6 +964,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  		{  			RTLIL::Wire *wire = NULL;  			RTLIL::SigChunk chunk; +			bool is_interface = false;  			int add_undef_bits_msb = 0;  			int add_undef_bits_lsb = 0; @@ -964,19 +980,42 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  			}  			else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) {  				if (id2ast->children[0]->type != AST_CONSTANT) -					log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", -						       str.c_str()); +					log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n", str.c_str());  				chunk = RTLIL::Const(id2ast->children[0]->bits);  				goto use_const_chunk;  			} -			else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE && -					id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0) -				log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", -						str.c_str()); +			else if (id2ast && (id2ast->type == AST_WIRE || id2ast->type == AST_AUTOWIRE || id2ast->type == AST_MEMORY) && current_module->wires_.count(str) != 0) { +				RTLIL::Wire *current_wire = current_module->wire(str); +				if (current_wire->get_bool_attribute("\\is_interface")) +					is_interface = true; +				// Ignore +			} +			// If an identifier is found that is not already known, assume that it is an interface: +			else if (1) { // FIXME: Check if sv_mode first? +				is_interface = true; +			} +			else { +				log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n", str.c_str()); +			}  			if (id2ast->type == AST_MEMORY) -				log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", -					       str.c_str()); +				log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n", str.c_str()); + +			// If identifier is an interface, create a RTLIL::SigSpec with a dummy wire with a attribute called 'is_interface' +			// This makes it possible for the hierarchy pass to see what are interface connections and then replace them +			// with the individual signals: +			if (is_interface) { +				RTLIL::Wire *dummy_wire; +				std::string dummy_wire_name = "$dummywireforinterface" + str; +				if (current_module->wires_.count(dummy_wire_name)) +					dummy_wire = current_module->wires_[dummy_wire_name]; +				else { +					dummy_wire = current_module->addWire(dummy_wire_name); +					dummy_wire->set_bool_attribute("\\is_interface"); +				} +				RTLIL::SigSpec tmp = RTLIL::SigSpec(dummy_wire); +				return tmp; +			}  			wire = current_module->wires_[str];  			chunk.wire = wire; @@ -995,8 +1034,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  					while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }  					while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }  					if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) -						log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", -							       str.c_str()); +						log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());  					int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;  					AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?  							children[0]->children[1]->clone() : children[0]->children[0]->clone()); @@ -1025,10 +1063,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  					if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) {  						if (chunk.width == 1)  							log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n", -									 str.c_str()); +									str.c_str());  						else -							log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting all %d result bits to undef.\n", -									str.c_str(), chunk.width); +							log_file_warning(filename, linenum, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n", +									children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width);  						chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);  					} else {  						if (chunk.width + chunk.offset > source_width) { @@ -1041,11 +1079,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  							chunk.offset += add_undef_bits_lsb;  						}  						if (add_undef_bits_lsb) -							log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", -									 str.c_str(), add_undef_bits_lsb); +							log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n", +									children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb);  						if (add_undef_bits_msb) -							log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", -									 str.c_str(), add_undef_bits_msb); +							log_file_warning(filename, linenum, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n", +									children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb);  					}  				}  			} @@ -1380,8 +1418,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  			for (auto &attr : attributes) {  				if (attr.second->type != AST_CONSTANT) -					log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", -						       attr.first.c_str()); +					log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());  				cell->attributes[attr.first] = attr.second->asAttrConst();  			} @@ -1403,9 +1440,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  						new_right.append(right[i]);  					}  				log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n" -						 "    old assignment: %s = %s\n    new assignment: %s = %s.\n", -						 log_signal(left), log_signal(right), -						 log_signal(new_left), log_signal(new_right)); +						"    old assignment: %s = %s\n    new assignment: %s = %s.\n", +						log_signal(left), log_signal(right), +						log_signal(new_left), log_signal(new_right));  				left = new_left;  				right = new_right;  			} @@ -1423,6 +1460,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  			RTLIL::Cell *cell = current_module->addCell(str, "");  			cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); +			// Set attribute 'module_not_derived' which will be cleared again after the hierarchy pass +			cell->set_bool_attribute("\\module_not_derived");  			for (auto it = children.begin(); it != children.end(); it++) {  				AstNode *child = *it; @@ -1436,14 +1475,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  					IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;  					if (child->children[0]->type == AST_REALVALUE) {  						log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n", -								 log_id(cell), log_id(paraname), child->children[0]->realvalue); +								log_id(cell), log_id(paraname), child->children[0]->realvalue);  						auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue));  						strnode->cloneInto(child->children[0]);  						delete strnode;  					}  					if (child->children[0]->type != AST_CONSTANT)  						log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n", -							       log_id(cell), log_id(paraname)); +								log_id(cell), log_id(paraname));  					cell->parameters[paraname] = child->children[0]->asParaConst();  					continue;  				} @@ -1464,8 +1503,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  			}  			for (auto &attr : attributes) {  				if (attr.second->type != AST_CONSTANT) -					log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", -						       attr.first.c_str()); +					log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());  				cell->attributes[attr.first] = attr.second->asAttrConst();  			}  		} @@ -1493,18 +1531,17 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  				if (GetSize(children) > 1)  					log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n", -						       RTLIL::unescape_id(str).c_str(), GetSize(children)); +							RTLIL::unescape_id(str).c_str(), GetSize(children));  				if (GetSize(children) == 1) {  					if (children[0]->type != AST_CONSTANT)  						log_file_error(filename, linenum, "System function %s called with non-const argument!\n", -							       RTLIL::unescape_id(str).c_str()); +								RTLIL::unescape_id(str).c_str());  					width = children[0]->asInt(true);  				}  				if (width <= 0) -					log_file_error(filename, linenum, "Failed to detect width of %s!\n", -						       RTLIL::unescape_id(str).c_str()); +					log_file_error(filename, linenum, "Failed to detect width of %s!\n", RTLIL::unescape_id(str).c_str());  				Cell *cell = current_module->addCell(myid, str.substr(1));  				cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); @@ -1531,8 +1568,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  		for (auto f : log_files)  			current_ast->dumpAst(f, "verilog-ast> ");  		type_name = type2str(type); -		log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", -			       type_name.c_str()); +		log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str());  	}  	return RTLIL::SigSpec(); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 71eba547c..83714f897 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -71,7 +71,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  	if (stage == 0)  	{ -		log_assert(type == AST_MODULE); +		log_assert(type == AST_MODULE || type == AST_INTERFACE);  		last_blocking_assignment_warn = pair<string, int>();  		deep_recursion_warning = true; @@ -196,7 +196,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		int nargs = GetSize(children);  		if (nargs < 1)  			log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n", -				       str.c_str(), int(children.size())); +					str.c_str(), int(children.size()));  		// First argument is the format string  		AstNode *node_string = children[0]; @@ -240,7 +240,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  					case 'X':  						if (next_arg >= GetSize(children))  							log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n", -								       cformat, str.c_str()); +									cformat, str.c_str());  						node_arg = children[next_arg++];  						while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -450,8 +450,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  				children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment  			if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg)  				log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); -			if (type == AST_ASSIGN && children[0]->id2ast->is_reg) -				log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); +			if (type == AST_ASSIGN && children[0]->id2ast->is_reg) { +				bool is_rand_reg = false; +				if (children[1]->type == AST_FCALL) { +					if (children[1]->str == "\\$anyconst") +						is_rand_reg = true; +					if (children[1]->str == "\\$anyseq") +						is_rand_reg = true; +					if (children[1]->str == "\\$allconst") +						is_rand_reg = true; +					if (children[1]->str == "\\$allseq") +						is_rand_reg = true; +				} +				if (!is_rand_reg) +					log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); +			}  			children[0]->was_checked = true;  		}  		break; @@ -732,7 +745,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		if (current_scope.at(modname)->type != AST_CELL)  			log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n", -				       RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); +					RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());  		AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL);  		paraset->str = paramname; @@ -880,7 +893,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			if (children[0]->type == AST_REALVALUE) {  				RTLIL::Const constvalue = children[0]->realAsConst(width);  				log_file_warning(filename, linenum, "converting real value %e to binary %s.\n", -						 children[0]->realvalue, log_signal(constvalue)); +						children[0]->realvalue, log_signal(constvalue));  				delete children[0];  				children[0] = mkconst_bits(constvalue.bits, sign_hint);  				did_something = true; @@ -1299,8 +1312,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  	if (type == AST_PRIMITIVE)  	{  		if (children.size() < 2) -			log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", -				       str.c_str()); +			log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n", str.c_str());  		std::vector<AstNode*> children_list;  		for (auto child : children) { @@ -1315,8 +1327,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")  		{  			if (children_list.size() != 3) -				log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", -					       str.c_str()); +				log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n", str.c_str());  			std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz); @@ -1336,6 +1347,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			str.clear();  			type = AST_ASSIGN;  			children.push_back(children_list.at(0)); +			children.back()->was_checked = true;  			children.push_back(node);  			did_something = true;  		} @@ -1372,6 +1384,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			str.clear();  			type = AST_ASSIGN;  			children.push_back(children_list[0]); +			children.back()->was_checked = true;  			children.push_back(node);  			did_something = true;  		} @@ -1401,8 +1414,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }  			while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }  			if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) -				log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", -					       str.c_str()); +				log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());  			result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;  		}  		did_something = true; @@ -1530,6 +1542,7 @@ skip_dynamic_range_lvalue_expansion:;  			wire_tmp_id->str = wire_tmp->str;  			newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, wire_tmp_id, children[1]->clone())); +			newNode->children.back()->was_checked = true;  			int cursor = 0;  			for (auto child : children[0]->children) @@ -1772,11 +1785,11 @@ skip_dynamic_range_lvalue_expansion:;  				if (GetSize(children) != 1 && GetSize(children) != 2)  					log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", -						       RTLIL::unescape_id(str).c_str(), int(children.size())); +							RTLIL::unescape_id(str).c_str(), int(children.size()));  				if (!current_always_clocked)  					log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", -						       RTLIL::unescape_id(str).c_str()); +							RTLIL::unescape_id(str).c_str());  				if (GetSize(children) == 2)  				{ @@ -1797,6 +1810,11 @@ skip_dynamic_range_lvalue_expansion:;  				log_assert(block != nullptr); +				if (num_steps == 0) { +					newNode = children[0]->clone(); +					goto apply_newNode; +				} +  				int myidx = autoidx++;  				AstNode *outreg = nullptr; @@ -1815,6 +1833,7 @@ skip_dynamic_range_lvalue_expansion:;  					AstNode *regid = new AstNode(AST_IDENTIFIER);  					regid->str = reg->str;  					regid->id2ast = reg; +					regid->was_checked = true;  					AstNode *rhs = nullptr; @@ -1840,11 +1859,11 @@ skip_dynamic_range_lvalue_expansion:;  			{  				if (GetSize(children) != 1)  					log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", -						       RTLIL::unescape_id(str).c_str(), int(children.size())); +							RTLIL::unescape_id(str).c_str(), int(children.size()));  				if (!current_always_clocked)  					log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n", -						       RTLIL::unescape_id(str).c_str()); +							RTLIL::unescape_id(str).c_str());  				AstNode *present = children.at(0)->clone();  				AstNode *past = clone(); @@ -1857,10 +1876,14 @@ skip_dynamic_range_lvalue_expansion:;  					newNode = new AstNode(AST_NE, past, present);  				else if (str == "\\$rose") -					newNode = new AstNode(AST_LOGIC_AND, new AstNode(AST_LOGIC_NOT, past), present); +					newNode = new AstNode(AST_LOGIC_AND, +							new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, past, mkconst_int(1,false))), +							new AstNode(AST_BIT_AND, present, mkconst_int(1,false)));  				else if (str == "\\$fell") -					newNode = new AstNode(AST_LOGIC_AND, past, new AstNode(AST_LOGIC_NOT, present)); +					newNode = new AstNode(AST_LOGIC_AND, +							new AstNode(AST_BIT_AND, past, mkconst_int(1,false)), +							new AstNode(AST_LOGIC_NOT, new AstNode(AST_BIT_AND, present, mkconst_int(1,false))));  				else  					log_abort(); @@ -1878,7 +1901,7 @@ skip_dynamic_range_lvalue_expansion:;  			{  				if (children.size() != 1)  					log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", -						       RTLIL::unescape_id(str).c_str(), int(children.size())); +							RTLIL::unescape_id(str).c_str(), int(children.size()));  				AstNode *buf = children[0]->clone();  				while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -1895,7 +1918,7 @@ skip_dynamic_range_lvalue_expansion:;  					if (arg_value.bits.at(i) == RTLIL::State::S1)  						result = i + 1; -				newNode = mkconst_int(result, false); +				newNode = mkconst_int(result, true);  				goto apply_newNode;  			} @@ -1903,11 +1926,11 @@ skip_dynamic_range_lvalue_expansion:;  			{  				if (str == "\\$bits" && children.size() != 1)  					log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", -						       RTLIL::unescape_id(str).c_str(), int(children.size())); +							RTLIL::unescape_id(str).c_str(), int(children.size()));  				if (str == "\\$size" && children.size() != 1 && children.size() != 2)  					log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n", -						       RTLIL::unescape_id(str).c_str(), int(children.size())); +							RTLIL::unescape_id(str).c_str(), int(children.size()));  				int dim = 1;  				if (str == "\\$size" && children.size() == 2) { @@ -1981,18 +2004,18 @@ skip_dynamic_range_lvalue_expansion:;  				if (func_with_two_arguments) {  					if (children.size() != 2)  						log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n", -							       RTLIL::unescape_id(str).c_str(), int(children.size())); +								RTLIL::unescape_id(str).c_str(), int(children.size()));  				} else {  					if (children.size() != 1)  						log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n", -							       RTLIL::unescape_id(str).c_str(), int(children.size())); +								RTLIL::unescape_id(str).c_str(), int(children.size()));  				}  				if (children.size() >= 1) {  					while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }  					if (!children[0]->isConst())  						log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", -							       RTLIL::unescape_id(str).c_str()); +								RTLIL::unescape_id(str).c_str());  					int child_width_hint = width_hint;  					bool child_sign_hint = sign_hint;  					children[0]->detectSignWidth(child_width_hint, child_sign_hint); @@ -2003,7 +2026,7 @@ skip_dynamic_range_lvalue_expansion:;  					while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }  					if (!children[1]->isConst())  						log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n", -							       RTLIL::unescape_id(str).c_str()); +								RTLIL::unescape_id(str).c_str());  					int child_width_hint = width_hint;  					bool child_sign_hint = sign_hint;  					children[1]->detectSignWidth(child_width_hint, child_sign_hint); @@ -2091,7 +2114,7 @@ skip_dynamic_range_lvalue_expansion:;  			{  				if (GetSize(children) < 2 || GetSize(children) > 4)  					log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n", -						       RTLIL::unescape_id(str).c_str(), int(children.size())); +							RTLIL::unescape_id(str).c_str(), int(children.size()));  				AstNode *node_filename = children[0]->clone();  				while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } @@ -2204,6 +2227,8 @@ skip_dynamic_range_lvalue_expansion:;  			AstNode *always = new AstNode(AST_ALWAYS, new AstNode(AST_BLOCK,  					new AstNode(AST_ASSIGN_EQ, lvalue, clone()))); +			always->children[0]->children[0]->was_checked = true; +  			current_ast_mod->children.push_back(always);  			goto replace_fcall_with_id; @@ -2253,6 +2278,7 @@ skip_dynamic_range_lvalue_expansion:;  						AstNode *assign = child->is_input ?  								new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg) :  								new AstNode(AST_ASSIGN_EQ, arg, wire_id->clone()); +						assign->children[0]->was_checked = true;  						for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {  							if (*it != current_block_child) @@ -2323,6 +2349,7 @@ skip_dynamic_range_lvalue_expansion:;  					AstNode *assign = child->is_input ?  							new AstNode(AST_ASSIGN_EQ, wire_id, arg) :  							new AstNode(AST_ASSIGN_EQ, arg, wire_id); +					assign->children[0]->was_checked = true;  					for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {  						if (*it != current_block_child) @@ -2762,6 +2789,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m  				block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor, false))), value));  				block->children.back()->children[0]->str = memory->str;  				block->children.back()->children[0]->id2ast = memory; +				block->children.back()->children[0]->was_checked = true;  			}  			cursor += increment; @@ -3022,6 +3050,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,  		AstNode *newNode = clone();  		newNode->type = AST_ASSIGN_EQ; +		newNode->children[0]->was_checked = true;  		async_block->children[0]->children.push_back(newNode);  		newNode = new AstNode(AST_NONE); @@ -3067,6 +3096,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,  		AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());  		assign_addr->children[0]->str = id_addr; +		assign_addr->children[0]->was_checked = true;  		block->children.insert(block->children.begin()+assign_idx+1, assign_addr);  		AstNode *case_node = new AstNode(AST_CASE, new AstNode(AST_IDENTIFIER)); @@ -3090,6 +3120,7 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,  		children[0]->id2ast = NULL;  		children[0]->str = id_data;  		type = AST_ASSIGN_EQ; +		children[0]->was_checked = true;  		did_something = true;  	} @@ -3247,12 +3278,12 @@ void AstNode::replace_variables(std::map<std::string, AstNode::varinfo_t> &varia  		if (!children.empty()) {  			if (children.size() != 1 || children.at(0)->type != AST_RANGE)  				log_file_error(filename, linenum, "Memory access in constant function is not supported\n%s:%d: ...called from here.\n", -					       fcall->filename.c_str(), fcall->linenum); +						fcall->filename.c_str(), fcall->linenum);  			children.at(0)->replace_variables(variables, fcall);  			while (simplify(true, false, false, 1, -1, false, true)) { }  			if (!children.at(0)->range_valid)  				log_file_error(filename, linenum, "Non-constant range\n%s:%d: ... called from here.\n", -					       fcall->filename.c_str(), fcall->linenum); +						fcall->filename.c_str(), fcall->linenum);  			offset = min(children.at(0)->range_left, children.at(0)->range_right);  			width = min(std::abs(children.at(0)->range_left - children.at(0)->range_right) + 1, width);  		} @@ -3292,7 +3323,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)  			while (child->simplify(true, false, false, 1, -1, false, true)) { }  			if (!child->range_valid)  				log_file_error(child->filename, child->linenum, "Can't determine size of variable %s\n%s:%d: ... called from here.\n", -					       child->str.c_str(), fcall->filename.c_str(), fcall->linenum); +						child->str.c_str(), fcall->filename.c_str(), fcall->linenum);  			variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);  			variables[child->str].offset = min(child->range_left, child->range_right);  			variables[child->str].is_signed = child->is_signed; @@ -3336,15 +3367,15 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)  			if (stmt->children.at(1)->type != AST_CONSTANT)  				log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here. X\n", -					       fcall->filename.c_str(), fcall->linenum); +						fcall->filename.c_str(), fcall->linenum);  			if (stmt->children.at(0)->type != AST_IDENTIFIER)  				log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function\n%s:%d: ... called from here.\n", -					       fcall->filename.c_str(), fcall->linenum); +						fcall->filename.c_str(), fcall->linenum);  			if (!variables.count(stmt->children.at(0)->str))  				log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function\n%s:%d: ... called from here.\n", -					       fcall->filename.c_str(), fcall->linenum); +						fcall->filename.c_str(), fcall->linenum);  			if (stmt->children.at(0)->children.empty()) {  				variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size()); @@ -3352,7 +3383,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)  				AstNode *range = stmt->children.at(0)->children.at(0);  				if (!range->range_valid)  					log_file_error(range->filename, range->linenum, "Non-constant range\n%s:%d: ... called from here.\n", -						       fcall->filename.c_str(), fcall->linenum); +							fcall->filename.c_str(), fcall->linenum);  				int offset = min(range->range_left, range->range_right);  				int width = std::abs(range->range_left - range->range_right) + 1;  				varinfo_t &v = variables[stmt->children.at(0)->str]; @@ -3384,7 +3415,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)  			if (cond->type != AST_CONSTANT)  				log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", -					       fcall->filename.c_str(), fcall->linenum); +						fcall->filename.c_str(), fcall->linenum);  			if (cond->asBool()) {  				block->children.insert(block->children.begin(), stmt->children.at(1)->clone()); @@ -3405,7 +3436,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)  			if (num->type != AST_CONSTANT)  				log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", -					       fcall->filename.c_str(), fcall->linenum); +						fcall->filename.c_str(), fcall->linenum);  			block->children.erase(block->children.begin());  			for (int i = 0; i < num->bitsAsConst().as_int(); i++) @@ -3443,7 +3474,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)  					if (cond->type != AST_CONSTANT)  						log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function\n%s:%d: ... called from here.\n", -							       fcall->filename.c_str(), fcall->linenum); +								fcall->filename.c_str(), fcall->linenum);  					found_match = cond->asBool();  					delete cond; @@ -3473,7 +3504,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)  		}  		log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function\n%s:%d: ... called from here.\n", -			       fcall->filename.c_str(), fcall->linenum); +				fcall->filename.c_str(), fcall->linenum);  		log_abort();  	} diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index bfc062fec..b957ecd96 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -387,17 +387,13 @@ sigspec:  		$$ = new RTLIL::SigSpec(current_module->wires_[$1]);  		free($1);  	} | -	TOK_ID '[' TOK_INT ']' { -		if (current_module->wires_.count($1) == 0) -			rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str()); -		$$ = new RTLIL::SigSpec(current_module->wires_[$1], $3); -		free($1); +	sigspec '[' TOK_INT ']' { +		$$ = new RTLIL::SigSpec($1->extract($3)); +		delete $1;  	} | -	TOK_ID '[' TOK_INT ':' TOK_INT ']' { -		if (current_module->wires_.count($1) == 0) -			rtlil_frontend_ilang_yyerror(stringf("ilang error: wire %s not found", $1).c_str()); -		$$ = new RTLIL::SigSpec(current_module->wires_[$1], $5, $3 - $5 + 1); -		free($1); +	sigspec '[' TOK_INT ':' TOK_INT ']' { +		$$ = new RTLIL::SigSpec($1->extract($5, $3 - $5 + 1)); +		delete $1;  	} |  	'{' sigspec_list '}' {  		$$ = $2; diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 0a5bd84de..4acfbf1cb 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -36,7 +36,8 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *&  	int id_len = 0;  	while (('a' <= expr[id_len] && expr[id_len] <= 'z') || ('A' <= expr[id_len] && expr[id_len] <= 'Z') || -			('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' || expr[id_len] == '_') id_len++; +			('0' <= expr[id_len] && expr[id_len] <= '9') || expr[id_len] == '.' || +			expr[id_len] == '_' || expr[id_len] == '[' || expr[id_len] == ']') id_len++;  	if (id_len == 0)  		log_error("Expected identifier at `%s'.\n", expr); @@ -634,9 +635,12 @@ struct LibertyFrontend : public Frontend {  				}  			} -			for (auto node : cell->children) +			if (!flag_lib)  			{ -				if (!flag_lib) { +				// some liberty files do not put ff/latch at the beginning of a cell +				// try to find "ff" or "latch" and create FF/latch _before_ processing all other nodes +				for (auto node : cell->children) +				{  					if (node->id == "ff" && node->args.size() == 2)  						create_ff(module, node);  					if (node->id == "latch" && node->args.size() == 2) @@ -645,7 +649,10 @@ struct LibertyFrontend : public Frontend {  							goto skip_cell;  						}  				} +			} +			for (auto node : cell->children) +			{  				if (node->id == "pin" && node->args.size() == 1)  				{  					LibertyAst *dir = node->find("direction"); diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index dba3b0f0c..61d9d593c 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -130,6 +130,15 @@ bool is_blackbox(Netlist *nl)  	return false;  } +RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj) +{ +	std::string s = stringf("$verific$%s", obj->Name()); +	if (obj->Linefile()) +		s += stringf("$%s:%d", Verific::LineFile::GetFileName(obj->Linefile()), Verific::LineFile::GetLineNo(obj->Linefile())); +	s += stringf("$%d", autoidx++); +	return s; +} +  void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj)  {  	MapIter mi; @@ -215,7 +224,7 @@ RTLIL::SigSpec VerificImporter::operatorOutput(Instance *inst, const pool<Net*,  			dummy_wire = NULL;  		} else {  			if (dummy_wire == NULL) -				dummy_wire = module->addWire(NEW_ID); +				dummy_wire = module->addWire(new_verific_id(inst));  			else  				dummy_wire->width++;  			sig.append(RTLIL::SigSpec(dummy_wire, dummy_wire->width - 1)); @@ -231,8 +240,8 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr  	}  	if (inst->Type() == PRIM_NAND) { -		RTLIL::SigSpec tmp = module->addWire(NEW_ID); -		module->addAndGate(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); +		RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); +		module->addAndGate(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);  		module->addNotGate(inst_name, tmp, net_map_at(inst->GetOutput()));  		return true;  	} @@ -243,8 +252,8 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr  	}  	if (inst->Type() == PRIM_NOR) { -		RTLIL::SigSpec tmp = module->addWire(NEW_ID); -		module->addOrGate(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); +		RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); +		module->addOrGate(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp);  		module->addNotGate(inst_name, tmp, net_map_at(inst->GetOutput()));  		return true;  	} @@ -284,16 +293,16 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr  	if (inst->Type() == PRIM_FADD)  	{  		RTLIL::SigSpec a = net_map_at(inst->GetInput1()), b = net_map_at(inst->GetInput2()), c = net_map_at(inst->GetCin()); -		RTLIL::SigSpec x = inst->GetCout() ? net_map_at(inst->GetCout()) : module->addWire(NEW_ID); -		RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(NEW_ID); -		RTLIL::SigSpec tmp1 = module->addWire(NEW_ID); -		RTLIL::SigSpec tmp2 = module->addWire(NEW_ID); -		RTLIL::SigSpec tmp3 = module->addWire(NEW_ID); -		module->addXorGate(NEW_ID, a, b, tmp1); +		RTLIL::SigSpec x = inst->GetCout() ? net_map_at(inst->GetCout()) : module->addWire(new_verific_id(inst)); +		RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(new_verific_id(inst)); +		RTLIL::SigSpec tmp1 = module->addWire(new_verific_id(inst)); +		RTLIL::SigSpec tmp2 = module->addWire(new_verific_id(inst)); +		RTLIL::SigSpec tmp3 = module->addWire(new_verific_id(inst)); +		module->addXorGate(new_verific_id(inst), a, b, tmp1);  		module->addXorGate(inst_name, tmp1, c, y); -		module->addAndGate(NEW_ID, tmp1, c, tmp2); -		module->addAndGate(NEW_ID, a, b, tmp3); -		module->addOrGate(NEW_ID, tmp2, tmp3, x); +		module->addAndGate(new_verific_id(inst), tmp1, c, tmp2); +		module->addAndGate(new_verific_id(inst), a, b, tmp3); +		module->addOrGate(new_verific_id(inst), tmp2, tmp3, x);  		return true;  	} @@ -320,63 +329,78 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr  bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdString inst_name)  { +	RTLIL::Cell *cell = nullptr; +  	if (inst->Type() == PRIM_AND) { -		module->addAnd(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); +		cell = module->addAnd(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == PRIM_NAND) { -		RTLIL::SigSpec tmp = module->addWire(NEW_ID); -		module->addAnd(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); -		module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); +		RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); +		cell = module->addAnd(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); +		import_attributes(cell->attributes, inst); +		cell = module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == PRIM_OR) { -		module->addOr(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); +		cell = module->addOr(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == PRIM_NOR) { -		RTLIL::SigSpec tmp = module->addWire(NEW_ID); -		module->addOr(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); -		module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); +		RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst)); +		cell = module->addOr(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), tmp); +		import_attributes(cell->attributes, inst); +		cell = module->addNot(inst_name, tmp, net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == PRIM_XOR) { -		module->addXor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); +		cell = module->addXor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == PRIM_XNOR) { -		module->addXnor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); +		cell = module->addXnor(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == PRIM_INV) { -		module->addNot(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); +		cell = module->addNot(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == PRIM_MUX) { -		module->addMux(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); +		cell = module->addMux(inst_name, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == PRIM_TRI) { -		module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); +		cell = module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == PRIM_FADD)  	{ -		RTLIL::SigSpec a_plus_b = module->addWire(NEW_ID, 2); -		RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(NEW_ID); +		RTLIL::SigSpec a_plus_b = module->addWire(new_verific_id(inst), 2); +		RTLIL::SigSpec y = inst->GetOutput() ? net_map_at(inst->GetOutput()) : module->addWire(new_verific_id(inst));  		if (inst->GetCout())  			y.append(net_map_at(inst->GetCout())); -		module->addAdd(NEW_ID, net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), a_plus_b); -		module->addAdd(inst_name, a_plus_b, net_map_at(inst->GetCin()), y); +		cell = module->addAdd(new_verific_id(inst), net_map_at(inst->GetInput1()), net_map_at(inst->GetInput2()), a_plus_b); +		import_attributes(cell->attributes, inst); +		cell = module->addAdd(inst_name, a_plus_b, net_map_at(inst->GetCin()), y); +		import_attributes(cell->attributes, inst);  		return true;  	} @@ -387,24 +411,26 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr  		log_assert(clocking.body_net == nullptr);  		if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd()) -			clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); +			cell = clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));  		else if (inst->GetSet()->IsGnd()) -			clocking.addAdff(inst_name, net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S0); +			cell = clocking.addAdff(inst_name, net_map_at(inst->GetReset()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S0);  		else if (inst->GetReset()->IsGnd()) -			clocking.addAdff(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S1); +			cell = clocking.addAdff(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()), RTLIL::State::S1);  		else -			clocking.addDffsr(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetReset()), +			cell = clocking.addDffsr(inst_name, net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),  					net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == PRIM_DLATCHRS)  	{  		if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd()) -			module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); +			cell = module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));  		else -			module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()), +			cell = module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),  					net_map_at(inst->GetInput()), net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	} @@ -420,37 +446,45 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr  		if (inst->GetCout() != NULL)  			out.append(net_map_at(inst->GetCout()));  		if (inst->GetCin()->IsGnd()) { -			module->addAdd(inst_name, IN1, IN2, out, SIGNED); +			cell = module->addAdd(inst_name, IN1, IN2, out, SIGNED); +			import_attributes(cell->attributes, inst);  		} else { -			RTLIL::SigSpec tmp = module->addWire(NEW_ID, GetSize(out)); -			module->addAdd(NEW_ID, IN1, IN2, tmp, SIGNED); -			module->addAdd(inst_name, tmp, net_map_at(inst->GetCin()), out, false); +			RTLIL::SigSpec tmp = module->addWire(new_verific_id(inst), GetSize(out)); +			cell = module->addAdd(new_verific_id(inst), IN1, IN2, tmp, SIGNED); +			import_attributes(cell->attributes, inst); +			cell = module->addAdd(inst_name, tmp, net_map_at(inst->GetCin()), out, false); +			import_attributes(cell->attributes, inst);  		}  		return true;  	}  	if (inst->Type() == OPER_MULTIPLIER) { -		module->addMul(inst_name, IN1, IN2, OUT, SIGNED); +		cell = module->addMul(inst_name, IN1, IN2, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_DIVIDER) { -		module->addDiv(inst_name, IN1, IN2, OUT, SIGNED); +		cell = module->addDiv(inst_name, IN1, IN2, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_MODULO) { -		module->addMod(inst_name, IN1, IN2, OUT, SIGNED); +		cell = module->addMod(inst_name, IN1, IN2, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_REMAINDER) { -		module->addMod(inst_name, IN1, IN2, OUT, SIGNED); +		cell = module->addMod(inst_name, IN1, IN2, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_SHIFT_LEFT) { -		module->addShl(inst_name, IN1, IN2, OUT, false); +		cell = module->addShl(inst_name, IN1, IN2, OUT, false); +		import_attributes(cell->attributes, inst);  		return true;  	} @@ -460,7 +494,8 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr  		for (unsigned i = 1; i < inst->OutputSize(); i++) {  			vec.append(RTLIL::State::S0);  		} -		module->addShl(inst_name, vec, IN, OUT, false); +		cell = module->addShl(inst_name, vec, IN, OUT, false); +		import_attributes(cell->attributes, inst);  		return true;  	} @@ -470,7 +505,8 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr  		for (unsigned i = 1; i < inst->OutputSize(); i++) {  			vec.append(RTLIL::State::S0);  		} -		module->addShl(inst_name, vec, IN, OUT, false); +		cell = module->addShl(inst_name, vec, IN, OUT, false); +		import_attributes(cell->attributes, inst);  		return true;  	} @@ -478,108 +514,127 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr  		Net *net_cin = inst->GetCin();  		Net *net_a_msb = inst->GetInput1Bit(0);  		if (net_cin->IsGnd()) -			module->addShr(inst_name, IN1, IN2, OUT, false); +			cell = module->addShr(inst_name, IN1, IN2, OUT, false);  		else if (net_cin == net_a_msb) -			module->addSshr(inst_name, IN1, IN2, OUT, true); +			cell = module->addSshr(inst_name, IN1, IN2, OUT, true);  		else  			log_error("Can't import Verific OPER_SHIFT_RIGHT instance %s: carry_in is neither 0 nor msb of left input\n", inst->Name()); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_REDUCE_AND) { -		module->addReduceAnd(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); +		cell = module->addReduceAnd(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_REDUCE_OR) { -		module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); +		cell = module->addReduceOr(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_REDUCE_XOR) { -		module->addReduceXor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); +		cell = module->addReduceXor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_REDUCE_XNOR) { -		module->addReduceXnor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); +		cell = module->addReduceXnor(inst_name, IN, net_map_at(inst->GetOutput()), SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_REDUCE_NOR) { -		SigSpec t = module->ReduceOr(NEW_ID, IN, SIGNED); -		module->addNot(inst_name, t, net_map_at(inst->GetOutput())); +		SigSpec t = module->ReduceOr(new_verific_id(inst), IN, SIGNED); +		cell = module->addNot(inst_name, t, net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_LESSTHAN) {  		Net *net_cin = inst->GetCin();  		if (net_cin->IsGnd()) -			module->addLt(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); +			cell = module->addLt(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);  		else if (net_cin->IsPwr()) -			module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); +			cell = module->addLe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED);  		else  			log_error("Can't import Verific OPER_LESSTHAN instance %s: carry_in is neither 0 nor 1\n", inst->Name()); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_WIDE_AND) { -		module->addAnd(inst_name, IN1, IN2, OUT, SIGNED); +		cell = module->addAnd(inst_name, IN1, IN2, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_WIDE_OR) { -		module->addOr(inst_name, IN1, IN2, OUT, SIGNED); +		cell = module->addOr(inst_name, IN1, IN2, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_WIDE_XOR) { -		module->addXor(inst_name, IN1, IN2, OUT, SIGNED); +		cell = module->addXor(inst_name, IN1, IN2, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_WIDE_XNOR) { -		module->addXnor(inst_name, IN1, IN2, OUT, SIGNED); +		cell = module->addXnor(inst_name, IN1, IN2, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_WIDE_BUF) { -		module->addPos(inst_name, IN, FILTERED_OUT, SIGNED); +		cell = module->addPos(inst_name, IN, FILTERED_OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_WIDE_INV) { -		module->addNot(inst_name, IN, OUT, SIGNED); +		cell = module->addNot(inst_name, IN, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_MINUS) { -		module->addSub(inst_name, IN1, IN2, OUT, SIGNED); +		cell = module->addSub(inst_name, IN1, IN2, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_UMINUS) { -		module->addNeg(inst_name, IN, OUT, SIGNED); +		cell = module->addNeg(inst_name, IN, OUT, SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_EQUAL) { -		module->addEq(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); +		cell = module->addEq(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_NEQUAL) { -		module->addNe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); +		cell = module->addNe(inst_name, IN1, IN2, net_map_at(inst->GetOutput()), SIGNED); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_WIDE_MUX) { -		module->addMux(inst_name, IN1, IN2, net_map_at(inst->GetControl()), OUT); +		cell = module->addMux(inst_name, IN1, IN2, net_map_at(inst->GetControl()), OUT); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_NTO1MUX) { -		module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput())); +		cell = module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	} @@ -599,25 +654,29 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr  			padded_data.append(d);  		} -		module->addShr(inst_name, padded_data, sel, out); +		cell = module->addShr(inst_name, padded_data, sel, out); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_SELECTOR)  	{ -		module->addPmux(inst_name, State::S0, IN2, IN1, net_map_at(inst->GetOutput())); +		cell = module->addPmux(inst_name, State::S0, IN2, IN1, net_map_at(inst->GetOutput())); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_WIDE_SELECTOR)  	{  		SigSpec out = OUT; -		module->addPmux(inst_name, SigSpec(State::S0, GetSize(out)), IN2, IN1, out); +		cell = module->addPmux(inst_name, SigSpec(State::S0, GetSize(out)), IN2, IN1, out); +		import_attributes(cell->attributes, inst);  		return true;  	}  	if (inst->Type() == OPER_WIDE_TRI) { -		module->addMux(inst_name, RTLIL::SigSpec(RTLIL::State::Sz, inst->OutputSize()), IN, net_map_at(inst->GetControl()), OUT); +		cell = module->addMux(inst_name, RTLIL::SigSpec(RTLIL::State::Sz, inst->OutputSize()), IN, net_map_at(inst->GetControl()), OUT); +		import_attributes(cell->attributes, inst);  		return true;  	} @@ -631,9 +690,10 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr  		RTLIL::SigSpec sig_reset = operatorInport(inst, "reset");  		if (sig_set.is_fully_const() && !sig_set.as_bool() && sig_reset.is_fully_const() && !sig_reset.as_bool()) -			clocking.addDff(inst_name, IN, OUT); +			cell = clocking.addDff(inst_name, IN, OUT);  		else -			clocking.addDffsr(inst_name, sig_set, sig_reset, IN, OUT); +			cell = clocking.addDffsr(inst_name, sig_set, sig_reset, IN, OUT); +		import_attributes(cell->attributes, inst);  		return true;  	} @@ -862,7 +922,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  						ascii_initdata++;  					}  					if (initval_valid) { -						RTLIL::Cell *cell = module->addCell(NEW_ID, "$meminit"); +						RTLIL::Cell *cell = module->addCell(new_verific_id(net), "$meminit");  						cell->parameters["\\WORDS"] = 1;  						if (net->GetOrigTypeRange()->LeftRangeBound() < net->GetOrigTypeRange()->RightRangeBound())  							cell->setPort("\\ADDR", word_idx); @@ -925,7 +985,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  		if (net->Bus())  			continue; -		RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : NEW_ID); +		RTLIL::IdString wire_name = module->uniquify(mode_names || net->IsUserDeclared() ? RTLIL::escape_id(net->Name()) : new_verific_id(net));  		if (verific_verbose)  			log("  importing net %s as %s.\n", net->Name(), log_id(wire_name)); @@ -949,7 +1009,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  		if (found_new_net)  		{ -			RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : NEW_ID); +			RTLIL::IdString wire_name = module->uniquify(mode_names || netbus->IsUserDeclared() ? RTLIL::escape_id(netbus->Name()) : new_verific_id(netbus));  			if (verific_verbose)  				log("  importing netbus %s as %s.\n", netbus->Name(), log_id(wire_name)); @@ -1025,16 +1085,16 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  		}  		if (GetSize(anyconst_sig)) -			module->connect(anyconst_sig, module->Anyconst(NEW_ID, GetSize(anyconst_sig))); +			module->connect(anyconst_sig, module->Anyconst(new_verific_id(netbus), GetSize(anyconst_sig)));  		if (GetSize(anyseq_sig)) -			module->connect(anyseq_sig, module->Anyseq(NEW_ID, GetSize(anyseq_sig))); +			module->connect(anyseq_sig, module->Anyseq(new_verific_id(netbus), GetSize(anyseq_sig)));  		if (GetSize(allconst_sig)) -			module->connect(allconst_sig, module->Allconst(NEW_ID, GetSize(allconst_sig))); +			module->connect(allconst_sig, module->Allconst(new_verific_id(netbus), GetSize(allconst_sig)));  		if (GetSize(allseq_sig)) -			module->connect(allseq_sig, module->Allseq(NEW_ID, GetSize(allseq_sig))); +			module->connect(allseq_sig, module->Allseq(new_verific_id(netbus), GetSize(allseq_sig)));  	}  	for (auto it : init_nets) @@ -1058,10 +1118,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  	}  	for (auto net : anyconst_nets) -		module->connect(net_map_at(net), module->Anyconst(NEW_ID)); +		module->connect(net_map_at(net), module->Anyconst(new_verific_id(net)));  	for (auto net : anyseq_nets) -		module->connect(net_map_at(net), module->Anyseq(NEW_ID)); +		module->connect(net_map_at(net), module->Anyseq(new_verific_id(net)));  	pool<Instance*, hash_ptr_ops> sva_asserts;  	pool<Instance*, hash_ptr_ops> sva_assumes; @@ -1072,7 +1132,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  	FOREACH_INSTANCE_OF_NETLIST(nl, mi, inst)  	{ -		RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : NEW_ID); +		RTLIL::IdString inst_name = module->uniquify(mode_names || inst->IsUserDeclared() ? RTLIL::escape_id(inst->Name()) : new_verific_id(inst));  		if (verific_verbose)  			log("  importing cell %s (%s) as %s.\n", inst->Name(), inst->View()->Owner()->Name(), log_id(inst_name)); @@ -1196,7 +1256,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  			log_assert(inst->Input1Size() == inst->OutputSize());  			SigSpec sig_d, sig_q, sig_o; -			sig_q = module->addWire(NEW_ID, inst->Input1Size()); +			sig_q = module->addWire(new_verific_id(inst), inst->Input1Size());  			for (int i = int(inst->Input1Size())-1; i >= 0; i--){  				sig_d.append(net_map_at(inst->GetInput1Bit(i))); @@ -1210,8 +1270,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  						log_signal(sig_d), log_signal(sig_q), log_signal(sig_o));  			} -			clocking.addDff(NEW_ID, sig_d, sig_q); -			module->addXnor(NEW_ID, sig_d, sig_q, sig_o); +			clocking.addDff(new_verific_id(inst), sig_d, sig_q); +			module->addXnor(new_verific_id(inst), sig_d, sig_q, sig_o);  			if (!mode_keep)  				continue; @@ -1225,7 +1285,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  			SigSpec sig_d = net_map_at(inst->GetInput1());  			SigSpec sig_o = net_map_at(inst->GetOutput()); -			SigSpec sig_q = module->addWire(NEW_ID); +			SigSpec sig_q = module->addWire(new_verific_id(inst));  			if (verific_verbose) {  				log("    %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg", @@ -1234,8 +1294,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  						log_signal(sig_d), log_signal(sig_q), log_signal(sig_o));  			} -			clocking.addDff(NEW_ID, sig_d, sig_q); -			module->addXnor(NEW_ID, sig_d, sig_q, sig_o); +			clocking.addDff(new_verific_id(inst), sig_d, sig_q); +			module->addXnor(new_verific_id(inst), sig_d, sig_q, sig_o);  			if (!mode_keep)  				continue; @@ -1254,7 +1314,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  				log("    %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg",  						log_signal(sig_d), log_signal(sig_q), log_signal(clocking.clock_sig)); -			past_ffs.insert(clocking.addDff(NEW_ID, sig_d, sig_q)); +			past_ffs.insert(clocking.addDff(new_verific_id(inst), sig_d, sig_q));  			if (!mode_keep)  				continue; @@ -1268,14 +1328,14 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  			SigBit sig_d = net_map_at(inst->GetInput1());  			SigBit sig_o = net_map_at(inst->GetOutput()); -			SigBit sig_q = module->addWire(NEW_ID); +			SigBit sig_q = module->addWire(new_verific_id(inst));  			if (verific_verbose)  				log("    %sedge FF with D=%s, Q=%s, C=%s.\n", clocking.posedge ? "pos" : "neg",  						log_signal(sig_d), log_signal(sig_q), log_signal(clocking.clock_sig)); -			clocking.addDff(NEW_ID, sig_d, sig_q); -			module->addEq(NEW_ID, {sig_q, sig_d}, Const(inst->Type() == PRIM_SVA_ROSE ? 1 : 2, 2), sig_o); +			clocking.addDff(new_verific_id(inst), sig_d, sig_q); +			module->addEq(new_verific_id(inst), {sig_q, sig_d}, Const(inst->Type() == PRIM_SVA_ROSE ? 1 : 2, 2), sig_o);  			if (!mode_keep)  				continue; @@ -1298,9 +1358,9 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  			Cell *cell = nullptr;  			if (assume_attr != nullptr && !strcmp(assume_attr, "1")) -				cell = module->addAssume(NEW_ID, cond, State::S1); +				cell = module->addAssume(new_verific_id(inst), cond, State::S1);  			else -				cell = module->addAssert(NEW_ID, cond, State::S1); +				cell = module->addAssert(new_verific_id(inst), cond, State::S1);  			import_attributes(cell->attributes, inst);  			continue; @@ -1342,7 +1402,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se  			IdString port_name_id = RTLIL::escape_id(port_name);  			auto &sigvec = cell_port_conns[port_name_id];  			if (GetSize(sigvec) <= port_offset) { -				SigSpec zwires = module->addWire(NEW_ID, port_offset+1-GetSize(sigvec)); +				SigSpec zwires = module->addWire(new_verific_id(inst), port_offset+1-GetSize(sigvec));  				for (auto bit : zwires)  					sigvec.push_back(bit);  			} @@ -1835,6 +1895,7 @@ struct VerificPass : public Pass {  			Message::RegisterCallBackMsg(msg_func);  			RuntimeFlags::SetVar("db_preserve_user_nets", 1);  			RuntimeFlags::SetVar("db_allow_external_nets", 1); +			RuntimeFlags::SetVar("vhdl_support_variable_slice", 1);  			RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0);  			RuntimeFlags::SetVar("veri_extract_dualport_rams", 0);  			RuntimeFlags::SetVar("veri_extract_multiport_rams", 1); @@ -2093,42 +2154,6 @@ struct VerificPass : public Pass {  			if (mode_all)  			{ -#if 0 -				log("Running veri_file::ElaborateAll().\n"); -				if (!veri_file::ElaborateAll()) -					log_cmd_error("Elaboration of Verilog modules failed.\n"); - -				log("Running vhdl_file::ElaborateAll().\n"); -				if (!vhdl_file::ElaborateAll()) -					log_cmd_error("Elaboration of VHDL modules failed.\n"); - -				Library *lib = Netlist::PresentDesign()->Owner()->Owner(); - -				if (argidx == GetSize(args)) -				{ -					MapIter iter; -					char *iter_name; -					Verific::Cell *iter_cell; - -					FOREACH_MAP_ITEM(lib->GetCells(), iter, &iter_name, &iter_cell) { -						if (*iter_name != '$') -							nl_todo.insert(iter_cell->GetFirstNetlist()); -					} -				} -				else -				{ -					for (; argidx < GetSize(args); argidx++) -					{ -						Verific::Cell *cell = lib->GetCell(args[argidx].c_str()); - -						if (cell == nullptr) -							log_cmd_error("Module not found: %s\n", args[argidx].c_str()); - -						nl_todo.insert(cell->GetFirstNetlist()); -						cell->GetFirstNetlist()->SetPresentDesign(); -					} -				} -#else  				log("Running hier_tree::ElaborateAll().\n");  				VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1); @@ -2145,28 +2170,12 @@ struct VerificPass : public Pass {  				FOREACH_ARRAY_ITEM(netlists, i, nl)  					nl_todo.insert(nl);  				delete netlists; -#endif  			}  			else  			{  				if (argidx == GetSize(args))  					log_cmd_error("No top module specified.\n"); -#if 0 -				for (; argidx < GetSize(args); argidx++) { -					if (veri_file::GetModule(args[argidx].c_str())) { -						log("Running veri_file::Elaborate(\"%s\").\n", args[argidx].c_str()); -						if (!veri_file::Elaborate(args[argidx].c_str())) -							log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str()); -						nl_todo.insert(Netlist::PresentDesign()); -					} else { -						log("Running vhdl_file::Elaborate(\"%s\").\n", args[argidx].c_str()); -						if (!vhdl_file::Elaborate(args[argidx].c_str())) -							log_cmd_error("Elaboration of top module `%s' failed.\n", args[argidx].c_str()); -						nl_todo.insert(Netlist::PresentDesign()); -					} -				} -#else  				Array veri_modules, vhdl_units;  				for (; argidx < GetSize(args); argidx++)  				{ @@ -2198,7 +2207,6 @@ struct VerificPass : public Pass {  				FOREACH_ARRAY_ITEM(netlists, i, nl)  					nl_todo.insert(nl);  				delete netlists; -#endif  			}  			if (!verific_error_msg.empty()) diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h index 334a436af..b331dd4b9 100644 --- a/frontends/verific/verific.h +++ b/frontends/verific/verific.h @@ -78,6 +78,7 @@ struct VerificImporter  	RTLIL::SigBit net_map_at(Verific::Net *net); +	RTLIL::IdString new_verific_id(Verific::DesignObj *obj);  	void import_attributes(dict<RTLIL::IdString, RTLIL::Const> &attributes, Verific::DesignObj *obj);  	RTLIL::SigSpec operatorInput(Verific::Instance *inst); diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 83921bf0b..f9118e142 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -135,6 +135,9 @@ YOSYS_NAMESPACE_END  		frontend_verilog_yyerror("Unsupported default nettype: %s", p);  } +"`protect"[^\n]* /* ignore `protect*/ +"`endprotect"[^\n]* /* ignore `endprotect*/ +  "`"[a-zA-Z_$][a-zA-Z0-9_$]* {  	frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext);  } @@ -150,6 +153,9 @@ YOSYS_NAMESPACE_END  "specparam"    { return TOK_SPECPARAM; }  "package"      { SV_KEYWORD(TOK_PACKAGE); }  "endpackage"   { SV_KEYWORD(TOK_ENDPACKAGE); } +"interface"    { SV_KEYWORD(TOK_INTERFACE); } +"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); } +"modport"      { SV_KEYWORD(TOK_MODPORT); }  "parameter"    { return TOK_PARAMETER; }  "localparam"   { return TOK_LOCALPARAM; }  "defparam"     { return TOK_DEFPARAM; } @@ -295,6 +301,11 @@ supply1 { return TOK_SUPPLY1; }  	return TOK_ID;  } +[a-zA-Z_$][a-zA-Z0-9_$\.]* { +	frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); +    return TOK_ID; +} +  "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {  	static bool printed_warning = false;  	if (!printed_warning) { diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 16cac1460..51e112ed3 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -35,6 +35,7 @@  %{  #include <list> +#include <stack>  #include <string.h>  #include "frontends/verilog/verilog_frontend.h"  #include "kernel/log.h" @@ -47,7 +48,8 @@ YOSYS_NAMESPACE_BEGIN  namespace VERILOG_FRONTEND {  	int port_counter;  	std::map<std::string, int> port_stubs; -	std::map<std::string, AstNode*> attr_list, default_attr_list; +	std::map<std::string, AstNode*> *attr_list, default_attr_list; +	std::stack<std::map<std::string, AstNode*> *> attr_list_stack;  	std::map<std::string, AstNode*> *albuf;  	std::vector<AstNode*> ast_stack;  	struct AstNode *astbuf1, *astbuf2, *astbuf3; @@ -61,6 +63,7 @@ namespace VERILOG_FRONTEND {  	bool noassert_mode, noassume_mode, norestrict_mode;  	bool assume_asserts_mode, assert_assumes_mode;  	bool current_wire_rand, current_wire_const; +	bool current_modport_input, current_modport_output;  	std::istream *lexin;  }  YOSYS_NAMESPACE_END @@ -106,6 +109,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)  %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END  %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM  %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP +%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT  %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC  %token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL  %token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT @@ -123,7 +127,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)  %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 tok_prim_wrapper hierarchical_id -%type <boolean> opt_signed unique_case_attr +%type <boolean> opt_signed opt_property unique_case_attr  %type <al> attr case_attr  // operator precedence from low to high @@ -168,19 +172,23 @@ design:  	param_decl design |  	localparam_decl design |  	package design | +	interface design |  	/* empty */;  attr:  	{ -		for (auto &it : attr_list) -			delete it.second; -		attr_list.clear(); +		if (attr_list != nullptr) +			attr_list_stack.push(attr_list); +		attr_list = new std::map<std::string, AstNode*>;  		for (auto &it : default_attr_list) -			attr_list[it.first] = it.second->clone(); +			(*attr_list)[it.first] = it.second->clone();  	} attr_opt { -		std::map<std::string, AstNode*> *al = new std::map<std::string, AstNode*>; -		al->swap(attr_list); -		$$ = al; +		$$ = attr_list; +		if (!attr_list_stack.empty()) { +			attr_list = attr_list_stack.top(); +			attr_list_stack.pop(); +		} else +			attr_list = nullptr;  	};  attr_opt: @@ -189,15 +197,20 @@ attr_opt:  defattr:  	DEFATTR_BEGIN { +		if (attr_list != nullptr) +			attr_list_stack.push(attr_list); +		attr_list = new std::map<std::string, AstNode*>;  		for (auto &it : default_attr_list)  			delete it.second;  		default_attr_list.clear(); -		for (auto &it : attr_list) -			delete it.second; -		attr_list.clear();  	} opt_attr_list { -		default_attr_list = attr_list; -		attr_list.clear(); +		attr_list->swap(default_attr_list); +		delete attr_list; +		if (!attr_list_stack.empty()) { +			attr_list = attr_list_stack.top(); +			attr_list_stack.pop(); +		} else +			attr_list = nullptr;  	} DEFATTR_END;  opt_attr_list: @@ -209,15 +222,15 @@ attr_list:  attr_assign:  	hierarchical_id { -		if (attr_list.count(*$1) != 0) -			delete attr_list[*$1]; -		attr_list[*$1] = AstNode::mkconst_int(1, false); +		if (attr_list->count(*$1) != 0) +			delete (*attr_list)[*$1]; +		(*attr_list)[*$1] = AstNode::mkconst_int(1, false);  		delete $1;  	} |  	hierarchical_id '=' expr { -		if (attr_list.count(*$1) != 0) -			delete attr_list[*$1]; -		attr_list[*$1] = $3; +		if (attr_list->count(*$1) != 0) +			delete (*attr_list)[*$1]; +		(*attr_list)[*$1] = $3;  		delete $1;  	}; @@ -302,7 +315,7 @@ module_arg_opt_assignment:  			else  				ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));  		} else -			frontend_verilog_yyerror("Syntax error."); +			frontend_verilog_yyerror("SystemVerilog interface in module port list cannot have a default value.");  	} |  	/* empty */; @@ -320,6 +333,21 @@ module_arg:  		}  		delete $1;  	} module_arg_opt_assignment | +	TOK_ID { +		astbuf1 = new AstNode(AST_INTERFACEPORT); +		astbuf1->children.push_back(new AstNode(AST_INTERFACEPORTTYPE)); +		astbuf1->children[0]->str = *$1; +		delete $1; +	} TOK_ID {  /* SV interfaces */ +		if (!sv_mode) +			frontend_verilog_yyerror("Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str()); +		astbuf2 = astbuf1->clone(); // really only needed if multiple instances of same type. +		astbuf2->str = *$3; +		delete $3; +		astbuf2->port_id = ++port_counter; +		ast_stack.back()->children.push_back(astbuf2); +		delete astbuf1; // really only needed if multiple instances of same type. +	} module_arg_opt_assignment |  	attr wire_type range TOK_ID {  		AstNode *node = $2;  		node->str = *$4; @@ -357,6 +385,33 @@ package_body:  package_body_stmt:  	localparam_decl; +interface: +	TOK_INTERFACE TOK_ID { +		do_not_require_port_stubs = false; +		AstNode *intf = new AstNode(AST_INTERFACE); +		ast_stack.back()->children.push_back(intf); +		ast_stack.push_back(intf); +		current_ast_mod = intf; +		port_stubs.clear(); +		port_counter = 0; +		intf->str = *$2; +		delete $2; +	} module_para_opt module_args_opt ';' interface_body TOK_ENDINTERFACE { +		if (port_stubs.size() != 0) +			frontend_verilog_yyerror("Missing details for module port `%s'.", +				port_stubs.begin()->first.c_str()); +		ast_stack.pop_back(); +		log_assert(ast_stack.size() == 1); +		current_ast_mod = NULL; +	}; + +interface_body: +	interface_body interface_body_stmt |; + +interface_body_stmt: +	param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | +	modport_stmt; +  non_opt_delay:  	'#' TOK_ID { delete $2; } |  	'#' TOK_CONSTVAL { delete $2; } | @@ -627,7 +682,7 @@ task_func_port:  		astbuf2 = $3;  		if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {  			if (astbuf2) { -				frontend_verilog_yyerror("Syntax error."); +				frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions (task/function arguments)");  			} else {  				astbuf2 = new AstNode(AST_RANGE);  				astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); @@ -635,7 +690,7 @@ task_func_port:  			}  		}  		if (astbuf2 && astbuf2->children.size() != 2) -			frontend_verilog_yyerror("Syntax error."); +			frontend_verilog_yyerror("task/function argument range must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");  	} wire_name | wire_name;  task_func_body: @@ -838,7 +893,7 @@ param_signed:  param_integer:  	TOK_INTEGER {  		if (astbuf1->children.size() != 1) -			frontend_verilog_yyerror("Syntax error."); +			frontend_verilog_yyerror("Internal error in param_integer - should not happen?");  		astbuf1->children.push_back(new AstNode(AST_RANGE));  		astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true));  		astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true)); @@ -848,7 +903,7 @@ param_integer:  param_real:  	TOK_REAL {  		if (astbuf1->children.size() != 1) -			frontend_verilog_yyerror("Syntax error."); +			frontend_verilog_yyerror("Parameter already declared as integer, cannot set to real.");  		astbuf1->children.push_back(new AstNode(AST_REALVALUE));  	} | /* empty */; @@ -856,7 +911,7 @@ param_range:  	range {  		if ($1 != NULL) {  			if (astbuf1->children.size() != 1) -				frontend_verilog_yyerror("Syntax error."); +				frontend_verilog_yyerror("integer/real parameters should not have a range.");  			astbuf1->children.push_back($1);  		}  	}; @@ -885,7 +940,7 @@ single_param_decl:  		AstNode *node;  		if (astbuf1 == nullptr) {  			if (!sv_mode) -				frontend_verilog_yyerror("syntax error"); +				frontend_verilog_yyerror("In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword");  			node = new AstNode(AST_PARAMETER);  			node->children.push_back(AstNode::mkconst_int(0, true));  		} else { @@ -921,7 +976,7 @@ wire_decl:  		astbuf2 = $3;  		if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {  			if (astbuf2) { -				frontend_verilog_yyerror("Syntax error."); +				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)); @@ -929,7 +984,7 @@ wire_decl:  			}  		}  		if (astbuf2 && astbuf2->children.size() != 2) -			frontend_verilog_yyerror("Syntax error."); +			frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");  	} wire_name_list {  		delete astbuf1;  		if (astbuf2 != NULL) @@ -1023,7 +1078,7 @@ wire_name_and_opt_assign:  wire_name:  	TOK_ID range_or_multirange {  		if (astbuf1 == nullptr) -			frontend_verilog_yyerror("Syntax error."); +			frontend_verilog_yyerror("Internal error - should not happen - no AST_WIRE node.");  		AstNode *node = astbuf1->clone();  		node->str = *$1;  		append_attr_clone(node, albuf); @@ -1031,7 +1086,7 @@ wire_name:  			node->children.push_back(astbuf2->clone());  		if ($2 != NULL) {  			if (node->is_input || node->is_output) -				frontend_verilog_yyerror("Syntax error."); +				frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions.");  			if (!astbuf2) {  				AstNode *rng = new AstNode(AST_RANGE);  				rng->children.push_back(AstNode::mkconst_int(0, true)); @@ -1275,11 +1330,51 @@ opt_label:  	};  opt_property: -	TOK_PROPERTY | /* empty */; +	TOK_PROPERTY { +		$$ = true; +	} | +	/* empty */ { +		$$ = false; +	};  opt_stmt_label:  	TOK_ID ':' | /* empty */; +modport_stmt: +    TOK_MODPORT TOK_ID { +        AstNode *modport = new AstNode(AST_MODPORT); +        ast_stack.back()->children.push_back(modport); +        ast_stack.push_back(modport); +        modport->str = *$2; +        delete $2; +    }  modport_args_opt { +        ast_stack.pop_back(); +        log_assert(ast_stack.size() == 2); +    } ';' + +modport_args_opt: +    '(' ')' | '(' modport_args optional_comma ')'; + +modport_args: +    modport_arg | modport_args ',' modport_arg; + +modport_arg: +    modport_type_token modport_member | +    modport_member + +modport_member: +    TOK_ID { +        AstNode *modport_member = new AstNode(AST_MODPORTMEMBER); +        ast_stack.back()->children.push_back(modport_member); +        modport_member->str = *$1; +        modport_member->is_input = current_modport_input; +        modport_member->is_output = current_modport_output; +        delete $1; +    } + +modport_type_token: +    TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} +  assert:  	opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' {  		if (noassert_mode) @@ -1319,12 +1414,16 @@ assert:  			delete $5;  		else  			ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); +		if (!$3) +			log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");  	} |  	opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {  		if (norestrict_mode)  			delete $6;  		else  			ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); +		if (!$3) +			log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");  	};  assert_property: @@ -1398,7 +1497,7 @@ behavioral_stmt:  			node->str = *$3;  	} behavioral_stmt_list TOK_END opt_label {  		if ($3 != NULL && $7 != NULL && *$3 != *$7) -			frontend_verilog_yyerror("Syntax error."); +			frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1);  		if ($3 != NULL)  			delete $3;  		if ($7 != NULL) @@ -1714,7 +1813,7 @@ basic_expr:  	} |  	'(' expr ')' TOK_CONSTVAL {  		if ($4->substr(0, 1) != "'") -			frontend_verilog_yyerror("Syntax error."); +			frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str());  		AstNode *bits = $2;  		AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);  		if (val == NULL) @@ -1724,7 +1823,7 @@ basic_expr:  	} |  	hierarchical_id TOK_CONSTVAL {  		if ($2->substr(0, 1) != "'") -			frontend_verilog_yyerror("Syntax error."); +			frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str());  		AstNode *bits = new AstNode(AST_IDENTIFIER);  		bits->str = *$1;  		AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);  | 
