Skip to content

Commit

Permalink
Move dependency related classes to Transactron (#544)
Browse files Browse the repository at this point in the history
  • Loading branch information
tilk authored Jan 6, 2024
1 parent 9b5a156 commit f242864
Show file tree
Hide file tree
Showing 23 changed files with 123 additions and 105 deletions.
2 changes: 1 addition & 1 deletion coreblocks/core.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from amaranth import *

from coreblocks.params.dependencies import DependencyManager
from transactron.utils.dependencies import DependencyManager
from coreblocks.stages.func_blocks_unifier import FuncBlocksUnifier
from coreblocks.structs_common.instr_counter import CoreInstructionCounter
from coreblocks.structs_common.interrupt_controller import InterruptController
Expand Down
2 changes: 1 addition & 1 deletion coreblocks/fu/exception.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Sequence
from amaranth import *
from coreblocks.params.dependencies import DependencyManager
from transactron.utils.dependencies import DependencyManager
from coreblocks.params.isa import Funct3, ExceptionCause

from transactron import *
Expand Down
1 change: 1 addition & 0 deletions coreblocks/fu/jumpbranch.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from transactron import *
from transactron.core import def_method
from transactron.lib import *
from transactron.utils import DependencyManager

from coreblocks.params import *
from coreblocks.params.keys import AsyncInterruptInsertSignalKey
Expand Down
1 change: 1 addition & 0 deletions coreblocks/fu/priv.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from transactron import *
from transactron.lib import BasicFifo
from transactron.utils import DependencyManager

from coreblocks.params import *
from coreblocks.params.keys import MretKey
Expand Down
2 changes: 1 addition & 1 deletion coreblocks/lsu/dummyLsu.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from coreblocks.params import *
from coreblocks.peripherals.wishbone import WishboneMaster
from transactron.lib.connectors import Forwarder
from transactron.utils import assign, ModuleLike
from transactron.utils import assign, ModuleLike, DependencyManager
from coreblocks.utils.protocols import FuncBlock

from coreblocks.lsu.pma import PMAChecker
Expand Down
1 change: 0 additions & 1 deletion coreblocks/params/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@
from .fu_params import * # noqa: F401
from .keys import * # noqa: F401
from .icache_params import * # noqa: F401
from .dependencies import * # noqa: F401
from .instr import * # noqa: F401
42 changes: 1 addition & 41 deletions coreblocks/params/genparams.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from __future__ import annotations

from typing import TypeVar, Type, Any
from amaranth.utils import log2_int

from .isa import ISA, gen_isa_string
from .icache_params import ICacheParameters
from .fu_params import extensions_supported
from ..peripherals.wishbone import WishboneParameters
from transactron.utils import make_hashable
from transactron.utils import DependentCache

from typing import TYPE_CHECKING

Expand All @@ -16,45 +15,6 @@

__all__ = ["GenParams"]

T = TypeVar("T")


class DependentCache:
"""
Cache for classes, that depend on the `DependentCache` class itself.
Cached classes may accept one positional argument in the constructor, where this `DependentCache` class will
be passed. Classes may define any number keyword arguments in the constructor and separate cache entry will
be created for each set of the arguments.
Methods
-------
get: T, **kwargs -> T
Gets class `cls` from cache. Caches `cls` reference if this is the first call for it.
Optionally accepts `kwargs` for additional arguments in `cls` constructor.
"""

def __init__(self):
self._depcache: dict[tuple[Type, Any], Type] = {}

def get(self, cls: Type[T], **kwargs) -> T:
cache_key = make_hashable(kwargs)
v = self._depcache.get((cls, cache_key), None)
if v is None:
positional_count = cls.__init__.__code__.co_argcount

# first positional arg is `self` field, second may be `DependentCache`
if positional_count > 2:
raise KeyError(f"Too many positional arguments in {cls!r} constructor")

if positional_count > 1:
v = cls(self, **kwargs)
else:
v = cls(**kwargs)
self._depcache[(cls, cache_key)] = v
return v


class GenParams(DependentCache):
def __init__(self, cfg: CoreConfiguration):
Expand Down
2 changes: 1 addition & 1 deletion coreblocks/params/keys.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING

from coreblocks.params.dependencies import SimpleKey, UnifierKey
from transactron.lib.dependencies import SimpleKey, UnifierKey
from transactron import Method
from transactron.lib import MethodTryProduct, Collector
from coreblocks.peripherals.wishbone import WishboneMaster
Expand Down
7 changes: 3 additions & 4 deletions coreblocks/stages/func_blocks_unifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

from amaranth import *

from coreblocks.params import GenParams, BlockComponentParams, DependencyManager
from coreblocks.params.dependencies import UnifierKey
from coreblocks.params import GenParams, BlockComponentParams
from transactron.lib.dependencies import UnifierKey, DependencyManager
from transactron import Method, TModule
from transactron.lib import MethodProduct, Collector
from coreblocks.utils.protocols import Unifier
from transactron.lib import MethodProduct, Collector, Unifier

__all__ = ["FuncBlocksUnifier"]

Expand Down
2 changes: 1 addition & 1 deletion coreblocks/stages/retirement.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from transactron.core import Method, Transaction, TModule
from transactron.lib.simultaneous import condition
from transactron.utils.dependencies import DependencyManager

from coreblocks.params.genparams import GenParams
from coreblocks.params.dependencies import DependencyManager
from coreblocks.params.isa import ExceptionCause
from coreblocks.params.keys import GenericCSRRegistersKey
from coreblocks.structs_common.csr_generic import CSRAddress, DoubleCounterCSR
Expand Down
2 changes: 1 addition & 1 deletion coreblocks/structs_common/csr.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from transactron import Method, def_method, Transaction, TModule
from transactron.utils import assign, bits_from_int
from coreblocks.params.genparams import GenParams
from coreblocks.params.dependencies import DependencyManager, ListKey
from transactron.utils.dependencies import DependencyManager, ListKey
from coreblocks.params.fu_params import BlockComponentParams
from coreblocks.params.layouts import FetchLayouts, FuncUnitLayouts, CSRLayouts
from coreblocks.params.isa import Funct3, ExceptionCause
Expand Down
2 changes: 1 addition & 1 deletion coreblocks/structs_common/exception.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from amaranth import *
from coreblocks.params.dependencies import DependencyManager
from transactron.utils.dependencies import DependencyManager
from coreblocks.params.genparams import GenParams

from coreblocks.params.isa import ExceptionCause
Expand Down
2 changes: 1 addition & 1 deletion coreblocks/structs_common/interrupt_controller.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from amaranth import *
from coreblocks.params.dependencies import DependencyManager
from transactron.utils.dependencies import DependencyManager
from coreblocks.params.genparams import GenParams
from coreblocks.params.keys import AsyncInterruptInsertSignalKey, MretKey

Expand Down
9 changes: 1 addition & 8 deletions coreblocks/utils/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,7 @@
from transactron.utils._typing import HasElaborate


__all__ = ["FuncUnit", "FuncBlock", "Unifier"]


class Unifier(HasElaborate, Protocol):
method: Method

def __init__(self, targets: list[Method]):
...
__all__ = ["FuncUnit", "FuncBlock"]


class FuncUnit(HasElaborate, Protocol):
Expand Down
2 changes: 1 addition & 1 deletion test/fu/functional_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from coreblocks.params import GenParams
from coreblocks.params.configurations import test_core_config
from coreblocks.params.dependencies import DependencyManager
from transactron.utils.dependencies import DependencyManager
from coreblocks.params.fu_params import FunctionalComponentParams
from coreblocks.params.isa import Funct3, Funct7
from coreblocks.params.keys import AsyncInterruptInsertSignalKey, ExceptionReportKey
Expand Down
2 changes: 1 addition & 1 deletion test/lsu/test_dummylsu.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from coreblocks.params.configurations import test_core_config
from coreblocks.params.isa import *
from coreblocks.params.keys import ExceptionReportKey
from coreblocks.params.dependencies import DependencyManager
from transactron.utils.dependencies import DependencyManager
from coreblocks.params.layouts import ExceptionRegisterLayouts
from coreblocks.peripherals.wishbone import *
from test.common import TestbenchIO, TestCaseWithSimulator, def_method_mock
Expand Down
2 changes: 1 addition & 1 deletion test/lsu/test_pma.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from coreblocks.params.configurations import test_core_config
from coreblocks.params.isa import *
from coreblocks.params.keys import ExceptionReportKey
from coreblocks.params.dependencies import DependencyManager
from transactron.utils.dependencies import DependencyManager
from coreblocks.params.layouts import ExceptionRegisterLayouts
from coreblocks.peripherals.wishbone import *
from test.common import TestbenchIO, TestCaseWithSimulator, def_method_mock
Expand Down
2 changes: 1 addition & 1 deletion test/structs_common/test_csr.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from coreblocks.params.configurations import test_core_config
from coreblocks.params.layouts import ExceptionRegisterLayouts
from coreblocks.params.keys import AsyncInterruptInsertSignalKey, ExceptionReportKey
from coreblocks.params.dependencies import DependencyManager
from transactron.utils.dependencies import DependencyManager
from coreblocks.frontend.decoder import OpType

from ..common import *
Expand Down
40 changes: 40 additions & 0 deletions transactron/lib/dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from collections.abc import Callable

from .. import Method
from .transformers import Unifier
from ..utils.dependencies import *


__all__ = [
"DependencyManager",
"DependencyKey",
"SimpleKey",
"ListKey",
"UnifierKey"
]


class UnifierKey(DependencyKey["Method", tuple["Method", dict[str, "Unifier"]]]):
"""Base class for method unifier dependency keys.
Method unifier dependency keys are used to collect methods to be called by
some part of the core. As multiple modules may wish to be called, a method
unifier is used to present a single method interface to the caller, which
allows to customize the calling behavior.
"""

unifier: Callable[[list["Method"]], "Unifier"]

def __init_subclass__(cls, unifier: Callable[[list["Method"]], "Unifier"], **kwargs) -> None:
cls.unifier = unifier
return super().__init_subclass__(**kwargs)

def combine(self, data: list["Method"]) -> tuple["Method", dict[str, "Unifier"]]:
if len(data) == 1:
return data[0], {}
else:
unifiers: dict[str, Unifier] = {}
unifier_inst = self.unifier(data)
unifiers[self.__class__.__name__ + "_unifier"] = unifier_inst
method = unifier_inst.method
return method, unifiers
25 changes: 16 additions & 9 deletions transactron/lib/transformers.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
from abc import ABC
from amaranth import *

from transactron.utils.transactron_helpers import get_src_loc
from ..core import *
from ..core import RecordDict
from ..utils import SrcLoc
from typing import Optional
from typing import Optional, Protocol
from collections.abc import Callable
from transactron.utils import ValueLike, assign, AssignType, ModuleLike
from transactron.utils import ValueLike, assign, AssignType, ModuleLike, HasElaborate
from .connectors import Forwarder, ManyToOneConnectTrans, ConnectTrans
from .simultaneous import condition

__all__ = [
"Transformer",
"Unifier",
"MethodMap",
"MethodFilter",
"MethodProduct",
Expand All @@ -23,7 +23,7 @@
]


class Transformer(ABC, Elaboratable):
class Transformer(HasElaborate, Protocol):
"""Method transformer abstract class.
Method transformers construct a new method which utilizes other methods.
Expand All @@ -49,7 +49,14 @@ def use(self, m: ModuleLike):
return self.method


class MethodMap(Transformer):
class Unifier(Transformer, Protocol):
method: Method

def __init__(self, targets: list[Method]):
...


class MethodMap(Elaboratable, Transformer):
"""Bidirectional map for methods.
Takes a target method and creates a transformed method which calls the
Expand Down Expand Up @@ -110,7 +117,7 @@ def _(arg):
return m


class MethodFilter(Transformer):
class MethodFilter(Elaboratable, Transformer):
"""Method filter.
Takes a target method and creates a method which calls the target method
Expand Down Expand Up @@ -192,7 +199,7 @@ def _(arg):
return m


class MethodProduct(Transformer):
class MethodProduct(Elaboratable, Unifier):
def __init__(
self,
targets: list[Method],
Expand Down Expand Up @@ -246,7 +253,7 @@ def _(arg):
return m


class MethodTryProduct(Transformer):
class MethodTryProduct(Elaboratable, Unifier):
def __init__(
self,
targets: list[Method],
Expand Down Expand Up @@ -304,7 +311,7 @@ def _(arg):
return m


class Collector(Transformer):
class Collector(Elaboratable, Unifier):
"""Single result collector.
Creates method that collects results of many methods with identical
Expand Down
2 changes: 2 additions & 0 deletions transactron/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
from .assign import * # noqa: F401
from .amaranth_ext import * # noqa: F401
from .transactron_helpers import * # noqa: F401
from .dependencies import * # noqa: F401
from .depcache import * # noqa: F401
44 changes: 44 additions & 0 deletions transactron/utils/depcache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from typing import TypeVar, Type, Any

from transactron.utils import make_hashable

__all__ = ["DependentCache"]

T = TypeVar("T")


class DependentCache:
"""
Cache for classes, that depend on the `DependentCache` class itself.
Cached classes may accept one positional argument in the constructor, where this `DependentCache` class will
be passed. Classes may define any number keyword arguments in the constructor and separate cache entry will
be created for each set of the arguments.
Methods
-------
get: T, **kwargs -> T
Gets class `cls` from cache. Caches `cls` reference if this is the first call for it.
Optionally accepts `kwargs` for additional arguments in `cls` constructor.
"""

def __init__(self):
self._depcache: dict[tuple[Type, Any], Type] = {}

def get(self, cls: Type[T], **kwargs) -> T:
cache_key = make_hashable(kwargs)
v = self._depcache.get((cls, cache_key), None)
if v is None:
positional_count = cls.__init__.__code__.co_argcount

# first positional arg is `self` field, second may be `DependentCache`
if positional_count > 2:
raise KeyError(f"Too many positional arguments in {cls!r} constructor")

if positional_count > 1:
v = cls(self, **kwargs)
else:
v = cls(**kwargs)
self._depcache[(cls, cache_key)] = v
return v
Loading

0 comments on commit f242864

Please sign in to comment.