Date:2010-05-29 23:13:48 (9 years 2 months ago)
Author:werner
Commit:c9af8cd0fe183d31d1bc7079cb8e7deec3bbe74d
Message:The mechanism for selecting points for measurements reaches its limits when using frames to encapsulate building blocks, e.g., like macros or functions in a programming language. Since measurements only know about the frame containing a vector but not the frames containing that frame, invocations of this frame from different places can only be distinguished within the min/next/max scheme. (See the example in README.)

To eliminate this limitation, one needs a way to tell fped to consider a point
only if it has been instantiated through a certain path, e.g., by requiring
some other frames to be visited in its instantiation. This increases the number
of distinct points available for measurements.

The mechanism chosen is to qualify a measurement point with frames that lead to
it. This list of outer frames does not have to include all frames. Without
qualifying, the old behaviour results.

Note that this doesn't cover all possible ways in which a point can appear in
different roles. Multiple frame references can also result from repeating the
same frame reference in the same parent frame. The current qualification
mechanism does not allow such paths to be distinguished. However, one can
always introduce intermediate frames for this purpose.

Furthermore, repetitions create multiple instances of a point, although in what
should be considered the same role.

- fpd.l: make scanner support free-format a little better by switching back to
keyword mode after frame braces. This way, one can write a simple frame in a
single line, which is useful for regression tests.
- fpd.l, fpd.y, README, test/dbg_meas: added %meas directive to print the
result of a measurement
- fpd.y, README: measurements can now be labeled. Note that, due to limitations
of the grammar, the first measurement cannot be labeled.
- error.h, error.c (yywarn): new function for non-fatal diagnostics that always
get reported to standard error
- bitset.h, bitset.c: functions to manipulate variable-size bit sets
- meas.h, fpd.y, README, test/meas_qual: added the means to specify qualifiers
for points used in measurements
- dump.c (print_meas_base, print_meas): dump qualifiers
- delete.c (delete_references, test/del_frame): delete measurements that
reference a frame being deleted in their qualifiers
- obj.h, obj.c (enumerate_frames, instantiate): enumerate all frames so that we
have an index into the bit vector of visited frames
- meas.h, meas.c (reset_samples, meas_post), obj.c (generate_vecs,
generate_frame, instantiate): record the set of frames visited for each
sample
- meas.c (meas_post): only treat two instances of a point as equivalent if the
set of frames visited of one of them is a superset of set of the other. In
this case, keep the union of the two sets.
- meas.h, meas.c (meas_find_min, meas_find_next, meas_find_max),
test/meas_qual: instantiate_meas_pkg only select points for which all frames
in the qualification have been visited
- gui_meas.c (is_min, is_next, is_max, is_a_next): updated for above change
- inst.h, inst.c (curr_frame, propagate_bbox, add_inst, inst_begin_frame,
inst_end_frame, inst_start): renamed curr_frame to frame_instantiating to
avoid clash with curr_frame in fpd.y
- inst.h, inst.c (find_meas_hint): make global
- test/structure, test/del_vec, test/del_frame: fped now warns if a measurement
is in an unlinked frame. Changed regressions tests to avoid this warning.
- test/Common: new function expect_grep to compare only part of the output



git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5967 99fdad57-331a-0410-800a-d7fa5415bdb3
Files: Makefile (1 diff)
README (3 diffs)
bitset.c (1 diff)
bitset.h (1 diff)
delete.c (2 diffs)
dump.c (3 diffs)
error.c (2 diffs)
error.h (2 diffs)
fpd.l (2 diffs)
fpd.y (13 diffs)
gui_meas.c (3 diffs)
inst.c (6 diffs)
inst.h (2 diffs)
meas.c (6 diffs)
meas.h (5 diffs)
obj.c (6 diffs)
obj.h (1 diff)
test/Common (1 diff)
test/dbg_meas (1 diff)
test/del_frame (2 diffs)
test/del_vec (2 diffs)
test/meas_qual (1 diff)
test/structure (2 diffs)

Change Details

Makefile
1616
1717OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \
1818       unparse.o file.o dump.o kicad.o postscript.o meas.o \
19       layer.o overlap.o hole.o tsort.o \
19       layer.o overlap.o hole.o tsort.o bitset.o \
2020       cpp.o lex.yy.o y.tab.o \
2121       gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \
2222       gui_tool.o gui_over.o gui_meas.o gui_frame.o gui_frame_drag.o
README
582582would print "width = 1mm"
583583
584584
585Additional qualifiers
586- - - - - - - - - - -
587
588When using frames as reusable building blocks, similar to functions or
589macros in many programming languages, one may need finer control over
590the points that are selected for measurements.
591
592For example, let us consider a frame "square" that draws a square
593centered at the frame's origin and with a side length given by the
594variable "size". This variable be set in the frame referencing
595"square".
596
597    frame square {
598    a: vec @(-size/2, -size/2)
599    b: vec @(size/2, size/2)
600    rect a b
601    }
602
603    frame small {
604    set size = 2mm
605    frame square @
606    }
607
608    frame big {
609    set size = 5mm
610    frame square @
611    }
612
613    frame small @
614    vec @(5mm, 0mm)
615    frame big .
616
617If we want to measure the size of each square, we could use
618
619measx square.a -> square.b
620
621Unfortunately, this only measures the small square. To reach the
622big frame, we need to tell fped to use only those points in "square"
623that have been placed when "square" was invoked from the big frame.
624
625This is accomplished by prefixing the points in question with the
626name(s) of the frames that need to be visited. The frame names are
627separated by slashes (/).
628
629measx big/square.a -> square.b
630
631For clarity, it's better to qualify both points, e.g.,
632
633measx big/square.a -> big/square.b
634
635If multiple frame names are given, they must be in the order in
636which they are invoked.
637
638
585639Experimental: debugging directives
586640----------------------------------
587641
...... 
592646%move <identifier> [<number>] <identifier>
593647%frame <identifier> <qualified-base>
594648%print <expression>
649%meas <identifier>
595650%dump
596651%exit
597652%tsort { -<id> | +<id> | <id-before> <id-after> [<number>] ... }
...... 
622677%dump writes the footprint definition in the fped language to standard
623678output. %exit immediately exits fped, without invoking the GUI.
624679
680%print evaluates the expression and prints the result to standard output.
681%meas performs an instantiation and prints the value of the labeled
682measurement.
683
625684%tsort is used to test-drive the topological sort algorithm. The items
626685in the curly braces are declarations of nodes with (-<id>) or without
627686(+<id>) decay or edges in the partial order. The optional number is
bitset.c
1/*
2 * bitset.c - Arbitrary-length bit sets
3 *
4 * Written 2010 by Werner Almesberger
5 * Copyright 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#include <sys/types.h>
18
19#include "util.h"
20#include "bitset.h"
21
22
23struct bitset {
24    int v_n;
25    unsigned *v;
26};
27
28#define BITS (sizeof(unsigned)*8)
29
30
31struct bitset *bitset_new(int n)
32{
33    struct bitset *new;
34
35    new = alloc_type(struct bitset);
36    new->v_n = (n+BITS-1) & ~(BITS-1);
37    new->v = zalloc_size(sizeof(unsigned)*new->v_n);
38    return new;
39}
40
41
42struct bitset *bitset_clone(const struct bitset *old)
43{
44    struct bitset *new;
45    size_t bytes;
46
47    new = alloc_type(struct bitset);
48    bytes = sizeof(unsigned)*old->v_n;
49    new->v_n = old->v_n;
50    new->v = alloc_size(bytes);
51    memcpy(new->v, old->v, bytes);
52    return new;
53}
54
55
56void bitset_free(struct bitset *set)
57{
58    free(set->v);
59    free(set);
60}
61
62
63void bitset_set(struct bitset *set, int n)
64{
65    assert(n < set->v_n*BITS);
66    set->v[n/BITS] |= 1U << (n % BITS);
67}
68
69
70void bitset_clear(struct bitset *set, int n)
71{
72    assert(n < set->v_n*BITS);
73    set->v[n/BITS] &= ~(1U << (n % BITS));
74}
75
76
77int bitset_pick(const struct bitset *set, int n)
78{
79    assert(n < set->v_n*BITS);
80    return !!(set->v[n/BITS] & (1U << (n % BITS)));
81}
82
83
84int bitset_is_empty(const struct bitset *set)
85{
86    int i;
87
88    for (i = 0; i != set->v_n; i++)
89        if (set->v[i])
90            return 0;
91    return 1;
92}
93
94
95void bitset_zero(struct bitset *a)
96{
97    int i;
98
99    for (i = 0; i != a->v_n; i++)
100        a->v[i] = 0;
101}
102
103
104void bitset_and(struct bitset *a, const struct bitset *b)
105{
106    int i;
107
108    assert(a->v_n == b->v_n);
109    for (i = 0; i != a->v_n; i++)
110        a->v[i] &= b->v[i];
111}
112
113
114void bitset_or(struct bitset *a, const struct bitset *b)
115{
116    int i;
117
118    assert(a->v_n == b->v_n);
119    for (i = 0; i != a->v_n; i++)
120        a->v[i] |= b->v[i];
121}
122
123
124int bitset_ge(const struct bitset *a, const struct bitset *b)
125{
126    int i;
127
128    assert(a->v_n == b->v_n);
129    for (i = 0; i != a->v_n; i++)
130        if (~a->v[i] & b->v[i])
131            return 0;
132    return 1;
133}
bitset.h
1/*
2 * bitset.h - Arbitrary-length bit sets
3 *
4 * Written 2010 by Werner Almesberger
5 * Copyright 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#ifndef BITSET_H
14#define BITSET_H
15
16struct bitset;
17
18struct bitset *bitset_new(int n);
19struct bitset *bitset_clone(const struct bitset *old);
20void bitset_free(struct bitset *set);
21
22void bitset_set(struct bitset *set, int n);
23void bitset_clear(struct bitset *set, int n);
24int bitset_pick(const struct bitset *set, int n);
25
26int bitset_is_empty(const struct bitset *set);
27void bitset_zero(struct bitset *a);
28
29void bitset_and(struct bitset *a, const struct bitset *b);
30void bitset_or(struct bitset *a, const struct bitset *b);
31
32int bitset_ge(const struct bitset *a, const struct bitset *b);
33
34#endif /* !BITSET_H */
delete.c
521521}
522522
523523
524static int qual_ref(const struct frame_qual *qual, const struct frame *ref)
525{
526    while (qual) {
527        if (qual->frame == ref)
528            return 1;
529        qual = qual->next;
530    }
531    return 0;
532}
533
534
524535static void delete_references(const struct frame *ref)
525536{
526537    struct frame *frame;
...... 
535546                break;
536547            case ot_meas:
537548                if (obj->base->frame == ref ||
538                    obj->u.meas.high->frame == ref)
549                    obj->u.meas.high->frame == ref ||
550                    qual_ref(obj->u.meas.low_qual, ref) ||
551                    qual_ref(obj->u.meas.high_qual, ref))
539552                    do_delete_obj(obj);
540553                break;
541554            default:
dump.c
1313
1414#include <stdlib.h>
1515#include <stdio.h>
16#include <string.h>
17#include <sys/types.h>
1618
1719#include "util.h"
1820#include "unparse.h"
...... 
389391
390392
391393
392static char *print_meas_base(struct vec *base)
394static char *print_meas_base(struct vec *base, const struct frame_qual *qual)
393395{
394396    const char *name;
397    size_t n;
398    const struct frame_qual *walk;
399    char *s, *p;
395400
396401    name = base_name(base, NULL);
397    if (base->frame == frames)
398        return stralloc(name);
399    return stralloc_printf("%s.%s", base->frame->name, name);
402    n = strlen(name)+1; /* vec\0 */
403    for (walk = qual; walk; walk = walk->next)
404        n += strlen(walk->frame->name)+1; /* frame/ */
405    if (base->frame != frames)
406        n += strlen(base->frame->name)+1; /* frame. */
407
408    s = p = alloc_size(n);
409    for (walk = qual; walk; walk = walk->next) {
410        n = strlen(walk->frame->name);
411        memcpy(p, walk->frame->name, n);
412        p[n] = '/';
413        p += n+1;
414    }
415    if (base->frame != frames) {
416        n = strlen(base->frame->name);
417        memcpy(p, base->frame->name, n);
418        p[n] = '.';
419        p += n+1;
420    }
421    strcpy(p, name);
422    return s;
400423}
401424
402425
...... 
413436        free(s);
414437        s = t;
415438    }
416    s1 = print_meas_base(obj->base);
439    s1 = print_meas_base(obj->base, obj->u.meas.low_qual);
417440    s2 = stralloc_printf(" %s ",
418441            obj->u.meas.type < 3 ? obj->u.meas.inverted ? "<-" : "->" :
419442            obj->u.meas.inverted ? "<<" : ">>");
420    s3 = print_meas_base(obj->u.meas.high);
443    s3 = print_meas_base(obj->u.meas.high, obj->u.meas.high_qual);
421444    t = stralloc_printf("%s%s%s%s", s, s1, s2, s3);
422445    free(s);
423446    free(s1);
error.c
11/*
22 * error.c - Error reporting
33 *
4 * Written 2009 by Werner Almesberger
5 * Copyright 2009 by Werner Almesberger
4 * Written 2009, 2010 by Werner Almesberger
5 * Copyright 2009, 2010 by Werner Almesberger
66 *
77 * This program is free software; you can redistribute it and/or modify
88 * it under the terms of the GNU General Public License as published by
...... 
2525void (*reporter)(const char *s) = report_to_stderr;
2626
2727
28void yywarn(const char *s)
29{
30    /* we use yywarn only when starting */
31    fprintf(stderr, "%d: warning: %s near \"%s\"\n", lineno, s, yytext);
32}
33
34
2835void yyerrorf(const char *fmt, ...)
2936{
3037    va_list ap;
error.h
11/*
22 * error.h - Error reporting
33 *
4 * Written 2009 by Werner Almesberger
5 * Copyright 2009 by Werner Almesberger
4 * Written 2009, 2010 by Werner Almesberger
5 * Copyright 2009, 2010 by Werner Almesberger
66 *
77 * This program is free software; you can redistribute it and/or modify
88 * it under the terms of the GNU General Public License as published by
...... 
2020extern void (*reporter)(const char *s);
2121
2222
23void yywarn(const char *s);
24
2325void yyerrorf(const char *fmt, ...)
2426    __attribute__((format(printf, 1, 2)));
2527void yyerror(const char *s);
fpd.l
131131                  return TOK_DBG_FRAME; }
132132<INITIAL>"%print" { BEGIN(NOKEYWORD);
133133                  return TOK_DBG_PRINT; }
134<INITIAL>"%meas" { BEGIN(NOKEYWORD);
135                  return TOK_DBG_MEAS; }
134136<INITIAL>"%dump" { BEGIN(NOKEYWORD);
135137                  return TOK_DBG_DUMP; }
136138<INITIAL>"%exit" { BEGIN(NOKEYWORD);
...... 
173175
174176; BEGIN(INITIAL);
175177
176"{" { BEGIN(NOKEYWORD);
177                  disable_keywords = is_table;
178"{" { disable_keywords = is_table;
179                  BEGIN(disable_keywords ?
180                    NOKEYWORD : INITIAL);
178181                  return '{'; }
179182"}" { disable_keywords = 0;
183                  BEGIN(INITIAL);
180184                  return '}'; }
181185
182186^#\ [0-9]+\ \"[^"]*\"(\ [0-9]+)*\n {
fpd.y
1717
1818#include "util.h"
1919#include "error.h"
20#include "coord.h"
2021#include "expr.h"
2122#include "obj.h"
2223#include "meas.h"
2324#include "gui_status.h"
25#include "gui_inst.h" /* for %meas */
2426#include "dump.h"
2527#include "tsort.h"
2628#include "fpd.h"
2729
30#include "y.tab.h"
31
2832
2933struct expr *expr_result;
3034const char *var_id;
...... 
4953static struct tsort *tsort;
5054
5155
56/* ----- lookup functions -------------------------------------------------- */
57
58
5259static struct frame *find_frame(const char *name)
5360{
5461    struct frame *f;
...... 
109116}
110117
111118
119/* ----- item creation ----------------------------------------------------- */
120
121
112122static void set_frame(struct frame *frame)
113123{
114124    curr_frame = frame;
...... 
177187}
178188
179189
190/* ---- frame qualifiers --------------------------------------------------- */
191
192
193static int duplicate_qualifier(const struct frame_qual *a,
194    const struct frame_qual *b)
195{
196    if (!b)
197        return 0;
198    if (a != b && a->frame == b->frame) {
199        yyerrorf("duplicate qualifier \"%s\"", a->frame->name);
200        return 1;
201    }
202    if (b && duplicate_qualifier(a, b->next))
203        return 1;
204    return duplicate_qualifier(a->next, a->next);
205}
206
207
208static int can_reach(const struct frame *curr, const struct frame_qual *qual,
209    const struct frame *end)
210{
211    const struct obj *obj;
212
213    if (curr == end)
214        return !qual;
215
216    /*
217     * Don't recurse for removing the qualifier alone. We require a frame
218     * reference step as well, so that things like foo.foo.foo.bar.vec
219     * aren't allowed.
220     *
221     * Since a duplicate qualifier can never work, we test for this error
222     * explicitly in "duplicate_qualifier".
223     */
224    if (qual && curr == qual->frame)
225        qual = qual->next;
226
227    for (obj = curr->objs; obj; obj = obj->next)
228        if (obj->type == ot_frame)
229            if (can_reach(obj->u.frame.ref, qual, end))
230                return 1;
231    return 0;
232}
233
234
235static int check_qbase(struct qbase *qbase)
236{
237    if (duplicate_qualifier(qbase->qualifiers, qbase->qualifiers))
238        return 0;
239
240    if (!can_reach(frames, qbase->qualifiers, qbase->vec->frame))
241        yywarn("not all qualifiers can be reached");
242    return 1;
243}
244
245
246/* ----- debugging directives ---------------------------------------------- */
247
248
180249static int dbg_delete(const char *frame_name, const char *name)
181250{
182251    struct vec *vec;
...... 
314383}
315384
316385
386static int dbg_meas(const char *name)
387{
388    const struct obj *obj;
389    const struct inst *inst;
390    struct coord a1, b1;
391    char *s;
392
393    obj = find_obj(frames, name);
394    if (!obj) {
395        yyerrorf("unknown object \"%s\"", name);
396        return 0;
397    }
398
399    /* from fped.c:main */
400
401    if (!pkg_name)
402                pkg_name = stralloc("_");
403        reporter = report_to_stderr;
404    if (!instantiate())
405        return 0;
406
407    inst = find_meas_hint(obj);
408    if (!inst) {
409        yyerrorf("measurement \"%s\" was not instantiated", name);
410        return 0;
411    }
412
413    project_meas(inst, &a1, &b1);
414    s = format_len(obj->u.meas.label ? obj->u.meas.label : "",
415        dist_point(a1, b1), curr_unit);
416    printf("%s\n", s);
417    free(s);
418
419    return 1;
420}
421
422
317423%}
318424
319425
...... 
339445        struct frame *frame;
340446        struct vec *vec;
341447    } qvec;
448    struct qbase {
449        struct vec *vec;
450        struct frame_qual *qualifiers;
451    } qbase;
342452};
343453
344454
...... 
348458%token TOK_MEAS TOK_MEASX TOK_MEASY TOK_UNIT
349459%token TOK_NEXT TOK_NEXT_INVERTED TOK_MAX TOK_MAX_INVERTED
350460%token TOK_DBG_DEL TOK_DBG_MOVE TOK_DBG_FRAME TOK_DBG_PRINT
351%token TOK_DBG_DUMP TOK_DBG_EXIT TOK_DBG_TSORT
461%token TOK_DBG_DUMP TOK_DBG_EXIT TOK_DBG_TSORT TOK_DBG_MEAS
352462
353463%token <num> NUMBER
354464%token <str> STRING
...... 
358468%type <var> vars var
359469%type <row> rows
360470%type <value> row value opt_value_list
361%type <vec> vec base qbase
362%type <obj> object obj meas
471%type <vec> vec base
472%type <obj> object obj meas unlabeled_meas
363473%type <expr> expr opt_expr add_expr mult_expr unary_expr primary_expr
364474%type <num> opt_num
365475%type <frame> frame_qualifier
...... 
368478%type <mt> meas_type
369479%type <mo> meas_op
370480%type <qvec> qualified_base
481%type <qbase> qbase qbase_unchecked
371482
372483%%
373484
...... 
538649            if (!dbg_print($2))
539650                YYABORT;
540651        }
652    | TOK_DBG_MEAS ID
653        {
654            if (!dbg_meas($2))
655                YYABORT;
656        }
541657    | TOK_DBG_DUMP
542658        {
543659            if (!dump(stdout)) {
...... 
867983    ;
868984
869985measurements:
870    meas
986    unlabeled_meas /* @@@ hack */
871987        {
872988            *next_obj = $1;
873989            next_obj = &$1->next;
...... 
881997    ;
882998
883999meas:
1000    unlabeled_meas
1001        {
1002            $$ = $1;
1003        }
1004    | LABEL unlabeled_meas
1005        {
1006            $$ = $2;
1007            if (find_label(curr_frame, $1)) {
1008                yyerrorf("duplicate label \"%s\"", $1);
1009                YYABORT;
1010            }
1011            $$->name = $1;
1012        }
1013    ;
1014
1015unlabeled_meas:
8841016    meas_type opt_string qbase meas_op qbase opt_expr
8851017        {
8861018            struct meas *meas;
...... 
8891021            meas = &$$->u.meas;
8901022            meas->type = $4.max ? $1+3 : $1;
8911023            meas->label = $2;
892            $$->base = $3;
1024            $$->base = $3.vec;
1025            meas->low_qual = $3.qualifiers;
8931026            meas->inverted = $4.inverted;
894            meas->high = $5;
1027            meas->high = $5.vec;
1028            meas->high_qual = $5.qualifiers;
8951029            meas->offset = $6;
8961030            $$->next = NULL;
8971031        }
8981032    ;
8991033
9001034qbase:
1035    qbase_unchecked
1036        {
1037            $$ = $1;
1038            if (!check_qbase(&$$))
1039                YYABORT;
1040        }
1041    ;
1042
1043qbase_unchecked:
9011044    ID
9021045        {
903            $$ = find_vec(frames, $1);
904            if (!$$) {
1046            $$.vec = find_vec(frames, $1);
1047            if (!$$.vec) {
9051048                yyerrorf("unknown vector \"%s\"", $1);
9061049                YYABORT;
9071050            }
1051            $$.qualifiers = NULL;
9081052        }
9091053    | ID '.' ID
9101054        {
9111055            const struct frame *frame;
9121056
9131057            frame = find_frame($1);
914            $$ = frame ? find_vec(frame, $3) : NULL;
915            if (!$$) {
1058            $$.vec = frame ? find_vec(frame, $3) : NULL;
1059            if (!$$.vec) {
9161060                yyerrorf("unknown vector \"%s.%s\"", $1, $3);
9171061                YYABORT;
9181062            }
1063            $$.qualifiers = NULL;
1064        }
1065    | ID '/' qbase
1066        {
1067            const struct frame *frame;
1068            struct frame_qual *qual;
1069
1070            $$ = $3;
1071            frame = find_frame($1);
1072            if (!frame) {
1073                yyerrorf("unknown frame \"%s\"", $1);
1074                YYABORT;
1075            } else {
1076                qual = alloc_type(struct frame_qual);
1077                qual->frame = frame;
1078                qual->next = $$.qualifiers;
1079                $$.qualifiers = qual;
1080            }
9191081        }
9201082    ;
9211083
gui_meas.c
11/*
22 * gui_meas.c - GUI, measurements
33 *
4 * Written 2009 by Werner Almesberger
5 * Copyright 2009 by Werner Almesberger
4 * Written 2009, 2010 by Werner Almesberger
5* Copyright 2009, 2010 by Werner Almesberger
66 *
77 * This program is free software; you can redistribute it and/or modify
88 * it under the terms of the GNU General Public License as published by
...... 
6161
6262static int is_min(lt_op_type lt, const struct inst *inst)
6363{
64    struct coord min;
64    const struct sample *min;
6565
66    min = meas_find_min(lt, active_pkg->samples[inst->vec->n]);
67    return coord_eq(inst->u.vec.end, min);
66    min = meas_find_min(lt, active_pkg->samples[inst->vec->n], NULL);
67    return coord_eq(inst->u.vec.end, min->pos);
6868}
6969
7070
7171static int is_next(lt_op_type lt,
7272    const struct inst *inst, const struct inst *ref)
7373{
74    struct coord next;
74    const struct sample *next;
7575
7676    next = meas_find_next(lt, active_pkg->samples[inst->vec->n],
77        ref->u.vec.end);
78    return coord_eq(inst->u.vec.end, next);
77        ref->u.vec.end, NULL);
78    return coord_eq(inst->u.vec.end, next->pos);
7979}
8080
8181
8282static int is_max(lt_op_type lt, const struct inst *inst)
8383{
84    struct coord max;
84    const struct sample *max;
8585
86    max = meas_find_max(lt, active_pkg->samples[inst->vec->n]);
87    return coord_eq(inst->u.vec.end, max);
86    max = meas_find_max(lt, active_pkg->samples[inst->vec->n], NULL);
87    return coord_eq(inst->u.vec.end, max->pos);
8888}
8989
9090
9191static int is_a_next(lt_op_type lt, struct inst *inst)
9292{
9393    struct inst *a;
94    struct coord min, next;
94    const struct sample *min, *next;
9595
9696    for (a = insts_ip_vec(); a; a = a->next) {
97        min = meas_find_min(lt, active_pkg->samples[a->vec->n]);
97        min = meas_find_min(lt, active_pkg->samples[a->vec->n], NULL);
9898        next = meas_find_next(lt, active_pkg->samples[inst->vec->n],
99            min);
100        if (coord_eq(next, inst->u.vec.end))
99            min->pos, NULL);
100        if (coord_eq(next->pos, inst->u.vec.end))
101101            return 1;
102102    }
103103    return 0;
...... 
309309        (mode == min_to_next_or_max);
310310    meas->offset = NULL;
311311    meas_dsc = NULL;
312    /* we don't support qualifiers through the GUI yet */
313    meas->low_qual = NULL;
314    meas->high_qual = NULL;
312315    return 1;
313316}
314317
inst.c
3535struct inst *selected_inst = NULL;
3636struct bbox active_frame_bbox;
3737struct pkg *pkgs, *active_pkg, *curr_pkg;
38struct inst *curr_frame = NULL;
38struct inst *frame_instantiating = NULL;
3939
4040static struct pkg *prev_pkgs;
4141
...... 
574574
575575static void propagate_bbox(const struct inst *inst)
576576{
577    struct inst *frame =
578        curr_frame ? curr_frame : curr_pkg->insts[ip_frame];
577    struct inst *frame = frame_instantiating ?
578        frame_instantiating : curr_pkg->insts[ip_frame];
579579
580580    update_bbox(&frame->bbox, inst->bbox.min);
581581    update_bbox(&frame->bbox, inst->bbox.max);
...... 
602602    inst->vec = NULL;
603603    inst->obj = NULL;
604604    inst->base = inst->bbox.min = inst->bbox.max = base;
605    inst->outer = curr_frame;
605    inst->outer = frame_instantiating;
606606    inst->active = IS_ACTIVE;
607607    inst->next = NULL;
608608    *curr_pkg->next_inst[prio] = inst;
...... 
10301030};
10311031
10321032
1033static struct inst *find_meas_hint(const struct obj *obj)
1033struct inst *find_meas_hint(const struct obj *obj)
10341034{
10351035    struct inst *inst;
10361036
...... 
11511151    inst->u.frame.active = is_active_frame;
11521152    inst->active = active;
11531153    find_inst(inst);
1154    curr_frame = inst;
1154    frame_instantiating = inst;
11551155}
11561156
11571157
11581158void inst_end_frame(const struct frame *frame)
11591159{
1160    struct inst *inst = curr_frame;
1160    struct inst *inst = frame_instantiating;
11611161
1162    curr_frame = curr_frame->outer;
1163    if (curr_frame)
1162    frame_instantiating = frame_instantiating->outer;
1163    if (frame_instantiating)
11641164        propagate_bbox(inst);
11651165    if (inst->u.frame.active && frame == active_frame)
11661166        active_frame_bbox = inst->bbox;
...... 
12451245    pkgs = NULL;
12461246    inst_select_pkg(NULL);
12471247    curr_pkg = pkgs;
1248    curr_frame = NULL;
1248    frame_instantiating = NULL;
12491249}
12501250
12511251
inst.h
137137
138138/*
139139 * frame being instantiated - we need to export this one for meas.c, so that
140 * measurement scan update the root frame's bounding box.
140 * measurements can update the root frame's bounding box.
141141 */
142extern struct inst *curr_frame;
142extern struct inst *frame_instantiating;
143143
144144/*
145145 * @@@ Note that we over-generalize a bit here: the only item that ever ends up
...... 
183183int inst_hole(struct obj *obj, struct coord a, struct coord b);
184184int inst_arc(struct obj *obj, struct coord center, struct coord start,
185185    struct coord stop, unit_type width);
186struct inst *find_meas_hint(const struct obj *obj);
186187int inst_meas(struct obj *obj, struct coord from, struct coord to);
187188void inst_meas_hint(struct obj *obj, unit_type offset);
188189
meas.c
11/*
22 * meas.c - Measurements
33 *
4 * Written 2009 by Werner Almesberger
5 * Copyright 2009 by Werner Almesberger
4 * Written 2009, 2010 by Werner Almesberger
5 * Copyright 2009, 2010 by Werner Almesberger
66 *
77 * This program is free software; you can redistribute it and/or modify
88 * it under the terms of the GNU General Public License as published by
...... 
3535    for (i = 0; i != n; i++)
3636        while (samples[i]) {
3737            next = samples[i]->next;
38            bitset_free(samples[i]->frame_set);
3839            free(samples[i]);
3940            samples[i] = next;
4041        }
...... 
5354}
5455
5556
56void meas_post(const struct vec *vec, struct coord pos)
57void meas_post(const struct vec *vec, struct coord pos,
58    const struct bitset *frame_set)
5759{
5860    struct sample **walk, *new;
5961
...... 
6466            continue;
6567        if (pos.x < (*walk)->pos.x)
6668            break;
67        if (pos.x == (*walk)->pos.x)
69        if (pos.x != (*walk)->pos.x)
70            continue;
71        if (bitset_ge((*walk)->frame_set, frame_set))
72            return;
73        if (bitset_ge(frame_set, (*walk)->frame_set)) {
74            bitset_or((*walk)->frame_set, frame_set);
6875            return;
76        }
6977    }
7078    new = alloc_type(struct sample);
7179    new->pos = pos;
80    new->frame_set = bitset_clone(frame_set);
7281    new->next = *walk;
7382    *walk = new;
7483}
...... 
177186 * else if (*a == a0 && *a <xy a0) use *a
178187 */
179188
180struct coord meas_find_min(lt_op_type lt, const struct sample *s)
189const struct sample *meas_find_min(lt_op_type lt, const struct sample *s,
190    const struct bitset *qual)
181191{
182    struct coord min;
192    const struct sample *min = NULL;
183193
184    min = s->pos;
185194    while (s) {
186        if (lt(s->pos, min) ||
187            (!lt(min, s->pos) && lt_xy(s->pos, min)))
188            min = s->pos;
195        if (!qual || bitset_ge(s->frame_set, qual))
196            if (!min || lt(s->pos, min->pos) ||
197                (!lt(min->pos, s->pos) && lt_xy(s->pos, min->pos)))
198                min = s;
189199        s = s->next;
190200    }
191201    return min;
192202}
193203
194204
195struct coord meas_find_next(lt_op_type lt, const struct sample *s,
196    struct coord ref)
205const struct sample *meas_find_next(lt_op_type lt, const struct sample *s,
206    struct coord ref, const struct bitset *qual)
197207{
198    struct coord next;
208    const struct sample *next = NULL;
199209
200    next = s->pos;
201210    while (s) {
202        if (better_next(lt, ref, next, s->pos))
203            next = s->pos;
211        if (!qual || bitset_ge(s->frame_set, qual))
212            if (!next || better_next(lt, ref, next->pos, s->pos))
213                next = s;
204214        s = s->next;
205215    }
206216    return next;
207217}
208218
209219
210struct coord meas_find_max(lt_op_type lt, const struct sample *s)
220const struct sample *meas_find_max(lt_op_type lt, const struct sample *s,
221    const struct bitset *qual)
211222{
212    struct coord max;
223    const struct sample *max = NULL;
213224
214    max = s->pos;
215225    while (s) {
216        if (lt(max, s->pos) ||
217            (!lt(s->pos, max) && lt_xy(max, s->pos)))
218            max = s->pos;
226        if (!qual || bitset_ge(s->frame_set, qual))
227            if (!max || lt(max->pos, s->pos) ||
228                (!lt(s->pos, max->pos) && lt_xy(max->pos, s->pos)))
229                max = s;
219230        s = s->next;
220231    }
221232    return max;
...... 
225236/* ----- instantiation ----------------------------------------------------- */
226237
227238
228static int instantiate_meas_pkg(void)
239static struct bitset *make_frame_set(struct frame_qual *qual, int n_frames)
240{
241    struct bitset *set;
242
243    set = bitset_new(n_frames);
244    while (qual) {
245        bitset_set(set, qual->frame->n);
246        qual = qual->next;
247    }
248    return set;
249}
250
251
252static int instantiate_meas_pkg(int n_frames)
229253{
230254    struct obj *obj;
231255    const struct meas *meas;
232    struct coord a0, b0;
256    struct bitset *set;
257    const struct sample *a0, *b0;
233258    lt_op_type lt;
234259
235260    for (obj = frames->objs; obj; obj = obj->next) {
236261        if (obj->type != ot_meas)
237262            continue;
238263        meas = &obj->u.meas;
264
265        /* optimization. not really needed anymore. */
239266        if (!curr_pkg->samples[obj->base->n] ||
240267            !curr_pkg->samples[meas->high->n])
241268            continue;
242269
243270        lt = lt_op[meas->type];
244        a0 = meas_find_min(lt, curr_pkg->samples[obj->base->n]);
271
272        set = make_frame_set(meas->low_qual, n_frames);
273        a0 = meas_find_min(lt, curr_pkg->samples[obj->base->n], set);
274        bitset_free(set);
275        if (!a0)
276            continue;
277
278        set = make_frame_set(meas->high_qual, n_frames);
245279        if (is_next[meas->type])
246280            b0 = meas_find_next(lt,
247                curr_pkg->samples[meas->high->n], a0);
281                curr_pkg->samples[meas->high->n], a0->pos, set);
248282        else
249283            b0 = meas_find_max(lt,
250                curr_pkg->samples[meas->high->n]);
284                curr_pkg->samples[meas->high->n], set);
285        bitset_free(set);
286        if (!b0)
287            continue;
251288
252289        inst_meas(obj,
253            meas->inverted ? b0 : a0, meas->inverted ? a0 : b0);
290            meas->inverted ? b0->pos : a0->pos,
291            meas->inverted ? a0->pos : b0->pos);
254292    }
255293    return 1;
256294}
257295
258296
259int instantiate_meas(void)
297int instantiate_meas(int n_frames)
260298{
261299    struct pkg *pkg;
262300
263    curr_frame = pkgs->insts[ip_frame];
301    frame_instantiating = pkgs->insts[ip_frame];
264302    for (pkg = pkgs; pkg; pkg = pkg->next)
265303        if (pkg->name) {
266304            inst_select_pkg(pkg->name);
267            if (!instantiate_meas_pkg())
305            if (!instantiate_meas_pkg(n_frames))
268306                return 0;
269307        }
270308    return 1;
meas.h
11/*
22 * meas.h - Measurements
33 *
4 * Written 2009 by Werner Almesberger
5 * Copyright 2009 by Werner Almesberger
4 * Written 2009, 2010 by Werner Almesberger
5 * Copyright 2009, 2010 by Werner Almesberger
66 *
77 * This program is free software; you can redistribute it and/or modify
88 * it under the terms of the GNU General Public License as published by
...... 
1717
1818#include "coord.h"
1919#include "expr.h"
20#include "bitset.h"
2021
2122
2223typedef int (*lt_op_type)(struct coord a, struct coord b);
...... 
2425struct vec;
2526struct obj;
2627
28struct frame_qual {
29    const struct frame *frame;
30    struct frame_qual *next;
31};
32
2733struct meas {
2834    enum meas_type {
2935        mt_xy_next,
...... 
3945    /* low is obj->base */
4046    struct vec *high;
4147    struct expr *offset;
48
49    /* frame qualifiers */
50    struct frame_qual *low_qual;
51    struct frame_qual *high_qual;
4252};
4353
4454struct sample {
4555    struct coord pos;
56    struct bitset *frame_set;
4657    struct sample *next;
4758};
4859
...... 
5465int lt_y(struct coord a, struct coord b);
5566int lt_xy(struct coord a, struct coord b);
5667
57struct coord meas_find_min(lt_op_type lt, const struct sample *s);
58struct coord meas_find_next(lt_op_type lt, const struct sample *s,
59    struct coord ref);
60struct coord meas_find_max(lt_op_type lt, const struct sample *s);
68const struct sample *meas_find_min(lt_op_type lt, const struct sample *s,
69    const struct bitset *qual);
70const struct sample *meas_find_next(lt_op_type lt, const struct sample *s,
71    struct coord ref, const struct bitset *qual);
72const struct sample *meas_find_max(lt_op_type lt, const struct sample *s,
73    const struct bitset *qual);
6174
6275
6376void reset_samples(struct sample **samples, int n);
6477void meas_start(void);
65void meas_post(const struct vec *vec, struct coord pos);
66int instantiate_meas(void);
78void meas_post(const struct vec *vec, struct coord pos,
79    const struct bitset *frame_set);
80int instantiate_meas(int n_frames);
6781
6882#endif /* !MEAS_H */
obj.c
1818#include "util.h"
1919#include "error.h"
2020#include "expr.h"
21#include "bitset.h"
2122#include "meas.h"
2223#include "inst.h"
2324#include "hole.h"
...... 
3839void *instantiation_error = NULL;
3940
4041
42static struct bitset *frame_set; /* frames visited in "call chain" */
43
44
4145/* ----- Searching --------------------------------------------------------- */
4246
4347
...... 
181185        vec->pos.y += y.n;
182186        if (!inst_vec(vec, vec_base))
183187            goto error;
184        meas_post(vec, vec->pos);
188        meas_post(vec, vec->pos, frame_set);
185189    }
186190    return 1;
187191
...... 
399403    inst_begin_frame(frame_ref, frame, base,
400404        active && parent == active_frame,
401405        active && frame == active_frame);
406    bitset_set(frame_set, frame->n);
402407    frame->curr_parent = parent;
403408    ok = iterate_tables(frame, frame->tables, base, active);
404409    inst_end_frame(frame);
410    bitset_clear(frame_set, frame->n);
405411    frame->curr_parent = NULL;
406412    return ok;
407413}
...... 
458464}
459465
460466
467static int enumerate_frames(void)
468{
469    struct frame *frame;
470    int n = 0;
471
472    for (frame = frames; frame; frame = frame->next)
473        frame->n = n++;
474    return n;
475}
476
477
461478int instantiate(void)
462479{
463480    struct coord zero = { 0, 0 };
481    int n_frames;
464482    int ok;
465483
466484    meas_start();
467485    inst_start();
486    n_frames = enumerate_frames();
487    frame_set = bitset_new(n_frames);
468488    instantiation_error = NULL;
469489    reset_all_loops();
470490    reset_found();
...... 
480500    if (ok)
481501        ok = refine_layers();
482502    if (ok)
483        ok = instantiate_meas();
503        ok = instantiate_meas(n_frames);
484504    if (ok)
485505        inst_commit();
486506    else
487507        inst_revert();
508    bitset_free(frame_set);
488509    return ok;
489510}
490511
obj.h
163163    /* generating and editing */
164164    struct obj *active_ref;
165165
166    /* For searching */
166    /* for searching */
167167    struct obj *found_ref; /* NULL if not found yet */
168168
169    /* index into bit vector in samples */
170    int n;
171
169172    /* for dumping */
170173    int dumped;
171174
test/Common
6262}
6363
6464
65expect_grep()
66{
67    grep "$1" <_out >_tmp || exit 1
68    mv _tmp _out
69    shift
70    expect "$@"
71}
72
73
6574if [ ! -z "$CWD_PREFIX" -a ! -z "$FPED" -a "$FPED" = "${FPED#/}" ]; then
6675    FPED="$CWD_PREFIX/$FPED"
6776fi
test/dbg_meas
1#!/bin/sh
2. ./Common
3
4###############################################################################
5
6fped "%meas: print mm (default)" <<EOF
7a: vec @(0mm, 0mm)
8b: vec @(3mm, 4mm)
9meas a >> b /* work-around to simplify grammar */
10m: meas a >> b
11%meas m
12EOF
13expect <<EOF
145
15EOF
16
17#------------------------------------------------------------------------------
18
19fped "%meas: print mil" <<EOF
20unit mil
21a: vec @(0mm, 0mm)
22b: vec @(2.54mm, 0mm)
23meas a >> b /* work-around to simplify grammar */
24m: meas a >> b
25%meas m
26EOF
27expect <<EOF
28100
29EOF
30
31#------------------------------------------------------------------------------
32
33fped_fail "%meas: invalid ID" <<EOF
34%meas m
35EOF
36expect <<EOF
371: unknown object "m" near "m"
38EOF
39
40#------------------------------------------------------------------------------
41
42fped_fail "%meas: measurement not instantiated" <<EOF
43a: vec @(0mm, 0mm)
44loop i = 1, 0
45b: vec @(i*1mm, 0mm)
46meas a >> b /* work-around to simplify grammar */
47m: meas a >> b
48%meas m
49EOF
50expect <<EOF
51measurement "m" was not instantiated
52EOF
53
54###############################################################################
test/del_frame
5353    v: vec @(0mm, 0mm)
5454}
5555
56frame f @
5657meas f.v -> f.v
5758
5859%del f
...... 
6465unit mm
6566EOF
6667
68#------------------------------------------------------------------------------
69
70fped_dump "delete frame: measurements with qualifiers disappear" <<EOF
71frame f {
72    v: vec @(0mm, 0mm)
73}
74
75frame g { frame f @ }
76
77frame g @
78meas g/f.v -> f.v
79
80%del g
81EOF
82expect <<EOF
83/* MACHINE-GENERATED ! */
84
85frame f {
86    v: vec @(0mm, 0mm)
87}
88
89package "_"
90unit mm
91EOF
92
6793###############################################################################
test/del_vec
4848frame f {
4949    v: vec @(0mm, 0mm)
5050}
51frame f @
5152meas f.v -> f.v
5253%del f.v
5354EOF
...... 
5960
6061package "_"
6162unit mm
63frame f @
6264EOF
6365
6466###############################################################################
test/meas_qual
1#!/bin/sh
2. ./Common
3
4###############################################################################
5
6fped_dump "qualified measurements: no qualifier" <<EOF
7frame c { v: vec @(0mm, 0mm) }
8frame b { frame c @ }
9frame a { frame b @ }
10frame a @
11meas c.v >> c.v
12EOF
13expect <<EOF
14/* MACHINE-GENERATED ! */
15
16frame c {
17    v: vec @(0mm, 0mm)
18}
19
20frame b {
21    frame c @
22}
23
24frame a {
25    frame b @
26}
27
28package "_"
29unit mm
30frame a @
31meas c.v >> c.v
32EOF
33
34#------------------------------------------------------------------------------
35
36fped_dump "qualified measurements: fully qualified" <<EOF
37frame c { v: vec @(0mm, 0mm) }
38frame b { frame c @ }
39frame a { frame b @ }
40frame a @
41meas a/b/c.v >> c.v
42EOF
43expect_grep '^meas' <<EOF
44meas a/b/c.v >> c.v
45EOF
46
47#------------------------------------------------------------------------------
48
49fped_dump "qualified measurements: partially qualified" <<EOF
50frame c { v: vec @(0mm, 0mm) }
51frame b { frame c @ }
52frame a { frame b @ }
53frame a @
54meas a/c.v >> c.v
55EOF
56expect_grep '^meas' <<EOF
57meas a/c.v >> c.v
58EOF
59
60#------------------------------------------------------------------------------
61
62fped_dump "qualified measurements: wrong order" <<EOF
63frame c { v: vec @(0mm, 0mm) }
64frame b { frame c @ }
65frame a { frame b @ }
66frame a @
67meas b/a/c.v >> c.v
68EOF
69expect_grep 'warning' <<EOF
705: warning: not all qualifiers can be reached near "v"
71EOF
72
73#------------------------------------------------------------------------------
74
75fped_dump "qualified measurements: unlinked frame" <<EOF
76frame c { v: vec @(0mm, 0mm) }
77frame b { frame c @ }
78frame a { frame b @ }
79frame x {}
80frame a @
81frame x @
82meas a/c.v >> x/c.v
83EOF
84expect_grep 'warning' <<EOF
857: warning: not all qualifiers can be reached near "v"
86EOF
87
88#------------------------------------------------------------------------------
89
90fped_fail "qualified measurements: duplicate qualifier" <<EOF
91frame c { v: vec @(0mm, 0mm) }
92frame b { frame c @ }
93frame a { frame b @ }
94frame a @
95meas b/b/c.v >> c.v
96EOF
97expect <<EOF
985: duplicate qualifier "b" near "v"
99EOF
100
101#------------------------------------------------------------------------------
102
103fped "qualified measurements: \"macro\" unqualified" <<EOF
104frame x {
105    a: vec @(0mm, 0mm)
106    b: vec .(d, 0mm)
107}
108frame a {
109    set d = 2mm
110    frame x @
111}
112frame b {
113    set d = 3mm
114    frame x @
115}
116frame a @
117vec @(1mm, 0mm)
118frame b .
119meas x.a >> x.b /* dummy */
120m: meas x.a >> x.b
121%meas m
122EOF
123expect <<EOF
1244
125EOF
126
127#------------------------------------------------------------------------------
128
129fped "qualified measurements: \"macro\" qualified (a)" <<EOF
130frame x {
131    a: vec @(0mm, 0mm)
132    b: vec .(d, 0mm)
133}
134frame a {
135    set d = 2mm
136    frame x @
137}
138frame b {
139    set d = 3mm
140    frame x @
141}
142frame a @
143vec @(1mm, 0mm)
144frame b .
145meas x.a >> x.b /* dummy */
146m: meas a/x.a >> a/x.b
147%meas m
148EOF
149expect <<EOF
1502
151EOF
152
153#------------------------------------------------------------------------------
154
155fped "qualified measurements: \"macro\" qualified (b)" <<EOF
156frame x {
157    a: vec @(0mm, 0mm)
158    b: vec .(d, 0mm)
159}
160frame a {
161    set d = 2mm
162    frame x @
163}
164frame b {
165    set d = 3mm
166    frame x @
167}
168frame a @
169vec @(1mm, 0mm)
170frame b .
171meas x.a >> x.b /* dummy */
172m: meas b/x.a >> b/x.b
173%meas m
174EOF
175expect <<EOF
1763
177EOF
178
179#------------------------------------------------------------------------------
180
181fped "qualified measurements: \"macro\" qualified (a/b)" <<EOF
182frame x {
183    a: vec @(0mm, 0mm)
184    b: vec .(d, 0mm)
185}
186frame a {
187    set d = 2mm
188    frame x @
189}
190frame b {
191    set d = 3mm
192    frame x @
193}
194frame a @
195vec @(1mm, 0mm)
196frame b .
197meas x.a >> x.b /* dummy */
198m: meas a/x.a >> b/x.b
199%meas m
200EOF
201expect <<EOF
2024
203EOF
204
205#------------------------------------------------------------------------------
206
207fped "qualified measurements: \"macro\" qualified (b/a)" <<EOF
208frame x {
209    a: vec @(0mm, 0mm)
210    b: vec .(d, 0mm)
211}
212frame a {
213    set d = 2mm
214    frame x @
215}
216frame b {
217    set d = 3mm
218    frame x @
219}
220frame a @
221vec @(1mm, 0mm)
222frame b .
223meas x.a >> x.b /* dummy */
224m: meas b/x.a >> a/x.b
225%meas m
226EOF
227expect <<EOF
2281
229EOF
230
231###############################################################################
test/structure
7272    a: vec @(0mm, 0mm)
7373    b: vec @(1mm, 1mm)
7474}
75frame f @
7576meas f.a -> f.b
7677EOF
7778expect <<EOF
...... 
8485
8586package "_"
8687unit mm
88frame f @
8789meas f.a -> f.b
8890EOF
8991

Archive Download the corresponding diff file

Branches:
master



interactive