pete > courses > CS 202 Spring 24 > Lecture 04: testing and style


Lecture 04: testing and style

Goals


first two problems ask you to build circuits with particular behaviors

how will you know you’ve got the correct answer?

in these cases, it’s pretty straightforward: both of the circuits have two input pins and therefore four possible combinations of input values, and you can just use the Poke tool to set the inputs to each of those four in turn and verify that the output is what you want

note that it’s a really good idea to explicitly write down all the possible inputs and the corresponding desired output

it’s really easy to forget or skip something

this is where truth tables come very much in handy


what about larger circuits, though?

even our 2-input multiplexer, with eight different input combinations, may feel like it would be cumbersome to test

fortunately, we’ve already enumerated exactly the behavior we want in a truth table:

 A | B | sel | result
---------------------
 0   0    0      0
 0   0    1      0
 0   1    0      0
 0   1    1      1
 1   0    0      1
 1   0    1      0
 1   1    0      1
 1   1    1      1

it would be really nice if we could give this truth table to Logisim and have it test the circuit for us…


and we can!

and in fact the format of the truth table that Logisim wants is pretty much exactly the same as the truth table I showed above

the only difference is that it doesn’t want any of the dividing lines

it must be a plain text file (so write it using your text editor, not Word)

the first line must be a list of input and output labels, separated by spaces

each line after that is a single test

since the 2-input mux has 8 different inputs, this table has 8 rows (plus the column headers)

here is the exact contents of the file we want:

 A   B   sel   result
 0   0    0      0
 0   0    1      0
 0   1    0      0
 0   1    1      1
 1   0    0      1
 1   0    1      0
 1   1    0      1
 1   1    1      1

to feed it to Logisim, open the circuit file, go to the "Simulate" menu and select "Test Vector…"

in the bottom left, click "Load Vector" and navigate to the text file containing the table above

the tests will automatically run when the file is loaded

if you change the circuit, you have to click "Run" to run the tests again

if there’s a difference between the desired output and the actual output, the incorrect output will be highlighted in red (and the table will show the actual output, not the desired output)


side note: to add the little negation circle to gate inputs, select the gate with the Arrow tool, go to the Properties pane, and twiddle the "Negate N" property to "Yes"

there is not a similar feature to add the little negation circle to the output: for that, you have to select a different gate (NAND, NOR, XNOR)


what about the 4-input mux I showed you at the end of class on Friday?

we can certainly do the same thing

except I’m guessing the idea of writing out the truth table for a 6-input circuit is not terribly exciting and doesn’t seem like a valuable learning exercise

I agree

so I wrote a program to produce a table that enumerates all possible inputs

and all we have to do is add the column headers and the output value(s)

it’s on weathertop:

$ 202 truth-table
Usage: 202 truth-table number-of-inputs
$ 202 truth-table 3
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

now you might be asking yourself: that’s all well and good but how do I get it into a file?

Linux has a handy trick here: while normally programs print to the terminal window, you can ask Linux to instead cause all output to be sent to a file

you do this by following your command with the greater-than sign and the name of the file you want it to fill

beware, though, because the file’s contents will be replaced!

$ 202 truth-table 3 > truth-table.txt

the cat program will output the contents of a file to the terminal, and we can use that to verify it worked:

$ cat truth-table.txt
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

now I can copy the truth-table.txt file off weathertop, add the column headers, add the output column(s), and send it to Logisim to test my circuit


you don’t have to write tests for the first couple problems, but you will have to do so for later ones (such a requirement will be clearly stated)

this is one way you can have confidence in the correctness of your submissions


new topic: style

here’s the inverter circuit from last week: inverter.circ

and here is a functionally identical circuit: inverter_ugly.circ

even without looking at the file names, which one is better?

most people would probably pick the circuit we created last week

but why?

what is it about the second circuit that makes it so clearly inferior?

it’s got wires that needlessly cross

it’s got superfluous wires that lead to nowhere

components that fulfill complementary functionality (eg, the power and ground inputs, the pair of transistors) are laid out completely differently to each other

the input and the output pins are offset

all of these things make it more difficult to understand the behavior of the circuit by looking at it

and therefore require more thinking to achieve that understanding

and thinking is always error-prone

so the clearer we can make our circuits (and, later, our programs), the less thinking is involved in trying to understand them, and the less opportunity for mistakes


another example is the 2-input mux from Friday: mux_2.circ

and an equivalent circuit: mux_2_ugly.circ

this comparison reveals many similar complaints

one thing that I actually think is worth considering retaining about the "ugly" version is the rotated "sel" input: by rotating it, we indicate that it is different from the "A" and "B" inputs, which could be helpful in understanding how the circuit works


and that’s the entire point of good style (in both circuits and traditional coding): to make it easy to understand what the circuit/code does

form should reflect function

regularity is good: discrepancies are easier to spot

if different parts of your circuit behave the same way, they should look the same

logic flow should be apparent

related inputs/outputs should be grouped

inputs and outputs should have descriptive labels

if there is symmetry in the concept or functionality, there should be corresponding symmetry in the circuitry

extraneous stuff (wires, components, labels) should be removed


abstraction is an especially effective way to improve style

because, as you will recall, abstraction means hiding details

hiding the details of intricate circuitry inside a black box makes the larger circuit more understandable

the trick is to pick the correct chunk of logic to stuff inside the black box

it takes experience to judge what works well here, but if you find yourself placing the same collection of components over and over again, consider using Logisim’s abstraction feature: subcircuits


here’s how:

a Logisim file can store multiple, separate circuits

up ’til now, we’ve only used one, and you can see it listed in the top-left pane: it’s labeled "main"

to create a second circuit in the same file, click the green "+" sign just above

you’ll be prompted for a name and here descriptive names are best (though you can’t use spaces or hyphens: I suggest using underscores to separate words)

now you can design to your heart’s content on a new canvas

any logic you place on this canvas will be inside the black box and any input pins and output pins you place will be the inputs and outputs of the black box

if we paste the logic for a 2-input mux on this canvas, then we can place a black box on the "main" canvas that implements the 2-input mux behavior

double-click on the name "main" in the circuit list to switch to that view

now, single-click the 2-input mux circuit in the list to place a 2-input mux in the main circuit


it’s important to remember, though:

DOUBLE-CLICK to edit a different circuit

SINGLE-CLICK to place an instance of a subcircuit


you can also change the appearance of the subcircuit (but beware: this is a bottomless bit of creativity that will consume all your time if you let it)

in the list of subcircuits, right-click the circuit whose appearance you want to tweak and click "Edit Circuit Appearance"

the menu turns into drawing tools, which you can play with

for full details, check Help -> User’s Guide -> Subcircuits -> Customize the appearance

note that when you place a subcircuit with customized appearance, you need to set an attribute to actually show the new image: click the component you’ve placed and change the Appearance attribute to Custom

(after you do so, any further instances of the same component you place should also use the Custom appearance)


here’s the circuit file that has a 4-input mux built from 2-input muxes as subcircuits: mux_4_from_mux_2.circ


note: this functionality of Logisim-Evolution appears (to me) a bit delicate

I strongly recommend that you save often and make backups

Last modified: