-
Notifications
You must be signed in to change notification settings - Fork 7
/
prssim.h
459 lines (384 loc) · 10.3 KB
/
prssim.h
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
/*************************************************************************
*
* Copyright (c) 2020 Rajit Manohar
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
**************************************************************************
*/
#ifndef __ACT_PRS_SIM_H__
#define __ACT_PRS_SIM_H__
#include <common/simdes.h>
#include "actsim.h"
/**
* Used to represent upgoing and downgoing delays. We need one bit of info
* to know if this is a single value or a value table; this information is
* not in this class, otherwise padding requirements would increase the
* storage needs. The bit is passed in to all methods.
*
* Delay table representation:
* [0] = # of slots
* [2*i+1] and [2*i+2] is slot i, corresponding to an (idx,val) pair
*
* If the msb of idx is 1, that is an unused slot.
*
*
*/
class gate_delay_info_onedir {
private:
union {
int val; // up delay is either a value (std)
int *val_tab; // ... or a value table (not std)
};
public:
// default is to assume it is a fixed delay
gate_delay_info_onedir() { val = -1; }
void clear() { val = -1; }
void delete_table() { FREE (val_tab); }
#define VAL_UNUSED (int)((1UL << (8*sizeof(int)-1)))
int lookup (int idx, bool fixed_delay = true) {
if (fixed_delay) {
return val;
}
int maxval = -1;
for (int i=0; i < val_tab[0]; i++) {
if (val_tab[2*i+1] == VAL_UNUSED) break;
if (val_tab[2*i+1] == idx) {
return val_tab[2*i+2];
}
if (maxval < val_tab[2*i+2]) {
maxval = val_tab[2*i+2];
}
}
// not found, return max value (conservative); returns -1 if there
// are no values in the table, i.e. the default delay.
return maxval;
}
void add (int idx, int dval, bool fixed_delay = true) {
int j = -1;
if (fixed_delay) {
val = dval;
return;
}
for (int i=0; i < val_tab[0]; i++) {
if (val_tab[2*i+1] == idx) {
if (val_tab[2*i+2] < dval) {
// this maxes out the sdf_conds for the moment
val_tab[2*i+2] = dval;
}
return;
}
if (val_tab[2*i+1] == VAL_UNUSED) {
j = i;
break;
}
}
if (j == -1) {
j = val_tab[0] + 2;
REALLOC (val_tab, int, j*2+1);
val_tab[0] = j;
j -= 2;
val_tab[2*j+1] = idx;
val_tab[2*j+2] = dval;
val_tab[2*j+3] = VAL_UNUSED;
}
else {
val_tab[2*j+1] = idx;
val_tab[2*j+2] = dval;
}
}
/*
* Increment delay!
*/
void inc (int idx, int dval, bool fixed_delay = true) {
int j = -1;
if (fixed_delay) {
val = dval;
return;
}
for (int i=0; i < val_tab[0]; i++) {
if (val_tab[2*i+1] == idx) {
val_tab[2*i+2] += dval;
return;
}
if (val_tab[2*i+1] == VAL_UNUSED) {
j = i;
break;
}
}
if (j == -1) {
j = val_tab[0] + 2;
REALLOC (val_tab, int, j*2+1);
val_tab[0] = j;
j -= 2;
val_tab[2*j+1] = idx;
val_tab[2*j+2] = dval;
val_tab[2*j+3] = VAL_UNUSED;
}
else {
val_tab[2*j+1] = idx;
val_tab[2*j+2] = dval;
}
}
void dump_table(FILE *fp) {
if (val_tab[0] != 0) {
fprintf (fp, "[");
for (int i=0; i < val_tab[0]; i++) {
if (val_tab[2*i+1] == VAL_UNUSED) break;
if (i != 0) {
fprintf (fp, " ");
}
fprintf (fp, "%d:%d", val_tab[2*i+1], val_tab[2*i+2]);
}
fprintf (fp, "]");
}
else {
fprintf (fp, "*");
}
}
void mkTables() {
MALLOC (val_tab, int, 3);
val_tab[0] = 1;
val_tab[1] = VAL_UNUSED; // unused marker
}
#undef VAL_UNUSED
};
struct gate_delay_info {
gate_delay_info_onedir up, dn;
gate_delay_info() : up(), dn() { }
void clear() {
up.clear ();
dn.clear();
}
void mkTables() {
up.mkTables();
dn.mkTables();
}
void delete_tables() {
up.delete_table();
dn.delete_table();
}
void dump_tables(FILE *fp) {
fprintf (fp, "{up: ");
up.dump_table (fp);
fprintf (fp, "; dn: ");
dn.dump_table (fp);
fprintf (fp, "}");
}
};
/*
* up, down, wup, wdn
*/
#define PRSSIM_EXPR_AND 0
#define PRSSIM_EXPR_OR 1
#define PRSSIM_EXPR_NOT 2
#define PRSSIM_EXPR_VAR 3
#define PRSSIM_EXPR_TRUE 4
#define PRSSIM_EXPR_FALSE 5
struct prssim_expr {
unsigned int type:3; /* AND, OR, NOT, VAR */
union {
struct {
prssim_expr *l, *r;
};
struct {
int vid;
act_connection *c;
};
};
};
#define PRSSIM_RULE 0
#define PRSSIM_PASSP 1
#define PRSSIM_PASSN 2
#define PRSSIM_TGATE 3
#define PRSSIM_NORM 0
#define PRSSIM_WEAK 1
struct prssim_stmt {
unsigned int type:2; /* RULE, P, N, TRANSGATE */
unsigned int unstab:1; /* is unstable? */
unsigned int std_delay:1; /* 1 if this uses the standard delay,
0 if it uses delay tables */
struct prssim_stmt *next;
// default inst-independent delays/delay tables
gate_delay_info delay;
union {
struct {
prssim_expr *up[2], *dn[2];
int vid;
act_connection *c;
};
struct {
int t1, t2, g, _g;
};
};
int delayUp(int idx) {
return delay.up.lookup (idx, std_delay ? true : false);
}
int delayDn(int idx) {
return delay.dn.lookup (idx, std_delay ? true : false);
}
void setUpDelay (int idx, int val) {
if (std_delay) return;
delay.up.add (idx, val, false);
}
void setDnDelay (int idx, int val) {
if (std_delay) return;
delay.dn.add (idx, val, false);
}
void incUpDelay (int idx, int val) {
if (std_delay) return;
delay.up.inc (idx, val, false);
}
void incDnDelay (int idx, int val) {
if (std_delay) return;
delay.dn.inc (idx, val, false);
}
void setDelayDefault() {
std_delay = 1;
delay.clear ();
}
/*
* delay tables:
* [0] = # of slots
* [2*i+1] and [2*i+2] is slot i, corresponding to an (idx, val) pair
*/
void setDelayTables() {
delay.mkTables ();
}
void setUpDelay (int val) {
if (!std_delay) return;
delay.up.add (0, val, true);
}
void setDnDelay (int val) {
if (!std_delay) return;
delay.dn.add (0, val, true);
}
bool simpleDelay() {
return std_delay ? true : false;
}
};
class PrsSimGraph {
private:
struct prssim_stmt *_rules, *_tail;
struct Hashtable *_labels;
void _add_one_rule (ActSimCore *, act_prs_lang_t *, sdf_cell *);
void _add_one_gate (ActSimCore *, act_prs_lang_t *);
public:
PrsSimGraph();
~PrsSimGraph();
void addPrs (ActSimCore *, act_prs_lang_t *, sdf_cell *);
prssim_stmt *getRules () { return _rules; }
struct Hashtable *getLabels() { return _labels; }
static PrsSimGraph *buildPrsSimGraph (ActSimCore *, act_prs *, sdf_cell *ci);
static void checkFragmentation (ActSimCore *, PrsSim *, act_prs *);
static void checkFragmentation (ActSimCore *, PrsSim *, act_prs_lang_t *);
static void checkFragmentation (ActSimCore *, PrsSim *, ActId *, int);
static void checkFragmentation (ActSimCore *, PrsSim *, act_prs_expr_t *);
};
class PrsSim : public ActSimObj {
public:
PrsSim (PrsSimGraph *, ActSimCore *sim, Process *p);
/* initialize simulation, and create initial event */
~PrsSim ();
int Step (Event *ev); /* run a step of the simulation */
void computeFanout ();
void initState ();
int getBool (int lid, int *gid = NULL) {
int off = getGlobalOffset (lid, 0);
if (gid) {
*gid = off;
}
return _sc->getBool (off);
}
int isSpecialBool (int lid) {
int off = getGlobalOffset (lid, 0);
return _sc->isSpecialBool (off);
}
bool isHazard (int lid) {
int off = getGlobalOffset (lid, 0);
return _sc->isHazard (off);
}
int myGid (int lid) { return getGlobalOffset (lid, 0); }
/*
me, cause are both used for cause tracing
*/
bool setBool (int lid, int v, OnePrsSim *me, ActSimObj *cause = NULL);
void printName (FILE *fp, int lid);
void sPrintName (char *buf, int sz, int lid);
void dumpState (FILE *fp);
inline int getDelay (int delay) { return _sc->getDelay (delay); }
inline int isResetMode() { return _sc->isResetMode (); }
inline int onWarning() { return _sc->onWarning(); }
void printStatus (int val, bool io_glob = false);
void registerExcl ();
void updateDelays (act_prs *prs, sdf_celltype *ci);
inline gate_delay_info *getInstDelay (OnePrsSim *sim);
private:
void _computeFanout (prssim_expr *, SimDES *);
void _updatePrs (act_prs_lang_t *p);
PrsSimGraph *_g;
int _nobjs; // # of simulation objects
OnePrsSim *_sim; // simulation objects
gate_delay_info **_inst_gate_delay; // delay info specific to each instance
};
/*-- not actsimobj so that it can be lightweight --*/
class OnePrsSim : public ActSimDES {
private:
PrsSim *_proc; // process core [maps, etc]
struct prssim_stmt *_me; // the rule
Event *_pending;
int eval (prssim_expr *, int cause_id = -1, int *lid = NULL);
public:
OnePrsSim (PrsSim *p, struct prssim_stmt *x);
int Step (Event *ev);
void propagate (void *cause);
void printName ();
int matches (int val);
void registerExcl ();
void flushPending ();
int isPending() { return _pending == NULL ? 0 : 1; }
void sPrintCause (char *buf, int sz);
int causeGlobalIdx ();
friend class MultiPrsSim;
};
class MultiPrsSim : public ActSimDES {
private:
OnePrsSim **_objs;
int _nobjs, _count;
public:
MultiPrsSim (int nobjs) {
Assert (nobjs > 1, "What?");
_nobjs = nobjs;
MALLOC (_objs, OnePrsSim *, _nobjs);
_count = 0;
}
~MultiPrsSim () {
if (_objs) {
FREE (_objs);
_objs = NULL;
}
}
void addOnePrsSim (OnePrsSim *x) {
Assert (_count < _nobjs, "What?");
_objs[_count++] = x;
}
/*-- virtual methods --*/
int Step (Event *ev);
void propagate (void *cause);
void sPrintCause (char *buf, int sz);
int causeGlobalIdx ();
};
#endif /* __ACT_CHP_SIM_H__ */