Skip to content
Open
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 xls/codegen/vast/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ cc_library(
":verilog_keywords",
"//xls/common:indent",
"//xls/common:visitor",
"//xls/common/status:ret_check",
"//xls/common/status:status_macros",
"//xls/ir:bits",
"//xls/ir:bits_ops",
Expand Down
60 changes: 42 additions & 18 deletions xls/codegen/vast/vast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "absl/types/variant.h"
#include "xls/codegen/vast/verilog_keywords.h"
#include "xls/common/indent.h"
#include "xls/common/status/ret_check.h"
#include "xls/common/status/status_macros.h"
#include "xls/common/visitor.h"
#include "xls/ir/bits_ops.h"
Expand Down Expand Up @@ -729,37 +730,49 @@ LogicRef* Module::AddPortDef(ModulePortDirection direction, Def* def,
}

LogicRef* Module::AddInputInternal(std::string_view name, DataType* type,
const SourceInfo& loc) {
return AddPortDef(
ModulePortDirection::kInput,
type->IsUserDefined()
? static_cast<Def*>(file()->Make<UserDefinedDef>(loc, name, type))
: static_cast<Def*>(file()->Make<WireDef>(loc, name, type)),
loc);
DataKind data_kind, const SourceInfo& loc) {
Def* def;
if (type->IsUserDefined()) {
def = static_cast<Def*>(file()->Make<UserDefinedDef>(loc, name, type));
} else if (data_kind == DataKind::kWire) {
def = static_cast<Def*>(file()->Make<WireDef>(loc, name, type));
} else {
CHECK_EQ(data_kind, DataKind::kLogic);
def = static_cast<Def*>(file()->Make<LogicDef>(loc, name, type));
}
return AddPortDef(ModulePortDirection::kInput, def, loc);
}

LogicRef* Module::AddOutputInternal(std::string_view name, DataType* type,
const SourceInfo& loc) {
return AddPortDef(
ModulePortDirection::kOutput,
type->IsUserDefined()
? static_cast<Def*>(file()->Make<UserDefinedDef>(loc, name, type))
: static_cast<Def*>(file()->Make<WireDef>(loc, name, type)),
loc);
DataKind data_kind, const SourceInfo& loc) {
Def* def;
if (type->IsUserDefined()) {
def = static_cast<Def*>(file()->Make<UserDefinedDef>(loc, name, type));
} else if (data_kind == DataKind::kWire) {
def = static_cast<Def*>(file()->Make<WireDef>(loc, name, type));
} else {
CHECK_EQ(data_kind, DataKind::kLogic);
def = static_cast<Def*>(file()->Make<LogicDef>(loc, name, type));
}
return AddPortDef(ModulePortDirection::kOutput, def, loc);
}

absl::StatusOr<LogicRef*> Module::AddInput(std::string_view name,
DataType* type,
const SourceInfo& loc) {
const SourceInfo& loc,
DataKind data_kind) {
XLS_RET_CHECK(data_kind == DataKind::kWire || data_kind == DataKind::kLogic);
XLS_RETURN_IF_ERROR(NoteDefined(&defined_names_, name, "input"));
return AddInputInternal(name, type, loc);
return AddInputInternal(name, type, data_kind, loc);
}

absl::StatusOr<LogicRef*> Module::AddOutput(std::string_view name,
DataType* type,
const SourceInfo& loc) {
const SourceInfo& loc,
DataKind data_kind) {
XLS_RET_CHECK(data_kind == DataKind::kWire || data_kind == DataKind::kLogic);
XLS_RETURN_IF_ERROR(NoteDefined(&defined_names_, name, "output"));
return AddOutputInternal(name, type, loc);
return AddOutputInternal(name, type, data_kind, loc);
}

LogicRef* Module::AddRegInternal(std::string_view name, DataType* type,
Expand Down Expand Up @@ -796,6 +809,17 @@ absl::StatusOr<LogicRef*> Module::AddWire(std::string_view name, DataType* type,
return AddWireInternal(name, type, loc, section);
}

absl::StatusOr<LogicRef*> Module::AddLogic(std::string_view name,
DataType* type,
const SourceInfo& loc,
ModuleSection* section) {
XLS_RETURN_IF_ERROR(NoteDefined(&defined_names_, name, "logic"));
if (section == nullptr) {
section = &top_;
}
return file()->Make<LogicRef>(loc, section->Add<LogicDef>(loc, name, type));
}

LogicRef* Module::AddWireInternal(std::string_view name, DataType* type,
Expression* init, const SourceInfo& loc,
ModuleSection* section) {
Expand Down
17 changes: 13 additions & 4 deletions xls/codegen/vast/vast.h
Original file line number Diff line number Diff line change
Expand Up @@ -2277,10 +2277,15 @@ class Module final : public VastNode {
template <typename T, typename... Args>
inline T* Add(const SourceInfo& loc, Args&&... args);

// Add an input or output port to the module. `data_kind` must be either kWire
// or kLogic and indicates whether to use `wire` or `logic` when defining the
// port if `type` is a bit vector or scalar type.
absl::StatusOr<LogicRef*> AddInput(std::string_view name, DataType* type,
const SourceInfo& loc);
const SourceInfo& loc,
DataKind data_kind = DataKind::kWire);
absl::StatusOr<LogicRef*> AddOutput(std::string_view name, DataType* type,
const SourceInfo& loc);
const SourceInfo& loc,
DataKind data_kind = DataKind::kWire);

absl::StatusOr<LogicRef*> AddReg(std::string_view name, DataType* type,
const SourceInfo& loc,
Expand All @@ -2289,6 +2294,10 @@ class Module final : public VastNode {
absl::StatusOr<LogicRef*> AddWire(std::string_view name, DataType* type,
const SourceInfo& loc,
ModuleSection* section = nullptr);
absl::StatusOr<LogicRef*> AddLogic(std::string_view name, DataType* type,
const SourceInfo& loc,
ModuleSection* section = nullptr);

// Variation of AddWire that takes an initializer expression.
absl::StatusOr<LogicRef*> AddWire(std::string_view name, DataType* type,
Expression* init, const SourceInfo& loc,
Expand Down Expand Up @@ -2326,9 +2335,9 @@ class Module final : public VastNode {
// Adds a (wire) port to this module with the given name and type. Returns
// a reference to that wire.
LogicRef* AddInputInternal(std::string_view name, DataType* type,
const SourceInfo& loc);
DataKind data_kind, const SourceInfo& loc);
LogicRef* AddOutputInternal(std::string_view name, DataType* type,
const SourceInfo& loc);
DataKind data_kind, const SourceInfo& loc);

// Adds a reg/wire definition to the module with the given type and, for regs,
// initialized with the given value. Returns a reference to the definition.
Expand Down
32 changes: 30 additions & 2 deletions xls/codegen/vast/vast_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@
#include <utility>
#include <vector>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/types/span.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "xls/common/status/matchers.h"
#include "xls/ir/bits.h"
#include "xls/ir/fileno.h"
Expand Down Expand Up @@ -1553,6 +1553,34 @@ TEST_P(VastTest, InstantiationWithEmptyPort) {
);)");
}

TEST_P(VastTest, ModuleWithLogicDataKind) {
if (GetFileType() != FileType::kSystemVerilog) {
GTEST_SKIP();
}

VerilogFile f(GetFileType());
Module* m = f.AddModule("top", SourceInfo());

XLS_ASSERT_OK(m->AddInput("a", f.ScalarType(SourceInfo()), SourceInfo(),
DataKind::kLogic)
.status());
XLS_ASSERT_OK(m->AddOutput("y", f.BitVectorType(32, SourceInfo()),
SourceInfo(), DataKind::kLogic)
.status());

XLS_ASSERT_OK(
m->AddLogic("foo", f.BitVectorType(8, SourceInfo()), SourceInfo())
.status());

EXPECT_EQ(m->Emit(nullptr),
R"(module top(
input logic a,
output logic [31:0] y
);
logic [7:0] foo;
endmodule)");
}

TEST_P(VastTest, TemplateInstantiationTest) {
VerilogFile f(GetFileType());
auto* a_def =
Expand Down
5 changes: 5 additions & 0 deletions xls/public/c_api_symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ xls_vast_logic_ref_get_name
xls_vast_make_verilog_file
xls_vast_parameter_ref_as_expression
xls_vast_slice_as_expression
xls_vast_statement_block_add_blocking_assignment
xls_vast_statement_block_add_nonblocking_assignment
xls_vast_verilog_file_add_include
xls_vast_verilog_file_add_module
Expand Down Expand Up @@ -317,8 +318,12 @@ xls_vast_verilog_file_make_slice_i64
xls_vast_verilog_file_make_ternary
xls_vast_verilog_file_make_unary
xls_vast_verilog_module_add_always_at
xls_vast_verilog_module_add_always_comb
xls_vast_verilog_module_add_always_ff
xls_vast_verilog_module_add_input
xls_vast_verilog_module_add_logic
xls_vast_verilog_module_add_logic_input
xls_vast_verilog_module_add_logic_output
xls_vast_verilog_module_add_member_comment
xls_vast_verilog_module_add_member_continuous_assignment
xls_vast_verilog_module_add_member_instantiation
Expand Down
70 changes: 70 additions & 0 deletions xls/public/c_api_vast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,28 @@ struct xls_vast_logic_ref* xls_vast_verilog_module_add_output(
return reinterpret_cast<xls_vast_logic_ref*>(logic_ref.value());
}

struct xls_vast_logic_ref* xls_vast_verilog_module_add_logic_input(
struct xls_vast_verilog_module* m, const char* name,
struct xls_vast_data_type* type) {
auto* cpp_module = reinterpret_cast<xls::verilog::Module*>(m);
auto* cpp_type = reinterpret_cast<xls::verilog::DataType*>(type);
absl::StatusOr<xls::verilog::LogicRef*> logic_ref = cpp_module->AddInput(
name, cpp_type, xls::SourceInfo(), xls::verilog::DataKind::kLogic);
CHECK_OK(logic_ref.status());
return reinterpret_cast<xls_vast_logic_ref*>(logic_ref.value());
}

struct xls_vast_logic_ref* xls_vast_verilog_module_add_logic_output(
struct xls_vast_verilog_module* m, const char* name,
struct xls_vast_data_type* type) {
auto* cpp_module = reinterpret_cast<xls::verilog::Module*>(m);
auto* cpp_type = reinterpret_cast<xls::verilog::DataType*>(type);
absl::StatusOr<xls::verilog::LogicRef*> logic_ref = cpp_module->AddOutput(
name, cpp_type, xls::SourceInfo(), xls::verilog::DataKind::kLogic);
CHECK_OK(logic_ref.status());
return reinterpret_cast<xls_vast_logic_ref*>(logic_ref.value());
}

struct xls_vast_logic_ref* xls_vast_verilog_module_add_wire(
struct xls_vast_verilog_module* m, const char* name,
struct xls_vast_data_type* type) {
Expand Down Expand Up @@ -609,6 +631,23 @@ bool xls_vast_verilog_module_add_always_at(
return true;
}

bool xls_vast_verilog_module_add_always_comb(
struct xls_vast_verilog_module* m,
struct xls_vast_always_base** out_always_comb, char** error_out) {
auto* cpp_module = reinterpret_cast<xls::verilog::Module*>(m);
xls::verilog::AlwaysComb* cpp_always_comb =
cpp_module->Add<xls::verilog::AlwaysComb>(xls::SourceInfo());
if (cpp_always_comb == nullptr) {
*error_out = xls::ToOwnedCString(
"Failed to create always_comb block in Verilog module.");
*out_always_comb = nullptr;
return false;
}
*out_always_comb = reinterpret_cast<xls_vast_always_base*>(cpp_always_comb);
*error_out = nullptr;
return true;
}

bool xls_vast_verilog_module_add_reg(struct xls_vast_verilog_module* m,
const char* name,
struct xls_vast_data_type* type,
Expand All @@ -629,6 +668,25 @@ bool xls_vast_verilog_module_add_reg(struct xls_vast_verilog_module* m,
return true;
}

bool xls_vast_verilog_module_add_logic(
struct xls_vast_verilog_module* m, const char* name,
struct xls_vast_data_type* type, struct xls_vast_logic_ref** out_logic_ref,
char** error_out) {
auto* cpp_module = reinterpret_cast<xls::verilog::Module*>(m);
auto* cpp_data_type = reinterpret_cast<xls::verilog::DataType*>(type);
absl::StatusOr<xls::verilog::LogicRef*> cpp_logic_ref_status =
cpp_module->AddLogic(name, cpp_data_type, xls::SourceInfo());
if (!cpp_logic_ref_status.ok()) {
*error_out = xls::ToOwnedCString(cpp_logic_ref_status.status().ToString());
*out_logic_ref = nullptr;
return false;
}
*out_logic_ref =
reinterpret_cast<xls_vast_logic_ref*>(cpp_logic_ref_status.value());
*error_out = nullptr;
return true;
}

struct xls_vast_expression* xls_vast_verilog_file_make_pos_edge(
struct xls_vast_verilog_file* f, struct xls_vast_expression* signal_expr) {
auto* cpp_file = reinterpret_cast<xls::verilog::VerilogFile*>(f);
Expand Down Expand Up @@ -674,6 +732,18 @@ struct xls_vast_statement* xls_vast_statement_block_add_nonblocking_assignment(
return reinterpret_cast<xls_vast_statement*>(cpp_assignment);
}

struct xls_vast_statement* xls_vast_statement_block_add_blocking_assignment(
struct xls_vast_statement_block* block, struct xls_vast_expression* lhs,
struct xls_vast_expression* rhs) {
auto* cpp_block = reinterpret_cast<xls::verilog::StatementBlock*>(block);
auto* cpp_lhs = reinterpret_cast<xls::verilog::Expression*>(lhs);
auto* cpp_rhs = reinterpret_cast<xls::verilog::Expression*>(rhs);
xls::verilog::BlockingAssignment* cpp_assignment =
cpp_block->Add<xls::verilog::BlockingAssignment>(xls::SourceInfo(),
cpp_lhs, cpp_rhs);
return reinterpret_cast<xls_vast_statement*>(cpp_assignment);
}

struct xls_vast_module_port** xls_vast_verilog_module_get_ports(
struct xls_vast_verilog_module* m, size_t* out_count) {
CHECK(out_count != nullptr);
Expand Down
28 changes: 28 additions & 0 deletions xls/public/c_api_vast.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ struct xls_vast_logic_ref* xls_vast_verilog_module_add_input(
struct xls_vast_logic_ref* xls_vast_verilog_module_add_output(
struct xls_vast_verilog_module* m, const char* name,
struct xls_vast_data_type* type);
// Adds input/output ports using SystemVerilog `logic` for the declaration.
struct xls_vast_logic_ref* xls_vast_verilog_module_add_logic_input(
struct xls_vast_verilog_module* m, const char* name,
struct xls_vast_data_type* type);
struct xls_vast_logic_ref* xls_vast_verilog_module_add_logic_output(
struct xls_vast_verilog_module* m, const char* name,
struct xls_vast_data_type* type);
struct xls_vast_logic_ref* xls_vast_verilog_module_add_wire(
struct xls_vast_verilog_module* m, const char* name,
struct xls_vast_data_type* type);
Expand Down Expand Up @@ -324,6 +331,12 @@ struct xls_vast_statement* xls_vast_statement_block_add_nonblocking_assignment(
struct xls_vast_statement_block* block, struct xls_vast_expression* lhs,
struct xls_vast_expression* rhs);

// Adds a blocking assignment statement (lhs = rhs) to a statement block and
// returns a pointer to the created statement.
struct xls_vast_statement* xls_vast_statement_block_add_blocking_assignment(
struct xls_vast_statement_block* block, struct xls_vast_expression* lhs,
struct xls_vast_expression* rhs);

// Emits/formats the contents of the given verilog file to a string.
//
// Note: caller owns the returned string, to be freed by `xls_c_str_free`.
Expand Down Expand Up @@ -351,6 +364,13 @@ bool xls_vast_verilog_module_add_always_at(
size_t sensitivity_list_count, struct xls_vast_always_base** out_always_at,
char** error_out);

// Adds an always_comb block to the module (SystemVerilog).
// Returns true on success. On failure, returns false and sets error_out. The
// caller is responsible for freeing error_out if it is not NULL.
bool xls_vast_verilog_module_add_always_comb(
struct xls_vast_verilog_module* m,
struct xls_vast_always_base** out_always_comb, char** error_out);

// Adds a register (reg) definition to the module.
// Returns true on success. On failure, returns false and sets error_out.
// The caller is responsible for freeing error_out if it is not NULL.
Expand All @@ -360,6 +380,14 @@ bool xls_vast_verilog_module_add_reg(struct xls_vast_verilog_module* m,
struct xls_vast_logic_ref** out_reg_ref,
char** error_out);

// Adds a `logic` variable definition to the module.
// Returns true on success. On failure, returns false and sets error_out.
// The caller is responsible for freeing error_out if it is not NULL.
bool xls_vast_verilog_module_add_logic(
struct xls_vast_verilog_module* m, const char* name,
struct xls_vast_data_type* type, struct xls_vast_logic_ref** out_logic_ref,
char** error_out);

// Creates a positive edge expression (e.g., "posedge clk").
// 'signal_expr' is typically a logic_ref_as_expression.
struct xls_vast_expression* xls_vast_verilog_file_make_pos_edge(
Expand Down
Loading