diff --git a/xls/codegen/module_builder.cc b/xls/codegen/module_builder.cc index 90a93b4c49..84684161d1 100644 --- a/xls/codegen/module_builder.cc +++ b/xls/codegen/module_builder.cc @@ -439,9 +439,8 @@ absl::StatusOr ModuleBuilder::AddInputPort( if (sv_type && options_.emit_sv_types()) { XLS_ASSIGN_OR_RETURN( LogicRef * port, - module_->AddInput( - name, file_->ExternType(raw_bits_type, *sv_type, SourceInfo()), - loc ? loc.value() : SourceInfo())); + module_->AddInput(name, file_->ExternType(*sv_type, SourceInfo()), + loc ? loc.value() : SourceInfo())); if (!sv_type.has_value()) { return port; } @@ -485,8 +484,7 @@ absl::Status ModuleBuilder::AddOutputPort( } XLS_ASSIGN_OR_RETURN( output_port, - module_->AddOutput(name, - file_->ExternType(bits_type, *sv_type, SourceInfo()), + module_->AddOutput(name, file_->ExternType(*sv_type, SourceInfo()), SourceInfo())); } else { XLS_ASSIGN_OR_RETURN(output_port, @@ -524,8 +522,7 @@ absl::Status ModuleBuilder::AddOutputPort( if (sv_type && options_.emit_sv_types()) { XLS_ASSIGN_OR_RETURN( output_port, - module_->AddOutput(name, - file_->ExternType(bits_type, *sv_type, SourceInfo()), + module_->AddOutput(name, file_->ExternType(*sv_type, SourceInfo()), SourceInfo())); } else { XLS_ASSIGN_OR_RETURN(output_port, diff --git a/xls/codegen/vast/vast.cc b/xls/codegen/vast/vast.cc index 706d3eb515..6ae820fcc8 100644 --- a/xls/codegen/vast/vast.cc +++ b/xls/codegen/vast/vast.cc @@ -460,6 +460,13 @@ std::string MacroRef::Emit(LineInfo* line_info) const { LineInfoStart(line_info, this); LineInfoIncrease(line_info, NumberOfNewlines(name_)); LineInfoEnd(line_info, this); + if (args_.has_value()) { + std::string args_str = absl::StrJoin( + args_.value(), ", ", [=](std::string* out, Expression* e) { + absl::StrAppend(out, e->Emit(line_info)); + }); + return absl::StrCat("`", name_, "(", args_str, ")"); + } return absl::StrCat("`", name_); } @@ -470,9 +477,9 @@ std::string Include::Emit(LineInfo* line_info) const { return absl::StrFormat("`include \"%s\"", path_); } -DataType* VerilogFile::ExternType(DataType* punable_type, std::string_view name, +DataType* VerilogFile::ExternType(std::string_view name, const SourceInfo& loc) { - return Make(loc, punable_type, name); + return Make(loc, name); } BitVectorType* VerilogFile::BitVectorTypeNoScalar(int64_t bit_count, @@ -1763,14 +1770,12 @@ std::string TypedefType::Emit(LineInfo* line_info) const { std::string ExternType::Emit(LineInfo* line_info) const { LineInfoStart(line_info, this); - std::string result = name_; - LineInfoEnd(line_info, this); - return result; -} - -std::string ExternPackageType::Emit(LineInfo* line_info) const { - LineInfoStart(line_info, this); - std::string result = absl::StrCat(package_name_, "::", type_name_); + std::string result; + if (package_name_.has_value()) { + result = absl::StrCat(package_name_.value(), "::", type_name_); + } else { + result = type_name_; + } LineInfoEnd(line_info, this); return result; } diff --git a/xls/codegen/vast/vast.h b/xls/codegen/vast/vast.h index 66194f37de..18876d3014 100644 --- a/xls/codegen/vast/vast.h +++ b/xls/codegen/vast/vast.h @@ -1143,16 +1143,49 @@ class TemplateInstantiation final : public Instantiation { std::string template_text_; }; -// Represents a reference to an already-defined macro. For example: `MY_MACRO. +// Represents a reference to an already-defined macro. Examples: +// +// `MY_MACRO // Arguments not given. +// `MY_MACRO(arg1, arg2) // Two argments. +// `MY_MACRO() // Arguments given, but empty. class MacroRef final : public Expression { public: MacroRef(std::string_view name, VerilogFile* file, const SourceInfo& loc) : Expression(file, loc), name_(name) {} + MacroRef(std::string_view name, absl::Span args, + VerilogFile* file, const SourceInfo& loc) + : Expression(file, loc), + name_(name), + args_(std::vector(args.begin(), args.end())) {} std::string Emit(LineInfo* line_info) const final; private: std::string name_; + std::optional> args_; +}; + +// A macro in a statement position. Example: +// +// `MY_MACRO; +// `MY_OTHER_MACRO() +// +// The emitted text is the member MacroRef optionally followed by a semicolon. +class MacroStatement final : public Statement { + public: + MacroStatement(MacroRef* macro_ref, bool emit_semicolon, VerilogFile* file, + const SourceInfo& loc) + : Statement(file, loc), + macro_ref_(macro_ref), + emit_semicolon_(emit_semicolon) {} + + std::string Emit(LineInfo* line_info) const final { + return macro_ref_->Emit(line_info) + (emit_semicolon_ ? ";" : ""); + } + + private: + MacroRef* macro_ref_; + bool emit_semicolon_; }; // Defines a module parameter. A parameter must be assigned to an expression, @@ -1243,13 +1276,15 @@ class Typedef final : public VastNode { Def* def_; }; -// A type that is defined in an external package, where we may not know the -// underlying bit vector count as we request in `ExternType`. -class ExternPackageType : public DataType { +// A type that is defined elsewhere including in an external package. +class ExternType : public DataType { public: - explicit ExternPackageType(std::string_view package_name, - std::string_view type_name, VerilogFile* file, - const SourceInfo& loc) + ExternType(std::string_view type_name, VerilogFile* file, + const SourceInfo& loc) + : DataType(file, loc), type_name_(type_name) {} + // A type from a external package (e.g, `the_pkg::the_type`). + ExternType(std::string_view package_name, std::string_view type_name, + VerilogFile* file, const SourceInfo& loc) : DataType(file, loc), package_name_(package_name), type_name_(type_name) {} @@ -1270,7 +1305,7 @@ class ExternPackageType : public DataType { bool is_signed() const final { return false; } private: - std::string package_name_; + std::optional package_name_; std::string type_name_; }; @@ -1291,19 +1326,6 @@ class TypedefType final : public UserDefinedAliasType { Typedef* type_def_; }; -class ExternType final : public UserDefinedAliasType { - public: - explicit ExternType(DataType* bitvec_repr, std::string_view name, - VerilogFile* file, const SourceInfo& loc) - : UserDefinedAliasType(bitvec_repr, file, loc), name_(name) {} - - // Just emits the name_ - std::string Emit(LineInfo* line_info) const final; - - private: - std::string name_; -}; - // Represents the definition of a member of an enum. class EnumMember final : public NamedTrait { public: @@ -2261,7 +2283,7 @@ using ModuleMember = ModuleSection*, // Generate loop, can effectively generate more module members // at elaboration time - GenerateLoop*>; + GenerateLoop*, MacroStatement*>; // Represents a generate loop construct. Example: // ```verilog @@ -2893,8 +2915,7 @@ class VerilogFile { DataType* BitVectorType(int64_t bit_count, const SourceInfo& loc, bool is_signed = false); - DataType* ExternType(DataType* punable_type, std::string_view name, - const SourceInfo& loc); + DataType* ExternType(std::string_view name, const SourceInfo& loc); // As above, but does not produce a scalar value when the bit_count is 1. // diff --git a/xls/codegen/vast/vast_test.cc b/xls/codegen/vast/vast_test.cc index 9ef62e3d9d..24d0cd8eeb 100644 --- a/xls/codegen/vast/vast_test.cc +++ b/xls/codegen/vast/vast_test.cc @@ -21,14 +21,14 @@ #include #include -#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" @@ -556,11 +556,8 @@ TEST_P(VastTest, ModuleWithUserDataTypes) { Module* module = f.Make(SourceInfo(), "my_module"); XLS_ASSERT_OK_AND_ASSIGN( LogicRef * out_ref, - module->AddOutput( - "out", - f.Make(SourceInfo(), f.BitVectorType(64, SourceInfo()), - "foobar"), - SourceInfo())); + module->AddOutput("out", f.Make(SourceInfo(), "foobar"), + SourceInfo())); module->Add(SourceInfo(), out_ref, f.Literal(UBits(32, 64), SourceInfo())); if (UseSystemVerilog()) { @@ -1825,25 +1822,21 @@ TEST_P(VastTest, TypeCastEmission) { m->AddInput("a", f.BitVectorType(8, si), si)); XLS_ASSERT_OK_AND_ASSIGN( LogicRef * out_foo, - m->AddOutput("out_foo", - f.Make(si, f.BitVectorType(8, si), "foobar"), - si)); + m->AddOutput("out_foo", f.Make(si, "foobar"), si)); XLS_ASSERT_OK_AND_ASSIGN( LogicRef * out_pkg, - m->AddOutput("out_pkg", - f.Make(si, "my_pkg", "my_type_t"), si)); + m->AddOutput("out_pkg", f.Make(si, "my_pkg", "my_type_t"), + si)); // assign out_foo = foobar'(a + 1); m->Add( si, out_foo, - f.Make(si, - f.Make(si, f.BitVectorType(8, si), "foobar"), + f.Make(si, f.Make(si, "foobar"), f.Add(a, f.PlainLiteral(1, si), si))); // assign out_pkg = my_pkg::my_type_t'(a); m->Add( si, out_pkg, - f.Make(si, f.Make(si, "my_pkg", "my_type_t"), - a)); + f.Make(si, f.Make(si, "my_pkg", "my_type_t"), a)); EXPECT_EQ(m->Emit(nullptr), R"(module top( @@ -2673,7 +2666,7 @@ TEST_P(VastTest, EnumAssignment) { enum_type->AddMember("RED", f.PlainLiteral(0, si), si); // Note that this is an externally defined type. - DataType* extern_enum_type = f.ExternType(enum_type, "color_e", si); + DataType* extern_enum_type = f.ExternType("color_e", si); XLS_ASSERT_OK_AND_ASSIGN( LogicRef * signal, m->AddWire("signal", extern_enum_type, SourceInfo())); @@ -2699,7 +2692,7 @@ TEST_P(VastTest, ExternTypePort) { enum_type->AddMember("RED", f.PlainLiteral(0, si), si); // Note that this is an externally defined type. - DataType* extern_enum_type = f.ExternType(enum_type, "color_e", si); + DataType* extern_enum_type = f.ExternType("color_e", si); // Declare a port of the extern type. XLS_ASSERT_OK_AND_ASSIGN(LogicRef * input, @@ -2729,7 +2722,7 @@ TEST_P(VastTest, ExternalPackageTypePort) { Module* m = f.AddModule("top", si); // Make an extern package type to use in the `input` construction. - auto* data_type = f.Make(si, "mypack", "mystruct_t"); + auto* data_type = f.Make(si, "mypack", "mystruct_t"); XLS_ASSERT_OK_AND_ASSIGN(LogicRef * input, m->AddInput("my_input", data_type, si)); @@ -2753,7 +2746,7 @@ TEST_P(VastTest, ExternalPackageTypePackedArrayPort) { Module* m = f.AddModule("top", si); // Make an extern package type to use in the `input` construction. - auto* data_type = f.Make(si, "mypack", "mystruct_t"); + auto* data_type = f.Make(si, "mypack", "mystruct_t"); const std::vector packed_dims = {2, 3, 4}; const bool dims_are_max = false; auto* packed_array = @@ -2943,6 +2936,42 @@ TEST_P(VastTest, ModuleParameterPortsWithIo) { endmodule)"); } +TEST_P(VastTest, MacroStatements) { + VerilogFile f(GetFileType()); + Module* m = f.AddModule("top", SourceInfo()); + XLS_ASSERT_OK_AND_ASSIGN( + LogicRef * a, + m->AddInput("a", f.BitVectorType(8, SourceInfo()), SourceInfo())); + XLS_ASSERT_OK_AND_ASSIGN( + LogicRef * b, + m->AddInput("b", f.BitVectorType(8, SourceInfo()), SourceInfo())); + + m->Add(SourceInfo(), + f.Make(SourceInfo(), "MY_MACRO1"), + /*emit_semicolon=*/true); + m->Add( + SourceInfo(), + f.Make(SourceInfo(), "MY_MACRO2", std::vector{}), + /*emit_semicolon=*/false); + m->Add( + SourceInfo(), + f.Make(SourceInfo(), "MY_MACRO3", std::vector{a}), + /*emit_semicolon=*/false); + m->Add(SourceInfo(), + f.Make(SourceInfo(), "MY_MACRO4", + std::vector{a, b}), + /*emit_semicolon=*/true); + EXPECT_EQ(m->Emit(nullptr), R"(module top( + input wire [7:0] a, + input wire [7:0] b +); + `MY_MACRO1; + `MY_MACRO2() + `MY_MACRO3(a) + `MY_MACRO4(a, b); +endmodule)"); +} + INSTANTIATE_TEST_SUITE_P(VastTestInstantiation, VastTest, testing::Values(false, true), [](const testing::TestParamInfo& info) { diff --git a/xls/public/c_api_symbols.txt b/xls/public/c_api_symbols.txt index ec8476bf8c..f8b1be9de1 100644 --- a/xls/public/c_api_symbols.txt +++ b/xls/public/c_api_symbols.txt @@ -352,6 +352,7 @@ xls_vast_localparam_ref_as_expression xls_vast_logic_ref_as_expression xls_vast_logic_ref_as_indexable_expression xls_vast_logic_ref_get_name +xls_vast_macro_ref_as_expression xls_vast_make_verilog_file xls_vast_parameter_ref_as_expression xls_vast_slice_as_expression @@ -362,6 +363,8 @@ xls_vast_statement_block_add_comment_text xls_vast_statement_block_add_conditional xls_vast_statement_block_add_inline_text xls_vast_statement_block_add_nonblocking_assignment +xls_vast_verilog_file_add_blank_line +xls_vast_verilog_file_add_comment xls_vast_verilog_file_add_include xls_vast_verilog_file_add_module xls_vast_verilog_file_emit @@ -376,6 +379,7 @@ xls_vast_verilog_file_make_concat xls_vast_verilog_file_make_continuous_assignment xls_vast_verilog_file_make_def xls_vast_verilog_file_make_extern_package_type +xls_vast_verilog_file_make_extern_type xls_vast_verilog_file_make_index xls_vast_verilog_file_make_index_i64 xls_vast_verilog_file_make_inline_verilog_statement @@ -385,6 +389,9 @@ xls_vast_verilog_file_make_int_type xls_vast_verilog_file_make_integer_def xls_vast_verilog_file_make_integer_type xls_vast_verilog_file_make_literal +xls_vast_verilog_file_make_macro_ref +xls_vast_verilog_file_make_macro_ref_with_args +xls_vast_verilog_file_make_macro_statement xls_vast_verilog_file_make_nonblocking_assignment xls_vast_verilog_file_make_packed_array_type xls_vast_verilog_file_make_plain_literal @@ -417,6 +424,7 @@ xls_vast_verilog_module_add_member_comment xls_vast_verilog_module_add_member_continuous_assignment xls_vast_verilog_module_add_member_inline_statement xls_vast_verilog_module_add_member_instantiation +xls_vast_verilog_module_add_member_macro_statement xls_vast_verilog_module_add_output xls_vast_verilog_module_add_parameter xls_vast_verilog_module_add_parameter_port @@ -429,4 +437,4 @@ xls_vast_verilog_module_get_name xls_vast_verilog_module_get_ports xls_vast_verilog_module_port_get_def xls_vast_verilog_module_port_get_direction -xls_verify_package +xls_verify_package \ No newline at end of file diff --git a/xls/public/c_api_vast.cc b/xls/public/c_api_vast.cc index 921f643376..c3c7842a40 100644 --- a/xls/public/c_api_vast.cc +++ b/xls/public/c_api_vast.cc @@ -137,6 +137,20 @@ void xls_vast_verilog_file_add_include(struct xls_vast_verilog_file* f, cpp_file->AddInclude(path, xls::SourceInfo()); } +void xls_vast_verilog_file_add_blank_line(struct xls_vast_verilog_file* f) { + auto* cpp_file = reinterpret_cast(f); + auto* blank = cpp_file->Make(xls::SourceInfo()); + cpp_file->Add(blank); +} + +void xls_vast_verilog_file_add_comment(struct xls_vast_verilog_file* f, + const char* text) { + auto* cpp_file = reinterpret_cast(f); + auto* comment = + cpp_file->Make(xls::SourceInfo(), text); + cpp_file->Add(comment); +} + char* xls_vast_verilog_module_get_name(struct xls_vast_verilog_module* m) { auto* cpp_module = reinterpret_cast(m); return xls::ToOwnedCString(cpp_module->name()); @@ -363,12 +377,18 @@ struct xls_vast_data_type* xls_vast_verilog_file_make_extern_package_type( struct xls_vast_verilog_file* f, const char* package_name, const char* entity_name) { auto* cpp_file = reinterpret_cast(f); - xls::verilog::DataType* type = - cpp_file->Make( - xls::SourceInfo(), package_name, entity_name); + xls::verilog::DataType* type = cpp_file->Make( + xls::SourceInfo(), package_name, entity_name); return reinterpret_cast(type); } +struct xls_vast_data_type* xls_vast_verilog_file_make_extern_type( + struct xls_vast_verilog_file* f, const char* entity_name) { + auto* cpp_file = reinterpret_cast(f); + xls::verilog::DataType* type = + cpp_file->Make(xls::SourceInfo(), entity_name); + return reinterpret_cast(type); +} struct xls_vast_data_type* xls_vast_verilog_file_make_packed_array_type( struct xls_vast_verilog_file* f, struct xls_vast_data_type* element_type, const int64_t* packed_dims, size_t packed_dims_count) { @@ -430,6 +450,14 @@ void xls_vast_verilog_module_add_member_inline_statement( cpp_module->AddModuleMember(cpp_stmt); } +void xls_vast_verilog_module_add_member_macro_statement( + struct xls_vast_verilog_module* m, + struct xls_vast_macro_statement* statement) { + auto* cpp_module = reinterpret_cast(m); + auto* cpp_stmt = reinterpret_cast(statement); + cpp_module->AddModuleMember(cpp_stmt); +} + struct xls_vast_literal* xls_vast_verilog_file_make_plain_literal( struct xls_vast_verilog_file* f, int32_t value) { auto* cpp_file = reinterpret_cast(f); @@ -516,6 +544,50 @@ xls_vast_verilog_file_make_inline_verilog_statement( return reinterpret_cast(cpp_stmt); } +struct xls_vast_macro_ref* xls_vast_verilog_file_make_macro_ref( + struct xls_vast_verilog_file* f, const char* name) { + auto* cpp_file = reinterpret_cast(f); + auto* cpp_ref = + cpp_file->Make(xls::SourceInfo(), name); + return reinterpret_cast(cpp_ref); +} + +struct xls_vast_macro_ref* xls_vast_verilog_file_make_macro_ref_with_args( + struct xls_vast_verilog_file* f, const char* name, + struct xls_vast_expression** args, size_t arg_count) { + auto* cpp_file = reinterpret_cast(f); + if (arg_count == 0) { + auto* cpp_ref = cpp_file->Make( + xls::SourceInfo(), name, std::vector{}); + return reinterpret_cast(cpp_ref); + } + std::vector cpp_args; + cpp_args.reserve(arg_count); + for (size_t i = 0; i < arg_count; ++i) { + cpp_args.push_back(reinterpret_cast(args[i])); + } + auto* cpp_ref = cpp_file->Make( + xls::SourceInfo(), name, absl::MakeConstSpan(cpp_args)); + return reinterpret_cast(cpp_ref); +} + +struct xls_vast_expression* xls_vast_macro_ref_as_expression( + struct xls_vast_macro_ref* ref) { + auto* cpp_ref = reinterpret_cast(ref); + auto* cpp_expr = static_cast(cpp_ref); + return reinterpret_cast(cpp_expr); +} + +struct xls_vast_macro_statement* xls_vast_verilog_file_make_macro_statement( + struct xls_vast_verilog_file* f, struct xls_vast_macro_ref* ref, + bool emit_semicolon) { + auto* cpp_file = reinterpret_cast(f); + auto* cpp_ref = reinterpret_cast(ref); + auto* cpp_stmt = cpp_file->Make( + xls::SourceInfo(), cpp_ref, emit_semicolon); + return reinterpret_cast(cpp_stmt); +} + struct xls_vast_instantiation* xls_vast_verilog_file_make_instantiation( struct xls_vast_verilog_file* f, const char* module_name, const char* instance_name, const char** parameter_port_names, diff --git a/xls/public/c_api_vast.h b/xls/public/c_api_vast.h index 47d349e628..ab8df29a6a 100644 --- a/xls/public/c_api_vast.h +++ b/xls/public/c_api_vast.h @@ -47,6 +47,8 @@ struct xls_vast_instantiation; struct xls_vast_continuous_assignment; struct xls_vast_comment; struct xls_vast_inline_verilog_statement; +struct xls_vast_macro_ref; +struct xls_vast_macro_statement; struct xls_vast_always_base; struct xls_vast_statement; struct xls_vast_statement_block; @@ -143,6 +145,8 @@ struct xls_vast_def* xls_vast_verilog_file_make_int_def( struct xls_vast_data_type* xls_vast_verilog_file_make_extern_package_type( struct xls_vast_verilog_file* f, const char* package_name, const char* entity_name); +struct xls_vast_data_type* xls_vast_verilog_file_make_extern_type( + struct xls_vast_verilog_file* f, const char* entity_name); struct xls_vast_data_type* xls_vast_verilog_file_make_packed_array_type( struct xls_vast_verilog_file* f, xls_vast_data_type* element_type, @@ -163,6 +167,11 @@ void xls_vast_verilog_module_add_member_inline_statement( struct xls_vast_verilog_module* m, struct xls_vast_inline_verilog_statement* stmt); +// Adds a macro statement (e.g. `FOO(...);) to the module. +void xls_vast_verilog_module_add_member_macro_statement( + struct xls_vast_verilog_module* m, + struct xls_vast_macro_statement* statement); + struct xls_vast_logic_ref* xls_vast_verilog_module_add_input( struct xls_vast_verilog_module* m, const char* name, struct xls_vast_data_type* type); @@ -291,6 +300,22 @@ struct xls_vast_inline_verilog_statement* xls_vast_verilog_file_make_inline_verilog_statement( struct xls_vast_verilog_file* f, const char* text); +// Creates a MacroRef expression: `NAME or `NAME(args...) +struct xls_vast_macro_ref* xls_vast_verilog_file_make_macro_ref( + struct xls_vast_verilog_file* f, const char* name); +struct xls_vast_macro_ref* xls_vast_verilog_file_make_macro_ref_with_args( + struct xls_vast_verilog_file* f, const char* name, + struct xls_vast_expression** args, size_t arg_count); + +// Cast: MacroRef -> Expression +struct xls_vast_expression* xls_vast_macro_ref_as_expression( + struct xls_vast_macro_ref* ref); + +// Creates a MacroStatement from a MacroRef: e.g. `NAME(...); +struct xls_vast_macro_statement* xls_vast_verilog_file_make_macro_statement( + struct xls_vast_verilog_file* f, struct xls_vast_macro_ref* ref, + bool emit_semicolon); + struct xls_vast_instantiation* xls_vast_verilog_file_make_instantiation( struct xls_vast_verilog_file* f, const char* module_name, const char* instance_name, const char** parameter_port_names, @@ -302,6 +327,13 @@ struct xls_vast_instantiation* xls_vast_verilog_file_make_instantiation( void xls_vast_verilog_file_add_include(struct xls_vast_verilog_file* f, const char* path); +// Adds a blank line to the file. +void xls_vast_verilog_file_add_blank_line(struct xls_vast_verilog_file* f); + +// Adds a comment to the file. +void xls_vast_verilog_file_add_comment(struct xls_vast_verilog_file* f, + const char* text); + struct xls_vast_concat* xls_vast_verilog_file_make_concat( struct xls_vast_verilog_file* f, struct xls_vast_expression** elements, size_t element_count); diff --git a/xls/public/c_api_vast_test.cc b/xls/public/c_api_vast_test.cc index e5035a9ca4..777c209138 100644 --- a/xls/public/c_api_vast_test.cc +++ b/xls/public/c_api_vast_test.cc @@ -23,8 +23,8 @@ #include #include -#include "gtest/gtest.h" #include "absl/cleanup/cleanup.h" +#include "gtest/gtest.h" #include "xls/public/c_api.h" #include "xls/public/c_api_format_preference.h" @@ -196,9 +196,10 @@ endmodule EXPECT_EQ(std::string_view{emitted}, kWant); } -TEST(XlsCApiTest, VastExternPackageTypePackedArrayPort) { +TEST(XlsCApiTest, VastExternTypesPackedArrayPort) { const std::string_view kWantEmitted = R"(module top( - input mypack::mystruct_t [1:0][2:0][3:0] my_input + input mypack::mystruct_t [1:0][2:0][3:0] my_input, + output yourstruct_t my_output ); endmodule @@ -213,12 +214,15 @@ endmodule xls_vast_data_type* my_struct = xls_vast_verilog_file_make_extern_package_type(f, "mypack", "mystruct_t"); + xls_vast_data_type* your_struct = + xls_vast_verilog_file_make_extern_type(f, "yourstruct_t"); const std::vector packed_dims = {2, 3, 4}; xls_vast_data_type* my_input_type = xls_vast_verilog_file_make_packed_array_type( f, my_struct, packed_dims.data(), packed_dims.size()); xls_vast_verilog_module_add_input(m, "my_input", my_input_type); + xls_vast_verilog_module_add_output(m, "my_output", your_struct); char* emitted = xls_vast_verilog_file_emit(f); ASSERT_NE(emitted, nullptr); @@ -296,6 +300,32 @@ endmodule EXPECT_EQ(std::string_view{emitted}, kWantEmittedWithExtras); } +TEST(XlsCApiTest, VastFileLevelBlankLineAndComment) { + const std::string_view kWantEmitted = R"(// file header + +module top; + +endmodule +)"; + xls_vast_verilog_file* f = + xls_vast_make_verilog_file(xls_vast_file_type_verilog); + ASSERT_NE(f, nullptr); + absl::Cleanup free_file([&] { xls_vast_verilog_file_free(f); }); + + // Add a file-level comment and a blank line. + xls_vast_verilog_file_add_comment(f, "file header"); + xls_vast_verilog_file_add_blank_line(f); + + // Add a trivial module so the file emits something after the header. + xls_vast_verilog_module* m = xls_vast_verilog_file_add_module(f, "top"); + ASSERT_NE(m, nullptr); + + char* emitted = xls_vast_verilog_file_emit(f); + ASSERT_NE(emitted, nullptr); + absl::Cleanup free_emitted([&] { xls_c_str_free(emitted); }); + EXPECT_EQ(std::string_view{emitted}, kWantEmitted); +} + TEST(XlsCApiTest, VastEmitExpression) { // Create a file and module. xls_vast_verilog_file* f = @@ -1998,6 +2028,79 @@ TEST(XlsCApiTest, VastMakeBlockingAssignmentFactorySmoke) { ASSERT_NE(stmt, nullptr); } +TEST(XlsCApiTest, VastMacroStatements) { + const std::string_view kWantEmitted = R"(module top( + input wire [7:0] a, + input wire [7:0] b +); + `MY_MACRO1; + `MY_MACRO2() + `MY_MACRO3(a) + `MY_MACRO4(a, b); +endmodule +)"; + xls_vast_verilog_file* f = + xls_vast_make_verilog_file(xls_vast_file_type_verilog); + ASSERT_NE(f, nullptr); + absl::Cleanup free_file([&] { xls_vast_verilog_file_free(f); }); + + xls_vast_verilog_module* m = xls_vast_verilog_file_add_module(f, "top"); + ASSERT_NE(m, nullptr); + + xls_vast_data_type* u8 = + xls_vast_verilog_file_make_bit_vector_type(f, 8, /*is_signed=*/false); + xls_vast_logic_ref* a = xls_vast_verilog_module_add_input(m, "a", u8); + xls_vast_logic_ref* b = xls_vast_verilog_module_add_input(m, "b", u8); + ASSERT_NE(a, nullptr); + ASSERT_NE(b, nullptr); + + // `MY_MACRO1; + xls_vast_macro_ref* mr1 = + xls_vast_verilog_file_make_macro_ref(f, "MY_MACRO1"); + ASSERT_NE(mr1, nullptr); + xls_vast_macro_statement* ms1 = xls_vast_verilog_file_make_macro_statement( + f, mr1, /*emit_semicolon=*/true); + xls_vast_verilog_module_add_member_macro_statement(m, ms1); + + // `MY_MACRO2(); + xls_vast_expression** empty_args = nullptr; + xls_vast_macro_ref* mr2 = xls_vast_verilog_file_make_macro_ref_with_args( + f, "MY_MACRO2", empty_args, 0); + ASSERT_NE(mr2, nullptr); + xls_vast_macro_statement* ms2 = xls_vast_verilog_file_make_macro_statement( + f, mr2, /*emit_semicolon=*/false); + xls_vast_verilog_module_add_member_macro_statement(m, ms2); + + // `MY_MACRO3(a); + xls_vast_expression* args3[] = { + xls_vast_logic_ref_as_expression(a), + }; + xls_vast_macro_ref* mr3 = + xls_vast_verilog_file_make_macro_ref_with_args(f, "MY_MACRO3", args3, 1); + ASSERT_NE(mr3, nullptr); + xls_vast_macro_statement* ms3 = xls_vast_verilog_file_make_macro_statement( + f, mr3, /*emit_semicolon=*/false); + xls_vast_verilog_module_add_member_macro_statement(m, ms3); + + // `MY_MACRO4(a, b); + xls_vast_expression* args4[] = { + xls_vast_logic_ref_as_expression(a), + xls_vast_logic_ref_as_expression(b), + }; + xls_vast_macro_ref* mr4 = + xls_vast_verilog_file_make_macro_ref_with_args(f, "MY_MACRO4", args4, 2); + ASSERT_NE(mr4, nullptr); + xls_vast_macro_statement* ms4 = xls_vast_verilog_file_make_macro_statement( + f, mr4, /*emit_semicolon=*/true); + xls_vast_verilog_module_add_member_macro_statement(m, ms4); + + char* emitted = xls_vast_verilog_file_emit(f); + ASSERT_NE(emitted, nullptr); + absl::Cleanup free_emitted([&] { xls_c_str_free(emitted); }); + + EXPECT_EQ(std::string_view{emitted}, kWantEmitted); +} + TEST(XlsCApiTest, ModuleWithParameterPort) { xls_vast_verilog_file* f = xls_vast_make_verilog_file(xls_vast_file_type_verilog);