我正在尝试在 LaTeX 上绘制类似这样的内容:
这是我的代码:
\documentclass[12pt]{article}
\usepackage{tikz}
\usetikzlibrary{shapes}
\usepackage[american,siunitx]{circuitikz}
\usepackage[margin=1in, landscape]{geometry}
\usepackage{changepage}
\usepackage{float}
\begin{document}
\begin{center}
\begin{circuitikz}
\tikzset{mux 4by1/.style={muxdemux,
muxdemux def={Lh=4, NL=4, Rh=2,
NB=2, w=2, square pins=1}}};
\draw(0, 0) node[mux 4by1, anchor=lpin 1](mux1){MUX};
\draw(mux1.lpin 3) to[short,*-] (mux1.lpin 4);
\draw($(mux1.rpin 1) + (2, 0)$) node[draw, text width = 2cm, minimum height = 2.5cm, text centered] (PC) {Program Counter};
\draw(PC.west) -- (mux1.rpin 1);
\draw($(PC.east) + (3, 0)$) node[draw, text width = 2cm, minimum height = 2.5cm, text centered] (IM) {Instruction Memory};
\tikzset{adder/.style={muxdemux,
muxdemux def={Lh=4, NL=2, Rh=2, NR=1, NB=0, w=1.5,
inset w=0.5, inset Lh=2, inset Rh=1.5}}};
\draw($(IM.north) + (0, 3)$) node[adder](add1){\Large $ + $};
\draw($(IM.south) + (0, -3)$) node[draw, text width = 2cm, minimum height = 2.5cm, text centered] (PCB) {PC Buffer};
\draw[very thick] (PC.east) to[bmultiwire=8, -*] ++(1, 0) coordinate(PCBusCon1) -- (IM.west);
\draw[very thick](PCBusCon1) |- (add1.blpin 2);
\draw (add1.rpin 1) -- ++(0.5, 0) -- ++(0, 1.5) -| (mux1.lpin 1);
\draw (add1.lpin 1) node[left]{$1$};
\draw[very thick](PCBusCon1) |- (PCB.west);'
\draw($(IM.east) + (3, 0)$) node[draw, minimum width = 1.25cm, minimum height = 14cm] (buff1){};
\node[align=center,rotate=90] at (buff1.center) {IF/ID Buffer};
\draw[very thick](PCB.east) to[bmultiwire=8] (PCB.east -| buff1.west);
\draw[very thick](IM.east) to[bmultiwire=8] (buff1.west);
\draw($(buff1.east) + (4, 0)$) node[draw, minimum width = 4 cm, text width = 2cm, minimum height = 5cm, text centered] (reg) {Register File};
\draw($(reg.north west)!1/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Read Address}](rA1){};
\draw($(reg.north west)!2/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Read Address}](rA2){};
\draw($(reg.north west)!6/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Write Address}](wA){};
\draw($(reg.north west)!7/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Data}](dataIn){};
\draw($(reg.north east)!1/8!(reg.south east)$)node[xshift = 0.2cm, label={[font=\scriptsize]left:Data}](dataOut1){};
\draw($(reg.north east)!2/8!(reg.south east)$)node[xshift = 0.2cm, label={[font=\scriptsize]left:Data}](dataOut2){};
\draw(reg.south) node[yshift = -0.2cm, label={[font=\scriptsize]above:Write}](writeIn){};
\tikzset{ellipseNode/.style={ellipse, draw = black, minimum width = 2 cm, minimum height = 4 cm}};
\draw($(reg.north) + (0, 3)$) node[ellipseNode](ctrl){Control};
\draw($(ctrl.north east)!2/8!(ctrl.south east)$) -- ++(1, 0);
\draw($(ctrl.north east)!3/8!(ctrl.south east)$) -- ++(1, 0);
\draw($(ctrl.north east)!4/8!(ctrl.south east)$) -- ++(1, 0);
\draw($(ctrl.north east)!5/8!(ctrl.south east)$) -- ++(1, 0);
\end{circuitikz}
\end{center}
\end{document}
输出:
有没有办法编写代码使得 LaTeX 中的输出与上面的相同?
答案1
这个答案引用了许多其他帖子,这些帖子都有链接。保护节点, 你可以说
\draw($(reg.north) + (0, 3)$) node[ellipseNode,protect](ctrl){Control};
\tikzset{protect last node}
那么没有路径可以进入该节点。这可以通过保存节点路径然后使用奇偶剪辑一些中的超大的盒子和节点路径。这意味着节点路径内部或超大框外部的所有内容(由于这是允许的 TeX 尺寸的最大值,您将无法到达)都将被剪掉。要详细了解这些步骤,请点击链接,那里的解释很棒,这个答案没有空间重复它们,也没有多大意义。
\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{circuitikz}
\usetikzlibrary{shapes.geometric,arrows.meta, positioning}
\makeatletter
% based on
% https://tex.stackexchange.com/a/38995/121799
% https://tex.stackexchange.com/a/76216
% https://tex.stackexchange.com/a/59168/194703
% https://tex.stackexchange.com/q/448920/194703
\tikzset{
reuse path/.code={\pgfsyssoftpath@setcurrentpath{#1}}
}
\tikzset{protect/.style={save path=\tmprotect},
even odd clip/.code={\pgfseteorule},
protect last node/.code={
\clip[overlay,even odd clip,reuse path=\tmprotect]
(-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt);
}}
\makeatother
\begin{document}
\begin{circuitikz}
\tikzset{mux 4by1/.style={muxdemux,
muxdemux def={Lh=4, NL=4, Rh=2,
NB=2, w=2, square pins=1}}};
\draw(0, 0) node[mux 4by1, anchor=lpin 1](mux1){MUX};
\draw(mux1.lpin 3) to[short,*-] (mux1.lpin 4);
\draw($(mux1.rpin 1) + (2, 0)$) node[draw, text width = 2cm, minimum height = 2.5cm, text centered] (PC) {Program Counter};
\draw(PC.west) -- (mux1.rpin 1);
\draw($(PC.east) + (3, 0)$) node[draw, text width = 2cm, minimum height = 2.5cm, text centered] (IM) {Instruction Memory};
\tikzset{adder/.style={muxdemux,
muxdemux def={Lh=4, NL=2, Rh=2, NR=1, NB=0, w=1.5,
inset w=0.5, inset Lh=2, inset Rh=1.5}}};
\draw($(IM.north) + (0, 3)$) node[adder](add1){\Large $ + $};
\draw($(IM.south) + (0, -3)$) node[draw, text width = 2cm, minimum height = 2.5cm, text centered] (PCB) {PC Buffer};
\draw[very thick] (PC.east) to[bmultiwire=8, -*] ++(1, 0) coordinate(PCBusCon1) -- (IM.west);
\draw[very thick](PCBusCon1) |- (add1.blpin 2);
\draw (add1.rpin 1) -- ++(0.5, 0) -- ++(0, 1.5) -| (mux1.lpin 1);
\draw (add1.lpin 1) node[left]{$1$};
\draw[very thick](PCBusCon1) |- (PCB.west);'
\draw($(IM.east) + (3, 0)$) node[draw, minimum width = 1.25cm, minimum height = 14cm] (buff1){};
\node[align=center,rotate=90] at (buff1.center) {IF/ID Buffer};
\draw[very thick](PCB.east) to[bmultiwire=8] (PCB.east -| buff1.west);
\draw[very thick](IM.east) to[bmultiwire=8] (buff1.west);
\draw($(buff1.east) + (4, 0)$) node[draw, minimum width = 4 cm, text width = 2cm, minimum height = 5cm, text centered] (reg) {Register File};
\draw($(reg.north west)!1/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Read Address}](rA1){};
\draw($(reg.north west)!2/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Read Address}](rA2){};
\draw($(reg.north west)!6/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Write Address}](wA){};
\draw($(reg.north west)!7/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Data}](dataIn){};
\draw($(reg.north east)!1/8!(reg.south east)$)node[xshift = 0.2cm, label={[font=\scriptsize]left:Data}](dataOut1){};
\draw($(reg.north east)!2/8!(reg.south east)$)node[xshift = 0.2cm, label={[font=\scriptsize]left:Data}](dataOut2){};
\draw(reg.south) node[yshift = -0.2cm, label={[font=\scriptsize]above:Write}](writeIn){};
\tikzset{ellipseNode/.style={ellipse, draw = black, minimum width = 2 cm, minimum height = 4 cm}};
\draw($(reg.north) + (0, 3)$) node[ellipseNode,protect](ctrl){Control};
\tikzset{protect last node}
\draw($(ctrl.north east)!2/8!(ctrl.south east)$) -- ++(1, 0);
\draw($(ctrl.north east)!3/8!(ctrl.south east)$) -- ++(1, 0);
\draw($(ctrl.north east)!4/8!(ctrl.south east)$) -- ++(1, 0);
\draw($(ctrl.north east)!5/8!(ctrl.south east)$) -- ++(1, 0);
\end{circuitikz}
\end{document}
当然也有一些快速而粗糙的选择,比如用白色填充节点并在背景层上绘图。
\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{circuitikz}
\usetikzlibrary{shapes.geometric,arrows.meta, positioning,backgrounds}
\begin{document}
\begin{circuitikz}
\tikzset{mux 4by1/.style={muxdemux,
muxdemux def={Lh=4, NL=4, Rh=2,
NB=2, w=2, square pins=1}}};
\draw(0, 0) node[mux 4by1, anchor=lpin 1](mux1){MUX};
\draw(mux1.lpin 3) to[short,*-] (mux1.lpin 4);
\draw($(mux1.rpin 1) + (2, 0)$) node[draw, text width = 2cm, minimum height = 2.5cm, text centered] (PC) {Program Counter};
\draw(PC.west) -- (mux1.rpin 1);
\draw($(PC.east) + (3, 0)$) node[draw, text width = 2cm, minimum height = 2.5cm, text centered] (IM) {Instruction Memory};
\tikzset{adder/.style={muxdemux,
muxdemux def={Lh=4, NL=2, Rh=2, NR=1, NB=0, w=1.5,
inset w=0.5, inset Lh=2, inset Rh=1.5}}};
\draw($(IM.north) + (0, 3)$) node[adder](add1){\Large $ + $};
\draw($(IM.south) + (0, -3)$) node[draw, text width = 2cm, minimum height = 2.5cm, text centered] (PCB) {PC Buffer};
\draw[very thick] (PC.east) to[bmultiwire=8, -*] ++(1, 0) coordinate(PCBusCon1) -- (IM.west);
\draw[very thick](PCBusCon1) |- (add1.blpin 2);
\draw (add1.rpin 1) -- ++(0.5, 0) -- ++(0, 1.5) -| (mux1.lpin 1);
\draw (add1.lpin 1) node[left]{$1$};
\draw[very thick](PCBusCon1) |- (PCB.west);'
\draw($(IM.east) + (3, 0)$) node[draw, minimum width = 1.25cm, minimum height = 14cm] (buff1){};
\node[align=center,rotate=90] at (buff1.center) {IF/ID Buffer};
\draw[very thick](PCB.east) to[bmultiwire=8] (PCB.east -| buff1.west);
\draw[very thick](IM.east) to[bmultiwire=8] (buff1.west);
\draw($(buff1.east) + (4, 0)$) node[draw, minimum width = 4 cm, text width = 2cm, minimum height = 5cm, text centered] (reg) {Register File};
\draw($(reg.north west)!1/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Read Address}](rA1){};
\draw($(reg.north west)!2/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Read Address}](rA2){};
\draw($(reg.north west)!6/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Write Address}](wA){};
\draw($(reg.north west)!7/8!(reg.south west)$)node[xshift = -0.2cm, label={[font=\scriptsize]right:Data}](dataIn){};
\draw($(reg.north east)!1/8!(reg.south east)$)node[xshift = 0.2cm, label={[font=\scriptsize]left:Data}](dataOut1){};
\draw($(reg.north east)!2/8!(reg.south east)$)node[xshift = 0.2cm, label={[font=\scriptsize]left:Data}](dataOut2){};
\draw(reg.south) node[yshift = -0.2cm, label={[font=\scriptsize]above:Write}](writeIn){};
\tikzset{ellipseNode/.style={ellipse, draw = black, minimum width = 2 cm, minimum height = 4 cm}};
\draw($(reg.north) + (0, 3)$) node[ellipseNode,fill=white](ctrl){Control};
\begin{scope}[on background layer]
\draw($(ctrl.north east)!2/8!(ctrl.south east)$) -- ++(1, 0);
\draw($(ctrl.north east)!3/8!(ctrl.south east)$) -- ++(1, 0);
\draw($(ctrl.north east)!4/8!(ctrl.south east)$) -- ++(1, 0);
\draw($(ctrl.north east)!5/8!(ctrl.south east)$) -- ++(1, 0);
\end{scope}
\end{circuitikz}
\end{document}
或者缓慢而昂贵的解决方案,例如计算与节点边界的交点。