Root/
Source at commit a6d21bb4bb963e7ca5049851a91318878cf89d95 created 13 years 5 months ago. By Xiangfu Liu, update take svn rev: 5983 | |
---|---|
1 | /* |
2 | * obj.c - Object definition model |
3 | * |
4 | * Written 2009, 2010 by Werner Almesberger |
5 | * Copyright 2009, 2010 by Werner Almesberger |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | */ |
12 | |
13 | |
14 | #include <stdlib.h> |
15 | #include <string.h> |
16 | #include <assert.h> |
17 | |
18 | #include "util.h" |
19 | #include "error.h" |
20 | #include "expr.h" |
21 | #include "bitset.h" |
22 | #include "meas.h" |
23 | #include "inst.h" |
24 | #include "hole.h" |
25 | #include "overlap.h" |
26 | #include "layer.h" |
27 | #include "delete.h" |
28 | #include "obj.h" |
29 | |
30 | |
31 | #define DEFAULT_SILK_WIDTH make_mil(15) /* @@@ */ |
32 | #define DEFAULT_OFFSET make_mil(0) /* @@@ */ |
33 | |
34 | #define MAX_ITERATIONS 1000 /* abort "loop"s at this limit */ |
35 | |
36 | |
37 | char *pkg_name = NULL; |
38 | struct frame *frames = NULL; |
39 | struct frame *active_frame = NULL; |
40 | void *instantiation_error = NULL; |
41 | enum allow_overlap allow_overlap = ao_none; |
42 | |
43 | |
44 | static struct bitset *frame_set; /* frames visited in "call chain" */ |
45 | |
46 | |
47 | /* ----- Searching --------------------------------------------------------- */ |
48 | |
49 | |
50 | /* |
51 | * @@@ Known bug: we should compare all parameters of an instance, not just the |
52 | * object's base or the vectors end. |
53 | */ |
54 | |
55 | static int found = 0; |
56 | static int search_suspended = 0; |
57 | static const struct vec *find_vec = NULL; |
58 | static const struct obj *find_obj = NULL; |
59 | static struct coord find_pos; |
60 | |
61 | |
62 | static void suspend_search(void) |
63 | { |
64 | search_suspended++; |
65 | } |
66 | |
67 | static void resume_search(void) |
68 | { |
69 | assert(search_suspended > 0); |
70 | search_suspended--; |
71 | } |
72 | |
73 | |
74 | static struct coord get_pos(const struct inst *inst) |
75 | { |
76 | return inst->obj ? inst->base : inst->u.vec.end; |
77 | } |
78 | |
79 | |
80 | void find_inst(const struct inst *inst) |
81 | { |
82 | struct coord pos; |
83 | |
84 | if (search_suspended) |
85 | return; |
86 | if (find_vec != inst->vec) |
87 | return; |
88 | if (find_obj != inst->obj) |
89 | return; |
90 | pos = get_pos(inst); |
91 | if (pos.x != find_pos.x || pos.y != find_pos.y) |
92 | return; |
93 | found++; |
94 | } |
95 | |
96 | |
97 | void search_inst(const struct inst *inst) |
98 | { |
99 | find_vec = inst->vec; |
100 | find_obj = inst->obj; |
101 | find_pos = get_pos(inst); |
102 | } |
103 | |
104 | |
105 | /* ----- Get the list of anchors of an object ------------------------------ */ |
106 | |
107 | |
108 | int obj_anchors(struct obj *obj, struct vec ***anchors) |
109 | { |
110 | anchors[0] = &obj->base; |
111 | switch (obj->type) { |
112 | case ot_frame: |
113 | return 1; |
114 | case ot_rect: |
115 | case ot_line: |
116 | anchors[1] = &obj->u.rect.other; |
117 | return 2; |
118 | case ot_pad: |
119 | anchors[1] = &obj->u.pad.other; |
120 | return 2; |
121 | case ot_hole: |
122 | anchors[1] = &obj->u.hole.other; |
123 | return 2; |
124 | case ot_meas: |
125 | anchors[1] = &obj->u.meas.high; |
126 | return 2; |
127 | case ot_arc: |
128 | /* |
129 | * Put end point first so that this is what we grab if dragging |
130 | * a circle (thereby turning it into an arc). |
131 | */ |
132 | anchors[1] = &obj->u.arc.end; |
133 | anchors[2] = &obj->u.arc.start; |
134 | return 3; |
135 | default: |
136 | abort(); |
137 | } |
138 | } |
139 | |
140 | |
141 | /* ----- Instantiation ----------------------------------------------------- */ |
142 | |
143 | |
144 | static int generate_frame(struct frame *frame, struct coord base, |
145 | const struct frame *parent, struct obj *frame_ref, int active); |
146 | |
147 | |
148 | struct num eval_unit(const struct expr *expr, const struct frame *frame); |
149 | /*static*/ struct num eval_unit(const struct expr *expr, const struct frame *frame) |
150 | { |
151 | struct num d; |
152 | |
153 | d = eval_num(expr, frame); |
154 | if (!is_undef(d) && to_unit(&d)) |
155 | return d; |
156 | fail_expr(expr); |
157 | return undef; |
158 | } |
159 | |
160 | |
161 | static struct num eval_unit_default(const struct expr *expr, |
162 | const struct frame *frame, struct num def) |
163 | { |
164 | if (expr) |
165 | return eval_unit(expr, frame); |
166 | to_unit(&def); |
167 | return def; |
168 | } |
169 | |
170 | |
171 | static int generate_vecs(struct frame *frame, struct coord base) |
172 | { |
173 | struct coord vec_base; |
174 | struct vec *vec; |
175 | struct num x, y; |
176 | |
177 | for (vec = frame->vecs; vec; vec = vec->next) { |
178 | x = eval_unit(vec->x, frame); |
179 | if (is_undef(x)) |
180 | goto error; |
181 | y = eval_unit(vec->y, frame); |
182 | if (is_undef(y)) |
183 | goto error; |
184 | vec_base = vec->base ? vec->base->pos : base; |
185 | vec->pos = vec_base; |
186 | vec->pos.x += x.n; |
187 | vec->pos.y += y.n; |
188 | if (!inst_vec(vec, vec_base)) |
189 | goto error; |
190 | meas_post(vec, vec->pos, frame_set); |
191 | } |
192 | return 1; |
193 | |
194 | error: |
195 | instantiation_error = vec; |
196 | return 0; |
197 | } |
198 | |
199 | |
200 | static int generate_objs(struct frame *frame, struct coord base, int active) |
201 | { |
202 | struct obj *obj; |
203 | char *name; |
204 | int ok; |
205 | struct num width, offset; |
206 | |
207 | for (obj = frame->objs; obj; obj = obj->next) |
208 | switch (obj->type) { |
209 | case ot_frame: |
210 | if (!generate_frame(obj->u.frame.ref, |
211 | obj->base ? obj->base->pos : base, frame, obj, |
212 | active && obj->u.frame.ref->active_ref == obj)) |
213 | return 0; |
214 | break; |
215 | case ot_line: |
216 | width = eval_unit_default(obj->u.line.width, frame, |
217 | DEFAULT_SILK_WIDTH); |
218 | if (is_undef(width)) |
219 | goto error; |
220 | if (!inst_line(obj, obj->base ? obj->base->pos : base, |
221 | obj->u.line.other ? obj->u.line.other->pos : base, |
222 | width.n)) |
223 | goto error; |
224 | break; |
225 | case ot_rect: |
226 | width = eval_unit_default(obj->u.rect.width, frame, |
227 | DEFAULT_SILK_WIDTH); |
228 | if (is_undef(width)) |
229 | goto error; |
230 | if (!inst_rect(obj, obj->base ? obj->base->pos : base, |
231 | obj->u.rect.other ? obj->u.rect.other->pos : base, |
232 | width.n)) |
233 | goto error; |
234 | break; |
235 | case ot_pad: |
236 | name = expand(obj->u.pad.name, frame); |
237 | if (!name) |
238 | goto error; |
239 | ok = inst_pad(obj, name, |
240 | obj->base ? obj->base->pos : base, |
241 | obj->u.pad.other ? obj->u.pad.other->pos : base); |
242 | free(name); |
243 | if (!ok) |
244 | goto error; |
245 | break; |
246 | case ot_hole: |
247 | if (!inst_hole(obj, obj->base ? obj->base->pos : base, |
248 | obj->u.hole.other ? obj->u.hole.other->pos : base)) |
249 | goto error; |
250 | break; |
251 | case ot_arc: |
252 | width = eval_unit_default(obj->u.arc.width, frame, |
253 | DEFAULT_SILK_WIDTH); |
254 | if (is_undef(width)) |
255 | goto error; |
256 | if (!inst_arc(obj, obj->base ? obj->base->pos : base, |
257 | obj->u.arc.start ? obj->u.arc.start->pos : base, |
258 | obj->u.arc.end ? obj->u.arc.end->pos : base, |
259 | width.n)) |
260 | goto error; |
261 | break; |
262 | case ot_meas: |
263 | assert(frame == frames); |
264 | offset = eval_unit_default(obj->u.meas.offset, frame, |
265 | DEFAULT_OFFSET); |
266 | if (is_undef(offset)) |
267 | goto error; |
268 | inst_meas_hint(obj, offset.n); |
269 | break; |
270 | default: |
271 | abort(); |
272 | } |
273 | return 1; |
274 | |
275 | error: |
276 | instantiation_error = obj; |
277 | return 0; |
278 | } |
279 | |
280 | |
281 | static int generate_items(struct frame *frame, struct coord base, int active) |
282 | { |
283 | char *s; |
284 | int ok; |
285 | |
286 | if (frame == frames) { |
287 | s = expand(pkg_name, frame); |
288 | inst_select_pkg(s); |
289 | free(s); |
290 | } |
291 | inst_begin_active(active && frame == active_frame); |
292 | ok = generate_vecs(frame, base) && generate_objs(frame, base, active); |
293 | inst_end_active(); |
294 | return ok; |
295 | } |
296 | |
297 | |
298 | static int run_loops(struct frame *frame, struct loop *loop, |
299 | struct coord base, int active) |
300 | { |
301 | struct num from, to; |
302 | int n; |
303 | int found_before, ok; |
304 | |
305 | if (!loop) |
306 | return generate_items(frame, base, active); |
307 | from = eval_num(loop->from.expr, frame); |
308 | if (is_undef(from)) { |
309 | fail_expr(loop->from.expr); |
310 | instantiation_error = loop; |
311 | return 0; |
312 | } |
313 | if (!is_dimensionless(from)) { |
314 | fail("incompatible type for start value"); |
315 | fail_expr(loop->from.expr); |
316 | instantiation_error = loop; |
317 | return 0; |
318 | } |
319 | |
320 | to = eval_num(loop->to.expr, frame); |
321 | if (is_undef(to)) { |
322 | fail_expr(loop->to.expr); |
323 | instantiation_error = loop; |
324 | return 0; |
325 | } |
326 | if (!is_dimensionless(to)) { |
327 | fail("incompatible type for end value"); |
328 | fail_expr(loop->to.expr); |
329 | instantiation_error = loop; |
330 | return 0; |
331 | } |
332 | |
333 | assert(!loop->initialized); |
334 | loop->curr_value = from.n; |
335 | loop->initialized = 1; |
336 | |
337 | n = 0; |
338 | for (; loop->curr_value <= to.n; loop->curr_value += 1) { |
339 | if (n >= MAX_ITERATIONS) { |
340 | fail("%s: too many iterations (%d)", loop->var.name, |
341 | MAX_ITERATIONS); |
342 | instantiation_error = loop; |
343 | goto fail; |
344 | } |
345 | found_before = found; |
346 | if (loop->found == loop->active) |
347 | suspend_search(); |
348 | ok = run_loops(frame, loop->next, base, |
349 | active && loop->active == n); |
350 | if (loop->found == loop->active) |
351 | resume_search(); |
352 | if (!ok) |
353 | goto fail; |
354 | if (found_before != found) |
355 | loop->found = n; |
356 | n++; |
357 | } |
358 | loop->initialized = 0; |
359 | loop->curr_value = UNDEF; |
360 | if (active) { |
361 | loop->n = from.n; |
362 | loop->iterations = n; |
363 | } |
364 | return 1; |
365 | |
366 | fail: |
367 | loop->initialized = 0; |
368 | return 0; |
369 | } |
370 | |
371 | |
372 | static int iterate_tables(struct frame *frame, struct table *table, |
373 | struct coord base, int active) |
374 | { |
375 | int found_before, ok; |
376 | |
377 | if (!table) |
378 | return run_loops(frame, frame->loops, base, active); |
379 | for (table->curr_row = table->rows; table->curr_row; |
380 | table->curr_row = table->curr_row->next) { |
381 | found_before = found; |
382 | if (table->found_row == table->active_row) |
383 | suspend_search(); |
384 | ok = iterate_tables(frame, table->next, base, |
385 | active && table->active_row == table->curr_row); |
386 | if (table->found_row == table->active_row) |
387 | resume_search(); |
388 | if (!ok) |
389 | return 0; |
390 | if (found_before != found) |
391 | table->found_row = table->curr_row; |
392 | } |
393 | return 1; |
394 | } |
395 | |
396 | |
397 | static int generate_frame(struct frame *frame, struct coord base, |
398 | const struct frame *parent, struct obj *frame_ref, int active) |
399 | { |
400 | int ok; |
401 | |
402 | /* |
403 | * We ensure during construction that frames can never recurse. |
404 | */ |
405 | inst_begin_frame(frame_ref, frame, base, |
406 | active && parent == active_frame, |
407 | active && frame == active_frame); |
408 | bitset_set(frame_set, frame->n); |
409 | frame->curr_parent = parent; |
410 | ok = iterate_tables(frame, frame->tables, base, active); |
411 | inst_end_frame(frame); |
412 | bitset_clear(frame_set, frame->n); |
413 | frame->curr_parent = NULL; |
414 | return ok; |
415 | } |
416 | |
417 | |
418 | static void reset_all_loops(void) |
419 | { |
420 | const struct frame *frame; |
421 | struct loop *loop; |
422 | |
423 | for (frame = frames; frame; frame = frame->next) |
424 | for (loop = frame->loops; loop; loop = loop->next) |
425 | loop->iterations = 0; |
426 | } |
427 | |
428 | |
429 | static void reset_found(void) |
430 | { |
431 | struct frame *frame; |
432 | struct table *table; |
433 | struct loop *loop; |
434 | |
435 | for (frame = frames; frame; frame = frame->next) { |
436 | for (table = frame->tables; table; table = table->next) |
437 | table->found_row = NULL; |
438 | for (loop = frame->loops; loop; loop = loop->next) |
439 | loop->found = -1; |
440 | frame->found_ref = NULL; |
441 | } |
442 | } |
443 | |
444 | |
445 | /* |
446 | * Note: we don't use frame->found_ref yet. Instead, we adjust the frame |
447 | * references with activate_item in inst.c |
448 | */ |
449 | |
450 | static void activate_found(void) |
451 | { |
452 | struct frame *frame; |
453 | struct table *table; |
454 | struct loop *loop; |
455 | |
456 | for (frame = frames; frame; frame = frame->next) { |
457 | for (table = frame->tables; table; table = table->next) |
458 | if (table->found_row) |
459 | table->active_row = table->found_row; |
460 | for (loop = frame->loops; loop; loop = loop->next) |
461 | if (loop->found != -1) |
462 | loop->active = loop->found; |
463 | if (frame->found_ref) |
464 | frame->active_ref = frame->found_ref; |
465 | } |
466 | } |
467 | |
468 | |
469 | static int enumerate_frames(void) |
470 | { |
471 | struct frame *frame; |
472 | int n = 0; |
473 | |
474 | for (frame = frames; frame; frame = frame->next) |
475 | frame->n = n++; |
476 | return n; |
477 | } |
478 | |
479 | |
480 | int instantiate(void) |
481 | { |
482 | struct coord zero = { 0, 0 }; |
483 | int n_frames; |
484 | int ok; |
485 | |
486 | meas_start(); |
487 | inst_start(); |
488 | n_frames = enumerate_frames(); |
489 | frame_set = bitset_new(n_frames); |
490 | instantiation_error = NULL; |
491 | reset_all_loops(); |
492 | reset_found(); |
493 | found = 0; |
494 | search_suspended = 0; |
495 | ok = generate_frame(frames, zero, NULL, NULL, 1); |
496 | if (ok && (find_vec || find_obj) && found) |
497 | activate_found(); |
498 | find_vec = NULL; |
499 | find_obj = NULL; |
500 | if (ok) |
501 | ok = link_holes(); |
502 | if (ok) |
503 | ok = refine_layers(allow_overlap); |
504 | if (ok) |
505 | ok = instantiate_meas(n_frames); |
506 | if (ok) |
507 | inst_commit(); |
508 | else |
509 | inst_revert(); |
510 | bitset_free(frame_set); |
511 | return ok; |
512 | } |
513 | |
514 | |
515 | /* ----- deallocation ------------------------------------------------------ */ |
516 | |
517 | |
518 | void obj_cleanup(void) |
519 | { |
520 | free(pkg_name); |
521 | while (frames) { |
522 | delete_frame(frames); |
523 | destroy(); |
524 | } |
525 | } |
526 |
Branches:
master