Skip to content

Commit 39ff49c

Browse files
committed
Make PortMap more normal
1 parent cfe44b1 commit 39ff49c

File tree

4 files changed

+38
-67
lines changed

4 files changed

+38
-67
lines changed

chipflow_lib/pin_lock.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import logging
44

55
from pathlib import Path
6+
from pprint import pformat
67

78
from chipflow_lib import _parse_config, _ensure_chipflow_root
89
from chipflow_lib.platforms import top_components, LockFile, PACKAGE_DEFINITIONS
@@ -23,7 +24,7 @@ def lock_pins() -> None:
2324

2425
if lockfile.exists():
2526
oldlock = LockFile.model_validate_json(lockfile.read_text())
26-
27+
print(f"Old Lock =\n{pformat(oldlock)}")
2728
print(f"Locking pins: {'using pins.lock' if lockfile.exists() else ''}")
2829

2930
# Get package definition from dict instead of Pydantic model

chipflow_lib/platforms/utils.py

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ def __str__(self):
285285

286286
class Port(pydantic.BaseModel):
287287
type: str
288-
pins: List[str] | None # None implies must be allocated at end
288+
pins: List[Pin] | None # None implies must be allocated at end
289289
port_name: str
290290
direction: Optional[io.Direction] = None
291291
options: Optional[dict] = None
@@ -430,57 +430,28 @@ def _allocate_pins(name: str, member: Dict[str, Any], pins: List[str], port_name
430430
Interface = Dict[str, Port]
431431
Component = Dict[str, Interface]
432432

433-
class PortMap(MutableMapping[str, Component]):
434-
def __init__(self, data = {}):
435-
self.map: Dict[str, Component] = data
436-
return super().__init__()
437-
"Represents a mapping of `Port`s to Package pins, grouped by `Component` and `Interface`"
438-
def __getitem__(self, key: str):
439-
"Gets an `Component` from the map by name"
440-
return self.map[key]
441-
442-
def __setitem__(self, key: str, value: Component):
443-
"Adds or modifies a `Component` in the map by name"
444-
self.map[key] = value
445-
446-
def __delitem__(self, key: str):
447-
"Deletes a `Component` in the map by name"
448-
del self.map[key]
449-
450-
def __iter__(self):
451-
"Iterates `Component`s in the map by name"
452-
return iter(self.map)
453-
454-
def __len__(self):
455-
return len(self.map)
433+
class PortMap(pydantic.BaseModel):
434+
ports: Dict[str, Component] = {}
456435

457436
def _add_port(self, component: str, interface: str, port_name: str, port: Port):
458437
"Internally used by a `PackageDef`"
459-
if component not in self:
460-
self[component] = {}
461-
if interface not in self[component]:
462-
self[component][interface] = {}
463-
self[component][interface][port_name] = port
438+
if component not in self.ports:
439+
self.ports[component] = {}
440+
if interface not in self.ports[component]:
441+
self.ports[component][interface] = {}
442+
self.ports[component][interface][port_name] = port
464443

465444
def _add_ports(self, component: str, interface: str, ports: Dict[str, Port]):
466445
"Internally used by a `PackageDef`"
467-
if component not in self:
468-
self[component] = {}
469-
self[component][interface] = ports
446+
if component not in self.ports:
447+
self.ports[component] = {}
448+
self.ports[component][interface] = ports
470449

471450
def get_ports(self, component: str, interface: str) -> Dict[str, Port]:
472451
"List the ports allocated in this PortMap for the given `Component` and `Interface`"
473-
if component not in self:
452+
if component not in self.ports:
474453
raise KeyError(f"'{component}' not found in {self}")
475-
return self[component][interface]
476-
477-
@classmethod
478-
def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler):
479-
return core_schema.dict_schema(
480-
keys_schema=core_schema.str_schema(),
481-
values_schema=core_schema.any_schema()
482-
)
483-
454+
return self.ports[component][interface]
484455

485456

486457
class LockFile(pydantic.BaseModel):

tests/test_package_pins.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ def test_basic_properties(self):
5050
self.assertEqual(self.package.width, 36)
5151
self.assertEqual(self.package.height, 36)
5252
self.assertEqual(self.package.package_type, "QuadPackageDef")
53-
self.assertTrue(self.package.allocate_jtag) # Default should be True
5453

5554
def test_bringup_pins(self):
5655
"""Test bringup pins configuration"""

tests/test_utils_additional.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -87,34 +87,34 @@ def test_portmap_creation(self):
8787
}
8888

8989
# Create a PortMap
90-
port_map = PortMap(data)
90+
port_map = PortMap(ports=data)
9191

9292
# Basic checks
93-
self.assertEqual(len(port_map), 1)
94-
self.assertIn("comp1", port_map)
95-
self.assertIn("iface1", port_map["comp1"])
96-
self.assertIn("port1", port_map["comp1"]["iface1"])
97-
self.assertEqual(port_map["comp1"]["iface1"]["port1"], port1)
93+
self.assertEqual(len(port_map.ports), 1)
94+
self.assertIn("comp1", port_map.ports)
95+
self.assertIn("iface1", port_map.ports["comp1"])
96+
self.assertIn("port1", port_map.ports["comp1"]["iface1"])
97+
self.assertEqual(port_map.ports["comp1"]["iface1"]["port1"], port1)
9898

9999
def test_portmap_mutable_mapping(self):
100100
"""Test PortMap MutableMapping methods"""
101101
# Create an empty PortMap
102-
port_map = PortMap({})
102+
port_map = PortMap()
103103

104104
# Test __setitem__ and __getitem__
105-
port_map["comp1"] = {"iface1": {"port1": Port(type="input", pins=["1"], port_name="port1")}}
106-
self.assertIn("comp1", port_map)
107-
self.assertEqual(port_map["comp1"]["iface1"]["port1"].pins, ["1"])
105+
port_map.ports["comp1"] = {"iface1": {"port1": Port(type="input", pins=["1"], port_name="port1")}}
106+
self.assertIn("comp1", port_map.ports)
107+
self.assertEqual(port_map.ports["comp1"]["iface1"]["port1"].pins, ["1"])
108108

109109
# Test __delitem__
110-
del port_map["comp1"]
111-
self.assertNotIn("comp1", port_map)
110+
del port_map.ports["comp1"]
111+
self.assertNotIn("comp1", port_map.ports)
112112

113113
# Test __iter__ and __len__
114-
port_map["comp1"] = {"iface1": {}}
115-
port_map["comp2"] = {"iface2": {}}
116-
self.assertEqual(len(port_map), 2)
117-
self.assertEqual(set(port_map), {"comp1", "comp2"})
114+
port_map.ports["comp1"] = {"iface1": {}}
115+
port_map.ports["comp2"] = {"iface2": {}}
116+
self.assertEqual(len(port_map.ports), 2)
117+
self.assertEqual(set(port_map.ports), {"comp1", "comp2"})
118118

119119
def test_portmap_methods(self):
120120
"""Test PortMap helper methods"""
@@ -125,10 +125,10 @@ def test_portmap_methods(self):
125125
port1 = Port(type="input", pins=["1"], port_name="port1", direction=io.Direction.Input)
126126
port_map._add_port("comp1", "iface1", "port1", port1)
127127

128-
self.assertIn("comp1", port_map)
129-
self.assertIn("iface1", port_map["comp1"])
130-
self.assertIn("port1", port_map["comp1"]["iface1"])
131-
self.assertEqual(port_map["comp1"]["iface1"]["port1"], port1)
128+
self.assertIn("comp1", port_map.ports)
129+
self.assertIn("iface1", port_map.ports["comp1"])
130+
self.assertIn("port1", port_map.ports["comp1"]["iface1"])
131+
self.assertEqual(port_map.ports["comp1"]["iface1"]["port1"], port1)
132132

133133
# Test _add_ports with a new interface
134134
ports = {
@@ -137,9 +137,9 @@ def test_portmap_methods(self):
137137
}
138138
port_map._add_ports("comp1", "iface2", ports)
139139

140-
self.assertIn("iface2", port_map["comp1"])
141-
self.assertEqual(len(port_map["comp1"]["iface2"]), 2)
142-
self.assertEqual(port_map["comp1"]["iface2"]["port2"].pins, ["2"])
140+
self.assertIn("iface2", port_map.ports["comp1"])
141+
self.assertEqual(len(port_map.ports["comp1"]["iface2"]), 2)
142+
self.assertEqual(port_map.ports["comp1"]["iface2"]["port2"].pins, ["2"])
143143

144144
# Test get_ports
145145
result = port_map.get_ports("comp1", "iface1")

0 commit comments

Comments
 (0)