[MSFT] Use a DeviceDB to seed a PlacementDB (#1922)

Just checks validity of placements for now.
This commit is contained in:
John Demme 2021-10-02 17:40:40 -07:00 committed by GitHub
parent 1b0fe70750
commit 12720afe41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 85 additions and 18 deletions

View File

@ -38,7 +38,7 @@ typedef struct {
void *ptr;
} CirctMSFTDeviceDB;
CirctMSFTDeviceDB circtMSFTCreateDeviceDB();
CirctMSFTDeviceDB circtMSFTCreateDeviceDB(MlirContext);
void circtMSFTDeleteDeviceDB(CirctMSFTDeviceDB self);
MlirLogicalResult circtMSFTDeviceDBAddPrimitive(CirctMSFTDeviceDB,
MlirAttribute locAndPrim);
@ -60,7 +60,8 @@ typedef struct {
MlirOperation op;
} CirctMSFTPlacedInstance;
CirctMSFTPlacementDB circtMSFTCreatePlacementDB(MlirOperation top);
CirctMSFTPlacementDB circtMSFTCreatePlacementDB(MlirOperation top,
CirctMSFTDeviceDB seed);
void circtMSFTDeletePlacementDB(CirctMSFTPlacementDB self);
size_t circtMSFTPlacementDBAddDesignPlacements(CirctMSFTPlacementDB);
MlirLogicalResult

View File

@ -26,13 +26,17 @@ namespace msft {
class DeviceDB {
public:
/// Create a DB treating 'top' as the root module.
DeviceDB();
DeviceDB(MLIRContext *);
/// Place a primitive at a location.
LogicalResult addPrimitive(PhysLocationAttr);
/// Check to see if a primitive exists.
bool isValidLocation(PhysLocationAttr);
/// Iterate over all the primitive locations, executing 'callback' on each
/// one.
void foreach (function_ref<void(PhysLocationAttr)> callback) const;
private:
using DimPrimitiveType = DenseSet<PrimitiveType>;
using DimNumMap = DenseMap<size_t, DimPrimitiveType>;
@ -42,8 +46,10 @@ private:
/// Get the leaf node. Abstract this out to make it easier to change the
/// underlying data structure.
DimPrimitiveType &getLeaf(PhysLocationAttr);
// TODO: Create read-only version of getLeaf.
DimXMap placements;
MLIRContext *ctxt;
};
} // namespace msft

View File

@ -14,6 +14,7 @@
#ifndef CIRCT_DIALECT_MSFT_PLACEMENTDB_H
#define CIRCT_DIALECT_MSFT_PLACEMENTDB_H
#include "circt/Dialect/MSFT/DeviceDB.h"
#include "circt/Dialect/MSFT/MSFTAttributes.h"
#include "mlir/IR/Operation.h"
@ -34,6 +35,7 @@ class PlacementDB {
public:
/// Create a DB treating 'top' as the root module.
PlacementDB(Operation *top);
PlacementDB(Operation *top, const DeviceDB &seed);
// TODO: Add calls to model the device primitive locations.
@ -70,7 +72,12 @@ private:
using DimYMap = DenseMap<size_t, DimNumMap>;
using DimXMap = DenseMap<size_t, DimYMap>;
/// Get the leaf node. Abstract this out to make it easier to change the
/// underlying data structure.
Optional<PlacedInstance *> getLeaf(PhysLocationAttr);
DimXMap placements;
bool seeded;
};
} // namespace msft

View File

@ -95,3 +95,12 @@ with ir.Context() as ctx, ir.Location.unknown():
assert not devdb.is_valid_location(physAttr)
devdb.add_primitive(physAttr)
assert devdb.is_valid_location(physAttr)
seeded_pdb = msft.PlacementDB(top.operation, devdb)
rc = seeded_pdb.add_placement(physAttr, path, "subpath", resolved_inst)
assert rc
bad_loc = msft.PhysLocationAttr.get(msft.M20K, x=7, y=99, num=1)
rc = seeded_pdb.add_placement(bad_loc, path, "subpath", resolved_inst)
assert not rc
# ERR: error: 'hw.instance' op Could not apply placement. Invalid location

View File

@ -27,7 +27,7 @@ using namespace mlir::python::adaptors;
class DeviceDB {
public:
DeviceDB() { db = circtMSFTCreateDeviceDB(); }
DeviceDB(MlirContext ctxt) { db = circtMSFTCreateDeviceDB(ctxt); }
~DeviceDB() { circtMSFTDeleteDeviceDB(db); }
bool addPrimitive(MlirAttribute locAndPrim) {
return mlirLogicalResultIsSuccess(
@ -37,13 +37,15 @@ public:
return circtMSFTDeviceDBIsValidLocation(db, loc);
}
private:
CirctMSFTDeviceDB db;
};
class PlacementDB {
public:
PlacementDB(MlirOperation top) { db = circtMSFTCreatePlacementDB(top); }
PlacementDB(MlirOperation top, DeviceDB *seed) {
db = circtMSFTCreatePlacementDB(top, seed ? seed->db
: CirctMSFTDeviceDB{nullptr});
}
~PlacementDB() { circtMSFTDeletePlacementDB(db); }
size_t addDesignPlacements() {
return circtMSFTPlacementDBAddDesignPlacements(db);
@ -162,7 +164,7 @@ void circt::python::populateDialectMSFTSubmodule(py::module &m) {
});
py::class_<DeviceDB>(m, "DeviceDB")
.def(py::init<>())
.def(py::init<MlirContext>(), py::arg("ctxt") = py::none())
.def("add_primitive", &DeviceDB::addPrimitive,
"Inform the DB about a new placement.", py::arg("loc_and_prim"))
.def("is_valid_location", &DeviceDB::isValidLocation,
@ -170,7 +172,8 @@ void circt::python::populateDialectMSFTSubmodule(py::module &m) {
py::arg("loc"));
py::class_<PlacementDB>(m, "PlacementDB")
.def(py::init<MlirOperation>(), py::arg("top"))
.def(py::init<MlirOperation, DeviceDB *>(), py::arg("top"),
py::arg("seed") = nullptr)
.def("add_design_placements", &PlacementDB::addDesignPlacements,
"Add the placements already present in the design.")
.def("add_placement", &PlacementDB::addPlacement,

View File

@ -40,7 +40,9 @@ MlirLogicalResult mlirMSFTExportTcl(MlirOperation module,
DEFINE_C_API_PTR_METHODS(CirctMSFTDeviceDB, circt::msft::DeviceDB)
CirctMSFTDeviceDB circtMSFTCreateDeviceDB() { return wrap(new DeviceDB()); }
CirctMSFTDeviceDB circtMSFTCreateDeviceDB(MlirContext ctxt) {
return wrap(new DeviceDB(unwrap(ctxt)));
}
void circtMSFTDeleteDeviceDB(CirctMSFTDeviceDB self) { delete unwrap(self); }
MlirLogicalResult circtMSFTDeviceDBAddPrimitive(CirctMSFTDeviceDB self,
MlirAttribute cLoc) {
@ -59,8 +61,11 @@ bool circtMSFTDeviceDBIsValidLocation(CirctMSFTDeviceDB self,
DEFINE_C_API_PTR_METHODS(CirctMSFTPlacementDB, circt::msft::PlacementDB)
CirctMSFTPlacementDB circtMSFTCreatePlacementDB(MlirOperation top) {
return wrap(new PlacementDB(unwrap(top)));
CirctMSFTPlacementDB circtMSFTCreatePlacementDB(MlirOperation top,
CirctMSFTDeviceDB seed) {
if (seed.ptr == nullptr)
return wrap(new PlacementDB(unwrap(top)));
return wrap(new PlacementDB(unwrap(top), *unwrap(seed)));
}
void circtMSFTDeletePlacementDB(CirctMSFTPlacementDB self) {
delete unwrap(self);

View File

@ -20,7 +20,7 @@ using namespace msft;
// not an immediate goal.
//===----------------------------------------------------------------------===//
DeviceDB::DeviceDB() {}
DeviceDB::DeviceDB(MLIRContext *ctxt) : ctxt(ctxt) {}
/// Assign an instance to a primitive. Return false if another instance is
/// already placed at that location.
@ -44,3 +44,12 @@ bool DeviceDB::isValidLocation(PhysLocationAttr loc) {
DeviceDB::DimPrimitiveType &DeviceDB::getLeaf(PhysLocationAttr loc) {
return placements[loc.getX()][loc.getY()][loc.getNum()];
}
void DeviceDB::foreach (function_ref<void(PhysLocationAttr)> callback) const {
for (auto x : placements)
for (auto y : x.second)
for (auto n : y.second)
for (auto p : n.second)
callback(PhysLocationAttr::get(ctxt, PrimitiveTypeAttr::get(ctxt, p),
x.first, y.first, n.first));
}

View File

@ -20,18 +20,28 @@ using namespace msft;
// not an immediate goal.
//===----------------------------------------------------------------------===//
PlacementDB::PlacementDB(Operation *top) : ctxt(top->getContext()), top(top) {}
PlacementDB::PlacementDB(Operation *top)
: ctxt(top->getContext()), top(top), seeded(false) {}
PlacementDB::PlacementDB(Operation *top, const DeviceDB &seed)
: ctxt(top->getContext()), top(top), seeded(false) {
seed.foreach ([this](PhysLocationAttr loc) { (void)addPlacement(loc, {}); });
seeded = true;
}
/// Assign an instance to a primitive. Return false if another instance is
/// already placed at that location.
LogicalResult PlacementDB::addPlacement(PhysLocationAttr loc,
PlacedInstance inst) {
PlacedInstance &cell = placements[loc.getX()][loc.getY()][loc.getNum()]
[loc.getPrimitiveType().getValue()];
if (cell.op != nullptr)
Optional<PlacedInstance *> leaf = getLeaf(loc);
if (!leaf)
return inst.op->emitOpError("Could not apply placement. Invalid location");
PlacedInstance *cell = *leaf;
if (cell->op != nullptr)
return inst.op->emitOpError("Could not apply placement ")
<< loc << ". Position already occupied by " << cell.op << ".";
cell = inst;
<< loc << ". Position already occupied by " << cell->op << ".";
*cell = inst;
return success();
}
@ -102,6 +112,23 @@ PlacementDB::getInstanceAt(PhysLocationAttr loc) {
return instF->getSecond();
}
Optional<PlacementDB::PlacedInstance *>
PlacementDB::getLeaf(PhysLocationAttr loc) {
PrimitiveType primType = loc.getPrimitiveType().getValue();
DimNumMap &nums = placements[loc.getX()][loc.getY()];
if (!seeded)
return &nums[loc.getNum()][primType];
auto primitivesF = nums.find(loc.getNum());
if (primitivesF == nums.end())
return {};
auto primitives = primitivesF->second;
if (primitives.count(primType) == 0)
return {};
return &primitives[primType];
}
/// Walker for placements.
void PlacementDB::walkPlacements(
function_ref<void(PhysLocationAttr, PlacedInstance)> callback) {