bool LayoutOperations::prepareSwappingCoordinatesFailedAlignment(CorblivarCore const& corb, int& tuple1) { std::vector<unsigned> failed_reqs_tuple_index; // determine failed alignments w/ flexible alignment handling; only such flexible // requests allow to swap their coordinates / partial requests for (unsigned r = 0; r < corb.getAlignments().size(); r++) { if (!corb.getAlignments()[r].fulfilled && corb.getAlignments()[r].handling == CorblivarAlignmentReq::Handling::FLEXIBLE) { failed_reqs_tuple_index.push_back(r); } } // randomly pick any failed alignment; onl if (!failed_reqs_tuple_index.empty()) { tuple1 = failed_reqs_tuple_index[Math::randI(0, failed_reqs_tuple_index.size())]; if (CorblivarAlignmentReq::DBG_HANDLE_FAILED) { std::cout << "DBG_ALIGNMENT> " << corb.getAlignments()[tuple1].tupleString() << " failed so far;" << std::endl; std::cout << "DBG_ALIGNMENT> swapping flexible partial alignments (swapping x- and y-alignment)" << std::endl; } return true; } return false; }
bool LayoutOperations::performOpSwapAlignmentCoordinates(bool const& revert, CorblivarCore& corb, int& tuple1) const { if (!revert) { // sanity check for assigned and valid tuple if (tuple1 == -1 || tuple1 >= static_cast<int>(corb.getAlignments().size())) { return false; } if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_SWAP_ALIGNMENT_COORDINATES; revert: " << revert << "; tuple: " << tuple1 << std::endl; } corb.swapAlignmentCoordinates(tuple1); } else { if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_SWAP_ALIGNMENT_COORDINATES; revert: " << revert << "; tuple: " << this->last_op_tuple1 << std::endl; } corb.swapAlignmentCoordinates(this->last_op_tuple1); } return true; }
bool LayoutOperations::prepareBlockSwappingFailedAlignment(CorblivarCore const& corb, int& die1, int& tuple1, int& die2, int& tuple2) { CorblivarAlignmentReq const* failed_req = nullptr; std::vector<CorblivarAlignmentReq const*> failed_reqs; Block const* b1; Block const* b1_partner; Block const* b1_neighbour = nullptr; Rect bb; // determine failed alignments for (unsigned r = 0; r < corb.getAlignments().size(); r++) { if (!corb.getAlignments()[r].fulfilled) { failed_reqs.push_back(&corb.getAlignments()[r]); } } // randomly pick any failed alignment if (!failed_reqs.empty()) { failed_req = failed_reqs[Math::randI(0, failed_reqs.size())]; // randomly decide for one block to move around / to swap with other // blocks; avoid the dummy reference block if required if ( // randomly select s_i if it's not the RBOD (failed_req->s_i->numerical_id != RBOD::NUMERICAL_ID && Math::randB()) || // also consider s_i if s_j is the RBOD failed_req->s_j->numerical_id == RBOD::NUMERICAL_ID ) { // sanity check for both s_i and s_j being RBOD if (failed_req->s_i->numerical_id == RBOD::NUMERICAL_ID) { return false; } // s_i is the block to be changed b1 = failed_req->s_i; // memorize the opposite block s_j b1_partner = failed_req->s_j; } else { // s_j is the block to be changed b1 = failed_req->s_j; // memorize the opposite block s_i b1_partner = failed_req->s_i; } // determine die and tuple variables; tuple2 is to be determined below // die1 = b1->layer; tuple1 = corb.getDie(die1).getTuple(b1); // for RBOD being the partner, we assume the same die as for the block to // be changed if (b1_partner->numerical_id == RBOD::NUMERICAL_ID) { die2 = die1; } else { die2 = b1_partner->layer; } if (CorblivarAlignmentReq::DBG_HANDLE_FAILED) { std::cout << "DBG_ALIGNMENT> s_i: " << failed_req->s_i->id << std::endl; std::cout << "DBG_ALIGNMENT> s_j: " << failed_req->s_j->id << std::endl; std::cout << "DBG_ALIGNMENT> b1: " << b1->id << std::endl; std::cout << "DBG_ALIGNMENT> b1_partner: " << b1_partner->id << std::endl; std::cout << "DBG_ALIGNMENT> die1: " << die1 << std::endl; std::cout << "DBG_ALIGNMENT> tuple1: " << tuple1 << std::endl; std::cout << "DBG_ALIGNMENT> die2: " << die2 << std::endl; std::cout << "DBG_ALIGNMENT> tuple1: to be determined" << std::endl; } // dedicatedly defined vertical bus; failed vertical alignment across // different dies if (failed_req->vertical_bus()) { // select block to swap with b1 such that blocks to be aligned (b1 // and its partner) are initially at least intersecting blocks; // that means, we need to swap with a block that is intersecting // with b1's partner block // // if b1 and its partner block are in one die, b1 needs to be // swapped with a block on another layer which is intersecting // b1's partner block; randomly select another layer // if (die1 == die2) { // such vertical alignment is only possible for > 1 // layers; sanity check if (this->parameters.layers == 1) { return false; } while (die1 == die2) { die2 = Math::randI(0, this->parameters.layers); } } // if b1 and its partner block are in different dies, b1 can be // swapped with a block intersecting b1's partner block on the // current die of b1 else { die2 = die1; } // the block to swap w/ is stepwise searched according to this bb; // init it with the bb of b1's partner block bb = b1_partner->bb; while (true) { for (Block const* b2 : corb.getDie(die2).getBlocks()) { // candidate block; overlaps with b1's partner // block if (Rect::rectsIntersect(bb, b2->bb) && // avoid swapping with b1 itself b1->numerical_id != b2->numerical_id && // also check that blocks are not partner blocks // of the alignment request; otherwise, // consecutively circular swap might occur which // are not resolving the failing alignment !failed_req->partner_blocks(b1, b2) ) { b1_neighbour = b2; break; } } // no intersecting block was found, increase the search // radius by doubling the considered bb if (b1_neighbour == nullptr) { bb.ll.x -= bb.w / 2.0; bb.ur.x += bb.w / 2.0; bb.ll.y -= bb.h / 2.0; bb.ur.y += bb.h / 2.0; } else { break; } } } // other failed alignment ranges or non-zero-offset fixed alignment // // determine relevant neighbour block to perform swap operation, i.e., // nearest neighbour w.r.t. failure type else { // also consider to randomly change die2 as well; this is required // for alignments which cannot be fulfilled within one die and // does not harm for alignments which could be fulfilled within // one die (they can then also be fulfilled across dies); note // that an explicit check for all the different options of // alignments not possible within one die are not performed here // but rather a die change is considered randomly // // note that changing dies is only possible for > 1 layers if (Math::randB() && this->parameters.layers > 1) { while (die1 == die2) { die2 = Math::randI(0, this->parameters.layers); } } // consider different neighbours for different alignment failures switch (b1->alignment) { // determine nearest right block case Block::AlignmentStatus::FAIL_HOR_TOO_LEFT: for (Block const* b2 : corb.getDie(die2).getBlocks()) { if (Rect::rectA_leftOf_rectB(b1->bb, b2->bb, true) && // also check that blocks are not partner blocks // of the alignment request; otherwise, // consecutively circular swap might occur which // are not resolving the failing alignment !failed_req->partner_blocks(b1, b2) ) { if (b1_neighbour == nullptr || b2->bb.ll.x < b1_neighbour->bb.ll.x) { b1_neighbour = b2; } } } break; // determine nearest left block case Block::AlignmentStatus::FAIL_HOR_TOO_RIGHT: for (Block const* b2 : corb.getDie(die2).getBlocks()) { if (Rect::rectA_leftOf_rectB(b2->bb, b1->bb, true) && // also check that blocks are not partner blocks // of the alignment request; otherwise, // consecutively circular swap might occur which // are not resolving the failing alignment !failed_req->partner_blocks(b1, b2) ) { if (b1_neighbour == nullptr || b2->bb.ur.x > b1_neighbour->bb.ur.x) { b1_neighbour = b2; } } } break; // determine nearest block above case Block::AlignmentStatus::FAIL_VERT_TOO_LOW: for (Block const* b2 : corb.getDie(die2).getBlocks()) { if (Rect::rectA_below_rectB(b1->bb, b2->bb, true) && // also check that blocks are not partner blocks // of the alignment request; otherwise, // consecutively circular swap might occur which // are not resolving the failing alignment !failed_req->partner_blocks(b1, b2) ) { if (b1_neighbour == nullptr || b2->bb.ll.y < b1_neighbour->bb.ll.y) { b1_neighbour = b2; } } } break; // determine nearest block below case Block::AlignmentStatus::FAIL_VERT_TOO_HIGH: for (Block const* b2 : corb.getDie(die2).getBlocks()) { if (Rect::rectA_below_rectB(b2->bb, b1->bb, true) && // also check that blocks are not partner blocks // of the alignment request; otherwise, // consecutively circular swap might occur which // are not resolving the failing alignment !failed_req->partner_blocks(b1, b2) ) { if (b1_neighbour == nullptr || b2->bb.ur.y > b1_neighbour->bb.ur.y) { b1_neighbour = b2; } } } break; // dummy case, to catch other (here not occurring) // alignment status default: break; } } // determine related tuple of neighbour block; == -1 in case the tuple // cannot be find; sanity check for undefined neighbour if (b1_neighbour != nullptr) { tuple2 = corb.getDie(die2).getTuple(b1_neighbour); if (CorblivarAlignmentReq::DBG_HANDLE_FAILED) { std::cout << "DBG_ALIGNMENT> " << failed_req->tupleString() << " failed so far;" << std::endl; std::cout << "DBG_ALIGNMENT> failed alignment status (" << b1->id << "): " << b1->alignment << std::endl; std::cout << "DBG_ALIGNMENT> considering swapping block " << b1->id << " on layer " << b1->layer; std::cout << " with block " << b1_neighbour->id << " on layer " << b1_neighbour->layer << std::endl; } return true; } else { tuple2 = -1; if (CorblivarAlignmentReq::DBG_HANDLE_FAILED) { std::cout << "DBG_ALIGNMENT> " << failed_req->tupleString() << " failed so far;" << std::endl; std::cout << "DBG_ALIGNMENT> failed alignment status (" << b1->id << "): " << b1->alignment << std::endl; std::cout << "DBG_ALIGNMENT> no appropriate block to swap with found" << std::endl; } return false; } } // no failing request was found else { return false; } }