diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2016-03-19 21:18:35 +0000 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2016-04-08 19:38:36 +0200 |
commit | cc4c9b70bcac048fc388d0f553b7621f52449526 (patch) | |
tree | 68e7757577855c81e2b0a3f4f3d2b0762d4dcc31 /utils | |
parent | f6c61eb11a13f7a5141a980f56b9a14b3309c449 (diff) |
regtools: add register access to soc desc
Registers (and variants) can now specify the type of access supported:
- unspecified: for variant means same as register, for register defaults R/W
- read/write
- read only
- write only
Backward compatibility is preserved by setting access to unspecified by default.
Change-Id: I3e84ae18f962a45db62f996a542d08405d05b895
Diffstat (limited to 'utils')
-rw-r--r-- | utils/regtools/desc/regs-vsoc2000.xml | 6 | ||||
-rw-r--r-- | utils/regtools/include/soc_desc.hpp | 27 | ||||
-rw-r--r-- | utils/regtools/lib/soc_desc.cpp | 41 |
3 files changed, 68 insertions, 6 deletions
diff --git a/utils/regtools/desc/regs-vsoc2000.xml b/utils/regtools/desc/regs-vsoc2000.xml index bcd6d08d38..858c13254c 100644 --- a/utils/regtools/desc/regs-vsoc2000.xml +++ b/utils/regtools/desc/regs-vsoc2000.xml @@ -390,6 +390,12 @@ </instance> <register> <width>8</width> + <access>read-only</access> + <variant> + <type>debug</type> + <offset>4</offset> + <access>write-only</access> + </variant> </register> </node> </node> diff --git a/utils/regtools/include/soc_desc.hpp b/utils/regtools/include/soc_desc.hpp index 66562f80d9..99f8706789 100644 --- a/utils/regtools/include/soc_desc.hpp +++ b/utils/regtools/include/soc_desc.hpp @@ -77,6 +77,21 @@ protected: * Bare representation of the format */ +/** Register access type and rules + * + * Access can be specified on registers and register variants. When left + * unspecified (aka DEFAULT), a register variant inherit the access from + * the register, and a register defaults to read-write if unspecified. + * When specified, the register variant access takes precedence over the register + * access. */ +enum access_t +{ + UNSPECIFIED = 0, /** Register: read-write, fields: inherit from register */ + READ_ONLY, /** Read-only */ + READ_WRITE, /** Read-write */ + WRITE_ONLY, /** Write-only */ +}; + /** Enumerated value (aka named value), represents a special value for a field */ struct enum_t { @@ -137,33 +152,37 @@ struct field_t /** Register variant information * * A register variant provides an alternative access to the register, potentially - * we special semantics. Although there are no constraints on the type string, + * with special semantics. Although there are no constraints on the type string, * the following types have well-defined semantics: * - alias: the same register at another address * - set: writing to this register will set the 1s bits and ignore the 0s * - clr: writing to this register will clear the 1s bits and ignore the 0s * - tog: writing to this register will toggle the 1s bits and ignore the 0s + * Note that by default, variants inherit the access type of the register but + * can override it. */ struct variant_t { soc_id_t id; /** ID (must be unique among register variants) */ std::string type; /** type of the variant */ soc_addr_t offset; /** offset of the variant */ + access_t access; /** Access type */ - /** Default constructor: default ID, offset is 0 */ - variant_t():id(DEFAULT_ID), offset(0) {} + /** Default constructor: default ID, offset is 0, access is unspecified */ + variant_t():id(DEFAULT_ID), offset(0), access(UNSPECIFIED) {} }; /** Register information */ struct register_t { size_t width; /** Size in bits */ + access_t access; /** Access type */ std::string desc; /** Optional description of the register */ std::vector< field_t > field; /** List of fields */ std::vector< variant_t > variant; /** List of variants */ /** Default constructor: width is 32 */ - register_t():width(32) {} + register_t():width(32), access(UNSPECIFIED) {} }; /** Node address range information */ diff --git a/utils/regtools/lib/soc_desc.cpp b/utils/regtools/lib/soc_desc.cpp index a72e7e9f7c..b52201672f 100644 --- a/utils/regtools/lib/soc_desc.cpp +++ b/utils/regtools/lib/soc_desc.cpp @@ -262,6 +262,20 @@ bool parse_unknown_elem(xmlNode *node, error_context_t& ctx) return add_fatal(ctx, node, oss.str()); } +bool parse_access_elem(xmlNode *node, access_t& acc, xmlChar *content, error_context_t& ctx) +{ + const char *text = XML_CHAR_TO_CHAR(content); + if(strcmp(text, "read-only") == 0) + acc = READ_ONLY; + else if(strcmp(text, "read-write") == 0) + acc = READ_WRITE; + else if(strcmp(text, "write-only") == 0) + acc = WRITE_ONLY; + else + return add_fatal(ctx, node, "unknown access type " + std::string(text)); + return true; +} + template<typename T, typename U> bool parse_unsigned_text(U *node, T& res, xmlChar *content, error_context_t& ctx) { @@ -348,30 +362,36 @@ bool parse_field_elem(xmlNode *node, field_t& field, error_context_t& ctx) bool parse_variant_elem(xmlNode *node, variant_t& variant, error_context_t& ctx) { bool ret = true; - bool has_type = false, has_offset = false; + bool has_type = false, has_offset = false, has_access = false; BEGIN_NODE_MATCH(node->children) MATCH_UNIQUE_TEXT_NODE("type", variant.type, has_type, parse_name_elem, ctx) MATCH_UNIQUE_TEXT_NODE("offset", variant.offset, has_offset, parse_unsigned_elem, ctx) + MATCH_UNIQUE_TEXT_NODE("access", variant.access, has_access, parse_access_elem, ctx) MATCH_UNUSED_NODE(parse_unknown_elem, ctx) END_NODE_MATCH() CHECK_HAS(node, "type", has_type, ctx) CHECK_HAS(node, "offset", has_offset, ctx) + if(!has_access) + variant.access = UNSPECIFIED; return ret; } bool parse_register_elem(xmlNode *node, register_t& reg, error_context_t& ctx) { bool ret = true; - bool has_width = false, has_desc = false; + bool has_width = false, has_desc = false, has_access = false; BEGIN_NODE_MATCH(node->children) MATCH_UNIQUE_TEXT_NODE("desc", reg.desc, has_desc, parse_text_elem, ctx) MATCH_UNIQUE_TEXT_NODE("width", reg.width, has_width, parse_unsigned_elem, ctx) + MATCH_UNIQUE_TEXT_NODE("access", reg.access, has_access, parse_access_elem, ctx) MATCH_ELEM_NODE("field", reg.field, parse_field_elem, ctx) MATCH_ELEM_NODE("variant", reg.variant, parse_variant_elem, ctx) MATCH_UNUSED_NODE(parse_unknown_elem, ctx) END_NODE_MATCH() if(!has_width) reg.width = 32; + if(!has_access) + reg.access = UNSPECIFIED; return ret; } @@ -746,6 +766,17 @@ int produce_field(xmlTextWriterPtr writer, const field_t& field, error_context_t return 0; } +const char *access_string(access_t acc) +{ + switch(acc) + { + case READ_ONLY: return "read-only"; + case READ_WRITE: return "read-write"; + case WRITE_ONLY: return "write-only"; + default: return "bug-invalid-access"; + } +} + int produce_variant(xmlTextWriterPtr writer, const variant_t& variant, error_context_t& ctx) { /* <variant> */ @@ -754,6 +785,9 @@ int produce_variant(xmlTextWriterPtr writer, const variant_t& variant, error_con SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "type", BAD_CAST variant.type.c_str())); /* <position/> */ SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "offset", "%lu", (unsigned long)variant.offset)); + /* <access/> */ + if(variant.access != UNSPECIFIED) + SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "access", BAD_CAST access_string(variant.access))); /* </variant> */ SAFE(xmlTextWriterEndElement(writer)); return 0; @@ -769,6 +803,9 @@ int produce_register(xmlTextWriterPtr writer, const register_t& reg, error_conte /* <desc/> */ if(!reg.desc.empty()) SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str())); + /* <access/> */ + if(reg.access != UNSPECIFIED) + SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "access", BAD_CAST access_string(reg.access))); /* fields */ for(size_t i = 0; i < reg.field.size(); i++) SAFE(produce_field(writer, reg.field[i], ctx)); |