Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/Conversion/ImportVerilog/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include(SlangCompilerOptions)

add_circt_translation_library(CIRCTImportVerilog
ImportVerilogDebugStream.cpp
AssertionExpr.cpp
Expressions.cpp
FormatStrings.cpp
Expand Down
4 changes: 3 additions & 1 deletion lib/Conversion/ImportVerilog/Expressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -994,8 +994,10 @@ struct RvalueExprVisitor : public ExprVisitor {

case (1):
value = context.convertRvalueExpression(*args[0]);
if (!value)
if (!value){
dbgs(loc) << "Failed to convert RValue Expression of call " << subroutine.name;
return {};
}
result = context.convertSystemCallArity1(subroutine, loc, value);
break;

Expand Down
4 changes: 3 additions & 1 deletion lib/Conversion/ImportVerilog/HierarchicalNames.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,10 @@ LogicalResult Context::traverseInstanceBody(const slang::ast::Symbol &symbol) {
if (auto *instBodySymbol = symbol.as_if<slang::ast::InstanceBodySymbol>())
for (auto &member : instBodySymbol->members()) {
auto loc = convertLocation(member.location);
if (failed(member.visit(InstBodyVisitor(*this, loc))))
if (failed(member.visit(InstBodyVisitor(*this, loc)))) {
dbgs(member.location) << ": Failed to convert symbol " << member.name;
return failure();
}
}
return success();
}
8 changes: 6 additions & 2 deletions lib/Conversion/ImportVerilog/ImportVerilog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,10 @@ LogicalResult ImportDriver::importVerilog(ModuleOp module) {
auto compilation = driver.createCompilation();
for (auto &diag : compilation->getAllDiagnostics())
driver.diagEngine.issue(diag);
if (!parseSuccess || driver.diagEngine.getNumErrors() > 0)
if (!parseSuccess || driver.diagEngine.getNumErrors() > 0) {
dbgs() << "Failed to parse and elaborate inputs!";
return failure();
}
compileTimer.stop();

// If we were only supposed to lint the input, return here. This leaves the
Expand All @@ -278,8 +280,10 @@ LogicalResult ImportDriver::importVerilog(ModuleOp module) {
debug::DebugDialect>();
auto conversionTimer = ts.nest("Verilog to dialect mapping");
Context context(options, *compilation, module, driver.sourceManager);
if (failed(context.convertCompilation()))
if (failed(context.convertCompilation())) {
dbgs() << "Failed to convert Slang compilation!";
return failure();
}
conversionTimer.stop();

// Run the verifier on the constructed module to ensure it is clean.
Expand Down
28 changes: 28 additions & 0 deletions lib/Conversion/ImportVerilog/ImportVerilogDebugStream.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "ImportVerilogDebugStream.h"
#include "ImportVerilogInternals.h"

ImportVerilogDebugStream
dbgs(const std::optional<mlir::Location> sourceLocation,
const std::optional<std::source_location> cl) {

return ImportVerilogDebugStream(sourceLocation, cl);
}

ImportVerilogDebugStream circt::ImportVerilog::Context::dbgs(
const std::optional<std::variant<mlir::Location, slang::SourceLocation>>
sourceLocation,
const std::optional<std::source_location> cl) {

std::optional<mlir::Location> mlirLoc = {};

if (sourceLocation) {
if (auto *ml = std::get_if<mlir::Location>(&*sourceLocation)) {
mlirLoc = *ml;
} else if (auto *sl =
std::get_if<slang::SourceLocation>(&*sourceLocation)) {
mlirLoc = convertLocation(*sl);
}
}

return ImportVerilogDebugStream(mlirLoc, cl);
}
93 changes: 93 additions & 0 deletions lib/Conversion/ImportVerilog/ImportVerilogDebugStream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//===- ImportVerilogDebugStream.h - A debug stream wrapper for importverilog
//---------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef IMPORT_VERILOG_DEBUG_H
#define IMPORT_VERILOG_DEBUG_H

#include "mlir/IR/Location.h"
#include "slang/ast/Compilation.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>
#include <source_location>
#include <utility>

// If includer defined DEBUG_TYPE, use that; else fall back to our default.
#ifndef IMPORTVERILOG_DEBUG_TYPE
#ifdef DEBUG_TYPE
#define IMPORTVERILOG_DEBUG_TYPE DEBUG_TYPE
#else
#define IMPORTVERILOG_DEBUG_TYPE "import-verilog"
#endif
#endif

struct ImportVerilogDebugStream {
std::optional<mlir::Location> srcLoc;
std::optional<std::source_location> compLoc;
llvm::SmallString<128> buffer;
llvm::raw_svector_ostream os;

ImportVerilogDebugStream(std::optional<mlir::Location> sl,
std::optional<std::source_location> cl)
: srcLoc(sl), compLoc(cl), os(buffer) {}

inline ~ImportVerilogDebugStream() {
DEBUG_WITH_TYPE(IMPORTVERILOG_DEBUG_TYPE, {
if (compLoc)
llvm::dbgs() << compLoc->file_name() << ":" << compLoc->line() << " ("
<< compLoc->function_name() << ") ";
if (srcLoc) {
srcLoc->print(llvm::dbgs());
llvm::dbgs() << ": ";
}
llvm::dbgs() << buffer << "\n";
});
}

inline llvm::raw_ostream &stream() { return os; }
inline const llvm::raw_ostream &stream() const { return os; }
};

// lvalue wrapper
template <typename T>
inline ImportVerilogDebugStream &operator<<(ImportVerilogDebugStream &s,
const T &v) {
s.stream() << v;
return s;
}

// rvalue/temporary wrapper
template <typename T>
inline ImportVerilogDebugStream &&operator<<(ImportVerilogDebugStream &&s,
const T &v) {
s.stream() << v;
return std::move(s);
}

// support ostream manipulators that look like functions, e.g. write_hex, etc.
inline ImportVerilogDebugStream &
operator<<(ImportVerilogDebugStream &s,
llvm::raw_ostream &(*manip)(llvm::raw_ostream &)) {
manip(s.stream());
return s;
}
inline ImportVerilogDebugStream &&
operator<<(ImportVerilogDebugStream &&s,
llvm::raw_ostream &(*manip)(llvm::raw_ostream &)) {
manip(s.stream());
return std::move(s);
}

/// Helper function to set up a debug stream with reasonable defaults
ImportVerilogDebugStream
dbgs(std::optional<mlir::Location> sourceLocation = {},
std::optional<std::source_location> cl = std::source_location::current());

#endif // IMPORT_VERILOG_DEBUG_H
9 changes: 9 additions & 0 deletions lib/Conversion/ImportVerilog/ImportVerilogInternals.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#ifndef CONVERSION_IMPORTVERILOG_IMPORTVERILOGINTERNALS_H
#define CONVERSION_IMPORTVERILOG_IMPORTVERILOGINTERNALS_H

#include "ImportVerilogDebugStream.h"
#include "circt/Conversion/ImportVerilog.h"
#include "circt/Dialect/Debug/DebugOps.h"
#include "circt/Dialect/HW/HWOps.h"
Expand Down Expand Up @@ -94,6 +95,14 @@ struct Context {
/// Convert a slang `SourceRange` into an MLIR `Location`.
Location convertLocation(slang::SourceRange range);

/// A convenient debug stream wrapper which attaches information about input
/// source location and compiler source location; also accepts
/// slang::SourceLocation and tries to unwrap it.
ImportVerilogDebugStream dbgs(
std::optional<std::variant<mlir::Location, slang::SourceLocation>>
sourceLocation = {},
std::optional<std::source_location> cl = std::source_location::current());

/// Convert a slang type into an MLIR type. Returns null on failure. Uses the
/// provided location for error reporting, or tries to guess one from the
/// given type. Types tend to have unreliable location information, so it's
Expand Down
22 changes: 18 additions & 4 deletions lib/Conversion/ImportVerilog/Statements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include "ImportVerilogInternals.h"
#include "slang/ast/Compilation.h"
#include "slang/ast/SystemSubroutine.h"
#include "slang/syntax/AllSyntax.h"
#include "llvm/ADT/ScopeExit.h"
#include <slang/ast/SFormat.h>

using namespace mlir;
using namespace circt;
Expand Down Expand Up @@ -138,8 +140,11 @@ struct StmtVisitor {
mlir::emitWarning(loc, "unreachable code");
break;
}
if (failed(context.convertStatement(*stmt)))
if (failed(context.convertStatement(*stmt))) {
context.dbgs(stmt->syntax->sourceRange().start())
<< "Failed to convert statement " << stmt->syntax->toString();
return failure();
}
}
return success();
}
Expand All @@ -157,17 +162,26 @@ struct StmtVisitor {
std::get_if<slang::ast::CallExpression::SystemCallInfo>(
&call->subroutine)) {
auto handled = visitSystemCall(stmt, *call, *info);
if (failed(handled))
if (failed(handled)) {
context.dbgs(stmt.sourceRange.start())
<< "Failed to convert system call " << stmt.syntax->toString();
return failure();
}
if (handled == true)
return success();
}
context.dbgs(stmt.sourceRange.start())
<< "Assuming statement " << stmt.syntax->toString()
<< " is not a system task";
}

auto value = context.convertRvalueExpression(stmt.expr);
if (!value)
if (!value) {
context.dbgs(stmt.sourceRange.start())
<< "Failed to convert expression statement as RValue "
<< stmt.expr.syntax->toString();
return failure();

}
// Expressions like calls to void functions return a dummy value that has no
// uses. If the returned value is trivially dead, remove it.
if (auto *defOp = value.getDefiningOp())
Expand Down
25 changes: 18 additions & 7 deletions lib/Conversion/ImportVerilog/Structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,23 +669,30 @@ LogicalResult Context::convertCompilation() {
for (auto *unit : root.compilationUnits) {
for (const auto &member : unit->members()) {
auto loc = convertLocation(member.location);
if (failed(member.visit(RootVisitor(*this, loc))))
if (failed(member.visit(RootVisitor(*this, loc)))) {
dbgs(loc) << "Failed to convert top-level object " << member.name;
return failure();
}
}
}

// Prime the root definition worklist by adding all the top-level modules.
SmallVector<const slang::ast::InstanceSymbol *> topInstances;
for (auto *inst : root.topInstances)
if (!convertModuleHeader(&inst->body))
if (!convertModuleHeader(&inst->body)) {
dbgs(inst->location) << ": Failed to convert module header of module "
<< inst->name;
return failure();

}
// Convert all the root module definitions.
while (!moduleWorklist.empty()) {
auto *module = moduleWorklist.front();
moduleWorklist.pop();
if (failed(convertModuleBody(module)))
if (failed(convertModuleBody(module))) {
dbgs(module->location)
<< ": Failed to convert module body of module " << module->name;
return failure();
}
}

return success();
Expand Down Expand Up @@ -1057,8 +1064,10 @@ Context::convertFunction(const slang::ast::SubroutineSymbol &subroutine) {

// First get or create the function declaration.
auto *lowering = declareFunction(subroutine);
if (!lowering)
if (!lowering) {
dbgs(subroutine.location) << "Failed to lower function " << subroutine.name;
return failure();
}
ValueSymbolScope scope(valueSymbols);

// Create a function body block and populate it with block arguments.
Expand Down Expand Up @@ -1101,9 +1110,11 @@ Context::convertFunction(const slang::ast::SubroutineSymbol &subroutine) {
valueSymbols.insert(subroutine.returnValVar, returnVar);
}

if (failed(convertStatement(subroutine.getBody())))
if (failed(convertStatement(subroutine.getBody()))) {
dbgs(subroutine.location)
<< "Failed to convert body of function " << subroutine.name;
return failure();

}
// If there was no explicit return statement provided by the user, insert a
// default one.
if (builder.getBlock()) {
Expand Down
Loading