6db4831e98
Android 14
167 lines
3.6 KiB
C
167 lines
3.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
#include "cmdq_prof.h"
|
|
#include "mdp_cmdq_helper_ext.h"
|
|
|
|
/* expect no EMI latency, GCE spends 80 ns per 4 cycle*/
|
|
#define CMDQ_HW_EXEC_NS(hw_cycle) (hw_cycle * (80 / 4))
|
|
|
|
enum CMDQ_OP_STATISTIC_ENUM {
|
|
CMDQ_STA_READ = 0,
|
|
CMDQ_STA_MOVE,
|
|
CMDQ_STA_WRI,
|
|
CMDQ_STA_WRI_WITH_MASK,
|
|
CMDQ_STA_POLL,
|
|
CMDQ_STA_JUMP,
|
|
CMDQ_STA_WFE, /* wait for event */
|
|
CMDQ_STA_SYNC, /* sync op and no wait for event */
|
|
CMDQ_STA_EOC,
|
|
CMDQ_STA_MAX_COUNT, /* always keep at the end */
|
|
};
|
|
|
|
const char *cmdq_prof_get_statistic_id_name(
|
|
const enum CMDQ_OP_STATISTIC_ENUM statisticId)
|
|
{
|
|
const char *IDName = "UNKNOWN";
|
|
|
|
#undef DECLARE_CMDQ_INSTR_CYCLE
|
|
#define DECLARE_CMDQ_INSTR_CYCLE(id, hw_op, cycle, name) { \
|
|
if (id == statisticId) { \
|
|
IDName = #name; \
|
|
break; \
|
|
} }
|
|
|
|
do {
|
|
#include "cmdq_instr_cycle.h"
|
|
} while (0);
|
|
#undef DECLARE_CMDQ_INSTR_CYCLE
|
|
|
|
return IDName;
|
|
}
|
|
|
|
u32 cmdq_prof_get_statistic_id(const u32 *pCmd)
|
|
{
|
|
const u32 arg_b = pCmd[0];
|
|
const u32 arg_a = pCmd[1];
|
|
const u32 op = arg_a >> 24;
|
|
u32 addr;
|
|
u32 maskEn = 0;
|
|
|
|
switch (op) {
|
|
case CMDQ_CODE_WRITE_S:
|
|
return CMDQ_STA_WRI;
|
|
case CMDQ_CODE_WRITE_S_W_MASK:
|
|
return CMDQ_STA_WRI_WITH_MASK;
|
|
case CMDQ_CODE_WRITE:
|
|
/* check address */
|
|
if (arg_a & (1 << 23)) {
|
|
/* address is GPR */
|
|
return CMDQ_STA_WRI;
|
|
}
|
|
addr = cmdq_core_subsys_to_reg_addr(arg_a);
|
|
maskEn = (addr & 0x1);
|
|
if (maskEn)
|
|
return CMDQ_STA_WRI_WITH_MASK;
|
|
else
|
|
return CMDQ_STA_WRI;
|
|
|
|
case CMDQ_CODE_WFE:
|
|
/* check waiting flag */
|
|
if ((arg_b >> 15) & 0x1)
|
|
return CMDQ_STA_WFE;
|
|
else
|
|
return CMDQ_STA_SYNC;
|
|
|
|
case CMDQ_CODE_READ:
|
|
case CMDQ_CODE_READ_S:
|
|
return CMDQ_STA_READ;
|
|
|
|
case CMDQ_CODE_MOVE:
|
|
return CMDQ_STA_MOVE;
|
|
|
|
case CMDQ_CODE_POLL:
|
|
return CMDQ_STA_POLL;
|
|
|
|
case CMDQ_CODE_JUMP:
|
|
return CMDQ_STA_JUMP;
|
|
|
|
case CMDQ_CODE_EOC:
|
|
case CMDQ_CODE_LOGIC:
|
|
case CMDQ_CODE_JUMP_C_RELATIVE:
|
|
return CMDQ_STA_EOC;
|
|
default:
|
|
CMDQ_ERR("unknown op, arg_a: 0x%08x\n", arg_a);
|
|
return 0;
|
|
}
|
|
|
|
CMDQ_ERR("unknown op, arg_a: 0x%08x\n", arg_a);
|
|
return 0;
|
|
}
|
|
|
|
u32 cmdq_prof_calculate_HW_cycle(
|
|
const enum CMDQ_OP_STATISTIC_ENUM statisticId, const u32 count)
|
|
{
|
|
u32 hwCycle = -1;
|
|
|
|
#undef DECLARE_CMDQ_INSTR_CYCLE
|
|
#define DECLARE_CMDQ_INSTR_CYCLE(id, hw_op, cycle, name) { \
|
|
if (id == statisticId) { \
|
|
hwCycle = (count * cycle); \
|
|
break; } }
|
|
|
|
do {
|
|
#include "cmdq_instr_cycle.h"
|
|
} while (0);
|
|
#undef DECLARE_CMDQ_INSTR_CYCLE
|
|
|
|
if (-1 == hwCycle) {
|
|
/* Error message dump */
|
|
CMDQ_ERR("unknown statisticId: %d\n", statisticId);
|
|
}
|
|
|
|
return hwCycle;
|
|
}
|
|
|
|
s32 cmdq_prof_estimate_command_exe_time(const u32 *pCmd,
|
|
u32 commandSize)
|
|
{
|
|
u32 statistic[CMDQ_STA_MAX_COUNT] = { 0 };
|
|
int i;
|
|
u32 statisticId = 0;
|
|
u32 cycle = 0;
|
|
u32 totalCycle = 0;
|
|
u32 totalNS = 0;
|
|
|
|
if (pCmd == NULL)
|
|
return -EFAULT;
|
|
|
|
/* gather statistic */
|
|
for (i = 0; i < commandSize; i += CMDQ_INST_SIZE, pCmd += 2) {
|
|
statisticId = cmdq_prof_get_statistic_id(pCmd);
|
|
statistic[statisticId] += 1;
|
|
}
|
|
|
|
CMDQ_LOG("NAME, COUNT, least HW exec cycle\n");
|
|
/* calculate execution time */
|
|
for (i = 0; i < CMDQ_STA_MAX_COUNT; i++) {
|
|
cycle = cmdq_prof_calculate_HW_cycle(i, statistic[i]);
|
|
totalCycle += cycle;
|
|
CMDQ_LOG("%d:%11s, %d, %3d\n",
|
|
i, cmdq_prof_get_statistic_id_name(i), statistic[i],
|
|
cycle);
|
|
}
|
|
|
|
totalNS = CMDQ_HW_EXEC_NS(totalCycle);
|
|
CMDQ_LOG("=====================================\n");
|
|
CMDQ_LOG("estimated least HW exec time(ns): %6d\n", totalNS);
|
|
CMDQ_LOG("***each HW cycle spends time(ns): %6d\n",
|
|
CMDQ_HW_EXEC_NS(1));
|
|
CMDQ_LOG(
|
|
"***Real exec time will be longer when POLL/WAIT instr cannot pass their condition immediately.\n");
|
|
|
|
return totalNS;
|
|
}
|