double get_shared_len(flp_t *flp, int i, int j) { double p11, p12, p21, p22; p11 = p12 = p21 = p22 = 0.0; if (i==j) return FALSE; if (is_horiz_adj(flp, i, j)) { p11 = flp->units[i].bottomy; p12 = p11 + flp->units[i].height; p21 = flp->units[j].bottomy; p22 = p21 + flp->units[j].height; } if (is_vert_adj(flp, i, j)) { p11 = flp->units[i].leftx; p12 = p11 + flp->units[i].width; p21 = flp->units[j].leftx; p22 = p21 + flp->units[j].width; } return (MIN(p12, p22) - MAX(p11, p21)); }
void create_RC_matrices(flp_t *flp, int omit_lateral) { int i, j, k = 0, n = flp->n_units; int **border; double **len, *gx, *gy, **g, *c_ver, **t, *gx_sp, *gy_sp; double r_sp1, r_sp2, r_hs; /* lateral resistances to spreader and heatsink */ /* NOTE: *_mid - the vertical R/C from CENTER nodes of spreader * and heatsink. *_per - the vertical R/C from PERIPHERAL (n,s,e,w) nodes */ double r_sp_per, r_hs_mid, r_hs_per, c_sp_per, c_hs_mid, c_hs_per; double gn_sp=0, gs_sp=0, ge_sp=0, gw_sp=0; double w_chip = get_total_width (flp); /* x-axis */ double l_chip = get_total_height (flp); /* y-axis */ border = imatrix(n, 4); len = matrix(n, n); /* len[i][j] = length of shared edge bet. i & j */ gx = vector(n); /* lumped conductances in x direction */ gy = vector(n); /* lumped conductances in y direction */ gx_sp = vector(n); /* lateral conductances in the spreader layer */ gy_sp = vector(n); g = matrix(NL*n+EXTRA, NL*n+EXTRA); /* g[i][j] = conductance bet. nodes i & j */ c_ver = vector(NL*n+EXTRA); /* vertical capacitance */ b = matrix(NL*n+EXTRA, NL*n+EXTRA); /* B, C, INVA and INVB are (NL*n+EXTRA)x(NL*n+EXTRA) matrices */ c = matrix(NL*n+EXTRA, NL*n+EXTRA); inva = matrix(NL*n+EXTRA, NL*n+EXTRA); invb = matrix(NL*n+EXTRA, NL*n+EXTRA); t = matrix (NL*n+EXTRA, NL*n+EXTRA); /* copy of B */ /* compute the silicon fitting factor - see pg 10 of the UVA CS tech report - CS-TR-2003-08 */ factor_chip = C_FACTOR * ((SPEC_HEAT_INT / SPEC_HEAT_SI) * (w_chip + 0.88 * t_interface) \ * (l_chip + 0.88 * t_interface) * t_interface / ( w_chip * l_chip * t_chip) + 1); /* fitting factor for interface - same rationale as above */ factor_int = C_FACTOR * ((SPEC_HEAT_CU / SPEC_HEAT_INT) * (w_chip + 0.88 * t_spreader) \ * (l_chip + 0.88 * t_spreader) * t_spreader / ( w_chip * l_chip * t_interface) + 1); /*printf("fitting factors : %lf, %lf\n", factor_chip, factor_int); */ /* gx's and gy's of blocks */ for (i = 0; i < n; i++) { /* at the silicon layer */ if (omit_lateral) { gx[i] = gy[i] = 0; } else { gx[i] = 1.0/getr(K_SI, flp->units[i].height, flp->units[i].width, l_chip, t_chip); gy[i] = 1.0/getr(K_SI, flp->units[i].width, flp->units[i].height, w_chip, t_chip); } /* at the spreader layer */ gx_sp[i] = 1.0/getr(K_CU, flp->units[i].height, flp->units[i].width, l_chip, t_spreader); gy_sp[i] = 1.0/getr(K_CU, flp->units[i].width, flp->units[i].height, w_chip, t_spreader); } /* shared lengths between blocks */ for (i = 0; i < n; i++) for (j = i; j < n; j++) len[i][j] = len[j][i] = get_shared_len(flp, i, j); /* lateral R's of spreader and sink */ r_sp1 = getr(K_CU, (s_spreader+3*w_chip)/4.0, (s_spreader-w_chip)/4.0, w_chip, t_spreader); r_sp2 = getr(K_CU, (3*s_spreader+w_chip)/4.0, (s_spreader-w_chip)/4.0, (s_spreader+3*w_chip)/4.0, t_spreader); r_hs = getr(K_CU, (s_sink+3*s_spreader)/4.0, (s_sink-s_spreader)/4.0, s_spreader, t_sink); /* vertical R's and C's of spreader and sink */ r_sp_per = RHO_CU * t_spreader * 4.0 / (s_spreader * s_spreader - w_chip*l_chip); c_sp_per = factor_pack * SPEC_HEAT_CU * t_spreader * (s_spreader * s_spreader - w_chip*l_chip) / 4.0; r_hs_mid = RHO_CU * t_sink / (s_spreader*s_spreader); c_hs_mid = factor_pack * SPEC_HEAT_CU * t_sink * (s_spreader * s_spreader); r_hs_per = RHO_CU * t_sink * 4.0 / (s_sink * s_sink - s_spreader*s_spreader); c_hs_per = factor_pack * SPEC_HEAT_CU * t_sink * (s_sink * s_sink - s_spreader*s_spreader) / 4.0; /* short the R's from block centers to a particular chip edge */ for (i = 0; i < n; i++) { if (eq(flp->units[i].bottomy + flp->units[i].height, l_chip)) { gn_sp += gy_sp[i]; border[i][2] = 1; /* block is on northern border */ } if (eq(flp->units[i].bottomy, 0)) { gs_sp += gy_sp[i]; border[i][3] = 1; /* block is on southern border */ } if (eq(flp->units[i].leftx + flp->units[i].width, w_chip)) { ge_sp += gx_sp[i]; border[i][1] = 1; /* block is on eastern border */ } if (eq(flp->units[i].leftx, 0)) { gw_sp += gx_sp[i]; border[i][0] = 1; /* block is on western border */ } } /* overall R and C between nodes */ for (i = 0; i < n; i++) { double area = (flp->units[i].height * flp->units[i].width); /* * amongst functional units in the various layers * resistances in the interface layer are assumed * to be infinite */ for (j = 0; j < n; j++) { double part = 0, part_sp = 0; if (is_horiz_adj(flp, i, j)) { part = gx[i] / flp->units[i].height; part_sp = gx_sp[i] / flp->units[i].height; } else if (is_vert_adj(flp, i,j)) { part = gy[i] / flp->units[i].width; part_sp = gy_sp[i] / flp->units[i].width; } g[i][j] = part * len[i][j]; g[HSP*n+i][HSP*n+j] = part_sp * len[i][j]; } /* vertical g's in the silicon layer */ g[i][IFACE*n+i]=g[IFACE*n+i][i]=2.0/(RHO_SI * t_chip / area); /* vertical g's in the interface layer */ g[IFACE*n+i][HSP*n+i]=g[HSP*n+i][IFACE*n+i]=2.0/(RHO_INT * t_interface / area); /* vertical g's in the spreader layer */ g[HSP*n+i][NL*n+SP_B]=g[NL*n+SP_B][HSP*n+i]=2.0/(RHO_CU * t_spreader / area); /* C's from functional units to ground */ c_ver[i] = factor_chip * SPEC_HEAT_SI * t_chip * area; /* C's from interface portion of the functional units to ground */ c_ver[IFACE*n+i] = factor_int * SPEC_HEAT_INT * t_interface * area; /* C's from spreader portion of the functional units to ground */ c_ver[HSP*n+i] = factor_pack * SPEC_HEAT_CU * t_spreader * area; /* lateral g's from block center (spreader layer) to peripheral (n,s,e,w) spreader nodes */ g[HSP*n+i][NL*n+SP_N]=g[NL*n+SP_N][HSP*n+i]=2.0*border[i][2]/((1.0/gy_sp[i])+r_sp1*gn_sp/gy_sp[i]); g[HSP*n+i][NL*n+SP_S]=g[NL*n+SP_S][HSP*n+i]=2.0*border[i][3]/((1.0/gy_sp[i])+r_sp1*gs_sp/gy_sp[i]); g[HSP*n+i][NL*n+SP_E]=g[NL*n+SP_E][HSP*n+i]=2.0*border[i][1]/((1.0/gx_sp[i])+r_sp1*ge_sp/gx_sp[i]); g[HSP*n+i][NL*n+SP_W]=g[NL*n+SP_W][HSP*n+i]=2.0*border[i][0]/((1.0/gx_sp[i])+r_sp1*gw_sp/gx_sp[i]); } /* max slope (max_power * max_vertical_R / vertical RC time constant) for silicon */ max_slope = MAX_PD / (factor_chip * t_chip * SPEC_HEAT_SI); /* vertical g's and C's between central nodes */ /* between spreader bottom and sink bottom */ g[NL*n+SINK_B][NL*n+SP_B]=g[NL*n+SP_B][NL*n+SINK_B]=2.0/r_hs_mid; /* from spreader bottom to ground */ c_ver[NL*n+SP_B]=c_hs_mid; /* from sink bottom to ground */ c_ver[NL*n+SINK_B] = factor_pack * c_convec; /* g's and C's from peripheral(n,s,e,w) nodes */ for (i = 1; i <= 4; i++) { /* vertical g's between peripheral spreader nodes and spreader bottom */ g[NL*n+SP_B-i][NL*n+SP_B]=g[NL*n+SP_B][NL*n+SP_B-i]=2.0/r_sp_per; /* lateral g's between peripheral spreader nodes and peripheral sink nodes */ g[NL*n+SP_B-i][NL*n+SINK_B-i]=g[NL*n+SINK_B-i][NL*n+SP_B-i]=2.0/(r_hs + r_sp2); /* vertical g's between peripheral sink nodes and sink bottom */ g[NL*n+SINK_B-i][NL*n+SINK_B]=g[NL*n+SINK_B][NL*n+SINK_B-i]=2.0/r_hs_per; /* from peripheral spreader nodes to ground */ c_ver[NL*n+SP_B-i]=c_sp_per; /* from peripheral sink nodes to ground */ c_ver[NL*n+SINK_B-i]=c_hs_per; } /* calculate matrices A, B such that A(dT) + BT = POWER */ for (i = 0; i < NL*n+EXTRA; i++) { for (j = 0; j < NL*n+EXTRA; j++) { if (i==j) { inva[i][j] = 1.0/c_ver[i]; if (i == NL*n+SINK_B) /* sink bottom */ b[i][j] += 1.0 / r_convec; for (k = 0; k < NL*n+EXTRA; k++) { if ((g[i][k]==0.0)||(g[k][i])==0.0) continue; else /* here is why the 2.0 factor comes when calculating g[][] */ b[i][j] += 1.0/((1.0/g[i][k])+(1.0/g[k][i])); } } else { inva[i][j]=0.0; if ((g[i][j]==0.0)||(g[j][i])==0.0) b[i][j]=0.0; else b[i][j]=-1.0/((1.0/g[i][j])+(1.0/g[j][i])); } } } /* we are always going to use the eqn dT + A^-1 * B T = A^-1 * POWER. so, store C = A^-1 * B */ matmult(c, inva, b, NL*n+EXTRA); /* we will also be needing INVB so store it too */ copy_matrix(t, b, NL*n+EXTRA, NL*n+EXTRA); matinv(invb, t, NL*n+EXTRA); /* dump_vector(c_ver, NL*n+EXTRA); */ /* dump_matrix(g, NL*n+EXTRA, NL*n+EXTRA); */ /* dump_matrix(c, NL*n+EXTRA, NL*n+EXTRA); */ /* cleanup */ free_matrix(t, NL*n+EXTRA); free_matrix(g, NL*n+EXTRA); free_matrix(len, n); free_imatrix(border, n); free_vector(c_ver); free_vector(gx); free_vector(gy); free_vector(gx_sp); free_vector(gy_sp); }
/* creates matrices B and invB: BT = Power in the steady state. * NOTE: EXTRA nodes: 4 heat spreader peripheral nodes, 4 heat * sink inner peripheral nodes, 4 heat sink outer peripheral * nodes(north, south, east and west) and 1 ambient node. */ void populate_R_model_block(block_model_t *model, flp_t *flp) { /* shortcuts */ double **b = model->b; double *gx = model->gx, *gy = model->gy; double *gx_int = model->gx_int, *gy_int = model->gy_int; double *gx_sp = model->gx_sp, *gy_sp = model->gy_sp; double *gx_hs = model->gx_hs, *gy_hs = model->gy_hs; double *g_amb = model->g_amb; double **len = model->len, **g = model->g, **lu = model->lu; int **border = model->border; int *p = model->p; double t_chip = model->config.t_chip; double r_convec = model->config.r_convec; double s_sink = model->config.s_sink; double t_sink = model->config.t_sink; double s_spreader = model->config.s_spreader; double t_spreader = model->config.t_spreader; double t_interface = model->config.t_interface; double k_chip = model->config.k_chip; double k_sink = model->config.k_sink; double k_spreader = model->config.k_spreader; double k_interface = model->config.k_interface; int i, j, n = flp->n_units; double gn_sp=0, gs_sp=0, ge_sp=0, gw_sp=0; double gn_hs=0, gs_hs=0, ge_hs=0, gw_hs=0; double r_amb; double w_chip = get_total_width (flp); /* x-axis */ double l_chip = get_total_height (flp); /* y-axis */ /* sanity check on floorplan sizes */ if (w_chip > s_sink || l_chip > s_sink || w_chip > s_spreader || l_chip > s_spreader) { //print_flp(flp); //print_flp_fig(flp); //fatal("inordinate floorplan size!\n"); } if(model->flp != flp || model->n_units != flp->n_units || model->n_nodes != NL * flp->n_units + EXTRA) fatal("mismatch between the floorplan and the thermal model\n"); /* gx's and gy's of blocks */ for (i = 0; i < n; i++) { /* at the silicon layer */ if (model->config.block_omit_lateral) { gx[i] = gy[i] = 0; } else { gx[i] = 1.0/getr(k_chip, flp->units[i].width / 2.0, flp->units[i].height * t_chip); gy[i] = 1.0/getr(k_chip, flp->units[i].height / 2.0, flp->units[i].width * t_chip); } /* at the interface layer */ gx_int[i] = 1.0/getr(k_interface, flp->units[i].width / 2.0, flp->units[i].height * t_interface); gy_int[i] = 1.0/getr(k_interface, flp->units[i].height / 2.0, flp->units[i].width * t_interface); /* at the spreader layer */ gx_sp[i] = 1.0/getr(k_spreader, flp->units[i].width / 2.0, flp->units[i].height * t_spreader); gy_sp[i] = 1.0/getr(k_spreader, flp->units[i].height / 2.0, flp->units[i].width * t_spreader); /* at the heatsink layer */ gx_hs[i] = 1.0/getr(k_sink, flp->units[i].width / 2.0, flp->units[i].height * t_sink); gy_hs[i] = 1.0/getr(k_sink, flp->units[i].height / 2.0, flp->units[i].width * t_sink); } /* shared lengths between blocks */ for (i = 0; i < n; i++) for (j = i; j < n; j++) len[i][j] = len[j][i] = get_shared_len(flp, i, j); /* package R's */ populate_package_R(&model->pack, &model->config, w_chip, l_chip); /* short the R's from block centers to a particular chip edge */ for (i = 0; i < n; i++) { if (eq(flp->units[i].bottomy + flp->units[i].height, l_chip)) { gn_sp += gy_sp[i]; gn_hs += gy_hs[i]; border[i][2] = 1; /* block is on northern border */ } else border[i][2] = 0; if (eq(flp->units[i].bottomy, 0)) { gs_sp += gy_sp[i]; gs_hs += gy_hs[i]; border[i][3] = 1; /* block is on southern border */ } else border[i][3] = 0; if (eq(flp->units[i].leftx + flp->units[i].width, w_chip)) { ge_sp += gx_sp[i]; ge_hs += gx_hs[i]; border[i][1] = 1; /* block is on eastern border */ } else border[i][1] = 0; if (eq(flp->units[i].leftx, 0)) { gw_sp += gx_sp[i]; gw_hs += gx_hs[i]; border[i][0] = 1; /* block is on western border */ } else border[i][0] = 0; } /* initialize g */ zero_dmatrix(g, NL*n+EXTRA, NL*n+EXTRA); zero_dvector(g_amb, n+EXTRA); /* overall Rs between nodes */ for (i = 0; i < n; i++) { double area = (flp->units[i].height * flp->units[i].width); /* amongst functional units in the various layers */ for (j = 0; j < n; j++) { double part = 0, part_int = 0, part_sp = 0, part_hs = 0; if (is_horiz_adj(flp, i, j)) { part = gx[i] / flp->units[i].height; part_int = gx_int[i] / flp->units[i].height; part_sp = gx_sp[i] / flp->units[i].height; part_hs = gx_hs[i] / flp->units[i].height; } else if (is_vert_adj(flp, i,j)) { part = gy[i] / flp->units[i].width; part_int = gy_int[i] / flp->units[i].width; part_sp = gy_sp[i] / flp->units[i].width; part_hs = gy_hs[i] / flp->units[i].width; } g[i][j] = part * len[i][j]; g[IFACE*n+i][IFACE*n+j] = part_int * len[i][j]; g[HSP*n+i][HSP*n+j] = part_sp * len[i][j]; g[HSINK*n+i][HSINK*n+j] = part_hs * len[i][j]; } /* the 2.0 factor in the following equations is * explained during the calculation of the B matrix */ /* vertical g's in the silicon layer */ g[i][IFACE*n+i]=g[IFACE*n+i][i]=2.0/getr(k_chip, t_chip, area); /* vertical g's in the interface layer */ g[IFACE*n+i][HSP*n+i]=g[HSP*n+i][IFACE*n+i]=2.0/getr(k_interface, t_interface, area); /* vertical g's in the spreader layer */ g[HSP*n+i][HSINK*n+i]=g[HSINK*n+i][HSP*n+i]=2.0/getr(k_spreader, t_spreader, area); /* vertical g's in the heatsink core layer */ /* vertical R to ambient: divide r_convec proportional to area */ r_amb = r_convec * (s_sink * s_sink) / area; g_amb[i] = 1.0 / (getr(k_sink, t_sink, area) + r_amb); /* lateral g's from block center (spreader layer) to peripheral (n,s,e,w) spreader nodes */ g[HSP*n+i][NL*n+SP_N]=g[NL*n+SP_N][HSP*n+i]=2.0*border[i][2] / ((1.0/gy_sp[i])+model->pack.r_sp1_y*gn_sp/gy_sp[i]); g[HSP*n+i][NL*n+SP_S]=g[NL*n+SP_S][HSP*n+i]=2.0*border[i][3] / ((1.0/gy_sp[i])+model->pack.r_sp1_y*gs_sp/gy_sp[i]); g[HSP*n+i][NL*n+SP_E]=g[NL*n+SP_E][HSP*n+i]=2.0*border[i][1] / ((1.0/gx_sp[i])+model->pack.r_sp1_x*ge_sp/gx_sp[i]); g[HSP*n+i][NL*n+SP_W]=g[NL*n+SP_W][HSP*n+i]=2.0*border[i][0] / ((1.0/gx_sp[i])+model->pack.r_sp1_x*gw_sp/gx_sp[i]); /* lateral g's from block center (heatsink layer) to peripheral (n,s,e,w) heatsink nodes */ g[HSINK*n+i][NL*n+SINK_C_N]=g[NL*n+SINK_C_N][HSINK*n+i]=2.0*border[i][2] / ((1.0/gy_hs[i])+model->pack.r_hs1_y*gn_hs/gy_hs[i]); g[HSINK*n+i][NL*n+SINK_C_S]=g[NL*n+SINK_C_S][HSINK*n+i]=2.0*border[i][3] / ((1.0/gy_hs[i])+model->pack.r_hs1_y*gs_hs/gy_hs[i]); g[HSINK*n+i][NL*n+SINK_C_E]=g[NL*n+SINK_C_E][HSINK*n+i]=2.0*border[i][1] / ((1.0/gx_hs[i])+model->pack.r_hs1_x*ge_hs/gx_hs[i]); g[HSINK*n+i][NL*n+SINK_C_W]=g[NL*n+SINK_C_W][HSINK*n+i]=2.0*border[i][0] / ((1.0/gx_hs[i])+model->pack.r_hs1_x*gw_hs/gx_hs[i]); } /* g's from peripheral(n,s,e,w) nodes */ /* vertical g's between peripheral spreader nodes and center peripheral heatsink nodes */ g[NL*n+SP_N][NL*n+SINK_C_N]=g[NL*n+SINK_C_N][NL*n+SP_N]=2.0/model->pack.r_sp_per_y; g[NL*n+SP_S][NL*n+SINK_C_S]=g[NL*n+SINK_C_S][NL*n+SP_S]=2.0/model->pack.r_sp_per_y; g[NL*n+SP_E][NL*n+SINK_C_E]=g[NL*n+SINK_C_E][NL*n+SP_E]=2.0/model->pack.r_sp_per_x; g[NL*n+SP_W][NL*n+SINK_C_W]=g[NL*n+SINK_C_W][NL*n+SP_W]=2.0/model->pack.r_sp_per_x; /* lateral g's between peripheral outer sink nodes and center peripheral sink nodes */ g[NL*n+SINK_C_N][NL*n+SINK_N]=g[NL*n+SINK_N][NL*n+SINK_C_N]=2.0/(model->pack.r_hs + model->pack.r_hs2_y); g[NL*n+SINK_C_S][NL*n+SINK_S]=g[NL*n+SINK_S][NL*n+SINK_C_S]=2.0/(model->pack.r_hs + model->pack.r_hs2_y); g[NL*n+SINK_C_E][NL*n+SINK_E]=g[NL*n+SINK_E][NL*n+SINK_C_E]=2.0/(model->pack.r_hs + model->pack.r_hs2_x); g[NL*n+SINK_C_W][NL*n+SINK_W]=g[NL*n+SINK_W][NL*n+SINK_C_W]=2.0/(model->pack.r_hs + model->pack.r_hs2_x); /* vertical g's between inner peripheral sink nodes and ambient */ g_amb[n+SINK_C_N] = g_amb[n+SINK_C_S] = 1.0 / (model->pack.r_hs_c_per_y+model->pack.r_amb_c_per_y); g_amb[n+SINK_C_E] = g_amb[n+SINK_C_W] = 1.0 / (model->pack.r_hs_c_per_x+model->pack.r_amb_c_per_x); /* vertical g's between outer peripheral sink nodes and ambient */ g_amb[n+SINK_N] = g_amb[n+SINK_S] = g_amb[n+SINK_E] = g_amb[n+SINK_W] = 1.0 / (model->pack.r_hs_per+model->pack.r_amb_per); /* calculate matrix B such that BT = POWER in steady state */ /* non-diagonal elements */ for (i = 0; i < NL*n+EXTRA; i++) for (j = 0; j < i; j++) if ((g[i][j] == 0.0) || (g[j][i] == 0.0)) b[i][j] = b[j][i] = 0.0; else /* here is why the 2.0 factor comes when calculating g[][] */ b[i][j] = b[j][i] = -1.0/((1.0/g[i][j])+(1.0/g[j][i])); /* diagonal elements */ for (i = 0; i < NL*n+EXTRA; i++) { /* functional blocks in the heat sink layer */ if (i >= HSINK*n && i < NL*n) b[i][i] = g_amb[i%n]; /* heat sink peripheral nodes */ else if (i >= NL*n+SINK_C_W) b[i][i] = g_amb[n+i-NL*n]; /* all other nodes that are not connected to the ambient */ else b[i][i] = 0.0; /* sum up the conductances */ for(j=0; j < NL*n+EXTRA; j++) if (i != j) b[i][i] -= b[i][j]; } /* compute the LUP decomposition of B and store it too */ copy_dmatrix(lu, b, NL*n+EXTRA, NL*n+EXTRA); /* * B is a symmetric positive definite matrix. It is * symmetric because if a node A is connected to B, * then B is also connected to A with the same R value. * It is positive definite because of the following * informal argument from Professor Lieven Vandenberghe's * lecture slides for the spring 2004-2005 EE 103 class * at UCLA: http://www.ee.ucla.edu/~vandenbe/103/chol.pdf * x^T*B*x = voltage^T * (B*x) = voltage^T * current * = total power dissipated in the resistors > 0 * for x != 0. */ lupdcmp(lu, NL*n+EXTRA, p, 1); /* done */ model->flp = flp; model->r_ready = TRUE; }
/* creates 3 matrices: invA, B, C: dT + A^-1*BT = A^-1*Power, * C = A^-1 * B. note that A is a diagonal matrix (no lateral * capacitances. all capacitances are to ground). so, inva[i][i] * (= 1/a[i][i]) is just enough. * * NOTE: EXTRA nodes: 1 chip bottom, 5 spreader and 5 heat sink nodes * (north, south, east, west and bottom). */ void create_RC_matrices(flp_t *flp, int omit_lateral) { int i, j, k = 0, n = flp->n_units; int **border; double **len, *gx, *gy, **g, *c_ver, **t; double r_sp1, r_sp2, r_hs; /* lateral resistances to spreader and heatsink */ /* NOTE: *_mid - the vertical R/C from center nodes of spreader * and heatsink. *_ver - the vertical R/C from peripheral (n,s,e,w) nodes */ double r_sp_mid, r_sp_ver, r_hs_mid, r_hs_ver, c_sp_mid, c_sp_ver, c_hs_mid, c_hs_ver; double gn=0, gs=0, ge=0, gw=0; double w_chip = get_total_width (flp); /* x-axis */ double l_chip = get_total_height (flp); /* y-axis */ FILE *fp_b,*fp_c,*fp_inva,*fp_invb; fp_b=fopen("B","w"); fp_c=fopen("C","w"); fp_invb=fopen("invB","w"); fp_inva=fopen("invA","w"); border = imatrix(n, 4); len = matrix(n, n); /* len[i][j] = length of shared edge bet. i & j */ gx = vector(n); /* lumped conductances in x direction */ gy = vector(n); /* lumped conductances in y direction */ g = matrix(n+EXTRA, n+EXTRA); /* g[i][j] = conductance bet. nodes i & j */ c_ver = vector(n+EXTRA); /* vertical capacitance */ b = matrix(n+EXTRA, n+EXTRA); /* B, C, INVA and INVB are (n+EXTRA)x(n+EXTRA) matrices */ c = matrix(n+EXTRA, n+EXTRA); inva = matrix(n+EXTRA, n+EXTRA); invb = matrix(n+EXTRA, n+EXTRA); t = matrix (n+EXTRA, n+EXTRA); /* copy of B */ /* compute the silicon fitting factor - see pg 10 of the UVA CS tech report - CS-TR-2003-08 */ factor_chip = C_FACTOR * ((SPEC_HEAT_CU / SPEC_HEAT_SI) * (w_chip + 0.88 * t_spreader) \ * (l_chip + 0.88 * t_spreader) * t_spreader / ( w_chip * l_chip * t_chip) + 1); /* gx's and gy's of blocks */ for (i = 0; i < n; i++) { gx[i] = 1.0/getr(K_SI, flp->units[i].height, flp->units[i].width, l_chip); gy[i] = 1.0/getr(K_SI, flp->units[i].width, flp->units[i].height, w_chip); } /* shared lengths between blocks */ for (i = 0; i < n; i++) for (j = i; j < n; j++) len[i][j] = len[j][i] = get_shared_len(flp, i, j); /* lateral R's of spreader and sink */ r_sp1 = getr(K_CU, (s_spreader+3*w_chip)/4.0, (s_spreader-w_chip)/4.0, w_chip); r_sp2 = getr(K_CU, (3*s_spreader+w_chip)/4.0, (s_spreader-w_chip)/4.0, (s_spreader+3*w_chip)/4.0); r_hs = getr(K_CU, (s_sink+3*s_spreader)/4.0, (s_sink-s_spreader)/4.0, s_spreader); /* vertical R's and C's of spreader and sink */ r_sp_mid = RHO_CU * t_spreader / (w_chip * l_chip); c_sp_mid = factor_pack * SPEC_HEAT_CU * t_spreader * (w_chip * l_chip); r_sp_ver = RHO_CU * t_spreader * 4.0 / (s_spreader * s_spreader - w_chip*l_chip); c_sp_ver = factor_pack * SPEC_HEAT_CU * t_spreader * (s_spreader * s_spreader - w_chip*l_chip) / 4.0; r_hs_mid = RHO_CU * t_sink / (s_spreader*s_spreader); c_hs_mid = factor_pack * SPEC_HEAT_CU * t_sink * (s_spreader * s_spreader); r_hs_ver = RHO_CU * t_sink * 4.0 / (s_sink * s_sink - s_spreader*s_spreader); c_hs_ver = factor_pack * SPEC_HEAT_CU * t_sink * (s_sink * s_sink - s_spreader*s_spreader) / 4.0; /* short the R's from block centers to a particular chip edge */ for (i = 0; i < n; i++) { if (eq(flp->units[i].bottomy + flp->units[i].height, l_chip)) { gn += gy[i]; border[i][2] = 1; /* block is on northern border */ } if (eq(flp->units[i].bottomy, 0)) { gs += gy[i]; border[i][3] = 1; /* block is on southern border */ } if (eq(flp->units[i].leftx + flp->units[i].width, w_chip)) { ge += gx[i]; border[i][1] = 1; /* block is on eastern border */ } if (eq(flp->units[i].leftx, 0)) { gw += gx[i]; border[i][0] = 1; /* block is on western border */ } } /* overall R and C between nodes */ for (i = 0; i < n; i++) { /* amongst functional units */ for (j = 0; j < n; j++) { double part = 0; if (!omit_lateral) { if (is_horiz_adj(flp, i, j)){ part = gx[i] / flp->units[i].height; printf("%d %d horiz adj\n",i,j); } else if (is_vert_adj(flp, i,j)) { part = gy[i] / flp->units[i].width; printf("%d %d vert adj\n",i,j); } } g[i][j] = part * len[i][j]; } /* C's from functional units to ground */ c_ver[i] = factor_chip * SPEC_HEAT_SI * t_chip * flp->units[i].height * flp->units[i].width; /* lateral g's from block center to peripheral (n,s,e,w) spreader nodes */ g[i][n+SP_N]=g[n+SP_N][i]=2.0*border[i][2]/((1.0/gy[i])+r_sp1*gn/gy[i]); g[i][n+SP_S]=g[n+SP_S][i]=2.0*border[i][3]/((1.0/gy[i])+r_sp1*gs/gy[i]); g[i][n+SP_E]=g[n+SP_E][i]=2.0*border[i][1]/((1.0/gx[i])+r_sp1*ge/gx[i]); g[i][n+SP_W]=g[n+SP_W][i]=2.0*border[i][0]/((1.0/gx[i])+r_sp1*gw/gx[i]); /* vertical g's from block center to chip bottom */ g[i][n+CHIP_B]=g[n+CHIP_B][i]=2.0/(RHO_SI * t_chip / (flp->units[i].height * flp->units[i].width)); } /* max slope (1/vertical RC time constant) for silicon */ max_slope = 1.0 / (factor_chip * t_chip * t_chip * RHO_SI * SPEC_HEAT_SI); /* vertical g's and C's between central nodes */ /* between chip bottom and spreader bottom */ g[n+CHIP_B][n+SP_B]=g[n+SP_B][n+CHIP_B]=2.0/r_sp_mid; /* from chip bottom to ground */ c_ver[n+CHIP_B]=c_sp_mid; /* between spreader bottom and sink bottom */ g[n+SINK_B][n+SP_B]=g[n+SP_B][n+SINK_B]=2.0/r_hs_mid; /* from spreader bottom to ground */ c_ver[n+SP_B]=c_hs_mid; /* from sink bottom to ground */ c_ver[n+SINK_B]=c_convec; /* g's and C's from peripheral(n,s,e,w) nodes */ for (i = 1; i <= 4; i++) { /* vertical g's between peripheral spreader nodes and spreader bottom */ g[n+SP_B-i][n+SP_B]=g[n+SP_B][n+SP_B-i]=2.0/r_sp_ver; /* lateral g's between peripheral spreader nodes and peripheral sink nodes */ g[n+SP_B-i][n+SINK_B-i]=g[n+SINK_B-i][n+SP_B-i]=2.0/(r_hs + r_sp2); /* vertical g's between peripheral sink nodes and sink bottom */ g[n+SINK_B-i][n+SINK_B]=g[n+SINK_B][n+SINK_B-i]=2.0/r_hs_ver; /* from peripheral spreader nodes to ground */ c_ver[n+SP_B-i]=c_sp_ver; /* from peripheral sink nodes to ground */ c_ver[n+SINK_B-i]=c_hs_ver; } /* calculate matrices A, B such that A(dT) + BT = POWER */ for (i = 0; i < n+EXTRA; i++) { for (j = 0; j < n+EXTRA; j++) { if (i==j) { inva[i][j] = 1.0/c_ver[i]; if (i == n+SINK_B) /* sink bottom */ b[i][j] += 1.0 / r_convec; for (k = 0; k < n+EXTRA; k++) { if ((g[i][k]==0.0)||(g[k][i])==0.0) continue; else /* here is why the 2.0 factor comes when calculating g[][] */ b[i][j] += 1.0/((1.0/g[i][k])+(1.0/g[k][i])); } } else { inva[i][j]=0.0; if ((g[i][j]==0.0)||(g[j][i])==0.0) b[i][j]=0.0; else b[i][j]=-1.0/((1.0/g[i][j])+(1.0/g[j][i])); } } } /* we are always going to use the eqn dT + A^-1 * B T = A^-1 * POWER. so, store C = A^-1 * B */ matmult(c, inva, b, n+EXTRA); /* we will also be needing INVB so store it too */ copy_matrix(t, b, n+EXTRA, n+EXTRA); matinv(invb, t, n+EXTRA); for (i = 0; i < n+EXTRA; i++) { for (j = 0; j < n+EXTRA; j++) { fprintf(fp_inva,"%f ",inva[i][j]); fprintf(fp_invb,"%f ",invb[i][j]); fprintf(fp_c,"%f ",c[i][j]); fprintf(fp_b,"%f ",b[i][j]); } fprintf(fp_inva, "\n"); fprintf(fp_invb, "\n"); fprintf(fp_c , "\n"); fprintf(fp_b, "\n"); } fclose(fp_inva); fclose(fp_b); fclose(fp_c); fclose(fp_invb); /* dump_vector(c_ver, n+EXTRA); */ /* dump_matrix(invb, n+EXTRA, n+EXTRA); */ /* dump_matrix(c, n+EXTRA, n+EXTRA); */ /* cleanup */ free_matrix(t, n+EXTRA); free_matrix(g, n+EXTRA); free_matrix(len, n); free_imatrix(border, n); free_vector(c_ver); free_vector(gx); free_vector(gy); }