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