Skip to content

Commit

Permalink
Merge pull request #1604 from xlsynth:cdleary/2024-09-12-vast-wide-li…
Browse files Browse the repository at this point in the history
…teral-via-bits

PiperOrigin-RevId: 674068965
  • Loading branch information
copybara-github committed Sep 13, 2024
2 parents 33b61ea + 346ccd9 commit b05d500
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
42 changes: 42 additions & 0 deletions xls/public/c_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ bool ReturnStringHelper(absl::StatusOr<std::string>& to_return,
return false;
}

// Converts a C-API-given format preference value into the XLS internal enum --
// since these values can be out of normal enum class range when passed to the
// API, we validate here.
bool FormatPreferenceFromC(xls_format_preference c_pref,
xls::FormatPreference* cpp_pref, char** error_out) {
switch (c_pref) {
Expand Down Expand Up @@ -187,6 +190,25 @@ bool xls_parse_typed_value(const char* input, char** error_out,
return false;
}

bool xls_value_get_bits(const struct xls_value* value, char** error_out,
struct xls_bits** bits_out) {
CHECK(value != nullptr);
CHECK(error_out != nullptr);
CHECK(bits_out != nullptr);

const auto* cpp_value = reinterpret_cast<const xls::Value*>(value);
absl::StatusOr<xls::Bits> bits_or = cpp_value->GetBitsWithStatus();
if (bits_or.ok()) {
xls::Bits* heap_bits = new xls::Bits(std::move(bits_or).value());
*bits_out = reinterpret_cast<xls_bits*>(heap_bits);
return true;
}

*bits_out = nullptr;
*error_out = ToOwnedCString(bits_or.status().ToString());
return false;
}

struct xls_value* xls_value_make_token() {
auto* value = new xls::Value(xls::Value::Token());
return reinterpret_cast<xls_value*>(value);
Expand All @@ -202,6 +224,8 @@ struct xls_value* xls_value_make_false() {
return reinterpret_cast<xls_value*>(value);
}

void xls_bits_free(xls_bits* b) { delete reinterpret_cast<xls::Bits*>(b); }

void xls_value_free(xls_value* v) {
delete reinterpret_cast<xls::Value*>(v);
}
Expand Down Expand Up @@ -540,6 +564,24 @@ struct xls_vast_literal* xls_vast_verilog_file_make_plain_literal(
return reinterpret_cast<xls_vast_literal*>(cpp_literal);
}

bool xls_vast_verilog_file_make_literal(struct xls_vast_verilog_file* f,
struct xls_bits* bits,
xls_format_preference format_preference,
bool emit_bit_count, char** error_out,
struct xls_vast_literal** literal_out) {
auto* cpp_file = reinterpret_cast<xls::verilog::VerilogFile*>(f);
auto* cpp_bits = reinterpret_cast<xls::Bits*>(bits);
xls::FormatPreference cpp_pref;
if (!FormatPreferenceFromC(format_preference, &cpp_pref, error_out)) {
return false;
}
xls::verilog::Literal* cpp_literal = cpp_file->Make<xls::verilog::Literal>(
xls::SourceInfo(), *cpp_bits, cpp_pref, emit_bit_count);
*error_out = nullptr;
*literal_out = reinterpret_cast<xls_vast_literal*>(cpp_literal);
return true;
}

struct xls_vast_continuous_assignment*
xls_vast_verilog_file_make_continuous_assignment(
struct xls_vast_verilog_file* f, struct xls_vast_expression* lhs,
Expand Down
17 changes: 17 additions & 0 deletions xls/public/c_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ struct xls_value* xls_value_make_token();
// Returns a new `bits[1]:1` XLS value which the caller must free.
struct xls_value* xls_value_make_true();

// Attempts to extract a "bits" value from the given XLS value -- the resulting
// `bits_out` is owned by the caller and must be freed via `xls_bits_free()` on
// success.
bool xls_value_get_bits(const struct xls_value* value, char** error_out,
struct xls_bits** bits_out);

void xls_bits_free(struct xls_bits* bits);

// Returns a new `bits[1]:0` XLS value which the caller must free.
struct xls_value* xls_value_make_false();

Expand Down Expand Up @@ -269,6 +277,15 @@ struct xls_vast_slice* xls_vast_verilog_file_make_slice_i64(
struct xls_vast_literal* xls_vast_verilog_file_make_plain_literal(
struct xls_vast_verilog_file* f, int32_t value);

// Creates a VAST literal with an arbitrary bit count.
//
// Returns an error if the given format preference is invalid.
bool xls_vast_verilog_file_make_literal(struct xls_vast_verilog_file* f,
struct xls_bits* bits,
xls_format_preference format_preference,
bool emit_bit_count, char** error_out,
struct xls_vast_literal** literal_out);

// Casts to turn the given node to an expression, where possible.
struct xls_vast_expression* xls_vast_literal_as_expression(
struct xls_vast_literal* v);
Expand Down
57 changes: 57 additions & 0 deletions xls/public/c_api_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -426,4 +426,61 @@ endmodule
EXPECT_EQ(std::string_view{emitted}, kWant);
}

// Tests that we can assign a 128-bit output wire using a 128-bit literal
// value.
TEST(XlsCApiTest, ContinuousAssignmentOf128BitLiteral) {
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, "my_module");
ASSERT_NE(m, nullptr);

xls_vast_data_type* u128 =
xls_vast_verilog_file_make_bit_vector_type(f, 128, false);
xls_vast_logic_ref* output_ref =
xls_vast_verilog_module_add_output(m, "my_output", u128);

char* error_out = nullptr;
struct xls_value* value = nullptr;
ASSERT_TRUE(xls_parse_typed_value(
"bits[128]:"
"0b1001001000110100010101100111100010010000101010111100110111101111000100"
"1000110100010101100111100010010000101010111100110111101111",
&error_out, &value));
ASSERT_EQ(error_out, nullptr);
absl::Cleanup free_value([value] { xls_value_free(value); });

struct xls_bits* bits = nullptr;
ASSERT_TRUE(xls_value_get_bits(value, &error_out, &bits));
ASSERT_EQ(error_out, nullptr);
absl::Cleanup free_bits([bits] { xls_bits_free(bits); });

xls_vast_literal* literal_128b = nullptr;
ASSERT_TRUE(xls_vast_verilog_file_make_literal(
f, bits, xls_format_preference_binary, /*emit_bit_count=*/true,
&error_out, &literal_128b));
ASSERT_EQ(error_out, nullptr);
ASSERT_NE(literal_128b, nullptr);

xls_vast_continuous_assignment* assignment =
xls_vast_verilog_file_make_continuous_assignment(
f, xls_vast_logic_ref_as_expression(output_ref),
xls_vast_literal_as_expression(literal_128b));

xls_vast_verilog_module_add_member_continuous_assignment(m, assignment);

char* emitted = xls_vast_verilog_file_emit(f);
ASSERT_NE(emitted, nullptr);
absl::Cleanup free_emitted([&] { xls_c_str_free(emitted); });
const std::string_view kWant = R"(module my_module(
output wire [127:0] my_output
);
assign my_output = 128'b1001_0010_0011_0100_0101_0110_0111_1000_1001_0000_1010_1011_1100_1101_1110_1111_0001_0010_0011_0100_0101_0110_0111_1000_1001_0000_1010_1011_1100_1101_1110_1111;
endmodule
)";
EXPECT_EQ(std::string_view{emitted}, kWant);
}

} // namespace

0 comments on commit b05d500

Please sign in to comment.