Skip to content

Commit

Permalink
[MSFT] Python bindings for ops and changes to make them work
Browse files Browse the repository at this point in the history
- Adds python bindings for MSFTModuleOp and InstanceOp.
- Re-use as much as possible from `circt.hw._hw_ops_ext`. Required changes to
  ODS definitions.
- Found and fixed some bugs.
  • Loading branch information
teqdruid committed Sep 17, 2021
1 parent 853c97d commit 67fd0f8
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 10 deletions.
11 changes: 8 additions & 3 deletions include/circt/Dialect/MSFT/MSFTOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ def InstanceOp : MSFTOp<"instance", [
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
DeclareOpInterfaceMethods<SymbolUserOpInterface>
]> {
let summary = "Create an instance of a module";
let summary = "Instantiate a module";

let arguments = (ins StrAttr:$instanceName,
FlatSymbolRefAttr:$moduleName,
Variadic<AnyType>:$inputs,
OptionalAttr<DictionaryAttr>:$parameters);
Variadic<AnyType>:$inputs);
let results = (outs Variadic<AnyType>);

let extraClassDeclaration = [{
Expand Down Expand Up @@ -60,6 +59,12 @@ def MSFTModuleOp : MSFTOp<"module",
let results = (outs);
let regions = (region OneOrNoBlocksRegion:$body);

let skipDefaultBuilders = 1;
let builders = [
OpBuilder<(ins "StringAttr":$name, "ArrayRef<hw::PortInfo>":$ports,
"ArrayRef<NamedAttribute>":$params)>
];

let extraClassDeclaration = [{
using FunctionLike::front;
using FunctionLike::getBody;
Expand Down
11 changes: 10 additions & 1 deletion integration_test/Bindings/Python/dialects/msft.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import circt
from circt import msft
from circt.dialects import hw, seq
from circt.dialects import hw, msft as msft_ops

import mlir.ir as ir
import sys
Expand All @@ -24,16 +24,24 @@
input_ports=[],
output_ports=[],
body_builder=lambda module: hw.OutputOp([]))

top = hw.HWModuleOp(name='top',
input_ports=[],
output_ports=[],
body_builder=lambda module: hw.OutputOp([]))

msft_mod = msft_ops.MSFTModuleOp(
name='msft_mod',
input_ports=[],
output_ports=[],
parameters={"WIDTH": ir.IntegerAttr.get(i32, 8)})

with ir.InsertionPoint.at_block_terminator(op.body.blocks[0]):
ext_inst = extmod.create("ext1")

with ir.InsertionPoint.at_block_terminator(top.body.blocks[0]):
path = op.create("inst1")
minst = msft_mod.create("minst")

# CHECK: #msft.physloc<M20K, 2, 6, 1>
physAttr = msft.PhysLocationAttr.get(msft.M20K, x=2, y=6, num=1)
Expand All @@ -58,6 +66,7 @@

# CHECK: hw.module @MyWidget()
# CHECK: hw.output
# CHECK: msft.module @msft_mod {WIDTH = 8 : i32} ()
m.operation.print()

db = msft.DeviceDB(top.operation)
Expand Down
9 changes: 9 additions & 0 deletions lib/Bindings/Python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ declare_mlir_dialect_python_bindings(
circt/dialects/_hw_ops_ext.py
DIALECT_NAME hw)

declare_mlir_dialect_python_bindings(
ADD_TO_PARENT CIRCTBindingsPythonSources.Dialects
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
TD_FILE circt/dialects/MSFTOps.td
SOURCES
circt/dialects/msft.py
circt/dialects/_msft_ops_ext.py
DIALECT_NAME msft)

declare_mlir_dialect_python_bindings(
ADD_TO_PARENT CIRCTBindingsPythonSources.Dialects
ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
Expand Down
15 changes: 15 additions & 0 deletions lib/Bindings/Python/circt/dialects/MSFTOps.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//===-- MSFTOps.td - Entry point for MSFTOps bindings ------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef BINDINGS_PYTHON_MSFT_OPS
#define BINDINGS_PYTHON_MSFT_OPS

include "mlir/Bindings/Python/Attributes.td"
include "circt/Dialect/MSFT/MSFT.td"

#endif
2 changes: 1 addition & 1 deletion lib/Bindings/Python/circt/dialects/_hw_ops_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def __init__(
input_ports=[],
output_ports=[],
*,
attributes={},
body_builder=None,
loc=None,
ip=None,
Expand All @@ -104,7 +105,6 @@ def __init__(
"""
operands = []
results = []
attributes = {}
attributes["sym_name"] = StringAttr.get(str(name))

input_types = []
Expand Down
78 changes: 78 additions & 0 deletions lib/Bindings/Python/circt/dialects/_msft_ops_ext.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

from circt.dialects import msft as _msft
import circt.dialects._hw_ops_ext as _hw_ext
import circt.support as support

import mlir.ir as _ir


class InstanceBuilder(support.NamedValueOpView):
"""Helper class to incrementally construct an instance of a module."""

def __init__(self,
module,
name,
input_port_mapping,
*,
results=None,
sym_name=None,
loc=None,
ip=None):
self.module = module
instance_name = _ir.StringAttr.get(name)
module_name = _ir.FlatSymbolRefAttr.get(_ir.StringAttr(module.name).value)
if sym_name:
sym_name = _ir.StringAttr.get(sym_name)
pre_args = [instance_name, module_name]
if results is None:
results = module.type.results

super().__init__(_msft.InstanceOp,
results,
input_port_mapping,
pre_args, [],
loc=loc,
ip=ip)

def create_default_value(self, index, data_type, arg_name):
type = self.module.type.inputs[index]
return support.BackedgeBuilder.create(type,
arg_name,
self,
instance_of=self.module)

def operand_names(self):
arg_names = _ir.ArrayAttr(self.module.attributes["argNames"])
arg_name_attrs = map(_ir.StringAttr, arg_names)
return list(map(lambda s: s.value, arg_name_attrs))

def result_names(self):
arg_names = _ir.ArrayAttr(self.module.attributes["resultNames"])
arg_name_attrs = map(_ir.StringAttr, arg_names)
return list(map(lambda s: s.value, arg_name_attrs))


class MSFTModuleOp(_hw_ext.ModuleLike):

def __init__(
self,
name,
input_ports=[],
output_ports=[],
parameters={},
loc=None,
ip=None,
):
attrs = {"parameters": _ir.DictAttr.get(parameters)}
super().__init__(name,
input_ports,
output_ports,
attributes=attrs,
loc=loc,
ip=ip)

def create(self, name: str, results=None, loc=None, ip=None, **kwargs):
return InstanceBuilder(self, name, kwargs, results=results, loc=loc, ip=ip)
5 changes: 5 additions & 0 deletions lib/Bindings/Python/circt/dialects/msft.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

from ._msft_ops_gen import *
8 changes: 7 additions & 1 deletion lib/Dialect/MSFT/MSFTOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,19 @@ hw::ModulePortInfo MSFTModuleOp::getPorts() {
return hw::ModulePortInfo(inputs, outputs);
}

void MSFTModuleOp::build(OpBuilder &odsBuilder, OperationState &odsState,
StringAttr name, ArrayRef<hw::PortInfo> ports,
ArrayRef<NamedAttribute> params) {
assert(false && "Unimplemented");
}

LogicalResult InstanceOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
auto *module = symbolTable.lookupNearestSymbolFrom(*this, moduleNameAttr());
if (module == nullptr)
return emitError("Cannot find module definition '") << moduleName() << "'";

// It must be some sort of module.
if (!hw::isAnyModule(module))
if (!hw::isAnyModule(module) && !isa<MSFTModuleOp>(module))
return emitError("symbol reference '")
<< moduleName() << "' isn't a module";
return success();
Expand Down
11 changes: 7 additions & 4 deletions test/Dialect/MSFT/module_instance.mlir
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// RUN: circt-opt %s -verify-diagnostics | circt-opt -verify-diagnostics | FileCheck %s
// RUN: circt-opt %s --msft-lower-to-hw -verify-diagnostics | circt-opt -verify-diagnostics | FileCheck %s --check-prefix=HWLOW

hw.module.extern @fooMod () -> (x: i32)
msft.module @Foo { "WIDTH" = 1 } () -> (x: i32) {
%c0 = hw.constant 0 : i32
msft.output %c0 : i32
}

// CHECK-LABEL: hw.module @top
// HWLOW-LABEL: hw.module @top
hw.module @top () {
msft.instance "foo" @fooMod () : () -> (i32)
// CHECK: %foo.x = msft.instance "foo" @fooMod() : () -> i32
// HWLOW: %foo.x = hw.instance "foo" @fooMod() -> (x: i32)
msft.instance "foo" @Foo() : () -> (i32)
// CHECK: %foo.x = msft.instance "foo" @Foo() : () -> i32
// HWLOW: %foo.x = hw.instance "foo" @Foo() -> (x: i32)
}

// CHECK-LABEL: msft.module @B {WIDTH = 1 : i64} (%a: i4) -> (nameOfPortInSV: i4) {
Expand Down

0 comments on commit 67fd0f8

Please sign in to comment.