diff --git a/backend/etc/devices/mpw1/acpu.json b/backend/etc/devices/mpw1/acpu.json index 1c836a74..922426db 100644 --- a/backend/etc/devices/mpw1/acpu.json +++ b/backend/etc/devices/mpw1/acpu.json @@ -5,5 +5,15 @@ { "name": "ACPU_LOW_LOAD_FACTOR" , "value": 6.22030740524698E-06 }, { "name": "ACPU_MEDIUM_LOAD_FACTOR", "value": 7.03786731129023E-06 }, { "name": "ACPU_HIGH_LOAD_FACTOR" , "value": 0.0000105978995482262 } + ], + "static_power": [ + { + "rail_type": "Vcc_core (A45)", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.00000000000008, -0.000000000004, 0.0000000004, 0.00000003, 0.000002, 0.00008], "factor": 1.0 }, + { "type": "typical", "coeffs": [0.000000000006, -0.000000000006, -0.000000005, 0.0000007, 0.00002], "factor": 1.0 } + ] + } ] } diff --git a/backend/etc/devices/mpw1/bcpu.json b/backend/etc/devices/mpw1/bcpu.json index 0e34fabf..6c37516a 100644 --- a/backend/etc/devices/mpw1/bcpu.json +++ b/backend/etc/devices/mpw1/bcpu.json @@ -5,5 +5,15 @@ { "name": "BCPU_LOW_LOAD_FACTOR" , "value": 6.22030740524698E-06 }, { "name": "BCPU_MEDIUM_LOAD_FACTOR", "value": 7.03786731129023E-06 }, { "name": "BCPU_HIGH_LOAD_FACTOR" , "value": 0.0000105978995482262 } + ], + "static_power": [ + { + "rail_type": "Vcc_core (Config)", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.0000000001, -0.000000002, 0.000000004, 0.00002, 0.0007], "factor": 1.0 }, + { "type": "typical", "coeffs": [0.0000000000005, -0.00000000002, 0.000000003, 0.0000002, 0.00001, 0.0013], "factor": 1.0 } + ] + } ] } diff --git a/backend/etc/devices/mpw1/bram.json b/backend/etc/devices/mpw1/bram.json index b7542838..5541cd89 100644 --- a/backend/etc/devices/mpw1/bram.json +++ b/backend/etc/devices/mpw1/bram.json @@ -5,5 +5,15 @@ { "name": "BRAM_WRITE_CAP", "value": 0.000002 }, { "name": "BRAM_READ_CAP" , "value": 0.0000025 }, { "name": "BRAM_FIFO_CAP" , "value": 0.0000007 } + ], + "static_power": [ + { + "rail_type": "Vcc_core (BRAM)", + "domain": "Core", + "scenarios": [ + { "type": "worse", "coeffs": [0.000000000001, -0.00000000003, 0.00000000006, 0.0000004, 0.00001], "factor": 1.0 }, + { "type": "typical", "coeffs": [0.000000000001, -0.00000000006, 0.0000000005, 0.0000002, 0.000003], "factor": 1.0 } + ] + } ] } diff --git a/backend/etc/devices/mpw1/ddr.json b/backend/etc/devices/mpw1/ddr.json index 42dbb2f2..0f22aca5 100644 --- a/backend/etc/devices/mpw1/ddr.json +++ b/backend/etc/devices/mpw1/ddr.json @@ -5,5 +5,23 @@ { "name": "DDR_ACLK_FACTOR" , "value": 0.0000688892039916618 }, { "name": "DDR_WRITE_FACTOR", "value": 0.0000421054185139638 }, { "name": "DDR_READ_FACTOR" , "value": 0.0000397024214264236 } + ], + "static_power": [ + { + "rail_type": "Vcc_core (Mem_SS)", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.0000000001, -0.000000003, 0.000000005, 0.00003, 0.0009], "factor": 1.0 }, + { "type": "typical", "coeffs": [0.0000000001, -0.000000006, 0.00000005, 0.00002, 0.0003], "factor": 1.0 } + ] + }, + { + "rail_type": "VCC_DDR_IO", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.000000000001, -0.00000000003, 0.00000000006, 0.0000003, 0.000009], "factor": 1.25 }, + { "type": "typical", "coeffs": [0.000000000001, -0.00000000006, 0.0000000005, 0.0000002, 0.000003], "factor": 1.25 } + ] + } ] } diff --git a/backend/etc/devices/mpw1/dsp.json b/backend/etc/devices/mpw1/dsp.json index a437ed0c..a73fdf55 100644 --- a/backend/etc/devices/mpw1/dsp.json +++ b/backend/etc/devices/mpw1/dsp.json @@ -4,5 +4,15 @@ { "name": "DSP_MULT_CAP" , "value": 0.0000015 }, { "name": "DSP_MULT_CAP2", "value": 0.00000007 }, { "name": "DSP_INT_CAP" , "value": 0.0000001 } + ], + "static_power": [ + { + "rail_type": "Vcc_core (DSP)", + "domain": "Core", + "scenarios": [ + { "type": "worse", "coeffs": [0.000000000002, -0.00000000004, 0.00000000008, 0.0000005, 0.00001], "factor": 1.0 }, + { "type": "typical", "coeffs": [0.000000000002, -0.00000000008, 0.0000000007, 0.0000003, 0.000004], "factor": 1.0 } + ] + } ] } diff --git a/backend/etc/devices/mpw1/fabric_le.json b/backend/etc/devices/mpw1/fabric_le.json index e535a1d0..5e201bb4 100644 --- a/backend/etc/devices/mpw1/fabric_le.json +++ b/backend/etc/devices/mpw1/fabric_le.json @@ -6,5 +6,15 @@ { "name": "FF_CLK_CAP" , "value": 2.91375291375291E-09 }, { "name": "LUT_INT_CAP", "value": 0.00000002 }, { "name": "FF_INT_CAP" , "value": 0.00000004 } + ], + "static_power": [ + { + "rail_type": "Vcc_core (CLB)", + "domain": "Core", + "scenarios": [ + { "type": "worse", "coeffs": [0.000000000000002, -0.0000000000001, 0.00000000001, 0.0000000008, 0.00000006, 0.000002], "factor": 1.0 }, + { "type": "typical", "coeffs": [0.0000000000003, -0.00000000001, 0.0000000001, 0.00000006, 0.0000007], "factor": 1.0 } + ] + } ] } diff --git a/backend/etc/devices/mpw1/gige.json b/backend/etc/devices/mpw1/gige.json index 309012e9..5c1945cc 100644 --- a/backend/etc/devices/mpw1/gige.json +++ b/backend/etc/devices/mpw1/gige.json @@ -4,5 +4,23 @@ { "name": "GIGE_CLK_FACTOR" , "value": 0.000124771586466165 }, { "name": "GIGE_SWITCHING_FACTOR", "value": 0.00504040314066422 }, { "name": "GIGE_IO_FACTOR" , "value": 0.000071487696 } + ], + "static_power": [ + { + "rail_type": "VCC_GIGE_IO", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.000000000001, -0.00000000003, 0.00000000006, 0.0000003, 0.000009], "factor": 1.25 }, + { "type": "typical", "coeffs": [0.000000000001, -0.00000000006, 0.0000000005, 0.0000002, 0.000003], "factor": 1.25 } + ] + }, + { + "rail_type": "VCC_GIGE_AUX", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.0000000008, 0.0000002, 0.00001, 0.007], "factor": 0.555555555555556 }, + { "type": "typical", "coeffs": [0.0000000008, 0.0000002, 0.00001, 0.007], "factor": 0.444444444444445 } + ] + } ] } diff --git a/backend/etc/devices/mpw1/gpio.json b/backend/etc/devices/mpw1/gpio.json index 5f45726a..8a87b00d 100644 --- a/backend/etc/devices/mpw1/gpio.json +++ b/backend/etc/devices/mpw1/gpio.json @@ -4,5 +4,39 @@ { "name": "GPIO_CLK_FACTOR" , "value": 0.0000773683364661654 }, { "name": "GPIO_SWITCHING_FACTOR", "value": 5.89015486234265E-06 }, { "name": "GPIO_IO_FACTOR" , "value": 0.0000001688475 } + ], + "static_power": [ + { + "rail_type": "VCC_BOOT_IO", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.000000000001, -0.00000000003, 0.00000000006, 0.0000003, 0.000009], "factor": 1.25 }, + { "type": "typical", "coeffs": [0.000000000001, -0.00000000006, 0.0000000005, 0.0000002, 0.000003], "factor": 1.25 } + ] + }, + { + "rail_type": "VCC_SOC_IO", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.000000000001, -0.00000000003, 0.00000000006, 0.0000003, 0.000009], "factor": 1.25 }, + { "type": "typical", "coeffs": [0.000000000001, -0.00000000006, 0.0000000005, 0.0000002, 0.000003], "factor": 1.25 } + ] + }, + { + "rail_type": "VCC_BOOT_AUX", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.0000000008, 0.0000002, 0.00001, 0.007], "factor": 0.555555555555556 }, + { "type": "typical", "coeffs": [0.0000000008, 0.0000002, 0.00001, 0.007], "factor": 0.44444444444445 } + ] + }, + { + "rail_type": "VCC_SOC_AUX", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.0000000008, 0.0000002, 0.00001, 0.007], "factor": 0.555555555555556 }, + { "type": "typical", "coeffs": [0.0000000008, 0.0000002, 0.00001, 0.007], "factor": 0.44444444444445 } + ] + } ] } diff --git a/backend/etc/devices/mpw1/noc.json b/backend/etc/devices/mpw1/noc.json index 6b3762ec..d7e7f2c7 100644 --- a/backend/etc/devices/mpw1/noc.json +++ b/backend/etc/devices/mpw1/noc.json @@ -58,5 +58,15 @@ { "name": "dma.ocm", "value": 4.64649E-06 }, { "name": "dma.ocm", "value": 4.74549E-06 }, { "name": "dma.ocm", "value": 4.69132E-06 } + ], + "static_power": [ + { + "rail_type": "Vcc_core (NOC)", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.00000000005, -0.000000001, 0.000000002, 0.00001, 0.0003], "factor": 1.0 }, + { "type": "typical", "coeffs": [0.00000000003, -0.000000001, 0.00000001, 0.000005, 0.00006], "factor": 1.0 } + ] + } ] } diff --git a/backend/etc/devices/mpw1/power_data.json b/backend/etc/devices/mpw1/power_data.json index 4b7b4211..1d9f13eb 100644 --- a/backend/etc/devices/mpw1/power_data.json +++ b/backend/etc/devices/mpw1/power_data.json @@ -1,7 +1,4 @@ { - "static": { - "$ref": "static_power_data.json" - }, "components": [ { "$ref": "clocking.json" }, { "$ref": "dsp.json" }, @@ -21,6 +18,8 @@ { "$ref": "sram.json" }, { "$ref": "pwm.json" }, { "$ref": "noc.json" }, + { "$ref": "puffcc.json" }, + { "$ref": "rc_osc.json" }, { "$ref": "regulator.json" } ] } diff --git a/backend/etc/devices/mpw1/puffcc.json b/backend/etc/devices/mpw1/puffcc.json new file mode 100644 index 00000000..61598691 --- /dev/null +++ b/backend/etc/devices/mpw1/puffcc.json @@ -0,0 +1,13 @@ +{ + "type": "puffcc", + "static_power": [ + { + "rail_type": "VCC_PUF", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.001], "factor": 0.555555555555556 }, + { "type": "typical", "coeffs": [0.0005], "factor": 0.555555555555556 } + ] + } + ] +} diff --git a/backend/etc/devices/mpw1/rc_osc.json b/backend/etc/devices/mpw1/rc_osc.json new file mode 100644 index 00000000..03a14d06 --- /dev/null +++ b/backend/etc/devices/mpw1/rc_osc.json @@ -0,0 +1,13 @@ +{ + "type": "rc_osc", + "static_power": [ + { + "rail_type": "VCC_RC_OSC", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.0005], "factor": 0.555555555555556 }, + { "type": "typical", "coeffs": [0.0001], "factor": 0.555555555555556 } + ] + } + ] +} diff --git a/backend/etc/devices/mpw1/regulator.json b/backend/etc/devices/mpw1/regulator.json index 008d27ca..77c38cd5 100644 --- a/backend/etc/devices/mpw1/regulator.json +++ b/backend/etc/devices/mpw1/regulator.json @@ -4,15 +4,15 @@ { "name": "VCC_CORE" , "value": 0.8 }, { "name": "VCC_AUX" , "value": 1.8 }, { "name": "VCC_BOOT_IO" , "value": 1.8 }, - { "name": "VCC_DDR_IO" , "value": 0.0 }, + { "name": "VCC_DDR_IO" , "value": 0.8 }, { "name": "VCC_SOC_IO" , "value": 1.8 }, - { "name": "VCC_GBE_IO" , "value": 0.0 }, - { "name": "VCC_USB_IO" , "value": 0.0 }, + { "name": "VCC_GBE_IO" , "value": 0.8 }, + { "name": "VCC_USB_IO" , "value": 0.8 }, { "name": "VCC_BOOT_AUX", "value": 1.8 }, { "name": "VCC_SOC_AUX" , "value": 1.8 }, - { "name": "VCC_GBE_AUX" , "value": 0.0 }, - { "name": "VCC_USB_AUX" , "value": 0.0 }, + { "name": "VCC_GBE_AUX" , "value": 1.8 }, + { "name": "VCC_USB_AUX" , "value": 1.8 }, { "name": "VCC_PUF" , "value": 1.8 }, - { "name": "VCC_RC_OSC" , "value": 0.0 } + { "name": "VCC_RC_OSC" , "value": 1.8 } ] } diff --git a/backend/etc/devices/mpw1/usb2.json b/backend/etc/devices/mpw1/usb2.json index b5e129a1..b0e86797 100644 --- a/backend/etc/devices/mpw1/usb2.json +++ b/backend/etc/devices/mpw1/usb2.json @@ -4,5 +4,23 @@ { "name": "USB2_CLK_FACTOR" , "value": 0.0000261772947994987 }, { "name": "USB2_SWITCHING_FACTOR", "value": 0.0000440759304744493 }, { "name": "USB2_IO_FACTOR" , "value": 0.00166056666666667 } + ], + "static_power": [ + { + "rail_type": "VCC_USB_IO", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.000000000001, -0.00000000003, 0.00000000006, 0.0000003, 0.000009], "factor": 1.25 }, + { "type": "typical", "coeffs": [0.000000000001, -0.00000000006, 0.0000000005, 0.0000002, 0.000003], "factor": 1.25 } + ] + }, + { + "rail_type": "VCC_USB_AUX", + "domain": "SOC", + "scenarios": [ + { "type": "worse", "coeffs": [0.0000000008, 0.0000002, 0.00001, 0.007], "factor": 0.555555555555556 }, + { "type": "typical", "coeffs": [0.000000001, 0.0000002, 0.00021, 0.0003], "factor": 0.555555555555556 } + ] + } ] } diff --git a/backend/submodule/bram.py b/backend/submodule/bram.py index ff285405..25a3c8f2 100644 --- a/backend/submodule/bram.py +++ b/backend/submodule/bram.py @@ -4,9 +4,12 @@ # from dataclasses import dataclass, field from typing import List +import numpy as np from utilities.common_utils import RsEnum, update_attributes -from .rs_device_resources import BramNotFoundException +from .rs_power_config import ElementType, PowerValue, ScenarioType +from .rs_device_resources import BramNotFoundException, RsDeviceResources from .rs_message import RsMessage, RsMessageManager +from .rs_logger import RsLogLevel, log class BRAM_Type(RsEnum): BRAM_18K_SDP = 0, "18k SDP" @@ -175,7 +178,7 @@ def compute_dynamic_power(self, clock_a, clock_b, WRITE_CAP, READ_CAP, INT_CAP, class BRAM_SubModule: - def __init__(self, resources, itemlist: List[BRAM] = None): + def __init__(self, resources: RsDeviceResources, itemlist: List[BRAM] = None): self.resources = resources self.total_18k_bram_available = resources.get_num_18K_BRAM() self.total_36k_bram_available = resources.get_num_36K_BRAM() @@ -249,3 +252,26 @@ def compute_output_power(self): total_power = self.total_block_power + self.total_interconnect_power for item in self.itemlist: item.compute_percentage(total_power) + + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> float: + NUM_36K_BRAM = self.resources.get_num_36K_BRAM() + mylist = [] + + for rail_type, scene_list in self.resources.powercfg.get_polynomial(ElementType.BRAM, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * s.factor + power = power * NUM_36K_BRAM + total_power += power + # debug info + log(f'[BRAM] {rail_type = }', RsLogLevel.DEBUG) + log(f'[BRAM] {temperature = }', RsLogLevel.DEBUG) + log(f'[BRAM] {scenario = }', RsLogLevel.DEBUG) + log(f'[BRAM] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[BRAM] {s.factor = }', RsLogLevel.DEBUG) + log(f'[BRAM] {NUM_36K_BRAM = }', RsLogLevel.DEBUG) + log(f'[BRAM] {power = }', RsLogLevel.DEBUG) + log(f'[BRAM] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist diff --git a/backend/submodule/dsp.py b/backend/submodule/dsp.py index d3288846..818e36d2 100644 --- a/backend/submodule/dsp.py +++ b/backend/submodule/dsp.py @@ -2,11 +2,14 @@ # Copyright (C) 2024 RapidSilicon # Authorized use only # +import numpy as np from dataclasses import dataclass, field from typing import List from utilities.common_utils import RsEnum, update_attributes -from .rs_device_resources import DspNotFoundException +from .rs_device_resources import DspNotFoundException, RsDeviceResources from .rs_message import RsMessage, RsMessageManager +from .rs_power_config import ElementType, PowerValue, ScenarioType +from .rs_logger import RsLogLevel, log class Pipelining(RsEnum): INPUT_AND_OUTPUT = 0, "Input and Output" @@ -103,7 +106,7 @@ def compute_dynamic_power(self, clock, VCC_CORE, DSP_MULT_CAP, DSP_MULT_CAP2, DS class DSP_SubModule: - def __init__(self, resources, itemlist: List[DSP] = None): + def __init__(self, resources: RsDeviceResources, itemlist: List[DSP] = None): self.resources = resources self.total_dsp_blocks_available = resources.get_num_DSP_BLOCKs() self.total_interconnect_power = 0.0 @@ -173,3 +176,26 @@ def compute_output_power(self): total_power = self.total_block_power + self.total_interconnect_power for item in self.itemlist: item.compute_percentage(total_power) + + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + DSP_BlOCKS = self.resources.get_num_DSP_BLOCKs() + mylist = [] + + for rail_type, scene_list in self.resources.powercfg.get_polynomial(ElementType.DSP, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * s.factor + power = power * DSP_BlOCKS + total_power += power + # debug info + log(f'[DSP] {rail_type = }', RsLogLevel.DEBUG) + log(f'[DSP] {temperature = }', RsLogLevel.DEBUG) + log(f'[DSP] {scenario = }', RsLogLevel.DEBUG) + log(f'[DSP] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[DSP] {s.factor = }', RsLogLevel.DEBUG) + log(f'[DSP] {DSP_BlOCKS = }', RsLogLevel.DEBUG) + log(f'[DSP] {power = }', RsLogLevel.DEBUG) + log(f'[DSP] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist diff --git a/backend/submodule/fabric_logic_element.py b/backend/submodule/fabric_logic_element.py index 6ae23d58..f14a3122 100644 --- a/backend/submodule/fabric_logic_element.py +++ b/backend/submodule/fabric_logic_element.py @@ -2,11 +2,14 @@ # Copyright (C) 2024 RapidSilicon # Authorized use only # +import numpy as np from dataclasses import dataclass, field -from typing import List +from typing import Dict, List from utilities.common_utils import RsEnum, update_attributes -from .rs_device_resources import FabricLeNotFoundException, FabricLeDescriptionAlreadyExistsException +from .rs_device_resources import FabricLeNotFoundException, FabricLeDescriptionAlreadyExistsException, RsDeviceResources from .rs_message import RsMessage, RsMessageManager +from .rs_power_config import ElementType, ScenarioType, PowerValue +from .rs_logger import RsLogLevel, log class Glitch_Factor(RsEnum): TYPICAL = 0, "Typical" @@ -91,7 +94,7 @@ def compute_dynamic_power(self, clock, VCC_CORE, LUT_CAP, FF_CAP, FF_CLK_CAP, LU class Fabric_LE_SubModule: - def __init__(self, resources, itemlist: List[Fabric_LE] = None): + def __init__(self, resources: RsDeviceResources, itemlist: List[Fabric_LE] = None): self.resources = resources self.total_lut6_available = resources.get_num_LUTs() self.total_flipflop_available = resources.get_num_FFs() @@ -168,3 +171,26 @@ def compute_output_power(self): total_power = self.total_block_power + self.total_interconnect_power for item in self.itemlist: item.compute_percentage(total_power) + + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + NUM_CLB = self.resources.get_num_CLBs() + mylist = [] + + for rail_type, scene_list in self.resources.powercfg.get_polynomial(ElementType.FABRIC_LE, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * s.factor + power = power * NUM_CLB + total_power += power + # debug info + log(f'[FLE] {rail_type = }', RsLogLevel.DEBUG) + log(f'[FLE] {temperature = }', RsLogLevel.DEBUG) + log(f'[FLE] {scenario = }', RsLogLevel.DEBUG) + log(f'[FLE] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[FLE] {s.factor = }', RsLogLevel.DEBUG) + log(f'[FLE] {NUM_CLB = }', RsLogLevel.DEBUG) + log(f'[FLE] {power = }', RsLogLevel.DEBUG) + log(f'[FLE] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist diff --git a/backend/submodule/peripherals.py b/backend/submodule/peripherals.py index 692d2bdd..c564fda8 100644 --- a/backend/submodule/peripherals.py +++ b/backend/submodule/peripherals.py @@ -2,12 +2,15 @@ # Copyright (C) 2024 RapidSilicon # Authorized use only # +import math +import numpy as np from abc import ABC, abstractmethod from dataclasses import dataclass, field from enum import IntFlag from typing import Any, List, Dict, Tuple from utilities.common_utils import RsEnum, update_attributes from .rs_device_resources import IO_Standard, IO_Standard_Coeff, ModuleType, PeripheralPortNotFoundException, RsDeviceResources, PeripheralNotFoundException, PeripheralType +from .rs_power_config import ElementType, PowerValue, ScenarioType from .rs_message import RsMessage, RsMessageManager from .rs_logger import log, RsLogLevel @@ -185,30 +188,7 @@ class Peripheral_SubModule(SubModule): def __init__(self, resources : RsDeviceResources): self.resources = resources - - # for debugging usage - # self.peripherals : List[Peripheral] = [ - # Peripheral(name='SPI/QSPI', type=PeripheralType.SPI, usage=Peripherals_Usage.Boot, targets=PeripheralTarget.ACPU | PeripheralTarget.BCPU | PeripheralTarget.FABRIC | PeripheralTarget.DMA, context=self), - # Peripheral(name='JTAG', type=PeripheralType.JTAG, usage=Peripherals_Usage.Debug, targets=PeripheralTarget.ACPU | PeripheralTarget.BCPU, context=self), - # Peripheral(name='I2C', type=PeripheralType.I2C, usage=Peripherals_Usage.App, targets=PeripheralTarget.ACPU | PeripheralTarget.FABRIC | PeripheralTarget.DMA, context=self), - # Peripheral(name='UART0 (BCPU)', type=PeripheralType.UART, index=0, usage=Peripherals_Usage.Debug, targets=PeripheralTarget.BCPU, context=self), - # Peripheral(name='UART1 (ACPU)', type=PeripheralType.UART, index=1, usage=Peripherals_Usage.Debug, targets=PeripheralTarget.ACPU, context=self), - # Peripheral(name='USB 2.0', type=PeripheralType.USB2, usage=Peripherals_Usage.App, targets=PeripheralTarget.ACPU | PeripheralTarget.FABRIC, context=self), - # Peripheral(name='GigE', type=PeripheralType.GIGE, usage=Peripherals_Usage.App, targets=PeripheralTarget.ACPU | PeripheralTarget.FABRIC, context=self), - # Peripheral(name="GPIO (BCPU)", type=PeripheralType.GPIO, index=0, usage=Peripherals_Usage.App, targets=PeripheralTarget.BCPU, enable=True, context=self), - # Peripheral(name="GPIO (ACPU)", type=PeripheralType.GPIO, index=1, usage=Peripherals_Usage.App, targets=PeripheralTarget.ACPU, enable=True, context=self), - # Peripheral(name="GPIO (Fabric)", type=PeripheralType.GPIO, index=2, usage=Peripherals_Usage.App, targets=PeripheralTarget.FABRIC, enable=True, context=self), - # Peripheral(name="PWM", type=PeripheralType.PWM, usage=Peripherals_Usage.App, enable=True, context=self), - # Peripheral(name="DDR", type=PeripheralType.DDR, index=0, usage=Peripherals_Usage.App, targets=PeripheralTarget.ACPU | PeripheralTarget.BCPU | PeripheralTarget.FABRIC | PeripheralTarget.DMA, enable=False, context=self, init_props={ "data_rate" : 1333000000, "memory_type" : Memory_Type.DDR4 }), - # Peripheral(name="OCM", type=PeripheralType.OCM, index=1, usage=Peripherals_Usage.App, targets=PeripheralTarget.ACPU | PeripheralTarget.BCPU | PeripheralTarget.FABRIC | PeripheralTarget.DMA, enable=False, context=self, init_props={ "data_rate" : 533000000, "memory_type" : Memory_Type.SRAM }), - # Peripheral(name='DMA', type=PeripheralType.DMA, enable=True, max_ports=4, context=self), - # Peripheral(name='N22 RISC-V', type=PeripheralType.BCPU, enable=True, max_ports=4, context=self), - # Peripheral(name='A45 RISC-V', type=PeripheralType.ACPU, enable=True, max_ports=4, context=self, init_props={ 'frequency' : 533000000 }), - # Peripheral(name='Fabric', type=PeripheralType.FPGA_COMPLEX, enable=True, targets=PeripheralTarget.DMA, max_ports=4, context=self), - # ] - self.peripherals : List[Peripheral] = self.initialize_peripherals() - # todo: total io available should be populated from device xml self.total_io_available = 40 self.total_io_used = 0 @@ -221,7 +201,7 @@ def __init__(self, resources : RsDeviceResources): self.total_dma_block_power = 0.0 def initialize_peripherals(self) -> List['Peripheral']: - # add peripherals based onthe configuration in device.xml + # add peripherals based on the configuration in device.xml peripherals: List['Peripheral'] = [] peripherals += self.create_peripherals(1, 'SPI/QSPI', PeripheralType.SPI) peripherals += self.create_peripherals(self.resources.get_num_I2Cs(), 'I2C', PeripheralType.I2C) @@ -235,7 +215,10 @@ def initialize_peripherals(self) -> List['Peripheral']: peripherals += self.create_peripherals(self.resources.get_num_DMAs(), 'DMA', PeripheralType.DMA) peripherals += self.create_peripherals(1, 'N22 RISC-V', PeripheralType.BCPU) peripherals += self.create_peripherals(1, 'Fabric', PeripheralType.FPGA_COMPLEX) - # todo: add GPIO + peripherals += self.create_peripherals(1, 'GPIO', PeripheralType.GPIO) + peripherals += self.create_peripherals(1, 'PUFFcc', PeripheralType.PUFFCC) + peripherals += self.create_peripherals(1, 'RC Oscillator', PeripheralType.RC_OSC) + peripherals += self.create_peripherals(1, 'NOC', PeripheralType.NOC) # add application processor for Gemini if self.resources.get_series() == 'Gemini': @@ -443,6 +426,9 @@ def set_properties(self, props: Dict[str, Any]) -> None: def compute(self) -> bool: return False + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + return [] + @classmethod def get_compute_object(cls, type: PeripheralType, context: IPeripheral) -> 'ComputeObject': if type == PeripheralType.UART: @@ -472,6 +458,12 @@ def get_compute_object(cls, type: PeripheralType, context: IPeripheral) -> 'Comp return FPGA_Fabric(context=context) elif type == PeripheralType.DMA: return Dma0(context=context) + elif type == PeripheralType.PUFFCC: + return Puffcc0(context=context) + elif type == PeripheralType.RC_OSC: + return RCOsc0(context=context) + elif type == PeripheralType.NOC: + return Noc0(context=context) return None @dataclass @@ -552,6 +544,9 @@ def set_targets(self, targets: PeripheralTarget) -> None: def compute(self) -> bool: return self.object.compute() + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + return self.object.compute_static_power(temperature, scenario) + @dataclass class common_output_: calculated_bandwidth: float = field(default=0.0) @@ -895,6 +890,27 @@ def compute(self) -> bool: self.output.block_power = block_power return True + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + resources = self.get_context().get_device_resources() + mylist = [] + + for rail_type, scene_list in resources.powercfg.get_polynomial(ElementType.ACPU, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * s.factor + total_power += power + # debug info + log(f'[ACPU] {rail_type = }', RsLogLevel.DEBUG) + log(f'[ACPU] {temperature = }', RsLogLevel.DEBUG) + log(f'[ACPU] {scenario = }', RsLogLevel.DEBUG) + log(f'[ACPU] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[ACPU] {s.factor = }', RsLogLevel.DEBUG) + log(f'[ACPU] {power = }', RsLogLevel.DEBUG) + log(f'[ACPU] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist + @dataclass class N22_RISC_V_BCPU(ComputeObject): @dataclass @@ -1025,6 +1041,27 @@ def compute(self) -> bool: self.output.boot_power = boot_power return True + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + resources = self.get_context().get_device_resources() + mylist = [] + + for rail_type, scene_list in resources.powercfg.get_polynomial(ElementType.BCPU, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * s.factor + total_power += power + # debug info + log(f'[BCPU] {rail_type = }', RsLogLevel.DEBUG) + log(f'[BCPU] {temperature = }', RsLogLevel.DEBUG) + log(f'[BCPU] {scenario = }', RsLogLevel.DEBUG) + log(f'[BCPU] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[BCPU] {s.factor = }', RsLogLevel.DEBUG) + log(f'[BCPU] {power = }', RsLogLevel.DEBUG) + log(f'[BCPU] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist + @dataclass class Memory0(ComputeObject): @dataclass @@ -1156,6 +1193,37 @@ def compute(self) -> bool: return True + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + if self.get_context().get_type() != PeripheralType.DDR: + return [] + + resources = self.get_context().get_device_resources() + VCC_DDR_IO = resources.get_VCC_DDR_IO() + DDR_IOS = resources.get_num_DDR_IOs() + mylist = [] + + for rail_type, scene_list in resources.powercfg.get_polynomial(ElementType.DDR, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * s.factor + if rail_type == 'VCC_DDR_IO': + power = power * VCC_DDR_IO * DDR_IOS / 2 + total_power += power + # debug info + log(f'[MEM0] {rail_type = }', RsLogLevel.DEBUG) + log(f'[MEM0] {temperature = }', RsLogLevel.DEBUG) + log(f'[MEM0] {scenario = }', RsLogLevel.DEBUG) + log(f'[MEM0] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[MEM0] {s.factor = }', RsLogLevel.DEBUG) + log(f'[MEM0] {self.get_context().get_type() = }', RsLogLevel.DEBUG) + log(f'[MEM0] {VCC_DDR_IO = }', RsLogLevel.DEBUG) + log(f'[MEM0] {DDR_IOS = }', RsLogLevel.DEBUG) + log(f'[MEM0] {power = }', RsLogLevel.DEBUG) + log(f'[MEM0] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist + @dataclass class Gpio0(ComputeObject): @dataclass @@ -1263,6 +1331,45 @@ def compute(self) -> bool: return True + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + resources = self.get_context().get_device_resources() + voltages = { + "VCC_BOOT_IO" : resources.get_VCC_BOOT_IO(), + "VCC_SOC_IO" : resources.get_VCC_SOC_IO(), + "VCC_BOOT_AUX": resources.get_VCC_BOOT_AUX(), + "VCC_SOC_AUX" : resources.get_VCC_SOC_AUX(), + } + BOOT_IOS = resources.get_num_BOOT_IOs() + SOC_IOS = resources.get_num_SOC_IOs() + ios = { + "VCC_BOOT_IO" : math.ceil(BOOT_IOS / 2), + "VCC_SOC_IO" : (SOC_IOS / 2), + "VCC_BOOT_AUX": (BOOT_IOS / 40), + "VCC_SOC_AUX" : (SOC_IOS / 40) + } + mylist = [] + + for rail_type, scene_list in resources.powercfg.get_polynomial(ElementType.GPIO, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * s.factor * voltages.get(rail_type, 0.0) * ios.get(rail_type, 0.0) + total_power += power + # debug info + log(f'[GPIO] {rail_type = }', RsLogLevel.DEBUG) + log(f'[GPIO] {temperature = }', RsLogLevel.DEBUG) + log(f'[GPIO] {scenario = }', RsLogLevel.DEBUG) + log(f'[GPIO] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[GPIO] {s.factor = }', RsLogLevel.DEBUG) + log(f'[GPIO] {BOOT_IOS = }', RsLogLevel.DEBUG) + log(f'[GPIO] {SOC_IOS = }', RsLogLevel.DEBUG) + log(f'[GPIO] {voltages = }', RsLogLevel.DEBUG) + log(f'[GPIO] {ios = }', RsLogLevel.DEBUG) + log(f'[GPIO] {power = }', RsLogLevel.DEBUG) + log(f'[GPIO] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist + @dataclass class Usb2_0(ComputeObject): @dataclass @@ -1367,6 +1474,39 @@ def compute(self) -> bool: return True + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + resources = self.get_context().get_device_resources() + voltages = { + "VCC_USB_IO" : resources.get_VCC_USB_IO(), + "VCC_USB_AUX": resources.get_VCC_USB_AUX() + } + USB_IOS = resources.get_num_USB_IOs() + ios = { + "VCC_USB_IO" : math.ceil(USB_IOS / 2), + "VCC_USB_AUX" : USB_IOS / 40 + } + mylist = [] + + for rail_type, scene_list in resources.powercfg.get_polynomial(ElementType.USB2, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * s.factor * voltages.get(rail_type, 0.0) * ios.get(rail_type, 0.0) + total_power += power + # debug info + log(f'[USB2] {rail_type = }', RsLogLevel.DEBUG) + log(f'[USB2] {temperature = }', RsLogLevel.DEBUG) + log(f'[USB2] {scenario = }', RsLogLevel.DEBUG) + log(f'[USB2] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[USB2] {s.factor = }', RsLogLevel.DEBUG) + log(f'[USB2] {USB_IOS = }', RsLogLevel.DEBUG) + log(f'[USB2] {voltages = }', RsLogLevel.DEBUG) + log(f'[USB2] {ios = }', RsLogLevel.DEBUG) + log(f'[USB2] {power = }', RsLogLevel.DEBUG) + log(f'[USB2] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist + @dataclass class GigE_0(ComputeObject): @dataclass @@ -1472,6 +1612,112 @@ def compute(self) -> bool: return True + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + resources = self.get_context().get_device_resources() + voltages = { + "VCC_GIGE_IO" : resources.get_VCC_GBE_IO(), + "VCC_GIGE_AUX": resources.get_VCC_GBE_AUX() + } + GIGE_IOS = resources.get_num_GIGE_IOs() + ios = { + "VCC_GIGE_IO" : GIGE_IOS / 2, + "VCC_GIGE_AUX": GIGE_IOS / 40 + } + mylist = [] + + for rail_type, scene_list in resources.powercfg.get_polynomial(ElementType.GIGE, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * s.factor * voltages.get(rail_type, 0.0) * ios.get(rail_type, 0.0) + total_power += power + # debug info + log(f'[GIGE] {rail_type = }', RsLogLevel.DEBUG) + log(f'[GIGE] {temperature = }', RsLogLevel.DEBUG) + log(f'[GIGE] {scenario = }', RsLogLevel.DEBUG) + log(f'[GIGE] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[GIGE] {s.factor = }', RsLogLevel.DEBUG) + log(f'[GIGE] {GIGE_IOS = }', RsLogLevel.DEBUG) + log(f'[GIGE] {voltages = }', RsLogLevel.DEBUG) + log(f'[GIGE] {ios = }', RsLogLevel.DEBUG) + log(f'[GIGE] {power = }', RsLogLevel.DEBUG) + log(f'[GIGE] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist + +@dataclass +class Puffcc0(ComputeObject): + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + resources = self.get_context().get_device_resources() + VCC_PUF = resources.get_VCC_PUF() + mylist = [] + + for rail_type, scene_list in resources.powercfg.get_polynomial(ElementType.PUFFCC, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * VCC_PUF * s.factor + total_power += power + # debug info + log(f'[PUFFCC] {rail_type = }', RsLogLevel.DEBUG) + log(f'[PUFFCC] {temperature = }', RsLogLevel.DEBUG) + log(f'[PUFFCC] {scenario = }', RsLogLevel.DEBUG) + log(f'[PUFFCC] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[PUFFCC] {s.factor = }', RsLogLevel.DEBUG) + log(f'[PUFFCC] {VCC_PUF = }', RsLogLevel.DEBUG) + log(f'[PUFFCC] {power = }', RsLogLevel.DEBUG) + log(f'[PUFFCC] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist + +@dataclass +class RCOsc0(ComputeObject): + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + resources = self.get_context().get_device_resources() + VCC_RC_OSC = resources.get_VCC_RC_OSC() + mylist = [] + + for rail_type, scene_list in resources.powercfg.get_polynomial(ElementType.RC_OSC, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * VCC_RC_OSC * s.factor + total_power += power + # debug info + log(f'[RC_OSC] {rail_type = }', RsLogLevel.DEBUG) + log(f'[RC_OSC] {temperature = }', RsLogLevel.DEBUG) + log(f'[RC_OSC] {scenario = }', RsLogLevel.DEBUG) + log(f'[RC_OSC] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[RC_OSC] {s.factor = }', RsLogLevel.DEBUG) + log(f'[RC_OSC] {VCC_RC_OSC = }', RsLogLevel.DEBUG) + log(f'[RC_OSC] {power = }', RsLogLevel.DEBUG) + log(f'[RC_OSC] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist + +@dataclass +class Noc0(ComputeObject): + def compute_static_power(self, temperature: float, scenario: ScenarioType) -> List[PowerValue]: + resources = self.get_context().get_device_resources() + mylist = [] + + for rail_type, scene_list in resources.powercfg.get_polynomial(ElementType.NOC, scenario): + total_power = 0.0 + for s in scene_list: + power = np.polyval(s.coeffs, temperature) * s.factor + total_power += power + # debug info + log(f'[NOC] {rail_type = }', RsLogLevel.DEBUG) + log(f'[NOC] {temperature = }', RsLogLevel.DEBUG) + log(f'[NOC] {scenario = }', RsLogLevel.DEBUG) + log(f'[NOC] {s.coeffs = }', RsLogLevel.DEBUG) + log(f'[NOC] {s.factor = }', RsLogLevel.DEBUG) + log(f'[NOC] {power = }', RsLogLevel.DEBUG) + log(f'[NOC] {total_power = }', RsLogLevel.DEBUG) + mylist.append(PowerValue(type=rail_type, value=total_power)) + + return mylist + @dataclass class I2c0(ComputeObject): @dataclass diff --git a/backend/submodule/rs_device.py b/backend/submodule/rs_device.py index 30d0cc36..ab8df260 100644 --- a/backend/submodule/rs_device.py +++ b/backend/submodule/rs_device.py @@ -5,12 +5,13 @@ import numpy as np import math from typing import List +from .rs_power_config import PowerValue, ScenarioType from .rs_device_resources import RsDeviceResources, ModuleType, IO_BankType -from .clock import Clock_SubModule, Clock -from .fabric_logic_element import Fabric_LE_SubModule, Fabric_LE -from .dsp import DSP_SubModule, DSP -from .bram import BRAM_SubModule, BRAM, BRAM_Type, PortProperties -from .io import IO_SubModule, IO +from .clock import Clock_SubModule +from .fabric_logic_element import Fabric_LE_SubModule +from .dsp import DSP_SubModule +from .bram import BRAM_SubModule +from .io import IO_SubModule from .peripherals import Peripheral_SubModule from utilities.common_utils import update_attributes from dataclasses import dataclass, field @@ -105,66 +106,21 @@ class Specification: @dataclass class StaticPowerResult(): - NOC: float = field(default=0.0) - Mem_SS: float = field(default=0.0) - A45: float = field(default=0.0) - Config: float = field(default=0.0) - CLB: float = field(default=0.0) - BRAM: float = field(default=0.0) - DSP: float = field(default=0.0) - Gearbox_HP: float = field(default=0.0) - Gearbox_HR: float = field(default=0.0) - HP_IO: float = field(default=0.0) - HR_IO: float = field(default=0.0) - Aux: float = field(default=0.0) - HP_Aux: float = field(default=0.0) - HR_Aux: float = field(default=0.0) - HR_IO_1_8V: float = field(default=0.0) - HR_IO_2_5V: float = field(default=0.0) - HR_IO_3_3V: float = field(default=0.0) - HP_IO_1_2V: float = field(default=0.0) - HP_IO_1_5V: float = field(default=0.0) - HP_IO_1_8V: float = field(default=0.0) - VCC_BOOT_IO: float = field(default=0.0) - VCC_DDR_IO: float = field(default=0.0) - VCC_SOC_IO: float = field(default=0.0) - VCC_GIGE_IO: float = field(default=0.0) - VCC_USB_IO: float = field(default=0.0) - VCC_BOOT_AUX: float = field(default=0.0) - VCC_SOC_AUX: float = field(default=0.0) - VCC_GIGE_AUX: float = field(default=0.0) - VCC_USB_AUX: float = field(default=0.0) - VCC_RC_OSC: float = field(default=0.0) - VCC_PUF: float = field(default=0.0) - temperature: float = field(default=0.0) + powers: List[PowerValue] = field(default_factory=list) next_temperature: float = field(default=0.0) + temperature: float = field(default=0.0) + + def add(self, powers: List[PowerValue]) -> None: + self.powers.extend(powers) def get_total_power(self) -> float: - total = 0.0 - for key, value in self.__dict__.items(): - if key == 'temperature' or key == 'next_temperature': - continue - total += value - return total + return sum([x.value for x in self.powers]) def get_processing_total_power(self) -> float: - total = 0.0 - total += self.NOC - total += self.Mem_SS - total += self.A45 - total += self.Config - total += self.VCC_BOOT_IO - total += self.VCC_DDR_IO - total += self.VCC_SOC_IO - total += self.VCC_GIGE_IO - total += self.VCC_USB_IO - total += self.VCC_BOOT_AUX - total += self.VCC_SOC_AUX - total += self.VCC_GIGE_AUX - total += self.VCC_USB_AUX - total += self.VCC_RC_OSC - total += self.VCC_PUF - return total + return sum([x.value for x in self.powers if x.type in [ + 'Vcc_core (NOC)', 'Vcc_core (Mem_SS)', 'Vcc_core (A45)', 'Vcc_core (Config)', 'VCC_BOOT_IO', 'VCC_DDR_IO', 'VCC_SOC_IO', + 'VCC_GIGE_IO', 'VCC_USB_IO', 'VCC_BOOT_AUX', 'VCC_SOC_AUX', 'VCC_GIGE_AUX', 'VCC_USB_AUX', 'VCC_RC_OSC', 'VCC_PUF' + ]]) def get_fpga_total_power(self) -> float: return self.get_total_power() - self.get_processing_total_power() @@ -204,34 +160,19 @@ def __init__(self, device): self.static_power_output = [StaticPowerResult(), StaticPowerResult()] # fabric logic element module - self.resources.register_module(ModuleType.FABRIC_LE, Fabric_LE_SubModule(self.resources, [ - # Fabric_LE(enable=True, clock='CLK_100', name='Test 1', lut6=20, flip_flop=50), - # Fabric_LE(enable=True, clock='CLK_233', name='Test 2', lut6=10, flip_flop=30) - ])) + self.resources.register_module(ModuleType.FABRIC_LE, Fabric_LE_SubModule(self.resources, [])) # dsp module - self.resources.register_module(ModuleType.DSP, DSP_SubModule(self.resources, [ - # DSP(number_of_multipliers=11, enable=True, name="test test 1", clock='CLK_100'), - # DSP(number_of_multipliers=12, enable=True, name="test test 2", clock='CLK_233') - ])) + self.resources.register_module(ModuleType.DSP, DSP_SubModule(self.resources, [])) # bram module - self.resources.register_module(ModuleType.BRAM, BRAM_SubModule(self.resources, [ - # BRAM(name="test 1", bram_used=16, enable=True, type=BRAM_Type.BRAM_18k_TDP, port_a=PortProperties(clock='CLK_100'), port_b=PortProperties(clock='CLK_233')), - # BRAM(name="test 2", bram_used=17, enable=True, type=BRAM_Type.BRAM_18k_TDP) - ])) + self.resources.register_module(ModuleType.BRAM, BRAM_SubModule(self.resources, [])) # io module - self.resources.register_module(ModuleType.IO, IO_SubModule(self.resources, [ - # IO(name="test 1", clock="CLK_100", enable=True), - # IO(name="test 2", clock="CLK_233") - ])) + self.resources.register_module(ModuleType.IO, IO_SubModule(self.resources, [])) # clocking module - self.resources.register_module(ModuleType.CLOCKING, Clock_SubModule(self.resources, [ - # Clock(True, "Default Clock", port="CLK_100", frequency=100000000), - # Clock(True, "PLL Clock", port="CLK_233", frequency=233000000) - ])) + self.resources.register_module(ModuleType.CLOCKING, Clock_SubModule(self.resources, [])) # soc peripherals module self.resources.register_module(ModuleType.SOC_PERIPHERALS, Peripheral_SubModule(self.resources)) @@ -359,50 +300,6 @@ def calculate(self, temperature : float, coeffs : List[List[float]], factor : fl total += values[0] return total * factor - def compute_NOC(self, temperature : float, worsecase : bool) -> float: - # todo: not all device has NOC - divfactor, coeff = self.resources.get_divfactor_coeff_NOC(worsecase) - power = self.calculate(temperature, coeff) - return power - - def compute_Mem_SS(self, temperature : float, worsecase : bool) -> float: - # todo: not all device has Mem - divfactor, coeff = self.resources.get_divfactor_coeff_Mem_SS(worsecase) - power = self.calculate(temperature, coeff) - return power - - def compute_A45(self, temperature : float, worsecase : bool) -> float: - # todo: not all device has ACPU - divfactor, coeff = self.resources.get_divfactor_coeff_A45(worsecase) - power = self.calculate(temperature, coeff) - return power - - def compute_Config(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_Config(worsecase) - power = self.calculate(temperature, coeff) - return power - - def compute_CLB(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_CLB(worsecase) - power = self.calculate(temperature, coeff) - num_clbs = self.resources.get_num_CLBs() - total_power = num_clbs * power - return total_power - - def compute_BRAM(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_BRAM(worsecase) - power = self.calculate(temperature, coeff) - num_brams = self.resources.get_num_36K_BRAM() - total_power = num_brams * power - return total_power - - def compute_DSP(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_DSP(worsecase) - power = self.calculate(temperature, coeff) - num_dsps = self.resources.get_num_DSP_BLOCKs() - total_power = num_dsps * power - return total_power - def compute_Gearbox_IO_bank_type(self, temperature : float, bank_type : IO_BankType, worsecase : bool) -> float: divfactor, coeff = self.resources.get_divfactor_coeff_GEARBOX_IO_bank_type(bank_type.value, worsecase) power = self.calculate(temperature, coeff) @@ -436,95 +333,16 @@ def compute_IO_bank_type_voltage(self, temperature : float, bank_type : IO_BankT total_power = power * num_io_banks_used * 20 * voltage / divfactor return total_power - def compute_VCC_BOOT_IO(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_BOOT_IO(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_BOOT_IO() / divfactor) - num_boot_ios = self.resources.get_num_BOOT_IOs() - total_power = power * math.ceil(num_boot_ios / 2) - return total_power - - def compute_VCC_DDR_IO(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_DDR_IO(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_DDR_IO() / divfactor) - num_ddr_ios = self.resources.get_num_DDR_IOs() - total_power = power * (num_ddr_ios / 2) - return total_power - - def compute_VCC_SOC_IO(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_SOC_IO(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_SOC_IO() / divfactor) - num_soc_ios = self.resources.get_num_SOC_IOs() - total_power = power * (num_soc_ios / 2) - return total_power - - def compute_VCC_GIGE_IO(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_GIGE_IO(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_GBE_IO() / divfactor) - num_gige_ios = self.resources.get_num_GIGE_IOs() - total_power = power * (num_gige_ios / 2) - return total_power - - def compute_VCC_USB_IO(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_USB_IO(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_USB_IO() / divfactor) - num_usb_ios = self.resources.get_num_USB_IOs() - total_power = power * math.ceil(num_usb_ios / 2) - return total_power - - def compute_VCC_BOOT_AUX(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_BOOT_AUX(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_BOOT_AUX() / divfactor) - num_boot_ios = self.resources.get_num_BOOT_IOs() - total_power = power * (num_boot_ios / 40) - if worsecase == False: - total_power *= 0.8 - return total_power - - def compute_VCC_SOC_AUX(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_SOC_AUX(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_SOC_AUX() / divfactor) - num_soc_ios = self.resources.get_num_SOC_IOs() - total_power = power * (num_soc_ios / 40) - if worsecase == False: - total_power *= 0.8 - return total_power - - def compute_VCC_GIGE_AUX(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_GIGE_AUX(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_GBE_AUX() / divfactor) - num_gige_ios = self.resources.get_num_GIGE_IOs() - total_power = power * (num_gige_ios / 40) - if worsecase == False: - total_power *= 0.8 - return total_power - - def compute_VCC_USB_AUX(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_USB_AUX(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_USB_AUX() / divfactor) - num_usb_ios = self.resources.get_num_USB_IOs() - total_power = power * (num_usb_ios / 40) - return total_power - - def compute_VCC_RC_OSC(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_RC_OSC(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_RC_OSC() / divfactor) - return power - - def compute_VCC_PUF(self, temperature : float, worsecase : bool) -> float: - divfactor, coeff = self.resources.get_divfactor_coeff_VCC_PUF(worsecase) - power = self.calculate(temperature, coeff, self.resources.get_VCC_PUF() / divfactor) - return power - - def compute(self, temperature : float, worsecase : bool = True) -> StaticPowerResult: + def compute_OBSOLETE(self, temperature : float, worsecase : bool = True) -> StaticPowerResult: result = StaticPowerResult( temperature = temperature, - NOC = self.compute_NOC(temperature, worsecase), - Mem_SS = self.compute_Mem_SS(temperature, worsecase), - A45 = self.compute_A45(temperature, worsecase), - Config = self.compute_Config(temperature, worsecase), - CLB = self.compute_CLB(temperature, worsecase), - BRAM = self.compute_BRAM(temperature, worsecase), - DSP = self.compute_DSP(temperature, worsecase), + # NOC = self.compute_NOC(temperature, worsecase), + # Mem_SS = self.compute_Mem_SS(temperature, worsecase), + # A45 = self.compute_A45(temperature, worsecase), + # Config = self.compute_Config(temperature, worsecase), + # CLB = self.compute_CLB(temperature, worsecase), + # BRAM = self.compute_BRAM(temperature, worsecase), + # DSP = self.compute_DSP(temperature, worsecase), Gearbox_HP = self.compute_Gearbox_IO_bank_type(temperature, IO_BankType.HP, worsecase), Gearbox_HR = self.compute_Gearbox_IO_bank_type(temperature, IO_BankType.HR, worsecase), HP_IO = self.compute_IO_bank_type(temperature, IO_BankType.HP, worsecase), @@ -538,34 +356,39 @@ def compute(self, temperature : float, worsecase : bool = True) -> StaticPowerRe HP_IO_1_2V = self.compute_IO_bank_type_voltage(temperature, IO_BankType.HP, 1.2, worsecase), HP_IO_1_5V = self.compute_IO_bank_type_voltage(temperature, IO_BankType.HP, 1.5, worsecase), HP_IO_1_8V = self.compute_IO_bank_type_voltage(temperature, IO_BankType.HP, 1.8, worsecase), - VCC_BOOT_IO = self.compute_VCC_BOOT_IO(temperature, worsecase), - VCC_DDR_IO = self.compute_VCC_DDR_IO(temperature, worsecase), - VCC_SOC_IO = self.compute_VCC_SOC_IO(temperature, worsecase), - VCC_GIGE_IO = self.compute_VCC_GIGE_IO(temperature, worsecase), - VCC_USB_IO = self.compute_VCC_USB_IO(temperature, worsecase), - VCC_BOOT_AUX = self.compute_VCC_BOOT_AUX(temperature, worsecase), - VCC_SOC_AUX = self.compute_VCC_SOC_AUX(temperature, worsecase), - VCC_GIGE_AUX = self.compute_VCC_GIGE_AUX(temperature, worsecase), - VCC_USB_AUX = self.compute_VCC_USB_AUX(temperature, worsecase), - VCC_RC_OSC = self.compute_VCC_RC_OSC(temperature, worsecase), - VCC_PUF = self.compute_VCC_PUF(temperature, worsecase) + # VCC_BOOT_IO = self.compute_VCC_BOOT_IO(temperature, worsecase), + # VCC_DDR_IO = self.compute_VCC_DDR_IO(temperature, worsecase), + # VCC_SOC_IO = self.compute_VCC_SOC_IO(temperature, worsecase), + # VCC_GIGE_IO = self.compute_VCC_GIGE_IO(temperature, worsecase), + # VCC_USB_IO = self.compute_VCC_USB_IO(temperature, worsecase), + # VCC_BOOT_AUX = self.compute_VCC_BOOT_AUX(temperature, worsecase), + # VCC_SOC_AUX = self.compute_VCC_SOC_AUX(temperature, worsecase), + # VCC_GIGE_AUX = self.compute_VCC_GIGE_AUX(temperature, worsecase), + # VCC_USB_AUX = self.compute_VCC_USB_AUX(temperature, worsecase), + # VCC_RC_OSC = self.compute_VCC_RC_OSC(temperature, worsecase), + # VCC_PUF = self.compute_VCC_PUF(temperature, worsecase) ) return result - def compute_power_junction_temperature(self, temperature : float, theta_ja : float, dynamic_power : float, \ - worsecase : bool, N : int = 4) -> StaticPowerResult: + def compute(self, temperature: float, scenerio: ScenarioType) -> StaticPowerResult: + # compute fabric/fpga static power + power = StaticPowerResult() + for modtype in (ModuleType.FABRIC_LE, ModuleType.BRAM, ModuleType.DSP): + power.add(self.get_module(modtype).compute_static_power(temperature, scenerio)) + + # compute processin/peripheral static power + for periph in self.get_module(ModuleType.SOC_PERIPHERALS).get_peripherals(): + power.add(periph.compute_static_power(temperature, scenerio)) + return power + + def compute_power_junction_temperature(self, temperature: float, theta_ja: float, dynamic_power: float, \ + scenario: ScenarioType, N: int = 4) -> StaticPowerResult: next_temperature = temperature res = None for i in range(N): - res = self.compute(next_temperature, worsecase) + res = self.compute(next_temperature, scenario) res.next_temperature = temperature + (theta_ja * (res.get_total_power() + dynamic_power)) next_temperature = res.next_temperature - # print("[DEBUG]", i, temperature, theta_ja, dynamic_power, worsecase, next_temperature, \ - # res.get_total_power(), \ - # res.get_processing_total_power(), \ - # res.get_fpga_total_power(), \ - # # res, \ - # file=sys.stderr) return res def compute_static_power(self): @@ -574,14 +397,14 @@ def compute_static_power(self): self.specification.thermal.ambient.worsecase, \ self.specification.thermal.theta_ja, \ self.get_total_dynamic_power(True), - True) + ScenarioType.WORSE) # static power & junction temperature for typical case self.static_power_output[1] = self.compute_power_junction_temperature( \ self.specification.thermal.ambient.typical, \ self.specification.thermal.theta_ja, \ self.get_total_dynamic_power(False), - False) + ScenarioType.TYPICAL) def clear(self) -> None: # clear all device inputs by user diff --git a/backend/submodule/rs_device_resources.py b/backend/submodule/rs_device_resources.py index 83136028..dcf97a20 100644 --- a/backend/submodule/rs_device_resources.py +++ b/backend/submodule/rs_device_resources.py @@ -100,6 +100,9 @@ class PeripheralType(Enum): DDR = 'ddr' OCM = 'ocm' CONFIG = 'config' + PUFFCC = 'puffcc' + RC_OSC = 'rc_osc' + NOC = 'noc' class IO_BankType(RsEnum): HP = 0, "HP" @@ -533,15 +536,6 @@ def get_polynomial_coeff(self, type: ElementType, worse: bool): coeffs = [c.coeffs[:c.length] for c in polynomials] return 1/polynomials[0].factor, coeffs - def get_divfactor_coeff_CLB(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.CLB, worsecase) - - def get_divfactor_coeff_BRAM(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.BRAM, worsecase) - - def get_divfactor_coeff_DSP(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.DSP, worsecase) - def get_divfactor_coeff_GEARBOX_IO_bank_type(self, bank_type : int, worsecase : bool): return self.get_polynomial_coeff(ElementType.GEARBOX_IO_HP if bank_type == 0 else ElementType.GEARBOX_IO_HR, worsecase) @@ -551,18 +545,6 @@ def get_divfactor_coeff_IO_bank_type(self, bank_type : int, worsecase : bool): def get_divfactor_coeff_AUX(self, worsecase : bool): return self.get_polynomial_coeff(ElementType.AUX, worsecase) - def get_divfactor_coeff_NOC(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.NOC, worsecase) - - def get_divfactor_coeff_Mem_SS(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.MEM_SS, worsecase) - - def get_divfactor_coeff_A45(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.ACPU, worsecase) - - def get_divfactor_coeff_Config(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.CONFIG, worsecase) - def get_divfactor_coeff_Aux_bank_type(self, bank_type: int, worsecase: bool): return self.get_polynomial_coeff(ElementType.AUX_HP if bank_type == 0 else ElementType.AUX_HR, worsecase) @@ -582,39 +564,6 @@ def get_divfactor_coeff_IO_bank_type_voltage(self, bank_type : int, voltage : fl elif voltage == 1.8: return self.get_polynomial_coeff(ElementType.IO_HP_1_8V, worsecase) - def get_divfactor_coeff_VCC_BOOT_IO(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.VCC_BOOT_IO, worsecase) - - def get_divfactor_coeff_VCC_DDR_IO(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.VCC_DDR_IO, worsecase) - - def get_divfactor_coeff_VCC_SOC_IO(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.VCC_SOC_IO, worsecase) - - def get_divfactor_coeff_VCC_GIGE_IO(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.VCC_GIGE_IO, worsecase) - - def get_divfactor_coeff_VCC_USB_IO(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.VCC_USB_IO, worsecase) - - def get_divfactor_coeff_VCC_BOOT_AUX(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.VCC_BOOT_AUX, worsecase) - - def get_divfactor_coeff_VCC_SOC_AUX(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.VCC_SOC_AUX, worsecase) - - def get_divfactor_coeff_VCC_GIGE_AUX(self, worsecase: bool): - return self.get_polynomial_coeff(ElementType.VCC_GIGE_AUX, worsecase) - - def get_divfactor_coeff_VCC_USB_AUX(self, worsecase: bool): - return self.get_polynomial_coeff(ElementType.VCC_USB_AUX, worsecase) - - def get_divfactor_coeff_VCC_PUF(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.VCC_PUF, worsecase) - - def get_divfactor_coeff_VCC_RC_OSC(self, worsecase : bool): - return self.get_polynomial_coeff(ElementType.VCC_RC_OSC, worsecase) - def register_module(self, modtype, module): self.modules[modtype.value] = module return module diff --git a/backend/submodule/rs_power_config.py b/backend/submodule/rs_power_config.py index 0f4a4042..d87f0e34 100644 --- a/backend/submodule/rs_power_config.py +++ b/backend/submodule/rs_power_config.py @@ -3,7 +3,7 @@ from marshmallow import Schema, fields, post_load, validate from marshmallow.exceptions import ValidationError from utilities.common_utils import RsCustomException -from typing import Any, List +from typing import List, Tuple import json import jsonref import os @@ -12,10 +12,6 @@ class PowerConfigFileNotFoundException(RsCustomException): def __init__(self, filepath: str): super().__init__(f"Power config file '{filepath}' not found") -class PowerConfigStaticComponentNotFoundException(RsCustomException): - def __init__(self, component: str): - super().__init__(f"Static component '{component}' not found") - class PowerConfigComponentNotFoundException(RsCustomException): def __init__(self, component: str): super().__init__(f"Component '{component}' not found") @@ -24,10 +20,6 @@ class PowerConfigCoeffNotFoundException(RsCustomException): def __init__(self, component: str, name: str): super().__init__(f"Coeff '{name}' of component '{component}' not found") -class PowerConfigPolynomialNotFoundException(RsCustomException): - def __init__(self, component: str, scenario: str): - super().__init__(f"Polynomial '{component}' for '{scenario}' case not found") - class PowerConfigParsingException(RsCustomException): def __init__(self, error_message: str): super().__init__(f"Parsing Error: {error_message}") @@ -87,86 +79,82 @@ class ElementType(Enum): SRAM = 'sram' PWM = 'pwm' REGULATOR = 'regulator' + PUFFCC = 'puffcc' + RC_OSC = 'rc_osc' class ScenarioType(Enum): TYPICAL = 'typical' WORSE = 'worse' @dataclass -class RsStaticPowerPolynomial: - length: int = field(default=0) - coeffs: List[float] = field(default_factory=list) - factor: float = field(default=0) +class PowerValue: + type: str + value: float + +@dataclass +class RsDynamicPowerCoeff: + name: str = field(default='') + value: float = field(default=0.0) @dataclass class RsStaticPowerScenario: type: ScenarioType - polynomials: List[RsStaticPowerPolynomial] = field(default_factory=list) + coeffs: List[float] + factor: float @dataclass -class RsStaticPowerElement: - type: ElementType +class RsStaticPowerConfig: + rail_type: str + domain: str scenarios: List[RsStaticPowerScenario] = field(default_factory=list) @dataclass -class RsDynamicPowerCoeff: - name: str = field(default='') - value: float = field(default=0.0) - -@dataclass -class RsDynamicPowerComponent: +class RsComponent: type: ElementType coeffs: List[RsDynamicPowerCoeff] = field(default_factory=list) + static_power: List[RsStaticPowerConfig] = field(default_factory=list) @dataclass class RsPowerConfigData: - static: List[RsStaticPowerElement] = field(default_factory=list) - components: List[RsDynamicPowerComponent] = field(default_factory=list) + components: List[RsComponent] = field(default_factory=list) -class RsStaticPowerPolynomialSchema(Schema): - length = fields.Int() - coeffs = fields.List(fields.Float()) - factor = fields.Float() +class RsDynamicPowerCoeffSchema(Schema): + name = fields.Str(required=True) + value = fields.Float(required=True) @post_load def post_load(self, data, **kwargs): - return RsStaticPowerPolynomial(**data) + return RsDynamicPowerCoeff(**data) class RsStaticPowerScenarioSchema(Schema): type = fields.Enum(ScenarioType, by_value=True, required=True) - polynomials = fields.Nested(RsStaticPowerPolynomialSchema, many=True, validate=validate.Length(min=1), required=True) + coeffs = fields.List(fields.Float, required=True) + factor = fields.Float(required=True) @post_load def post_load(self, data, **kwargs): return RsStaticPowerScenario(**data) - -class RsStaticPowerElementSchema(Schema): - type = fields.Enum(ElementType, by_value=True, required=True) + +class RsStaticPowerConfigSchema(Schema): + rail_type = fields.Str(required=True) + domain = fields.Str(required=True) scenarios = fields.Nested(RsStaticPowerScenarioSchema, many=True, required=True) @post_load def post_load(self, data, **kwargs): - return RsStaticPowerElement(**data) + return RsStaticPowerConfig(**data) -class RsDynamicPowerCoeffSchema(Schema): - name = fields.Str(required=True) - value = fields.Float(required=True) - - @post_load - def post_load(self, data, **kwargs): - return RsDynamicPowerCoeff(**data) - -class RsDynamicPowerComponentSchema(Schema): +class RsComponentSchema(Schema): type = fields.Enum(ElementType, by_value=True, required=True) - coeffs = fields.Nested(RsDynamicPowerCoeffSchema, many=True, required=True) + coeffs = fields.Nested(RsDynamicPowerCoeffSchema, many=True, required=False) + static_power = fields.Nested(RsStaticPowerConfigSchema, many=True, required=False) @post_load def post_load(self, data, **kwargs): - return RsDynamicPowerComponent(**data) + return RsComponent(**data) class RsPowerConfigDataSchema(Schema): - static = fields.Nested(RsStaticPowerElementSchema, many=True, required=True) - components = fields.Nested(RsDynamicPowerComponentSchema, many=True, required=True) + components = fields.Nested(RsComponentSchema, many=True, required=True) @post_load def post_load(self, data, **kwargs): @@ -208,17 +196,7 @@ def load(self, filepath: str) -> bool: def is_loaded(self) -> bool: return self.loaded - def get_static_component(self, type: ElementType) -> RsStaticPowerElement: - # raise power data not available exception - if not self.loaded: - raise PowerConfigNotAvailable() - - comps = [c for c in self.data.static if c.type == type] - if comps: - return comps[0] - raise PowerConfigStaticComponentNotFoundException(type.value) - - def get_component(self, type: ElementType) -> RsDynamicPowerComponent: + def get_component(self, type: ElementType) -> RsComponent: # raise power data not available exception if not self.loaded: raise PowerConfigNotAvailable() @@ -234,8 +212,13 @@ def get_coeff(self, type: ElementType, name: str) -> float: return sum(values) / len(values) raise PowerConfigCoeffNotFoundException(type.value, name) - def get_polynomial_coeff(self, type: ElementType, scenario: ScenarioType) -> List[RsStaticPowerPolynomial]: - coeffs = [c for c in self.get_static_component(type).scenarios if c.type == scenario] - if coeffs: - return coeffs[0].polynomials - raise PowerConfigPolynomialNotFoundException(type.value, scenario.value) + def get_polynomial(self, type: ElementType, scenario: ScenarioType = None, rail_type: str = None) -> List[Tuple[str, List[RsStaticPowerScenario]]]: + mylist = [] + for sp in self.get_component(type).static_power: + if rail_type is None or sp.rail_type == rail_type: + scene_list = [] + for scene in sp.scenarios: + if scenario is None or scene.type == scenario: + scene_list.append(scene) + mylist.append((sp.rail_type, scene_list)) + return mylist diff --git a/tests/data/dsp.json b/tests/data/dsp.json index 58457e20..902a12f6 100644 --- a/tests/data/dsp.json +++ b/tests/data/dsp.json @@ -4,5 +4,14 @@ { "name": "TEST1", "value": 0.1234 } + ], + "static_power": [ + { + "rail_type": "Vcc_core (DSP)", + "domain": "Core", + "scenarios": [ + { "type": "typical", "coeffs": [0.1, 0.2, 0.3, 0.4, 0.5], "factor": 54321.1 } + ] + } ] } diff --git a/tests/data/power_config.json b/tests/data/power_config.json index 576fed65..08f5e62b 100644 --- a/tests/data/power_config.json +++ b/tests/data/power_config.json @@ -1,21 +1,4 @@ { - "static": [ - { - "type": "clb", - "scenarios": [ - { - "type": "typical", - "polynomials": [ - { - "length": 5, - "coeffs": [0.1, 0.2, 0.3, 0.4, 0.5], - "factor": 1.25 - } - ] - } - ] - } - ], "components": [ { "$ref": "dsp.json" } ] diff --git a/tests/test_rs_device_resources.py b/tests/test_rs_device_resources.py index 88d5c121..083c9a06 100644 --- a/tests/test_rs_device_resources.py +++ b/tests/test_rs_device_resources.py @@ -5,7 +5,6 @@ import pytest from unittest.mock import MagicMock, patch from submodule.rs_power_config import ElementType -from submodule.rs_power_config import RsStaticPowerPolynomial from submodule.rs_device_resources import ( RsDeviceResources, IO_Standard_Coeff, @@ -30,7 +29,6 @@ def mock_device(): def device_resources(mock_device): with patch('submodule.rs_device_resources.RsPowerConfig') as MockRsPowerConfig: MockRsPowerConfig.return_value.load.return_value = True - MockRsPowerConfig.return_value.get_polynomial_coeff.return_value = [RsStaticPowerPolynomial(length=5, factor=1.25, coeffs=[0.1, 0.2, 0.3, 0.4, 0.5])] yield RsDeviceResources(mock_device) def test_get_device_name(device_resources): @@ -75,11 +73,6 @@ def test_register_module(device_resources): device_resources.register_module(ModuleType.CLOCKING, module) assert device_resources.get_module(ModuleType.CLOCKING) == module -def test_get_divfactor_coeff_CLB(device_resources): - factor, coeffs = device_resources.get_divfactor_coeff_CLB(worsecase=True) - assert factor == 0.8 - assert len(coeffs) > 0 - def test_get_clock_not_found(device_resources): device_resources.register_module(ModuleType.CLOCKING, MagicMock(get_all=MagicMock(return_value=[]))) assert device_resources.get_clock('non_existent_clock') is None diff --git a/tests/test_rs_power_config.py b/tests/test_rs_power_config.py index 5919cc0c..3e9e1864 100644 --- a/tests/test_rs_power_config.py +++ b/tests/test_rs_power_config.py @@ -12,9 +12,7 @@ PowerConfigFileNotFoundException, PowerConfigParsingException, PowerConfigSchemaValidationException, - PowerConfigComponentNotFoundException, - PowerConfigStaticComponentNotFoundException, - PowerConfigPolynomialNotFoundException + PowerConfigComponentNotFoundException ) def test_not_loaded(): @@ -54,25 +52,15 @@ def test_get_coeff(): pwrcfg.load('tests/data/power_config.json') assert 0.1234 == pwrcfg.get_coeff(ElementType.DSP, "TEST1") -def test_get_polynomial_coeff_with_not_exist_component(): - pwrcfg = RsPowerConfig() - pwrcfg.load('tests/data/power_config.json') - with pytest.raises(PowerConfigStaticComponentNotFoundException): - pwrcfg.get_polynomial_coeff(ElementType.NOC, ScenarioType.TYPICAL) - -def test_get_polynomial_coeff_with_not_exist_scenario(): - pwrcfg = RsPowerConfig() - pwrcfg.load('tests/data/power_config.json') - with pytest.raises(PowerConfigPolynomialNotFoundException): - pwrcfg.get_polynomial_coeff(ElementType.CLB, ScenarioType.WORSE) - def test_get_polynomial_coeff(): pwrcfg = RsPowerConfig() result = pwrcfg.load('tests/data/power_config.json') - polynomials = pwrcfg.get_polynomial_coeff(ElementType.CLB, ScenarioType.TYPICAL) + polynomials = pwrcfg.get_polynomial(ElementType.DSP, ScenarioType.TYPICAL) assert 1 == len(polynomials) assert True == result assert True == pwrcfg.is_loaded() - assert 5 == polynomials[0].length - assert 1.25 == polynomials[0].factor - assert [0.1, 0.2, 0.3, 0.4, 0.5] == polynomials[0].coeffs + assert 'Vcc_core (DSP)' == polynomials[0][0] + assert True == isinstance(polynomials[0][1], list) + assert 1 == len(polynomials[0][1]) + assert 54321.1 == polynomials[0][1][0].factor + assert [0.1, 0.2, 0.3, 0.4, 0.5] == polynomials[0][1][0].coeffs