@@ -79,14 +79,20 @@ class sct_prim_fifo :
79
79
bool sync_ready;
80
80
const bool USE_ELEM_NUM;
81
81
82
- bool cthread_put = false ;
83
- bool cthread_get = false ;
82
+ bool cthread_put = false ;
83
+ bool cthread_get = false ;
84
+ bool cthread_peek = false ;
84
85
85
- sc_in_clk* clk_in = nullptr ;
86
+ // / FIFO used for Target/Initiator simulation
87
+ bool targ_init = false ;
88
+ bool targ_init_sync = false ;
89
+
90
+ sc_in_clk* clk_in = nullptr ;
86
91
sc_time clk_period = SC_ZERO_TIME;
87
92
88
- sc_time GET_TIME = SC_ZERO_TIME;
89
- sc_time PUT_TIME = SC_ZERO_TIME;
93
+ sc_time GET_TIME = SC_ZERO_TIME;
94
+ sc_time PUT_TIME = SC_ZERO_TIME;
95
+ sc_time PEEK_TIME = SC_ZERO_TIME;
90
96
91
97
sct_prim_signal<bool > has_reset{" has_reset" };
92
98
sct_prim_signal<bool > put_req{" put_req" };
@@ -98,6 +104,8 @@ class sct_prim_fifo :
98
104
sc_signal<unsigned > element_num{" element_num" };
99
105
sc_signal<T> get_data{" get_data" };
100
106
sc_signal<T> get_data_next{" get_data_next" };
107
+
108
+ sc_signal<bool > put_done{" put_done" }; // Auxiliary signal to meet RTL timing
101
109
102
110
bool hasReset= 0 ;
103
111
unsigned getIndx = 0 ; // Index of element that will be get
@@ -114,6 +122,7 @@ class sct_prim_fifo :
114
122
115
123
sc_event put_event;
116
124
sc_event get_event;
125
+ sc_event* peek_event = nullptr ;
117
126
sc_event update_event;
118
127
119
128
// / Channel update, run at DC 0
@@ -159,14 +168,23 @@ class sct_prim_fifo :
159
168
cout << " NOTIFIED update get " << name () << endl;
160
169
#endif
161
170
}
162
-
171
+ if (peek_event && (!cthread_peek || (doPut && sync_valid))) {
172
+ peek_event->notify (PEEK_TIME);
173
+ }
174
+
163
175
#ifdef NOTIFY_DEBUG
164
176
// if (std::string(name()).find("tresp") != std::string::npos)
165
177
cout << sc_time_stamp () << " " << sc_delta_count () << " updateProc "
166
178
<< name () << " doPut|doGet " << doPut << doGet << " elemNum" << elemNum << endl;
167
179
#endif
168
180
}
169
181
182
+ if (targ_init_sync) {
183
+ // To provide de-assert for @put_done
184
+ if (!cthread_put && (doPut || doGet)) update_event.notify (clk_period);
185
+ put_done = doPut || doGet;
186
+ }
187
+
170
188
element_num = elemNum;
171
189
get_data = buffer[getIndx];
172
190
get_data_next = buffer[getIndx == fifoSize-1 ? 0 : getIndx+1 ];
@@ -178,8 +196,22 @@ class sct_prim_fifo :
178
196
179
197
// / Internal ready/valid/data functions equivalent to RTL logic
180
198
inline bool putReady () const {
199
+ // For Target/Initiator mode get required at almost full FIFO to allow put
200
+ // cout << sc_time_stamp() << " " << sc_delta_count()
201
+ // << " targ_init_sync " << targ_init_sync
202
+ // << " put_done " << put_done
203
+ // << " get_req == get_req_d " << (get_req == get_req_d)
204
+ // << " put_req == put_req_d " << (put_req == put_req_d)
205
+ // << " element_num " << element_num.read() << endl;
206
+
207
+ if (targ_init_sync && !cthread_put) {
208
+ if (cthread_get && get_req != get_req_d) { return true ; }
209
+ if (!put_done && element_num.read () != 0 ) { return false ; }
210
+ }
211
+
181
212
return ((element_num.read () != fifoSize &&
182
- (!cthread_put || put_req == put_req_d ||
213
+ (!cthread_put ||
214
+ (targ_init ? get_req != get_req_d : put_req == put_req_d) ||
183
215
element_num.read () != fifoSize-1 )) ||
184
216
(!sync_ready && get_req != get_req_d));
185
217
}
@@ -201,8 +233,11 @@ class sct_prim_fifo :
201
233
assert (clk_in && " clk_in is nullptr" );
202
234
clk_period = get_clk_period (clk_in);
203
235
204
- GET_TIME = cthread_get ? clk_period : SC_ZERO_TIME;
205
- PUT_TIME = cthread_put ? clk_period : SC_ZERO_TIME;
236
+ GET_TIME = cthread_get ? clk_period : SC_ZERO_TIME;
237
+ PUT_TIME = cthread_put ? clk_period : SC_ZERO_TIME;
238
+ PEEK_TIME = cthread_peek ? clk_period : SC_ZERO_TIME;
239
+
240
+ // cout << "PUT_TIME " << PUT_TIME << " GET_TIME " << GET_TIME << " PEEK_TIME " << PEEK_TIME << endl;
206
241
207
242
// Do not check @sync_valid and @sync_ready as prim_fifo could be used
208
243
// as part of target/initiator in non-process context
@@ -222,6 +257,7 @@ class sct_prim_fifo :
222
257
// Notify put/get processes at reset exit
223
258
put_event.notify (PUT_TIME);
224
259
get_event.notify (GET_TIME);
260
+ if (peek_event) peek_event->notify (PEEK_TIME);
225
261
}
226
262
}
227
263
@@ -233,11 +269,14 @@ class sct_prim_fifo :
233
269
put_data = T{};
234
270
}
235
271
236
- if (!cthread_get && !cthread_put && !sync_valid && put_req != put_req_d) {
237
- get_event.notify (GET_TIME);
238
- #ifdef NOTIFY_DEBUG
239
- cout << " NOTIFIED reset_put() " << name () << endl;
240
- #endif
272
+ if (!cthread_put && !sync_valid && put_req != put_req_d) {
273
+ if (!cthread_get) {
274
+ get_event.notify (GET_TIME);
275
+ #ifdef NOTIFY_DEBUG
276
+ cout << " NOTIFIED reset_put() " << name () << endl;
277
+ #endif
278
+ }
279
+ if (peek_event && !cthread_peek) peek_event->notify (PEEK_TIME);
241
280
}
242
281
}
243
282
@@ -246,11 +285,14 @@ class sct_prim_fifo :
246
285
put_data = T{};
247
286
248
287
// Clear put notifies get process if both are methods
249
- if (!cthread_get && !cthread_put && !sync_valid && put_req != put_req_d) {
250
- get_event.notify (GET_TIME);
251
- #ifdef NOTIFY_DEBUG
252
- cout << " NOTIFIED clear_put() " << name () << endl;
253
- #endif
288
+ if (!cthread_put && !sync_valid && put_req != put_req_d) {
289
+ if (!cthread_get) {
290
+ get_event.notify (GET_TIME);
291
+ #ifdef NOTIFY_DEBUG
292
+ cout << " NOTIFIED clear_put() " << name () << endl;
293
+ #endif
294
+ }
295
+ if (peek_event && !cthread_peek) peek_event->notify (PEEK_TIME);
254
296
}
255
297
}
256
298
@@ -303,9 +345,10 @@ class sct_prim_fifo :
303
345
// If put() in thread and get makes FIFO empty, notifies get process
304
346
// as this put() allows one more get
305
347
if (!sync_valid && (USE_ELEM_NUM || element_num == 0 ||
306
- (cthread_put && get_req != get_req_d && element_num == 1 )))
348
+ (cthread_put && get_req != get_req_d && element_num == 1 )))
307
349
{
308
350
get_event.notify (GET_TIME);
351
+ if (peek_event) peek_event->notify (PEEK_TIME);
309
352
#ifdef NOTIFY_DEBUG
310
353
cout << " NOTIFIED put() " << name () << endl;
311
354
#endif
@@ -314,7 +357,7 @@ class sct_prim_fifo :
314
357
if (cthread_put) put_event.notify (PUT_TIME);
315
358
316
359
#ifdef SCT_TLM_DEBUG
317
- if (putTime == sc_time_stamp ()) {
360
+ if (cthread_put && putTime == sc_time_stamp ()) {
318
361
cout << sc_time_stamp () << " " << name () << " , ERROR: multiple put\n " << endl;
319
362
sc_assert (false );
320
363
}
@@ -337,6 +380,7 @@ class sct_prim_fifo :
337
380
(cthread_put && get_req != get_req_d && element_num == 1 )))
338
381
{
339
382
get_event.notify (GET_TIME);
383
+ if (peek_event) peek_event->notify (PEEK_TIME);
340
384
#ifdef NOTIFY_DEBUG
341
385
cout << " NOTIFIED put() " << name () << endl;
342
386
#endif
@@ -345,7 +389,7 @@ class sct_prim_fifo :
345
389
if (cthread_put) put_event.notify (PUT_TIME);
346
390
347
391
#ifdef SCT_TLM_DEBUG
348
- if (putTime == sc_time_stamp ()) {
392
+ if (cthread_put && putTime == sc_time_stamp ()) {
349
393
cout << sc_time_stamp () << " " << name () << " , ERROR: multiple put\n " << endl;
350
394
sc_assert (false );
351
395
}
@@ -371,8 +415,12 @@ class sct_prim_fifo :
371
415
// If @USE_ELEM_NUM every get notifies put process
372
416
// If get() in thread and put makes FIFO full, notifies put process
373
417
// as this get() allows one more put
418
+ // For Target/Initiator mode notify at almost full FIFO to allow put
419
+
374
420
if (!sync_ready && (USE_ELEM_NUM || element_num == fifoSize ||
375
- (cthread_get && put_req != put_req_d && element_num == fifoSize-1 )))
421
+ (cthread_get && put_req != put_req_d && element_num == fifoSize-1 ) ||
422
+ (targ_init && cthread_put && element_num == fifoSize-1 ) ||
423
+ (targ_init_sync && !cthread_put && cthread_get) ))
376
424
{
377
425
put_event.notify (PUT_TIME);
378
426
#ifdef NOTIFY_DEBUG
@@ -381,9 +429,10 @@ class sct_prim_fifo :
381
429
}
382
430
// Notify thread itself to allow next get
383
431
if (cthread_get) get_event.notify (GET_TIME);
432
+ if (peek_event && cthread_peek) peek_event->notify (PEEK_TIME);
384
433
385
434
#ifdef SCT_TLM_DEBUG
386
- if (getTime == sc_time_stamp ()) {
435
+ if (cthread_get && getTime == sc_time_stamp ()) {
387
436
cout << sc_time_stamp () << " " << name () << " , ERROR: multiple get\n " << endl;
388
437
sc_assert (false );
389
438
}
@@ -413,9 +462,10 @@ class sct_prim_fifo :
413
462
}
414
463
// Notify thread itself to allow next get
415
464
if (cthread_get) get_event.notify (GET_TIME);
465
+ if (peek_event && cthread_peek) peek_event->notify (PEEK_TIME);
416
466
417
467
#ifdef SCT_TLM_DEBUG
418
- if (getTime == sc_time_stamp ()) {
468
+ if (cthread_get && getTime == sc_time_stamp ()) {
419
469
cout << sc_time_stamp () << " " << name () << " , ERROR: multiple get\n " << endl;
420
470
sc_assert (false );
421
471
}
@@ -492,6 +542,12 @@ class sct_prim_fifo :
492
542
sync_ready = syncReady;
493
543
}
494
544
545
+ // / Set the FIFO used for Target/Initiator simulation
546
+ void setTargInit (bool sync = false ) {
547
+ if (sync ) targ_init_sync = true ;
548
+ else targ_init = true ;
549
+ }
550
+
495
551
public:
496
552
template <typename RSTN_t>
497
553
void clk_nrst (sc_in_clk& clk_in_, RSTN_t& nrst_in) {
@@ -554,9 +610,22 @@ class sct_prim_fifo :
554
610
555
611
void addPeekTo (sc_sensitive& s) override {
556
612
auto procKind = sc_get_current_process_handle ().proc_kind ();
613
+ bool cthread = procKind == SC_THREAD_PROC_ || procKind == SC_CTHREAD_PROC_;
614
+
615
+ if (peek_event) {
616
+ if (cthread_peek != cthread) {
617
+ cout << " \n Double addPeekTo() with different process kinds for : "
618
+ << name () << endl;
619
+ assert (false );
620
+ }
621
+ } else {
622
+ auto eventName = std::string (std::string (basename ()))+" _peek_event" ;
623
+ peek_event = new sc_event ( eventName.c_str () );
624
+ cthread_peek = cthread;
625
+ }
557
626
558
627
if (procKind != SC_CTHREAD_PROC_) {
559
- s << get_event ;
628
+ s << *peek_event ;
560
629
}
561
630
}
562
631
0 commit comments