mirror of https://github.com/YosysHQ/yosys.git
cxxrtl: export wire attributes through the C API.
Co-authored-by: Charlotte <charlotte@lottia.net>
This commit is contained in:
parent
d21c464ae4
commit
6ffc315936
|
@ -1019,14 +1019,14 @@ struct metadata {
|
||||||
|
|
||||||
// In debug mode, using the wrong .as_*() function will assert.
|
// In debug mode, using the wrong .as_*() function will assert.
|
||||||
// In release mode, using the wrong .as_*() function will safely return a default value.
|
// In release mode, using the wrong .as_*() function will safely return a default value.
|
||||||
const unsigned uint_value = 0;
|
const uint64_t uint_value = 0;
|
||||||
const signed sint_value = 0;
|
const int64_t sint_value = 0;
|
||||||
const std::string string_value = "";
|
const std::string string_value = "";
|
||||||
const double double_value = 0.0;
|
const double double_value = 0.0;
|
||||||
|
|
||||||
metadata() : value_type(MISSING) {}
|
metadata() : value_type(MISSING) {}
|
||||||
metadata(unsigned value) : value_type(UINT), uint_value(value) {}
|
metadata(uint64_t value) : value_type(UINT), uint_value(value) {}
|
||||||
metadata(signed value) : value_type(SINT), sint_value(value) {}
|
metadata(int64_t value) : value_type(SINT), sint_value(value) {}
|
||||||
metadata(const std::string &value) : value_type(STRING), string_value(value) {}
|
metadata(const std::string &value) : value_type(STRING), string_value(value) {}
|
||||||
metadata(const char *value) : value_type(STRING), string_value(value) {}
|
metadata(const char *value) : value_type(STRING), string_value(value) {}
|
||||||
metadata(double value) : value_type(DOUBLE), double_value(value) {}
|
metadata(double value) : value_type(DOUBLE), double_value(value) {}
|
||||||
|
@ -1034,12 +1034,12 @@ struct metadata {
|
||||||
metadata(const metadata &) = default;
|
metadata(const metadata &) = default;
|
||||||
metadata &operator=(const metadata &) = delete;
|
metadata &operator=(const metadata &) = delete;
|
||||||
|
|
||||||
unsigned as_uint() const {
|
uint64_t as_uint() const {
|
||||||
assert(value_type == UINT);
|
assert(value_type == UINT);
|
||||||
return uint_value;
|
return uint_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
signed as_sint() const {
|
int64_t as_sint() const {
|
||||||
assert(value_type == SINT);
|
assert(value_type == SINT);
|
||||||
return sint_value;
|
return sint_value;
|
||||||
}
|
}
|
||||||
|
@ -1068,6 +1068,9 @@ using debug_outline = ::_cxxrtl_outline;
|
||||||
//
|
//
|
||||||
// To avoid violating strict aliasing rules, this structure has to be a subclass of the one used
|
// To avoid violating strict aliasing rules, this structure has to be a subclass of the one used
|
||||||
// in the C API, or it would not be possible to cast between the pointers to these.
|
// in the C API, or it would not be possible to cast between the pointers to these.
|
||||||
|
//
|
||||||
|
// The `attrs` member cannot be owned by this structure because a `cxxrtl_object` can be created
|
||||||
|
// from external C code.
|
||||||
struct debug_item : ::cxxrtl_object {
|
struct debug_item : ::cxxrtl_object {
|
||||||
// Object types.
|
// Object types.
|
||||||
enum : uint32_t {
|
enum : uint32_t {
|
||||||
|
@ -1103,6 +1106,7 @@ struct debug_item : ::cxxrtl_object {
|
||||||
curr = item.data;
|
curr = item.data;
|
||||||
next = item.data;
|
next = item.data;
|
||||||
outline = nullptr;
|
outline = nullptr;
|
||||||
|
attrs = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t Bits>
|
template<size_t Bits>
|
||||||
|
@ -1118,6 +1122,7 @@ struct debug_item : ::cxxrtl_object {
|
||||||
curr = const_cast<chunk_t*>(item.data);
|
curr = const_cast<chunk_t*>(item.data);
|
||||||
next = nullptr;
|
next = nullptr;
|
||||||
outline = nullptr;
|
outline = nullptr;
|
||||||
|
attrs = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t Bits>
|
template<size_t Bits>
|
||||||
|
@ -1134,6 +1139,7 @@ struct debug_item : ::cxxrtl_object {
|
||||||
curr = item.curr.data;
|
curr = item.curr.data;
|
||||||
next = item.next.data;
|
next = item.next.data;
|
||||||
outline = nullptr;
|
outline = nullptr;
|
||||||
|
attrs = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t Width>
|
template<size_t Width>
|
||||||
|
@ -1149,6 +1155,7 @@ struct debug_item : ::cxxrtl_object {
|
||||||
curr = item.data ? item.data[0].data : nullptr;
|
curr = item.data ? item.data[0].data : nullptr;
|
||||||
next = nullptr;
|
next = nullptr;
|
||||||
outline = nullptr;
|
outline = nullptr;
|
||||||
|
attrs = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t Bits>
|
template<size_t Bits>
|
||||||
|
@ -1164,6 +1171,7 @@ struct debug_item : ::cxxrtl_object {
|
||||||
curr = const_cast<chunk_t*>(item.data);
|
curr = const_cast<chunk_t*>(item.data);
|
||||||
next = nullptr;
|
next = nullptr;
|
||||||
outline = nullptr;
|
outline = nullptr;
|
||||||
|
attrs = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t Bits>
|
template<size_t Bits>
|
||||||
|
@ -1180,6 +1188,7 @@ struct debug_item : ::cxxrtl_object {
|
||||||
curr = const_cast<chunk_t*>(item.curr.data);
|
curr = const_cast<chunk_t*>(item.curr.data);
|
||||||
next = nullptr;
|
next = nullptr;
|
||||||
outline = nullptr;
|
outline = nullptr;
|
||||||
|
attrs = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t Bits>
|
template<size_t Bits>
|
||||||
|
@ -1195,6 +1204,7 @@ struct debug_item : ::cxxrtl_object {
|
||||||
curr = const_cast<chunk_t*>(item.data);
|
curr = const_cast<chunk_t*>(item.data);
|
||||||
next = nullptr;
|
next = nullptr;
|
||||||
outline = &group;
|
outline = &group;
|
||||||
|
attrs = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t Bits, class IntegerT>
|
template<size_t Bits, class IntegerT>
|
||||||
|
@ -1215,10 +1225,28 @@ struct debug_item : ::cxxrtl_object {
|
||||||
};
|
};
|
||||||
static_assert(std::is_standard_layout<debug_item>::value, "debug_item is not compatible with C layout");
|
static_assert(std::is_standard_layout<debug_item>::value, "debug_item is not compatible with C layout");
|
||||||
|
|
||||||
|
} // namespace cxxrtl
|
||||||
|
|
||||||
|
typedef struct _cxxrtl_attr_set {
|
||||||
|
cxxrtl::metadata_map map;
|
||||||
|
} *cxxrtl_attr_set;
|
||||||
|
|
||||||
|
namespace cxxrtl {
|
||||||
|
|
||||||
|
// Representation of an attribute set in the C++ interface.
|
||||||
|
using debug_attrs = ::_cxxrtl_attr_set;
|
||||||
|
|
||||||
struct debug_items {
|
struct debug_items {
|
||||||
std::map<std::string, std::vector<debug_item>> table;
|
std::map<std::string, std::vector<debug_item>> table;
|
||||||
|
std::map<std::string, std::unique_ptr<debug_attrs>> attrs_table;
|
||||||
|
|
||||||
void add(const std::string &name, debug_item &&item) {
|
void add(const std::string &name, debug_item &&item, metadata_map &&item_attrs = {}) {
|
||||||
|
std::unique_ptr<debug_attrs> &attrs = attrs_table[name];
|
||||||
|
if (attrs.get() == nullptr)
|
||||||
|
attrs = std::unique_ptr<debug_attrs>(new debug_attrs);
|
||||||
|
for (auto attr : item_attrs)
|
||||||
|
attrs->map.insert(attr);
|
||||||
|
item.attrs = attrs.get();
|
||||||
std::vector<debug_item> &parts = table[name];
|
std::vector<debug_item> &parts = table[name];
|
||||||
parts.emplace_back(item);
|
parts.emplace_back(item);
|
||||||
std::sort(parts.begin(), parts.end(),
|
std::sort(parts.begin(), parts.end(),
|
||||||
|
@ -1246,6 +1274,10 @@ struct debug_items {
|
||||||
const debug_item &operator [](const std::string &name) const {
|
const debug_item &operator [](const std::string &name) const {
|
||||||
return at(name);
|
return at(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const metadata_map &attrs(const std::string &name) const {
|
||||||
|
return attrs_table.at(name)->map;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Tag class to disambiguate the default constructor used by the toplevel module that calls reset(),
|
// Tag class to disambiguate the default constructor used by the toplevel module that calls reset(),
|
||||||
|
|
|
@ -2120,6 +2120,46 @@ struct CxxrtlWorker {
|
||||||
dec_indent();
|
dec_indent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dump_metadata_map(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map)
|
||||||
|
{
|
||||||
|
if (metadata_map.empty()) {
|
||||||
|
f << "metadata_map()";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
f << "metadata_map({\n";
|
||||||
|
inc_indent();
|
||||||
|
for (auto metadata_item : metadata_map) {
|
||||||
|
if (!metadata_item.first.isPublic())
|
||||||
|
continue;
|
||||||
|
if (metadata_item.second.size() > 64 && (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) == 0) {
|
||||||
|
f << indent << "/* attribute " << metadata_item.first.str().substr(1) << " is over 64 bits wide */";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
f << indent << "{ " << escape_cxx_string(metadata_item.first.str().substr(1)) << ", ";
|
||||||
|
// In Yosys, a real is a type of string.
|
||||||
|
if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) {
|
||||||
|
f << std::showpoint << std::stod(metadata_item.second.decode_string()) << std::noshowpoint;
|
||||||
|
} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) {
|
||||||
|
f << escape_cxx_string(metadata_item.second.decode_string());
|
||||||
|
} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED) {
|
||||||
|
f << "INT64_C(" << metadata_item.second.as_int(/*is_signed=*/true) << ")";
|
||||||
|
} else {
|
||||||
|
f << "UINT64_C(" << metadata_item.second.as_int(/*is_signed=*/false) << ")";
|
||||||
|
}
|
||||||
|
f << " },\n";
|
||||||
|
}
|
||||||
|
dec_indent();
|
||||||
|
f << indent << "})";
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_debug_attrs(const RTLIL::AttrObject *object)
|
||||||
|
{
|
||||||
|
dict<RTLIL::IdString, RTLIL::Const> attributes = object->attributes;
|
||||||
|
// Inherently necessary to get access to the object, so a waste of space to emit.
|
||||||
|
attributes.erase(ID::hdlname);
|
||||||
|
dump_metadata_map(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
void dump_debug_info_method(RTLIL::Module *module)
|
void dump_debug_info_method(RTLIL::Module *module)
|
||||||
{
|
{
|
||||||
size_t count_public_wires = 0;
|
size_t count_public_wires = 0;
|
||||||
|
@ -2205,7 +2245,9 @@ struct CxxrtlWorker {
|
||||||
}
|
}
|
||||||
f << "debug_item::" << flag;
|
f << "debug_item::" << flag;
|
||||||
}
|
}
|
||||||
f << "));\n";
|
f << "), ";
|
||||||
|
dump_debug_attrs(wire);
|
||||||
|
f << ");\n";
|
||||||
count_member_wires++;
|
count_member_wires++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2220,7 +2262,9 @@ struct CxxrtlWorker {
|
||||||
f << "debug_eval_outline";
|
f << "debug_eval_outline";
|
||||||
else
|
else
|
||||||
f << "debug_alias()";
|
f << "debug_alias()";
|
||||||
f << ", " << mangle(aliasee) << ", " << wire->start_offset << "));\n";
|
f << ", " << mangle(aliasee) << ", " << wire->start_offset << "), ";
|
||||||
|
dump_debug_attrs(aliasee);
|
||||||
|
f << ");\n";
|
||||||
count_alias_wires++;
|
count_alias_wires++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2230,14 +2274,18 @@ struct CxxrtlWorker {
|
||||||
dump_const(debug_wire_type.sig_subst.as_const());
|
dump_const(debug_wire_type.sig_subst.as_const());
|
||||||
f << ";\n";
|
f << ";\n";
|
||||||
f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
|
f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
|
||||||
f << ", debug_item(const_" << mangle(wire) << ", " << wire->start_offset << "));\n";
|
f << ", debug_item(const_" << mangle(wire) << ", " << wire->start_offset << "), ";
|
||||||
|
dump_debug_attrs(wire);
|
||||||
|
f << ");\n";
|
||||||
count_const_wires++;
|
count_const_wires++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WireType::OUTLINE: {
|
case WireType::OUTLINE: {
|
||||||
// Localized or inlined, but rematerializable wire
|
// Localized or inlined, but rematerializable wire
|
||||||
f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
|
f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire));
|
||||||
f << ", debug_item(debug_eval_outline, " << mangle(wire) << ", " << wire->start_offset << "));\n";
|
f << ", debug_item(debug_eval_outline, " << mangle(wire) << ", " << wire->start_offset << "), ";
|
||||||
|
dump_debug_attrs(wire);
|
||||||
|
f << ");\n";
|
||||||
count_inline_wires++;
|
count_inline_wires++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2254,7 +2302,13 @@ struct CxxrtlWorker {
|
||||||
continue;
|
continue;
|
||||||
f << indent << "items.add(path + " << escape_cxx_string(mem.packed ? get_hdl_name(mem.cell) : get_hdl_name(mem.mem));
|
f << indent << "items.add(path + " << escape_cxx_string(mem.packed ? get_hdl_name(mem.cell) : get_hdl_name(mem.mem));
|
||||||
f << ", debug_item(" << mangle(&mem) << ", ";
|
f << ", debug_item(" << mangle(&mem) << ", ";
|
||||||
f << mem.start_offset << "));\n";
|
f << mem.start_offset << "), ";
|
||||||
|
if (mem.packed) {
|
||||||
|
dump_debug_attrs(mem.cell);
|
||||||
|
} else {
|
||||||
|
dump_debug_attrs(mem.mem);
|
||||||
|
}
|
||||||
|
f << ");\n";
|
||||||
}
|
}
|
||||||
for (auto cell : module->cells()) {
|
for (auto cell : module->cells()) {
|
||||||
if (is_internal_cell(cell->type))
|
if (is_internal_cell(cell->type))
|
||||||
|
@ -2282,33 +2336,6 @@ struct CxxrtlWorker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_metadata_map(const dict<RTLIL::IdString, RTLIL::Const> &metadata_map)
|
|
||||||
{
|
|
||||||
if (metadata_map.empty()) {
|
|
||||||
f << "metadata_map()";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
f << "metadata_map({\n";
|
|
||||||
inc_indent();
|
|
||||||
for (auto metadata_item : metadata_map) {
|
|
||||||
if (!metadata_item.first.begins_with("\\"))
|
|
||||||
continue;
|
|
||||||
f << indent << "{ " << escape_cxx_string(metadata_item.first.str().substr(1)) << ", ";
|
|
||||||
if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) {
|
|
||||||
f << std::showpoint << std::stod(metadata_item.second.decode_string()) << std::noshowpoint;
|
|
||||||
} else if (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) {
|
|
||||||
f << escape_cxx_string(metadata_item.second.decode_string());
|
|
||||||
} else {
|
|
||||||
f << metadata_item.second.as_int(/*is_signed=*/metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED);
|
|
||||||
if (!(metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED))
|
|
||||||
f << "u";
|
|
||||||
}
|
|
||||||
f << " },\n";
|
|
||||||
}
|
|
||||||
dec_indent();
|
|
||||||
f << indent << "})";
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_module_intf(RTLIL::Module *module)
|
void dump_module_intf(RTLIL::Module *module)
|
||||||
{
|
{
|
||||||
dump_attrs(module);
|
dump_attrs(module);
|
||||||
|
|
|
@ -90,3 +90,46 @@ void cxxrtl_enum(cxxrtl_handle handle, void *data,
|
||||||
void cxxrtl_outline_eval(cxxrtl_outline outline) {
|
void cxxrtl_outline_eval(cxxrtl_outline outline) {
|
||||||
outline->eval();
|
outline->eval();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cxxrtl_attr_type(cxxrtl_attr_set attrs_, const char *name) {
|
||||||
|
auto attrs = (cxxrtl::metadata_map*)attrs_;
|
||||||
|
if (!attrs->count(name))
|
||||||
|
return CXXRTL_ATTR_NONE;
|
||||||
|
switch (attrs->at(name).value_type) {
|
||||||
|
case cxxrtl::metadata::UINT:
|
||||||
|
return CXXRTL_ATTR_UNSIGNED_INT;
|
||||||
|
case cxxrtl::metadata::SINT:
|
||||||
|
return CXXRTL_ATTR_SIGNED_INT;
|
||||||
|
case cxxrtl::metadata::STRING:
|
||||||
|
return CXXRTL_ATTR_STRING;
|
||||||
|
case cxxrtl::metadata::DOUBLE:
|
||||||
|
return CXXRTL_ATTR_DOUBLE;
|
||||||
|
default:
|
||||||
|
// Present unsupported attribute type the same way as no attribute at all.
|
||||||
|
return CXXRTL_ATTR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t cxxrtl_attr_get_unsigned_int(cxxrtl_attr_set attrs_, const char *name) {
|
||||||
|
auto &attrs = *(cxxrtl::metadata_map*)attrs_;
|
||||||
|
assert(attrs.count(name) && attrs.at(name).value_type == cxxrtl::metadata::UINT);
|
||||||
|
return attrs[name].as_uint();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t cxxrtl_attr_get_signed_int(cxxrtl_attr_set attrs_, const char *name) {
|
||||||
|
auto &attrs = *(cxxrtl::metadata_map*)attrs_;
|
||||||
|
assert(attrs.count(name) && attrs.at(name).value_type == cxxrtl::metadata::SINT);
|
||||||
|
return attrs[name].as_sint();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cxxrtl_attr_get_string(cxxrtl_attr_set attrs_, const char *name) {
|
||||||
|
auto &attrs = *(cxxrtl::metadata_map*)attrs_;
|
||||||
|
assert(attrs.count(name) && attrs.at(name).value_type == cxxrtl::metadata::STRING);
|
||||||
|
return attrs[name].as_string().c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
double cxxrtl_attr_get_double(cxxrtl_attr_set attrs_, const char *name) {
|
||||||
|
auto &attrs = *(cxxrtl::metadata_map*)attrs_;
|
||||||
|
assert(attrs.count(name) && attrs.at(name).value_type == cxxrtl::metadata::DOUBLE);
|
||||||
|
return attrs[name].as_double();
|
||||||
|
}
|
||||||
|
|
|
@ -249,6 +249,15 @@ struct cxxrtl_object {
|
||||||
// this field to NULL.
|
// this field to NULL.
|
||||||
struct _cxxrtl_outline *outline;
|
struct _cxxrtl_outline *outline;
|
||||||
|
|
||||||
|
// Opaque reference to an attribute set.
|
||||||
|
//
|
||||||
|
// See the documentation of `cxxrtl_attr_set` for details. When creating a `cxxrtl_object`, set
|
||||||
|
// this field to NULL.
|
||||||
|
//
|
||||||
|
// The lifetime of the pointers returned by `cxxrtl_attr_*` family of functions is the same as
|
||||||
|
// the lifetime of this structure.
|
||||||
|
struct _cxxrtl_attr_set *attrs;
|
||||||
|
|
||||||
// More description fields may be added in the future, but the existing ones will never change.
|
// More description fields may be added in the future, but the existing ones will never change.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -304,6 +313,62 @@ typedef struct _cxxrtl_outline *cxxrtl_outline;
|
||||||
// re-evaluated, otherwise the bits read from that object are meaningless.
|
// re-evaluated, otherwise the bits read from that object are meaningless.
|
||||||
void cxxrtl_outline_eval(cxxrtl_outline outline);
|
void cxxrtl_outline_eval(cxxrtl_outline outline);
|
||||||
|
|
||||||
|
// Opaque reference to an attribute set.
|
||||||
|
//
|
||||||
|
// An attribute set is a map between attribute names (always strings) and values (which may have
|
||||||
|
// several different types). To find out the type of an attribute, use `cxxrtl_attr_type`, and
|
||||||
|
// to retrieve the value of an attribute, use `cxxrtl_attr_as_string`.
|
||||||
|
typedef struct _cxxrtl_attr_set *cxxrtl_attr_set;
|
||||||
|
|
||||||
|
// Type of an attribute.
|
||||||
|
enum cxxrtl_attr_type {
|
||||||
|
// Attribute is not present.
|
||||||
|
CXXRTL_ATTR_NONE = 0,
|
||||||
|
|
||||||
|
// Attribute has an unsigned integer value.
|
||||||
|
CXXRTL_ATTR_UNSIGNED_INT = 1,
|
||||||
|
|
||||||
|
// Attribute has an unsigned integer value.
|
||||||
|
CXXRTL_ATTR_SIGNED_INT = 2,
|
||||||
|
|
||||||
|
// Attribute has a string value.
|
||||||
|
CXXRTL_ATTR_STRING = 3,
|
||||||
|
|
||||||
|
// Attribute has a double precision floating point value.
|
||||||
|
CXXRTL_ATTR_DOUBLE = 4,
|
||||||
|
|
||||||
|
// More attribute types may be defined in the future, but the existing values will never change.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine the presence and type of an attribute in an attribute set.
|
||||||
|
//
|
||||||
|
// This function returns one of the possible `cxxrtl_attr_type` values.
|
||||||
|
int cxxrtl_attr_type(cxxrtl_attr_set attrs, const char *name);
|
||||||
|
|
||||||
|
// Retrieve an unsigned integer valued attribute from an attribute set.
|
||||||
|
//
|
||||||
|
// This function asserts that `cxxrtl_attr_type(attrs, name) == CXXRTL_ATTR_UNSIGNED_INT`.
|
||||||
|
// If assertions are disabled, returns 0 if the attribute is missing or has an incorrect type.
|
||||||
|
uint64_t cxxrtl_attr_get_unsigned_int(cxxrtl_attr_set attrs, const char *name);
|
||||||
|
|
||||||
|
// Retrieve a signed integer valued attribute from an attribute set.
|
||||||
|
//
|
||||||
|
// This function asserts that `cxxrtl_attr_type(attrs, name) == CXXRTL_ATTR_SIGNED_INT`.
|
||||||
|
// If assertions are disabled, returns 0 if the attribute is missing or has an incorrect type.
|
||||||
|
int64_t cxxrtl_attr_get_signed_int(cxxrtl_attr_set attrs, const char *name);
|
||||||
|
|
||||||
|
// Retrieve a string valued attribute from an attribute set. The returned string is zero-terminated.
|
||||||
|
//
|
||||||
|
// This function asserts that `cxxrtl_attr_type(attrs, name) == CXXRTL_ATTR_STRING`. If assertions
|
||||||
|
// are disabled, returns NULL if the attribute is missing or has an incorrect type.
|
||||||
|
const char *cxxrtl_attr_get_string(cxxrtl_attr_set attrs, const char *name);
|
||||||
|
|
||||||
|
// Retrieve a double precision floating point valued attribute from an attribute set.
|
||||||
|
//
|
||||||
|
// This function asserts that `cxxrtl_attr_type(attrs, name) == CXXRTL_ATTR_DOUBLE`. If assertions
|
||||||
|
// are disabled, returns NULL if the attribute is missing or has an incorrect type.
|
||||||
|
double cxxrtl_attr_get_double(cxxrtl_attr_set attrs, const char *name);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue