[Intel-gfx] [PATCH] drm/i915: Use hash tables for the command parser

Damien Lespiau damien.lespiau at intel.com
Thu May 8 15:52:28 CEST 2014


On Thu, May 08, 2014 at 12:44:57PM +0100, Damien Lespiau wrote:
> I was hoping we could compute a (near) minimal perfect hash function
> though. Let me try to dig a bit.

So, I went a bit further here and we can actually generate a minimal
perfect hash function. I took the 44 HSW render opcodes and fed them
into:

  http://burtleburtle.net/bob/hash/perfect.html
  https://github.com/driedfruit/jenkins-minimal-perfect-hash

The resulting hash function is:

static uint8_t mph_tab[] = {
        0,0,10,0,51,0,34,0,12,22,0,0,28,0,9,0,
        9,0,19,0,0,0,11,0,10,61,20,50,49,60,45,55,
};

static uint32_t mph_hash(uint32_t val)
{
        uint32_t a, b, rsl;

        val += 0xa195a44b;
        val += (val << 8);
        val ^= (val >> 4);
        b = (val >> 18) & 0x1f;
        a = val >> 27;
        rsl = (a^mph_tab[b]);

        return rsl;
}

When used the 44 HSW opcodes (opcode & 0xffff0000) it produces distinct numbers
(perfect hash) from 0 to 43 (minimal) that could then be used to address an array.

You can play with the joined test:

$ ./minimal-hash-hsw-render  | sort -nk2

So now, how useful is that is an interesting question. We do have static tables
upstream (IIUC), but Tvrtko reminded me that it may not match other trees,
which is sad.

-- 
Damien
-------------- next part --------------
#include <stdint.h>
#include <stdio.h>

#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))

#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))

#define MI_NOOP			MI_INSTR(0, 0)
#define MI_USER_INTERRUPT	MI_INSTR(0x02, 0)
#define MI_WAIT_FOR_EVENT       MI_INSTR(0x03, 0)
#define MI_ARB_CHECK            MI_INSTR(0x05, 0)
#define MI_REPORT_HEAD		MI_INSTR(0x07, 0)
#define MI_ARB_ON_OFF		MI_INSTR(0x08, 0)
#define MI_BATCH_BUFFER_END	MI_INSTR(0x0a, 0)
#define MI_SUSPEND_FLUSH	MI_INSTR(0x0b, 0)
#define MI_OVERLAY_FLIP		MI_INSTR(0x11, 0)
#define MI_SET_PREDICATE        MI_INSTR(0x01, 0)
#define MI_ARB_CHECK            MI_INSTR(0x05, 0)
#define MI_RS_CONTROL           MI_INSTR(0x06, 0)
#define MI_URB_ATOMIC_ALLOC     MI_INSTR(0x09, 0)
#define MI_PREDICATE            MI_INSTR(0x0C, 0)
#define MI_RS_CONTEXT           MI_INSTR(0x0F, 0)
#define MI_TOPOLOGY_FILTER      MI_INSTR(0x0D, 0)
#define MI_LOAD_SCAN_LINES_EXCL MI_INSTR(0x13, 0)
#define MI_URB_CLEAR            MI_INSTR(0x19, 0)
#define MI_UPDATE_GTT           MI_INSTR(0x23, 0)
#define MI_CLFLUSH              MI_INSTR(0x27, 0)
#define MI_REPORT_PERF_COUNT    MI_INSTR(0x28, 0)
#define MI_LOAD_REGISTER_MEM    MI_INSTR(0x29, 0)
#define MI_LOAD_REGISTER_REG    MI_INSTR(0x2A, 0)
#define MI_RS_STORE_DATA_IMM    MI_INSTR(0x2B, 0)
#define MI_LOAD_URB_MEM         MI_INSTR(0x2C, 0)
#define MI_STORE_URB_MEM        MI_INSTR(0x2D, 0)
#define MI_CONDITIONAL_BATCH_BUFFER_END MI_INSTR(0x36, 0)
#define MI_SEMAPHORE_MBOX	MI_INSTR(0x16, 1) /* gen6+ */
#define MI_STORE_DWORD_IMM	MI_INSTR(0x20, 1)
#define MI_STORE_DWORD_INDEX	MI_INSTR(0x21, 1)
#define MI_SET_CONTEXT		MI_INSTR(0x18, 0)
#define MI_LOAD_REGISTER_IMM(x)	MI_INSTR(0x22, 2*(x)-1)
#define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*(x)-1)
#define MI_BATCH_BUFFER_START	MI_INSTR(0x31, 0)
#define MI_FLUSH		MI_INSTR(0x04, 0)
#define MI_DISPLAY_FLIP		MI_INSTR(0x14, 2)
#define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0)

#define GFX_OP_PIPE_CONTROL(len)	((0x3<<29)|(0x3<<27)|(0x2<<24)|(len-2))
#define PIPELINE_SELECT                ((0x3<<29)|(0x1<<27)|(0x1<<24)|(0x4<<16))
#define GFX_OP_3DSTATE_VF_STATISTICS   ((0x3<<29)|(0x1<<27)|(0x0<<24)|(0xB<<16))
#define MEDIA_VFE_STATE                ((0x3<<29)|(0x2<<27)|(0x0<<24)|(0x0<<16))
#define  MEDIA_VFE_STATE_MMIO_ACCESS_MASK (0x18)
#define GPGPU_OBJECT                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16))
#define GPGPU_WALKER                   ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16))
#define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \
	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x39<<16))
#define GFX_OP_3DSTATE_DX9_CONSTANTF_PS \
	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x3A<<16))
#define GFX_OP_3DSTATE_SO_DECL_LIST \
	((0x3<<29)|(0x3<<27)|(0x1<<24)|(0x17<<16))

#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS \
	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x43<<16))
#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS \
	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x44<<16))
#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS \
	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x45<<16))
#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS \
	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x46<<16))
#define GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS \
	((0x3<<29)|(0x3<<27)|(0x0<<24)|(0x47<<16))

#define MFX_WAIT  ((0x3<<29)|(0x1<<27)|(0x0<<16))

#define COLOR_BLT     ((0x2<<29)|(0x40<<22))
#define SRC_COPY_BLT  ((0x2<<29)|(0x43<<22))

uint32_t opcodes[] = {
	MI_NOOP,
	MI_USER_INTERRUPT,
	MI_WAIT_FOR_EVENT,
	MI_ARB_CHECK,
	MI_REPORT_HEAD,
	MI_SUSPEND_FLUSH,
	MI_SEMAPHORE_MBOX,
	MI_STORE_DWORD_INDEX,
	MI_LOAD_REGISTER_IMM(1),
	MI_STORE_REGISTER_MEM(1),
	MI_LOAD_REGISTER_MEM,
	MI_BATCH_BUFFER_START,
	MI_FLUSH,
	MI_ARB_ON_OFF,
	MI_PREDICATE,
	MI_TOPOLOGY_FILTER,
	MI_DISPLAY_FLIP,
	MI_SET_CONTEXT,
	MI_URB_CLEAR,
	MI_STORE_DWORD_IMM,
	MI_UPDATE_GTT,
	MI_CLFLUSH,
	MI_REPORT_PERF_COUNT,
	MI_CONDITIONAL_BATCH_BUFFER_END,
	GFX_OP_3DSTATE_VF_STATISTICS,
	PIPELINE_SELECT,
	MEDIA_VFE_STATE,
	GPGPU_OBJECT,
	GPGPU_WALKER,
	GFX_OP_3DSTATE_SO_DECL_LIST,
	GFX_OP_PIPE_CONTROL(5),
	MI_LOAD_SCAN_LINES_INCL,
	MI_LOAD_SCAN_LINES_EXCL,
	MI_LOAD_REGISTER_REG,
	MI_RS_STORE_DATA_IMM,
	MI_LOAD_URB_MEM,
	MI_STORE_URB_MEM,
	GFX_OP_3DSTATE_DX9_CONSTANTF_VS,
	GFX_OP_3DSTATE_DX9_CONSTANTF_PS,
	GFX_OP_3DSTATE_BINDING_TABLE_EDIT_VS,
	GFX_OP_3DSTATE_BINDING_TABLE_EDIT_GS,
	GFX_OP_3DSTATE_BINDING_TABLE_EDIT_HS,
	GFX_OP_3DSTATE_BINDING_TABLE_EDIT_DS,
	GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS,
};

#define STD_MI_OPCODE_MASK  0xFF800000
#define STD_3D_OPCODE_MASK  0xFFFF0000
#define STD_2D_OPCODE_MASK  0xFFC00000
#define STD_MFX_OPCODE_MASK 0xFFFF0000
#define CMD_HASH_MASK STD_MI_OPCODE_MASK


/* small adjustments to _a_ to make values distinct */
static uint8_t mph_tab[] = {
	0,0,10,0,51,0,34,0,12,22,0,0,28,0,9,0,
	9,0,19,0,0,0,11,0,10,61,20,50,49,60,45,55,
};

/* The hash function */
static uint32_t mph_hash(uint32_t val)
{
	uint32_t a, b, rsl;
	val += 0xa195a44b;

	val += (val << 8);
	val ^= (val >> 4);
	b = (val >> 18) & 0x1f;
	a = val >> 27;
	rsl = (a^mph_tab[b]);

	return rsl;
}

int main(void)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(opcodes); i++)
		printf("%08x %d\n", opcodes[i] & 0xffff0000,
			mph_hash(opcodes[i] & 0xffff0000));

	return 0;
}


More information about the Intel-gfx mailing list