mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 03:08:05 +02:00
pco, pygen: define and emit isa instruction group header variant fields
Signed-off-by: Simon Perretta <simon.perretta@imgtec.com> Acked-by: Frank Binns <frank.binns@imgtec.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32258>
This commit is contained in:
parent
ee312ebd6f
commit
4ca21e7038
4 changed files with 353 additions and 19 deletions
|
|
@ -35,15 +35,17 @@ enum ${enum.name} {
|
|||
};
|
||||
|
||||
% endfor
|
||||
/** Sub-enums. */
|
||||
% for enum in [enum for enum in enums.values() if enum.parent is not None]:
|
||||
#define ${enum.name} ${enum.parent.name}
|
||||
% for bit_set in bit_sets.values():
|
||||
enum ${bit_set.name}_variant {
|
||||
% for variant in bit_set.variants:
|
||||
${variant},
|
||||
% endfor
|
||||
};
|
||||
% endfor
|
||||
|
||||
#endif /* PCO_COMMON_H */"""
|
||||
|
||||
def main():
|
||||
print(Template(template).render(enums=enums))
|
||||
print(Template(template).render(enums=enums, bit_sets=bit_sets))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -19,14 +19,26 @@ template = """/*
|
|||
* \\brief PCO ISA definitions.
|
||||
*/
|
||||
|
||||
#include "pco_common.h"
|
||||
#include "util/macros.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
% for _bit_set_name, bit_set in bit_sets.items():
|
||||
/** ${_bit_set_name} */
|
||||
% for bit_struct in bit_set.bit_structs.values():
|
||||
struct ${bit_struct.name} {
|
||||
% for type, field, bits in bit_struct.struct_fields.values():
|
||||
${type} ${field} : ${bits};
|
||||
% endfor
|
||||
};
|
||||
|
||||
% endfor
|
||||
% endfor
|
||||
#endif /* PCO_ISA_H */"""
|
||||
|
||||
def main():
|
||||
print(Template(template).render())
|
||||
print(Template(template).render(bit_sets=bit_sets))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -38,3 +38,173 @@ F_UINT4_POS_WRAP = field_type('uint4_pos_wrap', BaseType.uint, 4, dec_bits=5, ch
|
|||
F_OFFSET31 = field_type('offset31', BaseType.uint, 31, dec_bits=32, check='!(val & 0b1)', encode='val >> 1')
|
||||
## 8-bit value; lowest 2 bits == 0b00.
|
||||
F_UINT6MUL4 = field_type('uint6mul4', BaseType.uint, 6, dec_bits=8, check='!(val & 0b11)', encode='val >> 2')
|
||||
|
||||
# Instruction group header definitions.
|
||||
F_OPORG = field_enum_type(
|
||||
name='oporg', num_bits=3,
|
||||
elems=[
|
||||
('p0', 0b000),
|
||||
('p2', 0b001),
|
||||
('be', 0b010),
|
||||
('p0_p1', 0b011),
|
||||
('p0_p2', 0b100),
|
||||
('p0_p1_p2', 0b101),
|
||||
('p0_p2_be', 0b110),
|
||||
('p0_p1_p2_be', 0b111),
|
||||
])
|
||||
|
||||
F_OPCNT = field_enum_type(
|
||||
name='opcnt', num_bits=3,
|
||||
elems=[
|
||||
('p0', 0b001),
|
||||
('p1', 0b010),
|
||||
('p2', 0b100),
|
||||
], is_bitset=True)
|
||||
|
||||
F_CC = field_enum_type(
|
||||
name='cc', num_bits=2,
|
||||
elems=[
|
||||
('e1_zx', 0b00),
|
||||
('e1_z1', 0b01),
|
||||
('ex_zx', 0b10),
|
||||
('e1_z0', 0b11),
|
||||
])
|
||||
|
||||
F_CC1 = field_enum_subtype(name='cc1', parent=F_CC, num_bits=1)
|
||||
|
||||
F_ALUTYPE = field_enum_type(
|
||||
name='alutype', num_bits=2,
|
||||
elems=[
|
||||
('main', 0b00),
|
||||
('bitwise', 0b10),
|
||||
('control', 0b11),
|
||||
])
|
||||
|
||||
F_CTRLOP = field_enum_type(
|
||||
name='ctrlop', num_bits=4,
|
||||
elems=[
|
||||
('b', 0b0000),
|
||||
('lapc', 0b0001),
|
||||
('savl', 0b0010),
|
||||
('cnd', 0b0011),
|
||||
('wop', 0b0100),
|
||||
('wdf', 0b0101),
|
||||
('mutex', 0b0110),
|
||||
('nop', 0b0111),
|
||||
('itrsmp', 0b1000),
|
||||
('sbo', 0b1011),
|
||||
])
|
||||
|
||||
I_IGRP_HDR = bit_set(
|
||||
name='igrp_hdr',
|
||||
pieces=[
|
||||
('da', (0, '7:4')),
|
||||
('length', (0, '3:0')),
|
||||
('ext', (1, '7')),
|
||||
('oporg', (1, '6:4')),
|
||||
('opcnt', (1, '6:4')),
|
||||
('olchk', (1, '3')),
|
||||
('w1p', (1, '2')),
|
||||
('w0p', (1, '1')),
|
||||
('cc', (1, '0')),
|
||||
|
||||
('end', (2, '7')),
|
||||
('alutype', (2, '6:5')),
|
||||
('rsvd', (2, '4')),
|
||||
('atom', (2, '3')),
|
||||
('rpt', (2, '2:1')),
|
||||
('ccext', (2, '0')),
|
||||
|
||||
('miscctl', (2, '7')),
|
||||
('ctrlop', (2, '4:1')),
|
||||
],
|
||||
fields=[
|
||||
('da', (F_UINT4, ['da'])),
|
||||
('length', (F_UINT4_POS_WRAP, ['length'])),
|
||||
('ext', (F_BOOL, ['ext'])),
|
||||
('oporg', (F_OPORG, ['oporg'])),
|
||||
('opcnt', (F_OPCNT, ['opcnt'])),
|
||||
('olchk', (F_BOOL, ['olchk'])),
|
||||
('w1p', (F_BOOL, ['w1p'])),
|
||||
('w0p', (F_BOOL, ['w0p'])),
|
||||
('cc1', (F_CC1, ['cc'])),
|
||||
|
||||
('end', (F_BOOL, ['end'])),
|
||||
('alutype', (F_ALUTYPE, ['alutype'])),
|
||||
('rsvd', (F_UINT1, ['rsvd'], 0)),
|
||||
('atom', (F_BOOL, ['atom'])),
|
||||
('rpt', (F_UINT2_POS_INC, ['rpt'])),
|
||||
('cc', (F_CC, ['ccext', 'cc'])),
|
||||
|
||||
('miscctl', (F_UINT1, ['miscctl'])),
|
||||
('ctrlop', (F_CTRLOP, ['ctrlop'])),
|
||||
])
|
||||
|
||||
I_IGRP_HDR_MAIN_BRIEF = bit_struct(
|
||||
name='main_brief',
|
||||
bit_set=I_IGRP_HDR,
|
||||
field_mappings=[
|
||||
'da',
|
||||
'length',
|
||||
('ext', 'ext', False),
|
||||
'oporg',
|
||||
'olchk',
|
||||
'w1p',
|
||||
'w0p',
|
||||
('cc', 'cc1'),
|
||||
])
|
||||
|
||||
I_IGRP_HDR_MAIN = bit_struct(
|
||||
name='main',
|
||||
bit_set=I_IGRP_HDR,
|
||||
field_mappings=[
|
||||
'da',
|
||||
'length',
|
||||
('ext', 'ext', True),
|
||||
'oporg',
|
||||
'olchk',
|
||||
'w1p',
|
||||
'w0p',
|
||||
'cc',
|
||||
'end',
|
||||
('alutype', 'alutype', 'main'),
|
||||
'rsvd',
|
||||
'atom',
|
||||
'rpt',
|
||||
])
|
||||
|
||||
I_IGRP_HDR_BITWISE = bit_struct(
|
||||
name='bitwise',
|
||||
bit_set=I_IGRP_HDR,
|
||||
field_mappings=[
|
||||
'da',
|
||||
'length',
|
||||
('ext', 'ext', True),
|
||||
'opcnt',
|
||||
'olchk',
|
||||
'w1p',
|
||||
'w0p',
|
||||
'cc',
|
||||
'end',
|
||||
('alutype', 'alutype', 'bitwise'),
|
||||
'rsvd',
|
||||
'atom',
|
||||
'rpt',
|
||||
])
|
||||
|
||||
I_IGRP_HDR_CONTROL = bit_struct(
|
||||
name='control',
|
||||
bit_set=I_IGRP_HDR,
|
||||
field_mappings=[
|
||||
'da',
|
||||
'length',
|
||||
('ext', 'ext', True),
|
||||
('opcnt', 'opcnt', 0),
|
||||
'olchk',
|
||||
'w1p',
|
||||
'w0p',
|
||||
'cc',
|
||||
'miscctl',
|
||||
('alutype', 'alutype', 'control'),
|
||||
'ctrlop',
|
||||
])
|
||||
|
|
|
|||
|
|
@ -7,13 +7,16 @@ _ = None
|
|||
|
||||
prefix = 'pco'
|
||||
|
||||
def val_fits_in_bits(val, num_bits):
|
||||
return val < pow(2, num_bits)
|
||||
|
||||
class BaseType(Enum):
|
||||
bool = auto()
|
||||
uint = auto()
|
||||
enum = auto()
|
||||
|
||||
class Type(object):
|
||||
def __init__(self, name, base_type, num_bits, dec_bits, check, encode, nzdefault, print_early):
|
||||
def __init__(self, name, base_type, num_bits, dec_bits, check, encode, nzdefault, print_early, enum):
|
||||
self.name = name
|
||||
self.base_type = base_type
|
||||
self.num_bits = num_bits
|
||||
|
|
@ -22,12 +25,23 @@ class Type(object):
|
|||
self.encode = encode
|
||||
self.nzdefault = nzdefault
|
||||
self.print_early = print_early
|
||||
self.enum = enum
|
||||
|
||||
types = {}
|
||||
|
||||
def type(name, base_type, num_bits=None, dec_bits=None, check=None, encode=None, nzdefault=None, print_early=False):
|
||||
def type(name, base_type, num_bits=None, dec_bits=None, check=None, encode=None, nzdefault=None, print_early=False, enum=None):
|
||||
assert name not in types.keys(), f'Duplicate type "{name}".'
|
||||
t = Type(name, base_type, num_bits, dec_bits, check, encode, nzdefault, print_early)
|
||||
|
||||
if base_type == BaseType.bool:
|
||||
_name = 'bool'
|
||||
elif base_type == BaseType.uint:
|
||||
_name = 'unsigned'
|
||||
elif base_type == BaseType.enum:
|
||||
_name = f'enum {prefix}_{name}'
|
||||
else:
|
||||
assert False, f'Invalid base type for type {name}.'
|
||||
|
||||
t = Type(_name, base_type, num_bits, dec_bits, check, encode, nzdefault, print_early, enum)
|
||||
types[name] = t
|
||||
return t
|
||||
|
||||
|
|
@ -42,9 +56,6 @@ class EnumType(object):
|
|||
self.parent = parent
|
||||
|
||||
enums = {}
|
||||
def val_fits_in_bits(val, num_bits):
|
||||
return val < pow(2, num_bits)
|
||||
|
||||
def enum_type(name, elems, is_bitset=False, num_bits=None, *args, **kwargs):
|
||||
assert name not in enums.keys(), f'Duplicate enum "{name}".'
|
||||
|
||||
|
|
@ -86,21 +97,22 @@ def enum_type(name, elems, is_bitset=False, num_bits=None, *args, **kwargs):
|
|||
_name = f'{prefix}_{name}'
|
||||
_valid = _valid_valmask if is_bitset else _valid_vals
|
||||
_unique_count = bin(_valid_valmask).count('1') if is_bitset else len(_valid_vals)
|
||||
enums[name] = EnumType(_name, _elems, _valid, _unique_count, is_bitset, parent=None)
|
||||
enum = EnumType(_name, _elems, _valid, _unique_count, is_bitset, parent=None)
|
||||
enums[name] = enum
|
||||
|
||||
return type(name, BaseType.enum, num_bits, *args, **kwargs)
|
||||
return type(name, BaseType.enum, num_bits, *args, **kwargs, enum=enum)
|
||||
|
||||
def enum_subtype(name, parent, num_bits):
|
||||
assert name not in enums.keys(), f'Duplicate enum "{name}".'
|
||||
|
||||
assert parent.name in enums.keys()
|
||||
enum_parent = enums[parent.name]
|
||||
assert not enum_parent.is_bitset
|
||||
assert parent.enum is not None
|
||||
assert not parent.enum.is_bitset
|
||||
assert parent.num_bits is not None and parent.num_bits > num_bits
|
||||
|
||||
_name = f'{prefix}_{name}'
|
||||
enums[name] = EnumType(_name, None, None, None, False, enum_parent)
|
||||
return type(name, BaseType.enum, num_bits)
|
||||
enum = EnumType(_name, None, None, None, False, parent)
|
||||
enums[name] = enum
|
||||
return type(name, BaseType.enum, num_bits, enum=enum)
|
||||
|
||||
# Type specializations.
|
||||
|
||||
|
|
@ -162,3 +174,141 @@ def ref_mod_enum(name, *args, **kwargs):
|
|||
ref_mod_enums[name] = enums[name]
|
||||
assert len(ref_mods) <= 64, 'Too many ref mods!'
|
||||
return t
|
||||
|
||||
# Bit encoding definition helpers.
|
||||
|
||||
class BitPiece(object):
|
||||
def __init__(self, name, byte, hi_bit, lo_bit, num_bits):
|
||||
self.name = name
|
||||
self.byte = byte
|
||||
self.hi_bit = hi_bit
|
||||
self.lo_bit = lo_bit
|
||||
self.num_bits = num_bits
|
||||
|
||||
def bit_piece(name, byte, bit_range):
|
||||
assert bit_range.count(':') <= 1, f'Invalid bit range specification in bit piece {name}.'
|
||||
is_one_bit = not bit_range.count(':')
|
||||
|
||||
split_range = [bit_range, bit_range] if is_one_bit else bit_range.split(':', 1)
|
||||
(hi_bit, lo_bit) = list(map(int, split_range))
|
||||
assert hi_bit < 8 and hi_bit >= 0 and lo_bit < 8 and lo_bit >= 0 and hi_bit >= lo_bit
|
||||
|
||||
_num_bits = hi_bit - lo_bit + 1
|
||||
return BitPiece(name, byte, hi_bit, lo_bit, _num_bits)
|
||||
|
||||
class BitField(object):
|
||||
def __init__(self, name, field_type, pieces, reserved):
|
||||
self.name = name
|
||||
self.field_type = field_type
|
||||
self.pieces = pieces
|
||||
self.reserved = reserved
|
||||
|
||||
def bit_field(name, bit_set_pieces, field_type, pieces, reserved=None):
|
||||
_pieces = [bit_set_pieces[p] for p in pieces]
|
||||
|
||||
total_bits = sum([p.num_bits for p in _pieces])
|
||||
assert total_bits == field_type.num_bits, f'Expected {field_type.num_bits}, got {total_bits} in bit field {name}.'
|
||||
|
||||
if reserved is not None:
|
||||
assert val_fits_in_bits(reserved, total_bits), f'Reserved value for bit field {name} is too large.'
|
||||
|
||||
return BitField(name, field_type, _pieces, reserved)
|
||||
|
||||
class BitSet(object):
|
||||
def __init__(self, name, pieces, fields):
|
||||
self.name = name
|
||||
self.pieces = pieces
|
||||
self.fields = fields
|
||||
self.bit_structs = {}
|
||||
self.variants = []
|
||||
|
||||
bit_sets = {}
|
||||
|
||||
def bit_set(name, pieces, fields):
|
||||
assert name not in bit_sets.keys(), f'Duplicate bit set "{name}".'
|
||||
|
||||
_pieces = {}
|
||||
for (piece, spec) in pieces:
|
||||
assert piece not in _pieces.keys(), f'Duplicate bit piece "{n}" in bit set "{name}".'
|
||||
_pieces[piece] = bit_piece(piece, *spec)
|
||||
|
||||
_fields = {}
|
||||
for (field, spec) in fields:
|
||||
assert field not in _fields.keys(), f'Duplicate bit field "{n}" in bit set "{name}".'
|
||||
_fields[field] = bit_field(field, _pieces, *spec)
|
||||
|
||||
_name = f'{prefix}_{name}'
|
||||
bs = BitSet(_name, _pieces, _fields)
|
||||
bit_sets[name] = bs
|
||||
return bs
|
||||
|
||||
class BitStruct(object):
|
||||
def __init__(self, name, struct_fields, num_bytes):
|
||||
self.name = name
|
||||
self.struct_fields = struct_fields
|
||||
self.num_bytes = num_bytes
|
||||
|
||||
def bit_struct(name, bit_set, field_mappings):
|
||||
assert name not in bit_set.bit_structs.keys(), f'Duplicate bit struct "{name}" in bit set "{bit_set.name}".'
|
||||
|
||||
struct_fields = {}
|
||||
all_pieces = []
|
||||
total_bits = 0
|
||||
for mapping in field_mappings:
|
||||
if isinstance(mapping, str):
|
||||
struct_field = mapping
|
||||
_field = mapping
|
||||
fixed_value = None
|
||||
else:
|
||||
assert isinstance(mapping, tuple)
|
||||
struct_field, _field, *fixed_value = mapping
|
||||
assert len(fixed_value) == 0 or len(fixed_value) == 1
|
||||
fixed_value = None if len(fixed_value) == 0 else fixed_value[0]
|
||||
|
||||
assert struct_field not in struct_fields.keys(), f'Duplicate struct field "{struct_field}" in bit struct "{name}".'
|
||||
assert _field in bit_set.fields.keys(), f'Field "{_field}" in mapping for struct field "{name}.{struct_field}" not defined in bit set "{bit_set.name}".'
|
||||
field = bit_set.fields[_field]
|
||||
field_type = field.field_type
|
||||
is_enum = field_type.base_type == BaseType.enum
|
||||
|
||||
if fixed_value is not None:
|
||||
assert field.reserved is None, f'Fixed value for field mapping "{struct_field}" using field "{_field}" cannot overwrite its reserved value.'
|
||||
|
||||
if is_enum and isinstance(fixed_value, str):
|
||||
enum = field_type.enum
|
||||
assert fixed_value in enum.elems.keys(), f'Fixed value for field mapping "{struct_field}" using field "{_field}" is not an element of enum {field_type.name}.'
|
||||
fixed_value = f'{prefix}_{field_type.name}_{fixed_value}'.upper()
|
||||
else:
|
||||
if isinstance(fixed_value, bool):
|
||||
fixed_value = int(fixed_value)
|
||||
|
||||
assert isinstance(fixed_value, int)
|
||||
assert val_fits_in_bits(fixed_value, field_type.num_bits), f'Fixed value for field mapping "{struct_field}" using field "{_field}" is too large.'
|
||||
|
||||
all_pieces.extend([(piece.lo_bit + (8 * piece.byte), piece.hi_bit + (8 * piece.byte), piece.name) for piece in field.pieces])
|
||||
total_bits += field_type.num_bits
|
||||
|
||||
if field.reserved is None and fixed_value is None:
|
||||
# Use parent enum for struct fields.
|
||||
if is_enum and field_type.enum.parent is not None:
|
||||
field_type = field_type.enum.parent
|
||||
|
||||
struct_field_bits = field_type.dec_bits if field_type.dec_bits is not None else field_type.num_bits
|
||||
struct_fields[struct_field] = (field_type.name, struct_field, struct_field_bits)
|
||||
|
||||
# Check for overlapping pieces.
|
||||
for p0 in all_pieces:
|
||||
for p1 in all_pieces:
|
||||
if p0 == p1:
|
||||
continue
|
||||
assert p0[1] < p1[0] or p0[0] > p1[1], f'Pieces "{p0[2]}" and "{p1[2]}" overlap in bit struct "{name}".'
|
||||
|
||||
# Check for byte-alignment.
|
||||
assert (total_bits % 8) == 0, f'Bit struct "{name}" has a non-byte-aligned number of bits ({total_bits}).'
|
||||
|
||||
_name = f'{bit_set.name}_{name}'
|
||||
bs = BitStruct(_name, struct_fields, total_bits // 8)
|
||||
bit_set.bit_structs[name] = bs
|
||||
bit_set.variants.append(f'{bit_set.name}_{name}'.upper())
|
||||
|
||||
return bs
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue