mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-30 19:22:31 +00:00 
			
		
		
		
	Improve simplec back-end
This commit is contained in:
		
							parent
							
								
									7931e1ebb4
								
							
						
					
					
						commit
						ef7594ce3d
					
				
					 3 changed files with 79 additions and 13 deletions
				
			
		|  | @ -19,6 +19,7 @@ | |||
| 
 | ||||
| #include "kernel/yosys.h" | ||||
| #include "kernel/sigtools.h" | ||||
| #include "kernel/utils.h" | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
|  | @ -134,6 +135,8 @@ struct SimplecWorker | |||
| 	dict<Module*, dict<SigBit, pool<tuple<Cell*, IdString, int>>>> bit2cell; | ||||
| 	dict<Module*, dict<SigBit, pool<SigBit>>> bit2output; | ||||
| 
 | ||||
| 	dict<Cell*, int> topoidx; | ||||
| 
 | ||||
| 	SimplecWorker(Design *design) : design(design) | ||||
| 	{ | ||||
| 	} | ||||
|  | @ -290,11 +293,49 @@ struct SimplecWorker | |||
| 				create_module_struct(design->module(c->type)); | ||||
| 		} | ||||
| 
 | ||||
| 		struct_declarations.push_back(""); | ||||
| 		struct_declarations.push_back(stringf("struct %s_state_t {", cid(mod->name).c_str())); | ||||
| 		TopoSort<IdString> topo; | ||||
| 
 | ||||
| 		for (Cell *c : mod->cells()) | ||||
| 		{ | ||||
| 			topo.node(c->name); | ||||
| 
 | ||||
| 			for (auto &conn : c->connections()) | ||||
| 			{ | ||||
| 				if (!c->input(conn.first)) | ||||
| 					continue; | ||||
| 
 | ||||
| 				for (auto bit : sigmaps.at(mod)(conn.second)) | ||||
| 				for (auto &it : bit2cell[mod][bit]) | ||||
| 					topo.edge(c->name, std::get<0>(it)->name); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		topo.analyze_loops = false; | ||||
| 		topo.sort(); | ||||
| 
 | ||||
| 		for (int i = 0; i < GetSize(topo.sorted); i++) | ||||
| 			topoidx[mod->cell(topo.sorted[i])] = i; | ||||
| 
 | ||||
| 		struct_declarations.push_back(""); | ||||
| 		struct_declarations.push_back(stringf("struct %s_state_t", cid(mod->name).c_str())); | ||||
| 		struct_declarations.push_back("{"); | ||||
| 
 | ||||
| 		struct_declarations.push_back("  // Input Ports"); | ||||
| 		for (Wire *w : mod->wires()) | ||||
| 			struct_declarations.push_back(stringf("  %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w))); | ||||
| 			if (w->port_input) | ||||
| 				struct_declarations.push_back(stringf("  %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w))); | ||||
| 
 | ||||
| 		struct_declarations.push_back(""); | ||||
| 		struct_declarations.push_back("  // Output Ports"); | ||||
| 		for (Wire *w : mod->wires()) | ||||
| 			if (!w->port_input && w->port_output) | ||||
| 				struct_declarations.push_back(stringf("  %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w))); | ||||
| 
 | ||||
| 		struct_declarations.push_back(""); | ||||
| 		struct_declarations.push_back("  // Internal Wires"); | ||||
| 		for (Wire *w : mod->wires()) | ||||
| 			if (!w->port_input && !w->port_output) | ||||
| 				struct_declarations.push_back(stringf("  %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w))); | ||||
| 
 | ||||
| 		for (Cell *c : mod->cells()) | ||||
| 			if (design->module(c->type)) | ||||
|  | @ -303,7 +344,7 @@ struct SimplecWorker | |||
| 		struct_declarations.push_back(stringf("};")); | ||||
| 	} | ||||
| 
 | ||||
| 	void eval_cell(HierDirtyFlags *work, string &prefix, string &/* log_prefix */, Cell *cell) | ||||
| 	void eval_cell(HierDirtyFlags *work, const string &prefix, const string &/* log_prefix */, Cell *cell) | ||||
| 	{ | ||||
| 		if (cell->type.in("$_BUF_", "$_NOT_")) | ||||
| 		{ | ||||
|  | @ -420,10 +461,13 @@ struct SimplecWorker | |||
| 		log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type)); | ||||
| 	} | ||||
| 
 | ||||
| 	void eval_dirty(HierDirtyFlags *work, string prefix, string log_prefix, string parent_prefix) | ||||
| 	void eval_dirty(HierDirtyFlags *work, const string &prefix, const string &log_prefix, const string &parent_prefix, const string &parent_log_prefix) | ||||
| 	{ | ||||
| 		while (work->dirty) | ||||
| 		{ | ||||
| 			if (verbose && (!work->dirty_bits.empty() || !work->dirty_cells.empty())) | ||||
| 				log("In %s:\n", log_prefix.c_str()); | ||||
| 
 | ||||
| 			while (!work->dirty_bits.empty() || !work->dirty_cells.empty()) | ||||
| 			{ | ||||
| 				if (!work->dirty_bits.empty()) | ||||
|  | @ -431,8 +475,11 @@ struct SimplecWorker | |||
| 					SigSpec dirtysig(work->dirty_bits); | ||||
| 					dirtysig.sort_and_unify(); | ||||
| 
 | ||||
| 					for (SigChunk chunk : dirtysig.chunks()) | ||||
| 						funct_declarations.push_back(stringf("  // New dirty bits in %s: %s", log_prefix.c_str(), log_signal(chunk))); | ||||
| 					for (SigChunk chunk : dirtysig.chunks()) { | ||||
| 						if (verbose) | ||||
| 							log("  Propagating %s.%s[%d:%d].\n", log_prefix.c_str(), log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset); | ||||
| 						funct_declarations.push_back(stringf("  // Updated signal in %s: %s", log_prefix.c_str(), log_signal(chunk))); | ||||
| 					} | ||||
| 
 | ||||
| 					for (SigBit bit : dirtysig) | ||||
| 					{ | ||||
|  | @ -453,21 +500,34 @@ struct SimplecWorker | |||
| 										util_get_bit(bit.wire->width, bit.offset).c_str(), | ||||
| 										(prefix + cid(bit.wire->name)).c_str())); | ||||
| 								work->parent->set_dirty(parent_bit); | ||||
| 
 | ||||
| 								if (verbose) | ||||
| 									log("    Propagating %s.%s[%d] -> %s.%s[%d].\n", log_prefix.c_str(), log_id(bit.wire), bit.offset, | ||||
| 											parent_log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset); | ||||
| 							} | ||||
| 
 | ||||
| 						for (auto &port : bit2cell[work->module][bit]) | ||||
| 						{ | ||||
| 							if (work->children.count(std::get<0>(port)->name)) { | ||||
| 							if (work->children.count(std::get<0>(port)->name)) | ||||
| 							{ | ||||
| 								HierDirtyFlags *child = work->children.at(std::get<0>(port)->name); | ||||
| 								SigBit child_bit = sigmaps.at(child->module)(SigBit(child->module->wire(std::get<1>(port)), std::get<2>(port))); | ||||
| 								log_assert(bit.wire && child_bit.wire); | ||||
| 
 | ||||
| 								funct_declarations.push_back(stringf("  %s(&%s, %s(&%s));", | ||||
| 										util_set_bit(child_bit.wire->width, child_bit.offset).c_str(), | ||||
| 										(prefix + cid(child->hiername) + "." + cid(child_bit.wire->name)).c_str(), | ||||
| 										util_get_bit(bit.wire->width, bit.offset).c_str(), | ||||
| 										(prefix + cid(bit.wire->name)).c_str())); | ||||
| 								child->set_dirty(child_bit); | ||||
| 
 | ||||
| 								if (verbose) | ||||
| 									log("    Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", log_prefix.c_str(), log_id(bit.wire), bit.offset, | ||||
| 											log_prefix.c_str(), log_id(std::get<0>(port)), log_id(child_bit.wire), child_bit.offset); | ||||
| 							} else { | ||||
| 								if (verbose) | ||||
| 									log("    Marking cell %s.%s (via %s.%s[%d]).\n", log_prefix.c_str(), log_id(std::get<0>(port)), | ||||
| 											log_prefix.c_str(), log_id(bit.wire), bit.offset); | ||||
| 								work->set_dirty(std::get<0>(port)); | ||||
| 							} | ||||
| 						} | ||||
|  | @ -477,14 +537,20 @@ struct SimplecWorker | |||
| 
 | ||||
| 				if (!work->dirty_cells.empty()) | ||||
| 				{ | ||||
| 					Cell *cell = *work->dirty_cells.begin(); | ||||
| 					Cell *cell = nullptr; | ||||
| 					for (auto c : work->dirty_cells) | ||||
| 						if (cell == nullptr || topoidx.at(cell) < topoidx.at(c)) | ||||
| 							cell = c; | ||||
| 
 | ||||
| 					if (verbose) | ||||
| 						log("  Evaluating %s.%s (%s, best of %d).\n", log_prefix.c_str(), log_id(cell), log_id(cell->type), GetSize(work->dirty_cells)); | ||||
| 					eval_cell(work, prefix, log_prefix, cell); | ||||
| 					work->unset_dirty(cell); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			for (auto &child : work->children) | ||||
| 				eval_dirty(child.second, prefix + cid(child.first) + ".", log_prefix + "." + cid(child.first), prefix); | ||||
| 				eval_dirty(child.second, prefix + cid(child.first) + ".", log_prefix + "." + cid(child.first), prefix, log_prefix); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -509,7 +575,7 @@ struct SimplecWorker | |||
| 					dirty_flags->set_dirty(bit); | ||||
| 		} | ||||
| 
 | ||||
| 		eval_dirty(dirty_flags, "state->", log_id(mod), ""); | ||||
| 		eval_dirty(dirty_flags, "state->", log_id(mod), "", ""); | ||||
| 
 | ||||
| 		funct_declarations.push_back("}"); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| #!/bin/bash | ||||
| set -ex | ||||
| ../../yosys -p 'synth -top test; write_simplec -i8 test00_uut.c' test00_uut.v | ||||
| ../../yosys -p 'synth -top test; write_simplec -verbose -i8 test00_uut.c' test00_uut.v | ||||
| clang -o test00_tb test00_tb.c | ||||
| ./test00_tb | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ int main() | |||
| 	struct test_state_t state; | ||||
| 	uint32_t a, b, c, x, y, z; | ||||
| 
 | ||||
| 	for (int i = 0; i < 100; i++) | ||||
| 	for (int i = 0; i < 10; i++) | ||||
| 	{ | ||||
| 		a = xorshift32(); | ||||
| 		b = xorshift32(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue