Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
	}
}
Ejemplo n.º 5
0
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;
			}
		}
	}
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
int main (int argc, char** argv) {
	FloorPlanner fp;

	samples_data_type temp_samples;
	samples_data_type power_samples;

	double avg_power, avg_temp;
	double std_dev_power, std_dev_temp;
	double cur_power_dev, cur_temp_dev;

	double cov;

	double corr;
	double avg_corr;
	int count_corr;

	// construct a trivial random generator engine from a time-based seed:
	unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
	std::default_random_engine random_generator(seed);

	std::cout << std::endl;
	std::cout << "Thermal Side-Channel Leakage Verification: Determine Entropy and Correlation of Power and Thermal Maps" << std::endl;
	std::cout << "------------------------------------------------------------------------------------------------------" << std::endl;
	std::cout << "WARNING: File handling implicitly assumes that the dimensions of power and thermal maps are all the same, both within HotSpot and Corblivar; parsing and calculation will most likely fail if there are dimension mismatches!" << std:: endl;
	std::cout << std::endl;

	// parse program parameter, config file, and further files
	IO::parseParametersFiles(fp, argc, argv);
	// parse blocks
	IO::parseBlocks(fp);
	// parse nets
	IO::parseNets(fp);

	// generate DAG (directed acyclic graph) for SL-STA (system-level static timing analysis)
	fp.initTimingPowerAnalyser();

	// init Corblivar core
	CorblivarCore corb = CorblivarCore(fp.getLayers(), fp.getBlocks().size());

	// parse alignment request
	IO::parseAlignmentRequests(fp, corb.editAlignments());

	// init thermal analyzer, only reasonable after parsing config file
	fp.initThermalAnalyzer();

	// init routing-utilization analyzer
	fp.initRoutingUtilAnalyzer();

	// no solution file found; error
	if (!fp.inputSolutionFileOpen()) {
		std::cout << "Corblivar> ";
		std::cout << "ERROR: Solution file required for call of " << argv[0] << std::endl << std::endl;
		exit(1);
	}

	// required solution file found; parse from file, and generate layout and all data such as power and thermal maps
	//
	// read from file
	IO::parseCorblivarFile(fp, corb);

	// assume read in data as currently best solution
	corb.storeBestCBLs();

	// overall cost is not determined; cost cannot be determined since no
	// normalization during SA search was performed
	//
	// generates also all required files
	fp.finalize(corb, false);
	std::cout << std::endl;

	// allocate vectors
	for (int layer = 0; layer < fp.getLayers(); layer++) {

		power_samples.emplace_back(samples_data_layer_type());
		temp_samples.emplace_back(samples_data_layer_type());
	}

	// generate power data and gather related HotSpot simulation temperature data
	//
	for (unsigned sampling_iter = 0; sampling_iter < SAMPLING_ITERATIONS; sampling_iter++) {

		std::cout << std::endl;
		std::cout << "Sampling iteration: " << (sampling_iter + 1) << "/" << SAMPLING_ITERATIONS << std::endl;
		std::cout << "------------------------------" << std::endl;

		// first, randomly vary power densities in blocks
		//
		for (Block const& b : fp.getBlocks()) {

			// restore original value, used as mean for Gaussian distribution of power densities
			b.power_density_unscaled = b.power_density_unscaled_back;

			// calculate new power value, based on Gaussian distribution
			std::normal_distribution<double> gaussian(b.power_density_unscaled, b.power_density_unscaled * MEAN_TO_STD_DEV_FACTOR);

			b.power_density_unscaled = gaussian(random_generator);

			if (DBG) {
				std::cout << "Block " << b.id << ":" << std::endl;
				std::cout << " Original power = " << b.power_density_unscaled_back << std::endl;
				std::cout << " New random power = " << b.power_density_unscaled << std::endl;
			}
		}

		// second, generate new power maps
		//
		fp.editThermalAnalyzer().generatePowerMaps(fp.getLayers(), fp.getBlocks(), fp.getOutline(), fp.getPowerBlurringParameters());

		// copy data from Corblivar power maps into local data structure power_samples
		//
		for (int layer = 0; layer < fp.getLayers(); layer++) {
			for (unsigned x = 0; x < ThermalAnalyzer::THERMAL_MAP_DIM; x++) {
				for (unsigned y = 0; y < ThermalAnalyzer::THERMAL_MAP_DIM; y++) {

					power_samples[layer][x][y][sampling_iter] = fp.getThermalAnalyzer().getPowerMapsOrig()[layer][x][y].power_density;
				}
			}
		}

		// third, run HotSpot on this new map
		//
		// generate new ptrace file first
		writeHotSpotPtrace(fp);
		// HotSpot.sh system call
		system(std::string("./HotSpot.sh " + fp.getBenchmark() + " " + std::to_string(fp.getLayers())).c_str());

		// fourth, read in the new HotSpot results into local data structure temp_samples
		//
		parseHotSpotFiles(fp, sampling_iter, temp_samples);


		if (DBG) {
			std::cout << "Printing gathered power/temperature data for sampling iteration " << sampling_iter << std::endl;
			std::cout << std::endl;

			for (int layer = 0; layer < fp.getLayers(); layer++) {
				std::cout << " Layer " << layer << std::endl;
				std::cout << std::endl;

				for (unsigned x = 0; x < ThermalAnalyzer::THERMAL_MAP_DIM; x++) {
					for (unsigned y = 0; y < ThermalAnalyzer::THERMAL_MAP_DIM; y++) {

						std::cout << "  Power[" << x << "][" << y << "]: " << power_samples[layer][x][y][sampling_iter] << std::endl;
						std::cout << "  Temp [" << x << "][" << y << "]: " << temp_samples[layer][x][y][sampling_iter] << std::endl;
					}
				}
			}
		}
	}

	// calculate avg Pearson correlation over all bins
	//
	std::cout << std::endl;
	std::cout << "Sampling results" << std::endl;
	std::cout << "----------------" << std::endl;

	for (int layer = 0; layer < fp.getLayers(); layer++) {

		// dbg output
		if (DBG) {
			std::cout << std::endl;
			std::cout << "Pearson correlations on layer " << layer << std::endl;
			std::cout << std::endl;
		}

		avg_corr = 0.0;
		count_corr = 0;

		for (unsigned x = 0; x < ThermalAnalyzer::THERMAL_MAP_DIM; x++) {
			for (unsigned y = 0; y < ThermalAnalyzer::THERMAL_MAP_DIM; y++) {

				avg_power = avg_temp = 0.0;
				cov = std_dev_power = std_dev_temp = 0.0;
				corr = 0.0;

				// first pass: determine avg values
				//
				for (unsigned sampling_iter = 0; sampling_iter < SAMPLING_ITERATIONS; sampling_iter++) {

					avg_power += power_samples[layer][x][y][sampling_iter];
					avg_temp += temp_samples[layer][x][y][sampling_iter];
				}
				avg_power /= SAMPLING_ITERATIONS;
				avg_temp /= SAMPLING_ITERATIONS;

				// dbg output
				if (DBG) {
					std::cout << "Bin: " << x << ", " << y << std::endl;
					std::cout << " Avg power: " << avg_power << std::endl;
					std::cout << " Avg temp: " << avg_temp << std::endl;
				}
				
				// second pass: determine covariance and standard deviations
				//
				for (unsigned sampling_iter = 0; sampling_iter < SAMPLING_ITERATIONS; sampling_iter++) {

					// deviations of current values from avg values
					cur_power_dev = power_samples[layer][x][y][sampling_iter] - avg_power;
					cur_temp_dev = temp_samples[layer][x][y][sampling_iter] - avg_temp;

					// covariance
					cov += cur_power_dev * cur_temp_dev;

					// standard deviation, calculate its sqrt later on
					std_dev_power += std::pow(cur_power_dev, 2.0);
					std_dev_temp += std::pow(cur_temp_dev, 2.0);
				}
				cov /= SAMPLING_ITERATIONS;
				std_dev_power /= SAMPLING_ITERATIONS;
				std_dev_temp /= SAMPLING_ITERATIONS;

				std_dev_power = std::sqrt(std_dev_power);
				std_dev_temp = std::sqrt(std_dev_temp);

				// calculate Pearson correlation: covariance over product of standard deviations
				//
				corr = cov / (std_dev_power * std_dev_temp);

				// consider only valid correlations values
				if (!std::isnan(corr)) {
					avg_corr += corr;
					count_corr++;
				}

				// dbg output
				if (DBG) {
					std::cout << " Correlation: " << corr << std::endl;
					if (std::isnan(corr)) {
						std::cout << "  NAN, because of zero power; to be skipped" << std::endl;
					}
				}
			}
		}
		avg_corr /= count_corr;

		std::cout << "Avg Pearson correlations over all bins on layer " << layer << ": " << avg_corr << std::endl;
	}
}
Ejemplo n.º 9
0
int main (int argc, char** argv) {
	FloorPlanner fp;
	bool done;

	cout << endl;
	cout << "Corblivar: Corner Block List for Varied [Block] Alignment Requests" << endl;
	cout << "----- 3D floorplanning tool v 1.1.1 ------------------------------" << endl << endl;

	// set IO mode
	IO::mode = IO::Mode::REGULAR;

	// parse program parameter, config file, and further files
	IO::parseParametersFiles(fp, argc, argv);
	// parse blocks
	IO::parseBlocks(fp);
	// parse nets
	IO::parseNets(fp);

	// init Corblivar core
	CorblivarCore corb = CorblivarCore(fp.getLayers(), fp.getBlocks().size());

	// parse alignment request
	IO::parseAlignmentRequests(fp, corb.editAlignments());

	// init thermal analyzer, only reasonable after parsing config file
	fp.initThermalAnalyzer();

	// non-regular run; read in solution file
	// (TODO) adapt if further optimization of read in data is desired
	if (fp.inputSolutionFileOpen()) {

		if (fp.logMin()) {
			cout << "Corblivar> ";
			cout << "Handling given solution file ..." << endl << endl;
		}

		// read from file
		IO::parseCorblivarFile(fp, corb);

		// assume read in data as currently best solution
		corb.storeBestCBLs();

		// overall cost is not determined; cost cannot be determined since no
		// normalization during SA search was performed
		fp.finalize(corb, false);
	}
	// regular run; perform floorplanning
	else {
		// generate new, random data set
		corb.initCorblivarRandomly(fp.logMed(), fp.getLayers(), fp.getBlocks(), fp.powerAwareBlockHandling());

		if (fp.logMin()) {
			cout << "Corblivar> ";
			cout << "Performing SA floorplanning optimization ..." << endl << endl;
		}

		// perform SA; main handler
		done = fp.performSA(corb);

		if (fp.logMin()) {
			cout << "Corblivar> ";
			if (done) {
				cout << "Done, floorplanning was successful" << endl << endl;
			}
			else {
				cout << "Done, floorplanning was _not_ successful" << endl << endl;
			}
		}

		// finalize: generate output files, final logging
		fp.finalize(corb);
	}
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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;
	}
}
Ejemplo n.º 12
0
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;
	}
}
Ejemplo n.º 13
0
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;
}