aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--frontends/ast/genrtlil.cc3
-rw-r--r--manual/APPNOTE_011_Design_Investigation.tex239
-rw-r--r--manual/APPNOTE_011_Design_Investigation/.gitignore4
-rw-r--r--manual/APPNOTE_011_Design_Investigation/example.v5
-rw-r--r--manual/APPNOTE_011_Design_Investigation/example.ys6
-rw-r--r--manual/APPNOTE_011_Design_Investigation/make.sh8
-rw-r--r--manual/APPNOTE_011_Design_Investigation/splice.v9
-rw-r--r--manual/make_appnotes.sh4
-rw-r--r--passes/cmds/select.cc79
-rw-r--r--passes/cmds/show.cc91
11 files changed, 399 insertions, 51 deletions
diff --git a/Makefile b/Makefile
index 3a12ad81e..31ae76553 100644
--- a/Makefile
+++ b/Makefile
@@ -146,7 +146,7 @@ clean:
rm -f $(OBJS) $(GENFILES) $(TARGETS)
rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]*
rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d
- cd manual && rm -f *.aux *.bbl *.blg *.idx *.log *.out *.pdf *.toc
+ cd manual && rm -f *.aux *.bbl *.blg *.idx *.log *.out *.pdf *.toc *.ok
test ! -f libs/svgviewer/Makefile || make -C libs/svgviewer distclean
mrproper: clean
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index f7e7b852c..1453d13a9 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -265,6 +265,7 @@ struct AST_INTERNAL::ProcessGenerator
{
// generate process and simple root case
proc = new RTLIL::Process;
+ proc->attributes["\\src"] = stringf("%s:%d", always->filename.c_str(), always->linenum);
proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->linenum, RTLIL::autoidx++);
for (auto &attr : always->attributes) {
if (attr.second->type != AST_CONSTANT)
@@ -360,6 +361,8 @@ struct AST_INTERNAL::ProcessGenerator
do {
wire->name = stringf("$%d%s[%d:%d]", new_temp_count[chunk.wire]++,
chunk.wire->name.c_str(), chunk.width+chunk.offset-1, chunk.offset);;
+ if (chunk.wire->name.find('$') != std::string::npos)
+ wire->name += stringf("$%d", RTLIL::autoidx++);
} while (current_module->wires.count(wire->name) > 0);
wire->width = chunk.width;
current_module->wires[wire->name] = wire;
diff --git a/manual/APPNOTE_011_Design_Investigation.tex b/manual/APPNOTE_011_Design_Investigation.tex
new file mode 100644
index 000000000..9791ef797
--- /dev/null
+++ b/manual/APPNOTE_011_Design_Investigation.tex
@@ -0,0 +1,239 @@
+
+% IEEEtran howto:
+% http://ftp.univie.ac.at/packages/tex/macros/latex/contrib/IEEEtran/IEEEtran_HOWTO.pdf
+\documentclass[9pt,technote,a4paper]{IEEEtran}
+
+\usepackage[T1]{fontenc} % required for luximono!
+\usepackage[scaled=0.8]{luximono} % typewriter font with bold face
+
+% To install the luximono font files:
+% getnonfreefonts-sys --all or
+% getnonfreefonts-sys luximono
+%
+% when there are trouble you might need to:
+% - Create /etc/texmf/updmap.d/99local-luximono.cfg
+% containing the single line: Map ul9.map
+% - Run update-updmap followed by mktexlsr and updmap-sys
+%
+% This commands must be executed as root with a root environment
+% (i.e. run "sudo su" and then execute the commands in the root
+% shell, don't just prefix the commands with "sudo").
+
+\usepackage[unicode,bookmarks=false]{hyperref}
+\usepackage[english]{babel}
+\usepackage[utf8]{inputenc}
+\usepackage{amssymb}
+\usepackage{amsmath}
+\usepackage{amsfonts}
+\usepackage{units}
+\usepackage{nicefrac}
+\usepackage{eurosym}
+\usepackage{graphicx}
+\usepackage{verbatim}
+\usepackage{algpseudocode}
+\usepackage{scalefnt}
+\usepackage{xspace}
+\usepackage{color}
+\usepackage{colortbl}
+\usepackage{multirow}
+\usepackage{hhline}
+\usepackage{listings}
+\usepackage{float}
+
+\usepackage{tikz}
+\usetikzlibrary{calc}
+\usetikzlibrary{arrows}
+\usetikzlibrary{scopes}
+\usetikzlibrary{through}
+\usetikzlibrary{shapes.geometric}
+
+\def\FIXME{{\color{red}\bf FIXME}}
+
+\lstset{basicstyle=\ttfamily,frame=trBL,xleftmargin=2em,xrightmargin=1em,numbers=left}
+
+\begin{document}
+
+\title{Yosys Application Note 011: \\ Interactive Design Investigation}
+\author{Clifford Wolf \\ November 2013}
+\maketitle
+
+\begin{abstract}
+Yosys \cite{yosys} can be a great environment for building custom synthesis
+flows \cite{glaserwolf}. It can also be an excellent tool for teaching and
+learning Verilog based RTL synthesis. In both applications it is of great
+importance to be able to analyze the designs produces easily.
+
+This Yosys application note covers the generation of circuit diagrams with the
+Yosys {\tt show} command and the selection of interesting parts of the circuit
+using the {\tt select} command.
+\end{abstract}
+
+\section{Installation and Prerequisites}
+
+This Application Note is based on GIT Rev. {\tt \FIXME} from \FIXME{} of
+Yosys \cite{yosys}. The {\tt README} file covers how to install Yosys. The
+{\tt show} command requires a working installation of GraphViz \cite{graphviz}
+for generating the actual circuit diagrams. Yosys must be build with Qt
+support in order to activate the built-in SVG viewer. Alternatively an
+external viewer can be used.
+
+\section{Introduction to the {\tt show} command}
+
+The {\tt show} command generates a circuit diagram for the design in its
+current state. Various options can be used to change the appearance of the
+circuit diagram, set the name and format for the output file, and so forth.
+When called without any special options, it saves the circuit diagram in
+a temporary file and launches {\tt yosys-svgviewer} to display the diagram.
+Subsequent calls to {\tt show} re-use the {\tt yosys-svgviewer} instance
+(if still running).
+
+Fig.~\ref{example_src} shows a simple synthesis script and Verilog file that
+demonstrates the usage of {\tt show} in a simple setting. Note that {\tt show}
+is called with the {\tt -pause} option, that halts execution of the Yosys
+script until the user presses the Enter key. The {\tt show -pause} command
+also allows the user to enter an interactive shell to further investigate the
+circuit before continuing synthesis.
+
+\begin{figure}[b]
+\begin{lstlisting}
+$ cat example.ys
+read_verilog example.v
+show -pause
+proc
+show -pause
+opt
+show -pause
+
+$ cat example.v
+module example(input clk, a, b, c,
+ output reg [1:0] y);
+ always @(posedge clk)
+ if (c)
+ y <= c ? a + b : 2'd0;
+endmodule
+\end{lstlisting}
+\caption{Yosys script with {\tt show} commands and example design}
+\label{example_src}
+\end{figure}
+
+So this script, when executed, will show the design after each of the three
+synthesis commands. The generated circuit diagrams are shown in Fig.~\ref{example_out}.
+
+The first diagram (from top to bottom) shows the design directly after being
+read by the Verilog front-end. Input and output ports are visualized using
+octagonal shapes. Cells are visualized as rectangles with inputs on the left
+and outputs on the right side. The cell labels are two lines long: The first line
+contains the cell name (or a {\tt \_<number\_} placeholder for cells without
+a name from the original Verilog, such as cells created from Verilog
+expressions) and the second line contains the cell type. Internal cell types
+are prefixed with a dollar sign. The Yosys manual contains a chapter on the
+internal cell library used in Yosys.
+
+Constants are shown as ellipses with the constant value as label. The syntax
+{\tt <bit\_width>'<bits>} is used for for constants that are not 32-bit wide
+and/or contain bits that are not 0 or 1 (but {\tt x} or {\tt z}). Ordinary
+32-bit constants are written using decimal numbers.
+
+Single-bit signals are shown as thin arrows pointing from the driver to the
+load. Signals that are multiple bits wide are shown as think arrows.
+
+Finally {\it processes\/} are shown in boxes with round corners. Processes
+are Yosys' internal representation of the decision-trees and synchronization
+events modelled in a Verilog {\tt always}-block. The label reads {\tt PROC} in the
+first line and contains the source code location of the original {\tt
+always}-block in the 2nd line. Not how the multiplexer from the {\tt ?:}-expression
+is represented as a {\tt \$mux} cell but the multiplexer from the {\tt if}-statement
+is yet still hidden within the process.
+
+\medskip
+
+The {\tt proc} command transforms the process from the first diagram into a
+multiplexer and a d-type flip-flip, which brings us to the 2nd diagram.
+
+Note that the auto-generated numbers for the cells have changed since the first
+diagram, because they are just placeholders . We will cover how to avoid this
+later in this document.
+
+
+\begin{figure}[b!]
+\includegraphics[width=\linewidth]{APPNOTE_011_Design_Investigation/example_00.pdf}
+\includegraphics[width=\linewidth]{APPNOTE_011_Design_Investigation/example_01.pdf}
+\includegraphics[width=\linewidth]{APPNOTE_011_Design_Investigation/example_02.pdf}
+\caption{Output of the three {\tt show} commands from Fig.~\ref{example_src}}
+\label{example_out}
+\end{figure}
+
+Also note that the design now contains two instances of a {\tt BUF}-node. The
+Rhombus shape to the right is a dangling wire. (Wire nodes are only shown if
+they are dangling or have names assigned from the Verilog input.) This are
+artefacts left behind by the {\tt proc}-command. It is quite usual to see such
+artefacts after calling commands that perform changes in the design, as most
+commands only care about doing the transformation in a foolproof way, not about
+cleaning up after them. The next call to {\tt clean} (or {\tt opt}, which
+includes {\tt clean} as one of its operations) will clean up this artefacts.
+This operation is so common in Yosys scripts that it can simply be abbreviated
+by using the {\tt ;;} token, which doubles as separator for commands. Unless
+one wants to specifically analyze this artefacts left behind some operations,
+it is therefore recommended to call {\tt clean} before calling {\tt show}.
+
+\medskip
+
+In this script we directly call {\tt opt} as next step, which finally leads us to
+the 3rd diagram in Fig.~\ref{example_out}. Here we see that the {\tt opt} command
+not only has removed the artifacts left behind by {\tt proc}, but also determined
+correctly that it can remove the first {\tt \$mux} cell without changing the behavior
+of the circuit.
+
+\begin{figure}[b!]
+\includegraphics[width=\linewidth,trim=0 2cm 0 0]{APPNOTE_011_Design_Investigation/splice.pdf}
+\caption{Output of {\tt yosys -p 'proc; opt; show' splice.v}}
+\label{example_src}
+\end{figure}
+
+\begin{figure}[b!]
+\begin{lstlisting}
+module splice_demo(a, b, c, d, e, f, x, y);
+
+input [1:0] a, b, c, d, e, f;
+output [1:0] x = {a[0], a[1]};
+
+output [11:0] y;
+assign {y[11:4], y[1:0], y[3:2]} =
+ {a, b, -{c, d}, ~{e, f}};
+
+endmodule
+\end{lstlisting}
+\caption{\tt splice.v}
+\label{example_src}
+\end{figure}
+
+\FIXME{} --- Splicing, Cell libraries
+
+\section{Navigating the design}
+
+\FIXME{} --- cd and ls, multi-page diagrams, select, cones and boolean operations
+
+\section{Advanced investigation techniques}
+
+\FIXME{} --- dump, eval, sat
+
+\begin{thebibliography}{9}
+
+\bibitem{yosys}
+Clifford Wolf. The Yosys Open SYnthesis Suite.
+\url{http://www.clifford.at/yosys/}
+
+\bibitem{glaserwolf}
+Johann Glaser. Clifford Wolf. Methodology and Example-Driven Interconnect
+Synthesis for Designing Heterogeneous Coarse-Grain Reconfigurable
+Architectures. In: Jan Haase (Editor). {\it Models, Methods, and Tools for Complex Chip Design.
+Lecture Notes in Electrical Engineering. Volume 265, 2014, pp 201-221.\/}
+\href{http://dx.doi.org/10.1007/978-3-319-01418-0_12}{DOI 10.1007/978-3-319-01418-0\_12}
+
+\bibitem{graphviz}
+Graphviz - Graph Visualization Software.
+\url{http://www.graphviz.org/}
+
+\end{thebibliography}
+
+\end{document}
diff --git a/manual/APPNOTE_011_Design_Investigation/.gitignore b/manual/APPNOTE_011_Design_Investigation/.gitignore
new file mode 100644
index 000000000..b6fb30680
--- /dev/null
+++ b/manual/APPNOTE_011_Design_Investigation/.gitignore
@@ -0,0 +1,4 @@
+example_00.dot
+example_01.dot
+example_02.dot
+splice.dot
diff --git a/manual/APPNOTE_011_Design_Investigation/example.v b/manual/APPNOTE_011_Design_Investigation/example.v
new file mode 100644
index 000000000..ec272011c
--- /dev/null
+++ b/manual/APPNOTE_011_Design_Investigation/example.v
@@ -0,0 +1,5 @@
+module example(input clk, a, b, c, output reg [1:0] y);
+always @(posedge clk)
+ if (c)
+ y <= c ? a + b : 2'd0;
+endmodule
diff --git a/manual/APPNOTE_011_Design_Investigation/example.ys b/manual/APPNOTE_011_Design_Investigation/example.ys
new file mode 100644
index 000000000..6c9ff7983
--- /dev/null
+++ b/manual/APPNOTE_011_Design_Investigation/example.ys
@@ -0,0 +1,6 @@
+read_verilog example.v
+show -format dot -prefix example_00
+proc
+show -format dot -prefix example_01
+opt
+show -format dot -prefix example_02
diff --git a/manual/APPNOTE_011_Design_Investigation/make.sh b/manual/APPNOTE_011_Design_Investigation/make.sh
new file mode 100644
index 000000000..60c6c6be3
--- /dev/null
+++ b/manual/APPNOTE_011_Design_Investigation/make.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+../../yosys example.ys
+../../yosys -p 'proc; opt; show -format dot -prefix splice' splice.v
+sed -i '/^label=/ d;' example_*.dot splice.dot
+dot -Tpdf -o example_00.pdf example_00.dot
+dot -Tpdf -o example_01.pdf example_01.dot
+dot -Tpdf -o example_02.pdf example_02.dot
+dot -Tpdf -o splice.pdf splice.dot
diff --git a/manual/APPNOTE_011_Design_Investigation/splice.v b/manual/APPNOTE_011_Design_Investigation/splice.v
new file mode 100644
index 000000000..b6796c516
--- /dev/null
+++ b/manual/APPNOTE_011_Design_Investigation/splice.v
@@ -0,0 +1,9 @@
+module splice_demo(a, b, c, d, e, f, x, y);
+
+input [1:0] a, b, c, d, e, f;
+output [1:0] x = {a[0], a[1]};
+
+output [11:0] y;
+assign {y[11:4], y[1:0], y[3:2]} = {a, b, -{c, d}, ~{e, f}};
+
+endmodule
diff --git a/manual/make_appnotes.sh b/manual/make_appnotes.sh
index 00f875760..478e4cf9e 100644
--- a/manual/make_appnotes.sh
+++ b/manual/make_appnotes.sh
@@ -1,10 +1,10 @@
#!/bin/bash
set -ex
-for job in APPNOTE_010_Verilog_to_BLIF
+for job in APPNOTE_010_Verilog_to_BLIF APPNOTE_011_Design_Investigation
do
[ -f $job.ok -a $job.ok -nt $job.tex ] && continue
- old_md5=$([ -f $job.aux ] && md5sum < $job.aux)
+ old_md5=$([ -f $job.aux ] && md5sum < $job.aux || true)
while
pdflatex -shell-escape -halt-on-error $job.tex
new_md5=$(md5sum < $job.aux)
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index 1ab15c9a9..c424966ff 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -29,10 +29,20 @@ static std::vector<RTLIL::Selection> work_stack;
static bool match_ids(RTLIL::IdString id, std::string pattern)
{
- if (!fnmatch(pattern.c_str(), id.c_str(), FNM_NOESCAPE))
+ if (id == pattern)
return true;
- if (id.size() > 0 && id[0] == '\\' && !fnmatch(pattern.c_str(), id.substr(1).c_str(), FNM_NOESCAPE))
+ if (id.size() > 0 && id[0] == '\\' && id.substr(1) == pattern)
return true;
+ if (!fnmatch(pattern.c_str(), id.c_str(), 0))
+ return true;
+ if (id.size() > 0 && id[0] == '\\' && !fnmatch(pattern.c_str(), id.substr(1).c_str(), 0))
+ return true;
+ if (id.size() > 0 && id[0] == '$' && pattern.size() > 0 && pattern[0] == '$') {
+ const char *p = id.c_str();
+ const char *q = strrchr(p, '$');
+ if (pattern == q)
+ return true;
+ }
return false;
}
@@ -993,6 +1003,24 @@ struct CdPass : public Pass {
log_cmd_error("No such module `%s' found!\n", RTLIL::id2cstr(modname));
}
} CdPass;
+
+template<typename T>
+static int log_matches(const char *title, std::string pattern, T list)
+{
+ std::vector<std::string> matches;
+
+ for (auto &it : list)
+ if (pattern.empty() || match_ids(it.first, pattern))
+ matches.push_back(it.first);
+
+ if (matches.empty())
+ return 0;
+
+ log("\n%d %s:\n", int(matches.size()), title);
+ for (auto &id : matches)
+ log(" %s\n", RTLIL::id2cstr(id));
+ return matches.size();
+}
struct LsPass : public Pass {
LsPass() : Pass("ls", "list modules or objects in modules") { }
@@ -1000,53 +1028,40 @@ struct LsPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" ls\n");
+ log(" ls [pattern]\n");
log("\n");
- log("When no active module is selected, this prints a list of all module.\n");
+ log("When no active module is selected, this prints a list of all modules.\n");
log("\n");
log("When an active module is selected, this prints a list of objects in the module.\n");
log("\n");
+ log("If a pattern is given, the objects matching the pattern are printed\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- if (args.size() != 1)
+ std::string pattern;
+ int counter = 0;
+
+ if (args.size() != 1 && args.size() != 2)
log_cmd_error("Invalid number of arguments.\n");
+ if (args.size() == 2)
+ pattern = args.at(1);
if (design->selected_active_module.empty())
{
- log("\n%d modules:\n", int(design->modules.size()));
- for (auto &it : design->modules)
- log(" %s\n", RTLIL::id2cstr(it.first));
+ counter += log_matches("modules", pattern, design->modules);
}
else
if (design->modules.count(design->selected_active_module) > 0)
{
RTLIL::Module *module = design->modules.at(design->selected_active_module);
-
- if (module->wires.size()) {
- log("\n%d wires:\n", int(module->wires.size()));
- for (auto &it : module->wires)
- log(" %s\n", RTLIL::id2cstr(it.first));
- }
-
- if (module->memories.size()) {
- log("\n%d memories:\n", int(module->memories.size()));
- for (auto &it : module->memories)
- log(" %s\n", RTLIL::id2cstr(it.first));
- }
-
- if (module->cells.size()) {
- log("\n%d cells:\n", int(module->cells.size()));
- for (auto &it : module->cells)
- log(" %s\n", RTLIL::id2cstr(it.first));
- }
-
- if (module->processes.size()) {
- log("\n%d processes:\n", int(module->processes.size()));
- for (auto &it : module->processes)
- log(" %s\n", RTLIL::id2cstr(it.first));
- }
+ counter += log_matches("wires", pattern, module->wires);
+ counter += log_matches("memories", pattern, module->memories);
+ counter += log_matches("cells", pattern, module->cells);
+ counter += log_matches("processes", pattern, module->processes);
}
+
+ // log("\nfound %d item%s.\n", counter, counter == 1 ? "" : "s");
}
} LsPass;
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index adb925cb9..fc3575c62 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -22,6 +22,7 @@
#include "kernel/log.h"
#include <string.h>
#include <dirent.h>
+#include <readline/readline.h>
using RTLIL::id2cstr;
@@ -45,6 +46,8 @@ struct ShowWorker
uint32_t currentColor;
bool genWidthLabels;
bool stretchIO;
+ bool enumerateIds;
+ bool abbreviateIds;
int page_counter;
const std::vector<std::pair<std::string, RTLIL::Selection>> &color_selections;
@@ -113,11 +116,17 @@ struct ShowWorker
return "";
if (id[0] == '$' && is_name) {
- if (autonames.count(id) == 0) {
- autonames[id] = autonames.size() + 1;
- log("Generated short name for internal identifier: _%d_ -> %s\n", autonames[id], id.c_str());
+ if (enumerateIds) {
+ if (autonames.count(id) == 0) {
+ autonames[id] = autonames.size() + 1;
+ log("Generated short name for internal identifier: _%d_ -> %s\n", autonames[id], id.c_str());
+ }
+ id = stringf("_%d_", autonames[id]);
+ } else if (abbreviateIds) {
+ const char *p = id.c_str();
+ const char *q = strrchr(p, '$');
+ id = std::string(q);
}
- id = stringf("_%d_", autonames[id]);
}
if (id[0] == '\\')
@@ -376,6 +385,8 @@ struct ShowWorker
code += gen_portbox("", sig, false, &node);
fprintf(f, "%s", code.c_str());
net_conn_map[node].out.insert(stringf("p%d", pidx));
+ net_conn_map[node].bits = sig.width;
+ net_conn_map[node].color = nextColor(sig, net_conn_map[node].color);
}
for (auto &sig : output_signals) {
@@ -383,9 +394,14 @@ struct ShowWorker
code += gen_portbox("", sig, true, &node);
fprintf(f, "%s", code.c_str());
net_conn_map[node].in.insert(stringf("p%d", pidx));
+ net_conn_map[node].bits = sig.width;
+ net_conn_map[node].color = nextColor(sig, net_conn_map[node].color);
}
- fprintf(f, "p%d [shape=box, style=rounded, label=\"PROC\\n%s\"];\n", pidx, RTLIL::id2cstr(proc->name));
+ std::string proc_src = RTLIL::unescape_id(proc->name);
+ if (proc->attributes.count("\\src") > 0)
+ proc_src = proc->attributes.at("\\src").str;
+ fprintf(f, "p%d [shape=box, style=rounded, label=\"PROC %s\\n%s\"];\n", pidx, escape(proc->name, true), proc_src.c_str());
}
for (auto &conn : module->connections)
@@ -410,8 +426,8 @@ struct ShowWorker
if (left_node[0] == 'x' && right_node[0] == 'x') {
currentColor = xorshift32(currentColor);
- 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.width).c_str());
- } else {
+ 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.width).c_str());
+ } else {
net_conn_map[right_node].bits = conn.first.width;
net_conn_map[right_node].color = nextColor(conn, net_conn_map[right_node].color);
net_conn_map[left_node].bits = conn.first.width;
@@ -454,10 +470,12 @@ struct ShowWorker
fprintf(f, "};\n");
}
- ShowWorker(FILE *f, RTLIL::Design *design, std::vector<RTLIL::Design*> &libs, uint32_t colorSeed, bool genWidthLabels, bool stretchIO,
+ ShowWorker(FILE *f, RTLIL::Design *design, std::vector<RTLIL::Design*> &libs, uint32_t colorSeed,
+ bool genWidthLabels, bool stretchIO, bool enumerateIds, bool abbreviateIds,
const std::vector<std::pair<std::string, RTLIL::Selection>> &color_selections,
const std::vector<std::pair<std::string, RTLIL::Selection>> &label_selections) :
- f(f), design(design), currentColor(colorSeed), genWidthLabels(genWidthLabels), stretchIO(stretchIO),
+ f(f), design(design), currentColor(colorSeed), genWidthLabels(genWidthLabels),
+ stretchIO(stretchIO), enumerateIds(enumerateIds), abbreviateIds(abbreviateIds),
color_selections(color_selections), label_selections(label_selections)
{
ct.setup_internals();
@@ -536,6 +554,15 @@ struct ShowPass : public Pass {
log(" stretch the graph so all inputs are on the left side and all outputs\n");
log(" (including inout ports) are on the right side.\n");
log("\n");
+ log(" -pause\n");
+ log(" wait for the use to press enter to before returning\n");
+ log("\n");
+ log(" -enum\n");
+ log(" enumerate objects with internal ($-prefixed) names\n");
+ log("\n");
+ log(" -long\n");
+ log(" do not abbeviate objects with internal ($-prefixed) names\n");
+ log("\n");
log("When no <format> is specified, SVG is used. When no <format> and <viewer> is\n");
log("specified, 'yosys-svgviewer' is used to display the schematic.\n");
log("\n");
@@ -559,6 +586,9 @@ struct ShowPass : public Pass {
uint32_t colorSeed = 0;
bool flag_width = false;
bool flag_stretch = false;
+ bool flag_pause = false;
+ bool flag_enum = false;
+ bool flag_abbeviate = true;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -610,6 +640,20 @@ struct ShowPass : public Pass {
flag_stretch= true;
continue;
}
+ if (arg == "-pause") {
+ flag_pause= true;
+ continue;
+ }
+ if (arg == "-enum") {
+ flag_enum = true;
+ flag_abbeviate = false;
+ continue;
+ }
+ if (arg == "-long") {
+ flag_enum = false;
+ flag_abbeviate = false;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -651,7 +695,7 @@ struct ShowPass : public Pass {
delete lib;
log_cmd_error("Can't open dot file `%s' for writing.\n", dot_file.c_str());
}
- ShowWorker worker(f, design, libs, colorSeed, flag_width, flag_stretch, color_selections, label_selections);
+ ShowWorker worker(f, design, libs, colorSeed, flag_width, flag_stretch, flag_enum, flag_abbeviate, color_selections, label_selections);
fclose(f);
for (auto lib : libs)
@@ -660,24 +704,39 @@ struct ShowPass : public Pass {
if (worker.page_counter == 0)
log_cmd_error("Nothing there to show.\n");
- std::string cmd = stringf("dot -T%s -o '%s' '%s'", format.empty() ? "svg" : format.c_str(), out_file.c_str(), dot_file.c_str());
- log("Exec: %s\n", cmd.c_str());
- if (system(cmd.c_str()) != 0)
- log_cmd_error("Shell command failed!\n");
+ if (format != "dot") {
+ std::string cmd = stringf("dot -T%s -o '%s' '%s'", format.empty() ? "svg" : format.c_str(), out_file.c_str(), dot_file.c_str());
+ log("Exec: %s\n", cmd.c_str());
+ if (system(cmd.c_str()) != 0)
+ log_cmd_error("Shell command failed!\n");
+ }
if (!viewer_exe.empty()) {
- cmd = stringf("%s '%s' &", viewer_exe.c_str(), out_file.c_str());
+ std::string cmd = stringf("%s '%s' &", viewer_exe.c_str(), out_file.c_str());
log("Exec: %s\n", cmd.c_str());
if (system(cmd.c_str()) != 0)
log_cmd_error("Shell command failed!\n");
} else
if (format.empty()) {
- cmd = stringf("fuser -s '%s' || '%s' '%s' &", out_file.c_str(), rewrite_yosys_exe("yosys-svgviewer").c_str(), out_file.c_str());
+ std::string cmd = stringf("fuser -s '%s' || '%s' '%s' &", out_file.c_str(), rewrite_yosys_exe("yosys-svgviewer").c_str(), out_file.c_str());
log("Exec: %s\n", cmd.c_str());
if (system(cmd.c_str()) != 0)
log_cmd_error("Shell command failed!\n");
}
+ if (flag_pause) {
+ char *input = NULL;
+ while ((input = readline("Press ENTER to continue (or type 'shell' to open a shell)> ")) != NULL) {
+ if (input[strspn(input, " \t\r\n")] == 0)
+ break;
+ char *p = input + strspn(input, " \t\r\n");
+ if (!strcmp(p, "shell")) {
+ Pass::call(design, "shell");
+ break;
+ }
+ }
+ }
+
log_pop();
}
} ShowPass;