[MSFT] [DeviceDB] Find nearest free location in column (#1937)

Find the nearest primitive in a column to the desired row. Said primitive should be of a given primitive type, and be unoccupied.
This commit is contained in:
John Demme 2021-10-06 11:12:01 -07:00 committed by GitHub
parent 9909253abf
commit d488343996
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 98 additions and 27 deletions

View File

@ -24,6 +24,9 @@ MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(MSFT, msft);
MLIR_CAPI_EXPORTED void mlirMSFTRegisterPasses();
// Values represented in `MSFT.td`.
typedef uint32_t CirctMSFTPrimitiveType;
/// Emits tcl for the specified module using the provided callback and user
/// data
MLIR_CAPI_EXPORTED MlirLogicalResult mlirMSFTExportTcl(MlirOperation,
@ -70,6 +73,9 @@ circtMSFTPlacementDBAddPlacement(CirctMSFTPlacementDB, MlirAttribute loc,
bool circtMSFTPlacementDBTryGetInstanceAt(CirctMSFTPlacementDB,
MlirAttribute loc,
CirctMSFTPlacedInstance *out);
MlirAttribute circtMSFTPlacementDBGetNearestFreeInColumn(
CirctMSFTPlacementDB, CirctMSFTPrimitiveType prim, uint64_t column,
uint64_t nearestToY);
//===----------------------------------------------------------------------===//
// MSFT Attributes.
@ -82,9 +88,6 @@ MLIR_CAPI_EXPORTED void mlirMSFTAddPhysLocationAttr(MlirOperation op,
PrimitiveType type, long x,
long y, long num);
// Values represented in `MSFT.td`.
typedef uint32_t CirctMSFTPrimitiveType;
bool circtMSFTAttributeIsAPhysLocationAttribute(MlirAttribute);
MlirAttribute circtMSFTPhysLocationAttrGet(MlirContext, CirctMSFTPrimitiveType,
uint64_t x, uint64_t y,

View File

@ -60,9 +60,19 @@ public:
/// Lookup the instance at a particular location.
Optional<PlacedInstance> getInstanceAt(PhysLocationAttr);
/// Find the nearest unoccupied primitive location to 'nearestToY' in
/// 'column'.
PhysLocationAttr getNearestFreeInColumn(PrimitiveType prim, uint64_t column,
uint64_t nearestToY);
/// Walk the placement information in some sort of reasonable order.
void walkPlacements(function_ref<void(PhysLocationAttr, PlacedInstance)>);
/// Walk the column placements in some sort of reasonable order.
void
walkColumnPlacements(uint64_t column,
function_ref<void(PhysLocationAttr, PlacedInstance)>);
private:
MLIRContext *ctxt;
Operation *top;

View File

@ -94,12 +94,20 @@ with ir.Context() as ctx, ir.Location.unknown():
devdb = msft.DeviceDB()
assert not devdb.is_valid_location(physAttr)
devdb.add_primitive(physAttr)
devdb.add_primitive(msft.PhysLocationAttr.get(msft.M20K, x=2, y=50, num=1))
assert devdb.is_valid_location(physAttr)
seeded_pdb = msft.PlacementDB(top.operation, devdb)
print(seeded_pdb.get_nearest_free_in_column(msft.M20K, 2, 4))
# CHECK: #msft.physloc<M20K, 2, 6, 1>
rc = seeded_pdb.add_placement(physAttr, path, "subpath", resolved_inst)
assert rc
print(seeded_pdb.get_nearest_free_in_column(msft.M20K, 2, 4))
# CHECK: #msft.physloc<M20K, 2, 50, 1>
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

View File

@ -63,6 +63,14 @@ public:
std::string subpath(inst.subpath, inst.subpathLength);
return (py::tuple)py::cast(std::make_tuple(inst.path, subpath, inst.op));
}
py::object getNearestFreeInColumn(CirctMSFTPrimitiveType prim,
uint64_t column, uint64_t nearestToY) {
MlirAttribute nearest = circtMSFTPlacementDBGetNearestFreeInColumn(
db, prim, column, nearestToY);
if (!nearest.ptr)
return py::none();
return py::cast(nearest);
}
private:
CirctMSFTPlacementDB db;
@ -179,6 +187,9 @@ void circt::python::populateDialectMSFTSubmodule(py::module &m) {
.def("add_placement", &PlacementDB::addPlacement,
"Inform the DB about a new placement.", py::arg("location"),
py::arg("path"), py::arg("subpath"), py::arg("op"))
.def("get_nearest_free_in_column", &PlacementDB::getNearestFreeInColumn,
"Find the nearest free primitive location in column.",
py::arg("prim_type"), py::arg("column"), py::arg("nearest_to_y"))
.def("get_instance_at", &PlacementDB::getInstanceAt,
"Get the instance at location. Returns None if nothing exists "
"there. Otherwise, returns (path, subpath, op) of the instance "

View File

@ -102,6 +102,14 @@ bool circtMSFTPlacementDBTryGetInstanceAt(CirctMSFTPlacementDB self,
return true;
}
MlirAttribute circtMSFTPlacementDBGetNearestFreeInColumn(
CirctMSFTPlacementDB cdb, CirctMSFTPrimitiveType prim, uint64_t column,
uint64_t nearestToY) {
auto db = unwrap(cdb);
return wrap(
db->getNearestFreeInColumn((PrimitiveType)prim, column, nearestToY));
}
//===----------------------------------------------------------------------===//
// MSFT Attributes.
//===----------------------------------------------------------------------===//

View File

@ -112,6 +112,27 @@ PlacementDB::getInstanceAt(PhysLocationAttr loc) {
return instF->getSecond();
}
PhysLocationAttr PlacementDB::getNearestFreeInColumn(PrimitiveType prim,
uint64_t columnNum,
uint64_t nearestToY) {
// Simplest possible algorithm.
PhysLocationAttr nearest = {};
walkColumnPlacements(columnNum, [&nearest, columnNum](PhysLocationAttr loc,
PlacedInstance inst) {
if (inst.op)
return;
if (!nearest) {
nearest = loc;
return;
}
int64_t curDist = std::abs((int64_t)columnNum - (int64_t)nearest.getY());
int64_t replDist = std::abs((int64_t)columnNum - (int64_t)loc.getY());
if (replDist < curDist)
nearest = loc;
});
return nearest;
}
Optional<PlacementDB::PlacedInstance *>
PlacementDB::getLeaf(PhysLocationAttr loc) {
PrimitiveType primType = loc.getPrimitiveType().getValue();
@ -119,11 +140,10 @@ PlacementDB::getLeaf(PhysLocationAttr loc) {
DimNumMap &nums = placements[loc.getX()][loc.getY()];
if (!seeded)
return &nums[loc.getNum()][primType];
auto primitivesF = nums.find(loc.getNum());
if (primitivesF == nums.end())
if (!nums.count(loc.getNum()))
return {};
auto primitives = primitivesF->second;
DimDevType &primitives = nums[loc.getNum()];
if (primitives.count(primType) == 0)
return {};
return &primitives[primType];
@ -136,30 +156,41 @@ void PlacementDB::walkPlacements(
for (auto colF = placements.begin(), colE = placements.end(); colF != colE;
++colF) {
size_t x = colF->getFirst();
DimYMap yMap = colF->getSecond();
walkColumnPlacements(x, callback);
}
}
// Y loop.
for (auto rowF = yMap.begin(), rowE = yMap.end(); rowF != rowE; ++rowF) {
size_t y = rowF->getFirst();
DimNumMap numMap = rowF->getSecond();
/// Walk the column placements in some sort of reasonable order.
void PlacementDB::walkColumnPlacements(
uint64_t columnNum,
function_ref<void(PhysLocationAttr, PlacedInstance)> callback) {
// Num loop.
for (auto numF = numMap.begin(), numE = numMap.end(); numF != numE;
++numF) {
size_t num = numF->getFirst();
DimDevType devMap = numF->getSecond();
auto colF = placements.find(columnNum);
if (colF == placements.end())
return;
DimYMap yMap = colF->getSecond();
// DevType loop.
for (auto devF = devMap.begin(), devE = devMap.end(); devF != devE;
++devF) {
PrimitiveType devtype = devF->getFirst();
PlacedInstance inst = devF->getSecond();
// Y loop.
for (auto rowF = yMap.begin(), rowE = yMap.end(); rowF != rowE; ++rowF) {
size_t y = rowF->getFirst();
DimNumMap numMap = rowF->getSecond();
// Marshall and run the callback.
PhysLocationAttr loc = PhysLocationAttr::get(
ctxt, PrimitiveTypeAttr::get(ctxt, devtype), x, y, num);
callback(loc, inst);
}
// Num loop.
for (auto numF = numMap.begin(), numE = numMap.end(); numF != numE;
++numF) {
size_t num = numF->getFirst();
DimDevType devMap = numF->getSecond();
// DevType loop.
for (auto devF = devMap.begin(), devE = devMap.end(); devF != devE;
++devF) {
PrimitiveType devtype = devF->getFirst();
PlacedInstance inst = devF->getSecond();
// Marshall and run the callback.
PhysLocationAttr loc = PhysLocationAttr::get(
ctxt, PrimitiveTypeAttr::get(ctxt, devtype), columnNum, y, num);
callback(loc, inst);
}
}
}