mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	cxxrtl_backend: respect sync $print priority
				
					
				
			We add a new flow graph node type, PRINT_SYNC, as they don't get handled with regular CELL_EVALs. We could probably move this grouping out of the dump method.
This commit is contained in:
		
							parent
							
								
									04582f2fb7
								
							
						
					
					
						commit
						ce245b5105
					
				
					 3 changed files with 68 additions and 42 deletions
				
			
		|  | @ -282,6 +282,7 @@ struct FlowGraph { | ||||||
| 			CONNECT, | 			CONNECT, | ||||||
| 			CELL_SYNC, | 			CELL_SYNC, | ||||||
| 			CELL_EVAL, | 			CELL_EVAL, | ||||||
|  | 			PRINT_SYNC, | ||||||
| 			PROCESS_SYNC, | 			PROCESS_SYNC, | ||||||
| 			PROCESS_CASE, | 			PROCESS_CASE, | ||||||
| 			MEM_RDPORT, | 			MEM_RDPORT, | ||||||
|  | @ -472,6 +473,8 @@ struct FlowGraph { | ||||||
| 
 | 
 | ||||||
| 		Node *node = new Node; | 		Node *node = new Node; | ||||||
| 		node->type = Node::Type::CELL_EVAL; | 		node->type = Node::Type::CELL_EVAL; | ||||||
|  | 		if (cell->type == ID($print) && cell->getParam(ID::TRG_ENABLE).as_bool()) | ||||||
|  | 			node->type = Node::Type::PRINT_SYNC; | ||||||
| 		node->cell = cell; | 		node->cell = cell; | ||||||
| 		nodes.push_back(node); | 		nodes.push_back(node); | ||||||
| 		add_cell_eval_defs_uses(node, cell); | 		add_cell_eval_defs_uses(node, cell); | ||||||
|  | @ -1043,9 +1046,49 @@ struct CxxrtlWorker { | ||||||
| 		Fmt fmt = {}; | 		Fmt fmt = {}; | ||||||
| 		fmt.parse_rtlil(cell); | 		fmt.parse_rtlil(cell); | ||||||
| 
 | 
 | ||||||
|  | 		f << indent << "if ("; | ||||||
|  | 		dump_sigspec_rhs(cell->getPort(ID::EN)); | ||||||
|  | 		f << " == value<1>{1u}) {\n"; | ||||||
|  | 		inc_indent(); | ||||||
| 			f << indent << print_output; | 			f << indent << print_output; | ||||||
| 			fmt.emit_cxxrtl(f, [this](const RTLIL::SigSpec &sig) { dump_sigspec_rhs(sig); }); | 			fmt.emit_cxxrtl(f, [this](const RTLIL::SigSpec &sig) { dump_sigspec_rhs(sig); }); | ||||||
| 			f << ";\n"; | 			f << ";\n"; | ||||||
|  | 		dec_indent(); | ||||||
|  | 		f << indent << "}\n"; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void dump_sync_print(const RTLIL::SigSpec &trg, const RTLIL::Const &polarity, std::vector<const RTLIL::Cell*> &cells) | ||||||
|  | 	{ | ||||||
|  | 		f << indent << "if ("; | ||||||
|  | 		for (int i = 0; i < trg.size(); i++) { | ||||||
|  | 			RTLIL::SigBit trg_bit = trg[i]; | ||||||
|  | 			trg_bit = sigmaps[trg_bit.wire->module](trg_bit); | ||||||
|  | 			log_assert(trg_bit.wire); | ||||||
|  | 
 | ||||||
|  | 			if (i != 0) | ||||||
|  | 				f << " || "; | ||||||
|  | 
 | ||||||
|  | 			if (polarity[i] == State::S1) | ||||||
|  | 				f << "posedge_"; | ||||||
|  | 			else | ||||||
|  | 				f << "negedge_"; | ||||||
|  | 			f << mangle(trg_bit); | ||||||
|  | 		} | ||||||
|  | 		f << ") {\n"; | ||||||
|  | 		inc_indent(); | ||||||
|  | 			std::sort(cells.begin(), cells.end(), [](const RTLIL::Cell *a, const RTLIL::Cell *b) { | ||||||
|  | 				return a->getParam(ID::PRIORITY).as_int() > b->getParam(ID::PRIORITY).as_int(); | ||||||
|  | 			}); | ||||||
|  | 			for (auto cell : cells) { | ||||||
|  | 				log_assert(cell->getParam(ID::TRG_ENABLE).as_bool()); | ||||||
|  | 				std::vector<const RTLIL::Cell*> inlined_cells; | ||||||
|  | 				collect_cell_eval(cell, /*for_debug=*/false, inlined_cells); | ||||||
|  | 				dump_inlined_cells(inlined_cells); | ||||||
|  | 				dump_print(cell); | ||||||
|  | 			} | ||||||
|  | 		dec_indent(); | ||||||
|  | 
 | ||||||
|  | 		f << indent << "}\n"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void dump_inlined_cells(const std::vector<const RTLIL::Cell*> &cells) | 	void dump_inlined_cells(const std::vector<const RTLIL::Cell*> &cells) | ||||||
|  | @ -1218,47 +1261,21 @@ struct CxxrtlWorker { | ||||||
| 		} else if (cell->type == ID($print)) { | 		} else if (cell->type == ID($print)) { | ||||||
| 			log_assert(!for_debug); | 			log_assert(!for_debug); | ||||||
| 
 | 
 | ||||||
| 			auto trg_enable = cell->getParam(ID::TRG_ENABLE).as_bool(); | 			// Sync $print cells become PRINT_SYNC in the FlowGraph, not CELL_EVAL.
 | ||||||
|  | 			log_assert(!cell->getParam(ID::TRG_ENABLE).as_bool()); | ||||||
| 
 | 
 | ||||||
| 			if (!trg_enable) { |  | ||||||
| 			f << indent << "auto " << mangle(cell) << "_curr = "; | 			f << indent << "auto " << mangle(cell) << "_curr = "; | ||||||
| 			dump_sigspec_rhs(cell->getPort(ID::EN)); | 			dump_sigspec_rhs(cell->getPort(ID::EN)); | ||||||
| 			f << ".concat("; | 			f << ".concat("; | ||||||
| 			dump_sigspec_rhs(cell->getPort(ID::ARGS)); | 			dump_sigspec_rhs(cell->getPort(ID::ARGS)); | ||||||
| 			f << ").val();\n"; | 			f << ").val();\n"; | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			f << indent << "if ("; | 			f << indent << "if (" << mangle(cell) << " != " << mangle(cell) << "_curr) {\n"; | ||||||
| 			if (trg_enable) { |  | ||||||
| 				f << '('; |  | ||||||
| 				for (size_t i = 0; i < (size_t)cell->getParam(ID::TRG_WIDTH).as_int(); i++) { |  | ||||||
| 					RTLIL::SigBit trg_bit = cell->getPort(ID::TRG)[i]; |  | ||||||
| 					trg_bit = sigmaps[trg_bit.wire->module](trg_bit); |  | ||||||
| 					log_assert(trg_bit.wire); |  | ||||||
| 
 |  | ||||||
| 					if (i != 0) |  | ||||||
| 						f << " || "; |  | ||||||
| 
 |  | ||||||
| 					if (cell->getParam(ID::TRG_POLARITY)[i] == State::S1) |  | ||||||
| 						f << "posedge_"; |  | ||||||
| 					else |  | ||||||
| 						f << "negedge_"; |  | ||||||
| 					f << mangle(trg_bit); |  | ||||||
| 				} |  | ||||||
| 				f << ") && "; |  | ||||||
| 			} else { |  | ||||||
| 				f << mangle(cell) << " != " << mangle(cell) << "_curr && "; |  | ||||||
| 			} |  | ||||||
| 			dump_sigspec_rhs(cell->getPort(ID::EN)); |  | ||||||
| 			f << " == value<1>{1u}) {\n"; |  | ||||||
| 			inc_indent(); | 			inc_indent(); | ||||||
| 				dump_print(cell); | 				dump_print(cell); | ||||||
|  | 				f << indent << mangle(cell) << " = " << mangle(cell) << "_curr;\n"; | ||||||
| 			dec_indent(); | 			dec_indent(); | ||||||
| 			f << indent << "}\n"; | 			f << indent << "}\n"; | ||||||
| 
 |  | ||||||
| 			if (!trg_enable) { |  | ||||||
| 				f << indent << mangle(cell) << " = " << mangle(cell) << "_curr;\n"; |  | ||||||
| 			} |  | ||||||
| 		// Flip-flops
 | 		// Flip-flops
 | ||||||
| 		} else if (is_ff_cell(cell->type)) { | 		} else if (is_ff_cell(cell->type)) { | ||||||
| 			log_assert(!for_debug); | 			log_assert(!for_debug); | ||||||
|  | @ -1971,6 +1988,8 @@ struct CxxrtlWorker { | ||||||
| 
 | 
 | ||||||
| 	void dump_eval_method(RTLIL::Module *module) | 	void dump_eval_method(RTLIL::Module *module) | ||||||
| 	{ | 	{ | ||||||
|  | 		std::map<std::pair<RTLIL::SigSpec, RTLIL::Const>, std::vector<const RTLIL::Cell*>> sync_print_cells; | ||||||
|  | 
 | ||||||
| 		inc_indent(); | 		inc_indent(); | ||||||
| 			f << indent << "bool converged = " << (eval_converges.at(module) ? "true" : "false") << ";\n"; | 			f << indent << "bool converged = " << (eval_converges.at(module) ? "true" : "false") << ";\n"; | ||||||
| 			if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) { | 			if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) { | ||||||
|  | @ -2003,6 +2022,9 @@ struct CxxrtlWorker { | ||||||
| 						case FlowGraph::Node::Type::CELL_EVAL: | 						case FlowGraph::Node::Type::CELL_EVAL: | ||||||
| 							dump_cell_eval(node.cell); | 							dump_cell_eval(node.cell); | ||||||
| 							break; | 							break; | ||||||
|  | 						case FlowGraph::Node::Type::PRINT_SYNC: | ||||||
|  | 							sync_print_cells[make_pair(node.cell->getPort(ID::TRG), node.cell->getParam(ID::TRG_POLARITY))].push_back(node.cell); | ||||||
|  | 							break; | ||||||
| 						case FlowGraph::Node::Type::PROCESS_CASE: | 						case FlowGraph::Node::Type::PROCESS_CASE: | ||||||
| 							dump_process_case(node.process); | 							dump_process_case(node.process); | ||||||
| 							break; | 							break; | ||||||
|  | @ -2017,6 +2039,8 @@ struct CxxrtlWorker { | ||||||
| 							break; | 							break; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  | 				for (auto &it : sync_print_cells) | ||||||
|  | 					dump_sync_print(it.first.first, it.first.second, it.second); | ||||||
| 			} | 			} | ||||||
| 			f << indent << "return converged;\n"; | 			f << indent << "return converged;\n"; | ||||||
| 		dec_indent(); | 		dec_indent(); | ||||||
|  | @ -2808,6 +2832,8 @@ struct CxxrtlWorker { | ||||||
| 			for (auto node : flow.nodes) { | 			for (auto node : flow.nodes) { | ||||||
| 				if (node->type == FlowGraph::Node::Type::CELL_EVAL && is_effectful_cell(node->cell->type)) | 				if (node->type == FlowGraph::Node::Type::CELL_EVAL && is_effectful_cell(node->cell->type)) | ||||||
| 					worklist.insert(node); // node has effects
 | 					worklist.insert(node); // node has effects
 | ||||||
|  | 				else if (node->type == FlowGraph::Node::Type::PRINT_SYNC) | ||||||
|  | 					worklist.insert(node); // node is sync $print
 | ||||||
| 				else if (node->type == FlowGraph::Node::Type::MEM_WRPORTS) | 				else if (node->type == FlowGraph::Node::Type::MEM_WRPORTS) | ||||||
| 					worklist.insert(node); // node is memory write
 | 					worklist.insert(node); // node is memory write
 | ||||||
| 				else if (node->type == FlowGraph::Node::Type::PROCESS_SYNC && is_memwr_process(node->process)) | 				else if (node->type == FlowGraph::Node::Type::PROCESS_SYNC && is_memwr_process(node->process)) | ||||||
|  |  | ||||||
|  | @ -1006,7 +1006,7 @@ void dump_cell_expr_binop(std::ostream &f, std::string indent, RTLIL::Cell *cell | ||||||
| 	f << stringf(";\n"); | 	f << stringf(";\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void dump_cell_expr_print(std::ostream &f, std::string indent, RTLIL::Cell *cell) | void dump_cell_expr_print(std::ostream &f, std::string indent, const RTLIL::Cell *cell) | ||||||
| { | { | ||||||
| 	Fmt fmt = {}; | 	Fmt fmt = {}; | ||||||
| 	fmt.parse_rtlil(cell); | 	fmt.parse_rtlil(cell); | ||||||
|  | @ -1893,7 +1893,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void dump_sync_print(std::ostream &f, std::string indent, const RTLIL::SigSpec &trg, const RTLIL::Const &polarity, std::vector<RTLIL::Cell*> &cells) | void dump_sync_print(std::ostream &f, std::string indent, const RTLIL::SigSpec &trg, const RTLIL::Const &polarity, std::vector<const RTLIL::Cell*> &cells) | ||||||
| { | { | ||||||
| 	f << stringf("%s" "always @(", indent.c_str()); | 	f << stringf("%s" "always @(", indent.c_str()); | ||||||
| 	for (int i = 0; i < trg.size(); i++) { | 	for (int i = 0; i < trg.size(); i++) { | ||||||
|  | @ -2102,7 +2102,7 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo | ||||||
| 
 | 
 | ||||||
| void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) | void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) | ||||||
| { | { | ||||||
| 	std::map<std::pair<RTLIL::SigSpec, RTLIL::Const>, std::vector<RTLIL::Cell*>> sync_print_cells; | 	std::map<std::pair<RTLIL::SigSpec, RTLIL::Const>, std::vector<const RTLIL::Cell*>> sync_print_cells; | ||||||
| 
 | 
 | ||||||
| 	reg_wires.clear(); | 	reg_wires.clear(); | ||||||
| 	reset_auto_counter(module); | 	reset_auto_counter(module); | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ test_roundtrip bin_signed -DBASE_HEX -DSIGN="signed" | ||||||
| test_cxxrtl () { | test_cxxrtl () { | ||||||
| 	local subtest=$1; shift | 	local subtest=$1; shift | ||||||
| 
 | 
 | ||||||
| 	../../yosys -p "read_verilog ${subtest}.v; write_cxxrtl -print-output std::cerr yosys-${subtest}.cc" | 	../../yosys -p "read_verilog ${subtest}.v; proc; clean; write_cxxrtl -print-output std::cerr yosys-${subtest}.cc" | ||||||
| 	${CC:-gcc} -std=c++11 -o yosys-${subtest} -I../.. ${subtest}_tb.cc -lstdc++ | 	${CC:-gcc} -std=c++11 -o yosys-${subtest} -I../.. ${subtest}_tb.cc -lstdc++ | ||||||
| 	./yosys-${subtest} 2>yosys-${subtest}.log | 	./yosys-${subtest} 2>yosys-${subtest}.log | ||||||
| 	iverilog -o iverilog-${subtest} ${subtest}.v ${subtest}_tb.v | 	iverilog -o iverilog-${subtest} ${subtest}.v ${subtest}_tb.v | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue