bool LayoutOperations::performOpSwitchTupleJunctions(bool const& revert, CorblivarCore& corb, int& die1, int& tuple1, int& juncts) const { int new_juncts; if (!revert) { // randomly select die, if not preassigned if (die1 == -1) { die1 = Math::randI(0, this->parameters.layers); } // sanity check for empty dies if (corb.getDie(die1).getCBL().empty()) { return false; } // randomly select tuple, if not preassigned if (tuple1 == -1) { tuple1 = Math::randI(0, corb.getDie(die1).getCBL().size()); } // juncts is for return-by-reference, new_juncts for updating junctions new_juncts = juncts = corb.getDie(die1).getJunctions(tuple1); // junctions must be geq 0 if (new_juncts == 0) { new_juncts++; } else { if (Math::randB()) { new_juncts++; } else { new_juncts--; } } if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_SWITCH_TUPLE_JUNCTS; revert: " << revert << "; die1: " << die1 << "; tuple1: " << tuple1 << "; juncts: " << new_juncts << std::endl; } corb.switchTupleJunctions(die1, tuple1, new_juncts); } else { if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_SWITCH_TUPLE_JUNCTS; revert: " << revert << "; die1: " << this->last_op_die1 << "; tuple1: " << this->last_op_tuple1 << "; juncts: " << this->last_op_juncts << std::endl; } corb.switchTupleJunctions(this->last_op_die1, this->last_op_tuple1, this->last_op_juncts); } return true; }
bool LayoutOperations::performOpEnhancedHardBlockRotation(CorblivarCore const& corb, Block const* shape_block) const { double col_max_width, row_max_height; double gain, loss; // horizontal block if (shape_block->bb.w > shape_block->bb.h) { // check blocks in (implicitly constructed) row row_max_height = shape_block->bb.h; for (Block const* b : corb.getDie(shape_block->layer).getBlocks()) { if (shape_block->bb.ll.y == b->bb.ll.y) { row_max_height = std::max(row_max_height, b->bb.h); } } // gain in horizontal direction by rotation gain = shape_block->bb.w - shape_block->bb.h; // loss in vertical direction; only if new block // height (current width) would be larger than the // row's current height loss = shape_block->bb.w - row_max_height; } // vertical block else { // check blocks in (implicitly constructed) column col_max_width = shape_block->bb.w; for (Block const* b : corb.getDie(shape_block->layer).getBlocks()) { if (shape_block->bb.ll.x == b->bb.ll.x) { col_max_width = std::max(col_max_width, b->bb.w); } } // gain in vertical direction by rotation gain = shape_block->bb.h - shape_block->bb.w; // loss in horizontal direction; only if new block // width (current height) would be larger than the // column's current width loss = shape_block->bb.h - col_max_width; } // perform rotation if no loss or gain > loss if (loss < 0.0 || gain > loss) { return shape_block->rotate(); } else { return false; } }
void LayoutOperations::prepareHandlingOutlineCriticalBlock(CorblivarCore const& corb, int& die1, int& tuple1) const { int random_tuple; tuple1 = -1; // randomly decide whether to work on the x- or y-dimension; this part is // for x-direction if (Math::randB()) { // search for one critical block among all dies for (int l = 0; l < this->parameters.layers; l++) { for (unsigned b = 0; b < corb.getDie(l).getBlocks().size(); b++) { // randomly consider any block on the current die; // when it's exceeding the outline it's to be // altered random_tuple = Math::randI(0, corb.getDie(l).getBlocks().size()); // current block exceeding die width? if (corb.getDie(l).getBlock(random_tuple)->bb.ur.x > this->parameters.outline.x) { die1 = l; tuple1 = random_tuple; break; } } if (tuple1 != -1) { break; } } } // randomly decide whether to work on the x- or y-dimension; this part is for // y-direction else { // search for one critical block among all dies for (int l = 0; l < this->parameters.layers; l++) { for (unsigned b = 0; b < corb.getDie(l).getBlocks().size(); b++) { // randomly consider any block on the current die; // when it's exceeding the outline it's to be // altered random_tuple = Math::randI(0, corb.getDie(l).getBlocks().size()); // current block exceeding die height? if (corb.getDie(l).getBlock(random_tuple)->bb.ur.y > this->parameters.outline.y) { die1 = l; tuple1 = random_tuple; break; } } if (tuple1 != -1) { break; } } } }
bool LayoutOperations::performOpSwitchInsertionDirection(bool const& revert, CorblivarCore& corb, int& die1, int& tuple1) const { if (!revert) { // randomly select die, if not preassigned if (die1 == -1) { die1 = Math::randI(0, this->parameters.layers); } // sanity check for empty dies if (corb.getDie(die1).getCBL().empty()) { return false; } // randomly select tuple, if not preassigned if (tuple1 == -1) { tuple1 = Math::randI(0, corb.getDie(die1).getCBL().size()); } if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_SWITCH_INSERTION_DIR; revert: " << revert << "; die1: " << die1 << "; tuple1: " << tuple1 << std::endl; } corb.switchInsertionDirection(die1, tuple1); } else { if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_SWITCH_INSERTION_DIR; revert: " << revert << "; die1: " << this->last_op_die1 << "; tuple1: " << this->last_op_tuple1 << std::endl; } corb.switchInsertionDirection(this->last_op_die1, this->last_op_tuple1); } return true; }
void LayoutOperations::preselectBlockFromLargestNet(CorblivarCore const& corb, int& die1, int& tuple1) const { // sanity check for largest net if (this->parameters.largest_net == nullptr) { return; } // randomly select one block from the largest net Block const* block = this->parameters.largest_net->blocks[Math::randI(0, this->parameters.largest_net->blocks.size())]; if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> LayoutOperations::preselectBlockFromLargestNet" << std::endl; std::cout << "DBG_LAYOUT> Net ID: " << this->parameters.largest_net->id << std::endl; std::cout << "DBG_LAYOUT> (Randomly) selected block to be altered: " << block->id << " on die " << block-> layer << std::endl; } // assign the die according to the selected block die1 = block->layer; // also determine the related tuple for the selected block tuple1 = corb.getDie(die1).getTuple(block); return; }
bool LayoutOperations::performOpMoveOrSwapBlocks(int const& mode, bool const& revert, bool const& SA_phase_one, CorblivarCore& corb, int& die1, int& die2, int& tuple1, int& tuple2) const { Block const* b2; if (!revert) { // randomly select die, if not preassigned if (die1 == -1) { die1 = Math::randI(0, this->parameters.layers); } if (die2 == -1) { die2 = Math::randI(0, this->parameters.layers); } // sanity checks; move operations: check for empty (origin) die if (mode == LayoutOperations::OP_MOVE_TUPLE) { if (corb.getDie(die1).getCBL().empty()) { return false; } } // sanity checks; swap operations: check for empty dies else { // sanity check for empty dies if (corb.getDie(die1).getCBL().empty() || corb.getDie(die2).getCBL().empty()) { return false; } } // randomly select tuple, if not preassigned if (tuple1 == -1) { tuple1 = Math::randI(0, corb.getDie(die1).getCBL().size()); } if (tuple2 == -1) { tuple2 = Math::randI(0, corb.getDie(die2).getCBL().size()); } // in case of swapping/moving w/in same die, ensure that tuples are // different if (die1 == die2) { // this is, however, only possible if at least two // tuples are given in that die if (corb.getDie(die1).getCBL().size() < 2) { return false; } // determine two different tuples while (tuple1 == tuple2) { tuple2 = Math::randI(0, corb.getDie(die1).getCBL().size()); } } // dbg output for operation if (LayoutOperations::DBG) { if (mode == LayoutOperations::OP_MOVE_TUPLE) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_MOVE_TUPLE;"; } else if (mode == LayoutOperations::OP_SWAP_BLOCKS) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_SWAP_BLOCKS;"; } else if (mode == LayoutOperations::OP_SWAP_BLOCKS_ENFORCE) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_SWAP_BLOCKS_ENFORCE;"; } std::cout << " revert: 0;"; std::cout << " SA_phase_one: " << SA_phase_one; std::cout << "; die1: " << die1 << "; die2: " << die2 << "; tuple1: " << tuple1 << "; tuple2: " << tuple2 << std::endl; } // improve alignment optimization; in case the block from die1 is // associated with some vertical bus, ensure that these bus' blocks are // not within one die afterwards if (this->parameters.opt_alignment) { for (CorblivarAlignmentReq const* req : corb.getDie(die1).getBlock(tuple1)->alignments_vertical_bus) { if (req->s_i->numerical_id == corb.getDie(die1).getBlock(tuple1)->numerical_id) { b2 = req->s_j; } else { b2 = req->s_i; } // if the target die die2 is the same as of the // alignment's partner block b2, prohibit this operation if (die2 == b2->layer) { if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> Alignment-aware block handling; operation not allowed" << std::endl; std::cout << "DBG_LAYOUT> Related alignment: " << req->tupleString() << std::endl; } return false; } } } // for power-aware block handling, ensure that blocks w/ higher power // density remain in upper layer if (this->parameters.power_aware_block_handling) { // if the higher-power block is in the upper layer d1, both swaps // and moves from the upper layer d1 down to the lower layer d2 // should be prohibited if (die1 > die2 && (corb.getDie(die1).getBlock(tuple1)->power_density() > corb.getDie(die2).getBlock(tuple2)->power_density()) // but for OP_SWAP_BLOCKS_ENFORCE (which is used // for handling failed alignments) they should be // considered && mode != LayoutOperations::OP_SWAP_BLOCKS_ENFORCE) { if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> Power-aware block handling; operation not allowed" << std::endl; std::cout << "DBG_LAYOUT> b1: " << corb.getDie(die1).getBlock(tuple1)->power_density() << "; b2: " << corb.getDie(die2).getBlock(tuple2)->power_density() << std::endl; } return false; } // if the higher-power block is in the upper layer d2, the same // applies else if (die2 > die1 && (corb.getDie(die2).getBlock(tuple2)->power_density() > corb.getDie(die1).getBlock(tuple1)->power_density()) // but for OP_SWAP_BLOCKS_ENFORCE (which is used // for handling failed alignments) they should be // considered && mode != LayoutOperations::OP_SWAP_BLOCKS_ENFORCE) { if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> Power-aware block handling; operation not allowed" << std::endl; std::cout << "DBG_LAYOUT> b2: " << corb.getDie(die2).getBlock(tuple2)->power_density() << "; b1: " << corb.getDie(die1).getBlock(tuple1)->power_density() << std::endl; } return false; } } // for SA phase one, floorplacement blocks, i.e., large macros, should not // be moved/swapped if (this->parameters.floorplacement && SA_phase_one && (corb.getDie(die1).getBlock(tuple1)->floorplacement || corb.getDie(die2).getBlock(tuple2)->floorplacement)) { return false; } // perform actual move or swap operation; applies only to valid candidates if (mode == LayoutOperations::OP_MOVE_TUPLE) { corb.moveTuples(die1, die2, tuple1, tuple2); } else { corb.swapBlocks(die1, die2, tuple1, tuple2); } } // revert last operation else { // offsets may have to be adapted for moves within one die // if (mode == LayoutOperations::OP_MOVE_TUPLE && this->last_op_die1 == this->last_op_die2) { // previous move: origin offset was greater than target offset; // thus, the tuple was moved before the origin offset, and the // origin offset has to increased by one // // note that, if last_op_tuple1 was the last element in the // underlying vector, the index will then refer to the // vector::end, which does not trigger memory errors and is also // the correct index if (this->last_op_tuple1 > this->last_op_tuple2) { this->last_op_tuple1++; } // previous move: origin offset was less than target offset; thus, // the target offset has to be decreased by one to account for the // removed tuple // // note that, since tuple1 != tuple2 by previously defined // original move operation for within one die, and since tuple1 < // tuple2 due to previous reason and above case handling (tuple1 > // tuple2), tuple2 is guaranteed to meet tuple2 > 1. This avoids // tuple2-- to be < 0 and thus avoids memory access errors else { this->last_op_tuple2--; } } // dbg output for operation if (LayoutOperations::DBG) { if (mode == LayoutOperations::OP_MOVE_TUPLE) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_MOVE_TUPLE;"; } else if (mode == LayoutOperations::OP_SWAP_BLOCKS) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_SWAP_BLOCKS;"; } else if (mode == LayoutOperations::OP_SWAP_BLOCKS_ENFORCE) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_SWAP_BLOCKS_ENFORCE;"; } std::cout << " revert: 1;"; std::cout << " SA_phase_one: " << SA_phase_one; std::cout << "; die1: " << this->last_op_die1 << "; die2: " << this->last_op_die2 << "; tuple1: " << this->last_op_tuple1 << "; tuple2: " << this->last_op_tuple2; std::cout << std::endl; } // perform actual operation if (mode == LayoutOperations::OP_MOVE_TUPLE) { corb.moveTuples(this->last_op_die2, this->last_op_die1, this->last_op_tuple2, this->last_op_tuple1); } else { corb.swapBlocks(this->last_op_die1, this->last_op_die2, this->last_op_tuple1, this->last_op_tuple2); } } return true; }
bool LayoutOperations::performOpEnhancedSoftBlockShaping(CorblivarCore const& corb, Block const* shape_block) const { int op; double boundary_x, boundary_y; double width, height; // see defined op-codes in class FloorPlanner to set random-number ranges; // recall that randI(x,y) is [x,y) op = Math::randI(10, 15); switch (op) { // stretch such that shape_block's right front aligns w/ the right front // of the nearest other block case LayoutOperations::OP_SHAPE_BLOCK__STRETCH_HORIZONTAL: // op-code: 10 // dummy value, to be large than right front boundary_x = 2.0 * shape_block->bb.ur.x; for (Block const* b : corb.getDie(shape_block->layer).getBlocks()) { // determine nearest right front of other blocks if (b->bb.ur.x > shape_block->bb.ur.x) { boundary_x = std::min(boundary_x, b->bb.ur.x); } } // determine resulting new dimensions width = boundary_x - shape_block->bb.ll.x; height = shape_block->bb.area / width; // apply new dimensions in case the resulting AR is allowed return shape_block->shapeByWidthHeight(width, height); // shrink such that shape_block's right front aligns w/ the left front of // the nearest other block case LayoutOperations::OP_SHAPE_BLOCK__SHRINK_HORIZONTAL: // op-code: 12 boundary_x = 0.0; for (Block const* b : corb.getDie(shape_block->layer).getBlocks()) { // determine nearest left front of other blocks if (b->bb.ll.x < shape_block->bb.ur.x) { boundary_x = std::max(boundary_x, b->bb.ll.x); } } // determine resulting new dimensions width = boundary_x - shape_block->bb.ll.x; height = shape_block->bb.area / width; // apply new dimensions in case the resulting AR is allowed return shape_block->shapeByWidthHeight(width, height); // stretch such that shape_block's top front aligns w/ the top front of // the nearest other block case LayoutOperations::OP_SHAPE_BLOCK__STRETCH_VERTICAL: // op-code: 11 // dummy value, to be large than top front boundary_y = 2.0 * shape_block->bb.ur.y; for (Block const* b : corb.getDie(shape_block->layer).getBlocks()) { // determine nearest top front of other blocks if (b->bb.ur.y > shape_block->bb.ur.y) { boundary_y = std::min(boundary_y, b->bb.ur.y); } } // determine resulting new dimensions height = boundary_y - shape_block->bb.ll.y; width = shape_block->bb.area / height; // apply new dimensions in case the resulting AR is allowed return shape_block->shapeByWidthHeight(width, height); // shrink such that shape_block's top front aligns w/ the bottom front of // the nearest other block case LayoutOperations::OP_SHAPE_BLOCK__SHRINK_VERTICAL: // op-code: 13 boundary_y = 0.0; for (Block const* b : corb.getDie(shape_block->layer).getBlocks()) { // determine nearest bottom front of other blocks if (b->bb.ll.y < shape_block->bb.ur.y) { boundary_y = std::max(boundary_y, b->bb.ll.y); } } // determine resulting new dimensions height = boundary_y - shape_block->bb.ll.y; width = shape_block->bb.area / height; // apply new dimensions in case the resulting AR is allowed return shape_block->shapeByWidthHeight(width, height); case LayoutOperations::OP_SHAPE_BLOCK__RANDOM_AR: // op-code: 14 return shape_block->shapeRandomlyByAR(); // to avoid compiler warnings, non-reachable code due to // constrained op value default: return false; } }
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; } }
bool LayoutOperations::performOpShapeBlock(bool const& revert, CorblivarCore& corb, int& die1, int& tuple1) const { Block const* shape_block; if (!revert) { // randomly select die, if not preassigned if (die1 == -1) { die1 = Math::randI(0, this->parameters.layers); } // sanity check for empty dies if (corb.getDie(die1).getCBL().empty()) { return false; } // randomly select tuple, if not preassigned if (tuple1 == -1) { tuple1 = Math::randI(0, corb.getDie(die1).getCBL().size()); } if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_ROTATE_BLOCK__SHAPE_BLOCK; revert: " << revert << "; die1: " << die1 << "; tuple1: " << tuple1 << std::endl; } // determine related block to be shaped shape_block = corb.getDie(die1).getBlock(tuple1); // backup current shape shape_block->bb_backup = shape_block->bb; // soft blocks: enhanced block shaping if (shape_block->soft) { // enhanced shaping, according to [Chen06] if (this->parameters.enhanced_soft_block_shaping) { return this->performOpEnhancedSoftBlockShaping(corb, shape_block); } // simple random shaping else { return shape_block->shapeRandomlyByAR(); } } // hard blocks: simple rotation or enhanced rotation (perform block // rotation only if layout compaction is achievable); note that this // enhanced rotation relies on non-compacted, i.e., non-packed layouts, // which is checked during config file parsing else { // enhanced rotation if (this->parameters.enhanced_hard_block_rotation) { return this->performOpEnhancedHardBlockRotation(corb, shape_block); } // simple rotation else { return shape_block->rotate(); } } } // revert last rotation else { if (LayoutOperations::DBG) { std::cout << "DBG_LAYOUT> LayoutOperations::OP_ROTATE_BLOCK__SHAPE_BLOCK; revert: " << revert << "; die1: " << this->last_op_die1 << "; tuple1: " << this->last_op_tuple1 << std::endl; } // revert by restoring backup bb corb.getDie(this->last_op_die1).getBlock(this->last_op_tuple1)->bb = corb.getDie(this->last_op_die1).getBlock(this->last_op_tuple1)->bb_backup; } return true; }