source: branches/with_autoconf/src/graph_cass.cc @ 9

Last change on this file since 9 was 8, checked in by nipo, 16 years ago

Checkin autotools magic

File size: 11.4 KB
Line 
1/*------------------------------------------------------------\
2|                                                             |
3| Tool    :                  systemcass                       |
4|                                                             |
5| File    :                 graph_cass.cc                     |
6|                                                             |
7| Author  :                 Petrot Frédéric                   |
8|                           Taktak Sami                       |
9|                           Buchmann Richard                  |
10|                                                             |
11| Date    :                   09_07_2004                      |
12|                                                             |
13\------------------------------------------------------------*/
14
15/*
16 * This file is part of the Disydent Project
17 * Copyright (C) Laboratoire LIP6 - Département ASIM
18 * Universite Pierre et Marie Curie
19 *
20 * Home page          : http://www-asim.lip6.fr/disydent
21 * E-mail             : mailto:richard.buchmann@lip6.fr
22 *
23 * This library is free software; you  can redistribute it and/or modify it
24 * under the terms  of the GNU Library General Public  License as published
25 * by the Free Software Foundation; either version 2 of the License, or (at
26 * your option) any later version.
27 *
28 * Disydent is distributed  in the hope  that it  will be
29 * useful, but WITHOUT  ANY WARRANTY; without even the  implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
31 * Public License for more details.
32 *
33 * You should have received a copy  of the GNU General Public License along
34 * with the GNU C Library; see the  file COPYING. If not, write to the Free
35 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36 */
37
38/*
39 * $Log: graph_cass.cc,v $
40 * Revision 1.5  2006/06/12 14:02:04  buchmann
41 * - Now sort transition and generation functions by fonction pointer
42 *   (Thank to Nicolas Pouillon)
43 * - Add Nicolas Pouillon as contributor into splash screen
44 * - Rename files and classes from "dependancy" to "dependency".
45 * - Add some references to bibliography file
46 * - Add licence note to every files
47 * - Rename "module graph" to "process graph"
48 * - Now dump module graph when using --t option and CASS scheduling at the same
49 *   time
50 *
51 * Bug fixes :
52 * - check user time ( != 0) before computing simulation performance
53 * - Remove reinterpret_cast (for pending write) because of unexpected results
54 * - Add ASSERT in trace functions
55 *
56 * Revision 1.4  2005/09/14 14:08:24  buchmann
57 * Add Werror flag to compile the debug library.
58 * Split sc_clock implementation from sc_port to sc_clock.
59 * Add a helper message to write mealy functions avoiding combinational cycle.
60 *
61 * Bug fix :
62 * - cvs rules is no longer circular
63 * - bit2string
64 * - port binding (sc_in to sc_out)
65 * - error message from FSM rules checker
66 * - sc_time copy operator
67 *
68 * Code cleaning :
69 * - remove duplicated code (entity.cc and sc_port.cc)
70 * - remove duplicated declarations (internal_ext.h and internal.h)
71 *
72 * Revision 1.3  2005/06/22 09:15:03  buchmann
73 * Add some *_ext.h files to split internal implementation from API interface.
74 *
75 * Add -Wunused to detect unused functions.
76 *
77 * Include directory now contains API interface file only.
78 *
79 * Declar all the implementation/interface inside sc_core namespace as LRM 2.1
80 * advices.
81 *
82 * Remove casc namespace.
83 *
84 * Clean up dead code segments.
85 *
86 * Add hexadecimal dumping support.
87 *
88 * Add empty implementation of functions for object hierarchy traversal. (LRM 2.1)
89 *
90 * Bug fixes :
91 * - reference return of the following functions : operators =, |=, &= and so on.
92 * - range functions now return an sc_int_subref instead of an int.
93 *
94 * Revision 1.2  2005/05/30 12:33:50  buchmann
95 * Makefile :
96 * - use ${...} form instead of $(...) one.
97 * - add entity file object and entity, sc_signal headers.
98 *
99 * Split sc_signal(s)/sc_port(s) into two separate files.
100 * Add some codes to check hex2string function.
101 * Add some informations about -rdynamic when there is an error using dlopen.
102 * Add some ASSERT(s) for debug library.
103 * Add module name into the warning printing.
104 * Minor changes for PAT traces.
105 *
106 * Revision 1.1  2004/09/27 14:40:13  buchmann
107 * bug fix :
108 * - allow the use of user-defined structs in sc_signal/sc_in/sc_out/sc_inout
109 * - use sc_dt namespace like official SystemC engine
110 *
111 * add :
112 * - dump the signal/port/module dependancy graph in dot format
113 *
114 * Graph library is now splitted from the SystemCASS specific code.
115 *
116 */
117
118#include <iostream>
119#include <fstream>
120#include <stdio.h>
121#include <map>
122#include <string>
123
124#include "graph_cass.h"
125#include "sc_sensitive.h"
126#include "sc_module.h"
127#include "sc_port.h"
128#include "entity.h"
129#include "simplify_string.h" // simplify_string
130#include "sc_ver_ext.h"      // sc_version for dumping to DOT
131#ifdef HAVE_CONFIG_H
132#include "config.h"
133#endif
134
135using namespace std;
136
137namespace sc_core {
138
139#if 0
140static
141ostream& operator << (ostream& o,
142                      const Vertex & v)
143{
144#if 0
145      if (v.arcs == NULL)
146        o << v.name << "(" << v.module->ins_name << ")->(none)\n";
147      Arc *a;
148      for (a = v.arcs; a; a = a->next)
149        o << v.name << "(" << v.module->ins_name << ")->"
150                << a->tip->name << "(" << a->tip->module << ")\n";
151  return o;
152#endif
153        method_process_t* m = (method_process_t*)(v.data);
154  if (v.arcs == NULL)
155          o << *m << "\n";
156  Arc *a;
157  for (a = v.arcs; a; a = a->next) {
158          method_process_t* m2 = (method_process_t*)(a->tip->data);
159    o << *m << "->"
160                  << *m2 << ")\n";
161        }
162  return o;
163
164}
165#endif
166
167#if 0
168static
169ostream&
170operator << (ostream &o,
171                         const Graph &g)
172{
173  Vertex     *v;
174    for (v = g.vertices; v < g.vertices + g.n; v++) {
175        o << *v;
176    }
177    return o;
178}
179#endif
180
181std::map<const method_process_t*,Vertex*> m_v;
182
183/* Ajoute un arc */ 
184void add_arcs(const method_process_t &mp, const sc_module &module)
185{
186        std::map<const method_process_t*,Vertex*>::iterator i;
187  for (i =      m_v.begin ();    i != m_v.end (); ++i) {
188          if (i->first->module == &module)
189                        new_arc (m_v[&mp],i->second);
190        }
191}
192
193/* Ajoute un arc */ 
194void add_arcs(const  method_process_t &mp,
195              tab_t *signal_pointer)
196{
197  equi_t &e = get_equi (signal_pointer);
198  equi_t::iterator i;
199  for (i = e.begin (); i != e.end (); ++i) {
200                const char *kind = i->kind ();
201    if (strstr (kind,"out")) {
202                        const sc_port_base &port = *(i->port);
203                  const sc_module &module = port.get_module ();
204                        if (&module == mp.module)
205                                continue;
206                        add_arcs (mp, module);
207      break;
208                }
209  }
210}
211
212void
213add_arcs(const method_process_t &mp)
214{
215  sensitivity_list_t::const_iterator port_bound;
216        for (port_bound = mp.sensitivity_list.begin(); port_bound != mp.sensitivity_list.end(); ++port_bound) {
217      // pour tous les ports/signaux p associés à la fonction au couple m
218        /* si pp est un port de sortie d'une autre fonction de mealy,
219           crée un arc entre m et mm */
220        /* on ne peut pas savoir si un port est la sortie d'une fonction de mealy.
221           on va donc chercher à savoir si c'est un port de sortie d'un automate de moore,
222           sinon on considère que c'est une sortie de mealy.
223        */
224
225      add_arcs(mp, port_bound->get_interface().get_pointer ());
226    }
227}
228
229/* Construit le graph de dépendance des signaux de Mealy */
230/* lm est la liste des fonctions de Mealy */
231/* -----
232   Graph
233   -----
234   node = module
235   edge = dependency
236
237   Vertex is an array of (method_process_t*)
238   Edge is a couple Vertex->Vertex.
239*/
240extern Graph*
241makegraph (const method_process_list_t *lm)
242{
243  method_process_list_t::const_iterator mp;
244
245  int         n = 0; /* Number of vertices */
246  Graph      *g;
247  Vertex     *v;
248 
249  /* Compute the number of vertices in the graph:
250   * The vertices set is the method set. */
251 
252/*  for (m = lm->begin(); m != lm->end(); m++)
253    n++;*/
254  n = lm->size ();
255 
256  /* Create the graph */
257  g = gb_new_graph(n);
258
259  /* Associate the netlist elements to the graph vertices, and vice-versa */
260  v = g->vertices;
261
262  /* initialisation des vertices */
263  for (mp = lm->begin(); mp != lm->end(); ++mp) {
264    v->data = *mp;
265    m_v[*mp] = v++;
266  }
267
268  for (mp = lm->begin(); mp != lm->end(); ++mp) { 
269    // pour tous couples m, instance module/function de la liste lm
270    add_arcs (**mp);
271  }
272
273  return g;
274}   
275
276/*
277void
278dot_write_edge (const  method_process_t &mp,
279                tab_t *signal_pointer)
280{
281  equi_t &e = get_equi (signal_pointer);
282  equi_t::iterator i;
283  for (i = e.begin (); i != e.end (); ++i) {
284                const char *kind = i->kind ();
285    if (strstr (kind,"out")) {
286                        const sc_port_base &port = *(i->port);
287                  const sc_module &module = port.get_module ();
288                        if (&module == mp.module)
289                                continue;
290                        add_arcs (mp, module);
291            o << "edge [label="
292        << "];\n";
293      o << " -> ";
294      o << ";\n";
295                }
296  }
297}
298
299static
300bool
301dot_write_edge (ofstream &o,
302                const method_process_t &mp)
303{
304  sensitivity_list_t::const_iterator port_bound;
305        for (port_bound = mp.sensitivity_list.begin(); port_bound != mp.sensitivity_list.end(); ++port_bound)
306      dot_write_edge (o, mp, port_bound->get_interface().get_pointer ());
307}
308
309static
310bool
311dot_write (ofstream &o,
312           const method_process_list_t &lm)
313{
314  // Printing into dot file
315  string s;
316  method_process_list_t::const_iterator mp;
317  for (mp = lm.begin(); mp != lm.end(); ++mp) {
318    method_process_t *amp = *mp;
319    sc_module *module = amp->module;
320    o << "node [name="
321//      << simplify_name(module.get_name().c_str(),s)
322      << "];\n";
323  }
324  for (mp = lm->begin(); mp != lm->end(); ++mp)
325    dot_write (o, **mp);
326}
327*/
328
329static
330string&
331get_method_process_fullname (string &name, 
332                             const method_process_t &mp)
333{
334  sc_module *module = mp.module;
335  name = module->name ();
336  name += "_";
337  name += mp.name;
338  return name;
339}
340
341static
342bool
343dot_write (ofstream &o,
344           const Graph &g)
345{
346  string name1,name2,s;
347  // Printing into dot file
348  for (int i = 0; i < g.n; ++i)
349  { // Printing node list
350    Vertex *v = g.vertices + i;
351    method_process_t *mp     = (method_process_t*) (v->data);
352    get_method_process_fullname (name1,*mp);
353    const char *pname1 = name1.c_str();
354    o << "node [name=";
355    o.width (35);
356    o << simplify_name(pname1,s);
357    o << "];\n";
358  }
359  for (int i = 0; i < g.n; ++i)
360  { // Printing edge list
361    Vertex *v1 = g.vertices + i;
362    method_process_t *mp1     = (method_process_t*) (v1->data);
363    get_method_process_fullname (name1,*mp1);
364    const char *pname1 = name1.c_str();
365    for (Arc *a = v1->arcs; a != NULL; a = a->next)
366    {
367      Vertex *v2 = a->tip;
368      method_process_t *mp2 = (method_process_t*) (v2->data);
369      get_method_process_fullname (name2,*mp2);
370      const char *pname2 = name2.c_str();
371      o.width (35);
372      o << simplify_name(pname2,s);
373      o << " -> ";
374      o.width (35);
375      o << simplify_name(pname1,s);
376      o << ";\n";
377    }
378  }
379
380  return true;
381}
382
383extern bool
384graph2dot (const char *name,
385           const Graph &g)
386{
387        if (!name)
388                return false;
389        string filename;
390        filename =  name;
391        filename += ".dot";
392        ofstream o;
393  o.open (filename.c_str(),ios::out | ios::trunc);
394        if (o.is_open () == false)
395                return false;
396        o << "// Module dependency graph\n"
397       "// Generated by "
398    << sc_version () << "\n";
399        o << "strict digraph " << name << " {\n";
400  o << "node [shape=box];\n";
401//       "concentrate=true;\n";
402  o << left;
403        dot_write (o,g);
404  // Closing dot file
405        o << "}\n";
406        o.close ();
407  if (dump_stage)
408    cerr << "Module dependency graph written into '" 
409         << filename << "'.\n";
410        return true;
411}
412
413} // end of sc_core namespace
414
Note: See TracBrowser for help on using the repository browser.