diff --git a/source/util/CommandLine.cpp b/source/util/CommandLine.cpp index 08f6e8c3b..c60f24f94 100644 --- a/source/util/CommandLine.cpp +++ b/source/util/CommandLine.cpp @@ -674,7 +674,7 @@ bool CommandLine::Option::expectsValue() const { std::string CommandLine::Option::set(string_view name, string_view value, bool ignoreDup) { std::string pathMem; - if (isFileName && !value.empty()) { + if (isFileName && !value.empty() && value != "-") { std::error_code ec; fs::path path = fs::weakly_canonical(fs::u8path(value), ec); if (!ec) { diff --git a/tools/netlist/include/DirectedGraph.h b/tools/netlist/include/DirectedGraph.h index 576040478..975c12024 100644 --- a/tools/netlist/include/DirectedGraph.h +++ b/tools/netlist/include/DirectedGraph.h @@ -294,7 +294,16 @@ class DirectedGraph { } /// Return the size of the graph. - size_t size() const { return nodes.size(); } + size_t numNodes() const { return nodes.size(); } + + /// Return the number of edges in the graph. + size_t numEdges() const { + size_t count = 0; + for (auto &node : nodes) { + count += node->outDegree(); + } + return count; + } private: NodeListType nodes; diff --git a/tools/netlist/netlist.cpp b/tools/netlist/netlist.cpp index 7d520c8b1..286a9ee20 100644 --- a/tools/netlist/netlist.cpp +++ b/tools/netlist/netlist.cpp @@ -112,21 +112,20 @@ class NetlistEdge : public DirectedEdge { NetlistEdge(NetlistNode &targetNode) : DirectedEdge(targetNode) {} }; +/// An AST visitor to identify variable references with selectors in +/// expressions only. class VariableReferenceVisitor : public ASTVisitor { public: - explicit VariableReferenceVisitor(Netlist &netlist, EvalContext &evalCtx) : - netlist(netlist), evalCtx(evalCtx) {} - - void handle(const AssignmentExpression &expr) { - std::cout << "AssignmentExpression non-blocking " << expr.isNonBlocking() << "\n"; - expr.left().visit(*this); - expr.right().visit(*this); - // Add an edge... - } + explicit VariableReferenceVisitor(Netlist &netlist, + std::vector &visitList, + EvalContext &evalCtx) : + netlist(netlist), visitList(visitList), evalCtx(evalCtx) {} void handle(const NamedValueExpression &expr) { auto &node = netlist.addNode(); + visitList.push_back(&node); node.setName(expr.symbol.name); + //std::cout<<"Got node "<kind == ExpressionKind::ElementSelect) { auto index = selector->as().selector().eval(evalCtx); @@ -162,10 +161,45 @@ class VariableReferenceVisitor : public ASTVisitor &visitList; EvalContext &evalCtx; std::vector selectors; }; +/// An AST visitor to create dependencies between occurrances of variables +/// appearing on the left and right hand sides of assignment statements. +class AssignmentVisitor : public ASTVisitor { +public: + explicit AssignmentVisitor(Netlist &netlist, EvalContext &evalCtx) : + netlist(netlist), evalCtx(evalCtx) {} + + void handle(const AssignmentExpression &expr) { + std::cout << "AssignmentExpression non-blocking " << expr.isNonBlocking() << "\n"; + // Collect variable references on the left and right hand sides of the + // assignment. + std::vector visitListLHS, visitListRHS; + { + VariableReferenceVisitor visitor(netlist, visitListLHS, evalCtx); + expr.left().visit(visitor); + } + { + VariableReferenceVisitor visitor(netlist, visitListRHS, evalCtx); + expr.right().visit(visitor); + } + // Add edges RHS -> LHS... + for (auto *leftNode : visitListLHS) { + for (auto *rightNode : visitListRHS) { + netlist.addEdge(*leftNode, *rightNode); + //std::cout<<"add edge "<getName()<< " to " <getName()<<"\n"; + } + } + } + +private: + Netlist &netlist; + EvalContext &evalCtx; +}; + class UnrollVisitor : public ASTVisitor { public: bool anyErrors = false; @@ -179,10 +213,10 @@ class UnrollVisitor : public ASTVisitor { std::cout << "InstanceSymbol " << symbol.name << "\n"; for (auto *portConnection : symbol.getPortConnections()) { std::cout << "Port " << portConnection->port.name << " connects to:\n"; - if (portConnection->getExpression()) { - VariableReferenceVisitor visitor(netlist, evalCtx); - portConnection->getExpression()->visit(visitor); - } + //if (portConnection->getExpression()) { + //VariableReferenceVisitor visitor(netlist, evalCtx); + //portConnection->getExpression()->visit(visitor); + //} } symbol.body.visit(*this); } @@ -199,7 +233,7 @@ class UnrollVisitor : public ASTVisitor { } void handle(const ForLoopStatement& loop) { - std::cout << "Unroll ForLoopStatement\n"; +// std::cout << "Unroll ForLoopStatement\n"; // Conditions this loop cannot be unrolled. if (loop.loopVars.empty() || !loop.stopExpr || loop.steps.empty() || anyErrors) { @@ -273,7 +307,7 @@ class UnrollVisitor : public ASTVisitor { } void handle(const ConditionalStatement& stmt) { - std::cout << "ConditionalStatement\n"; +// std::cout << "ConditionalStatement\n"; // Evaluate the condition; if not constant visit both sides, // otherwise visit only the side that matches the condition. auto fallback = [&] { @@ -305,12 +339,17 @@ class UnrollVisitor : public ASTVisitor { } void handle(const ExpressionStatement& stmt) { - std::cout << "ExpressionStatement\n"; +// std::cout << "ExpressionStatement\n"; step(); - VariableReferenceVisitor visitor(netlist, evalCtx); + AssignmentVisitor visitor(netlist, evalCtx); stmt.visit(visitor); } + void handle(const ContinuousAssignSymbol &symbol) { + AssignmentVisitor visitor(netlist, evalCtx); + symbol.visit(visitor); + } + private: bool step() { if (anyErrors || !evalCtx.step(SourceLocation::NoLocation)) { @@ -352,7 +391,7 @@ void printDOT(const Netlist &netlist, const std::string &fileName) { } for (auto &node : netlist) { for (auto &edge : node->getEdges()) { - buffer.format(" N{} -> N{}\n", node->getName(), edge->getTargetNode().getName()); + buffer.format(" N{} -> N{}\n", node->ID, edge->getTargetNode().ID); } } buffer.append("}\n"); @@ -369,7 +408,6 @@ void writeToFile(Stream& os, string_view fileName, String contents) { } void writeToFile(string_view fileName, string_view contents) { - std::cout<<"filename "<getRoot().visit(visitor); - std::cout << "Netlist has " << netlist.size() << " nodes\n"; + std::cout << fmt::format("Netlist has {} nodes and {} edges\n", + netlist.numNodes(), netlist.numEdges()); if (netlistDotFile) { printDOT(netlist, *netlistDotFile); diff --git a/tools/netlist/tests/DirectedGraphTest.cpp b/tools/netlist/tests/DirectedGraphTest.cpp index 1782c47a6..4c80d2e06 100644 --- a/tools/netlist/tests/DirectedGraphTest.cpp +++ b/tools/netlist/tests/DirectedGraphTest.cpp @@ -25,13 +25,15 @@ TEST_CASE("Test basic connectivity") { auto &n1 = graph.addNode(); auto &n2 = graph.addNode(); auto &n3 = graph.addNode(); - CHECK(graph.size() == 4); + CHECK(graph.numNodes() == 4); + CHECK(graph.numEdges() == 0); auto &e0 = graph.addEdge(n0, n1); auto &e1 = graph.addEdge(n0, n2); auto &e2 = graph.addEdge(n0, n3); auto &e3 = graph.addEdge(n1, n2); auto &e4 = graph.addEdge(n1, n3); auto &e5 = graph.addEdge(n2, n3); + CHECK(graph.numEdges() == 6); // Edge target nodes. CHECK(e0.getTargetNode() == n1); CHECK(e1.getTargetNode() == n2); @@ -56,11 +58,12 @@ TEST_CASE("Test removing nodes") { auto &n0 = graph.addNode(); auto &n1 = graph.addNode(); auto &n2 = graph.addNode(); - CHECK(graph.size() == 3); // Create a ring of n0, n1, n2 graph.addEdge(n0, n1); graph.addEdge(n1, n2); graph.addEdge(n2, n0); + CHECK(graph.numNodes() == 3); + CHECK(graph.numEdges() == 3); // Remove n0 CHECK(graph.removeNode(n0)); CHECK(graph.inDegree(n1) == 0); @@ -73,7 +76,7 @@ TEST_CASE("Test removing nodes") { CHECK(graph.outDegree(n2) == 0); // Remove n2 CHECK(graph.removeNode(n2)); - CHECK(graph.size() == 0); + CHECK(graph.numNodes() == 0); } TEST_CASE("Test removing edges") { @@ -81,11 +84,12 @@ TEST_CASE("Test removing edges") { auto &n0 = graph.addNode(); auto &n1 = graph.addNode(); auto &n2 = graph.addNode(); - CHECK(graph.size() == 3); // Create a ring of n0 -e0- n1 -e1- n2 -e2- graph.addEdge(n0, n1); // e0 graph.addEdge(n1, n2); // e1 graph.addEdge(n2, n0); // e2 + CHECK(graph.numNodes() == 3); + CHECK(graph.numEdges() == 3); // Remove e0. CHECK(graph.removeEdge(n0, n1)); CHECK(graph.outDegree(n0) == 0);