-
Notifications
You must be signed in to change notification settings - Fork 318
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[circt-verilog-lsp-server] Add Verilog Language Server
This is a first PR to add a Language Server Protocol (LSP) implementation for Verilog/SystemVerilog using the slang frontend. This enables IDE features like syntax error checking and diagnostics. The server is built as circt-verilog-lsp-server and integrates with CIRCT's existing Verilog import capabilities. It leverages MLIR's LSP server support libraries for the protocol implementation.
- Loading branch information
Showing
25 changed files
with
1,102 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# slang uses exceptions | ||
set(LLVM_REQUIRES_EH ON) | ||
set(LLVM_REQUIRES_RTTI ON) | ||
|
||
# For ABI compatibility, define the DEBUG macro in debug builds. Slang sets this | ||
# internally. If we don't set this here as well, header-defined things like the | ||
# destructor of `Driver`, which is generated in ImportVerilog's compilation | ||
# unit, will destroy a different set of fields than what was potentially built | ||
# or modified by code compiled in the Slang compilation unit. | ||
add_compile_definitions($<$<CONFIG:Debug>:DEBUG>) | ||
|
||
# Disable some compiler warnings caused by slang headers such that the | ||
# `ImportVerilog` build doesn't spew out a ton of warnings that are not related | ||
# to CIRCT. | ||
if (MSVC) | ||
# No idea what to put here | ||
else () | ||
# slang uses exceptions; we intercept these in ImportVerilog | ||
add_compile_options(-fexceptions) | ||
add_compile_options(-frtti) | ||
# slang has some classes with virtual funcs but non-virtual destructor. | ||
add_compile_options(-Wno-non-virtual-dtor) | ||
# some other warnings we've seen | ||
add_compile_options(-Wno-c++98-compat-extra-semi) | ||
add_compile_options(-Wno-ctad-maybe-unsupported) | ||
add_compile_options(-Wno-cast-qual) | ||
# visitor switch statements cover all cases but have default | ||
add_compile_options(-Wno-covered-switch-default) | ||
endif () | ||
|
51 changes: 51 additions & 0 deletions
51
include/circt/Tools/circt-verilog-lsp-server/CirctVerilogLspServerMain.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Main entry function for circt-verilog-lsp-server for when built as standalone | ||
// binary. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef CIRCT_TOOLS_CIRCT_VERILOG_LSP_SERVER_CIRCTVERILOGLSPSERVERMAIN_H | ||
#define CIRCT_TOOLS_CIRCT_VERILOG_LSP_SERVER_CIRCTVERILOGLSPSERVERMAIN_H | ||
#include "mlir/Support/LLVM.h" | ||
#include "llvm/ADT/StringRef.h" | ||
#include <memory> | ||
#include <optional> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace llvm { | ||
struct LogicalResult; | ||
} // namespace llvm | ||
|
||
namespace mlir { | ||
namespace lsp { | ||
class JSONTransport; | ||
} // namespace lsp | ||
} // namespace mlir | ||
|
||
namespace circt { | ||
namespace lsp { | ||
struct VerilogServerOptions { | ||
VerilogServerOptions(const std::vector<std::string> &libDirs) | ||
: libDirs(libDirs) {} | ||
/// Additional list of RTL directories to search. | ||
const std::vector<std::string> &libDirs; | ||
}; | ||
// namespace lsp | ||
|
||
/// Implementation for tools like `circt-verilog-lsp-server`. | ||
llvm::LogicalResult | ||
CirctVerilogLspServerMain(const VerilogServerOptions &options, | ||
mlir::lsp::JSONTransport &transport); | ||
|
||
} // namespace lsp | ||
} // namespace circt | ||
|
||
#endif // CIRCT_TOOLS_CIRCT_VERILOG_LSP_SERVER_CIRCTVERILOGLSPSERVERMAIN_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
add_subdirectory(circt-bmc) | ||
add_subdirectory(circt-lec) | ||
add_subdirectory(rtgtool) | ||
|
||
if(CIRCT_SLANG_FRONTEND_ENABLED) | ||
add_subdirectory(circt-verilog-lsp-server) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
add_subdirectory(VerilogServerImpl) | ||
|
||
add_circt_library(CIRCTVerilogLspServerLib | ||
CirctVerilogLspServerMain.cpp | ||
LSPServer.cpp | ||
LSPUtils.cpp | ||
|
||
ADDITIONAL_HEADER_DIRS | ||
${MLIR_MAIN_INCLUDE_DIR}/circt/Tools/crct-verilog-lsp-server | ||
|
||
LINK_LIBS PUBLIC | ||
CIRCTVerilogLspServerImpl | ||
MLIRLspServerSupportLib | ||
) |
22 changes: 22 additions & 0 deletions
22
lib/Tools/circt-verilog-lsp-server/CirctVerilogLspServerMain.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "circt/Tools/circt-verilog-lsp-server/CirctVerilogLspServerMain.h" | ||
#include "LSPServer.h" | ||
#include "VerilogServer.h" | ||
#include "mlir/Tools/lsp-server-support/Transport.h" | ||
|
||
using namespace mlir; | ||
using namespace mlir::lsp; | ||
|
||
llvm::LogicalResult circt::lsp::CirctVerilogLspServerMain( | ||
const circt::lsp::VerilogServerOptions &options, | ||
mlir::lsp::JSONTransport &transport) { | ||
circt::lsp::VerilogServer server(options); | ||
return circt::lsp::runVerilogLSPServer(server, transport); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "LSPServer.h" | ||
#include "VerilogServer.h" | ||
#include "mlir/Tools/lsp-server-support/Protocol.h" | ||
#include "mlir/Tools/lsp-server-support/Transport.h" | ||
#include <optional> | ||
|
||
#define DEBUG_TYPE "circt-verilog-lsp-server" | ||
|
||
using namespace mlir; | ||
using namespace mlir::lsp; | ||
|
||
//===----------------------------------------------------------------------===// | ||
// LSPServer | ||
//===----------------------------------------------------------------------===// | ||
|
||
namespace { | ||
struct LSPServer { | ||
LSPServer(circt::lsp::VerilogServer &server, JSONTransport &transport) | ||
: server(server), transport(transport) {} | ||
|
||
//===--------------------------------------------------------------------===// | ||
// Initialization | ||
//===--------------------------------------------------------------------===// | ||
|
||
void onInitialize(const InitializeParams ¶ms, | ||
Callback<llvm::json::Value> reply); | ||
void onInitialized(const InitializedParams ¶ms); | ||
void onShutdown(const NoParams ¶ms, Callback<std::nullptr_t> reply); | ||
|
||
//===--------------------------------------------------------------------===// | ||
// Document Change | ||
//===--------------------------------------------------------------------===// | ||
|
||
void onDocumentDidOpen(const DidOpenTextDocumentParams ¶ms); | ||
void onDocumentDidClose(const DidCloseTextDocumentParams ¶ms); | ||
void onDocumentDidChange(const DidChangeTextDocumentParams ¶ms); | ||
|
||
//===--------------------------------------------------------------------===// | ||
// Fields | ||
//===--------------------------------------------------------------------===// | ||
|
||
circt::lsp::VerilogServer &server; | ||
JSONTransport &transport; | ||
|
||
/// An outgoing notification used to send diagnostics to the client when they | ||
/// are ready to be processed. | ||
OutgoingNotification<PublishDiagnosticsParams> publishDiagnostics; | ||
|
||
/// Used to indicate that the 'shutdown' request was received from the | ||
/// Language Server client. | ||
bool shutdownRequestReceived = false; | ||
}; | ||
} // namespace | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Initialization | ||
//===----------------------------------------------------------------------===// | ||
|
||
void LSPServer::onInitialize(const InitializeParams ¶ms, | ||
Callback<llvm::json::Value> reply) { | ||
// Send a response with the capabilities of this server. | ||
llvm::json::Object serverCaps{ | ||
{"textDocumentSync", | ||
llvm::json::Object{ | ||
{"openClose", true}, | ||
{"change", (int)TextDocumentSyncKind::Incremental}, | ||
{"save", true}, | ||
}}}; | ||
|
||
llvm::json::Object result{ | ||
{{"serverInfo", llvm::json::Object{{"name", "circt-verilog-lsp-server"}, | ||
{"version", "0.0.1"}}}, | ||
{"capabilities", std::move(serverCaps)}}}; | ||
reply(std::move(result)); | ||
} | ||
void LSPServer::onInitialized(const InitializedParams &) {} | ||
void LSPServer::onShutdown(const NoParams &, Callback<std::nullptr_t> reply) { | ||
shutdownRequestReceived = true; | ||
reply(nullptr); | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Document Change | ||
//===----------------------------------------------------------------------===// | ||
|
||
void LSPServer::onDocumentDidOpen(const DidOpenTextDocumentParams ¶ms) { | ||
PublishDiagnosticsParams diagParams(params.textDocument.uri, | ||
params.textDocument.version); | ||
server.addDocument(params.textDocument.uri, params.textDocument.text, | ||
params.textDocument.version, diagParams.diagnostics); | ||
|
||
// Publish any recorded diagnostics. | ||
publishDiagnostics(diagParams); | ||
} | ||
|
||
void LSPServer::onDocumentDidClose(const DidCloseTextDocumentParams ¶ms) { | ||
std::optional<int64_t> version = | ||
server.removeDocument(params.textDocument.uri); | ||
if (!version) | ||
return; | ||
|
||
// Empty out the diagnostics shown for this document. This will clear out | ||
// anything currently displayed by the client for this document (e.g. in the | ||
// "Problems" pane of VSCode). | ||
publishDiagnostics( | ||
PublishDiagnosticsParams(params.textDocument.uri, *version)); | ||
} | ||
|
||
void LSPServer::onDocumentDidChange(const DidChangeTextDocumentParams ¶ms) { | ||
PublishDiagnosticsParams diagParams(params.textDocument.uri, | ||
params.textDocument.version); | ||
server.updateDocument(params.textDocument.uri, params.contentChanges, | ||
params.textDocument.version, diagParams.diagnostics); | ||
|
||
// Publish any recorded diagnostics. | ||
publishDiagnostics(diagParams); | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Entry Point | ||
//===----------------------------------------------------------------------===// | ||
|
||
LogicalResult circt::lsp::runVerilogLSPServer(VerilogServer &server, | ||
JSONTransport &transport) { | ||
LSPServer lspServer(server, transport); | ||
MessageHandler messageHandler(transport); | ||
|
||
// Initialization | ||
messageHandler.method("initialize", &lspServer, &LSPServer::onInitialize); | ||
messageHandler.notification("initialized", &lspServer, | ||
&LSPServer::onInitialized); | ||
messageHandler.method("shutdown", &lspServer, &LSPServer::onShutdown); | ||
|
||
// Document Changes | ||
messageHandler.notification("textDocument/didOpen", &lspServer, | ||
&LSPServer::onDocumentDidOpen); | ||
messageHandler.notification("textDocument/didClose", &lspServer, | ||
&LSPServer::onDocumentDidClose); | ||
messageHandler.notification("textDocument/didChange", &lspServer, | ||
&LSPServer::onDocumentDidChange); | ||
|
||
// Diagnostics | ||
lspServer.publishDiagnostics = | ||
messageHandler.outgoingNotification<PublishDiagnosticsParams>( | ||
"textDocument/publishDiagnostics"); | ||
|
||
// Run the main loop of the transport. | ||
if (llvm::Error error = transport.run(messageHandler)) { | ||
Logger::error("Transport error: {0}", error); | ||
llvm::consumeError(std::move(error)); | ||
return failure(); | ||
} | ||
|
||
return success(lspServer.shutdownRequestReceived); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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 LIB_CIRCT_TOOLS_CIRCT_VERILOG_LSP_LSPSERVER_H | ||
#define LIB_CIRCT_TOOLS_CIRCT_VERILOG_LSP_LSPSERVER_H | ||
|
||
#include <memory> | ||
|
||
namespace llvm { | ||
struct LogicalResult; | ||
} // namespace llvm | ||
namespace mlir { | ||
namespace lsp { | ||
class JSONTransport; | ||
} // namespace lsp | ||
} // namespace mlir | ||
|
||
namespace circt { | ||
namespace lsp { | ||
class VerilogServer; | ||
|
||
/// Run the main loop of the LSP server using the given Verilog server and | ||
/// transport. | ||
llvm::LogicalResult runVerilogLSPServer(VerilogServer &server, | ||
mlir::lsp::JSONTransport &transport); | ||
|
||
} // namespace lsp | ||
} // namespace circt | ||
|
||
#endif // LIB_CIRCT_TOOLS_CIRCT_VERILOG_LSP_LSPSERVER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file contains utilities for CIRCT Verilog LSP server. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "LSPUtils.h" | ||
#include "mlir/Tools/lsp-server-support/Logging.h" | ||
|
||
void circt::lsp::Logger::error(Twine message) { | ||
mlir::lsp::Logger::error("{}", message); | ||
} | ||
|
||
void circt::lsp::Logger::info(Twine message) { | ||
mlir::lsp::Logger::info("{}", message); | ||
} | ||
|
||
void circt::lsp::Logger::debug(Twine message) { | ||
mlir::lsp::Logger::debug("{}", message); | ||
} |
Oops, something went wrong.