aboutsummaryrefslogtreecommitdiffstats
path: root/libs/subcircuit/scshell.cc
blob: c4b37a4defccf32fb69de8d14ca9ef0a07031b0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#! /bin/sh

. ../../testenv.sh

export GHDL_STD_FLAGS=--std=08
analyze --work=osvvm ScoreboardGenericPkg.vhd

analyze_failure repro_err.vhdl
analyze repro.vhdl
elab_simulate e

clean
clean osvvm

echo "Test successful"
04' href='#n204'>204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
#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;
}