A combination of fit (for the box around it) and calc (for the placement of the ports).
One could also think of a new shape like the circuits with their inputs and output anchors.
One can add new functions to place the ports by adding more choices to place ports function or by simply redefining \tikzPlacePorts yourself.
One could also implement the function by means of the /pgf/declare function key (different syntax, works better with PGF math).
Code B shows an implementation via PGFkeys and the usage of do ports directly on the node that shall recieve the ports.
Code A
\documentclass[tikz,convert=false]{standalone}
\usetikzlibrary{positioning, fit, calc}
\providecommand*{\tikzPlacePorts}{}
\tikzset{
place ports/.code args={#1:#2:(#3)}{
\ifcase#1 % east
\def\anchorA{north east}%
\def\anchorB{south east}%
\def\direc{e}%
\or % north
\def\anchorA{north west}%
\def\anchorB{north east}%
\def\direc{n}%
\or % west
\def\anchorA{north west}%
\def\anchorB{south west}%
\def\direc{w}%
\else % south
\def\anchorA{south west}%
\def\anchorB{south east}%
\def\direc{s}%
\fi
\tikzset{
@place ports/.ecode={\noexpand\node[port] at ($(#3.\anchorA)!\noexpand\tikzPlacePorts{##1}{#2}!(#3.\anchorB)$) (#3-\direc-##1) {};},
@place ports/.list={1,...,#2}
}
},
place ports function/.is choice,
place ports function/on corners/.code =\def\tikzPlacePorts##1##2{(##1-1)/(##2-1)},
place ports function/not on corners/.code=\def\tikzPlacePorts##1##2{(##1)/(##2+1)},
place ports function=not on corners
}
\tikzset{
foo/.style={shape=circle,draw, inner sep=+0pt, minimum size=+.8cm},
arr/.style={->, >=latex, shorten >=1pt, semithick},
port/.style={shape=rectangle, draw, fill, inner sep=+0pt, minimum size=+1mm}}
\begin{document}
\begin{tikzpicture}
\node[foo] (a) {};
\node[foo, right=of a] (b) {};
\node[draw, fit=(a)(b), inner xsep=.5cm, inner ysep=.8cm, outer sep=+0pt] (ab) {};
\tikzset{place ports=2:2:(ab)}
\tikzset{place ports=0:1:(ab)}
\path[arr] (ab-w-1) edge (a.west)
(ab-w-2) edge (a.west)
(a) edge (b)
(b) edge (ab-e-1);
\end{tikzpicture}
\begin{tikzpicture}
\node[foo, label=$a$] (a) {};
\node[draw, fit=(a), inner sep=.8cm, outer sep=+0pt] (a') {};
\tikzset{place ports function=on corners, place ports=2:2:(a')}
\tikzset{place ports function=not on corners, place ports=0:1:(a')}
\path[arr] (a'-w-1) edge (a)
(a'-w-2) edge (a)
(a) edge node[above] {$\alpha$} (a'-e-1);
\end{tikzpicture}
\end{document}
Code B
\documentclass[tikz,convert=false]{standalone}
\makeatletter
\pgfkeys{/handlers/.pgfmath/.code=\pgfmathparse{#1}\expandafter\pgfkeys@exp@call\expandafter{\pgfmathresult}}
\makeatother
\usetikzlibrary{positioning, fit}
\tikzset{
ports/.code={\pgfqkeys{/tikz/ports}{#1}},
do ports/.code={\pgfqkeys{/tikz/ports}{#1, do}},
ports/.cd,
rect east/.code={%
\def\tikzPlacePortsName{east}%
\def\tikzPlacePortsStart##1{##1.north east}%
\def\tikzPlacePortsTarget##1{##1.south east}},
rect west/.code={%
\def\tikzPlacePortsName{west}%
\def\tikzPlacePortsStart##1{##1.north west}%
\def\tikzPlacePortsTarget##1{##1.south west}},
function/.is choice,
function/not on corners/.code={%
\def\tikzPlacePorts##1##2{pos/.pgfmath={(##1)/(##2+1)}}},
function/on corners/.code={%
\def\tikzPlacePorts##1##2{pos/.pgfmath={(##1-1)/(##2-1)}}},
function=not on corners,
total/.initial=1,
do/.style={
place ports/.estyle={%
/tikz/append after command={{%
(\tikzPlacePortsStart{\noexpand\tikzlastnode})
edge[draw=none] node[ports/port/.try, \tikzPlacePorts{##1}{#1}] (\noexpand\tikzlastnode-\tikzPlacePortsName-##1) {}
(\tikzPlacePortsTarget{\noexpand\tikzlastnode})}}},
place ports/.list={1,...,#1}
},
do/.default={\pgfkeysvalueof{/tikz/ports/total}}
}
\tikzset{
foo/.style={shape=circle,draw, inner sep=+0pt, minimum size=+.8cm},
arr/.style={->, >=latex, shorten >=1pt, semithick},
ports/port/.style={shape=rectangle, draw, fill, inner sep=+0pt, minimum size=+1mm}}
\begin{document}
\begin{tikzpicture}
\node[foo] (a) {};
\node[foo, right=of a] (b) {};
\node[draw, fit=(a)(b), inner xsep=.5cm, inner ysep=.8cm, outer sep=+0pt,
do ports={rect west, total=2}, do ports={rect east, total=1}
] (ab) {};
\path[arr] (ab-west-1) edge (a.west)
(ab-west-2) edge (a.west)
(a) edge (b)
(b) edge (ab-east-1);
\end{tikzpicture}
\begin{tikzpicture}
\node[foo, label=$a$] (a) {};
\node[draw, fit=(a), inner sep=.8cm, outer sep=+0pt,
do ports={rect east, total=1}, do ports={rect west, function=on corners, total=2}
] (a') {};
\path[arr] (a'-west-1) edge (a)
(a'-west-2) edge (a)
(a) edge node[above] {$\alpha$} (a'-east-1);
\end{tikzpicture}
\end{document}
Output


\node[foo] (a) [label={[overlay]above:$a$}] {};so that the label does not affect the bounding box. – Qrrbrbirlbel Aug 23 '13 at 01:32