Skip to content

Commit

Permalink
Add a new tool: slang-netlist (#757)
Browse files Browse the repository at this point in the history
  • Loading branch information
jameshanlon committed May 20, 2023
1 parent 043c177 commit 5030a2a
Show file tree
Hide file tree
Showing 29 changed files with 2,602 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
.vscode/
.venv/
.idea/
.cache/
.DS_Store
build/
install/
compile_commands.json
Expand Down
5 changes: 3 additions & 2 deletions include/slang/diagnostics/Diagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ class Symbol;
x(SysFuncs) \
x(ConstEval) \
x(Compilation) \
x(Meta) \
x(Tidy)
x(Meta) \
x(Tidy) \
x(Netlist)
SLANG_ENUM_SIZED(DiagSubsystem, uint16_t, DS)
#undef DS

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion source/ast/Bitstream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
//------------------------------------------------------------------------------
#include "slang/ast/Bitstream.h"

#include "../text/FormatBuffer.h"
#include <numeric>

#include "slang/ast/Compilation.h"
Expand All @@ -18,6 +17,7 @@
#include "slang/diagnostics/ConstEvalDiags.h"
#include "slang/diagnostics/ExpressionsDiags.h"
#include "slang/diagnostics/NumericDiags.h"
#include "slang/text/FormatBuffer.h"

namespace slang::ast {

Expand Down
3 changes: 1 addition & 2 deletions source/ast/EvalContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@
//------------------------------------------------------------------------------
#include "slang/ast/EvalContext.h"

#include "../text/FormatBuffer.h"

#include "slang/ast/ASTContext.h"
#include "slang/ast/Compilation.h"
#include "slang/ast/symbols/SubroutineSymbols.h"
#include "slang/ast/symbols/VariableSymbols.h"
#include "slang/ast/types/Type.h"
#include "slang/diagnostics/ConstEvalDiags.h"
#include "slang/text/FormatBuffer.h"

namespace slang::ast {

Expand Down
3 changes: 1 addition & 2 deletions source/ast/Symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
//------------------------------------------------------------------------------
#include "slang/ast/Symbol.h"

#include "../text/FormatBuffer.h"

#include "slang/ast/ASTVisitor.h"
#include "slang/ast/Compilation.h"
#include "slang/ast/Definition.h"
#include "slang/ast/symbols/CompilationUnitSymbols.h"
#include "slang/ast/symbols/MemberSymbols.h"
#include "slang/ast/types/Type.h"
#include "slang/syntax/AllSyntax.h"
#include "slang/text/FormatBuffer.h"
#include "slang/text/SourceManager.h"

namespace {
Expand Down
3 changes: 1 addition & 2 deletions source/ast/types/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
//------------------------------------------------------------------------------
#include "slang/ast/types/TypePrinter.h"

#include "../../text/FormatBuffer.h"

#include "slang/ast/ASTVisitor.h"
#include "slang/text/FormatBuffer.h"

namespace slang::ast {

Expand Down
3 changes: 1 addition & 2 deletions source/diagnostics/TextDiagnosticClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
//------------------------------------------------------------------------------
#include "slang/diagnostics/TextDiagnosticClient.h"

#include "../text/FormatBuffer.h"

#include "slang/text/CharInfo.h"
#include "slang/text/FormatBuffer.h"
#include "slang/text/SourceManager.h"

namespace slang {
Expand Down
2 changes: 1 addition & 1 deletion source/numeric/ConstantValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
//------------------------------------------------------------------------------
#include "slang/numeric/ConstantValue.h"

#include "../text/FormatBuffer.h"
#include <ostream>

#include "slang/text/FormatBuffer.h"
#include "slang/util/Hash.h"

namespace slang {
Expand Down
2 changes: 1 addition & 1 deletion source/text/Json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
//------------------------------------------------------------------------------
#include "slang/text/Json.h"

#include "FormatBuffer.h"
#include <climits>

#include "slang/text/FormatBuffer.h"
#include "slang/util/SmallVector.h"
#include "slang/util/String.h"

Expand Down
2 changes: 1 addition & 1 deletion source/util/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ bool CommandLine::Option::expectsValue() const {
std::string CommandLine::Option::set(std::string_view name, std::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::path(widen(value)), ec);
if (!ec) {
Expand Down
1 change: 1 addition & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ if(SLANG_INCLUDE_INSTALL)
install(TARGETS slang_driver RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()

add_subdirectory(netlist)
add_subdirectory(tidy)
21 changes: 21 additions & 0 deletions tools/netlist/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# ~~~
# SPDX-FileCopyrightText: Michael Popoloski
# SPDX-License-Identifier: MIT
# ~~~
add_executable(slang_netlist netlist.cpp)
add_executable(slang::netlist ALIAS slang_netlist)

target_link_libraries(
slang_netlist
PRIVATE slang::slang fmt::fmt
PUBLIC ${SLANG_LIBRARIES})
target_include_directories(slang_netlist PRIVATE include ../../include)
set_target_properties(slang_netlist PROPERTIES OUTPUT_NAME "slang-netlist")

if(SLANG_INCLUDE_INSTALL)
install(TARGETS slang_netlist RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()

if(SLANG_INCLUDE_TESTS)
add_subdirectory(tests)
endif()
45 changes: 45 additions & 0 deletions tools/netlist/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
slang-netlist
=============

slang-netlist is a library and tool for analysing the source-level static
connectivity of a design. This capability can be useful, for example, to
develop structural checks or to investigate timing paths, rather than having to
use synthesis to obtain a gate-level netlist.

Using the example of a simple adder:
```
module adder
#(parameter p_width = 32)(
input logic [p_width-1:0] i_a,
input logic [p_width-1:0] i_b,
output logic [p_width-1:0] o_sum,
output logic o_co
);
logic [p_width-1:0] sum;
logic co;
assign {co, sum} = i_a + i_b;
assign o_sum = sum;
assign o_co = co;
endmodule
```

The slang-netlist command-line tool can be used to trace paths through the
design, such as:
```
➜ slang-netlist adder.sv --from adder.i_a --to adder.o_sum -q
adder.sv:10:22: note: variable i_a read from
assign {co, sum} = i_a + i_b;
^~~
adder.sv:10:15: note: variable sum assigned to
assign {co, sum} = i_a + i_b;
^~~
adder.sv:11:18: note: variable sum read from
assign o_sum = sum;
^~~
adder.sv:11:10: note: variable o_sum assigned to
assign o_sum = sum;
^~~~~
```
12 changes: 12 additions & 0 deletions tools/netlist/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
To dos
======

- Reporting of variables in the netlist (by type, matching patterns).
- Infer sequential elements in the netlist (ie non-blocking assignment and
sensitive to a clock edge).
- Constrain paths to start on particular node types (port, register, net etc).
- Support restricting paths to stop at sequential elements.
- Support paths passing through particular nodes.
- Support paths avoiding particular nodes.
- Support reporting of paths fanning into or out of a particular node.
- Provide Python bindings.
29 changes: 29 additions & 0 deletions tools/netlist/include/Config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//------------------------------------------------------------------------------
//! @file Config.h
//! @brief Provide singleton configuration class debug printing macro.
//
// SPDX-FileCopyrightText: Michael Popoloski
// SPDX-License-Identifier: MIT
//------------------------------------------------------------------------------
#pragma once

namespace netlist {

/// A singleton to hold global configuration options.
class Config {
public:
bool debugEnabled{};

Config() = default;

static Config& getInstance() {
static Config instance;
return instance;
}

// Prevent copies from being made.
Config(Config const&) = delete;
void operator=(Config const&) = delete;
};

} // namespace netlist
20 changes: 20 additions & 0 deletions tools/netlist/include/Debug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//------------------------------------------------------------------------------
//! @file Debug.h
//! @brief Provide a debug printing macro.
//
// SPDX-FileCopyrightText: Michael Popoloski
// SPDX-License-Identifier: MIT
//------------------------------------------------------------------------------
#pragma once

#include "Config.h"
#include <iostream>

#ifdef DEBUG
# define DEBUG_PRINT(x) \
if (netlist::Config::getInstance().debugEnabled) { \
std::cerr << x; \
}
#else
# define DEBUG_PRINT(x)
#endif
82 changes: 82 additions & 0 deletions tools/netlist/include/DepthFirstSearch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
//! @file DepthFirstSearch.h
//! @brief Implementation of depth-first search on a directed graph.
//
// SPDX-FileCopyrightText: Michael Popoloski
// SPDX-License-Identifier: MIT
//------------------------------------------------------------------------------
#pragma once

#include "DirectedGraph.h"
#include <set>
#include <vector>

namespace netlist {

struct select_all {
template<typename T>
bool operator()(const T&) const {
return true;
}
};

/// Depth-first search on a directed graph. A visitor class provides visibility
/// to the caller of visits to edges and nodes. An optional edge predicate
/// selects which edges can be included in the traversal.
template<class NodeType, class EdgeType, class Visitor, class EdgePredicate = select_all>
class DepthFirstSearch {
public:
DepthFirstSearch(Visitor& visitor, NodeType& startNode) : visitor(visitor) {
setup(startNode);
run();
}

DepthFirstSearch(Visitor& visitor, EdgePredicate edgePredicate, NodeType& startNode) :
visitor(visitor), edgePredicate(edgePredicate) {
setup(startNode);
run();
}

private:
using EdgeIteratorType = typename NodeType::iterator;
using VisitStackElement = std::pair<NodeType&, EdgeIteratorType>;

/// Setup the traversal.
void setup(NodeType& startNode) {
visitedNodes.insert(&startNode);
visitStack.push_back(VisitStackElement(startNode, startNode.begin()));
visitor.visitNode(startNode);
}

/// Perform a depth-first traversal, calling the visitor methods on the way.
void run() {
while (!visitStack.empty()) {
auto& node = visitStack.back().first;
auto& nodeIt = visitStack.back().second;
// Visit each child node that hasn't already been visited.
while (nodeIt != node.end()) {
auto* edge = nodeIt->get();
auto& targetNode = edge->getTargetNode();
nodeIt++;
if (edgePredicate(*edge) && visitedNodes.count(&targetNode) == 0) {
// Push a new 'current' node onto the stack and mark it as visited.
visitStack.push_back(VisitStackElement(targetNode, targetNode.begin()));
visitedNodes.insert(&targetNode);
visitor.visitEdge(*edge);
visitor.visitNode(targetNode);
return run();
}
}
// All children of this node have been visited or skipped, so remove from the stack.
visitStack.pop_back();
}
}

private:
Visitor& visitor;
EdgePredicate edgePredicate;
std::set<const NodeType*> visitedNodes;
std::vector<VisitStackElement> visitStack;
};

} // namespace netlist
Loading

0 comments on commit 5030a2a

Please sign in to comment.