summaryrefslogtreecommitdiff
path: root/src/intersim/outputset.cpp
blob: b3970dd02abdaf11bf80b3dad107b5468f7b028d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "booksim.hpp"
#include <assert.h>

#include "outputset.hpp"

OutputSet::OutputSet( int num_outputs )
{
   _num_outputs = num_outputs;

   _outputs = new list<sSetElement> [_num_outputs];
}

OutputSet::~OutputSet( )
{
   delete [] _outputs;
}

void OutputSet::Clear( )
{
   for ( int i = 0; i < _num_outputs; ++i ) {
      _outputs[i].clear( );
   }
}

void OutputSet::Add( int output_port, int vc, int pri  )
{
   AddRange( output_port, vc, vc, pri );
}

void OutputSet::AddRange( int output_port, int vc_start, int vc_end, int pri )
{
   assert( ( output_port >= 0 ) && 
           ( output_port < _num_outputs ) &&
           ( vc_start <= vc_end ) );

   sSetElement s;

   s.vc_start = vc_start;
   s.vc_end   = vc_end;
   s.pri      = pri;

   _outputs[output_port].push_back( s );
}

int OutputSet::Size( ) const
{
   return _num_outputs;
}

bool OutputSet::OutputEmpty( int output_port ) const
{
   assert( ( output_port >= 0 ) && 
           ( output_port < _num_outputs ) );

   return _outputs[output_port].empty( );
}

int OutputSet::NumVCs( int output_port ) const
{
   assert( ( output_port >= 0 ) && 
           ( output_port < _num_outputs ) );

   int total = 0;

   for ( list<sSetElement>::const_iterator i = _outputs[output_port].begin( );
       i != _outputs[output_port].end( ); i++ ) {
      total += i->vc_end - i->vc_start + 1;
   }

   return total;
}

int OutputSet::GetVC( int output_port, int vc_index, int *pri ) const
{
   assert( ( output_port >= 0 ) && 
           ( output_port < _num_outputs ) );

   int range;
   int remaining = vc_index;
   int vc = -1;

   if ( pri ) {
      *pri = -1;
   }

   for ( list<sSetElement>::const_iterator i = _outputs[output_port].begin( );
       i != _outputs[output_port].end( ); i++ ) {

      range = i->vc_end - i->vc_start + 1;
      if ( remaining >= range ) {
         remaining -= range;
      } else {
         vc = i->vc_start + remaining;
         if ( pri ) {
            *pri = i->pri;
         }
         break;
      }
   }

   return vc;
}

bool OutputSet::GetPortVC( int *out_port, int *out_vc ) const
{
   bool single_output = false;
   int  used_outputs  = 0;

   for ( int output = 0; output < _num_outputs; ++output ) {

      list<sSetElement>::const_iterator i = _outputs[output].begin( );

      if ( i != _outputs[output].end( ) ) {
         ++used_outputs;

         if ( i->vc_start == i->vc_end ) {
            *out_vc   = i->vc_start;
            *out_port = output;
            single_output = true;
         } else {
            // multiple vc's selected
            break;
         }
      }

      if ( used_outputs > 1 ) {
         // multiple outputs selected
         single_output = false;
         break;
      }
   }

   return single_output;
}