diff options
Diffstat (limited to 'frontends/ast')
| -rw-r--r-- | frontends/ast/ast.cc | 2 | ||||
| -rw-r--r-- | frontends/ast/ast.h | 2 | ||||
| -rw-r--r-- | frontends/ast/genrtlil.cc | 56 | ||||
| -rw-r--r-- | frontends/ast/simplify.cc | 58 | 
4 files changed, 89 insertions, 29 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index af5e326ad..3b6319071 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -54,6 +54,8 @@ namespace AST_INTERNAL {  	AstNode *current_always, *current_top_block, *current_block, *current_block_child;  	AstModule *current_module;  	bool current_always_clocked; +	dict<std::string, int> current_memwr_count; +	dict<std::string, pool<int>> current_memwr_visible;  }  // convert node types to string diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 1c9a6ee47..1447bf568 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -381,6 +381,8 @@ namespace AST_INTERNAL  	extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child;  	extern AST::AstModule *current_module;  	extern bool current_always_clocked; +	extern dict<std::string, int> current_memwr_count; +	extern dict<std::string, pool<int>> current_memwr_visible;  	struct LookaheadRewriter;  	struct ProcessGenerator;  } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index e0a522430..ad5814f1b 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -399,6 +399,9 @@ struct AST_INTERNAL::ProcessGenerator  			if (child->type == AST_BLOCK)  				processAst(child); +		for (auto sync: proc->syncs) +			processMemWrites(sync); +  		if (initSyncSignals.size() > 0)  		{  			RTLIL::SyncRule *sync = new RTLIL::SyncRule; @@ -698,6 +701,34 @@ struct AST_INTERNAL::ProcessGenerator  			log_abort();  		}  	} + +	void processMemWrites(RTLIL::SyncRule *sync) +	{ +		// Maps per-memid AST_MEMWR IDs to indices in the mem_write_actions array. +		dict<std::pair<std::string, int>, int> port_map; +		for (auto child : always->children) +			if (child->type == AST_MEMWR) +			{ +				std::string memid = child->str; +				int portid = child->children[3]->asInt(false); +				int cur_idx = GetSize(sync->mem_write_actions); +				RTLIL::MemWriteAction action; +				set_src_attr(&action, child); +				action.memid = memid; +				action.address = child->children[0]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap()); +				action.data = child->children[1]->genWidthRTLIL(current_module->memories[memid]->width, &subst_rvalue_map.stdmap()); +				action.enable = child->children[2]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap()); +				RTLIL::Const orig_priority_mask = child->children[4]->bitsAsConst(); +				RTLIL::Const priority_mask = RTLIL::Const(0, cur_idx); +				for (int i = 0; i < portid; i++) { +					int new_bit = port_map[std::make_pair(memid, i)]; +					priority_mask.bits[new_bit] = orig_priority_mask.bits[i]; +				} +				action.priority_mask = priority_mask; +				sync->mem_write_actions.push_back(action); +				port_map[std::make_pair(memid, portid)] = cur_idx; +			} +	}  };  // detect sign and width of an expression @@ -1644,26 +1675,22 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  			return RTLIL::SigSpec(wire);  		} -	// generate $memwr cells for memory write ports -	case AST_MEMWR: +	// generate $meminit cells  	case AST_MEMINIT:  		{  			std::stringstream sstr; -			sstr << (type == AST_MEMWR ? "$memwr$" : "$meminit$") << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++); +			sstr << "$meminit$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++); -			RTLIL::Cell *cell = current_module->addCell(sstr.str(), type == AST_MEMWR ? ID($memwr) : ID($meminit)); +			RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($meminit));  			set_src_attr(cell, this);  			int mem_width, mem_size, addr_bits;  			id2ast->meminfo(mem_width, mem_size, addr_bits); -			int num_words = 1; -			if (type == AST_MEMINIT) { -				if (children[2]->type != AST_CONSTANT) -					log_file_error(filename, location.first_line, "Memory init with non-constant word count!\n"); -				num_words = int(children[2]->asInt(false)); -				cell->parameters[ID::WORDS] = RTLIL::Const(num_words); -			} +			if (children[2]->type != AST_CONSTANT) +				log_file_error(filename, location.first_line, "Memory init with non-constant word count!\n"); +			int num_words = int(children[2]->asInt(false)); +			cell->parameters[ID::WORDS] = RTLIL::Const(num_words);  			SigSpec addr_sig = children[0]->genRTLIL(); @@ -1674,13 +1701,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)  			cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig));  			cell->parameters[ID::WIDTH] = RTLIL::Const(current_module->memories[str]->width); -			if (type == AST_MEMWR) { -				cell->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::Sx, 1)); -				cell->setPort(ID::EN, children[2]->genRTLIL()); -				cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(0); -				cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(0); -			} -  			cell->parameters[ID::PRIORITY] = RTLIL::Const(autoidx-1);  		}  		break; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index e7f897b3c..e0ac58f20 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1217,6 +1217,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		}  	} +	dict<std::string, pool<int>> backup_memwr_visible; +	dict<std::string, pool<int>> final_memwr_visible; + +	if (type == AST_CASE && stage == 2) { +		backup_memwr_visible = current_memwr_visible; +		final_memwr_visible = current_memwr_visible; +	} +  	// simplify all children first  	// (iterate by index as e.g. auto wires can add new children in the process)  	for (size_t i = 0; i < children.size(); i++) { @@ -1279,11 +1287,25 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,  		}  		flag_autowire = backup_flag_autowire;  		unevaluated_tern_branch = backup_unevaluated_tern_branch; +		if (stage == 2 && type == AST_CASE) { +			for (auto &x : current_memwr_visible) { +				for (int y : x.second) +					final_memwr_visible[x.first].insert(y); +			} +			current_memwr_visible = backup_memwr_visible; +		}  	}  	for (auto &attr : attributes) {  		while (attr.second->simplify(true, false, false, stage, -1, false, true))  			did_something = true;  	} +	if (type == AST_CASE && stage == 2) { +		current_memwr_visible = final_memwr_visible; +	} +	if (type == AST_ALWAYS && stage == 2) { +		current_memwr_visible.clear(); +		current_memwr_count.clear(); +	}  	if (reset_width_after_children) {  		width_hint = backup_width_hint; @@ -2570,12 +2592,12 @@ skip_dynamic_range_lvalue_expansion:;  			current_scope[wire_addr->str] = wire_addr;  			while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { } -			AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false)); +			AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false));  			assign_addr->children[0]->str = id_addr;  			assign_addr->children[0]->was_checked = true;  			defNode->children.push_back(assign_addr); -			assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone()); +			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;  			newNode->children.push_back(assign_addr); @@ -2596,7 +2618,7 @@ skip_dynamic_range_lvalue_expansion:;  			current_scope[wire_data->str] = wire_data;  			while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } -			AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false)); +			AstNode *assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false));  			assign_data->children[0]->str = id_data;  			assign_data->children[0]->was_checked = true;  			defNode->children.push_back(assign_data); @@ -2616,7 +2638,7 @@ skip_dynamic_range_lvalue_expansion:;  			current_scope[wire_en->str] = wire_en;  			while (wire_en->simplify(true, false, false, 1, -1, false, false)) { } -			AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width)); +			AstNode *assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));  			assign_en->children[0]->str = id_en;  			assign_en->children[0]->was_checked = true;  			defNode->children.push_back(assign_en); @@ -2642,7 +2664,7 @@ skip_dynamic_range_lvalue_expansion:;  				std::vector<RTLIL::State> padding_x(offset, RTLIL::State::Sx); -				assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), +				assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER),  						new AstNode(AST_CONCAT, mkconst_bits(padding_x, false), children[1]->clone()));  				assign_data->children[0]->str = id_data;  				assign_data->children[0]->was_checked = true; @@ -2650,7 +2672,7 @@ skip_dynamic_range_lvalue_expansion:;  				if (current_always->type != AST_INITIAL) {  					for (int i = 0; i < mem_width; i++)  						set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0; -					assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false)); +					assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));  					assign_en->children[0]->str = id_en;  					assign_en->children[0]->was_checked = true;  				} @@ -2671,7 +2693,7 @@ skip_dynamic_range_lvalue_expansion:;  					log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());  				int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; -				assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), +				assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER),  						new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone()));  				assign_data->children[0]->str = id_data;  				assign_data->children[0]->was_checked = true; @@ -2679,7 +2701,7 @@ skip_dynamic_range_lvalue_expansion:;  				if (current_always->type != AST_INITIAL) {  					for (int i = 0; i < mem_width; i++)  						set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0; -					assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), +					assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER),  							new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));  					assign_en->children[0]->str = id_en;  					assign_en->children[0]->was_checked = true; @@ -2693,13 +2715,13 @@ skip_dynamic_range_lvalue_expansion:;  		else  		{  			if (!(children[0]->children.size() == 1 && children[1]->isConst())) { -				assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone()); +				assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[1]->clone());  				assign_data->children[0]->str = id_data;  				assign_data->children[0]->was_checked = true;  			}  			if (current_always->type != AST_INITIAL) { -				assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false)); +				assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));  				assign_en->children[0]->str = id_en;  				assign_en->children[0]->was_checked = true;  			} @@ -2712,7 +2734,21 @@ skip_dynamic_range_lvalue_expansion:;  		AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR, node_addr, node_data, node_en);  		wrnode->str = children[0]->str;  		wrnode->id2ast = children[0]->id2ast; -		current_ast_mod->children.push_back(wrnode); +		wrnode->location = location; +		if (wrnode->type == AST_MEMWR) { +			int portid = current_memwr_count[wrnode->str]++; +			wrnode->children.push_back(mkconst_int(portid, false)); +			std::vector<RTLIL::State> priority_mask; +			for (int i = 0; i < portid; i++) { +				bool has_prio = current_memwr_visible[wrnode->str].count(i); +				priority_mask.push_back(State(has_prio)); +			} +			wrnode->children.push_back(mkconst_bits(priority_mask, false)); +			current_memwr_visible[wrnode->str].insert(portid); +			current_always->children.push_back(wrnode); +		} else { +			current_ast_mod->children.push_back(wrnode); +		}  		if (newNode->children.empty()) {  			delete newNode;  | 
