Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add utilities for BOM generation #173

Merged
merged 3 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions src/faebryk/core/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from faebryk.library.has_overriden_name_defined import has_overriden_name_defined
from faebryk.library.Range import Range
from faebryk.library.Set import Set
from faebryk.libs.util import NotNone, cast_assert
from faebryk.libs.util import NotNone, cast_assert, round_str

logger = logging.getLogger(__name__)
T = TypeVar("T")
Expand Down Expand Up @@ -56,7 +56,6 @@ def unit_map(

effective_mantissa = mantissa * (base**exponent_difference)
round_digits = round(math.log(base, 10) * (1 - exponent_difference))
# print(f"{exponent_difference=}, {effective_mantissa=}, {round_digits=}")

idx = available_exponent + start_idx
rounded_mantissa = round(effective_mantissa, round_digits)
Expand All @@ -83,6 +82,15 @@ def as_unit(value: SupportsFloat, unit: str, base: int = 1000):
return get_unit_prefix(value, base=base) + unit


def as_unit_with_tolerance(param: Range | Constant, unit: str, base: int = 1000):
if isinstance(param, Constant):
return as_unit(param.value, unit, base=base) + " ± 0%"
center, delta = param.as_center_tuple()
delta_percent = delta / center * 100

return f"{as_unit(center, unit, base=base)} ± {round_str(delta_percent)}%"


def get_all_nodes(node: Node, order_types=None) -> list[Node]:
if order_types is None:
order_types = []
Expand All @@ -96,9 +104,9 @@ def get_all_nodes(node: Node, order_types=None) -> list[Node]:

out = sorted(
out,
key=lambda x: order_types.index(type(x))
if type(x) in order_types
else len(order_types),
key=lambda x: (
order_types.index(type(x)) if type(x) in order_types else len(order_types)
),
)

return out
Expand Down Expand Up @@ -241,7 +249,7 @@ def get_mif_tree(

def format_mif_tree(tree: dict[ModuleInterface, dict[ModuleInterface, dict]]) -> str:
def str_tree(
tree: dict[ModuleInterface, dict[ModuleInterface, dict]]
tree: dict[ModuleInterface, dict[ModuleInterface, dict]],
) -> dict[str, dict]:
def get_name(k: ModuleInterface):
# get_parent never none, since k gotten from parent
Expand Down
18 changes: 12 additions & 6 deletions src/faebryk/library/Capacitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
from enum import IntEnum, auto

from faebryk.core.core import Module
from faebryk.core.util import as_unit
from faebryk.core.util import as_unit, as_unit_with_tolerance
from faebryk.library.can_attach_to_footprint_symmetrically import (
can_attach_to_footprint_symmetrically,
)
from faebryk.library.can_bridge_defined import can_bridge_defined
from faebryk.library.Electrical import Electrical
from faebryk.library.has_designator_prefix_defined import has_designator_prefix_defined
from faebryk.library.has_simple_value_representation_based_on_param import (
has_simple_value_representation_based_on_param,
from faebryk.library.has_simple_value_representation_based_on_params import (
has_simple_value_representation_based_on_params,
)
from faebryk.library.TBD import TBD
from faebryk.libs.util import times
Expand Down Expand Up @@ -50,9 +50,15 @@ class _PARAMs(Module.PARAMS()):
self.add_trait(can_bridge_defined(*self.IFs.unnamed))

self.add_trait(
has_simple_value_representation_based_on_param(
self.PARAMs.capacitance,
lambda p: as_unit(p, "F"),
has_simple_value_representation_based_on_params(
(
self.PARAMs.capacitance,
self.PARAMs.rated_voltage,
self.PARAMs.temperature_coefficient,
),
lambda ps: f"{as_unit_with_tolerance(ps[0], 'F')} "
f"{as_unit(ps[1].max, 'V')} "
f"{ps[2].max.name}",
)
)
self.add_trait(can_attach_to_footprint_symmetrically())
Expand Down
3 changes: 3 additions & 0 deletions src/faebryk/library/Range.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ def contains(self, value_to_check: PV) -> bool:
def as_tuple(self) -> tuple[PV, PV]:
return (self.min, self.max)

def as_center_tuple(self) -> tuple[PV, PV]:
return (self.min + self.max) / 2, (self.max - self.min) / 2

@classmethod
def from_center(cls, center: PV, delta: PV) -> "Range[PV]":
return cls(center - delta, center + delta)
Expand Down
30 changes: 24 additions & 6 deletions src/faebryk/library/Resistor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
from math import sqrt

from faebryk.core.core import Module, Parameter
from faebryk.core.util import as_unit
from faebryk.core.util import (
as_unit,
as_unit_with_tolerance,
)
from faebryk.library.can_attach_to_footprint_symmetrically import (
can_attach_to_footprint_symmetrically,
)
from faebryk.library.can_bridge_defined import can_bridge_defined
from faebryk.library.Electrical import Electrical
from faebryk.library.has_designator_prefix_defined import has_designator_prefix_defined
from faebryk.library.has_simple_value_representation_based_on_param import (
has_simple_value_representation_based_on_param,
from faebryk.library.has_simple_value_representation_based_on_params import (
has_simple_value_representation_based_on_params,
)
from faebryk.library.TBD import TBD
from faebryk.libs.util import times
Expand All @@ -30,14 +33,19 @@ class _IFs(super().IFS()):

class PARAMS(super().PARAMS()):
resistance = TBD[float]()
rated_power = TBD[float]()

self.PARAMs = PARAMS(self)

self.add_trait(can_attach_to_footprint_symmetrically())
self.add_trait(
has_simple_value_representation_based_on_param(
self.PARAMs.resistance,
lambda p: as_unit(p, "Ω"),
has_simple_value_representation_based_on_params(
(
self.PARAMs.resistance,
self.PARAMs.rated_power,
),
lambda ps: f"{as_unit_with_tolerance(ps[0], 'Ω')} "
f"{as_unit(ps[1].max, 'W')}",
)
)
self.add_trait(has_designator_prefix_defined("R"))
Expand Down Expand Up @@ -101,3 +109,13 @@ def get_power_dissipation_by_voltage_current(
voltage_drop_V: Parameter, current_A
) -> Parameter:
return voltage_drop_V * current_A

def set_rated_power_by_voltage_resistance(self, voltage_drop_V: Parameter):
self.PARAMs.rated_power.merge(
self.get_power_dissipation_by_voltage_resistance(voltage_drop_V)
)

def set_rated_power_by_current_resistance(self, current_A: Parameter):
self.PARAMs.rated_power.merge(
self.get_power_dissipation_by_current_resistance(current_A)
)
1 change: 1 addition & 0 deletions src/faebryk/library/_F.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
from faebryk.library.has_resistance import has_resistance
from faebryk.library.has_simple_value_representation import has_simple_value_representation
from faebryk.library.has_simple_value_representation_based_on_param import has_simple_value_representation_based_on_param
from faebryk.library.has_simple_value_representation_based_on_params import has_simple_value_representation_based_on_params
from faebryk.library.has_simple_value_representation_defined import has_simple_value_representation_defined
from faebryk.library.has_single_connection import has_single_connection
from faebryk.library.has_single_connection_impl import has_single_connection_impl
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This file is part of the faebryk project
# SPDX-License-Identifier: MIT

from typing import Callable, Sequence

from faebryk.core.core import Parameter
from faebryk.library.Constant import Constant
from faebryk.library.has_simple_value_representation import (
has_simple_value_representation,
)
from faebryk.library.Range import Range


class has_simple_value_representation_based_on_params(
has_simple_value_representation.impl()
):
def __init__(
self,
params: Sequence[Parameter],
transformer: Callable[[Sequence[Constant | Range]], str],
) -> None:
super().__init__()
self.transformer = transformer
self.params = params

def get_value(self) -> str:
params_const = tuple(param.get_most_narrow() for param in self.params)
assert all(isinstance(p, (Constant, Range)) for p in params_const)
return self.transformer(params_const)

def is_implemented(self):
return all(
isinstance(p.get_most_narrow(), (Range, Constant)) for p in self.params
)
9 changes: 7 additions & 2 deletions src/faebryk/libs/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
Iterator,
List,
Optional,
SupportsFloat,
SupportsInt,
Type,
TypeVar,
Expand Down Expand Up @@ -226,8 +227,7 @@ def get_all(self) -> list[T]:

return self._list

def handle_add(self, name: str, obj: T) -> None:
...
def handle_add(self, name: str, obj: T) -> None: ...

def get_parent(self) -> P:
return self._parent
Expand Down Expand Up @@ -287,6 +287,11 @@ def is_type_set_subclasses(type_subclasses: set[type], types: set[type]) -> bool
)


def round_str(value: SupportsFloat, n=8):
f = round(float(value), n)
return str(f).rstrip("0").rstrip(".")


def _print_stack(stack):
from colorama import Fore

Expand Down