Skip to content

Commit b0d5ab7

Browse files
Merge pull request #2047 from benquike:main
PiperOrigin-RevId: 751602123
2 parents 9be96a4 + 0b24db1 commit b0d5ab7

File tree

4 files changed

+199
-0
lines changed

4 files changed

+199
-0
lines changed

xls/public/c_api.cc

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <string.h> // NOLINT(modernize-deprecated-headers)
1818

19+
#include <algorithm>
1920
#include <cstddef>
2021
#include <cstdint>
2122
#include <cstdlib>
@@ -347,6 +348,32 @@ struct xls_value* xls_value_clone(const struct xls_value* value) {
347348
return reinterpret_cast<xls_value*>(new xls::Value(*cpp_value));
348349
}
349350

351+
bool xls_value_get_kind(const struct xls_value* value, char** error_out,
352+
xls_value_kind* kind_out) {
353+
CHECK(value != nullptr);
354+
const auto* cpp_value = reinterpret_cast<const xls::Value*>(value);
355+
*error_out = nullptr;
356+
switch (cpp_value->kind()) {
357+
case xls::ValueKind::kBits:
358+
*kind_out = xls_value_kind_bits;
359+
break;
360+
case xls::ValueKind::kToken:
361+
*kind_out = xls_value_kind_token;
362+
break;
363+
case xls::ValueKind::kArray:
364+
*kind_out = xls_value_kind_array;
365+
break;
366+
case xls::ValueKind::kTuple:
367+
*kind_out = xls_value_kind_tuple;
368+
break;
369+
case xls::ValueKind::kInvalid:
370+
*error_out = xls::ToOwnedCString(
371+
absl::InvalidArgumentError("Value is invalid").ToString());
372+
return false;
373+
}
374+
return true;
375+
}
376+
350377
bool xls_value_make_ubits(int64_t bit_count, uint64_t value, char** error_out,
351378
struct xls_value** xls_value_out) {
352379
CHECK(error_out != nullptr);
@@ -428,6 +455,50 @@ bool xls_bits_get_bit(const struct xls_bits* bits, int64_t index) {
428455
return cpp_bits->Get(index);
429456
}
430457

458+
bool xls_bits_to_bytes(const struct xls_bits* bits, char** error_out,
459+
uint8_t** bytes_out, size_t* byte_count_out) {
460+
CHECK(bits != nullptr);
461+
CHECK(bytes_out != nullptr);
462+
CHECK(error_out != nullptr);
463+
CHECK(byte_count_out != nullptr);
464+
const auto* cpp_bits = reinterpret_cast<const xls::Bits*>(bits);
465+
std::vector<uint8_t> bytes = cpp_bits->ToBytes();
466+
*byte_count_out = bytes.size();
467+
*bytes_out = new uint8_t[bytes.size()];
468+
std::copy(bytes.begin(), bytes.end(), *bytes_out);
469+
return true;
470+
}
471+
472+
bool xls_bits_to_uint64(const struct xls_bits* bits, char** error_out,
473+
uint64_t* value_out) {
474+
CHECK(bits != nullptr);
475+
CHECK(value_out != nullptr);
476+
CHECK(error_out != nullptr);
477+
const auto* cpp_bits = reinterpret_cast<const xls::Bits*>(bits);
478+
absl::StatusOr<uint64_t> result = cpp_bits->ToUint64();
479+
if (!result.ok()) {
480+
*error_out = xls::ToOwnedCString(result.status().ToString());
481+
return false;
482+
}
483+
*value_out = result.value();
484+
return true;
485+
}
486+
487+
bool xls_bits_to_int64(const struct xls_bits* bits, char** error_out,
488+
int64_t* value_out) {
489+
CHECK(bits != nullptr);
490+
CHECK(value_out != nullptr);
491+
CHECK(error_out != nullptr);
492+
const auto* cpp_bits = reinterpret_cast<const xls::Bits*>(bits);
493+
absl::StatusOr<int64_t> result = cpp_bits->ToInt64();
494+
if (!result.ok()) {
495+
*error_out = xls::ToOwnedCString(result.status().ToString());
496+
return false;
497+
}
498+
*value_out = result.value();
499+
return true;
500+
}
501+
431502
struct xls_bits* xls_bits_width_slice(const struct xls_bits* bits,
432503
int64_t start, int64_t width) {
433504
CHECK(bits != nullptr);
@@ -678,6 +749,8 @@ void xls_c_strs_free(char** c_strs, size_t count) {
678749
delete[] c_strs;
679750
}
680751

752+
void xls_bytes_free(uint8_t* bytes) { delete[] bytes; }
753+
681754
bool xls_value_to_string(const struct xls_value* v, char** string_out) {
682755
CHECK(v != nullptr);
683756
CHECK(string_out != nullptr);

xls/public/c_api.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@
4343

4444
extern "C" {
4545

46+
typedef int32_t xls_value_kind;
47+
enum {
48+
xls_value_kind_invalid,
49+
xls_value_kind_bits,
50+
xls_value_kind_array,
51+
xls_value_kind_tuple,
52+
xls_value_kind_token,
53+
};
54+
4655
// Opaque structs.
4756
struct xls_bits;
4857
struct xls_function;
@@ -130,6 +139,11 @@ bool xls_parse_typed_value(const char* input, char** error_out,
130139
bool xls_value_make_ubits(int64_t bit_count, uint64_t value, char** error_out,
131140
struct xls_value** xls_value_out);
132141

142+
// Returns the kind of the given value. The caller must free the returned
143+
// `error_out` string via `xls_c_str_free` if an error is returned.
144+
bool xls_value_get_kind(const struct xls_value* value, char** error_out,
145+
xls_value_kind* kind_out);
146+
133147
bool xls_value_make_sbits(int64_t bit_count, int64_t value, char** error_out,
134148
struct xls_value** xls_value_out);
135149

@@ -199,6 +213,23 @@ bool xls_bits_eq(const struct xls_bits* a, const struct xls_bits* b);
199213
// returns 1, `xls_bits_get_bit(bits, 1)` returns 0.
200214
bool xls_bits_get_bit(const struct xls_bits* bits, int64_t index);
201215

216+
// Converts the given bits value to a byte array, whose length is saved in
217+
// byte_count_out. The caller must free the returned `bytes_out` pointer
218+
// via `xls_bytes_free` if xls_bits_to_bytes returns true.
219+
// If the conversion fails and it returns false, error_out is populated
220+
// with an error message and the caller must free the
221+
// `error_out` pointer with `xls_c_str_free`.
222+
bool xls_bits_to_bytes(const struct xls_bits* bits, char** error_out,
223+
uint8_t** bytes_out, size_t* byte_count_out);
224+
225+
// Converts the given bits value to a signed or unsigned integer 64-bit integer
226+
// value. If the conversion is not possible, false is returned, `error_out`
227+
// contains the error message and the caller must free the `error_out` pointer
228+
// with `xls_c_str_free`.
229+
bool xls_bits_to_uint64(const struct xls_bits* bits, char** error_out,
230+
uint64_t* value_out);
231+
bool xls_bits_to_int64(const struct xls_bits* bits, char** error_out,
232+
int64_t* value_out);
202233
struct xls_bits* xls_bits_width_slice(const struct xls_bits* bits,
203234
int64_t start, int64_t width);
204235

@@ -305,6 +336,10 @@ void xls_c_str_free(char* c_str);
305336
// Frees an array of C strings that were provided by this XLS public API.
306337
void xls_c_strs_free(char** c_strs, size_t count);
307338

339+
// Frees the given `bytes` -- the bytes should have been allocated by the
340+
// XLS library where ownership was passed back to the caller.
341+
void xls_bytes_free(uint8_t* bytes);
342+
308343
// Returns a string representation of the given IR package `p`.
309344
bool xls_package_to_string(const struct xls_package* p, char** string_out);
310345

xls/public/c_api_symbols.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ xls_bits_shift_right_arithmetic
1515
xls_bits_shift_right_logical
1616
xls_bits_smul
1717
xls_bits_sub
18+
xls_bits_to_bytes
1819
xls_bits_to_debug_string
20+
xls_bits_to_int64
1921
xls_bits_to_string
22+
xls_bits_to_uint64
2023
xls_bits_umul
2124
xls_bits_width_slice
2225
xls_bits_xor
@@ -56,6 +59,7 @@ xls_builder_base_add_xor
5659
xls_builder_base_add_xor_reduce
5760
xls_builder_base_add_zero_extend
5861
xls_bvalue_free
62+
xls_bytes_free
5963
xls_c_str_free
6064
xls_c_strs_free
6165
xls_convert_dslx_path_to_ir
@@ -172,6 +176,7 @@ xls_value_from_bits_owned
172176
xls_value_get_bits
173177
xls_value_get_element
174178
xls_value_get_element_count
179+
xls_value_get_kind
175180
xls_value_make_array
176181
xls_value_make_false
177182
xls_value_make_sbits

xls/public/c_api_test.cc

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <cstddef>
1818
#include <cstdint>
19+
#include <cstdlib>
1920
#include <filesystem> // NOLINT
2021
#include <functional>
2122
#include <initializer_list>
@@ -304,6 +305,11 @@ TEST(XlsCApiTest, FlattenBitsValueToBits) {
304305
ASSERT_TRUE(xls_parse_typed_value("bits[32]:0x42", &error_out, &value));
305306
absl::Cleanup free_value([value] { xls_value_free(value); });
306307

308+
xls_value_kind kind = xls_value_kind_invalid;
309+
ASSERT_TRUE(xls_value_get_kind(value, &error_out, &kind));
310+
EXPECT_EQ(kind, xls_value_kind_bits);
311+
ASSERT_EQ(error_out, nullptr);
312+
307313
// Get the bits from within the value. Note that it's owned by the caller.
308314
xls_bits* value_bits = nullptr;
309315
ASSERT_TRUE(xls_value_get_bits(value, &error_out, &value_bits));
@@ -336,6 +342,10 @@ TEST(XlsCApiTest, FlattenTupleValueToBits) {
336342
xls_value* tuple = xls_value_make_tuple(/*element_count=*/2, elements);
337343
absl::Cleanup free_tuple([tuple] { xls_value_free(tuple); });
338344

345+
xls_value_kind kind = xls_value_kind_invalid;
346+
ASSERT_TRUE(xls_value_get_kind(tuple, &error_out, &kind));
347+
EXPECT_EQ(kind, xls_value_kind_tuple);
348+
339349
// Get the elements and check they are equal to the originals.
340350
xls_value* u3_7_extracted = nullptr;
341351
ASSERT_TRUE(xls_value_get_element(tuple, 0, &error_out, &u3_7_extracted));
@@ -390,6 +400,10 @@ TEST(XlsCApiTest, MakeArrayValue) {
390400
/*element_count=*/2, elements, &error_out, &array));
391401
absl::Cleanup free_array([array] { xls_value_free(array); });
392402

403+
xls_value_kind kind = xls_value_kind_invalid;
404+
ASSERT_TRUE(xls_value_get_kind(array, &error_out, &kind));
405+
EXPECT_EQ(kind, xls_value_kind_array);
406+
393407
char* value_str = nullptr;
394408
ASSERT_TRUE(xls_value_to_string(array, &value_str));
395409
absl::Cleanup free_value_str([value_str] { xls_c_str_free(value_str); });
@@ -422,6 +436,78 @@ TEST(XlsCApiTest, MakeBitsFromUint8DataWithMsbPadding) {
422436
EXPECT_EQ(xls_bits_get_bit(bits, 5), 1);
423437
}
424438

439+
TEST(XlsCApiTest, BitsToBytes) {
440+
char* error_out = nullptr;
441+
xls_bits* bits = nullptr;
442+
ASSERT_TRUE(xls_bits_make_ubits(32, 0x0A0B0C0D, &error_out, &bits));
443+
uint8_t* bytes = nullptr;
444+
size_t byte_count = 0;
445+
446+
absl::Cleanup free_memory([&error_out, &bits, &bytes] {
447+
xls_c_str_free(error_out);
448+
xls_bits_free(bits);
449+
xls_bytes_free(bytes);
450+
});
451+
452+
ASSERT_TRUE(xls_bits_to_bytes(bits, &error_out, &bytes, &byte_count));
453+
EXPECT_EQ(byte_count, 4);
454+
EXPECT_EQ(bytes[0], 0x0D);
455+
EXPECT_EQ(bytes[1], 0x0C);
456+
EXPECT_EQ(bytes[2], 0x0B);
457+
EXPECT_EQ(bytes[3], 0x0A);
458+
}
459+
460+
TEST(XlsCApiTest, BitsToBytesWithPadding) {
461+
char* error_out = nullptr;
462+
xls_bits* bits = nullptr;
463+
ASSERT_TRUE(xls_bits_make_ubits(
464+
34, 0b11'0000'0000'0000'0000'0000'0000'0000'0000, &error_out, &bits));
465+
uint8_t* bytes = nullptr;
466+
size_t byte_count = 0;
467+
468+
absl::Cleanup free_memory([&error_out, &bits, &bytes] {
469+
xls_c_str_free(error_out);
470+
xls_bits_free(bits);
471+
xls_bytes_free(bytes);
472+
});
473+
474+
ASSERT_TRUE(xls_bits_to_bytes(bits, &error_out, &bytes, &byte_count));
475+
EXPECT_EQ(byte_count, 5);
476+
EXPECT_EQ(bytes[0], 0x00);
477+
EXPECT_EQ(bytes[1], 0x00);
478+
EXPECT_EQ(bytes[2], 0x00);
479+
EXPECT_EQ(bytes[3], 0x00);
480+
EXPECT_EQ(bytes[4], 0b11);
481+
}
482+
483+
TEST(XlsCApiTest, BitsToUint64Fit) {
484+
char* error_out = nullptr;
485+
xls_bits* bits = nullptr;
486+
ASSERT_TRUE(xls_bits_make_ubits(64, 0x0A0B0C0D, &error_out, &bits));
487+
absl::Cleanup free_memory([&error_out, &bits] {
488+
xls_c_str_free(error_out);
489+
xls_bits_free(bits);
490+
});
491+
492+
uint64_t value = 0;
493+
ASSERT_TRUE(xls_bits_to_uint64(bits, &error_out, &value));
494+
EXPECT_EQ(value, 0x0A0B0C0D);
495+
}
496+
497+
TEST(XlsCApiTest, BitsToInt64Fit) {
498+
char* error_out = nullptr;
499+
xls_bits* bits = nullptr;
500+
ASSERT_TRUE(xls_bits_make_ubits(64, 0x0A0B0C0D, &error_out, &bits));
501+
absl::Cleanup free_memory([&error_out, &bits] {
502+
xls_c_str_free(error_out);
503+
xls_bits_free(bits);
504+
});
505+
506+
int64_t value = 0;
507+
ASSERT_TRUE(xls_bits_to_int64(bits, &error_out, &value));
508+
EXPECT_EQ(value, 0x0A0B0C0D);
509+
}
510+
425511
TEST(XlsCApiTest, MakeSbitsDoesNotFit) {
426512
char* error_out = nullptr;
427513
xls_bits* bits = nullptr;

0 commit comments

Comments
 (0)