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