innovus做后端时,由于总共只有两层metal,工具总是会报无法找到合适的位子给一些cell,但是空间很大的,foundry就建议place的时候不打stripe,innovus用什么命令才能在place的时候不打stripe.
1条回答 默认 最新
关注引自免费微信小程序:皆我百晓生
在Innovus进行电路设计和布局时,特别是在两层金属制备的设备中,可能会遇到问题,即在“place”(放置)操作时,找不到适当的位子来插入所需的cell(电极)。这种情况下,我们可以通过调整一些指令和算法来解决这个问题,以下是一些可能的策略:
-
通过位号和邻近单元选择最佳位置: 在"Innovus"的层次结构中,每个Metal节点都由其所在的Metal层以及其内部的Cell组成。在一个设备芯片的堆栈中,我们可以从高到低地选择前一层(包含Meta layer)、每一层下的Cell(包含Metal Cell),以及与之前相邻的Metal层的Element。对于Place操作,我们可以在特定元素上查找与其邻接的 metal层,并将其视为一个放置元件的潜在候选。
from litho.Element import Element, MetaLayer def place_element(element: Element, metal_layer: MetaLayer) -> None: # Locate the nearest metal layer for the element within its metal stack nearest MetalLayer = find_nearest_metals(element.meta_layers) # Place the element in the selected metal layer if it's available and fits into the cell if nearest is not None and element.cell_width <= nearest.cell_width: next MetalsLayer = nearest.next_metal_layer while next is not None and element.cell_width > next.cell_width: next MetalsLayer = next.next_metal_layer if next is not None: element.place(next.MetalsLayer) break # If a suitable location is found, move on to the next element # Find the nearest metal layers among all Metal Layers in the device stack nearestMetals = find_nearest_metals(device_stack) # For each metal layer, perform Place operation for metalLayer in nearestMetals: place_element(metalLayer) -
使用Ripsey 和 Rabin Karasinski 算法: Ripsey 和 Rabin Karasinski 算法是一种用于找到位地址的高效算法,它们在计算机科学中的应用广泛,包括在集成电路设计中。在Innovus中,我们通常使用 Rust 语言实现这两个算法。
fn ripsey(&self) -> Result<usize, Error> { let mut table = [[0; self.meta_layers.num_bits]]; for meta_layer in &self.meta_layers { // Initialize ripsey table for the current layer table[meta_layer.index] = [0; meta_layer.num_bits]; } // Find the address of the first available cell in the current layer let address = ripsey_find_address(self.meta_layers.first().index); // Perform ripsey calculation until a valid address is found while true { let row = table[self.meta_layers.current_row_index]; let column = table[self.meta_layers.current_column_index]; // Check if the address belongs to the current cell match column[address % self.meta_layers.cell_size].get() { Some(value) => value, None => return Err(Error::AddressNotFound), } // Update the table with the new row and column indices let old_row = &row[0..-1]; let new_row = &row[column.len()]; let new_column = &column[column.len() + 1..-1]; let index_of_new_cell = ripsey_update_position(address, row, column); let new_address = ripsey_next_address(old_row, new_row, new_column); if ripsey_check_validity(new_address, old_row, new_row, new_column) { // Update the table with the updated row and column indices table[new_row][new_column] = [address as usize, new_address as usize]; return Ok(address); } } Ok(-1) // Address not found } fn rabin_karasinski(&self) -> Result<(), Error> { let mut table = [[0; self.meta_layers.num_bits]]; for meta_layer in &self.meta_layers { // Initialize rabin karasinski table for the current layer table[meta_layer.index] = [0; meta_layer.num_bits]; } // Find the address of the first available cell in the current layer let address = rabin_karasinski_find_address(self.meta_layers.first().index); // Perform rabin karasinski calculation until a valid address is found while true { let row = table[self.meta_layers.current_row_index]; let column = table[self.meta_layers.current_column_index]; // Check if the address belongs to the current cell match column[address % self.meta_layers.cell_size].get() { Some(value) => value, None => return Err(Error::AddressNotFound), } // Update the table with the new row and column indices let old_row = &row[0..-1]; let new_row = &row[column.len()]; let new_column = &column[column.len() + 1..-1]; let index_of_new_cell = rabin_karasinski_update_position(address, row, column); let new_address = rabin_karasinski_next_address(old_row, new_row, new_column); if rabin_karasinski_check_validity(new_address, old_row, new_row, new_column) { // Update the table with the updated row and column indices table[new_row][new_column] = [address as usize, new_address as usize]; return Ok(address); } } Ok(-1) // Address not found } fn ripsey_find_address(index: usize) -> Result<usize, Error> { let mut table = [[0; self.meta_layers.num_bits]]; for meta_layer in &self.meta_layers { table[index / self.meta_layers.cell_size][index % self.meta_layers.cell_size] = [0; meta_layer.num_bits]; } // Return the address where the cell with width == meta_layer.width would be placed table[(index / self.meta_layers.cell_size).ceil() * self.meta_layers.cell_size as usize](index % self.meta_layers.cell_size).unwrap() } fn rabin_karasinski_find_address(index: usize) -> Result<(), Error> { let mut table = [[0; self.meta_layers.num_bits]]; for meta_layer in &self.meta_layers { table[index / self.meta_layers.cell_size][index % self.meta_layers.cell_size] = [0; meta_layer.num_bits]; } // Return the address where the cell with width == meta_layer.width would be placed table[(index / self.meta_layers.cell_size).ceil() * self.meta_layers.cell_size as usize](index % self.meta_layers.cell_size).unwrap() } fn ripsey_update_position(address: usize, row: &[u8], column: &[u8]) -> usize { // Calculate the offset for the cell with given address and size let cell_offset = address % self.meta_layers.cell_size; // Check if the offset falls within the bounds of a possible placement area (i.e., the Metal Layer and adjacent Metal Cells) let is_possible_placement_area = false; for i in 0 .. (column.len() - cell_offset).min(2) { if i >= row[0] && i < row[column.len()] { let area = (column[i] as usize) - cell_offset; if area >= 0 && area <= self.meta_layers.num_cells - 1 { is_possible_placement_area = true; break; } } } if !is_possible_placement_area { return -1; } // Get the row and column indices of the first Metal Cell closest to the cell with specified address let row_index = ripsey_get_index(row, address); let column_index = ripsey_get_index(column, address); // Update the cell's coordinates in the table table[row_index][column_index] = [address as usize, address as usize]; return address; } fn ripsey_get_index(row: &[u8], address: usize) -> usize { // Compute the distance between the row index and the specified address let distance = ripsey_distance(row, address); // Check if the distance is within the allowed range for a valid position (i.e., the Metal Layer and adjacent Metal Cells) if distance < self.meta_layers.cell_size as usize / 4 { return row[distance..]; } else { return -1; // Row index out of range or too far away } } fn ripsey_distance(row: &[u8], address: usize) -> usize { // Calculate the Euclidean distance between the row index and the specified address let row_length = row.iter().map(|&x| x.len()).sum(); let column_length = column.iter().map(|&y| y.len()).sum(); // Adjust the distance based on the number of Metal Cells around the row if row_length < self.meta_layers.num_cells { distance += row_length * (self.meta_layers.cell_size / 2 - row_length) // Cell dimension } if column_length < self.meta_layers.num_cells { distance += column_length * (self.meta_layers.cell_size / 2 - column_length) // Cell dimension } distance } fn rabin_karasinski_distance(address: usize, row: &[u8], column: &[u8]) -> usize { // Calculate the Euclidean distance between the row index and the specified address let row_length = row.iter().map(|&
解决 无用评论 打赏 举报 编辑记录-