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