package org.javafans.print.common;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import javax.imageio.ImageIO;
import org.nutz.log.Logs;
public class DrawKL {
public static void main(String[] args) throws Exception {
getInstanse().CreateSegmentationMap(
new Rectangle2D.Float(0F,0F, 990.0F, 800.0F),
new Rectangle2D.Float(0f,0F, 200.0F, 400.0F), 3, new File("d:/1/real.jpg"), false);
}
/**
* @author tangsu
* @param outside 外面的大矩形
* @param inside 里面的小矩形
* @param type 分割类型 2横着 3 混放 默认竖着
* @param tofile 图片保存到的文件
* @param isbook 是否是书本 true 是
* @return 返回HspaiResult 最后选择的画法的描述 如果outside 最大的边 小于 inside 最大的边 返回 null
*/
public HspaiResult CreateSegmentationMap(Rectangle2D r_outside, Rectangle2D r_inside, int type, File tofile, boolean isbook){
Rectangle2D outside = new Rectangle2D.Double(r_outside.getX(), r_outside.getY(), r_outside.getWidth(), r_outside.getHeight());
Rectangle2D inside = new Rectangle2D.Double(r_inside.getX(), r_inside.getY(), r_inside.getWidth(), r_inside.getHeight());
double a_w = outside.getWidth();
double a_h = outside.getHeight();
double b_w = inside.getWidth();
double b_h = inside.getHeight();
double d_temp = 0d;
if(a_w < a_h){
d_temp = a_w;
a_w = a_h;
a_h = d_temp;
outside.setRect(0d, 0d, a_w, a_h);
}
if(b_w < b_h){
d_temp = b_w;
b_w = b_h;
b_h = d_temp;
inside.setRect(0d, 0d, b_w, b_h);
}
if(a_w < b_w){//大矩形 小于 小矩形 直接返回null
return null;
}
this.isbook = isbook;
resultoutfile = tofile;
if(!resultoutfile.getParentFile().exists()){
resultoutfile.getParentFile().mkdirs();
}
if(isbook){
xuxianbs = new BasicStroke(LINEPX / 2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10F,
new float[]{2, 2f, 4f, 2f, 2f, 2f}, 0F);
xxline = new Line2D.Double();
}
try {
HspaiResult resu = null;
if(type == 2){
resu = StartDrew(CreateTransverse(outside, inside), outside, inside);
}else if(type == 3){
resu = CreateAnyway(outside, inside, false);// true 开启测试 显示计算结果 false 不测试
}else{
resu = StartDrew(CreateVertical(outside, inside), outside, inside);
}
if(resu == null){
return null;
}
resu.outside = r_outside;
resu.inside = r_inside;
resu.clxl = getClxl(resu);
return resu;
} catch (Exception e) {
Logs.getLog(DrawKL.class).error(e);
return null;
}
}
//横放 和 竖放 决定后 开始 画图
private HspaiResult StartDrew(HspaiResult result, Rectangle2D outside, Rectangle2D inside) throws Exception{
Rectangle2D huabu = getBigRect(outside, inside);
BufferedImage img = new BufferedImage((int)huabu.getWidth(), (int)huabu.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D)img.getGraphics();
BasicStroke basic = new BasicStroke(LINEPX);
g2.setStroke(basic);
g2.setColor(Color.WHITE);
g2.setBackground(Color.WHITE);
g2.fill(huabu);
g2.setColor(Color.RED);
huabu.setRect(0, 0, huabu.getWidth() - LINEPX, huabu.getHeight() - LINEPX);
g2.draw(huabu);
g2.setColor(Color.BLACK);
for(int i = 1; i <= result.description.size(); i++){
for(Rectangle2D r : result.description.get(i)){
if(isbook){
drawXXLine(g2, r, xxline, xuxianbs, basic);
}
g2.draw(r);
}
}
ImageIO.write(img, "JPEG", new FileOutputStream(resultoutfile));
return result;
}
//小矩形只能横放
private HspaiResult CreateTransverse(Rectangle2D outside, Rectangle2D inside) throws Exception{
double dw = outside.getWidth() / inside.getWidth();
int wn = (int) dw;
double dh = outside.getHeight() / inside.getHeight();
int hn = (int) dh;
if(outside.getWidth() < outside.getHeight()){
outside.setRect(0, 0, outside.getHeight(), outside.getWidth());
}
double f_y_t = 0d;
double f_x_t = 0d;
int row = 0;
List<Rectangle2D> dep_arl = new LinkedList<Rectangle2D>();
HashMap<Integer, List<Rectangle2D>> description = new HashMap<Integer, List<Rectangle2D>>();
description.put(++row, dep_arl);
HspaiResult re_temp = new HspaiResult();
re_temp.description = description;
for(int i = 0; i <= hn; i++){
if(outside.getHeight() - f_y_t < inside.getHeight()){
break;
}
f_x_t = 0d;
for(int j = 0; j <= wn; j++){
if(outside.getWidth() - f_x_t < inside.getWidth()){
break;
}
inside.setRect(f_x_t , f_y_t, inside.getWidth(), inside.getHeight());
dep_arl.add(new Rectangle2D.Double(inside.getX(), inside.getY(), inside.getWidth(), inside.getHeight()));
++ re_temp.total;
f_x_t += inside.getWidth();
}
f_y_t += inside.getHeight();
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
}
return re_temp;
}
//小矩形只能竖放
private HspaiResult CreateVertical(Rectangle2D outside, Rectangle2D inside) throws Exception{
inside.setRect(inside.getX(), inside.getY(), inside.getHeight(), inside.getWidth());
return CreateTransverse(outside, inside);
}
//小矩形可以随意放
private HspaiResult CreateAnyway(Rectangle2D outside, Rectangle2D inside, boolean debug) throws Exception{
//全部横排
HspaiResult hzfimg = CreateTransverse(outside, inside);
int hp_total = hzfimg.total;
//全部竖排
HspaiResult szfimg = CreateVertical(outside, inside);
int sp_total = szfimg.total;
//混排
int hsp_total = getMaxiMum(outside, inside);
if(debug){
hp_total = 0;
sp_total = 0;
}
if(hp_total >= sp_total && hp_total >= hsp_total){//横排最多
return StartDrew(hzfimg,outside, inside);
}else if(sp_total >= hp_total && sp_total >= hsp_total){//竖排最多
return StartDrew(szfimg,outside, inside);
}else{//横竖混排最多
Rectangle2D huabu = null;
if(maxresult.description.size() > 0){
List<Rectangle2D> frow = maxresult.description.get(1);
double huabu_w = outside.getWidth() + ((frow.size() + 1) * LINEPX);
double huabu_h = outside.getHeight() + ((maxresult.description.size() + 1) * LINEPX);
outside.setRect(0, 0, huabu_w, huabu_h);
huabu = outside;
}else{
huabu = getBigRect(outside, inside);
}
BufferedImage img = new BufferedImage((int)huabu.getWidth(), (int)huabu.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D)img.getGraphics();
g2.setStroke(new BasicStroke(LINEPX));
g2.setColor(Color.WHITE);
g2.setBackground(Color.WHITE);
g2.fill(huabu);
g2.setColor(Color.RED);
outside.setRect(0, 0, outside.getWidth() - LINEPX, outside.getHeight() - LINEPX);
g2.draw(huabu);
g2.setColor(Color.BLACK);
BasicStroke bases = new BasicStroke(LINEPX);
//--------------------------------测试计算过程-------实际应用中 debug = false ------------------------------------------
int iname = 0;
if(debug){
for(HspaiResult hs_resu_te : relist){
iname++;
for(int i = 1; i <= maxresult.description.size(); i++){
for(Rectangle2D r : maxresult.description.get(i)){
if(isbook){
drawXXLine(g2, r, xxline, xuxianbs, bases);
}
g2.draw(r);
System.out.println(r);
}
}
System.out.println("============================= " + iname + " ===========================");
ImageIO.write(img, "JPEG", new FileOutputStream(new File("d:/1/"+iname+".jpg")));
img = new BufferedImage((int)huabu.getWidth(), (int)huabu.getHeight(), BufferedImage.TYPE_INT_RGB);
g2 = (Graphics2D)img.getGraphics();
g2.setStroke(bases);
g2.setColor(Color.WHITE);
g2.setBackground(Color.WHITE);
g2.fill(huabu);
g2.setColor(Color.RED);
outside.setRect(0, 0, outside.getWidth() - LINEPX, outside.getHeight() - LINEPX);
g2.draw(huabu);
g2.setColor(Color.BLACK);
}
img = new BufferedImage((int)huabu.getWidth(), (int)huabu.getHeight(), BufferedImage.TYPE_INT_RGB);
g2 = (Graphics2D)img.getGraphics();
g2.setStroke(bases);
g2.setColor(Color.WHITE);
g2.setBackground(Color.WHITE);
g2.fill(huabu);
g2.setColor(Color.RED);
outside.setRect(0, 0, outside.getWidth() - LINEPX, outside.getHeight() - LINEPX);
g2.draw(huabu);
g2.setColor(Color.BLACK);
}
//------------------debug code row end ----------------------------------------------------------------------------------------
for(int i = 1; i <= maxresult.description.size(); i++){
for(Rectangle2D r : maxresult.description.get(i)){
if(isbook){
drawXXLine(g2, r, xxline, xuxianbs, bases);
}
g2.draw(r);
if(debug){
System.out.println(r);
}
}
}
System.out.println(maxresult.total);
resultoutfile.deleteOnExit();
if(debug){
ImageIO.write(img, "JPEG", new FileOutputStream(new File("d:/1/"+(iname+1)+".jpg")));
}else{
ImageIO.write(img, "JPEG", new FileOutputStream(resultoutfile));
}
return maxresult;
}
}
private int getMaxiMum(Rectangle2D outside, Rectangle2D inside){//开始混排 分别 2种混排 方式 返回混排最大能排的数量
double a_w = outside.getWidth();
double a_h = outside.getHeight();
double b_w = inside.getWidth();
double b_h = inside.getHeight();
double d_temp = 0d;
if(a_w < a_h){
d_temp = a_w;
a_w = a_h;
a_h = d_temp;
}
if(b_w < b_h){
d_temp = b_w;
b_w = b_h;
b_h = d_temp;
}
getMaxiMumOne(a_w, a_h, b_w, b_h, 3, outside); //使用第一种混排方法 一直排列 竖着的 从1开始
getMaxiMumTwo(a_w, a_h, b_w, b_h, 3, outside); //使用第2种混排方法 每排竖着开始
//全部计算完成 遍历 所有排法 找到最多的
for(HspaiResult r : relist){//循环查找裁剪最多的方法
if(maxresult == null && r != null){
maxresult = r;
}else if(r != null && maxresult.total < r.total){
maxresult = r;
}
}
if(maxresult != null){
return maxresult.total;
}
return 0;
}
private void getMaxiMumOne(double a_w, double a_h, double b_w, double b_h, int type, Rectangle2D outside){//页面 混排法1 一个个 竖排着走
int sp_total = (int)((a_w/b_w) * (a_h/b_h));
List<Rectangle2D> dep_arl = null;
HashMap<Integer, List<Rectangle2D>> description = null;
HspaiResult re_temp = null;
Rectangle2D rectangle2d_cell_temp = null;
int max_sp = (int)(a_w / b_h);
double last_sz_hight = 0d;//最高的一个 竖着的,用于 判断是否画完了
boolean isDown = false;// 是否不能再往下填 竖着的 了
for(int i = 1; i <= sp_total; i++){
if(isDown){//如果不能往下填 竖着的了 直接结束循环
break;
}
int row = 1;
re_temp = new HspaiResult();
description = new HashMap<Integer, List<Rectangle2D>>();
dep_arl = new LinkedList<Rectangle2D>();
re_temp.description = description;
description.put(row, dep_arl);
int first_add_sp_row = i % max_sp == 0 ? i / max_sp : (i / max_sp + 1);
first_add_sp_row = first_add_sp_row == 0 ? 1 : first_add_sp_row;
float first_sp_x = 0F;
float first_sp_y = 0F;
for(int iii = 1; iii <= i; iii++){//填充开始的竖着的图形
if(a_w - first_sp_x < b_h){//横排 竖行 放满了 需要换行
first_sp_y += b_w;
if(a_h - first_sp_y < b_w){//检查是否 无法再 放竖着的了
isDown = true;
break;
}
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
first_sp_x = 0F;
rectangle2d_cell_temp = new Rectangle2D.Float(first_sp_x, first_sp_y, (float)b_h, (float)b_w);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
}else{//不用换行
rectangle2d_cell_temp = new Rectangle2D.Float(first_sp_x, first_sp_y, (float)b_h, (float)b_w);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
}
if(rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight() > last_sz_hight){
last_sz_hight = rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight();
}
first_sp_x += b_h;
}
Rectangle2D last_sp = rectangle2d_cell_temp;
double x = 0d;
double y = 0d;
//开始计算并且插入横着的图形
if(last_sp != null){
while(true){
if(a_w - rectangle2d_cell_temp.getX() - rectangle2d_cell_temp.getWidth() < b_w){ //判断是否已经裁剪完成了
if(rectangle2d_cell_temp == last_sp){//最后一个是竖着的
if(a_h - last_sz_hight < b_h){
break;
}
}else{
if(last_sz_hight > rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight()){
if(a_h - last_sz_hight < b_h){
break;
}
}else if(a_h - rectangle2d_cell_temp.getY() - rectangle2d_cell_temp.getHeight() < b_h){
break;
}
}
}
if(rectangle2d_cell_temp == last_sp){//说明最后一个是竖着的 直接比较内存地址
if(a_w - last_sp.getX() - last_sp.getWidth() >= b_w){//还能放下一个横着的
x = last_sp.getX() + last_sp.getWidth();
y = last_sp.getY();
}else{
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
x = 0;
y = last_sp.getY() + last_sp.getHeight();
}
}else{//最后一个是横着的
if(a_w - rectangle2d_cell_temp.getX() - rectangle2d_cell_temp.getWidth() >= b_w){
x = rectangle2d_cell_temp.getX() + rectangle2d_cell_temp.getWidth();
y = rectangle2d_cell_temp.getY();
}else{//换行,考虑在不在竖着的影响内
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
if(last_sz_hight - rectangle2d_cell_temp.getY() - rectangle2d_cell_temp.getHeight() >= b_h){//就算换行也在竖着的高内 (能够放的下)
x = last_sp.getX() + last_sp.getWidth();
y = rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight();
}else{
x = 0d;
if(last_sz_hight > rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight()){
y = last_sz_hight;
}else{
y = rectangle2d_cell_temp.getY() + rectangle2d_cell_temp.getHeight();
}
}
}
}
rectangle2d_cell_temp = new Rectangle2D.Double(x, y, b_w, b_h);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
}
}else{//一个竖着的都放不下
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
rectangle2d_cell_temp = new Rectangle2D.Double(0d, 0d, b_w, b_h);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
isDown = true;
}
relist.add(re_temp);
}
}
private void getMaxiMumTwo(double a_w, double a_h, double b_w, double b_h, int type, Rectangle2D outside){//页面 混排法2 每列 开头都是横的 然后用竖的填
int hp_total = (int)((a_w/b_w) * (a_h/b_h));
List<Rectangle2D> dep_arl = null;
HashMap<Integer, List<Rectangle2D>> description = null;
HspaiResult re_temp = null;
Rectangle2D rectangle2d_cell_temp = null;
int max_sp = (int)(a_w / b_h);
boolean isDown = false;// 是否不能再往下填 竖着的 了
for(int i = 1; i <= hp_total; i++){
if(isDown){//如果不能往下填 横着的了 直接结束循环
break;
}
int row = 1;
re_temp = new HspaiResult();
description = new HashMap<Integer, List<Rectangle2D>>();
dep_arl = new LinkedList<Rectangle2D>();
re_temp.description = description;
description.put(row, dep_arl);
int first_add_sp_row = i % max_sp == 0 ? i / max_sp : (i / max_sp + 1);
first_add_sp_row = first_add_sp_row == 0 ? 1 : first_add_sp_row;
double hx = 0d;
double hy = 0d;
for(int iii = 1; iii <= i; iii++){//填充开始的竖着的图形
while(true){//放 横着的
if(a_w - hx - b_w < b_w){//这排 横着的 放满了
if(a_h - hy < b_h){// 已经不能继续循环了查找排法了
isDown = true;
break;
}
}
//没有放完
if(a_h - hy < b_h){
break;
}else{
rectangle2d_cell_temp = new Rectangle2D.Double(hx, hy, b_w, b_h);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
hy += b_h;
}
}
if(isDown){
break;
}
if(iii != i){
hx += b_w;
hy = 0d;
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
}
}
// Rectangle2D last_sp = rectangle2d_cell_temp;//最后一个自动模式添加的
double x = hx + b_w;
double y = 0d;
//开始计算并且插入竖着的图形
if(a_w - x >= b_h){
while(true){
if(a_h - y < b_w){//必须换行
if(a_w - x - b_h < b_h){//判断 是否还能继续 换行 添加 竖着的
break;
}
dep_arl = new LinkedList<Rectangle2D>();
description.put(++row, dep_arl);
y = 0d;
x += hx + b_h;
}
rectangle2d_cell_temp = new Rectangle2D.Double(x, y, b_h, b_w);
dep_arl.add(rectangle2d_cell_temp);
++re_temp.total;
y += b_w;
}
}
relist.add(re_temp);
}
}
/**
* 返回 画布的 估计大小
* @param out 大矩形
* @param ins 小矩形
* @return 返回画布
*/
private Rectangle2D getBigRect(Rectangle2D out, Rectangle2D ins){
double a_w = out.getWidth();
double a_h = out.getHeight();
double b_w = ins.getWidth();
double b_h = ins.getHeight();
double d_temp=0d;
if(a_w < a_h){
d_temp = a_w;
a_w = a_h;
a_h = d_temp;
}
if(b_w < b_h){
d_temp = b_h;
b_h = b_w;
b_w = d_temp;
}
double w = a_w + ((int)(a_w / b_h) + 1) * LINEPX;
double h = a_h + ((int)(a_h / b_h) + 1) * LINEPX;
return new Rectangle2D.Double(0d, 0d, w, h);
}
public static DrawKL getInstanse(){
return new DrawKL();
}
private DrawKL() {
}
/**
* 描述 画图结果
* @author 樱花林下
*
*/
public class HspaiResult{
/**
* 小图总数
*/
public int total = 0;
/**
* 画法描述
* key 为 行数 1 2 3以此类推
*/
public HashMap<Integer, List<Rectangle2D>> description = null;
/**
* 材料的利用率
*/
public double clxl = 0d;
/**
* 画图的大小矩形
*/
public Rectangle2D outside = null;
public Rectangle2D inside = null;
/**
* 输出的文件路径
*/
public String filepath = null;
/**
* 理论原纸数
*/
public double papernum = 0d;
}
/**
* 用于画 书籍 的 虚线
* @param g2 画笔
* @param r 当前的小矩形
* @param xxline 要更新的虚线对象
* @param xuxianbs 虚线的样式
* @param bases 原来的样式
*/
private void drawXXLine(Graphics2D g2, Rectangle2D r, Line2D xxline, BasicStroke xuxianbs, BasicStroke bases){
g2.setStroke(xuxianbs);
g2.setColor(Color.RED);
if(r.getWidth() > r.getHeight()){
xxline.setLine(r.getX() + (r.getWidth() / 2), r.getY(), r.getX() + (r.getWidth() / 2), r.getY()+r.getHeight());
}else{
xxline.setLine(r.getX(), r.getY() + (r.getHeight() / 2), r.getX() + r.getWidth(), r.getY() + (r.getHeight() / 2));
}
g2.draw(xxline);
g2.setStroke(bases);
g2.setColor(Color.BLACK);
}
/**
* 计算材料利用率
* @param 画法描述
* @return 利用率
*/
private double getClxl(HspaiResult resu) {
double a_in_m = resu.inside.getWidth() * resu.inside.getHeight() * resu.total;
double a_ou_m = resu.outside.getWidth() * resu.outside.getHeight();
return BigDecimal.valueOf((a_in_m / a_ou_m) * 100).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
}
private File resultoutfile = null; // 要把最后的 结果 画到的 图片文件
private HspaiResult maxresult = null; // 混合排版 最后找到的最多 的 结果
private List<HspaiResult> relist = new LinkedList<HspaiResult>(); // 混合排版 的 所有排法的 描述
private final static int LINEPX = 1; // 图形的 边框 宽度
private boolean isbook = false;//是否是书本
//如果是书本 会初始化
private BasicStroke xuxianbs = null;
private Line2D xxline = null;
}
分享到:
相关推荐
在“用工具画的,比较清晰”的描述中,这表明了该版图是使用专业的设计工具绘制的,这些工具可以提供精细的几何形状控制、复杂的布线算法以及全面的物理验证能力,使得设计师能够创建出既符合设计规则又满足性能需求...
完成CMOS与非门版图设计,CMOS与非门的原理图如下,要求在L-edit工具中画出以下电路元件,并且给出输入输出端口以及电源和地线。画出上述晶体管对应的版图,并且要求画出的版图在电学上、物理几何上,以及功能一致性...
Schematic (LVS)** 是比较版图和对应的电路原理图的过程,确保两者的一致性。LVS检查包括元件匹配、连接正确性、网络一致性等。在Virtuoso中,设计师可以导出版图数据,并在Calibre中进行LVS验证,以确保版图的物理...
然后,用户可以打开文件,生成cell0,选择要绘制的图形和图层。当图形绘制完成后,进入编辑图形阶段,可以进行水平切割、移动、合并对象以及布尔运算等操作。 在版图设计中,布尔运算是一个重要的概念,它允许设计...
除了以上核心内容,版图教程可能还会涵盖更多相关知识,如版图优化策略、多项目晶圆(MPW)服务、IP核的复用与封装,以及版图物理验证工具的使用等。 总之,《TSMC工艺的-版图教程》全面介绍了从电路设计到版图实现...
GIV 2025 是一份关于智能世界产业版图的报告,该报告旨在描绘未来智能世界的产业版图,并为相关企业和个人提供指导和参考。下面是该报告的详细知识点: 一、智能世界产业版图的定义 智能世界产业版图是指在智能...
绘制版图时,我们需要根据电路的设计要求选择合适的版图层次和显示属性,以确保版图的正确性和可靠性。 Cadence 版图设计为我们提供了一个强大的工具来实现模拟集成电路的设计和模拟,使得我们可以快速地设计和实现...
这个项目将带领我们深入理解收音机的工作原理,并通过分析其原理图和PCB(Printed Circuit Board)版图,了解实际的设计过程。 一、收音机工作原理 收音机的基本功能是接收广播电台的无线电波并将其转化为声音信号...
版图设计是集成电路设计的关键步骤,它涉及到物理布局、布线和优化,直接影响芯片的性能、功耗和良率。以下是一些版图设计的重要注意事项: 1. **Tap(晶体管包围环)处理**:在器件周围放置Tap时,确保Tap的连接处...
在这里,我们总结了 ic 版图设计的经验总结,包括版图设计的基本原则、版图设计的步骤、版图设计的注意事项和版图设计的技巧。 版图设计的基本原则 1. 版图设计的目标是实现芯片的可靠性、性能和制造效率。 2. ...
基本的门电路电路图及版图,详细对照,有兴趣的可以下来看看
后端设计流程主要包括三步:绘制schematic电路图、版图设计和后端验证和提取。 1. 绘制schematic电路图 在绘制schematic电路图时,我们需要使用专门的电路设计软件,例如Cadence或Synopsys等。我们需要按照电路图...
本实验的目的是设计一个CMOS反相器的电路原理图、电气符号图和版图,并使用Virtuoso工具对版图进行设计规则验证(DRC)。 一、实验目的 1. 创建CMOS反相器的电路原理图(schematic)、电气符号图(symbol)和版图...
ADS 版图和 HFSS 之间相互导入的方法 ADS 版图和 HFSS 之间相互导入的方法是指在高频电路设计中,将 HFSS 仿真数据导入到 ADS 中,并将 ADS 版图导入到 HFSS 中的方法。这种方法可以实现 HFSS 和 ADS 之间的数据...
1. **环境设置**:首先,你需要配置Virtuoso的工作环境,包括安装必要的软件组件、设置工作目录、加载库和项目模板。了解如何启动和配置Virtuoso工作空间至关重要。 2. **设计层次化**:Virtuoso支持层次化设计,这...
版图设计就是按照线路的要求和一定的工艺参数,设计出元件的图形并进行排列互连,以设计出一套供IC制造工艺中使用的光刻掩膜版的图形,称为版图或工艺复合图。 版图设计是制造IC的基本条件,版图设计...
- 编辑单元内部版图时,要在单元实例上添加POLY、有源区层和METAL1等层的版图元素,确保与单元模板一致。 - 选中所有属于单元内部的版图元素,但不包括单元实例本身,然后通过“创建单元内部版图”命令将这些元素...
版图设计是指在集成电路设计中对版图的设计和优化,以提高集成电路的性能和可靠性。在版图设计中,噪声和匹配是两个非常重要的概念。 噪声是指在版图设计中由于各种原因引起的不确定性和随机性,例如光刻、刻蚀、...