-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspef.h
642 lines (497 loc) · 15 KB
/
spef.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
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
/*************************************************************************
*
* Copyright (c) 2022-2024 Rajit Manohar
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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_SPEF_H__
#define __ACT_SPEF_H__
#include <common/lex.h>
#include <common/hash.h>
#include <common/array.h>
#include <act/act.h>
/**
*
* @file spef.h
* @brief SPEF reader/writer API
*
*/
/**
* Use this macro to access any of the ActId pointers in the Spef data
* structures.
*/
#define SPEF_GET_PTR(x) ((ActId *)(((unsigned long)(x))&~3UL))
/**
* Returns 1 if the ActId pointer is in fact an absolute path to an
* identifier specified in the Spef rather than a simple path.
*/
#define SPEF_IS_ABS(x) (((unsigned long)x) & 1)
class Spef;
/** SPEF triplet structure for values. Values correspond to three
* different operating points: typical, best-case, and worst-case.
* Values are used for any paramter in the SPEF file.
*/
struct spef_triplet {
/// best case value
float best;
/// typical value
float typ;
/// worst-case value
float worst;
bool issingleton() { return (best == typ && best == worst) ? true : false; }
};
/** A collection of SPEF attributes that can be associated with a
* number of different parts of a SPEF file. The structure has flags
* to determine which attributes were in fact found in the file, and
* it also contains the values of the attributes that were found.
*/
struct spef_attributes {
/// 1 if simple attribute (not used)
unsigned int simple:1;
/// coordinates are specified
unsigned int coord:1;
/// load is specified
unsigned int load:1;
/// slew is specified
unsigned int slew:1;
/// threshold is specified as part of slew
unsigned int slewth:1;
/// driving cell is specified
unsigned int drive:1;
/// x-coordinate, if coordinates specified
double cx;
/// y-coordinate, if coordinates specified
double cy;
/// value of load capacitance, if specified
spef_triplet l;
/// the rising slew, if specified
spef_triplet s1;
/// the falling slew, if specified
spef_triplet s2;
/// the rising threshold (%), if specified
spef_triplet t1;
/// the falling threshold (%), if specified
spef_triplet t2;
/// driving cell type
ActId *cell;
};
/** An individual SPEF port. This specifies the instance + port
* combination, along with any attributes for the port and direction
* specifications.
*/
struct spef_ports {
/// The instance ID
ActId *inst;
/// The port from this instance
ActId *port;
/// SPEF attributes associated with this port
spef_attributes *a;
/// Port direction, 0 = in, 1 = out, 2 = bidir
unsigned int dir;
};
/** SPEF definitions. These are used for hierarchical SPEF files. The
* actual SPEF file corresponding to the definition is supposed to be
* determined in some "out-of-band" fashion. Parasitics from the
* sub-spef files are supposed to be merged in with the parent.
*/
struct spef_defines {
/// 1 for PDEFINE, 0 for DEFINE
unsigned int phys:1;
/// name of the instance
ActId *inst;
/// design name, which must match the design name in the child SPEF
char *design_name;
/// Spef data structure for the sub-SPEF corresponding to this definition
Spef *spef;
};
/** An individual end-point of a SPEF connection. A detailed net
* description consists of a number of these connections. A connection
* of type "P" is a port. A connection of type "I" is an internal
* node. The type "N" is used to specify coordinates for
* an internal node.
*/
struct spef_conn {
/// Type of connection: 0 = *P, 1 = *I, 2 = *N
unsigned int type:2;
/// Direction flag: 0 = in, 1 = out, 2 = bidir
unsigned int dir:2;
/// Connection name (path to the instance)
ActId *inst;
/// Pin name
ActId *pin;
/// Any attributes associate with this connection end-point
spef_attributes *a;
/// node number used to sub-divide net into different physical points for *N
int ipin;
/// coordinates for *N
float cx, cy;
};
/**
* A single SPEF node. It consists of an instance:pin, and an optional
* index that specifies the piece of the electrical node this
* corresponds to.
*
* The instance name can be NULL. The integer for internal nodes can
* also be omitted, in which case the idx field will be -1.
*/
struct spef_node {
/// instance name, if any; could be NULL
ActId *inst;
/// pin name
ActId *pin; // or pin
void Print (FILE *fp, char delim);
void mPrint (FILE *fp, char delim);
bool exists() { return pin ? true : false; }
void clear () {
if (SPEF_GET_PTR (inst))
delete SPEF_GET_PTR(inst);
if (SPEF_GET_PTR (pin))
delete SPEF_GET_PTR(pin);
inst = NULL; pin = NULL;
}
};
/**
* This is used to represent a parasitic value. For capacitors, the
* second node can be NULL (for cap to ground), or non-NULL for
* coupling capacitances. For resistors and inductors, both nodes must
* be non-NULL.
*/
struct spef_parasitic {
/// The integer id for this particular parasitic value
int id;
/// The first node associated with the parasitic value.
spef_node n;
/// The second node associated with the parastic value.
spef_node n2;
/// The actual value
spef_triplet val;
/* XXX: sensitivity: use with variations */
void Print (FILE *fp, char delim);
void spPrint (FILE *fp, char delim, double units);
void clear() {
n.clear ();
n2.clear ();
}
};
/**
* This holds the information for a SPEF *D_NET detailed net
* specification. It contains a list of connection end-points,
* followed by capacitors, resistors, and inductors for the net.
*/
struct spef_detailed_net {
/// array of connections for the detailed net
A_DECL (spef_conn, conn);
/// array of capacitors for the detailed net
A_DECL (spef_parasitic, caps);
/// array of resistors for the detailed net
A_DECL (spef_parasitic, res);
/// array of inductors for the detailed net
A_DECL (spef_parasitic, induc);
};
/**
* This holds a term for the RC reduced model for a net. The instance
* and pin name is included, followed by the RC value and optionally
* the complex pole and residue values for the particular node.
*/
struct spef_rc_desc {
/// instance + pin name
spef_node n;
/// RC value
spef_triplet val;
/**
* Pole/residue value structure
*/
struct pole_desc {
/// numerical index value, -1 means not specified
int idx;
/// real-part of value
spef_triplet re;
/// imaginary part of value
spef_triplet im;
} pole /** value of pole */, residue /** value of residue */;
};
/**
* Data structure that holds the information for one driver in a
* reduced *R_NET model for a net.
*/
struct spef_reduced {
/// instance name for driver
ActId *driver_inst;
/// pin for driver
ActId *pin;
/// cell type for driving cell
ActId *cell_type;
spef_triplet c2 /** pi-model C2 capacitance, the cap closest to the
driving cell */,
r1 /** pi model resistance */, c1 /** pi-model C1 capacitance,
the cap furthest from the
driving cell */;
/// array of RC values for different end-points of the net
A_DECL (spef_rc_desc, rc);
};
/**
* A spef *R_NET consists of a collection of drivers, and this holds
* the information for all the drivers.
*/
struct spef_reduced_net {
/// an array of drivers, each with their own end-point RC values and
/// parasitics
A_DECL (spef_reduced, drivers);
};
/**
* A SPEF net with parasitic information
*/
struct spef_net {
/// the net name
ActId *net;
/// total capacitance for the net
spef_triplet tot_cap;
/// routing confidence integer
int routing_confidence;
/// 0 = D_NET, 1 = R_NET, 2 = D_PNET, 3 = R_PNET
unsigned int type:2;
union {
/// if this is a detailed net, the information is here
spef_detailed_net d;
/// if this is a reduced net spec, the information is here
spef_reduced_net r;
} u /** the parasitic information */;
spef_net() {
net = NULL; type = 0;
A_INIT (u.d.conn);
A_INIT (u.d.caps);
A_INIT (u.d.induc);
A_INIT (u.d.res);
}
~spef_net() {
if (type == 0 || type == 2) {
for (int i=0; i < A_LEN (u.d.conn); i++) {
if (SPEF_GET_PTR (u.d.conn[i].inst)) {
delete SPEF_GET_PTR (u.d.conn[i].inst);
}
if (SPEF_GET_PTR (u.d.conn[i].pin)) {
delete SPEF_GET_PTR (u.d.conn[i].pin);
}
}
A_FREE (u.d.conn);
for (int i=0; i < A_LEN (u.d.caps); i++) {
u.d.caps[i].clear();
}
A_FREE (u.d.caps);
for (int i=0; i < A_LEN (u.d.induc); i++) {
u.d.induc[i].clear ();
}
A_FREE (u.d.induc);
for (int i=0; i < A_LEN (u.d.res); i++) {
u.d.res[i].clear ();
}
A_FREE (u.d.res);
}
else {
for (int i=0; i < A_LEN (u.r.drivers); i++) {
for (int j=0; j < A_LEN (u.r.drivers[i].rc); j++) {
u.r.drivers[i].rc[j].n.clear ();
}
A_FREE (u.r.drivers[i].rc);
if (SPEF_GET_PTR (u.r.drivers[i].driver_inst)) {
delete SPEF_GET_PTR (u.r.drivers[i].driver_inst);
}
if (SPEF_GET_PTR (u.r.drivers[i].pin)) {
delete SPEF_GET_PTR (u.r.drivers[i].pin);
}
if (SPEF_GET_PTR (u.r.drivers[i].cell_type)) {
delete SPEF_GET_PTR (u.r.drivers[i].cell_type);
}
}
A_FREE (u.r.drivers);
}
}
void Print (Spef *S, FILE *fp);
void spPrint (Spef *S, FILE *fp);
};
class SpefCollection;
/**
* API to read/write/query a SPEF file
*/
class Spef {
public:
/// @param mangled_ids should be set to true if the SPEF file
/// corresonds to layout where the names were generated using ACT
/// name mangling conventions. Doing so will convert all the names
/// back into sane ACT names.
Spef(bool mangled_ids = false);
~Spef();
/**
* Read in a SPEF file.
* @param fp the file pointer for the file to be read
* @return true on success, false on error
*/
bool Read (FILE *fp);
/**
* Read in a SPEF file.
* @param name the name of the SPEF file
* @return true on success, false on error
*/
bool Read (const char *name);
/**
* Print the SPEF data structure in SPEF format
* @param fp the output stream where the SPEF file should be printed
*/
void Print (FILE *fp);
/**
* Parse a SPEF triplet
* @param l is the lexer
* @param colon is the token name for ":"
* @param t is used to return the value of the triplet
* @return true if successful, false otherwise
*/
static bool getParasitics (LEX_T *l, int colon, spef_triplet *t);
char getPinDivider () { return _delimiter; }
/**
* @return true if this is a valid SPEF file, false otherwise
*/
bool isValid() { return _valid ? true : false; }
/**
* @return true if the specified net name is
* associated with parasitics, false otherwise
*/
bool isSplit (const char *s);
/**
* Print out the parasitics to a file
* @param fp is the output file
*/
void dumpRC (FILE *fp);
/**
* @return capacitance of 1 unit (F)
*/
double unitCap() { return _c_unit; }
/**
* @return resistance of 1 unit (Ohms)
*/
double unitResis() { return _r_unit; }
private:
/** The lexical analysis engine. This is non-NULL during the parsing
phase only.
*/
LEX_T *_l;
/** tokens */
int
#define TOKEN(a,b) a,
#include <act/spef.def>
_tok_hier_delim,
_tok_pin_delim,
_tok_prefix_bus_delim,
_tok_suffix_bus_delim;
char *_prevString ();
char *_getTokId();
ActId *_getTokPhysicalRef ();
ActId *_getTokPath (); // lsb is set to 1 if it is an abs path
ActId *_getTokName();
ActId *_getIndex(); // return ID from index, if it is an index
ActId *_strToId (char *s); // convert string to ActId segment
// return true on success, false otherwise
// isphy = true for physical ports, false otherwise
// returns inst name and port name
bool _getPortName (bool isphy, ActId **inst_name, ActId **port);
bool _getPinPortInternal (spef_node *n);
bool _getParasitics (spef_triplet *t);
bool _getComplexParasitics (spef_triplet *re, spef_triplet *im);
spef_attributes *_getAttributes();
/* read each section */
bool _read_header ();
bool _read_units ();
bool _read_name_map ();
bool _read_power_def ();
bool _read_external_def ();
bool _read_define_def ();
bool _read_variation_def ();
bool _read_internal_def ();
Act *_a;
/// This holds the SPEF version string from the file
char *_spef_version;
/// This holds the design name from the file
char *_design_name;
/// This holds the date string
char *_date;
/// This holds the vendor string
char *_vendor;
/// This holds the program string (the program that generated this file)
char *_program;
/// This holds the version number
char *_version;
/// SI units for time. The actual time in SI units is the value
/// multipled by _time_unit
double _time_unit;
/// units for capacitance.
double _c_unit;
/// units for resistance
double _r_unit;
/// units for inductance
double _l_unit;
/// character used for path divider
char _divider;
/// character used to divide the name from the path/net to pin
char _delimiter;
/// character for array open parens
char _bus_prefix_delim;
/// character for array close parens
char _bus_suffix_delim;
/* name map */
struct iHashtable *_nH;
/// 1 when the SPEF data stucture is populated and valid
unsigned int _valid:1;
/// An array of power nets in the design
A_DECL (ActId *, _power_nets);
/// An array of ground nets in the design
A_DECL (ActId *, _gnd_nets);
/// The top-level SPEF ports
A_DECL (spef_ports, _ports);
/// The top-level SPEF physical ports
A_DECL (spef_ports, _phyports);
/// SPEF defines, if any
A_DECL (spef_defines, _defines);
/// The SPEF nets with parasitic information
//A_DECL (spef_net, _nets);
struct cHashtable *_nets;
friend class SpefCollection;
};
/**
* A SPEF collection is a collection of individual parasitic SPEF
* files.
*/
class SpefCollection {
public:
SpefCollection();
~SpefCollection();
/**
* Add a SPEF file to the Spef collection
* @param name the name of the SPEF file
* @return true on success, false on error
*/
bool addSPEF (const char *name);
/**
* Read in extract file
* @param name the name of the SPEF file
* @return true on success, false on error
*/
bool ReadExt (const char *name);
private:
struct Hashtable *H; // hash of spef design names
};
struct cHashtable *idhash_new (int sz);
#endif /* __ACT_SPEF_H__ */