From d2caf6af7c764c94d5619cd96284d00eeb53d419 Mon Sep 17 00:00:00 2001 From: Lekcyjna <309016@uwr.edu.pl> Date: Fri, 6 Oct 2023 18:31:36 +0200 Subject: [PATCH] Split transactions to connectors and transformers. --- transactron/lib/__init__.py | 1 - transactron/lib/connectors.py | 66 +++++++++++++ transactron/lib/transactions.py | 161 -------------------------------- transactron/lib/transformers.py | 92 +++++++++++++++++- 4 files changed, 155 insertions(+), 165 deletions(-) delete mode 100644 transactron/lib/transactions.py diff --git a/transactron/lib/__init__.py b/transactron/lib/__init__.py index f4d3b8a23..1caa56d21 100644 --- a/transactron/lib/__init__.py +++ b/transactron/lib/__init__.py @@ -2,7 +2,6 @@ from .buttons import * # noqa: F401 from .adapters import * # noqa: F401 from .transformers import * # noqa: F401 -from .transactions import * # noqa: F401 from .reqres import * # noqa: F401 from .storage import * # noqa: F401 from .simultaneous import * # noqa: F401 diff --git a/transactron/lib/connectors.py b/transactron/lib/connectors.py index 8d4c580d4..3b9b18b83 100644 --- a/transactron/lib/connectors.py +++ b/transactron/lib/connectors.py @@ -6,6 +6,8 @@ "FIFO", "Forwarder", "Connect", + "ConnectTrans", + "ManyToOneConnectTrans", ] @@ -184,3 +186,67 @@ def _(arg): return read_value return m + + +class ConnectTrans(Elaboratable): + """Simple connecting transaction. + + Takes two methods and creates a transaction which calls both of them. + Result of the first method is connected to the argument of the second, + and vice versa. Allows easily connecting methods with compatible + layouts. + """ + + def __init__(self, method1: Method, method2: Method): + """ + Parameters + ---------- + method1: Method + First method. + method2: Method + Second method. + """ + self.method1 = method1 + self.method2 = method2 + + def elaborate(self, platform): + m = TModule() + + with Transaction().body(m): + data1 = Record.like(self.method1.data_out) + data2 = Record.like(self.method2.data_out) + + m.d.top_comb += data1.eq(self.method1(m, data2)) + m.d.top_comb += data2.eq(self.method2(m, data1)) + + return m + + +class ManyToOneConnectTrans(Elaboratable): + """Many-to-one method connection. + + Connects each of a set of methods to another method using separate + transactions. Equivalent to a set of `ConnectTrans`. + """ + + def __init__(self, *, get_results: list[Method], put_result: Method): + """ + Parameters + ---------- + get_results: list[Method] + Methods to be connected to the `put_result` method. + put_result: Method + Common method for each of the connections created. + """ + self.get_results = get_results + self.m_put_result = put_result + + self.count = len(self.get_results) + + def elaborate(self, platform): + m = TModule() + + for i in range(self.count): + m.submodules[f"ManyToOneConnectTrans_input_{i}"] = ConnectTrans(self.m_put_result, self.get_results[i]) + + return m diff --git a/transactron/lib/transactions.py b/transactron/lib/transactions.py deleted file mode 100644 index 4364dce3d..000000000 --- a/transactron/lib/transactions.py +++ /dev/null @@ -1,161 +0,0 @@ -from amaranth import * -from ..core import * -from ..core import RecordDict -from typing import Optional, Callable -from . import transformers - -__all__ = [ - "ConnectTrans", - "ConnectAndTransformTrans", - "CatTrans", - "ManyToOneConnectTrans", -] - - -class ConnectTrans(Elaboratable): - """Simple connecting transaction. - - Takes two methods and creates a transaction which calls both of them. - Result of the first method is connected to the argument of the second, - and vice versa. Allows easily connecting methods with compatible - layouts. - """ - - def __init__(self, method1: Method, method2: Method): - """ - Parameters - ---------- - method1: Method - First method. - method2: Method - Second method. - """ - self.method1 = method1 - self.method2 = method2 - - def elaborate(self, platform): - m = TModule() - - with Transaction().body(m): - data1 = Record.like(self.method1.data_out) - data2 = Record.like(self.method2.data_out) - - m.d.top_comb += data1.eq(self.method1(m, data2)) - m.d.top_comb += data2.eq(self.method2(m, data1)) - - return m - - -class ConnectAndTransformTrans(Elaboratable): - """Connecting transaction with transformations. - - Behaves like `ConnectTrans`, but modifies the transferred data using - functions or `Method`s. Equivalent to a combination of - `ConnectTrans` and `MethodTransformer`. The transformation - functions take two parameters, a `Module` and the `Record` being - transformed. - """ - - def __init__( - self, - method1: Method, - method2: Method, - *, - i_fun: Optional[Callable[[TModule, Record], RecordDict]] = None, - o_fun: Optional[Callable[[TModule, Record], RecordDict]] = None, - ): - """ - Parameters - ---------- - method1: Method - First method. - method2: Method - Second method, and the method being transformed. - i_fun: function or Method, optional - Input transformation (`method1` to `method2`). - o_fun: function or Method, optional - Output transformation (`method2` to `method1`). - """ - self.method1 = method1 - self.method2 = method2 - self.i_fun = i_fun or (lambda _, x: x) - self.o_fun = o_fun or (lambda _, x: x) - - def elaborate(self, platform): - m = TModule() - - m.submodules.transformer = transformer = transformers.MethodTransformer( - self.method2, - i_transform=(self.method1.data_out.layout, self.i_fun), - o_transform=(self.method1.data_in.layout, self.o_fun), - ) - m.submodules.connect = ConnectTrans(self.method1, transformer.method) - - return m - - -class ManyToOneConnectTrans(Elaboratable): - """Many-to-one method connection. - - Connects each of a set of methods to another method using separate - transactions. Equivalent to a set of `ConnectTrans`. - """ - - def __init__(self, *, get_results: list[Method], put_result: Method): - """ - Parameters - ---------- - get_results: list[Method] - Methods to be connected to the `put_result` method. - put_result: Method - Common method for each of the connections created. - """ - self.get_results = get_results - self.m_put_result = put_result - - self.count = len(self.get_results) - - def elaborate(self, platform): - m = TModule() - - for i in range(self.count): - m.submodules[f"ManyToOneConnectTrans_input_{i}"] = ConnectTrans(self.m_put_result, self.get_results[i]) - - return m - - -class CatTrans(Elaboratable): - """Concatenating transaction. - - Concatenates the results of two methods and passes the result to the - third method. - """ - - def __init__(self, src1: Method, src2: Method, dst: Method): - """ - Parameters - ---------- - src1: Method - First input method. - src2: Method - Second input method. - dst: Method - The method which receives the concatenation of the results of input - methods. - """ - self.src1 = src1 - self.src2 = src2 - self.dst = dst - - def elaborate(self, platform): - m = TModule() - - with Transaction().body(m): - sdata1 = self.src1(m) - sdata2 = self.src2(m) - ddata = Record.like(self.dst.data_in) - self.dst(m, ddata) - - m.d.comb += ddata.eq(Cat(sdata1, sdata2)) - - return m diff --git a/transactron/lib/transformers.py b/transactron/lib/transformers.py index 28bd82255..23c385b53 100644 --- a/transactron/lib/transformers.py +++ b/transactron/lib/transformers.py @@ -3,8 +3,7 @@ from ..core import RecordDict from typing import Optional, Callable, Tuple from coreblocks.utils import ValueLike, assign, AssignType -from . import transactions -from .connectors import Forwarder +from .connectors import Forwarder, ManyToOneConnectTrans, ConnectTrans __all__ = [ "MethodTransformer", @@ -12,6 +11,8 @@ "MethodProduct", "MethodTryProduct", "Collector", + "CatTrans", + "ConnectAndTransformTrans", ] @@ -260,10 +261,95 @@ def elaborate(self, platform): m.submodules.forwarder = forwarder = Forwarder(self.method.data_out.layout) - m.submodules.connect = transactions.ManyToOneConnectTrans( + m.submodules.connect = ManyToOneConnectTrans( get_results=[get for get in self.method_list], put_result=forwarder.write ) self.method.proxy(m, forwarder.read) return m + + +class CatTrans(Elaboratable): + """Concatenating transaction. + + Concatenates the results of two methods and passes the result to the + third method. + """ + + def __init__(self, src1: Method, src2: Method, dst: Method): + """ + Parameters + ---------- + src1: Method + First input method. + src2: Method + Second input method. + dst: Method + The method which receives the concatenation of the results of input + methods. + """ + self.src1 = src1 + self.src2 = src2 + self.dst = dst + + def elaborate(self, platform): + m = TModule() + + with Transaction().body(m): + sdata1 = self.src1(m) + sdata2 = self.src2(m) + ddata = Record.like(self.dst.data_in) + self.dst(m, ddata) + + m.d.comb += ddata.eq(Cat(sdata1, sdata2)) + + return m + + +class ConnectAndTransformTrans(Elaboratable): + """Connecting transaction with transformations. + + Behaves like `ConnectTrans`, but modifies the transferred data using + functions or `Method`s. Equivalent to a combination of + `ConnectTrans` and `MethodTransformer`. The transformation + functions take two parameters, a `Module` and the `Record` being + transformed. + """ + + def __init__( + self, + method1: Method, + method2: Method, + *, + i_fun: Optional[Callable[[TModule, Record], RecordDict]] = None, + o_fun: Optional[Callable[[TModule, Record], RecordDict]] = None, + ): + """ + Parameters + ---------- + method1: Method + First method. + method2: Method + Second method, and the method being transformed. + i_fun: function or Method, optional + Input transformation (`method1` to `method2`). + o_fun: function or Method, optional + Output transformation (`method2` to `method1`). + """ + self.method1 = method1 + self.method2 = method2 + self.i_fun = i_fun or (lambda _, x: x) + self.o_fun = o_fun or (lambda _, x: x) + + def elaborate(self, platform): + m = TModule() + + m.submodules.transformer = transformer = MethodTransformer( + self.method2, + i_transform=(self.method1.data_out.layout, self.i_fun), + o_transform=(self.method1.data_in.layout, self.o_fun), + ) + m.submodules.connect = ConnectTrans(self.method1, transformer.method) + + return m