diff options
Diffstat (limited to 'libs/subcircuit/scshell.cc')
-rw-r--r-- | libs/subcircuit/scshell.cc | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/libs/subcircuit/scshell.cc b/libs/subcircuit/scshell.cc new file mode 100644 index 00000000..70afcfd4 --- /dev/null +++ b/libs/subcircuit/scshell.cc @@ -0,0 +1,235 @@ +#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<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] == "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())); + 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"); + } + } + printf("\n"); + if (expected != int(results.size())) { + printf("^^ expected %d, Got %d ^^\n\n", expected, int(results.size())); + printf(" +----------------+\n"); + printf(" | \\|/ ____ \\|/ |\n"); + printf(" | \"@'/ ,. \\`@\" |\n"); + printf(" | /_| \\__/ |_\\ |\n"); + printf(" | \\__U_/ |\n"); + printf(" | | | |\n"); + printf(" +----------------+\n\n"); + return 1; + } + results.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())); + 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"); + } + } + } else + printf("PASSED.\n"); + + printf("\n"); + + return 0; +} + |