r5942 - trunk/eda/fped
werner at docs.openmoko.org
werner at docs.openmoko.org
Mon Apr 26 17:18:01 CEST 2010
Author: werner
Date: 2010-04-26 17:18:01 +0200 (Mon, 26 Apr 2010)
New Revision: 5942
Added:
trunk/eda/fped/tsort.c
trunk/eda/fped/tsort.h
Modified:
trunk/eda/fped/Makefile
trunk/eda/fped/README
trunk/eda/fped/TODO
trunk/eda/fped/fpd.l
trunk/eda/fped/fpd.y
Log:
Added a topological sort algorithm, for use when dumping.
- tsort.h, tsort.c, Makefile: stable topological sort with priorities
- fpd.l, fpd.y: added directive %tsort to test-drive the sort algorithm
- README: documented %tsort
Modified: trunk/eda/fped/Makefile
===================================================================
--- trunk/eda/fped/Makefile 2010-04-25 15:27:27 UTC (rev 5941)
+++ trunk/eda/fped/Makefile 2010-04-26 15:18:01 UTC (rev 5942)
@@ -16,7 +16,7 @@
OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \
unparse.o file.o dump.o kicad.o postscript.o meas.o \
- layer.o overlap.o hole.o \
+ layer.o overlap.o hole.o tsort.o \
cpp.o lex.yy.o y.tab.o \
gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \
gui_tool.o gui_over.o gui_meas.o gui_frame.o gui_frame_drag.o
Modified: trunk/eda/fped/README
===================================================================
--- trunk/eda/fped/README 2010-04-25 15:27:27 UTC (rev 5941)
+++ trunk/eda/fped/README 2010-04-26 15:18:01 UTC (rev 5942)
@@ -582,14 +582,15 @@
Experimental: debugging directives
----------------------------------
-For debugging and regression tests, fped supports the following commands
-that mimick the effect of GUI operations:
+For debugging and regression tests, fped supports the following commands,
+most of which mimick the effect of GUI operations:
%del <identifier>
%move <identifier> [<number>] <identifier>
%print <expression>
%dump
%exit
+%tsort { -<id> | +<id> | <id-before> <id-after> [<number>] ... }
%del and %move take as their first argument the name of the vector or
object to manipulate. For this purpose, also objects can be labeled.
@@ -608,3 +609,8 @@
%dump writes the footprint definition in the fped language to standard
output. %exit immediately exits fped, without invoking the GUI.
+
+%tsort is used to test-drive the topological sort algorithm. The items
+in the curly braces are declarations of nodes with (-<id>) or without
+(+<id>) decay or edges in the partial order. The optional number is
+the edge's priority. See tsort.c for details.
Modified: trunk/eda/fped/TODO
===================================================================
--- trunk/eda/fped/TODO 2010-04-25 15:27:27 UTC (rev 5941)
+++ trunk/eda/fped/TODO 2010-04-26 15:18:01 UTC (rev 5942)
@@ -69,7 +69,6 @@
- live update of value when entering strings and expressions ?
- advanced: non-standard solder mask
- advanced: solder paste exceptions (subtractive, additive)
-- advanced: holes
- advanced: silk line width
- future: consider editing non-canvas items (e.g., variable names/values) in
place
Modified: trunk/eda/fped/fpd.l
===================================================================
--- trunk/eda/fped/fpd.l 2010-04-25 15:27:27 UTC (rev 5941)
+++ trunk/eda/fped/fpd.l 2010-04-26 15:18:01 UTC (rev 5942)
@@ -133,6 +133,8 @@
return TOK_DBG_DUMP; }
<INITIAL>"%exit" { BEGIN(NOKEYWORD);
return TOK_DBG_EXIT; }
+<INITIAL>"%tsort" { BEGIN(NOKEYWORD);
+ return TOK_DBG_TSORT; }
<INITIAL>[a-zA-Z_][a-zA-Z_0-9]*: { *strchr(yytext, ':') = 0;
yylval.id = unique(yytext);
Modified: trunk/eda/fped/fpd.y
===================================================================
--- trunk/eda/fped/fpd.y 2010-04-25 15:27:27 UTC (rev 5941)
+++ trunk/eda/fped/fpd.y 2010-04-26 15:18:01 UTC (rev 5942)
@@ -22,6 +22,7 @@
#include "meas.h"
#include "gui_status.h"
#include "dump.h"
+#include "tsort.h"
#include "fpd.h"
@@ -46,7 +47,9 @@
static const char *id_sin, *id_cos, *id_sqrt;
+static struct tsort *tsort;
+
static struct frame *find_frame(const char *name)
{
struct frame *f;
@@ -289,7 +292,7 @@
%token TOK_MEAS TOK_MEASX TOK_MEASY TOK_UNIT
%token TOK_NEXT TOK_NEXT_INVERTED TOK_MAX TOK_MAX_INVERTED
%token TOK_DBG_DEL TOK_DBG_MOVE TOK_DBG_PRINT TOK_DBG_DUMP
-%token TOK_DBG_EXIT
+%token TOK_DBG_EXIT TOK_DBG_TSORT
%token <num> NUMBER
%token <str> STRING
@@ -481,8 +484,41 @@
{
exit(0);
}
+ | TOK_DBG_TSORT '{'
+ {
+ tsort = begin_tsort();
+ }
+ sort_items '}'
+ {
+ void **sort, **walk;
+
+ sort = end_tsort(tsort);
+ for (walk = sort; *walk; walk++)
+ printf("%s\n", (char *) *walk);
+ free(sort);
+ }
;
+sort_items:
+ | sort_items '+' ID
+ {
+ add_node(tsort, (void *) $3, 0);
+ }
+ | sort_items '-' ID
+ {
+ add_node(tsort, (void *) $3, 1);
+ }
+ | sort_items ID ID opt_num
+ {
+ struct node *a, *b;
+
+ /* order is important here ! */
+ a = add_node(tsort, (void *) $2, 0);
+ b = add_node(tsort, (void *) $3, 0);
+ add_edge(a, b, $4.n);
+ }
+ ;
+
table:
TOK_TABLE
{
Added: trunk/eda/fped/tsort.c
===================================================================
--- trunk/eda/fped/tsort.c (rev 0)
+++ trunk/eda/fped/tsort.c 2010-04-26 15:18:01 UTC (rev 5942)
@@ -0,0 +1,160 @@
+/*
+ * tsort.c - Topological sort
+ *
+ * Written 2010 by Werner Almesberger
+ * Copyright 2010 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/*
+ * We use a slight variation of Kahn's algorithm. The difference is that we add
+ * a priority. Edges with the highest priority get selected before edges with
+ * lower priority.
+ *
+ * We maintain the initial list of nodes in the order in which they were added.
+ * Therefore, the first node with inbound edges will always be sorted first.
+ * E.g., the root frame.
+ *
+ * add_node and add_edge can be invoked multiple times with the same
+ * parameters. In the case of add_node, simply the existing node is returned.
+ * In the case of add_edge, the new edge's priority is added to the priority of
+ * the previous edges.
+ *
+ * Priority is accumulated in a node until the node is output. If a node has
+ * the "decay" flag set, it resets the priorities of all other nodes when
+ * output. E.g., when outputting a vector, all priorities accumulated from
+ * previous vectors (towards referencing them with ".") lose their effect.
+ *
+ * Last but not least, the algorithm is stable: a pre-existing order that
+ * conflicts neither with the partial order nor the priorities is preserved.
+ *
+ * Thus, we have the following sorting criteria, in decreasing importance:
+ * - the destination if an edge never precedes its origin
+ * - higher priority comes before lower priority
+ * - earlier add_node comes before later
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
+#include "util.h"
+#include "tsort.h"
+
+
+struct edge {
+ struct node *to;
+ int priority; /* edge priority */
+ struct edge *next;
+};
+
+struct node {
+ void *user;
+ struct edge *edges; /* outbound edges */
+ int incoming; /* number of incoming edges */
+ int priority; /* cumulative node priority */
+ int decay; /* all node prio. decay after issuing this */
+ struct node *next;
+};
+
+struct tsort {
+ struct node *nodes;
+ struct node **next_node;
+ int n_nodes;
+};
+
+
+void add_edge(struct node *from, struct node *to, int priority)
+{
+ struct edge **edge;
+
+ for (edge = &from->edges; *edge; edge = &(*edge)->next)
+ if ((*edge)->to == to) {
+ (*edge)->priority += priority;
+ return;
+ }
+ *edge = alloc_type(struct edge);
+ (*edge)->to = to;
+ (*edge)->priority = priority;
+ (*edge)->next = NULL;
+ to->incoming++;
+}
+
+
+struct node *add_node(struct tsort *tsort, void *user, int decay)
+{
+ struct node *node;
+
+ for (node = tsort->nodes; node; node = node->next)
+ if (node->user == user)
+ return node;
+ node = alloc_type(struct node);
+ node->user = user;
+ node->edges = NULL;
+ node->incoming = 0;
+ node->priority = 0;
+ node->decay = decay;
+ node->next = NULL;
+ *tsort->next_node = node;
+ tsort->next_node = &node->next;
+ tsort->n_nodes++;
+ return node;
+}
+
+
+struct tsort *begin_tsort(void)
+{
+ struct tsort *tsort;
+
+ tsort = alloc_type(struct tsort);
+ tsort->nodes = NULL;
+ tsort->next_node = &tsort->nodes;
+ tsort->n_nodes = 0;
+ return tsort;
+}
+
+
+void **end_tsort(struct tsort *tsort)
+{
+ struct node **walk, **first, *node;
+ struct edge *edge;
+ void **res;
+ int n = 0;
+
+ res = alloc_size(sizeof(void *)*(tsort->n_nodes+1));
+ while (1) {
+ first = NULL;
+ for (walk = &tsort->nodes; *walk; walk = &(*walk)->next) {
+ if ((*walk)->incoming)
+ continue;
+ if (!first || (*first)->priority < (*walk)->priority)
+ first = walk;
+ }
+ if (!first)
+ break;
+ if ((*first)->decay)
+ for (node = tsort->nodes; node; node = node->next)
+ node->priority = 0;
+ node = *first;
+ *first = node->next;
+ res[n++] = node->user;
+ while (node->edges) {
+ edge = node->edges;
+ edge->to->incoming--;
+ edge->to->priority += edge->priority;
+ node->edges = edge->next;
+ free(edge);
+ }
+ free(node);
+ }
+ if (tsort->nodes) /* we have at least one cycle */
+ abort();
+ free(tsort);
+ res[n] = NULL;
+ return res;
+}
Added: trunk/eda/fped/tsort.h
===================================================================
--- trunk/eda/fped/tsort.h (rev 0)
+++ trunk/eda/fped/tsort.h 2010-04-26 15:18:01 UTC (rev 5942)
@@ -0,0 +1,25 @@
+/*
+ * tsort.h - Topological sort
+ *
+ * Written 2010 by Werner Almesberger
+ * Copyright 2010 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef TSORT_H
+#define TSORT_H
+
+struct node;
+struct tsort;
+
+struct node *add_node(struct tsort *tsort, void *user, int decay);
+void add_edge(struct node *from, struct node *to, int priority);
+
+struct tsort *begin_tsort(void);
+void **end_tsort(struct tsort *tsort);
+
+#endif /* !TSORT_H */
More information about the commitlog
mailing list