Home

Abstraction


Computer
CPU.hdl
// Parses the binary code in the instruction input and executes it according to the
// Hack machine language specification. 

CHIP CPU {

    IN  inM[16],         // M value input  (M = contents of RAM[A])
        instruction[16], // Instruction for execution
        reset;           // Signals whether to re-start the current
                         // program (reset==1) or continue executing
                         // the current program (reset==0).

    OUT outM[16],        // M value output
        writeM,          // Write to M? 
        addressM[15],    // Address in data memory (of M)
        pc[15];          // address of next instruction 

    PARTS:
    //The first thing to figure out is whether the instruction is an A instruction or a C instruction.
    //A instruction: instruction[15] == 0
    //C instruction: instruction[15] == 1
    Not(in= instruction[15], out= isAInstruction);
    And(a= instruction[15], b= true, out= isCInstruction);

    //The A register has two possible inputs.
    //If we are dealing with an A instruction, the instruction itself becomes the new value.
    //If we are dealing with a C instruction, the ALU output can become the new value.
    Mux16(a= aluOut, b= instruction, sel= isAInstruction, out= aRegisterInput);

    //The A register should load if this is an A instruction.
    //It should also load if this is a C instruction and the A destination bit is turned on.
    And(a= isCInstruction, b= instruction[5], out= cInstructionLoadsA);
    Or(a= isAInstruction, b= cInstructionLoadsA, out= loadARegister);
    ARegister(in= aRegisterInput, load= loadARegister, out= aRegisterOut, out[0..14]= addressM);

    //The D register should only load if this is a C instruction and the D destination bit is turned on.
    And(a= isCInstruction, b= instruction[4], out= loadDRegister);
    DRegister(in= aluOut, load= loadDRegister, out= dRegisterOut);

    //The ALU's second input is either A or M.
    //The a-bit in the instruction chooses which one.
    Mux16(a= aRegisterOut, b= inM, sel= instruction[12], out= aOrM);

    //The ALU does the actual C instruction computation.
    ALU(x= dRegisterOut, y= aOrM,
        zx= instruction[11],
        nx= instruction[10],
        zy= instruction[9],
        ny= instruction[8],
        f= instruction[7],
        no= instruction[6],
        out= aluOut,
        out= outM,
        zr= zr,
        ng= ng);

    //The M destination bit controls whether we write the ALU output to memory.
    And(a= isCInstruction, b= instruction[3], out= writeM);

    //For jump logic we need to know whether the ALU output is positive, zero, or negative.
    Not(in= zr, out= notZero);
    Not(in= ng, out= notNegative);
    And(a= notZero, b= notNegative, out= positive);

    //The jump bits are JLT, JEQ, JGT.
    //instruction[2] says jump if negative.
    //instruction[1] says jump if zero.
    //instruction[0] says jump if positive.
    And(a= instruction[2], b= ng, out= jumpIfNegative);
    And(a= instruction[1], b= zr, out= jumpIfZero);
    And(a= instruction[0], b= positive, out= jumpIfPositive);

    Or(a= jumpIfNegative, b= jumpIfZero, out= jumpOne);
    Or(a= jumpOne, b= jumpIfPositive, out= jumpTwo);
    And(a= isCInstruction, b= jumpTwo, out= loadPC);

    //If loadPC is true, PC becomes A.
    //Otherwise it increments.
    //If reset is true, PC handles that internally and becomes 0.
    PC(in= aRegisterOut, load= loadPC, inc= true, reset= reset, out[0..14]= pc);
}
Memory and I/O
Memory.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/5/Memory.hdl
/**
 * The complete address space of the Hack computer's memory,
 * including RAM and memory-mapped I/O. 
 * The chip facilitates read and write operations, as follows:
 *     Read:  out(t) = Memory[address(t)](t)
 *     Write: if load(t-1) then Memory[address(t-1)](t) = in(t-1)
 * In words: the chip always outputs the value stored at the memory 
 * location specified by address. If load=1, the in value is loaded 
 * into the memory location specified by address. This value becomes 
 * available through the out output from the next time step onward.
 * Address space rules:
 * Only the upper 16K+8K+1 words of the Memory chip are used. 
 * Access to address>0x6000 is invalid and reads 0. Access to any address
 * in the range 0x4000-0x5FFF results in accessing the screen memory 
 * map. Access to address 0x6000 results in accessing the keyboard 
 * memory map. The behavior in these addresses is described in the Screen
 * and Keyboard chip specifications given in the lectures and the book.
 */
CHIP Memory {
    IN in[16], load, address[15];
    OUT out[16];

    PARTS:
    DMux4Way(in= load, sel= address[13..14], a= ramLoadOne, b= ramLoadTwo, c= screenLoad, d= keyboardLoad);
    Or(a= ramLoadOne, b= ramLoadTwo, out= ramLoad);

    //24577-32,768 = 110000000000001
    //24576 = 110000000000000
    Keyboard(out= keyboardOut);
    //16384-24575 = 100000000000000-101111111111111
    Screen(in= in, load= screenLoad, address=address[0..12], out= screenOut);
    //0-16383 = 000000000000000-011111111111111
    RAM16K(in= in, load= ramLoad, address=address[0..13], out= ramOut);
    //00:a, 01:b, 10:c, 11:d
    Mux4Way16(a= ramOut, b= ramOut, c= screenOut, d= keyboardOut, sel= address[13..14], out= out);
    
}
RAM16K.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/b/RAM16K.hdl
/**
 * Memory of 16K 16-bit registers.
 * If load is asserted, the value of the register selected by
 * address is set to in; Otherwise, the value does not change.
 * The value of the selected register is emitted by out.
 */
CHIP RAM16K {
    IN in[16], load, address[14];
    OUT out[16];

    PARTS:
    //Take the load bit and assign it to the correct output via address
    DMux(in= load, sel=address[1] , a= o1, b= o2);
    DMux(in= o1, sel= address[0], a= oo1, b= oo2);
    DMux(in= o2, sel= address[0], a= oo3, b= oo4);
    //Create the RAM. The correct RAM will recieve the load bit. 
    RAM4K(in= in, load= oo1, address= address[2..13], out= ob1);
    RAM4K(in= in, load= oo2, address= address[2..13], out= ob2);
    RAM4K(in= in, load= oo3, address= address[2..13], out= ob3);
    RAM4K(in= in, load= oo4, address= address[2..13], out= ob4);
    //The output register will be based on the address.
    Mux4Way16(a= ob1, b= ob2, c= ob3, d= ob4, sel= address[0..1], out= out);
}
RAM4K.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/b/RAM4K.hdl
/**
 * Memory of 4K 16-bit registers.
 * If load is asserted, the value of the register selected by
 * address is set to in; Otherwise, the value does not change.
 * The value of the selected register is emitted by out.
 */
CHIP RAM4K {
    IN in[16], load, address[12];
    OUT out[16];

    PARTS:
    //Take the load bit and assign it to the correct output via address
    DMux(in= load, sel=address[2] , a= o1, b= o2);
    DMux(in= o1, sel= address[1], a= o3, b= o4);
    DMux(in= o2, sel= address[1], a= o5, b= o6);
    DMux(in= o3, sel= address[0], a= oo1, b= oo2);
    DMux(in= o4, sel= address[0], a= oo3, b= oo4);
    DMux(in= o5, sel= address[0], a= oo5, b= oo6);
    DMux(in= o6, sel= address[0], a= oo7, b= oo8);
    //Create the RAM. The correct RAM will recieve the load bit. 
    RAM512(in= in, load= oo1, address= address[3..11], out= ob1);
    RAM512(in= in, load= oo2, address= address[3..11], out= ob2);
    RAM512(in= in, load= oo3, address= address[3..11], out= ob3);
    RAM512(in= in, load= oo4, address= address[3..11], out= ob4);
    RAM512(in= in, load= oo5, address= address[3..11], out= ob5);
    RAM512(in= in, load= oo6, address= address[3..11], out= ob6);
    RAM512(in= in, load= oo7, address= address[3..11], out= ob7);
    RAM512(in= in, load= oo8, address= address[3..11], out= ob8);
    //The output register will be based on the address.
    Mux8Way16(a= ob1, b= ob2, c= ob3, d= ob4, e= ob5, f= ob6, g= ob7, h= ob8, sel= address[0..2], out= out);
}
RAM512.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/b/RAM512.hdl
/**
 * Memory of 512 16-bit registers.
 * If load is asserted, the value of the register selected by
 * address is set to in; Otherwise, the value does not change.
 * The value of the selected register is emitted by out.
 */
CHIP RAM512 {
    IN in[16], load, address[9];
    OUT out[16];

    PARTS:
    //Take the load bit and assign it to the correct output via address
    DMux(in= load, sel=address[2] , a= o1, b= o2);
    DMux(in= o1, sel= address[1], a= o3, b= o4);
    DMux(in= o2, sel= address[1], a= o5, b= o6);
    DMux(in= o3, sel= address[0], a= oo1, b= oo2);
    DMux(in= o4, sel= address[0], a= oo3, b= oo4);
    DMux(in= o5, sel= address[0], a= oo5, b= oo6);
    DMux(in= o6, sel= address[0], a= oo7, b= oo8);
    //Create the RAM. The correct RAM will recieve the load bit. 
    RAM64(in= in, load= oo1, address= address[3..8], out= ob1);
    RAM64(in= in, load= oo2, address= address[3..8], out= ob2);
    RAM64(in= in, load= oo3, address= address[3..8], out= ob3);
    RAM64(in= in, load= oo4, address= address[3..8], out= ob4);
    RAM64(in= in, load= oo5, address= address[3..8], out= ob5);
    RAM64(in= in, load= oo6, address= address[3..8], out= ob6);
    RAM64(in= in, load= oo7, address= address[3..8], out= ob7);
    RAM64(in= in, load= oo8, address= address[3..8], out= ob8);
    //The output register will be based on the address.
    Mux8Way16(a= ob1, b= ob2, c= ob3, d= ob4, e= ob5, f= ob6, g= ob7, h= ob8, sel= address[0..2], out= out);
}
RAM64.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/a/RAM64.hdl
/**
 * Memory of sixty four 16-bit registers.
 * If load is asserted, the value of the register selected by
 * address is set to in; Otherwise, the value does not change.
 * The value of the selected register is emitted by out.
 */
CHIP RAM64 {
    IN in[16], load, address[6];
    OUT out[16];

    PARTS:
    //Take the load bit and assign it to the correct output via address
    DMux(in= load, sel=address[2] , a= o1, b= o2);
    DMux(in= o1, sel= address[1], a= o3, b= o4);
    DMux(in= o2, sel= address[1], a= o5, b= o6);
    DMux(in= o3, sel= address[0], a= oo1, b= oo2);
    DMux(in= o4, sel= address[0], a= oo3, b= oo4);
    DMux(in= o5, sel= address[0], a= oo5, b= oo6);
    DMux(in= o6, sel= address[0], a= oo7, b= oo8);
    //Create the RAM. The correct RAM will recieve the load bit. 
    RAM8(in= in, load= oo1, address= address[3..5], out= ob1);
    RAM8(in= in, load= oo2, address= address[3..5], out= ob2);
    RAM8(in= in, load= oo3, address= address[3..5], out= ob3);
    RAM8(in= in, load= oo4, address= address[3..5], out= ob4);
    RAM8(in= in, load= oo5, address= address[3..5], out= ob5);
    RAM8(in= in, load= oo6, address= address[3..5], out= ob6);
    RAM8(in= in, load= oo7, address= address[3..5], out= ob7);
    RAM8(in= in, load= oo8, address= address[3..5], out= ob8);
    //The output register will be based on the address.
    Mux8Way16(a= ob1, b= ob2, c= ob3, d= ob4, e= ob5, f= ob6, g= ob7, h= ob8, sel= address[0..2], out= out);
}
RAM8.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/a/RAM8.hdl
/**
 * Memory of eight 16-bit registers.
 * If load is asserted, the value of the register selected by
 * address is set to in; Otherwise, the value does not change.
 * The value of the selected register is emitted by out.
 */
CHIP RAM8 {
    IN in[16], load, address[3];
    OUT out[16];

    PARTS:
    //Take the load bit and assign it to the correct output via address
    DMux(in= load, sel=address[2] , a= o1, b= o2);
    DMux(in= o1, sel= address[1], a= o3, b= o4);
    DMux(in= o2, sel= address[1], a= o5, b= o6);
    DMux(in= o3, sel= address[0], a= oo1, b= oo2);
    DMux(in= o4, sel= address[0], a= oo3, b= oo4);
    DMux(in= o5, sel= address[0], a= oo5, b= oo6);
    DMux(in= o6, sel= address[0], a= oo7, b= oo8);
    //Create the registers. The correct register will recieve the load bit. 
    Register(in= in, load= oo1, out= ob1);
    Register(in= in, load= oo2, out= ob2);
    Register(in= in, load= oo3, out= ob3);
    Register(in= in, load= oo4, out= ob4);
    Register(in= in, load= oo5, out= ob5);
    Register(in= in, load= oo6, out= ob6);
    Register(in= in, load= oo7, out= ob7);
    Register(in= in, load= oo8, out= ob8);
    //The output register will be based on the address.
    Mux8Way16(a= ob1, b= ob2, c= ob3, d= ob4, e= ob5, f= ob6, g= ob7, h= ob8, sel= address, out= out);

}
Register.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/a/Register.hdl
/**
 * 16-bit register:
 * If load is asserted, the register's value is set to in;
 * Otherwise, the register maintains its current value:
 * if (load(t)) out(t+1) = int(t), else out(t+1) = out(t)
 */
CHIP Register {
    IN in[16], load;
    OUT out[16];

    PARTS:
    /*
    Similar to the bit chip, the description doesn't specify the case in which garbage is returned. 
    */
    Bit(in= in[0], load= load, out= out[0]);
    Bit(in= in[1], load= load, out= out[1]);
    Bit(in= in[2], load= load, out= out[2]);
    Bit(in= in[3], load= load, out= out[3]);
    Bit(in= in[4], load= load, out= out[4]);
    Bit(in= in[5], load= load, out= out[5]);
    Bit(in= in[6], load= load, out= out[6]);
    Bit(in= in[7], load= load, out= out[7]);
    Bit(in= in[8], load= load, out= out[8]);
    Bit(in= in[9], load= load, out= out[9]);
    Bit(in= in[10], load= load, out= out[10]);
    Bit(in= in[11], load= load, out= out[11]);
    Bit(in= in[12], load= load, out= out[12]);
    Bit(in= in[13], load= load, out= out[13]);
    Bit(in= in[14], load= load, out= out[14]);
    Bit(in= in[15], load= load, out= out[15]);
}
Bit.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/a/Bit.hdl
/**
 * 1-bit register:
 * If load is asserted, the register's value is set to in;
 * Otherwise, the register maintains its current value:
 * if (load(t)) out(t+1) = in(t), else out(t+1) = out(t)
 */
CHIP Bit {
    IN in, load;
    OUT out;

    PARTS:
    //Very simple. 
    //if load:
    //  return input
    //if not load:
    //  if DFF contains prior value:
    //    return prior value
    //  else:
    //    return garbage
    //The value is either the prior value (captured via DFF) 
    Mux(a= o1, b= in, sel= load, out= o2);
    DFF(in= o2, out= out, out= o1);
}
Program Counter
PC.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/3/a/PC.hdl
/**
 * A 16-bit counter.
 * if      reset(t): out(t+1) = 0
 * else if load(t):  out(t+1) = in(t)
 * else if inc(t):   out(t+1) = out(t) + 1
 * else              out(t+1) = out(t)
 */
CHIP PC {
    IN in[16], reset, load, inc;
    OUT out[16];
    
    PARTS:

    //If inc out = out + 1
    Inc16(in= registerOut, out= o1);
    Mux16(a= registerOut, b= o1, sel= inc, out= o2);

    //If load out = in
    Mux16(a= o2, b= in, sel= load, out= o3);

    //If reset out = 0
    Mux16(a= o3, b= false, sel= reset, out= newValue);

    Or(a= load, b= inc, out= loadOrInc);
    Or(a= loadOrInc, b= reset, out= loadOrIncOrReset);
    Register(in= newValue, load= loadOrIncOrReset, out= registerOut, out=out);


}
ALU
ALU.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/2/ALU.hdl
/**
 * ALU (Arithmetic Logic Unit):
 * Computes out = one of the following functions:
 *                0, 1, -1,
 *                x, y, !x, !y, -x, -y,
 *                x + 1, y + 1, x - 1, y - 1,
 *                x + y, x - y, y - x,
 *                x & y, x | y
 * on the 16-bit inputs x, y,
 * according to the input bits zx, nx, zy, ny, f, no.
 * In addition, computes the two output bits:
 * if (out == 0) zr = 1, else zr = 0
 * if (out < 0)  ng = 1, else ng = 0
 */
// Implementation: Manipulates the x and y inputs
// and operates on the resulting values, as follows:
// if (zx == 1) sets x = 0        // 16-bit constant
// if (nx == 1) sets x = !x       // bitwise not
// if (zy == 1) sets y = 0        // 16-bit constant
// if (ny == 1) sets y = !y       // bitwise not
// if (f == 1)  sets out = x + y  // integer 2's complement addition
// if (f == 0)  sets out = x & y  // bitwise and
// if (no == 1) sets out = !out   // bitwise not

CHIP ALU {
    IN  
        x[16], y[16],  // 16-bit inputs        
        zx, // zero the x input?
        nx, // negate the x input?
        zy, // zero the y input?
        ny, // negate the y input?
        f,  // compute (out = x + y) or (out = x & y)?
        no; // negate the out output?
    OUT 
        out[16], // 16-bit output
        zr,      // if (out == 0) equals 1, else 0
        ng;      // if (out < 0)  equals 1, else 0

    PARTS:
    //zx
    Mux16(a= x, b= false, sel= zx, out= outZX);
    //nx
    Not16(in= outZX, out= notX);
    Mux16(a= outZX, b= notX, sel= nx, out= outNX);
    //zy
    Mux16(a= y, b= false, sel= zy, out= outZY);
    //ny
    Not16(in= outZY, out= notY);
    Mux16(a= outZY, b= notY, sel= ny, out= outNY);
    //f
    Add16(a= outNX, b= outNY, out= outF1);
    And16(a= outNX, b= outNY, out= outF2);
    Mux16(a= outF2, b= outF1, sel= f, out= outF);

    //no
    Not16(in= outF, out= outNO1);
    Mux16(a= outF, b= outNO1, sel= no, out= out, out[15]= mostSignificantBit,
    out[0]=o0,
    out[1]=o1,
    out[2]=o2,
    out[3]=o3,
    out[4]=o4,
    out[5]=o5,
    out[6]=o6,
    out[7]=o7,
    out[8]=o8,
    out[9]=o9,
    out[10]=o10,
    out[11]=o11,
    out[12]=o12,
    out[13]=o13,
    out[14]=o14,
    out[15]=o15
    );

    //zr
    //what logic gate can we use to check if both are zero
    //Not 16
    //If 1, then 0, if 0 then 1. 
    Or(a= o0, b= false, out= or0);
    Or(a= o1, b= or0, out= or1);
    Or(a= o2, b= or1, out= or2);
    Or(a= o3, b= or2, out= or3);
    Or(a= o4, b= or3, out= or4);
    Or(a= o5, b= or4, out= or5);
    Or(a= o6, b= or5, out= or6);
    Or(a= o7, b= or6, out= or7);
    Or(a= o8, b= or7, out= or8);
    Or(a= o9, b= or8, out= or9);
    Or(a= o10, b= or9, out= or10);
    Or(a= o11, b= or10, out= or11);
    Or(a= o12, b= or11, out= or12);
    Or(a= o13, b= or12, out= or13);
    Or(a= o14, b= or13, out= or14);
    Or(a= o15, b= or14, out= or15);
    Mux(a= true, b= false, sel= or15, out= zr);


    //ng
    Mux(a= false, b= true, sel= mostSignificantBit, out= ng);


}
Arithmetic
Inc16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/2/Inc16.hdl
/**
 * 16-bit incrementer:
 * out = in + 1
 */
CHIP Inc16 {
    IN in[16];
    OUT out[16];

    PARTS:
    Add16(a= in[0..15], b[0]= true, b[1..15]=false, out=out );
    //// Replace this comment with your code.
}
Add16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/2/Add16.hdl
/**
 * 16-bit adder: Adds two 16-bit two's complement values.
 * The most significant carry bit is ignored.
 */
CHIP Add16 {
    IN a[16], b[16];
    OUT out[16];
    PARTS:
    HalfAdder(a= a[0], b= b[0], sum= out[0], carry= c0);
    FullAdder(a= a[1], b= b[1], c= c0, sum= out[1], carry= c1);
    FullAdder(a= a[2], b= b[2], c= c1, sum= out[2], carry= c2);
    FullAdder(a= a[3], b= b[3], c= c2, sum= out[3], carry= c3);
    FullAdder(a= a[4], b= b[4], c= c3, sum= out[4], carry= c4);
    FullAdder(a= a[5], b= b[5], c= c4, sum= out[5], carry= c5);
    FullAdder(a= a[6], b= b[6], c= c5, sum= out[6], carry= c6);
    FullAdder(a= a[7], b= b[7], c= c6, sum= out[7], carry= c7);
    FullAdder(a= a[8], b= b[8], c= c7, sum= out[8], carry= c8);
    FullAdder(a= a[9], b= b[9], c= c8, sum= out[9], carry= c9);
    FullAdder(a= a[10], b= b[10], c= c9, sum= out[10], carry= c10);
    FullAdder(a= a[11], b= b[11], c= c10, sum= out[11], carry= c11);
    FullAdder(a= a[12], b= b[12], c= c11, sum= out[12], carry= c12);
    FullAdder(a= a[13], b= b[13], c= c12, sum= out[13], carry= c13);
    FullAdder(a= a[14], b= b[14], c= c13, sum= out[14], carry= c14);
    FullAdder(a= a[15], b= b[15], c= c14, sum= out[15], carry= c15);
}
FullAdder.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/2/FullAdder.hdl
/**
 * Computes the sum of three bits.
 */
CHIP FullAdder {
    IN a, b, c;  // 1-bit inputs
    OUT sum,     // Right bit of a + b + c
        carry;   // Left bit of a + b + c

    PARTS:

    /*
    | a | b |sum|car|
    | 0 | 0 | 0 | 0 |
    | 0 | 1 | 1 | 0 |
    | 1 | 0 | 1 | 0 |
    | 1 | 1 | 0 | 1 |

    | a | b | c |sum|carry|
    | 0 | 0 | 0 | 0 |  0  |
    | 0 | 0 | 1 | 1 |  0  |
    | 0 | 1 | 0 | 1 |  0  |
    | 0 | 1 | 1 | 0 |  1  |
    | 1 | 0 | 0 | 1 |  0  |
    | 1 | 0 | 1 | 0 |  1  |
    | 1 | 1 | 0 | 0 |  1  |
    | 1 | 1 | 1 | 1 |  1  |
    */
    HalfAdder(a= b, b= c, sum= sum1 , carry= carry1);
    Not(in=sum1 , out= sum2);
    //if a == 0 SAME

    //if a == 1 -> SUM GETS INVERTED
    //if a == 1 -> CARRY IS 1 IF NOT SAME

    Xor(a= b, b= c, out= o1);
    And(a= b, b= c, out= o2);
    Or(a= o1, b= o2, out= carry2);



    //How do we "glue" another half adder to get this functionality.
    //We can use AND OR NOT XOR MUX ETC
    //We can use MUX with A as SEL
    //If A is Zero then we route half adder
    Mux(a=sum1 , b=sum2 , sel=a, out=sum );
    Mux(a=carry1 , b=carry2 , sel=a , out=carry );


}
HalfAdder.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/2/HalfAdder.hdl
/**
 * Computes the sum of two bits.
 */
CHIP HalfAdder {
    IN a, b;    // 1-bit inputs
    OUT sum,    // Right bit of a + b 
        carry;  // Left bit of a + b

    PARTS:
    //// Replace this comment with your code.
    Xor(a= a, b= b, out=sum);
    And(a= a, b=b , out=carry);
}
16-bit Logic
Mux8Way16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Mux8Way16.hdl
/**
 * 8-way 16-bit multiplexor:
 * out = a if sel = 000
 *       b if sel = 001
 *       c if sel = 010
 *       d if sel = 011
 *       e if sel = 100
 *       f if sel = 101
 *       g if sel = 110
 *       h if sel = 111
 */
CHIP Mux8Way16 {
    IN a[16], b[16], c[16], d[16],
       e[16], f[16], g[16], h[16],
       sel[3];
    OUT out[16];

    PARTS:
    //// Replace this comment with your code.
    Mux4Way16(a= a[0..15], b= b[0..15], c= c[0..15], d= d[0..15], sel= sel[0..1], out= o1);
    Mux4Way16(a= e[0..15], b= f[0..15], c= g[0..15], d= h[0..15], sel= sel[0..1], out= o2);
    Mux16(a= o1, b= o2, sel= sel[2], out= out);
}
Mux4Way16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Mux4Way16.hdl
/**
 * 4-way 16-bit multiplexor:
 * out = a if sel = 00
 *       b if sel = 01
 *       c if sel = 10
 *       d if sel = 11
 */
CHIP Mux4Way16 {
    IN a[16], b[16], c[16], d[16], sel[2];
    OUT out[16];
    PARTS:

    //a if sel[1] is 0 b if sel[1] is 1
    Mux16(a= a[0..15], b= b[0..15], sel= sel[0], out= o1);
    //c if sel[1] is 0 d if sel[1] is 1
    Mux16(a= c[0..15], b= d[0..15], sel=sel[0], out= o2);
    //o1 if sel[0] is 0 o2 if sel[0] is 1
    Mux16(a= o1, b= o2, sel=sel[1], out=out);

}
Mux16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Mux16.hdl
/**
 * 16-bit multiplexor: 
 * for i = 0, ..., 15:
 * if (sel = 0) out[i] = a[i], else out[i] = b[i]
 */
CHIP Mux16 {
    IN a[16], b[16], sel;
    OUT out[16];

    PARTS:
    Mux(a= a[0], b=b[0], sel=sel, out=out[0]);
    Mux(a= a[1], b=b[1], sel=sel, out=out[1]);
    Mux(a= a[2], b=b[2], sel=sel, out=out[2]);
    Mux(a= a[3], b=b[3], sel=sel, out=out[3]);
    Mux(a= a[4], b=b[4], sel=sel, out=out[4]);
    Mux(a= a[5], b=b[5], sel=sel, out=out[5]);
    Mux(a= a[6], b=b[6], sel=sel, out=out[6]);
    Mux(a= a[7], b=b[7], sel=sel, out=out[7]);
    Mux(a= a[8], b=b[8], sel=sel, out=out[8]);
    Mux(a= a[9], b=b[9], sel=sel, out=out[9]);
    Mux(a= a[10], b=b[10], sel=sel, out=out[10]);
    Mux(a= a[11], b=b[11], sel=sel, out=out[11]);
    Mux(a= a[12], b=b[12], sel=sel, out=out[12]);
    Mux(a= a[13], b=b[13], sel=sel, out=out[13]);
    Mux(a= a[14], b=b[14], sel=sel, out=out[14]);
    Mux(a= a[15], b=b[15], sel=sel, out=out[15]);
}
Or8Way.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Or8Way.hdl
/**
 * 8-way Or gate: 
 * out = in[0] Or in[1] Or ... Or in[7]
 */
CHIP Or8Way {
    IN in[8];
    OUT out;

    PARTS:
    Or(a= in[0], b= in[1], out= o1);
    Or(a= o1, b= in[2], out= o2);
    Or(a= o2, b= in[3], out= o3);
    Or(a= o3, b= in[4], out= o4);
    Or(a= o4, b= in[5], out= o5);
    Or(a= o5, b= in[6], out= o6);
    Or(a= o6, b= in[7], out= out);
}
Or16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Or16.hdl
/**
 * 16-bit Or gate:
 * for i = 0, ..., 15:
 * out[i] = a[i] Or b[i] 
 */
CHIP Or16 {
    IN a[16], b[16];
    OUT out[16];

    PARTS:
    Or(a= a[0], b=b[0], out=out[0]);
    Or(a= a[1], b=b[1], out=out[1]);
    Or(a= a[2], b=b[2], out=out[2]);
    Or(a= a[3], b=b[3], out=out[3]);
    Or(a= a[4], b=b[4], out=out[4]);
    Or(a= a[5], b=b[5], out=out[5]);
    Or(a= a[6], b=b[6], out=out[6]);
    Or(a= a[7], b=b[7], out=out[7]);
    Or(a= a[8], b=b[8], out=out[8]);
    Or(a= a[9], b=b[9], out=out[9]);
    Or(a= a[10], b=b[10], out=out[10]);
    Or(a= a[11], b=b[11], out=out[11]);
    Or(a= a[12], b=b[12], out=out[12]);
    Or(a= a[13], b=b[13], out=out[13]);
    Or(a= a[14], b=b[14], out=out[14]);
    Or(a= a[15], b=b[15], out=out[15]);
}
And16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/And16.hdl
/**
 * 16-bit And gate:
 * for i = 0, ..., 15:
 * out[i] = a[i] And b[i] 
 */
CHIP And16 {
    IN a[16], b[16];
    OUT out[16];

    PARTS:
    And(a= a[0], b=b[0], out=out[0]);
    And(a= a[1], b=b[1], out=out[1]);
    And(a= a[2], b=b[2], out=out[2]);
    And(a= a[3], b=b[3], out=out[3]);
    And(a= a[4], b=b[4], out=out[4]);
    And(a= a[5], b=b[5], out=out[5]);
    And(a= a[6], b=b[6], out=out[6]);
    And(a= a[7], b=b[7], out=out[7]);
    And(a= a[8], b=b[8], out=out[8]);
    And(a= a[9], b=b[9], out=out[9]);
    And(a= a[10], b=b[10], out=out[10]);
    And(a= a[11], b=b[11], out=out[11]);
    And(a= a[12], b=b[12], out=out[12]);
    And(a= a[13], b=b[13], out=out[13]);
    And(a= a[14], b=b[14], out=out[14]);
    And(a= a[15], b=b[15], out=out[15]);
    
    
}
Not16.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Not16.hdl
/**
 * 16-bit Not gate:
 * for i = 0, ..., 15:
 * out[i] = Not(a[i])
 */
CHIP Not16 {
    IN in[16];
    OUT out[16];

    PARTS:
        Not(in=in[0], out= out[0]);
        Not(in=in[1], out= out[1]);
        Not(in=in[2], out= out[2]);
        Not(in=in[3], out= out[3]);
        Not(in=in[4], out= out[4]);
        Not(in=in[5], out= out[5]);
        Not(in=in[6], out= out[6]);
        Not(in=in[7], out= out[7]);
        Not(in=in[8], out= out[8]);
        Not(in=in[9], out= out[9]);
        Not(in=in[10], out= out[10]);
        Not(in=in[11], out= out[11]);
        Not(in=in[12], out= out[12]);
        Not(in=in[13], out= out[13]);
        Not(in=in[14], out= out[14]);
        Not(in=in[15], out= out[15]);
    }
Single-bit Logic
DMux8Way.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/DMux8Way.hdl
/**
 * 8-way demultiplexor:
 * [a, b, c, d, e, f, g, h] = [in, 0,  0,  0,  0,  0,  0,  0] if sel = 000
 *                            [0, in,  0,  0,  0,  0,  0,  0] if sel = 001
 *                            [0,  0, in,  0,  0,  0,  0,  0] if sel = 010
 *                            [0,  0,  0, in,  0,  0,  0,  0] if sel = 011
 *                            [0,  0,  0,  0, in,  0,  0,  0] if sel = 100
 *                            [0,  0,  0,  0,  0, in,  0,  0] if sel = 101
 *                            [0,  0,  0,  0,  0,  0, in,  0] if sel = 110
 *                            [0,  0,  0,  0,  0,  0,  0, in] if sel = 111
 */
CHIP DMux8Way {
    IN in, sel[3];
    OUT a, b, c, d, e, f, g, h;

    PARTS:
    DMux4Way(in= o1, sel= sel[0..1], a= a, b= b, c= c, d= d);
    DMux4Way(in= o2, sel= sel[0..1], a= e, b= f, c= g, d= h);
    DMux(in= in, sel= sel[2], a= o1, b= o2);
}
DMux4Way.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/DMux4Way.hdl
/**
 * 4-way demultiplexor:
 * [a, b, c, d] = [in, 0, 0, 0] if sel = 00
 *                [0, in, 0, 0] if sel = 01
 *                [0, 0, in, 0] if sel = 10
 *                [0, 0, 0, in] if sel = 11
 */
CHIP DMux4Way {
    IN in, sel[2];
    OUT a, b, c, d;

    PARTS:
    /*
    |in | sel  | a | b | c | d |
    | 0 |  00  | 0 | 0 | 0 | 0 |
    | 0 |  01  | 0 | 0 | 0 | 0 |
    | 0 |  10  | 0 | 0 | 0 | 0 |
    | 0 |  11  | 0 | 0 | 0 | 0 |
    | 1 |  00  | 1 | 0 | 0 | 0 |
    | 1 |  01  | 0 | 1 | 0 | 0 |
    | 1 |  10  | 0 | 0 | 1 | 0 |
    | 1 |  11  | 0 | 0 | 0 | 1 |
    */
    DMux(in= o1, sel= sel[0], a= a, b= b);
    DMux(in= o2, sel= sel[0], a= c, b= d);
    DMux(in= in, sel= sel[1], a= o1, b= o2);
}
DMux.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/DMux.hdl
/**
 * Demultiplexor:
 * [a, b] = [in, 0] if sel = 0
 *          [0, in] if sel = 1
 */
CHIP DMux {
    IN in, sel;
    OUT a, b;

    PARTS:
    //|in |sel| a | b |
    //| 0 | 0 | 0 | 0 |
    //| 0 | 1 | 0 | 0 |
    //| 1 | 0 | 1 | 0 |
    //| 1 | 1 | 0 | 1 |
    Not(in= sel, out= notSel);
    And(a= in, b= notSel, out=a);
    And(a= in, b= sel, out=b);

}
Mux.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Mux.hdl
/** 
 * Multiplexor:
 * if (sel = 0) out = a, else out = b
 */


/*

*/

CHIP Mux {
    IN a, b, sel;
    OUT out;

    PARTS:
    Not(in= a, out= notA);
    Not(in= b, out= notB);
    Not(in= sel, out= notSel);
    And(a= a, b= b, out= aAndB);
    And(a= notA, b= b, out= notAAndB);
    And(a= a, b= notB, out= aAndNotB);

    //| 0 | 1 | 0 | 0 |
    And(a= notAAndB, b= notSel, out= notAAndBAndNotSel);

    //| 0 | 1 | 1 | 1 |
    And(a= notAAndB, b= sel, out= notAAndBAndSel);

    //| 1 | 0 | 0 | 1 |

    And(a= aAndNotB, b= notSel, out= aAndNotBAndNotSel);

    //| 1 | 1 | 0 | 1 |
    And(a= aAndB, b= notSel, out= aAndBAndNotSel);

    //| 1 | 1 | 1 | 1 |
    And(a= aAndB, b= sel, out= aAndBAndSel);

    Or(a= notAAndBAndSel, b= notAAndBAndSel, out= o3);
    Or(a= o3, b= aAndNotBAndNotSel, out= o4);
    Or(a= o4, b= aAndBAndNotSel, out= o6);
    Or(a= o6, b= aAndBAndSel, out= out);
}
Xor.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Xor.hdl
/**
 * Exclusive-or gate:
 * if ((a and Not(b)) or (Not(a) and b)) out = 1, else out = 0
 */
CHIP Xor {
    IN a, b;
    OUT out;

    PARTS:
    Not(in= a, out= notA);
    And(a= notA, b= b, out= notAAndB);

    Not(in= b, out= notB);
    And(a= a, b= notB, out= aAndNotB);

    Or(a= notAAndB, b= aAndNotB, out= out);
}
Or.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Or.hdl
/**
 * Or gate:
 * if (a or b) out = 1, else out = 0 
 */
CHIP Or {
    IN a, b;
    OUT out;

    PARTS:
    Not(in= a, out= o1);
    Not(in= b, out= o2);
    Nand(a= o1, b= o2, out= out);
}
And.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/And.hdl
/**
 * And gate:
 * if (a and b) out = 1, else out = 0 
 */

CHIP And {
    IN a, b;
    OUT out;
    
    PARTS:
    Nand(a= a, b= b, out= o1);
    Not(in= o1, out= out);

}
Not.hdl
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/1/Not.hdl
/**
 * Not gate:
 * if (in) out = 0, else out = 1
 */
CHIP Not {
    IN in;
    OUT out;

    PARTS:
    Nand(a= in, b= in, out= out);
}