mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	cxxrtl: Support memory writes in processes.
This commit is contained in:
		
							parent
							
								
									af7fa62251
								
							
						
					
					
						commit
						37506d737c
					
				
					 1 changed files with 55 additions and 6 deletions
				
			
		|  | @ -226,6 +226,14 @@ bool is_cxxrtl_blackbox_cell(const RTLIL::Cell *cell) | |||
| 	return cell_module->get_bool_attribute(ID(cxxrtl_blackbox)); | ||||
| } | ||||
| 
 | ||||
| bool is_memwr_process(const RTLIL::Process *process) | ||||
| { | ||||
| 	for (auto sync : process->syncs) | ||||
| 		if (!sync->mem_write_actions.empty()) | ||||
| 			return true; | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| enum class CxxrtlPortType { | ||||
| 	UNKNOWN = 0, // or mixed comb/sync
 | ||||
| 	COMB = 1, | ||||
|  | @ -481,14 +489,20 @@ struct FlowGraph { | |||
| 
 | ||||
| 	void add_sync_rules_defs_uses(Node *node, const RTLIL::Process *process) | ||||
| 	{ | ||||
| 		for (auto sync : process->syncs) | ||||
| 			for (auto action : sync->actions) { | ||||
| 		for (auto sync : process->syncs) { | ||||
| 			for (auto &action : sync->actions) { | ||||
| 				if (sync->type == RTLIL::STp || sync->type == RTLIL::STn || sync->type == RTLIL::STe) | ||||
| 					add_defs(node, action.first, /*is_ff=*/true,  /*inlinable=*/false); | ||||
| 				else | ||||
| 					add_defs(node, action.first, /*is_ff=*/false, /*inlinable=*/false); | ||||
| 				add_uses(node, action.second); | ||||
| 			} | ||||
| 			for (auto &memwr : sync->mem_write_actions) { | ||||
| 				add_uses(node, memwr.address); | ||||
| 				add_uses(node, memwr.data); | ||||
| 				add_uses(node, memwr.enable); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	Node *add_node(const RTLIL::Process *process) | ||||
|  | @ -685,6 +699,7 @@ struct CxxrtlWorker { | |||
| 
 | ||||
| 	dict<const RTLIL::Module*, SigMap> sigmaps; | ||||
| 	dict<const RTLIL::Module*, std::vector<Mem>> mod_memories; | ||||
| 	pool<std::pair<const RTLIL::Module*, RTLIL::IdString>> writable_memories; | ||||
| 	pool<const RTLIL::Wire*> edge_wires; | ||||
| 	dict<const RTLIL::Wire*, RTLIL::Const> wire_init; | ||||
| 	dict<RTLIL::SigBit, RTLIL::SyncType> edge_types; | ||||
|  | @ -776,6 +791,11 @@ struct CxxrtlWorker { | |||
| 		return mangle_memory_name(mem->memid); | ||||
| 	} | ||||
| 
 | ||||
| 	std::string mangle(const RTLIL::Memory *memory) | ||||
| 	{ | ||||
| 		return mangle_memory_name(memory->name); | ||||
| 	} | ||||
| 
 | ||||
| 	std::string mangle(const RTLIL::Cell *cell) | ||||
| 	{ | ||||
| 		return mangle_cell_name(cell->name); | ||||
|  | @ -1498,8 +1518,28 @@ struct CxxrtlWorker { | |||
| 				} | ||||
| 				f << ") {\n"; | ||||
| 				inc_indent(); | ||||
| 					for (auto action : sync->actions) | ||||
| 					for (auto &action : sync->actions) | ||||
| 						dump_assign(action, for_debug); | ||||
| 					for (auto &memwr : sync->mem_write_actions) { | ||||
| 						RTLIL::Memory *memory = proc->module->memories.at(memwr.memid); | ||||
| 						std::string valid_index_temp = fresh_temporary(); | ||||
| 						f << indent << "auto " << valid_index_temp << " = memory_index("; | ||||
| 						dump_sigspec_rhs(memwr.address); | ||||
| 						f << ", " << memory->start_offset << ", " << memory->size << ");\n"; | ||||
| 						// See below for rationale of having both the assert and the condition.
 | ||||
| 						//
 | ||||
| 						// If assertions are disabled, out of bounds writes are defined to do nothing.
 | ||||
| 						f << indent << "CXXRTL_ASSERT(" << valid_index_temp << ".valid && \"out of bounds write\");\n"; | ||||
| 						f << indent << "if (" << valid_index_temp << ".valid) {\n"; | ||||
| 						inc_indent(); | ||||
| 							f << indent << mangle(memory) << ".update(" << valid_index_temp << ".index, "; | ||||
| 							dump_sigspec_rhs(memwr.data); | ||||
| 							f << ", "; | ||||
| 							dump_sigspec_rhs(memwr.enable); | ||||
| 							f << ");\n"; | ||||
| 						dec_indent(); | ||||
| 						f << indent << "}\n"; | ||||
| 					} | ||||
| 				dec_indent(); | ||||
| 				f << indent << "}\n"; | ||||
| 			} | ||||
|  | @ -1917,7 +1957,7 @@ struct CxxrtlWorker { | |||
| 			} | ||||
| 			if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) { | ||||
| 				for (auto &mem : mod_memories[module]) { | ||||
| 					if (!GetSize(mem.wr_ports)) | ||||
| 					if (!writable_memories.count({module, mem.memid})) | ||||
| 						continue; | ||||
| 					f << indent << "if (" << mangle(&mem) << ".commit()) changed = true;\n"; | ||||
| 				} | ||||
|  | @ -2556,12 +2596,15 @@ struct CxxrtlWorker { | |||
| 							register_edge_signal(sigmap, port.clk, | ||||
| 								port.clk_polarity ? RTLIL::STp : RTLIL::STn); | ||||
| 				} | ||||
| 
 | ||||
| 				if (!mem.wr_ports.empty()) | ||||
| 					writable_memories.insert({module, mem.memid}); | ||||
| 			} | ||||
| 
 | ||||
| 			for (auto proc : module->processes) { | ||||
| 				flow.add_node(proc.second); | ||||
| 
 | ||||
| 				for (auto sync : proc.second->syncs) | ||||
| 				for (auto sync : proc.second->syncs) { | ||||
| 					switch (sync->type) { | ||||
| 						// Edge-type sync rules require pre-registration.
 | ||||
| 						case RTLIL::STp: | ||||
|  | @ -2584,6 +2627,10 @@ struct CxxrtlWorker { | |||
| 						case RTLIL::STi: | ||||
| 							log_assert(false); | ||||
| 					} | ||||
| 					for (auto &memwr : sync->mem_write_actions) { | ||||
| 						writable_memories.insert({module, memwr.memid}); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			// Construct a linear order of the flow graph that minimizes the amount of feedback arcs. A flow graph
 | ||||
|  | @ -2655,6 +2702,8 @@ struct CxxrtlWorker { | |||
| 					worklist.insert(node); // node has effects
 | ||||
| 				else if (node->type == FlowGraph::Node::Type::MEM_WRPORTS) | ||||
| 					worklist.insert(node); // node is memory write
 | ||||
| 				else if (node->type == FlowGraph::Node::Type::PROCESS_SYNC && is_memwr_process(node->process)) | ||||
| 					worklist.insert(node); // node is memory write
 | ||||
| 				else if (flow.node_sync_defs.count(node)) | ||||
| 					worklist.insert(node); // node is a flip-flop
 | ||||
| 				else if (flow.node_comb_defs.count(node)) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue