Merge pull request #1175 from whitequark/write_verilog-fix-case-attr-position
[yosys.git] / libs / subcircuit / scshell.cc
1 #include "subcircuit.h"
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5
6 std::vector<std::string> readLine()
7 {
8 char buffer[4096];
9 std::vector<std::string> tokenList;
10
11 while (tokenList.size() == 0 && fgets(buffer, sizeof(buffer), stdin) != NULL) {
12 for (char *p = buffer; char *tok = strtok(p, " \t\r\n"); p = NULL) {
13 if (p != NULL && tok[0] == '#')
14 break;
15 tokenList.push_back(tok);
16 }
17 }
18
19 return tokenList;
20 }
21
22 int main()
23 {
24 std::string graphId;
25 SubCircuit::Graph *graph = NULL;
26 SubCircuit::Solver solver;
27 std::map<std::string, std::set<std::string>> initialMappings;
28 std::vector<SubCircuit::Solver::Result> results;
29 std::vector<SubCircuit::Solver::MineResult> mineResults;
30 std::vector<std::string> cmdBuffer;
31 bool lastCommandExpect = false;
32
33 while (1)
34 {
35 cmdBuffer = readLine();
36 if (cmdBuffer.empty())
37 break;
38
39 printf(graph == NULL || cmdBuffer[0] == "endgraph" ? ">" : "> ");
40 for (const auto &tok : cmdBuffer)
41 printf(" %s", tok.c_str());
42 printf("\n");
43
44 lastCommandExpect = false;
45
46 if (graph != NULL)
47 {
48 if (cmdBuffer[0] == "node" && cmdBuffer.size() >= 3) {
49 graph->createNode(cmdBuffer[1], cmdBuffer[2]);
50 for (int i = 3; i < int(cmdBuffer.size()); i++) {
51 std::string portId = cmdBuffer[i];
52 int width = 1, minWidth = -1;
53 if (i+1 < int(cmdBuffer.size()) && '0' <= cmdBuffer[i+1][0] && cmdBuffer[i+1][0] <= '9')
54 width = atoi(cmdBuffer[++i].c_str());
55 if (i+1 < int(cmdBuffer.size()) && '0' <= cmdBuffer[i+1][0] && cmdBuffer[i+1][0] <= '9')
56 minWidth = atoi(cmdBuffer[++i].c_str());
57 graph->createPort(cmdBuffer[1], portId, width, minWidth);
58 }
59 continue;
60 }
61
62 if (cmdBuffer[0] == "connect" && cmdBuffer.size() == 5) {
63 graph->createConnection(cmdBuffer[1], cmdBuffer[2], cmdBuffer[3], cmdBuffer[4]);
64 continue;
65 }
66
67 if (cmdBuffer[0] == "connect" && cmdBuffer.size() == 7) {
68 graph->createConnection(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str()), cmdBuffer[4], cmdBuffer[5], atoi(cmdBuffer[6].c_str()));
69 continue;
70 }
71
72 if (cmdBuffer[0] == "connect" && cmdBuffer.size() == 8) {
73 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()));
74 continue;
75 }
76
77 if (cmdBuffer[0] == "constant" && cmdBuffer.size() == 5) {
78 int constValue = cmdBuffer[4].size() > 1 && cmdBuffer[4][0] == '#' ? atoi(cmdBuffer[4].c_str()+1) : cmdBuffer[4][0];
79 graph->createConstant(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str()), constValue);
80 continue;
81 }
82
83 if (cmdBuffer[0] == "constant" && cmdBuffer.size() == 4) {
84 graph->createConstant(cmdBuffer[1], cmdBuffer[2], atoi(cmdBuffer[3].c_str()));
85 continue;
86 }
87
88 if (cmdBuffer[0] == "extern" && cmdBuffer.size() >= 3) {
89 for (int i = 2; i < int(cmdBuffer.size()); i++) {
90 std::string portId = cmdBuffer[i];
91 int bit = -1;
92 if (i+1 < int(cmdBuffer.size()) && '0' <= cmdBuffer[i+1][0] && cmdBuffer[i+1][0] <= '9')
93 bit = atoi(cmdBuffer[++i].c_str());
94 graph->markExtern(cmdBuffer[1], portId, bit);
95 }
96 continue;
97 }
98
99 if (cmdBuffer[0] == "allextern" && cmdBuffer.size() == 1) {
100 graph->markAllExtern();
101 continue;
102 }
103
104 if (cmdBuffer[0] == "endgraph" && cmdBuffer.size() == 1) {
105 solver.addGraph(graphId, *graph);
106 delete graph;
107 graph = NULL;
108 continue;
109 }
110 }
111 else
112 {
113 if (cmdBuffer[0] == "graph" && cmdBuffer.size() == 2) {
114 graph = new SubCircuit::Graph;
115 graphId = cmdBuffer[1];
116 continue;
117 }
118
119 if (cmdBuffer[0] == "compatible" && cmdBuffer.size() == 3) {
120 solver.addCompatibleTypes(cmdBuffer[1], cmdBuffer[2]);
121 continue;
122 }
123
124 if (cmdBuffer[0] == "constcompat" && cmdBuffer.size() == 3) {
125 int needleConstValue = cmdBuffer[1].size() > 1 && cmdBuffer[1][0] == '#' ? atoi(cmdBuffer[1].c_str()+1) : cmdBuffer[1][0];
126 int haystackConstValue = cmdBuffer[2].size() > 1 && cmdBuffer[2][0] == '#' ? atoi(cmdBuffer[2].c_str()+1) : cmdBuffer[2][0];
127 solver.addCompatibleConstants(needleConstValue, haystackConstValue);
128 continue;
129 }
130
131 if (cmdBuffer[0] == "swapgroup" && cmdBuffer.size() >= 4) {
132 std::set<std::string> ports;
133 for (int i = 2; i < int(cmdBuffer.size()); i++)
134 ports.insert(cmdBuffer[i]);
135 solver.addSwappablePorts(cmdBuffer[1], ports);
136 continue;
137 }
138
139 if (cmdBuffer[0] == "swapperm" && cmdBuffer.size() >= 4 && cmdBuffer.size() % 2 == 1 && cmdBuffer[cmdBuffer.size()/2 + 1] == ":") {
140 std::map<std::string, std::string> portMapping;
141 int n = (cmdBuffer.size()-3) / 2;
142 for (int i = 0; i < n; i++)
143 portMapping[cmdBuffer[i+2]] = cmdBuffer[i+3+n];
144 solver.addSwappablePortsPermutation(cmdBuffer[1], portMapping);
145 continue;
146 }
147
148 if (cmdBuffer[0] == "initmap" && cmdBuffer.size() >= 4) {
149 for (int i = 2; i < int(cmdBuffer.size()); i++)
150 initialMappings[cmdBuffer[1]].insert(cmdBuffer[i]);
151 continue;
152 }
153
154 if (cmdBuffer[0] == "solve" && 3 <= cmdBuffer.size() && cmdBuffer.size() <= 5) {
155 bool allowOverlap = true;
156 int maxSolutions = -1;
157 if (cmdBuffer.size() >= 4)
158 allowOverlap = cmdBuffer[3] == "true" || atoi(cmdBuffer[3].c_str()) ? true : false;
159 if (cmdBuffer.size() >= 5)
160 maxSolutions = atoi(cmdBuffer[4].c_str());
161 solver.solve(results, cmdBuffer[1], cmdBuffer[2], initialMappings, allowOverlap, maxSolutions);
162 initialMappings.clear();
163 continue;
164 }
165
166 if (cmdBuffer[0] == "mine" && 4 <= cmdBuffer.size() && cmdBuffer.size() <= 5) {
167 solver.mine(mineResults, atoi(cmdBuffer[1].c_str()), atoi(cmdBuffer[2].c_str()),
168 atoi(cmdBuffer[3].c_str()), cmdBuffer.size() == 5 ? atoi(cmdBuffer[4].c_str()) : -1);
169 continue;
170 }
171
172 if (cmdBuffer[0] == "clearoverlap" && cmdBuffer.size() == 1) {
173 solver.clearOverlapHistory();
174 continue;
175 }
176
177 if (cmdBuffer[0] == "clearconfig" && cmdBuffer.size() == 1) {
178 solver.clearConfig();
179 continue;
180 }
181
182 if (cmdBuffer[0] == "verbose" && cmdBuffer.size() == 1) {
183 solver.setVerbose();
184 continue;
185 }
186
187 if (cmdBuffer[0] == "expect" && cmdBuffer.size() == 2) {
188 int expected = atoi(cmdBuffer[1].c_str());
189 printf("\n-- Expected %d, Got %d --\n", expected, int(results.size()) + int(mineResults.size()));
190 for (int i = 0; i < int(results.size()); i++) {
191 printf("\nMatch #%d: (%s in %s)\n", i, results[i].needleGraphId.c_str(), results[i].haystackGraphId.c_str());
192 for (const auto &it : results[i].mappings) {
193 printf(" %s -> %s", it.first.c_str(), it.second.haystackNodeId.c_str());
194 for (const auto &it2 : it.second.portMapping)
195 printf(" %s:%s", it2.first.c_str(), it2.second.c_str());
196 printf("\n");
197 }
198 }
199 for (auto &result : mineResults) {
200 printf("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits);
201 printf(" primary match in %s:", result.graphId.c_str());
202 for (auto &node : result.nodes)
203 printf(" %s", node.nodeId.c_str());
204 printf("\n");
205 for (auto &it : result.matchesPerGraph)
206 printf(" matches in %s: %d\n", it.first.c_str(), it.second);
207 }
208 printf("\n");
209 if (expected != int(results.size()) + int(mineResults.size())) {
210 printf("^^ expected %d, Got %d ^^\n\n", expected, int(results.size()) + int(mineResults.size()));
211 printf(" +----------------+\n");
212 printf(" | \\|/ ____ \\|/ |\n");
213 printf(" | \"@'/ ,. \\`@\" |\n");
214 printf(" | /_| \\__/ |_\\ |\n");
215 printf(" | \\__U_/ |\n");
216 printf(" | | | |\n");
217 printf(" +----------------+\n\n");
218 return 1;
219 }
220 results.clear();
221 mineResults.clear();
222 lastCommandExpect = true;
223 continue;
224 }
225 }
226
227 printf("Invalid input command!\n");
228 return 1;
229 }
230
231 if (graph)
232 delete graph;
233
234 if (!lastCommandExpect) {
235 printf("\n-- Got %d --\n", int(results.size()) + int(mineResults.size()));
236 for (int i = 0; i < int(results.size()); i++) {
237 printf("\nMatch #%d: (%s in %s)\n", i, results[i].needleGraphId.c_str(), results[i].haystackGraphId.c_str());
238 for (const auto &it : results[i].mappings) {
239 printf(" %s -> %s", it.first.c_str(), it.second.haystackNodeId.c_str());
240 for (const auto &it2 : it.second.portMapping)
241 printf(" %s:%s", it2.first.c_str(), it2.second.c_str());
242 printf("\n");
243 }
244 }
245 for (auto &result : mineResults) {
246 printf("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits);
247 printf(" primary match in %s:", result.graphId.c_str());
248 for (auto &node : result.nodes)
249 printf(" %s", node.nodeId.c_str());
250 printf("\n");
251 for (auto &it : result.matchesPerGraph)
252 printf(" matches in %s: %d\n", it.first.c_str(), it.second);
253 }
254 } else
255 printf("PASSED.\n");
256
257 printf("\n");
258
259 return 0;
260 }
261