Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTML Composer 1 - IR changes #162

Open
wants to merge 6 commits into
base: next_release
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 98 additions & 1 deletion spydrnet/ir/cable.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from copy import deepcopy
from spydrnet.ir import Bundle
from spydrnet.ir import Wire
from spydrnet.ir import Port
from spydrnet.ir import Instance
from spydrnet.ir import InnerPin
from spydrnet.ir.views.listview import ListView
from spydrnet.global_state import global_callback
from spydrnet.global_state.global_callback import _call_create_cable
Expand Down Expand Up @@ -62,6 +65,11 @@ def _items(self):
"""Overrides the bundle _items function to return wires"""
return self._wires

@property
def size(self):
""" Retruns the size of the cable """
return len(self._wires)

@property
def wires(self):
"""Gets a list of wires that are in this cable"""
Expand Down Expand Up @@ -104,7 +112,7 @@ def create_wire(self):

def add_wire(self, wire, position=None):
"""
Adds a wire to the cable at the given position. This wire must not belong to
Adds a wire to the cable at the given position. This wire must not belong to
a cable already

parameters
Expand Down Expand Up @@ -161,6 +169,95 @@ def _remove_wire(self, wire):
global_callback._call_cable_remove_wire(self, wire)
wire._cable = None

def check_concat(self):
"""
Checks if the cable is concatenated while connecting to other ports
"""
assert self.size, "Cable does not contain any wires"

# get all pins of index 0 wire
connected_pins = len(self._wires[0].pins)
connected_port = set([p.port for p in self._wires[0].pins])
# iterate each wire in cable
for wire in self._wires:
# If this wire is connected to different number of pins
if not connected_pins == len(wire.pins):
return False
# If this wire is connected to different ports
if connected_port.difference([p.port for p in wire.pins]):
return False
# Sequence of connection is same
for pin in wire.pins:
if isinstance(pin, InnerPin):
if not pin.port.size == self.size:
return False
if not pin.index() == wire.index():
return False
else:
if not pin.inner_pin.port.size == self.size:
return False
if not pin.inner_pin.index() == wire.index():
return False
return True

def connect_instance_port(self, instance, port):
"""
Connect cable to given Instance and Port (Straight connection)
"""
assert isinstance(instance, Instance), \
"Argument to connect_port should be port"
assert isinstance(port, Port), \
"Argument to connect_port should be port"
assert port.size, "Port has no pins"
assert port.size == self.size, "Port and cable size do not match"
assert port in instance.reference.ports, \
f"Port {port.name} in not part of instance definition {instance.reference.name}"

for wire in self.wires:
if port.is_downto:
wire.connect_pin(instance.pins[port.pins[wire.index()]])
else:
wire.connect_pin(instance.pins[port.pins[-(wire.index()+1)]])

def disconnect_instance_port(self, instance, port):
assert isinstance(instance, Instance), \
"Argument to connect_port should be port"
assert isinstance(port, Port), \
"Argument to connect_port should be port"
assert port.size, "Port has no pins"
assert port.size == self.size, "Port and cable size do not match"
assert port in instance.reference.ports, \
f"Port {port.name} in not part of instance definition {instance.reference.name}"
for wire in self.wires:
if port.is_downto:
wire.disconnect_pin(instance.pins[port.pins[wire.index()]])
else:
wire.disconnect_pin(instance.pins[port.pins[-(wire.index()+1)]])

def connect_port(self, port):
""" Connet cable to port (innerpins connection)"""
assert isinstance(port, Port), \
"Argument to connect_port should be port"
assert port.size, "Port has no pins"

for wire in self.wires:
if port.is_downto:
wire.connect_pin(port.pins[wire.index()])
else:
wire.connect_pin(port.pins[-(wire.index()+1)])

def merge_cables(self, cables):
""" Merges multiple cables to this cable in given sequence """
for cable in cables:
assert isinstance(cable, Cable), \
"All arguments should be cable instance"

for cable in cables[::-1]:
wires = list(cable.wires)
for wire in wires[::-1]:
cable.remove_wire(wire)
self.add_wire(wire)

def _clone_rip_and_replace(self, memo):
"""Remove from its current environment and place it into the new cloned environment with
references held in the memo dictionary"""
Expand Down
7 changes: 7 additions & 0 deletions spydrnet/ir/innerpin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ def port(self):
This object cannot be modified directly by the end user."""
return self._port

def index(self):
"""if this wire is in a cable, returns the index number of the wire in the parent cable"""

assert self._port is not None, "the wire does not belong to a cable"

return self._port.pins.index(self)

def _clone_rip_and_replace(self, memo):
"""Remove from its current environment and place it into the new cloned environment with
references held in the memo dictionary"""
Expand Down
7 changes: 7 additions & 0 deletions spydrnet/ir/outerpin.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ def inner_pin(self):
"""get the inner pin associated with this outer pin"""
return self._inner_pin

@property
def port(self):
"""Return the port that the inner pin is a part of.

This object cannot be modified directly by the end user."""
return self._inner_pin._port

def __eq__(self, other):
if isinstance(other, OuterPin):
return (
Expand Down
32 changes: 32 additions & 0 deletions spydrnet/ir/port.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,26 @@ def direction(self, value):
"Type {} cannot be assigned to direction".format(type(value))
)

@property
def is_input(self):
""" Shortcut property"""
return self.direction == self.Direction.IN

@property
def is_output(self):
""" Shortcut property"""
return self.direction == self.Direction.OUT

@property
def is_inout(self):
""" Shortcut property"""
return self.direction == self.Direction.INOUT

@property
def size(self):
"""Get a list of the pins that are in the port"""
return len(self._pins)

@property
def pins(self):
"""Get a list of the pins that are in the port"""
Expand All @@ -148,6 +168,18 @@ def pins(self, value):
must be unique"
self._pins = value_list

@property
def inner_wires(self):
""" Returns list of internal wires connected to the port """
return (p.wire for p in self.pins if p.wire)

@property
def outer_wires(self, instance):
""" Returns list of externla wires connected to the port """
assert instance.reference == self.definition, \
"Port does not belong to given instance definition"
return (instance.pins[p].wire for p in self.pins if instance.pins[p].wire)

def create_pins(self, pin_count):
"""Create pin_count pins in the given port a downto style syntax is assumed.

Expand Down
78 changes: 78 additions & 0 deletions tests/spydrnet/ir/tests/test_cable.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,84 @@ def test_remove_wire_from(self):
self.assertTrue(wire_included in self.cable.wires)
self.assertEqual(wire_included.cable, self.cable)

def test_check_concat(self):
# TODO: test connections to inner_pins as well
port0 = sdn.Port(name="p0", direction=sdn.Port.Direction.OUT)
port1 = sdn.Port(name="p1", direction=sdn.Port.Direction.IN)
port2 = sdn.Port(name="p2", direction=sdn.Port.Direction.IN)
port0.create_pins(4)
port1.create_pins(4)
port2.create_pins(4)
self.cable.create_wires(4)
for wire in self.cable.wires:
wire.connect_pin(port0.pins[wire.index()])
wire.connect_pin(port1.pins[wire.index()])
wire.connect_pin(port2.pins[wire.index()])
self.assertTrue(self.cable.check_concat())
port1._pins = port1.pins[::-1]
self.assertFalse(self.cable.check_concat())
port1._pins = port1.pins[::-1]
self.assertTrue(self.cable.check_concat())
self.cable.wires[-1].disconnect_pin(port2.pins[-1])
self.assertFalse(self.cable.check_concat())
self.cable.wires[-1].connect_pin(port2.pins[-1])
self.assertTrue(self.cable.check_concat())
new_pin = port2.create_pin()
self.assertFalse(self.cable.check_concat())
port2.remove_pin(new_pin)
self.assertTrue(self.cable.check_concat())
port2.add_pin(new_pin, position=0)
self.assertFalse(self.cable.check_concat())

def test_connect_port_1(self):
port = sdn.Port(name="p0", direction=sdn.Port.Direction.IN)
port.create_pins(4)
w = self.cable.create_wires(4)
self.assertIsNone(self.cable.connect_port(port))
self.assertTrue(port.pins[0].wire is w[0])
self.assertTrue(port.pins[1].wire is w[1])
self.assertTrue(port.pins[2].wire is w[2])
self.assertTrue(port.pins[3].wire is w[3])

def test_connect_port_2(self):
port = sdn.Port(name="p0",
direction=sdn.Port.Direction.IN,
is_downto=False)
port.create_pins(4)
w = self.cable.create_wires(4)
self.assertIsNone(self.cable.connect_port(port))
self.assertTrue(port.pins[0].wire is w[3])
self.assertTrue(port.pins[1].wire is w[2])
self.assertTrue(port.pins[2].wire is w[1])
self.assertTrue(port.pins[3].wire is w[0])

def test_connect_instance_port(self):
top = sdn.Definition(name="top")
module = sdn.Definition(name="module1")
port = module.create_port(name="p0",
direction=sdn.Port.Direction.IN,
is_downto=False)
port.create_pins(4)
inst1 = top.create_child(name="inst1", reference=module)

w = self.cable.create_wires(4)
self.assertIsNone(self.cable.connect_instance_port(inst1, port))
self.assertTrue(inst1.pins[port.pins[0]].wire is w[3])
self.assertTrue(inst1.pins[port.pins[1]].wire is w[2])
self.assertTrue(inst1.pins[port.pins[2]].wire is w[1])
self.assertTrue(inst1.pins[port.pins[3]].wire is w[0])

def test_merge_cables(self):
cable1 = sdn.Cable()
cable2 = sdn.Cable()
w_1 = cable1.create_wires(2)
w_2 = cable2.create_wires(4)
self.cable.merge_cables([cable1, cable2])
self.assertEqual(self.cable.size, 6)
for indx, wire in enumerate(w_2[::-1] + w_1[::-1]):
self.assertEqual(self.cable.wires[indx], wire)
self.assertEqual(cable1.wires, [])
self.assertEqual(cable1.wires, [])
def test_scalar_false(self):
cable = sdn.Cable()
cable.create_wire()
Expand Down
8 changes: 8 additions & 0 deletions tests/spydrnet/ir/tests/test_port.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,11 @@ def test_is_array(self):
def test_is_array_clear_on_array_bundle(self):
self.port.create_pins(2)
self.port.is_array = False

@unittest.expectedFailure
def test_inner_wires(self):
self.assertTrue(False)

@unittest.expectedFailure
def test_outer_wires(self):
self.assertTrue(False)