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 toplevel directory. This spreadsheet should help you wade
10 through the various fcns used during processing.
12 No guarantee is made that these notes are accurate, useful,
13 or even understandable to anybody else. -- SDB 12.5.2003
16 Updated on 7.17.2004. SDB.
19 -----------------------------------------------------------------------
21 1. Input sheets as in gnetlist. Use fcns from libgeda. Result is
22 linked list of TOPLEVEL entries. (*pr_current) This data structure
25 The file is opened and read using:
26 libgeda/noweb/f_basic.nw:f_open(TOPLEVEL *w_current, char *filename)
28 f_open invokes o_read, which fills out the objects:
29 libgeda/noweb/a_basic.nw:o_read(TOPLEVEL *w_current,
30 OBJECT *object_list, char *filename)
32 At the end of this process, we have filled out (TOPLEVEL pr_current).
34 2. Create (SHEET_DATA *sheet_head), which is the data structure intermediating
35 between gEDA's TOPLEVEL and GtkSheet's gtk_sheet. It holds all info
36 important to drive the spreadsheet app in a form easy to access.
38 3. Build master lists which are part of SHEET_DATA. The master lists
39 are used when building the row and column label cells, and for
40 keeping track of which components and attribtues are in play.
42 Master lists are built for each of these objects:
43 * Component refdeses found in the design.
44 sheet_head->master_comp_list_head
45 * Component attributes found in the design.
46 sheet_head->master_comp_attrib_list_head
47 * Netnames found in the design.
48 sheet_head->master_net_list_head (TBD)
49 * Net attributes found in the design.
50 sheet_head->master_net_attrib_list_head (TBD)
51 * Component pins found in the design (TBD)
53 * Component pins attributes found in the design (TBD)
55 Each master list is stored using a STRING_DATA struct.
56 Attach pointers to these master lists inside SHEET_DATA.
57 This stage of processing also counts up the number of each
58 item. These lists are used to index the table entries, and form the
59 row and column labels on the gtk_sheet.
61 4. Create TABLE, which is the data structure holding the info to be displayed
62 in the gtk_sheet cells. TABLE is basically a 2D array of structs.
64 Tables are built for the following types of objects:
65 * Component refdeses & attached attributes.
66 sheet_head->component_table
67 * Netnames and attached attributes. (TBD)
69 * Component pins and attached attributes. (TBD)
71 After creation, attach TABLE inside SHEET_DATA. The fcns which add components
72 and nets to the internal data structs are called s_*_set_*" Items in the table
73 are referenced using a construct like:
74 sheet_head->component_table)[i][j].attrib_value
76 5. Then build gtk_sheet using fcns available in x_gtksheet. They
77 take the data from SHEET_DATA and stick them into the gtk_sheet
78 widget for display on the spreadsheet.
80 6. Run gtk_main. Wait for user clicks & invoke appropriate callbacks.
81 Callback fcns are specified in include/menu.h
83 7. The save callback is x_fileselect_*. Upon a save/saveas event invoked
84 from the menu, take all data out of gtk_sheet and stick it into SHEET_DATA
85 using various fcns named "s_*_update_*". Then take data out of SHEET_DATA
86 and stick it into (TOPLEVEL *pr_current). Then use standard gEDA
87 fcns to save out the data in .sch format.
91 -----------------------------------------------------------------------
92 gattrib data structures:
95 Toplevel holds page info, and is a linked list with one entry per page/window.
96 Defined in libgeda/include/struct.h, fcns to manipulate TOPLEVEL data live in
97 libgeda/src/s_project.c
101 Holds data taken from TOPLEVEL in form relevant for display in spreadsheet.
104 struct st_sheet_data {
105 STRING_LIST *master_comp_list_head; /* Sorted list of all components used in design */
106 int comp_count; /* number of components in design */
107 STRING_LIST *master_comp_attrib_list_head; /* Sorted list of all component attribs used in design */
108 int comp_attrib_count; /* number of component attribs in design */
110 STRING_LIST *master_net_list_head; /* Sorted list of all nets used in design */
111 int net_count; /* number of nets in design */
112 STRING_LIST *master_net_attrib_list_head; /* Sorted list of all net attribss used in design */
113 int net_attrib_count; /* number of net attribss in design */
115 STRING_LIST *master_pin_list_head; /* Sorted list of all pins used in design */
116 int pin_count; /* number of pins in design */
117 STRING_LIST *master_pin_attrib_list_head; /* Sorted list of all pin attribss used in design */
118 int pin_attrib_count; /* number of pin attribss in design */
120 TABLE **component_table; /* points to 2d array of component attribs */
121 TABLE **net_table; /* points to 2d array of net attribs */
122 TABLE **pin_table; /* points to 2d array of pin attribs */
127 Is 2D array of structs. Each struct member holds info about
128 one particular attrib.
131 A linked list of strings. Used to create the component and net
135 These are the spreadsheet widgets themselves. There are thre of them:
137 2. Net attribs (currently TBD)
138 3. Pin attribs (i.e. pinseq and so on).
141 ---------------------------------------------------------------------------------
142 ******** How data gets from TOPLEVEL into GtkSheet ********
143 ---------------------------------------------------------------------------------
144 Here's what happens when the program starts, or file->save is invoked from the menu
145 and the data is read in. (I handle data structure initialization elsewhere.) Keep
146 in mind that gattrib is a thin layer between GtkSheet and TOPLEVEL. When you read
147 in a design, libgeda functions are used to fill out the TOPLEVEL data structure. The
148 the purpose of gattrib is to take all teh stuff out of TOPLEVEL and stick it into
149 GtkSheet for user manipulation.
151 1. Loop on each page. For each page in the design, read it in using
152 s_toplevel_read_page. Then invoke s_sheet_data_add_master_*_list items.
154 2. Create the tables using s_table_new.
156 3. Load the tables using s_sheet_data_add_*_table_items.
163 ---------------------------------------------------------------------------------
164 ******** How data gets from GtkSheet into TOPLEVEL upon saving a sheet ********
165 ---------------------------------------------------------------------------------
166 Here's what happens when file->save is invoked from the menu. Please keep in
167 mind that gattrib is a thin layer between GtkSheet and TOPLEVEL. When you save
168 out a design, the purpose of gattrib is to take all the stuff out of GtkSheet
169 and stick it into TOPLEVEL and then save it.
171 1. Selecting "save" from the menubar invokes the callback s_toplevel_menubar_file_save.
172 (callbacks are defined in includes/x_menu.h)
173 This calls s_toplevel_gtksheet_to_toplevel.
175 2. s_toplevel_gtksheet_to_toplevel calls s_sheet_data_gtksheet_to_sheetdata.
176 Then it loops on all pages and calls s_toplevel_sheetdata_to_toplevel. (Described
177 starting in item 6 below.)
179 3. s_sheet_data_gtksheet_to_sheetdata calls s_table_gtksheet_to_all_tables.
181 4. s_table_gtksheet_to_all_tables calls s_table_gtksheet_to_table individually
182 for each sheet (comps, nets, pins)
184 5. s_table_gtksheet_to_table loops on the gtksheet and loads all the stuff it
185 finds back into TABLE (part of sheet_data).
187 6. Back in s_toplevel_gtksheet_to_toplevel. Now that the tables are loaded,
188 we loop on all pages and call s_toplevel_sheetdata_to_toplevel with a pointer
189 to the first obj on the page as the calling arg.
191 7. Inside s_toplevel_sheetdata_to_toplevel, we loop on all objs in teh page,
192 find the corresponding entry in TABLE, and then copy all attribs out of
193 TABLE and back into the object's attrib list.
195 8. Finally, the libgeda fcn s_page_save_all is called. This saves out all
199 -----------------------------------------------------------------------
200 Data structures used in gEDA.
202 These notes attempt to document the data structures used in gEDA. I
203 present them here because they may not be familiar to those interested
204 in hacking gattrib. I also want to record these findings somewhere
205 because it took me some time to figure this out.
207 TOPLEVEL: The basic data structure in gschem. Basically holds info
208 about the entire design.
209 PAGE: Self explanatory. The entire design is held as a
210 doubly linked list of PAGEs under TOPLEVEL.
211 OBJECT: A graphical object on the gschem page. Can be a net
212 segment, a component complex, a bit of text, a
213 component's pin, or whatever. Each page holds a
214 doubly linked list of OBJECTs present on that page.
215 TILE: A section of the graphical page. Important in
216 gschem, a TILE holds a single linked list of OBJECTs
217 present in its subsection of the page. Each page
218 holds a two dimensional doubly linked list of TILEs.
219 A TILE is used to quickly locate a particular object
220 when handling the graphical drawing of a schematic.
221 NETLIST: Important in gnetlist. This is a doubly linked list
222 of component objects and pins.
225 -----------------------------------------------------------------------------
226 Represenatation of components, component attributes, & pins in gattrib & gEDA.
229 From the top down to a particular graphical object on a schematic page:
231 (TOPLEVEL *pr_current)->(PAGE page_current)->(OBJECT o_current)
233 That is, all objects in the design are graphical objects, and are held
234 in a linked list. Note that an object is any graphical object,
235 such as text, a component (COMPLEX), an attribute, a line, a net, etc.
236 Stuff attached below the OBJECT level determine
237 what kind of object the graphic is, its visibility, its name, etc. etc. etc.
240 ---- Components with attributes ----
241 Starting from a component (COMPLEX), an attribute is represented like this:
242 (OBJECT *component)->(ATTRIB *attribs)->(OBJECT *attrib_graphic)->(TEXT *text)->(char *string) // name=value string
243 ->(int x, y) // which coords?
244 ->(int screen_x) // ???
246 ->(int type) // types defined in o_types.h
247 ->(int sid) // unique identifier
248 ->(char *name) // something like text.3732
250 Note that ATTRIB is a linked list of (pointers to) attributes.
251 (OBJECT *component) points to the ATTRIB list, and "attrib_graphic" points
252 to the attrib OBJECT itself (which is a graphical element like everything else).
256 Since each attribute is itself a graphical object present in the design,
257 an attribute graphic is represented like this:
258 (OBJECT *attribute)->(TEXT *text)->(char *string) // name=value string
259 ->(int x, y) // which coords?
260 ->(int screen_x) // ???
262 ->(int type) // for attribute, type is text
263 // #define OBJ_TEXT 'T'
266 ->(ATTRIB *attached_to) // points back to (OBJECT *component)
267 ->(int attribute) // = 1 for attribute, = 0 otherwise.
268 ->(int show_name_value) // #define SHOW_NAME_VALUE 0
269 // #define SHOW_VALUE 1
270 // #define SHOW_NAME 2
271 ->(int visibility) // #define INVISIBLE 0
274 Attrib_graphic is stored internally as a "name=value" string, and is disassembled
275 by various fcns when needed.
279 As for pins, they are attached to components (COMPLEX) in the following way.
280 Starting from the component:
281 (OBJECT *component)->(COMPLEX *complex)->(OBJECT *prim_objs)->(int type) // #define OBJ_PIN 'P'
282 ->(ATTRIB *attribs) // pin attrib list.
283 ->(int sid) // unique identifier
284 ->(char *name) // something like pin.3372
287 Pins also are held in the NETLIST data structure, which is a separate data structure.
288 NETLIST is more important in gnetlist than in gschem. A pin is held in the following
290 (NETLIST *node)->(OBJECT *object_ptr)
291 ->(CPINLIST *cpins)->(char *pin_number)
298 Component objects (COMPLEX) have lots of other other fields in teh struct.
299 Here's an example taken from a real design:
301 (OBJECT *component)->name = complex.188 // unique ID of component
303 ->attribs->object->name = complex.188 // first "attribs" points back to component
304 ->attribs->next->object->name = text.272 // attrib text
305 ->attribs->next->object->text->string = refdes=C1 // actual attrib
307 ->complex->prim_objs->name = complex-head.189 // head of prim_objs list
308 ->complex->prim_objs->next->name = pin.190 // actual object
310 Each list attached to a component has a head, followed by the actual list
314 -----------------------------------------------------------------------
315 From include/struct.h:
317 /* ----------- SDB note about philosophy behind globals -------------- *
318 * I made the "TOPLEVEL project" and all the GTK window stuff into
319 * global variables. I know that this is supposedly bad programming form.
320 * However, here are some observations:
321 * -- I wanted to use gEDA's TOPLEVEL structure as much as possible, at
322 * least to hold info about the design's netlist & components.
323 * The TOPLEVEL strucuture is architected to hold info about gschem's
324 * window also. HOwever, gschem's windows are architected differently
325 * than mine in gattrib. This is because my windowing system does
326 * completely different things, and also uses the GtkSheet widget, which
327 * is architected completely differently from TOPLEVEL.
328 * -- Since I couldn't easily or naturally cram my windowing scheme into
329 * TOPLEVEL (or so I think), I decided to use a separate set of windows
330 * from those defined under TOPLEVEL for my application.
331 * -- The problem arises when using callbacks. Callbacks from GTK allow
332 * only one argument to be passed. Given the way I set up the menu bar,
333 * I didn't have easy acces to the information inside both the GtkSHeet
334 * objects *and* the TOPLEVEL stuff while only having one callback
335 * argument. This makes it hard to have access to e.g. a GtkSheet window
336 * and a list of files (in TOPLEVEL) simultaneously.
337 * -- Therefore, I decided to make both the window stuff and TOPLEVEL
339 * -- Similarly, because I couldn't cram the SHEET_DATA struct into any
340 * hook in TOPLEVEL, I just made it a global also.
341 * -- Finally, in my defense, in gschem and gnetlist, (TOPLEVEL *w_current
342 * or pr_current) is passed to almost every function. Since it
343 * is just a pointer to a huge struct of stuff, manipulating
344 * the stuff in the struct has a global
345 * effect. That is, manipulating w_current (or pr_current) has side
346 * effects, so it is basically a global anyway. The real problem with
347 * globals occurs when you have a global variable caled "i" or "temp"
348 * which conflicts with a global in a module written by somebody else.
349 * Since pr_current is a very uncommon name, this should not be a
350 * problem here. Therefore, I decided
351 * to make life easy for myself dealing with callbacks by making both
352 * the windows and TOPLEVEL global variables.
353 * If there is a better way to solve this problem, I'd like to hear it.
354 * ------------------------------------------------------------------ */
357 -----------------------------------------------------------------------
359 1. Before building spreadsheet, create and sort component and net
360 master lists. They are used to index components in the TABLE,
361 and also label the gtk_sheet rows and cols.
362 2. How to handle attribute visibility? Maybe right-click on cell & set
363 vis. Default = invisible and "both name and value".
364 3. Need fcns to allow for adding and deleting of entire attrib
365 columns. Don't need to allow for adding/deleting components
366 -- users should use gschem to add/delete components because
367 gattrib can't do anything about the graphical position data
372 -----------------------------------------------------------------------
373 Here's what the filename prefix letters mean:
375 a_ : Action (this was a really poor choice, and will be removed)
376 g_ : Guile related functions
377 i_ : Interface related functions
378 o_ : graphic Object related functions
379 x_ : X related functions
380 f_ : File related functions
381 m_ : Math related functions
382 s_ : data Structure related functions
384 I've tried to keep the function names in the files correct, but
385 sometimes I failed. (look at libgeda/a_basic.c for an example of
386 a file which has a bunch of functions which shouldn't be in there)
389 -----------------------------------------------------------------------