diff options
| author | Clifford Wolf <clifford@clifford.at> | 2019-04-20 22:24:50 +0200 | 
|---|---|---|
| committer | Clifford Wolf <clifford@clifford.at> | 2019-04-20 22:24:50 +0200 | 
| commit | fb7f02be5561ccfd5bee5f3235fbbae5ef618f36 (patch) | |
| tree | 76e175ebc3419b6d0bc12cb2a6d5e557ac839af7 /frontends | |
| parent | f84a84e3f1a27b361c21fcd30fcf50c1a6586629 (diff) | |
| download | yosys-fb7f02be5561ccfd5bee5f3235fbbae5ef618f36.tar.gz yosys-fb7f02be5561ccfd5bee5f3235fbbae5ef618f36.tar.bz2 yosys-fb7f02be5561ccfd5bee5f3235fbbae5ef618f36.zip  | |
New behavior for front-end handling of whiteboxes
Signed-off-by: Clifford Wolf <clifford@clifford.at>
Diffstat (limited to 'frontends')
| -rw-r--r-- | frontends/ast/ast.cc | 84 | ||||
| -rw-r--r-- | frontends/ast/ast.h | 4 | ||||
| -rw-r--r-- | frontends/verilog/verilog_frontend.cc | 29 | ||||
| -rw-r--r-- | frontends/verilog/verilog_frontend.h | 7 | ||||
| -rw-r--r-- | frontends/verilog/verilog_parser.y | 10 | 
5 files changed, 100 insertions, 34 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 720b3f3d1..e4f18a2ac 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_lib, flag_wb, flag_noopt, flag_icells, flag_autowire; +	bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, 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; @@ -956,18 +956,67 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast  			log("--- END OF AST DUMP ---\n");  		} -		if (flag_wb) { -			if (!ast->attributes.count("\\whitebox")) -				goto blackbox_module; +		if (flag_nowb && ast->attributes.count("\\whitebox")) { +			delete ast->attributes.at("\\whitebox"); +			ast->attributes.erase("\\whitebox"); +		} + +		if (ast->attributes.count("\\lib_whitebox")) { +			if (!flag_lib || flag_nowb) { +				delete ast->attributes.at("\\lib_whitebox"); +				ast->attributes.erase("\\lib_whitebox"); +			} else { +				if (ast->attributes.count("\\whitebox")) { +					delete ast->attributes.at("\\whitebox"); +					ast->attributes.erase("\\whitebox"); +				} +				AstNode *n = ast->attributes.at("\\lib_whitebox"); +				ast->attributes["\\whitebox"] = n; +				ast->attributes.erase("\\lib_whitebox"); +			} +		} + +		bool blackbox_module = flag_lib; + +		if (!blackbox_module && ast->attributes.count("\\blackbox")) { +			AstNode *n = ast->attributes.at("\\blackbox"); +			if (n->type != AST_CONSTANT) +				log_file_error(ast->filename, ast->linenum, "Blackbox attribute with non-constant value!\n"); +			blackbox_module = n->asBool(); +		} + +		if (!blackbox_module && !flag_noblackbox) +		{ +			for (auto child : ast->children) { +				if (child->type == AST_WIRE && (child->is_input || child->is_output)) +					continue; +				if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM) +					continue; +				goto noblackbox; +			} +			blackbox_module = 1; +		} + +	noblackbox: +		if (blackbox_module && ast->attributes.count("\\whitebox")) {  			AstNode *n = ast->attributes.at("\\whitebox");  			if (n->type != AST_CONSTANT)  				log_file_error(ast->filename, ast->linenum, "Whitebox attribute with non-constant value!\n"); -			if (!n->asBool()) -				goto blackbox_module; +			blackbox_module = !n->asBool();  		} -		if (flag_lib) { -	blackbox_module: +		if (blackbox_module) +		{ +			if (ast->attributes.count("\\whitebox")) { +				delete ast->attributes.at("\\whitebox"); +				ast->attributes.erase("\\whitebox"); +			} + +			if (ast->attributes.count("\\lib_whitebox")) { +				delete ast->attributes.at("\\lib_whitebox"); +				ast->attributes.erase("\\lib_whitebox"); +			} +  			std::vector<AstNode*> new_children;  			for (auto child : ast->children) {  				if (child->type == AST_WIRE && (child->is_input || child->is_output)) { @@ -980,12 +1029,12 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast  					delete child;  				}  			} +  			ast->children.swap(new_children); -			if (ast->attributes.count("\\whitebox")) { -				delete ast->attributes.at("\\whitebox"); -				ast->attributes.erase("\\whitebox"); + +			if (ast->attributes.count("\\blackbox") == 0) { +				ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false);  			} -			ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false);  		}  		ignoreThisSignalsInInitial = RTLIL::SigSpec(); @@ -1024,8 +1073,9 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast  	current_module->nomeminit = flag_nomeminit;  	current_module->nomem2reg = flag_nomem2reg;  	current_module->mem2reg = flag_mem2reg; +	current_module->noblackbox = flag_noblackbox;  	current_module->lib = flag_lib; -	current_module->wb = flag_wb; +	current_module->nowb = flag_nowb;  	current_module->noopt = flag_noopt;  	current_module->icells = flag_icells;  	current_module->autowire = flag_autowire; @@ -1042,7 +1092,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 lib, bool wb, 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 nooverwrite, bool overwrite, bool defer, bool autowire)  {  	current_ast = ast;  	flag_dump_ast1 = dump_ast1; @@ -1055,8 +1105,9 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump  	flag_nomeminit = nomeminit;  	flag_nomem2reg = nomem2reg;  	flag_mem2reg = mem2reg; +	flag_noblackbox = noblackbox;  	flag_lib = lib; -	flag_wb = wb; +	flag_nowb = nowb;  	flag_noopt = noopt;  	flag_icells = icells;  	flag_autowire = autowire; @@ -1390,8 +1441,9 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString  	flag_nomeminit = nomeminit;  	flag_nomem2reg = nomem2reg;  	flag_mem2reg = mem2reg; +	flag_noblackbox = noblackbox;  	flag_lib = lib; -	flag_wb = wb; +	flag_nowb = nowb;  	flag_noopt = noopt;  	flag_icells = icells;  	flag_autowire = autowire; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 610e00fbf..281cbe086 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -283,13 +283,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 lib, bool wb, 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 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, lib, wb, noopt, icells, autowire; +		bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, 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; diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 4e2c5abb5..ed6ce2ecb 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -145,12 +145,18 @@ struct VerilogFrontend : public Frontend {  		log("    -nodpi\n");  		log("        disable DPI-C support\n");  		log("\n"); +		log("    -noblackbox\n"); +		log("        do not automatically add a (* blackbox *) attribute to an\n"); +		log("        empty module.\n"); +		log("\n");  		log("    -lib\n");  		log("        only create empty blackbox modules. This implies -DBLACKBOX.\n"); +		log("        modules with the (* whitebox *) attribute will be preserved.\n"); +		log("        (* lib_whitebox *) will be treated like (* whitebox *).\n");  		log("\n"); -		log("    -wb\n"); -		log("        like -lib, except do not touch modules with the whitebox\n"); -		log("        attribute set. This also implies -DBLACKBOX.\n"); +		log("    -nowb\n"); +		log("        delete (* whitebox *) and (* lib_whitebox *) attributes from\n"); +		log("        all modules.\n");  		log("\n");  		log("    -noopt\n");  		log("        don't perform basic optimizations (such as const folding) in the\n"); @@ -231,8 +237,9 @@ struct VerilogFrontend : public Frontend {  		formal_mode = false;  		norestrict_mode = false;  		assume_asserts_mode = false; +		noblackbox_mode = false;  		lib_mode = false; -		wb_mode = false; +		nowb_mode = false;  		default_nettype_wire = true;  		log_header(design, "Executing Verilog-2005 frontend.\n"); @@ -334,14 +341,17 @@ struct VerilogFrontend : public Frontend {  				flag_nodpi = true;  				continue;  			} -			if (arg == "-lib" && !wb_mode) { +			if (arg == "-noblackbox") { +				noblackbox_mode = true; +				continue; +			} +			if (arg == "-lib") {  				lib_mode = true;  				defines_map["BLACKBOX"] = string();  				continue;  			} -			if (arg == "-wb" && !lib_mode) { -				wb_mode = true; -				defines_map["BLACKBOX"] = string(); +			if (arg == "-nowb") { +				nowb_mode = true;  				continue;  			}  			if (arg == "-noopt") { @@ -439,7 +449,8 @@ struct VerilogFrontend : public Frontend {  		if (flag_nodpi)  			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, lib_mode, wb_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire); +		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, noblackbox_mode, lib_mode, nowb_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);  		if (!flag_nopp)  			delete lexin; diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index b5cf70c57..ca40946cb 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -69,11 +69,14 @@ namespace VERILOG_FRONTEND  	// running in -assert-assumes mode  	extern bool assert_assumes_mode; +	// running in -noblackbox mode +	extern bool noblackbox_mode; +  	// running in -lib mode  	extern bool lib_mode; -	// running in -wb mode -	extern bool wb_mode; +	// running in -nowb mode +	extern bool nowb_mode;  	// lexer input stream  	extern std::istream *lexin; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 122eb1230..40968d17a 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -59,7 +59,7 @@ namespace VERILOG_FRONTEND {  	std::vector<char> case_type_stack;  	bool do_not_require_port_stubs;  	bool default_nettype_wire; -	bool sv_mode, formal_mode, lib_mode, wb_mode; +	bool sv_mode, formal_mode, noblackbox_mode, lib_mode, nowb_mode;  	bool noassert_mode, noassume_mode, norestrict_mode;  	bool assume_asserts_mode, assert_assumes_mode;  	bool current_wire_rand, current_wire_const; @@ -1906,7 +1906,7 @@ basic_expr:  		if ($4->substr(0, 1) != "'")  			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 && !wb_mode); +		AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);  		if (val == NULL)  			log_error("Value conversion failed: `%s'\n", $4->c_str());  		$$ = new AstNode(AST_TO_BITS, bits, val); @@ -1917,7 +1917,7 @@ basic_expr:  			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 && !wb_mode); +		AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);  		if (val == NULL)  			log_error("Value conversion failed: `%s'\n", $2->c_str());  		$$ = new AstNode(AST_TO_BITS, bits, val); @@ -1925,14 +1925,14 @@ basic_expr:  		delete $2;  	} |  	TOK_CONSTVAL TOK_CONSTVAL { -		$$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode && !wb_mode); +		$$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);  		if ($$ == NULL || (*$2)[0] != '\'')  			log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str());  		delete $1;  		delete $2;  	} |  	TOK_CONSTVAL { -		$$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode && !wb_mode); +		$$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);  		if ($$ == NULL)  			log_error("Value conversion failed: `%s'\n", $1->c_str());  		delete $1;  | 
