badcrossbar : A Python tool for computing and plotting currents and voltages in passive crossbar arrays

Crossbar arrays are a popular solution when implementing systems that have array-like architecture. With the recent developments in the field of neuromorphic engineering


Introduction
In the most general definition, crossbar arrays are structures with m inputs and n outputs producing a 2D grid of m × n intersections. The inputs are applied to the conductive lines which are referred to as word lines. The outputs are obtained from the conductive lines which are referred to as the bit lines. Devices are placed at the intersections of the word and bit lines, as shown in Fig. 1A.
Even in their early implementations, crossbar array applications ranged from simple control of the flow of signals [1] * Corresponding author. to performing mathematical operations [2]. The matrix-like arrangement of crossbar arrays' devices makes them natural candidates for some linear algebra operations. Specifically, crossbar arrays are capable of computing vector-matrix products. This can be achieved by employing analogue two-terminal devices with variable conductance, such as memristors [3]. Fig. 1B shows circuit diagram of a crossbar array (with crossbar devices depicted as memristors). Word and bit line segments bounded by neighbouring nodes (depicted as black dots), like crossbar devices, can have resistance. However, if the resistance of these segments (which we will refer to as interconnects) is negligible, then the output currents (depicted as I 1 , I 2 , . . . in  With the development of memristive devices [3,4], practical implementations of DPEs became more realisable. Because memristive devices are capable of gradual conductance change [5], memristive crossbar arrays can be used to encode matrix entries. Although conductances can only be positive, it is possible to encode negative numbers by using pairs of memristors [6,7]. Because of the flexibility, DPEs are now often used for in-memory computing, most notably-in the implementation of memristive neural networks [8]. However, such systems are still often limited by the non-ideal nature of crossbar arrays-non-negligible resistance of interconnects can significantly affect the performance. Computing currents and voltages in crossbar arrays is essential to understanding their behaviour under non-ideal conditions. So naturally, there have been careful analyses of line resistance effects in passive crossbar arrays in the past [9]. However, to the best of our knowledge, there are no open-source context-independent tools available to analyse line resistance effects in crossbar arrays. For example, being able to compute output currents of a crossbar array when multiple sets of inputs are applied would be useful in simulations of memristive neural networks [10]. Computing node voltages or currents in other branches than the output ones would be useful in the analysis of line resistance or sneak-path currents. Serb et al. have examined the issue of accurate readout of the resistive state of devices within selectorless crossbar arrays and concluded that the line resistance is significant even for smaller crossbars (12 × 12) [11].
Advanced mapping or compensation schemes have been proposed to mitigate the issue [12]. Additionally, our simulation tool could supplement the analysis of various effects, such as defects of crossbar devices (and their mitigation), that have been well studied in the past [13][14][15].
Furthermore, visualising the distribution of currents and voltages in a crossbar array can provide additional insight. Although the devices in crossbar arrays are arranged in a matrix-like fashion, they do not paint the complete picture. In addition to the devices, there are word-and bit-line branches, that all together form 3 × m × n unique branches (see Fig. 1B) through which the currents flow. Also, there are 2 × m × n unique nodes, each of which can be associated with a voltage value. Visualising currents and voltages (or any other numerical variables) in the branches and on the nodes of the crossbar array can help understand the nature of these structures.

Problems and background
To set up equations to solve for the currents and voltages in circuits containing only passive elements requires just Kirchhoff's current law (KCL) and Ohm's law. In the specific case of crossbar arrays, the relevant equations can be set up easily for arbitrary number of word lines, m, and arbitrary number of bit lines, n, due to simple architecture of these arrays. Most circuit simulators use nodal analysis (or its variants) to analyse circuits and it has been applied to crossbar arrays in the past [9]. However, we will briefly explain this method.
If interconnect resistances are non-zero, then there are 2 × m × n unknown node voltages one has to solve for, as shown in Fig. 2A. One can solve for these voltages by applying KCL to currents (shown in Fig. 2B) flowing into/out of a particular node.
For the case of m, n > 1, we can set up KCL equations for a word line node and a bit line node at the intersection of i th word line and j th bit line using Eqs. (1)a, b and (1)c, d, respectively.
Using Ohm's law, we can express currents using node voltages, applied voltages, conductances of the interconnects along the word lines, G WL , conductances of the interconnects along the bit lines, G BL , and conductances of the devices, G (i,j) . By doing that and rearranging, we get Eq. (2)a-f.
where G is a coefficient matrix containing conductances, V is a vector (or a matrix, if more than one set of voltages is applied) of node voltages, and I is a vector (or a matrix) of constants which, in this context, is known currents.
One can solve for node voltages V using conventional linear algebra methods. Branch currents can then be computed by applying Ohm's law. In a special case where either one type of the interconnects, or both, have zero resistance, the number of unique nodes is reduced. In that case, one has to apply KCL to compute unknown currents through the perfectly conductive interconnects because it is not possible to apply Ohm's law across elements with zero resistance.

Software framework
The badcrossbar package is implemented in Python 3. This programming language was chosen due to its popularity, intuitive syntax and availability of open-source packages. Specifically, it features packages such as numpy or scipy that enable efficient manipulation of vectors and matrices necessary for computing currents and voltages in crossbar arrays. It is true that Python is an interpreted language which might result in slower computation when compared to compiled languages. However, numpy and scipy are written mostly in C [16], so there may be only a small decrease in performance due to pure Python code-these two libraries handle the heaviest computations in badcrossbar. Finally, it is important to note that Python is widely used nowadays, especially among machine learning researchers. numpy arrays employed by badcrossbar are easy to convert to data structures used by the most popular machine learning frameworks, such as TensorFlow or PyTorch that are often utilised when simulating crossbar-based neural networks.

badcrossbar.compute().
The output of badcrossbar.compute() is a named tuple with fields voltages and currents. Both of the fields are named tuples themselves. voltages has fields word_line and bit_line that contain node voltages on the word and bit lines, respectively (visualised in Fig. 2A). currents has fields device, word_line and bit_line that contain currents flowing through devices, word line interconnects and bit line interconnects, respectively (visualised in Fig. 2B). It additionally has a field output which contains the output currents as a 2D array. It represents essentially the same information as the currents in the last row of currents.bit_line, just in a more convenient format.
Assuming a crossbar with m word lines, n bit lines and p sets of applied voltages, all the computed voltages and currents, except for the output currents, will be arrays of shape m × n if p = 1 and arrays of shape m × n × p if p > 1. Output currents, on the other hand, will always be arrays of shape p × n.

Plotting
Functions badcrossbar.plot.branches() and badcrossbar.plot.nodes() accept either individual arrays associated with different types of branches or nodes, or named tuples (usually produced by the function badcrossbar.compute()) containing currents and voltages. Although the most likely variables to be plotted using these functions are currents and voltages, the arrays that are being passed can be associated with any type of numeric variables. Importantly, a large number of optional keyword arguments allows to modify the produced diagrams. Widths of the wires, devices or nodes, the colour scheme of the colour bar, and other elements of the diagram can be changed. Because the functions produce vector diagrams (in PDF), they can be easily modified in any vector graphics manipulation program. Thus, the optional keyword arguments that are provided mostly allow to modify parameters that would be difficult to change once the diagram is produced. A complete description of the arguments can be found in the docstrings of badcrossbar.plot.branches() and badcrossbar.plot.nodes().

Computing
When computing currents and voltages in a crossbar array, there are three major steps in the process. Firstly, it is necessary to fill the matrices G and I (referred to as arrays g and i in code to comply with Python naming conventions), as seen in Eq. (3). This is done by firstly initialising the empty arrays (g also using sparse representation) and then efficiently populating them using Eq. (2)a-f. Once that is done, the two arrays are passed to function linalg.spsolve() of scipy.sparse sub-package, which solves for matrix V (v in code). Finally, the array v is reshaped into a convenient form and the currents are then computed by applying Ohm's law in every branch. The second step is usually the most time-consuming part of the computing process. Fig. 3 shows the median time needed to compute currents and voltages in square crosssbars of shape n × n. We see that above certain time threshold, the curves become linear; given log-log scale of the graph, this suggests that with large enough inputs median time, t, increases as a power of n. That is in agreement with the theory on solving systems of linear equations [17]. We also find that there is usually an optimal number of voltage sets that should be supplied at a time. For example, in the case of Fig. 3, supplying a 1,000 sets of applied voltages at once would result in faster computation than supplying them in 10 separate batches (each of size 100). However, supplying 10,000 sets at once would result in slower computation than supplying them in 10 separate batches (each of size 1,000). These trade-offs are most likely related to memory management and optimal configurations might thus vary from machine to machine. Because of this, we did not optimise this particular aspect of our software and left the choice to individual users.

Plotting
The plotting functions are implemented using cairo graphics library. All the elements (branches, nodes, colour bar and the labels) are drawn one after another with the setup being described using optional parameters as mentioned in sub-Section 3.2.2. Although cairo is available on all major operating systems (Linux, MacOS, Windows), it might be more difficult to install on Windows. Because of that, the badcrossbar package is built so that the computing sub-package could be used independently from the plotting sub-package, i.e. without installing it.

Illustrative example
Suppose we wanted to compute branch currents in a crossbar array over multiple sets of inputs and then plot their average values over all those sets of applied inputs. The following piece of code computes branch currents and node voltages in a 3 × 5 crossbar array over four sets of applied voltages. It then plots average branch currents over those four sets of inputs. When executed, this code produces a PDF file named ''Example.pdf''; its contents are shown in Fig. 4   of these structures and where large numbers of inputs have to be tested [10]. Additionally, the plotting functionality may help visualise physical variables and discover trends, such as where in crossbar arrays current decreases tend to be the most severe. We believe that this package will be useful in both the simulations and the design of crossbar arrays.

Conclusions
We present a Python package for computing currents and voltages in crossbar arrays, as well as plotting them (or any other numerical variables) on these structures. The use of numpy enables easy integration with a wide range of packages, while the use of vector graphics in produced diagrams allows to modify them using external programs. In the future, we plan to give users more control over how voltages are applied across crossbar arrays and to allow to specify the resistances of individual interconnects. Furthermore, we plan to add more options for specifying plotting behaviour, as well as to allow to export to other formats, e.g. TikZ.

Declaration of competing interest
The authors declare that they have no known competing financial interests or personal relationships that could have appeared to influence the work reported in this paper.