This repository was archived by the owner on Mar 7, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathpins.zen
More file actions
118 lines (96 loc) · 4.36 KB
/
pins.zen
File metadata and controls
118 lines (96 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
Pins = dict[str, Net]
PinOption = record(name=str, interface_type=typing.Any, field=str)
PinMap = dict[str, list[PinOption]]
PinInterfaces = dict[str, list[str]]
PinBuilder = record(pin_map=PinMap, pins=dict[str, Net | None])
def PinInterface(name: str, interface_type) -> struct:
"""Return a struct of PinOption objects for *interface_type* bound to *name*.
Example:
load("stdlib/interfaces.zen", "OscPair", "Usb2")
load("stdlib/pins.zen", "bind_interface")
OSC = PinInterface("OSC", OscPair, ["xin", "xout"])
USB = PinInterface("USB", Usb2, ["dp", "dm"])
"""
# Extract interface fields: str(Spi) -> "<Interface: cs=Net, miso=Net, mosi=Net, clk=Net>"
fields = dir(interface_type)
# # One-liner dict-comprehension keeps behaviour yet trims verbosity
pin_options = {f: PinOption(name=name, interface_type=interface_type, field=f) for f in fields}
return struct(**pin_options)
def PinMapBuilder(pin_map: PinMap, pin_nets: Pins = {}):
"""Return a stateful, chain-able pin-map builder."""
state = {
"pin_map": pin_map,
"pins": {p: None for p in pin_map}, # type: dict[str, Net | None]
}
# ---------------------------------------------------------------------
# Core helpers
# ---------------------------------------------------------------------
def _make_interfaces(_pin_map):
"""Helper: build { interface_name -> { pin_name -> PinOption } }."""
interfaces = {}
for _pin, _opts in _pin_map.items():
for _opt in _opts:
interfaces.setdefault(_opt.name, {}).setdefault(_pin, _opt)
return interfaces
def _connect(pin_name: str, net: Net):
pins = state["pins"]
pin_net = pins.get(pin_name)
if pin_net:
error("Pin already connected: {} -> {}, can't be {}".format(pin_name, pin_net, net))
if pin_name not in state["pin_map"]:
available = state["pin_map"].keys()
error("Pin {} not found in pin map: {}".format(pin_name, available))
pins[pin_name] = net
return builder # fluent chaining
def _assign(name: str, nets, **kwargs):
interfaces = _make_interfaces(state["pin_map"])
if name not in interfaces:
iface_keys = interfaces.keys()
error("{} not in {}".format(name, iface_keys))
# Filter by interface type – only keep pins where *nets* matches.
iface_pins = {p: o for p, o in interfaces[name].items() if isinstance(nets, o.interface_type)}
if not iface_pins:
net_type = str(type(nets))
error("{} can't take interface of type {}".format(name, net_type))
available_pins = iface_pins.keys()
available_fields = {i.field: None for i in iface_pins.values()}.keys()
for field, pin_name in kwargs.items():
pin = iface_pins.get(pin_name)
if not pin:
error("Pin {} not found for {}: {}".format(pin_name, name, available_pins))
if field not in available_fields:
error("Field {} not found for {}: {}".format(field, name, available_fields))
if pin.field != field:
alt_pins = [p for p, i in iface_pins.items() if i.field == field]
error("{} can't be {}.{}: pick from {}".format(pin_name, name, field, alt_pins))
_connect(pin_name, getattr(nets, field))
return builder
# ---------------------------------------------------------------------
# Public API
# ---------------------------------------------------------------------
def assign(name, nets, **kwargs):
return _assign(name, nets, **kwargs)
def connect(pin_name, net):
return _connect(pin_name, net)
def build(fill_unconnected=False, warn=True):
result = {}
unconnected = []
for _pin, _net in state["pins"].items():
if _net == None:
if fill_unconnected:
result[_pin] = Net(_pin)
unconnected.append(_pin)
else:
result[_pin] = _net
if unconnected and warn:
print(f"Warning: Unconnected pins: {unconnected}")
return result
builder = struct(
connect=connect,
assign=assign,
build=build,
pins=build,
)
for pin, net in pin_nets.items():
_connect(pin, net)
return builder