2

I am trying to draw something like this on LaTeX:

enter image description here

Here is my code:

\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}

Output:

enter image description here

Is there a way to write a code such that the output in LaTeX is the same as above?

Superman
  • 1,615

1 Answers1

2

This answer uses a lot of other posts, which are linked. To protect the node, you can say

\draw($(reg.north) + (0, 3)$) node[ellipseNode,protect](ctrl){Control};
\tikzset{protect last node}

Then no path can enter that node. This works by saving the node path and then using an even odd clip of some insanely large box and the node path. This means that everything inside the node path or outside the insanely large box, which you will not reach because this is at the maximum of the allowed TeX dimensions, will be clipped away. To understand these steps in super great detail, please follow the links, the explanations there are great and this answer has not the space to repeat them, nor would it make much sense.

\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}

enter image description here

Of course there are also quick and dirty options such as filling the node in white and drawing on the background layer.

\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}

Or slow and expensive solutions such as computing the intersections with the node boundary.