v3d: Create XML fields for min_ver and max_ver of a packet/struct/enum.
authorEric Anholt <eric@anholt.net>
Wed, 27 Jun 2018 18:10:07 +0000 (11:10 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 29 Jun 2018 20:36:28 +0000 (13:36 -0700)
This will be used to merge together the V3D 3.3-4.1 XML with the variants
disabled based on the version.

src/broadcom/cle/gen_pack_header.py
src/broadcom/cle/v3d_decoder.c

index df547fb..c6e1c56 100644 (file)
@@ -192,6 +192,8 @@ class Group(object):
         self.count = count
         self.size = 0
         self.fields = []
+        self.min_ver = 0
+        self.max_ver = 0
 
     def emit_template_struct(self, dim):
         if self.count == 0:
@@ -414,6 +416,24 @@ class Parser(object):
     def gen_guard(self):
         return self.gen_prefix("PACK_H")
 
+    def attrs_version_valid(self, attrs):
+        if "min_ver" in attrs and self.ver < attrs["min_ver"]:
+            return False
+
+        if "max_ver" in attrs and self.ver > attrs["max_ver"]:
+            return False
+
+        return True
+
+    def group_enabled(self):
+        if self.group.min_ver != 0 and self.ver < self.group.min_ver:
+            return False
+
+        if self.group.max_ver != 0 and self.ver > self.group.max_ver:
+            return False
+
+        return True
+
     def start_element(self, name, attrs):
         if name == "vcxml":
             self.platform = "V3D {}.{}".format(self.ver[0], self.ver[1])
@@ -449,6 +469,11 @@ class Parser(object):
                 field.values = []
                 self.group.fields.append(field)
 
+            if "min_ver" in attrs:
+                self.group.min_ver = attrs["min_ver"]
+            if "max_ver" in attrs:
+                self.group.max_ver = attrs["max_ver"]
+
         elif name == "field":
             self.group.fields.append(Field(self, attrs))
             self.values = []
@@ -456,12 +481,14 @@ class Parser(object):
             self.values = []
             self.enum = safe_name(attrs["name"])
             self.enums.add(attrs["name"])
+            self.enum_enabled = self.attrs_version_valid(attrs)
             if "prefix" in attrs:
                 self.prefix = attrs["prefix"]
             else:
                 self.prefix= None
         elif name == "value":
-            self.values.append(Value(attrs))
+            if self.attrs_version_valid(attrs):
+                self.values.append(Value(attrs))
 
     def end_element(self, name):
         if name  == "packet":
@@ -480,7 +507,8 @@ class Parser(object):
         elif name  == "field":
             self.group.fields[-1].values = self.values
         elif name  == "enum":
-            self.emit_enum()
+            if self.enum_enabled:
+                self.emit_enum()
             self.enum = None
         elif name == "vcxml":
             print('#endif /* %s */' % self.gen_guard())
@@ -525,6 +553,9 @@ class Parser(object):
         print('')
 
     def emit_packet(self):
+        if not self.group_enabled():
+            return
+
         name = self.packet
 
         assert(self.group.fields[0].name == "opcode")
@@ -539,6 +570,9 @@ class Parser(object):
         print('')
 
     def emit_register(self):
+        if not self.group_enabled():
+            return
+
         name = self.register
         if not self.reg_num == None:
             print('#define %-33s 0x%04x' %
@@ -549,6 +583,9 @@ class Parser(object):
         self.emit_unpack_function(self.register, self.group)
 
     def emit_struct(self):
+        if not self.group_enabled():
+            return
+
         name = self.struct
 
         self.emit_header(name)
index ed9cb7d..d76c004 100644 (file)
@@ -58,6 +58,7 @@ struct location {
 
 struct parser_context {
         XML_Parser parser;
+        const struct v3d_device_info *devinfo;
         int foo;
         struct location loc;
 
@@ -68,6 +69,9 @@ struct parser_context {
         struct v3d_value *values[256];
 
         struct v3d_spec *spec;
+
+        int parse_depth;
+        int parse_skip_depth;
 };
 
 const char *
@@ -414,6 +418,25 @@ set_group_opcode(struct v3d_group *group, const char **atts)
         return;
 }
 
+static bool
+ver_in_range(int ver, int min_ver, int max_ver)
+{
+        return ((min_ver == 0 || ver >= min_ver) &&
+                (max_ver == 0 || ver <= max_ver));
+}
+
+static bool
+skip_if_ver_mismatch(struct parser_context *ctx, int min_ver, int max_ver)
+{
+        if (!ctx->parse_skip_depth && !ver_in_range(ctx->devinfo->ver,
+                                                    min_ver, max_ver)) {
+                assert(ctx->parse_depth != 0);
+                ctx->parse_skip_depth = ctx->parse_depth;
+        }
+
+        return ctx->parse_skip_depth;
+}
+
 static void
 start_element(void *data, const char *element_name, const char **atts)
 {
@@ -421,6 +444,8 @@ start_element(void *data, const char *element_name, const char **atts)
         int i;
         const char *name = NULL;
         const char *ver = NULL;
+        int min_ver = 0;
+        int max_ver = 0;
 
         ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
 
@@ -429,8 +454,15 @@ start_element(void *data, const char *element_name, const char **atts)
                         name = atts[i + 1];
                 else if (strcmp(atts[i], "gen") == 0)
                         ver = atts[i + 1];
+                else if (strcmp(atts[i], "min_ver") == 0)
+                        min_ver = strtoul(atts[i + 1], NULL, 0);
+                else if (strcmp(atts[i], "max_ver") == 0)
+                        max_ver = strtoul(atts[i + 1], NULL, 0);
         }
 
+        if (skip_if_ver_mismatch(ctx, min_ver, max_ver))
+                goto skip;
+
         if (strcmp(element_name, "vcxml") == 0) {
                 if (ver == NULL)
                         fail(&ctx->loc, "no ver given");
@@ -470,6 +502,8 @@ start_element(void *data, const char *element_name, const char **atts)
                 assert(ctx->nvalues < ARRAY_SIZE(ctx->values));
         }
 
+skip:
+        ctx->parse_depth++;
 }
 
 static void
@@ -478,6 +512,14 @@ end_element(void *data, const char *name)
         struct parser_context *ctx = data;
         struct v3d_spec *spec = ctx->spec;
 
+        ctx->parse_depth--;
+
+        if (ctx->parse_skip_depth) {
+                if (ctx->parse_skip_depth == ctx->parse_depth)
+                        ctx->parse_skip_depth = 0;
+                return;
+        }
+
         if (strcmp(name, "packet") == 0 ||
             strcmp(name, "struct") == 0 ||
             strcmp(name, "register") == 0) {
@@ -603,6 +645,7 @@ v3d_spec_load(const struct v3d_device_info *devinfo)
 
         memset(&ctx, 0, sizeof ctx);
         ctx.parser = XML_ParserCreate(NULL);
+        ctx.devinfo = devinfo;
         XML_SetUserData(ctx.parser, &ctx);
         if (ctx.parser == NULL) {
                 fprintf(stderr, "failed to create parser\n");