mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	flowmap: cleanup for clarity. NFCI.
This commit is contained in:
		
							parent
							
								
									fd21564deb
								
							
						
					
					
						commit
						9bc5cf0844
					
				
					 3 changed files with 185 additions and 113 deletions
				
			
		|  | @ -402,29 +402,34 @@ struct FlowGraph | ||||||
| struct FlowmapWorker | struct FlowmapWorker | ||||||
| { | { | ||||||
| 	int order; | 	int order; | ||||||
| 	pool<IdString> cell_types; |  | ||||||
| 	bool debug; | 	bool debug; | ||||||
| 
 | 
 | ||||||
| 	RTLIL::Module *module; | 	RTLIL::Module *module; | ||||||
| 	SigMap sigmap; | 	SigMap sigmap; | ||||||
| 	ModIndex index; | 	ModIndex index; | ||||||
| 	pool<RTLIL::Cell*> cells; | 
 | ||||||
|  | 	dict<RTLIL::SigBit, ModIndex::PortInfo> node_origins; | ||||||
| 
 | 
 | ||||||
| 	pool<RTLIL::SigBit> nodes, inputs, outputs; | 	pool<RTLIL::SigBit> nodes, inputs, outputs; | ||||||
| 	dict<RTLIL::SigBit, pool<RTLIL::SigBit>> edges_fw, edges_bw; | 	dict<RTLIL::SigBit, pool<RTLIL::SigBit>> edges_fw, edges_bw; | ||||||
| 	dict<RTLIL::SigBit, int> labels; | 	dict<RTLIL::SigBit, int> labels; | ||||||
| 
 | 
 | ||||||
| 	dict<RTLIL::SigBit, pool<RTLIL::SigBit>> lut_gates, lut_inputs; | 	pool<RTLIL::SigBit> lut_nodes; | ||||||
|  | 	dict<RTLIL::SigBit, pool<RTLIL::SigBit>> lut_gates; | ||||||
|  | 	dict<RTLIL::SigBit, pool<RTLIL::SigBit>> lut_edges_fw, lut_edges_bw; | ||||||
| 
 | 
 | ||||||
| 	dict<RTLIL::SigBit, ModIndex::PortInfo> node_origins; | 	int gate_count = 0, lut_count = 0, packed_count = 0; | ||||||
| 	dict<RTLIL::Cell*, pool<RTLIL::SigBit>> cell_fanout; | 	int gate_area = 0, lut_area = 0; | ||||||
| 
 | 
 | ||||||
| 	int mapped_count = 0, packed_count = 0, unique_packed_count = 0; | 	enum class GraphMode { | ||||||
|  | 		Label, | ||||||
|  | 		Cut, | ||||||
|  | 	}; | ||||||
| 
 | 
 | ||||||
| 	void dump_dot_graph(string filename, | 	void dump_dot_graph(string filename, GraphMode mode, | ||||||
| 	                    pool<RTLIL::SigBit> subgraph_nodes = {}, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> subgraph_edges = {}, | 	                    pool<RTLIL::SigBit> subgraph_nodes = {}, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> subgraph_edges = {}, | ||||||
| 	                    pair<pool<RTLIL::SigBit>, pool<RTLIL::SigBit>> cut = {}, | 	                    dict<RTLIL::SigBit, pool<RTLIL::SigBit>> collapsed = {}, | ||||||
| 	                    dict<RTLIL::SigBit, pool<RTLIL::SigBit>> collapsed = {}) | 	                    pair<pool<RTLIL::SigBit>, pool<RTLIL::SigBit>> cut = {}) | ||||||
| 	{ | 	{ | ||||||
| 		if (subgraph_nodes.empty()) | 		if (subgraph_nodes.empty()) | ||||||
| 			subgraph_nodes = nodes; | 			subgraph_nodes = nodes; | ||||||
|  | @ -436,26 +441,29 @@ struct FlowmapWorker | ||||||
| 			for (auto collapsed_node : collapsed[node]) | 			for (auto collapsed_node : collapsed[node]) | ||||||
| 				if (collapsed_node != node) | 				if (collapsed_node != node) | ||||||
| 					label += stringf(" %s", log_signal(collapsed_node)); | 					label += stringf(" %s", log_signal(collapsed_node)); | ||||||
| 			if (labels[node] == -1) | 			switch (mode) | ||||||
| 				label += "\nl=?"; |  | ||||||
| 			else |  | ||||||
| 				label += stringf("\nl=%d", labels[node]); |  | ||||||
| 			if (cut.first.empty() && cut.second.empty()) |  | ||||||
| 			{ | 			{ | ||||||
| 				if (labels[node] == -1) | 				case GraphMode::Label: | ||||||
|  | 					if (labels[node] == -1) | ||||||
|  | 					{ | ||||||
|  | 						label += "\nl=?"; | ||||||
|  | 						return GraphStyle{label}; | ||||||
|  | 					} | ||||||
|  | 					else | ||||||
|  | 					{ | ||||||
|  | 						label += stringf("\nl=%d", labels[node]); | ||||||
|  | 						string fillcolor = stringf("/set311/%d", 1 + labels[node] % 11); | ||||||
|  | 						return GraphStyle{label, "", fillcolor}; | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 				case GraphMode::Cut: | ||||||
|  | 					if (cut.first[node]) | ||||||
|  | 						return GraphStyle{label, "blue"}; | ||||||
|  | 					if (cut.second[node]) | ||||||
|  | 						return GraphStyle{label, "red"}; | ||||||
| 					return GraphStyle{label}; | 					return GraphStyle{label}; | ||||||
| 				string fillcolor = stringf("/set311/%d", 1 + labels[node] % 11); |  | ||||||
| 				return GraphStyle{label, "", fillcolor}; |  | ||||||
| 			} |  | ||||||
| 			else |  | ||||||
| 			{ |  | ||||||
| 				string color = "black"; |  | ||||||
| 				if (cut.first[node]) |  | ||||||
| 					color = "blue"; |  | ||||||
| 				if (cut.second[node]) |  | ||||||
| 					color = "red"; |  | ||||||
| 				return GraphStyle{label, color}; |  | ||||||
| 			} | 			} | ||||||
|  | 			return GraphStyle{label}; | ||||||
| 		}; | 		}; | ||||||
| 		auto edge_style = [&](RTLIL::SigBit, RTLIL::SigBit) { | 		auto edge_style = [&](RTLIL::SigBit, RTLIL::SigBit) { | ||||||
| 			return GraphStyle{}; | 			return GraphStyle{}; | ||||||
|  | @ -519,57 +527,56 @@ struct FlowmapWorker | ||||||
| 		return flow_graph; | 		return flow_graph; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	FlowmapWorker(int order, pool<IdString> cell_types, bool debug, RTLIL::Module *module) : | 	void discover_nodes(pool<IdString> cell_types) | ||||||
| 		order(order), cell_types(cell_types), debug(debug), module(module), sigmap(module), index(module) |  | ||||||
| 	{ | 	{ | ||||||
| 		log("Labeling cells.\n"); |  | ||||||
| 		for (auto cell : module->selected_cells()) | 		for (auto cell : module->selected_cells()) | ||||||
| 		{ | 		{ | ||||||
| 			if (cell_types[cell->type]) | 			if (!cell_types[cell->type]) | ||||||
|  | 				continue; | ||||||
|  | 
 | ||||||
|  | 			if (!cell->known()) | ||||||
|  | 				log_error("Cell %s (%s.%s) is unknown.\n", cell->type.c_str(), log_id(module), log_id(cell)); | ||||||
|  | 
 | ||||||
|  | 			pool<RTLIL::SigBit> fanout; | ||||||
|  | 			for (auto conn : cell->connections()) | ||||||
| 			{ | 			{ | ||||||
| 				if (!cell->known()) | 				if (!cell->output(conn.first)) continue; | ||||||
|  | 				int offset = -1; | ||||||
|  | 				for (auto bit : conn.second) | ||||||
| 				{ | 				{ | ||||||
| 					log_error("Cell %s (%s.%s) is unknown.\n", cell->type.c_str(), log_id(module), log_id(cell)); | 					offset++; | ||||||
|  | 					if (!bit.wire) continue; | ||||||
|  | 					auto mapped_bit = sigmap(bit); | ||||||
|  | 					if (nodes[mapped_bit]) | ||||||
|  | 						log_error("Multiple drivers found for wire %s.\n", log_signal(mapped_bit)); | ||||||
|  | 					nodes.insert(mapped_bit); | ||||||
|  | 					node_origins[mapped_bit] = ModIndex::PortInfo(cell, conn.first, offset); | ||||||
|  | 					fanout.insert(mapped_bit); | ||||||
| 				} | 				} | ||||||
| 				cells.insert(cell); |  | ||||||
| 
 |  | ||||||
| 				for (auto conn : cell->connections()) |  | ||||||
| 				{ |  | ||||||
| 					if (!cell->output(conn.first)) continue; |  | ||||||
| 					int offset = -1; |  | ||||||
| 					for (auto bit : conn.second) |  | ||||||
| 					{ |  | ||||||
| 						offset++; |  | ||||||
| 						if (!bit.wire) continue; |  | ||||||
| 						auto mapped_bit = sigmap(bit); |  | ||||||
| 						if (nodes[mapped_bit]) |  | ||||||
| 							log_error("Multiple drivers found for wire %s.\n", log_signal(mapped_bit)); |  | ||||||
| 						nodes.insert(mapped_bit); |  | ||||||
| 						node_origins[mapped_bit] = ModIndex::PortInfo(cell, conn.first, offset); |  | ||||||
| 						cell_fanout[cell].insert(mapped_bit); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				int fanin = 0; |  | ||||||
| 				for (auto conn : cell->connections()) |  | ||||||
| 				{ |  | ||||||
| 					if (!cell->input(conn.first)) continue; |  | ||||||
| 					for (auto bit : sigmap(conn.second)) |  | ||||||
| 					{ |  | ||||||
| 						if (!bit.wire) continue; |  | ||||||
| 						for (auto fanout_bit : cell_fanout[cell]) |  | ||||||
| 						{ |  | ||||||
| 							edges_fw[bit].insert(fanout_bit); |  | ||||||
| 							edges_bw[fanout_bit].insert(bit); |  | ||||||
| 						} |  | ||||||
| 						fanin++; |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				if (fanin > order) |  | ||||||
| 					log_error("Cell %s (%s.%s) with fan-in %d cannot be mapped to a %d-LUT.\n", |  | ||||||
| 					          cell->type.c_str(), log_id(module), log_id(cell), fanin, order); |  | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
|  | 			int fanin = 0; | ||||||
|  | 			for (auto conn : cell->connections()) | ||||||
|  | 			{ | ||||||
|  | 				if (!cell->input(conn.first)) continue; | ||||||
|  | 				for (auto bit : sigmap(conn.second)) | ||||||
|  | 				{ | ||||||
|  | 					if (!bit.wire) continue; | ||||||
|  | 					for (auto fanout_bit : fanout) | ||||||
|  | 					{ | ||||||
|  | 						edges_fw[bit].insert(fanout_bit); | ||||||
|  | 						edges_bw[fanout_bit].insert(bit); | ||||||
|  | 					} | ||||||
|  | 					fanin++; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (fanin > order) | ||||||
|  | 				log_error("Cell %s (%s.%s) with fan-in %d cannot be mapped to a %d-LUT.\n", | ||||||
|  | 				          cell->type.c_str(), log_id(module), log_id(cell), fanin, order); | ||||||
|  | 
 | ||||||
|  | 			gate_count++; | ||||||
|  | 			gate_area += 1 << fanin; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for (auto edge : edges_fw) | 		for (auto edge : edges_fw) | ||||||
|  | @ -591,15 +598,23 @@ struct FlowmapWorker | ||||||
| 					outputs.insert(node); | 					outputs.insert(node); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		if (debug) | ||||||
|  | 		{ | ||||||
|  | 			dump_dot_graph("flowmap-initial.dot", GraphMode::Label); | ||||||
|  | 			log("Dumped initial graph to `flowmap-initial.dot`.\n"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void label_nodes() | ||||||
|  | 	{ | ||||||
| 		for (auto node : nodes) | 		for (auto node : nodes) | ||||||
| 			labels[node] = -1; | 			labels[node] = -1; | ||||||
| 		for (auto input : inputs) | 		for (auto input : inputs) | ||||||
| 			labels[input] = 0; |  | ||||||
| 
 |  | ||||||
| 		if (debug) |  | ||||||
| 		{ | 		{ | ||||||
| 			dump_dot_graph("flowmap-initial.dot"); | 			if (input.wire->attributes.count("\\$flowmap_level")) | ||||||
| 			log("Dumped complete initial graph to `flowmap-initial.dot`.\n"); | 				labels[input] = input.wire->attributes["\\$flowmap_level"].as_int(); | ||||||
|  | 			else | ||||||
|  | 				labels[input] = 0; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		pool<RTLIL::SigBit> worklist = nodes; | 		pool<RTLIL::SigBit> worklist = nodes; | ||||||
|  | @ -661,70 +676,73 @@ struct FlowmapWorker | ||||||
| 						k.insert(xi_node_pred); | 						k.insert(xi_node_pred); | ||||||
| 			} | 			} | ||||||
| 			log_assert((int)k.size() <= order); | 			log_assert((int)k.size() <= order); | ||||||
| 			lut_inputs[sink] = k; | 			lut_edges_bw[sink] = k; | ||||||
|  | 			for (auto k_node : k) | ||||||
|  | 				lut_edges_fw[k_node].insert(sink); | ||||||
| 
 | 
 | ||||||
| 			if (debug) | 			if (debug) | ||||||
| 			{ | 			{ | ||||||
| 				log("  Maximum flow: %d. Assigned label %d.\n", flow, labels[sink]); | 				log("  Maximum flow: %d. Assigned label %d.\n", flow, labels[sink]); | ||||||
| 				dump_dot_graph(stringf("flowmap-%d-sub.dot", debug_num), subgraph, {}, {x, xi}); | 				dump_dot_graph(stringf("flowmap-%d-sub.dot", debug_num), GraphMode::Cut, subgraph, {}, {}, {x, xi}); | ||||||
| 				log("  Dumped subgraph to `flowmap-%d-sub.dot`.\n", debug_num); | 				log("  Dumped subgraph to `flowmap-%d-sub.dot`.\n", debug_num); | ||||||
| 				flow_graph.dump_dot_graph(stringf("flowmap-%d-flow.dot", debug_num)); | 				flow_graph.dump_dot_graph(stringf("flowmap-%d-flow.dot", debug_num)); | ||||||
| 				log("  Dumped flow graph to `flowmap-%d-flow.dot`.\n", debug_num); | 				log("  Dumped flow graph to `flowmap-%d-flow.dot`.\n", debug_num); | ||||||
| 				log("    LUT packed:"); |  | ||||||
| 				for (auto xi_node : xi) |  | ||||||
| 					log(" %s", log_signal(xi_node)); |  | ||||||
| 				log(".\n"); |  | ||||||
| 				log("    LUT inputs:"); | 				log("    LUT inputs:"); | ||||||
| 				for (auto k_node : k) | 				for (auto k_node : k) | ||||||
| 					log(" %s", log_signal(k_node)); | 					log(" %s", log_signal(k_node)); | ||||||
| 				log(".\n"); | 				log(".\n"); | ||||||
|  | 				log("    LUT packed gates:"); | ||||||
|  | 				for (auto xi_node : xi) | ||||||
|  | 					log(" %s", log_signal(xi_node)); | ||||||
|  | 				log(".\n"); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			for (auto sink_succ : edges_fw[sink]) | 			for (auto sink_succ : edges_fw[sink]) | ||||||
| 				worklist.insert(sink_succ); | 				worklist.insert(sink_succ); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		int depth = 0; |  | ||||||
| 		for (auto label : labels) |  | ||||||
| 			depth = max(depth, label.second); |  | ||||||
| 		log("Maximum depth: %d levels.\n", depth); |  | ||||||
| 
 |  | ||||||
| 		if (debug) | 		if (debug) | ||||||
| 		{ | 		{ | ||||||
| 			dump_dot_graph("flowmap-labeled.dot"); | 			dump_dot_graph("flowmap-labeled.dot", GraphMode::Label); | ||||||
| 			log("Dumped complete labeled graph to `flowmap-labeled.dot`.\n"); | 			log("Dumped labeled graph to `flowmap-labeled.dot`.\n"); | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 		pool<RTLIL::SigBit> lut_nodes; | 	int pack_luts() | ||||||
| 		dict<RTLIL::SigBit, pool<RTLIL::SigBit>> lut_edges; | 	{ | ||||||
| 		worklist = outputs; | 		pool<RTLIL::SigBit> worklist = outputs; | ||||||
| 		while (!worklist.empty()) | 		while (!worklist.empty()) | ||||||
| 		{ | 		{ | ||||||
| 			auto lut_node = worklist.pop(); | 			auto lut_node = worklist.pop(); | ||||||
| 			lut_nodes.insert(lut_node); | 			lut_nodes.insert(lut_node); | ||||||
| 			for (auto input_node : lut_inputs[lut_node]) | 			for (auto input_node : lut_edges_bw[lut_node]) | ||||||
| 			{ |  | ||||||
| 				lut_edges[input_node].insert(lut_node); |  | ||||||
| 				if (!lut_nodes[input_node] && !inputs[input_node]) | 				if (!lut_nodes[input_node] && !inputs[input_node]) | ||||||
| 					worklist.insert(input_node); | 					worklist.insert(input_node); | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		int depth = 0; | ||||||
|  | 		for (auto label : labels) | ||||||
|  | 			depth = max(depth, label.second); | ||||||
|  | 		log("Solved to %d LUTs in %d levels.\n", (int)lut_nodes.size(), depth); | ||||||
|  | 
 | ||||||
| 		if (debug) | 		if (debug) | ||||||
| 		{ | 		{ | ||||||
| 			pool<RTLIL::SigBit> lut_and_input_nodes = lut_nodes; | 			pool<RTLIL::SigBit> lut_and_input_nodes; | ||||||
|  | 			lut_and_input_nodes.insert(lut_nodes.begin(), lut_nodes.end()); | ||||||
| 			lut_and_input_nodes.insert(inputs.begin(), inputs.end()); | 			lut_and_input_nodes.insert(inputs.begin(), inputs.end()); | ||||||
| 			dump_dot_graph("flowmap-packed.dot", lut_and_input_nodes, lut_edges, {}, lut_gates); | 			dump_dot_graph("flowmap-packed.dot", GraphMode::Label, lut_and_input_nodes, lut_edges_fw, lut_gates); | ||||||
| 			log("Dumped complete packed graph to `flowmap-packed.dot`.\n"); | 			log("Dumped packed graph to `flowmap-packed.dot`.\n"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		return depth; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void map_cells() | ||||||
|  | 	{ | ||||||
| 		ConstEval ce(module); | 		ConstEval ce(module); | ||||||
| 		for (auto input_node : inputs) | 		for (auto input_node : inputs) | ||||||
| 			ce.stop(input_node); | 			ce.stop(input_node); | ||||||
| 
 | 
 | ||||||
| 		log("\n"); |  | ||||||
| 		log("Mapping cells.\n"); |  | ||||||
| 
 |  | ||||||
| 		pool<RTLIL::SigBit> mapped_nodes; | 		pool<RTLIL::SigBit> mapped_nodes; | ||||||
| 		for (auto node : lut_nodes) | 		for (auto node : lut_nodes) | ||||||
| 		{ | 		{ | ||||||
|  | @ -759,7 +777,7 @@ struct FlowmapWorker | ||||||
| 					    log_id(module), log_id(gate_origin.cell), gate_origin.port.c_str(), gate_origin.offset, log_signal(gate_node)); | 					    log_id(module), log_id(gate_origin.cell), gate_origin.port.c_str(), gate_origin.offset, log_signal(gate_node)); | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			vector<RTLIL::SigBit> input_nodes(lut_inputs[node].begin(), lut_inputs[node].end()); | 			vector<RTLIL::SigBit> input_nodes(lut_edges_bw[node].begin(), lut_edges_bw[node].end()); | ||||||
| 			RTLIL::Const lut_table(State::Sx, 1 << input_nodes.size()); | 			RTLIL::Const lut_table(State::Sx, 1 << input_nodes.size()); | ||||||
| 			for (unsigned i = 0; i < (1 << input_nodes.size()); i++) | 			for (unsigned i = 0; i < (1 << input_nodes.size()); i++) | ||||||
| 			{ | 			{ | ||||||
|  | @ -786,7 +804,6 @@ struct FlowmapWorker | ||||||
| 				lut_a.append_bit(input_node); | 				lut_a.append_bit(input_node); | ||||||
| 
 | 
 | ||||||
| 			RTLIL::Cell *lut = module->addLut(NEW_ID, lut_a, lut_y, lut_table); | 			RTLIL::Cell *lut = module->addLut(NEW_ID, lut_a, lut_y, lut_table); | ||||||
| 			mapped_count++; |  | ||||||
| 			mapped_nodes.insert(node); | 			mapped_nodes.insert(node); | ||||||
| 			for (auto gate_node : lut_gates[node]) | 			for (auto gate_node : lut_gates[node]) | ||||||
| 			{ | 			{ | ||||||
|  | @ -794,11 +811,11 @@ struct FlowmapWorker | ||||||
| 				lut->add_strpool_attribute("\\src", gate_origin.cell->get_strpool_attribute("\\src")); | 				lut->add_strpool_attribute("\\src", gate_origin.cell->get_strpool_attribute("\\src")); | ||||||
| 				packed_count++; | 				packed_count++; | ||||||
| 			} | 			} | ||||||
|  | 			lut_count++; | ||||||
|  | 			lut_area += 1 << input_nodes.size(); | ||||||
| 			log("  Packed into a %d-LUT %s.%s.\n", (int)input_nodes.size(), log_id(module), log_id(lut)); | 			log("  Packed into a %d-LUT %s.%s.\n", (int)input_nodes.size(), log_id(module), log_id(lut)); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		unique_packed_count += nodes.size(); |  | ||||||
| 
 |  | ||||||
| 		for (auto node : mapped_nodes) | 		for (auto node : mapped_nodes) | ||||||
| 		{ | 		{ | ||||||
| 			auto origin = node_origins[node]; | 			auto origin = node_origins[node]; | ||||||
|  | @ -807,6 +824,19 @@ struct FlowmapWorker | ||||||
| 			origin.cell->setPort(origin.port, driver); | 			origin.cell->setPort(origin.port, driver); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	FlowmapWorker(int order, pool<IdString> cell_types, bool debug, RTLIL::Module *module) : | ||||||
|  | 		order(order), debug(debug), module(module), sigmap(module), index(module) | ||||||
|  | 	{ | ||||||
|  | 		log("Labeling cells.\n"); | ||||||
|  | 		discover_nodes(cell_types); | ||||||
|  | 		label_nodes(); | ||||||
|  | 		pack_luts(); | ||||||
|  | 
 | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("Mapping cells.\n"); | ||||||
|  | 		map_cells(); | ||||||
|  | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static void split(std::vector<std::string> &tokens, const std::string &text, char sep) | static void split(std::vector<std::string> &tokens, const std::string &text, char sep) | ||||||
|  | @ -832,7 +862,7 @@ struct FlowmapPass : public Pass { | ||||||
| 		log("be evaluated with the `eval` pass, including cells with multiple output ports\n"); | 		log("be evaluated with the `eval` pass, including cells with multiple output ports\n"); | ||||||
| 		log("and multi-bit input and output ports.\n"); | 		log("and multi-bit input and output ports.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -maxlut <k>\n"); | 		log("    -maxlut k\n"); | ||||||
| 		log("        perform technology mapping for a k-LUT architecture. if not specified,\n"); | 		log("        perform technology mapping for a k-LUT architecture. if not specified,\n"); | ||||||
| 		log("        defaults to 3.\n"); | 		log("        defaults to 3.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | @ -846,8 +876,6 @@ struct FlowmapPass : public Pass { | ||||||
| 	} | 	} | ||||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
| 		log_header(design, "Executing FLOWMAP pass (pack LUTs with FlowMap).\n"); |  | ||||||
| 
 |  | ||||||
| 		int order = 3; | 		int order = 3; | ||||||
| 		vector<string> cells; | 		vector<string> cells; | ||||||
| 		bool debug = false; | 		bool debug = false; | ||||||
|  | @ -885,18 +913,24 @@ struct FlowmapPass : public Pass { | ||||||
| 			cell_types = {"$_NOT_", "$_AND_", "$_OR_", "$_XOR_", "$_MUX_"}; | 			cell_types = {"$_NOT_", "$_AND_", "$_OR_", "$_XOR_", "$_MUX_"}; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		int mapped_count = 0, packed_count = 0, unique_packed_count = 0; | 		log_header(design, "Executing FLOWMAP pass (pack LUTs with FlowMap).\n"); | ||||||
|  | 
 | ||||||
|  | 		int gate_count = 0, lut_count = 0, packed_count = 0; | ||||||
|  | 		int gate_area = 0, lut_area = 0; | ||||||
| 		for (auto module : design->selected_modules()) | 		for (auto module : design->selected_modules()) | ||||||
| 		{ | 		{ | ||||||
| 			FlowmapWorker worker(order, cell_types, debug, module); | 			FlowmapWorker worker(order, cell_types, debug, module); | ||||||
| 			mapped_count += worker.mapped_count; | 			gate_count += worker.gate_count; | ||||||
|  | 			lut_count += worker.lut_count; | ||||||
| 			packed_count += worker.packed_count; | 			packed_count += worker.packed_count; | ||||||
| 			unique_packed_count += worker.unique_packed_count; | 			gate_area += worker.gate_area; | ||||||
|  | 			lut_area += worker.lut_area; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("Mapped %d LUTs.\n", mapped_count); | 		log("Mapped %d LUTs.\n", lut_count); | ||||||
| 		log("Packed %d cells %d times.\n", unique_packed_count, packed_count); | 		log("Packed %d cells; duplicated %d cells.\n", packed_count, packed_count - gate_count); | ||||||
|  | 		log("Solution has %.1f%% area overhead.\n", (lut_area - gate_area) * 100.0 / gate_area); | ||||||
| 	} | 	} | ||||||
| } FlowmapPass; | } FlowmapPass; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								passes/tests/flowmap/flow.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								passes/tests/flowmap/flow.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | // Exact reproduction of Figure 2(a) from 10.1109/43.273754. | ||||||
|  | module top(...); | ||||||
|  | 	input a,b,c,d,e,f; | ||||||
|  | 	wire nA = b&c; | ||||||
|  | 	wire A = !nA; | ||||||
|  | 	wire nB = c|d; | ||||||
|  | 	wire B = !nB; | ||||||
|  | 	wire nC = e&f; | ||||||
|  | 	wire C = !nC; | ||||||
|  | 	wire D = A|B; | ||||||
|  | 	wire E = a&D; | ||||||
|  | 	wire nF = D&C; | ||||||
|  | 	wire F = !nF; | ||||||
|  | 	wire nG = F|B; | ||||||
|  | 	wire G = !nG; | ||||||
|  | 	wire H = a&F; | ||||||
|  | 	wire I = E|G; | ||||||
|  | 	wire J = G&C; | ||||||
|  | 	wire np = H&I; | ||||||
|  | 	output p = !np; | ||||||
|  | 	output q = A|J; | ||||||
|  | endmodule | ||||||
							
								
								
									
										16
									
								
								passes/tests/flowmap/flowp.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								passes/tests/flowmap/flowp.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | // Like flow.v, but results in a network identical to Figure 2(b). | ||||||
|  | module top(...); | ||||||
|  | 	input a,b,c,d,e,f; | ||||||
|  | 	wire A = b&c; | ||||||
|  | 	wire B = c|d; | ||||||
|  | 	wire C = e&f; | ||||||
|  | 	wire D = A|B; | ||||||
|  | 	wire E = a&D; | ||||||
|  | 	wire F = D&C; | ||||||
|  | 	wire G = F|B; | ||||||
|  | 	wire H = a&F; | ||||||
|  | 	wire I = E|G; | ||||||
|  | 	wire J = G&C; | ||||||
|  | 	output p = H&I; | ||||||
|  | 	output q = A|J; | ||||||
|  | endmodule | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue