summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/regtools/desc/regs-vsoc2000.xml6
-rw-r--r--utils/regtools/include/soc_desc.hpp27
-rw-r--r--utils/regtools/lib/soc_desc.cpp41
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 @@
390 </instance> 390 </instance>
391 <register> 391 <register>
392 <width>8</width> 392 <width>8</width>
393 <access>read-only</access>
394 <variant>
395 <type>debug</type>
396 <offset>4</offset>
397 <access>write-only</access>
398 </variant>
393 </register> 399 </register>
394 </node> 400 </node>
395 </node> 401 </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:
77 * Bare representation of the format 77 * Bare representation of the format
78 */ 78 */
79 79
80/** Register access type and rules
81 *
82 * Access can be specified on registers and register variants. When left
83 * unspecified (aka DEFAULT), a register variant inherit the access from
84 * the register, and a register defaults to read-write if unspecified.
85 * When specified, the register variant access takes precedence over the register
86 * access. */
87enum access_t
88{
89 UNSPECIFIED = 0, /** Register: read-write, fields: inherit from register */
90 READ_ONLY, /** Read-only */
91 READ_WRITE, /** Read-write */
92 WRITE_ONLY, /** Write-only */
93};
94
80/** Enumerated value (aka named value), represents a special value for a field */ 95/** Enumerated value (aka named value), represents a special value for a field */
81struct enum_t 96struct enum_t
82{ 97{
@@ -137,33 +152,37 @@ struct field_t
137/** Register variant information 152/** Register variant information
138 * 153 *
139 * A register variant provides an alternative access to the register, potentially 154 * A register variant provides an alternative access to the register, potentially
140 * we special semantics. Although there are no constraints on the type string, 155 * with special semantics. Although there are no constraints on the type string,
141 * the following types have well-defined semantics: 156 * the following types have well-defined semantics:
142 * - alias: the same register at another address 157 * - alias: the same register at another address
143 * - set: writing to this register will set the 1s bits and ignore the 0s 158 * - set: writing to this register will set the 1s bits and ignore the 0s
144 * - clr: writing to this register will clear the 1s bits and ignore the 0s 159 * - clr: writing to this register will clear the 1s bits and ignore the 0s
145 * - tog: writing to this register will toggle the 1s bits and ignore the 0s 160 * - tog: writing to this register will toggle the 1s bits and ignore the 0s
161 * Note that by default, variants inherit the access type of the register but
162 * can override it.
146 */ 163 */
147struct variant_t 164struct variant_t
148{ 165{
149 soc_id_t id; /** ID (must be unique among register variants) */ 166 soc_id_t id; /** ID (must be unique among register variants) */
150 std::string type; /** type of the variant */ 167 std::string type; /** type of the variant */
151 soc_addr_t offset; /** offset of the variant */ 168 soc_addr_t offset; /** offset of the variant */
169 access_t access; /** Access type */
152 170
153 /** Default constructor: default ID, offset is 0 */ 171 /** Default constructor: default ID, offset is 0, access is unspecified */
154 variant_t():id(DEFAULT_ID), offset(0) {} 172 variant_t():id(DEFAULT_ID), offset(0), access(UNSPECIFIED) {}
155}; 173};
156 174
157/** Register information */ 175/** Register information */
158struct register_t 176struct register_t
159{ 177{
160 size_t width; /** Size in bits */ 178 size_t width; /** Size in bits */
179 access_t access; /** Access type */
161 std::string desc; /** Optional description of the register */ 180 std::string desc; /** Optional description of the register */
162 std::vector< field_t > field; /** List of fields */ 181 std::vector< field_t > field; /** List of fields */
163 std::vector< variant_t > variant; /** List of variants */ 182 std::vector< variant_t > variant; /** List of variants */
164 183
165 /** Default constructor: width is 32 */ 184 /** Default constructor: width is 32 */
166 register_t():width(32) {} 185 register_t():width(32), access(UNSPECIFIED) {}
167}; 186};
168 187
169/** Node address range information */ 188/** 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)
262 return add_fatal(ctx, node, oss.str()); 262 return add_fatal(ctx, node, oss.str());
263} 263}
264 264
265bool parse_access_elem(xmlNode *node, access_t& acc, xmlChar *content, error_context_t& ctx)
266{
267 const char *text = XML_CHAR_TO_CHAR(content);
268 if(strcmp(text, "read-only") == 0)
269 acc = READ_ONLY;
270 else if(strcmp(text, "read-write") == 0)
271 acc = READ_WRITE;
272 else if(strcmp(text, "write-only") == 0)
273 acc = WRITE_ONLY;
274 else
275 return add_fatal(ctx, node, "unknown access type " + std::string(text));
276 return true;
277}
278
265template<typename T, typename U> 279template<typename T, typename U>
266bool parse_unsigned_text(U *node, T& res, xmlChar *content, error_context_t& ctx) 280bool parse_unsigned_text(U *node, T& res, xmlChar *content, error_context_t& ctx)
267{ 281{
@@ -348,30 +362,36 @@ bool parse_field_elem(xmlNode *node, field_t& field, error_context_t& ctx)
348bool parse_variant_elem(xmlNode *node, variant_t& variant, error_context_t& ctx) 362bool parse_variant_elem(xmlNode *node, variant_t& variant, error_context_t& ctx)
349{ 363{
350 bool ret = true; 364 bool ret = true;
351 bool has_type = false, has_offset = false; 365 bool has_type = false, has_offset = false, has_access = false;
352 BEGIN_NODE_MATCH(node->children) 366 BEGIN_NODE_MATCH(node->children)
353 MATCH_UNIQUE_TEXT_NODE("type", variant.type, has_type, parse_name_elem, ctx) 367 MATCH_UNIQUE_TEXT_NODE("type", variant.type, has_type, parse_name_elem, ctx)
354 MATCH_UNIQUE_TEXT_NODE("offset", variant.offset, has_offset, parse_unsigned_elem, ctx) 368 MATCH_UNIQUE_TEXT_NODE("offset", variant.offset, has_offset, parse_unsigned_elem, ctx)
369 MATCH_UNIQUE_TEXT_NODE("access", variant.access, has_access, parse_access_elem, ctx)
355 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 370 MATCH_UNUSED_NODE(parse_unknown_elem, ctx)
356 END_NODE_MATCH() 371 END_NODE_MATCH()
357 CHECK_HAS(node, "type", has_type, ctx) 372 CHECK_HAS(node, "type", has_type, ctx)
358 CHECK_HAS(node, "offset", has_offset, ctx) 373 CHECK_HAS(node, "offset", has_offset, ctx)
374 if(!has_access)
375 variant.access = UNSPECIFIED;
359 return ret; 376 return ret;
360} 377}
361 378
362bool parse_register_elem(xmlNode *node, register_t& reg, error_context_t& ctx) 379bool parse_register_elem(xmlNode *node, register_t& reg, error_context_t& ctx)
363{ 380{
364 bool ret = true; 381 bool ret = true;
365 bool has_width = false, has_desc = false; 382 bool has_width = false, has_desc = false, has_access = false;
366 BEGIN_NODE_MATCH(node->children) 383 BEGIN_NODE_MATCH(node->children)
367 MATCH_UNIQUE_TEXT_NODE("desc", reg.desc, has_desc, parse_text_elem, ctx) 384 MATCH_UNIQUE_TEXT_NODE("desc", reg.desc, has_desc, parse_text_elem, ctx)
368 MATCH_UNIQUE_TEXT_NODE("width", reg.width, has_width, parse_unsigned_elem, ctx) 385 MATCH_UNIQUE_TEXT_NODE("width", reg.width, has_width, parse_unsigned_elem, ctx)
386 MATCH_UNIQUE_TEXT_NODE("access", reg.access, has_access, parse_access_elem, ctx)
369 MATCH_ELEM_NODE("field", reg.field, parse_field_elem, ctx) 387 MATCH_ELEM_NODE("field", reg.field, parse_field_elem, ctx)
370 MATCH_ELEM_NODE("variant", reg.variant, parse_variant_elem, ctx) 388 MATCH_ELEM_NODE("variant", reg.variant, parse_variant_elem, ctx)
371 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 389 MATCH_UNUSED_NODE(parse_unknown_elem, ctx)
372 END_NODE_MATCH() 390 END_NODE_MATCH()
373 if(!has_width) 391 if(!has_width)
374 reg.width = 32; 392 reg.width = 32;
393 if(!has_access)
394 reg.access = UNSPECIFIED;
375 return ret; 395 return ret;
376} 396}
377 397
@@ -746,6 +766,17 @@ int produce_field(xmlTextWriterPtr writer, const field_t& field, error_context_t
746 return 0; 766 return 0;
747} 767}
748 768
769const char *access_string(access_t acc)
770{
771 switch(acc)
772 {
773 case READ_ONLY: return "read-only";
774 case READ_WRITE: return "read-write";
775 case WRITE_ONLY: return "write-only";
776 default: return "bug-invalid-access";
777 }
778}
779
749int produce_variant(xmlTextWriterPtr writer, const variant_t& variant, error_context_t& ctx) 780int produce_variant(xmlTextWriterPtr writer, const variant_t& variant, error_context_t& ctx)
750{ 781{
751 /* <variant> */ 782 /* <variant> */
@@ -754,6 +785,9 @@ int produce_variant(xmlTextWriterPtr writer, const variant_t& variant, error_con
754 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "type", BAD_CAST variant.type.c_str())); 785 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "type", BAD_CAST variant.type.c_str()));
755 /* <position/> */ 786 /* <position/> */
756 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "offset", "%lu", (unsigned long)variant.offset)); 787 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "offset", "%lu", (unsigned long)variant.offset));
788 /* <access/> */
789 if(variant.access != UNSPECIFIED)
790 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "access", BAD_CAST access_string(variant.access)));
757 /* </variant> */ 791 /* </variant> */
758 SAFE(xmlTextWriterEndElement(writer)); 792 SAFE(xmlTextWriterEndElement(writer));
759 return 0; 793 return 0;
@@ -769,6 +803,9 @@ int produce_register(xmlTextWriterPtr writer, const register_t& reg, error_conte
769 /* <desc/> */ 803 /* <desc/> */
770 if(!reg.desc.empty()) 804 if(!reg.desc.empty())
771 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str())); 805 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str()));
806 /* <access/> */
807 if(reg.access != UNSPECIFIED)
808 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "access", BAD_CAST access_string(reg.access)));
772 /* fields */ 809 /* fields */
773 for(size_t i = 0; i < reg.field.size(); i++) 810 for(size_t i = 0; i < reg.field.size(); i++)
774 SAFE(produce_field(writer, reg.field[i], ctx)); 811 SAFE(produce_field(writer, reg.field[i], ctx));