Skip to content

Commit

Permalink
Add some basic boilerplate and support for bit / int and bool P4 types
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Korobeynikov <anton@korobeynikov.info>
  • Loading branch information
asl committed Jan 22, 2025
1 parent 0ca5a92 commit 8763f05
Show file tree
Hide file tree
Showing 18 changed files with 432 additions and 62 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${MLIR_INCLUDE_DIRS})
include_directories(${P4MLIR_SOURCE_DIR}/include)
include_directories(${P4MLIR_BINARY_DIR}/include)

set(LLVM_RUNTIME_OUTPUT_INTDIR "${P4MLIR_BINARY_DIR}/bin")
add_subdirectory(include)
add_subdirectory(lib)
add_subdirectory(test)
Expand Down
3 changes: 3 additions & 0 deletions include/p4mlir/Dialect/P4HIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ mlir_tablegen(P4HIR_Ops.h.inc -gen-op-decls)
mlir_tablegen(P4HIR_Ops.cpp.inc -gen-op-defs)
mlir_tablegen(P4HIR_Types.h.inc -gen-typedef-decls -typedefs-dialect=p4hir)
mlir_tablegen(P4HIR_Types.cpp.inc -gen-typedef-defs -typedefs-dialect=p4hir)
mlir_tablegen(P4HIR_Attrs.h.inc -gen-attrdef-decls -attrdefs-dialect=p4hir)
mlir_tablegen(P4HIR_Attrs.cpp.inc -gen-attrdef-defs -attrdefs-dialect=p4hir)

add_public_tablegen_target(P4MLIR_P4HIR_IncGen)
add_dependencies(mlir-headers P4MLIR_P4HIR_IncGen)
10 changes: 10 additions & 0 deletions include/p4mlir/Dialect/P4HIR/P4HIR_Attrs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef P4MLIR_DIALECT_P4HIR_P4HIR_ATTRS_H
#define P4MLIR_DIALECT_P4HIR_P4HIR_ATTRS_H

#include "mlir/IR/BuiltinAttributes.h"
#include "p4mlir/Dialect/P4HIR/P4HIR_Types.h"

#define GET_ATTRDEF_CLASSES
#include "p4mlir/Dialect/P4HIR/P4HIR_Attrs.h.inc"

#endif // P4MLIR_DIALECT_P4HIR_P4HIR_ATTRS_H
62 changes: 62 additions & 0 deletions include/p4mlir/Dialect/P4HIR/P4HIR_Attrs.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#ifndef P4MLIR_DIALECT_P4HIR_P4HIR_ATTRS_TD
#define P4MLIR_DIALECT_P4HIR_P4HIR_ATTRS_TD

include "mlir/IR/BuiltinAttributeInterfaces.td"
include "mlir/IR/EnumAttr.td"

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

class P4HIR_Attr<string name, string attrMnemonic, list<Trait> traits = []>
: AttrDef<P4HIR_Dialect, name, traits> {
let mnemonic = attrMnemonic;
}

//===----------------------------------------------------------------------===//
// BoolAttr
//===----------------------------------------------------------------------===//

def P4_BoolAttr : P4HIR_Attr<"Bool", "bool", [TypedAttrInterface]> {
let summary = "Represent true/false for !p4hir.bool types";
let description = [{
The BoolAttr represents a 'true' or 'false' value.
}];

let parameters = (ins AttributeSelfTypeParameter<"", "BoolType">:$type,
"bool":$value);

let assemblyFormat = [{
`<` $value `>`
}];
}

//===----------------------------------------------------------------------===//
// IntegerAttr
//===----------------------------------------------------------------------===//

def IntAttr : P4HIR_Attr<"Int", "int", [TypedAttrInterface]> {
let summary = "An Attribute containing a integer value";
let description = [{
An integer attribute is a literal attribute that represents an integral
value of the specified integer type.
}];
let parameters = (ins AttributeSelfTypeParameter<"">:$type, "llvm::APInt":$value);
let builders = [
AttrBuilderWithInferredContext<(ins "mlir::Type":$type, "const llvm::APInt &":$value), [{
return $_get(type.getContext(), type, value);
}]>,
AttrBuilderWithInferredContext<(ins "mlir::Type":$type, "int64_t":$value), [{
BitsType intType = mlir::cast<BitsType>(type);
mlir::APInt apValue(intType.getWidth(), value, intType.isSigned());
return $_get(intType.getContext(), intType, apValue);
}]>,
];
let extraClassDeclaration = [{
int64_t getSInt() const { return getValue().getSExtValue(); }
uint64_t getUInt() const { return getValue().getZExtValue(); }
bool isNullValue() const { return getValue() == 0; }
}];
let genVerifyDecl = 1;
let hasCustomAssemblyFormat = 1;
}

#endif // P4MLIR_DIALECT_P4HIR_P4HIR_ATTRS_TD
6 changes: 5 additions & 1 deletion include/p4mlir/Dialect/P4HIR/P4HIR_Dialect.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#ifndef P4MLIR_DIALECT_P4HIR_P4HIR_DIALECT_H
#define P4MLIR_DIALECT_P4HIR_P4HIR_DIALECT_H

// We explicitly do not use push / pop for diagnostic in
// order to propagate pragma further on
#pragma GCC diagnostic ignored "-Wunused-parameter"

#include "mlir/Bytecode/BytecodeOpInterface.h"
#include "mlir/IR/Dialect.h"

#include "p4mlir/Dialect/P4HIR/P4HIR_Dialect.h.inc"

#endif // P4MLIR_DIALECT_P4HIR_P4HIR_DIALECT_H
#endif // P4MLIR_DIALECT_P4HIR_P4HIR_DIALECT_H
11 changes: 10 additions & 1 deletion include/p4mlir/Dialect/P4HIR/P4HIR_Dialect.td
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ def P4HIR_Dialect : Dialect {
}];
let cppNamespace = "::P4::P4MLIR::P4HIR";

let useDefaultTypePrinterParser = 1;
let useDefaultTypePrinterParser = 0;
let useDefaultAttributePrinterParser = 1;

let extraClassDeclaration = [{
mlir::Type parseType(mlir::DialectAsmParser &parser) const override;
void printType(mlir::Type type, mlir::DialectAsmPrinter &printer) const override;

void registerAttributes();
void registerTypes();
}];
}

#endif // P4MLIR_DIALECT_P4HIR_P4HIR_DIALECT_TD
4 changes: 4 additions & 0 deletions include/p4mlir/Dialect/P4HIR/P4HIR_Ops.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef P4MLIR_DIALECT_P4HIR_P4HIR_OPS_H
#define P4MLIR_DIALECT_P4HIR_P4HIR_OPS_H

// We explicitly do not use push / pop for diagnostic in
// order to propagate pragma further on
#pragma GCC diagnostic ignored "-Wunused-parameter"

#include "mlir/Bytecode/BytecodeOpInterface.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
Expand Down
28 changes: 14 additions & 14 deletions include/p4mlir/Dialect/P4HIR/P4HIR_Ops.td
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ include "mlir/Interfaces/SideEffectInterfaces.td"

include "p4mlir/Dialect/P4HIR/P4HIR_Dialect.td"
include "p4mlir/Dialect/P4HIR/P4HIR_Types.td"
include "p4mlir/Dialect/P4HIR/P4HIR_Attrs.td"

//===----------------------------------------------------------------------===//
// Base P4HIR operation definition.
Expand All @@ -20,31 +21,30 @@ class P4HIR_Op<string mnemonic, list<Trait> traits = []> :
// P4HIR operation definitions.
//===----------------------------------------------------------------------===//

def P4HIR_ConstOp : P4HIR_Op<"const", [Pure]> {
let summary = "const operation";
def P4HIR_ConstOp : P4HIR_Op<"const",
[ConstantLike, Pure, AllTypesMatch<["value", "res"]>]> {
let summary = "Defines a P4 constant";
let description = [{
The `p4hir.const` operation turns a literal into an SSA value. It
The `p4hir.const` operation turns a literal into an SSA value.
The data is attached to the operation as an attribute. It
represents a constant declaration in P4.

Example:

```mlir
%0 = p4hir.const 42 : ui32 -> !p4hir.bit<32>
%0 = p4hir.const p4hir.int<-128> : !p4hir.int<8>
```
}];

Corresponding P4 code:
// The constant operation takes an attribute as the only input.
let arguments = (ins TypedAttrInterface:$value);

```p4
const bit<32> a = 42;
```
}];
// The constant operation returns a single value of AnyP4Type.
let results = (outs AnyP4Type:$res);

let arguments = (ins APIntAttr:$value);
let results = (outs P4HIR_P4Type:$result);
let assemblyFormat = "attr-dict $value";

let assemblyFormat = [{
$value attr-dict `->` qualified(type($result))
}];
let hasVerifier = 1;
}

#endif // P4MLIR_DIALECT_P4HIR_P4HIR_OPS_TD
73 changes: 66 additions & 7 deletions include/p4mlir/Dialect/P4HIR/P4HIR_Types.td
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,80 @@ class P4HIR_Type<string name, string typeMnemonic, list<Trait> traits = []>
let mnemonic = typeMnemonic;
}

def P4HIR_BitType : P4HIR_Type<"BitType", "bit"> {
let summary = "fixed width unsigned integer type";
class P4HIR_TypeNoMnemonic<string name, string typeMnemonic, list<Trait> traits = []>
: TypeDef<P4HIR_Dialect, name, traits> {
string typeName = dialect.name # "." # typeMnemonic;
}

//===----------------------------------------------------------------------===//
// Integer types: signed (int) and unsigned (bit)
def P4HIR_BitsType : P4HIR_TypeNoMnemonic<"Bits", "bits"> {
let summary = "fixed width integer type";
let description = [{
The `p4hir.bit` type represents a P4 `bit` type.
The `p4hir.bit` / `p4hir.int` type represents a P4 `bit` or `int` type.

For example, `p4hir.bit<32>` represents `bit<32>` in P4 and
`p4hir.int<42>` is `int<42>` in P4.
}];
let parameters = (ins "unsigned":$width, "bool":$isSigned);
let extraClassDeclaration = [{
/// Return true if this is a signed integer type.
bool isSigned() const { return getIsSigned(); }
/// Return true if this is an unsigned integer type.
bool isUnsigned() const { return !getIsSigned(); }

static mlir::Type parse(mlir::AsmParser &parser, bool isSigned);
void print(mlir::AsmPrinter &printer) const;
}];
}

For example, `p4hir.bit<32>` represents `bit<32>` in P4.
// Unsigned integer type of a specific width (bits<width>).
class P4HIR_Bit<int width>
: Type<And<[
CPred<"::mlir::isa<::p4hir::BitsType>($_self)">,
CPred<"::mlir::cast<::p4hir::BitsType>($_self).isUnsigned()">,
CPred<"::mlir::cast<::p4hir::BitsType>($_self).getWidth() == " # width>
]>, width # "-bit unsigned integer", "::p4hir::BitsType">,
BuildableType<
"p4hir::BitsType::get($_builder.getContext(), "
# width # ", /*isSigned=*/false)"> {
int bitwidth = width;
}

// Signed integer type of a specific width (int<width>).
class P4HIR_Int<int width>
: Type<And<[
CPred<"::mlir::isa<::p4hir::IntType>($_self)">,
CPred<"::mlir::cast<::p4hir::IntType>($_self).isSigned()">,
CPred<"::mlir::cast<::p4hir::IntType>($_self).getWidth() == " # width>
]>, width # "-bit signed integer", "::p4hir::BitsType">,
BuildableType<
"p4hir::BitsType::get($_builder.getContext(), "
# width # ", /*isSigned=*/true)"> {
int bitwidth = width;
}

//===----------------------------------------------------------------------===//
// BoolType
//
// An alternative here is to represent bool as mlir::i1, but let's be more
// generic.
//
//===----------------------------------------------------------------------===//

def P4HIR_BooleanType : P4HIR_Type<"Bool", "bool"> {
let summary = "boolean type";
let description = [{
`p4hir.bool` represents a P4 `bool` type.
}];
let parameters = (ins "uint64_t":$width);
let assemblyFormat = "`<` $width `>`";

let hasCustomAssemblyFormat = 1;
}

//===----------------------------------------------------------------------===//
// P4HIR type constraints.
//===----------------------------------------------------------------------===//

def P4HIR_P4Type : AnyTypeOf<[P4HIR_BitType]> {}
def AnyP4Type : AnyTypeOf<[P4HIR_BitsType, P4HIR_BooleanType]> {}

#endif // P4MLIR_DIALECT_P4HIR_P4HIR_TYPES_TD
4 changes: 3 additions & 1 deletion lib/Dialect/P4HIR/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
add_mlir_dialect_library(P4MLIR_P4HIR
P4HIR.cpp
P4HIR_Ops.cpp
P4HIR_Types.cpp
P4HIR_Attrs.cpp

ADDITIONAL_HEADER_DIRS
${PROJECT_SOURCE_DIR}/include/p4mlir/Dialect/P4HIR
Expand Down
28 changes: 0 additions & 28 deletions lib/Dialect/P4HIR/P4HIR.cpp

This file was deleted.

Loading

0 comments on commit 8763f05

Please sign in to comment.