Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More parser operations #87

Merged
merged 5 commits into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions include/p4mlir/Dialect/P4HIR/P4HIR_Attrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,34 @@ def ParamDirection : I32EnumAttr<

def ParamDirAttr : EnumAttr<P4HIR_Dialect, ParamDirection, "dir">;

//===----------------------------------------------------------------------===//
// CtorParamAttr
//===----------------------------------------------------------------------===//

def P4HIR_CtorParamAttr : P4HIR_Attr<"CtorParam", "ctor_param", [TypedAttrInterface]> {
let summary = "An Attribute containing an constructor parameter value";
let description = [{
An attribute to represent constructor argument value for parsers and controls.
These values are compile-time constants but are not known until instantiation.
The attribute serves as a placeholder that could be resolved during instantiation.
}];
let parameters = (ins AttributeSelfTypeParameter<"">:$type,
"mlir::SymbolRefAttr":$parent,
"mlir::StringAttr":$name);

let builders = [
AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
"mlir::SymbolRefAttr":$parent,
"mlir::StringAttr":$name), [{
return $_get(type.getContext(), type, parent, name);
}]>
];
// let genVerifyDecl = 1;
let assemblyFormat = [{
`<` $parent `,` $name `>`
}];

}


#endif // P4MLIR_DIALECT_P4HIR_P4HIR_ATTRS_TD
110 changes: 109 additions & 1 deletion include/p4mlir/Dialect/P4HIR/P4HIR_Ops.td
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,7 @@ def FuncOp : P4HIR_Op<"func", [

let builders = [
OpBuilder<(ins "llvm::StringRef":$name, "FuncType":$type,
CArg<"bool", "false">:$isExternal,
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs,
CArg<"llvm::ArrayRef<mlir::DictionaryAttr>", "{}">:$argAttrs)>
];
Expand All @@ -699,7 +700,7 @@ def FuncOp : P4HIR_Op<"func", [
P4HIR::FuncType type,
llvm::ArrayRef<mlir::NamedAttribute> attrs = {},
llvm::ArrayRef<mlir::DictionaryAttr> argAttrs = {}) {
auto op = builder.create<FuncOp>(loc, name, type, attrs, argAttrs);
auto op = builder.create<FuncOp>(loc, name, type, false, attrs, argAttrs);
op.createEntryBlock();
op.setAction(true);
return op;
Expand Down Expand Up @@ -996,6 +997,113 @@ def TupleExtractOp : P4HIR_Op<"tuple_extract",
let hasVerifier = 1;
}

def InstantiateOp : P4HIR_Op<"instantiate",
[NoRegionArguments, CallOpInterface,
DeclareOpInterfaceMethods<SymbolUserOpInterface>,
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]> {
let summary = "constructor call operation";
let description = [{
Instantiate P4 object: extern, parser, control or package.

Example:

```mlir
// Instantiate a subparser
%sp = p4hir.instantiate @subparser() as "sp" : () -> !p4hir.parser<"subparser", (!empty)>
// Instantiate a subparser with ctor parameters
%false = p4hir.const #false
%sp2 = p4hir.instantiate @subparser2(%false) as "sp2" : (!p4hir.bool) -> !p4hir.parser<"subparser2", (!empty)>
...
```
}];

// TODO: Refine result types, refine parameter type (must be constants!)
let results = (outs P4ObjectType:$result);
let arguments = (ins FlatSymbolRefAttr:$callee, Variadic<AnyType>:$operands,
OptionalAttr<StrAttr>:$name);

// TODO: Add verifier
let hasVerifier = 0;

let extraClassDeclaration = [{
/// Get the argument operands to the called function.
mlir::OperandRange getArgOperands() {
return {arg_operand_begin(), arg_operand_end()};
}

mlir::MutableOperandRange getArgOperandsMutable() {
return getOperandsMutable();
}

operand_iterator arg_operand_begin() { return operand_begin(); }
operand_iterator arg_operand_end() { return operand_end(); }

/// Return the callee of this operation.
mlir::CallInterfaceCallable getCallableForCallee() {
return (*this)->getAttrOfType<mlir::SymbolRefAttr>("callee");
}

/// Set the callee for this operation.
void setCalleeFromCallable(mlir::CallInterfaceCallable callee) {
(*this)->setAttr("callee", callee.get<mlir::SymbolRefAttr>());
}

void setArg(unsigned index, mlir::Value value) {
setOperand(index, value);
}
}];

let assemblyFormat = [{
$callee `(` $operands `)` `as` $name attr-dict `:` functional-type($operands, results)
}];
}

def ApplyOp : P4HIR_Op<"apply",
[NoRegionArguments, CallOpInterface,
//DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>
TypesMatchWith<
"the apply type of the object matches the types of operands",
"callee", "arg_operands", "cast<P4HIR::ParserType>($_self).getInputs()">,
]> {
let summary = "apply operation";
let description = [{
Applies P4 parser, table or control

Example:

```mlir
// Application of a subparser
%sp = p4hir.instantiate @subparser() as "sp" : () -> !p4hir.parser<"subparser", ()>
p4hir.apply %sp() : !p4hir.parser<"subparser", ()>
...
```
}];

// TODO: Refine result types, refine parameter type (must be constants!)
let results = (outs);
let arguments = (ins P4ObjectType:$callee, Variadic<AnyType>:$arg_operands);

// TODO: Add verifier
let hasVerifier = 0;

let extraClassDeclaration = [{
/// Return the callee of this operation.
mlir::CallInterfaceCallable getCallableForCallee() {
return getCallee();
}

/// Set the callee for this operation.
void setCalleeFromCallable(mlir::CallInterfaceCallable callee) {
getCalleeMutable().assign(callee.get<mlir::Value>());
}
}];

let assemblyFormat = [{
$callee `(` $arg_operands `)` attr-dict `:` type($callee)
}];
}


include "p4mlir/Dialect/P4HIR/P4HIR_ParserOps.td"

#endif // P4MLIR_DIALECT_P4HIR_P4HIR_OPS_TD
9 changes: 8 additions & 1 deletion include/p4mlir/Dialect/P4HIR/P4HIR_ParserOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@ def ParserOp : P4HIR_Op<"parser",
[Symbol, SymbolTable, IsolatedFromAbove,
FunctionOpInterface, AutomaticAllocationScope]> {
let arguments = (ins SymbolNameAttr:$sym_name,
TypeAttrOf<FuncType>:$applyType);
TypeAttrOf<FuncType>:$applyType,
TypeAttrOf<CtorType>:$ctorType);
let regions = (region SizedRegion<1>:$body);
let hasCustomAssemblyFormat = 1;

let skipDefaultBuilders = 1;

let builders = [
OpBuilder<(ins "llvm::StringRef":$sym_name, "P4HIR::FuncType":$applyType, "P4HIR::CtorType":$ctorType)>
];

let extraClassDeclaration = [{
mlir::Region *getCallableRegion() { return &getBody(); }

Expand Down
30 changes: 30 additions & 0 deletions include/p4mlir/Dialect/P4HIR/P4HIR_Types.td
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,35 @@ def ParserType : P4HIR_Type<"Parser", "parser"> {
}];
}

//===----------------------------------------------------------------------===//
// CtorType
//===----------------------------------------------------------------------===//
// We keep parameter names to simplify matching for ctor arguments during
// instantiation and specialization.
def CtorType : P4HIR_Type<"Ctor", "ctor"> {
let parameters = (ins ArrayRefParameter<"std::pair<mlir::StringAttr, mlir::Type>">:$inputs,
"mlir::Type":$returnType);

let builders = [
// Construct with an actual return type
TypeBuilderWithInferredContext<(ins
"llvm::ArrayRef<std::pair<mlir::StringAttr, mlir::Type>>":$inputs, "mlir::Type":$returnType), [{
return $_get(returnType.getContext(), inputs, returnType);
}]>
];

let assemblyFormat = [{
`<` custom<CtorType>($inputs, $returnType) `>`
}];

let extraClassDeclaration = [{
/// Returns the `i`th input operand type. Asserts if out of bounds.
mlir::Type getInput(unsigned i) const { return getInputs()[i].second; }

/// Returns the number of arguments to the function.
unsigned getNumInputs() const { return getInputs().size(); }
}];
}

//===----------------------------------------------------------------------===//
// StructType
Expand Down Expand Up @@ -543,6 +572,7 @@ def LoadableP4Type : AnyTypeOf<[BitsType, BooleanType, InfIntType,
ValidBitType]> {}
def AnyEnumType : AnyTypeOf<[EnumType, SerEnumType]>;
def StructLikeType : AnyTypeOf<[StructType, HeaderType]>;
def P4ObjectType : AnyTypeOf<[ParserType]>;

/// A ref type with the specified constraints on the nested type.
class SpecificRefType<Type type> : ConfinedType<ReferenceType,
Expand Down
Loading
Loading