Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamie Hanlon committed Mar 15, 2023
1 parent d49d29e commit d3a78e3
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 26 deletions.
2 changes: 1 addition & 1 deletion source/util/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
11 changes: 10 additions & 1 deletion tools/netlist/include/DirectedGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
79 changes: 59 additions & 20 deletions tools/netlist/netlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,21 +112,20 @@ class NetlistEdge : public DirectedEdge<NetlistNode, NetlistEdge> {
NetlistEdge(NetlistNode &targetNode) : DirectedEdge(targetNode) {}
};

/// An AST visitor to identify variable references with selectors in
/// expressions only.
class VariableReferenceVisitor : public ASTVisitor<VariableReferenceVisitor, false, true> {
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<NetlistNode*> &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 "<<node.getName()<<"\n";
for (auto *selector : selectors) {
if (selector->kind == ExpressionKind::ElementSelect) {
auto index = selector->as<ElementSelectExpression>().selector().eval(evalCtx);
Expand Down Expand Up @@ -162,10 +161,45 @@ class VariableReferenceVisitor : public ASTVisitor<VariableReferenceVisitor, fal

private:
Netlist &netlist;
std::vector<NetlistNode*> &visitList;
EvalContext &evalCtx;
std::vector<const Expression*> 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<AssignmentVisitor, false, true> {
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<NetlistNode*> 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 "<<rightNode->getName()<< " to " <<leftNode->getName()<<"\n";
}
}
}

private:
Netlist &netlist;
EvalContext &evalCtx;
};

class UnrollVisitor : public ASTVisitor<UnrollVisitor, true, false> {
public:
bool anyErrors = false;
Expand All @@ -179,10 +213,10 @@ class UnrollVisitor : public ASTVisitor<UnrollVisitor, true, false> {
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);
}
Expand All @@ -199,7 +233,7 @@ class UnrollVisitor : public ASTVisitor<UnrollVisitor, true, false> {
}

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) {
Expand Down Expand Up @@ -273,7 +307,7 @@ class UnrollVisitor : public ASTVisitor<UnrollVisitor, true, false> {
}

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 = [&] {
Expand Down Expand Up @@ -305,12 +339,17 @@ class UnrollVisitor : public ASTVisitor<UnrollVisitor, true, false> {
}

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)) {
Expand Down Expand Up @@ -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");
Expand All @@ -369,7 +408,6 @@ void writeToFile(Stream& os, string_view fileName, String contents) {
}

void writeToFile(string_view fileName, string_view contents) {
std::cout<<"filename "<<fileName<<"\n";
if (fileName == "-") {
writeToFile(std::cout, "stdout", contents);
} else {
Expand Down Expand Up @@ -446,7 +484,8 @@ int main(int argc, char** argv) {
Netlist netlist;
UnrollVisitor visitor(*compilation, netlist);
compilation->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);
Expand Down
12 changes: 8 additions & 4 deletions tools/netlist/tests/DirectedGraphTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -73,19 +76,20 @@ 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") {
DirectedGraph<TestNode, TestEdge> graph;
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);
Expand Down

0 comments on commit d3a78e3

Please sign in to comment.