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