@@ -58,9 +58,7 @@ def action(
5858 where energy is in Joules, throughput is in actions/second, and latency is in
5959 seconds. If the component has subcomponents, then None return values are assumed to
6060 be zero cost, and subcomponent actions that occur during the component's action will
61- be added to the component's cost. Subcomponents are not affected by the scaling
62- factors of the component; to scale these, set the subcomponents' scaling factors
63- directly.
61+ be added to the component's cost.
6462
6563 Costs compose in the following ways for subcomponents:
6664
@@ -224,55 +222,44 @@ class ComponentModel(ListLoggable, ABC):
224222 not set.
225223 area: float | None
226224 The area of the component in m^2. Must be set if subcomponents is not set.
227- energy_scale: float
228- A scale factor for the energy. All calls to @action will be scaled by this
229- factor.
230- area_scale: float
231- A scale factor for the area. All calls to area will be scaled by this
232- factor.
233- throughput_scale: float
234- A scale factor for the throughput. All calls to @action will be scaled by
235- this factor.
236- latency_scale: float
237- A scale factor for the latency. All calls to @action will be scaled by this
238- factor.
239- leak_power_scale: float
240- A scale factor for the leakage power. All calls to leak_power will be scaled
241- by this factor.
242225 subcomponents: list[ComponentModel] | None
243226 A list of subcomponents. If set, the area and leak power of the
244227 subcomponents will be added to the area and leak power of the component. All
245228 calls to @action functions will be added to the cost of the component if
246- they occur during one of the component's actions. The area, energy, leak
247- power, and throughput of subcomponents WILL NOT BE scaled by the component's
248- energy_scale, area_scale, throughput_scale, or leak_power_scale; if you want
249- to scale the subcomponents, multiply their energy_scale, area_scale,
250- throughput_scale, or leak_power_scale by the desired scale factor.
229+ they occur during one of the component's actions.
251230
252231 Attributes
253232 ----------
254233 component_name: The name of the component. Must be a string or list/tuple of
255234 strings. Can be omitted if the component name is the same as the class name.
256235 priority: The priority of the model. Higher priority models are used first.
257236 Must be a number between 0 and 1.
258- energy_scale: A scale factor for the energy. All calls to action
259- will be scaled by this factor.
260- area_scale: A scale factor for the area. All calls to area
261- will be scaled by this factor.
262- throughput_scale: A scale factor for the throughput. All calls to @action
263- will be scaled by this factor.
264- latency_scale: A scale factor for the latency. All calls to @action
265- will be scaled by this factor.
266- leak_power_scale: A scale factor for the leakage power. All calls to leak_power
267- will be scaled by this factor.
237+ energy_scale:
238+ A scale factor for the energy of this component. The energy of all calls to
239+ actions will be scaled by this factor. WILL NOT AFFECT SUBCOMPONENT ENERGY.
240+ area_scale:
241+ A scale factor for the area of this component. All accesses to area will be
242+ scaled by this factor. WILL NOT AFFECT SUBCOMPONENT AREA.
243+ throughput_scale:
244+ A scale factor for the throughput of this component. The throughput of all
245+ calls to @action will be scaled by this factor. WILL NOT AFFECT SUBCOMPONENT
246+ THROUGHPUT.
247+ latency_scale:
248+ A scale factor for the latency of this component. The latency of all calls
249+ to @action will be scaled by this factor. WILL NOT AFFECT SUBCOMPONENT
250+ LATENCY.
251+ leak_power_scale: A scale factor for the leakage power of this component. All
252+ accesses to leak_power will be scaled by this factor. WILL NOT AFFECT
253+ SUBCOMPONENT LEAK POWER.
268254 subcomponents: A list of subcomponents. If set, the area and leak power of the
269- subcomponents will be added to the area and leak power of the component. All
270- calls to @action functions will be added to the cost of the component if
271- they occur during one of the component's actions. The area, energy, leak
272- power, and throughput of subcomponents WILL NOT BE scaled by the component's
255+ subcomponents are added to the area and leak power of the component, and all
256+ calls to @action functions are added to the cost of the component if they
257+ occur during one of the component's actions. The area, energy, leak power,
258+ and throughput of subcomponents WILL NOT BE scaled by the component's
273259 energy_scale, area_scale, throughput_scale, or leak_power_scale; if you want
274- to scale the subcomponents, multiply their energy_scale, area_scale,
275- throughput_scale, or leak_power_scale by the desired scale factor.
260+ to scale the subcomponents, use scale_area, scale_energy, scale_latency,
261+ scale_throughput, scale_leak_power, or scale with include_subcomponents=True
262+ or call scaling functions on the subcomponents directly.
276263 """
277264
278265 component_name : Union [str , List [str ], None ] = None
@@ -302,11 +289,11 @@ def __init__(
302289 f"must be set."
303290 )
304291 super ().__init__ ()
305- self .area_scale : float = 1
306- self .energy_scale : float = 1
307- self .latency_scale : float = 1
308- self .throughput_scale : float = 1
309- self .leak_power_scale : float = 1
292+ self ._area_scale : float = 1
293+ self ._energy_scale : float = 1
294+ self ._latency_scale : float = 1
295+ self ._throughput_scale : float = 1
296+ self ._leak_power_scale : float = 1
310297 self ._leak_power : float = leak_power if leak_power is not None else 0
311298 self ._area : float = area if area is not None else 0
312299 self .subcomponents : list ["ComponentModel" ] = (
@@ -326,7 +313,7 @@ def leak_power(self) -> Number:
326313 -------
327314 The leakage power in Watts.
328315 """
329- return self ._leak_power * self .leak_power_scale + sum (
316+ return self ._leak_power * self ._leak_power_scale + sum (
330317 s .leak_power for s in self .subcomponents
331318 )
332319
@@ -339,7 +326,167 @@ def area(self) -> Number:
339326 -------
340327 The area in m^2 of the component.
341328 """
342- return self ._area * self .area_scale + sum (s .area for s in self .subcomponents )
329+ return self ._area * self ._area_scale + sum (s .area for s in self .subcomponents )
330+
331+ @property
332+ def area_scale (self ) -> float :
333+ """
334+ A scale factor for the area of this component. All accesses to area will be
335+ scaled by this factor. WILL NOT AFFECT SUBCOMPONENT AREA.
336+ """
337+ return self ._area_scale
338+
339+ @area_scale .setter
340+ def area_scale (self , value : float ):
341+ """Do not set area_scale directly. Use scale_area instead."""
342+ raise AttributeError (
343+ "area_scale cannot be set directly. Use scale_area instead."
344+ )
345+
346+ @property
347+ def energy_scale (self ) -> float :
348+ """
349+ A scale factor for the energy of this component. The energy of all calls to
350+ actions will be scaled by this factor. WILL NOT AFFECT SUBCOMPONENT ENERGY.
351+ """
352+ return self ._energy_scale
353+
354+ @energy_scale .setter
355+ def energy_scale (self , value : float ):
356+ """Do not set energy_scale directly. Use scale_energy instead."""
357+ raise AttributeError (
358+ "energy_scale cannot be set directly. Use scale_energy instead."
359+ )
360+
361+ @property
362+ def latency_scale (self ) -> float :
363+ """
364+ A scale factor for the latency of this component. The latency of all calls to
365+ @action will be scaled by this factor. WILL NOT AFFECT SUBCOMPONENT LATENCY.
366+ """
367+ return self ._latency_scale
368+
369+ @latency_scale .setter
370+ def latency_scale (self , value : float ):
371+ """Do not set latency_scale directly. Use scale_latency instead."""
372+ raise AttributeError (
373+ "latency_scale cannot be set directly. Use scale_latency instead."
374+ )
375+
376+ @property
377+ def throughput_scale (self ) -> float :
378+ """
379+ A scale factor for the throughput of this component. The throughput of all calls
380+ to @action will be scaled by this factor. WILL NOT AFFECT SUBCOMPONENT
381+ THROUGHPUT.
382+ """
383+ return self ._throughput_scale
384+
385+ @throughput_scale .setter
386+ def throughput_scale (self , value : float ):
387+ """Do not set throughput_scale directly. Use scale_throughput instead."""
388+ raise AttributeError (
389+ "throughput_scale cannot be set directly. Use scale_throughput instead."
390+ )
391+
392+ @property
393+ def leak_power_scale (self ) -> float :
394+ """
395+ A scale factor for the leakage power of this component. All accesses to
396+ leak_power will be scaled by this factor. WILL NOT AFFECT SUBCOMPONENT LEAK
397+ POWER.
398+ """
399+ return self ._leak_power_scale
400+
401+ @leak_power_scale .setter
402+ def leak_power_scale (self , value : float ):
403+ """Do not set leak_power_scale directly. Use scale_leak_power instead."""
404+ raise AttributeError (
405+ "leak_power_scale cannot be set directly. Use scale_leak_power instead."
406+ )
407+
408+ def _scale_attr (self , attr : str , scale : float , include_subcomponents : bool ):
409+ setattr (self , attr , getattr (self , attr ) * scale )
410+ if include_subcomponents :
411+ for s in self .subcomponents :
412+ s ._scale_attr (attr , scale , include_subcomponents )
413+
414+ def scale_area (self , scale : float , include_subcomponents : bool ):
415+ """
416+ Multiplies this component's area scale factor by ``scale``. If
417+ ``include_subcomponents`` is True, then subcomponent area is scaled as well.
418+
419+ Parameters
420+ ----------
421+ scale: float
422+ The factor by which to scale the area.
423+ include_subcomponents: bool
424+ Whether to scale subcomponent area by the same factor. Finds all
425+ subcomponents recursively.
426+ """
427+ self ._scale_attr ("_area_scale" , scale , include_subcomponents )
428+
429+ def scale_energy (self , scale : float , include_subcomponents : bool ):
430+ """
431+ Multiplies this component's energy scale factor by ``scale``. If
432+ ``include_subcomponents`` is True, then subcomponent energy is scaled as well.
433+
434+ Parameters
435+ ----------
436+ scale: float
437+ The factor by which to scale the energy.
438+ include_subcomponents: bool
439+ Whether to scale subcomponent energy by the same factor. Finds all
440+ subcomponents recursively.
441+ """
442+ self ._scale_attr ("_energy_scale" , scale , include_subcomponents )
443+
444+ def scale_latency (self , scale : float , include_subcomponents : bool ):
445+ """
446+ Multiplies this component's latency scale factor by ``scale``. If
447+ ``include_subcomponents`` is True, then subcomponent latency is scaled as well.
448+
449+ Parameters
450+ ----------
451+ scale: float
452+ The factor by which to scale the latency.
453+ include_subcomponents: bool
454+ Whether to scale subcomponent latency by the same factor. Finds all
455+ subcomponents recursively.
456+ """
457+ self ._scale_attr ("_latency_scale" , scale , include_subcomponents )
458+
459+ def scale_throughput (self , scale : float , include_subcomponents : bool ):
460+ """
461+ Multiplies this component's throughput scale factor by ``scale``. If
462+ ``include_subcomponents`` is True, then subcomponent throughput is scaled as
463+ well.
464+
465+ Parameters
466+ ----------
467+ scale: float
468+ The factor by which to scale the throughput.
469+ include_subcomponents: bool
470+ Whether to scale subcomponent throughput by the same factor. Finds all
471+ subcomponents recursively.
472+ """
473+ self ._scale_attr ("_throughput_scale" , scale , include_subcomponents )
474+
475+ def scale_leak_power (self , scale : float , include_subcomponents : bool ):
476+ """
477+ Multiplies this component's leak power scale factor by ``scale``. If
478+ ``include_subcomponents`` is True, then subcomponent leak power is scaled as
479+ well.
480+
481+ Parameters
482+ ----------
483+ scale: float
484+ The factor by which to scale the leak power.
485+ include_subcomponents: bool
486+ Whether to scale subcomponent leak power by the same factor. Finds all
487+ subcomponents recursively.
488+ """
489+ self ._scale_attr ("_leak_power_scale" , scale , include_subcomponents )
343490
344491 @classmethod
345492 def _component_name (cls ) -> str :
@@ -359,6 +506,7 @@ def scale(
359506 throughput_scale_function : (
360507 Callable [[float , float ], float ] | tuple | None
361508 ) = None ,
509+ include_subcomponents : bool = True ,
362510 ) -> float :
363511 """
364512 Scales this model's area, energy, latency, leak power, and throughput to the
@@ -389,35 +537,33 @@ def scale(
389537 throughput_scale_function: Callable[[float, float], float] | tuple
390538 The function (or tuple of composed functions) to use to scale the
391539 throughput. None if no scaling should be done.
540+ include_subcomponents: bool
541+ Whether to also scale the subcomponents by the same factors. Defaults to
542+ True. When True, subcomponents are scaled as well.
392543 """
393544 super ()._init_logger (f"{ self ._component_name ()} " )
394545 if target == default :
395546 return target
396547
397- for attr , callfunc in [
398- ("area_scale" , area_scale_function ),
399- ("energy_scale" , energy_scale_function ),
400- ("latency_scale" , latency_scale_function ),
401- ("leak_power_scale" , leak_power_scale_function ),
402- ("throughput_scale" , throughput_scale_function ),
548+ for attr , scale_method , callfunc in [
549+ ("area_scale" , self . scale_area , area_scale_function ),
550+ ("energy_scale" , self . scale_energy , energy_scale_function ),
551+ ("latency_scale" , self . scale_latency , latency_scale_function ),
552+ ("leak_power_scale" , self . scale_leak_power , leak_power_scale_function ),
553+ ("throughput_scale" , self . scale_throughput , throughput_scale_function ),
403554 ]:
555+ if callfunc is None :
556+ continue
404557 try :
405- if callfunc is None :
406- continue
407- prev_val = getattr (self , attr )
408558 scale = _apply_scale_func (callfunc , target , default )
409- setattr (self , attr , prev_val * scale )
410- self .logger .info (
411- f"Scaled { key } from { default } to { target } : { attr } multiplied by { scale } "
412- )
413559 except :
414560 target_float = parse_float (target , f"{ self ._component_name ()} .{ key } " )
415561 default_float = parse_float (default , f"{ self ._component_name ()} .{ key } " )
416562 scale = _apply_scale_func (callfunc , target_float , default_float )
417- setattr ( self , attr , prev_val * scale )
418- self .logger .info (
419- f"Scaled { key } from { default } to { target } : { attr } multiplied by { scale } "
420- )
563+ scale_method ( scale , include_subcomponents )
564+ self .logger .info (
565+ f"Scaled { key } from { default } to { target } : { attr } multiplied by { scale } "
566+ )
421567
422568 return target
423569
0 commit comments