@modular-circuit/perc 0.0.59 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +476 -0
- package/dist/index.d.ts +476 -0
- package/dist/index.js +1874 -0
- package/dist/index.mjs +1838 -0
- package/package.json +14 -11
- package/build/erc/connect_graph_visitor/index.d.ts +0 -2
- package/build/erc/connect_graph_visitor/index.d.ts.map +0 -1
- package/build/erc/connect_graph_visitor/index.js +0 -1
- package/build/erc/connect_graph_visitor/visitor.d.ts +0 -5
- package/build/erc/connect_graph_visitor/visitor.d.ts.map +0 -1
- package/build/erc/connect_graph_visitor/visitor.js +0 -0
- package/build/erc/context/connection_graph_builder_ctx.d.ts +0 -7
- package/build/erc/context/connection_graph_builder_ctx.d.ts.map +0 -1
- package/build/erc/context/connection_graph_builder_ctx.js +0 -0
- package/build/erc/context/error_severity.d.ts +0 -11
- package/build/erc/context/error_severity.d.ts.map +0 -1
- package/build/erc/context/error_severity.js +0 -13
- package/build/erc/context/graph.d.ts +0 -3
- package/build/erc/context/graph.d.ts.map +0 -1
- package/build/erc/context/graph.js +0 -0
- package/build/erc/context/graph_converter.d.ts +0 -8
- package/build/erc/context/graph_converter.d.ts.map +0 -1
- package/build/erc/context/graph_converter.js +0 -0
- package/build/erc/context/index.d.ts +0 -6
- package/build/erc/context/index.d.ts.map +0 -1
- package/build/erc/context/index.js +0 -5
- package/build/erc/context/pin_to_pin_test_ctx.d.ts +0 -7
- package/build/erc/context/pin_to_pin_test_ctx.d.ts.map +0 -1
- package/build/erc/context/pin_to_pin_test_ctx.js +0 -0
- package/build/erc/index.d.ts +0 -5
- package/build/erc/index.d.ts.map +0 -1
- package/build/erc/index.js +0 -4
- package/build/erc/netlist/constraints.d.ts +0 -5
- package/build/erc/netlist/constraints.d.ts.map +0 -1
- package/build/erc/netlist/constraints.js +0 -30
- package/build/erc/netlist/index.d.ts +0 -3
- package/build/erc/netlist/index.d.ts.map +0 -1
- package/build/erc/netlist/index.js +0 -2
- package/build/erc/netlist/tester.d.ts +0 -10
- package/build/erc/netlist/tester.d.ts.map +0 -1
- package/build/erc/netlist/tester.js +0 -44
- package/build/erc/parameter_propagation/error_code.d.ts +0 -41
- package/build/erc/parameter_propagation/error_code.d.ts.map +0 -1
- package/build/erc/parameter_propagation/error_code.js +0 -73
- package/build/erc/parameter_propagation/index.d.ts +0 -3
- package/build/erc/parameter_propagation/index.d.ts.map +0 -1
- package/build/erc/parameter_propagation/index.js +0 -2
- package/build/erc/parameter_propagation/link_testers/index.d.ts +0 -2
- package/build/erc/parameter_propagation/link_testers/index.d.ts.map +0 -1
- package/build/erc/parameter_propagation/link_testers/index.js +0 -1
- package/build/erc/parameter_propagation/link_testers/link_tester_base.d.ts +0 -23
- package/build/erc/parameter_propagation/link_testers/link_tester_base.d.ts.map +0 -1
- package/build/erc/parameter_propagation/link_testers/link_tester_base.js +0 -39
- package/build/erc/parameter_propagation/link_testers/tester_impl.d.ts +0 -247
- package/build/erc/parameter_propagation/link_testers/tester_impl.d.ts.map +0 -1
- package/build/erc/parameter_propagation/link_testers/tester_impl.js +0 -994
- package/build/erc/parameter_propagation/tester.d.ts +0 -16
- package/build/erc/parameter_propagation/tester.d.ts.map +0 -1
- package/build/erc/parameter_propagation/tester.js +0 -147
- package/build/erc/pin_compatibility_matrix/erc_setting.d.ts +0 -29
- package/build/erc/pin_compatibility_matrix/erc_setting.d.ts.map +0 -1
- package/build/erc/pin_compatibility_matrix/erc_setting.js +0 -108
- package/build/erc/pin_compatibility_matrix/error_code.d.ts +0 -55
- package/build/erc/pin_compatibility_matrix/error_code.d.ts.map +0 -1
- package/build/erc/pin_compatibility_matrix/error_code.js +0 -56
- package/build/erc/pin_compatibility_matrix/index.d.ts +0 -5
- package/build/erc/pin_compatibility_matrix/index.d.ts.map +0 -1
- package/build/erc/pin_compatibility_matrix/index.js +0 -4
- package/build/erc/pin_compatibility_matrix/pin_error.d.ts +0 -7
- package/build/erc/pin_compatibility_matrix/pin_error.d.ts.map +0 -1
- package/build/erc/pin_compatibility_matrix/pin_error.js +0 -7
- package/build/erc/pin_compatibility_matrix/tester.d.ts +0 -9
- package/build/erc/pin_compatibility_matrix/tester.d.ts.map +0 -1
- package/build/erc/pin_compatibility_matrix/tester.js +0 -22
- package/build/graphics/index.d.ts +0 -3
- package/build/graphics/index.d.ts.map +0 -1
- package/build/graphics/index.js +0 -2
- package/build/graphics/maker/index.d.ts +0 -4
- package/build/graphics/maker/index.d.ts.map +0 -1
- package/build/graphics/maker/index.js +0 -3
- package/build/graphics/maker/maker_base.d.ts +0 -35
- package/build/graphics/maker/maker_base.d.ts.map +0 -1
- package/build/graphics/maker/maker_base.js +0 -0
- package/build/graphics/maker/maker_type.d.ts +0 -10
- package/build/graphics/maker/maker_type.d.ts.map +0 -1
- package/build/graphics/maker/maker_type.js +0 -10
- package/build/graphics/maker/sch_maker.d.ts +0 -5
- package/build/graphics/maker/sch_maker.d.ts.map +0 -1
- package/build/graphics/maker/sch_maker.js +0 -0
- package/build/graphics/sch_erc_item.d.ts +0 -28
- package/build/graphics/sch_erc_item.d.ts.map +0 -1
- package/build/graphics/sch_erc_item.js +0 -0
- package/build/index.d.ts +0 -6
- package/build/index.d.ts.map +0 -1
- package/build/index.js +0 -5
- package/build/report/erc_report.d.ts +0 -16
- package/build/report/erc_report.d.ts.map +0 -1
- package/build/report/erc_report.js +0 -15
- package/build/report/erc_reporter.d.ts +0 -88
- package/build/report/erc_reporter.d.ts.map +0 -1
- package/build/report/erc_reporter.js +0 -87
- package/build/report/index.d.ts +0 -3
- package/build/report/index.d.ts.map +0 -1
- package/build/report/index.js +0 -2
- package/build/rule_check_item/erc_item.d.ts +0 -4
- package/build/rule_check_item/erc_item.d.ts.map +0 -1
- package/build/rule_check_item/erc_item.js +0 -0
- package/build/rule_check_item/index.d.ts +0 -3
- package/build/rule_check_item/index.d.ts.map +0 -1
- package/build/rule_check_item/index.js +0 -2
- package/build/rule_check_item/rc_item.d.ts +0 -33
- package/build/rule_check_item/rc_item.d.ts.map +0 -1
- package/build/rule_check_item/rc_item.js +0 -0
- package/build/tester/erc_tester.d.ts +0 -18
- package/build/tester/erc_tester.d.ts.map +0 -1
- package/build/tester/erc_tester.js +0 -28
- package/build/tester/graph/connection_graphs_builder.d.ts +0 -22
- package/build/tester/graph/connection_graphs_builder.d.ts.map +0 -1
- package/build/tester/graph/connection_graphs_builder.js +0 -99
- package/build/tester/graph/graph_erc.d.ts +0 -16
- package/build/tester/graph/graph_erc.d.ts.map +0 -1
- package/build/tester/graph/graph_erc.js +0 -11
- package/build/tester/graph/index.d.ts +0 -4
- package/build/tester/graph/index.d.ts.map +0 -1
- package/build/tester/graph/index.js +0 -3
- package/build/tester/graph/ir_graph_converter.d.ts +0 -30
- package/build/tester/graph/ir_graph_converter.d.ts.map +0 -1
- package/build/tester/graph/ir_graph_converter.js +0 -138
- package/build/tester/index.d.ts +0 -3
- package/build/tester/index.d.ts.map +0 -1
- package/build/tester/index.js +0 -2
- package/build/tsconfig.build.tsbuildinfo +0 -1
- package/build/utils/get_dependent_modules_definition.d.ts +0 -4
- package/build/utils/get_dependent_modules_definition.d.ts.map +0 -1
- package/build/utils/get_dependent_modules_definition.js +0 -18
- package/build/utils/index.d.ts +0 -2
- package/build/utils/index.d.ts.map +0 -1
- package/build/utils/index.js +0 -1
|
@@ -1,994 +0,0 @@
|
|
|
1
|
-
// add the other testers following the AnalogLinkTester
|
|
2
|
-
import { PortType, all_range_are_defined, contains, filter_defined_range, hull, interests, intersection, r_div, range_is_defined, sum, } from '@modular-circuit/electronics-model';
|
|
3
|
-
import { CompositePortLinkTesterBase, LinkTesterBase } from './link_tester_base';
|
|
4
|
-
import { PP_DUPLICATED_SOURCES, PP_ILLEGAL_CONNECTION, PP_IMPEDANCE_SIGNAL_INTEGRITY, PP_INCOMPATIBLE_DIGITAL_THRESHOLDS, PP_INCOMPATIBLE_SIGNAL_LEVELS, PP_INCOMPATIBLE_VOLTAGE_LEVELS, PP_NOT_DRIVEN, PP_OVER_DRIVEN, PP_REQUIRES_CONNECTED_SOURCE_OR_BIDIR, PP_SIGNAL_LEVELS_NOT_CONTAINED_WITHIN_VOLTAGE, } from '../../../report';
|
|
5
|
-
/**
|
|
6
|
-
self.assign(self.sink_impedance, 1 / (1 / self.sinks.map_extract(lambda x: x.impedance)).sum())
|
|
7
|
-
self.require(self.source.impedance.upper() <= self.sink_impedance.lower() * 0.1) # about 10x for signal integrity
|
|
8
|
-
self.assign(self.current_drawn, self.sinks.sum(lambda x: x.current_draw))
|
|
9
|
-
|
|
10
|
-
self.assign(self.voltage_limits, self.sinks.intersection(lambda x: x.voltage_limits))
|
|
11
|
-
self.require(self.voltage_limits.contains(self.voltage), "incompatible voltage levels")
|
|
12
|
-
self.assign(self.signal_limits, self.sinks.intersection(lambda x: x.signal_limits))
|
|
13
|
-
self.require(self.voltage.contains(self.signal), "signal levels not contained within voltage")
|
|
14
|
-
self.require(self.signal_limits.contains(self.signal), "incompatible signal levels")
|
|
15
|
-
self.assign(self.current_limits, self.source.current_limits)
|
|
16
|
-
self.require(self.current_limits.contains(self.current_drawn), "overcurrent")
|
|
17
|
-
*/
|
|
18
|
-
export class AnalogLinkTester extends LinkTesterBase {
|
|
19
|
-
init_link() {
|
|
20
|
-
const sources = [];
|
|
21
|
-
const sinks = [];
|
|
22
|
-
for (const v of this.ports) {
|
|
23
|
-
switch (v.type) {
|
|
24
|
-
case PortType.AnalogSource: {
|
|
25
|
-
sources.push(v);
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
|
-
case PortType.AnalogSink: {
|
|
29
|
-
sinks.push(v);
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
if (sources.length === 0) {
|
|
35
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'Requires a connected analog source'));
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
if (sources.length > 1) {
|
|
39
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'Multiple analog sources are not allowed'));
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
this.link = {
|
|
43
|
-
source: sources[0],
|
|
44
|
-
sinks,
|
|
45
|
-
};
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
check_parameter_propagation() {
|
|
49
|
-
if (!this.link)
|
|
50
|
-
return;
|
|
51
|
-
const source = this.link.source;
|
|
52
|
-
const sinks = this.link.sinks;
|
|
53
|
-
const source_id = this.ctx.port_id.get(source);
|
|
54
|
-
if (range_is_defined(source.impedance)) {
|
|
55
|
-
const all_sinks_impedance = filter_defined_range(sinks.map((v) => v.impedance));
|
|
56
|
-
if (all_sinks_impedance.length > 0) {
|
|
57
|
-
const sink_impedance = r_div(sum(all_sinks_impedance.map((v) => r_div(v, 1))), 1);
|
|
58
|
-
if (source.impedance.upper > sink_impedance.lower * 0.1) {
|
|
59
|
-
this.ctx.report.erc_errors.push(PP_IMPEDANCE_SIGNAL_INTEGRITY(this.all_port_ids));
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (range_is_defined(source.voltage_out)) {
|
|
64
|
-
const all_voltage_limits = filter_defined_range(sinks.map((v) => v.voltage_limits));
|
|
65
|
-
if (all_voltage_limits.length > 0) {
|
|
66
|
-
const voltage_limits = intersection(all_voltage_limits);
|
|
67
|
-
if (!interests(voltage_limits, source.voltage_out)) {
|
|
68
|
-
this.ctx.report.erc_errors.push(PP_INCOMPATIBLE_VOLTAGE_LEVELS(source_id));
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (all_range_are_defined(source.signal_out, source.voltage_out)) {
|
|
73
|
-
if (!interests(source.voltage_out, source.signal_out)) {
|
|
74
|
-
this.ctx.report.erc_errors.push(PP_SIGNAL_LEVELS_NOT_CONTAINED_WITHIN_VOLTAGE(source_id));
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (range_is_defined(source.signal_out)) {
|
|
78
|
-
const all_sinks_signal_limits = filter_defined_range(sinks.map((v) => v.signal_limits));
|
|
79
|
-
if (all_sinks_signal_limits.length > 0) {
|
|
80
|
-
const signal_limits = intersection(all_sinks_signal_limits);
|
|
81
|
-
if (!interests(signal_limits, source.signal_out)) {
|
|
82
|
-
this.ctx.report.erc_errors.push(PP_INCOMPATIBLE_SIGNAL_LEVELS(source_id));
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
if (range_is_defined(source.current_limits)) {
|
|
87
|
-
const all_sinks_current_drawn = filter_defined_range(sinks.map((v) => v.current_drawn));
|
|
88
|
-
if (all_sinks_current_drawn.length > 0) {
|
|
89
|
-
const current_drawn = sum(all_sinks_current_drawn);
|
|
90
|
-
if (interests(current_drawn, source.current_limits)) {
|
|
91
|
-
this.ctx.report.erc_errors.push(PP_OVER_DRIVEN([source_id], 'current'));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
|
|
99
|
-
voltage_hull = self.bidirs.hull(lambda x: x.voltage_out)
|
|
100
|
-
voltage_hull = self.sources.any_connected().then_else(
|
|
101
|
-
voltage_hull.hull(self.sources.hull(lambda x: x.voltage_out)),
|
|
102
|
-
voltage_hull
|
|
103
|
-
)
|
|
104
|
-
self.assign(self.voltage, voltage_hull)
|
|
105
|
-
|
|
106
|
-
self.assign(self.voltage_limits,
|
|
107
|
-
self.sinks.intersection(lambda x: x.voltage_limits).intersect(self.bidirs.intersection(lambda x: x.voltage_limits))
|
|
108
|
-
)
|
|
109
|
-
self.require(self.voltage_limits.contains(self.voltage), "overvoltage")
|
|
110
|
-
|
|
111
|
-
self.assign(self.current_drawn,
|
|
112
|
-
self.sinks.sum(lambda x: x.current_draw) + self.bidirs.sum(lambda x: x.current_draw)
|
|
113
|
-
)
|
|
114
|
-
self.assign(self.current_limits,
|
|
115
|
-
self.sources.intersection(lambda x: x.current_limits)
|
|
116
|
-
.intersect(self.bidirs.intersection(lambda x: x.current_limits)))
|
|
117
|
-
self.require(self.current_limits.contains(self.current_drawn), "overcurrent")
|
|
118
|
-
|
|
119
|
-
self.assign(self.output_thresholds,
|
|
120
|
-
self.sources.intersection(lambda x: x.output_thresholds)
|
|
121
|
-
.intersect(self.bidirs.intersection(lambda x: x.output_thresholds),))
|
|
122
|
-
self.assign(self.input_thresholds,
|
|
123
|
-
self.sinks.hull(lambda x: x.input_thresholds).hull(self.bidirs.hull(lambda x: x.input_thresholds)),
|
|
124
|
-
)
|
|
125
|
-
self.require(self.output_thresholds.contains(self.input_thresholds), "incompatible digital thresholds")
|
|
126
|
-
|
|
127
|
-
self.require(self.sources.any_connected() | (self.bidirs.length() > 0),
|
|
128
|
-
"requires connected source or bidir")
|
|
129
|
-
|
|
130
|
-
# ensure both digital levels can be driven (but pull-up or -down only connections are allowed)
|
|
131
|
-
self.assign(self.pullup_capable,
|
|
132
|
-
self.sources.any(lambda x: x.pullup_capable) |
|
|
133
|
-
self.sinks.any(lambda x: x.pullup_capable) |
|
|
134
|
-
self.bidirs.any(lambda x: x.pullup_capable))
|
|
135
|
-
self.assign(self.pulldown_capable,
|
|
136
|
-
self.sources.any(lambda x: x.pulldown_capable) |
|
|
137
|
-
self.sinks.any(lambda x: x.pulldown_capable) |
|
|
138
|
-
self.bidirs.any(lambda x: x.pulldown_capable))
|
|
139
|
-
self.assign(self._has_low_signal_driver, # assumed bidirs are true directional drivers
|
|
140
|
-
self.bidirs.any_connected() | self.sources.any(lambda x: x.low_driver))
|
|
141
|
-
self.assign(self._has_high_signal_driver,
|
|
142
|
-
self.bidirs.any_connected() | self.sources.any(lambda x: x.high_driver))
|
|
143
|
-
|
|
144
|
-
is_bridged_internal = (self.sources.any(lambda x: x._bridged_internal) |
|
|
145
|
-
self.sinks.any(lambda x: x._bridged_internal) |
|
|
146
|
-
self.bidirs.any(lambda x: x._bridged_internal))
|
|
147
|
-
self.require(is_bridged_internal |
|
|
148
|
-
self._has_high_signal_driver.implies(self._has_low_signal_driver | self.pulldown_capable), "requires low driver or pulldown")
|
|
149
|
-
self.require(is_bridged_internal |
|
|
150
|
-
self._has_low_signal_driver.implies(self._has_high_signal_driver | self.pullup_capable), "requires high driver or pullup")
|
|
151
|
-
|
|
152
|
-
# when multiple sources, ensure they all drive only one signal direction (eg, open drain)
|
|
153
|
-
self.require((self.sources.count(lambda x: x.high_driver) > 1).implies(~self.sources.any(lambda x: x.low_driver)) &
|
|
154
|
-
(self.sources.count(lambda x: x.low_driver) > 1).implies(~self.sources.any(lambda x: x.high_driver)),
|
|
155
|
-
"conflicting source drivers")
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
*/
|
|
159
|
-
export class DigitalLinkTester extends LinkTesterBase {
|
|
160
|
-
init_link() {
|
|
161
|
-
const sinks = [];
|
|
162
|
-
const sources = [];
|
|
163
|
-
const bidirs = [];
|
|
164
|
-
for (const v of this.ports) {
|
|
165
|
-
switch (v.type) {
|
|
166
|
-
case PortType.DigitalSource: {
|
|
167
|
-
sources.push(v);
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
case PortType.DigitalSink: {
|
|
171
|
-
sinks.push(v);
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
|
-
case PortType.DigitalBidir: {
|
|
175
|
-
bidirs.push(v);
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
this.link = {
|
|
181
|
-
sources,
|
|
182
|
-
sinks,
|
|
183
|
-
bidirs,
|
|
184
|
-
};
|
|
185
|
-
return true;
|
|
186
|
-
}
|
|
187
|
-
check_parameter_propagation() {
|
|
188
|
-
if (!this.link)
|
|
189
|
-
return;
|
|
190
|
-
const sources = this.link.sources ?? [];
|
|
191
|
-
const sinks = this.link.sinks ?? [];
|
|
192
|
-
const bidirs = this.link.bidirs ?? [];
|
|
193
|
-
const all_defined_voltage = filter_defined_range(...bidirs.map((v) => v.voltage_out), ...sources.map((v) => v.voltage_out));
|
|
194
|
-
if (all_defined_voltage.length > 0) {
|
|
195
|
-
const voltage = hull(all_defined_voltage);
|
|
196
|
-
const all_defined_voltage_limits = filter_defined_range(sinks.map((v) => v.voltage_limits));
|
|
197
|
-
if (all_defined_voltage_limits.length > 0) {
|
|
198
|
-
const voltage_limits = intersection(all_defined_voltage_limits);
|
|
199
|
-
if (!contains(voltage_limits, voltage)) {
|
|
200
|
-
this.ctx.report.erc_errors.push(PP_OVER_DRIVEN(this.all_port_ids, 'voltage'));
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
const all_defined_current_limits = filter_defined_range(...bidirs.map((v) => v.current_limits), ...sources.map((v) => v.current_limits));
|
|
205
|
-
if (all_defined_current_limits.length > 0) {
|
|
206
|
-
const current_limits = sum(all_defined_current_limits);
|
|
207
|
-
const all_defined_current_drawn = filter_defined_range(sinks.map((v) => v.current_drawn));
|
|
208
|
-
if (all_defined_current_drawn.length > 0) {
|
|
209
|
-
const current_drawn = sum(all_defined_current_drawn);
|
|
210
|
-
if (interests(current_drawn, current_limits)) {
|
|
211
|
-
this.ctx.report.erc_errors.push(PP_OVER_DRIVEN(this.all_port_ids, 'current'));
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
const all_defined_output_thresholds = filter_defined_range(...bidirs.map((v) => v.output_thresholds), ...sources.map((v) => v.output_thresholds));
|
|
216
|
-
if (all_defined_output_thresholds.length > 0) {
|
|
217
|
-
const output_thresholds = intersection(all_defined_output_thresholds);
|
|
218
|
-
const all_defined_input_thresholds = filter_defined_range(sinks.map((v) => v.input_thresholds));
|
|
219
|
-
if (all_defined_input_thresholds.length > 0) {
|
|
220
|
-
const input_thresholds = hull(all_defined_input_thresholds);
|
|
221
|
-
if (!contains(output_thresholds, input_thresholds)) {
|
|
222
|
-
this.ctx.report.erc_errors.push(PP_INCOMPATIBLE_DIGITAL_THRESHOLDS(this.all_port_ids));
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
if (!sources.length && !bidirs.length) {
|
|
227
|
-
this.ctx.report.erc_errors.push(PP_REQUIRES_CONNECTED_SOURCE_OR_BIDIR(this.all_port_ids));
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
self.assign(self.voltage, self.source.voltage_out)
|
|
233
|
-
self.assign(self.voltage_limits, self.sinks.intersection(lambda x: x.voltage_limits))
|
|
234
|
-
self.require(self.voltage_limits.contains(self.voltage), "overvoltage")
|
|
235
|
-
self.assign(self.current_limits, self.source.current_limits)
|
|
236
|
-
|
|
237
|
-
self.assign(self.current_drawn, self.sinks.sum(lambda x: x.current_draw))
|
|
238
|
-
self.require(self.current_limits.contains(self.current_drawn), "overcurrent")
|
|
239
|
-
*/
|
|
240
|
-
export class VoltageLinkTester extends LinkTesterBase {
|
|
241
|
-
check_parameter_propagation() {
|
|
242
|
-
const source = this.link.source;
|
|
243
|
-
const sinks = this.link.sinks;
|
|
244
|
-
if (range_is_defined(source.voltage_out)) {
|
|
245
|
-
const all_voltage_limits = filter_defined_range(sinks.map((v) => v.voltage_limits));
|
|
246
|
-
if (all_voltage_limits.length > 0) {
|
|
247
|
-
const voltage_limits = intersection(all_voltage_limits);
|
|
248
|
-
if (!interests(voltage_limits, source.voltage_out)) {
|
|
249
|
-
this.ctx.report.erc_errors.push(PP_OVER_DRIVEN(this.all_port_ids, 'voltage'));
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
if (range_is_defined(source.current_limits)) {
|
|
254
|
-
const all_sinks_current_drawn = filter_defined_range(sinks.map((v) => v.current_drawn));
|
|
255
|
-
if (all_sinks_current_drawn.length > 0) {
|
|
256
|
-
const current_drawn = sum(all_sinks_current_drawn);
|
|
257
|
-
if (interests(current_drawn, source.current_limits)) {
|
|
258
|
-
this.ctx.report.erc_errors.push(PP_OVER_DRIVEN(this.all_port_ids, 'current'));
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
init_link() {
|
|
264
|
-
const sources = [];
|
|
265
|
-
const sinks = [];
|
|
266
|
-
for (const v of this.ports) {
|
|
267
|
-
switch (v.type) {
|
|
268
|
-
case PortType.VoltageSource: {
|
|
269
|
-
sources.push(v);
|
|
270
|
-
break;
|
|
271
|
-
}
|
|
272
|
-
case PortType.VoltageSink: {
|
|
273
|
-
sinks.push(v);
|
|
274
|
-
break;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
if (sources.length === 0) {
|
|
279
|
-
this.ctx.report.erc_errors.push(PP_NOT_DRIVEN(this.all_port_ids));
|
|
280
|
-
return false;
|
|
281
|
-
}
|
|
282
|
-
if (sources.length > 1) {
|
|
283
|
-
this.ctx.report.erc_errors.push(PP_DUPLICATED_SOURCES(this.all_port_ids));
|
|
284
|
-
return false;
|
|
285
|
-
}
|
|
286
|
-
this.link = {
|
|
287
|
-
source: sources[0],
|
|
288
|
-
sinks,
|
|
289
|
-
};
|
|
290
|
-
return true;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
/*
|
|
294
|
-
self.description = DescriptionString(
|
|
295
|
-
"<b>voltage</b>: ", DescriptionString.FormatUnits(self.voltage, "V"),
|
|
296
|
-
" <b>of limits</b>: ", DescriptionString.FormatUnits(self.voltage_limits, "V"))
|
|
297
|
-
|
|
298
|
-
self.assign(self.voltage, self.ref.is_connected().then_else(
|
|
299
|
-
self.ref.voltage_out, (0, 0)*Volt
|
|
300
|
-
))
|
|
301
|
-
self.assign(self.voltage_limits, self.gnds.intersection(lambda x: x.voltage_limits))
|
|
302
|
-
self.require(self.voltage_limits.contains(self.voltage), "overvoltage")
|
|
303
|
-
*/
|
|
304
|
-
export class GroundLinkTester extends LinkTesterBase {
|
|
305
|
-
check_parameter_propagation() {
|
|
306
|
-
if (!this.link)
|
|
307
|
-
return;
|
|
308
|
-
const ref = this.link.ref;
|
|
309
|
-
const gnds = this.link.gnds;
|
|
310
|
-
let voltage = ref?.voltage_out;
|
|
311
|
-
if (!voltage || !range_is_defined(voltage))
|
|
312
|
-
voltage = { lower: 0, upper: 0 };
|
|
313
|
-
const all_defined_voltage_limits = filter_defined_range(gnds.map((v) => v.voltage_limits));
|
|
314
|
-
if (all_defined_voltage_limits.length > 0) {
|
|
315
|
-
const voltage_limits = intersection(all_defined_voltage_limits);
|
|
316
|
-
if (!interests(voltage_limits, voltage)) {
|
|
317
|
-
this.ctx.report.erc_errors.push(PP_OVER_DRIVEN(this.all_port_ids, 'voltage'));
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
init_link() {
|
|
322
|
-
const refs = [];
|
|
323
|
-
const gnds = [];
|
|
324
|
-
for (const v of this.ports) {
|
|
325
|
-
switch (v.type) {
|
|
326
|
-
case PortType.GroundReference: {
|
|
327
|
-
refs.push(v);
|
|
328
|
-
break;
|
|
329
|
-
}
|
|
330
|
-
case PortType.Ground: {
|
|
331
|
-
gnds.push(v);
|
|
332
|
-
break;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
if (refs.length > 1) {
|
|
337
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'Cannot connect multiple ground references to a ground.'));
|
|
338
|
-
return false;
|
|
339
|
-
}
|
|
340
|
-
this.link = {
|
|
341
|
-
ref: refs[0],
|
|
342
|
-
gnds,
|
|
343
|
-
};
|
|
344
|
-
return true;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
self.txd = self.connect(self.controller.txd, self.transceiver.txd, self.passive.map_extract(lambda port: port.txd),
|
|
349
|
-
flatten=True)
|
|
350
|
-
self.rxd = self.connect(self.controller.rxd, self.transceiver.rxd, self.passive.map_extract(lambda port: port.rxd),
|
|
351
|
-
flatten=True)
|
|
352
|
-
*/
|
|
353
|
-
export class CanLogicLinkTester extends CompositePortLinkTesterBase {
|
|
354
|
-
check_parameter_propagation() {
|
|
355
|
-
if (!this.link)
|
|
356
|
-
return;
|
|
357
|
-
const txd_tester = new DigitalLinkTester(this.ctx, [
|
|
358
|
-
this.link.controller.txd,
|
|
359
|
-
this.link.transceiver.rxd,
|
|
360
|
-
...this.link.passive.map((port) => port.rxd),
|
|
361
|
-
]);
|
|
362
|
-
const rxd_tester = new DigitalLinkTester(this.ctx, [
|
|
363
|
-
this.link.controller.rxd,
|
|
364
|
-
this.link.transceiver.txd,
|
|
365
|
-
...this.link.passive.map((port) => port.txd),
|
|
366
|
-
]);
|
|
367
|
-
for (const tst of [txd_tester, rxd_tester])
|
|
368
|
-
tst.test();
|
|
369
|
-
}
|
|
370
|
-
init_link() {
|
|
371
|
-
const controllers = [];
|
|
372
|
-
const transceivers = [];
|
|
373
|
-
const passive = [];
|
|
374
|
-
for (const v of this.ports) {
|
|
375
|
-
switch (v.type) {
|
|
376
|
-
case PortType.CanControllerPort: {
|
|
377
|
-
controllers.push(v);
|
|
378
|
-
break;
|
|
379
|
-
}
|
|
380
|
-
case PortType.CanTransceiverPort: {
|
|
381
|
-
transceivers.push(v);
|
|
382
|
-
break;
|
|
383
|
-
}
|
|
384
|
-
case PortType.CanPassivePort: {
|
|
385
|
-
passive.push(v);
|
|
386
|
-
break;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
if (controllers.length !== 1) {
|
|
391
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one controller port.'));
|
|
392
|
-
return false;
|
|
393
|
-
}
|
|
394
|
-
if (transceivers.length !== 1) {
|
|
395
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one transceiver port.'));
|
|
396
|
-
return false;
|
|
397
|
-
}
|
|
398
|
-
this.link = {
|
|
399
|
-
controller: controllers[0],
|
|
400
|
-
transceiver: transceivers[0],
|
|
401
|
-
passive,
|
|
402
|
-
};
|
|
403
|
-
return true;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
|
-
self.canh = self.connect(self.nodes.map_extract(lambda node: node.canh),
|
|
408
|
-
flatten=True)
|
|
409
|
-
self.canl = self.connect(self.nodes.map_extract(lambda node: node.canl),
|
|
410
|
-
flatten=True)
|
|
411
|
-
*/
|
|
412
|
-
export class CanDiffLinkTester extends CompositePortLinkTesterBase {
|
|
413
|
-
check_parameter_propagation() {
|
|
414
|
-
if (!this.link)
|
|
415
|
-
return;
|
|
416
|
-
const canh_tester = new DigitalLinkTester(this.ctx, this.link.nodes.map((node) => node.canh));
|
|
417
|
-
const canl_tester = new DigitalLinkTester(this.ctx, this.link.nodes.map((node) => node.canl));
|
|
418
|
-
for (const tst of [canh_tester, canl_tester])
|
|
419
|
-
tst.test();
|
|
420
|
-
}
|
|
421
|
-
init_link() {
|
|
422
|
-
const nodes = [];
|
|
423
|
-
for (const v of this.ports) {
|
|
424
|
-
if (v.type === PortType.CanDiffPort) {
|
|
425
|
-
nodes.push(v);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
if (nodes.length === 0) {
|
|
429
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'Requires at least one CAN differential port'));
|
|
430
|
-
return false;
|
|
431
|
-
}
|
|
432
|
-
this.link = {
|
|
433
|
-
nodes,
|
|
434
|
-
};
|
|
435
|
-
return true;
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
self.require(self.driver.frequency_limits.contains(self.frequency))
|
|
440
|
-
|
|
441
|
-
self.xi = self.connect(self.driver.xtal_in, self.crystal.xtal_in)
|
|
442
|
-
self.xo = self.connect(self.driver.xtal_out, self.crystal.xtal_out)
|
|
443
|
-
*/
|
|
444
|
-
export class CrystalLinkTester extends CompositePortLinkTesterBase {
|
|
445
|
-
check_parameter_propagation() {
|
|
446
|
-
if (!this.link)
|
|
447
|
-
return;
|
|
448
|
-
const driver = this.link.driver;
|
|
449
|
-
const crystal = this.link.crystal;
|
|
450
|
-
if (all_range_are_defined(driver.frequency_limits, crystal.frequency)) {
|
|
451
|
-
if (!contains(driver.frequency_limits, crystal.frequency)) {
|
|
452
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'Frequency out of range'));
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
init_link() {
|
|
457
|
-
const drivers = [];
|
|
458
|
-
const crystals = [];
|
|
459
|
-
for (const v of this.ports) {
|
|
460
|
-
switch (v.type) {
|
|
461
|
-
case PortType.CrystalDriver: {
|
|
462
|
-
drivers.push(v);
|
|
463
|
-
break;
|
|
464
|
-
}
|
|
465
|
-
case PortType.CrystalPort: {
|
|
466
|
-
crystals.push(v);
|
|
467
|
-
break;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
if (drivers.length !== 1) {
|
|
472
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one crystal driver port.'));
|
|
473
|
-
return false;
|
|
474
|
-
}
|
|
475
|
-
if (crystals.length !== 1) {
|
|
476
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one crystal port.'));
|
|
477
|
-
return false;
|
|
478
|
-
}
|
|
479
|
-
this.link = {
|
|
480
|
-
driver: drivers[0],
|
|
481
|
-
crystal: crystals[0],
|
|
482
|
-
};
|
|
483
|
-
return true;
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
/**
|
|
487
|
-
self.swdio = self.connect(self.host.swdio, self.device.swdio, self.pull.map_extract(lambda port: port.swdio),
|
|
488
|
-
flatten=True)
|
|
489
|
-
self.swclk = self.connect(self.host.swclk, self.device.swclk, self.pull.map_extract(lambda port: port.swclk),
|
|
490
|
-
flatten=True)
|
|
491
|
-
*/
|
|
492
|
-
export class SwdLinkTester extends CompositePortLinkTesterBase {
|
|
493
|
-
check_parameter_propagation() {
|
|
494
|
-
if (!this.link)
|
|
495
|
-
return;
|
|
496
|
-
const swdio_tester = new DigitalLinkTester(this.ctx, [
|
|
497
|
-
this.link.host.swdio,
|
|
498
|
-
this.link.device.swdio,
|
|
499
|
-
...this.link.pull.map((port) => port.swdio),
|
|
500
|
-
]);
|
|
501
|
-
const swclk_tester = new DigitalLinkTester(this.ctx, [
|
|
502
|
-
this.link.host.swclk,
|
|
503
|
-
this.link.device.swclk,
|
|
504
|
-
...this.link.pull.map((port) => port.swclk),
|
|
505
|
-
]);
|
|
506
|
-
for (const tst of [swdio_tester, swclk_tester])
|
|
507
|
-
tst.test();
|
|
508
|
-
}
|
|
509
|
-
init_link() {
|
|
510
|
-
const hosts = [];
|
|
511
|
-
const devices = [];
|
|
512
|
-
const pull = [];
|
|
513
|
-
for (const v of this.ports) {
|
|
514
|
-
switch (v.type) {
|
|
515
|
-
case PortType.SwdHostPort: {
|
|
516
|
-
hosts.push(v);
|
|
517
|
-
break;
|
|
518
|
-
}
|
|
519
|
-
case PortType.SwdTargetPort: {
|
|
520
|
-
devices.push(v);
|
|
521
|
-
break;
|
|
522
|
-
}
|
|
523
|
-
case PortType.SwdPullPort: {
|
|
524
|
-
pull.push(v);
|
|
525
|
-
break;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
if (hosts.length !== 1) {
|
|
530
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one SWD host port.'));
|
|
531
|
-
return false;
|
|
532
|
-
}
|
|
533
|
-
if (devices.length !== 1) {
|
|
534
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one SWD target port.'));
|
|
535
|
-
return false;
|
|
536
|
-
}
|
|
537
|
-
this.link = {
|
|
538
|
-
host: hosts[0],
|
|
539
|
-
device: devices[0],
|
|
540
|
-
pull,
|
|
541
|
-
};
|
|
542
|
-
return true;
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
/**
|
|
546
|
-
self.require(self.pull.any_connected() | self.controller.has_pullup)
|
|
547
|
-
self.require(self.pull.length() <= 1, "at most one pullup")
|
|
548
|
-
self.require(self.addresses.all_unique(), "conflicting addresses on I2C bus")
|
|
549
|
-
self.scl = self.connect(self.pull.map_extract(lambda device: device.scl),
|
|
550
|
-
self.controller.scl, self.targets.map_extract(lambda device: device.scl),
|
|
551
|
-
flatten=True)
|
|
552
|
-
self.sda = self.connect(self.pull.map_extract(lambda device: device.sda),
|
|
553
|
-
self.controller.sda, self.targets.map_extract(lambda device: device.sda),
|
|
554
|
-
flatten=True)
|
|
555
|
-
*/
|
|
556
|
-
export class I2cLinkTester extends CompositePortLinkTesterBase {
|
|
557
|
-
check_parameter_propagation() {
|
|
558
|
-
if (!this.link)
|
|
559
|
-
return;
|
|
560
|
-
const scl_tester = new DigitalLinkTester(this.ctx, [
|
|
561
|
-
...this.link.pull.map((device) => device.scl),
|
|
562
|
-
this.link.controller.scl,
|
|
563
|
-
...this.link.targets.map((device) => device.scl),
|
|
564
|
-
]);
|
|
565
|
-
const sda_tester = new DigitalLinkTester(this.ctx, [
|
|
566
|
-
...this.link.pull.map((device) => device.sda),
|
|
567
|
-
this.link.controller.sda,
|
|
568
|
-
...this.link.targets.map((device) => device.sda),
|
|
569
|
-
]);
|
|
570
|
-
for (const tst of [scl_tester, sda_tester])
|
|
571
|
-
tst.test();
|
|
572
|
-
if (!this.link.pull.length && !this.link.controller.has_pullup) {
|
|
573
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'Requires at least one pullup'));
|
|
574
|
-
}
|
|
575
|
-
if (this.link.pull.length > 1) {
|
|
576
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'At most one pullup allowed'));
|
|
577
|
-
}
|
|
578
|
-
const addresses = this.link.targets.map((target) => target.addresses);
|
|
579
|
-
if (new Set(addresses).size !== addresses.length) {
|
|
580
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'Conflicting addresses on I2C bus'));
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
init_link() {
|
|
584
|
-
const pull = [];
|
|
585
|
-
const controllers = [];
|
|
586
|
-
const targets = [];
|
|
587
|
-
for (const v of this.ports) {
|
|
588
|
-
switch (v.type) {
|
|
589
|
-
case PortType.I2cPullupPort: {
|
|
590
|
-
pull.push(v);
|
|
591
|
-
break;
|
|
592
|
-
}
|
|
593
|
-
case PortType.I2cController: {
|
|
594
|
-
controllers.push(v);
|
|
595
|
-
break;
|
|
596
|
-
}
|
|
597
|
-
case PortType.I2cTarget: {
|
|
598
|
-
targets.push(v);
|
|
599
|
-
break;
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
if (controllers.length !== 1) {
|
|
604
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one I2C controller port.'));
|
|
605
|
-
return false;
|
|
606
|
-
}
|
|
607
|
-
if (targets.length === 0) {
|
|
608
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be at least one I2C target port.'));
|
|
609
|
-
return false;
|
|
610
|
-
}
|
|
611
|
-
this.link = {
|
|
612
|
-
pull,
|
|
613
|
-
controller: controllers[0],
|
|
614
|
-
targets,
|
|
615
|
-
};
|
|
616
|
-
return true;
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
/**
|
|
620
|
-
self.sck = self.connect(self.controller.sck, self.target_receiver.sck)
|
|
621
|
-
self.ws = self.connect(self.controller.ws, self.target_receiver.ws)
|
|
622
|
-
self.sd = self.connect(self.controller.sd, self.target_receiver.sd)
|
|
623
|
-
|
|
624
|
-
*/
|
|
625
|
-
export class I2sLinkTester extends CompositePortLinkTesterBase {
|
|
626
|
-
check_parameter_propagation() {
|
|
627
|
-
if (!this.link)
|
|
628
|
-
return;
|
|
629
|
-
const controller = this.link.controller;
|
|
630
|
-
const target_receiver = this.link.target_receiver;
|
|
631
|
-
const sck_tester = new DigitalLinkTester(this.ctx, [controller.sck, target_receiver.sck]);
|
|
632
|
-
const ws_tester = new DigitalLinkTester(this.ctx, [controller.ws, target_receiver.ws]);
|
|
633
|
-
const sd_tester = new DigitalLinkTester(this.ctx, [controller.sd, target_receiver.sd]);
|
|
634
|
-
for (const tst of [sck_tester, ws_tester, sd_tester])
|
|
635
|
-
tst.test();
|
|
636
|
-
}
|
|
637
|
-
init_link() {
|
|
638
|
-
const controllers = [];
|
|
639
|
-
const target_receivers = [];
|
|
640
|
-
for (const v of this.ports) {
|
|
641
|
-
switch (v.type) {
|
|
642
|
-
case PortType.I2sController: {
|
|
643
|
-
controllers.push(v);
|
|
644
|
-
break;
|
|
645
|
-
}
|
|
646
|
-
case PortType.I2sTargetReceiver: {
|
|
647
|
-
target_receivers.push(v);
|
|
648
|
-
break;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
if (controllers.length !== 1) {
|
|
653
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one I2S controller port.'));
|
|
654
|
-
return false;
|
|
655
|
-
}
|
|
656
|
-
if (target_receivers.length !== 1) {
|
|
657
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one I2S target receiver port.'));
|
|
658
|
-
return false;
|
|
659
|
-
}
|
|
660
|
-
this.link = {
|
|
661
|
-
controller: controllers[0],
|
|
662
|
-
target_receiver: target_receivers[0],
|
|
663
|
-
};
|
|
664
|
-
return true;
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
/**
|
|
668
|
-
self.sck = self.connect(self.controller.sck, self.peripherals.map_extract(lambda device: device.sck),
|
|
669
|
-
flatten=True)
|
|
670
|
-
self.miso = self.connect(self.controller.miso, self.peripherals.map_extract(lambda device: device.miso),
|
|
671
|
-
flatten=True)
|
|
672
|
-
self.mosi = self.connect(self.controller.mosi, self.peripherals.map_extract(lambda device: device.mosi),
|
|
673
|
-
flatten=True)
|
|
674
|
-
|
|
675
|
-
*/
|
|
676
|
-
export class SpiLinkTester extends CompositePortLinkTesterBase {
|
|
677
|
-
check_parameter_propagation() {
|
|
678
|
-
if (!this.link)
|
|
679
|
-
return;
|
|
680
|
-
const controller = this.link.controller;
|
|
681
|
-
const peripherals = this.link.peripherals;
|
|
682
|
-
const sck_tester = new DigitalLinkTester(this.ctx, [controller.sck, ...peripherals.map((device) => device.sck)]);
|
|
683
|
-
const miso_tester = new DigitalLinkTester(this.ctx, [controller.miso, ...peripherals.map((device) => device.miso)]);
|
|
684
|
-
const mosi_tester = new DigitalLinkTester(this.ctx, [controller.mosi, ...peripherals.map((device) => device.mosi)]);
|
|
685
|
-
for (const tst of [sck_tester, miso_tester, mosi_tester])
|
|
686
|
-
tst.test();
|
|
687
|
-
}
|
|
688
|
-
init_link() {
|
|
689
|
-
const controllers = [];
|
|
690
|
-
const peripherals = [];
|
|
691
|
-
for (const v of this.ports) {
|
|
692
|
-
switch (v.type) {
|
|
693
|
-
case PortType.SpiController: {
|
|
694
|
-
controllers.push(v);
|
|
695
|
-
break;
|
|
696
|
-
}
|
|
697
|
-
case PortType.SpiPeripheral: {
|
|
698
|
-
peripherals.push(v);
|
|
699
|
-
break;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
if (controllers.length !== 1) {
|
|
704
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one SPI controller port.'));
|
|
705
|
-
return false;
|
|
706
|
-
}
|
|
707
|
-
if (peripherals.length === 0) {
|
|
708
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be at least one SPI peripheral port.'));
|
|
709
|
-
return false;
|
|
710
|
-
}
|
|
711
|
-
this.link = {
|
|
712
|
-
controller: controllers[0],
|
|
713
|
-
peripherals,
|
|
714
|
-
};
|
|
715
|
-
return true;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
/**
|
|
719
|
-
self.a = self.connect(self.source.a, self.sink.a)
|
|
720
|
-
self.b = self.connect(self.source.b, self.sink.b)
|
|
721
|
-
*/
|
|
722
|
-
export class SpeakerLinkTester extends CompositePortLinkTesterBase {
|
|
723
|
-
check_parameter_propagation() {
|
|
724
|
-
if (!this.link)
|
|
725
|
-
return;
|
|
726
|
-
const a_tester = new AnalogLinkTester(this.ctx, [this.link.source.a, this.link.sink.a]);
|
|
727
|
-
const b_tester = new AnalogLinkTester(this.ctx, [this.link.source.b, this.link.sink.b]);
|
|
728
|
-
for (const tst of [a_tester, b_tester])
|
|
729
|
-
tst.test();
|
|
730
|
-
}
|
|
731
|
-
init_link() {
|
|
732
|
-
const sources = [];
|
|
733
|
-
const sinks = [];
|
|
734
|
-
for (const v of this.ports) {
|
|
735
|
-
switch (v.type) {
|
|
736
|
-
case PortType.SpeakerDriverPort: {
|
|
737
|
-
sources.push(v);
|
|
738
|
-
break;
|
|
739
|
-
}
|
|
740
|
-
case PortType.SpeakerPort: {
|
|
741
|
-
sinks.push(v);
|
|
742
|
-
break;
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
if (sources.length !== 1) {
|
|
747
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one speaker driver port.'));
|
|
748
|
-
return false;
|
|
749
|
-
}
|
|
750
|
-
if (sinks.length !== 1) {
|
|
751
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one speaker port.'));
|
|
752
|
-
return false;
|
|
753
|
-
}
|
|
754
|
-
this.link = {
|
|
755
|
-
source: sources[0],
|
|
756
|
-
sink: sinks[0],
|
|
757
|
-
};
|
|
758
|
-
return true;
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
/**
|
|
762
|
-
self.driver = self.Port(TouchDriver())
|
|
763
|
-
self.pad = self.Port(TouchPadPort())
|
|
764
|
-
*/
|
|
765
|
-
export class TouchLinkTester extends LinkTesterBase {
|
|
766
|
-
init_link() {
|
|
767
|
-
const drivers = [];
|
|
768
|
-
const pads = [];
|
|
769
|
-
for (const v of this.ports) {
|
|
770
|
-
switch (v.type) {
|
|
771
|
-
case PortType.TouchDriver: {
|
|
772
|
-
drivers.push(v);
|
|
773
|
-
break;
|
|
774
|
-
}
|
|
775
|
-
case PortType.TouchPadPort: {
|
|
776
|
-
pads.push(v);
|
|
777
|
-
break;
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
if (drivers.length !== 1) {
|
|
782
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one touch driver port.'));
|
|
783
|
-
return false;
|
|
784
|
-
}
|
|
785
|
-
if (pads.length !== 1) {
|
|
786
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one touch pad port.'));
|
|
787
|
-
return false;
|
|
788
|
-
}
|
|
789
|
-
this.link = {
|
|
790
|
-
driver: drivers[0],
|
|
791
|
-
pad: pads[0],
|
|
792
|
-
};
|
|
793
|
-
return true;
|
|
794
|
-
}
|
|
795
|
-
check_parameter_propagation() {
|
|
796
|
-
return;
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
/**
|
|
800
|
-
self.a_tx = self.connect(self.a.tx, self.b.rx)
|
|
801
|
-
self.b_tx = self.connect(self.b.tx, self.a.rx)
|
|
802
|
-
|
|
803
|
-
*/
|
|
804
|
-
export class UartLinkTester extends CompositePortLinkTesterBase {
|
|
805
|
-
check_parameter_propagation() {
|
|
806
|
-
if (!this.link)
|
|
807
|
-
return;
|
|
808
|
-
const tx_tester = new DigitalLinkTester(this.ctx, [this.link.a.tx, this.link.b.rx]);
|
|
809
|
-
const rx_tester = new DigitalLinkTester(this.ctx, [this.link.b.tx, this.link.a.rx]);
|
|
810
|
-
for (const tst of [tx_tester, rx_tester])
|
|
811
|
-
tst.test();
|
|
812
|
-
}
|
|
813
|
-
init_link() {
|
|
814
|
-
const ports = [];
|
|
815
|
-
for (const v of this.ports) {
|
|
816
|
-
if (v.type === PortType.UartPort) {
|
|
817
|
-
ports.push(v);
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
if (ports.length !== 2) {
|
|
821
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly two UART ports.'));
|
|
822
|
-
return false;
|
|
823
|
-
}
|
|
824
|
-
this.link = {
|
|
825
|
-
a: ports[0],
|
|
826
|
-
b: ports[1],
|
|
827
|
-
};
|
|
828
|
-
return true;
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
/**
|
|
832
|
-
|
|
833
|
-
self.d_P = self.connect(self.host.dp, self.device.dp, self.passive.map_extract(lambda port: port.dp),
|
|
834
|
-
flatten=True)
|
|
835
|
-
self.d_N = self.connect(self.host.dm, self.device.dm, self.passive.map_extract(lambda port: port.dm),
|
|
836
|
-
flatten=True)
|
|
837
|
-
*/
|
|
838
|
-
export class UsbLinkTester extends CompositePortLinkTesterBase {
|
|
839
|
-
check_parameter_propagation() {
|
|
840
|
-
if (!this.link)
|
|
841
|
-
return;
|
|
842
|
-
const dp_tester = new DigitalLinkTester(this.ctx, [
|
|
843
|
-
this.link.host.dp,
|
|
844
|
-
this.link.device.dp,
|
|
845
|
-
...this.link.passive.map((port) => port.dp),
|
|
846
|
-
]);
|
|
847
|
-
const dm_tester = new DigitalLinkTester(this.ctx, [
|
|
848
|
-
this.link.host.dm,
|
|
849
|
-
this.link.device.dm,
|
|
850
|
-
...this.link.passive.map((port) => port.dm),
|
|
851
|
-
]);
|
|
852
|
-
for (const tst of [dp_tester, dm_tester])
|
|
853
|
-
tst.test();
|
|
854
|
-
}
|
|
855
|
-
init_link() {
|
|
856
|
-
const hosts = [];
|
|
857
|
-
const devices = [];
|
|
858
|
-
const passive = [];
|
|
859
|
-
for (const v of this.ports) {
|
|
860
|
-
switch (v.type) {
|
|
861
|
-
case PortType.UsbHostPort: {
|
|
862
|
-
hosts.push(v);
|
|
863
|
-
break;
|
|
864
|
-
}
|
|
865
|
-
case PortType.UsbDevicePort: {
|
|
866
|
-
devices.push(v);
|
|
867
|
-
break;
|
|
868
|
-
}
|
|
869
|
-
case PortType.UsbPassivePort: {
|
|
870
|
-
passive.push(v);
|
|
871
|
-
break;
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
if (hosts.length !== 1) {
|
|
876
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one USB host port.'));
|
|
877
|
-
return false;
|
|
878
|
-
}
|
|
879
|
-
if (devices.length !== 1) {
|
|
880
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one USB device port.'));
|
|
881
|
-
return false;
|
|
882
|
-
}
|
|
883
|
-
this.link = {
|
|
884
|
-
host: hosts[0],
|
|
885
|
-
device: devices[0],
|
|
886
|
-
passive,
|
|
887
|
-
};
|
|
888
|
-
return true;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
/**
|
|
892
|
-
self.cc1 = self.Port(DigitalBidir(pullup_capable=pullup_capable))
|
|
893
|
-
self.cc2 = self.Port(DigitalBidir(pullup_capable=pullup_capable))
|
|
894
|
-
|
|
895
|
-
*/
|
|
896
|
-
export class UsbCcLinkTester extends CompositePortLinkTesterBase {
|
|
897
|
-
check_parameter_propagation() {
|
|
898
|
-
if (!this.link)
|
|
899
|
-
return;
|
|
900
|
-
const cc1_tester = new DigitalLinkTester(this.ctx, [this.link.a.cc1, this.link.b.cc1]);
|
|
901
|
-
const cc2_tester = new DigitalLinkTester(this.ctx, [this.link.a.cc2, this.link.b.cc2]);
|
|
902
|
-
for (const tst of [cc1_tester, cc2_tester])
|
|
903
|
-
tst.test();
|
|
904
|
-
}
|
|
905
|
-
init_link() {
|
|
906
|
-
const nodes = [];
|
|
907
|
-
for (const v of this.ports) {
|
|
908
|
-
if (v.type === PortType.UsbCcPort) {
|
|
909
|
-
nodes.push(v);
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
if (nodes.length !== 2) {
|
|
913
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly two CC ports.'));
|
|
914
|
-
return false;
|
|
915
|
-
}
|
|
916
|
-
this.link = {
|
|
917
|
-
a: nodes[0],
|
|
918
|
-
b: nodes[1],
|
|
919
|
-
};
|
|
920
|
-
return true;
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
/**
|
|
924
|
-
|
|
925
|
-
self.xclk = self.connect(self.host.xclk, self.cam.xclk)
|
|
926
|
-
self.pclk = self.connect(self.host.pclk, self.cam.pclk)
|
|
927
|
-
self.href = self.connect(self.host.href, self.cam.href)
|
|
928
|
-
self.vsync = self.connect(self.host.vsync, self.cam.vsync)
|
|
929
|
-
|
|
930
|
-
self.y0 = self.connect(self.host.y0, self.cam.y0)
|
|
931
|
-
self.y1 = self.connect(self.host.y1, self.cam.y1)
|
|
932
|
-
self.y2 = self.connect(self.host.y2, self.cam.y2)
|
|
933
|
-
self.y3 = self.connect(self.host.y3, self.cam.y3)
|
|
934
|
-
self.y4 = self.connect(self.host.y4, self.cam.y4)
|
|
935
|
-
self.y5 = self.connect(self.host.y5, self.cam.y5)
|
|
936
|
-
self.y6 = self.connect(self.host.y6, self.cam.y6)
|
|
937
|
-
self.y7 = self.connect(self.host.y7, self.cam.y7)
|
|
938
|
-
|
|
939
|
-
*/
|
|
940
|
-
export class Dvp8LinkTester extends CompositePortLinkTesterBase {
|
|
941
|
-
check_parameter_propagation() {
|
|
942
|
-
if (!this.link)
|
|
943
|
-
return;
|
|
944
|
-
const host = this.link.host;
|
|
945
|
-
const cam = this.link.cam;
|
|
946
|
-
const digitalLinks = [
|
|
947
|
-
[host.xclk, cam.xclk],
|
|
948
|
-
[host.pclk, cam.pclk],
|
|
949
|
-
[host.href, cam.href],
|
|
950
|
-
[host.vsync, cam.vsync],
|
|
951
|
-
[host.y0, cam.y0],
|
|
952
|
-
[host.y1, cam.y1],
|
|
953
|
-
[host.y2, cam.y2],
|
|
954
|
-
[host.y3, cam.y3],
|
|
955
|
-
[host.y4, cam.y4],
|
|
956
|
-
[host.y5, cam.y5],
|
|
957
|
-
[host.y6, cam.y6],
|
|
958
|
-
[host.y7, cam.y7],
|
|
959
|
-
];
|
|
960
|
-
for (const [hostPort, camPort] of digitalLinks) {
|
|
961
|
-
const tester = new DigitalLinkTester(this.ctx, [hostPort, camPort]);
|
|
962
|
-
tester.test();
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
init_link() {
|
|
966
|
-
const hosts = [];
|
|
967
|
-
const cams = [];
|
|
968
|
-
for (const v of this.ports) {
|
|
969
|
-
switch (v.type) {
|
|
970
|
-
case PortType.Dvp8Host: {
|
|
971
|
-
hosts.push(v);
|
|
972
|
-
break;
|
|
973
|
-
}
|
|
974
|
-
case PortType.Dvp8Camera: {
|
|
975
|
-
cams.push(v);
|
|
976
|
-
break;
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
if (hosts.length !== 1) {
|
|
981
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one DVP8 host port.'));
|
|
982
|
-
return false;
|
|
983
|
-
}
|
|
984
|
-
if (cams.length !== 1) {
|
|
985
|
-
this.ctx.report.erc_errors.push(PP_ILLEGAL_CONNECTION(this.all_port_ids, 'There must be exactly one DVP8 camera port.'));
|
|
986
|
-
return false;
|
|
987
|
-
}
|
|
988
|
-
this.link = {
|
|
989
|
-
host: hosts[0],
|
|
990
|
-
cam: cams[0],
|
|
991
|
-
};
|
|
992
|
-
return true;
|
|
993
|
-
}
|
|
994
|
-
}
|