Skip to content

Commit 52462f8

Browse files
committed
buffered ram simulation and reduce cycle buffer to use 2 bit per cycle
1 parent 21917c4 commit 52462f8

File tree

8 files changed

+418
-175
lines changed

8 files changed

+418
-175
lines changed

ODIN_II/SRC/include/AtomicBuffer.hpp

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

ODIN_II/SRC/include/AtomicRam.hpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#ifndef SIMULATION_RAM_H
2+
#define SIMULATION_RAM_H
3+
4+
#include <mutex>
5+
#include <memory>
6+
#include <vector>
7+
#include "AtomicRow.hpp"
8+
9+
class AtomicRam
10+
{
11+
private:
12+
std::mutex ramlock;
13+
std::vector<AtomicRow *> data_cells;
14+
15+
16+
public:
17+
AtomicRam(size_t address_size, size_t word_size, int8_t init_value)
18+
{
19+
// compute the real depth from the adress space
20+
long long max_address = 1 << address_size;
21+
22+
for(size_t address=0; address< max_address; address++)
23+
{
24+
data_cells.push_back(new AtomicRow(word_size, init_value));
25+
}
26+
}
27+
28+
~AtomicRam()
29+
{
30+
for(size_t address=0; address< data_cells.size(); address++)
31+
{
32+
delete data_cells[address];
33+
}
34+
}
35+
36+
bool empty()
37+
{
38+
return this->data_cells.empty();
39+
}
40+
41+
std::vector<int8_t> get_word_line(long long address, int64_t cycle)
42+
{
43+
if(address < 0 || address > data_cells.size())
44+
return std::vector<int8_t>(data_cells.size(), -1);
45+
46+
std::lock_guard<std::mutex> lock(this->ramlock);
47+
return data_cells[address]->lock_free_get_data_row(cycle);
48+
}
49+
50+
void set_word_line(long long address, std::vector<int8_t> values, int64_t cycle)
51+
{
52+
if(address < 0 || address > data_cells.size())
53+
return;
54+
55+
std::lock_guard<std::mutex> lock(this->ramlock);
56+
data_cells[address]->lock_free_set_data_row(values, cycle);
57+
}
58+
59+
void init_word_line(long long address, char *values_in, int width)
60+
{
61+
if(address < 0 || address > data_cells.size())
62+
return;
63+
64+
std::vector<int8_t> values;
65+
for(size_t i =0; i<data_cells[address]->size(); i++)
66+
{
67+
if(i< width)
68+
values.push_back(values_in[i]);
69+
else
70+
values.push_back(-1);
71+
}
72+
std::lock_guard<std::mutex> lock(this->ramlock);
73+
data_cells[address]->init_line_values(values);
74+
}
75+
76+
void copy_ram_foward_one_cycle(int64_t cycle)
77+
{
78+
std::lock_guard<std::mutex> lock(this->ramlock);
79+
for(size_t address=0; address< data_cells.size(); address++)
80+
data_cells[address]->lock_free_copy_row_foward_one_cycle(cycle);
81+
}
82+
};
83+
84+
#endif

ODIN_II/SRC/include/AtomicRow.hpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#ifndef SIMULATION_RAM_Hs
2+
#define SIMULATION_RAM_H
3+
4+
#include <mutex>
5+
#include <memory>
6+
#include <vector>
7+
#include "AtomicBuffer.hpp"
8+
9+
class AtomicRow
10+
{
11+
private:
12+
std::mutex word_lock;
13+
std::vector<AtomicBuffer*> data_row;
14+
15+
public:
16+
AtomicRow(size_t word_size, int8_t init_value)
17+
{
18+
for(size_t cell=0; cell< word_size; cell++)
19+
data_row.push_back(new AtomicBuffer(init_value));
20+
}
21+
22+
AtomicRow(std::vector<AtomicBuffer*> prebuilt_row)
23+
{
24+
data_row = std::vector<AtomicBuffer*>(prebuilt_row.begin(), prebuilt_row.end());
25+
}
26+
27+
~AtomicRow()
28+
{
29+
for(size_t cell=0; cell< data_row.size(); cell++)
30+
{
31+
delete data_row[cell];
32+
}
33+
}
34+
35+
bool empty()
36+
{
37+
return this->data_row.empty();
38+
}
39+
40+
size_t size()
41+
{
42+
return this->data_row.size();
43+
}
44+
45+
std::vector<int8_t> get_data_row(int64_t cycle)
46+
{
47+
std::vector<int8_t> word_line;
48+
49+
for(size_t i=0; i< data_row.size(); i++)
50+
word_line.push_back(data_row[i]->get_value(cycle));
51+
52+
return word_line;
53+
}
54+
55+
void set_data_row(std::vector<int8_t> values, int64_t cycle)
56+
{
57+
for(size_t i=0; i< data_row.size(); i++)
58+
data_row[i]->update_value(values[i], cycle);
59+
}
60+
61+
void copy_row_foward_one_cycle(int64_t cycle)
62+
{
63+
for(size_t i=0; i< data_row.size(); i++)
64+
data_row[i]->copy_foward_one_cycle(cycle);
65+
}
66+
67+
68+
std::vector<int8_t> lock_free_get_data_row(int64_t cycle)
69+
{
70+
std::vector<int8_t> word_line;
71+
72+
for(size_t i=0; i< data_row.size(); i++)
73+
word_line.push_back(data_row[i]->lock_free_get_value(cycle));
74+
75+
return word_line;
76+
}
77+
78+
void lock_free_set_data_row(std::vector<int8_t> values, int64_t cycle)
79+
{
80+
for(size_t i=0; i< data_row.size(); i++)
81+
data_row[i]->lock_free_update_value(values[i], cycle);
82+
}
83+
84+
void lock_free_copy_row_foward_one_cycle(int64_t cycle)
85+
{
86+
for(size_t i=0; i< data_row.size(); i++)
87+
data_row[i]->lock_free_copy_foward_one_cycle(cycle);
88+
}
89+
90+
void init_line_values(std::vector<int8_t> values)
91+
{
92+
for(size_t i=0; i< data_row.size(); i++)
93+
data_row[i]->init_all_values(values[i]);
94+
}
95+
};
96+
97+
#endif

ODIN_II/SRC/include/simulate_blif.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ OTHER DEALINGS IN THE SOFTWARE.
2828
#include <stdarg.h>
2929
#include <unordered_map>
3030

31-
32-
33-
#define SIM_WAVE_LENGTH 16
3431
#define BUFFER_MAX_SIZE 1024
3532

3633
#include <queue>
@@ -56,8 +53,6 @@ OTHER DEALINGS IN THE SOFTWARE.
5653
#define OUTPUT_ACTIVITY_FILE_NAME "output_activity"
5754
#define MODEL_SIM_FILE_NAME "test.do"
5855

59-
#define CONCURENT_SIMULATION_LIMIT 32
60-
6156
#define SINGLE_PORT_MEMORY_NAME "single_port_ram"
6257
#define DUAL_PORT_MEMORY_NAME "dual_port_ram"
6358

0 commit comments

Comments
 (0)