--- nand.py- +++ nand.py @@ -34,15 +34,19 @@ other.conn = self def set(self, v): + v = bool_v(v) if v == self.v: return self.v = v self.dbgout( str_v(v) ) - if 'O' in self.direc and self.conn: + if self.has('O') and self.conn: self.conn.set(v) - if 'I' in self.direc and self.parent and hasattr(self.parent, 'update'): + if self.has('I') and self.parent and hasattr(self.parent, 'update'): self.enque(self.parent.update) + def has(self, direc): # direc 'I' or 'O' + return direc in self.direc + class Foo(Obj): def __init__(self, parent, latency=None): Obj.__init__(self, parent, 'foo', latency) @@ -75,6 +79,40 @@ v = not ( self.inp_a.v and self.inp_b.v ) self.enque( self.out.set, (v,) ) +class Joint(Obj): + def __init__(self, parent, name='jt', latency=None): + Obj.__init__(self, parent, name, latency) + self.pins = [] + + def connect(self, other_pin): + direc = { 'I': 'O', 'O': 'I' }.get(other_pin.direc, 'IO') + pin = self.new_pin(direc) + pin.connect(other_pin) + + def new_pin(self, direc='IO'): + i = len(self.pins) + name = 'pin{}_{}'.format(i, direc) + pin = Pin(self, name, direc) + self.pins.append(pin) + return pin + + def update(self): + ivs = [ pin.v for pin in self.pins if pin.has('I') ] + f = lambda r, v: r if v == None else ( v if r == None else r or v ) # OR + v = reduce(f, ivs, None) + for pin in self.pins: + if pin.has('O'): + pin.set(v) + +class Lamp(Obj): + def __init__(self, parent, name='lamp', latency=None): + Obj.__init__(self, parent, name, latency) + Pin(self, 'inp', 'I') + + def update(self): + msg = str_v( self.inp.v ) + self.enque( self.dbgout, (msg, True) ) + class Sched: def __init__(self): self.que = [] @@ -109,6 +147,9 @@ def str_v(v): return { True: 'H', False: 'L', None: 'Hi-Z' }.get(v, '?') +def bool_v(v): + return {'H': True, 'L': False, 'Hi-Z': None }.get(v, v) + def dbgout(s, always=False): if always or '-v' in sys.argv: print '{} {}'.format( sched.now, s ) @@ -128,14 +169,24 @@ o.foo.out.connect( o.slow.foo.inp ) o.slow.foo.out.connect( o.slow_12.foo.inp ) - sched.enque( 200, o.foo.out.set, (True,) ) + sched.enque( 200, o.foo.out.set, ('H',) ) NAND(o) - sched.enque( 300, o.nand.inp_a.set, (False,) ) - sched.enque( 300, o.nand.inp_b.set, (False,) ) - sched.enque( 320, o.nand.inp_a.set, (True,) ) - sched.enque( 340, o.nand.inp_b.set, (True,) ) - sched.enque( 360, o.nand.inp_a.set, (False,) ) + sched.enque( 300, o.nand.inp_a.set, ('L',) ) + sched.enque( 300, o.nand.inp_b.set, ('L',) ) + sched.enque( 320, o.nand.inp_a.set, ('H',) ) + sched.enque( 340, o.nand.inp_b.set, ('H',) ) + sched.enque( 360, o.nand.inp_a.set, ('L',) ) + + test1 = Obj(o, 'test1') + NAND(test1) + Joint(test1) + Lamp(test1) + o.test1.jt.connect( o.test1.nand.out ) + o.test1.jt.connect( o.test1.nand.inp_a ) + o.test1.jt.new_pin('O').connect( o.test1.lamp.inp ) + sched.enque( 400, o.test1.nand.inp_b.set, ('H',) ) + sched.enque( 500, o.test1.nand.inp_b.set, ('L',) ) sched.main_loop()