1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { SpSystemTrace } from '../SpSystemTrace'; 17import { TraceRow } from '../trace/base/TraceRow'; 18import { renders } from '../../database/ui-worker/ProcedureWorker'; 19import { info } from '../../../log/Log'; 20import { ClockRender, ClockStruct } from '../../database/ui-worker/ProcedureWorkerClock'; 21import { ColorUtils } from '../trace/base/ColorUtils'; 22import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; 23import { Utils } from '../trace/base/Utils'; 24import { clockDataSender } from '../../database/data-trafic/ClockDataSender'; 25import { queryClockData } from '../../database/sql/Clock.sql'; 26import { DmaFenceRender, DmaFenceStruct } from '../../database/ui-worker/ProcedureWorkerDmaFence'; 27import { dmaFenceSender } from '../../database/data-trafic/dmaFenceSender'; 28import { queryDmaFenceName } from '../../database/sql/dmaFence.sql'; 29import { BaseStruct } from '../../bean/BaseStruct'; 30import { promises } from 'dns'; 31 32export class SpClockChart { 33 private readonly trace: SpSystemTrace; 34 35 constructor(trace: SpSystemTrace) { 36 this.trace = trace; 37 } 38 39 async init(parentRow?: TraceRow<BaseStruct>, traceId?: string): Promise<void> { 40 let clockList = await queryClockData(traceId); 41 if (clockList.length === 0) { 42 return; 43 } 44 let folder = await this.initFolder(traceId); 45 if (parentRow) { 46 parentRow.addChildTraceRow(folder); 47 } else { 48 this.trace.rowsEL?.appendChild(folder); 49 } 50 // heca_freq Frequency移动到数组末尾 51 const index = clockList.findIndex(item => item.name === 'heca_freq Frequency'); 52 if (index !== -1) { 53 const item = clockList.splice(index, 1); 54 if (item && item.length) { 55 clockList.push(item[0]); 56 } 57 } 58 await this.initDmaFence(folder); 59 await this.initData(folder, clockList, traceId); 60 } 61 62 private clockSupplierFrame( 63 traceRow: TraceRow<ClockStruct>, 64 it: { 65 name: string; 66 num: number; 67 srcname: string; 68 maxValue?: number; 69 }, 70 isState: boolean, 71 isScreenState: boolean, 72 ): void { 73 traceRow.supplierFrame = (): Promise<ClockStruct[]> => { 74 let promiseData = null; 75 if (it.name.endsWith(' Frequency')) { 76 promiseData = clockDataSender(it.srcname, 'clockFrequency', traceRow); 77 } else if (isState) { 78 promiseData = clockDataSender(it.srcname, 'clockState', traceRow); 79 } else if (isScreenState) { 80 promiseData = clockDataSender('', 'screenState', traceRow); 81 } 82 if (promiseData === null) { 83 // @ts-ignore 84 return new Promise<Array<unknown>>((resolve) => resolve([])); 85 } else { 86 // @ts-ignore 87 return promiseData.then((resultClock: Array<unknown>) => { 88 for (let j = 0; j < resultClock.length; j++) { 89 // @ts-ignore 90 resultClock[j].type = 'measure'; // @ts-ignore 91 if ((resultClock[j].value || 0) > it.maxValue!) { 92 // @ts-ignore 93 it.maxValue = resultClock[j].value || 0; 94 } 95 if (j > 0) { 96 // @ts-ignore 97 resultClock[j].delta = (resultClock[j].value || 0) - (resultClock[j - 1].value || 0); 98 } else { 99 // @ts-ignore 100 resultClock[j].delta = 0; 101 } 102 } 103 return resultClock; 104 }); 105 } 106 }; 107 } 108 109 private clockThreadHandler( 110 traceRow: TraceRow<ClockStruct>, 111 it: { 112 name: string; 113 num: number; 114 srcname: string; 115 maxValue?: number; 116 }, 117 isState: boolean, 118 isScreenState: boolean, 119 clockId: number 120 ): void { 121 traceRow.onThreadHandler = (useCache): void => { 122 let context: CanvasRenderingContext2D; 123 if (traceRow.currentContext) { 124 context = traceRow.currentContext; 125 } else { 126 context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 127 } 128 traceRow.canvasSave(context); 129 (renders.clock as ClockRender).renderMainThread( 130 { 131 context: context, 132 useCache: useCache, 133 type: it.name, 134 maxValue: it.maxValue === 0 ? 1 : it.maxValue!, 135 index: clockId, 136 maxName: 137 isState || isScreenState 138 ? it.maxValue!.toString() 139 : Utils.getFrequencyWithUnit(it.maxValue! / 1000).maxFreqName, 140 }, 141 traceRow 142 ); 143 traceRow.canvasRestore(context, this.trace); 144 }; 145 } 146 147 async initData(folder: TraceRow<BaseStruct>, clockList: Array<{ 148 name: string; 149 num: number; 150 srcname: string; 151 maxValue?: number; 152 }>, traceId?: string): Promise<void> { 153 let clockStartTime = new Date().getTime(); 154 info('clockList data size is: ', clockList!.length); 155 if (!traceId) { 156 this.trace.rowsEL?.appendChild(folder); 157 } 158 ClockStruct.maxValue = clockList.map((item) => item.num).reduce((a, b) => Math.max(a, b)); 159 for (let i = 0; i < clockList.length; i++) { 160 const it = clockList[i]; 161 it.maxValue = 0; 162 let traceRow = TraceRow.skeleton<ClockStruct>(traceId); 163 let isState = it.name.endsWith(' State'); 164 let isScreenState = it.name.endsWith('ScreenState'); 165 traceRow.rowId = it.name; 166 traceRow.rowType = TraceRow.ROW_TYPE_CLOCK; 167 traceRow.rowParentId = folder.rowId; 168 traceRow.style.height = '40px'; 169 traceRow.name = it.name; 170 traceRow.rowHidden = !folder.expansion; 171 traceRow.setAttribute('children', ''); 172 traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 173 traceRow.selectChangeHandler = this.trace.selectChangeHandler; 174 this.clockSupplierFrame(traceRow, it, isState, isScreenState); 175 traceRow.getCacheData = (args: unknown): Promise<ClockStruct[]> | undefined => { 176 let result: Promise<ClockStruct[]> | undefined; 177 if (it.name.endsWith(' Frequency')) { 178 result = clockDataSender(it.srcname, 'clockFrequency', traceRow, args); 179 } else if (isState) { 180 result = clockDataSender(it.srcname, 'clockState', traceRow, args); 181 } else if (isScreenState) { 182 result = clockDataSender('', 'screenState', traceRow, args); 183 } 184 return result; 185 }; 186 traceRow.focusHandler = (ev): void => { 187 this.trace?.displayTip( 188 traceRow, 189 ClockStruct.hoverClockStruct, 190 `<span>${ColorUtils.formatNumberComma(ClockStruct.hoverClockStruct?.value!)}</span>` 191 ); 192 }; 193 traceRow.findHoverStruct = (): void => { 194 ClockStruct.hoverClockStruct = traceRow.getHoverStruct(); 195 }; 196 this.clockThreadHandler(traceRow, it, isState, isScreenState, i); 197 folder.addChildTraceRow(traceRow); 198 } 199 let durTime = new Date().getTime() - clockStartTime; 200 info('The time to load the ClockData is: ', durTime); 201 } 202 203 // @ts-ignore 204 async initDmaFence(folder: TraceRow<unknown>): Promise<void> { 205 let dmaFenceNameList = await queryDmaFenceName(); 206 if (dmaFenceNameList.length) { 207 let dmaFenceList = []; 208 const timelineValues = dmaFenceNameList.map(obj => obj.timeline); 209 for (let i = 0; i < timelineValues.length; i++) { 210 let traceRow: TraceRow<DmaFenceStruct> = TraceRow.skeleton<DmaFenceStruct>(); 211 traceRow.rowId = timelineValues[i]; 212 traceRow.rowType = TraceRow.ROW_TYPE_DMA_FENCE; 213 traceRow.rowParentId = folder.rowId; 214 traceRow.style.height = 40 + 'px'; 215 traceRow.name = `${timelineValues[i]}`; 216 traceRow.folder = false; 217 traceRow.rowHidden = !folder.expansion; 218 traceRow.setAttribute('children', ''); 219 traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 220 traceRow.selectChangeHandler = this.trace.selectChangeHandler; 221 // @ts-ignore 222 traceRow.supplierFrame = (): Promise<DmaFenceStruct[]> => { 223 return dmaFenceSender('dma_fence_init', `${timelineValues[i]}`, traceRow).then((res) => { 224 res.forEach((item: unknown) => { 225 // @ts-ignore 226 let detail = Utils.DMAFENCECAT_MAP.get(item.id!); 227 if (detail) { 228 let catValue = (detail.cat.match(/^dma_(.*)$/))![1]; 229 // @ts-ignore 230 item.sliceName = catValue.endsWith('ed') ? `${catValue.slice(0, -2)}(${detail.seqno})` : `${catValue}(${detail.seqno})`; 231 // @ts-ignore 232 item.driver = detail.driver; 233 // @ts-ignore 234 item.context = detail.context; 235 // @ts-ignore 236 item.depth = 0; 237 } 238 239 }); 240 return dmaFenceList = res; 241 }); 242 243 }; 244 traceRow.onThreadHandler = (useCache): void => { 245 let context: CanvasRenderingContext2D; 246 if (traceRow.currentContext) { 247 context = traceRow.currentContext; 248 } else { 249 context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 250 } 251 traceRow.canvasSave(context); 252 (renders.dmaFence as DmaFenceRender).renderMainThread( 253 { 254 dmaFenceContext: context, 255 useCache: useCache, 256 type: 'dmaFence', 257 maxValue: 20, 258 index: 1, 259 maxName: '' 260 }, 261 traceRow 262 ); 263 traceRow.canvasRestore(context, this.trace); 264 }; 265 folder.addChildTraceRow(traceRow); 266 } 267 268 } 269 270 } 271 272 273 async initFolder(traceId?: string): Promise<TraceRow<BaseStruct>> { 274 let clockFolder = TraceRow.skeleton(traceId); 275 clockFolder.rowId = 'Clocks'; 276 clockFolder.index = 0; 277 clockFolder.rowType = TraceRow.ROW_TYPE_CLOCK_GROUP; 278 clockFolder.rowParentId = ''; 279 clockFolder.style.height = '40px'; 280 clockFolder.folder = true; 281 clockFolder.name = 'Clocks'; 282 clockFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler; 283 clockFolder.selectChangeHandler = this.trace.selectChangeHandler; 284 clockFolder.supplier = (): Promise<BaseStruct[]> => new Promise<Array<BaseStruct>>((resolve) => resolve([])); 285 clockFolder.onThreadHandler = (useCache): void => { 286 clockFolder.canvasSave(this.trace.canvasPanelCtx!); 287 if (clockFolder.expansion) { 288 this.trace.canvasPanelCtx?.clearRect(0, 0, clockFolder.frame.width, clockFolder.frame.height); 289 } else { 290 (renders.empty as EmptyRender).renderMainThread( 291 { 292 context: this.trace.canvasPanelCtx, 293 useCache: useCache, 294 type: '', 295 }, 296 clockFolder 297 ); 298 } 299 clockFolder.canvasRestore(this.trace.canvasPanelCtx!, this.trace); 300 }; 301 return clockFolder; 302 } 303} 304