Skip to content

Commit 7cf46ef

Browse files
committed
[xls][mlir] Support XLS fifo properties/config in MLIR channels.
This also adds support for converting these properties to/from XLS, and updates different passes (array_to_bits, index_type_conversion) to ensure these attributes are maintained when channels are modified. Finally, these properties are also exposed for sproc channels, and the proc elaboration pass is updated to assign said properties to all eproc channels that are generated from an sproc channel.
1 parent a45f782 commit 7cf46ef

File tree

13 files changed

+230
-30
lines changed

13 files changed

+230
-30
lines changed

xls/contrib/mlir/IR/xls_ops.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,9 @@ ParseResult SchanOp::parse(OpAsmParser& parser, OperationState& result) {
620620
result.addAttribute("type", TypeAttr::get(type));
621621
result.types.push_back(SchanType::get(parser.getContext(), type, false));
622622
result.types.push_back(SchanType::get(parser.getContext(), type, true));
623-
return success();
623+
624+
return failure(
625+
parser.parseOptionalAttrDictWithKeyword(result.attributes).failed());
624626
}
625627

626628
void SchanOp::print(OpAsmPrinter& printer) {
@@ -630,6 +632,9 @@ void SchanOp::print(OpAsmPrinter& printer) {
630632
printer << '(';
631633
printer.printString(getName());
632634
printer << ')';
635+
printer << ") ";
636+
printer.printOptionalAttrDictWithKeyword(getOperation()->getAttrs(),
637+
{"type", "name"});
633638
}
634639

635640
void SprocOp::print(OpAsmPrinter& printer) {

xls/contrib/mlir/IR/xls_ops.td

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,75 @@ def Xls_TranslationLinkage : Xls_Attr<"TranslationLinkage"> {
135135
let attrName = "xls.translation_linkage";
136136
}
137137

138+
def Xls_FlopKindNone : I32EnumAttrCase<"kNone", 0, "none"> {
139+
let summary = "No flop.";
140+
let description = [{
141+
Adds no buffer to the input/output.
142+
143+
See https://google.github.io/xls/codegen_options/#io-behavior for more information.
144+
}];
145+
}
146+
def Xls_FlopKindFlop : I32EnumAttrCase<"kFlop", 1, "flop"> {
147+
let summary = "Basic flop.";
148+
let description = [{
149+
Adds a pipeline stage to the input/output. This is essentially a single-element FIFO
150+
151+
See https://google.github.io/xls/codegen_options/#io-behavior for more information.
152+
}];
153+
}
154+
def Xls_FlopKindSkid : I32EnumAttrCase<"kSkid", 2, "skid"> {
155+
let summary = "Skip flop.";
156+
let description = [{
157+
Adds a skid buffer to the input/output. The skid buffer can hold 2 entries.
158+
159+
See https://google.github.io/xls/codegen_options/#io-behavior for more information.
160+
}];
161+
}
162+
def Xls_FlopKindZeroLatency : I32EnumAttrCase<"kZeroLatency", 3, "zero-latency"> {
163+
let summary = "Zero-latency flop.";
164+
let description = [{
165+
Adds a zero-latency buffer to the input/output. This is essentially a
166+
single-element FIFO with bypass.
167+
168+
See https://google.github.io/xls/codegen_options/#io-behavior for more information.
169+
}];
170+
}
171+
def Xls_FlopKind : I32EnumAttr<"FlopKind", "XLS flop kind",
172+
[Xls_FlopKindNone, Xls_FlopKindFlop, Xls_FlopKindSkid, Xls_FlopKindZeroLatency]> {
173+
let genSpecializedAttr = 0;
174+
let cppNamespace = "::mlir::xls";
175+
}
176+
def Xls_FlopKindAttr : EnumAttr<Xls_Dialect, Xls_FlopKind, "flop_kind"> {
177+
let summary = "Channel flop/buffer kind.";
178+
let description = [{
179+
The inputs/outputs of procs/blocks can optionally be fitted with one of a
180+
number of buffer types. This is specified on the channel connected to this
181+
proc input/output, using the `input_flop_kind` and `output_flop_kind`
182+
property.
183+
184+
See https://google.github.io/xls/codegen_options/#io-behavior for more information.
185+
}];
186+
}
187+
188+
def Xls_FifoConfig : Xls_Attr<"FifoConfig"> {
189+
let summary = "FIFO Configuration Attribute";
190+
let description = [{
191+
Definies the properties of the physical FIFO to be instantiated from
192+
an (internal) channel.
193+
}];
194+
195+
let parameters = (ins
196+
"int64_t":$fifo_depth,
197+
"bool":$bypass,
198+
"bool":$register_push_outputs,
199+
"bool":$register_pop_outputs
200+
);
201+
202+
let mnemonic = "fifo_config";
203+
204+
let assemblyFormat = "`<` struct(params) `>`";
205+
}
206+
138207
class GetShapeSplat<string name> :
139208
StrFunc<"getShapeSplat($" # name # ".getType())">;
140209

@@ -1626,6 +1695,9 @@ def Xls_ChanOp : Xls_Op<"chan", [
16261695
let arguments = (ins
16271696
SymbolNameAttr:$sym_name,
16281697
TypeAttr:$type,
1698+
OptionalAttr<Xls_FifoConfig>: $fifo_config,
1699+
OptionalAttr<Xls_FlopKindAttr>: $input_flop_kind,
1700+
OptionalAttr<Xls_FlopKindAttr>: $output_flop_kind,
16291701
DefaultValuedAttr<BoolAttr, "true">:$send_supported,
16301702
DefaultValuedAttr<BoolAttr, "true">:$recv_supported
16311703
);
@@ -1653,7 +1725,6 @@ def Xls_ChanOp : Xls_Op<"chan", [
16531725
void setArgAttrsAttr(ArrayAttr) { return; }
16541726
void setResAttrsAttr(ArrayAttr) { return; }
16551727
}];
1656-
16571728
}
16581729

16591730
def Xls_InstantiateEprocOp : Xls_Op<"instantiate_eproc", [DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
@@ -1763,7 +1834,10 @@ def Xls_SchanOp : Xls_Op<"schan", [Pure, HasParent<"SprocOp">]> {
17631834
}];
17641835
let arguments = (ins
17651836
StrAttr:$name,
1766-
TypeAttr:$type
1837+
TypeAttr:$type,
1838+
OptionalAttr<Xls_FifoConfig>: $fifo_config,
1839+
OptionalAttr<Xls_FlopKindAttr>: $input_flop_kind,
1840+
OptionalAttr<Xls_FlopKindAttr>: $output_flop_kind
17671841
);
17681842
let results = (outs
17691843
Xls_SchanType:$out,
@@ -1774,7 +1848,8 @@ def Xls_SchanOp : Xls_Op<"schan", [Pure, HasParent<"SprocOp">]> {
17741848
OpBuilder<(ins "::mlir::StringRef":$name, "::mlir::Type":$element_type), [{
17751849
auto inChanTy = SchanType::get($_builder.getContext(), element_type, /*isInput=*/true);
17761850
auto outChanTy = SchanType::get($_builder.getContext(), element_type, /*isInput=*/false);
1777-
build($_builder, $_state, ::mlir::TypeRange{outChanTy, inChanTy}, name, element_type);
1851+
// TODO(jpienaar): Remove unecessary default args once they are generated automatically.
1852+
build($_builder, $_state, ::mlir::TypeRange{outChanTy, inChanTy}, name, element_type, /*fifo_config=*/nullptr, /*input_flop_kind=*/nullptr, /*output_flop_kind=*/nullptr);
17781853
}]>
17791854
];
17801855
}

xls/contrib/mlir/testdata/array_to_bits.mlir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ func.func @tensor_empty() -> !xls.array<4 x i32> attributes {xls = true} {
215215
return %0 : !xls.array<4 x i32>
216216
}
217217

218-
// CHECK-LABEL: xls.chan @mychan : i24
219-
xls.chan @mychan : !xls.array<3 x i8>
218+
// CHECK-LABEL: xls.chan @mychan {fifo_config = #xls.fifo_config<fifo_depth = 1, bypass = true, register_push_outputs = true, register_pop_outputs = false>} : i24
219+
xls.chan @mychan {fifo_config = #xls.fifo_config<fifo_depth = 1, bypass = true, register_push_outputs = true, register_pop_outputs = false>} : !xls.array<3 x i8>
220220

221221
// CHECK-LABEL: xls.eproc @eproc(
222222
// CHECK-SAME: %[[VAL_0:.*]]: i32) zeroinitializer {

xls/contrib/mlir/testdata/index_type_conversion.mlir

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func.func @forloop(%arg0: i32, %arg1: i8, %arg2: i9) -> i32 attributes {xls = tr
164164
return %0 : i32
165165
}
166166

167-
// INDEX32-LABEL: xls.chan @mychan : i32
168-
// INDEX64-LABEL: xls.chan @mychan : i64
169-
xls.chan @mychan : index
167+
// INDEX32-LABEL: xls.chan @mychan {fifo_config = #xls.fifo_config<fifo_depth = 1, bypass = true, register_push_outputs = true, register_pop_outputs = false>} : i32
168+
// INDEX64-LABEL: xls.chan @mychan {fifo_config = #xls.fifo_config<fifo_depth = 1, bypass = true, register_push_outputs = true, register_pop_outputs = false>} : i64
169+
xls.chan @mychan {fifo_config = #xls.fifo_config<fifo_depth = 1, bypass = true, register_push_outputs = true, register_pop_outputs = false>} : index
170170

xls/contrib/mlir/testdata/proc_elaboration.mlir

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: xls_opt -elaborate-procs -split-input-file %s 2>&1 | FileCheck %s
2-
// CHECK-LABEL: xls.chan @req : i32
3-
// CHECK-NEXT: xls.chan @resp : i32
2+
// CHECK-LABEL: xls.chan @req : i32
3+
// CHECK-NEXT: xls.chan @resp {fifo_config = #xls.fifo_config<fifo_depth = 1, bypass = true, register_push_outputs = true, register_pop_outputs = false>} : i32
44
// CHECK-NEXT: xls.chan @rom1_req : i32
55
// CHECK-NEXT: xls.chan @rom1_resp : i32
66
// CHECK-NEXT: xls.eproc @rom(%arg0: i32) zeroinitializer discardable {
@@ -45,7 +45,7 @@
4545
xls.sproc @fetch() top {
4646
spawns {
4747
%req_out, %req_in = xls.schan<i32>("req")
48-
%resp_out, %resp_in = xls.schan<i32>("resp")
48+
%resp_out, %resp_in = xls.schan<i32>("resp") attributes { fifo_config = #xls.fifo_config<fifo_depth = 1, bypass = true, register_push_outputs = true, register_pop_outputs = false> }
4949
xls.spawn @proxy(%req_in, %resp_out) : !xls.schan<i32, in>, !xls.schan<i32, out>
5050
xls.yield %req_out, %resp_in : !xls.schan<i32, out>, !xls.schan<i32, in>
5151
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: xls_translate --mlir-xls-to-xls %s -- 2>&1 | FileCheck %s
2+
3+
// CHECK-LABEL: chan ch_inp
4+
// CHECK-SAME: kind=streaming
5+
// CHECK-SAME: ops=receive_only
6+
xls.chan @ch_inp {send_supported = false} : i32
7+
8+
// CHECK-LABEL: chan ch_out
9+
// CHECK-SAME: kind=streaming
10+
// CHECK-SAME: ops=send_only
11+
// CHECK-SAME: fifo_depth=1
12+
// CHECK-SAME: bypass=true
13+
// CHECK-SAME: register_push_outputs=true
14+
// CHECK-SAME: register_pop_outputs=false
15+
xls.chan @ch_out {
16+
fifo_config = #xls.fifo_config<fifo_depth = 1, bypass = true, register_push_outputs = true, register_pop_outputs = false>,
17+
recv_supported = false
18+
} : i32
19+
20+
// CHECK: top proc eproc
21+
xls.eproc @eproc() zeroinitializer {
22+
%tok0 = xls.after_all : !xls.token
23+
%tok1, %val = xls.blocking_receive %tok0, @ch_inp : i32
24+
xls.send %tok1, %val, @ch_out : i32
25+
xls.yield
26+
}
27+

xls/contrib/mlir/testdata/translate_from_xls/proc.ir

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@ file_number 0 "./simple_proc.x"
77
// CHECK-LABEL: xls.chan @ch_inp {send_supported = false} : i32
88
chan ch_inp(bits[32], id=0, kind=streaming, ops=receive_only)
99

10-
// CHECK-LABEL: xls.chan @ch_out {recv_supported = false} : i32
11-
chan ch_out(bits[32], id=1, kind=streaming, ops=send_only)
10+
// CHECK-LABEL: xls.chan @ch_out {
11+
// CHECK-SAME: fifo_config = #xls.fifo_config<fifo_depth = 1, bypass = true, register_push_outputs = true, register_pop_outputs = false>,
12+
// CHECK-SAME: input_flop_kind = #xls<flop_kind zero-latency>,
13+
// CHECK-SAME: output_flop_kind = #xls<flop_kind skid>
14+
// CHECK-SAME: recv_supported = false
15+
// CHECK-SAME: } : i32
16+
chan ch_out(bits[32], id=1, kind=streaming, ops=send_only, flow_control=ready_valid, strictness=proven_mutually_exclusive, fifo_depth=1, bypass=true, register_push_outputs=true, register_pop_outputs=false, input_flop_kind=zero_latency, output_flop_kind=skid)
1217

1318
// CHECK-LABEL: xls.eproc @ident() zeroinitializer {
1419
// CHECK: xls.yield

xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.cc

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#include "xls/common/file/get_runfile_path.h"
6969
#include "xls/contrib/mlir/IR/xls_ops.h"
7070
#include "xls/ir/bits.h"
71+
#include "xls/ir/channel.h"
7172
#include "xls/ir/foreign_function.h"
7273
#include "xls/ir/foreign_function_data.pb.h"
7374
#include "xls/ir/nodes.h"
@@ -1409,6 +1410,19 @@ absl::StatusOr<::xls::Function*> wrapDslxFunctionIfNeeded(
14091410
return xlsFunc;
14101411
}
14111412

1413+
::xls::FlopKind convertFlopKind(FlopKind kind) {
1414+
switch (kind) {
1415+
case FlopKind::kNone:
1416+
return ::xls::FlopKind::kNone;
1417+
case FlopKind::kFlop:
1418+
return ::xls::FlopKind::kFlop;
1419+
case FlopKind::kSkid:
1420+
return ::xls::FlopKind::kSkid;
1421+
case FlopKind::kZeroLatency:
1422+
return ::xls::FlopKind::kZeroLatency;
1423+
}
1424+
}
1425+
14121426
FailureOr<std::unique_ptr<Package>> mlirXlsToXls(
14131427
Operation* op, llvm::StringRef dslx_search_path,
14141428
DslxPackageCache& dslx_cache) {
@@ -1453,7 +1467,30 @@ FailureOr<std::unique_ptr<Package>> mlirXlsToXls(
14531467
} else if (!chan_op.getRecvSupported()) {
14541468
kind = ::xls::ChannelOps::kSendOnly; // NOLINT
14551469
}
1456-
auto channel = package->CreateStreamingChannel(name, kind, xls_type);
1470+
1471+
std::optional<::xls::FifoConfig> fifo_config = std::nullopt;
1472+
if (auto mlir_fifo_config = chan_op.getFifoConfig()) {
1473+
fifo_config = ::xls::FifoConfig(
1474+
mlir_fifo_config->getFifoDepth(), mlir_fifo_config->getBypass(),
1475+
mlir_fifo_config->getRegisterPushOutputs(),
1476+
mlir_fifo_config->getRegisterPopOutputs());
1477+
}
1478+
1479+
std::optional<::xls::FlopKind> input_flop = std::nullopt;
1480+
std::optional<::xls::FlopKind> output_flop = std::nullopt;
1481+
if (auto attr = chan_op.getInputFlopKind()) {
1482+
input_flop = convertFlopKind(*attr);
1483+
}
1484+
if (auto attr = chan_op.getOutputFlopKind()) {
1485+
output_flop = convertFlopKind(*attr);
1486+
}
1487+
1488+
auto channel_config =
1489+
::xls::ChannelConfig(fifo_config, input_flop, output_flop);
1490+
1491+
auto channel = package->CreateStreamingChannel(name, kind, xls_type, {},
1492+
channel_config);
1493+
14571494
if (!channel.ok()) {
14581495
chan_op.emitOpError("failed to create streaming channel: ")
14591496
<< channel.status().message();

xls/contrib/mlir/tools/xls_translate/xls_translate_to_mlir.cc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "xls/ir/bits.h"
4646
#include "xls/ir/channel.h"
4747
#include "xls/ir/fileno.h"
48+
#include "xls/ir/channel.h"
4849
#include "xls/ir/function.h"
4950
#include "xls/ir/function_base.h"
5051
#include "xls/ir/lsb_or_msb.h"
@@ -1600,15 +1601,50 @@ absl::StatusOr<Operation*> translateProc(::xls::Proc& xls_proc,
16001601
// Channel Translation
16011602
//===----------------------------------------------------------------------===//
16021603

1604+
FlopKind convertFlopKind(::xls::FlopKind kind) {
1605+
switch (kind) {
1606+
case ::xls::FlopKind::kNone:
1607+
return FlopKind::kNone;
1608+
case ::xls::FlopKind::kFlop:
1609+
return FlopKind::kFlop;
1610+
case ::xls::FlopKind::kSkid:
1611+
return FlopKind::kSkid;
1612+
case ::xls::FlopKind::kZeroLatency:
1613+
return FlopKind::kZeroLatency;
1614+
}
1615+
}
1616+
16031617
absl::Status translateChannel(::xls::Channel& xls_chn, OpBuilder& builder,
16041618
MLIRContext* ctx, TranslationState& state) {
16051619
auto chn = builder.create<xls::ChanOp>(
16061620
builder.getUnknownLoc(),
16071621
/*name=*/builder.getStringAttr(xls_chn.name()),
16081622
/*type=*/TypeAttr::get(translateType(xls_chn.type(), builder, ctx)),
1623+
/*fifo_config=*/nullptr,
1624+
/*input_flop_kind=*/nullptr,
1625+
/*output_flop_kind=*/nullptr,
16091626
/*send_supported=*/builder.getBoolAttr(xls_chn.CanSend()),
16101627
/*recv_supported=*/builder.getBoolAttr(xls_chn.CanReceive()));
16111628

1629+
if (auto xls_streaming_chn =
1630+
dynamic_cast<::xls::StreamingChannel*>(&xls_chn)) {
1631+
auto xls_ch_config = xls_streaming_chn->channel_config();
1632+
if (auto xls_fifo_config = xls_ch_config.fifo_config()) {
1633+
chn.setFifoConfigAttr(FifoConfig::get(
1634+
ctx, xls_fifo_config->depth(), xls_fifo_config->bypass(),
1635+
xls_fifo_config->register_push_outputs(),
1636+
xls_fifo_config->register_pop_outputs()));
1637+
}
1638+
1639+
if (auto xls_input_flop = xls_ch_config.input_flop_kind()) {
1640+
chn.setInputFlopKind(convertFlopKind(*xls_input_flop));
1641+
}
1642+
1643+
if (auto xls_output_flop = xls_ch_config.output_flop_kind()) {
1644+
chn.setOutputFlopKind(convertFlopKind(*xls_output_flop));
1645+
}
1646+
}
1647+
16121648
return state.setChannel(std::string(xls_chn.name()),
16131649
SymbolRefAttr::get(chn.getNameAttr()));
16141650
}

xls/contrib/mlir/transforms/array_to_bits.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ class LegalizeChanOpPattern : public OpConversionPattern<ChanOp> {
147147
ChanOp op, OpAdaptor adaptor,
148148
ConversionPatternRewriter& rewriter) const override {
149149
(void)adaptor;
150-
auto newOp = rewriter.replaceOpWithNewOp<ChanOp>(
151-
op, op.getSymName(), typeConverter->convertType(op.getType()));
152-
newOp.setSendSupported(op.getSendSupported());
153-
newOp.setRecvSupported(op.getRecvSupported());
150+
rewriter.replaceOpWithNewOp<ChanOp>(
151+
op, op.getSymName(), typeConverter->convertType(op.getType()),
152+
op.getFifoConfigAttr(), op.getInputFlopKindAttr(), op.getOutputFlopKindAttr(),
153+
op.getSendSupported(), op.getRecvSupported());
154154
return success();
155155
}
156156
};

0 commit comments

Comments
 (0)