source: sources/src/graph_cass.cc @ 22

Last change on this file since 22 was 17, checked in by buchmann, 16 years ago

Fix :

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