Skip to content

Commit 8ab1c03

Browse files
committed
[AXI4] Add concurrent read/write count to subordinate-like ops
AI-assisted-by: Claude Opus 5
1 parent 18a9d3a commit 8ab1c03

3 files changed

Lines changed: 28 additions & 14 deletions

File tree

include/circt/Dialect/AXI4/AXI4Ops.td

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,25 @@ def AbstractSubordinateOp : AXI4Op<"abstract_subordinate"> {
6767
let summary = "A stand-alone AXI4 subordinate endpoint";
6868
let description = [{
6969
Models a subordinate endpoint with no concrete implementation, for abstract
70-
network modelling. Takes the upstream `!axi4.port` it responds to.
70+
network modelling. Takes the upstream `!axi4.port` it responds to, and the
71+
number of writes and reads it can handle concurrently.
7172

7273
Example:
7374
```mlir
74-
axi4.abstract_subordinate %clk, %rst_ni, %mgr : !axi4.port<...>
75+
axi4.abstract_subordinate %clk, %rst_ni, %mgr
76+
concurrent_writes 4 concurrent_reads 4 : !axi4.port<...>
7577
```
7678
}];
7779

78-
let arguments = (ins ClockType:$clock, I1:$reset, PortType:$upstream);
80+
let arguments = (ins ClockType:$clock, I1:$reset, PortType:$upstream,
81+
I32Attr:$concurrent_writes, I32Attr:$concurrent_reads);
7982

80-
let assemblyFormat =
81-
"$clock `,` $reset `,` $upstream attr-dict `:` qualified(type($upstream))";
83+
let assemblyFormat = [{
84+
$clock `,` $reset `,` $upstream
85+
`concurrent_writes` $concurrent_writes
86+
`concurrent_reads` $concurrent_reads
87+
attr-dict `:` qualified(type($upstream))
88+
}];
8289
}
8390

8491
def ChannelStructsToPortOp : AXI4ChannelStructOp<"channel_structs_to_port",
@@ -124,8 +131,9 @@ def PortToChannelStructsOp : AXI4ChannelStructOp<"port_to_channel_structs"> {
124131
let summary = "Converts an AXI4 port to a HW expression of an AXI4 interface";
125132
let description = [{
126133
Bridges from an `!axi4.port` to a HW dialect expression of an AXI4
127-
interface. Takes the port, the AW, W and AR channel readys, and the B and R
128-
payloads and valids; returns the AW, W and AR payloads and valids, and the
134+
interface. Takes the port, the AW, W and AR channel readys, the B and R
135+
payloads and valids, and the number of writes and reads the interface can
136+
handle concurrently; returns the AW, W and AR payloads and valids, and the
129137
B and R readys.
130138

131139
Example:
@@ -134,6 +142,7 @@ def PortToChannelStructsOp : AXI4ChannelStructOp<"port_to_channel_structs"> {
134142
axi4.port_to_channel_structs %clk, %rst_ni, %port
135143
aw %aw_ready w %w_ready b %b, %b_valid
136144
ar %ar_ready r %r, %r_valid
145+
concurrent_writes 4 concurrent_reads 4
137146
: !axi4.port<...>
138147
```
139148
}];
@@ -142,7 +151,9 @@ def PortToChannelStructsOp : AXI4ChannelStructOp<"port_to_channel_structs"> {
142151
I1:$aw_ready, I1:$w_ready,
143152
StructType:$b, I1:$b_valid,
144153
I1:$ar_ready,
145-
StructType:$r, I1:$r_valid);
154+
StructType:$r, I1:$r_valid,
155+
I32Attr:$concurrent_writes,
156+
I32Attr:$concurrent_reads);
146157
let results = (outs StructType:$aw, I1:$aw_valid,
147158
StructType:$w, I1:$w_valid,
148159
I1:$b_ready,
@@ -153,6 +164,8 @@ def PortToChannelStructsOp : AXI4ChannelStructOp<"port_to_channel_structs"> {
153164
$clock `,` $reset `,` $port
154165
`aw` $aw_ready `w` $w_ready `b` $b `,` $b_valid
155166
`ar` $ar_ready `r` $r `,` $r_valid
167+
`concurrent_writes` $concurrent_writes
168+
`concurrent_reads` $concurrent_reads
156169
attr-dict `:` qualified(type($port))
157170
}];
158171
}

test/Dialect/AXI4/basic.mlir

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@
9999
hw.module @AbstractEndpoints(in %clk : !seq.clock, in %rst_ni : i1) {
100100
// CHECK: %[[MGR:.+]] = axi4.abstract_manager %clk, %rst_ni {a} : !axi4.port<addr_width = 32, data_width = 64, write_id_width = 5, read_id_width = 3, user_width = 4, windows = <<base = 0x0, last = 0xfff, burst_specs = <<fixed, len = 4>>>>, outstanding_writes = 4, outstanding_reads = 4>
101101
%mgr = axi4.abstract_manager %clk, %rst_ni {a} : !port
102-
// CHECK: axi4.abstract_subordinate %clk, %rst_ni, %[[MGR]] {b} : !axi4.port<addr_width = 32, data_width = 64, write_id_width = 5, read_id_width = 3, user_width = 4, windows = <<base = 0x0, last = 0xfff, burst_specs = <<fixed, len = 4>>>>, outstanding_writes = 4, outstanding_reads = 4>
103-
axi4.abstract_subordinate %clk, %rst_ni, %mgr {b} : !port
102+
// CHECK: axi4.abstract_subordinate %clk, %rst_ni, %[[MGR]] concurrent_writes 2 concurrent_reads 3 {b} : !axi4.port<addr_width = 32, data_width = 64, write_id_width = 5, read_id_width = 3, user_width = 4, windows = <<base = 0x0, last = 0xfff, burst_specs = <<fixed, len = 4>>>>, outstanding_writes = 4, outstanding_reads = 4>
103+
axi4.abstract_subordinate %clk, %rst_ni, %mgr concurrent_writes 2 concurrent_reads 3 {b} : !port
104104
}
105105

106106
// CHECK-LABEL: hw.module @Subordinate
@@ -123,9 +123,10 @@ hw.module @Manager(in %clk : !seq.clock, in %rst_ni : i1, in %port : !port,
123123
in %b : !b, in %b_valid : i1,
124124
in %ar_ready : i1,
125125
in %r : !r, in %r_valid : i1) {
126-
// CHECK: %aw, %aw_valid, %w, %w_valid, %b_ready, %ar, %ar_valid, %r_ready = axi4.port_to_channel_structs %clk, %rst_ni, %port aw %aw_ready w %w_ready b %b, %b_valid ar %ar_ready r %r, %r_valid : !axi4.port<addr_width = 32, data_width = 64, write_id_width = 5, read_id_width = 3, user_width = 4, windows = <<base = 0x0, last = 0xfff, burst_specs = <<fixed, len = 4>>>>, outstanding_writes = 4, outstanding_reads = 4>
126+
// CHECK: %aw, %aw_valid, %w, %w_valid, %b_ready, %ar, %ar_valid, %r_ready = axi4.port_to_channel_structs %clk, %rst_ni, %port aw %aw_ready w %w_ready b %b, %b_valid ar %ar_ready r %r, %r_valid concurrent_writes 2 concurrent_reads 3 : !axi4.port<addr_width = 32, data_width = 64, write_id_width = 5, read_id_width = 3, user_width = 4, windows = <<base = 0x0, last = 0xfff, burst_specs = <<fixed, len = 4>>>>, outstanding_writes = 4, outstanding_reads = 4>
127127
%aw, %aw_valid, %w, %w_valid, %b_ready, %ar, %ar_valid, %r_ready =
128128
axi4.port_to_channel_structs %clk, %rst_ni, %port
129129
aw %aw_ready w %w_ready b %b, %b_valid
130-
ar %ar_ready r %r, %r_valid : !port
130+
ar %ar_ready r %r, %r_valid
131+
concurrent_writes 2 concurrent_reads 3 : !port
131132
}

test/Dialect/AXI4/errors.mlir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@
100100
hw.module @Fanout(in %clk : !seq.clock, in %rst_ni : i1) {
101101
// expected-error @below {{'axi4.abstract_manager' op port result must have at most one use; route through an 'axi4.xbar' to fan out to multiple endpoints}}
102102
%mgr = axi4.abstract_manager %clk, %rst_ni : !port
103-
axi4.abstract_subordinate %clk, %rst_ni, %mgr : !port
104-
axi4.abstract_subordinate %clk, %rst_ni, %mgr : !port
103+
axi4.abstract_subordinate %clk, %rst_ni, %mgr concurrent_writes 4 concurrent_reads 4 : !port
104+
axi4.abstract_subordinate %clk, %rst_ni, %mgr concurrent_writes 4 concurrent_reads 4 : !port
105105
}
106106

107107
// -----

0 commit comments

Comments
 (0)