#! /usr/bin/env python # # The beginnings of the ripple-carry adder simulation for # CS 52, Assignment 5. # # Rett Bull # November 8, 2006 # # David Kauchak # October, 2015 # # # # The fundamental classes are Node and Gate. # class Node : """ A Node is a junction. (Think of a gate as having wires for input and output; a node is where the wires are connected.) A node maintains its current value, a bit, and a list of all gates whose inputs are connected to that node. There are three methods: get_state which returns the current bit value, set_state which changes the state and, if necessary, calls notify for all the gates in the input list, and connect which adds a gate to the notification list. """ def __init__(self, state): """ Create a node """ self.state = state self.notify_list = [] def set_state(self, newstate): """ Update the state of the node """ if self.state != newstate : self.state = newstate for gate in self.notify_list: gate.notify() def get_state(self): """ Return the state of the node """ return self.state def connect(self, gate): """ Add a gate to the notification list """ self.notify_list.append(gate) class Gate : """ A Gate has some input nodes, one output node, and two important methods. One is evaluate which--when defined in a subclass--- reads the input nodes and returns the value appropriate for that gate. The other is notify which obtains the resulting value for the current inputs and, if necessary, sets the output node to the correct value. """ def __init__(self, inputs, output): """ Create a gate """ self.out_state = output self.in_states = inputs for inp in inputs: inp.connect(self) self.out_state.set_state(self.evaluate()) def evaluate(self) : """ Evaluate the result of the gate """ pass def notify(self) : """ Respond to a notification by changing the output state, if necessary """ new_out_state = self.evaluate() if new_out_state != self.out_state.get_state(): self.out_state.set_state(new_out_state) # # Gate1 and Gate2 are specializations in which a gate is described with # either one or two input nodes, rather than an arbitrary list of them. # class Gate1: def __init__(self, input, output) : """ Create a gate with only one input node """ Gate.__init__(self, [input], output) class Gate2: def __init__(self, input0, input1, output) : """ Create a gate with only two input nodes """ Gate.__init__(self, [input0,input1], output) # # Here we create the AndGate and the AndGate2. Notice that no new code # is necessary for AndGate2. # class AndGate(Gate): def evaluate(self): """ Evaluate the logical-and of the input nodes """ for inp in self.in_states: if inp.get_state() == 0: return 0 return 1 # python allows for multiple inheritence. We're inheriting from both # Gate2 and AndGate. We inherit the constructor from Gate2 and the # evaluate method from AndGate, so we're done! class AndGate2(Gate2, AndGate): pass # # Here we create NotGate1. There is no sensible way to define a not-gate # with more than one input. # # We inherit from Gate1 to get the single input constructor and from # class NotGate1(Gate1, Gate): def evaluate(self): inp = self.in_states[0] if inp.get_state() != 0 : return 0 else: return 1 # ---------------------------------------------------------------------- # Put your solutions below this line. Change nothing above it, except to # insert your name and the current date. #