mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			261 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			261 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "subcircuit.h"
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| 
 | |
| std::vector<std::string> readLine()
 | |
| {
 | |
| 	char buffer[4096];
 | |
| 	std::vector<std::string> tokenList;
 | |
| 
 | |
| 	while (tokenList.size() == 0 && fgets(buffer, sizeof(buffer), stdin) != NULL) {
 | |
| 		for (char *p = buffer; char *tok = strtok(p, " \t\r\n"); p = NULL) {
 | |
| 			if (p != NULL && tok[0] == '#')
 | |
| 				break;
 | |
| 			tokenList.push_back(tok);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return tokenList;
 | |
| }
 | |
| 
 | |
| int main()
 | |
| {
 | |
| 	std::string graphId;
 | |
| 	SubCircuit::Graph *graph = NULL;
 | |
| 	SubCircuit::Solver solver;
 | |
| 	std::map<std::string, std::set<std::string>> initialMappings;
 | |
| 	std::vector<SubCircuit::Solver::Result> results;
 | |
| 	std::vector<SubCircuit::Solver::MineResult> mineResults;
 | |
| 	std::vector<std::string> cmdBuffer;
 | |
| 	bool lastCommandExpect = false;
 | |
| 
 | |
| 	while (1)
 | |
| 	{
 | |
| 		cmdBuffer = readLine();
 | |
| 		if (cmdBuffer.empty())
 | |
| 			break;
 | |
| 
 | |
| 		printf(graph == NULL || cmdBuffer[0] == "endgraph" ? ">" : ">  ");
 | |
| 		for (const auto &tok : cmdBuffer)
 | |
| 			printf(" %s", tok.c_str());
 | |
| 		printf("\n");
 | |
| 
 | |
| 		lastCommandExpect = false;
 | |
| 
 | |
| 		if (graph != NULL)
 | |
| 		{
 | |
| 			if (cmdBuffer[0] == "node" && cmdBuffer.size() >= 3) {
 | |
| 				graph->createNode(cmdBuffer[1], cmdBuffer[2]);
 | |
| 				for (int i = 3; i < int(cmdBuffer.size()); i++) {
 | |
| 					std::string portId = cmdBuffer[i];
 | |
| 					int width = 1, minWidth = -1;
 | |
| 					if (i+1 < int(cmdBuffer.size()) && '0' <= cmdBuffer[i+1][0] && cmdBuffer[i+1][0] <= '9')
 | |
| 						width = atoi(cmdBuffer[++i].c_str());
 | |
| 					if (i+1 < int(cmdBuffer.size()) && '0' <= cmdBuffer[i+1][0] && cmdBuffer[i+1][0] <= '9')
 | |
| 						minWidth = atoi(cmdBuffer[++i].c_str());
 | |
| 					graph->createPort(cmdBuffer[1], portId, width, minWidth);
 | |
| 				}
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "connect" && cmdBuffer.size() == 5) {
 | |
| 				graph->createConnection(cmdBuffer[1], cmdBuffer[2], cmdBuffer[3], cmdBuffer[4]);
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "connect" && cmdBuffer.size() == 7) {
 | |
| 				graph->createConnection(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str()), cmdBuffer[4], cmdBuffer[5], atoi(cmdBuffer[6].c_str()));
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "connect" && cmdBuffer.size() == 8) {
 | |
| 				graph->createConnection(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str()), cmdBuffer[4], cmdBuffer[5], atoi(cmdBuffer[6].c_str()), atoi(cmdBuffer[7].c_str()));
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "constant" && cmdBuffer.size() == 5) {
 | |
| 				int constValue = cmdBuffer[4].size() > 1 && cmdBuffer[4][0] == '#' ? atoi(cmdBuffer[4].c_str()+1) : cmdBuffer[4][0];
 | |
| 				graph->createConstant(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str()), constValue);
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "constant" && cmdBuffer.size() == 4) {
 | |
| 				graph->createConstant(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str()));
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "extern" && cmdBuffer.size() >= 3) {
 | |
| 				for (int i = 2; i < int(cmdBuffer.size()); i++) {
 | |
| 					std::string portId = cmdBuffer[i];
 | |
| 					int bit = -1;
 | |
| 					if (i+1 < int(cmdBuffer.size()) && '0' <= cmdBuffer[i+1][0] && cmdBuffer[i+1][0] <= '9')
 | |
| 						bit = atoi(cmdBuffer[++i].c_str());
 | |
| 					graph->markExtern(cmdBuffer[1], portId, bit);
 | |
| 				}
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "allextern" && cmdBuffer.size() == 1) {
 | |
| 				graph->markAllExtern();
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "endgraph" && cmdBuffer.size() == 1) {
 | |
| 				solver.addGraph(graphId, *graph);
 | |
| 				delete graph;
 | |
| 				graph = NULL;
 | |
| 				continue;
 | |
| 			}
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			if (cmdBuffer[0] == "graph" && cmdBuffer.size() == 2) {
 | |
| 				graph = new SubCircuit::Graph;
 | |
| 				graphId = cmdBuffer[1];
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "compatible" && cmdBuffer.size() == 3) {
 | |
| 				solver.addCompatibleTypes(cmdBuffer[1], cmdBuffer[2]);
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "constcompat" && cmdBuffer.size() == 3) {
 | |
| 				int needleConstValue = cmdBuffer[1].size() > 1 && cmdBuffer[1][0] == '#' ? atoi(cmdBuffer[1].c_str()+1) : cmdBuffer[1][0];
 | |
| 				int haystackConstValue = cmdBuffer[2].size() > 1 && cmdBuffer[2][0] == '#' ? atoi(cmdBuffer[2].c_str()+1) : cmdBuffer[2][0];
 | |
| 				solver.addCompatibleConstants(needleConstValue, haystackConstValue);
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "swapgroup" && cmdBuffer.size() >= 4) {
 | |
| 				std::set<std::string> ports;
 | |
| 				for (int i = 2; i < int(cmdBuffer.size()); i++)
 | |
| 					ports.insert(cmdBuffer[i]);
 | |
| 				solver.addSwappablePorts(cmdBuffer[1], ports);
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "swapperm" && cmdBuffer.size() >= 4 && cmdBuffer.size() % 2 == 1 && cmdBuffer[cmdBuffer.size()/2 + 1] == ":") {
 | |
| 				std::map<std::string, std::string> portMapping;
 | |
| 				int n = (cmdBuffer.size()-3) / 2;
 | |
| 				for (int i = 0; i < n; i++)
 | |
| 					portMapping[cmdBuffer[i+2]] = cmdBuffer[i+3+n];
 | |
| 				solver.addSwappablePortsPermutation(cmdBuffer[1], portMapping);
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "initmap" && cmdBuffer.size() >= 4) {
 | |
| 				for (int i = 2; i < int(cmdBuffer.size()); i++)
 | |
| 					initialMappings[cmdBuffer[1]].insert(cmdBuffer[i]);
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "solve" && 3 <= cmdBuffer.size() && cmdBuffer.size() <= 5) {
 | |
| 				bool allowOverlap = true;
 | |
| 				int maxSolutions = -1;
 | |
| 				if (cmdBuffer.size() >= 4)
 | |
| 					allowOverlap = cmdBuffer[3] == "true" || atoi(cmdBuffer[3].c_str()) ? true : false;
 | |
| 				if (cmdBuffer.size() >= 5)
 | |
| 					maxSolutions = atoi(cmdBuffer[4].c_str());
 | |
| 				solver.solve(results, cmdBuffer[1], cmdBuffer[2], initialMappings, allowOverlap, maxSolutions);
 | |
| 				initialMappings.clear();
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "mine" && 4 <= cmdBuffer.size() && cmdBuffer.size() <= 5) {
 | |
| 				solver.mine(mineResults, atoi(cmdBuffer[1].c_str()), atoi(cmdBuffer[2].c_str()),
 | |
| 						atoi(cmdBuffer[3].c_str()), cmdBuffer.size() == 5 ? atoi(cmdBuffer[4].c_str()) : -1);
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "clearoverlap" && cmdBuffer.size() == 1) {
 | |
| 				solver.clearOverlapHistory();
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "clearconfig" && cmdBuffer.size() == 1) {
 | |
| 				solver.clearConfig();
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "verbose" && cmdBuffer.size() == 1) {
 | |
| 				solver.setVerbose();
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if (cmdBuffer[0] == "expect" && cmdBuffer.size() == 2) {
 | |
| 				int expected = atoi(cmdBuffer[1].c_str());
 | |
| 				printf("\n-- Expected %d, Got %d --\n", expected, int(results.size()) + int(mineResults.size()));
 | |
| 				for (int i = 0; i < int(results.size()); i++) {
 | |
| 					printf("\nMatch #%d: (%s in %s)\n", i, results[i].needleGraphId.c_str(), results[i].haystackGraphId.c_str());
 | |
| 					for (const auto &it : results[i].mappings) {
 | |
| 						printf("  %s -> %s", it.first.c_str(), it.second.haystackNodeId.c_str());
 | |
| 						for (const auto &it2 : it.second.portMapping)
 | |
| 							printf(" %s:%s", it2.first.c_str(), it2.second.c_str());
 | |
| 						printf("\n");
 | |
| 					}
 | |
| 				}
 | |
| 				for (auto &result : mineResults) {
 | |
| 					printf("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits);
 | |
| 					printf("  primary match in %s:", result.graphId.c_str());
 | |
| 					for (auto &node : result.nodes)
 | |
| 						printf(" %s", node.nodeId.c_str());
 | |
| 					printf("\n");
 | |
| 					for (auto &it : result.matchesPerGraph)
 | |
| 						printf("  matches in %s: %d\n", it.first.c_str(), it.second);
 | |
| 				}
 | |
| 				printf("\n");
 | |
| 				if (expected != int(results.size()) + int(mineResults.size())) {
 | |
| 					printf("^^ expected %d, Got %d ^^\n\n", expected, int(results.size()) + int(mineResults.size()));
 | |
| 					printf("   +----------------+\n");
 | |
| 					printf("   |  \\|/ ____ \\|/  |\n");
 | |
| 					printf("   |  \"@'/ ,. \\`@\"  |\n");
 | |
| 					printf("   |  /_| \\__/ |_\\  |\n");
 | |
| 					printf("   |     \\__U_/     |\n");
 | |
| 					printf("   |      |  |      |\n");
 | |
| 					printf("   +----------------+\n\n");
 | |
| 					return 1;
 | |
| 				}
 | |
| 				results.clear();
 | |
| 				mineResults.clear();
 | |
| 				lastCommandExpect = true;
 | |
| 				continue;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		printf("Invalid input command!\n");
 | |
| 		return 1;
 | |
| 	}
 | |
| 
 | |
| 	if (graph)
 | |
| 		delete graph;
 | |
| 
 | |
| 	if (!lastCommandExpect) {
 | |
| 		printf("\n-- Got %d --\n", int(results.size()) + int(mineResults.size()));
 | |
| 		for (int i = 0; i < int(results.size()); i++) {
 | |
| 			printf("\nMatch #%d: (%s in %s)\n", i, results[i].needleGraphId.c_str(), results[i].haystackGraphId.c_str());
 | |
| 			for (const auto &it : results[i].mappings) {
 | |
| 				printf("  %s -> %s", it.first.c_str(), it.second.haystackNodeId.c_str());
 | |
| 				for (const auto &it2 : it.second.portMapping)
 | |
| 					printf(" %s:%s", it2.first.c_str(), it2.second.c_str());
 | |
| 				printf("\n");
 | |
| 			}
 | |
| 		}
 | |
| 		for (auto &result : mineResults) {
 | |
| 			printf("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits);
 | |
| 			printf("  primary match in %s:", result.graphId.c_str());
 | |
| 			for (auto &node : result.nodes)
 | |
| 				printf(" %s", node.nodeId.c_str());
 | |
| 			printf("\n");
 | |
| 			for (auto &it : result.matchesPerGraph)
 | |
| 				printf("  matches in %s: %d\n", it.first.c_str(), it.second);
 | |
| 		}
 | |
| 	} else
 | |
| 		printf("PASSED.\n");
 | |
| 
 | |
| 	printf("\n");
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 |