You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -29,26 +29,28 @@ On the interface class, we can then implement `.send()` and `.recv()` methods li
29
29
```python
30
30
classStreamInterface(PureInterface):
31
31
asyncdefrecv(self, sim):
32
-
awaitself.ready.set(1)
32
+
awaitsim.set(self.ready, 1)
33
33
await sim.tick().until(self.valid)
34
34
35
-
value =awaitself.data.get()
35
+
value =awaitsim.get(self.data)
36
36
37
37
await sim.tick()
38
-
awaitself.ready.set(0)
38
+
awaitsim.set(self.ready, 0)
39
39
40
40
return value
41
41
42
42
asyncdefsend(self, sim, value):
43
-
awaitself.data.set(value)
43
+
awaitsim.set(self.data, value)
44
44
45
-
awaitself.valid.set(1)
45
+
awaitsim.set(self.valid, 1)
46
46
await sim.tick().until(self.ready)
47
47
48
48
await sim.tick()
49
-
awaitself.valid.set(0)
49
+
awaitsim.set(self.valid, 0)
50
50
```
51
51
52
+
`await sim.get()` and `await sim.set()` replaces the existing operations `yield signal` and `yield signal.eq()` respectively.
53
+
52
54
`sim.tick()` replaces the existing `Tick()`. It returns a trigger object that either can be awaited directly, or made conditional through `.until()`.
53
55
54
56
Using this stream interface, let's consider a colorspace converter accepting a stream of RGB values and outputting a stream of YUV values:
@@ -77,7 +79,7 @@ async def testbench(sim):
77
79
await test_rgb(sim, 255, 255, 255)
78
80
```
79
81
80
-
Since `.send()` and `.recv()` invokes `.get()` and `.set()` that a value castable (here `data.View`) can implement in a suitable manner, it is general enough to work for streams with arbitrary shapes.
82
+
Since `.send()` and `.recv()` invokes `sim.get()` and `sim.set()` that in turn will invoke the appropriate value conversions for a value castable (here `data.View`), it is general enough to work for streams with arbitrary shapes.
81
83
82
84
`Tick()` and `Delay()` are replaced by `sim.tick()` and `sim.delay()` respectively.
83
85
In addition, `sim.changed()` is introduced that allows creating triggers from arbitrary signals.
@@ -108,13 +110,21 @@ The following `Simulator` methods have their signatures updated:
108
110
109
111
The new optional named argument `passive` registers the testbench as passive when true.
110
112
111
-
Both methods are updated to accept an async function passed as `process`. When the function passed to `process` accepts an argument named `sim`, it will be passed a simulator context.
113
+
Both methods are updated to accept an async function passed as `process`.
114
+
The async function must accept a named argument `sim`, which will be passed a simulator context.
112
115
113
116
The simulator context have the following methods:
114
-
-`delay(interval=None)`
117
+
-`get(signal)`
118
+
- Returns the value of `signal` when awaited.
119
+
When `signal` is a value-castable, the value will be converted through `.from_bits()`. (Pending RFC #51)
120
+
-`set(signal, value)`
121
+
- Set `signal` to `value` when awaited.
122
+
When `signal` is a value-castable, the value will be converted through `.const()`.
123
+
-`delay(interval)`
115
124
- Return a trigger object for advancing simulation by `interval` seconds.
116
-
-`tick(domain="sync")`
125
+
-`tick(domain="sync", *, context=None)`
117
126
- Return a trigger object for advancing simulation by one tick of `domain`.
127
+
When an elaboratable is passed to `context`, `domain` will be resolved from its perspective.
118
128
-`changed(signal, value=None)`
119
129
- Return a trigger object for advancing simulation until `signal` is changed to `value`. `None` is a wildcard and will trigger on any change.
120
130
-`active()`
@@ -124,24 +134,27 @@ The simulator context have the following methods:
124
134
125
135
A trigger object has the following methods:
126
136
-`until(condition)`
127
-
- Repeat the trigger until `condition` is true. If `condition` is initially true, `await` will return immediately without advancing simulation.
137
+
- Repeat the trigger until `condition` is true.
138
+
`condition` is an arbitrary Amaranth expression.
139
+
If `condition` is initially true, `await` will return immediately without advancing simulation.
128
140
129
-
`Value`, `data.View` and `enum.EnumView` have `.get()` and `.set()` methods added.
141
+
~~`Value`, `data.View` and `enum.EnumView` have `.get()` and `.set()` methods added.~~
130
142
131
143
`Tick()`, `Delay()`, `Active()` and `Passive()` as well as the ability to pass generator coroutines as `process` are deprecated and removed in a future version.
132
144
133
145
## Drawbacks
134
146
[drawbacks]: #drawbacks
135
147
136
-
Reserves two new names on `Value` and value castables. Increase in API surface area and complexity. Churn.
148
+
-~~Reserves two new names on `Value` and value castables~~
- Do nothing. Keep the existing interface, add `Changed()` alongside `Delay()` and `Tick()`, use `yield from` when calling functions.
142
156
143
-
- Don't introduce `.get()` and `.set()`. Instead require a value castable and the return value of its `.eq()` to be awaitable so `await value` and `await value.eq(foo)` is possible.
144
-
157
+
-~~Don't introduce `.get()` and `.set()`. Instead require a value castable and the return value of its `.eq()` to be awaitable so `await value` and `await value.eq(foo)` is possible.~~
145
158
146
159
## Prior art
147
160
[prior-art]: #prior-art
@@ -156,9 +169,11 @@ Other python libraries like [cocotb](https://docs.cocotb.org/en/stable/coroutine
156
169
Simulating sync logic with async reset could be another.
157
170
What would be a good syntax to combine triggers?
158
171
- Is there any other functionality that's natural to have on the simulator context?
0 commit comments