• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright © 2020 Google, Inc.
4#
5# Permission is hereby granted, free of charge, to any person obtaining a
6# copy of this software and associated documentation files (the "Software"),
7# to deal in the Software without restriction, including without limitation
8# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9# and/or sell copies of the Software, and to permit persons to whom the
10# Software is furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice (including the next
13# paragraph) shall be included in all copies or substantial portions of the
14# Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22# IN THE SOFTWARE.
23
24from mako.template import Template
25from isa import ISA, BitSetDerivedField, BitSetAssertField
26import sys
27import re
28
29# Encoding is driven by the display template that would be used
30# to decode any given instruction, essentially working backwards
31# from the decode case.  (Or put another way, the decoded bitset
32# should contain enough information to re-encode it again.)
33#
34# In the xml, we can have multiple override cases per bitset,
35# which can override display template and/or fields.  Iterating
36# all this from within the template is messy, so use helpers
37# outside of the template for this.
38#
39# The hierarchy of iterators for encoding is:
40#
41#   // First level - Case()  (s.bitset_cases() iterator)
42#   if (caseA.expression()) {  // maps to <override/> in xml
43#      // Second level - DisplayField()  (case.display_fields() iterator)
44#      ... encode field A ...
45#      ... encode field B ...
46#
47#      // Third level - each display field can be potentially resolved
48#      // by multiple different overrides, you can end up with
49#      // an if/else ladder for an individual display field
50#      if (field_c_case1.expression()) {
51#         ... encode field C ...
52#      } else if (field_c_case2.expression() {
53#         ... encode field C ...
54#      } else {
55#      }
56#
57#   } else if (caseB.expression())(
58#   } else {  // maps to the default case in bitset, ie. outside <override/>
59#   }
60
61
62# Represents a concrete field, ie. a field can be overriden
63# by an override, so the exact choice to encode a given field
64# in a bitset may be conditional
65class FieldCase(object):
66    def __init__(self, field, case):
67        self.field = field
68        self.expr  = None
69        if case.expr is not None:
70            self.expr = isa.expressions[case.expr]
71
72    def signed(self):
73        if self.field.type in ['int', 'offset', 'branch']:
74            return 'true'
75        return 'false'
76
77class AssertField(object):
78    def __init__(self, field, case):
79        self.field = field
80        self.expr  = None
81        if case.expr is not None:
82            self.expr = isa.expressions[case.expr]
83
84    def signed(self):
85        return 'false'
86
87# Represents a field to be encoded:
88class DisplayField(object):
89    def __init__(self, bitset, case, name):
90        self.bitset = bitset   # leaf bitset
91        self.case = case
92        self.name = name
93
94    def fields(self, bitset=None):
95        if bitset is None:
96            bitset = self.bitset
97        # resolving the various cases for encoding a given
98        # field is similar to resolving the display template
99        # string
100        for case in bitset.cases:
101            if case.expr is not None:
102                expr = bitset.isa.expressions[case.expr]
103                self.case.append_expr_fields(expr)
104            if self.name in case.fields:
105                field = case.fields[self.name]
106                # For bitset fields, the bitset type could reference
107                # fields in this (the containing) bitset, in addition
108                # to the ones which are directly used to encode the
109                # field itself.
110                if field.get_c_typename() == 'TYPE_BITSET':
111                    for param in field.params:
112                        self.case.append_field(param[0])
113                # For derived fields, we want to consider any other
114                # fields that are referenced by the expr
115                if isinstance(field, BitSetDerivedField):
116                    expr = bitset.isa.expressions[field.expr]
117                    self.case.append_expr_fields(expr)
118                elif not isinstance(field, BitSetAssertField):
119                    yield FieldCase(field, case)
120                # if we've found an unconditional case specifying
121                # the named field, we are done
122                if case.expr is None:
123                    return
124        if bitset.extends is not None:
125            yield from self.fields(isa.bitsets[bitset.extends])
126
127# Represents an if/else case in bitset encoding which has a display
128# template string:
129class Case(object):
130    def __init__(self, bitset, case):
131        self.bitset = bitset   # leaf bitset
132        self.case = case
133        self.expr = None
134        if case.expr is not None:
135            self.expr = isa.expressions[case.expr]
136        self.fieldnames = re.findall(r"{([a-zA-Z0-9_]+)}", case.display)
137        self.append_forced(bitset)
138
139    # Handle fields which don't appear in display template but have
140    # force="true"
141    def append_forced(self, bitset):
142        if bitset.encode is not None:
143            for name, val in bitset.encode.forced.items():
144                self.append_field(name)
145        if bitset.extends is not None:
146            self.append_forced(isa.bitsets[bitset.extends])
147
148    # In the process of resolving a field, we might discover additional
149    # fields that need resolving:
150    #
151    # a) a derived field which maps to one or more other concrete fields
152    # b) a bitset field, which may be "parameterized".. for example a
153    #    #multisrc field which refers back to SRC1_R/SRC2_R outside of
154    #    the range of bits covered by the #multisrc field itself
155    def append_field(self, fieldname):
156        if fieldname not in self.fieldnames:
157            self.fieldnames.append(fieldname)
158
159    def append_expr_fields(self, expr):
160        for fieldname in expr.fieldnames:
161            self.append_field(fieldname)
162
163    def display_fields(self):
164        for fieldname in self.fieldnames:
165            yield DisplayField(self.bitset, self, fieldname)
166
167    def assert_cases(self, bitset=None):
168        if bitset is None:
169            bitset = self.bitset
170        for case in bitset.cases:
171            for name, field in case.fields.items():
172                if field.get_c_typename() == 'TYPE_ASSERT':
173                    yield AssertField(field, case)
174        if bitset.extends is not None:
175            yield from self.assert_cases(isa.bitsets[bitset.extends])
176
177# State and helpers used by the template:
178class State(object):
179    def __init__(self, isa):
180        self.isa = isa
181        self.warned_missing_extractors = []
182
183    def bitset_cases(self, bitset, leaf_bitset=None):
184        if leaf_bitset is None:
185            leaf_bitset = bitset;
186        for case in bitset.cases:
187            if case.display is None:
188                # if this is the last case (ie. case.expr is None)
189                # then we need to go up the inheritance chain:
190                if case.expr is None and bitset.extends is not None:
191                    parent_bitset = isa.bitsets[bitset.extends]
192                    yield from self.bitset_cases(parent_bitset, leaf_bitset)
193                continue;
194            yield Case(leaf_bitset, case)
195
196    # Find unique bitset remap/parameter names, to generate a struct
197    # used to pass "parameters" to bitset fields:
198    def unique_param_names(self):
199        unique_names = []
200        for root in self.encode_roots():
201            for leaf in self.encode_leafs(root):
202                for case in s.bitset_cases(leaf):
203                    for df in case.display_fields():
204                        for f in df.fields():
205                            if f.field.get_c_typename() == 'TYPE_BITSET':
206                                for param in f.field.params:
207                                    target_name = param[1]
208                                    if target_name not in unique_names:
209                                        yield target_name
210                                        unique_names.append(target_name)
211
212    def case_name(self, bitset, name):
213       return bitset.encode.case_prefix + name.upper().replace('.', '_').replace('-', '_').replace('#', '')
214
215    def encode_roots(self):
216       for name, root in self.isa.roots.items():
217          if root.encode is None:
218             continue
219          yield root
220
221    def encode_leafs(self, root):
222        for name, leafs in self.isa.leafs.items():
223            for leaf in leafs:
224                if leaf.get_root() != root:
225                    continue
226                yield leaf
227
228    def encode_leaf_groups(self, root):
229        for name, leafs in self.isa.leafs.items():
230            if leafs[0].get_root() != root:
231                continue
232            yield leafs
233
234    # expressions used in a bitset (case or field or recursively parent bitsets)
235    def bitset_used_exprs(self, bitset):
236       for case in bitset.cases:
237          if case.expr:
238             yield self.isa.expressions[case.expr]
239          for name, field in case.fields.items():
240             if isinstance(field, BitSetDerivedField):
241                yield self.isa.expressions[field.expr]
242       if bitset.extends is not None:
243          yield from self.bitset_used_exprs(self.isa.bitsets[bitset.extends])
244
245    def extractor_impl(self, bitset, name):
246        if bitset.encode is not None:
247            if name in bitset.encode.maps:
248                return bitset.encode.maps[name]
249        if bitset.extends is not None:
250            return self.extractor_impl(self.isa.bitsets[bitset.extends], name)
251        return None
252
253    # Default fallback when no mapping is defined, simply to avoid
254    # having to deal with encoding at the same time as r/e new
255    # instruction decoding.. but we can at least print warnings:
256    def extractor_fallback(self, bitset, name):
257        extr_name = bitset.name + '.' + name
258        if extr_name not in self.warned_missing_extractors:
259            print('WARNING: no encode mapping for {}.{}'.format(bitset.name, name))
260            self.warned_missing_extractors.append(extr_name)
261        return '0 /* XXX */'
262
263    def extractor(self, bitset, name):
264        extr = self.extractor_impl(bitset, name)
265        if extr is not None:
266            return extr
267        return self.extractor_fallback(bitset, name)
268
269    # In the special case of needing to access a field with bitset type
270    # for an expr, we need to encode the field so we end up with an
271    # integer, and not some pointer to a thing that will be encoded to
272    # an integer
273    def expr_extractor(self, bitset, name, p):
274        extr = self.extractor_impl(bitset, name)
275        field = self.resolve_simple_field(bitset, name)
276        if isinstance(field, BitSetDerivedField):
277            expr = self.isa.expressions[field.expr]
278            return self.expr_name(bitset.get_root(), expr) + '(s, p, src)'
279        if extr is None:
280            if name in self.unique_param_names():
281                extr = 'p->' + name
282            else:
283                extr = self.extractor_fallback(bitset, name)
284        if field and field.get_c_typename() == 'TYPE_BITSET':
285            extr = 'encode' + isa.roots[field.type].get_c_name() + '(s, ' + p + ', ' + extr + ')'
286        return extr
287
288    # A limited resolver for field type which doesn't properly account for
289    # overrides.  In particular, if a field is defined differently in multiple
290    # different cases, this just blindly picks the last one.
291    #
292    # TODO to do this properly, I don't think there is an alternative than
293    # to emit code which evaluates the case.expr
294    def resolve_simple_field(self, bitset, name):
295        field = None
296        for case in bitset.cases:
297            if name in case.fields:
298                field = case.fields[name]
299        if field is not None:
300            return field
301        if bitset.extends is not None:
302            return self.resolve_simple_field(isa.bitsets[bitset.extends], name)
303        return None
304
305    def encode_type(self, bitset):
306        if bitset.encode is not None:
307            if bitset.encode.type is not None:
308                return bitset.encode.type
309        if bitset.extends is not None:
310            return self.encode_type(isa.bitsets[bitset.extends])
311        return None
312
313    def expr_name(self, root, expr):
314       return root.get_c_name() + '_' + expr.get_c_name()
315
316template = """\
317/* Copyright (C) 2020 Google, Inc.
318 *
319 * Permission is hereby granted, free of charge, to any person obtaining a
320 * copy of this software and associated documentation files (the "Software"),
321 * to deal in the Software without restriction, including without limitation
322 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
323 * and/or sell copies of the Software, and to permit persons to whom the
324 * Software is furnished to do so, subject to the following conditions:
325 *
326 * The above copyright notice and this permission notice (including the next
327 * paragraph) shall be included in all copies or substantial portions of the
328 * Software.
329 *
330 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
331 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
332 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
333 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
334 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
335 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
336 * IN THE SOFTWARE.
337 */
338
339#include <stdbool.h>
340#include <stdint.h>
341#include <util/bitset.h>
342
343<%
344isa = s.isa
345%>
346
347#define BITMASK_WORDS BITSET_WORDS(${isa.bitsize})
348
349typedef struct {
350    BITSET_WORD bitset[BITMASK_WORDS];
351} bitmask_t;
352
353static inline uint64_t
354bitmask_to_uint64_t(bitmask_t mask)
355{
356    return ((uint64_t)mask.bitset[1] << 32) | mask.bitset[0];
357}
358
359static inline bitmask_t
360uint64_t_to_bitmask(uint64_t val)
361{
362    bitmask_t mask = {
363        .bitset[0] = val & 0xffffffff,
364        .bitset[1] = (val >> 32) & 0xffffffff,
365    };
366
367    return mask;
368}
369
370static inline void
371store_instruction(BITSET_WORD *dst, bitmask_t instr)
372{
373%   for i in range(0, int(isa.bitsize / 32)):
374    *(dst + ${i}) = instr.bitset[${i}];
375%   endfor
376}
377
378/**
379 * Opaque type from the PoV of generated code, but allows state to be passed
380 * thru to the hand written helpers used by the generated code.
381 */
382struct encode_state;
383
384struct bitset_params;
385
386static bitmask_t
387pack_field(unsigned low, unsigned high, int64_t val, bool is_signed)
388{
389   bitmask_t field, mask;
390
391   if (is_signed) {
392      /* NOTE: Don't assume val is already sign-extended to 64b,
393       * just check that the bits above the valid range are either
394       * all zero or all one:
395       */
396      assert(!(( val & ~BITFIELD64_MASK(1 + high - low)) &&
397               (~val & ~BITFIELD64_MASK(1 + high - low))));
398   } else {
399      assert(!(val & ~BITFIELD64_MASK(1 + high - low)));
400   }
401
402   BITSET_ZERO(field.bitset);
403
404   if (!val)
405      return field;
406
407   BITSET_ZERO(mask.bitset);
408   BITSET_SET_RANGE(mask.bitset, 0, high - low);
409
410   field = uint64_t_to_bitmask(val);
411   BITSET_AND(field.bitset, field.bitset, mask.bitset);
412   BITSET_SHL(field.bitset, low);
413
414   return field;
415}
416
417/*
418 * Forward-declarations (so we don't have to figure out which order to
419 * emit various encoders when they have reference each other)
420 */
421
422%for root in s.encode_roots():
423static bitmask_t encode${root.get_c_name()}(struct encode_state *s, struct bitset_params *p, ${root.encode.type} src);
424%endfor
425
426## TODO before the expr evaluators, we should generate extract_FOO() for
427## derived fields.. which probably also need to be in the context of the
428## respective root so they take the correct src arg??
429
430/*
431 * Expression evaluators:
432 */
433
434struct bitset_params {
435%for name in s.unique_param_names():
436   int64_t ${name};
437%endfor
438};
439
440## TODO can we share this def between the two templates somehow?
441<%def name="encode_params(leaf, field)">
442 struct bitset_params bp = {
443%for param in field.params:
444    .${param[1]} = ${s.expr_extractor(leaf, param[0], 'p')},  /* ${param[0]} */
445%endfor
446 };
447</%def>
448
449<%def name="render_expr(leaf, expr)">
450static inline int64_t
451${s.expr_name(leaf.get_root(), expr)}(struct encode_state *s, struct bitset_params *p, ${leaf.get_root().encode.type} src)
452{
453%   for fieldname in expr.fieldnames:
454    int64_t ${fieldname};
455%   endfor
456%   for fieldname in expr.fieldnames:
457<% field = s.resolve_simple_field(leaf, fieldname) %>
458%      if field is not None and field.get_c_typename() == 'TYPE_BITSET':
459          { ${encode_params(leaf, field)}
460          const bitmask_t tmp = ${s.expr_extractor(leaf, fieldname, '&bp')};
461          ${fieldname} = bitmask_to_uint64_t(tmp);
462          }
463%      else:
464          ${fieldname} = ${s.expr_extractor(leaf, fieldname, 'p')};
465%      endif
466%   endfor
467    return ${expr.expr};
468}
469</%def>
470
471## note, we can't just iterate all the expressions, but we need to find
472## the context in which they are used to know the correct src type
473
474%for root in s.encode_roots():
475%   for leaf in s.encode_leafs(root):
476%      for expr in s.bitset_used_exprs(leaf):
477static inline int64_t ${s.expr_name(leaf.get_root(), expr)}(struct encode_state *s, struct bitset_params *p, ${leaf.get_root().encode.type} src);
478%      endfor
479%   endfor
480%endfor
481
482%for root in s.encode_roots():
483<%
484    rendered_exprs = []
485%>
486%   for leaf in s.encode_leafs(root):
487%      for expr in s.bitset_used_exprs(leaf):
488<%
489          if expr in rendered_exprs:
490             continue
491          rendered_exprs.append(expr)
492%>
493          ${render_expr(leaf, expr)}
494%      endfor
495%   endfor
496%endfor
497
498
499/*
500 * The actual encoder definitions
501 */
502
503%for root in s.encode_roots():
504%   for leaf in s.encode_leafs(root):
505<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %>
506%      if snippet not in root.snippets.keys():
507<% snippet_name = "snippet" + root.get_c_name() + "_" + str(len(root.snippets)) %>
508static bitmask_t
509${snippet_name}(struct encode_state *s, struct bitset_params *p, ${root.encode.type} src)
510{
511   bitmask_t val = uint64_t_to_bitmask(0);
512${snippet}
513   return val;
514}
515<% root.snippets[snippet] = snippet_name %>
516%      endif
517%   endfor
518
519static bitmask_t
520encode${root.get_c_name()}(struct encode_state *s, struct bitset_params *p, ${root.encode.type} src)
521{
522%   if root.encode.case_prefix is not None:
523   switch (${root.get_c_name()}_case(s, src)) {
524%      for leafs in s.encode_leaf_groups(root):
525   case ${s.case_name(root, leafs[0].name)}: {
526%         for leaf in leafs:
527%           if leaf.has_gen_restriction():
528      if (s->gen >= ${leaf.gen_min} && s->gen <= ${leaf.gen_max}) {
529%           endif
530<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %>
531<%    words = isa.split_bits((leaf.get_pattern().match), 64) %>
532      bitmask_t val = uint64_t_to_bitmask(${words[-1]});
533
534<%    words.pop() %>
535
536%     for x in reversed(range(len(words))):
537      {
538         bitmask_t word = uint64_t_to_bitmask(${words[x]});
539         BITSET_SHL(val.bitset, 64);
540         BITSET_OR(val.bitset, val.bitset, word.bitset);
541      }
542%     endfor
543
544      BITSET_OR(val.bitset, val.bitset, ${root.snippets[snippet]}(s, p, src).bitset);
545      return val;
546%           if leaf.has_gen_restriction():
547      }
548%           endif
549%         endfor
550%         if leaf.has_gen_restriction():
551      break;
552%         endif
553    }
554%      endfor
555   default:
556      /* Note that we need the default case, because there are
557       * instructions which we never expect to be encoded, (ie.
558       * meta/macro instructions) as they are removed/replace
559       * in earlier stages of the compiler.
560       */
561      break;
562   }
563   mesa_loge("Unhandled ${root.name} encode case: 0x%x\\n", ${root.get_c_name()}_case(s, src));
564   return uint64_t_to_bitmask(0);
565%   else: # single case bitset, no switch
566%      for leaf in s.encode_leafs(root):
567<% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %>
568      bitmask_t val = uint64_t_to_bitmask(${hex(leaf.get_pattern().match)});
569      BITSET_OR(val.bitset, val.bitset, ${root.snippets[snippet]}(s, p, src).bitset);
570      return val;
571%      endfor
572%   endif
573}
574%endfor
575"""
576
577encode_bitset_template = """
578<%
579isa = s.isa
580%>
581
582<%def name="case_pre(root, expr)">
583%if expr is not None:
584    if (${s.expr_name(root, expr)}(s, p, src)) {
585%else:
586    {
587%endif
588</%def>
589
590<%def name="case_post(root, expr)">
591%if expr is not None:
592    } else
593%else:
594    }
595%endif
596</%def>
597
598<%def name="encode_params(leaf, field)">
599 struct bitset_params bp = {
600%for param in field.params:
601    .${param[1]} = ${s.expr_extractor(leaf, param[0], 'p')},  /* ${param[0]} */
602%endfor
603 };
604</%def>
605
606      uint64_t fld;
607
608      (void)fld;
609<% visited_exprs = [] %>
610%for case in s.bitset_cases(leaf):
611<%
612    if case.expr is not None:
613        visited_exprs.append(case.expr)
614
615    # per-expression-case track display-field-names that we have
616    # already emitted encoding for.  It is possible that an
617    # <override> case overrides a given field (for ex. #cat5-src3)
618    # and we don't want to emit encoding for both the override and
619    # the fallback
620    seen_fields = {}
621%>
622    ${case_pre(root, case.expr)}
623%   for df in case.display_fields():
624%       for f in df.fields():
625<%
626          # simplify the control flow a bit to give the compiler a bit
627          # less to clean up
628          expr = f.expr
629          if expr == case.expr:
630              # Don't need to evaluate the same condition twice:
631              expr = None
632          elif expr in visited_exprs:
633              # We are in an 'else'/'else-if' leg that we wouldn't
634              # go down due to passing an earlier if()
635              continue
636
637          if not expr in seen_fields.keys():
638              seen_fields[expr] = []
639
640          if f.field.name in seen_fields[expr]:
641              continue
642          seen_fields[expr].append(f.field.name)
643%>
644           ${case_pre(root, expr)}
645%         if f.field.get_c_typename() == 'TYPE_BITSET':
646             { ${encode_params(leaf, f.field)}
647               bitmask_t tmp = encode${isa.roots[f.field.type].get_c_name()}(s, &bp, ${s.extractor(leaf, f.field.name)});
648               fld = bitmask_to_uint64_t(tmp);
649             }
650%         else:
651             fld = ${s.extractor(leaf, f.field.name)};
652%         endif
653             const bitmask_t packed = pack_field(${f.field.low}, ${f.field.high}, fld, ${f.signed()});  /* ${f.field.name} */
654             BITSET_OR(val.bitset, val.bitset, packed.bitset);
655             ${case_post(root, expr)}
656%       endfor
657%   endfor
658
659%   for f in case.assert_cases():
660<%
661      # simplify the control flow a bit to give the compiler a bit
662      # less to clean up
663      expr = f.expr
664      if expr == case.expr:
665          # Don't need to evaluate the same condition twice:
666          expr = None
667      elif expr in visited_exprs:
668          # We are in an 'else'/'else-if' leg that we wouldn't
669          # go down due to passing an earlier if()
670          continue
671%>
672       ${case_pre(root, expr)}
673       const bitmask_t packed = pack_field(${f.field.low}, ${f.field.high}, ${f.field.val}, ${f.signed()});
674       BITSET_OR(val.bitset, val.bitset, packed.bitset);
675       ${case_post(root, None)}
676%   endfor
677      {}  /* in case no unconditional field to close out last '} else' */
678    ${case_post(root, case.expr)}
679%endfor
680"""
681
682xml = sys.argv[1]
683dst = sys.argv[2]
684
685isa = ISA(xml)
686s = State(isa)
687
688with open(dst, 'w') as f:
689    f.write(Template(template).render(s=s, encode_bitset=Template(encode_bitset_template)))
690