GDS-Render v1.2.1
gds-tree-checker.c
Go to the documentation of this file.
1/*
2 * GDSII-Converter
3 * Copyright (C) 2019 Mario Hüttel <mario.huettel@gmx.net>
4 *
5 * This file is part of GDSII-Converter.
6 *
7 * GDSII-Converter is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * GDSII-Converter is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GDSII-Converter. If not, see <http://www.gnu.org/licenses/>.
18 */
19
36#include <stdio.h>
37#include <glib/gi18n.h>
39
41{
42 GList *cell_iter;
43 struct gds_cell *cell;
44 GList *instance_iter;
45 struct gds_cell_instance *cell_inst;
46 int total_unresolved_count = 0;
47
48 if (!lib)
49 return -1;
50
51 /* Iterate over all cells in library */
52 for (cell_iter = lib->cells; cell_iter != NULL; cell_iter = g_list_next(cell_iter)) {
53 cell = (struct gds_cell *)cell_iter->data;
54
55 /* Check if this list element is broken. This should never happen */
56 if (!cell) {
57 fprintf(stderr, _("Broken cell list item found. Will continue.\n"));
58 continue;
59 }
60
61 /* Reset the unresolved cell reference counter to 0 */
63
64 /* Iterate through all child cell references and check if the references are set */
65 for (instance_iter = cell->child_cells; instance_iter != NULL;
66 instance_iter = g_list_next(instance_iter)) {
67 cell_inst = (struct gds_cell_instance *)instance_iter->data;
68
69 /* Check if broken. This should not happen */
70 if (!cell_inst) {
71 fprintf(stderr, _("Broken cell list item found in cell %s. Will continue.\n"),
72 cell->name);
73 continue;
74 }
75
76 /* Check if instance is valid; else increment "error" counter of cell */
77 if (!cell_inst->cell_ref) {
78 total_unresolved_count++;
80 }
81 }
82 }
83
84 return total_unresolved_count;
85}
86
93static int gds_tree_check_list_contains_cell(GList *list, struct gds_cell *cell)
94{
95 GList *iter;
96
97 for (iter = list; iter != NULL; iter = g_list_next(iter)) {
98 if ((struct gds_cell *)iter->data == cell)
99 return 1;
100 }
101
102 return 0;
103}
104
111static int gds_tree_check_iterate_ref_and_check(struct gds_cell *cell_to_check, GList **visited_cells)
112{
113 GList *ref_iter;
114 struct gds_cell_instance *ref;
115 struct gds_cell *sub_cell;
116 int res;
117
118 if (!cell_to_check)
119 return -1;
120
121 /* Check if this cell is already contained in visited cells. This indicates a loop */
122 if (gds_tree_check_list_contains_cell(*visited_cells, cell_to_check))
123 return 1;
124
125 /* Add cell to visited cell list */
126 *visited_cells = g_list_append(*visited_cells, (gpointer)cell_to_check);
127
128 /* Mark references and process sub cells */
129 for (ref_iter = cell_to_check->child_cells; ref_iter != NULL; ref_iter = g_list_next(ref_iter)) {
130 ref = (struct gds_cell_instance *)ref_iter->data;
131
132 if (!ref)
133 return -1;
134
135 sub_cell = ref->cell_ref;
136
137 /* If cell is not resolved, ignore. No harm there */
138 if (!sub_cell)
139 continue;
140
141 res = gds_tree_check_iterate_ref_and_check(sub_cell, visited_cells);
142 if (res < 0) {
143 /* Error. return. */
144 return -3;
145 } else if (res > 0) {
146 /* Loop in subcell found. Propagate to top */
147 return 1;
148 }
149 }
150
151 /* Remove cell from visted cells */
152 *visited_cells = g_list_remove(*visited_cells, cell_to_check);
153
154 /* No error found in this chain */
155 return 0;
156}
157
159{
160 int res;
161 int loop_count = 0;
162 GList *cell_iter;
163 struct gds_cell *cell_to_check;
164 GList *visited_cells = NULL;
165
166
167 if (!lib)
168 return -1;
169
170 for (cell_iter = lib->cells; cell_iter != NULL; cell_iter = g_list_next(cell_iter)) {
171 cell_to_check = (struct gds_cell *)cell_iter->data;
172
173 /* A broken cell reference will be counted fatal in this case */
174 if (!cell_to_check)
175 return -2;
176
177 /* iterate through references and check if loop exists */
178 res = gds_tree_check_iterate_ref_and_check(cell_to_check, &visited_cells);
179
180 if (visited_cells) {
181 /*
182 * If cell contains no loop, print error when list not empty.
183 * In case of a loop, it is completely normal that the list is not empty,
184 * due to the instant return from gds_tree_check_iterate_ref_and_check()
185 */
186 if (res == 0)
187 fprintf(stderr,
188 _("Visited cell list should be empty. This is a bug. Please report this.\n"));
189 g_list_free(visited_cells);
190 visited_cells = NULL;
191 }
192
193 if (res < 0) {
194 /* Error */
195 return res;
196 } else if (res > 0) {
197 /* Loop found: increment loop count and flag cell */
198 cell_to_check->checks.affected_by_reference_loop = 1;
199 loop_count++;
200 } else if (res == 0) {
201 /* No error found for this cell */
202 cell_to_check->checks.affected_by_reference_loop = 0;
203 }
204
205 }
206
207
208 return loop_count;
209}
210
Checking functions of a cell tree (Header)
static int gds_tree_check_list_contains_cell(GList *list, struct gds_cell *cell)
Check if list contains a cell.
int gds_tree_check_reference_loops(struct gds_library *lib)
gds_tree_check_reference_loops checks if the given library contains reference loops
int gds_tree_check_cell_references(struct gds_library *lib)
gds_tree_check_cell_references checks if all child cell references can be resolved in the given libra...
static int gds_tree_check_iterate_ref_and_check(struct gds_cell *cell_to_check, GList **visited_cells)
This function follows down the reference list of a cell and marks each visited subcell and detects lo...
int unresolved_child_count
Number of unresolved cell instances inside this cell. Default: GDS_CELL_CHECK_NOT_RUN.
Definition: gds-types.h:72
int affected_by_reference_loop
1 if the cell is affected by a reference loop and therefore not renderable. Default: GDS_CELL_CHECK_N...
Definition: gds-types.h:73
This represents an instanc of a cell inside another cell.
Definition: gds-types.h:110
struct gds_cell * cell_ref
Referenced gds_cell structure.
Definition: gds-types.h:112
A Cell inside a gds_library.
Definition: gds-types.h:122
struct gds_cell_checks checks
Checking results.
Definition: gds-types.h:129
char name[CELL_NAME_MAX]
Definition: gds-types.h:123
GList * child_cells
List of gds_cell_instance elements.
Definition: gds-types.h:126
GDS Toplevel library.
Definition: gds-types.h:135
GList * cells
Definition: gds-types.h:140