|
|
1 #include "scv.h"
2
3 const unsigned ram_size = 256;
4
5 class rw_task_if : virtual public sc_interface {
6 public:
7 typedef sc_uint<8> addr_t;
8 typedef sc_uint<8> data_t;
9 struct write_t {
10 addr_t addr;
11 data_t data;
12 };
13
14 virtual data_t read(const addr_t*) = 0;
15 virtual void write(const write_t*) = 0;
16 };
17
18 SCV_EXTENSIONS(rw_task_if::write_t) {
19 public:
20 scv_extensions<rw_task_if::addr_t> addr;
21 scv_extensions<rw_task_if::data_t> data;
22 SCV_EXTENSIONS_CTOR(rw_task_if::write_t) {
23 SCV_FIELD(addr);
24 SCV_FIELD(data);
25 }
26 };
27
28 class pipelined_bus_ports : public sc_module {
29 public:
30 sc_in< bool > clk;
31 sc_inout< bool > rw;
32 sc_inout< bool > addr_req;
33 sc_inout< bool > addr_ack;
34 sc_inout< sc_uint<8> > bus_addr;
35 sc_inout< bool > data_rdy;
36 sc_inout< sc_uint<8> > bus_data;
37
38 SC_CTOR(pipelined_bus_ports)
39 : clk("clk"), rw("rw"),
40 addr_req("addr_req"),
41 addr_ack("addr_ack"), bus_addr("bus_addr"),
42 data_rdy("data_rdy"), bus_data("bus_data") {}
43 };
44
45 class rw_pipelined_transactor
46 : public rw_task_if,
47 public pipelined_bus_ports {
48
49 sc_mutex addr_phase;
50 sc_mutex data_phase;
51
52 scv_tr_stream pipelined_stream;
53 scv_tr_stream addr_stream;
54 scv_tr_stream data_stream;
55 scv_tr_generator<sc_uint<8>, sc_uint<8> > read_gen;
56 scv_tr_generator<sc_uint<8>, sc_uint<8> > write_gen;
57 scv_tr_generator<sc_uint<8> > addr_gen;
58 scv_tr_generator<sc_uint<8> > data_gen;
59
60 public:
61 rw_pipelined_transactor(sc_module_name nm) :
62 pipelined_bus_ports(nm),
63 addr_phase("addr_phase"),
64 data_phase("data_phase"),
65 pipelined_stream("pipelined_stream", "transactor"),
66 addr_stream("addr_stream", "transactor"),
67 data_stream("data_stream", "transactor"),
68 read_gen("read",pipelined_stream,"addr","data"),
69 write_gen("write",pipelined_stream,"addr","data"),
70 addr_gen("addr",addr_stream,"addr"),
71 data_gen("data",data_stream,"data")
72 {}
73 virtual data_t read(const addr_t* p_addr);
74 virtual void write(const write_t * req);
75 };
76
77 rw_task_if::data_t rw_pipelined_transactor::read(const rw_task_if::addr_t*
78 addr) {
79 addr_phase.lock();
80 scv_tr_handle h = read_gen.begin_transaction(*addr);
81
82 scv_tr_handle h1 = addr_gen.begin_transaction(*addr,"addr_phase",h);
83 wait(clk->posedge_event());
84 bus_addr = *addr;
85 addr_req = 1;
86 wait(addr_ack->posedge_event());
87 wait(clk->negedge_event());
88 addr_req = 0;
89 wait(addr_ack->negedge_event());
90 addr_gen.end_transaction(h1);
91 addr_phase.unlock();
92
93 data_phase.lock();
94 scv_tr_handle h2 = data_gen.begin_transaction("data_phase",h);
95 wait(data_rdy->posedge_event());
96 data_t data = bus_data.read();
97 wait(data_rdy->negedge_event());
98 data_gen.end_transaction(h2);
99 read_gen.end_transaction(h,data);
100 data_phase.unlock();
101
102 return data;
103 }
104
105 void rw_pipelined_transactor::write(const write_t * req) {
106 scv_tr_handle h = write_gen.begin_transaction(req->addr);
107 // ...
108 write_gen.end_transaction(h,req->data);
109 }
110
111 class test : public sc_module {
112 public:
113 sc_port< rw_task_if > transactor;
114 SC_CTOR(test) {
115 SC_THREAD(main);
116 }
117 void main();
118 };
119
120 class write_constraint : virtual public scv_constraint_base {
121 public:
122 scv_smart_ptr<rw_task_if::write_t> write;
123 SCV_CONSTRAINT_CTOR(write_constraint) {
124 SCV_CONSTRAINT( write->addr() <= ram_size );
125 SCV_CONSTRAINT( write->addr() ! = write->data() );
126 }
127 };
128
129 inline void process(scv_smart_ptr<int> data) {}
130
131 inline void test::main() {
132 // simple sequential tests
133 for (int i=0; i<3; i++) {
134 rw_task_if::addr_t addr = i;
135 rw_task_if::data_t data = transactor->read(&addr);
136 cout << "at time " << sc_time_stamp() << ": ";
137 cout << "received data : " << data << endl;
138 }
139
140 scv_smart_ptr<rw_task_if::addr_t> addr;
141 for (int i=0; i<3; i++) {
142
143 addr->next();
144 rw_task_if::data_t data = transactor->read( addr->get_instance() );
145 cout << "data for address " << *addr << " is " << data << endl;
146 }
147
148 scv_smart_ptr<rw_task_if::write_t> write;
149 for (int i=0; i<3; i++) {
150 write->next();
151 transactor->write( write->get_instance() );
152 cout << "send data : " << write->data << endl;
153 }
154
155 scv_smart_ptr<int> data;
156 scv_bag<int> distribution;
157 distribution.push(1,40);
158 distribution.push(2,60);
159 data->set_mode(distribution);
160 for (int i=0;i<3; i++) { data->next(); process(data); }
161 }
162
163 class design : public pipelined_bus_ports {
164 list< sc_uint<8> > outstandingAddresses;
165 list< bool > outstandingType;
166 sc_uint<8> memory[ram_size];
167
168 public:
169 SC_HAS_PROCESS(design);
170 design(sc_module_name nm) : pipelined_bus_ports(nm) {
171 for (unsigned i=0; i<ram_size; ++i) { memory[i] = i; }
172 SC_THREAD(addr_phase);
173 SC_THREAD(data_phase);
174 }
175 void addr_phase();
176 void data_phase();
177 };
178
179 inline void design::addr_phase() {
180 while (1) {
181 while (addr_req.read() ! = 1) {
182 wait(addr_req->value_changed_event());
183 }
184 sc_uint<8> _addr = bus_addr.read();
185 bool _rw = rw.read();
186
187 int cycle = rand() % 10 + 1;
188 while (cycle-- > 0) {
189 wait(clk->posedge_event());
190 }
191
192 addr_ack = 1;
193 wait(clk->posedge_event());
194 addr_ack = 0;
195
196 outstandingAddresses.push_back(_addr);
197 outstandingType.push_back(_rw);
198 cout << "at time " << sc_time_stamp() << ": ";
199 cout << "received request for memory address " << _addr << endl;
200 }
201 }
202
203 inline void design::data_phase() {
204 while (1) {
205 while (outstandingAddresses.empty()) {
206 wait(clk->posedge_event());
207 }
208 int cycle = rand() % 10 + 1;
209 while (cycle-- > 0) {
210 wait(clk->posedge_event());
211 }
212 if (outstandingType.front() == 0) {
213 cout << "reading memory address " << outstandingAddresses.front()
214 << " with value " << memory[outstandingAddresses.front()] << endl;
215 bus_data = memory[outstandingAddresses.front()];
216 data_rdy = 1;
217 wait(clk->posedge_event());
218 data_rdy = 0;
219
220 } else {
221 cout << "not implemented yet" << endl;
222 }
223 outstandingAddresses.pop_front();
224 outstandingType.pop_front();
225 }
226 }
227
228 int sc_main (int argc , char *argv[])
229 {
230 scv_startup();
231
232 scv_tr_text_init();
233 scv_tr_db db("my_db");
234 scv_tr_db::set_default_db(&db);
235
236 // create signals
237 sc_clock clk("clk",20,0.5,0,true);
238 sc_signal< bool > rw;
239 sc_signal< bool > addr_req;
240 sc_signal< bool > addr_ack;
241 sc_signal< sc_uint<8> > bus_addr;
242 sc_signal< bool > data_rdy;
243 sc_signal< sc_uint<8> > bus_data;
244
245 // create modules/channels
246 test t("t");
247 rw_pipelined_transactor tr("tr");
248 design duv("duv");
249
250 // connect them up
251 t.transactor(tr);
252
253 tr.clk(clk);
254 tr.rw(rw);
255 tr.addr_req(addr_req);
256 tr.addr_ack(addr_ack);
257 tr.bus_addr(bus_addr);
258 tr.data_rdy(data_rdy);
259 tr.bus_data(bus_data);
260
261 duv.clk(clk);
262 duv.rw(rw);
263 duv.addr_req(addr_req);
264 duv.addr_ack(addr_ack);
265 duv.bus_addr(bus_addr);
266 duv.data_rdy(data_rdy);
267 duv.bus_data(bus_data);
268
269 // run the simulation
270 sc_start(1000000);
271
272 return 0;
273 }
274
You could download file scv_recording.cpp here
|