mirror of https://github.com/llvm/circt.git
[MSFT] Use a DeviceDB to seed a PlacementDB (#1922)
Just checks validity of placements for now.
This commit is contained in:
parent
1b0fe70750
commit
12720afe41
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue