Skip to content

Commit 2e54316

Browse files
committed
Add Am62x Power Estimator Tool
1 parent 93ded85 commit 2e54316

14 files changed

+12603
-45
lines changed

config-manager.js

Lines changed: 736 additions & 0 deletions
Large diffs are not rendered by default.

data/am62x_dropdowns.js

Lines changed: 2012 additions & 0 deletions
Large diffs are not rendered by default.

data/am62x_pet_mapping.js

Lines changed: 490 additions & 0 deletions
Large diffs are not rendered by default.

data/am62x_power_data.js

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
/**
2+
* data/am62x_power_data.js
3+
*
4+
* Simplified JSON representation of the AM62x Power Estimation Tool.
5+
* In a production scenario, this file would be generated from the Excel spreadsheet
6+
* or contain the WASM/JS ported formulas.
7+
*
8+
* For this UI scaffold, we provide mock structural data and a simplified
9+
* estimation function.
10+
*/
11+
12+
const AM62x_DATA = {
13+
id: "am62x",
14+
name: "AM62x",
15+
description: "Multi-core Arm Cortex-A53 processor with 3D graphics",
16+
17+
// Valid input ranges
18+
inputs: {
19+
temperature: {
20+
min: -40,
21+
max: 125,
22+
default: 25,
23+
step: 1
24+
},
25+
processCorners: [
26+
{ id: "nominal", label: "Nominal" },
27+
{ id: "strong", label: "Strong" }
28+
],
29+
leakageMargins: [
30+
{ id: "0.0", label: "0%" },
31+
{ id: "0.1", label: "10%" },
32+
{ id: "0.2", label: "20%" },
33+
{ id: "0.3", label: "30%" }
34+
],
35+
voltages: [
36+
{ id: "VDD_CORE", label: "VDD_CORE Voltage", options: [{ val: 0.75, lbl: "0.75V" }, { val: 0.85, lbl: "0.85V" }, { val: 0.88, lbl: "0.88V (OD)" }, { val: 1.15, lbl: "1.15V" }] },
37+
{ id: "VDD_CORE_SRAM", label: "VDD_CORE_SRAM Voltage", options: [{ val: 0.85, lbl: "0.85V" }, { val: 0.88, lbl: "0.88V (OD)" }, { val: 1.15, lbl: "1.15V" }] }
38+
]
39+
},
40+
41+
// Fixed voltage rails (simplified representation of what's in the Excel)
42+
fixedVoltages: [
43+
{ id: "VDD_CANUART", label: "VDD_CANUART", nom: 0.85 },
44+
{ id: "VDDA_1P8", label: "VDDA_1P8", nom: 1.80 },
45+
{ id: "VDDA_3P3", label: "VDDA_3P3", nom: 3.30 }
46+
],
47+
48+
// Pre-defined use cases from Excel "Use Cases" sheet
49+
useCases: [
50+
{ id: "idle", label: "Idle" },
51+
{ id: "100_percent", label: "100% (Max Utility)" },
52+
{ id: "uc1_1_dual", label: "UC 1.1 Dual" },
53+
{ id: "uc1_1_quad", label: "UC 1.1 Quad" },
54+
{ id: "uc1_6_quad", label: "UC 1.6 Quad" },
55+
{ id: "max_current_125c", label: "Max Current 125C" }
56+
],
57+
58+
/**
59+
* MOCK CALCULATION FUNCTION
60+
* -------------------------
61+
* This function simulates the complex macro calculations in the Excel sheet.
62+
* It uses a baseline power for each use case and scales it linearly with
63+
* temperature and process corner to demonstrate UI responsiveness.
64+
*
65+
* @param {Object} config - The current UI configuration
66+
* @returns {Object} { total, static, dynamic, breakdown }
67+
*/
68+
calculatePower: function (config) {
69+
const temp = parseFloat(config['temperature-input'] || 25);
70+
const isStrong = config['process-corner'] === 'strong';
71+
const leakageMargin = parseFloat(config['leakage-margin'] || 0.0) / 100.0;
72+
73+
// Configuration Voltages
74+
const vddCore = parseFloat(config['VDD_CORE'] || 0.75);
75+
const vddarCore = parseFloat(config['VDDAR_CORE'] || 0.85);
76+
77+
// Fixed Voltages per CSV
78+
const vdda1p8 = 1.80;
79+
const vddsDdr = 1.10; // LPDDR4
80+
const dvdd1p8 = 1.80;
81+
const dvdd3p3 = 3.30;
82+
83+
let finalStatic = 0;
84+
let finalDynamic = 0;
85+
86+
// Breakdown categories for charts
87+
const breakdown = {
88+
'static_core': 0,
89+
'static_io': 0,
90+
'dyn_cpu': 0,
91+
'dyn_gpu': 0,
92+
'dyn_io': 0,
93+
'dyn_other': 0
94+
};
95+
96+
// Per-rail power tracking aligned with CSV
97+
const railPower = {
98+
'VDD_CORE': { voltage: vddCore, static: 0, dynamic: 0 },
99+
'VDDAR_CORE': { voltage: vddarCore, static: 0, dynamic: 0 },
100+
'VDDA_1V8': { voltage: vdda1p8, static: 0, dynamic: 0 },
101+
'VDDS_DDR': { voltage: vddsDdr, static: 0, dynamic: 0 },
102+
'SOC_DVDD1V8': { voltage: dvdd1p8, static: 0, dynamic: 0 },
103+
'SOC_DVDD3V3': { voltage: dvdd3p3, static: 0, dynamic: 0 }
104+
};
105+
106+
const normTemp = (temp + 40) / 165;
107+
const tempStaticFactor = 1 + (Math.pow(normTemp, 2) * 2.5);
108+
const tempDynamicFactor = 1 + (normTemp * 0.1);
109+
const cornerStaticFactor = isStrong ? 1.4 : 1.0;
110+
const marginFactor = 1 + leakageMargin;
111+
112+
const vRatioCore = vddCore / 0.75;
113+
const vFactorDynamicCore = Math.pow(vRatioCore, 2);
114+
115+
const vRatioVddar = vddarCore / 0.85;
116+
const vFactorDynamicVddar = Math.pow(vRatioVddar, 2);
117+
118+
const socdb = window.TI_AM62X_SOCDB || {};
119+
const mapping = window.TI_AM62X_PET_MAPPING || {};
120+
121+
for (const [key, chip] of Object.entries(socdb)) {
122+
let usage = 0.0;
123+
let proxyScale = 1.0;
124+
125+
const mapData = mapping[key];
126+
if (mapData) {
127+
if (mapData.utilization_ref) {
128+
if (config[mapData.utilization_ref] !== undefined) {
129+
usage = parseFloat(config[mapData.utilization_ref]);
130+
} else if (mapData.utilization_ref.includes('Summary!')) {
131+
usage = 100.0;
132+
}
133+
}
134+
135+
if (mapData.mode_ref && config[mapData.mode_ref]) {
136+
const modeVal = config[mapData.mode_ref];
137+
let f = parseFloat(modeVal);
138+
if (isNaN(f)) {
139+
const match = String(modeVal).match(/(\d+)/g);
140+
if (match) f = parseInt(match[match.length - 1]);
141+
}
142+
if (f && f > 0) {
143+
proxyScale = Math.min(Math.max((f / 1000), 0.5), 1.5);
144+
}
145+
}
146+
}
147+
148+
const utilRatio = (isNaN(usage) ? 0 : usage / 100.0) * proxyScale;
149+
150+
// 1. Static Power (Leakage)
151+
// Attributes base leakage to VDD_CORE, and vdda/vddr to their respective rails
152+
const chipBaseStatic = chip.base_lkg_mw * chip.qty * tempStaticFactor * cornerStaticFactor * marginFactor;
153+
const chipVddaStatic = chip.vdda_lkg_mw * chip.qty * tempStaticFactor * cornerStaticFactor * marginFactor;
154+
const chipVddrStatic = chip.vddr_lkg_mw * chip.qty * tempStaticFactor * cornerStaticFactor * marginFactor;
155+
156+
// 2. Dynamic Power
157+
// Attributes base specific power to VDD_CORE (or VDDAR_CORE if core subchip)
158+
const isCoreSubchip = chip.vdd_domain === "VDD_CORE" || chip.vdd_domain === "VDD_Core";
159+
const vFactorCore = isCoreSubchip ? vFactorDynamicCore : 1.0;
160+
const chipBaseDynamic = chip.base_dyn_mw * chip.qty * utilRatio * tempDynamicFactor * vFactorCore;
161+
162+
// vdda dynamic often scales with VDDAR_CORE if it's a core-related analog block
163+
const vFactorVddar = isCoreSubchip ? vFactorDynamicVddar : 1.0;
164+
const chipVddaDynamic = chip.vdda_dyn_mw * chip.qty * utilRatio * tempDynamicFactor * vFactorVddar;
165+
166+
finalStatic += (chipBaseStatic + chipVddaStatic + chipVddrStatic);
167+
finalDynamic += (chipBaseDynamic + chipVddaDynamic);
168+
169+
// Per-rail aggregation
170+
railPower['VDD_CORE'].static += chipBaseStatic;
171+
railPower['VDD_CORE'].dynamic += chipBaseDynamic;
172+
173+
railPower['VDDA_1V8'].static += chipVddaStatic; // All subchip vdda leakage contributes to VDDA_1V8
174+
175+
if (isCoreSubchip) {
176+
// VDDAR_CORE scales with core voltage and handles core-related analog dynamic
177+
railPower['VDDAR_CORE'].dynamic += chipVddaDynamic;
178+
} else {
179+
// All other analog dynamic power goes to the fixed VDDA_1V8 rail
180+
railPower['VDDA_1V8'].dynamic += chipVddaDynamic;
181+
}
182+
183+
railPower['VDDS_DDR'].static += chipVddrStatic;
184+
185+
// Distribution for Small IO (Simplified for the six CSV rails)
186+
if (chip.type.includes('IO') || chip.function.includes('LVCMOS')) {
187+
railPower['SOC_DVDD3V3'].dynamic += chipBaseDynamic * 0.1; // Estimate
188+
railPower['SOC_DVDD1V8'].dynamic += chipBaseDynamic * 0.05;
189+
}
190+
191+
// Categorize for breakdown visualization
192+
if (isCoreSubchip) {
193+
breakdown['static_core'] += chipBaseStatic;
194+
} else {
195+
breakdown['static_io'] += chipBaseStatic + chipVddaStatic + chipVddrStatic;
196+
}
197+
198+
if (chip.type.includes('MPU') || chip.type.includes('CPU') || chip.function.includes('CPU')) {
199+
breakdown['dyn_cpu'] += chipBaseDynamic;
200+
} else if (chip.type.includes('GPU') || key.toLowerCase().includes('gpu')) {
201+
breakdown['dyn_gpu'] += chipBaseDynamic;
202+
} else if (chip.type.includes('IO') || chip.function.includes('IO')) {
203+
breakdown['dyn_io'] += chipBaseDynamic + chipVddaDynamic;
204+
} else {
205+
breakdown['dyn_other'] += chipBaseDynamic + chipVddaDynamic;
206+
}
207+
}
208+
209+
// Fallback for demo
210+
if (Object.keys(socdb).length === 0) {
211+
finalStatic = 250 * tempStaticFactor;
212+
finalDynamic = 1000 * tempDynamicFactor * vFactorDynamicCore;
213+
breakdown['static_core'] = finalStatic;
214+
breakdown['dyn_other'] = finalDynamic;
215+
railPower['VDD_CORE'].static = finalStatic;
216+
railPower['VDD_CORE'].dynamic = finalDynamic;
217+
}
218+
219+
const total = finalStatic + finalDynamic;
220+
221+
// Convert railPower object to an array for display
222+
const rails = Object.entries(railPower).map(([name, data]) => ({
223+
name,
224+
voltage: data.voltage,
225+
power: Math.round((data.static + data.dynamic) * 10) / 10
226+
}));
227+
228+
return {
229+
total: Math.round(total * 10) / 10,
230+
static: Math.round(finalStatic * 10) / 10,
231+
dynamic: Math.round(finalDynamic * 10) / 10,
232+
breakdown: [
233+
{ id: 'static_core', label: 'Core Leakage', value: Math.round(breakdown['static_core']), type: 'leakage' },
234+
{ id: 'static_io', label: 'I/O Leakage', value: Math.round(breakdown['static_io']), type: 'leakage' },
235+
{ id: 'dyn_cpu', label: 'CPU Dynamic', value: Math.round(breakdown['dyn_cpu']), type: 'dynamic' },
236+
{ id: 'dyn_gpu', label: 'GPU Dynamic', value: Math.round(breakdown['dyn_gpu']), type: 'dynamic' },
237+
{ id: 'dyn_io', label: 'I/O Dynamic', value: Math.round(breakdown['dyn_io']), type: 'dynamic' },
238+
{ id: 'dyn_other', label: 'Other Dynamic', value: Math.round(breakdown['dyn_other']), type: 'dynamic' }
239+
],
240+
rails: rails
241+
};
242+
}
243+
};
244+
245+
// Expose to global window object
246+
window.TI_SOC_DATA = window.TI_SOC_DATA || {};
247+
window.TI_SOC_DATA["am62x"] = AM62x_DATA;

0 commit comments

Comments
 (0)