1 -----------------------------------------------------------------------
2 This file contains a few notes I made while creating
3 gattrib. These notes were useful to me in coming to grips with
4 understanding gEDA's data structures and gnetlist's operation.
5 The were also useful when architecting the workings of gattrib.
7 A spreadsheet holding function names is held in the file
8 called "ProgramArchitecture.gnumeric", which should live in the
9 design directory. This spreadsheet should help you wade
10 through the various fcns used during processing. Note that this
11 spreadsheet might be a little out of date. The source code is the
14 No guarantee is made that these notes are accurate, useful,
15 or even understandable to anybody else. -- SDB 12.5.2003
18 Last updated on 11.10.2004. SDB.
21 -----------------------------------------------------------------------
23 1. Input sheets as in gnetlist. Use fcns from libgeda. Result is
24 linked list of TOPLEVEL entries. (*pr_current) This data structure
27 The file is opened and read using:
28 libgeda/noweb/f_basic.nw:f_open(TOPLEVEL *w_current, char *filename)
30 f_open invokes o_read, which fills out the objects:
31 libgeda/noweb/a_basic.nw:o_read(TOPLEVEL *w_current,
32 OBJECT *object_list, char *filename)
34 At the end of this process, we have filled out (TOPLEVEL pr_current).
36 2. Create (SHEET_DATA *sheet_head), which is the data structure intermediating
37 between gEDA's TOPLEVEL and GtkSheet's gtk_sheet. It holds all info
38 important to drive the spreadsheet app in a form easy to access.
40 3. Build master lists which are part of SHEET_DATA. The master lists
41 are used when building the row and column label cells, and for
42 keeping track of which components and attribtues are in play.
44 Master lists are built for each of these objects:
45 * Component refdeses found in the design.
46 sheet_head->master_comp_list_head
47 * Component attributes found in the design.
48 sheet_head->master_comp_attrib_list_head
49 * Netnames found in the design.
50 sheet_head->master_net_list_head (TBD)
51 * Net attributes found in the design.
52 sheet_head->master_net_attrib_list_head (TBD)
53 * Component pins found in the design
54 sheet_head->master_pin_list_head
55 * Component pins attributes found in the design
56 sheet_head->master_pin_attrib_list_head
58 Each master list is stored using a STRING_DATA struct.
59 Attach pointers to these master lists inside SHEET_DATA.
60 This stage of processing also counts up the number of each
61 item. These lists are used to index the table entries, and form the
62 row and column labels on the gtk_sheet.
64 4. Create TABLE, which is the data structure holding the info to be displayed
65 in the gtk_sheet cells. TABLE is basically a 2D array of structs.
67 Tables are built for the following types of objects:
68 * Component refdeses & attached attributes.
69 sheet_head->component_table
70 * Netnames and attached attributes. (TBD)
72 * Component pins and attached attributes.
74 After creation, attach TABLE inside SHEET_DATA. The fcns which add components
75 and nets to the internal data structs are called s_*_set_*" Items in the table
76 are referenced using a construct like:
77 sheet_head->component_table)[i][j].attrib_value
79 5. Then build gtk_sheet using fcns available in x_gtksheet. They
80 take the data from SHEET_DATA and stick them into the gtk_sheet
81 widget for display on the spreadsheet.
83 6. Run gtk_main. Wait for user clicks & invoke appropriate callbacks.
84 Callback fcns are specified in include/menu.h
86 7. The save callback is x_fileselect_*. Upon a save/saveas event invoked
87 from the menu, take all data out of gtk_sheet and stick it into SHEET_DATA
88 using various fcns named "s_*_update_*". Then take data out of SHEET_DATA
89 and stick it into (TOPLEVEL *pr_current). Then use standard gEDA
90 fcns to save out the data in .sch format.
94 -----------------------------------------------------------------------
95 gattrib data structures:
98 Toplevel holds page info, and is a linked list with one entry per page/window.
99 Defined in libgeda/include/struct.h, fcns to manipulate TOPLEVEL data live in
100 libgeda/src/s_project.c
104 Holds data taken from TOPLEVEL in form relevant for display in spreadsheet.
107 struct st_sheet_data {
108 STRING_LIST *master_comp_list_head; /* Sorted list of all components used in design */
109 int comp_count; /* number of components in design */
110 STRING_LIST *master_comp_attrib_list_head; /* Sorted list of all component attribs used in design */
111 int comp_attrib_count; /* number of component attribs in design */
113 STRING_LIST *master_net_list_head; /* Sorted list of all nets used in design */
114 int net_count; /* number of nets in design */
115 STRING_LIST *master_net_attrib_list_head; /* Sorted list of all net attribss used in design */
116 int net_attrib_count; /* number of net attribss in design */
118 STRING_LIST *master_pin_list_head; /* Sorted list of all pins used in design */
119 int pin_count; /* number of pins in design */
120 STRING_LIST *master_pin_attrib_list_head; /* Sorted list of all pin attribss used in design */
121 int pin_attrib_count; /* number of pin attribss in design */
123 TABLE **component_table; /* points to 2d array of component attribs */
124 TABLE **net_table; /* points to 2d array of net attribs */
125 TABLE **pin_table; /* points to 2d array of pin attribs */
130 Is 2D array of structs. Each struct member holds info about
131 one particular attrib.
134 A linked list of strings. Used to create the component and net
138 These are the spreadsheet widgets themselves. There are three of them:
140 2. Net attribs (currently TBD)
141 3. Pin attribs (i.e. pinseq and so on).
144 ---------------------------------------------------------------------------------
145 ******** How data gets from TOPLEVEL into GtkSheet ********
146 ---------------------------------------------------------------------------------
147 Here's what happens when the program starts, or file->open is invoked from the menu
148 and the data is read in. (I handle data structure initialization elsewhere.) Keep
149 in mind that gattrib's data structures (in particular, SHEET_DATA) are
150 a thin layer between GtkSheet and TOPLEVEL. When you read in a
151 design, libgeda functions are used to fill out the TOPLEVEL data
152 structure. The the purpose of gattrib is to take all the stuff out of
153 TOPLEVEL run it throught SHEET_DATA, and finally stick it into
154 GtkSheet for user manipulation.
156 1. Loop on each page. For each page in the design, do this:
157 * Read in the page using s_toplevel_read_page.
158 * Invoke s_sheet_data_add_master_*_list items and
159 s_sheet_data_add_master_*_attrib_list items. This fills out the lists in
162 2. Sort the master lists.
164 3. Create the tables: sheet_head->*_table = s_table_new(. . . .)
166 4. Loop on pages again. Fill out the tables using
167 s_table_add_toplevel_*_items_to_*_table(. . . .)
169 5. Transfer data from tables to gtksheet using x_window_add_items.
170 This fcn does the following:
171 * Create a new gtksheet having the current dimensions.
172 * Call x_gktsheet_add_row_labels(*_count, master_*_list_head)
173 * Call x_gktsheet_add_col_labels(*_attrib_count, master_*_attrib_list_head)
174 * loop on i, j -- call x_gtksheet_add_entry(i, j, attrib_value), taking the
175 values out of sheet_heat->*_table.
176 * Call gtk_widget_show(window) to show new window.
179 ---------------------------------------------------------------------------------
180 ******** How data gets from GtkSheet into TOPLEVEL upon saving a sheet ********
181 ---------------------------------------------------------------------------------
182 Here's what happens when file->save is invoked from the menu. Please keep in
183 mind that gattrib is a thin layer between GtkSheet and TOPLEVEL. When you save
184 out a design, the purpose of gattrib is to take all the stuff out of GtkSheet
185 and put it temporarily into sheet_data->*_table. From there, it can then
186 stick it into TOPLEVEL. Thereafter, libgeda fcns are used to save it.
188 1. Selecting "save" from the menubar invokes the callback
189 s_toplevel_menubar_file_save.
190 (callbacks are defined in includes/x_menu.h)
191 This calls s_toplevel_gtksheet_to_toplevel.
193 2. s_toplevel_gtksheet_to_toplevel calls s_sheet_data_gtksheet_to_sheetdata.
194 Then it loops on all pages and calls s_toplevel_sheetdata_to_toplevel. (Described
195 starting in item 6 below.)
197 3. s_sheet_data_gtksheet_to_sheetdata calls s_table_gtksheet_to_all_tables.
199 4. s_table_gtksheet_to_all_tables calls s_table_gtksheet_to_table individually
200 for each sheet (comps, nets, pins)
202 5. s_table_gtksheet_to_table loops over all cells in the the gtksheet
203 and loads all the stuff it finds back into sheet_data->*_table.
205 6. Back in s_toplevel_gtksheet_to_toplevel. Now that the tables are loaded,
206 we loop on all pages and call s_toplevel_sheetdata_to_toplevel with a pointer
207 to the first obj on the page as the calling arg.
209 7. Inside s_toplevel_sheetdata_to_toplevel, we loop on all objs in the page,
210 find the corresponding entry in sheet_data->*_table, and then copy
211 all attribs out of sheet_data->*_table and back into the object's attrib list.
213 8. Finally, the libgeda fcn s_page_save_all is called. This saves out all
217 -----------------------------------------------------------------------
218 Data structures used in gEDA.
220 These notes attempt to document the data structures used in gEDA. I
221 present them here because they may not be familiar to those interested
222 in hacking gattrib. I also want to record these findings somewhere
223 because it took me some time to figure this out.
225 TOPLEVEL: The basic data structure in gschem. Basically holds info
226 about the entire design.
227 PAGE: Self explanatory. The entire design is held as a
228 doubly linked list of PAGEs under TOPLEVEL.
229 OBJECT: A graphical object on the gschem page. Can be a net
230 segment, a component complex, a bit of text, a
231 component's pin, or whatever. Each page holds a
232 doubly linked list of OBJECTs present on that page.
233 TILE: A section of the graphical page. Important in
234 gschem, a TILE holds a single linked list of OBJECTs
235 present in its subsection of the page. Each page
236 holds a two dimensional doubly linked list of TILEs.
237 A TILE is used to quickly locate a particular object
238 when handling the graphical drawing of a schematic.
239 NETLIST: Important in gnetlist. This is a doubly linked list
240 of component objects and pins.
243 -----------------------------------------------------------------------------
244 Represenatation of components, component attributes, & pins in gattrib & gEDA.
247 From the top down to a particular graphical object on a schematic page:
249 (TOPLEVEL *pr_current)->(PAGE page_current)->(OBJECT o_current)
251 That is, all objects in the design are graphical objects, and are held
252 in a linked list. Note that an object is any graphical object,
253 such as text, a component (COMPLEX), an attribute, a line, a net, etc.
254 Stuff attached below the OBJECT level determine
255 what kind of object the graphic is, its visibility, its name, etc. etc. etc.
258 ---- Components with attributes ----
259 Starting from a component (COMPLEX), an attribute is represented like this:
260 (OBJECT *component)->(ATTRIB *attribs)->(OBJECT *attrib_graphic)->(TEXT *text)->(char *string) // name=value string
261 ->(int x, y) // which coords?
262 ->(int screen_x) // ???
264 ->(int type) // types defined in o_types.h
265 ->(int sid) // unique identifier
266 ->(char *name) // something like text.3732
268 Note that ATTRIB is a linked list of (pointers to) attributes.
269 (OBJECT *component) points to the ATTRIB list, and "attrib_graphic" points
270 to the attrib OBJECT itself (which is a graphical element like everything else).
274 Since each attribute is itself a graphical object present in the design,
275 an attribute graphic is represented like this:
276 (OBJECT *attribute)->(TEXT *text)->(char *string) // name=value string
277 ->(int x, y) // which coords?
278 ->(int screen_x) // ???
280 ->(int type) // for attribute, type is text
281 // #define OBJ_TEXT 'T'
284 ->(ATTRIB *attached_to) // points back to (OBJECT *component)
285 ->(int attribute) // = 1 for attribute, = 0 otherwise.
286 ->(int show_name_value) // #define SHOW_NAME_VALUE 0
287 // #define SHOW_VALUE 1
288 // #define SHOW_NAME 2
289 ->(int visibility) // #define INVISIBLE 0
292 Attrib_graphic is stored internally as a "name=value" string, and is disassembled
293 by various fcns when needed.
297 As for pins, they are attached to components (COMPLEX) in the following way.
298 Starting from the component:
299 (OBJECT *component)->(COMPLEX *complex)->(OBJECT *prim_objs)->(int type) // #define OBJ_PIN 'P'
300 ->(ATTRIB *attribs) // pin attrib list.
301 ->(int sid) // unique identifier
302 ->(char *name) // something like pin.3372
305 Pins also are held in the NETLIST data structure, which is a separate data structure.
306 NETLIST is more important in gnetlist than in gschem. A pin is held in the following
308 (NETLIST *node)->(OBJECT *object_ptr)
309 ->(CPINLIST *cpins)->(char *pin_number)
316 Component objects (COMPLEX) have lots of other other fields in teh struct.
317 Here's an example taken from a real design:
319 (OBJECT *component)->name = complex.188 // unique ID of component
321 ->attribs->object->name = complex.188 // first "attribs" points back to component
322 ->attribs->next->object->name = text.272 // attrib text
323 ->attribs->next->object->text->string = refdes=C1 // actual attrib
325 ->complex->prim_objs->name = complex-head.189 // head of prim_objs list
326 ->complex->prim_objs->next->name = pin.190 // actual object
328 Each list attached to a component has a head, followed by the actual list
332 -----------------------------------------------------------------------
333 From include/struct.h:
335 /* ----------- SDB note about philosophy behind globals -------------- *
336 * I made the "TOPLEVEL project" and all the GTK window stuff into
337 * global variables. I know that this is supposedly bad programming form.
338 * However, here are some observations:
339 * -- I wanted to use gEDA's TOPLEVEL structure as much as possible, at
340 * least to hold info about the design's netlist & components.
341 * The TOPLEVEL strucuture is architected to hold info about gschem's
342 * window also. HOwever, gschem's windows are architected differently
343 * than mine in gattrib. This is because my windowing system does
344 * completely different things, and also uses the GtkSheet widget, which
345 * is architected completely differently from TOPLEVEL.
346 * -- Since I couldn't easily or naturally cram my windowing scheme into
347 * TOPLEVEL (or so I think), I decided to use a separate set of windows
348 * from those defined under TOPLEVEL for my application.
349 * -- The problem arises when using callbacks. Callbacks from GTK allow
350 * only one argument to be passed. Given the way I set up the menu bar,
351 * I didn't have easy acces to the information inside both the GtkSHeet
352 * objects *and* the TOPLEVEL stuff while only having one callback
353 * argument. This makes it hard to have access to e.g. a GtkSheet window
354 * and a list of files (in TOPLEVEL) simultaneously.
355 * -- Therefore, I decided to make both the window stuff and TOPLEVEL
357 * -- Similarly, because I couldn't cram the SHEET_DATA struct into any
358 * hook in TOPLEVEL, I just made it a global also.
359 * -- Finally, in my defense, in gschem and gnetlist, (TOPLEVEL *w_current
360 * or pr_current) is passed to almost every function. Since it
361 * is just a pointer to a huge struct of stuff, manipulating
362 * the stuff in the struct has a global
363 * effect. That is, manipulating w_current (or pr_current) has side
364 * effects, so it is basically a global anyway. The real problem with
365 * globals occurs when you have a global variable caled "i" or "temp"
366 * which conflicts with a global in a module written by somebody else.
367 * Since pr_current is a very uncommon name, this should not be a
368 * problem here. Therefore, I decided
369 * to make life easy for myself dealing with callbacks by making both
370 * the windows and TOPLEVEL global variables.
371 * If there is a better way to solve this problem, I'd like to hear it.
372 * ------------------------------------------------------------------ */
375 -----------------------------------------------------------------------
377 1. Before building spreadsheet, create and sort component and net
378 master lists. They are used to index components in the TABLE,
379 and also label the gtk_sheet rows and cols.
380 2. How to handle attribute visibility? Maybe right-click on cell & set
381 vis. Default = invisible and "both name and value".
382 3. Need fcns to allow for adding and deleting of entire attrib
383 columns. Don't need to allow for adding/deleting components
384 -- users should use gschem to add/delete components because
385 gattrib can't do anything about the graphical position data
390 -----------------------------------------------------------------------
391 Here's what the filename prefix letters mean:
393 a_ : Action (this was a really poor choice, and will be removed)
394 g_ : Guile related functions
395 i_ : Interface related functions
396 o_ : graphic Object related functions
397 x_ : X related functions
398 f_ : File related functions
399 m_ : Math related functions
400 s_ : data Structure related functions
402 I've tried to keep the function names in the files correct, but
403 sometimes I failed. (look at libgeda/a_basic.c for an example of
404 a file which has a bunch of functions which shouldn't be in there)
407 -----------------------------------------------------------------------