source: trunk/platforms/tsar_generic_leti/top.cpp @ 678

Last change on this file since 678 was 664, checked in by alain, 11 years ago

Improved platform supporting both external an internal peripherals.
Iti has been validated with the GIET_VM for the following xml mappingss:

  • 4c_4p_sort_leti
  • 4c_4p_sort_leti_ext
  • 4c_4p_transpose_leti
  • 4c_4p_transpose_leti_ext
  • 4c_1p_four_leti_ext
File size: 58.3 KB
Line 
1/////////////////////////////////////////////////////////////////////////
2// File: top.cpp (for tsar_generic_leti)
3// Author: Alain Greiner
4// Copyright: UPMC/LIP6
5// Date : february 2014
6// This program is released under the GNU public license
7/////////////////////////////////////////////////////////////////////////
8// This file define a generic TSAR architecture.
9// The processor is a MIPS32 processor wrapped in a GDB server
10// (this is defined in the tsar_xbar_cluster).
11//
12// The seg_reset_base and seg_kcode_base addresses are not constrained
13// to be 0xBFC00000 and 0x80000000.
14//
15// It does not use an external ROM, as the boot code must be (pre)loaded
16// in cluster (0,0) memory.
17//
18// The physical address space is 40 bits.
19// The 8 address MSB bits define the cluster index.
20//
21// The main hardware parameters are the mesh size (X_SIZE / Y_SIZE),
22// and the number of ptocessors per cluster (NB_PROCS_MAX).
23// The number of clusters cannot be larger than 256.
24// The number of processors per cluster cannot be larger than 4.
25//
26// Each cluster contains:
27// - 5 dspin_local_crossbar (local interconnect)
28// - 5 dspin_router (global interconnect)
29// - up to 4 vci_cc_vcache wrapping a MIPS32 processor
30// - 1 vci_mem_cache
31// - 1 vci_xicu
32// - 1 vci_simple_ram (to model the L3 cache).
33//
34// Each processor receive 4 consecutive IRQ lines from the local XICU.
35//
36// In all clusters, the MEMC IRQ line (signaling a late write error)
37// is connected to XICU HWI[8]
38// The cluster (0,0) contains two "internal" peripherals:
39// - one block device controller, whose IRQ is connected to XICU HWI[9].
40// - one single channel TTY controller, whose IRQ is connected to XICU HWI[10].
41//
42// The cluster internal architecture is defined in file tsar_leti_cluster,
43// that must be considered as an extension of this top.cpp file.
44//
45// Besides the hardware components in clusters, "external" peripherals
46// are connected to an external IO bus (implemented as a vci_local_crossbar):
47// - one disk controller
48// - one multi-channel ethernet controller
49// - one multi-channel chained buffer dma controller
50// - one multi-channel tty controller
51// - one frame buffer controller
52// - one 32 channels iopic controller
53//
54// This IOBUS is connected to the north  port of the DIR_CMD
55// and DIR_RSP routers, in cluster(X_SIZE-1, Y_SIZE-2).
56// For all external peripherals, the hardware interrupts (HWI) are
57// translated to write interrupts (WTI) by the iopic component:
58// - IOPIC HWI[1:0]     connected to IRQ_NIC_RX[1:0]
59// - IOPIC HWI[3:2]     connected to IRQ_NIC_TX[1:0]     
60// - IOPIC HWI[7:4]     connected to IRQ_CMA_TX[3:0]]
61// - IOPIC HWI[8]       connected to IRQ_BDEV
62// - IOPIC HWI[15:9]    unused       (grounded)
63// - IOPIC HWI[23:16]   connected to IRQ_TTY_RX[7:0]]
64// - IOPIC HWI[31:24]   connected to IRQ_TTY_TX[7:0]]
65////////////////////////////////////////////////////////////////////////////
66// The following parameters must be defined in the hard_config.h file :
67// - X_WIDTH          : number of bits for x coordinate (must be 4)
68// - Y_WIDTH          : number of bits for y coordinate (must be 4)
69// - X_SIZE           : number of clusters in a row
70// - Y_SIZE           : number of clusters in a column
71// - NB_PROCS_MAX     : number of processors per cluster (1, 2 or 4)
72// - NB_CMA_CHANNELS  : number of CMA channels in I/0 cluster (4 max)
73// - NB_TTY_CHANNELS  : number of TTY channels in I/O cluster (8 max)
74// - NB_NIC_CHANNELS  : number of NIC channels in I/O cluster (2 max)
75//
76// Some other hardware parameters are not used when compiling the OS,
77// and are only defined in this top.cpp file:
78// - XRAM_LATENCY     : external ram latency
79// - MEMC_WAYS        : L2 cache number of ways
80// - MEMC_SETS        : L2 cache number of sets
81// - L1_IWAYS         : L1 cache instruction number of ways
82// - L1_ISETS         : L1 cache instruction number of sets
83// - L1_DWAYS         : L1 cache data number of ways
84// - L1_DSETS         : L1 cache data number of sets
85// - FBUF_X_SIZE      : width of frame buffer (pixels)
86// - FBUF_Y_SIZE      : heigth of frame buffer (lines)
87// - BDEV_IMAGE_NAME  : file pathname for block device
88// - NIC_RX_NAME      : file pathname for NIC received packets
89// - NIC_TX_NAME      : file pathname for NIC transmited packets
90// - NIC_MAC4         : MAC address
91// - NIC_MAC2         : MAC address
92/////////////////////////////////////////////////////////////////////////
93// General policy for 40 bits physical address decoding:
94// All physical segments base addresses are multiple of 1 Mbytes
95// (=> the 24 LSB bits = 0, and the 16 MSB bits define the target)
96// The (X_WIDTH + Y_WIDTH) MSB bits (left aligned) define
97// the cluster index, and the LADR bits define the local index:
98//      |X_ID|Y_ID|  LADR |     OFFSET          |
99//      |  4 |  4 |   8   |       24            |
100/////////////////////////////////////////////////////////////////////////
101// General policy for 14 bits SRCID decoding:
102// Each component is identified by (x_id, y_id, l_id) tuple.
103//      |X_ID|Y_ID| L_ID |
104//      |  4 |  4 |  6   |
105/////////////////////////////////////////////////////////////////////////
106
107#include <systemc>
108#include <sys/time.h>
109#include <iostream>
110#include <sstream>
111#include <cstdlib>
112#include <cstdarg>
113#include <stdint.h>
114
115#include "gdbserver.h"
116#include "mapping_table.h"
117#include "tsar_leti_cluster.h"
118#include "vci_local_crossbar.h"
119#include "vci_dspin_initiator_wrapper.h"
120#include "vci_dspin_target_wrapper.h"
121#include "vci_multi_tty.h"
122#include "vci_multi_nic.h"
123#include "vci_chbuf_dma.h"
124#include "vci_block_device_tsar.h"
125#include "vci_framebuffer.h"
126#include "vci_iopic.h"
127#include "alloc_elems.h"
128
129//////////////////////////////////////////////////////////////////////////////////////////
130//    Parameters depending on the OS and software application         
131//    - path to hard_config file
132//    - path to binary code for the RAM loader
133//    - path to disk image for RAMDISK loader
134//    - path to disk image for IOC device
135//////////////////////////////////////////////////////////////////////////////////////////
136
137#define USE_GIET_VM     1
138#define USE_GIET_TSAR   0
139
140#if ( USE_GIET_VM and USE_GIET_TSAR )
141#error "Can't use Two different OS"
142#endif
143
144#if ( (not USE_GIET_VM) and (not USE_GIET_TSAR) )
145#error "You need to specify one OS"
146#endif
147
148#if USE_GIET_TSAR
149#include                         "../../softs/soft_transpose_giet/hard_config.h"
150#define BINARY_PATH_FOR_LOADER   "../../softs/soft_transpose_giet/bin.soft"
151#define RAMDISK_PATH_FOR_LOADER  "../../softs/soft_transpose_giet/images.raw@0x00800000:"
152#define DISK_IMAGE_PATH_FOR_IOC  "../../softs/soft_transpose_giet/images.raw"
153#endif
154
155#if USE_GIET_VM
156#include                         "../../../giet_vm/hard_config.h"
157#define BINARY_PATH_FOR_LOADER   "../../softs/tsar_boot/preloader.elf"
158#define RAMDISK_PATH_FOR_LOADER  "../../../giet_vm/hdd/virt_hdd.dmg@0x02000000:"
159#define DISK_IMAGE_PATH_FOR_IOC  "../../../giet_vm/hdd/virt_hdd.dmg"       
160#endif
161
162///////////////////////////////////////////////////
163//               Parallelisation
164///////////////////////////////////////////////////
165#define USE_OPENMP 0
166
167#if USE_OPENMP
168#include <omp.h>
169#endif
170
171///////////////////////////////////////////////////
172//  cluster index (from x,y coordinates)
173///////////////////////////////////////////////////
174
175#define cluster(x,y)   (y + (x << Y_WIDTH))
176
177#define min(a, b) (a < b ? a : b)
178
179///////////////////////////////////////////////////////////
180//          DSPIN parameters           
181///////////////////////////////////////////////////////////
182
183#define dspin_cmd_width      39
184#define dspin_rsp_width      32
185
186///////////////////////////////////////////////////////////
187//          VCI parameters           
188///////////////////////////////////////////////////////////
189
190#define vci_cell_width_int    4
191#define vci_cell_width_ext    8
192#define vci_address_width     40
193#define vci_plen_width        8
194#define vci_rerror_width      1
195#define vci_clen_width        1
196#define vci_rflag_width       1
197#define vci_srcid_width       14
198#define vci_pktid_width       4
199#define vci_trdid_width       4
200#define vci_wrplen_width      1
201
202
203/////////////////////////////////////////////////////////////////////////////////////////
204//    Secondary Hardware Parameters         
205/////////////////////////////////////////////////////////////////////////////////////////
206
207#define RESET_ADDRESS         0x0
208
209#define MAX_TTY_CHANNELS      8
210#define MAX_CMA_CHANNELS      4
211#define MAX_NIC_CHANNELS      2
212
213#define XRAM_LATENCY          0
214#define XRAM_SIZE             0x04000000    // 64 Mbytes per cluster
215
216#define MEMC_WAYS             16
217#define MEMC_SETS             256
218
219#define L1_IWAYS              4
220#define L1_ISETS              64
221
222#define L1_DWAYS              4
223#define L1_DSETS              64
224
225#define FBUF_X_SIZE           128
226#define FBUF_Y_SIZE           128
227
228#define NIC_MAC4              0XBABEF00D
229#define NIC_MAC2              0xBEEF
230#define NIC_RX_NAME           "./fake"
231#define NIC_TX_NAME           "./fake"
232
233#define NORTH                 0
234#define SOUTH                 1
235#define EAST                  2
236#define WEST                  3
237
238///////////////////////////////////////////////////////////////////////////////////////
239//     DEBUG Parameters default values         
240///////////////////////////////////////////////////////////////////////////////////////
241
242#define MAX_FROZEN_CYCLES     10000
243
244///////////////////////////////////////////////////////////////////////////////////////
245//     LOCAL TGTID & SRCID definition
246// For all components:  global TGTID = global SRCID = cluster_index
247///////////////////////////////////////////////////////////////////////////////////////
248
249#define MEMC_TGTID            0
250#define XICU_TGTID            1
251#define MTTY_TGTID            2
252#define BDEV_TGTID            3
253#define FBUF_TGTID            4
254#define MNIC_TGTID            5
255#define CDMA_TGTID            6
256#define IOPI_TGTID            7
257
258#define BDEV_SRCID            NB_PROCS_MAX
259#define CDMA_SRCID            NB_PROCS_MAX + 1
260#define IOPI_SRCID            NB_PROCS_MAX + 2
261
262//////////////////////////////////////////////////////////////////////////////////////
263//    Physical segments definition
264//////////////////////////////////////////////////////////////////////////////////////
265// - 3 segments are replicated in all clusters
266// - 2 segments are replicated in cluster[0,0] & [X_SIZE-1,Y_SIZE-1]
267// - 4 segments are only in cluster [X_SIZE-1,Y_SIZE-1]
268// The following values are for segments in cluster 0,
269// and these 32 bits values must be concatenate with the cluster
270// index (on 8 bits) to obtain the 40 bits address.
271//////////////////////////////////////////////////////////////////////////////////////
272
273   // in cluster [0,0] & [X_SIZE-1,Y_SIZE-1]
274
275   #define MTTY_BASE    0xF4000000
276   #define MTTY_SIZE    0x00001000   // 4 Kbytes
277
278   #define BDEV_BASE    0xF2000000
279   #define BDEV_SIZE    0x00001000   // 4 Kbytes
280
281   // in cluster [X_SIZE-1,Y_SIZE-1]
282
283   #define FBUF_BASE    0xF3000000
284   #define FBUF_SIZE    (FBUF_X_SIZE * FBUF_Y_SIZE * 2)
285
286   #define MNIC_BASE    0xF7000000
287   #define MNIC_SIZE    0x00800000   // 512 Kbytes (for 8 channels)
288
289   #define CDMA_BASE    0xF8000000
290   #define CDMA_SIZE    0x00004000 * NB_CMA_CHANNELS
291
292   #define IOPI_BASE    0xF9000000
293   #define IOPI_SIZE    0x00001000   // 4 Kbytes
294   
295   // replicated segments : address is extended to 40 bits by cluster_xy
296
297   #define MEMC_BASE    0x00000000
298   #define MEMC_SIZE    XRAM_SIZE
299
300   #define MCFG_BASE    0xE0000000
301   #define MCFG_SIZE    0x00001000   // 4 Kbytes per cluster
302
303   #define XICU_BASE    0xF0000000
304   #define XICU_SIZE    0x00001000   // 4 Kbytes per cluster
305
306bool stop_called = false;
307
308/////////////////////////////////
309int _main(int argc, char *argv[])
310{
311   using namespace sc_core;
312   using namespace soclib::caba;
313   using namespace soclib::common;
314
315   uint32_t ncycles          = 0xFFFFFFFF;         // max simulated cycles
316   size_t   threads          = 1;                  // simulator's threads number
317   bool     trace_ok         = false;              // trace activated
318   uint32_t trace_from       = 0;                  // trace start cycle
319   bool     trace_proc_ok    = false;              // detailed proc trace activated
320   size_t   trace_memc_ok    = false;              // detailed memc trace activated
321   size_t   trace_memc_id    = 0;                  // index of memc to be traced
322   size_t   trace_proc_id    = 0;                  // index of proc to be traced
323   uint32_t frozen_cycles    = MAX_FROZEN_CYCLES;  // monitoring frozen processor
324   struct   timeval t1,t2;
325   uint64_t ms1,ms2;
326
327   ////////////// command line arguments //////////////////////
328   if (argc > 1)
329   {
330      for (int n = 1; n < argc; n = n + 2)
331      {
332         if ((strcmp(argv[n], "-NCYCLES") == 0) && (n + 1 < argc))
333         {
334            ncycles = (uint64_t) strtol(argv[n + 1], NULL, 0);
335         }
336         else if ((strcmp(argv[n],"-DEBUG") == 0) && (n + 1 < argc))
337         {
338            trace_ok = true;
339            trace_from = (uint32_t) strtol(argv[n + 1], NULL, 0);
340         }
341         else if ((strcmp(argv[n], "-MEMCID") == 0) && (n + 1 < argc))
342         {
343            trace_memc_ok = true;
344            trace_memc_id = (size_t) strtol(argv[n + 1], NULL, 0);
345            size_t x = trace_memc_id >> Y_WIDTH;
346            size_t y = trace_memc_id & ((1<<Y_WIDTH)-1);
347
348            assert( (x < X_SIZE) and (y < (Y_SIZE-1)) and
349                  "MEMCID parameter refers a not valid memory cache");
350         }
351         else if ((strcmp(argv[n], "-PROCID") == 0) && (n + 1 < argc))
352         {
353            trace_proc_ok = true;
354            trace_proc_id = (size_t) strtol(argv[n + 1], NULL, 0);
355            size_t cluster_xy = trace_proc_id / NB_PROCS_MAX ;
356            size_t x          = cluster_xy >> Y_WIDTH;
357            size_t y          = cluster_xy & ((1<<Y_WIDTH)-1);
358            size_t l          = trace_proc_id % NB_PROCS_MAX ;
359
360            assert( (x < X_SIZE) and (y < (Y_SIZE-1)) and l < NB_PROCS_MAX and
361                  "PROCID parameter refers a not valid processor");
362         }
363         else if ((strcmp(argv[n], "-THREADS") == 0) && ((n + 1) < argc))
364         {
365            threads = (size_t) strtol(argv[n + 1], NULL, 0);
366            threads = (threads < 1) ? 1 : threads;
367         }
368         else if ((strcmp(argv[n], "-FROZEN") == 0) && (n + 1 < argc))
369         {
370            frozen_cycles = (uint32_t) strtol(argv[n + 1], NULL, 0);
371         }
372         else
373         {
374            std::cout << "   Arguments are (key,value) couples." << std::endl;
375            std::cout << "   The order is not important." << std::endl;
376            std::cout << "   Accepted arguments are :" << std::endl << std::endl;
377            std::cout << "     -NCYCLES number_of_simulated_cycles" << std::endl;
378            std::cout << "     -DEBUG debug_start_cycle" << std::endl;
379            std::cout << "     -THREADS simulator's threads number" << std::endl;
380            std::cout << "     -FROZEN max_number_of_lines" << std::endl;
381            std::cout << "     -PERIOD number_of_cycles between trace" << std::endl;
382            std::cout << "     -MEMCID index_memc_to_be_traced" << std::endl;
383            std::cout << "     -PROCID index_proc_to_be_traced" << std::endl;
384            exit(0);
385         }
386      }
387   }
388
389    // checking hardware parameters
390    assert( (X_SIZE <= 16) and
391            "The X_SIZE parameter cannot be larger than 16" );
392
393    assert( (Y_SIZE <= 16) and
394            "The Y_SIZE parameter cannot be larger than 16" );
395
396    assert( (NB_PROCS_MAX <= 4) and
397            "The NB_PROCS_MAX parameter cannot be larger than 4" );
398
399    assert( (NB_CMA_CHANNELS <= MAX_CMA_CHANNELS) and
400            "The NB_CMA_CHANNELS parameter cannot be larger than 4" );
401
402    assert( (NB_TTY_CHANNELS <= MAX_TTY_CHANNELS) and
403            "The NB_TTY_CHANNELS parameter cannot be larger than 8" );
404
405    assert( (NB_NIC_CHANNELS <= MAX_NIC_CHANNELS) and
406            "The NB_NIC_CHANNELS parameter cannot be larger than 2" );
407
408    assert( (vci_address_width == 40) and
409            "VCI address width with the GIET must be 40 bits" );
410
411    assert( (X_WIDTH == 4) and (Y_WIDTH == 4) and
412            "ERROR: you must have X_WIDTH == Y_WIDTH == 4");
413 
414    std::cout << std::endl;
415
416    std::cout << " - X_SIZE           = " << X_SIZE << std::endl;
417    std::cout << " - Y_SIZE           = " << Y_SIZE << std::endl;
418    std::cout << " - NB_PROCS_MAX     = " << NB_PROCS_MAX <<  std::endl;
419    std::cout << " - NB_DMA_CHANNELS  = " << NB_DMA_CHANNELS <<  std::endl;
420    std::cout << " - NB_TTY_CHANNELS  = " << NB_TTY_CHANNELS <<  std::endl;
421    std::cout << " - NB_NIC_CHANNELS  = " << NB_NIC_CHANNELS <<  std::endl;
422    std::cout << " - MEMC_WAYS        = " << MEMC_WAYS << std::endl;
423    std::cout << " - MEMC_SETS        = " << MEMC_SETS << std::endl;
424    std::cout << " - RAM_LATENCY      = " << XRAM_LATENCY << std::endl;
425    std::cout << " - MAX_FROZEN       = " << frozen_cycles << std::endl;
426    std::cout << " - MAX_CYCLES       = " << ncycles << std::endl;
427    std::cout << " - RESET_ADDRESS    = " << RESET_ADDRESS << std::endl;
428    std::cout << " - SOFT_PATH_NAME   = " << BINARY_PATH_FOR_LOADER << std::endl;
429    std::cout << " - DISK_IMAGE_PATH  = " << DISK_IMAGE_PATH_FOR_IOC << std::endl;
430
431    std::cout << std::endl;
432
433    // Internal and External VCI parameters definition
434    typedef soclib::caba::VciParams<vci_cell_width_int,
435                                    vci_plen_width,
436                                    vci_address_width,
437                                    vci_rerror_width,
438                                    vci_clen_width,
439                                    vci_rflag_width,
440                                    vci_srcid_width,
441                                    vci_pktid_width,
442                                    vci_trdid_width,
443                                    vci_wrplen_width> vci_param_int;
444
445    typedef soclib::caba::VciParams<vci_cell_width_ext,
446                                    vci_plen_width,
447                                    vci_address_width,
448                                    vci_rerror_width,
449                                    vci_clen_width,
450                                    vci_rflag_width,
451                                    vci_srcid_width,
452                                    vci_pktid_width,
453                                    vci_trdid_width,
454                                    vci_wrplen_width> vci_param_ext;
455
456#if USE_OPENMP
457   omp_set_dynamic(false);
458   omp_set_num_threads(threads);
459   std::cerr << "Built with openmp version " << _OPENMP << std::endl;
460#endif
461
462
463   ///////////////////////////////////////
464   //  Direct Network Mapping Table
465   ///////////////////////////////////////
466
467   MappingTable maptabd(vci_address_width, 
468                        IntTab(X_WIDTH + Y_WIDTH, 16 - X_WIDTH - Y_WIDTH), 
469                        IntTab(X_WIDTH + Y_WIDTH, vci_srcid_width - X_WIDTH - Y_WIDTH), 
470                        0x00FF000000ULL);
471
472   // replicated segments
473   for (size_t x = 0; x < X_SIZE; x++)
474   {
475      for (size_t y = 0; y < (Y_SIZE-1) ; y++)
476      {
477         sc_uint<vci_address_width> offset;
478         offset = ((sc_uint<vci_address_width>)cluster(x,y)) << 32;
479
480         std::ostringstream    si;
481         si << "seg_xicu_" << x << "_" << y;
482         maptabd.add(Segment(si.str(), XICU_BASE + offset, XICU_SIZE, 
483                  IntTab(cluster(x,y),XICU_TGTID), false));
484
485         std::ostringstream    sd;
486         sd << "seg_mcfg_" << x << "_" << y;
487         maptabd.add(Segment(sd.str(), MCFG_BASE + offset, MCFG_SIZE, 
488                  IntTab(cluster(x,y),MEMC_TGTID), false));
489
490         std::ostringstream    sh;
491         sh << "seg_memc_" << x << "_" << y;
492         maptabd.add(Segment(sh.str(), MEMC_BASE + offset, MEMC_SIZE, 
493                  IntTab(cluster(x,y),MEMC_TGTID), true));
494      }
495   }
496
497   // segments for peripherals in cluster(0,0)
498   maptabd.add(Segment("seg_tty0", MTTY_BASE, MTTY_SIZE, 
499               IntTab(cluster(0,0),MTTY_TGTID), false));
500
501   maptabd.add(Segment("seg_ioc0", BDEV_BASE, BDEV_SIZE, 
502               IntTab(cluster(0,0),BDEV_TGTID), false));
503
504   // segments for peripherals in cluster_io (X_SIZE-1,Y_SIZE-1)
505   sc_uint<vci_address_width> offset;
506   offset = ((sc_uint<vci_address_width>)cluster(X_SIZE-1,Y_SIZE-1)) << 32;
507
508   maptabd.add(Segment("seg_mtty", MTTY_BASE + offset, MTTY_SIZE, 
509               IntTab(cluster(X_SIZE-1, Y_SIZE-1),MTTY_TGTID), false));
510
511   maptabd.add(Segment("seg_fbuf", FBUF_BASE + offset, FBUF_SIZE, 
512               IntTab(cluster(X_SIZE-1, Y_SIZE-1),FBUF_TGTID), false));
513
514   maptabd.add(Segment("seg_bdev", BDEV_BASE + offset, BDEV_SIZE, 
515               IntTab(cluster(X_SIZE-1, Y_SIZE-1),BDEV_TGTID), false));
516
517   maptabd.add(Segment("seg_mnic", MNIC_BASE + offset, MNIC_SIZE, 
518               IntTab(cluster(X_SIZE-1, Y_SIZE-1),MNIC_TGTID), false));
519
520   maptabd.add(Segment("seg_cdma", CDMA_BASE + offset, CDMA_SIZE, 
521               IntTab(cluster(X_SIZE-1, Y_SIZE-1),CDMA_TGTID), false));
522
523   maptabd.add(Segment("seg_iopi", IOPI_BASE + offset, IOPI_SIZE, 
524               IntTab(cluster(X_SIZE-1, Y_SIZE-1),IOPI_TGTID), false));
525
526   std::cout << maptabd << std::endl;
527
528    /////////////////////////////////////////////////
529    // Ram network mapping table
530    /////////////////////////////////////////////////
531
532    MappingTable maptabx(vci_address_width, 
533                         IntTab(X_WIDTH+Y_WIDTH), 
534                         IntTab(X_WIDTH+Y_WIDTH), 
535                         0x00FF000000ULL);
536
537    for (size_t x = 0; x < X_SIZE; x++)
538    {
539        for (size_t y = 0; y < (Y_SIZE-1) ; y++)
540        { 
541            sc_uint<vci_address_width> offset;
542            offset = (sc_uint<vci_address_width>)cluster(x,y) 
543                      << (vci_address_width-X_WIDTH-Y_WIDTH);
544
545            std::ostringstream sh;
546            sh << "x_seg_memc_" << x << "_" << y;
547
548            maptabx.add(Segment(sh.str(), MEMC_BASE + offset, 
549                     MEMC_SIZE, IntTab(cluster(x,y)), false));
550        }
551    }
552    std::cout << maptabx << std::endl;
553
554    ////////////////////
555    // Signals
556    ///////////////////
557
558    sc_clock                          signal_clk("clk");
559    sc_signal<bool>                   signal_resetn("resetn");
560
561    // IRQs from external peripherals
562    sc_signal<bool>                   signal_irq_bdev;
563    sc_signal<bool>                   signal_irq_mnic_rx[NB_NIC_CHANNELS];
564    sc_signal<bool>                   signal_irq_mnic_tx[NB_NIC_CHANNELS];
565    sc_signal<bool>                   signal_irq_mtty_rx[NB_TTY_CHANNELS];
566//  sc_signal<bool>                   signal_irq_mtty_tx[NB_TTY_CHANNELS];
567    sc_signal<bool>                   signal_irq_cdma[NB_CMA_CHANNELS];
568    sc_signal<bool>                   signal_irq_false;
569
570   // Horizontal inter-clusters DSPIN signals
571   DspinSignals<dspin_cmd_width>** signal_dspin_h_cmd_inc =
572      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_h_cmd_inc", X_SIZE-1, Y_SIZE-1);
573   DspinSignals<dspin_cmd_width>** signal_dspin_h_cmd_dec =
574      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_h_cmd_dec", X_SIZE-1, Y_SIZE-1);
575
576   DspinSignals<dspin_rsp_width>** signal_dspin_h_rsp_inc =
577      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_h_rsp_inc", X_SIZE-1, Y_SIZE-1);
578   DspinSignals<dspin_rsp_width>** signal_dspin_h_rsp_dec =
579      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_h_rsp_dec", X_SIZE-1, Y_SIZE-1);
580
581   DspinSignals<dspin_cmd_width>** signal_dspin_h_m2p_inc =
582      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_h_m2p_inc", X_SIZE-1, Y_SIZE-1);
583   DspinSignals<dspin_cmd_width>** signal_dspin_h_m2p_dec =
584      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_h_m2p_dec", X_SIZE-1, Y_SIZE-1);
585
586   DspinSignals<dspin_rsp_width>** signal_dspin_h_p2m_inc =
587      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_h_p2m_inc", X_SIZE-1, Y_SIZE-1);
588   DspinSignals<dspin_rsp_width>** signal_dspin_h_p2m_dec =
589      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_h_p2m_dec", X_SIZE-1, Y_SIZE-1);
590
591   DspinSignals<dspin_cmd_width>** signal_dspin_h_cla_inc =
592      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_h_cla_inc", X_SIZE-1, Y_SIZE-1);
593   DspinSignals<dspin_cmd_width>** signal_dspin_h_cla_dec =
594      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_h_cla_dec", X_SIZE-1, Y_SIZE-1);
595
596   // Vertical inter-clusters DSPIN signals
597   DspinSignals<dspin_cmd_width>** signal_dspin_v_cmd_inc =
598      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_v_cmd_inc", X_SIZE, Y_SIZE-2);
599   DspinSignals<dspin_cmd_width>** signal_dspin_v_cmd_dec =
600      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_v_cmd_dec", X_SIZE, Y_SIZE-2);
601
602   DspinSignals<dspin_rsp_width>** signal_dspin_v_rsp_inc =
603      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_v_rsp_inc", X_SIZE, Y_SIZE-2);
604   DspinSignals<dspin_rsp_width>** signal_dspin_v_rsp_dec =
605      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_v_rsp_dec", X_SIZE, Y_SIZE-2);
606
607   DspinSignals<dspin_cmd_width>** signal_dspin_v_m2p_inc =
608      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_v_m2p_inc", X_SIZE, Y_SIZE-2);
609   DspinSignals<dspin_cmd_width>** signal_dspin_v_m2p_dec =
610      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_v_m2p_dec", X_SIZE, Y_SIZE-2);
611
612   DspinSignals<dspin_rsp_width>** signal_dspin_v_p2m_inc =
613      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_v_p2m_inc", X_SIZE, Y_SIZE-2);
614   DspinSignals<dspin_rsp_width>** signal_dspin_v_p2m_dec =
615      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_v_p2m_dec", X_SIZE, Y_SIZE-2);
616
617   DspinSignals<dspin_cmd_width>** signal_dspin_v_cla_inc =
618      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_v_cla_inc", X_SIZE, Y_SIZE-2);
619   DspinSignals<dspin_cmd_width>** signal_dspin_v_cla_dec =
620      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_v_cla_dec", X_SIZE, Y_SIZE-2);
621
622   // Mesh boundaries DSPIN signals (Most of those signals are not used...)
623   DspinSignals<dspin_cmd_width>*** signal_dspin_bound_cmd_in =
624      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_bound_cmd_in" , X_SIZE, Y_SIZE-1, 4);
625   DspinSignals<dspin_cmd_width>*** signal_dspin_bound_cmd_out =
626      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_bound_cmd_out", X_SIZE, Y_SIZE-1, 4);
627
628   DspinSignals<dspin_rsp_width>*** signal_dspin_bound_rsp_in =
629      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_bound_rsp_in" , X_SIZE, Y_SIZE-1, 4);
630   DspinSignals<dspin_rsp_width>*** signal_dspin_bound_rsp_out =
631      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_bound_rsp_out", X_SIZE, Y_SIZE-1, 4);
632
633   DspinSignals<dspin_cmd_width>*** signal_dspin_bound_m2p_in =
634      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_bound_m2p_in" , X_SIZE, Y_SIZE-1, 4);
635   DspinSignals<dspin_cmd_width>*** signal_dspin_bound_m2p_out =
636      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_bound_m2p_out", X_SIZE, Y_SIZE-1, 4);
637
638   DspinSignals<dspin_rsp_width>*** signal_dspin_bound_p2m_in =
639      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_bound_p2m_in" , X_SIZE, Y_SIZE-1, 4);
640   DspinSignals<dspin_rsp_width>*** signal_dspin_bound_p2m_out =
641      alloc_elems<DspinSignals<dspin_rsp_width> >("signal_dspin_bound_p2m_out", X_SIZE, Y_SIZE-1, 4);
642
643   DspinSignals<dspin_cmd_width>*** signal_dspin_bound_cla_in =
644      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_bound_cla_in" , X_SIZE, Y_SIZE-1, 4);
645   DspinSignals<dspin_cmd_width>*** signal_dspin_bound_cla_out =
646      alloc_elems<DspinSignals<dspin_cmd_width> >("signal_dspin_bound_cla_out", X_SIZE, Y_SIZE-1, 4);
647
648   // VCI signals for iobus and peripherals
649   VciSignals<vci_param_int>    signal_vci_ini_bdev("signal_vci_ini_bdev");
650   VciSignals<vci_param_int>    signal_vci_ini_cdma("signal_vci_ini_cdma");
651   VciSignals<vci_param_int>    signal_vci_ini_iopi("signal_vci_ini_iopi");
652
653   VciSignals<vci_param_int>*   signal_vci_ini_proc = 
654       alloc_elems<VciSignals<vci_param_int> >("signal_vci_ini_proc", NB_PROCS_MAX );
655
656   VciSignals<vci_param_int>    signal_vci_tgt_memc("signal_vci_tgt_memc");
657   VciSignals<vci_param_int>    signal_vci_tgt_xicu("signal_vci_tgt_xicu");
658   VciSignals<vci_param_int>    signal_vci_tgt_bdev("signal_vci_tgt_bdev");
659   VciSignals<vci_param_int>    signal_vci_tgt_mtty("signal_vci_tgt_mtty");
660   VciSignals<vci_param_int>    signal_vci_tgt_fbuf("signal_vci_tgt_fbuf");
661   VciSignals<vci_param_int>    signal_vci_tgt_mnic("signal_vci_tgt_mnic");
662   VciSignals<vci_param_int>    signal_vci_tgt_cdma("signal_vci_tgt_cdma");
663   VciSignals<vci_param_int>    signal_vci_tgt_iopi("signal_vci_tgt_iopi");
664
665   VciSignals<vci_param_int>    signal_vci_cmd_to_noc("signal_vci_cmd_to_noc");
666   VciSignals<vci_param_int>    signal_vci_cmd_from_noc("signal_vci_cmd_from_noc");
667   
668   ////////////////////////////
669   //      Loader   
670   ////////////////////////////
671
672#if USE_IOC_RDK
673   soclib::common::Loader loader( BINARY_PATH_FOR_LOADER, RAMDISK_PATH_FOR_LOADER );
674#else
675   soclib::common::Loader loader( BINARY_PATH_FOR_LOADER );
676#endif
677
678   ///////////////////////////
679   //  processor iss
680   ///////////////////////////
681
682   typedef soclib::common::GdbServer<soclib::common::Mips32ElIss> proc_iss;
683   proc_iss::set_loader( loader );
684
685   //////////////////////////////////////////////////////////////
686   // mesh construction: only (X_SIZE) * (Y_SIZE-1) clusters
687   //////////////////////////////////////////////////////////////
688
689   TsarLetiCluster<dspin_cmd_width,
690                   dspin_rsp_width,
691                   vci_param_int,
692                   vci_param_ext>*          clusters[X_SIZE][Y_SIZE-1];
693
694#if USE_OPENMP
695#pragma omp parallel
696    {
697#pragma omp for
698#endif
699        for (size_t i = 0; i  < (X_SIZE * (Y_SIZE-1)); i++)
700        {
701            size_t x = i / (Y_SIZE-1);
702            size_t y = i % (Y_SIZE-1);
703
704#if USE_OPENMP
705#pragma omp critical
706            {
707#endif
708            std::cout << std::endl;
709            std::cout << "Cluster_" << std::dec << x << "_" << y
710                      << " with cluster_xy = " << std::hex << cluster(x,y) << std::endl;
711            std::cout << std::endl;
712
713            std::ostringstream cluster_name;
714            cluster_name <<  "cluster_" << std::dec << x << "_" << y;
715
716            clusters[x][y] = new TsarLetiCluster<dspin_cmd_width,
717                                                 dspin_rsp_width,
718                                                 vci_param_int,
719                                                 vci_param_ext>
720            (
721                cluster_name.str().c_str(),
722                NB_PROCS_MAX,
723                x,
724                y,
725                cluster(x,y),
726                maptabd,
727                maptabx,
728                RESET_ADDRESS,
729                X_WIDTH,
730                Y_WIDTH,
731                vci_srcid_width - X_WIDTH - Y_WIDTH,   // l_id width,
732                MEMC_TGTID,
733                XICU_TGTID,
734                MTTY_TGTID,
735                BDEV_TGTID,
736                DISK_IMAGE_PATH_FOR_IOC,
737                MEMC_WAYS,
738                MEMC_SETS,
739                L1_IWAYS,
740                L1_ISETS,
741                L1_DWAYS,
742                L1_DSETS,
743                XRAM_LATENCY,
744                loader,
745                frozen_cycles,
746                trace_from,
747                trace_proc_ok, 
748                trace_proc_id,
749                trace_memc_ok, 
750                trace_memc_id
751            );
752
753#if USE_OPENMP
754            } // end critical
755#endif
756        } // end for
757#if USE_OPENMP
758    }
759#endif
760
761    //////////////////////////////////////////////////////////////////
762    // IO bus and external peripherals in cluster[X_SIZE-1,Y_SIZE]
763    // - 6 local targets    : FBF, TTY, CMA, NIC, PIC, IOC
764    // - 3 local initiators : IOC, CMA, PIC
765    // There is no PROC, no MEMC and no XICU in this cluster,
766    // but the crossbar has (NB_PROCS_MAX + 3) intiators and
767    // 8 targets, in order to use the same SRCID and TGTID space
768    // (same mapping table for the internal components,
769    //  and for the external peripherals)
770    //////////////////////////////////////////////////////////////////
771
772    std::cout << std::endl;
773    std::cout << " Building IO cluster (external peripherals)" << std::endl;
774    std::cout << std::endl;
775 
776    size_t cluster_io = cluster(X_SIZE-1, Y_SIZE-1);
777
778    //////////// vci_local_crossbar 
779    VciLocalCrossbar<vci_param_int>*
780    iobus = new VciLocalCrossbar<vci_param_int>(
781                "iobus",
782                maptabd,                      // mapping table
783                cluster_io,                   // cluster_xy
784                NB_PROCS_MAX + 3,             // number of local initiators
785                8,                            // number of local targets
786                BDEV_TGTID );                 // default target index
787
788    //////////// vci_framebuffer                       
789    VciFrameBuffer<vci_param_int>*
790    fbuf = new VciFrameBuffer<vci_param_int>(
791                "fbuf",
792                IntTab(cluster_io, FBUF_TGTID),
793                maptabd,
794                FBUF_X_SIZE, FBUF_Y_SIZE );
795
796    ////////////  vci_block_device               
797    VciBlockDeviceTsar<vci_param_int>*
798    bdev = new VciBlockDeviceTsar<vci_param_int>(
799                "bdev",
800                maptabd,
801                IntTab(cluster_io, BDEV_SRCID),
802                IntTab(cluster_io, BDEV_TGTID),
803                DISK_IMAGE_PATH_FOR_IOC,
804                512,                          // block size
805                64 );                         // burst size
806
807    //////////// vci_multi_nic               
808    VciMultiNic<vci_param_int>*
809    mnic = new VciMultiNic<vci_param_int>(
810                "mnic",
811                IntTab(cluster_io, MNIC_TGTID),
812                maptabd,
813                NB_NIC_CHANNELS,
814                NIC_MAC4,
815                NIC_MAC2,
816                NIC_RX_NAME,
817                NIC_TX_NAME );
818
819    ///////////// vci_chbuf_dma                   
820    VciChbufDma<vci_param_int>*
821    cdma = new VciChbufDma<vci_param_int>(
822                "cdma",
823                maptabd,
824                IntTab(cluster_io, CDMA_SRCID),
825                IntTab(cluster_io, CDMA_TGTID),
826                64,                          // burst size
827                NB_CMA_CHANNELS ); 
828
829    ////////////// vci_multi_tty
830    std::vector<std::string> vect_names;
831    for (size_t id = 0; id < NB_TTY_CHANNELS; id++)
832    {
833        std::ostringstream term_name;
834        term_name <<  "ext_" << id;
835        vect_names.push_back(term_name.str().c_str());
836    }
837
838    VciMultiTty<vci_param_int>* 
839    mtty = new VciMultiTty<vci_param_int>(
840                "mtty",
841                IntTab(cluster_io, MTTY_TGTID),
842                maptabd,
843                vect_names );
844
845    ///////////// vci_iopic
846    VciIopic<vci_param_int>*
847    iopic = new VciIopic<vci_param_int>(
848                "iopic",
849                maptabd,
850                IntTab(cluster_io, IOPI_SRCID),
851                IntTab(cluster_io, IOPI_TGTID),
852                32,
853                20000000 );
854
855    ////////////// vci_dspin wrappers
856    VciDspinTargetWrapper<vci_param_int, dspin_cmd_width, dspin_rsp_width>*
857    wt_iobus = new VciDspinTargetWrapper<vci_param_int, dspin_cmd_width, dspin_rsp_width>(
858                "wt_bdev",
859                vci_srcid_width );
860
861    VciDspinInitiatorWrapper<vci_param_int, dspin_cmd_width, dspin_rsp_width>*
862    wi_iobus = new VciDspinInitiatorWrapper<vci_param_int, dspin_cmd_width, dspin_rsp_width>(
863                "wi_bdev",
864                vci_srcid_width );
865
866    ///////////////////////////////////////////////////////////////
867    //     Net-list
868    ///////////////////////////////////////////////////////////////
869
870    // iobus
871    iobus->p_clk                       (signal_clk); 
872    iobus->p_resetn                    (signal_resetn);
873
874    iobus->p_target_to_up              (signal_vci_cmd_from_noc);
875    iobus->p_initiator_to_up           (signal_vci_cmd_to_noc);
876
877    iobus->p_to_target[MEMC_TGTID]     (signal_vci_tgt_memc);
878    iobus->p_to_target[XICU_TGTID]     (signal_vci_tgt_xicu);
879    iobus->p_to_target[MTTY_TGTID]     (signal_vci_tgt_mtty);
880    iobus->p_to_target[FBUF_TGTID]     (signal_vci_tgt_fbuf);
881    iobus->p_to_target[MNIC_TGTID]     (signal_vci_tgt_mnic);
882    iobus->p_to_target[BDEV_TGTID]     (signal_vci_tgt_bdev);
883    iobus->p_to_target[CDMA_TGTID]     (signal_vci_tgt_cdma);
884    iobus->p_to_target[IOPI_TGTID]     (signal_vci_tgt_iopi);
885
886    for( size_t p=0 ; p<NB_PROCS_MAX ; p++ )
887    {
888        iobus->p_to_initiator[p]       (signal_vci_ini_proc[p]);
889    }
890    iobus->p_to_initiator[BDEV_SRCID]  (signal_vci_ini_bdev);
891    iobus->p_to_initiator[CDMA_SRCID]  (signal_vci_ini_cdma);
892    iobus->p_to_initiator[IOPI_SRCID]  (signal_vci_ini_iopi);
893
894    std::cout << "  - IOBUS connected" << std::endl;
895
896    // block_device
897    bdev->p_clk                        (signal_clk);
898    bdev->p_resetn                     (signal_resetn);
899    bdev->p_vci_target                 (signal_vci_tgt_bdev);
900    bdev->p_vci_initiator              (signal_vci_ini_bdev);
901    bdev->p_irq                        (signal_irq_bdev);
902
903    std::cout << "  - BDEV connected" << std::endl;
904
905    // frame_buffer
906    fbuf->p_clk                        (signal_clk);
907    fbuf->p_resetn                     (signal_resetn);
908    fbuf->p_vci                        (signal_vci_tgt_fbuf);
909
910    std::cout << "  - FBUF connected" << std::endl;
911
912    // multi_nic
913    mnic->p_clk                        (signal_clk);
914    mnic->p_resetn                     (signal_resetn);
915    mnic->p_vci                        (signal_vci_tgt_mnic);
916    for ( size_t i=0 ; i<NB_NIC_CHANNELS ; i++ )
917    {
918         mnic->p_rx_irq[i]             (signal_irq_mnic_rx[i]);
919         mnic->p_tx_irq[i]             (signal_irq_mnic_tx[i]);
920    }
921
922    std::cout << "  - MNIC connected" << std::endl;
923
924    // chbuf_dma
925    cdma->p_clk                        (signal_clk);
926    cdma->p_resetn                     (signal_resetn);
927    cdma->p_vci_target                 (signal_vci_tgt_cdma);
928    cdma->p_vci_initiator              (signal_vci_ini_cdma);
929    for ( size_t i=0 ; i<NB_CMA_CHANNELS ; i++)
930    {
931        cdma->p_irq[i]                 (signal_irq_cdma[i]);
932    }
933
934    std::cout << "  - CDMA connected" << std::endl;
935
936    // multi_tty
937    mtty->p_clk                        (signal_clk);
938    mtty->p_resetn                     (signal_resetn);
939    mtty->p_vci                        (signal_vci_tgt_mtty);
940    for ( size_t i=0 ; i<NB_TTY_CHANNELS ; i++ )
941    {
942        mtty->p_irq[i]                  (signal_irq_mtty_rx[i]);
943    }
944
945    std::cout << "  - MTTY connected" << std::endl;
946
947    // iopic
948    // NB_NIC_CHANNELS <= 2
949    // NB_CMA_CHANNELS <= 4
950    // NB_TTY_CHANNELS <= 8
951    iopic->p_clk                       (signal_clk);
952    iopic->p_resetn                    (signal_resetn);
953    iopic->p_vci_target                (signal_vci_tgt_iopi);
954    iopic->p_vci_initiator             (signal_vci_ini_iopi);
955    for ( size_t i=0 ; i<32 ; i++)
956    {
957       if     (i < NB_NIC_CHANNELS)    iopic->p_hwi[i] (signal_irq_mnic_rx[i]);
958       else if(i < 2 )                 iopic->p_hwi[i] (signal_irq_false);
959       else if(i < 2+NB_NIC_CHANNELS)  iopic->p_hwi[i] (signal_irq_mnic_tx[i-2]);
960       else if(i < 4 )                 iopic->p_hwi[i] (signal_irq_false);
961       else if(i < 4+NB_CMA_CHANNELS)  iopic->p_hwi[i] (signal_irq_cdma[i-4]);
962       else if(i < 8)                  iopic->p_hwi[i] (signal_irq_false);
963       else if(i == 8)                 iopic->p_hwi[i] (signal_irq_bdev);
964       else if(i < 16)                 iopic->p_hwi[i] (signal_irq_false);
965       else if(i < 16+NB_TTY_CHANNELS) iopic->p_hwi[i] (signal_irq_mtty_rx[i-16]);
966       else if(i < 24)                 iopic->p_hwi[i] (signal_irq_false);
967       else if(i < 24+NB_TTY_CHANNELS) iopic->p_hwi[i] (signal_irq_false);
968//     else if(i < 24+NB_TTY_CHANNELS) iopic->p_hwi[i] (signal_irq_mtty_tx[i-24]);
969       else                            iopic->p_hwi[i] (signal_irq_false);
970    }
971
972    std::cout << "  - IOPIC connected" << std::endl;
973
974    // vci/dspin wrappers
975    wi_iobus->p_clk                    (signal_clk);
976    wi_iobus->p_resetn                 (signal_resetn);
977    wi_iobus->p_vci                    (signal_vci_cmd_to_noc);
978    wi_iobus->p_dspin_cmd              (signal_dspin_bound_cmd_in[X_SIZE-1][Y_SIZE-2][NORTH]);
979    wi_iobus->p_dspin_rsp              (signal_dspin_bound_rsp_out[X_SIZE-1][Y_SIZE-2][NORTH]);
980
981    // vci/dspin wrappers
982    wt_iobus->p_clk                    (signal_clk);
983    wt_iobus->p_resetn                 (signal_resetn);
984    wt_iobus->p_vci                    (signal_vci_cmd_from_noc);
985    wt_iobus->p_dspin_cmd              (signal_dspin_bound_cmd_out[X_SIZE-1][Y_SIZE-2][NORTH]);
986    wt_iobus->p_dspin_rsp              (signal_dspin_bound_rsp_in[X_SIZE-1][Y_SIZE-2][NORTH]);
987
988    // Clock & RESET for clusters
989    for (size_t x = 0; x < (X_SIZE); x++)
990    {
991        for (size_t y = 0; y < (Y_SIZE-1); y++)
992        {
993            clusters[x][y]->p_clk                    (signal_clk);
994            clusters[x][y]->p_resetn                 (signal_resetn);
995        }
996    }
997
998    // Inter Clusters horizontal connections
999    if (X_SIZE > 1)
1000    {
1001        for (size_t x = 0; x < (X_SIZE-1); x++)
1002        {
1003            for (size_t y = 0; y < (Y_SIZE-1); y++)
1004            {
1005                clusters[x][y]->p_cmd_out[EAST]      (signal_dspin_h_cmd_inc[x][y]);
1006                clusters[x+1][y]->p_cmd_in[WEST]     (signal_dspin_h_cmd_inc[x][y]);
1007                clusters[x][y]->p_cmd_in[EAST]       (signal_dspin_h_cmd_dec[x][y]);
1008                clusters[x+1][y]->p_cmd_out[WEST]    (signal_dspin_h_cmd_dec[x][y]);
1009
1010                clusters[x][y]->p_rsp_out[EAST]      (signal_dspin_h_rsp_inc[x][y]);
1011                clusters[x+1][y]->p_rsp_in[WEST]     (signal_dspin_h_rsp_inc[x][y]);
1012                clusters[x][y]->p_rsp_in[EAST]       (signal_dspin_h_rsp_dec[x][y]);
1013                clusters[x+1][y]->p_rsp_out[WEST]    (signal_dspin_h_rsp_dec[x][y]);
1014
1015                clusters[x][y]->p_m2p_out[EAST]      (signal_dspin_h_m2p_inc[x][y]);
1016                clusters[x+1][y]->p_m2p_in[WEST]     (signal_dspin_h_m2p_inc[x][y]);
1017                clusters[x][y]->p_m2p_in[EAST]       (signal_dspin_h_m2p_dec[x][y]);
1018                clusters[x+1][y]->p_m2p_out[WEST]    (signal_dspin_h_m2p_dec[x][y]);
1019
1020                clusters[x][y]->p_p2m_out[EAST]      (signal_dspin_h_p2m_inc[x][y]);
1021                clusters[x+1][y]->p_p2m_in[WEST]     (signal_dspin_h_p2m_inc[x][y]);
1022                clusters[x][y]->p_p2m_in[EAST]       (signal_dspin_h_p2m_dec[x][y]);
1023                clusters[x+1][y]->p_p2m_out[WEST]    (signal_dspin_h_p2m_dec[x][y]);
1024
1025                clusters[x][y]->p_cla_out[EAST]      (signal_dspin_h_cla_inc[x][y]);
1026                clusters[x+1][y]->p_cla_in[WEST]     (signal_dspin_h_cla_inc[x][y]);
1027                clusters[x][y]->p_cla_in[EAST]       (signal_dspin_h_cla_dec[x][y]);
1028                clusters[x+1][y]->p_cla_out[WEST]    (signal_dspin_h_cla_dec[x][y]);
1029            }
1030        }
1031    }
1032    std::cout << std::endl << "Horizontal connections done" << std::endl;   
1033
1034    // Inter Clusters vertical connections
1035    if (Y_SIZE > 2) 
1036    {
1037        for (size_t y = 0; y < (Y_SIZE-2); y++)
1038        {
1039            for (size_t x = 0; x < X_SIZE; x++)
1040            {
1041                clusters[x][y]->p_cmd_out[NORTH]     (signal_dspin_v_cmd_inc[x][y]);
1042                clusters[x][y+1]->p_cmd_in[SOUTH]    (signal_dspin_v_cmd_inc[x][y]);
1043                clusters[x][y]->p_cmd_in[NORTH]      (signal_dspin_v_cmd_dec[x][y]);
1044                clusters[x][y+1]->p_cmd_out[SOUTH]   (signal_dspin_v_cmd_dec[x][y]);
1045
1046                clusters[x][y]->p_rsp_out[NORTH]     (signal_dspin_v_rsp_inc[x][y]);
1047                clusters[x][y+1]->p_rsp_in[SOUTH]    (signal_dspin_v_rsp_inc[x][y]);
1048                clusters[x][y]->p_rsp_in[NORTH]      (signal_dspin_v_rsp_dec[x][y]);
1049                clusters[x][y+1]->p_rsp_out[SOUTH]   (signal_dspin_v_rsp_dec[x][y]);
1050
1051                clusters[x][y]->p_m2p_out[NORTH]     (signal_dspin_v_m2p_inc[x][y]);
1052                clusters[x][y+1]->p_m2p_in[SOUTH]    (signal_dspin_v_m2p_inc[x][y]);
1053                clusters[x][y]->p_m2p_in[NORTH]      (signal_dspin_v_m2p_dec[x][y]);
1054                clusters[x][y+1]->p_m2p_out[SOUTH]   (signal_dspin_v_m2p_dec[x][y]);
1055
1056                clusters[x][y]->p_p2m_out[NORTH]     (signal_dspin_v_p2m_inc[x][y]);
1057                clusters[x][y+1]->p_p2m_in[SOUTH]    (signal_dspin_v_p2m_inc[x][y]);
1058                clusters[x][y]->p_p2m_in[NORTH]      (signal_dspin_v_p2m_dec[x][y]);
1059                clusters[x][y+1]->p_p2m_out[SOUTH]   (signal_dspin_v_p2m_dec[x][y]);
1060
1061                clusters[x][y]->p_cla_out[NORTH]     (signal_dspin_v_cla_inc[x][y]);
1062                clusters[x][y+1]->p_cla_in[SOUTH]    (signal_dspin_v_cla_inc[x][y]);
1063                clusters[x][y]->p_cla_in[NORTH]      (signal_dspin_v_cla_dec[x][y]);
1064                clusters[x][y+1]->p_cla_out[SOUTH]   (signal_dspin_v_cla_dec[x][y]);
1065            }
1066        }
1067    }
1068    std::cout << std::endl << "Vertical connections done" << std::endl;
1069
1070    // East & West boundary cluster connections
1071    for (size_t y = 0; y < (Y_SIZE-1); y++)
1072    {
1073        clusters[0][y]->p_cmd_in[WEST]           (signal_dspin_bound_cmd_in[0][y][WEST]);
1074        clusters[0][y]->p_cmd_out[WEST]          (signal_dspin_bound_cmd_out[0][y][WEST]);
1075        clusters[X_SIZE-1][y]->p_cmd_in[EAST]    (signal_dspin_bound_cmd_in[X_SIZE-1][y][EAST]);
1076        clusters[X_SIZE-1][y]->p_cmd_out[EAST]   (signal_dspin_bound_cmd_out[X_SIZE-1][y][EAST]);
1077
1078        clusters[0][y]->p_rsp_in[WEST]           (signal_dspin_bound_rsp_in[0][y][WEST]);
1079        clusters[0][y]->p_rsp_out[WEST]          (signal_dspin_bound_rsp_out[0][y][WEST]);
1080        clusters[X_SIZE-1][y]->p_rsp_in[EAST]    (signal_dspin_bound_rsp_in[X_SIZE-1][y][EAST]);
1081        clusters[X_SIZE-1][y]->p_rsp_out[EAST]   (signal_dspin_bound_rsp_out[X_SIZE-1][y][EAST]);
1082
1083        clusters[0][y]->p_m2p_in[WEST]           (signal_dspin_bound_m2p_in[0][y][WEST]);
1084        clusters[0][y]->p_m2p_out[WEST]          (signal_dspin_bound_m2p_out[0][y][WEST]);
1085        clusters[X_SIZE-1][y]->p_m2p_in[EAST]    (signal_dspin_bound_m2p_in[X_SIZE-1][y][EAST]);
1086        clusters[X_SIZE-1][y]->p_m2p_out[EAST]   (signal_dspin_bound_m2p_out[X_SIZE-1][y][EAST]);
1087
1088        clusters[0][y]->p_p2m_in[WEST]           (signal_dspin_bound_p2m_in[0][y][WEST]);
1089        clusters[0][y]->p_p2m_out[WEST]          (signal_dspin_bound_p2m_out[0][y][WEST]);
1090        clusters[X_SIZE-1][y]->p_p2m_in[EAST]    (signal_dspin_bound_p2m_in[X_SIZE-1][y][EAST]);
1091        clusters[X_SIZE-1][y]->p_p2m_out[EAST]   (signal_dspin_bound_p2m_out[X_SIZE-1][y][EAST]);
1092
1093        clusters[0][y]->p_cla_in[WEST]           (signal_dspin_bound_cla_in[0][y][WEST]);
1094        clusters[0][y]->p_cla_out[WEST]          (signal_dspin_bound_cla_out[0][y][WEST]);
1095        clusters[X_SIZE-1][y]->p_cla_in[EAST]    (signal_dspin_bound_cla_in[X_SIZE-1][y][EAST]);
1096        clusters[X_SIZE-1][y]->p_cla_out[EAST]   (signal_dspin_bound_cla_out[X_SIZE-1][y][EAST]);
1097    }
1098
1099    std::cout << std::endl << "West & East boundaries connections done" << std::endl;
1100
1101    // North & South boundary clusters connections
1102    for (size_t x = 0; x < X_SIZE; x++)
1103    {
1104        clusters[x][0]->p_cmd_in[SOUTH]          (signal_dspin_bound_cmd_in[x][0][SOUTH]);
1105        clusters[x][0]->p_cmd_out[SOUTH]         (signal_dspin_bound_cmd_out[x][0][SOUTH]);
1106        clusters[x][Y_SIZE-2]->p_cmd_in[NORTH]   (signal_dspin_bound_cmd_in[x][Y_SIZE-2][NORTH]);
1107        clusters[x][Y_SIZE-2]->p_cmd_out[NORTH]  (signal_dspin_bound_cmd_out[x][Y_SIZE-2][NORTH]);
1108
1109        clusters[x][0]->p_rsp_in[SOUTH]          (signal_dspin_bound_rsp_in[x][0][SOUTH]);
1110        clusters[x][0]->p_rsp_out[SOUTH]         (signal_dspin_bound_rsp_out[x][0][SOUTH]);
1111        clusters[x][Y_SIZE-2]->p_rsp_in[NORTH]   (signal_dspin_bound_rsp_in[x][Y_SIZE-2][NORTH]);
1112        clusters[x][Y_SIZE-2]->p_rsp_out[NORTH]  (signal_dspin_bound_rsp_out[x][Y_SIZE-2][NORTH]);
1113
1114        clusters[x][0]->p_m2p_in[SOUTH]          (signal_dspin_bound_m2p_in[x][0][SOUTH]);
1115        clusters[x][0]->p_m2p_out[SOUTH]         (signal_dspin_bound_m2p_out[x][0][SOUTH]);
1116        clusters[x][Y_SIZE-2]->p_m2p_in[NORTH]   (signal_dspin_bound_m2p_in[x][Y_SIZE-2][NORTH]);
1117        clusters[x][Y_SIZE-2]->p_m2p_out[NORTH]  (signal_dspin_bound_m2p_out[x][Y_SIZE-2][NORTH]);
1118
1119        clusters[x][0]->p_p2m_in[SOUTH]          (signal_dspin_bound_p2m_in[x][0][SOUTH]);
1120        clusters[x][0]->p_p2m_out[SOUTH]         (signal_dspin_bound_p2m_out[x][0][SOUTH]);
1121        clusters[x][Y_SIZE-2]->p_p2m_in[NORTH]   (signal_dspin_bound_p2m_in[x][Y_SIZE-2][NORTH]);
1122        clusters[x][Y_SIZE-2]->p_p2m_out[NORTH]  (signal_dspin_bound_p2m_out[x][Y_SIZE-2][NORTH]);
1123
1124        clusters[x][0]->p_cla_in[SOUTH]          (signal_dspin_bound_cla_in[x][0][SOUTH]);
1125        clusters[x][0]->p_cla_out[SOUTH]         (signal_dspin_bound_cla_out[x][0][SOUTH]);
1126        clusters[x][Y_SIZE-2]->p_cla_in[NORTH]   (signal_dspin_bound_cla_in[x][Y_SIZE-2][NORTH]);
1127        clusters[x][Y_SIZE-2]->p_cla_out[NORTH]  (signal_dspin_bound_cla_out[x][Y_SIZE-2][NORTH]);
1128    }
1129
1130    std::cout << std::endl << "North & South boundaries connections done" << std::endl;
1131
1132    std::cout << std::endl;
1133
1134    ////////////////////////////////////////////////////////
1135    //   Simulation
1136    ///////////////////////////////////////////////////////
1137
1138    sc_start(sc_core::sc_time(0, SC_NS));
1139    signal_resetn    = false;
1140    signal_irq_false = false;
1141
1142    // set network boundaries signals default values
1143    // for all boundary clusters but the IO cluster
1144    for (size_t x = 0; x < X_SIZE ; x++)
1145    {
1146        for (size_t y = 0; y < Y_SIZE-1 ; y++)
1147        {
1148            for (size_t face = 0; face < 4; face++)
1149            {
1150                if ( (x != X_SIZE-1) or (y != Y_SIZE-2) or (face != NORTH) )
1151                {
1152                    signal_dspin_bound_cmd_in [x][y][face].write = false;
1153                    signal_dspin_bound_cmd_in [x][y][face].read  = true;
1154                    signal_dspin_bound_cmd_out[x][y][face].write = false;
1155                    signal_dspin_bound_cmd_out[x][y][face].read  = true;
1156
1157                    signal_dspin_bound_rsp_in [x][y][face].write = false;
1158                    signal_dspin_bound_rsp_in [x][y][face].read  = true;
1159                    signal_dspin_bound_rsp_out[x][y][face].write = false;
1160                    signal_dspin_bound_rsp_out[x][y][face].read  = true;
1161                }
1162
1163                signal_dspin_bound_m2p_in [x][y][face].write = false;
1164                signal_dspin_bound_m2p_in [x][y][face].read  = true;
1165                signal_dspin_bound_m2p_out[x][y][face].write = false;
1166                signal_dspin_bound_m2p_out[x][y][face].read  = true;
1167
1168                signal_dspin_bound_p2m_in [x][y][face].write = false;
1169                signal_dspin_bound_p2m_in [x][y][face].read  = true;
1170                signal_dspin_bound_p2m_out[x][y][face].write = false;
1171                signal_dspin_bound_p2m_out[x][y][face].read  = true;
1172
1173                signal_dspin_bound_cla_in [x][y][face].write = false;
1174                signal_dspin_bound_cla_in [x][y][face].read  = true;
1175                signal_dspin_bound_cla_out[x][y][face].write = false;
1176                signal_dspin_bound_cla_out[x][y][face].read  = true;
1177            }
1178        }
1179    }
1180
1181    // set default values for VCI signals connected to unused ports on iobus
1182    signal_vci_tgt_memc.rspval = false;
1183    signal_vci_tgt_xicu.rspval = false;
1184    for ( size_t p = 0 ; p < NB_PROCS_MAX ; p++ ) signal_vci_ini_proc[p].cmdval = false;
1185
1186    sc_start(sc_core::sc_time(1, SC_NS));
1187    signal_resetn = true;
1188
1189    if (gettimeofday(&t1, NULL) != 0) 
1190    {
1191        perror("gettimeofday");
1192        return EXIT_FAILURE;
1193    }
1194
1195    // variable used for IRQ trace
1196    bool prev_irq_bdev = false;
1197    bool prev_irq_mtty_rx[8];
1198    bool prev_irq_proc[16][16][4];
1199
1200    for( size_t x = 0 ; x<8  ; x++ ) prev_irq_mtty_rx[x] = false;
1201
1202    for( size_t x = 0 ; x<16 ; x++ )
1203    for( size_t y = 0 ; y<16 ; y++ )
1204    for( size_t i = 0 ; i<4  ; i++ ) prev_irq_proc[x][y][i] = false;
1205
1206    for (uint64_t n = 1; n < ncycles && !stop_called; n++)
1207    {
1208        // Monitor a specific address for L1 & L2 caches
1209        // clusters[0][0]->proc[0]->cache_monitor(0x110002C078ULL);
1210        // clusters[1][1]->memc->cache_monitor(0x110002c078ULL);
1211
1212        // stats display
1213        if( (n % 5000000) == 0)
1214        {
1215
1216            if (gettimeofday(&t2, NULL) != 0) 
1217            {
1218                perror("gettimeofday");
1219                return EXIT_FAILURE;
1220            }
1221
1222            ms1 = (uint64_t) t1.tv_sec * 1000ULL + (uint64_t) t1.tv_usec / 1000;
1223            ms2 = (uint64_t) t2.tv_sec * 1000ULL + (uint64_t) t2.tv_usec / 1000;
1224            std::cerr << "platform clock frequency " 
1225                      << (double) 5000000 / (double) (ms2 - ms1) << "Khz" << std::endl;
1226
1227            if (gettimeofday(&t1, NULL) != 0) 
1228            {
1229                perror("gettimeofday");
1230                return EXIT_FAILURE;
1231            }
1232        }
1233
1234        // trace display
1235        if ( trace_ok and (n > trace_from) )
1236        {
1237            std::cout << "****************** cycle " << std::dec << n ;
1238            std::cout << " ************************************************" << std::endl;
1239
1240            size_t l = 0;
1241            size_t x = 0;
1242            size_t y = 0;
1243
1244            if ( trace_proc_ok )
1245            {
1246                l = trace_proc_id % NB_PROCS_MAX ;
1247                x = (trace_proc_id / NB_PROCS_MAX) >> Y_WIDTH ;
1248                y = (trace_proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1);
1249
1250                std::ostringstream proc_signame;
1251                proc_signame << "[SIG]PROC_" << x << "_" << y << "_" << l ;
1252                clusters[x][y]->proc[l]->print_trace();
1253                clusters[x][y]->signal_vci_ini_proc[l].print_trace(proc_signame.str());
1254
1255                std::ostringstream xicu_signame;
1256                xicu_signame << "[SIG]XICU_" << x << "_" << y ;
1257                clusters[x][y]->xicu->print_trace(0);
1258                clusters[x][y]->signal_vci_tgt_xicu.print_trace(xicu_signame.str());
1259            }
1260
1261            if ( trace_memc_ok )
1262            {
1263                x = trace_memc_id >> Y_WIDTH;
1264                y = trace_memc_id & ((1<<Y_WIDTH) - 1);
1265
1266                std::ostringstream smemc;
1267                smemc << "[SIG]MEMC_" << x << "_" << y;
1268                std::ostringstream sxram;
1269                sxram << "[SIG]XRAM_" << x << "_" << y;
1270
1271                clusters[x][y]->memc->print_trace();
1272                clusters[x][y]->signal_vci_tgt_memc.print_trace(smemc.str());
1273                clusters[x][y]->signal_vci_xram.print_trace(sxram.str());
1274            }   
1275
1276            // trace coherence signals
1277            // clusters[0][0]->signal_dspin_m2p_proc[0].print_trace("[CC_M2P_0_0]");
1278            // clusters[0][1]->signal_dspin_m2p_proc[0].print_trace("[CC_M2P_0_1]");
1279            // clusters[1][0]->signal_dspin_m2p_proc[0].print_trace("[CC_M2P_1_0]");
1280            // clusters[1][1]->signal_dspin_m2p_proc[0].print_trace("[CC_M2P_1_1]");
1281
1282            // clusters[0][0]->signal_dspin_p2m_proc[0].print_trace("[CC_P2M_0_0]");
1283            // clusters[0][1]->signal_dspin_p2m_proc[0].print_trace("[CC_P2M_0_1]");
1284            // clusters[1][0]->signal_dspin_p2m_proc[0].print_trace("[CC_P2M_1_0]");
1285            // clusters[1][1]->signal_dspin_p2m_proc[0].print_trace("[CC_P2M_1_1]");
1286
1287            // trace xbar(s) m2p
1288            // clusters[0][0]->xbar_m2p->print_trace();
1289            // clusters[1][0]->xbar_m2p->print_trace();
1290            // clusters[0][1]->xbar_m2p->print_trace();
1291            // clusters[1][1]->xbar_m2p->print_trace();
1292       
1293            // trace router(s) m2p
1294            // clusters[0][0]->router_m2p->print_trace();
1295            // clusters[1][0]->router_m2p->print_trace();
1296            // clusters[0][1]->router_m2p->print_trace();
1297            // clusters[1][1]->router_m2p->print_trace();
1298       
1299            // trace external ioc
1300            bdev->print_trace();
1301            signal_vci_tgt_bdev.print_trace("[SIG]BDEV_TGT");
1302            signal_vci_ini_bdev.print_trace("[SIG]BDEV_INI");
1303
1304            // trace external iopic
1305            iopic->print_trace();
1306            signal_vci_tgt_iopi.print_trace("[SIG]IOPI_TGT");
1307            signal_vci_ini_iopi.print_trace("[SIG]IOPI_INI");
1308
1309            // trace internal tty
1310            // clusters[0][0]->mtty->print_trace();
1311            // clusters[0][0]->signal_vci_tgt_mtty.print_trace("[SIG]MTTY");
1312
1313        }  // end trace
1314
1315        if (0)
1316        {
1317            // trace BDV interrupts events
1318            if ( signal_irq_bdev.read() != prev_irq_bdev ) 
1319            {
1320                prev_irq_bdev = signal_irq_bdev.read();
1321                std::cout << std::dec << "@@@ IRQ_BDEV = " << signal_irq_bdev.read()
1322                          << " at cycle " << n << std::endl;
1323            }
1324       
1325            // trace TTY interrupts events
1326            for ( size_t x = 0 ; x < 8 ; x++ )
1327            {
1328                if ( signal_irq_mtty_rx[x].read() != prev_irq_mtty_rx[x] ) 
1329                {
1330                    prev_irq_mtty_rx[x] = signal_irq_mtty_rx[x].read();
1331                    std::cout << std::dec << "@@@ IRQ_MTTY["<<x<<"] = " 
1332                              << signal_irq_mtty_rx[x].read()
1333                              << " at cycle " << n << std::endl;
1334                }
1335            }
1336
1337            // trace processor interrupts events
1338            for ( size_t x = 0 ; x < 2 ; x++ )
1339            for ( size_t y = 0 ; y < 2 ; y++ )
1340            for ( size_t i = 0 ; i < 4 ; i++ )
1341            {
1342                if ( clusters[x][y]->signal_proc_irq[i] != prev_irq_proc[x][y][i] )
1343                { 
1344                    prev_irq_proc[x][y][i] = clusters[x][y]->signal_proc_irq[i];
1345                    std::cout << std::dec << "@@@ IRQ_PROC["<<x<<","<<y<<","<<i<<"] = "
1346                              << clusters[x][y]->signal_proc_irq[i]
1347                              << " at cycle " << n << std::endl;
1348                }
1349            }
1350
1351            // trace VCI transactions on IOPIC and XCU(0,0)
1352            signal_vci_tgt_iopi.print_trace("@@@ IOPI_TGT");
1353            signal_vci_ini_iopi.print_trace("@@@ IOPI_INI");
1354            clusters[0][0]->signal_vci_tgt_xicu.print_trace("@@@ XCU_0_0");
1355        }
1356
1357        sc_start(sc_core::sc_time(1, SC_NS));
1358    }
1359    // Free memory
1360    for (size_t i = 0 ; i  < (X_SIZE * (Y_SIZE-1)) ; i++)
1361    {
1362        size_t x = i / (Y_SIZE-1);
1363        size_t y = i % (Y_SIZE-1);
1364        delete clusters[x][y];
1365    }
1366
1367    return EXIT_SUCCESS;
1368}
1369
1370
1371void handler(int dummy = 0) 
1372{
1373   stop_called = true;
1374   sc_stop();
1375}
1376
1377void voidhandler(int dummy = 0) {}
1378
1379int sc_main (int argc, char *argv[])
1380{
1381   signal(SIGINT, handler);
1382   signal(SIGPIPE, voidhandler);
1383
1384   try {
1385      return _main(argc, argv);
1386   } catch (std::exception &e) {
1387      std::cout << e.what() << std::endl;
1388   } catch (...) {
1389      std::cout << "Unknown exception occured" << std::endl;
1390      throw;
1391   }
1392   return 1;
1393}
1394
1395
1396// Local Variables:
1397// tab-width: 3
1398// c-basic-offset: 3
1399// c-file-offsets:((innamespace . 0)(inline-open . 0))
1400// indent-tabs-mode: nil
1401// End:
1402
1403// vim: filetype=cpp:expandtab:shiftwidth=3:tabstop=3:softtabstop=3
Note: See TracBrowser for help on using the repository browser.