source: sources/src/graph_cass.cc @ 3

Last change on this file since 3 was 1, checked in by buchmann, 17 years ago

Initial import from CVS repository

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