314 fprintf(
f,
"rankdir=\"LR\";\n");
315 fprintf(
f,
"remincross=true;\n");
317 std::set<std::string> all_sources, all_sinks;
319 std::map<std::string, std::string> wires_on_demand;
323 const char *shape =
"diamond";
324 if (it.second->port_input || it.second->port_output)
326 if (it.first[0] ==
'\\') {
327 fprintf(
f,
"n%d [ shape=%s, label=\"%s\", %s, fontcolor=\"black\" ];\n",
330 if (it.second->port_input)
332 else if (it.second->port_output)
335 wires_on_demand[
stringf(
"n%d",
id2num(it.first))] = it.first.str();
341 fprintf(
f,
"{ rank=\"source\";");
342 for (
auto n : all_sources)
343 fprintf(
f,
" %s;",
n.c_str());
346 fprintf(
f,
"{ rank=\"sink\";");
347 for (
auto n : all_sinks)
348 fprintf(
f,
" %s;",
n.c_str());
357 std::vector<RTLIL::IdString> in_ports, out_ports;
359 for (
auto &conn : it.second->connections()) {
361 in_ports.push_back(conn.first);
363 out_ports.push_back(conn.first);
369 std::string label_string =
"{{";
371 for (
auto &p : in_ports)
374 it.second->getParam(p.str() +
"_SIGNED").as_bool() ?
"*" :
"");
375 if (label_string[label_string.size()-1] ==
'|')
376 label_string = label_string.substr(0, label_string.size()-1);
380 for (
auto &p : out_ports)
382 if (label_string[label_string.size()-1] ==
'|')
383 label_string = label_string.substr(0, label_string.size()-1);
385 label_string +=
"}}";
388 for (
auto &conn : it.second->connections()) {
393 #ifdef CLUSTER_CELLS_AND_PORTBOXES
395 fprintf(
f,
"subgraph cluster_c%d {\nc%d [ shape=record, label=\"%s\"%s ];\n%s}\n",
399 fprintf(
f,
"c%d [ shape=record, label=\"%s\"%s ];\n%s",
400 id2num(it.first), label_string.c_str(),
findColor(it.first.str()), code.c_str());
410 std::set<RTLIL::SigSpec> input_signals, output_signals;
417 for (
auto &sig : input_signals) {
418 std::string code, node;
420 fprintf(
f,
"%s", code.c_str());
426 for (
auto &sig : output_signals) {
427 std::string code, node;
429 fprintf(
f,
"%s", code.c_str());
436 if (proc->attributes.count(
"\\src") > 0)
437 proc_src = proc->attributes.at(
"\\src").decode_string();
438 fprintf(
f,
"p%d [shape=box, style=rounded, label=\"PROC %s\\n%s\"];\n", pidx,
findLabel(proc->
name.
str()), proc_src.c_str());
443 bool found_lhs_wire =
false;
444 for (
auto &c : conn.first.chunks()) {
446 found_lhs_wire =
true;
448 bool found_rhs_wire =
false;
449 for (
auto &c : conn.second.chunks()) {
451 found_rhs_wire =
true;
453 if (!found_lhs_wire || !found_rhs_wire)
456 std::string code, left_node, right_node;
457 code +=
gen_portbox(
"", conn.second,
false, &left_node);
458 code +=
gen_portbox(
"", conn.first,
true, &right_node);
459 fprintf(
f,
"%s", code.c_str());
461 if (left_node[0] ==
'x' && right_node[0] ==
'x') {
463 fprintf(
f,
"%s:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", left_node.c_str(), right_node.c_str(),
nextColor(conn).c_str(),
widthLabel(conn.first.size()).c_str());
469 if (left_node[0] ==
'x') {
471 }
else if (right_node[0] ==
'x') {
476 fprintf(
f,
"x%d [shape=box, style=rounded, label=\"BUF\"];\n",
single_idx_count++);
484 if (wires_on_demand.count(it.first) > 0) {
485 if (it.second.in.size() == 1 && it.second.out.size() > 1 && it.second.in.begin()->substr(0, 1) ==
"p")
486 it.second.out.erase(*it.second.in.begin());
487 if (it.second.in.size() == 1 && it.second.out.size() == 1) {
488 std::string from = *it.second.in.begin(), to = *it.second.out.begin();
489 if (from != to || from.substr(0, 1) !=
"p")
490 fprintf(
f,
"%s:e -> %s:w [%s, %s];\n", from.c_str(), to.c_str(),
nextColor(it.second.color).c_str(),
widthLabel(it.second.bits).c_str());
493 if (it.second.in.size() == 0 || it.second.out.size() == 0)
494 fprintf(
f,
"%s [ shape=diamond, label=\"%s\" ];\n", it.first.c_str(),
findLabel(wires_on_demand[it.first]));
496 fprintf(
f,
"%s [ shape=point ];\n", it.first.c_str());
498 for (
auto &it2 : it.second.in)
499 fprintf(
f,
"%s:e -> %s:w [%s, %s];\n", it2.c_str(), it.first.c_str(),
nextColor(it.second.color).c_str(),
widthLabel(it.second.bits).c_str());
500 for (
auto &it2 : it.second.out)
501 fprintf(
f,
"%s:e -> %s:w [%s, %s];\n", it.first.c_str(), it2.c_str(),
nextColor(it.second.color).c_str(),
widthLabel(it.second.bits).c_str());
std::string stringf(const char *fmt,...)
void sort(T *array, int size, LessThan lt)
const std::vector< RTLIL::SigSig > & connections() const
std::map< RTLIL::IdString, int > dot_id2num_store
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
static std::string unescape_id(std::string str)
const char * findColor(std::string member_name)
std::map< std::string, net_conn > net_conn_map
const char * findLabel(std::string member_name)
bool selected_member(RTLIL::IdString mod_name, RTLIL::IdString memb_name) const
bool cell_output(RTLIL::IdString type, RTLIL::IdString port)
const char * escape(std::string id, bool is_name=false)
std::vector< std::string > dot_escape_store
static uint32_t xorshift32(uint32_t x)
std::map< RTLIL::IdString, RTLIL::Process * > processes
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
void collect_proc_signals(std::vector< RTLIL::SigSpec > &obj, std::set< RTLIL::SigSpec > &signals)
std::string widthLabel(int bits)
std::string gen_portbox(std::string port, RTLIL::SigSpec sig, bool driver, std::string *node=NULL)
int id2num(RTLIL::IdString id)