1 #include <ot/liberty/celllib.hpp>
2
3 namespace ot {
4
5 // Procedure: _uncomment
_uncomment(std::vector<char> & buffer)6 void Celllib::_uncomment(std::vector<char>& buffer) {
7
8 auto fsize = buffer.size() > 0 ? buffer.size() - 1 : 0;
9
10 // Mart out the comment
11 for(size_t i=0; i<fsize; ++i) {
12
13 // Block comment
14 if(buffer[i] == '/' && buffer[i+1] == '*') {
15 buffer[i] = buffer[i+1] = ' ';
16 for(i=i+2; i<fsize; buffer[i++]=' ') {
17 if(buffer[i] == '*' && buffer[i+1] == '/') {
18 buffer[i] = buffer[i+1] = ' ';
19 i = i+1;
20 break;
21 }
22 }
23 }
24
25 // Line comment
26 if(buffer[i] == '/' && buffer[i+1] == '/') {
27 buffer[i] = buffer[i+1] = ' ';
28 for(i=i+2; i<fsize; ++i) {
29 if(buffer[i] == '\n' || buffer[i] == '\r') {
30 break;
31 }
32 else buffer[i] = ' ';
33 }
34 }
35
36 // Pond comment
37 if(buffer[i] == '#') {
38 buffer[i] = ' ';
39 for(i=i+1; i<fsize; ++i) {
40 if(buffer[i] == '\n' || buffer[i] == '\r') {
41 break;
42 }
43 else buffer[i] = ' ';
44 }
45 }
46 }
47 }
48
49 // Procedure: _tokenize
_tokenize(const std::vector<char> & buf,std::vector<std::string_view> & tokens)50 void Celllib::_tokenize(const std::vector<char>& buf, std::vector<std::string_view>& tokens) {
51
52 static std::string_view dels = "(),:;/#[]{}*\"\\";
53
54 // get the position
55 const char* beg = buf.data();
56 const char* end = buf.data() + buf.size();
57
58 // Parse the token.
59 const char *token {nullptr};
60 size_t len {0};
61
62 tokens.clear();
63
64 for(const char* itr = beg; itr != end && *itr != 0; ++itr) {
65
66 // extract the entire quoted string as a token
67 bool is_del = (dels.find(*itr) != std::string_view::npos);
68
69 if(std::isspace(*itr) || is_del) {
70 if(len > 0) { // Add the current token.
71 tokens.push_back({token, len});
72 token = nullptr;
73 len = 0;
74 }
75 // group delimiter is liberty token
76 if(*itr == '(' || *itr == ')' || *itr == '{' || *itr == '}') {
77 tokens.push_back({itr, 1});
78 }
79 // extract the entire quoted string (this is buggy now...)
80 //else if(*itr == '"') {
81 // for(++itr; itr != end && *itr != '"'; ++itr, ++len) ;
82 // if(len > 0) {
83 // tokens.push_back({itr-len, len});
84 // len = 0;
85 // }
86 //}
87 }
88 else {
89 if(len == 0) {
90 token = itr;
91 }
92 ++len;
93 }
94 }
95
96 if(len > 0) {
97 tokens.push_back({token, len});
98 }
99 }
100
101 // ------------------------------------------------------------------------------------------------
102
103 // Function: to_string
to_string(DelayModel m)104 std::string to_string(DelayModel m) {
105 switch(m) {
106 case DelayModel::GENERIC_CMOS:
107 return "generic_cmos";
108 break;
109
110 case DelayModel::TABLE_LOOKUP:
111 return "table_lookup";
112 break;
113
114 case DelayModel::CMOS2:
115 return "cmos2";
116 break;
117
118 case DelayModel::PIECEWISE_CMOS:
119 return "piecewise_cmos";
120 break;
121
122 case DelayModel::DCM:
123 return "dcm";
124 break;
125
126 case DelayModel::POLYNOMIAL:
127 return "polynomial";
128 break;
129
130 default:
131 return "undefined";
132 break;
133 }
134 }
135
136 // Function: lut_template
lut_template(const std::string & name) const137 const LutTemplate* Celllib::lut_template(const std::string& name) const {
138 if(auto itr = lut_templates.find(name); itr == lut_templates.end()) {
139 return nullptr;
140 }
141 else {
142 return &(itr->second);
143 }
144 }
145
146 // Function: lut_template
lut_template(const std::string & name)147 LutTemplate* Celllib::lut_template(const std::string& name) {
148 if(auto itr = lut_templates.find(name); itr == lut_templates.end()) {
149 return nullptr;
150 }
151 else {
152 return &(itr->second);
153 }
154 }
155
156 // Function: cell
cell(const std::string & name) const157 const Cell* Celllib::cell(const std::string& name) const {
158 if(auto itr = cells.find(name); itr == cells.end()) {
159 return nullptr;
160 }
161 else {
162 return &(itr->second);
163 }
164 }
165
166 // Function: cell
cell(const std::string & name)167 Cell* Celllib::cell(const std::string& name) {
168 if(auto itr = cells.find(name); itr == cells.end()) {
169 return nullptr;
170 }
171 else {
172 return &(itr->second);
173 }
174 }
175
176 // Function: _extract_lut_template
_extract_lut_template(token_iterator & itr,const token_iterator end)177 LutTemplate Celllib::_extract_lut_template(token_iterator& itr, const token_iterator end) {
178
179 LutTemplate lt;
180
181 if(itr=on_next_parentheses(
182 itr,
183 end,
184 [&] (auto& name) mutable { lt.name = name; }); itr == end) {
185 OT_LOGF("can't find lut template name");
186 }
187
188 // Extract the lut template group
189 if(itr = std::find(itr, end, "{"); itr == end) {
190 OT_LOGF("can't find lut template group brace '{'");
191 }
192
193 //std::cout << lt.name << std::endl;
194
195 int stack = 1;
196
197 while(stack && ++itr != end) {
198
199 // variable 1
200 if(*itr == "variable_1") { // Read the variable.
201
202 if(++itr == end) {
203 OT_LOGF("variable_1 error in lut template ", lt.name);
204 }
205
206 if(auto vitr = lut_vars.find(*itr); vitr != lut_vars.end()) {
207 lt.variable1 = vitr->second;
208 }
209 else {
210 OT_LOGW("unexpected lut template variable ", *itr);
211 }
212 }
213 // variable 2
214 else if(*itr == "variable_2") {
215
216 if(++itr == end) {
217 OT_LOGF("variable_2 error in lut template ", lt.name);
218 }
219
220 if(auto vitr = lut_vars.find(*itr); vitr != lut_vars.end()) {
221 lt.variable2 = vitr->second;
222 }
223 else {
224 OT_LOGW("unexpected lut template variable ", *itr);
225 }
226 }
227 // index_1
228 else if(*itr == "index_1") {
229 itr = on_next_parentheses(itr, end, [&] (auto& str) {
230 lt.indices1.push_back(std::strtof(str.data(), nullptr));
231 });
232 }
233 // index_2
234 else if(*itr == "index_2") {
235 itr = on_next_parentheses(itr, end, [&] (auto& str) {
236 lt.indices2.push_back(std::strtof(str.data(), nullptr));
237 });
238 }
239 else if(*itr == "}") {
240 stack--;
241 }
242 else if(*itr == "{") {
243 stack++;
244 }
245 else {
246 }
247 }
248
249 if(stack != 0 || *itr != "}") {
250 OT_LOGF("can't find lut template group brace '}'");
251 }
252
253 return lt;
254 }
255
256 // Function: _extract_lut
_extract_lut(token_iterator & itr,const token_iterator end)257 Lut Celllib::_extract_lut(token_iterator& itr, const token_iterator end) {
258
259 Lut lut;
260
261 if(itr=on_next_parentheses(
262 itr,
263 end,
264 [&] (auto& name) mutable { lut.name = name; }); itr == end) {
265 OT_LOGF("can't find lut template name");
266 }
267
268 // Set up the template
269 lut.lut_template = lut_template(lut.name);
270
271 // Extract the lut group
272 if(itr = std::find(itr, end, "{"); itr == end) {
273 OT_LOGF("group brace '{' error in lut ", lut.name);
274 }
275
276 int stack = 1;
277
278 size_t size1 = 1;
279 size_t size2 = 1;
280
281 while(stack && ++itr != end) {
282
283 if(*itr == "index_1") {
284 itr = on_next_parentheses(itr, end, [&] (auto& v) mutable {
285 lut.indices1.push_back(std::strtof(v.data(), nullptr));
286 });
287
288 if(lut.indices1.size() == 0) {
289 OT_LOGF("syntax error in ", lut.name, " index_1");
290 }
291
292 size1 = lut.indices1.size();
293 }
294 else if(*itr == "index_2") {
295 itr = on_next_parentheses(itr, end, [&] (auto& v) mutable {
296 lut.indices2.push_back(std::strtof(v.data(), nullptr));
297 });
298
299 if(lut.indices2.size() == 0) {
300 OT_LOGF("syntax error in ", lut.name, " index_2");
301 }
302
303 size2 = lut.indices2.size();
304 }
305 else if(*itr == "values") {
306
307 if(lut.indices1.empty()) {
308 if(size1 != 1) {
309 OT_LOGF("empty indices1 in non-scalar lut ", lut.name);
310 }
311 lut.indices1.resize(size1);
312 }
313
314 if(lut.indices2.empty()){
315 if(size2 != 1) {
316 OT_LOGF("empty indices2 in non-scalar lut ", lut.name);
317 }
318 lut.indices2.resize(size2);
319 }
320
321 lut.table.resize(size1*size2);
322
323 int id {0};
324 itr = on_next_parentheses(itr, end, [&] (auto& v) mutable {
325 lut.table[id++] = std::strtof(v.data(), nullptr);
326 });
327 }
328 else if(*itr == "}") {
329 stack--;
330 }
331 else if(*itr == "{") {
332 stack++;
333 }
334 else {
335 }
336 }
337
338 if(stack != 0 || *itr != "}") {
339 OT_LOGF("group brace '}' error in lut ", lut.name);
340 }
341
342 return lut;
343 }
344
345 // Function: _extract_timing
_extract_timing(token_iterator & itr,const token_iterator end)346 Timing Celllib::_extract_timing(token_iterator& itr, const token_iterator end) {
347
348 Timing timing;
349
350 // Extract the lut template group
351 if(itr = std::find(itr, end, "{"); itr == end) {
352 OT_LOGF("can't find group brace '{' in timing");
353 }
354
355 int stack = 1;
356
357 while(stack && ++itr != end) {
358
359 if (*itr == "cell_fall") {
360 timing.cell_fall = _extract_lut(itr, end);
361 }
362 else if (*itr == "cell_rise") { // Rise delay.
363 timing.cell_rise = _extract_lut(itr, end);
364 }
365 else if (*itr == "fall_transition") { // Fall slew.
366 timing.fall_transition = _extract_lut(itr, end);
367 }
368 else if (*itr == "rise_transition") { // Rise slew.
369 timing.rise_transition = _extract_lut(itr, end);
370 }
371 else if (*itr == "rise_constraint") { // FF rise constraint.
372 timing.rise_constraint = _extract_lut(itr, end);
373 }
374 else if(*itr == "fall_constraint") { // FF fall constraint.
375 timing.fall_constraint = _extract_lut(itr, end);
376 }
377 else if(*itr == "timing_sense") { // Read the timing sense.
378
379 OT_LOGF_IF(++itr == end, "syntex error in timing_sense");
380
381 if(*itr == "negative_unate") {
382 timing.sense = TimingSense::NEGATIVE_UNATE; // Negative unate.
383 }
384 else if(*itr == "positive_unate") { // Positive unate.
385 timing.sense = TimingSense::POSITIVE_UNATE;
386 }
387 else if(*itr == "non_unate") { // Non unate.
388 timing.sense = TimingSense::NON_UNATE;
389 }
390 else {
391 OT_LOGF("unexpected timing sense ", *itr);
392 }
393 }
394 else if(*itr == "timing_type") {
395
396 if(++itr == end) {
397 OT_LOGF("syntax error in timing_type");
398 }
399
400 if(auto titr = timing_types.find(*itr); titr != timing_types.end()) {
401 timing.type = titr->second;
402 }
403 else {
404 OT_LOGW("unexpected timing type ", *itr);
405 }
406 }
407 else if (*itr == "related_pin") {
408
409 if(++itr == end) {
410 OT_LOGF("syntax error in related_pin");
411 }
412
413 timing.related_pin = *itr;
414 }
415 else if(*itr == "}") {
416 stack--;
417 }
418 else if(*itr == "{") {
419 stack++;
420 }
421 else {
422 }
423 }
424
425 if(stack != 0 || *itr != "}") {
426 OT_LOGF("can't find group brace '}' in timing");
427 }
428
429 return timing;
430 }
431
432 // Functoin: _extract_cellpin
_extract_cellpin(token_iterator & itr,const token_iterator end)433 Cellpin Celllib::_extract_cellpin(token_iterator& itr, const token_iterator end) {
434
435 Cellpin cellpin;
436
437 if(itr=on_next_parentheses(
438 itr,
439 end,
440 [&] (auto& name) mutable { cellpin.name = name; }); itr == end) {
441 OT_LOGF("can't find cellpin name");
442 }
443
444 // Extract the lut template group
445 if(itr = std::find(itr, end, "{"); itr == end) {
446 OT_LOGF("can't find group brace '{' in cellpin ", cellpin.name);
447 }
448
449 //std::cout << " -->" << cellpin.name << std::endl;
450
451 int stack = 1;
452
453 while(stack && ++itr != end) {
454
455 if(*itr == "direction") {
456
457 if(++itr == end) {
458 OT_LOGF("can't get the direction in cellpin ", cellpin.name);
459 }
460
461 if(auto ditr = cellpin_directions.find(*itr); ditr != cellpin_directions.end()) {
462 cellpin.direction = ditr->second;
463 }
464 else {
465 OT_LOGW("unexpected cellpin direction ", *itr);
466 }
467 }
468 else if(*itr == "capacitance") {
469 OT_LOGF_IF(++itr == end, "can't get the capacitance in cellpin ", cellpin.name);
470 cellpin.capacitance = std::strtof(itr->data(), nullptr);
471 }
472 else if(*itr == "max_capacitance") {
473 OT_LOGF_IF(++itr == end, "can't get the max_capacitance in cellpin ", cellpin.name);
474 cellpin.max_capacitance = std::strtof(itr->data(), nullptr);
475 }
476 else if(*itr == "min_capacitance") {
477 OT_LOGF_IF(++itr == end, "can't get the min_capacitance in cellpin ", cellpin.name);
478 cellpin.min_capacitance = std::strtof(itr->data(), nullptr);
479 }
480 else if(*itr == "max_transition") {
481 OT_LOGF_IF(++itr == end, "can't get the max_transition in cellpin ", cellpin.name);
482 cellpin.max_transition = std::strtof(itr->data(), nullptr);
483 }
484 else if(*itr == "min_transition") {
485 OT_LOGF_IF(++itr == end, "can't get the min_transition in cellpin ", cellpin.name);
486 cellpin.min_transition = std::strtof(itr->data(), nullptr);
487 }
488 else if(*itr == "fall_capacitance") {
489 OT_LOGF_IF(++itr == end, "can't get fall_capacitance in cellpin ", cellpin.name);
490 cellpin.fall_capacitance = std::strtof(itr->data(), nullptr);
491 }
492 else if(*itr == "rise_capacitance") {
493 OT_LOGF_IF(++itr == end, "can't get rise_capacitance in cellpin ", cellpin.name);
494 cellpin.rise_capacitance = std::strtof(itr->data(), nullptr);
495 }
496 else if(*itr == "fanout_load") {
497 OT_LOGF_IF(++itr == end, "can't get fanout_load in cellpin ", cellpin.name);
498 cellpin.fanout_load = std::strtof(itr->data(), nullptr);
499 }
500 else if(*itr == "max_fanout") {
501 OT_LOGF_IF(++itr == end, "can't get max_fanout in cellpin ", cellpin.name);
502 cellpin.max_fanout = std::strtof(itr->data(), nullptr);
503 }
504 else if(*itr == "min_fanout") {
505 OT_LOGF_IF(++itr == end, "can't get min_fanout in cellpin ", cellpin.name);
506 cellpin.min_fanout = std::strtof(itr->data(), nullptr);
507 }
508 else if(*itr == "clock") {
509 OT_LOGF_IF(++itr == end, "can't get the clock status in cellpin ", cellpin.name);
510 cellpin.is_clock = (*itr == "true") ? true : false;
511 }
512 else if(*itr == "original_pin") {
513 OT_LOGF_IF(++itr == end, "can't get the original pin in cellpin ", cellpin.name);
514 cellpin.original_pin = *itr;
515 }
516 else if(*itr == "timing") {
517 cellpin.timings.push_back(_extract_timing(itr, end));
518 }
519 else if(*itr == "}") {
520 stack--;
521 }
522 else if(*itr == "{") {
523 stack++;
524 }
525 else {
526 }
527 }
528
529 if(stack != 0 || *itr != "}") {
530 OT_LOGF("can't find group brace '}' in cellpin ", cellpin.name);
531 }
532
533 return cellpin;
534 }
535
536 // Function: _extract_cell
_extract_cell(token_iterator & itr,const token_iterator end)537 Cell Celllib::_extract_cell(token_iterator& itr, const token_iterator end) {
538
539 Cell cell;
540
541 if(itr=on_next_parentheses(
542 itr,
543 end,
544 [&] (auto& name) mutable { cell.name = name; }); itr==end) {
545 OT_LOGF("can't find cell name");
546 }
547
548 // Extract the lut template group
549 if(itr = std::find(itr, end, "{"); itr == end) {
550 OT_LOGF("can't find group brace '{' in cell ", cell.name);
551 }
552
553 int stack = 1;
554
555 while(stack && ++itr != end) {
556
557 if(*itr == "cell_leakage_power") { // Read the leakage power.
558 OT_LOGF_IF(++itr == end, "can't get leakage power in cell ", cell.name);
559 cell.leakage_power = std::strtof(itr->data(), nullptr);
560 }
561 else if(*itr == "cell_footprint") { // Read the footprint.
562 OT_LOGF_IF(++itr == end, "can't get footprint in cell ", cell.name);
563 cell.cell_footprint = *itr;
564 }
565 else if(*itr == "area") { // Read the area.
566 OT_LOGF_IF(++itr == end, "can't get area in cell ", cell.name);
567 cell.area = std::strtof(itr->data(), nullptr);
568 }
569 else if(*itr == "pin") { // Read the cell pin group.
570 auto pin = _extract_cellpin(itr, end);
571 cell.cellpins[pin.name] = std::move(pin);
572 }
573 else if(*itr == "}") {
574 stack--;
575 }
576 else if(*itr == "{") {
577 stack++;
578 }
579 else {
580 //OT_LOGW("unexpected token ", *itr);
581 }
582 }
583
584 if(stack != 0 || *itr != "}") {
585 OT_LOGF("can't find group brace '}' in cell ", cell.name);
586 }
587
588 return cell;
589 }
590
591 // Procedure: read
read(const std::filesystem::path & path)592 void Celllib::read(const std::filesystem::path& path) {
593
594 std::ifstream ifs(path, std::ios::ate);
595
596 // return on failure
597 OT_LOGF_IF(!ifs, "failed to open celllib ", path);
598
599 size_t fsize = ifs.tellg();
600 ifs.seekg(0, std::ios::beg);
601 std::vector<char> buffer(fsize + 1);
602 ifs.read(buffer.data(), fsize);
603 buffer[fsize] = 0;
604
605 // get tokens
606 std::vector<std::string_view> tokens;
607 tokens.reserve(buffer.size() / sizeof(std::string));
608
609 _uncomment(buffer);
610 _tokenize (buffer, tokens);
611
612 // Set up the iterator
613 auto itr = tokens.begin();
614 auto end = tokens.end();
615
616 // Read the library name.
617 if(itr = std::find(itr, end, "library"); itr == end) {
618 OT_LOGF("can't find keyword ", std::quoted("library"));
619 }
620
621 if(itr = on_next_parentheses(
622 itr,
623 end,
624 [&] (auto& str) mutable { name = str; }); itr == end) {
625 OT_LOGF("can't find library name");
626 }
627
628 // Extract the library group
629 if(itr = std::find(itr, tokens.end(), "{"); itr == tokens.end()) {
630 OT_LOGF("can't find library group symbol '{'");
631 }
632
633 int stack = 1;
634
635 while(stack && ++itr != end) {
636
637 if(*itr == "lu_table_template") {
638 auto lut = _extract_lut_template(itr, end);
639 lut_templates[lut.name] = lut;
640 }
641 else if(*itr == "delay_model") {
642 OT_LOGF_IF(++itr == end, "syntax error in delay_model");
643 if(auto ditr = delay_models.find(*itr); ditr != delay_models.end()) {
644 delay_model = ditr->second;
645 }
646 else {
647 OT_LOGW("unexpected delay model ", *itr);
648 }
649 }
650 else if(*itr == "default_cell_leakage_power") {
651 OT_LOGF_IF(++itr == end, "syntax error in default_cell_leakage_power");
652 default_cell_leakage_power = std::strtof(itr->data(), nullptr);
653 }
654 else if(*itr == "default_inout_pin_cap") {
655 OT_LOGF_IF(++itr == end, "syntax error in default_inout_pin_cap");
656 default_inout_pin_cap = std::strtof(itr->data(), nullptr);
657 }
658 else if(*itr == "default_input_pin_cap") {
659 OT_LOGF_IF(++itr == end, "syntax error in default_input_pin_cap");
660 default_input_pin_cap = std::strtof(itr->data(), nullptr);
661 }
662 else if(*itr == "default_output_pin_cap") {
663 OT_LOGF_IF(++itr == end, "syntax error in default_output_pin_cap");
664 default_output_pin_cap = std::strtof(itr->data(), nullptr);
665 }
666 else if(*itr == "default_fanout_load") {
667 OT_LOGF_IF(++itr == end, "syntax error in default_fanout_load");
668 default_fanout_load = std::strtof(itr->data(), nullptr);
669 }
670 else if(*itr == "default_max_fanout") {
671 OT_LOGF_IF(++itr == end, "syntax error in default_max_fanout");
672 default_max_fanout = std::strtof(itr->data(), nullptr);
673 }
674 else if(*itr == "default_max_transition") {
675 OT_LOGF_IF(++itr == end, "syntax error in default_max_transition");
676 default_max_transition = std::strtof(itr->data(), nullptr);
677 }
678 // TODO: Unit field.
679 else if(*itr == "time_unit") {
680 OT_LOGF_IF(++itr == end, "time_unit syntax error");
681 time_unit = make_time_unit(*itr);
682 }
683 else if(*itr == "voltage_unit") {
684 OT_LOGF_IF(++itr == end, "voltage_unit syntax error");
685 voltage_unit = make_voltage_unit(*itr);
686 }
687 else if(*itr == "current_unit") {
688 OT_LOGF_IF(++itr == end, "current_unit syntax error");
689 current_unit = make_current_unit(*itr);
690 }
691 else if(*itr == "pulling_resistance_unit") {
692 OT_LOGF_IF(++itr == end, "pulling_resistance_unit syntax error");
693 resistance_unit = make_resistance_unit(*itr);
694 }
695 else if(*itr == "leakage_power_unit") {
696 OT_LOGF_IF(++itr == end, "leakage_power_unit syntax error");
697 power_unit = make_power_unit(*itr);
698 }
699 else if(*itr == "capacitive_load_unit") {
700 std::string unit;
701 if(itr = on_next_parentheses(
702 itr,
703 end,
704 [&] (auto& str) mutable { unit += str; }); itr == end) {
705 OT_LOGF("capacitive_load_unit syntax error");
706 }
707 capacitance_unit = make_capacitance_unit(unit);
708 }
709 else if(*itr == "cell") {
710 auto cell = _extract_cell(itr, end);
711 cells[cell.name] = std::move(cell);
712 }
713 else if(*itr == "}") {
714 stack--;
715 }
716 else if(*itr == "{") {
717 stack++;
718 }
719 else {
720 }
721 }
722
723 if(stack != 0 || *itr != "}") {
724 OT_LOGF("can't find library group brace '}'");
725 }
726
727 _apply_default_values();
728 }
729
730 // Procedure: _apply_default_values
_apply_default_values()731 void Celllib::_apply_default_values() {
732
733 for(auto& ckvp : cells) {
734
735 auto& cell = ckvp.second;
736
737 // apply the default leakage power
738 if(!cell.leakage_power) {
739 cell.leakage_power = default_cell_leakage_power;
740 }
741
742 for(auto& pkvp : cell.cellpins) {
743
744 auto& cpin = pkvp.second;
745
746 // direction-specific default values
747 if(!cpin.direction) {
748 OT_LOGW("cellpin ", cell.name, '/', cpin.name, " has no direction defined");
749 continue;
750 }
751
752 switch(*cpin.direction) {
753
754 case CellpinDirection::INPUT:
755 if(!cpin.capacitance) {
756 cpin.capacitance = default_input_pin_cap;
757 }
758
759 if(!cpin.fanout_load) {
760 cpin.fanout_load = default_fanout_load;
761 }
762 break;
763
764 case CellpinDirection::OUTPUT:
765 if(!cpin.capacitance) {
766 cpin.capacitance = default_output_pin_cap;
767 }
768
769 if(!cpin.max_fanout) {
770 cpin.max_fanout = default_max_fanout;
771 }
772
773 if(!cpin.max_transition) {
774 cpin.max_transition = default_max_transition;
775 }
776 break;
777
778 case CellpinDirection::INOUT:
779 if(!cpin.capacitance) {
780 cpin.capacitance = default_inout_pin_cap;
781 }
782 break;
783
784 case CellpinDirection::INTERNAL:
785 break;
786 }
787
788 }
789 }
790 }
791
792 // Procedure: scale_time
793 // Convert the numerics to the new unit
scale_time(float s)794 void Celllib::scale_time(float s) {
795
796 if(default_max_transition) {
797 default_max_transition = *default_max_transition * s;
798 }
799
800 for(auto& c : cells) {
801 c.second.scale_time(s);
802 }
803 }
804
805 // Procedure: scale_capacitance
scale_capacitance(float s)806 void Celllib::scale_capacitance(float s) {
807
808 if(default_inout_pin_cap) {
809 default_inout_pin_cap = *default_inout_pin_cap * s;
810 }
811
812 if(default_input_pin_cap) {
813 default_input_pin_cap = *default_input_pin_cap * s;
814 }
815
816 if(default_output_pin_cap) {
817 default_output_pin_cap = *default_output_pin_cap * s;
818 }
819
820 for(auto& c : cells) {
821 c.second.scale_capacitance(s);
822 }
823 }
824
825 // Procedure: scale_voltage
scale_voltage(float s)826 void Celllib::scale_voltage(float s) {
827 // TODO
828 }
829
830 // Procedure: scale_current
scale_current(float s)831 void Celllib::scale_current(float s) {
832
833 // TODO
834 }
835
836 // Procedure: scale_resistance
scale_resistance(float s)837 void Celllib::scale_resistance(float s) {
838 // TODO
839 }
840
841 // Procedure: scale_power
scale_power(float s)842 void Celllib::scale_power(float s) {
843 // TODO
844 }
845
846 // Operator: <<
operator <<(std::ostream & os,const Celllib & c)847 std::ostream& operator << (std::ostream& os, const Celllib& c) {
848
849 // Write the comment.
850 os << "/* Generated by OpenTimer " << " */\n";
851
852 // Write library name.
853 os << "library (\"" << c.name << "\") {\n\n";
854
855 // Delay modeA
856 if(c.delay_model) {
857 os << "delay_model : " << to_string(*(c.delay_model)) << ";\n";
858 }
859
860 // Library units
861 if(auto u = c.time_unit; u) {
862 os << "time_unit : \"" << u->value() << "s\"\n";
863 }
864
865 if(auto u = c.voltage_unit; u) {
866 os << "voltage_unit : \"" << u->value() << "V\"\n";
867 }
868
869 if(auto u = c.current_unit; u) {
870 os << "current_unit : \"" << u->value() << "A\"\n";
871 }
872
873 if(auto u = c.resistance_unit; u) {
874 os << "pulling_resistance_unit : \"" << u->value() << "ohm\"\n";
875 }
876
877 if(auto u = c.power_unit; u) {
878 os << "leakage_power_unit : \"" << u->value() << "W\"\n";
879 }
880
881 if(auto u = c.capacitance_unit; u) {
882 os << "capacitive_load_unit (" << u->value() << ",F)\"\n";
883 }
884
885 // default values
886 if(c.default_cell_leakage_power) {
887 os << *c.default_cell_leakage_power << '\n';
888 }
889
890 if(c.default_inout_pin_cap) {
891 os << *c.default_inout_pin_cap << '\n';
892 }
893
894 if(c.default_input_pin_cap) {
895 os << *c.default_input_pin_cap << '\n';
896 }
897
898 if(c.default_output_pin_cap) {
899 os << *c.default_fanout_load << '\n';
900 }
901
902 if(c.default_max_fanout) {
903 os << *c.default_max_fanout << '\n';
904 }
905
906 if(c.default_max_transition) {
907 os << *c.default_max_transition << '\n';
908 }
909
910 // Write the lut templates
911 for(const auto& kvp : c.lut_templates) {
912 os << kvp.second << '\n';
913 }
914
915 // Write all cells.
916 for(const auto& kvp : c.cells) {
917 os << kvp.second << '\n';
918 }
919
920 // Write library ending group symbol.
921 os << "}\n";
922
923 return os;
924 }
925
926
927
928 }; // namespace ot. ------------------------------------------------------------------------------
929
930
931
932
933
934