diff options
| author | Jim Lawson <ucbjrl@berkeley.edu> | 2019-04-30 13:19:27 -0700 | 
|---|---|---|
| committer | Jim Lawson <ucbjrl@berkeley.edu> | 2019-04-30 13:19:27 -0700 | 
| commit | 58650ffe876d1caedd8ffc9b0207f5cf75eef97b (patch) | |
| tree | 5389584f1c3ad8c9e9003e78d4b6e22dca5e3a83 /frontends/ast | |
| parent | 354ba5ba83f7b1fc3bb07aa6bf26dde7a00201d1 (diff) | |
| parent | e35fe1344dd4c8f11632ed2a7f5b0463352a1ee4 (diff) | |
| download | yosys-58650ffe876d1caedd8ffc9b0207f5cf75eef97b.tar.gz yosys-58650ffe876d1caedd8ffc9b0207f5cf75eef97b.tar.bz2 yosys-58650ffe876d1caedd8ffc9b0207f5cf75eef97b.zip | |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'frontends/ast')
| -rw-r--r-- | frontends/ast/ast.cc | 88 | ||||
| -rw-r--r-- | frontends/ast/ast.h | 4 | ||||
| -rw-r--r-- | frontends/ast/simplify.cc | 51 | 
3 files changed, 133 insertions, 10 deletions
| diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index d48996167..9f88b08c1 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_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; @@ -942,6 +942,20 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast  	if (!defer)  	{ +		bool blackbox_module = flag_lib; + +		if (!blackbox_module && !flag_noblackbox) { +			blackbox_module = true; +			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; +				blackbox_module = false; +				break; +			} +		} +  		while (ast->simplify(!flag_noopt, false, false, 0, -1, false, false)) { }  		if (flag_dump_ast2) { @@ -956,7 +970,63 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast  			log("--- END OF AST DUMP ---\n");  		} -		if (flag_lib) { +		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"); +			} +		} + +		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, "Got blackbox attribute with non-constant value!\n"); +			blackbox_module = n->asBool(); +		} + +		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, "Got whitebox attribute with non-constant value!\n"); +			blackbox_module = !n->asBool(); +		} + +		if (ast->attributes.count("\\noblackbox")) { +			if (blackbox_module) { +				AstNode *n = ast->attributes.at("\\noblackbox"); +				if (n->type != AST_CONSTANT) +					log_file_error(ast->filename, ast->linenum, "Got noblackbox attribute with non-constant value!\n"); +				blackbox_module = !n->asBool(); +			} +			delete ast->attributes.at("\\noblackbox"); +			ast->attributes.erase("\\noblackbox"); +		} + +		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)) { @@ -969,8 +1039,12 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast  					delete child;  				}  			} +  			ast->children.swap(new_children); -			ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); + +			if (ast->attributes.count("\\blackbox") == 0) { +				ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); +			}  		}  		ignoreThisSignalsInInitial = RTLIL::SigSpec(); @@ -1009,7 +1083,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->nowb = flag_nowb;  	current_module->noopt = flag_noopt;  	current_module->icells = flag_icells;  	current_module->autowire = flag_autowire; @@ -1026,7 +1102,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 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; @@ -1039,7 +1115,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_nowb = nowb;  	flag_noopt = noopt;  	flag_icells = icells;  	flag_autowire = autowire; @@ -1373,7 +1451,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_nowb = nowb;  	flag_noopt = noopt;  	flag_icells = icells;  	flag_autowire = autowire; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index ddd59d4be..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 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, 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/ast/simplify.cc b/frontends/ast/simplify.cc index 63b71b800..4d4b9dfe1 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1030,7 +1030,26 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n");  	if (type == AST_REPEAT) -		log_file_error(filename, linenum, "Repeat loops are only allowed in constant functions!\n"); +	{ +		AstNode *count = children[0]; +		AstNode *body = children[1]; + +		// eval count expression +		while (count->simplify(true, false, false, stage, 32, true, false)) { } + +		if (count->type != AST_CONSTANT) +			log_file_error(filename, linenum, "Repeat loops outside must have constant repeat counts!\n"); + +		// convert to a block with the body repeated n times +		type = AST_BLOCK; +		children.clear(); +		for (int i = 0; i < count->bitsAsConst().as_int(); i++) +			children.insert(children.begin(), body->clone()); + +		delete count; +		delete body; +		did_something = true; +	}  	// unroll for loops and generate-for blocks  	if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0) @@ -1066,7 +1085,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		// eval 1st expression  		AstNode *varbuf = init_ast->children[1]->clone(); -		while (varbuf->simplify(true, false, false, stage, 32, true, false)) { } +		{ +			int expr_width_hint = -1; +			bool expr_sign_hint = true; +			varbuf->detectSignWidth(expr_width_hint, expr_sign_hint); +			while (varbuf->simplify(true, false, false, stage, 32, true, false)) { } +		}  		if (varbuf->type != AST_CONSTANT)  			log_file_error(filename, linenum, "Right hand side of 1st expression of generate for-loop is not constant!\n"); @@ -1088,7 +1112,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		{  			// eval 2nd expression  			AstNode *buf = while_ast->clone(); -			while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { } +			{ +				int expr_width_hint = -1; +				bool expr_sign_hint = true; +				buf->detectSignWidth(expr_width_hint, expr_sign_hint); +				while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, false)) { } +			}  			if (buf->type != AST_CONSTANT)  				log_file_error(filename, linenum, "2nd expression of generate for-loop is not constant!\n"); @@ -1129,7 +1158,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			// eval 3rd expression  			buf = next_ast->children[1]->clone(); -			while (buf->simplify(true, false, false, stage, 32, true, false)) { } +			{ +				int expr_width_hint = -1; +				bool expr_sign_hint = true; +				buf->detectSignWidth(expr_width_hint, expr_sign_hint); +				while (buf->simplify(true, false, false, stage, expr_width_hint, expr_sign_hint, true)) { } +			}  			if (buf->type != AST_CONSTANT)  				log_file_error(filename, linenum, "Right hand side of 3rd expression of generate for-loop is not constant!\n"); @@ -1138,6 +1172,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  			varbuf->children[0] = buf;  		} +#if 0 +		if (type == AST_FOR) { +			AstNode *buf = next_ast->clone(); +			delete buf->children[1]; +			buf->children[1] = varbuf->children[0]->clone(); +			current_block->children.insert(current_block->children.begin() + current_block_idx++, buf); +		} +#endif +  		current_scope[varbuf->str] = backup_scope_varbuf;  		delete varbuf;  		delete_children(); | 
