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

Last change on this file since 49 was 20, checked in by nipo, 16 years ago

Sync up with trunk changes

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 <cstdio>
121#include <cstring>
122#include <map>
123#include <string>
124
125#include "graph_cass.h"
126#include "sc_sensitive.h"
127#include "sc_module.h"
128#include "sc_port.h"
129#include "entity.h"
130#include "simplify_string.h" // simplify_string
131#include "sc_ver_ext.h"      // sc_version for dumping to DOT
132#ifdef HAVE_CONFIG_H
133#include "config.h"
134#endif
135
136using namespace std;
137
138namespace sc_core {
139
140#if 0
141static
142ostream& operator << (ostream& o,
143                      const Vertex & v)
144{
145#if 0
146      if (v.arcs == NULL)
147        o << v.name << "(" << v.module->ins_name << ")->(none)\n";
148      Arc *a;
149      for (a = v.arcs; a; a = a->next)
150        o << v.name << "(" << v.module->ins_name << ")->"
151                << a->tip->name << "(" << a->tip->module << ")\n";
152  return o;
153#endif
154        method_process_t* m = (method_process_t*)(v.data);
155  if (v.arcs == NULL)
156          o << *m << "\n";
157  Arc *a;
158  for (a = v.arcs; a; a = a->next) {
159          method_process_t* m2 = (method_process_t*)(a->tip->data);
160    o << *m << "->"
161                  << *m2 << ")\n";
162        }
163  return o;
164
165}
166#endif
167
168#if 0
169static
170ostream&
171operator << (ostream &o,
172                         const Graph &g)
173{
174  Vertex     *v;
175    for (v = g.vertices; v < g.vertices + g.n; v++) {
176        o << *v;
177    }
178    return o;
179}
180#endif
181
182std::map<const method_process_t*,Vertex*> m_v;
183
184/* Ajoute un arc */ 
185void add_arcs(const method_process_t &mp, const sc_module &module)
186{
187        std::map<const method_process_t*,Vertex*>::iterator i;
188  for (i =      m_v.begin ();    i != m_v.end (); ++i) {
189          if (i->first->module == &module)
190                        new_arc (m_v[&mp],i->second);
191        }
192}
193
194/* Ajoute un arc */ 
195void add_arcs(const  method_process_t &mp,
196              tab_t *signal_pointer)
197{
198  equi_t &e = get_equi (signal_pointer);
199  equi_t::iterator i;
200  for (i = e.begin (); i != e.end (); ++i) {
201                const char *kind = i->kind ();
202    if (strstr (kind,"out")) {
203                        const sc_port_base &port = *(i->port);
204                  const sc_module &module = port.get_module ();
205                        if (&module == mp.module)
206                                continue;
207                        add_arcs (mp, module);
208      break;
209                }
210  }
211}
212
213void
214add_arcs(const method_process_t &mp)
215{
216  sensitivity_list_t::const_iterator port_bound;
217        for (port_bound = mp.sensitivity_list.begin(); port_bound != mp.sensitivity_list.end(); ++port_bound) {
218      // pour tous les ports/signaux p associés à la fonction au couple m
219        /* si pp est un port de sortie d'une autre fonction de mealy,
220           crée un arc entre m et mm */
221        /* on ne peut pas savoir si un port est la sortie d'une fonction de mealy.
222           on va donc chercher à savoir si c'est un port de sortie d'un automate de moore,
223           sinon on considère que c'est une sortie de mealy.
224        */
225
226      add_arcs(mp, port_bound->get_interface().get_pointer ());
227    }
228}
229
230/* Construit le graph de dépendance des signaux de Mealy */
231/* lm est la liste des fonctions de Mealy */
232/* -----
233   Graph
234   -----
235   node = module
236   edge = dependency
237
238   Vertex is an array of (method_process_t*)
239   Edge is a couple Vertex->Vertex.
240*/
241extern Graph*
242makegraph (const method_process_list_t *lm)
243{
244  method_process_list_t::const_iterator mp;
245
246  int         n = 0; /* Number of vertices */
247  Graph      *g;
248  Vertex     *v;
249 
250  /* Compute the number of vertices in the graph:
251   * The vertices set is the method set. */
252 
253/*  for (m = lm->begin(); m != lm->end(); m++)
254    n++;*/
255  n = lm->size ();
256 
257  /* Create the graph */
258  g = gb_new_graph(n);
259
260  /* Associate the netlist elements to the graph vertices, and vice-versa */
261  v = g->vertices;
262
263  /* initialisation des vertices */
264  for (mp = lm->begin(); mp != lm->end(); ++mp) {
265    v->data = *mp;
266    m_v[*mp] = v++;
267  }
268
269  for (mp = lm->begin(); mp != lm->end(); ++mp) { 
270    // pour tous couples m, instance module/function de la liste lm
271    add_arcs (**mp);
272  }
273
274  return g;
275}   
276
277/*
278void
279dot_write_edge (const  method_process_t &mp,
280                tab_t *signal_pointer)
281{
282  equi_t &e = get_equi (signal_pointer);
283  equi_t::iterator i;
284  for (i = e.begin (); i != e.end (); ++i) {
285                const char *kind = i->kind ();
286    if (strstr (kind,"out")) {
287                        const sc_port_base &port = *(i->port);
288                  const sc_module &module = port.get_module ();
289                        if (&module == mp.module)
290                                continue;
291                        add_arcs (mp, module);
292            o << "edge [label="
293        << "];\n";
294      o << " -> ";
295      o << ";\n";
296                }
297  }
298}
299
300static
301bool
302dot_write_edge (ofstream &o,
303                const method_process_t &mp)
304{
305  sensitivity_list_t::const_iterator port_bound;
306        for (port_bound = mp.sensitivity_list.begin(); port_bound != mp.sensitivity_list.end(); ++port_bound)
307      dot_write_edge (o, mp, port_bound->get_interface().get_pointer ());
308}
309
310static
311bool
312dot_write (ofstream &o,
313           const method_process_list_t &lm)
314{
315  // Printing into dot file
316  string s;
317  method_process_list_t::const_iterator mp;
318  for (mp = lm.begin(); mp != lm.end(); ++mp) {
319    method_process_t *amp = *mp;
320    sc_module *module = amp->module;
321    o << "node [name="
322//      << simplify_name(module.get_name().c_str(),s)
323      << "];\n";
324  }
325  for (mp = lm->begin(); mp != lm->end(); ++mp)
326    dot_write (o, **mp);
327}
328*/
329
330static
331string&
332get_method_process_fullname (string &name, 
333                             const method_process_t &mp)
334{
335  sc_module *module = mp.module;
336  name = module->name ();
337  name += "_";
338  name += mp.name;
339  return name;
340}
341
342static
343bool
344dot_write (ofstream &o,
345           const Graph &g)
346{
347  string name1,name2,s;
348  // Printing into dot file
349  for (int i = 0; i < g.n; ++i)
350  { // Printing node list
351    Vertex *v = g.vertices + i;
352    method_process_t *mp     = (method_process_t*) (v->data);
353    get_method_process_fullname (name1,*mp);
354    const char *pname1 = name1.c_str();
355    o << "node [name=";
356    o.width (35);
357    o << simplify_name(pname1,s);
358    o << "];\n";
359  }
360  for (int i = 0; i < g.n; ++i)
361  { // Printing edge list
362    Vertex *v1 = g.vertices + i;
363    method_process_t *mp1     = (method_process_t*) (v1->data);
364    get_method_process_fullname (name1,*mp1);
365    const char *pname1 = name1.c_str();
366    for (Arc *a = v1->arcs; a != NULL; a = a->next)
367    {
368      Vertex *v2 = a->tip;
369      method_process_t *mp2 = (method_process_t*) (v2->data);
370      get_method_process_fullname (name2,*mp2);
371      const char *pname2 = name2.c_str();
372      o.width (35);
373      o << simplify_name(pname2,s);
374      o << " -> ";
375      o.width (35);
376      o << simplify_name(pname1,s);
377      o << ";\n";
378    }
379  }
380
381  return true;
382}
383
384extern bool
385graph2dot (const char *name,
386           const Graph &g)
387{
388        if (!name)
389                return false;
390        string filename;
391        filename =  name;
392        filename += ".dot";
393        ofstream o;
394  o.open (filename.c_str(),ios::out | ios::trunc);
395        if (o.is_open () == false)
396                return false;
397        o << "// Module dependency graph\n"
398       "// Generated by "
399    << sc_version () << "\n";
400        o << "strict digraph " << name << " {\n";
401  o << "node [shape=box];\n";
402//       "concentrate=true;\n";
403  o << left;
404        dot_write (o,g);
405  // Closing dot file
406        o << "}\n";
407        o.close ();
408  if (dump_stage)
409    cerr << "Module dependency graph written into '" 
410         << filename << "'.\n";
411        return true;
412}
413
414} // end of sc_core namespace
415
Note: See TracBrowser for help on using the repository browser.