示例#1
0
    def _make_emit_pattern_low(self,iform):
        emit_pattern = []
        for action in iform.rule.actions:
            if action.type == 'emit':
                # if no field_name, then we must differentiate the
                # emit patterns using the value to avoid collisions.
                if action.field_name == None:
                    emit_pattern.append("emit {} nbits={} intval={}".format(
                        action.field_name,
                        action.nbits,
                        action.int_value))
                else:
                    emit_pattern.append("emit {} nbits={}".format(
                        action.field_name,
                        action.nbits))

            elif action.type == 'nt':
                emit_pattern.append(str(action))
            elif action.type == 'FB':
                # FB are not used in emit phase so we do not factor them 
                # in to the string that represents the pattern
                pass
            else:
                genutil.die("unexpected action type: %s" % action.type)    
        emit_actions_str = ', '.join(emit_pattern)
        return emit_actions_str
示例#2
0
    def _verify_naked_bits_in_unique_pattern(
            self):  # FIXME 2019-10-04 unused, no longer relevant
        ''' calculate how many references we have per each full
            instruction emit pattern.
        
            naked bits are bits in the pattern without a field name
            like 0x0F or 0b110.  earlier functions decorated
            opcode/legacy map.  

            If the naked bits just show up once, then we can hardcode
            those bits in the emit function. This is a test for that.

            Current design relies on the naked bits being the same in
            similar instruction patterns. If two patterns differ in
            any naked bits, they cannot share emit functions and we die.
            The workaround would be to capture the bits in some field to
            allow the emit function to be shared & generic.

            The current inputs to XED have no such conflicts.
        '''
        refs_per_ptrn = collections.defaultdict(int)
        for iform in self.iform_list:
            refs_per_ptrn[iform.emit_actions] += 1
            if refs_per_ptrn[iform.emit_actions] >= 2:
                if iform.rule.has_naked_bit_action():
                    # this assumes that the naked bits are going to be different.
                    # if the naked bits were the same, we could share the emit action.
                    genutil.die(
                        'emit pattern has more than one reference use of naked bits is not allowed: {}\n{}'
                        .format(iform.emit_actions, iform))
示例#3
0
文件: ild_phash.py 项目: xelxebar/xed
    def gen_find_fos(self, fname):  # L2 phash
        obj_str = self.cdict.strings_dict['obj_str']
        obj_type = self.cdict.strings_dict['obj_type']
        const = self.cdict.strings_dict['obj_const']
        hx2fo = {}
        for hx, phash in list(self.hx2phash.items()):
            fid = '%s_%d_l1' % (fname, hx)
            (hx2fo_list, operand_lu_fo) = phash.gen_find_fos(fid)
            if not operand_lu_fo:
                genutil.die("L2 hash cannot have trivial operand lu fn")
            hx2fo[hx] = hx2fo_list[0]

        fname = '%s' % fname
        if genutil.field_check(self.cdict, 'ntluf') or \
            genutil.field_check(self.cdict, 'nt'):
            return_type = 'xed_uint32_t'
        else:
            return_type = self.cdict.action_codegen.get_return_type()

        static = self.cdict.strings_dict['static']
        fo = codegen.function_object_t(fname,
                                       return_type=return_type,
                                       static=static,
                                       inline=False)
        fo.add_arg('%s%s* %s' % (const, obj_type, obj_str))
        self.add_lu_table(fo, hx2fo)
        #we only need to override add_lookup_lines
        lu_fname = operand_lu_fo.function_name
        self.add_op_lu_function(fo, lu_fname)
        self.add_find_lines(fo)
        fos = list(hx2fo.values())
        fos.append(fo)
        #all the operand_lu_fo going to be the same so we just take the last one
        return fos, operand_lu_fo
示例#4
0
 def _gen_tuple2int(self):
     ''' generate the int value of each tuple. 
         we shift each element by the number of bits that the previous 
         element took '''
     
     for tuple in self.tuple2rule:
         res = 0
         bit_shift = 0
         for i,byte in enumerate(tuple):
             if self.cnames[i] == 'UIMM0':
                 pass
             opwidth = self.op_widths[self.cnames[i]]
             res += byte << bit_shift
             bit_shift += opwidth
          
         if res not in self.int2tuple:
             self.tuple2int[tuple] = res
             self.int2tuple[res] = tuple
         else:
             conflict_tuple = self.int2tuple[res]
             err = "conflict in nt: %s\n" % self.nt_name
             err += "tuple      %s = %s\n" 
             err =err % (str(tuple),self.tuple2conditions[tuple]) 
             err += "and tuple: %s = %s\n" 
             err =err % (str(conflict_tuple),
                         self.tuple2conditions[conflict_tuple])
             err += "generate the same int value: %d" % res
             genutil.die(err)
示例#5
0
    def _unite_rules(self, nonterminal):
        ''' removing rules with identical constraints.
        if more than one rule has that same constraint then one of them must 
        be marked as encoder preferred.
        
        bucketing the rules, each bin represents unique constraint. 
        we go over each bin, if it has more than one rule, 
        we look for the attribute enc_preferred   '''

        rules_bin = []
        for rule in nonterminal.rules:
            found = False
            for bin in rules_bin:
                if bin[0].cdict == rule.cdict:
                    bin.append(rule)
                    found = True
                    break
            if not found:
                rules_bin.append([rule])

        rules = []
        for bin in rules_bin:
            if len(bin) > 1:
                preferred_rule = self._encoder_preferred(bin)
                if preferred_rule:
                    rules.append(preferred_rule)
                else:
                    err = "in nt %s several rules has the constraint: %s\n"
                    err += "one of them must be marked as encoder preferred\n"
                    genutil.die(err % (nonterminal.name, bin[0].conditions))
            else:
                rules.extend(bin)
        return rules
示例#6
0
文件: ins_emit.py 项目: zachlungu/xed
    def _verify_naked_bits_in_unique_pattern(self):
        ''' calculate how many references we have per each full
            instruction emit pattern.
        
            naked bits are bits in the pattern without a field name
            like 0x0F or 0b110.  earlier functions decorated
            opcode/legacy map.  

            If the naked bits just show up once, then we can hardcode
            those bits in the emit function. This is a test for that.

            Current design relies on the naked bits being the same in
            similar instruction patterns. If two patterns differ in
            any naked bits, they cannot share emit functions and we die.
            The workaround would be to capture the bits in some field to
            allow the emit function to be shared & generic.

            The current inputs to XED have no such conflicts.
        '''
        refs_per_ptrn = {}
        for iform in self.iform_list:
            if iform.emit_actions not in refs_per_ptrn:
                refs_per_ptrn[iform.emit_actions] = 1
            else:
                refs_per_ptrn[iform.emit_actions] += 1
                if iform.rule.has_naked_bit_action():
                    err = 'emit pattern: %s has more than one reference ' +\
                          'use of naked bits is not allowed'%iform.emit_actions
                    genutil.die(err)
示例#7
0
 def _generate_code_for_emit_action(self,bind_or_emit):
     """Emit code for emit action """
     if bind_or_emit == 'BIND':
         if self.emit_type == 'letters' or self.field_name == None:
             return ''
         elif self.emit_type == 'numeric':
             op_accessor = encutil.enc_strings['op_accessor']
             operand_setter = "%s_set_%s" % (op_accessor,
                                             self.field_name.lower())
             obj_name = encutil.enc_strings['obj_str']
             hex_val = hex(self.int_value)
             code = "%s(%s, %s);" % (operand_setter, obj_name, hex_val)
             return ['    ' + code]
         else:
             genutil.die("Unknown emit_type %s" % self.emit_type)
     else:  # EMIT
         emit_util_function = encutil.enc_strings['emit_util_function']
         obj_name = encutil.enc_strings['obj_str']
         nbits = self.nbits
         code = ''
         if self.field_name == None:
             if  self.emit_type == 'numeric':
                 hex_val = hex(self.int_value)
                 code = "%s(%s, %d, %s);" % (emit_util_function,obj_name,
                                             nbits,hex_val)
             else:
                 genutil.die("must have field name for letter action")
         else:
             op_accessor = encutil.enc_strings['op_accessor']
             operand_getter = "%s_get_%s(%s)" % (op_accessor, 
                                                 self.field_name.lower(),
                                                 obj_name)
             code = "%s(%s, %d, %s);" % (emit_util_function,
                                         obj_name,nbits,operand_getter)
         return ['    ' + code]
示例#8
0
    def work(self):  # main entry point
        ''' 
            Each instruction has 
                1) conditions (iclass, user registers, user inputs) and 

                2) actions. 3 types:
                   2a) field bindings, 
                   2b) nonterminals, 
                   2c) bit-emit of operand fields 
                          (hard-coded or from NT output)).

              fos = function output object (plural)

            generate the following:
            1) list of emit patterns fos  (2c)
            2) list of field bindings patterns fos (2a)
            3) list of all field bindings values  (values from prev step)
            4) max number of emit patterns  
            5) max number of field binding patterns
            6) max number of field bindings values
            7) list of groups fos (see explanation in instructions_group_t)
            
        '''

        for iform in self.iform_list:
            self._identify_map_and_nominal_opcode(iform)
            self._make_field_bindings_pattern(iform)
            self._make_emit_pattern(iform)
            #see explanation about bind patterns in instructions_group_t
            self._make_bind_pattern(iform)

        #self._study_emit_patterns()
        #self._verify_naked_bits_in_unique_pattern()

        self.fb_values_list = self._make_fb_values_list()  # step 3
        self.fb_values_table_size = len(self.fb_values_list)

        self.emit_ptrs_fo_list = self._make_emit_pattern_fos()
        self.max_emit_ptrns = len(self.emit_ptrs_fo_list)
        if self.max_emit_ptrns > max_in_byte:
            # we are using uint8 to hold the number of patterns,
            # we need to make sure we don't exceeds
            error = "total number of emit patterns(%d) exceeds 8 bits"
            genutil.die(error % self.max_emit_ptrns)

        self.instruction_groups = instructions_group_t(self.iarray,
                                                       self.logs_dir)

        self.fb_ptrs_fo_list = self._make_fb_pattern_fos()
        self.max_fb_ptrns = len(self.fb_ptrs_fo_list)
        if self.max_fb_ptrns > max_in_byte:
            # we are using uint8to hold the number of patterns,
            # we need to make sure we don't exceeds
            error = "total number of field binding patterns(%d) exceeds 8 bits"
            genutil.die(error % self.max_fb_ptrns)

        if verbosity.vencode():
            self._print_log()
示例#9
0
    def classify(self):
        if patterns.decimal_pattern.match(self.value):
            self.emit_type = 'numeric'
            self.int_value = int(self.value)
            t = hex(self.int_value)
            self.nbits = 4 * len(t[2:])
            if vclassify():
                msgb("CLASSIFY", "%s as decimal values" % (self.value))
            return

        if patterns.hex_pattern.match(self.value):
            self.emit_type = 'numeric'
            self.int_value = int(self.value, 16)
            self.nbits = 4 * (len(self.value) - 2
                              )  # drop the 0x, convert nibbles to bits
            if vclassify():
                msgb("CLASSIFY", "%s as hex" % (self.value))
            return
        if patterns.letter_and_underscore_pattern.match(self.value):
            self.emit_type = 'letters'
            t = self.value
            t = genutil.no_underscores(t)
            self.nbits = len(t)
            if vclassify():
                msgb("CLASSIFY", "%s as letters" % (self.value))
            return
        b = patterns.binary_pattern.match(self.value)  # leading "0b"
        if b:
            self.emit_type = 'numeric'
            t = '0b' + b.group('bits')  # pattern match strips out 0b
            self.int_value = genutil.make_numeric(t)
            bits_str = genutil.make_binary(t)
            self.nbits = len(bits_str)
            if vclassify():
                msgb(
                    "CLASSIFY",
                    "%s as explicit-binary -> int = %d nbits=%d [%s,%s]" %
                    (self.value, self.int_value, self.nbits, t, bits_str))
            return
        if patterns.bits_and_letters_underscore_pattern.match(self.value):
            self.emit_type = 'letters'
            v = genutil.no_underscores(self.value)
            self.nbits = len(v)
            if vclassify():
                msgb("CLASSIFY", "%s as mixed-letters" % (self.value))
            return

        if patterns.simple_number_pattern.match(self.value):
            self.emit_type = 'numeric'
            self.int_value = genutil.make_numeric(self.value)
            t = hex(self.int_value)
            self.nbits = 4 * len(t[2:])
            if vclassify():
                msgb("CLASSIFY", "%s as simple-number" % (self.value))
            return

        genutil.die("unknown pattern")
示例#10
0
def get_getter_fn(ptrn_list):
    if len(ptrn_list) == 0:
        genutil.die("P2341: SHOULD NOT REACH HERE")
    first = ptrn_list[0]
    for cur in ptrn_list[1:]:
        if first.easz_nt_seq != cur.easz_nt_seq:
            #conflict in easz resolution functions.. should not happen
            return None 
    return ild_codegen.get_derived_op_getter_fn(first.easz_nt_seq, _easz_token)
示例#11
0
    def _check_duplications(self, regs):
        ''' n^2 loop which verifies that each reg exists only once.  '''

        for reg in regs:
            count = 0
            for r in regs:
                if reg == r:
                    count += 1
            if count > 1:
                genutil.die("reg %s defined more than once" % reg)
示例#12
0
 def get_str_value(self):
     if self.is_field_binding() or self.is_return():
         return self.value
     if self.is_nonterminal():
         return self.nt
     if self.is_ntluf():
         return self.ntluf
     
     err = "unsupported type: %s for function get_str_value" % self.type
     genutil.die(err)
示例#13
0
 def _make_tuple2rule(self):
     ''' generate the tuple that represents the constraint
         e.g.: for the constraint: MODE=0 EASZ=1
         the tuple is (0,1) 
         if a rule does not have constraint over certain operand then 
         we splatter all the possible values '''
     verbose=False
     if verbose:
         print("_make_tuple2rule")
     for rule in self.rules:
         #print "\t RULE", str(rule)
         # ctup is a list of tuples of all possible value
         # combinations for the constraints.
         ctup = [] 
         first = True
         for cname in self.cnames:
             if verbose:
                 print("CNAME: {}".format(cname))
             new_ctup = []
             if cname in rule.cdict:
                 vals = rule.cdict[cname]
                 if verbose:
                     print("\tTHIS RULE VALS: {}".format(vals))
             else:
                 vals = self.state_space[cname]
                 if verbose:
                     print("\tSTATE SPACE VALS: {}".format(vals))
             if first:
                 first = False    
                 for val in vals:
                     ctup.append((val,))
                 if verbose:
                     print("\tFIRST CTUP: {}".format(ctup))
                 continue    
             else:  
                 # cross product of constraints
                 for val in vals:
                     for c in ctup:
                         new_ctup.append(c+(val,))
             if verbose:
                 print("\tNEW_CTUP: {}".format(new_ctup))
             ctup = new_ctup
         for tupl in ctup:
             if tupl not in self.tuple2rule:
                 if verbose:
                     print("TUPLE: {} RULE: {}".format(tupl, rule))
                 self.tuple2rule[tupl] = rule
                 self.tuple2conditions[tupl] = rule.conditions
             else:
                 err = "in nt {}\n".format(self.nt_name)
                 err += "generated tuple for constraint {} already exists\n"
                 err =  err.format(str(rule.cdict))
                 if verbose:
                     print(err)
                 genutil.die(err)
示例#14
0
    def __init__(
        self,
        name,
        aggtype,
        ctype,
        bitwidth,
        default_visibility=None,
        default_initializer=None,
        xprint='NOPRINT',
        internal_or_public="INTERNAL",
        dio="DO",
        eio="EO",
    ):

        self.name = name
        self.aggtype = aggtype
        self.ctype = ctype
        self.bitwidth = int(bitwidth)
        self.default_visibility = default_visibility
        self.xprint = xprint
        self.internal_or_public = internal_or_public
        self.dio = dio
        self.eio = eio

        if self.eio in ['EI', 'EO']:
            pass
        else:
            err = "Bad Encoder IO value: %s -- need one of {EI,EO}"
            genutil.die(err % self.eio)

        if self.dio in ['DI', 'DO', 'DS']:
            pass
        else:
            err = "Bad decoder IO value: %s -- need one of {DI,DO,DS}"
            genutil.die(err % self.eio)

        if self.eio == 'EI':
            self.encoder_input = True
        else:
            self.encoder_input = False

        if self.dio == 'DS':
            self.decoder_skip = True
        else:
            self.decoder_skip = False

        #NOTE: this next field is only used if initialize_each_field is True.
        self.default_initializer = default_initializer
        self.is_enum = 'enum' in self.ctype

        # this is the C type that will be used in the operand storage struct.
        self.storage_type = None

        #if True using bit fields
        self.compressed = False
示例#15
0
 def _cond_is_UIMM0_1(self, cond):
     ''' check whether the condition is UIMM0=1.
         die if the operand is UIMM0 but the value is different than 1'''
     if cond.field_name == 'UIMM0':
         if cond.rvalue.value == '1':
             return True
         else:
             #the operand is UIMM0 but the value is not 1
             err = ('not expecting UIMM0 will have any other constraint ' +
                    'other than UIMM0=1')
             genutil.die(err)
     return False
示例#16
0
    def _make_emit_fo(self, iform, i):
        ''' create the function object for this emit pattern
             
            @param iform: iform_t object
            @param i: index of the pattern function
            @return: function_object_t 
        '''

        fname = "%s_%d" % (emit_function_prefix, i)
        fo = codegen.function_object_t(fname, return_type='void')

        # obj_str is the function parameters for the emit function
        obj_str = encutil.enc_strings['obj_str']
        enc_arg = "%s* %s" % (encutil.enc_strings['obj_type'], obj_str)
        fo.add_arg(enc_arg)

        for action in iform.rule.actions:
            # MASSIVE HACK: we store the legacy_map as MAP0 in
            # xed_encode_iform_db[] (obj/xed-encoder-iforms-init.c)
            # for VEX/EVEX/XOP instr (see
            # _identify_map_and_nominal_opcode() ) to avoid emitting
            # any escape/map bytes at runtime.
            if action.field_name == 'MAP':
                if iform.encspace == 0:  # legacy
                    genutil.die("Should not see MAP here: {}".format(
                        iform.iclass))
                pass
            elif action.field_name and action.field_name in [
                    'LEGACY_MAP1', 'LEGACY_MAP2', 'LEGACY_MAP3',
                    'LEGACY_MAP3DNOW'
            ]:
                if iform.encspace != 0:  # legacy
                    genutil.die("This should only occur for legacy instr")
                self._emit_legacy_map(fo, iform)

            elif action.field_name and action.field_name == 'NOM_OPCODE':
                code = ''
                get_opcode = 'xed_encoder_get_nominal_opcode(%s)' % obj_str
                if action.nbits == 8:
                    emit_func = 'xed_encoder_request_emit_bytes'
                else:
                    emit_func = 'xed_encoder_request_encode_emit'
                code = ' ' * 4
                code += '%s(%s,%d,%s)' % (emit_func, obj_str, action.nbits,
                                          get_opcode)
                fo.add_code_eol(code)
            else:
                code = action.emit_code('EMIT')
                for c in code:
                    fo.add_code(c)

        return fo
示例#17
0
def read_file(fn):
    lines = open(fn, 'r').readlines()
    lines = map(genutil.no_comments, lines)
    lines = list(filter(genutil.blank_line, lines))
    d = {}  # isa-set to list of cpuid records
    for line in lines:
        wrds = line.split(':')
        isa_set = wrds[0].strip()
        cpuid_bits = wrds[1].upper().split()
        if isa_set in d:
            msg = "Duplicate cpuid definition for isa set. isa-set={} old={} new={}"
            genutil.die(msg.format(isa_set, d[isa_set], cpuid_bits))
        d[isa_set] = cpuid_bits
    return d
示例#18
0
def build_init(operand_names, dct, nelem):
    """Given a list of operand names and a dictory build by
    build_operand_bitvector, return an data initialization string"""
    values = [0] * nelem
    for o in operand_names:
        try:
            (xed_operand, biti, chunki, pos_in_chunk, mask) = dct[o]
        except:
            genutil.die("Could not find %s in operand names" % (o))
        values[chunki] |= mask
    t = []
    for v in values:
        t.append("%s" % (hex(v)))
    s = "XED_BIT_PAIR( %s )" % ",".join(t)
    return s
示例#19
0
 def _capture_cnames(self):
     ''' capture the superset of all constraint names '''  
     
     if not self.rules:
         return []
     
     cnames = set()
     for rule in self.rules:
         cnames.update(set(rule.cdict.keys()))
     cnames = list(cnames)
     cnames.sort()
     if not cnames:
         msg = "XED found rules without any constraints in nt %s"
         genutil.die(msg  % self.nt_name)
     return cnames
示例#20
0
def expand_all_slashes(s):
    global slash2_macro_pattern
    a = s
    m = slash2_macro_pattern.search(a)
    while m:
        n = int(m.group('number'))
        if n > 99:
            genutil.die(
                "Hit a very large number %d when explanding slash patterns in [%s]"
                % (n, s))
        new = n * m.group('letter')
        old = '%s/%s' % (m.group('letter'), m.group('number'))
        #print "old %s -> new %s" % (old,new)
        a = a.replace(old, new, 1)
        m = slash2_macro_pattern.search(a)
    return a
示例#21
0
 def prepare_lines(self):
     """Convert the lines to the appropriate type for emitting the
     enumeration"""
     self.tuples = []
     for line in self.lines:
         if isinstance(line, enumer.enumer_value_t):
             self.tuples.append(line)
         elif type(line) == tuple:
             if len(line) == 3:
                 (token, value, comment) = line
             else:
                 genutil.die("Cannot handle line: %s" % (str(line)))
             token = self.prep_name(token)
             self.tuples.append(enumer.enumer_value_t(token, value, comment))
         else:
             token = self.prep_name(line)
             self.tuples.append(enumer.enumer_value_t(token))
示例#22
0
    def _compute_type_in_storage(self):
        ''' detect the minimal C type data type can be used to represent 
           the operand. 
           the accessors will cast the operand to its C type according to the 
           data files'''

        for op in list(self.operand_fields.values()):
            width = op.bitwidth
            if width <= 8:
                op.storage_type = 'xed_uint8_t'
            elif width <= 16:
                op.storage_type = 'xed_uint16_t'
            elif width <= 32:
                op.storage_type = 'xed_uint32_t'
            elif width <= 64:
                op.storage_type = 'xed_uint64_t'
            else:
                genutil.die("unhandled width")
示例#23
0
    def read(self, lines):
        """Read lines from lines until a new header or a blank line is reached"""
        started = False
        while 1:
            if not lines:
                break
            self.nlines += 1            
            line = lines[0]
            line = line.strip()
            line = re.sub(r'#.*','',line)
            m= constant_table_t.match_blank.match(line)
            if m:
                del lines[0]
                continue

            m= constant_table_t.match_header.match(line)
            if m:
                if started:
                    return
                else:
                    started = True
                    del lines[0]
                    self.name = m.group('name')
                    self.operand = m.group('operand')
                    continue
            m = constant_table_t.match_pair.match(line)
            if m:
                value = m.group('value')
                symbol = m.group('symbol')
                numeric_value = genutil.make_numeric(value)
                #print "INPUT: [%s] [%s]" % (value,symbol)
                self.value_string_pairs.append((numeric_value,symbol))
                del lines[0]
                continue
            m = constant_table_t.match_pair_error.match(line)
            if m:
                value = m.group('value')
                numeric_value = genutil.make_numeric(value)
                self.value_string_pairs.append((numeric_value,None))
                del lines[0]
                continue
            else:
                genutil.die("Could not parse line %d: [%s]\n\n" % (self.nlines,line))
示例#24
0
def _has_VEXDEST210_equals_7_restriction(cnames, ptrn_list):
    """Return true if some pattern in the list of input pattern_t's has a
       VVVV=1111 restriction. If that occurs, we can replace all
       VEXDEST210 restricions since there are no other kinds of VVVV
       restrictions.    """
    if _vd_token not in cnames:
        return False
    
    for ptrn in ptrn_list:
        if _vd_token_7 in ptrn.constraints:
            genutil.die("XXX VEXDEST210_7 already exists in the patterns.")
            
    for ptrn in ptrn_list:
        if _vd_token in ptrn.constraints:
            cvals = ptrn.constraints[_vd_token]
            if len(cvals) == 1 and 7 in cvals:
                return True

    return False
示例#25
0
 def create_tuple2int(self, all_ops_widths):
     '''create the mapping of tuple to its int value by CONCATENTATING all
     the input constraint values to make an integer that is
     ultimately the input to the hash function. '''
     tuple2int = {}
     int2tuple = {}
     for t in self.tuple2rule.keys():
         res = tup2int.tuple2int(t, self.cnames, all_ops_widths)
         if res in int2tuple:
             err = "the tuple % and the tuple %s generate the same value:%d"
             genutil.die(err % (t,str(int2tuple[res]),res))    
         else:
             tuple2int[t] = res
             int2tuple[res] = t
     
     #later using the op_widths for the code generation             
     self.op_widths = all_ops_widths
     self.tuple2int = tuple2int
     self.int2tuple = int2tuple    
示例#26
0
    def _fix_bit_width_for_enums(self, agi):
        ''' the default width of the nums is to big and wasteful.
            we get the list of all values for each enum in agi 
            and set the bitwidth to the minimal width needed.
         '''

        # mx_bits is a mapping from enum name to the minimal number
        # of bits required to represent it
        max_bits_for_enum = self._gen_max_bits_per_enum(agi.all_enums)
        for op in list(self.operand_fields.values()):
            if op.ctype in max_bits_for_enum:
                needed_bits = max_bits_for_enum[op.ctype]
                if op.bitwidth < needed_bits:
                    # verify that the specified bitwidth form the data files
                    # is not smaller than the calculated
                    vals = agi.all_enums[op.ctype]
                    err = 'bit width for % is to small, has %d values'
                    genutil.die(err % (op.name, vals))
                else:
                    op.bitwidth = max_bits_for_enum[op.ctype]
示例#27
0
文件: ins_emit.py 项目: zachlungu/xed
    def _make_field_bindings_pattern(self, iform):
        ''' create the string that represents the field bindings pattern. '''

        bind_actions = []
        for action in iform.rule.actions:
            if action.type == 'nt':
                pass
            elif action.type == 'FB':
                bind_actions.append(action.field_name)
            elif action.type == 'emit':
                if action.emit_type == 'numeric' and action.field_name:
                    bind_actions.append(action.field_name)
                else:
                    pass
            else:
                genutil.die("unexpected action type: %s" % action.type)

        fb_ptrn = ''
        if bind_actions:
            fb_ptrn = ', '.join(sorted(bind_actions))
        iform.fb_ptrn = fb_ptrn
示例#28
0
文件: ins_emit.py 项目: zachlungu/xed
    def _make_emit_pattern(self, iform):
        ''' create the string that represents the action for the emit phase.
            using this string we will classify all 
            the emit actions into patterns 
            '''

        emit_pattern = []

        for action in iform.rule.actions:
            if action.type == 'emit':
                emit_pattern.append("emit %s nbits=%d" %
                                    (action.field_name, action.nbits))
            elif action.type == 'nt':
                emit_pattern.append(str(action))
            elif action.type == 'FB':
                # FB are not used in emit phase so we do not factor them
                # in to the string that represents the pattern
                pass
            else:
                genutil.die("unexpected action type: %s" % action.type)

        iform.emit_actions = ', '.join(emit_pattern)
示例#29
0
    def gen_function(self):
        ''' returns tuple of:
        1) list functions (we can have several functions in case we 
            need to levels of hashing)
        2) the operands lookup function (generates the key)        
        '''
        action_codegen = actions_codegen.actions_codegen_t(self.cvg.tuple2rule,
                                                       self.cvg.default_action,
                                                       self.cvg.strings_dict)
        self.cvg.action_codegen = action_codegen

        if self.cvg.no_constraints():
            fo = self._gen_empty_function(self.fname)
            return [fo], None
        
        phash = ild_phash.gen_hash(self.cvg)
        if phash == None:
            genutil.die("Failed to find perfect hash for %s" % self.fname)
        if verbosity.vfuncgen():
            self.cvg.log.write("%s" % phash)

        fos, operand_lu_fo = phash.gen_find_fos(self.fname)
        return fos, operand_lu_fo
示例#30
0
def _read_constant_tables(lines, tables):
    """Read lines from lines until a new header or a blank line is reached"""
    nlines = 0
    y = None
    for line in lines:
        nlines += 1
        line = line.strip()
        line = re.sub(r'#.*', '', line)
        m = constant_table_t.match_blank.match(line)
        if m:
            continue
        m = constant_table_t.match_header.match(line)
        if m:  # found next header
            name = m.group('name')
            y = None
            for t in tables:
                if t.name == name:
                    y = t
            if not y:
                y = constant_table_t()
                tables.append(y)
                y.name = name
                y.operand = m.group('operand')
            continue
        m = constant_table_t.match_pair.match(line)
        if m:
            value = m.group('value')
            symbol = m.group('symbol')
            numeric_value = genutil.make_numeric(value)
            #print "INPUT: [%s] [%s]" % (value,symbol)
            if not y:
                genutil.die(
                    "Malformed constant table line {}: [{}]\n\n".format(
                        nlines, line))
            y.value_string_pairs.append((numeric_value, symbol))
            continue
        m = constant_table_t.match_pair_error.match(line)
        if m:
            value = m.group('value')
            numeric_value = genutil.make_numeric(value)
            if not y:
                genutil.die(
                    "Malformed constant table line {}: [{}]\n\n".format(
                        nlines, line))
            y.value_string_pairs.append((numeric_value, None))
            continue
        else:
            genutil.die("Could not parse line {}: [{}]\n\n".format(
                nlines, line))