#include <stdarg.h>
#include <stdio.h>
+#ifdef _YOSYS_
+# include "kernel/log.h"
+# define my_printf log
+#else
+# define my_printf printf
+#endif
+
using namespace SubCircuit;
-static std::string stringf(const char *fmt, ...)
+static std::string my_stringf(const char *fmt, ...)
{
std::string string;
char *str = NULL;
{
for (int i = 0; i < int(nodes.size()); i++) {
const Node &node = nodes[i];
- printf("NODE %d: %s (%s)\n", i, node.nodeId.c_str(), node.typeId.c_str());
+ my_printf("NODE %d: %s (%s)\n", i, node.nodeId.c_str(), node.typeId.c_str());
for (int j = 0; j < int(node.ports.size()); j++) {
const Port &port = node.ports[j];
- printf(" PORT %d: %s (%d/%d)\n", j, port.portId.c_str(), port.minWidth, int(port.bits.size()));
+ my_printf(" PORT %d: %s (%d/%d)\n", j, port.portId.c_str(), port.minWidth, int(port.bits.size()));
for (int k = 0; k < int(port.bits.size()); k++) {
int edgeIdx = port.bits[k].edgeIdx;
- printf(" BIT %d (%d):", k, edgeIdx);
+ my_printf(" BIT %d (%d):", k, edgeIdx);
for (const auto &ref : edges[edgeIdx].portBits)
- printf(" %d.%d.%d", ref.nodeIdx, ref.portIdx, ref.bitIdx);
+ my_printf(" %d.%d.%d", ref.nodeIdx, ref.portIdx, ref.bitIdx);
if (edges[edgeIdx].isExtern)
- printf(" [extern]");
- printf("\n");
+ my_printf(" [extern]");
+ my_printf("\n");
}
}
}
static void printAdjMatrix(const adjMatrix_t &matrix)
{
- printf("%7s", "");
+ my_printf("%7s", "");
for (int i = 0; i < int(matrix.size()); i++)
- printf("%4d:", i);
- printf("\n");
+ my_printf("%4d:", i);
+ my_printf("\n");
for (int i = 0; i < int(matrix.size()); i++) {
- printf("%5d:", i);
+ my_printf("%5d:", i);
for (int j = 0; j < int(matrix.size()); j++)
if (matrix.at(i).count(j) == 0)
- printf("%5s", "-");
+ my_printf("%5s", "-");
else
- printf("%5d", matrix.at(i).at(j));
- printf("\n");
+ my_printf("%5d", matrix.at(i).at(j));
+ my_printf("\n");
}
}
std::string toString() const
{
- return stringf("%s[%d]:%s[%d]", fromPort.c_str(), fromBit, toPort.c_str(), toBit);
+ return my_stringf("%s[%d]:%s[%d]", fromPort.c_str(), fromBit, toPort.c_str(), toBit);
}
};
std::string str;
bool firstPort = true;
for (const auto &it : portSizes) {
- str += stringf("%s%s[%d]", firstPort ? "" : ",", it.first.c_str(), it.second);
+ str += my_stringf("%s%s[%d]", firstPort ? "" : ",", it.first.c_str(), it.second);
firstPort = false;
}
return typeId + "(" + str + ")";
void printEdgeTypes() const
{
for (int i = 0; i < int(edgeTypes.size()); i++)
- printf("%5d: %s\n", i, edgeTypes[i].toString().c_str());
+ my_printf("%5d: %s\n", i, edgeTypes[i].toString().c_str());
}
};
maxHaystackNodeIdx = std::max(maxHaystackNodeIdx, idx);
}
- printf(" ");
+ my_printf(" ");
for (int j = 0; j < maxHaystackNodeIdx; j += 5)
- printf("%-6d", j);
- printf("\n");
+ my_printf("%-6d", j);
+ my_printf("\n");
for (int i = 0; i < int(enumerationMatrix.size()); i++)
{
- printf("%5d:", i);
+ my_printf("%5d:", i);
for (int j = 0; j < maxHaystackNodeIdx; j++) {
if (j % 5 == 0)
- printf(" ");
- printf("%c", enumerationMatrix[i].count(j) > 0 ? '*' : '.');
+ my_printf(" ");
+ my_printf("%c", enumerationMatrix[i].count(j) > 0 ? '*' : '.');
}
- printf("\n");
+ my_printf("\n");
}
}
for (int j = 0; j < int(enumerationMatrix.size()); j++) {
if (portmapCandidates[j].size() == 0) {
if (verbose) {
- printf("\nSolution (rejected by portmapper):\n");
+ my_printf("\nSolution (rejected by portmapper):\n");
printEnumerationMatrix(enumerationMatrix, haystack.graph.nodes.size());
}
return;
if (!userSolver->userCheckSolution(result)) {
if (verbose) {
- printf("\nSolution (rejected by userCheckSolution):\n");
+ my_printf("\nSolution (rejected by userCheckSolution):\n");
printEnumerationMatrix(enumerationMatrix, haystack.graph.nodes.size());
}
return;
haystack.usedNodes[*enumerationMatrix[j].begin()] = true;
if (verbose) {
- printf("\nSolution:\n");
+ my_printf("\nSolution:\n");
printEnumerationMatrix(enumerationMatrix, haystack.graph.nodes.size());
}
}
if (verbose) {
- printf("\n");
- printf("Enumeration Matrix at recursion level %d (%d):\n", iter, i);
+ my_printf("\n");
+ my_printf("Enumeration Matrix at recursion level %d (%d):\n", iter, i);
printEnumerationMatrix(enumerationMatrix, haystack.graph.nodes.size());
}
std::string str = graphId + "(";
bool first = true;
for (int node : nodes) {
- str += stringf("%s%d", first ? "" : " ", node);
+ str += my_stringf("%s%d", first ? "" : " ", node);
first = false;
}
return str + ")";
int testForMining(std::vector<Solver::MineResult> &results, std::set<NodeSet> &usedSets, std::set<NodeSet> &nextPool, NodeSet &testSet,
const std::string &graphId, const Graph &graph, int minNodes, int minMatches, int limitMatchesPerGraph)
{
- // printf("test: %s\n", testSet.to_string().c_str());
+ // my_printf("test: %s\n", testSet.to_string().c_str());
GraphData needle;
std::vector<std::string> needle_nodes;
resultNodes.push_back(graphData[it.haystackGraphId].graph.nodeMap[i2.second.haystackNodeId]);
NodeSet resultSet(it.haystackGraphId, resultNodes);
- // printf("match: %s%s\n", resultSet.to_string().c_str(), usedSets.count(resultSet) > 0 ? " (dup)" : "");
+ // my_printf("match: %s%s\n", resultSet.to_string().c_str(), usedSets.count(resultSet) > 0 ? " (dup)" : "");
#if 0
if (usedSets.count(resultSet) > 0) {
nodePairs.clear();
if (verbose)
- printf("\nMining for frequent node pairs:\n");
+ my_printf("\nMining for frequent node pairs:\n");
for (auto &graph_it : graphData)
for (int node1 = 0; node1 < int(graph_it.second.graph.nodes.size()); node1++)
int matches = testForMining(results, usedPairs, nodePairs, pair, graphId, graph, minNodes, minMatches, limitMatchesPerGraph);
if (verbose)
- printf("Pair %s[%s,%s] -> %d%s\n", graphId.c_str(), graph.nodes[node1].nodeId.c_str(),
+ my_printf("Pair %s[%s,%s] -> %d%s\n", graphId.c_str(), graph.nodes[node1].nodeId.c_str(),
graph.nodes[node2].nodeId.c_str(), matches, matches < minMatches ? " *purge*" : "");
if (minMatches <= matches)
}
if (verbose)
- printf("Found a total of %d subgraphs in %d groups.\n", int(nodePairs.size()), groupCounter);
+ my_printf("Found a total of %d subgraphs in %d groups.\n", int(nodePairs.size()), groupCounter);
}
void findNextPool(std::vector<Solver::MineResult> &results, std::set<NodeSet> &pool,
poolPerGraph[it.graphId].push_back(&it);
if (verbose)
- printf("\nMining for frequent subcircuits of size %d using increment %d:\n", oldSetSize+increment, increment);
+ my_printf("\nMining for frequent subcircuits of size %d using increment %d:\n", oldSetSize+increment, increment);
std::set<NodeSet> usedSets;
for (auto &it : poolPerGraph)
int matches = testForMining(results, usedSets, nextPool, mergedSet, graphId, graph, minNodes, minMatches, limitMatchesPerGraph);
if (verbose) {
- printf("Set %s[", graphId.c_str());
+ my_printf("Set %s[", graphId.c_str());
bool first = true;
for (int nodeIdx : mergedSet.nodes) {
- printf("%s%s", first ? "" : ",", graph.nodes[nodeIdx].nodeId.c_str());
+ my_printf("%s%s", first ? "" : ",", graph.nodes[nodeIdx].nodeId.c_str());
first = false;
}
- printf("] -> %d%s\n", matches, matches < minMatches ? " *purge*" : "");
+ my_printf("] -> %d%s\n", matches, matches < minMatches ? " *purge*" : "");
}
if (minMatches <= matches)
pool.swap(nextPool);
if (verbose)
- printf("Found a total of %d subgraphs in %d groups.\n", int(pool.size()), groupCounter);
+ my_printf("Found a total of %d subgraphs in %d groups.\n", int(pool.size()), groupCounter);
}
// interface to the public solver class
if (verbose)
{
- printf("\n");
- printf("Needle Adjecency Matrix:\n");
+ my_printf("\n");
+ my_printf("Needle Adjecency Matrix:\n");
printAdjMatrix(needle.adjMatrix);
- printf("\n");
- printf("Haystack Adjecency Matrix:\n");
+ my_printf("\n");
+ my_printf("Haystack Adjecency Matrix:\n");
printAdjMatrix(haystack.adjMatrix);
- printf("\n");
- printf("Edge Types:\n");
+ my_printf("\n");
+ my_printf("Edge Types:\n");
diCache.printEdgeTypes();
- printf("\n");
- printf("Enumeration Matrix:\n");
+ my_printf("\n");
+ my_printf("Enumeration Matrix:\n");
printEnumerationMatrix(enumerationMatrix, haystack.graph.nodes.size());
}
#include <stdio.h>
#include <string.h>
+using RTLIL::id2cstr;
+
namespace
{
struct bit_ref_t {
std::map<RTLIL::SigChunk, bit_ref_t> sig_bit_ref;
if (sel && !sel->selected(mod)) {
- log(" Skipping module %s as it is not selected.\n", mod->name.c_str());
+ log(" Skipping module %s as it is not selected.\n", id2cstr(mod->name));
return false;
}
if (mod->processes.size() > 0) {
- log(" Skipping module %s as it contains unprocessed processes.\n", mod->name.c_str());
+ log(" Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name));
return false;
}
}
if (filename.empty())
- log_cmd_error("Missing option -map <verilog_or_ilang_file>.\n");
+ log_cmd_error("Missing option -map <verilog_or_ilang_file> or -mine <output_ilang_file>.\n");
RTLIL::Design *map = NULL;
replace(needle_map.at(result.needleGraphId), haystack_map.at(result.haystackGraphId), result);
}
}
-
- delete map;
}
else
{
log_header("Running miner from SubCircuit library.\n");
solver.mine(results, mine_cells_min, mine_cells_max, mine_min_freq, mine_limit_mod);
- // FIXME: Create output file
+ map = new RTLIL::Design;
- for (auto &result: results) {
- 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);
+ int needleCounter = 0;
+ for (auto &result: results)
+ {
+ log("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits);
+ log(" primary match in %s:", id2cstr(haystack_map.at(result.graphId)->name));
+ for (auto &node : result.nodes)
+ log(" %s", id2cstr(node.nodeId));
+ log("\n");
+ for (auto &it : result.matchesPerGraph)
+ log(" matches in %s: %d\n", id2cstr(haystack_map.at(it.first)->name), it.second);
+
+ RTLIL::Module *mod = haystack_map.at(result.graphId);
+ std::set<RTLIL::Cell*> cells;
+ std::set<RTLIL::Wire*> wires;
+
+ SigMap sigmap(mod);
+
+ for (auto &node : result.nodes)
+ cells.insert((RTLIL::Cell*)node.userData);
+
+ for (auto cell : cells)
+ for (auto &conn : cell->connections) {
+ RTLIL::SigSpec sig = sigmap(conn.second);
+ for (auto &chunk : sig.chunks)
+ if (chunk.wire != NULL)
+ wires.insert(chunk.wire);
+ }
+
+ RTLIL::Module *newMod = new RTLIL::Module;
+ newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, id2cstr(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits);
+ map->modules[newMod->name] = newMod;
+
+ int portCounter = 1;
+ for (auto wire : wires) {
+ RTLIL::Wire *newWire = new RTLIL::Wire;
+ newWire->name = wire->name;
+ newWire->width = wire->width;
+ newWire->port_id = portCounter++;
+ newWire->port_input = true;
+ newWire->port_output = true;
+ newMod->add(newWire);
+ }
+
+ for (auto cell : cells) {
+ RTLIL::Cell *newCell = new RTLIL::Cell;
+ newCell->name = cell->name;
+ newCell->type = cell->type;
+ newCell->parameters = cell->parameters;
+ for (auto &conn : cell->connections) {
+ RTLIL::SigSpec sig = sigmap(conn.second);
+ for (auto &chunk : sig.chunks)
+ if (chunk.wire != NULL)
+ chunk.wire = newMod->wires.at(chunk.wire->name);
+ newCell->connections[conn.first] = sig;
+ }
+ newMod->add(newCell);
+ }
}
+
+ FILE *f = fopen(filename.c_str(), "wt");
+ if (f == NULL)
+ log_cmd_error("Can't open output file `%s'.\n", filename.c_str());
+ Backend::backend_call(map, f, filename, "ilang");
+ fclose(f);
}
+ delete map;
log_pop();
}
} ExtractPass;