Here, we'll have a very quick look at the notion of a circuit. Circuits as another way that complexity theorists have tried to approach the $\mathbf P$ vs. $\mathbf{NP}$ problem. In particular, this stems from the fact that one way to show that the two classes aren't equal is if there exists some problem in $\mathbf{NP}$ that can't be solved with polynomial-sized circuits. We'll see why this is in a bit. Furthermore, it was believed in the early days that proving things about circuits (particularly lower bounds) would be easier than proving things about TMs. This evidently did not work out entirely as planned.
A circuit in the computational complexity sense should be very similar to a circuit that you may have seen before where you'd actually deal with hardware. We can think of it as a directed acyclic graph with $n$ inputs, a final sink vertex, and various gates for the standard logical operations $\vee$, $\wedge$, and $\neg$. The size of a circuit $C$ is the number of vertices in $C$, denoted $|C|$. For an input string $x \in \{0,1\}^n$, the output of $C$ on $x$ is denoted $C(x)$.
One immediate consequence of this definition is that the size of our input is fixed for each circuit. In other words, we have to define a set of circuits if we want to cover all inputs. Let $f:\mathbb N \to \mathbb N$ be a function. A $f(n)$-size circuit family is a sequence $\{C_n\}_{n \in \mathbb N}$ of boolean circuits, where $C_n$ has $n$ inputs and a single output, and its size $|C_n| \leq f(n)$ for every $n$. We say that a language $L$ is in $\mathbf{SIZE}(f(n))$ if there exists a $f(n)$-size circuit family $\{C_n\}_{n \in \mathbb N}$ such that for every $x \in \{0,1\}^n$, $x \in L \iff C_n(x) = 1$.
The parity function $p_n:\{0,1\}^n \to \{0,1\}$ outputs $1$ if an odd number of $1$s appears in the input variables. If we have $n$ variables, we can build a family of circuits with $O(n)$ gates. If $A$ is the language of strings that contains an odd number of $1$s, then $A$ has circuit complexity $O(n)$.
We define $\mathbf P/poly$ to be the class of languages that are computed by polynomial-sized circuits.
Theorem. $\mathbf P \subseteq \mathbf P/poly$.
Proof (sketch). Let $M$ be a TM that decides $A$ in time $n^k$. For each $n$, we construct a circuit $C_n$ that simulates $M$ on inputs of length $n$. The gates of $C_n$ are organized in rows, one for each step of computation of $M$. Each row represents a configuration of $M$ at each step. We wire each row from the previous row so that it can compute the configuration from the previous row's configuration. In total this requires $O(n^{2k})$ gates. $$\tag*{$\Box$}$$
Because of how this theorem was proved, we only have to do a bit more work to get an alternate proof of the Cook-Levin Theorem. As it turns out, we can ask whether, given a circuit $C$ if it is satisfiable in the same sense as a boolean formula. From there, it's not too hard to see how we can transform a circuit $C$ into an equivalent boolean formula $\varphi$.
However, back to the inclusion, it turns out, this inclusion is strict. We note that every unary language is in $\mathbf P/poly$. However, there are undecidable languages that are unary languages. For instance, $$ \{ 1^n \mid \text{the binary expansion of $n$ encodes $\langle M,w \rangle$ such that $M$ halts on input $w$}\}$$ is an undecidable unary language that has linear size circuits.
We can also characterize the class $\mathbf P/poly$ as a special kind of Turing machine. We call these Turing machines with advice.
Let $f,a: \mathbb N \to \mathbb N$ be functions. The class of languages decidable by $f(n)$-time TMs with $a(n)$ bits of advice, $\mathbf{TIME}(f(n))/a(n)$, contains every $L$ such that there exists a sequence $\{\alpha_n\}_{n \in \mathbb N}$ of strings $\alpha_n \in \{0,1\}^{a(n)}$ and a TM $M$ such that $w \in L \iff \text{$M$ accepts $\langle w,\alpha_n \rangle$}$ for every input string $w$ and $M$ runs for at most $O(f(n))$ steps on input $\langle w,\alpha_n \rangle$.
For example, every unary language can be decided by a polynomial time TM with 1 bit of advice. For inputs of length $n$, the advice string is a bit indicating whether or not $1^n$ is in the language. This works even for the unary halting problem mentioned above.
Theorem. $\mathbf P/poly = \bigcup_{k,\ell} \mathbf{TIME}(n^k)/n^\ell$.
Proof. If $L \in \mathbf P/poly$, then it is computably by a polynomial-sized circuit family $C_n$. Then we can use the description of $C_n$ as our advice string for inputs of size $n$ and the TM is a polynomial time machine that on some input string $w$ and the advice string corresponding to $C_n$ accepts if $C(w) = 1$.
If $L$ is decidable on a polynomial time TM $M$ with advice $\alpha_n$ of size $a(n)$, then we can construct a polynomial size circuit $D_n$, as proven in the theorem above. We build $D_n$ so that for every $w \in \{0,1\}^n$ and $\alpha \in \{0,1\}^{a(n)}$, $D_n(w,\alpha) = 1$ if and only if $M$ accepts $\langle w,\alpha \rangle$. Then we build a family $C_n$ that is equivalent to $D_n$ but with $\alpha_n$ hardwired. $$\tag*{$\Box$}$$
The following result stems from the question: Is $\mathrm{SAT}$ in $\mathbf P/poly$? In other words, can we define a family of small (polynomial-sized) circuits that will compute $\mathrm{SAT}$?
Theorem. (Karp-Lipton) If $\mathbf{NP} \subseteq \mathbf P/poly$, then $\mathbf{PH} = \Sigma_2^P$.
This seems to give us a way to separate $\mathbf P$ and $\mathbf{NP}$. Since $\mathbf P \subseteq \mathbf P/poly$, if $\mathbf{NP} \not\subseteq \mathbf P/poly$, then we have $\mathbf P \neq \mathbf{NP}$. Furthermore, the Karp-Lipton theorem gives us a pretty good bet that $\mathbf{NP} \not\subseteq \mathbf P/poly$, so it may be worth heading in this direction. Evidently, this has not happened yet.