#include "coloquinte/circuit_helper.hxx" #include #include #include namespace coloquinte{ namespace gp{ namespace{ //index_t const null_ind = std::numeric_limits::max(); inline void opt_orient(netlist const & circuit, placement_t & pl, std::function)> i_coor, std::function &)> b_coor,mask_t FLIPPABLE){ std::stack opt_cells; for(index_t cell_ind = 0; cell_ind < circuit.cell_cnt(); ++cell_ind){ if( (circuit.get_cell(cell_ind).attributes & FLIPPABLE) != 0) opt_cells.push(cell_ind); } while(not opt_cells.empty()){ index_t cell_ind = opt_cells.top(); opt_cells.pop(); assert((circuit.get_cell(cell_ind).attributes & FLIPPABLE) != 0); // What is the current orientation? bool old_orientation = b_coor(pl.orientations_[cell_ind]); int_t pos = i_coor(pl.positions_[cell_ind]); int_t size = i_coor(circuit.get_cell(cell_ind).size); // Check both orientations of the cell std::vector involved_nets; for(netlist::pin_t p : circuit.get_cell(cell_ind)){ involved_nets.push_back(p.net_ind); } // Deal with cells with multiple pins in one net (uniquify) std::sort(involved_nets.begin(), involved_nets.end()); involved_nets.resize(std::distance(involved_nets.begin(), std::unique(involved_nets.begin(), involved_nets.end()))); std::int64_t p_cost = 0, n_cost = 0; std::vector extreme_elements; for(index_t n : involved_nets){ std::vector other_pins; std::vector offsets; for(auto p : circuit.get_net(n)){ if(p.cell_ind != cell_ind){ other_pins.push_back(pin_1D( p.cell_ind, i_coor(pl.positions_[p.cell_ind]) + (b_coor(pl.orientations_[p.cell_ind]) ? i_coor(p.offset) : i_coor(circuit.get_cell(p.cell_ind).size) - i_coor(p.offset)), 0, // Don't care about the offset (circuit.get_cell(p.cell_ind).attributes & FLIPPABLE) != 0) ); } else{ offsets.push_back(i_coor(p.offset)); } } assert(offsets.size() > 0); if(other_pins.size() > 0){ // Else the orientation of the cell doesn't change anything auto minmaxC = std::minmax_element(other_pins.begin(), other_pins.end()); auto minmaxO = std::minmax_element(offsets.begin(), offsets.end()); p_cost += std::max(pos + *minmaxO.second, minmaxC.second->pos) - std::min(pos + *minmaxO.first, minmaxC.first->pos); n_cost += std::max(pos + size - *minmaxO.first, minmaxC.second->pos) - std::min(pos + size - *minmaxO.second, minmaxC.first->pos); int_t min_pin_pos = std::min(pos + *minmaxO.second, pos + size - *minmaxO.first), max_pin_pos = std::max(pos + *minmaxO.second, pos + size - *minmaxO.first); // Do the extreme elements change between the two positions? if(minmaxC.second->movable and (minmaxC.second->pos < max_pin_pos) and (minmaxC.second->pos > min_pin_pos) ){ extreme_elements.push_back(minmaxC.second->cell_ind); } if(minmaxC.first->movable and (minmaxC.first->pos < max_pin_pos) and (minmaxC.first->pos > min_pin_pos) ){ extreme_elements.push_back(minmaxC.first->cell_ind); } } } if(p_cost < n_cost) b_coor(pl.orientations_[cell_ind]) = true; if(p_cost > n_cost) b_coor(pl.orientations_[cell_ind]) = false; // If we changed the orientation, check the extreme pins which changed and try their cells again if(b_coor(pl.orientations_[cell_ind]) != old_orientation){ std::sort(extreme_elements.begin(), extreme_elements.end()); extreme_elements.resize(std::distance(extreme_elements.begin(), std::unique(extreme_elements.begin(), extreme_elements.end()))); for(index_t extreme_cell : extreme_elements){ if( (circuit.get_cell(extreme_cell).attributes & FLIPPABLE) != 0) opt_cells.push(extreme_cell); } } } } /* inline void spread_orient(netlist const & circuit, placement_t & pl, std::function &)> coor, mask_t FLIPPABLE){ std::vector weights(circuit.cell_cnt(), 0.0); for(index_t n=0; n max_pos){ max_pos = pos; max_ind = p.cell_ind; max_offs = coor(p.offset); } } else{ float_t pos = coor(pl.positions_[p.cell_ind]) + coor(pl.orientations_[p.cell_ind]) * coor(p.offset); if(pos < min_pos){ min_pos = pos; min_ind = null_ind; } if(pos > max_pos){ max_pos = pos; max_ind = null_ind; } } } float_t net_weight = circuit.get_net(n).weight; if(min_ind != null_ind) weights[min_ind] += net_weight * min_offs; if(max_ind != null_ind) weights[max_ind] -= net_weight * max_offs; } for(index_t c=0; c= 0.0) ? 1.0 : -1.0; } } */ } // End anonymous namespace void optimize_x_orientations(netlist const & circuit, placement_t & pl){ opt_orient(circuit, pl, [](point p) -> int_t { return p.x; }, [](point & p) -> bool & { return p.x; }, XFlippable); } void optimize_y_orientations(netlist const & circuit, placement_t & pl){ opt_orient(circuit, pl, [](point p) -> int_t { return p.y; }, [](point & p) -> bool & { return p.y; }, YFlippable); } // Iteratively optimize feasible orientations; performs only one pass void optimize_exact_orientations(netlist const & circuit, placement_t & pl){ optimize_x_orientations(circuit, pl); optimize_y_orientations(circuit, pl); } /* void spread_orientations(netlist const & circuit, placement_t & pl){ spread_orient(circuit, pl, [](point & p) -> float_t & { return p.x; }, XFlippable); spread_orient(circuit, pl, [](point & p) -> float_t & { return p.y; }, YFlippable); } */ } // namespace gp } // namespace coloquinte