2
2
#define SIMULATION_BUFFER_H
3
3
4
4
#include < atomic>
5
- #include < bitset>
6
- #include < mutex>
7
-
8
- #define BUFFER_SIZE 2
9
- #define CONCURENCY_LIMIT (BUFFER_SIZE-1 ) // access to cycle -1 with an extra pdding cell
10
- #define DATA_TYPE_BIT_SIZE 2 // we only need 2 bits to store all the possible values
11
- #define BUFFER_BIT_SIZE (BUFFER_SIZE*DATA_TYPE_BIT_SIZE)
12
-
13
5
14
6
/* *
15
7
* Odin use -1 internally, so we need to go back on forth
16
8
* TODO: change the default odin value to match both the Blif value and this buffer
17
9
*/
18
10
typedef signed char data_t ;
19
11
20
- typedef std::bitset<DATA_TYPE_BIT_SIZE> return_t ;
12
+ #define BUFFER_SIZE 8 // use something divisible by 4 since the compact buffer can contain 4 value
13
+ #define CONCURENCY_LIMIT (BUFFER_SIZE-1 ) // access to cycle -1 with an extra pdding cell
14
+
15
+
16
+ typedef struct
17
+ {
18
+ uint8_t i0:2 ;
19
+ uint8_t i1:2 ;
20
+ uint8_t i2:2 ;
21
+ uint8_t i3:2 ;
22
+ }BitFields;
21
23
22
24
class AtomicBuffer
23
25
{
24
26
private:
25
- std::mutex bitlock;
26
- std::bitset<BUFFER_BIT_SIZE> buffer;
27
- std::atomic<int64_t > cycle;
28
-
29
- uint64_t mod_cycle (int64_t cycle_in)
30
- {
31
- // buffer is length of 32 and each internal 'bits' need 2 bit
32
- return ((cycle_in & (BUFFER_SIZE-1 )) *DATA_TYPE_BIT_SIZE);
33
- }
34
-
35
- void set_bits (return_t value, uint8_t bit_index, bool lock_it)
36
- {
37
- if (lock_it)
38
- std::lock_guard<std::mutex> lock (this ->bitlock );
39
-
40
- for (size_t i=0 ; i<DATA_TYPE_BIT_SIZE; i++)
41
- this ->buffer [bit_index+i] = value[i];
42
- }
43
-
44
- return_t get_bits (uint8_t bit_index, bool lock_it)
45
- {
46
- if (lock_it)
47
- std::lock_guard<std::mutex> lock (this ->bitlock );
48
-
49
- return_t to_return = 0 ;
50
- for (size_t i=0 ; i<DATA_TYPE_BIT_SIZE; i++)
51
- to_return[i] = this ->buffer [bit_index+i];
52
-
53
- return to_return;
54
- }
55
-
56
- void copy_foward (uint8_t bit_index, bool lock_it)
57
- {
58
- if (lock_it)
59
- std::lock_guard<std::mutex> lock (this ->bitlock );
60
-
61
- for (size_t i=0 ; i<DATA_TYPE_BIT_SIZE; i++)
62
- this ->buffer [bit_index+DATA_TYPE_BIT_SIZE+i] = this ->buffer [bit_index+i];
63
- }
64
-
65
- return_t to_bit (data_t value_in)
66
- {
67
- return value_in; // cast to 11 a -1
68
- }
27
+ BitFields bits[BUFFER_SIZE/4 ];
28
+ std::atomic<bool > lock;
29
+ uint32_t cycle;
30
+
31
+ void lock_it ()
32
+ {
33
+ while (lock){}
34
+ this ->lock = true ;
35
+ }
36
+
37
+ void unlock_it ()
38
+ {
39
+ this ->lock = false ;
40
+ }
41
+
42
+ // /////////////////////////
43
+ // 2 bits are used per value
44
+ data_t val (uint8_t val_in)
45
+ {
46
+ return ((val_in != 0 && val_in != 1 )? -1 : val_in);
47
+ }
48
+
49
+ uint8_t get_bits (uint8_t index)
50
+ {
51
+ index = index%BUFFER_SIZE;
52
+ uint8_t address = index/4 ;
53
+ uint8_t bit_index = index%4 ;
54
+ switch (bit_index)
55
+ {
56
+ case 0 : return (this ->bits [address].i0 );
57
+ case 1 : return (this ->bits [address].i1 );
58
+ case 2 : return (this ->bits [address].i2 );
59
+ case 3 : return (this ->bits [address].i3 );
60
+ default : return 0x3 ;
61
+ }
62
+ }
63
+
64
+ void set_bits (uint8_t index, uint8_t value)
65
+ {
66
+ index = index%BUFFER_SIZE;
67
+ uint8_t address = index/4 ;
68
+ uint8_t bit_index = index%4 ;
69
+
70
+ value = value&0x3 ;
71
+
72
+ switch (bit_index)
73
+ {
74
+ case 0 : this ->bits [address].i0 = value; break ;
75
+ case 1 : this ->bits [address].i1 = value; break ;
76
+ case 2 : this ->bits [address].i2 = value; break ;
77
+ case 3 : this ->bits [address].i3 = value; break ;
78
+ default : break ;
79
+ }
80
+ }
81
+ public:
69
82
70
- data_t to_value ( return_t bit_in )
83
+ AtomicBuffer ( data_t value_in )
71
84
{
72
- if (bit_in == 0 ) return 0 ;
73
- else if (bit_in == 1 ) return 1 ;
74
- else return - 1 ;
85
+ this -> lock = false ;
86
+ this -> update_cycle (- 1 ) ;
87
+ this -> init_all_values (value_in) ;
75
88
}
76
89
77
- public:
78
-
79
- void init_all_values (data_t value)
90
+ void print ()
80
91
{
81
- return_t value_to_set = to_bit (value);
82
92
for (int i=0 ; i<BUFFER_SIZE; i++)
83
- this ->set_bits (value_to_set, this ->mod_cycle (i),false );
93
+ {
94
+ uint8_t value = get_bits ( i);
95
+ printf (" %s" ,(value == 0 )? " 0" : (value == 1 )? " 1" : " x" );
96
+ }
97
+ printf (" \n " );
84
98
}
85
99
86
- AtomicBuffer ( data_t value_in )
100
+ void init_all_values ( data_t value )
87
101
{
88
- this ->update_cycle (-1 );
89
- this ->init_all_values (value_in);
102
+ this ->lock = false ;
103
+ for (int i=0 ; i<BUFFER_SIZE; i++)
104
+ set_bits ( i, value);
90
105
}
91
106
92
- int64_t get_cycle ()
107
+ int32_t lock_free_get_cycle ()
93
108
{
94
109
return this ->cycle ;
95
110
}
96
111
97
- void update_cycle ( int64_t cycle_in)
112
+ void lock_free_update_cycle ( int64_t cycle_in)
98
113
{
99
114
this ->cycle = cycle_in;
100
115
}
101
116
102
- void print ( )
117
+ data_t lock_free_get_value ( int64_t cycle_in )
103
118
{
104
- printf (" \t " );
105
- for (int i=0 ; i<BUFFER_SIZE; i++)
106
- {
107
- if (!(i%4 ))
108
- printf (" " );
109
-
110
- data_t value = this ->get_value (i);
111
- if (value == -1 )
112
- printf (" x" );
113
- else
114
- printf (" %d" , value);
115
-
119
+ return val (get_bits ( cycle_in));
120
+ }
116
121
117
- }
118
-
119
- printf (" \n " );
122
+ void lock_free_update_value ( data_t value_in, int64_t cycle_in)
123
+ {
124
+ set_bits ( cycle_in,value_in);
125
+ lock_free_update_cycle ( cycle_in);
120
126
}
121
127
122
- data_t lock_free_get_value ( int64_t cycle_in)
128
+ void lock_free_copy_foward_one_cycle ( int64_t cycle_in)
123
129
{
124
- return this ->to_value (this ->get_bits (mod_cycle (cycle_in),false ));
130
+ set_bits ( cycle_in+1 ,get_bits (cycle_in));
131
+ lock_free_update_cycle ( cycle_in);
125
132
}
126
133
127
- data_t get_value ( int64_t cycle_in )
134
+ int32_t get_cycle ( )
128
135
{
129
- return this ->to_value (this ->get_bits (mod_cycle (cycle_in),true ));
136
+ lock_it ();
137
+ int32_t value = lock_free_get_cycle ();
138
+ unlock_it ();
139
+ return value;
130
140
}
131
141
132
- void lock_free_update_value ( data_t value_in, int64_t cycle_in)
142
+ void update_cycle ( int64_t cycle_in)
133
143
{
134
- this ->set_bits (this ->to_bit (value_in), mod_cycle (cycle_in),false );
135
- this ->update_cycle (cycle_in);
144
+ lock_it ();
145
+ lock_free_update_cycle (cycle_in);
146
+ unlock_it ();
136
147
}
137
148
138
- void update_value ( data_t value_in, int64_t cycle_in)
149
+ data_t get_value ( int64_t cycle_in)
139
150
{
140
- this ->set_bits (this ->to_bit (value_in), mod_cycle (cycle_in), true );
141
- this ->update_cycle (cycle_in);
151
+ lock_it ();
152
+ data_t value = lock_free_get_value ( cycle_in);
153
+ unlock_it ();
154
+ return value;
142
155
}
143
156
144
- void lock_free_copy_foward_one_cycle ( int64_t cycle_in)
157
+ void update_value ( data_t value_in, int64_t cycle_in)
145
158
{
146
- this ->copy_foward (mod_cycle (cycle_in), false );
147
- this ->update_cycle (cycle_in);
159
+ lock_it ();
160
+ lock_free_update_value ( value_in, cycle_in);
161
+ unlock_it ();
162
+
148
163
}
149
164
150
- void copy_foward_one_cycle (int64_t cycle_in)
165
+ void copy_foward_one_cycle ( int64_t cycle_in)
151
166
{
152
- this ->copy_foward (mod_cycle (cycle_in), true );
153
- this ->update_cycle (cycle_in);
167
+ lock_it ();
168
+ lock_free_copy_foward_one_cycle ( cycle_in);
169
+ unlock_it ();
154
170
}
171
+
155
172
};
156
173
157
- #endif
174
+ #endif
0 commit comments