[MSFT] [Py] Add physical location and switch instance attributes to python module (#1606)

This commit is contained in:
John Demme 2021-08-18 20:03:07 -07:00 committed by GitHub
parent 21485874c8
commit 43ccc6584e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 167 additions and 12 deletions

View File

@ -51,6 +51,30 @@ MLIR_CAPI_EXPORTED void mlirMSFTAddPhysLocationAttr(MlirOperation op,
DeviceType type, long x,
long y, long num);
// Values represented in `MSFT.td`.
typedef uint32_t CirctMSFTDevType;
bool circtMSFTAttributeIsAPhysLocationAttribute(MlirAttribute);
MlirAttribute circtMSFTPhysLocationAttrGet(MlirContext, CirctMSFTDevType,
uint64_t x, uint64_t y,
uint64_t num);
CirctMSFTDevType circtMSFTPhysLocationAttrGetDeviceType(MlirAttribute);
uint64_t circtMSFTPhysLocationAttrGetX(MlirAttribute);
uint64_t circtMSFTPhysLocationAttrGetY(MlirAttribute);
uint64_t circtMSFTPhysLocationAttrGetNum(MlirAttribute);
typedef struct {
MlirAttribute instance;
MlirAttribute attr;
} CirctMSFTSwitchInstanceCase;
bool circtMSFTAttributeIsASwitchInstanceAttribute(MlirAttribute);
MlirAttribute circtMSFTSwitchInstanceAttrGet(
MlirContext, CirctMSFTSwitchInstanceCase *listOfCases, size_t numCases);
size_t circtMSFTSwitchInstanceAttrGetNumCases(MlirAttribute);
void circtMSFTSwitchInstanceAttrGetCases(MlirAttribute,
CirctMSFTSwitchInstanceCase *dstArray,
size_t space);
#ifdef __cplusplus
}
#endif

View File

@ -61,7 +61,7 @@ def SwitchInstance : MSFT_Attr<"SwitchInstance"> {
let summary = "Select an attribute to be use based on the instance";
let mnemonic = "switch.inst";
let parameters = (ins
ArrayRefParameter<"InstIDAttrPair">:$instPairs);
ArrayRefParameter<"SwitchInstanceCase">:$cases);
let extraClassDeclaration = [{
Attribute lookup(InstanceIDAttr);

View File

@ -21,7 +21,7 @@
namespace circt {
namespace msft {
using InstanceIDAttr = mlir::SymbolRefAttr;
using InstIDAttrPair = std::pair<InstanceIDAttr, Attribute>;
using SwitchInstanceCase = std::pair<InstanceIDAttr, Attribute>;
} // namespace msft
} // namespace circt

View File

@ -5,16 +5,16 @@ import circt
from circt import msft
from circt.dialects import hw, seq
from mlir.ir import *
import mlir.ir as ir
import sys
with Context() as ctx, Location.unknown():
with ir.Context() as ctx, ir.Location.unknown():
circt.register_dialects(ctx)
i32 = IntegerType.get_signless(32)
i1 = IntegerType.get_signless(1)
i32 = ir.IntegerType.get_signless(32)
i1 = ir.IntegerType.get_signless(1)
m = Module.create()
with InsertionPoint(m.body):
m = ir.Module.create()
with ir.InsertionPoint(m.body):
# CHECK: hw.module @MyWidget()
# CHECK: hw.output
op = hw.HWModuleOp(name='MyWidget',
@ -26,7 +26,7 @@ with Context() as ctx, Location.unknown():
output_ports=[],
body_builder=lambda module: hw.OutputOp([]))
with InsertionPoint.at_block_terminator(top.body.blocks[0]):
with ir.InsertionPoint.at_block_terminator(top.body.blocks[0]):
inst = op.create("inst1")
msft.locate(inst.operation, "mem", devtype=msft.M20K, x=50, y=100, num=1)
# CHECK: hw.instance "inst1" @MyWidget() {"loc:mem" = #msft.physloc<M20K, 50, 100, 1>, parameters = {}} : () -> ()
@ -39,6 +39,16 @@ with Context() as ctx, Location.unknown():
m.operation.print()
physAttr = msft.PhysLocationAttr.get(msft.M20K, x=2, y=6, num=1)
# CHECK: #msft.physloc<M20K, 2, 6, 1>
print(physAttr)
inst = ir.Attribute.parse("@foo::@bar")
# CHECK-NEXT: #msft.switch.inst<@foo::@bar=#msft.physloc<M20K, 2, 6, 1>>
instSwitch = msft.SwitchInstance.get([(inst, physAttr)])
print(instSwitch)
# CHECK-LABEL: === tcl ===
print("=== tcl ===")

View File

@ -41,6 +41,8 @@ static void registerGenerator(MlirContext ctxt, std::string opName,
parameters);
}
using namespace mlir::python::adaptors;
/// Populate the msft python module.
void circt::python::populateDialectMSFTSubmodule(py::module &m) {
mlirMSFTRegisterPasses();
@ -65,4 +67,63 @@ void circt::python::populateDialectMSFTSubmodule(py::module &m) {
m.def("register_generator", &::registerGenerator,
"Register a generator for a design module");
mlir_attribute_subclass(m, "PhysLocationAttr",
circtMSFTAttributeIsAPhysLocationAttribute)
.def_classmethod(
"get",
[](py::object cls, DeviceType devType, uint64_t x, uint64_t y,
uint64_t num, MlirContext ctxt) {
return cls(circtMSFTPhysLocationAttrGet(ctxt, (uint64_t)devType, x,
y, num));
},
"Create a physical location attribute", py::arg(),
py::arg("dev_type"), py::arg("x"), py::arg("y"), py::arg("num"),
py::arg("ctxt") = py::none())
.def_property_readonly(
"devtype",
[](MlirAttribute self) {
return (DeviceType)circtMSFTPhysLocationAttrGetDeviceType(self);
})
.def_property_readonly("x",
[](MlirAttribute self) {
return (DeviceType)circtMSFTPhysLocationAttrGetX(
self);
})
.def_property_readonly("y",
[](MlirAttribute self) {
return (DeviceType)circtMSFTPhysLocationAttrGetY(
self);
})
.def_property_readonly("num", [](MlirAttribute self) {
return (DeviceType)circtMSFTPhysLocationAttrGetNum(self);
});
mlir_attribute_subclass(m, "SwitchInstance",
circtMSFTAttributeIsASwitchInstanceAttribute)
.def_classmethod(
"get",
[](py::object cls,
std::vector<std::tuple<MlirAttribute, MlirAttribute>> listOfCases,
MlirContext ctxt) {
std::vector<CirctMSFTSwitchInstanceCase> cases;
for (auto p : listOfCases)
cases.push_back({std::get<0>(p), std::get<1>(p)});
return cls(circtMSFTSwitchInstanceAttrGet(ctxt, cases.data(),
cases.size()));
},
"Create an instance switch attribute", py::arg(),
py::arg("list_of_cases"), py::arg("ctxt") = py::none())
.def_property_readonly(
"cases",
[](MlirAttribute self) {
size_t numCases = circtMSFTSwitchInstanceAttrGetNumCases(self);
std::vector<CirctMSFTSwitchInstanceCase> cases(numCases);
circtMSFTSwitchInstanceAttrGetCases(self, cases.data(),
cases.max_size());
return cases;
})
.def_property_readonly("num_cases", [](MlirAttribute self) {
return circtMSFTSwitchInstanceAttrGetNumCases(self);
});
}

View File

@ -11,10 +11,12 @@
#include "mlir/CAPI/Registration.h"
#include "mlir/CAPI/Support.h"
#include "mlir/CAPI/Utils.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"
MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(MSFT, msft, circt::msft::MSFTDialect)
using namespace circt;
using namespace circt::msft;
void mlirMSFTRegisterPasses() { circt::msft::registerMSFTPasses(); }
@ -50,3 +52,61 @@ void mlirMSFTAddPhysLocationAttr(MlirOperation cOp, const char *entityName,
entity.append(entityName);
op->setAttr(entity, loc);
}
bool circtMSFTAttributeIsAPhysLocationAttribute(MlirAttribute attr) {
return unwrap(attr).isa<PhysLocationAttr>();
}
MlirAttribute circtMSFTPhysLocationAttrGet(MlirContext cCtxt,
CirctMSFTDevType devType, uint64_t x,
uint64_t y, uint64_t num) {
auto ctxt = unwrap(cCtxt);
return wrap(PhysLocationAttr::get(
ctxt, DeviceTypeAttr::get(ctxt, (DeviceType)devType), x, y, num));
}
CirctMSFTDevType circtMSFTPhysLocationAttrGetDeviceType(MlirAttribute attr) {
return (CirctMSFTDevType)unwrap(attr)
.cast<PhysLocationAttr>()
.getDevType()
.getValue();
}
uint64_t circtMSFTPhysLocationAttrGetX(MlirAttribute attr) {
return (CirctMSFTDevType)unwrap(attr).cast<PhysLocationAttr>().getX();
}
uint64_t circtMSFTPhysLocationAttrGetY(MlirAttribute attr) {
return (CirctMSFTDevType)unwrap(attr).cast<PhysLocationAttr>().getY();
}
uint64_t circtMSFTPhysLocationAttrGetNum(MlirAttribute attr) {
return (CirctMSFTDevType)unwrap(attr).cast<PhysLocationAttr>().getNum();
}
bool circtMSFTAttributeIsASwitchInstanceAttribute(MlirAttribute attr) {
return unwrap(attr).isa<SwitchInstanceAttr>();
}
MlirAttribute
circtMSFTSwitchInstanceAttrGet(MlirContext cCtxt,
CirctMSFTSwitchInstanceCase *listOfCases,
size_t numCases) {
SmallVector<SwitchInstanceCase, 64> cases;
for (size_t i = 0; i < numCases; ++i) {
CirctMSFTSwitchInstanceCase pair = listOfCases[i];
auto instance = unwrap(pair.instance).cast<SymbolRefAttr>();
auto attr = unwrap(pair.attr);
cases.push_back(std::make_pair(instance, attr));
}
return wrap(SwitchInstanceAttr::get(unwrap(cCtxt), cases));
}
size_t circtMSFTSwitchInstanceAttrGetNumCases(MlirAttribute attr) {
return unwrap(attr).cast<SwitchInstanceAttr>().getCases().size();
}
void circtMSFTSwitchInstanceAttrGetCases(MlirAttribute attr,
CirctMSFTSwitchInstanceCase *dstArray,
size_t space) {
auto sw = unwrap(attr).cast<SwitchInstanceAttr>();
ArrayRef<SwitchInstanceCase> cases = sw.getCases();
assert(space >= cases.size());
for (size_t i = 0, e = cases.size(); i < e; ++i) {
auto c = cases[i];
dstArray[i] = {wrap(c.first), wrap(c.second)};
}
}

View File

@ -29,7 +29,7 @@ Attribute SwitchInstanceAttr::parse(MLIRContext *ctxt, DialectAsmParser &p,
if (!p.parseOptionalGreater())
return SwitchInstanceAttr::get(ctxt, {});
SmallVector<InstIDAttrPair> instPairs;
SmallVector<SwitchInstanceCase> instPairs;
do {
SymbolRefAttr instId;
Attribute attr;
@ -45,7 +45,7 @@ Attribute SwitchInstanceAttr::parse(MLIRContext *ctxt, DialectAsmParser &p,
void SwitchInstanceAttr::print(DialectAsmPrinter &p) const {
p << "switch.inst<";
llvm::interleaveComma(getInstPairs(), p, [&](auto instPair) {
llvm::interleaveComma(getCases(), p, [&](auto instPair) {
p << instPair.first << '=';
p.printAttribute(instPair.second);
});
@ -54,7 +54,7 @@ void SwitchInstanceAttr::print(DialectAsmPrinter &p) const {
Attribute SwitchInstanceAttr::lookup(InstanceIDAttr id) {
// TODO: This is obviously very slow. Speed this up by using a sorted list.
for (auto pair : getInstPairs())
for (auto pair : getCases())
if (pair.first == id)
return pair.second;
return Attribute();