Skip to content
This repository has been archived by the owner on Dec 10, 2024. It is now read-only.

Commit

Permalink
Works! Now speed optimize
Browse files Browse the repository at this point in the history
  • Loading branch information
iopapamanoglou committed Sep 20, 2024
1 parent 18e43a8 commit 8194b1e
Show file tree
Hide file tree
Showing 14 changed files with 229 additions and 159 deletions.
30 changes: 19 additions & 11 deletions src/faebryk/core/moduleinterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
cast,
)

from deprecated import deprecated
from typing_extensions import Self

from faebryk.core.graphinterface import (
Expand All @@ -25,7 +24,12 @@
LinkFilteredException,
LinkParent,
)
from faebryk.core.node import GraphInterfaceHierarchicalNode, Node, f_field
from faebryk.core.node import (
GraphInterfaceHierarchicalNode,
Node,
NodeException,
f_field,
)
from faebryk.core.trait import Trait
from faebryk.libs.util import groupby, unique

Expand Down Expand Up @@ -349,7 +353,7 @@ def _filter_paths_by_split_join(
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@staticmethod
def find_paths(src: "ModuleInterface"):
def find_paths[T: ModuleInterface](src: T) -> dict[T, list["_PathFinder.Path"]]:
multi_paths: list[_PathFinder.Path] = []

# Stage filters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -401,7 +405,9 @@ def filter_inline(path: _PathFinder.Path, _) -> tuple[bool, bool]:
paths = unique(paths, id)

node_paths = groupby(paths, lambda p: p[-1].node)
return node_paths

assert all(isinstance(p, type(src)) for p in node_paths.keys())
return cast(dict[T, list["_PathFinder.Path"]], node_paths)


class ModuleInterface(Node):
Expand Down Expand Up @@ -462,21 +468,23 @@ def is_connected_to(self, other: "ModuleInterface"):
return other in self.get_connected()

def get_path_to(self, other: "ModuleInterface"):
if type(other) is not type(self):
return None
paths = _PathFinder.find_paths(self)
return paths.get(other)

@deprecated("Does not work")
def _on_connect(self, other: Self):
"""override to handle custom connection logic"""
...
return paths.get(cast(Self, other))

def connect[T: "ModuleInterface"](
self: Self, *other: T, linkcls: type[Link] | None = None
) -> T | Self:
if linkcls is None:
linkcls = LinkDirect

assert {type(o) for o in other} == {type(self)}
if not {type(o) for o in other}.issubset({type(self)}):
raise NodeException(
self,
f"Can only connect modules of same type: {{{type(self)}}},"
f" got {{{','.join(str(type(o)) for o in other)}}}",
)

self.connected.connect(*{o.connected for o in other}, linkcls=linkcls)

Expand Down
6 changes: 6 additions & 0 deletions src/faebryk/core/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ class MergeException(Exception): ...
class SupportsSetOps:
def __contains__(self, other: "Parameter[PV].LIT_OR_PARAM") -> bool: ...

class is_dynamic(TraitT):
def exec(self) -> None: ...

def try_compress(self) -> "Parameter[PV]":
return self

Expand Down Expand Up @@ -367,6 +370,9 @@ def __rand__(self: "Parameter[PV]", other: "Parameter[PV]") -> "Parameter[PV]":
return self.intersect(other, self)

def get_most_narrow(self) -> "Parameter[PV]":
if self.has_trait(self.is_dynamic):
self.get_trait(self.is_dynamic).exec()

out = self.get_narrowing_chain()[-1]

com = out.try_compress()
Expand Down
11 changes: 3 additions & 8 deletions src/faebryk/library/ElectricPower.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@


import math
from typing import Self

import faebryk.library._F as F
from faebryk.core.node import Node
from faebryk.libs.library import L
from faebryk.libs.units import P, Quantity
from faebryk.libs.util import RecursionGuard


class ElectricPower(F.Power):
Expand Down Expand Up @@ -50,6 +48,7 @@ def protect(self):
lv: F.Electrical

voltage: F.TBD[Quantity]

max_current: F.TBD[Quantity]
"""
Only for this particular power interface
Expand Down Expand Up @@ -81,12 +80,8 @@ def fused(self, attach_to: Node | None = None):
return fused_power

def __preinit__(self) -> None:
...
self.voltage.add(F.is_dynamic_by_connections(lambda mif: mif.voltage))

# self.voltage.merge(
# self.hv.potential - self.lv.potential
# )

def _on_connect(self, other: Self) -> None:
super()._on_connect(other)

self.voltage.merge(other.voltage)
9 changes: 3 additions & 6 deletions src/faebryk/library/I2C.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# SPDX-License-Identifier: MIT
import logging
from enum import Enum
from typing import Self

import faebryk.library._F as F
from faebryk.core.moduleinterface import ModuleInterface
Expand Down Expand Up @@ -30,11 +29,6 @@ def terminate(self):
self.sda.pulled.pull(up=True)
self.scl.pulled.pull(up=True)

def _on_connect(self, other: Self):
super()._on_connect(other)

self.frequency.merge(other.frequency)

class SpeedMode(Enum):
low_speed = 10 * P.khertz
standard_speed = 100 * P.khertz
Expand All @@ -44,3 +38,6 @@ class SpeedMode(Enum):
@staticmethod
def define_max_frequency_capability(mode: SpeedMode):
return F.Range(I2C.SpeedMode.low_speed, mode)

def __preinit__(self) -> None:
self.frequency.add(F.is_dynamic_by_connections(lambda mif: mif.frequency))
3 changes: 2 additions & 1 deletion src/faebryk/library/TBD.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

from textwrap import indent

from faebryk.core.parameter import Parameter
from faebryk.core.parameter import Parameter, _resolved
from faebryk.libs.units import UnitsContainer


class TBD[PV](Parameter[PV]):
@_resolved
def __eq__(self, __value: object) -> bool:
if isinstance(__value, TBD):
return True
Expand Down
8 changes: 2 additions & 6 deletions src/faebryk/library/UART_Base.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# This file is part of the faebryk project
# SPDX-License-Identifier: MIT

from typing import Self

import faebryk.library._F as F
from faebryk.core.moduleinterface import ModuleInterface
from faebryk.libs.library import L
Expand All @@ -21,7 +19,5 @@ def single_electric_reference(self):
F.ElectricLogic.connect_all_module_references(self)
)

def _on_connect(self, other: Self):
super()._on_connect(other)

self.baud.merge(other.baud)
def __preinit__(self) -> None:
self.baud.add(F.is_dynamic_by_connections(lambda mif: mif.baud))
1 change: 1 addition & 0 deletions src/faebryk/library/_F.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from faebryk.library.has_pcb_position import has_pcb_position
from faebryk.library.has_single_electric_reference import has_single_electric_reference
from faebryk.library.Power import Power
from faebryk.library.is_dynamic_by_connections import is_dynamic_by_connections
from faebryk.library.Signal import Signal
from faebryk.library.has_construction_dependency import has_construction_dependency
from faebryk.library.has_footprint import has_footprint
Expand Down
54 changes: 54 additions & 0 deletions src/faebryk/library/is_dynamic_by_connections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# This file is part of the faebryk project
# SPDX-License-Identifier: MIT

import logging
from typing import Callable

from faebryk.core.moduleinterface import ModuleInterface
from faebryk.core.node import NodeException
from faebryk.core.parameter import Parameter
from faebryk.libs.util import NotNone, cast_assert

logger = logging.getLogger(__name__)


class is_dynamic_by_connections(Parameter.is_dynamic.impl()):
def __init__(self, key: Callable[[ModuleInterface], Parameter]) -> None:
super().__init__()
self._key = key
self._guard = False

def exec(self):
mif_parent = cast_assert(ModuleInterface, NotNone(self.obj.get_parent())[0])
param = self.get_obj(Parameter)
if self._key(mif_parent) is not param:
raise NodeException(self, "Key not mapping to parameter")

if self._guard:
return

print(f"EXEC {param.get_full_name()}")
mifs = mif_parent.get_connected()

# Disable guards to prevent infinite recursion
guards = [
trait
for mif in mifs
if self._key(mif).has_trait(Parameter.is_dynamic)
and isinstance(
trait := self._key(mif).get_trait(Parameter.is_dynamic),
is_dynamic_by_connections,
)
and not trait._guard
] + [self]
for guard in guards:
guard._guard = True

# Merge parameters
for mif in mifs:
mif_param = self._key(mif)
param.merge(mif_param)

# Enable guards again
for guard in guards:
guard._guard = False
8 changes: 6 additions & 2 deletions test/core/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ def test_fab_ll_chain_names(self):
x.add(y, f"i{i}")
x = y

self.assertEqual(x.get_full_name(), "*.i0.i1.i2.i3.i4.i5.i6.i7.i8.i9")
self.assertRegex(
x.get_full_name(), "<[0-9A-F]{4}>.i0.i1.i2.i3.i4.i5.i6.i7.i8.i9"
)

def test_fab_ll_chain_tree(self):
root = Node()
Expand All @@ -246,7 +248,9 @@ def test_fab_ll_chain_tree(self):
x.add(z, f"j{i}")
x = y

self.assertEqual(x.get_full_name(), "*.i0.i1.i2.i3.i4.i5.i6.i7.i8.i9")
self.assertRegex(
x.get_full_name(), "<[0-9A-F]{4}>.i0.i1.i2.i3.i4.i5.i6.i7.i8.i9"
)


if __name__ == "__main__":
Expand Down
7 changes: 0 additions & 7 deletions test/core/test_hierarchy_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
# SPDX-License-Identifier: MIT

import logging
import unittest
from itertools import chain

import pytest

import faebryk.library._F as F
from faebryk.core.core import logger as core_logger
from faebryk.core.graphinterface import GraphInterface
from faebryk.core.link import LinkDirectConditional
from faebryk.core.module import Module
Expand All @@ -18,7 +16,6 @@
from faebryk.libs.util import times

logger = logging.getLogger(__name__)
core_logger.setLevel(logger.getEffectiveLevel())


def test_up_connect():
Expand Down Expand Up @@ -295,7 +292,3 @@ def test_isolated_connect():

assert not a1.scl.reference.is_connected_to(b1.scl.reference)
assert not a1.sda.reference.is_connected_to(b1.sda.reference)


if __name__ == "__main__":
unittest.main()
72 changes: 35 additions & 37 deletions test/core/test_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,43 +324,41 @@ def test_specialize(self):
import faebryk.library._F as F
from faebryk.libs.brightness import TypicalLuminousIntensity

for i in range(10):

class App(Module):
led: F.PoweredLED
battery: F.Battery

def __preinit__(self) -> None:
self.led.power.connect(self.battery.power)

# Parametrize
self.led.led.color.merge(F.LED.Color.YELLOW)
self.led.led.brightness.merge(
TypicalLuminousIntensity.APPLICATION_LED_INDICATOR_INSIDE.value.value
)

app = App()

bcell = app.battery.specialize(F.ButtonCell())
bcell.voltage.merge(3 * P.V)
bcell.capacity.merge(F.Range.from_center(225 * P.mAh, 50 * P.mAh))
bcell.material.merge(F.ButtonCell.Material.Lithium)
bcell.size.merge(F.ButtonCell.Size.N_2032)
bcell.shape.merge(F.ButtonCell.Shape.Round)

app.led.led.color.merge(F.LED.Color.YELLOW)
app.led.led.max_brightness.merge(500 * P.millicandela)
app.led.led.forward_voltage.merge(1.2 * P.V)
app.led.led.max_current.merge(20 * P.mA)

v = app.battery.voltage
# vbcell = bcell.voltage
# print(pretty_param_tree_top(v))
# print(pretty_param_tree_top(vbcell))
self.assertEqual(v.get_most_narrow(), 3 * P.V)
r = app.led.current_limiting_resistor.resistance
r = r.get_most_narrow()
self.assertIsInstance(r, F.Range, f"{type(r)}")
class App(Module):
led: F.PoweredLED
battery: F.Battery

def __preinit__(self) -> None:
self.led.power.connect(self.battery.power)

# Parametrize
self.led.led.color.merge(F.LED.Color.YELLOW)
self.led.led.brightness.merge(
TypicalLuminousIntensity.APPLICATION_LED_INDICATOR_INSIDE.value.value
)

app = App()

bcell = app.battery.specialize(F.ButtonCell())
bcell.voltage.merge(3 * P.V)
bcell.capacity.merge(F.Range.from_center(225 * P.mAh, 50 * P.mAh))
bcell.material.merge(F.ButtonCell.Material.Lithium)
bcell.size.merge(F.ButtonCell.Size.N_2032)
bcell.shape.merge(F.ButtonCell.Shape.Round)

app.led.led.color.merge(F.LED.Color.YELLOW)
app.led.led.max_brightness.merge(500 * P.millicandela)
app.led.led.forward_voltage.merge(1.2 * P.V)
app.led.led.max_current.merge(20 * P.mA)

v = app.battery.voltage
# vbcell = bcell.voltage
# print(pretty_param_tree_top(v))
# print(pretty_param_tree_top(vbcell))
self.assertEqual(v.get_most_narrow(), 3 * P.V)
r = app.led.current_limiting_resistor.resistance
r = r.get_most_narrow()
self.assertIsInstance(r, F.Range, f"{type(r)}")

def test_units(self):
self.assertEqual(F.Constant(1e-9 * P.F), 1 * P.nF)
Expand Down
Loading

0 comments on commit 8194b1e

Please sign in to comment.