diff options
31 files changed, 250 insertions, 50 deletions
| @@ -21,7 +21,7 @@ Yosys 0.8 .. Yosys 0.8-dev      - Added "synth_xilinx -abc9" (experimental)      - Added "synth_ice40 -abc9" (experimental)      - Added "synth -abc9" (experimental) -    - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx" +    - Extended "muxcover -mux{4,8,16}=<cost>"  Yosys 0.7 .. Yosys 0.8 @@ -350,6 +350,14 @@ Verilog Attributes and non-standard features    through the synthesis. When entities are combined, a new |-separated    string is created that contains all the string from the original entities. +- The ``defaultvalue`` attribute is used to store default values for +  module inputs. The attribute is attached to the input wire by the HDL +  front-end when the input is declared with a default value. + +- The ``parameter`` and ``localparam`` attributes are used to mark wires +  that represent module parameters or localparams (when the HDL front-end +  is run in -pwires mode). +  - In addition to the ``(* ... *)`` attribute syntax, Yosys supports    the non-standard ``{* ... *}`` attribute syntax to set default attributes    for everything that comes after the ``{* ... *}`` statement. (Reset diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 516e538a5..4c2ea511a 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -776,6 +776,7 @@ struct AigerBackend : public Backend {  		writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);  		if (!map_filename.empty()) { +			rewrite_filename(filename);  			std::ofstream mapf;  			mapf.open(map_filename.c_str(), std::ofstream::trunc);  			if (mapf.fail()) diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index 04d1ee311..b4ba2b03f 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -483,6 +483,7 @@ struct DumpPass : public Pass {  		std::stringstream buf;  		if (!filename.empty()) { +			rewrite_filename(filename);  			std::ofstream *ff = new std::ofstream;  			ff->open(filename.c_str(), append ? std::ofstream::app : std::ofstream::trunc);  			if (ff->fail()) { diff --git a/backends/json/json.cc b/backends/json/json.cc index f5c687981..5022d5da1 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -525,6 +525,7 @@ struct JsonPass : public Pass {  		std::stringstream buf;  		if (!filename.empty()) { +			rewrite_filename(filename);  			std::ofstream *ff = new std::ofstream;  			ff->open(filename.c_str(), std::ofstream::trunc);  			if (ff->fail()) { diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc index 549fc73ae..fff110bb0 100644 --- a/backends/protobuf/protobuf.cc +++ b/backends/protobuf/protobuf.cc @@ -336,6 +336,7 @@ struct ProtobufPass : public Pass {  		std::stringstream buf;  		if (!filename.empty()) { +			rewrite_filename(filename);  			std::ofstream *ff = new std::ofstream;  			ff->open(filename.c_str(), std::ofstream::trunc);  			if (ff->fail()) { diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index ab20a4af2..cea0fc56c 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -1023,6 +1023,8 @@ class MkVcd:          assert t >= self.t          if t != self.t:              if self.t == -1: +                print("$version Generated by Yosys-SMTBMC $end", file=self.f) +                print("$timescale 1ns $end", file=self.f)                  print("$var integer 32 t smt_step $end", file=self.f)                  print("$var event 1 ! smt_clock $end", file=self.f) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index b5b968e9e..3d066af53 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -46,7 +46,7 @@ namespace AST {  // instantiate global variables (private API)  namespace AST_INTERNAL {  	bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit; -	bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_autowire; +	bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_autowire;  	AstNode *current_ast, *current_ast_mod;  	std::map<std::string, AstNode*> current_scope;  	const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL; @@ -1112,6 +1112,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast  	current_module->nowb = flag_nowb;  	current_module->noopt = flag_noopt;  	current_module->icells = flag_icells; +	current_module->pwires = flag_pwires;  	current_module->autowire = flag_autowire;  	current_module->fixup_ports(); @@ -1126,7 +1127,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast  // create AstModule instances for all modules in the AST tree and add them to 'design'  void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, -		bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire) +		bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire)  {  	current_ast = ast;  	flag_dump_ast1 = dump_ast1; @@ -1144,6 +1145,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump  	flag_nowb = nowb;  	flag_noopt = noopt;  	flag_icells = icells; +	flag_pwires = pwires;  	flag_autowire = autowire;  	log_assert(current_ast->type == AST_DESIGN); @@ -1480,6 +1482,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString  	flag_nowb = nowb;  	flag_noopt = noopt;  	flag_icells = icells; +	flag_pwires = pwires;  	flag_autowire = autowire;  	use_internal_line_num(); @@ -1551,6 +1554,7 @@ RTLIL::Module *AstModule::clone() const  	new_mod->lib = lib;  	new_mod->noopt = noopt;  	new_mod->icells = icells; +	new_mod->pwires = pwires;  	new_mod->autowire = autowire;  	return new_mod; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index b8cde060e..54b2fb319 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -286,13 +286,13 @@ namespace AST  	// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code  	void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, bool nolatches, bool nomeminit, -			bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire); +			bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire);  	// parametric modules are supported directly by the AST library  	// therefore we need our own derivate of RTLIL::Module with overloaded virtual functions  	struct AstModule : RTLIL::Module {  		AstNode *ast; -		bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, autowire; +		bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, 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; @@ -325,7 +325,7 @@ namespace AST_INTERNAL  {  	// internal state variables  	extern bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_rtlil, flag_nolatches, flag_nomeminit; -	extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire; +	extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_pwires, flag_autowire;  	extern AST::AstNode *current_ast, *current_ast_mod;  	extern std::map<std::string, AST::AstNode*> current_scope;  	extern const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 32ed401eb..079fc11e5 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -853,7 +853,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  	case AST_FUNCTION:  	case AST_DPI_FUNCTION:  	case AST_AUTOWIRE: -	case AST_LOCALPARAM:  	case AST_DEFPARAM:  	case AST_GENVAR:  	case AST_GENFOR: @@ -895,6 +894,26 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  	// remember the parameter, needed for example in techmap  	case AST_PARAMETER:  		current_module->avail_parameters.insert(str); +		/* fall through */ +	case AST_LOCALPARAM: +		if (flag_pwires) +		{ +			if (GetSize(children) < 1 || children[0]->type != AST_CONSTANT) +				log_file_error(filename, linenum, "Parameter `%s' with non-constant value!\n", str.c_str()); + +			RTLIL::Const val = children[0]->bitsAsConst(); +			RTLIL::Wire *wire = current_module->addWire(str, GetSize(val)); +			current_module->connect(wire, val); + +			wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); +			wire->attributes[type == AST_PARAMETER ? "\\parameter" : "\\localparam"] = 1; + +			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()); +				wire->attributes[attr.first] = attr.second->asAttrConst(); +			} +		}  		break;  	// create an RTLIL::Wire for an AST_WIRE node diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 01e589efb..0e2bead6f 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -168,6 +168,9 @@ struct VerilogFrontend : public Frontend {  		log("    -icells\n");  		log("        interpret cell types starting with '$' as internal cell types\n");  		log("\n"); +		log("    -pwires\n"); +		log("        add a wire for each module parameter\n"); +		log("\n");  		log("    -nooverwrite\n");  		log("        ignore re-definitions of modules. (the default behavior is to\n");  		log("        create an error message if the existing module is not a black box\n"); @@ -228,6 +231,7 @@ struct VerilogFrontend : public Frontend {  		bool flag_nodpi = false;  		bool flag_noopt = false;  		bool flag_icells = false; +		bool flag_pwires = false;  		bool flag_nooverwrite = false;  		bool flag_overwrite = false;  		bool flag_defer = false; @@ -368,6 +372,10 @@ struct VerilogFrontend : public Frontend {  				flag_icells = true;  				continue;  			} +			if (arg == "-pwires") { +				flag_pwires = true; +				continue; +			}  			if (arg == "-ignore_redef" || arg == "-nooverwrite") {  				flag_nooverwrite = true;  				flag_overwrite = false; @@ -458,7 +466,7 @@ struct VerilogFrontend : public Frontend {  			error_on_dpi_function(current_ast);  		AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, -				flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire); +				flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);  		if (!flag_nopp)  			delete lexin; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 3c612472d..d3fd91473 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -313,7 +313,7 @@ supply1 { return TOK_SUPPLY1; }  "$"(info|warning|error|fatal) {  	frontend_verilog_yylval.string = new std::string(yytext); -	return TOK_ELAB_TASK; +	return TOK_MSG_TASKS;  }  "$signed"   { return TOK_TO_SIGNED; } diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index a034f9601..4895d0302 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -133,7 +133,7 @@ struct specify_rise_fall {  }  %token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE -%token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_ELAB_TASK +%token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_MSG_TASKS  %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL  %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END  %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM @@ -319,15 +319,17 @@ module_para_list:  single_module_para:  	/* empty */ | -	TOK_PARAMETER { +	attr TOK_PARAMETER {  		if (astbuf1) delete astbuf1;  		astbuf1 = new AstNode(AST_PARAMETER);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); +		append_attr(astbuf1, $1);  	} param_signed param_integer param_range single_param_decl | -	TOK_LOCALPARAM { +	attr TOK_LOCALPARAM {  		if (astbuf1) delete astbuf1;  		astbuf1 = new AstNode(AST_LOCALPARAM);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); +		append_attr(astbuf1, $1);  	} param_signed param_integer param_range single_param_decl |  	single_param_decl; @@ -345,7 +347,13 @@ module_arg_opt_assignment:  		if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) {  			AstNode *wire = new AstNode(AST_IDENTIFIER);  			wire->str = ast_stack.back()->children.back()->str; -			if (ast_stack.back()->children.back()->is_reg) +			if (ast_stack.back()->children.back()->is_input) { +				AstNode *n = ast_stack.back()->children.back(); +				if (n->attributes.count("\\defaultvalue")) +					delete n->attributes.at("\\defaultvalue"); +				n->attributes["\\defaultvalue"] = $2; +			} else +			if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic)  				ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2))));  			else  				ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2)); @@ -1211,6 +1219,7 @@ param_decl:  	attr TOK_PARAMETER {  		astbuf1 = new AstNode(AST_PARAMETER);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); +		append_attr(astbuf1, $1);  	} param_signed param_integer param_real param_range param_decl_list ';' {  		delete astbuf1;  	}; @@ -1219,6 +1228,7 @@ localparam_decl:  	attr TOK_LOCALPARAM {  		astbuf1 = new AstNode(AST_LOCALPARAM);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); +		append_attr(astbuf1, $1);  	} param_signed param_integer param_real param_range param_decl_list ';' {  		delete astbuf1;  	}; @@ -1360,7 +1370,12 @@ wire_name_and_opt_assign:  	wire_name '=' expr {  		AstNode *wire = new AstNode(AST_IDENTIFIER);  		wire->str = ast_stack.back()->children.back()->str; -		if (astbuf1->is_reg) +		if (astbuf1->is_input) { +			if (astbuf1->attributes.count("\\defaultvalue")) +				delete astbuf1->attributes.at("\\defaultvalue"); +			astbuf1->attributes["\\defaultvalue"] = $3; +		} else +		if (astbuf1->is_reg || astbuf1->is_logic)  			ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $3))));  		else  			ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $3)); @@ -1385,7 +1400,13 @@ wire_name:  				node->children.push_back(rng);  			}  			node->type = AST_MEMORY; -			node->children.push_back($2); +			auto *rangeNode = $2; +			if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { +				// SV array size [n], rewrite as [n-1:0] +				rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); +				rangeNode->children.push_back(AstNode::mkconst_int(0, false)); +			} +			node->children.push_back(rangeNode);  		}  		if (current_function_or_task == NULL) {  			if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) { @@ -1881,6 +1902,16 @@ behavioral_stmt:  	} opt_arg_list ';'{  		ast_stack.pop_back();  	} | +	TOK_MSG_TASKS attr { +		AstNode *node = new AstNode(AST_TCALL); +		node->str = *$1; +		delete $1; +		ast_stack.back()->children.push_back(node); +		ast_stack.push_back(node); +		append_attr(node, $2); +	} opt_arg_list ';'{ +		ast_stack.pop_back(); +	} |  	attr TOK_BEGIN opt_label {  		AstNode *node = new AstNode(AST_BLOCK);  		ast_stack.back()->children.push_back(node); @@ -2177,7 +2208,7 @@ gen_stmt:  			delete $6;  		ast_stack.pop_back();  	} | -	TOK_ELAB_TASK { +	TOK_MSG_TASKS {  		AstNode *node = new AstNode(AST_TECALL);  		node->str = *$1;  		delete $1; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f732b56b0..502b45cfd 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1381,7 +1381,34 @@ void RTLIL::Module::check()  	for (auto &it : processes) {  		log_assert(it.first == it.second->name);  		log_assert(!it.first.empty()); -		// FIXME: More checks here.. +		log_assert(it.second->root_case.compare.empty()); +		std::vector<CaseRule*> all_cases = {&it.second->root_case}; +		for (size_t i = 0; i < all_cases.size(); i++) { +			for (auto &switch_it : all_cases[i]->switches) { +				for (auto &case_it : switch_it->cases) { +					for (auto &compare_it : case_it->compare) { +						log_assert(switch_it->signal.size() == compare_it.size()); +					} +					all_cases.push_back(case_it); +				} +			} +		} +		for (auto &sync_it : it.second->syncs) { +			switch (sync_it->type) { +				case SyncType::ST0: +				case SyncType::ST1: +				case SyncType::STp: +				case SyncType::STn: +				case SyncType::STe: +					log_assert(!sync_it->signal.empty()); +					break; +				case SyncType::STa: +				case SyncType::STg: +				case SyncType::STi: +					log_assert(sync_it->signal.empty()); +					break; +			} +		}  	}  	for (auto &it : connections_) { diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 377572fc2..94d6d675f 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -651,6 +651,10 @@ void rewrite_filename(std::string &filename)  		filename = filename.substr(1, GetSize(filename)-2);  	if (filename.substr(0, 2) == "+/")  		filename = proc_share_dirname() + filename.substr(2); +#ifndef _WIN32 +	if (filename.substr(0, 2) == "~/") +		filename = filename.replace(0, 1, getenv("HOME")); +#endif  }  #ifdef YOSYS_ENABLE_TCL diff --git a/manual/CHAPTER_Overview.tex b/manual/CHAPTER_Overview.tex index 2feb0f1cb..1a25c477f 100644 --- a/manual/CHAPTER_Overview.tex +++ b/manual/CHAPTER_Overview.tex @@ -350,6 +350,18 @@ and this bit is a one (the second ``1'').} for {\tt \textbackslash{}reset == 1}  sets {\tt \$0\textbackslash{}q[0:0]} to the value of {\tt \textbackslash{}d} if {\tt  \textbackslash{}enable} is active (lines $6 \dots 11$). +A case can specify zero or more compare values that will determine whether it matches. Each of the compare values +must be the exact same width as the control signal. When more than one compare value is specified, the case matches +if any of them matches the control signal; when zero compare values are specified, the case always matches (i.e. +it is the default case). + +A switch prioritizes cases from first to last: multiple cases can match, but only the first matched case becomes +active. This normally synthesizes to a priority encoder. The {\tt parallel\_case} attribute allows passes to assume +that no more than one case will match, and {\tt full\_case} attribute allows passes to assume that exactly one +case will match; if these invariants are ever dynamically violated, the behavior is undefined. These attributes +are useful when an invariant invisible to the synthesizer causes the control signal to never take certain +bit patterns. +  The lines $13 \dots 16$  then cause {\tt \textbackslash{}q} to be updated whenever there is  a positive clock edge on {\tt \textbackslash{}clock} or {\tt \textbackslash{}reset}. diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc index 6094f8f16..d09ed872e 100644 --- a/passes/cmds/blackbox.cc +++ b/passes/cmds/blackbox.cc @@ -23,7 +23,7 @@ USING_YOSYS_NAMESPACE  PRIVATE_NAMESPACE_BEGIN  struct BlackboxPass : public Pass { -	BlackboxPass() : Pass("blackbox", "change type of cells in the design") { } +	BlackboxPass() : Pass("blackbox", "convert modules into blackbox modules") { }  	void help() YS_OVERRIDE  	{  		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index d22685b62..27c5fb60c 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -285,8 +285,8 @@ struct StatPass : public Pass {  		log("        use cell area information from the provided liberty file\n");  		log("\n");  		log("    -tech <technology>\n"); -		log("        print area estemate for the specified technology. Corrently supported\n"); -		log("        calues for <technology>: xilinx\n"); +		log("        print area estemate for the specified technology. Currently supported\n"); +		log("        values for <technology>: xilinx\n");  		log("\n");  		log("    -width\n");  		log("        annotate internal cell types with their word width.\n"); diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc index 9613b462b..64a762d7c 100644 --- a/passes/cmds/write_file.cc +++ b/passes/cmds/write_file.cc @@ -62,7 +62,7 @@ struct WriteFileFrontend : public Frontend {  		if (argidx < args.size() && args[argidx].rfind("-", 0) != 0)  			output_filename = args[argidx++];  		else -			log_cmd_error("Missing putput filename.\n"); +			log_cmd_error("Missing output filename.\n");  		extra_args(f, filename, args, argidx); diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 24e64a9b2..213437c01 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -591,6 +591,9 @@ struct HierarchyPass : public Pass {  		log("        module instances when the width does not match the module port. This\n");  		log("        option disables this behavior.\n");  		log("\n"); +		log("    -nodefaults\n"); +		log("        do not resolve input port default values\n"); +		log("\n");  		log("    -nokeep_asserts\n");  		log("        per default this pass sets the \"keep\" attribute on all modules\n");  		log("        that directly or indirectly contain one or more formal properties.\n"); @@ -645,6 +648,7 @@ struct HierarchyPass : public Pass {  		bool generate_mode = false;  		bool keep_positionals = false;  		bool keep_portwidths = false; +		bool nodefaults = false;  		bool nokeep_asserts = false;  		std::vector<std::string> generate_cells;  		std::vector<generate_port_decl_t> generate_ports; @@ -712,6 +716,10 @@ struct HierarchyPass : public Pass {  				keep_portwidths = true;  				continue;  			} +			if (args[argidx] == "-nodefaults") { +				nodefaults = true; +				continue; +			}  			if (args[argidx] == "-nokeep_asserts") {  				nokeep_asserts = true;  				continue; @@ -940,6 +948,36 @@ struct HierarchyPass : public Pass {  			}  		} +		if (!nodefaults) +		{ +			dict<IdString, dict<IdString, Const>> defaults_db; + +			for (auto module : design->modules()) +				for (auto wire : module->wires()) +					if (wire->port_input && wire->attributes.count("\\defaultvalue")) +						defaults_db[module->name][wire->name] = wire->attributes.at("\\defaultvalue"); + +			for (auto module : design->modules()) +				for (auto cell : module->cells()) +				{ +					if (defaults_db.count(cell->type) == 0) +						continue; + +					if (keep_positionals) { +						bool found_positionals = false; +						for (auto &conn : cell->connections()) +							if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') +								found_positionals = true; +						if (found_positionals) +							continue; +					} + +					for (auto &it : defaults_db.at(cell->type)) +						if (!cell->hasPort(it.first)) +							cell->setPort(it.first, it.second); +				} +		} +  		std::set<Module*> blackbox_derivatives;  		std::vector<Module*> design_modules = design->modules(); diff --git a/passes/sat/assertpmux.cc b/passes/sat/assertpmux.cc index 509cb0ba9..3b432c461 100644 --- a/passes/sat/assertpmux.cc +++ b/passes/sat/assertpmux.cc @@ -180,7 +180,7 @@ struct AssertpmuxWorker  };  struct AssertpmuxPass : public Pass { -	AssertpmuxPass() : Pass("assertpmux", "convert internal signals to module ports") { } +	AssertpmuxPass() : Pass("assertpmux", "adds asserts for parallel muxes") { }  	void help() YS_OVERRIDE  	{  		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -195,8 +195,8 @@ struct AssertpmuxPass : public Pass {  		log("\n");  		log("    -always\n");  		log("        usually the $pmux condition is only checked when the $pmux output\n"); -		log("        is used be the mux tree it drives. this option will deactivate this\n"); -		log("        additional constrained and check the $pmux condition always.\n"); +		log("        is used by the mux tree it drives. this option will deactivate this\n"); +		log("        additional constraint and check the $pmux condition always.\n");  		log("\n");  	}  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc index 048aec7f3..b4549bc39 100644 --- a/passes/sat/cutpoint.cc +++ b/passes/sat/cutpoint.cc @@ -24,7 +24,7 @@ USING_YOSYS_NAMESPACE  PRIVATE_NAMESPACE_BEGIN  struct CutpointPass : public Pass { -	CutpointPass() : Pass("cutpoint", "add hi/lo cover cells for each wire bit") { } +	CutpointPass() : Pass("cutpoint", "adds formal cut points to the design") { }  	void help() YS_OVERRIDE  	{  		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc index 32102436d..8e44be148 100644 --- a/passes/techmap/muxcover.cc +++ b/passes/techmap/muxcover.cc @@ -610,7 +610,7 @@ struct MuxcoverPass : public Pass {  				use_mux4 = true;  				if (arg.size() > 5) {  					if (arg[5] != '=') break; -					cost_mux4 = atoi(arg.substr(5).c_str()); +					cost_mux4 = atoi(arg.substr(6).c_str());  				}  				continue;  			} @@ -618,7 +618,7 @@ struct MuxcoverPass : public Pass {  				use_mux8 = true;  				if (arg.size() > 5) {  					if (arg[5] != '=') break; -					cost_mux8 = atoi(arg.substr(5).c_str()); +					cost_mux8 = atoi(arg.substr(6).c_str());  				}  				continue;  			} @@ -626,7 +626,7 @@ struct MuxcoverPass : public Pass {  				use_mux16 = true;  				if (arg.size() > 6) {  					if (arg[6] != '=') break; -					cost_mux16 = atoi(arg.substr(6).c_str()); +					cost_mux16 = atoi(arg.substr(7).c_str());  				}  				continue;  			} diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 21dfe9619..18e60fa6b 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -605,9 +605,11 @@ struct ShregmapPass : public Pass {  		log("\n");  		log("    -tech greenpak4\n");  		log("        map to greenpak4 shift registers.\n"); +		log("        this option also implies -clkpol pos -zinit\n");  		log("\n");  		log("    -tech xilinx\n");  		log("        map to xilinx dynamic-length shift registers.\n"); +		log("        this option also implies -params -init\n");  		log("\n");  	}  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE diff --git a/techlibs/ice40/ice40_unlut.cc b/techlibs/ice40/ice40_unlut.cc index 2428a8e78..d16e6e6a3 100644 --- a/techlibs/ice40/ice40_unlut.cc +++ b/techlibs/ice40/ice40_unlut.cc @@ -74,7 +74,7 @@ static void run_ice40_unlut(Module *module)  }  struct Ice40UnlutPass : public Pass { -	Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: perform simple optimizations") { } +	Ice40UnlutPass() : Pass("ice40_unlut", "iCE40: transform SB_LUT4 cells to $lut cells") { }  	void help() YS_OVERRIDE  	{  		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| diff --git a/tests/aiger/.gitignore b/tests/aiger/.gitignore index 073f46157..9a26bb8f4 100644 --- a/tests/aiger/.gitignore +++ b/tests/aiger/.gitignore @@ -1,2 +1 @@ -*.log -*.out +/*_ref.v diff --git a/tests/aiger/run-test.sh b/tests/aiger/run-test.sh index f52eb4ac1..5246c1b48 100755 --- a/tests/aiger/run-test.sh +++ b/tests/aiger/run-test.sh @@ -10,8 +10,9 @@ for aag in *.aag; do      # Since ABC cannot read *.aag, read the *.aig instead      # (which would have been created by the reference aig2aig utility,      #  available from http://fmv.jku.at/aiger/) -    ../../yosys-abc -c "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" -    ../../yosys -p " +    echo "Checking $aag." +    ../../yosys-abc -q "read -c ${aag%.*}.aig; write ${aag%.*}_ref.v" +    ../../yosys -qp "  read_verilog ${aag%.*}_ref.v  prep  design -stash gold @@ -26,8 +27,9 @@ sat -verify -prove-asserts -show-ports -seq 16 miter  done  for aig in *.aig; do -    ../../yosys-abc -c "read -c $aig; write ${aig%.*}_ref.v" -    ../../yosys -p " +    echo "Checking $aig." +    ../../yosys-abc -q "read -c $aig; write ${aig%.*}_ref.v" +    ../../yosys -qp "  read_verilog ${aig%.*}_ref.v  prep  design -stash gold diff --git a/tests/simple/arrays02.sv b/tests/simple/arrays02.sv new file mode 100644 index 000000000..76c2a7388 --- /dev/null +++ b/tests/simple/arrays02.sv @@ -0,0 +1,16 @@ +module uut_arrays02(clock, we, addr, wr_data, rd_data); + +input clock, we; +input [3:0] addr, wr_data; +output [3:0] rd_data; +reg [3:0] rd_data; + +reg [3:0] memory [16]; + +always @(posedge clock) begin +	if (we) +		memory[addr] <= wr_data; +	rd_data <= memory[addr]; +end + +endmodule diff --git a/tests/simple/defvalue.sv b/tests/simple/defvalue.sv new file mode 100644 index 000000000..b0a087ecb --- /dev/null +++ b/tests/simple/defvalue.sv @@ -0,0 +1,22 @@ +module top(input clock, input [3:0] delta, output [3:0] cnt1, cnt2); +	cnt #(1) foo (.clock, .cnt(cnt1), .delta); +	cnt #(2) bar (.clock, .cnt(cnt2)); +endmodule + +module cnt #( +	parameter integer initval = 0 +) ( +	input clock, +	output logic [3:0] cnt = initval, +`ifdef __ICARUS__ +	input [3:0] delta +`else +	input [3:0] delta = 10 +`endif +); +`ifdef __ICARUS__ +	assign (weak0, weak1) delta = 10; +`endif +	always @(posedge clock) +		cnt <= cnt + delta; +endmodule diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh index 23964a751..96d9cdda9 100755 --- a/tests/tools/autotest.sh +++ b/tests/tools/autotest.sh @@ -89,8 +89,7 @@ done  compile_and_run() {  	exe="$1"; output="$2"; shift 2 -	ext=${1##*.} -	if [ "$ext" == "sv" ]; then +	if [ "${2##*.}" == "sv" ]; then  		language_gen="-g2012"  	else  		language_gen="-g2005" @@ -142,23 +141,25 @@ do  		cd ${bn}.out  		fn=$(basename $fn)  		bn=$(basename $bn) +		refext=v  		rm -f ${bn}_ref.fir  		if [[ "$ext" == "v" ]]; then  			egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext}  		elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then -			"$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.v" +			"$toolsdir"/../../yosys-abc -c "read_aiger ../${fn}; write ${bn}_ref.${refext}"  		else -			cp ../${fn} ${bn}_ref.${ext} +			refext=$ext +			cp ../${fn} ${bn}_ref.${refext}  		fi  		if [ ! -f ../${bn}_tb.v ]; then -			"$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.v +			"$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.${refext}  		else  			cp ../${bn}_tb.v ${bn}_tb.v  		fi  		if $genvcd; then sed -i 's,// \$dump,$dump,g' ${bn}_tb.v; fi -		compile_and_run ${bn}_tb_ref ${bn}_out_ref ${bn}_tb.v ${bn}_ref.v $libs \ +		compile_and_run ${bn}_tb_ref ${bn}_out_ref ${bn}_tb.v ${bn}_ref.${refext} $libs \  					"$toolsdir"/../../techlibs/common/simlib.v \  					"$toolsdir"/../../techlibs/common/simcells.v  		if $genvcd; then mv testbench.vcd ${bn}_ref.vcd; fi @@ -175,25 +176,25 @@ do  			test_count=$(( test_count + 1 ))  		} -		if [ "$frontend" = "verific" -o "$frontend" = "verific_gates" ] && grep -q VERIFIC-SKIP ${bn}_ref.v; then +		if [ "$frontend" = "verific" -o "$frontend" = "verific_gates" ] && grep -q VERIFIC-SKIP ${bn}_ref.${refext}; then  			touch ../${bn}.skip  			return  		fi  		if [ -n "$scriptfiles" ]; then -			test_passes -f "$frontend $include_opts" ${bn}_ref.v $scriptfiles +			test_passes -f "$frontend $include_opts" ${bn}_ref.${refext} $scriptfiles  		elif [ -n "$scriptopt" ]; then -			test_passes -f "$frontend $include_opts" -p "$scriptopt" ${bn}_ref.v +			test_passes -f "$frontend $include_opts" -p "$scriptopt" ${bn}_ref.${refext}  		elif [ "$frontend" = "verific" ]; then -			test_passes -p "verific -vlog2k ${bn}_ref.v; verific -import -all; opt; memory;;" +			test_passes -p "verific -vlog2k ${bn}_ref.${refext}; verific -import -all; opt; memory;;"  		elif [ "$frontend" = "verific_gates" ]; then -			test_passes -p "verific -vlog2k ${bn}_ref.v; verific -import -gates -all; opt; memory;;" +			test_passes -p "verific -vlog2k ${bn}_ref.${refext}; verific -import -gates -all; opt; memory;;"  		else -			test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.v -			test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.v +			test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.${refext} +			test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${refext}  			if [ -n "$firrtl2verilog" ]; then  			    if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then -				"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.v +				"$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt; memory; opt; fsm; opt -full -fine; pmuxtree" ${bn}_ref.${refext}  				$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v  				test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt; memory; opt; fsm; opt -full -fine" ${bn}_ref.fir.v  			    fi diff --git a/tests/various/.gitignore b/tests/various/.gitignore index 397b4a762..7b3e8c68e 100644 --- a/tests/various/.gitignore +++ b/tests/various/.gitignore @@ -1 +1,2 @@ -*.log +/*.log +/*.out | 
