r5827 - in trunk: eda eda/boom gta02-core/bom gta02-core/bom/fic
werner at docs.openmoko.org
werner at docs.openmoko.org
Sun Feb 7 15:33:41 CET 2010
Author: werner
Date: 2010-02-07 15:33:40 +0100 (Sun, 07 Feb 2010)
New Revision: 5827
Added:
trunk/eda/boom/
trunk/eda/boom/CHARACTERISTICS
trunk/eda/boom/Makefile
trunk/eda/boom/README
trunk/eda/boom/annotate
trunk/eda/boom/bom2part
trunk/eda/boom/boom
trunk/eda/boom/gen2chr
trunk/eda/boom/match.pl
trunk/eda/boom/misc.pl
trunk/eda/boom/pardup.pl
trunk/eda/boom/parser.pl
trunk/eda/boom/part2order
trunk/eda/boom/prettyord
trunk/eda/boom/test/
trunk/eda/boom/workflow.fig
Removed:
trunk/gta02-core/bom/CHARACTERISTICS
trunk/gta02-core/bom/README
trunk/gta02-core/bom/annotate
trunk/gta02-core/bom/bom2part
trunk/gta02-core/bom/gen2chr
trunk/gta02-core/bom/match.pl
trunk/gta02-core/bom/misc.pl
trunk/gta02-core/bom/parser.pl
trunk/gta02-core/bom/part2order
trunk/gta02-core/bom/prettyord
trunk/gta02-core/bom/test/
trunk/gta02-core/bom/workflow.fig
Modified:
trunk/gta02-core/bom/Makefile
trunk/gta02-core/bom/fic/Makefile
trunk/gta02-core/bom/fic/equ2equ
Log:
Moved BOM processor over to eda/boom/
- bom/: moved project-independent files to eda/boom/
- eda/boom/pardup.pl: oops, forget to add it to SVN
- eda/boom/boom: wrapper for the other scripts. Sets the include path.
- bom/Makefile, bom/fic/Makefile: updated to use boom wrapper
Copied: trunk/eda/boom/CHARACTERISTICS (from rev 5821, trunk/gta02-core/bom/CHARACTERISTICS)
===================================================================
--- trunk/eda/boom/CHARACTERISTICS (rev 0)
+++ trunk/eda/boom/CHARACTERISTICS 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,140 @@
+*** This is an older draft of the concept - differs sometimes from the way
+ things are done in gta02-core. ***
+
+
+BOM matching
+============
+
+BOMs are matched with inventories in the following way:
+
+- a .lst file with the BOM is generated by KiCad
+
+- using a ruleset, component characteristics are translated to a
+ canonical format and default values may be used for unspecified
+ characteristics
+
+- part catalogs are searched for matches with the canonical component
+ descriptions. This yields a list of supplier-specific part numbers
+ for each component.
+
+ Parts can be characterized by either specifying their properties or
+ by equating them to another part. E.g., a Digi-Key part may be
+ defined as an NXP part which in turn is equivalent to a TI part.
+
+- this list is then matched against inventories, using a suitable
+ optimization strategy (e.g., prioritize inventories and try to
+ pick as many suitable components as possible higher priority ones
+ before moving to lower priority ones)
+
+ E.g., local stock could be the first-level inventory, followed by
+ more distant warehouses, followed by distributors, followed by
+ manufacturers.
+
+ Inventories could also include pricing information.
+
+- TBD: it would be good if parameters gathered in the matching process
+ could be fed back into KiCad (as some sort of annotations, similar
+ to the expanded view of schematic symbols), such that under-specifed
+ parts yielding mismatches can be spotted by manual review.
+
+
+Catalog
+=======
+
+A catalog contains part characteristics and the reference number(s)
+assigned to them.
+
+
+Basic syntax
+------------
+
+Catalog entries consist of "words" in the sense that each word does
+not contain any whitespace and words are separated from each other by
+whitespace. Whitespace can be included in a word if it is enclosed in
+double quotes.
+
+Each entry begins in the first column of a line. If an entry needs
+more than one line, the words on the continuation line(s) must be
+indented by whitespace.
+
+Trailing whitespace is ignored, and so are comments beginning with a
+hash mark. Blank lines end any entry and are also ignored.
+
+Each catalog entry begins with the part number followed by a part type
+designator.
+
+Characteristics have the form <field>=<value>, where
+the fields follow the pattern outlined below. The value is some
+description of the value of that characteristic, typically a number
+and a unit (e.g., 4.7uF) or a name (e.g., X5R).
+
+Numbers use a decimal point where necessary. Mantissas are normalized
+such that they fall into the range 1 <= n < 1000. E.g., instead of
+0.1uF, write 100nF. There is no space between number and unit. The
+Omega of Ohm is written as "R".
+
+
+Fields
+------
+
+Each
+
+General fields
+- - - - - - -
+
+FP Footprint
+H Height (overrides any height implied by footprint)
+TOL Tolerance, with percent sign. Split tolerances are indicated as n/m%
+DSC Free-format description
+
+
+Resistors
+- - - - -
+
+RES Part type designator
+R Resistance, with unit
+P Maximum power dissipation
+V Maximum volatage
+
+
+Capacitors
+- - - - -
+
+CAP Part type designator
+C Capacitance, with unit
+M Material, e.g., TANT, NP0, X5R, etc.
+V Maximum voltage
+ESR ESR, with unit
+
+
+Inductors
+-- - - -
+
+Diodes
+- - -
+
+DIODE Regular diode
+STKY Schottky diode
+
+Vf Maximum forward voltage
+Vr Maximum reverse voltage
+If Maximum forward current
+Ir Maximum reverse current
+C Capacitance
+
+LED Ligh-emitting diode
+
+COL Color, multiple colors are separated by /, e.g., blue/red
+ARRAY If multiple diodes form an array, this parameter describes
+ its structure: CA = common anode, CC = common cathode,
+ SEQ = tap-A-C-tap-A-C-tap sequence
+
+ZENER Zener diode
+
+Vz Zener voltage
+
+TVS Transient voltage suppressor
+
+Vac Working voltage, AC
+Vdc Working voltage, DC
+E Energy
Added: trunk/eda/boom/Makefile
===================================================================
--- trunk/eda/boom/Makefile (rev 0)
+++ trunk/eda/boom/Makefile 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,19 @@
+UPLOAD=werner at sita.openmoko.org:public_html/gta02-core/
+COPY=rsync -e ssh --progress
+
+.PHONY: all xpdf spotless upload
+
+all:
+ @echo "make what ? xpdf, upload, or spotless ?" 1>&2
+
+workflow.pdf: workflow.fig
+ fig2dev -L pdf $< >$@ || { rm -f $@; exit 1; }
+
+xpdf: workflow.pdf
+ xpdf workflow.pdf
+
+upload: workflow.pdf
+ $(COPY) workflow.pdf $(UPLOAD)/bom-workflow.pdf
+
+spotless:
+ rm -f workflow.pdf
Copied: trunk/eda/boom/README (from rev 5823, trunk/gta02-core/bom/README)
===================================================================
--- trunk/eda/boom/README (rev 0)
+++ trunk/eda/boom/README 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,336 @@
+The BOM processing system
+=========================
+
+The BOM processing system takes a bill of material generated by
+KiCad and converts it in various steps into a "shopping list"
+that can be used to order from various providers.
+
+
+Introduction
+============
+
+The following sections describe how to use the basic elements of
+the BOM processing system.
+
+
+A simple BOM translation
+------------------------
+
+KiCad identifies components by a so-called component reference,
+e.g., R1001, U5, etc. In addition to this, each component can have
+various parameters, such as a "value", its footprint, and further
+user-defined items. These parameters can be shown in the schematics
+(e.g., the value usually is) or they can be hidden (e.g., the
+footprint).
+
+At the end of the process, we want a "shopping list" that can be
+used to order items or to find them in an inventory or catalog.
+Components in the shopping list are identified by a part number.
+
+...
+- BOM
+- inventory
+- ID matching
+
+
+Equivalences
+------------
+
+A single component can be associated with multiple part numbers.
+For example, a chip its manufacturer calls "XYZ-R1" may be listed in
+a distributor's catalog with a completely different order number,
+such as "20-1234-8". The BOM processing system therefore
+distinguishes multiple so-called name spaces. A name space is
+identified by a (unique) name and a part number is generally
+qualified by the name of the name space.
+
+E.g., if the manufacturer is called "ACME" and the distributor of
+electronical components calls itself "DIST-EL", the part in our
+example may have the equivalent names "ACME XYZ-R1" and "DIST-EL
+20-1234-8".
+
+...
+- revise .inv
+
+example.equ:
+
+#INV
+DIST-EL 20-1234-8
+#EQU
+ACME XYZ-R1 DIST-EL 20-1234-8
+
+
+Adding stock and cost
+---------------------
+
+- .inv, more fields
+- quanta
+
+Substituting component names
+----------------------------
+
+- intro to .sub
+- ad-hoc fixes
+
+
+Selecting characteristics
+-------------------------
+
+- .sub
+- .chr
+...
+
+
+Generating characteristics
+--------------------------
+
+- .gen
+
+
+Advanced topics
+===============
+
+- generating .inv files
+- different presentations (e.g., CT, TR, ...)
+- component substitution (one-way equivalence)
+- problem reports
+- hiding known problems (while sourcing)
+
+
+File formats
+============
+
+The BOM processing system uses a large number of different files to
+store information retrieved from the BOM, inventories, intermediate
+results, etc. The following sections describe the various formats.
+
+
+Part characteristics (.chr)
+---------------------------
+
+A part characteristics file lists the parameters of components.
+This information is then matched with the parameters specified in
+the schematics.
+
+The part characteristics file begins with a line containing only
+#CHR
+
+After this, each line contains the manufacturer (namespace), the
+part number, and a list of parameter=value entries. Fields are
+separated by spaces.
+
+Long lines can be wrapped by indenting the continuation lines.
+
+Blank lines and comments (#) are ignored.
+
+
+Substitutions (.sub)
+--------------------
+
+A substitutions file specifies rules for translating component
+parameters in schematics to part characteristics.
+
+A substitution rule consists of zero or more conditions and zero or
+more assignments. The conditions are of the form field=pattern. The
+field can be a per-component fields KiCad provides or any parameter
+set by substitutions.
+
+KiCad fields are named as follows:
+
+KiCad field Field name
+----------- ----------
+Reference REF (*)
+Value VAL
+FP Footprint
+Field1 F1
+... ...
+
+(*) As a shortcut, REF= can be omitted.
+
+Note that fields with a user-defined name currently still only appear
+as F1, F2, etc.
+
+The special field name FN can be used to look for a match in all of
+F1, F2, ... This way, it's sufficient to use a consistent syntax for
+additional parameters, without having to assign also a fixed location
+for them. If more than one field matches, the first match is taken.
+
+Field names are case-insensitive.
+
+The pattern is uses a notation similar to filename globbing. There
+are the following special constructs:
+
+- * matches a string of any length
+- ? matches a single character
+- (...) matches the pattern between the parentheses and records the
+ string matched
+- $X marks a value in nXn notation, e.g., 4u7 or 100R. Such values
+ are converted to SI-like notation.
+
+A rule is applied when all conditions are fulfilled. In this case,
+assignments of the form field=value are executed. Strings obtained
+in the match can be included in a value as follows:
+
+- $field and ${field} are replaced by the respective field
+- $field:n and ${field:n} are replaced by the n-th (...) pattern in
+ the match of the respective field
+
+If a rule ends with an exclamation mark, the substitution process stops
+after the rule is applied. Otherwise, further rules are processed.
+
+Examples:
+
+R* val=$R -> R=$val
+
+This rule translates the values of all resistors to SI notation.
+
+D* FN=(*)Vdc -> T=TSV Vdc=FN:1
+
+This rule sets the parameters T and Vdc for Zeners acting as TSVs.
+
+If a set of rules has a common set of conditions or assignments, the
+more compact block notation can be used instead of repeating them for
+each rule:
+
+common-conditions -> common-assignments {
+ rule-specific-conditions -> rule-specific-assignments
+ ...
+}
+
+Rules in a block only match if both the common and the rule-specific
+conditions are met. Then the common and the rule-specific assignments
+are performed. If a condition or an assignment appears both in the
+common and the rule-specific part, only the latter is used.
+
+Long lines can be wrapped by indenting the continuation lines. Note
+that { and ! are also considered to be part of the same line as the
+rest of the rule. In particular, the following construct wouldn't
+work:
+
+X=Y
+{
+ ...
+}
+
+With proper indentation, this would:
+
+X=Y
+ {
+ ...
+}
+
+
+Characteristics generation (.gen)
+---------------------------------
+
+The substitution mechanism can also be used to automatically generate
+characteristics from part numbers, e.g., for resistors or capacitors.
+
+.gen files are exactly .sub files, with the exception that the only
+field used is the REF field and that it contains the part number.
+
+Once the rule set has been processed, all fields (except REF) whose
+name doesn't begin with an underscore are placed in the characteristics
+entry as parameters.
+
+An entry is only produced if the rule set is explicitly terminated.
+
+
+Parts list (.par)
+------------------
+
+A parts file lists the parts that are suitable for a given BOM item.
+The file begins with a line containing only
+#PAR
+
+After this, each line contains the component reference, a space, and
+then one or more namespace part-number groups, separated by spaces as
+well.
+
+Blank lines and comments (#) are ignored.
+
+
+Order list (.ord)
+-----------------
+
+An order file lists the quantities to order from inventories, along
+with the cost and the component references the item is used for. The
+file begins with a line containing only
+#ORD
+
+After this, each line contains the supplier (namespace), the reference
+number, the number of items to order, the currency code, the cost,
+and one or more component references.
+
+Blank lines and comments (#) are ignored.
+
+
+Equivalence (.equ)
+------------------
+
+Equivalence files establish equivalences between parts numbers in the
+same or in different name spaces. An equivalence file begins with a
+line containing only
+#EQU
+
+After this, each line consists of the following four space-separated
+fields:
+
+namespace-1 part-number-1 namespace-2 part-number-2
+
+Blank lines and comments (#) are ignored.
+
+
+Inventory (.inv)
+----------------
+
+Inventory files list inventory and component cost. An inventory file
+begins with a line containing only
+#INV
+
+After this, each line contains the namespace and the part number,
+followed by the number of items in stock, the currency code, and one
+or more pricing entries.
+
+Each pricing entry consists of two fields: the number of items in an
+order, and the per item price at that quantity. A sequence of
+increasing order sizes indicates that they are quanta. A sequence of
+decreasing order sizes indicates that smaller quanta are possible
+after a previous larger threshold has been met.
+
+Example:
+
+... USD 1 0.5 10 0.4 100 0.2
+
+Means that an order of at least 170 units would be made either as
+2 * 100 units, costing USD 40, or as 1 * 100 + 7 * 10 units, costing
+USD 20 + USD 28 = USD 48.
+
+If the entry is
+
+... USD 1 0.5 10 0.4 100 0.2 1 0.2
+
+Then the USD 0.2 per unit cost would apply to any any quantity of at
+least 100 units. So a 170 units order would cost USD 34.
+
+Blank lines and comments (#) are ignored.
+
+The number of items in stock and the pricing data can be omitted. We
+call this "virtual inventory". In this case, the numer of items in
+stock and the price default to large numbers (e.g., 999999). Virtual
+inventory is used to suppress warnings for parts that have not been
+sourced yet, but where sourcing is in progress.
+
+
+Description (.dsc)
+------------------
+
+A description file contains plain text descriptions of parts. The file
+begins with a like containing only
+#DSC
+
+Each line contains the name space, a space, the part number, another
+space, and the description. The description can contain any printable
+character and ends with a newline.
+
+Blank lines and comments (#) are ignored.
Copied: trunk/eda/boom/annotate (from rev 5826, trunk/gta02-core/bom/annotate)
===================================================================
--- trunk/eda/boom/annotate (rev 0)
+++ trunk/eda/boom/annotate 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,188 @@
+#!/usr/bin/perl
+
+require "parser.pl";
+require "misc.pl";
+
+
+&parse;
+
+
+$H = 50; # character height
+$W = $H*0.9; # character width
+$L = $H+20; # line skip
+
+
+sub normalize
+{
+ my @t = @_;
+
+ # convert from (x0, y0, w, h) to (x0, y0, x1, y1)
+ $t[2] += $t[0];
+ $t[3] = $t[1]-$t[3];
+ return ($t[0], $t[3], $t[2], $t[1]);
+}
+
+
+#
+# 2x2 matrix inversion
+# http://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_2.C3.972_matrices
+#
+
+sub invert
+{
+ my @m = @_;
+ my $f = 1/($m[0]*$m[3]-$m[1]*$m[2]);
+ return ($f*$m[3], -$f*$m[1], -$f*$m[2], $f*$m[0]);
+}
+
+
+sub block
+{
+ my @t = &normalize(@_);
+ push(@block, [ @t ]);
+ $wnl .= "Wire Notes Line\n\t$t[0] $t[1] $t[2] $t[3]\n";
+}
+
+
+sub pass
+{
+ my @t = &normalize(@_);
+
+ for (@block) {
+ my @b = @{ $_ };
+ next if $t[0] > $b[2];
+ next if $t[2] < $b[0];
+ next if $t[1] > $b[3];
+ next if $t[3] < $b[1];
+ return 0;
+ }
+ return 1;
+}
+
+
+sub put
+{
+ local ($x0, $y0, $ref, @s) = @_;
+
+ my $h = @s*$L;
+ my $w = 0;
+ for (@s) {
+ my $t = $W*length $_;
+ $w = $t if $t > $w;
+ }
+ my $a = 270;
+ my $r = 100;
+ my $x, $y;
+ my $ym = $y0-$h+$H/2;
+ for ($i = 0; $i != 128; $i++) {
+ $x = int($x0+$r*cos($a/180*3.14159));
+ $y = int($ym+$r*sin($a/180*3.14159));
+ last if &pass($x, $y, $w, $h);
+ $a += 22.5;
+ $r += $L/8;
+ }
+ warn "no place found for \"$s[0]\"" if $i == 128;
+
+ my @m = &invert( @{ $m{$ref} });
+ &block($x, $y+$H/2, $w, $h);
+ my $n = 10;
+ for my $s (reverse @s) {
+ my $dx = $x-$x0;
+ my $dy = $y-$y0;
+ my $sx = $x0+$dx*$m[0]+$dy*$m[1];
+ my $sy = $y0+$dx*$m[2]+$dy*$m[3];
+ ($hv, $hj, $vj) = ("H", "L", "C") if $m[0] == 1;
+ ($hv, $hj, $vj) = ("H", "R", "C") if $m[0] == -1;
+ ($hv, $hj, $vj) = ("V", "C", "B") if $m[1] == 1;
+ ($hv, $hj, $vj) = ("V", "C", "T") if $m[1] == -1;
+ $s =~ s/~/-/g;
+ print "F $n \"$s\" $hv $sx $sy $H 0000 $hj ${vj}NN\n";
+ $y -= $L;
+ $n++;
+ }
+}
+
+
+#
+# pass 1: find the orientation of all parts
+#
+
+for (@eeschema) {
+ $ref = $1 if /^L \S+ (\S+)/;
+ undef $ref if /^\$EndComp/;
+ next unless /^\s+(-?[01])\s+(-?[01])\s+(-?[01])\s+(-?[01])\s*$/;
+ my @m = split(/\s+/);
+ shift @m;
+ $m{$ref} = [ @m ];
+}
+
+
+#
+# pass 2: block the spaces occupied by fields
+#
+
+for (@eeschema) {
+ $ref = $1 if /^L \S+ (\S+)/;
+ if (/^P (\d+) (\d+)/) {
+ $x0 = $1;
+ $y0 = $2;
+ }
+ next unless /^F /;
+ die "$_" unless
+ /^F \d+ "([^"]*)" ([HV]) (\d+) (\d+) (\d+) +(\d+) ([LC]) (C)/;
+ ($s, $hv, $x, $y, $size, $flag, $hj, $vj) =
+ ($1, $2, $3, $4, $5, $6, $7, $8);
+ $dx = $x-$x0;
+ $dy = $y-$y0;
+ $x = $x0+$dx*$m{$ref}[0]+$dy*$m{$ref}[1];
+ $y = $y0+$dx*$m{$ref}[2]+$dy*$m{$ref}[3];
+ next if $flag != 0;
+ $w = $size*0.8*length $s;
+ # we don't need to consider H/V
+ &block($hj eq "L" ? $x : $x-$w/2, $y+$size/2, $w, $size);
+}
+
+#
+# pass 3:
+#
+
+for (@eeschema) {
+ undef @f if /^\$Comp/;
+ if (/^L \S+ (\S+)/) {
+ $ref = $1;
+ my @p = @{ $parts{$ref} };
+ while (@p) {
+ my @id = splice(@p, 0, 2);
+ my $id = "$id[0] $id[1]";
+ for ($id, &eq($id)) {
+ next unless defined $dsc{$_};
+ push(@f, $dsc{$_});
+ last;
+ }
+ }
+ }
+ if (/^P (\d+) (\d+)/) {
+ $x = $1;
+ $y = $2;
+ }
+ if (/^\s+/) {
+ my %seen;
+ my @u = ();
+ for (@f) {
+ next if $seen{$_};
+ push(@u, $_);
+ $seen{$_} = 1;
+ }
+ undef @f;
+ # $m{$ref}[0] == 1 OK
+ # $m{$ref}[0] == -1 OK
+ # $m{$ref}[1] == 1 OK
+ # $m{$ref}[1] == -1 OK (small deviations found)
+ &put($x, $y, $ref, @u) if 1 || $m{$ref}[1] == -1;
+ }
+ if (/\$EndSCHEMATC/) {
+ # uncomment for debugging
+# print $wnl;
+ }
+ print "$_\n";
+}
Copied: trunk/eda/boom/bom2part (from rev 5819, trunk/gta02-core/bom/bom2part)
===================================================================
--- trunk/eda/boom/bom2part (rev 0)
+++ trunk/eda/boom/bom2part 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,92 @@
+#!/usr/bin/perl
+
+require "parser.pl";
+require "match.pl";
+require "misc.pl";
+
+
+sub issue
+{
+ print shift(@_), " ", join(" ", @_, &eq(@_)), "\n";
+}
+
+
+if ($ARGV[0] eq "-d") {
+ $debug = 1;
+ shift @ARGV;
+}
+&parse;
+
+$total = 0;
+$bad = 0;
+
+print "#PAR\n";
+for $ref (keys %cmp) {
+ @f = @{ $cmp{$ref} };
+ $total++;
+
+ print STDERR "REF $ref\n" if $debug;
+
+ # if we're lucky, we get a direct ID match
+
+ if (defined $id{$f[0]}) {
+ print STDERR "FIRST ID\n" if $debug;
+ &issue($ref, $id{$f[0]});
+ next;
+ }
+
+ # no such luck. Let's roll up our sleeves and to the substitutions.
+
+ undef %field;
+ $field{"REF"} = $ref;
+ $field{"VAL"} = $f[0];
+ if ($f[1] eq "") {
+ print STDERR "warning: $ref ($f[0]) has no footprint\n";
+ } else {
+ $field{"FP"} = $f[1];
+ }
+ for (my $i = 1; $i != 10; $i++) {
+ $field{"F$i"} = $f[$i+1];
+ }
+ &apply_rules();
+
+ # try our luck again
+
+ if (defined $id{$field{"VAL"}}) {
+ print STDERR "SECOND ID\n" if $debug;
+ &issue($ref, $id{$field{"VAL"}});
+ next;
+ }
+
+ # still nothing. Let's match characteristics then.
+
+ my @p = ();
+ COMP: for my $c (keys %chr) {
+ print STDERR "PART $c\n" if $debug;
+ for (keys %field) {
+ next if $_ eq "REF" || $_ eq "VAL" || $_ =~ /^F\d$/;
+ print STDERR " $_=",$field{$_}," " if $debug;
+ if (!defined $chr{$c}{$_}) {
+ print STDERR "NO FIELD\n" if $debug;
+ next COMP;
+ next;
+ }
+ if ($chr{$c}{$_} eq $field{$_}) {
+ print STDERR "== $chr{$c}{$_}\n" if $debug;
+ } else {
+ print STDERR "!= $chr{$c}{$_}\n" if $debug;
+ next COMP;
+ }
+ }
+ push(@p, $c);
+ }
+ if (@p) {
+ &issue($ref, @p);
+ next;
+ }
+
+ print STDERR "unmatched: $ref (", join(", ", @f), ")\n";
+ $bad++;
+# print join("#", ($ref, @f)), " -> $id{$f[0]}\n";
+}
+print STDERR "$bad/$total unmatched\n" if $bad;
Added: trunk/eda/boom/boom
===================================================================
--- trunk/eda/boom/boom (rev 0)
+++ trunk/eda/boom/boom 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+
+sub usage
+{
+ print STDERR "usage: $0 command [arg ...]\n";
+ exit(1);
+}
+
+
+&usage unless @ARGV;
+
+($d = $0) =~ s|/[^/]*$||;
+if ($d eq "") {
+ $p = "/";
+} elsif ($d =~ /^\//) {
+ $p = "$d";
+} else {
+ chomp($cwd = `pwd`);
+ $p = "$cwd/$d";
+}
+
+$cmd = shift @ARGV;
+$cmd = "$p/$cmd" unless $cmd =~ m|/|;
+exec("perl", "-I", $p, $cmd, @ARGV);
+die "exec perl: $!";
Property changes on: trunk/eda/boom/boom
___________________________________________________________________
Name: svn:executable
+ *
Copied: trunk/eda/boom/gen2chr (from rev 5804, trunk/gta02-core/bom/gen2chr)
===================================================================
--- trunk/eda/boom/gen2chr (rev 0)
+++ trunk/eda/boom/gen2chr 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+
+require "parser.pl";
+require "match.pl";
+
+
+if ($ARGV[0] eq "-d") {
+ $debug = 1;
+ shift @ARGV;
+}
+if ($ARGV[0] eq "-n") {
+ $negate = 1;
+ shift @ARGV;
+}
+$key = shift @ARGV;
+&parse;
+
+print "#CHR\n";
+for (keys %id) {
+ next unless $id{$_} eq "$key $_";
+ undef %field;
+ $field{"REF"} = $_;
+ if (!&apply_rules()) {
+ print "$id{$_}\n" if $negate;
+ next;
+ }
+ next if $negate;
+ print $id{$_};
+ for (sort keys %field) {
+ next if $_ =~ /^_/;
+ next if $_ eq "REF";
+ print " $_=$field{$_}";
+ }
+ print "\n";
+}
Copied: trunk/eda/boom/match.pl (from rev 5823, trunk/gta02-core/bom/match.pl)
===================================================================
--- trunk/eda/boom/match.pl (rev 0)
+++ trunk/eda/boom/match.pl 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,200 @@
+#!/usr/bin/perl
+
+use re 'eval';
+
+
+#
+# "sub" populates the following global variables:
+#
+# $end[rule-number] = 0 / 1
+# $match[rule-number]{field}[0] = original-pattern
+# $match[rule-number]{field}[1] = RE1
+# $match[rule-number]{field}[2] = RE2
+# $action[rule-number]{field} = value
+#
+# $match_stack[depth]{field}[0] = original-pattern
+# $match_stack[depth]{field}[1] = RE1
+# $match_stack[depth]{field}[2] = RE2
+# $action_stack[depth]{field} = value
+# $may_cont = 0 / 1
+# $last
+# $last_action
+#
+
+#
+# $cvn_from{internal-handle} = index
+# $cvn_to{internal-handle} = index
+# $cvn_unit{internal-handle} = unit-name
+# $cvn_num = internal-handle
+# $found{field-or-subfield} = string
+
+
+#
+# We convert each input pattern into two regular expressions: the first matches
+# units in the nXn notation, e.g., 4u7 or 100R. The second matches them in SI
+# notation (sans space).
+#
+# When matching (sub_match), we first apply the first expression. Each time we
+# encounter a unit ($R, $F, etc.), __cvn is called. __cvn stores the index of
+# the unit in %cvn_from and %cvn_to.
+#
+# We then pick these substrings from the input string and convert the units to
+# SI notation. At the same time, we normalize the mantissa. Once done, we run
+# the second expression. This one always matches (hopefully :-)
+#
+# All (...) ranges in the original pattern have been replaced with named
+# capture buffers in the second expression, so all these subfields are now
+# gathered in the $+ array. (The same also happened in the first pass, but we
+# ignore it.)
+#
+# Finally, when expanding a value (sub_expand), we look for $field and
+# $field:index, and expand accordingly.
+#
+
+
+sub __cvn
+{
+ local ($num) = @_;
+
+ $cvn_from{$num} = $-[$#-];
+ $cvn_to{$num} = $+[$#+];
+}
+
+
+sub sub_match
+{
+ local ($s, $field, $m1, $m2) = @_;
+
+ #
+ # Perform the first match and record where we saw $<unit> patterns.
+ #
+ undef %cvn_from;
+ undef %cvn_to;
+ return undef unless $s =~ $m1;
+
+ #
+ # Convert the unit patterns to almost-SI notation. (We don't put a space
+ # after the number, but the rest is SI-compliant.)
+ #
+ my $off = 0;
+ for (keys %cvn_from) {
+ my $unit = $cvn_unit{$_};
+ my $from = $cvn_from{$_}+$off;
+ my $len = $cvn_to{$_}-$cvn_from{$_};
+ die unless substr($s, $from, $len) =~
+ /(\d+)$unit(\d*)|(\d+)([GMkmunpf])(\d*)/;
+
+ #
+ # Normalize to \d+.\d*
+ #
+ my $v = "$1$3.$2$5";
+ my $exp = $4 eq "" ? " " : $4;
+
+ #
+ # Remove leading zeroes.
+ #
+ $v =~ s/^0*(\d+)/\1/;
+
+ #
+ # Mantissa must be < 1000.
+ # Do the math as string operation to avoid rounding errors.
+ #
+ while ($v =~ /(\d+)(\d{3})\./) {
+ $v = "$1.$2$'";
+ $exp =~ tr/GMk munpf/TGMk munp/;
+ }
+
+ #
+ # Mantissa must be >= 1.
+ #
+ while ($v =~ /\b0\.(\d+)/) {
+ if (length $1 < 3) {
+ $v = $1.("0" x (3-length $1)).".";
+ } else {
+ $v = substr($1, 0, 3).".".substr($1, 3);
+ }
+ $exp =~ tr/GMk munpf/Mk munpa/;
+ }
+
+ #
+ # Remove trailing zeroes
+ #
+ $v =~ s/(\.[1-9]*)0*/\1/;
+
+ $exp =~ s/ //;
+ $v =~ s/\.$//;
+ $v = $v.$exp.$unit;
+ $off += length($v)-$len;
+ substr($s, $from, $len, $v);
+ }
+
+ #
+ # Run the second match on the string to process any (...) patterns
+ #
+ $found{$field} = $s;
+ die $m2 unless $s =~ $m2;
+ for (keys %+) {
+ $found{$_} = $+{$_};
+ }
+ return $s;
+}
+
+
+sub sub_expand
+{
+ local ($s) = @_;
+
+ while ($s =~ /^([^\$]*)\$([A-Za-z_]\w*)(:(\d+))?|^([^\$]*)\${([A-Za-z_]\w*)(:(\d+))?}/) {
+ my $name = "$2$6";
+ $name .= "__$4$8" if defined($4) || defined($8);
+ die "don't know \"$name\"" unless defined $found{$name};
+ $s = $1.$5.$found{$name}.$';
+ }
+ return $s;
+}
+
+
+#
+# return 0 if all rules have been exhausted, 1 if there was an explicit halt.
+#
+
+sub apply_rules
+{
+ RULE: for (my $i = 0; $i <= $#match; $i++) {
+ print STDERR "RULE #$i\n" if $debug;
+ %found = %field;
+ FIELD: for my $f (keys %{ $match[$i] }) {
+ my @f = $f ne "FN" ? ($f) :
+ ("F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9");
+ for (@f) {
+ print STDERR " MATCH $_=$match[$i]{$f}[0] " if $debug;
+ if (!defined $found{$_}) {
+ print STDERR "NO FIELD\n" if $debug;
+ next;
+ }
+ print STDERR "FIELD $found{$_} " if $debug;
+ if (!defined &sub_match($found{$_}, $f,
+ $match[$i]{$f}[1], $match[$i]{$f}[2])) {
+ print STDERR "MISS\n" if $debug;
+ next;
+ }
+ print STDERR "MATCH\n" if $debug;
+ next FIELD;
+ }
+ next RULE;
+ }
+ for (keys %{ $action[$i] }) {
+ my $s = &sub_expand($action[$i]{$_});
+ print STDERR " SET $_=$action[$i]{$_} => $s\n" if $debug;
+ $field{$_} = $s;
+ }
+ if ($end[$i]) {
+ print STDERR " END\n" if $debug;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+return 1;
Copied: trunk/eda/boom/misc.pl (from rev 5819, trunk/gta02-core/bom/misc.pl)
===================================================================
--- trunk/eda/boom/misc.pl (rev 0)
+++ trunk/eda/boom/misc.pl 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+
+#
+# determine the equivalent parts, taking into account that %eq is transitive
+#
+
+sub eq
+{
+ my %seen;
+ my @p = @_; # parts to consider
+ my @r = (); # new equivalences we've found
+ my $skip = @p;
+
+ while (@p) {
+ my $p = shift @p;
+ next if $seen{$p};
+ $seen{$p} = 1;
+ push(@r, $p) if $skip-- <= 0;
+ push(@p, @{ $eq{$p} });
+ }
+ return @r;
+}
+
+
+return 1;
Added: trunk/eda/boom/pardup.pl
===================================================================
--- trunk/eda/boom/pardup.pl (rev 0)
+++ trunk/eda/boom/pardup.pl 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+while (<>) {
+ @f = split(/\s+/);
+ $ref = shift @f;
+ for ($i = 0; $i != @f; $i++) {
+ next unless $f[$i] eq "FIC" || $f[$i] eq "MISSING" ||
+ $f[$i] eq "DIGI-KEY";
+ splice(@f, $i, 2);
+ $i--;
+ }
+ next if @f < 3;
+ push(@{ $multi{join(" ", @f)} }, $ref);
+}
+for (sort keys %multi) {
+ print "$_ -- ", join(" ", @{ $multi{$_} }), "\n";
+}
Property changes on: trunk/eda/boom/pardup.pl
___________________________________________________________________
Name: svn:executable
+ *
Copied: trunk/eda/boom/parser.pl (from rev 5825, trunk/gta02-core/bom/parser.pl)
===================================================================
--- trunk/eda/boom/parser.pl (rev 0)
+++ trunk/eda/boom/parser.pl 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,392 @@
+#!/usr/bin/perl
+
+use re 'eval';
+
+
+sub skip
+{
+ # do nothing
+}
+
+
+#
+# "bom" populates the following global variable:
+#
+# $cmp{component-reference}[0] = value
+# $cmp{component-reference}[1] = footprint
+# $cmp{component-reference}[2] = field1
+# ...
+#
+
+sub bom
+{
+ if (/^#End Cmp/) {
+ $mode = *skip;
+ return;
+ }
+ die unless /^\|\s+(\S+)\s+/;
+ my $ref = $1;
+ my @f = split(/\s*;\s*/, $');
+ next if $f[0] eq "NC";
+ $cmp{$ref} = [ @f ];
+}
+
+
+#
+# "equ" populates the following global variables:
+#
+# $id{item-number} = "namespace item-number"
+# This is used for heuristics that look up parts commonly referred to by
+# their part number.
+#
+# $eq{"namespace0 item-number0"}[] = ("namespace1 item-number1", ...)
+# List of all parts a given part is equivalent to.
+#
+
+sub equ
+{
+ my @f = split(/\s+/);
+ my $a = "$f[0] $f[1]";
+ my $b = "$f[2] $f[3]";
+ $id{$f[1]} = $a;
+ $id{$f[3]} = $b;
+ push @{ $eq{$a} }, $b;
+ push @{ $eq{$b} }, $a;
+}
+
+
+#
+# "inv" populates the following global variables:
+#
+# $id{item-number} = "namespace item-number"
+# This is used for heuristics that look up parts commonly referred to by
+# their part number.
+#
+# $inv{"namespace item-number"}[0] = items-in-stock
+# $inv{"namespace item-number"}[1] = currency
+# $inv{"namespace item-number"}[2] = order-quantity
+# $inv{"namespace item-number"}[3] = unit-price
+# [2] and [3] may repeat.
+#
+
+sub inv
+{
+ my @f = split(/\s+/);
+ my $id = "$f[0] $f[1]";
+ shift @f;
+ my $ref = shift @f;
+ die "duplicate inventory entry for \"$id\"" if defined $inv{$id};
+ $id{$ref} = $id;
+ $inv{$id} = [ @f ];
+ $inv{$id}[0] = 999999 unless defined $inv{$id}[0];
+ $inv{$id}[1] = "N/A" unless defined $inv{$id}[1];
+ $inv{$id}[2] = 1 unless defined $inv{$id}[2];
+ $inv{$id}[3] = 999999 unless defined $inv{$id}[3];
+}
+
+
+#
+# "par" populates the following global variables:
+#
+# $parts{component-ref}[0] = namespace
+# $parts{component-ref}[1] = item-number
+# [0] and [1] may repeat
+#
+# $want{"namespace item"} = number of times we may use the part. If multiple
+# parts are eligible for a component, each of them is counted as desirable
+# for each component.
+#
+# $comps{"namespace item"}{component-ref} = 1
+# Set of components a part may be used for.
+#
+
+sub par
+{
+ my @f = split(/\s+/);
+ my $ref = shift @f;
+ $parts{$ref} = [ @f ];
+ while (@f) {
+ my @id = splice(@f, 0, 2);
+ my $id = "$id[0] $id[1]";
+ $want{$id}++;
+ $comps{$id}{$ref} = 1;
+ }
+}
+
+
+#
+# "chr" populates the following global variable:
+#
+# $chr{"namespace item-number"}{parameter} = value
+#
+# $last is used internally for continuation lines.
+#
+
+sub chr
+{
+ my @f;
+ if (/^\s+/) {
+ @f = split(/\s+/, $');
+ } else {
+ @f = split(/\s+/);
+ my $ref = shift @f;
+ my $num = shift @f;
+ $last = "$ref $num";
+ }
+ for (@f) {
+ die "\"=\" missing in $_" unless /=/;
+ $chr{$last}{uc($`)} = $';
+ }
+}
+
+
+#
+# "sub" populates the following global variables:
+#
+# $end[rule-number] = 0 / 1
+# $match[rule-number]{field}[0] = original-pattern
+# $match[rule-number]{field}[1] = RE1
+# $match[rule-number]{field}[2] = RE2
+# $action[rule-number]{field} = value
+#
+# $match_stack[depth]{field}[0] = original-pattern
+# $match_stack[depth]{field}[1] = RE1
+# $match_stack[depth]{field}[2] = RE2
+# $action_stack[depth]{field} = value
+# $may_cont = 0 / 1
+# $last
+# $last_action
+#
+
+#
+# $cvn_from{internal-handle} = index
+# $cvn_to{internal-handle} = index
+# $cvn_unit{internal-handle} = unit-name
+# $cvn_num = internal-handle
+# $found{field-or-subfield} = string
+
+
+sub sub_pattern
+{
+ local ($field, $p) = @_;
+ my $n = 0;
+ $p =~ s/\./\\./g;
+ $p =~ s/\+/\\+/g;
+ $p =~ s/\?/./g;
+ $p =~ s/\*/.*/g;
+ my $tmp = "";
+ while ($p =~ /^([^\(]*)\(/) {
+ $n++;
+ $tmp .= "$1(?'${field}__$n'";
+ $p = $';
+ }
+ $p = "^".$tmp.$p."\$";
+ my $q = $p;
+ while ($p =~ /^([^\$]*)\$(.)/) {
+ $p = "$1(\\d+$2\\d*|\\d+[GMkmunpf$2]\\d*)(?{ &__cvn($cvn_num); })$'";
+ $cvn_unit{$cvn_num} = $2;
+ die unless $q =~ /^([^\$]*)\$(.)/;
+ $q = "$1(\\d+(\.\\d+)?[GMkmunpf]?$2)$'";
+ $cvn_num++;
+ }
+ return ($p, $q);
+}
+
+
+sub sub_value
+{
+ return $_[0];
+}
+
+
+sub sub
+{
+ /^(\s*)/;
+ my $indent = $1;
+ my @f = split(/\s+/, $');
+ my $f;
+ my $in = 0; # indentation level
+ while (length $indent) {
+ my $c = substr($indent, 0, 1, "");
+ if ($c eq " ") {
+ $in++;
+ } elsif ($c eq "\t") {
+ $in = ($in+8) & ~7;
+ } else {
+ die;
+ }
+ }
+ if ($may_cont && $in > $last) {
+ pop(@match);
+ pop(@action);
+ pop(@end);
+ } else {
+ $match_stack[0] = undef;
+ $action_stack[0] = undef;
+ $last_action = 0;
+ $last = $in;
+ }
+ if (!$last_action) {
+ while (@f) {
+ $f = shift @f;
+ last if $f eq "->" || $f eq "{" || $f eq "}" || $f eq "!";
+ if ($f =~ /=/) {
+ $match_stack[0]{uc($`)} = [ $', &sub_pattern(uc($`), $') ];
+ } else {
+ $match_stack[0]{"REF"} = [ &sub_pattern("REF", $f) ];
+ }
+ }
+ $last_action = 1 if $f eq "->";
+ }
+ if ($last_action) {
+ while (@f) {
+ $f = shift @f;
+ last if $f eq "{" || $f eq "!";
+ die unless $f =~ /=/;
+ $action_stack[0]{uc($`)} = &sub_value($');
+ }
+ }
+ $may_cont = 0;
+ if ($f eq "{") {
+ unshift(@match_stack, undef);
+ unshift(@action_stack, undef);
+ die "items following {" if @f;
+ } elsif ($f eq "}") {
+ shift @match_stack;
+ shift @action_stack;
+ die "items following }" if @f;
+ } else {
+ die "items following !" if @f && $f eq "!";
+ push(@end, $f eq "!");
+ $may_cont = $f ne "!";
+ my $n = $#end;
+ push(@match, undef);
+ push(@action, undef);
+ for my $m (reverse @match_stack) {
+ for (keys %{ $m }) {
+ $match[$n]{$_} = $m->{$_};
+ }
+ }
+ for my $a (reverse @action_stack) {
+ for (keys %{ $a }) {
+ $action[$n]{$_} = $a->{$_};
+ }
+ }
+ }
+}
+
+
+#
+# "ord" populates the following global variables:
+#
+# $order{"namespace item-number"}[0] = quantity to order
+# $order{"namespace item-number"}[1] = currency
+# $order{"namespace item-number"}[2] = total cost in above currency
+# $order{"namespace item-number"}[3] = component reference
+# ...
+#
+
+sub ord
+{
+ my @f = split(/\s+/);
+ my @id = splice(@f, 0, 2);
+ @{ $order{"$id[0] $id[1]"} } = @f;
+}
+
+
+#
+# "dsc" populates the following global variable:
+#
+# $dsc{"namespace item-number"} = description
+#
+
+sub dsc
+{
+ my @f = split(/\s+/);
+ my @id = splice(@f, 0, 2);
+ $dsc{"$id[0] $id[1]"} = join(" ", @f);
+}
+
+
+#
+# "eeschema" populates the following global variable:
+#
+# $eeschema[] = line
+#
+
+
+sub eeschema
+{
+ push(@eeschema, $_[0]);
+ if ($_[0] =~ /^\$EndSCHEMATC/) {
+ $mode = *skip;
+ undef $raw;
+ }
+}
+
+
+sub parse
+{
+ $mode = *skip;
+ while (<>) {
+ chop;
+ if (/^#Cmp.*order = Reference/) {
+ $mode = *bom;
+ next;
+ }
+ if (/^#Cmp.*order = Value/) {
+ $mode = *skip;
+ next;
+ }
+ if (/^eeschema \(/) { # hack to allow loading in any order
+ $mode = *skip;
+ next;
+ }
+ if (/^EESchema Schematic/) {
+ $mode = *eeschema;
+ $raw = 1;
+ die "only one schematic allowed" if defined @eeschema;
+ &eeschema($_);
+ next;
+ }
+ if (/^#EQU\b/) {
+ $mode = *equ;
+ next;
+ }
+ if (/^#INV\b/) {
+ $mode = *inv;
+ next;
+ }
+ if (/^#PAR\b/) {
+ $mode = *par;
+ next;
+ }
+ if (/^#CHR\b/) {
+ $mode = *chr;
+ undef $last;
+ next;
+ }
+ if (/^#(SUB|GEN)\b/) {
+ $mode = *sub;
+ undef $last;
+ undef $last_action;
+ undef $may_cont;
+ next;
+ }
+ if (/^#ORD\b/) {
+ $mode = *ord;
+ next;
+ }
+ if (/^#DSC\b/) {
+ $mode = *dsc;
+ next;
+ }
+ if (!$raw) {
+ s/#.*//;
+ next if /^\s*$/;
+ }
+ &$mode($_);
+ }
+}
+
+return 1;
Copied: trunk/eda/boom/part2order (from rev 5819, trunk/gta02-core/bom/part2order)
===================================================================
--- trunk/eda/boom/part2order (rev 0)
+++ trunk/eda/boom/part2order 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,133 @@
+#!/usr/bin/perl
+
+require "parser.pl";
+require "misc.pl";
+
+$mult = shift(@ARGV);
+&parse;
+
+
+sub number
+{
+ local ($id) = @_;
+
+ my $s = $inv{$id}[0];
+ my $n = $want{$id}*$mult;
+ return $n < $s ? $n : $s;
+
+}
+
+
+#
+# The heuristics here aren't very nice. We give zero-cost stock priority over
+# any other stock, when we go by stock size up to the quantity we need. The
+# idea is to exhause local stock (zero-cost) first, then try to obtain the
+# parts with as few orders as possible.
+#
+# It would be better to have some sort of priority, so that we can express a
+# preference among stock we already own. Also, if non-zero-cost stock has widly
+# different prices, the smallest order cost may not be a good indicator of
+# which source we prefer.
+#
+# Furthermore, the algorithm doesn't consider the number of sources we use in
+# total or things like lead time, shipping cost, customs, etc.
+#
+
+sub rank
+{
+ local ($a, $b) = @_;
+
+ my $na = &number($a); # min(number wanted, available)
+ my $nb = &number($b);
+ my $pa = $inv{$a}[3]; # per unit price for smallest quantum
+ my $pb = $inv{$b}[3];
+
+#print STDERR "a=$a b=$b na=$na nb=$nb pa=$pa pb=$pb\n";
+ return 1 if $na && !$pa && $pb;
+ return -1 if $nb && $pa && !$pb;
+ return $na <=> $nb if $na != $nb;
+ return $pb <=> $pa;
+}
+
+
+for (keys %parts) {
+ $parts++;
+}
+
+print "#ORD\n";
+for (sort { &rank($b, $a) } keys %want) {
+ my $n = &number($_);
+ $n -= $n % $mult;
+ next unless $n;
+ my @f = @{ $inv{$_} };
+ my $max = shift @f;
+ my $currency = shift @f;
+ my @qty;
+ my @price;
+ my %index;
+ my $best_qty;
+ my $best_price = undef;
+ while (@f) {
+ my $q = shift @f;
+ my $p = shift @f;
+ if (defined $index{$q}) {
+ $price[$index{$q}] = $p;
+ } else {
+ push(@qty, $q);
+ push(@price, $p);
+ $index{$q} = $#qty;
+ # @@@ this fails if smaller quantities following a large quantity
+ # differ from the quantities preceding them. E.g., 1 10 100 25
+ # wouldn't yield correct results.
+ }
+ for (my $i = $#qty; $i >= 0; $i--) {
+ my $order = 0;
+ my $price = 0;
+ my $left = $n;
+ for (my $j = $#qty; $j >= $i; $j--) {
+ while ($left >= ($j == $i ? 1 : $qty[$j])) {
+ $left -= $qty[$j];
+ $order += $qty[$j];
+ $price += $price[$j]*$qty[$j];
+ }
+ }
+ next if $order > $max;
+ if (!defined $best_price || $price < $best_price) {
+ $best_price = $price;
+ $best_qty = $order;
+ }
+ }
+ }
+ next if !defined $best_price;
+ print "$_ $best_qty $currency $best_price";
+ my $id = $_;
+ while (keys %{ $comps{$id} }) {
+ last if $best_qty < $mult;
+ $best_qty -= $mult;
+ my $ref = (sort keys %{ $comps{$id} })[0];
+#print STDERR "$id: $ref + ", join("|", keys %{ $comps{$id} }), "\n";
+ my @f = @{ $parts{$ref} };
+ while (@f) {
+ my @id2 = splice(@f, 0, 2);
+ my $id2 = "$id2[0] $id2[1]";
+ $want{$id2}--;
+ delete $comps{$id2}{$ref};
+ }
+ print " $ref";
+ }
+ print "\n";
+}
+
+for my $id (sort { $want{$b} <=> $want{$a} } keys %want) {
+ next unless $want{$id};
+ print STDERR "$id";
+ for (&eq($id)) {
+# next unless $want{$_};
+ die "\n$_ ($want{$_}) vs. $id want ($want{$id})"
+ unless $want{$_} == $want{$id};
+ print STDERR " $_";
+ $want{$_} = 0;
+ }
+ print STDERR ": want $want{$id}\n";
+ $want{$id} = 0;
+}
Copied: trunk/eda/boom/prettyord (from rev 5820, trunk/gta02-core/bom/prettyord)
===================================================================
--- trunk/eda/boom/prettyord (rev 0)
+++ trunk/eda/boom/prettyord 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+
+require "parser.pl";
+require "misc.pl";
+
+&parse;
+
+$out[0][0] = "Pos";
+$out[1][0] = "Qty";
+$out[2][0] = "P/N";
+$out[3][0] = "Description";
+$out[4][0] = "Value";
+$out[5][0] = "";
+
+for (sort keys %order) {
+ push(@{ $out[0] }, ++$n);
+ push(@{ $out[1] }, $order{$_}[0]);
+ @f = split(/\s+/, $_);
+ push(@{ $out[2] }, $f[1]);
+ my $dsc = $dsc{$_};
+ if (!defined $dsc) {
+ for (&eq($_)) {
+ $dsc = $dsc{$_};
+ last if defined $dsc;
+ }
+ }
+ print STDERR "$_: no description\n" unless defined $dsc;
+ push(@{ $out[3] }, defined $dsc ? $dsc : "???");
+ push(@{ $out[4] }, $order{$_}[1]);
+ push(@{ $out[5] }, sprintf("%.2f", $order{$_}[2]));
+}
+
+for (@out) {
+ push(@max, 0);
+ for (@{ $_ }) {
+ $max[$#max] = length $_ if length $_ > $max[$#max];
+ }
+}
+
+for ($i = 0; $i <= $#{ $out[0] }; $i++) {
+ for ($j = 0; $j != 6; $j++) {
+ my $s = $out[$j][$i];;
+ print $s if $j == 2 || $j == 3 || $j == 4;
+ print " " x ($max[$j]-length $s);
+ print $s if $j == 0 || $j == 1 || $j == 5;
+ print " " unless $j == 5;
+ }
+ print "\n";
+}
Copied: trunk/eda/boom/test (from rev 5804, trunk/gta02-core/bom/test)
Copied: trunk/eda/boom/workflow.fig (from rev 5816, trunk/gta02-core/bom/workflow.fig)
===================================================================
--- trunk/eda/boom/workflow.fig (rev 0)
+++ trunk/eda/boom/workflow.fig 2010-02-07 14:33:40 UTC (rev 5827)
@@ -0,0 +1,147 @@
+#FIG 3.2 Produced by xfig version 3.2.5a
+Landscape
+Center
+Metric
+A4
+100.00
+Single
+-2
+1200 2
+6 450 5850 3150 6525
+4 0 0 50 -1 14 12 0.0000 4 180 2700 450 6030 Source file (in SVN)\001
+4 0 0 50 -1 12 12 0.0000 4 150 1890 450 6255 Generated file\001
+4 0 0 50 -1 18 12 0.0000 4 210 1830 450 6480 Program (in SVN)\001
+-6
+6 450 7875 6480 9000
+4 0 0 50 -1 12 12 0.0000 4 105 540 450 8055 .csv\001
+4 0 0 50 -1 12 12 0.0000 4 150 540 450 8280 .inv\001
+4 0 0 50 -1 12 12 0.0000 4 150 540 450 8505 .equ\001
+4 0 0 50 -1 12 12 0.0000 4 150 540 450 8730 .par\001
+4 0 0 50 -1 12 12 0.0000 4 150 540 450 8955 .ord\001
+4 0 0 50 -1 1 12 0.0000 4 195 2520 1350 8280 inventory with stock and cost\001
+4 0 0 50 -1 1 12 0.0000 4 195 3045 1350 8055 GTA02 EE component stock at FIC\001
+4 0 0 50 -1 1 12 0.0000 4 195 5130 1350 8505 part number equivalences, e.g., manufacturer vs. distributor\001
+4 0 0 50 -1 1 12 0.0000 4 195 2910 1350 8730 component to part number(s) map\001
+4 0 0 50 -1 1 12 0.0000 4 195 5025 1350 8955 list of parts to order, with price and component references\001
+-6
+6 450 7425 3465 7875
+4 0 0 50 -1 12 12 0.0000 4 150 540 450 7605 .chr\001
+4 0 0 50 -1 12 12 0.0000 4 150 540 450 7830 .sub\001
+4 0 0 50 -1 1 12 0.0000 4 195 1695 1350 7605 part characteristics\001
+4 0 0 50 -1 1 12 0.0000 4 195 2085 1350 7830 parameter substitutions\001
+-6
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
+ 1 1 2.00 60.00 60.00
+ 7875 2700 7875 2925 6525 2925 6525 4725
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
+ 1 1 2.00 60.00 60.00
+ 9000 2700 9000 5850 6525 5850 6525 6075
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
+ 1 1 2.00 60.00 60.00
+ 3150 1350 3150 5850 6075 5850 6075 6075
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 6300 2700 6300 4725
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 6300 2025 6300 2475
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 6300 1350 6300 1800
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
+ 1 1 2.00 60.00 60.00
+ 4950 1350 4950 4275 6075 4275 6075 4725
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
+ 1 1 2.00 60.00 60.00
+ 3150 4500 5850 4500 5850 4725
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
+ 1 1 2.00 60.00 60.00
+ 8100 4275 8100 4500 6750 4500 6750 4725
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
+ 11700 1575 11700 3150 10170 3150
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 6300 4950 6300 5400
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 6300 5625 6300 6075
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 6300 6300 6300 6750
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 6300 6975 6300 7425
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 6525 7650 6525 8100
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 9000 1350 9000 1800
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
+ 1 1 2.00 60.00 60.00
+ 9000 1575 7875 1575 7875 1800
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
+ 1 1 2.00 60.00 60.00
+ 9000 1575 10125 1575 10125 1800
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 7875 2025 7875 2475
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 9000 2025 9000 2475
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 7875 2925 7875 3375
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
+ 1 1 2.00 60.00 60.00
+ 8955 3150 8325 3150 8325 3375
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 8100 3600 8100 4050
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 10125 2025 10125 2475
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
+ 1 1 2.00 60.00 60.00
+ 10125 2700 10125 7200 6750 7200 6750 7425
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 60.00 60.00
+ 8955 4500 8100 4500
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+ 9045 3150 10080 3150
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
+ 11700 4050 11700 4500 10170 4500
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+ 10080 4500 9045 4500
+4 0 0 50 -1 2 16 0.0000 4 255 3345 450 675 BOM Processing - Workflow\001
+4 1 0 50 -1 12 12 0.0000 4 195 1890 6300 2655 gta02-core.lst\001
+4 1 0 50 -1 18 12 0.0000 4 165 1035 6300 1980 eeschema\001
+4 1 0 50 -1 14 12 0.0000 4 150 675 6300 1305 *.sch\001
+4 1 0 50 -1 18 12 0.0000 4 210 990 6300 4905 bom2part\001
+4 1 0 50 -1 18 12 0.0000 4 210 1110 6300 6255 part2order\001
+4 1 0 50 -1 12 12 0.0000 4 195 1890 6300 6930 gta02-core.ord\001
+4 1 0 50 -1 12 12 0.0000 4 195 1890 6300 5580 gta02-core.par\001
+4 1 0 50 -1 14 12 0.0000 4 195 1890 4950 1305 gta02-core.sub\001
+4 1 0 50 -1 14 12 0.0000 4 195 1890 3105 1305 gta02-core.inv\001
+4 1 0 50 -1 18 12 0.0000 4 210 975 6525 7605 prettyord\001
+4 1 0 50 -1 18 12 0.0000 4 165 1095 7875 1980 fic2vendor\001
+4 1 0 50 -1 18 12 0.0000 4 165 675 9000 1980 fic2inv\001
+4 1 0 50 -1 18 12 0.0000 4 210 855 8100 3555 gen2chr\001
+4 1 0 50 -1 12 12 0.0000 4 150 675 8100 4230 *.chr\001
+4 1 0 50 -1 12 12 0.0000 4 195 945 7875 2655 fic.equ\001
+4 1 0 50 -1 12 12 0.0000 4 150 945 9000 2655 fic.inv\001
+4 1 0 50 -1 18 12 0.0000 4 165 735 10125 1980 fic2dsc\001
+4 1 0 50 -1 14 12 0.0000 4 195 2700 9000 1305 inventory-fic-ee.csv\001
+4 0 0 50 -1 12 12 0.0000 4 150 540 450 7155 .lst\001
+4 0 0 50 -1 1 12 0.0000 4 195 2220 1350 7155 BOM generated by KiCad\001
+4 0 0 50 -1 12 12 0.0000 4 150 540 450 6930 .sch\001
+4 0 0 50 -1 1 12 0.0000 4 195 2010 1350 6930 schematics (for KiCad)\001
+4 0 0 50 -1 12 12 0.0000 4 150 540 450 7380 .gen\001
+4 0 0 50 -1 1 12 0.0000 4 195 2745 1350 7380 characteristics generation rules\001
+4 0 0 50 -1 12 12 0.0000 4 150 540 450 9180 .dsc\001
+4 0 0 50 -1 1 12 0.0000 4 195 2685 1350 9180 Textual component description\001
+4 1 0 50 -1 14 12 0.0000 4 180 675 11700 1305 *.gen\001
+4 1 0 50 -1 14 12 0.0000 4 150 675 11700 3780 *.chr\001
+4 1 0 50 -1 14 9 0.0000 4 135 1440 11700 4005 (acx, misc, ...)\001
+4 1 0 50 -1 14 9 0.0000 4 135 1800 11700 1530 (darfon, ralec, ...)\001
+4 1 0 50 -1 12 12 0.0000 4 150 945 10125 2655 fic.dsc\001
Deleted: trunk/gta02-core/bom/CHARACTERISTICS
===================================================================
--- trunk/gta02-core/bom/CHARACTERISTICS 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/CHARACTERISTICS 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,140 +0,0 @@
-*** This is an older draft of the concept - differs sometimes from the way
- things are done in gta02-core. ***
-
-
-BOM matching
-============
-
-BOMs are matched with inventories in the following way:
-
-- a .lst file with the BOM is generated by KiCad
-
-- using a ruleset, component characteristics are translated to a
- canonical format and default values may be used for unspecified
- characteristics
-
-- part catalogs are searched for matches with the canonical component
- descriptions. This yields a list of supplier-specific part numbers
- for each component.
-
- Parts can be characterized by either specifying their properties or
- by equating them to another part. E.g., a Digi-Key part may be
- defined as an NXP part which in turn is equivalent to a TI part.
-
-- this list is then matched against inventories, using a suitable
- optimization strategy (e.g., prioritize inventories and try to
- pick as many suitable components as possible higher priority ones
- before moving to lower priority ones)
-
- E.g., local stock could be the first-level inventory, followed by
- more distant warehouses, followed by distributors, followed by
- manufacturers.
-
- Inventories could also include pricing information.
-
-- TBD: it would be good if parameters gathered in the matching process
- could be fed back into KiCad (as some sort of annotations, similar
- to the expanded view of schematic symbols), such that under-specifed
- parts yielding mismatches can be spotted by manual review.
-
-
-Catalog
-=======
-
-A catalog contains part characteristics and the reference number(s)
-assigned to them.
-
-
-Basic syntax
-------------
-
-Catalog entries consist of "words" in the sense that each word does
-not contain any whitespace and words are separated from each other by
-whitespace. Whitespace can be included in a word if it is enclosed in
-double quotes.
-
-Each entry begins in the first column of a line. If an entry needs
-more than one line, the words on the continuation line(s) must be
-indented by whitespace.
-
-Trailing whitespace is ignored, and so are comments beginning with a
-hash mark. Blank lines end any entry and are also ignored.
-
-Each catalog entry begins with the part number followed by a part type
-designator.
-
-Characteristics have the form <field>=<value>, where
-the fields follow the pattern outlined below. The value is some
-description of the value of that characteristic, typically a number
-and a unit (e.g., 4.7uF) or a name (e.g., X5R).
-
-Numbers use a decimal point where necessary. Mantissas are normalized
-such that they fall into the range 1 <= n < 1000. E.g., instead of
-0.1uF, write 100nF. There is no space between number and unit. The
-Omega of Ohm is written as "R".
-
-
-Fields
-------
-
-Each
-
-General fields
-- - - - - - -
-
-FP Footprint
-H Height (overrides any height implied by footprint)
-TOL Tolerance, with percent sign. Split tolerances are indicated as n/m%
-DSC Free-format description
-
-
-Resistors
-- - - - -
-
-RES Part type designator
-R Resistance, with unit
-P Maximum power dissipation
-V Maximum volatage
-
-
-Capacitors
-- - - - -
-
-CAP Part type designator
-C Capacitance, with unit
-M Material, e.g., TANT, NP0, X5R, etc.
-V Maximum voltage
-ESR ESR, with unit
-
-
-Inductors
--- - - -
-
-Diodes
-- - -
-
-DIODE Regular diode
-STKY Schottky diode
-
-Vf Maximum forward voltage
-Vr Maximum reverse voltage
-If Maximum forward current
-Ir Maximum reverse current
-C Capacitance
-
-LED Ligh-emitting diode
-
-COL Color, multiple colors are separated by /, e.g., blue/red
-ARRAY If multiple diodes form an array, this parameter describes
- its structure: CA = common anode, CC = common cathode,
- SEQ = tap-A-C-tap-A-C-tap sequence
-
-ZENER Zener diode
-
-Vz Zener voltage
-
-TVS Transient voltage suppressor
-
-Vac Working voltage, AC
-Vdc Working voltage, DC
-E Energy
Modified: trunk/gta02-core/bom/Makefile
===================================================================
--- trunk/gta02-core/bom/Makefile 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/Makefile 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,37 +1,37 @@
UPLOAD=werner at sita.openmoko.org:public_html/gta02-core/
COPY=rsync -e ssh --progress
+BOOM=../../eda/boom/boom
+
KITS=20
EQU=fic/fic.equ fic/missing.equ digi-key.equ
INV=fic/fic.inv gta02-core.inv dummy.inv fic/missing.inv digi-key.inv
CHR=darfon.chr ralec.chr avx.chr acx.chr misc.chr
SCH=audio bt cpu-power cpu gps io lcm memory modem pmu sd-sim usb wlan
-.PHONY: all spotless upload show-dup show-missing show-dk
+.PHONY: all spotless show-dup show-missing show-dk
# mark them as phony since we have incomplete dependencies in this Makefile
.PHONY: fic/fic.equ fic/fic.inv fic/missing.equ
-.PHONY: ann sch gen generate gv xpdf
+.PHONY: ann sch gen generate gv xpdf upload
all: gta02-core.ord
-gta02-core.ord: part2order parser.pl \
- gta02-core.par $(INV) $(EQU)
- perl part2order $(KITS) \
+gta02-core.ord: gta02-core.par $(INV) $(EQU)
+ $(BOOM) part2order $(KITS) \
$(INV) $(EQU) gta02-core.par >$@ || \
{ rm -rf $@; exit 1; }
-gta02-core.par: bom2part parser.pl match.pl \
- $(EQU) $(INV) $(CHR) ../gta02-core.lst gta02-core.sub
- perl bom2part $(EQU) $(INV) $(CHR) \
+gta02-core.par: $(EQU) $(INV) $(CHR) ../gta02-core.lst gta02-core.sub
+ $(BOOM) bom2part $(EQU) $(INV) $(CHR) \
../gta02-core.lst gta02-core.sub \
>$@ || { rm -rf $@; exit 1; }
-darfon.chr: gen2chr parser.pl match.pl fic/fic.equ darfon.gen
- perl gen2chr DARFON fic/fic.equ darfon.gen >$@ || \
+darfon.chr: fic/fic.equ darfon.gen
+ $(BOOM) gen2chr DARFON fic/fic.equ darfon.gen >$@ || \
{ rm -f $@; exit 1; }
-ralec.chr: gen2chr parser.pl match.pl fic/fic.equ ralec.gen
- perl gen2chr RALEC fic/fic.equ ralec.gen >$@ || \
+ralec.chr: fic/fic.equ ralec.gen
+ $(BOOM) gen2chr RALEC fic/fic.equ ralec.gen >$@ || \
{ rm -f $@; exit 1; }
fic/fic.equ:
@@ -46,43 +46,34 @@
fic/missing.equ:
$(MAKE) -C fic missing.equ
-workflow.pdf: workflow.fig
- fig2dev -L pdf $< >$@ || { rm -f $@; exit 1; }
-
-xpdf: workflow.pdf
- xpdf workflow.pdf
-
-upload: workflow.pdf
- $(COPY) workflow.pdf $(UPLOAD)/bom-workflow.pdf
-
spotless:
$(MAKE) -C fic spotless
rm -f gta02-core.par gta02-core.ord darfon.chr ralec.chr
rm -f gta02-core-bom.pro gta02-core-bom.sch $(SCH:%=%-bom.sch)
-show-dup: pardup.pl gta02-core.par
- perl ./pardup.pl gta02-core.par
+show-dup: gta02-core.par
+ $(BOOM) ./pardup.pl gta02-core.par
show-missing: $(EQU) fic/fic.dsc
(echo '#ORD'; grep MISSING gta02-core.ord ; ) | \
- ./prettyord - $(EQU) fic/fic.dsc | \
+ $(BOOM) prettyord - $(EQU) fic/fic.dsc | \
sed 's/^... \(.\{,78\}\).*/\1/'
show-dk:
(echo '#ORD'; grep DIGI-KEY gta02-core.ord ; ) | \
- ./prettyord - digi-key.dsc | \
+ $(BOOM) prettyord - digi-key.dsc | \
sed 's/^... //'
#ANN = pmu
ANN = audio
-ann: annotate ../$(ANN).sch fic/fic.dsc gta02-core.par $(EQU)
- perl ./annotate ../$(ANN).sch fic/fic.dsc gta02-core.par \
+ann: ../$(ANN).sch fic/fic.dsc gta02-core.par $(EQU)
+ $(BOOM) annotate ../$(ANN).sch fic/fic.dsc gta02-core.par \
$(EQU) >$(ANN)-bom.sch || { rm -f $(ANN)-bom.sch; exit 1; }
$(SCH:%=%-bom.sch): \
- annotate $(SCH:%=../%.sch) fic/fic.dsc gta02-core.par $(EQU)
+ $(SCH:%=../%.sch) fic/fic.dsc gta02-core.par $(EQU)
for n in $(SCH); do \
- perl ./annotate ../$$n.sch fic/fic.dsc gta02-core.par \
+ $(BOOM) annotate ../$$n.sch fic/fic.dsc gta02-core.par \
$(EQU) >$$n-bom.sch || { rm -f $$n-bom.sch; exit 1; }; \
done
Deleted: trunk/gta02-core/bom/README
===================================================================
--- trunk/gta02-core/bom/README 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/README 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,336 +0,0 @@
-The BOM processing system
-=========================
-
-The BOM processing system takes a bill of material generated by
-KiCad and converts it in various steps into a "shopping list"
-that can be used to order from various providers.
-
-
-Introduction
-============
-
-The following sections describe how to use the basic elements of
-the BOM processing system.
-
-
-A simple BOM translation
-------------------------
-
-KiCad identifies components by a so-called component reference,
-e.g., R1001, U5, etc. In addition to this, each component can have
-various parameters, such as a "value", its footprint, and further
-user-defined items. These parameters can be shown in the schematics
-(e.g., the value usually is) or they can be hidden (e.g., the
-footprint).
-
-At the end of the process, we want a "shopping list" that can be
-used to order items or to find them in an inventory or catalog.
-Components in the shopping list are identified by a part number.
-
-...
-- BOM
-- inventory
-- ID matching
-
-
-Equivalences
-------------
-
-A single component can be associated with multiple part numbers.
-For example, a chip its manufacturer calls "XYZ-R1" may be listed in
-a distributor's catalog with a completely different order number,
-such as "20-1234-8". The BOM processing system therefore
-distinguishes multiple so-called name spaces. A name space is
-identified by a (unique) name and a part number is generally
-qualified by the name of the name space.
-
-E.g., if the manufacturer is called "ACME" and the distributor of
-electronical components calls itself "DIST-EL", the part in our
-example may have the equivalent names "ACME XYZ-R1" and "DIST-EL
-20-1234-8".
-
-...
-- revise .inv
-
-example.equ:
-
-#INV
-DIST-EL 20-1234-8
-#EQU
-ACME XYZ-R1 DIST-EL 20-1234-8
-
-
-Adding stock and cost
----------------------
-
-- .inv, more fields
-- quanta
-
-Substituting component names
-----------------------------
-
-- intro to .sub
-- ad-hoc fixes
-
-
-Selecting characteristics
--------------------------
-
-- .sub
-- .chr
-...
-
-
-Generating characteristics
---------------------------
-
-- .gen
-
-
-Advanced topics
-===============
-
-- generating .inv files
-- different presentations (e.g., CT, TR, ...)
-- component substitution (one-way equivalence)
-- problem reports
-- hiding known problems (while sourcing)
-
-
-File formats
-============
-
-The BOM processing system uses a large number of different files to
-store information retrieved from the BOM, inventories, intermediate
-results, etc. The following sections describe the various formats.
-
-
-Part characteristics (.chr)
----------------------------
-
-A part characteristics file lists the parameters of components.
-This information is then matched with the parameters specified in
-the schematics.
-
-The part characteristics file begins with a line containing only
-#CHR
-
-After this, each line contains the manufacturer (namespace), the
-part number, and a list of parameter=value entries. Fields are
-separated by spaces.
-
-Long lines can be wrapped by indenting the continuation lines.
-
-Blank lines and comments (#) are ignored.
-
-
-Substitutions (.sub)
---------------------
-
-A substitutions file specifies rules for translating component
-parameters in schematics to part characteristics.
-
-A substitution rule consists of zero or more conditions and zero or
-more assignments. The conditions are of the form field=pattern. The
-field can be a per-component fields KiCad provides or any parameter
-set by substitutions.
-
-KiCad fields are named as follows:
-
-KiCad field Field name
------------ ----------
-Reference REF (*)
-Value VAL
-FP Footprint
-Field1 F1
-... ...
-
-(*) As a shortcut, REF= can be omitted.
-
-Note that fields with a user-defined name currently still only appear
-as F1, F2, etc.
-
-The special field name FN can be used to look for a match in all of
-F1, F2, ... This way, it's sufficient to use a consistent syntax for
-additional parameters, without having to assign also a fixed location
-for them. If more than one field matches, the first match is taken.
-
-Field names are case-insensitive.
-
-The pattern is uses a notation similar to filename globbing. There
-are the following special constructs:
-
-- * matches a string of any length
-- ? matches a single character
-- (...) matches the pattern between the parentheses and records the
- string matched
-- $X marks a value in nXn notation, e.g., 4u7 or 100R. Such values
- are converted to SI-like notation.
-
-A rule is applied when all conditions are fulfilled. In this case,
-assignments of the form field=value are executed. Strings obtained
-in the match can be included in a value as follows:
-
-- $field and ${field} are replaced by the respective field
-- $field:n and ${field:n} are replaced by the n-th (...) pattern in
- the match of the respective field
-
-If a rule ends with an exclamation mark, the substitution process stops
-after the rule is applied. Otherwise, further rules are processed.
-
-Examples:
-
-R* val=$R -> R=$val
-
-This rule translates the values of all resistors to SI notation.
-
-D* FN=(*)Vdc -> T=TSV Vdc=FN:1
-
-This rule sets the parameters T and Vdc for Zeners acting as TSVs.
-
-If a set of rules has a common set of conditions or assignments, the
-more compact block notation can be used instead of repeating them for
-each rule:
-
-common-conditions -> common-assignments {
- rule-specific-conditions -> rule-specific-assignments
- ...
-}
-
-Rules in a block only match if both the common and the rule-specific
-conditions are met. Then the common and the rule-specific assignments
-are performed. If a condition or an assignment appears both in the
-common and the rule-specific part, only the latter is used.
-
-Long lines can be wrapped by indenting the continuation lines. Note
-that { and ! are also considered to be part of the same line as the
-rest of the rule. In particular, the following construct wouldn't
-work:
-
-X=Y
-{
- ...
-}
-
-With proper indentation, this would:
-
-X=Y
- {
- ...
-}
-
-
-Characteristics generation (.gen)
----------------------------------
-
-The substitution mechanism can also be used to automatically generate
-characteristics from part numbers, e.g., for resistors or capacitors.
-
-.gen files are exactly .sub files, with the exception that the only
-field used is the REF field and that it contains the part number.
-
-Once the rule set has been processed, all fields (except REF) whose
-name doesn't begin with an underscore are placed in the characteristics
-entry as parameters.
-
-An entry is only produced if the rule set is explicitly terminated.
-
-
-Parts list (.par)
-------------------
-
-A parts file lists the parts that are suitable for a given BOM item.
-The file begins with a line containing only
-#PAR
-
-After this, each line contains the component reference, a space, and
-then one or more namespace part-number groups, separated by spaces as
-well.
-
-Blank lines and comments (#) are ignored.
-
-
-Order list (.ord)
------------------
-
-An order file lists the quantities to order from inventories, along
-with the cost and the component references the item is used for. The
-file begins with a line containing only
-#ORD
-
-After this, each line contains the supplier (namespace), the reference
-number, the number of items to order, the currency code, the cost,
-and one or more component references.
-
-Blank lines and comments (#) are ignored.
-
-
-Equivalence (.equ)
-------------------
-
-Equivalence files establish equivalences between parts numbers in the
-same or in different name spaces. An equivalence file begins with a
-line containing only
-#EQU
-
-After this, each line consists of the following four space-separated
-fields:
-
-namespace-1 part-number-1 namespace-2 part-number-2
-
-Blank lines and comments (#) are ignored.
-
-
-Inventory (.inv)
-----------------
-
-Inventory files list inventory and component cost. An inventory file
-begins with a line containing only
-#INV
-
-After this, each line contains the namespace and the part number,
-followed by the number of items in stock, the currency code, and one
-or more pricing entries.
-
-Each pricing entry consists of two fields: the number of items in an
-order, and the per item price at that quantity. A sequence of
-increasing order sizes indicates that they are quanta. A sequence of
-decreasing order sizes indicates that smaller quanta are possible
-after a previous larger threshold has been met.
-
-Example:
-
-... USD 1 0.5 10 0.4 100 0.2
-
-Means that an order of at least 170 units would be made either as
-2 * 100 units, costing USD 40, or as 1 * 100 + 7 * 10 units, costing
-USD 20 + USD 28 = USD 48.
-
-If the entry is
-
-... USD 1 0.5 10 0.4 100 0.2 1 0.2
-
-Then the USD 0.2 per unit cost would apply to any any quantity of at
-least 100 units. So a 170 units order would cost USD 34.
-
-Blank lines and comments (#) are ignored.
-
-The number of items in stock and the pricing data can be omitted. We
-call this "virtual inventory". In this case, the numer of items in
-stock and the price default to large numbers (e.g., 999999). Virtual
-inventory is used to suppress warnings for parts that have not been
-sourced yet, but where sourcing is in progress.
-
-
-Description (.dsc)
-------------------
-
-A description file contains plain text descriptions of parts. The file
-begins with a like containing only
-#DSC
-
-Each line contains the name space, a space, the part number, another
-space, and the description. The description can contain any printable
-character and ends with a newline.
-
-Blank lines and comments (#) are ignored.
Deleted: trunk/gta02-core/bom/annotate
===================================================================
--- trunk/gta02-core/bom/annotate 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/annotate 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,188 +0,0 @@
-#!/usr/bin/perl
-
-require "parser.pl";
-require "misc.pl";
-
-
-&parse;
-
-
-$H = 50; # character height
-$W = $H*0.9; # character width
-$L = $H+20; # line skip
-
-
-sub normalize
-{
- my @t = @_;
-
- # convert from (x0, y0, w, h) to (x0, y0, x1, y1)
- $t[2] += $t[0];
- $t[3] = $t[1]-$t[3];
- return ($t[0], $t[3], $t[2], $t[1]);
-}
-
-
-#
-# 2x2 matrix inversion
-# http://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_2.C3.972_matrices
-#
-
-sub invert
-{
- my @m = @_;
- my $f = 1/($m[0]*$m[3]-$m[1]*$m[2]);
- return ($f*$m[3], -$f*$m[1], -$f*$m[2], $f*$m[0]);
-}
-
-
-sub block
-{
- my @t = &normalize(@_);
- push(@block, [ @t ]);
- $wnl .= "Wire Notes Line\n\t$t[0] $t[1] $t[2] $t[3]\n";
-}
-
-
-sub pass
-{
- my @t = &normalize(@_);
-
- for (@block) {
- my @b = @{ $_ };
- next if $t[0] > $b[2];
- next if $t[2] < $b[0];
- next if $t[1] > $b[3];
- next if $t[3] < $b[1];
- return 0;
- }
- return 1;
-}
-
-
-sub put
-{
- local ($x0, $y0, $ref, @s) = @_;
-
- my $h = @s*$L;
- my $w = 0;
- for (@s) {
- my $t = $W*length $_;
- $w = $t if $t > $w;
- }
- my $a = 270;
- my $r = 100;
- my $x, $y;
- my $ym = $y0-$h+$H/2;
- for ($i = 0; $i != 128; $i++) {
- $x = int($x0+$r*cos($a/180*3.14159));
- $y = int($ym+$r*sin($a/180*3.14159));
- last if &pass($x, $y, $w, $h);
- $a += 22.5;
- $r += $L/8;
- }
- warn "no place found for \"$s[0]\"" if $i == 128;
-
- my @m = &invert( @{ $m{$ref} });
- &block($x, $y+$H/2, $w, $h);
- my $n = 10;
- for my $s (reverse @s) {
- my $dx = $x-$x0;
- my $dy = $y-$y0;
- my $sx = $x0+$dx*$m[0]+$dy*$m[1];
- my $sy = $y0+$dx*$m[2]+$dy*$m[3];
- ($hv, $hj, $vj) = ("H", "L", "C") if $m[0] == 1;
- ($hv, $hj, $vj) = ("H", "R", "C") if $m[0] == -1;
- ($hv, $hj, $vj) = ("V", "C", "B") if $m[1] == 1;
- ($hv, $hj, $vj) = ("V", "C", "T") if $m[1] == -1;
- $s =~ s/~/-/g;
- print "F $n \"$s\" $hv $sx $sy $H 0000 $hj ${vj}NN\n";
- $y -= $L;
- $n++;
- }
-}
-
-
-#
-# pass 1: find the orientation of all parts
-#
-
-for (@eeschema) {
- $ref = $1 if /^L \S+ (\S+)/;
- undef $ref if /^\$EndComp/;
- next unless /^\s+(-?[01])\s+(-?[01])\s+(-?[01])\s+(-?[01])\s*$/;
- my @m = split(/\s+/);
- shift @m;
- $m{$ref} = [ @m ];
-}
-
-
-#
-# pass 2: block the spaces occupied by fields
-#
-
-for (@eeschema) {
- $ref = $1 if /^L \S+ (\S+)/;
- if (/^P (\d+) (\d+)/) {
- $x0 = $1;
- $y0 = $2;
- }
- next unless /^F /;
- die "$_" unless
- /^F \d+ "([^"]*)" ([HV]) (\d+) (\d+) (\d+) +(\d+) ([LC]) (C)/;
- ($s, $hv, $x, $y, $size, $flag, $hj, $vj) =
- ($1, $2, $3, $4, $5, $6, $7, $8);
- $dx = $x-$x0;
- $dy = $y-$y0;
- $x = $x0+$dx*$m{$ref}[0]+$dy*$m{$ref}[1];
- $y = $y0+$dx*$m{$ref}[2]+$dy*$m{$ref}[3];
- next if $flag != 0;
- $w = $size*0.8*length $s;
- # we don't need to consider H/V
- &block($hj eq "L" ? $x : $x-$w/2, $y+$size/2, $w, $size);
-}
-
-#
-# pass 3:
-#
-
-for (@eeschema) {
- undef @f if /^\$Comp/;
- if (/^L \S+ (\S+)/) {
- $ref = $1;
- my @p = @{ $parts{$ref} };
- while (@p) {
- my @id = splice(@p, 0, 2);
- my $id = "$id[0] $id[1]";
- for ($id, &eq($id)) {
- next unless defined $dsc{$_};
- push(@f, $dsc{$_});
- last;
- }
- }
- }
- if (/^P (\d+) (\d+)/) {
- $x = $1;
- $y = $2;
- }
- if (/^\s+/) {
- my %seen;
- my @u = ();
- for (@f) {
- next if $seen{$_};
- push(@u, $_);
- $seen{$_} = 1;
- }
- undef @f;
- # $m{$ref}[0] == 1 OK
- # $m{$ref}[0] == -1 OK
- # $m{$ref}[1] == 1 OK
- # $m{$ref}[1] == -1 OK (small deviations found)
- &put($x, $y, $ref, @u) if 1 || $m{$ref}[1] == -1;
- }
- if (/\$EndSCHEMATC/) {
- # uncomment for debugging
-# print $wnl;
- }
- print "$_\n";
-}
Deleted: trunk/gta02-core/bom/bom2part
===================================================================
--- trunk/gta02-core/bom/bom2part 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/bom2part 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,92 +0,0 @@
-#!/usr/bin/perl
-
-require "parser.pl";
-require "match.pl";
-require "misc.pl";
-
-
-sub issue
-{
- print shift(@_), " ", join(" ", @_, &eq(@_)), "\n";
-}
-
-
-if ($ARGV[0] eq "-d") {
- $debug = 1;
- shift @ARGV;
-}
-&parse;
-
-$total = 0;
-$bad = 0;
-
-print "#PAR\n";
-for $ref (keys %cmp) {
- @f = @{ $cmp{$ref} };
- $total++;
-
- print STDERR "REF $ref\n" if $debug;
-
- # if we're lucky, we get a direct ID match
-
- if (defined $id{$f[0]}) {
- print STDERR "FIRST ID\n" if $debug;
- &issue($ref, $id{$f[0]});
- next;
- }
-
- # no such luck. Let's roll up our sleeves and to the substitutions.
-
- undef %field;
- $field{"REF"} = $ref;
- $field{"VAL"} = $f[0];
- if ($f[1] eq "") {
- print STDERR "warning: $ref ($f[0]) has no footprint\n";
- } else {
- $field{"FP"} = $f[1];
- }
- for (my $i = 1; $i != 10; $i++) {
- $field{"F$i"} = $f[$i+1];
- }
- &apply_rules();
-
- # try our luck again
-
- if (defined $id{$field{"VAL"}}) {
- print STDERR "SECOND ID\n" if $debug;
- &issue($ref, $id{$field{"VAL"}});
- next;
- }
-
- # still nothing. Let's match characteristics then.
-
- my @p = ();
- COMP: for my $c (keys %chr) {
- print STDERR "PART $c\n" if $debug;
- for (keys %field) {
- next if $_ eq "REF" || $_ eq "VAL" || $_ =~ /^F\d$/;
- print STDERR " $_=",$field{$_}," " if $debug;
- if (!defined $chr{$c}{$_}) {
- print STDERR "NO FIELD\n" if $debug;
- next COMP;
- next;
- }
- if ($chr{$c}{$_} eq $field{$_}) {
- print STDERR "== $chr{$c}{$_}\n" if $debug;
- } else {
- print STDERR "!= $chr{$c}{$_}\n" if $debug;
- next COMP;
- }
- }
- push(@p, $c);
- }
- if (@p) {
- &issue($ref, @p);
- next;
- }
-
- print STDERR "unmatched: $ref (", join(", ", @f), ")\n";
- $bad++;
-# print join("#", ($ref, @f)), " -> $id{$f[0]}\n";
-}
-print STDERR "$bad/$total unmatched\n" if $bad;
Modified: trunk/gta02-core/bom/fic/Makefile
===================================================================
--- trunk/gta02-core/bom/fic/Makefile 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/fic/Makefile 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,3 +1,5 @@
+BOOM=../../../eda/boom/boom
+
INV = inventory-fic-ee.csv
.PHONY: all spotless
@@ -17,7 +19,8 @@
grep -v ' 0 USD' fic.inv >present.inv || { rm -f $@; exit 1; }
missing.equ: equ2equ missing.inv fic.equ
- perl equ2equ missing.inv fic.equ >$@ || { rm -f $@; exit 1; }
+ $(BOOM) ./equ2equ missing.inv fic.equ >$@ || \
+ { rm -f $@; exit 1; }
spotless:
rm -f fic.equ fic.inv fic.dsc present.inv missing.equ
Modified: trunk/gta02-core/bom/fic/equ2equ
===================================================================
--- trunk/gta02-core/bom/fic/equ2equ 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/fic/equ2equ 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,6 +1,6 @@
#!/usr/bin/perl
-require '../parser.pl';
+require 'parser.pl';
&parse;
Deleted: trunk/gta02-core/bom/gen2chr
===================================================================
--- trunk/gta02-core/bom/gen2chr 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/gen2chr 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,35 +0,0 @@
-#!/usr/bin/perl
-
-require "parser.pl";
-require "match.pl";
-
-
-if ($ARGV[0] eq "-d") {
- $debug = 1;
- shift @ARGV;
-}
-if ($ARGV[0] eq "-n") {
- $negate = 1;
- shift @ARGV;
-}
-$key = shift @ARGV;
-&parse;
-
-print "#CHR\n";
-for (keys %id) {
- next unless $id{$_} eq "$key $_";
- undef %field;
- $field{"REF"} = $_;
- if (!&apply_rules()) {
- print "$id{$_}\n" if $negate;
- next;
- }
- next if $negate;
- print $id{$_};
- for (sort keys %field) {
- next if $_ =~ /^_/;
- next if $_ eq "REF";
- print " $_=$field{$_}";
- }
- print "\n";
-}
Deleted: trunk/gta02-core/bom/match.pl
===================================================================
--- trunk/gta02-core/bom/match.pl 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/match.pl 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,200 +0,0 @@
-#!/usr/bin/perl
-
-use re 'eval';
-
-
-#
-# "sub" populates the following global variables:
-#
-# $end[rule-number] = 0 / 1
-# $match[rule-number]{field}[0] = original-pattern
-# $match[rule-number]{field}[1] = RE1
-# $match[rule-number]{field}[2] = RE2
-# $action[rule-number]{field} = value
-#
-# $match_stack[depth]{field}[0] = original-pattern
-# $match_stack[depth]{field}[1] = RE1
-# $match_stack[depth]{field}[2] = RE2
-# $action_stack[depth]{field} = value
-# $may_cont = 0 / 1
-# $last
-# $last_action
-#
-
-#
-# $cvn_from{internal-handle} = index
-# $cvn_to{internal-handle} = index
-# $cvn_unit{internal-handle} = unit-name
-# $cvn_num = internal-handle
-# $found{field-or-subfield} = string
-
-
-#
-# We convert each input pattern into two regular expressions: the first matches
-# units in the nXn notation, e.g., 4u7 or 100R. The second matches them in SI
-# notation (sans space).
-#
-# When matching (sub_match), we first apply the first expression. Each time we
-# encounter a unit ($R, $F, etc.), __cvn is called. __cvn stores the index of
-# the unit in %cvn_from and %cvn_to.
-#
-# We then pick these substrings from the input string and convert the units to
-# SI notation. At the same time, we normalize the mantissa. Once done, we run
-# the second expression. This one always matches (hopefully :-)
-#
-# All (...) ranges in the original pattern have been replaced with named
-# capture buffers in the second expression, so all these subfields are now
-# gathered in the $+ array. (The same also happened in the first pass, but we
-# ignore it.)
-#
-# Finally, when expanding a value (sub_expand), we look for $field and
-# $field:index, and expand accordingly.
-#
-
-
-sub __cvn
-{
- local ($num) = @_;
-
- $cvn_from{$num} = $-[$#-];
- $cvn_to{$num} = $+[$#+];
-}
-
-
-sub sub_match
-{
- local ($s, $field, $m1, $m2) = @_;
-
- #
- # Perform the first match and record where we saw $<unit> patterns.
- #
- undef %cvn_from;
- undef %cvn_to;
- return undef unless $s =~ $m1;
-
- #
- # Convert the unit patterns to almost-SI notation. (We don't put a space
- # after the number, but the rest is SI-compliant.)
- #
- my $off = 0;
- for (keys %cvn_from) {
- my $unit = $cvn_unit{$_};
- my $from = $cvn_from{$_}+$off;
- my $len = $cvn_to{$_}-$cvn_from{$_};
- die unless substr($s, $from, $len) =~
- /(\d+)$unit(\d*)|(\d+)([GMkmunpf])(\d*)/;
-
- #
- # Normalize to \d+.\d*
- #
- my $v = "$1$3.$2$5";
- my $exp = $4 eq "" ? " " : $4;
-
- #
- # Remove leading zeroes.
- #
- $v =~ s/^0*(\d+)/\1/;
-
- #
- # Mantissa must be < 1000.
- # Do the math as string operation to avoid rounding errors.
- #
- while ($v =~ /(\d+)(\d{3})\./) {
- $v = "$1.$2$'";
- $exp =~ tr/GMk munpf/TGMk munp/;
- }
-
- #
- # Mantissa must be >= 1.
- #
- while ($v =~ /\b0\.(\d+)/) {
- if (length $1 < 3) {
- $v = $1.("0" x (3-length $1)).".";
- } else {
- $v = substr($1, 0, 3).".".substr($1, 3);
- }
- $exp =~ tr/GMk munpf/Mk munpa/;
- }
-
- #
- # Remove trailing zeroes
- #
- $v =~ s/(\.[1-9]*)0*/\1/;
-
- $exp =~ s/ //;
- $v =~ s/\.$//;
- $v = $v.$exp.$unit;
- $off += length($v)-$len;
- substr($s, $from, $len, $v);
- }
-
- #
- # Run the second match on the string to process any (...) patterns
- #
- $found{$field} = $s;
- die $m2 unless $s =~ $m2;
- for (keys %+) {
- $found{$_} = $+{$_};
- }
- return $s;
-}
-
-
-sub sub_expand
-{
- local ($s) = @_;
-
- while ($s =~ /^([^\$]*)\$([A-Za-z_]\w*)(:(\d+))?|^([^\$]*)\${([A-Za-z_]\w*)(:(\d+))?}/) {
- my $name = "$2$6";
- $name .= "__$4$8" if defined($4) || defined($8);
- die "don't know \"$name\"" unless defined $found{$name};
- $s = $1.$5.$found{$name}.$';
- }
- return $s;
-}
-
-
-#
-# return 0 if all rules have been exhausted, 1 if there was an explicit halt.
-#
-
-sub apply_rules
-{
- RULE: for (my $i = 0; $i <= $#match; $i++) {
- print STDERR "RULE #$i\n" if $debug;
- %found = %field;
- FIELD: for my $f (keys %{ $match[$i] }) {
- my @f = $f ne "FN" ? ($f) :
- ("F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9");
- for (@f) {
- print STDERR " MATCH $_=$match[$i]{$f}[0] " if $debug;
- if (!defined $found{$_}) {
- print STDERR "NO FIELD\n" if $debug;
- next;
- }
- print STDERR "FIELD $found{$_} " if $debug;
- if (!defined &sub_match($found{$_}, $f,
- $match[$i]{$f}[1], $match[$i]{$f}[2])) {
- print STDERR "MISS\n" if $debug;
- next;
- }
- print STDERR "MATCH\n" if $debug;
- next FIELD;
- }
- next RULE;
- }
- for (keys %{ $action[$i] }) {
- my $s = &sub_expand($action[$i]{$_});
- print STDERR " SET $_=$action[$i]{$_} => $s\n" if $debug;
- $field{$_} = $s;
- }
- if ($end[$i]) {
- print STDERR " END\n" if $debug;
- return 1;
- }
- }
- return 0;
-}
-
-
-return 1;
Deleted: trunk/gta02-core/bom/misc.pl
===================================================================
--- trunk/gta02-core/bom/misc.pl 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/misc.pl 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,26 +0,0 @@
-#!/usr/bin/perl
-
-
-#
-# determine the equivalent parts, taking into account that %eq is transitive
-#
-
-sub eq
-{
- my %seen;
- my @p = @_; # parts to consider
- my @r = (); # new equivalences we've found
- my $skip = @p;
-
- while (@p) {
- my $p = shift @p;
- next if $seen{$p};
- $seen{$p} = 1;
- push(@r, $p) if $skip-- <= 0;
- push(@p, @{ $eq{$p} });
- }
- return @r;
-}
-
-
-return 1;
Deleted: trunk/gta02-core/bom/parser.pl
===================================================================
--- trunk/gta02-core/bom/parser.pl 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/parser.pl 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,392 +0,0 @@
-#!/usr/bin/perl
-
-use re 'eval';
-
-
-sub skip
-{
- # do nothing
-}
-
-
-#
-# "bom" populates the following global variable:
-#
-# $cmp{component-reference}[0] = value
-# $cmp{component-reference}[1] = footprint
-# $cmp{component-reference}[2] = field1
-# ...
-#
-
-sub bom
-{
- if (/^#End Cmp/) {
- $mode = *skip;
- return;
- }
- die unless /^\|\s+(\S+)\s+/;
- my $ref = $1;
- my @f = split(/\s*;\s*/, $');
- next if $f[0] eq "NC";
- $cmp{$ref} = [ @f ];
-}
-
-
-#
-# "equ" populates the following global variables:
-#
-# $id{item-number} = "namespace item-number"
-# This is used for heuristics that look up parts commonly referred to by
-# their part number.
-#
-# $eq{"namespace0 item-number0"}[] = ("namespace1 item-number1", ...)
-# List of all parts a given part is equivalent to.
-#
-
-sub equ
-{
- my @f = split(/\s+/);
- my $a = "$f[0] $f[1]";
- my $b = "$f[2] $f[3]";
- $id{$f[1]} = $a;
- $id{$f[3]} = $b;
- push @{ $eq{$a} }, $b;
- push @{ $eq{$b} }, $a;
-}
-
-
-#
-# "inv" populates the following global variables:
-#
-# $id{item-number} = "namespace item-number"
-# This is used for heuristics that look up parts commonly referred to by
-# their part number.
-#
-# $inv{"namespace item-number"}[0] = items-in-stock
-# $inv{"namespace item-number"}[1] = currency
-# $inv{"namespace item-number"}[2] = order-quantity
-# $inv{"namespace item-number"}[3] = unit-price
-# [2] and [3] may repeat.
-#
-
-sub inv
-{
- my @f = split(/\s+/);
- my $id = "$f[0] $f[1]";
- shift @f;
- my $ref = shift @f;
- die "duplicate inventory entry for \"$id\"" if defined $inv{$id};
- $id{$ref} = $id;
- $inv{$id} = [ @f ];
- $inv{$id}[0] = 999999 unless defined $inv{$id}[0];
- $inv{$id}[1] = "N/A" unless defined $inv{$id}[1];
- $inv{$id}[2] = 1 unless defined $inv{$id}[2];
- $inv{$id}[3] = 999999 unless defined $inv{$id}[3];
-}
-
-
-#
-# "par" populates the following global variables:
-#
-# $parts{component-ref}[0] = namespace
-# $parts{component-ref}[1] = item-number
-# [0] and [1] may repeat
-#
-# $want{"namespace item"} = number of times we may use the part. If multiple
-# parts are eligible for a component, each of them is counted as desirable
-# for each component.
-#
-# $comps{"namespace item"}{component-ref} = 1
-# Set of components a part may be used for.
-#
-
-sub par
-{
- my @f = split(/\s+/);
- my $ref = shift @f;
- $parts{$ref} = [ @f ];
- while (@f) {
- my @id = splice(@f, 0, 2);
- my $id = "$id[0] $id[1]";
- $want{$id}++;
- $comps{$id}{$ref} = 1;
- }
-}
-
-
-#
-# "chr" populates the following global variable:
-#
-# $chr{"namespace item-number"}{parameter} = value
-#
-# $last is used internally for continuation lines.
-#
-
-sub chr
-{
- my @f;
- if (/^\s+/) {
- @f = split(/\s+/, $');
- } else {
- @f = split(/\s+/);
- my $ref = shift @f;
- my $num = shift @f;
- $last = "$ref $num";
- }
- for (@f) {
- die "\"=\" missing in $_" unless /=/;
- $chr{$last}{uc($`)} = $';
- }
-}
-
-
-#
-# "sub" populates the following global variables:
-#
-# $end[rule-number] = 0 / 1
-# $match[rule-number]{field}[0] = original-pattern
-# $match[rule-number]{field}[1] = RE1
-# $match[rule-number]{field}[2] = RE2
-# $action[rule-number]{field} = value
-#
-# $match_stack[depth]{field}[0] = original-pattern
-# $match_stack[depth]{field}[1] = RE1
-# $match_stack[depth]{field}[2] = RE2
-# $action_stack[depth]{field} = value
-# $may_cont = 0 / 1
-# $last
-# $last_action
-#
-
-#
-# $cvn_from{internal-handle} = index
-# $cvn_to{internal-handle} = index
-# $cvn_unit{internal-handle} = unit-name
-# $cvn_num = internal-handle
-# $found{field-or-subfield} = string
-
-
-sub sub_pattern
-{
- local ($field, $p) = @_;
- my $n = 0;
- $p =~ s/\./\\./g;
- $p =~ s/\+/\\+/g;
- $p =~ s/\?/./g;
- $p =~ s/\*/.*/g;
- my $tmp = "";
- while ($p =~ /^([^\(]*)\(/) {
- $n++;
- $tmp .= "$1(?'${field}__$n'";
- $p = $';
- }
- $p = "^".$tmp.$p."\$";
- my $q = $p;
- while ($p =~ /^([^\$]*)\$(.)/) {
- $p = "$1(\\d+$2\\d*|\\d+[GMkmunpf$2]\\d*)(?{ &__cvn($cvn_num); })$'";
- $cvn_unit{$cvn_num} = $2;
- die unless $q =~ /^([^\$]*)\$(.)/;
- $q = "$1(\\d+(\.\\d+)?[GMkmunpf]?$2)$'";
- $cvn_num++;
- }
- return ($p, $q);
-}
-
-
-sub sub_value
-{
- return $_[0];
-}
-
-
-sub sub
-{
- /^(\s*)/;
- my $indent = $1;
- my @f = split(/\s+/, $');
- my $f;
- my $in = 0; # indentation level
- while (length $indent) {
- my $c = substr($indent, 0, 1, "");
- if ($c eq " ") {
- $in++;
- } elsif ($c eq "\t") {
- $in = ($in+8) & ~7;
- } else {
- die;
- }
- }
- if ($may_cont && $in > $last) {
- pop(@match);
- pop(@action);
- pop(@end);
- } else {
- $match_stack[0] = undef;
- $action_stack[0] = undef;
- $last_action = 0;
- $last = $in;
- }
- if (!$last_action) {
- while (@f) {
- $f = shift @f;
- last if $f eq "->" || $f eq "{" || $f eq "}" || $f eq "!";
- if ($f =~ /=/) {
- $match_stack[0]{uc($`)} = [ $', &sub_pattern(uc($`), $') ];
- } else {
- $match_stack[0]{"REF"} = [ &sub_pattern("REF", $f) ];
- }
- }
- $last_action = 1 if $f eq "->";
- }
- if ($last_action) {
- while (@f) {
- $f = shift @f;
- last if $f eq "{" || $f eq "!";
- die unless $f =~ /=/;
- $action_stack[0]{uc($`)} = &sub_value($');
- }
- }
- $may_cont = 0;
- if ($f eq "{") {
- unshift(@match_stack, undef);
- unshift(@action_stack, undef);
- die "items following {" if @f;
- } elsif ($f eq "}") {
- shift @match_stack;
- shift @action_stack;
- die "items following }" if @f;
- } else {
- die "items following !" if @f && $f eq "!";
- push(@end, $f eq "!");
- $may_cont = $f ne "!";
- my $n = $#end;
- push(@match, undef);
- push(@action, undef);
- for my $m (reverse @match_stack) {
- for (keys %{ $m }) {
- $match[$n]{$_} = $m->{$_};
- }
- }
- for my $a (reverse @action_stack) {
- for (keys %{ $a }) {
- $action[$n]{$_} = $a->{$_};
- }
- }
- }
-}
-
-
-#
-# "ord" populates the following global variables:
-#
-# $order{"namespace item-number"}[0] = quantity to order
-# $order{"namespace item-number"}[1] = currency
-# $order{"namespace item-number"}[2] = total cost in above currency
-# $order{"namespace item-number"}[3] = component reference
-# ...
-#
-
-sub ord
-{
- my @f = split(/\s+/);
- my @id = splice(@f, 0, 2);
- @{ $order{"$id[0] $id[1]"} } = @f;
-}
-
-
-#
-# "dsc" populates the following global variable:
-#
-# $dsc{"namespace item-number"} = description
-#
-
-sub dsc
-{
- my @f = split(/\s+/);
- my @id = splice(@f, 0, 2);
- $dsc{"$id[0] $id[1]"} = join(" ", @f);
-}
-
-
-#
-# "eeschema" populates the following global variable:
-#
-# $eeschema[] = line
-#
-
-
-sub eeschema
-{
- push(@eeschema, $_[0]);
- if ($_[0] =~ /^\$EndSCHEMATC/) {
- $mode = *skip;
- undef $raw;
- }
-}
-
-
-sub parse
-{
- $mode = *skip;
- while (<>) {
- chop;
- if (/^#Cmp.*order = Reference/) {
- $mode = *bom;
- next;
- }
- if (/^#Cmp.*order = Value/) {
- $mode = *skip;
- next;
- }
- if (/^eeschema \(/) { # hack to allow loading in any order
- $mode = *skip;
- next;
- }
- if (/^EESchema Schematic/) {
- $mode = *eeschema;
- $raw = 1;
- die "only one schematic allowed" if defined @eeschema;
- &eeschema($_);
- next;
- }
- if (/^#EQU\b/) {
- $mode = *equ;
- next;
- }
- if (/^#INV\b/) {
- $mode = *inv;
- next;
- }
- if (/^#PAR\b/) {
- $mode = *par;
- next;
- }
- if (/^#CHR\b/) {
- $mode = *chr;
- undef $last;
- next;
- }
- if (/^#(SUB|GEN)\b/) {
- $mode = *sub;
- undef $last;
- undef $last_action;
- undef $may_cont;
- next;
- }
- if (/^#ORD\b/) {
- $mode = *ord;
- next;
- }
- if (/^#DSC\b/) {
- $mode = *dsc;
- next;
- }
- if (!$raw) {
- s/#.*//;
- next if /^\s*$/;
- }
- &$mode($_);
- }
-}
-
-return 1;
Deleted: trunk/gta02-core/bom/part2order
===================================================================
--- trunk/gta02-core/bom/part2order 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/part2order 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,133 +0,0 @@
-#!/usr/bin/perl
-
-require "parser.pl";
-require "misc.pl";
-
-$mult = shift(@ARGV);
-&parse;
-
-
-sub number
-{
- local ($id) = @_;
-
- my $s = $inv{$id}[0];
- my $n = $want{$id}*$mult;
- return $n < $s ? $n : $s;
-
-}
-
-
-#
-# The heuristics here aren't very nice. We give zero-cost stock priority over
-# any other stock, when we go by stock size up to the quantity we need. The
-# idea is to exhause local stock (zero-cost) first, then try to obtain the
-# parts with as few orders as possible.
-#
-# It would be better to have some sort of priority, so that we can express a
-# preference among stock we already own. Also, if non-zero-cost stock has widly
-# different prices, the smallest order cost may not be a good indicator of
-# which source we prefer.
-#
-# Furthermore, the algorithm doesn't consider the number of sources we use in
-# total or things like lead time, shipping cost, customs, etc.
-#
-
-sub rank
-{
- local ($a, $b) = @_;
-
- my $na = &number($a); # min(number wanted, available)
- my $nb = &number($b);
- my $pa = $inv{$a}[3]; # per unit price for smallest quantum
- my $pb = $inv{$b}[3];
-
-#print STDERR "a=$a b=$b na=$na nb=$nb pa=$pa pb=$pb\n";
- return 1 if $na && !$pa && $pb;
- return -1 if $nb && $pa && !$pb;
- return $na <=> $nb if $na != $nb;
- return $pb <=> $pa;
-}
-
-
-for (keys %parts) {
- $parts++;
-}
-
-print "#ORD\n";
-for (sort { &rank($b, $a) } keys %want) {
- my $n = &number($_);
- $n -= $n % $mult;
- next unless $n;
- my @f = @{ $inv{$_} };
- my $max = shift @f;
- my $currency = shift @f;
- my @qty;
- my @price;
- my %index;
- my $best_qty;
- my $best_price = undef;
- while (@f) {
- my $q = shift @f;
- my $p = shift @f;
- if (defined $index{$q}) {
- $price[$index{$q}] = $p;
- } else {
- push(@qty, $q);
- push(@price, $p);
- $index{$q} = $#qty;
- # @@@ this fails if smaller quantities following a large quantity
- # differ from the quantities preceding them. E.g., 1 10 100 25
- # wouldn't yield correct results.
- }
- for (my $i = $#qty; $i >= 0; $i--) {
- my $order = 0;
- my $price = 0;
- my $left = $n;
- for (my $j = $#qty; $j >= $i; $j--) {
- while ($left >= ($j == $i ? 1 : $qty[$j])) {
- $left -= $qty[$j];
- $order += $qty[$j];
- $price += $price[$j]*$qty[$j];
- }
- }
- next if $order > $max;
- if (!defined $best_price || $price < $best_price) {
- $best_price = $price;
- $best_qty = $order;
- }
- }
- }
- next if !defined $best_price;
- print "$_ $best_qty $currency $best_price";
- my $id = $_;
- while (keys %{ $comps{$id} }) {
- last if $best_qty < $mult;
- $best_qty -= $mult;
- my $ref = (sort keys %{ $comps{$id} })[0];
-#print STDERR "$id: $ref + ", join("|", keys %{ $comps{$id} }), "\n";
- my @f = @{ $parts{$ref} };
- while (@f) {
- my @id2 = splice(@f, 0, 2);
- my $id2 = "$id2[0] $id2[1]";
- $want{$id2}--;
- delete $comps{$id2}{$ref};
- }
- print " $ref";
- }
- print "\n";
-}
-
-for my $id (sort { $want{$b} <=> $want{$a} } keys %want) {
- next unless $want{$id};
- print STDERR "$id";
- for (&eq($id)) {
-# next unless $want{$_};
- die "\n$_ ($want{$_}) vs. $id want ($want{$id})"
- unless $want{$_} == $want{$id};
- print STDERR " $_";
- $want{$_} = 0;
- }
- print STDERR ": want $want{$id}\n";
- $want{$id} = 0;
-}
Deleted: trunk/gta02-core/bom/prettyord
===================================================================
--- trunk/gta02-core/bom/prettyord 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/prettyord 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,49 +0,0 @@
-#!/usr/bin/perl
-
-require "parser.pl";
-require "misc.pl";
-
-&parse;
-
-$out[0][0] = "Pos";
-$out[1][0] = "Qty";
-$out[2][0] = "P/N";
-$out[3][0] = "Description";
-$out[4][0] = "Value";
-$out[5][0] = "";
-
-for (sort keys %order) {
- push(@{ $out[0] }, ++$n);
- push(@{ $out[1] }, $order{$_}[0]);
- @f = split(/\s+/, $_);
- push(@{ $out[2] }, $f[1]);
- my $dsc = $dsc{$_};
- if (!defined $dsc) {
- for (&eq($_)) {
- $dsc = $dsc{$_};
- last if defined $dsc;
- }
- }
- print STDERR "$_: no description\n" unless defined $dsc;
- push(@{ $out[3] }, defined $dsc ? $dsc : "???");
- push(@{ $out[4] }, $order{$_}[1]);
- push(@{ $out[5] }, sprintf("%.2f", $order{$_}[2]));
-}
-
-for (@out) {
- push(@max, 0);
- for (@{ $_ }) {
- $max[$#max] = length $_ if length $_ > $max[$#max];
- }
-}
-
-for ($i = 0; $i <= $#{ $out[0] }; $i++) {
- for ($j = 0; $j != 6; $j++) {
- my $s = $out[$j][$i];;
- print $s if $j == 2 || $j == 3 || $j == 4;
- print " " x ($max[$j]-length $s);
- print $s if $j == 0 || $j == 1 || $j == 5;
- print " " unless $j == 5;
- }
- print "\n";
-}
Deleted: trunk/gta02-core/bom/workflow.fig
===================================================================
--- trunk/gta02-core/bom/workflow.fig 2010-02-07 13:59:06 UTC (rev 5826)
+++ trunk/gta02-core/bom/workflow.fig 2010-02-07 14:33:40 UTC (rev 5827)
@@ -1,147 +0,0 @@
-#FIG 3.2 Produced by xfig version 3.2.5a
-Landscape
-Center
-Metric
-A4
-100.00
-Single
--2
-1200 2
-6 450 5850 3150 6525
-4 0 0 50 -1 14 12 0.0000 4 180 2700 450 6030 Source file (in SVN)\001
-4 0 0 50 -1 12 12 0.0000 4 150 1890 450 6255 Generated file\001
-4 0 0 50 -1 18 12 0.0000 4 210 1830 450 6480 Program (in SVN)\001
--6
-6 450 7875 6480 9000
-4 0 0 50 -1 12 12 0.0000 4 105 540 450 8055 .csv\001
-4 0 0 50 -1 12 12 0.0000 4 150 540 450 8280 .inv\001
-4 0 0 50 -1 12 12 0.0000 4 150 540 450 8505 .equ\001
-4 0 0 50 -1 12 12 0.0000 4 150 540 450 8730 .par\001
-4 0 0 50 -1 12 12 0.0000 4 150 540 450 8955 .ord\001
-4 0 0 50 -1 1 12 0.0000 4 195 2520 1350 8280 inventory with stock and cost\001
-4 0 0 50 -1 1 12 0.0000 4 195 3045 1350 8055 GTA02 EE component stock at FIC\001
-4 0 0 50 -1 1 12 0.0000 4 195 5130 1350 8505 part number equivalences, e.g., manufacturer vs. distributor\001
-4 0 0 50 -1 1 12 0.0000 4 195 2910 1350 8730 component to part number(s) map\001
-4 0 0 50 -1 1 12 0.0000 4 195 5025 1350 8955 list of parts to order, with price and component references\001
--6
-6 450 7425 3465 7875
-4 0 0 50 -1 12 12 0.0000 4 150 540 450 7605 .chr\001
-4 0 0 50 -1 12 12 0.0000 4 150 540 450 7830 .sub\001
-4 0 0 50 -1 1 12 0.0000 4 195 1695 1350 7605 part characteristics\001
-4 0 0 50 -1 1 12 0.0000 4 195 2085 1350 7830 parameter substitutions\001
--6
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
- 1 1 2.00 60.00 60.00
- 7875 2700 7875 2925 6525 2925 6525 4725
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
- 1 1 2.00 60.00 60.00
- 9000 2700 9000 5850 6525 5850 6525 6075
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
- 1 1 2.00 60.00 60.00
- 3150 1350 3150 5850 6075 5850 6075 6075
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 6300 2700 6300 4725
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 6300 2025 6300 2475
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 6300 1350 6300 1800
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
- 1 1 2.00 60.00 60.00
- 4950 1350 4950 4275 6075 4275 6075 4725
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
- 1 1 2.00 60.00 60.00
- 3150 4500 5850 4500 5850 4725
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
- 1 1 2.00 60.00 60.00
- 8100 4275 8100 4500 6750 4500 6750 4725
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
- 11700 1575 11700 3150 10170 3150
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 6300 4950 6300 5400
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 6300 5625 6300 6075
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 6300 6300 6300 6750
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 6300 6975 6300 7425
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 6525 7650 6525 8100
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 9000 1350 9000 1800
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
- 1 1 2.00 60.00 60.00
- 9000 1575 7875 1575 7875 1800
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
- 1 1 2.00 60.00 60.00
- 9000 1575 10125 1575 10125 1800
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 7875 2025 7875 2475
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 9000 2025 9000 2475
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 7875 2925 7875 3375
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
- 1 1 2.00 60.00 60.00
- 8955 3150 8325 3150 8325 3375
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 8100 3600 8100 4050
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 10125 2025 10125 2475
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 4
- 1 1 2.00 60.00 60.00
- 10125 2700 10125 7200 6750 7200 6750 7425
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
- 1 1 2.00 60.00 60.00
- 8955 4500 8100 4500
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
- 9045 3150 10080 3150
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
- 11700 4050 11700 4500 10170 4500
-2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
- 10080 4500 9045 4500
-4 0 0 50 -1 2 16 0.0000 4 255 3345 450 675 BOM Processing - Workflow\001
-4 1 0 50 -1 12 12 0.0000 4 195 1890 6300 2655 gta02-core.lst\001
-4 1 0 50 -1 18 12 0.0000 4 165 1035 6300 1980 eeschema\001
-4 1 0 50 -1 14 12 0.0000 4 150 675 6300 1305 *.sch\001
-4 1 0 50 -1 18 12 0.0000 4 210 990 6300 4905 bom2part\001
-4 1 0 50 -1 18 12 0.0000 4 210 1110 6300 6255 part2order\001
-4 1 0 50 -1 12 12 0.0000 4 195 1890 6300 6930 gta02-core.ord\001
-4 1 0 50 -1 12 12 0.0000 4 195 1890 6300 5580 gta02-core.par\001
-4 1 0 50 -1 14 12 0.0000 4 195 1890 4950 1305 gta02-core.sub\001
-4 1 0 50 -1 14 12 0.0000 4 195 1890 3105 1305 gta02-core.inv\001
-4 1 0 50 -1 18 12 0.0000 4 210 975 6525 7605 prettyord\001
-4 1 0 50 -1 18 12 0.0000 4 165 1095 7875 1980 fic2vendor\001
-4 1 0 50 -1 18 12 0.0000 4 165 675 9000 1980 fic2inv\001
-4 1 0 50 -1 18 12 0.0000 4 210 855 8100 3555 gen2chr\001
-4 1 0 50 -1 12 12 0.0000 4 150 675 8100 4230 *.chr\001
-4 1 0 50 -1 12 12 0.0000 4 195 945 7875 2655 fic.equ\001
-4 1 0 50 -1 12 12 0.0000 4 150 945 9000 2655 fic.inv\001
-4 1 0 50 -1 18 12 0.0000 4 165 735 10125 1980 fic2dsc\001
-4 1 0 50 -1 14 12 0.0000 4 195 2700 9000 1305 inventory-fic-ee.csv\001
-4 0 0 50 -1 12 12 0.0000 4 150 540 450 7155 .lst\001
-4 0 0 50 -1 1 12 0.0000 4 195 2220 1350 7155 BOM generated by KiCad\001
-4 0 0 50 -1 12 12 0.0000 4 150 540 450 6930 .sch\001
-4 0 0 50 -1 1 12 0.0000 4 195 2010 1350 6930 schematics (for KiCad)\001
-4 0 0 50 -1 12 12 0.0000 4 150 540 450 7380 .gen\001
-4 0 0 50 -1 1 12 0.0000 4 195 2745 1350 7380 characteristics generation rules\001
-4 0 0 50 -1 12 12 0.0000 4 150 540 450 9180 .dsc\001
-4 0 0 50 -1 1 12 0.0000 4 195 2685 1350 9180 Textual component description\001
-4 1 0 50 -1 14 12 0.0000 4 180 675 11700 1305 *.gen\001
-4 1 0 50 -1 14 12 0.0000 4 150 675 11700 3780 *.chr\001
-4 1 0 50 -1 14 9 0.0000 4 135 1440 11700 4005 (acx, misc, ...)\001
-4 1 0 50 -1 14 9 0.0000 4 135 1800 11700 1530 (darfon, ralec, ...)\001
-4 1 0 50 -1 12 12 0.0000 4 150 945 10125 2655 fic.dsc\001
More information about the commitlog
mailing list