Skip to content

Commit e29f67c

Browse files
authored
Static power calculation (#77)
1 parent d7fa9ae commit e29f67c

31 files changed

+1244
-277
lines changed

backend/api/device.py

+184-15
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,85 @@
22
# Copyright (C) 2024 RapidSilicon
33
# Authorized use only
44
#
5-
from flask import Blueprint
5+
from flask import Blueprint, request
66
from flask_restful import Api, Resource
7-
from marshmallow import Schema, fields
7+
from marshmallow import Schema, fields, ValidationError
88
from submodule.rs_device_manager import RsDeviceManager
99
from submodule.rs_device_resources import DeviceNotFoundException
1010
from submodule.rs_message import RsMessageType
11-
from .errors import DeviceNotExistsError, InternalServerError
11+
from .errors import DeviceNotExistsError, InternalServerError, SchemaValidationError
1212
from .errors import errors
1313

1414
#---------------------------------------------------------------------------#
1515
# endpoints | methods | classes #
1616
#---------------------------------------------------------------------------#
1717
# devices | get | DevicesApi #
18-
# devices/<device_id> | get | DeviceApi #
18+
# devices/<device_id> | get, patch | DeviceApi #
1919
# devices/<device_id>/consumption | get | DeviceConsumptionApi #
2020
#---------------------------------------------------------------------------#
2121

2222
class MessageSchema(Schema):
2323
type = fields.Enum(RsMessageType, by_value=True)
2424
text = fields.Str()
2525

26+
class AmbientSchema(Schema):
27+
typical = fields.Number()
28+
worsecase = fields.Number()
29+
30+
class ThermalSpecSchema(Schema):
31+
theta_ja = fields.Number()
32+
ambient = fields.Nested(AmbientSchema)
33+
34+
class TypicalDynamicScalingSchema(Schema):
35+
fpga_complex = fields.Number()
36+
processing_complex = fields.Number()
37+
38+
class PowerSpecSchema(Schema):
39+
budget = fields.Number()
40+
typical_dynamic_scaling = fields.Nested(TypicalDynamicScalingSchema)
41+
42+
class SpecificationSchema(Schema):
43+
thermal = fields.Nested(ThermalSpecSchema)
44+
power = fields.Nested(PowerSpecSchema)
45+
2646
class DeviceSchema(Schema):
2747
id = fields.Str()
2848
series = fields.Str()
2949
logic_density = fields.Str()
3050
package = fields.Str()
3151
speedgrade = fields.Str()
3252
temperature_grade = fields.Str()
53+
specification = fields.Nested(SpecificationSchema)
3354

34-
class DevicePowerThermalSchema(Schema):
35-
total_power = fields.Number()
36-
thermal = fields.Number()
55+
class DeviceTotalPowerTemperatureSchema(Schema):
56+
type = fields.Str()
57+
power = fields.Number()
58+
temperature = fields.Number()
59+
60+
class DeviceComponentSchema(Schema):
61+
type = fields.Str()
62+
power = fields.Number()
63+
percentage = fields.Number()
64+
65+
class DeviceDynamicSchema(Schema):
66+
components = fields.Nested(DeviceComponentSchema, many=True)
67+
power = fields.Number()
68+
percentage = fields.Number()
69+
70+
class DeviceStaticSchema(Schema):
71+
power = fields.Number()
72+
percentage = fields.Number()
73+
74+
class DeviceComplexSchema(Schema):
75+
dynamic = fields.Nested(DeviceDynamicSchema)
76+
static = fields.Nested(DeviceStaticSchema)
77+
total_power = fields.Number(default=0.0)
78+
total_percentage = fields.Number(default=0.0)
3779

3880
class DeviceConsumptionSchema(Schema):
39-
worsecase = fields.Nested(DevicePowerThermalSchema)
40-
typical = fields.Nested(DevicePowerThermalSchema)
81+
total_power_temperature = fields.Nested(DeviceTotalPowerTemperatureSchema, many=True)
82+
processing_complex = fields.Nested(DeviceComplexSchema)
83+
fpga_complex = fields.Nested(DeviceComplexSchema)
4184

4285
class DevicesApi(Resource):
4386
def get(self):
@@ -89,20 +132,102 @@ def get(self):
89132
type: string
90133
temperature_grade:
91134
type: string
92-
DevicePowerThermal:
135+
DeviceTotalPowerTemperature:
136+
type: object
137+
properties:
138+
type:
139+
type: string
140+
power:
141+
type: number
142+
temperature:
143+
type: number
144+
DeviceComponent:
145+
type: object
146+
properties:
147+
type:
148+
type: string
149+
power:
150+
type: number
151+
percentage:
152+
type: number
153+
DeviceDynamic:
154+
type: object
155+
properties:
156+
components:
157+
type: array
158+
items:
159+
$ref: '#/definitions/DeviceComponent'
160+
power:
161+
type: number
162+
percentage:
163+
type: number
164+
DeviceStatic:
93165
type: object
94166
properties:
167+
power:
168+
type: number
169+
percentage:
170+
type: number
171+
DeviceComplex:
172+
type: object
173+
properties:
174+
dynamic:
175+
$ref: '#/definitions/DeviceDynamic'
176+
static:
177+
$ref: '#/definitions/DeviceStatic'
95178
total_power:
96179
type: number
97-
thermal:
180+
total_percentage:
98181
type: number
99182
DeviceConsumption:
100183
type: object
101184
properties:
102-
worsecase:
103-
$ref: '#/definitions/DevicePowerThermal'
185+
total_power_temperature:
186+
type: array
187+
items:
188+
$ref: '#/definitions/DeviceTotalPowerTemperature'
189+
processing_complex:
190+
$ref: '#/definitions/DeviceComplex'
191+
fpga_complex:
192+
$ref: '#/definitions/DeviceComplex'
193+
Ambient:
194+
type: object
195+
properties:
104196
typical:
105-
$ref: '#/definitions/DevicePowerThermal'
197+
type: number
198+
worsecase:
199+
type: number
200+
TypicalDynamicScaling:
201+
type: object
202+
properties:
203+
fpga_complex:
204+
type: number
205+
processing_complex:
206+
type: number
207+
Thermal:
208+
type: object
209+
properties:
210+
theta_ja:
211+
type: number
212+
ambient:
213+
$ref: '#/definitions/Ambient'
214+
Power:
215+
type: object
216+
properties:
217+
budget:
218+
type: number
219+
typical_dynamic_scaling:
220+
$ref: '#/definitions/TypicalDynamicScaling'
221+
Specification:
222+
type: object
223+
properties:
224+
specification:
225+
type: object
226+
properties:
227+
thermal:
228+
$ref: '#/definitions/Thermal'
229+
power:
230+
$ref: '#/definitions/Power'
106231
responses:
107232
200:
108233
description: Successfully returned a list of devices
@@ -135,7 +260,9 @@ def get(self, device_id : str):
135260
200:
136261
description: Successfully returned the details of a device
137262
schema:
138-
$ref: '#/definitions/Device'
263+
allOf:
264+
- $ref: '#/definitions/Device'
265+
- $ref: '#/definitions/Specification'
139266
400:
140267
description: Invalid request
141268
schema:
@@ -151,6 +278,48 @@ def get(self, device_id : str):
151278
except Exception as e:
152279
raise InternalServerError
153280

281+
def patch(self, device_id : str):
282+
"""
283+
This is an endpoint that updates the power and thermal spec of a device
284+
---
285+
tags:
286+
- Device
287+
description: Update the power and thermal spec of a device.
288+
parameters:
289+
- name: device_id
290+
in: path
291+
type: string
292+
required: true
293+
- name: spec
294+
in: body
295+
description: Update the power and thermal spec of a device
296+
schema:
297+
$ref: '#/definitions/Specification'
298+
responses:
299+
200:
300+
description: Successfully updated the power and thermal spec
301+
schema:
302+
allOf:
303+
- $ref: '#/definitions/Device'
304+
- $ref: '#/definitions/Specification'
305+
400:
306+
description: Invalid request
307+
schema:
308+
$ref: '#/definitions/HTTPErrorMessage'
309+
"""
310+
try:
311+
device_mgr = RsDeviceManager.get_instance()
312+
device = device_mgr.get_device(device_id)
313+
schema = DeviceSchema()
314+
device.update_spec(schema.load(request.json))
315+
return schema.dump(device), 200
316+
except ValidationError as e:
317+
raise SchemaValidationError
318+
except DeviceNotFoundException as e:
319+
raise DeviceNotExistsError
320+
except Exception as e:
321+
raise InternalServerError
322+
154323
class DeviceConsumptionApi(Resource):
155324
def get(self, device_id : str):
156325
"""

backend/api/io.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class IoUsageAllocationSchema(Schema):
3434
io_available = fields.Int()
3535

3636
class IoUsageSchema(Schema):
37-
type = fields.Str()
37+
type = fields.Enum(IO_Bank_Type, by_value=True)
3838
total_banks_available = fields.Int()
3939
total_io_available = fields.Int()
4040
usage = fields.Nested(IoUsageAllocationSchema, many=True)

backend/submodule/bram.py

+3
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ def get_resources(self):
194194
total_36k_bram_used += item.bram_used
195195
return total_18k_bram_used, self.total_18k_bram_available, total_36k_bram_used, self.total_36k_bram_available
196196

197+
def get_total_output_power(self) -> float:
198+
return sum(self.get_power_consumption())
199+
197200
def get_power_consumption(self):
198201
return self.total_block_power, self.total_interconnect_power
199202

backend/submodule/clock.py

+3
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ def __init__(self, resources, itemlist):
7474
self.total_pll_power = 0.0
7575
self.itemlist = itemlist
7676

77+
def get_total_output_power(self) -> float:
78+
return sum(self.get_power_consumption())
79+
7780
def get_power_consumption(self):
7881
return self.total_block_power, self.total_interconnect_power, self.total_pll_power
7982

backend/submodule/dsp.py

+3
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ def get_resources(self):
117117
total_dsp_blocks_used += item.number_of_multipliers
118118
return total_dsp_blocks_used, self.total_dsp_blocks_available
119119

120+
def get_total_output_power(self) -> float:
121+
return sum(self.get_power_consumption())
122+
120123
def get_power_consumption(self):
121124
return self.total_block_power, self.total_interconnect_power
122125

backend/submodule/fabric_logic_element.py

+3
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ def __init__(self, resources, itemlist):
9999
self.total_interconnect_power = 0.0
100100
self.itemlist = itemlist
101101

102+
def get_total_output_power(self) -> float:
103+
return sum(self.get_power_consumption())
104+
102105
def get_power_consumption(self):
103106
return self.total_block_power, self.total_interconnect_power
104107

backend/submodule/io.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ class IO_Usage_Allocation:
165165

166166
@dataclass
167167
class IO_Usage:
168-
type : str = field(default='')
168+
type : IO_Bank_Type = field(default=IO_Bank_Type.HP)
169169
total_banks_available : int = field(default=0)
170170
total_io_available : int = field(default=0)
171171
usage : List[IO_Usage_Allocation] = field(default_factory=list)
@@ -184,8 +184,8 @@ def __init__(self, resources, itemlist):
184184
self.total_interconnect_power = 0.0
185185
self.total_on_die_termination_power = 0.0
186186
self.io_usage = [
187-
IO_Usage(type="HP", usage=[IO_Usage_Allocation(voltage=1.2), IO_Usage_Allocation(voltage=1.5), IO_Usage_Allocation(voltage=1.8)]),
188-
IO_Usage(type="HR", usage=[IO_Usage_Allocation(voltage=1.8), IO_Usage_Allocation(voltage=2.5), IO_Usage_Allocation(voltage=3.3)])
187+
IO_Usage(type=IO_Bank_Type.HP, usage=[IO_Usage_Allocation(voltage=1.2, banks_used=1), IO_Usage_Allocation(voltage=1.5, banks_used=1), IO_Usage_Allocation(voltage=1.8, banks_used=1)]),
188+
IO_Usage(type=IO_Bank_Type.HR, usage=[IO_Usage_Allocation(voltage=1.8, banks_used=1), IO_Usage_Allocation(voltage=2.5, banks_used=1), IO_Usage_Allocation(voltage=3.3, banks_used=1)])
189189
]
190190
self.io_on_die_termination = [
191191
IO_On_Die_Termination(bank_number=1),
@@ -197,6 +197,9 @@ def __init__(self, resources, itemlist):
197197
def get_resources(self):
198198
return self.io_usage, self.io_on_die_termination
199199

200+
def get_total_output_power(self) -> float:
201+
return sum(self.get_power_consumption())
202+
200203
def get_power_consumption(self):
201204
return self.total_block_power, self.total_interconnect_power, self.total_on_die_termination_power
202205

backend/submodule/peripherals.py

+24
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,30 @@ def __init__(self, resources):
401401
Fpga_Complex(name="FPGA Complex", ports=[Endpoint(), Endpoint(), Endpoint(), Endpoint()])
402402
]
403403

404+
def get_processor_output_power(self) -> float:
405+
# todo
406+
return 0.347
407+
408+
def get_peripherals_output_power(self) -> float:
409+
# todo
410+
return 0.024
411+
412+
def get_bcpu_output_power(self) -> float:
413+
# todo
414+
return 0.013
415+
416+
def get_memory_output_power(self) -> float:
417+
# todo
418+
return 0.001
419+
420+
def get_dma_output_power(self) -> float:
421+
# todo
422+
return 0.0001
423+
424+
def get_noc_output_power(self) -> float:
425+
# todo
426+
return 0.003
427+
404428
def get_power_consumption(self):
405429
# todo
406430
return 0.347, 0.024, 0.013, 0.001, 0.0001, 0.003

0 commit comments

Comments
 (0)