Source code for skidl.network
# -*- coding: utf-8 -*-
# The MIT License (MIT) - Copyright (c) 2016-2021 Dave Vandenbout.
"""
Object for for handling series and parallel networks of two-pin parts, nets, and pins.
"""
from __future__ import ( # isort:skip
absolute_import,
division,
print_function,
unicode_literals,
)
from builtins import range, super
from future import standard_library
from .logger import active_logger
from .utilities import *
standard_library.install_aliases()
[docs]class Network(list):
def __init__(self, *objs):
"""Create a Network object from a list of pins, nets, and parts."""
super().__init__()
for obj in objs:
try:
ntwk = obj.create_network() # Create a Network from each object.
except AttributeError:
active_logger.raise_(
TypeError,
"Can't create a network from a {} object ({}).".format(
type(obj), obj.__name__
),
)
# Add the in & out ports of the object network to this network.
self.extend(ntwk)
# A Network cannot have more than two ports. But it may have only
# one which will be used as both an input and an output. Or it may
# have zero, in which case it is just an empty container waiting to
# have ports added to it.
if len(self) > 2:
active_logger.raise_(
ValueError,
"A Network object can't have more than two nodes.",
)
def __and__(self, obj):
"""Combine two networks by placing them in series."""
# First, convert the object to a network.
try:
ntwk = obj.create_network()
except AttributeError:
active_logger.raise_(
TypeError,
"Unable to create a Network from a {} object ({}).".format(
type(obj), obj.__name__
),
)
# Attach the output of the first network to the input of the second.
# (Use -1 index to get the output port instead of 1 because the network
# may only have a single port serving as both the input and output.)
self[-1] += ntwk[0]
# Return a network consisting of the input of the first and the output of the second.
return Network(self[0], ntwk[-1])
def __rand__(self, obj):
"""Combine two networks by placing them in series. (Reverse-ordered operation.)"""
# Create a network from the first object and then place it in series with the second network.
return Network(obj) & self
def __or__(self, obj):
"""Combine two networks by placing them in parallel."""
# First, convert the object to a network.
try:
ntwk = obj.create_network()
except AttributeError:
active_logger.raise_(
TypeError,
"Unable to create a Network from a {} object ({}).".format(
type(obj), obj.__name__
),
)
# Attach the inputs of both networks and the outputs of both networks to
# place them in parallel.
self[0] += ntwk[0]
self[-1] += ntwk[-1]
# Just return one of the original networks since its I/O ports are attached to both.
return self
[docs] def create_network(self):
"""Creating a network from a network just returns the original network."""
return self
[docs]def tee(ntwk):
"""
Create a network "tee" by returning the first terminal of a Network object.
Then you can create tee'ed networks like so: vi & r1 & r2 & tee(r3 & r4 & gnd) & r5 & gnd
which becomes:
vi---r1---r2-+-r5---gnd
|
|
r3---r4---gnd
"""
if not isinstance(ntwk, Network):
# Convert an object into a Network if it isn't already.
ntwk = Network(ntwk)
# Return the first terminal of the network.
return ntwk[0]