Skip to content

Csl wrapper

csl_wrapper

i16 = builtin.IntegerType(16) module-attribute

CSL_WRAPPER = Dialect('csl_wrapper', [ImportOp, ModuleOp, YieldOp], [ParamAttribute]) module-attribute

ParamAttribute dataclass

Bases: ParametrizedAttribute

Represents a module parameter that needs to have a type, and may have a value.

Source code in xdsl/dialects/csl/csl_wrapper.py
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
@irdl_attr_definition
class ParamAttribute(ParametrizedAttribute):
    """
    Represents a module parameter that needs to have a type, and may have a value.
    """

    name = "csl_wrapper.param"

    key: StringAttr
    value: IntegerAttr[IntegerType] | NoneAttr
    type: IntegerType

    def print_parameters(self, printer: Printer) -> None:
        with printer.in_angle_brackets():
            printer.print_string_literal(self.key.data)
            if not isinstance(self.value, NoneAttr):
                printer.print_string(" default=")
                printer.print_attribute(self.value)
            else:
                printer.print_string(" : ")
                printer.print_attribute(self.type)

    @classmethod
    def parse_parameters(cls, parser: AttrParser) -> Sequence[Attribute]:
        with parser.in_angle_brackets():
            key = StringAttr(parser.parse_str_literal())
            if parser.parse_optional_keyword("default"):
                parser.parse_punctuation("=")
                val = parser.parse_attribute()
                assert isa(val, IntegerAttr)
                assert isinstance(val.type, IntegerType)
                type = val.type
            else:
                parser.parse_punctuation(":")
                val = NoneAttr()
                type = parser.parse_type()
        return key, val, type

    def verify(self) -> None:
        super().verify()
        if not isinstance(self.value, NoneAttr):
            if self.value.type != self.type:
                raise VerifyException(
                    f"Value expected to be of type {self.type}, found {self.value.type}"
                )

name = 'csl_wrapper.param' class-attribute instance-attribute

key: StringAttr instance-attribute

value: IntegerAttr[IntegerType] | NoneAttr instance-attribute

type: IntegerType instance-attribute

print_parameters(printer: Printer) -> None

Source code in xdsl/dialects/csl/csl_wrapper.py
58
59
60
61
62
63
64
65
66
def print_parameters(self, printer: Printer) -> None:
    with printer.in_angle_brackets():
        printer.print_string_literal(self.key.data)
        if not isinstance(self.value, NoneAttr):
            printer.print_string(" default=")
            printer.print_attribute(self.value)
        else:
            printer.print_string(" : ")
            printer.print_attribute(self.type)

parse_parameters(parser: AttrParser) -> Sequence[Attribute] classmethod

Source code in xdsl/dialects/csl/csl_wrapper.py
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
@classmethod
def parse_parameters(cls, parser: AttrParser) -> Sequence[Attribute]:
    with parser.in_angle_brackets():
        key = StringAttr(parser.parse_str_literal())
        if parser.parse_optional_keyword("default"):
            parser.parse_punctuation("=")
            val = parser.parse_attribute()
            assert isa(val, IntegerAttr)
            assert isinstance(val.type, IntegerType)
            type = val.type
        else:
            parser.parse_punctuation(":")
            val = NoneAttr()
            type = parser.parse_type()
    return key, val, type

verify() -> None

Source code in xdsl/dialects/csl/csl_wrapper.py
84
85
86
87
88
89
90
def verify(self) -> None:
    super().verify()
    if not isinstance(self.value, NoneAttr):
        if self.value.type != self.type:
            raise VerifyException(
                f"Value expected to be of type {self.type}, found {self.value.type}"
            )

ImportOp

Bases: IRDLOperation

Lightweight wrapper around csl.import_module that allows specifying field names directly and removes the need for handling structs or setting up struct operands.

Where existing structs need to be used in the import, they can be passed with an empty field name. This will concatenate them all together.

Named fields and empty fields can be used in the same import

Source code in xdsl/dialects/csl/csl_wrapper.py
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
@irdl_op_definition
class ImportOp(IRDLOperation):
    """
    Lightweight wrapper around `csl.import_module` that allows specifying field names directly
    and removes the need for handling structs or setting up struct operands.

    Where existing structs need to be used in the import, they can be passed
    with an empty field name. This will concatenate them all together.

    Named fields and empty fields can be used in the same import
    """

    name = "csl_wrapper.import"

    ops = var_operand_def()
    module = prop_def(StringAttr)
    fields = prop_def(ArrayAttr[StringAttr])
    result = result_def(csl.ImportedModuleType)

    def __init__(
        self, module: str, field_name_mapping: dict[str, Operation | SSAValue]
    ):
        ops: list[Operation | SSAValue] = []
        fields: list[StringAttr] = []
        for field, op in field_name_mapping.items():
            ops.append(op)
            fields.append(StringAttr(field))

        super().__init__(
            operands=[ops],
            properties={
                "module": StringAttr(module),
                "fields": ArrayAttr(fields),
            },
            result_types=[csl.ImportedModuleType()],
        )

    def verify_(self) -> None:
        if len(self.fields) != len(self.ops):
            raise VerifyException("Number of fields does not match number of operands")

name = 'csl_wrapper.import' class-attribute instance-attribute

ops = var_operand_def() class-attribute instance-attribute

module = prop_def(StringAttr) class-attribute instance-attribute

fields = prop_def(ArrayAttr[StringAttr]) class-attribute instance-attribute

result = result_def(csl.ImportedModuleType) class-attribute instance-attribute

__init__(module: str, field_name_mapping: dict[str, Operation | SSAValue])

Source code in xdsl/dialects/csl/csl_wrapper.py
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
def __init__(
    self, module: str, field_name_mapping: dict[str, Operation | SSAValue]
):
    ops: list[Operation | SSAValue] = []
    fields: list[StringAttr] = []
    for field, op in field_name_mapping.items():
        ops.append(op)
        fields.append(StringAttr(field))

    super().__init__(
        operands=[ops],
        properties={
            "module": StringAttr(module),
            "fields": ArrayAttr(fields),
        },
        result_types=[csl.ImportedModuleType()],
    )

verify_() -> None

Source code in xdsl/dialects/csl/csl_wrapper.py
130
131
132
def verify_(self) -> None:
    if len(self.fields) != len(self.ops):
        raise VerifyException("Number of fields does not match number of operands")

ModuleOp

Bases: IRDLOperation

Wrapper class that manages initialisation of layout and program module.

Specified properties will be lowered to module params (csl.param). As such, all properties are passed as BlockArgs to the layout_module and program_module region. The order in which properties are specified is important and must match the order of the block args.

Additionally, any value yielded by the layout_module is passed as a block arg (lowered to csl.param) to the program module. Order is important here as well. The layout module's yield op should be lowered to @set_tile_code, while the program module's yield op should be discarded.

The layout module has two additional block args x and y as part of the @set_tile_code loop nest. Operations using these args need to be lowered to the correct place in the loop nest.

The layout module has the following args (in order): * set_tile_code params: x and y * general params: width and height followed by everything specified in params

The program module has the following args (in order): * general params: width and height followed by everything specified in params * params from layout: everything defined by layout_yield_op.fields

Source code in xdsl/dialects/csl/csl_wrapper.py
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
@irdl_op_definition
class ModuleOp(IRDLOperation):
    """
    Wrapper class that manages initialisation of layout and program module.

    Specified properties will be lowered to module params (`csl.param`). As such, all properties
    are passed as BlockArgs to the `layout_module` and `program_module` region. The order in which
    properties are specified is important and must match the order of the block args.

    Additionally, any value yielded by the `layout_module` is passed as a block arg (lowered to `csl.param`)
    to the program module. Order is important here as well. The layout module's `yield` op should be lowered to
    `@set_tile_code`, while the program module's `yield` op should be discarded.

    The layout module has two additional block args `x` and `y` as part of the `@set_tile_code` loop nest.
    Operations using these args need to be lowered to the correct place in the loop nest.

    The layout module has the following args (in order):
      * set_tile_code params:  `x` and `y`
      * general params:        `width` and `height` followed by everything specified in `params`

    The program module has the following args (in order):
      * general params:        `width` and `height` followed by everything specified in `params`
      * params from layout:    everything defined by `layout_yield_op.fields`
    """

    name = "csl_wrapper.module"

    width = prop_def(IntegerAttr[IntegerType])
    height = prop_def(IntegerAttr[IntegerType])
    program_name = opt_prop_def(StringAttr)
    target = prop_def(StringAttr)
    params = prop_def(ArrayAttr[ParamAttribute])

    layout_module = region_def("single_block")
    program_module = region_def("single_block")

    def __init__(
        self,
        width: int | IntegerAttr[IntegerType],
        height: int | IntegerAttr[IntegerType],
        target: csl.Target | StringAttr,
        params: (
            dict[str, IntegerAttr[IntegerType]] | Sequence[ParamAttribute] | None
        ) = None,
    ):
        if not isinstance(width, IntegerAttr):
            width = IntegerAttr(width, i16)
        if not isinstance(height, IntegerAttr):
            height = IntegerAttr(height, i16)
        if not isinstance(target, StringAttr):
            target = StringAttr(target)
        if params is None:
            params = []
        elif isinstance(params, dict):
            params = [
                ParamAttribute(StringAttr(name), val, val.type)
                for name, val in params.items()
            ]
        params_attr = ArrayAttr(params)

        super().__init__(
            properties={
                "width": width,
                "height": height,
                "params": params_attr,
                "target": target,
            },
            regions=[
                Region(
                    Block(
                        arg_types=itertools.chain(
                            [i16] * 4,
                            (param.type for param in params),
                        )
                    )
                ),
                Region(
                    Block(
                        arg_types=itertools.chain(
                            [i16] * 2,
                            (param.type for param in params),
                        )
                    )
                ),
            ],
        )

    def update_program_block_args(
        self,
        yield_args: Iterable[tuple[str, SSAValue]] | None = None,
    ):
        """
        Update `program_module` BlockArguments by adding
        1. yield op fields (pass None to enable automated retrieval, pass empty list to add no yield op fields)
        2. additional exported symbols
        """
        assert (
            len(self.program_module.block.args)
            == len(self.layout_module.block.args) - 2
            # minus two as layout_module has additional x and y args
        ), (
            "program_module block args should only contain args from properties when calling this function"
        )

        if yield_args is None:
            yield_args = self.layout_yield_op.items()

        for name, op in yield_args:
            arg = self.program_module.block.insert_arg(
                op.type, len(self.program_module.block.args)
            )
            arg.name_hint = name

    def verify_(self):
        # verify that names are unique
        names: set[str] = {"x", "y", "width", "height"}
        for param in self.params.data:
            if param.key.data in names:
                raise VerifyException(f"Duplicate name in parameters: {param.key.data}")
            names.add(param.key.data)

        # verify that x, y, width, height are i16
        if not all(arg.type == i16 for arg in self.layout_module.block.args[:4]):
            raise VerifyException(
                "The first four arguments of the layout block (x, y, width, height) must be of type i16"
            )

        # verify that block args are of the right type for the provided params
        for arg, param in zip(
            self.layout_module.block.arg_types[4:],
            self.params,
            strict=True,
        ):
            if arg != param.type:
                raise ValueError(
                    f"Layout module block arg types do not match for arg {param.key} expected: {param.type} but got: "
                    f"{arg}. Block arg types must correspond to prop types (in order)"
                )

        # verify that the first two program block args (width, height) are correctly typed
        if not all(arg.type == i16 for arg in self.program_module.block.args[:2]):
            raise VerifyException(
                "The first two arguments of the program block (width, height) must be of type i16"
            )

        # verify that params and yielded arguments are typed correctly
        # these may be followed by input-output symbols which we cannot verify, therefore setting `strict=False`
        for got, (name, exp) in zip(
            self.program_module.block.arg_types[2:],
            itertools.chain(
                (
                    (param.key.data, cast(Attribute, param.type))
                    for param in self.params
                ),
                ((key, val.type) for key, val in self.layout_yield_op.items()),
            ),
            strict=False,
        ):
            if exp != got:
                raise VerifyException(
                    f"Program module block arg types do not match for arg {name} expected: {exp} but got: {got}. "
                    f"Block arg types must correspond to prop types and layout yield result types (in order)"
                )

    def get_layout_param(self, name: str) -> BlockArgument:
        """
        Retrieve layout block arg for name that is x, y, or one of the properties
        """
        # check static params:
        if name in ("x", "y", "width", "height"):
            return self.layout_module.block.args[
                ("x", "y", "width", "height").index(name)
            ]
        # check module params
        for i, param in enumerate(self.params):
            if param.key.data == name:
                return self.layout_module.block.args[4 + i]
        # not found = value error
        raise ValueError(f"{name} does not refer to a block arg of this layout_module")

    def get_program_param(self, name: str) -> BlockArgument:
        """Retrieve program block arg for name that is one of the properties or a param set up by layout yield"""
        # check static params
        if name in ("width", "height"):
            return self.program_module.block.args[("width", "height").index(name)]
        # check module params
        for i, param in enumerate(self.params):
            if param.key.data == name:
                return self.program_module.block.args[2 + i]
        # check yielded params:
        for i, (key, _) in enumerate(self.layout_yield_op.items()):
            if key == name:
                return self.program_module.block.args[2 + len(self.params) + i]
        # not found = value error
        raise ValueError(f"{name} does not refer to a block arg of this program_module")

    def get_param_value(self, name: str) -> IntegerAttr[IntegerType]:
        """Retrieve the value of a named op param."""
        if name == "width":
            return self.width
        elif name == "height":
            return self.height
        res = NoneAttr()
        for param in self.params.data:
            if name == param.key.data:
                res = param.value
        if isinstance(res, NoneAttr):
            raise ValueError(f"Parameter name is unknown or has no value: {name}")
        return res

    @property
    def layout_yield_op(self) -> YieldOp:
        """
        Get the yield op from the layout module. Used in various places.
        """
        return cast(YieldOp, self.layout_module.block.last_op)

    @property
    def exported_symbols(self) -> Sequence[BlockArgument]:
        """
        Get the exported symbols.
        """
        return self.program_module.block.args[
            2 + len(self.params) + len(self.layout_yield_op.fields) :
        ]

    def get_program_import(self, name: str) -> ImportOp:
        """Get top-level import op in the program_module"""
        for op in self.program_module.ops:
            if isinstance(op, ImportOp) and op.module.data == name:
                return op
        raise ValueError(f"Cannot get program_module import of {name}")

name = 'csl_wrapper.module' class-attribute instance-attribute

width = prop_def(IntegerAttr[IntegerType]) class-attribute instance-attribute

height = prop_def(IntegerAttr[IntegerType]) class-attribute instance-attribute

program_name = opt_prop_def(StringAttr) class-attribute instance-attribute

target = prop_def(StringAttr) class-attribute instance-attribute

params = prop_def(ArrayAttr[ParamAttribute]) class-attribute instance-attribute

layout_module = region_def('single_block') class-attribute instance-attribute

program_module = region_def('single_block') class-attribute instance-attribute

layout_yield_op: YieldOp property

Get the yield op from the layout module. Used in various places.

exported_symbols: Sequence[BlockArgument] property

Get the exported symbols.

__init__(width: int | IntegerAttr[IntegerType], height: int | IntegerAttr[IntegerType], target: csl.Target | StringAttr, params: dict[str, IntegerAttr[IntegerType]] | Sequence[ParamAttribute] | None = None)

Source code in xdsl/dialects/csl/csl_wrapper.py
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
def __init__(
    self,
    width: int | IntegerAttr[IntegerType],
    height: int | IntegerAttr[IntegerType],
    target: csl.Target | StringAttr,
    params: (
        dict[str, IntegerAttr[IntegerType]] | Sequence[ParamAttribute] | None
    ) = None,
):
    if not isinstance(width, IntegerAttr):
        width = IntegerAttr(width, i16)
    if not isinstance(height, IntegerAttr):
        height = IntegerAttr(height, i16)
    if not isinstance(target, StringAttr):
        target = StringAttr(target)
    if params is None:
        params = []
    elif isinstance(params, dict):
        params = [
            ParamAttribute(StringAttr(name), val, val.type)
            for name, val in params.items()
        ]
    params_attr = ArrayAttr(params)

    super().__init__(
        properties={
            "width": width,
            "height": height,
            "params": params_attr,
            "target": target,
        },
        regions=[
            Region(
                Block(
                    arg_types=itertools.chain(
                        [i16] * 4,
                        (param.type for param in params),
                    )
                )
            ),
            Region(
                Block(
                    arg_types=itertools.chain(
                        [i16] * 2,
                        (param.type for param in params),
                    )
                )
            ),
        ],
    )

update_program_block_args(yield_args: Iterable[tuple[str, SSAValue]] | None = None)

Update program_module BlockArguments by adding 1. yield op fields (pass None to enable automated retrieval, pass empty list to add no yield op fields) 2. additional exported symbols

Source code in xdsl/dialects/csl/csl_wrapper.py
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
def update_program_block_args(
    self,
    yield_args: Iterable[tuple[str, SSAValue]] | None = None,
):
    """
    Update `program_module` BlockArguments by adding
    1. yield op fields (pass None to enable automated retrieval, pass empty list to add no yield op fields)
    2. additional exported symbols
    """
    assert (
        len(self.program_module.block.args)
        == len(self.layout_module.block.args) - 2
        # minus two as layout_module has additional x and y args
    ), (
        "program_module block args should only contain args from properties when calling this function"
    )

    if yield_args is None:
        yield_args = self.layout_yield_op.items()

    for name, op in yield_args:
        arg = self.program_module.block.insert_arg(
            op.type, len(self.program_module.block.args)
        )
        arg.name_hint = name

verify_()

Source code in xdsl/dialects/csl/csl_wrapper.py
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
def verify_(self):
    # verify that names are unique
    names: set[str] = {"x", "y", "width", "height"}
    for param in self.params.data:
        if param.key.data in names:
            raise VerifyException(f"Duplicate name in parameters: {param.key.data}")
        names.add(param.key.data)

    # verify that x, y, width, height are i16
    if not all(arg.type == i16 for arg in self.layout_module.block.args[:4]):
        raise VerifyException(
            "The first four arguments of the layout block (x, y, width, height) must be of type i16"
        )

    # verify that block args are of the right type for the provided params
    for arg, param in zip(
        self.layout_module.block.arg_types[4:],
        self.params,
        strict=True,
    ):
        if arg != param.type:
            raise ValueError(
                f"Layout module block arg types do not match for arg {param.key} expected: {param.type} but got: "
                f"{arg}. Block arg types must correspond to prop types (in order)"
            )

    # verify that the first two program block args (width, height) are correctly typed
    if not all(arg.type == i16 for arg in self.program_module.block.args[:2]):
        raise VerifyException(
            "The first two arguments of the program block (width, height) must be of type i16"
        )

    # verify that params and yielded arguments are typed correctly
    # these may be followed by input-output symbols which we cannot verify, therefore setting `strict=False`
    for got, (name, exp) in zip(
        self.program_module.block.arg_types[2:],
        itertools.chain(
            (
                (param.key.data, cast(Attribute, param.type))
                for param in self.params
            ),
            ((key, val.type) for key, val in self.layout_yield_op.items()),
        ),
        strict=False,
    ):
        if exp != got:
            raise VerifyException(
                f"Program module block arg types do not match for arg {name} expected: {exp} but got: {got}. "
                f"Block arg types must correspond to prop types and layout yield result types (in order)"
            )

get_layout_param(name: str) -> BlockArgument

Retrieve layout block arg for name that is x, y, or one of the properties

Source code in xdsl/dialects/csl/csl_wrapper.py
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
def get_layout_param(self, name: str) -> BlockArgument:
    """
    Retrieve layout block arg for name that is x, y, or one of the properties
    """
    # check static params:
    if name in ("x", "y", "width", "height"):
        return self.layout_module.block.args[
            ("x", "y", "width", "height").index(name)
        ]
    # check module params
    for i, param in enumerate(self.params):
        if param.key.data == name:
            return self.layout_module.block.args[4 + i]
    # not found = value error
    raise ValueError(f"{name} does not refer to a block arg of this layout_module")

get_program_param(name: str) -> BlockArgument

Retrieve program block arg for name that is one of the properties or a param set up by layout yield

Source code in xdsl/dialects/csl/csl_wrapper.py
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
def get_program_param(self, name: str) -> BlockArgument:
    """Retrieve program block arg for name that is one of the properties or a param set up by layout yield"""
    # check static params
    if name in ("width", "height"):
        return self.program_module.block.args[("width", "height").index(name)]
    # check module params
    for i, param in enumerate(self.params):
        if param.key.data == name:
            return self.program_module.block.args[2 + i]
    # check yielded params:
    for i, (key, _) in enumerate(self.layout_yield_op.items()):
        if key == name:
            return self.program_module.block.args[2 + len(self.params) + i]
    # not found = value error
    raise ValueError(f"{name} does not refer to a block arg of this program_module")

get_param_value(name: str) -> IntegerAttr[IntegerType]

Retrieve the value of a named op param.

Source code in xdsl/dialects/csl/csl_wrapper.py
331
332
333
334
335
336
337
338
339
340
341
342
343
def get_param_value(self, name: str) -> IntegerAttr[IntegerType]:
    """Retrieve the value of a named op param."""
    if name == "width":
        return self.width
    elif name == "height":
        return self.height
    res = NoneAttr()
    for param in self.params.data:
        if name == param.key.data:
            res = param.value
    if isinstance(res, NoneAttr):
        raise ValueError(f"Parameter name is unknown or has no value: {name}")
    return res

get_program_import(name: str) -> ImportOp

Get top-level import op in the program_module

Source code in xdsl/dialects/csl/csl_wrapper.py
361
362
363
364
365
366
def get_program_import(self, name: str) -> ImportOp:
    """Get top-level import op in the program_module"""
    for op in self.program_module.ops:
        if isinstance(op, ImportOp) and op.module.data == name:
            return op
    raise ValueError(f"Cannot get program_module import of {name}")

YieldOp

Bases: IRDLOperation

Layout module yield ops should be lowered to @set_tile_code and must specify fields. Program module yield ops have no particular meaning and specify fields here is permitted but undefined.

Source code in xdsl/dialects/csl/csl_wrapper.py
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
@irdl_op_definition
class YieldOp(IRDLOperation):
    """
    Layout module `yield` ops should be lowered to `@set_tile_code` and must specify `fields`.
    Program module `yield` ops have no particular meaning and specify `fields` here is permitted but undefined.
    """

    name = "csl_wrapper.yield"

    values = var_operand_def(Attribute)
    fields = prop_def(ArrayAttr[StringAttr])

    traits = lazy_traits_def(
        lambda: (
            IsTerminator(),
            HasParent(ModuleOp),
            Pure(),
        )
    )

    def __init__(
        self,
        operands: Sequence[SSAValue | Operation],
        args: Sequence[str] | ArrayAttr[StringAttr],
    ):
        if not isinstance(args, ArrayAttr):
            args = ArrayAttr(StringAttr(arg) for arg in args)
        super().__init__(
            operands=[operands],
            properties={
                "fields": args,
            },
        )

    @staticmethod
    def from_field_name_mapping(field_name_mapping: dict[str, Operation | SSAValue]):
        operands: list[Operation | SSAValue] = []
        attributes: list[StringAttr] = []
        for attr, op in field_name_mapping.items():
            attributes.append(StringAttr(attr))
            operands.append(op)
        return YieldOp(operands, ArrayAttr[StringAttr](attributes))

    def verify_(self) -> None:
        if len(self.fields) != len(self.operands):
            raise VerifyException("Number of fields must match the number of operands")

    def items(self) -> Iterable[tuple[str, SSAValue]]:
        assert self.fields is not None
        return zip((elm.data for elm in self.fields.data), self.operands, strict=True)

name = 'csl_wrapper.yield' class-attribute instance-attribute

values = var_operand_def(Attribute) class-attribute instance-attribute

fields = prop_def(ArrayAttr[StringAttr]) class-attribute instance-attribute

traits = lazy_traits_def(lambda: (IsTerminator(), HasParent(ModuleOp), Pure())) class-attribute instance-attribute

__init__(operands: Sequence[SSAValue | Operation], args: Sequence[str] | ArrayAttr[StringAttr])

Source code in xdsl/dialects/csl/csl_wrapper.py
389
390
391
392
393
394
395
396
397
398
399
400
401
def __init__(
    self,
    operands: Sequence[SSAValue | Operation],
    args: Sequence[str] | ArrayAttr[StringAttr],
):
    if not isinstance(args, ArrayAttr):
        args = ArrayAttr(StringAttr(arg) for arg in args)
    super().__init__(
        operands=[operands],
        properties={
            "fields": args,
        },
    )

from_field_name_mapping(field_name_mapping: dict[str, Operation | SSAValue]) staticmethod

Source code in xdsl/dialects/csl/csl_wrapper.py
403
404
405
406
407
408
409
410
@staticmethod
def from_field_name_mapping(field_name_mapping: dict[str, Operation | SSAValue]):
    operands: list[Operation | SSAValue] = []
    attributes: list[StringAttr] = []
    for attr, op in field_name_mapping.items():
        attributes.append(StringAttr(attr))
        operands.append(op)
    return YieldOp(operands, ArrayAttr[StringAttr](attributes))

verify_() -> None

Source code in xdsl/dialects/csl/csl_wrapper.py
412
413
414
def verify_(self) -> None:
    if len(self.fields) != len(self.operands):
        raise VerifyException("Number of fields must match the number of operands")

items() -> Iterable[tuple[str, SSAValue]]

Source code in xdsl/dialects/csl/csl_wrapper.py
416
417
418
def items(self) -> Iterable[tuple[str, SSAValue]]:
    assert self.fields is not None
    return zip((elm.data for elm in self.fields.data), self.operands, strict=True)