| 427 | } |
| 428 | |
| 429 | string GetOpLabel(const Model& model, const Operator& op) { |
| 430 | // Use HTML-like labels (http://www.graphviz.org/doc/info/shapes.html#html) |
| 431 | string html; |
| 432 | html += "<"; |
| 433 | |
| 434 | // Begin Table |
| 435 | html += R"CODE(<FONT POINT-SIZE="10" FACE="Courier">)CODE"; |
| 436 | html += |
| 437 | R"CODE(<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" CELLPADDING="0">)CODE"; |
| 438 | |
| 439 | // Input Ports |
| 440 | if (!op.inputs.empty()) { |
| 441 | html += R"CODE(<TR><TD COLSPAN="2" ALIGN="CENTER">)CODE"; |
| 442 | // Distribute evenly using a sub-table |
| 443 | html += R"CODE(<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0">)CODE"; |
| 444 | html += R"CODE(<TR>)CODE"; |
| 445 | for (int i = 0; i < op.inputs.size(); i++) { |
| 446 | html += R"CODE(<TD PORT=")CODE"; |
| 447 | AppendF(&html, "i%d", i); |
| 448 | html += R"CODE(">)CODE"; |
| 449 | if (op.inputs.size() > 1) { |
| 450 | // Only number inputs when op has two or more inputs |
| 451 | AppendF(&html, "%d", i); |
| 452 | } |
| 453 | html += "</TD>"; |
| 454 | } |
| 455 | html += "</TR>"; |
| 456 | html += R"CODE(</TABLE></TD></TR>)CODE"; |
| 457 | } |
| 458 | |
| 459 | // Name |
| 460 | html += R"CODE(<TR><TD COLSPAN="2" CELLPADDING="3" ALIGN="CENTER">)CODE"; |
| 461 | html += R"CODE(<FONT POINT-SIZE="16" FACE="Helvetica"><B>)CODE"; |
| 462 | if (op.type == OperatorType::kUnsupported) { |
| 463 | html += static_cast<const TensorFlowUnsupportedOperator&>(op).tensorflow_op; |
| 464 | } else { |
| 465 | html += string(absl::StripPrefix(OperatorTypeName(op.type), "TensorFlow")); |
| 466 | } |
| 467 | html += R"CODE(</B></FONT>)CODE"; |
| 468 | html += "</TD></TR>"; |
| 469 | |
| 470 | // Attributes |
| 471 | Attributes attrs = GetOpAttributes(model, op); |
| 472 | html += AttributesToHtml(attrs); |
| 473 | |
| 474 | // Output Ports |
| 475 | if (!op.outputs.empty()) { |
| 476 | html += R"CODE(<TR><TD COLSPAN="2" ALIGN="CENTER">)CODE"; |
| 477 | // Distribute evenly using a sub-table |
| 478 | html += R"CODE(<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0">)CODE"; |
| 479 | html += R"CODE(<TR>)CODE"; |
| 480 | for (int i = 0; i < op.outputs.size(); i++) { |
| 481 | html += R"CODE(<TD PORT=")CODE"; |
| 482 | AppendF(&html, "o%d", i); |
| 483 | html += R"CODE(">)CODE"; |
| 484 | if (op.outputs.size() > 1) { |
| 485 | // Only number outputs when op has two or more outputs |
| 486 | AppendF(&html, "%d", i); |
no test coverage detected