-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Autumn cleaning part 2 - split transactron/lib.py (kuznia-rdzeni/core…
- Loading branch information
1 parent
20b43d6
commit 2ea5084
Showing
9 changed files
with
1,208 additions
and
1,187 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from .connectors import * # noqa: F401 | ||
from .buttons import * # noqa: F401 | ||
from .adapters import * # noqa: F401 | ||
from .transformers import * # noqa: F401 | ||
from .reqres import * # noqa: F401 | ||
from .storage import * # noqa: F401 | ||
from .simultaneous import * # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
from amaranth import * | ||
from ..core import * | ||
from ..core import SignalBundle | ||
from typing import Optional | ||
|
||
__all__ = [ | ||
"AdapterBase", | ||
"AdapterTrans", | ||
"Adapter", | ||
] | ||
|
||
|
||
class AdapterBase(Elaboratable): | ||
data_in: Record | ||
data_out: Record | ||
|
||
def __init__(self, iface: Method): | ||
self.iface = iface | ||
self.en = Signal() | ||
self.done = Signal() | ||
|
||
def debug_signals(self) -> SignalBundle: | ||
return [self.en, self.done, self.data_in, self.data_out] | ||
|
||
|
||
class AdapterTrans(AdapterBase): | ||
"""Adapter transaction. | ||
Creates a transaction controlled by plain Amaranth signals. Allows to | ||
expose a method to plain Amaranth code, including testbenches. | ||
Attributes | ||
---------- | ||
en: Signal, in | ||
Activates the transaction (sets the `request` signal). | ||
done: Signal, out | ||
Signals that the transaction is performed (returns the `grant` | ||
signal). | ||
data_in: Record, in | ||
Data passed to the `iface` method. | ||
data_out: Record, out | ||
Data returned from the `iface` method. | ||
""" | ||
|
||
def __init__(self, iface: Method): | ||
""" | ||
Parameters | ||
---------- | ||
iface: Method | ||
The method to be called by the transaction. | ||
""" | ||
super().__init__(iface) | ||
self.data_in = Record.like(iface.data_in) | ||
self.data_out = Record.like(iface.data_out) | ||
|
||
def elaborate(self, platform): | ||
m = TModule() | ||
|
||
# this forces data_in signal to appear in VCD dumps | ||
data_in = Signal.like(self.data_in) | ||
m.d.comb += data_in.eq(self.data_in) | ||
|
||
with Transaction(name=f"AdapterTrans_{self.iface.name}").body(m, request=self.en): | ||
data_out = self.iface(m, data_in) | ||
m.d.top_comb += self.data_out.eq(data_out) | ||
m.d.comb += self.done.eq(1) | ||
|
||
return m | ||
|
||
|
||
class Adapter(AdapterBase): | ||
"""Adapter method. | ||
Creates a method controlled by plain Amaranth signals. One of the | ||
possible uses is to mock a method in a testbench. | ||
Attributes | ||
---------- | ||
en: Signal, in | ||
Activates the method (sets the `ready` signal). | ||
done: Signal, out | ||
Signals that the method is called (returns the `run` signal). | ||
data_in: Record, in | ||
Data returned from the defined method. | ||
data_out: Record, out | ||
Data passed as argument to the defined method. | ||
""" | ||
|
||
def __init__(self, *, name: Optional[str] = None, i: MethodLayout = (), o: MethodLayout = ()): | ||
""" | ||
Parameters | ||
---------- | ||
i: record layout | ||
The input layout of the defined method. | ||
o: record layout | ||
The output layout of the defined method. | ||
""" | ||
super().__init__(Method(name=name, i=i, o=o)) | ||
self.data_in = Record.like(self.iface.data_out) | ||
self.data_out = Record.like(self.iface.data_in) | ||
|
||
def elaborate(self, platform): | ||
m = TModule() | ||
|
||
# this forces data_in signal to appear in VCD dumps | ||
data_in = Signal.like(self.data_in) | ||
m.d.comb += data_in.eq(self.data_in) | ||
|
||
@def_method(m, self.iface, ready=self.en) | ||
def _(arg): | ||
m.d.top_comb += self.data_out.eq(arg) | ||
m.d.comb += self.done.eq(1) | ||
return data_in | ||
|
||
return m |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
from amaranth import * | ||
from ..core import * | ||
|
||
__all__ = ["ClickIn", "ClickOut"] | ||
|
||
|
||
class ClickIn(Elaboratable): | ||
"""Clicked input. | ||
Useful for interactive simulations or FPGA button/switch interfaces. | ||
On a rising edge (tested synchronously) of `btn`, the `get` method | ||
is enabled, which returns the data present on `dat` at the time. | ||
Inputs are synchronized. | ||
Attributes | ||
---------- | ||
get: Method | ||
The method for retrieving data from the input. Accepts an empty | ||
argument, returns a `Record`. | ||
btn: Signal, in | ||
The button input. | ||
dat: Record, in | ||
The data input. | ||
""" | ||
|
||
def __init__(self, layout: MethodLayout): | ||
""" | ||
Parameters | ||
---------- | ||
layout: record layout | ||
The data format for the input. | ||
""" | ||
self.get = Method(o=layout) | ||
self.btn = Signal() | ||
self.dat = Record(layout) | ||
|
||
def elaborate(self, platform): | ||
m = TModule() | ||
|
||
btn1 = Signal() | ||
btn2 = Signal() | ||
dat1 = Signal.like(self.dat) | ||
m.d.sync += btn1.eq(self.btn) | ||
m.d.sync += btn2.eq(btn1) | ||
m.d.sync += dat1.eq(self.dat) | ||
get_ready = Signal() | ||
get_data = Signal.like(self.dat) | ||
|
||
@def_method(m, self.get, ready=get_ready) | ||
def _(): | ||
m.d.sync += get_ready.eq(0) | ||
return get_data | ||
|
||
with m.If(~btn2 & btn1): | ||
m.d.sync += get_ready.eq(1) | ||
m.d.sync += get_data.eq(dat1) | ||
|
||
return m | ||
|
||
|
||
class ClickOut(Elaboratable): | ||
"""Clicked output. | ||
Useful for interactive simulations or FPGA button/LED interfaces. | ||
On a rising edge (tested synchronously) of `btn`, the `put` method | ||
is enabled, which, when called, changes the value of the `dat` signal. | ||
Attributes | ||
---------- | ||
put: Method | ||
The method for retrieving data from the input. Accepts a `Record`, | ||
returns empty result. | ||
btn: Signal, in | ||
The button input. | ||
dat: Record, out | ||
The data output. | ||
""" | ||
|
||
def __init__(self, layout: MethodLayout): | ||
""" | ||
Parameters | ||
---------- | ||
layout: record layout | ||
The data format for the output. | ||
""" | ||
self.put = Method(i=layout) | ||
self.btn = Signal() | ||
self.dat = Record(layout) | ||
|
||
def elaborate(self, platform): | ||
m = TModule() | ||
|
||
btn1 = Signal() | ||
btn2 = Signal() | ||
m.d.sync += btn1.eq(self.btn) | ||
m.d.sync += btn2.eq(btn1) | ||
|
||
@def_method(m, self.put, ready=~btn2 & btn1) | ||
def _(arg): | ||
m.d.sync += self.dat.eq(arg) | ||
|
||
return m |
Oops, something went wrong.