rigless 0.3.0

Virtual hardware-in-the-loop runtime: run unmodified firmware on an emulated MCU with every peripheral, chip model and unit of virtual time in Rust, and a CPU core of its own that translates the firmware's instructions to host code
Documentation
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
// Copyright (c) 2026 Rigless Labs.
// SPDX-License-Identifier: MIT OR Apache-2.0
//! The STM32F427: its peripheral models, one module per generated register layout, and the MCU that
//! is made of them.
//!
//! A model is a building block. It's written against one register layout and knows nothing of any
//! part or board, so a second part of the family carrying the same layout has it for free. The
//! serial interface here is `Spi`, once, and this part holds six of it.
//!
//! [`Stm32f427`] is the whole microcontroller, and it holds its models as **fields**: `mcu.rcc`,
//! `mcu.spi[0]`, `mcu.tim[0]`. Reaching one is a field access that can't fail. It runs on its own,
//! with no board: [`Stm32f427::new`] gives a part fresh out of reset, running on its internal
//! oscillator, with nothing on its pins.
//!
//! A board is that MCU plus what a board adds. Nothing here knows about a board.

pub mod adc;
pub mod dbg;
pub mod dma;
pub mod flash;
pub mod gpio;
pub mod i2c;
pub mod iwdg;
pub mod otg;
pub mod pwr;
pub mod rcc;
pub mod rtc;
pub mod sdio;
pub mod spi;
pub mod tim;
pub mod usart;

use std::num::NonZeroU32;

use crate::device::{DeviceContext, ErasedDevice, RegisterFile, ResetCause};
use crate::mcu::{Mcu, Operate};
use crate::snapshot::store;
use crate::soc::{Bus, Error, FieldSpec, Layout};
use crate::time::VirtualNanos;

use crate::cpu::armv7m::Dwt;
use adc::{Adc, AdcCommon};
use dbg::Dbg;
use dma::{Dma, Wire};
use flash::Flash;
use gpio::Gpio;
use i2c::I2c;
use iwdg::Iwdg;
use otg::Otg;
use pwr::Pwr;
use rcc::Rcc;
use rtc::Rtc;
use sdio::Sdio;
use spi::Spi;
use tim::{Advanced, Counter, General, Tim};
use usart::{Kind, Usart};

/// What every bus runs at until a firmware touches the clock tree: the 16 MHz HSI, since `RCC_CFGR`
/// resets to zero and both peripheral prescalers are one. RM0090 rev 22 sections 6.2.2 and 6.3.3.
/// From the first write to the tree the clock controller drives what each bus comes to, and
/// `memory_map.rs` says which output each model that keeps time runs on.
const RESET_BUS_HZ: u64 = rcc::HSI_HZ;

/// One whole STM32F427: the bus, and a model for every instance this part has one for.
///
/// The fields are the part's inventory. Everything else about it (where each answers, what its
/// registers reset to, the corrections against RM0090) is the bus, built by
/// [`memory_map::builder`](super::memory_map::builder).
///
/// A part with no crystals, no rail and nothing on its buses: those are a board's, and a board
/// attaches them to these fields after the part is built.
#[derive(Debug)]
pub struct Stm32f427 {
    /// Reset and clock control, RM0090 rev 22 chapter 6.
    pub rcc: Rcc,
    /// The power controller, sections 5.5.1 and 5.5.2.
    pub pwr: Pwr,
    /// The eleven ports of chapter 8, in the order of [`PORTS`]. One model answers for all of them,
    /// because they're one layout and their reset values are the instances'.
    pub gpio: [Gpio; PORTS.len()],
    /// The six serial interfaces of chapter 28, in the manual's order. The two extended blocks the
    /// same chapter gives another job aren't among them. See [`SERIAL_INTERFACES`].
    pub spi: [Spi; SERIAL_INTERFACES.len()],
    /// The eight serial ports of chapter 30, in the order of [`SERIAL_PORTS`]: two layouts and one model,
    /// each answering from the table its entry names.
    pub usart: [Usart; SERIAL_PORTS.len()],
    /// The three inter-integrated circuit interfaces of chapter 27, one layout and one model,
    /// controller mode only, in the order of [`I2C_INTERFACES`].
    pub i2c: [I2c; I2C_INTERFACES.len()],
    /// The embedded flash memory interface of chapter 3.
    pub flash: Flash,
    /// The three converters of chapter 13, in the order of [`CONVERTERS`].
    pub adc: [Adc; CONVERTERS.len()],
    /// The converters' common block, which clocks them.
    pub adc_common: AdcCommon,
    /// The four general-purpose timers of chapter 18, in the order of [`TIMERS`]. They're two
    /// layouts and one model, counting in the width their table entry gives. Where the wide pair's
    /// two tables differ is the option register, and `tim.rs` records it.
    pub tim: [Tim<General>; TIMERS.len()],
    /// The two advanced-control timers of chapter 17, in the order of [`ADVANCED_TIMERS`]: the same model
    /// as the four above with the chapter's repetition counter, break, dead-time and complementary outputs.
    pub advanced: [Tim<Advanced>; ADVANCED_TIMERS.len()],
    /// The two direct memory access controllers of chapter 10, in the order of [`CONTROLLERS`].
    /// They're one layout and one model. What differs between them is the part's, and it's in that
    /// table.
    pub dma: [Dma; CONTROLLERS.len()],
    /// The USB on-the-go full-speed core of chapter 34, as far as its reset register. One register
    /// of nineteen and a deliberate partial. `otg.rs` records what it leaves out.
    pub otg: Otg,
    /// The secure digital card interface of chapter 31. A board puts a card on it. A part with
    /// nothing in the slot is a part with an empty slot, which is what the firmware then sees.
    pub sdio: Sdio,
    /// The backup domain, as far as the reset that clears it.
    pub rtc: Rtc,
    /// The MCU debug component, RM0090 rev 22 section 38.16, on the core's own private peripheral
    /// bus rather than this part's.
    pub dbg: Dbg,
    /// The independent watchdog of chapter 21.
    pub iwdg: Iwdg,
    /// The cycle counter the processor brings with it, which is ARM's rather than ST's and so is
    /// described in neither manual on this part's shelf. `cpu::armv7m` says which two describe it.
    pub dwt: Dwt,
    bus: Bus,
    /// Which field answers for each slot of the bus, resolved once in [`Stm32f427::new`] so that
    /// nothing after it looks a peripheral up by name.
    wiring: Box<[Field]>,
    /// Where each field's register file lives, resolved once for the same reason.
    slots: Slots,
}

/// The slot each model's register file is in. A model keeps what the manual calls its state in the
/// register file and what it calls its wires in itself, so reaching one to drive it from outside
/// means reaching both. These indices are what pairs them without a name.
#[derive(Debug, Clone, Copy)]
struct Slots {
    rcc: usize,
    pwr: usize,
    gpio: [usize; PORTS.len()],
    spi: [usize; SERIAL_INTERFACES.len()],
    usart: [usize; SERIAL_PORTS.len()],
    i2c: [usize; I2C_INTERFACES.len()],
    flash: usize,
    adc: [usize; CONVERTERS.len()],
    adc_common: usize,
    tim: [usize; TIMERS.len()],
    advanced: [usize; ADVANCED_TIMERS.len()],
    dma: [usize; CONTROLLERS.len()],
    otg: usize,
    sdio: usize,
    rtc: usize,
    dbg: usize,
    iwdg: usize,
    dwt: usize,
}

/// Which of the MCU's fields answers for one slot of its bus.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Field {
    /// A slot this part has no model for: its register file answers alone.
    None,
    Rcc,
    Pwr,
    /// The nth port, indexing [`Stm32f427::gpio`].
    Gpio(usize),
    /// The nth serial interface, indexing [`Stm32f427::spi`].
    Spi(usize),
    /// The nth serial port, indexing [`Stm32f427::usart`].
    Usart(usize),
    /// The nth inter-integrated circuit interface, indexing [`Stm32f427::i2c`].
    I2c(usize),
    /// The flash interface, [`Stm32f427::flash`].
    Flash,
    /// The nth converter, indexing [`Stm32f427::adc`].
    Adc(usize),
    AdcCommon,
    /// The nth timer, indexing [`Stm32f427::tim`].
    Tim(usize),
    /// The nth advanced-control timer, indexing [`Stm32f427::advanced`].
    Advanced(usize),
    /// The nth controller, indexing [`Stm32f427::dma`].
    Dma(usize),
    /// The USB core, [`Stm32f427::otg`].
    Otg,
    /// The card interface, [`Stm32f427::sdio`].
    Sdio,
    /// The backup domain, [`Stm32f427::rtc`].
    Rtc,
    /// The MCU debug component, [`Stm32f427::dbg`].
    Dbg,
    /// The independent watchdog, [`Stm32f427::iwdg`].
    Iwdg,
    /// The processor's cycle counter, [`Stm32f427::dwt`].
    Dwt,
}

impl Field {
    /// Every field this part has, which is what [`Stm32f427::new`] walks.
    ///
    /// Adding a field to the MCU means adding it here, and [`Field::instance`] below is an
    /// exhaustive match, so the compiler refuses a field that has no instance to answer for. That's
    /// the whole reason the mapping is written this way round: a table of names would let a field
    /// be forgotten and leave it pointing at whatever slot came first.
    fn all() -> Vec<Self> {
        let mut all = vec![Self::Rcc, Self::Pwr];
        all.extend((0..PORTS.len()).map(Self::Gpio));
        all.extend((0..SERIAL_INTERFACES.len()).map(Self::Spi));
        all.extend((0..SERIAL_PORTS.len()).map(Self::Usart));
        all.extend((0..I2C_INTERFACES.len()).map(Self::I2c));
        all.push(Self::Flash);
        all.extend((0..CONVERTERS.len()).map(Self::Adc));
        all.push(Self::AdcCommon);
        all.extend((0..TIMERS.len()).map(Self::Tim));
        all.extend((0..ADVANCED_TIMERS.len()).map(Self::Advanced));
        all.extend((0..CONTROLLERS.len()).map(Self::Dma));
        all.push(Self::Otg);
        all.push(Self::Sdio);
        all.push(Self::Rtc);
        all.push(Self::Dbg);
        all.push(Self::Iwdg);
        all.push(Self::Dwt);
        all
    }

    /// The instance this field answers for.
    fn instance(self) -> &'static str {
        match self {
            Self::None => unreachable!("the unmodeled slot answers for no instance"),
            Self::Rcc => "RCC",
            Self::Pwr => "PWR",
            Self::Gpio(nth) => PORTS[nth],
            Self::Spi(nth) => SERIAL_INTERFACES[nth],
            Self::Usart(nth) => SERIAL_PORTS[nth].instance,
            Self::I2c(nth) => I2C_INTERFACES[nth],
            Self::Flash => "FLASH",
            Self::Adc(nth) => CONVERTERS[nth],
            Self::AdcCommon => ADC_COMMON,
            Self::Tim(nth) => TIMERS[nth].instance,
            Self::Advanced(nth) => ADVANCED_TIMERS[nth].instance,
            Self::Dma(nth) => CONTROLLERS[nth].instance,
            // ST's file splits one peripheral into four blocks. This model answers for the first.
            Self::Otg => "OTG_FS_GLOBAL",
            Self::Sdio => "SDIO",
            Self::Rtc => "RTC",
            Self::Dbg => "DBG",
            Self::Iwdg => "IWDG",
            Self::Dwt => crate::cpu::armv7m::DWT,
        }
    }
}

/// The serial interfaces of chapter 28, in the manual's order, which is the order of
/// [`Stm32f427::spi`].
///
/// RM0090 rev 22 section 28.4.2: "The extended I2Ss (`I2Sx_ext`) can be used only in full duplex
/// mode. The `I2Sx_ext` operate always in slave mode." `I2S2ext` and `I2S3ext` carry this layout
/// and aren't serial interfaces, so they're not here and the part answers for neither.
pub const SERIAL_INTERFACES: [&str; 6] = ["SPI1", "SPI2", "SPI3", "SPI4", "SPI5", "SPI6"];

/// The three inter-integrated circuit interfaces of chapter 27, one layout, controller mode only,
/// `i2c.rs`, in the manual's order, which is the order of [`Stm32f427::i2c`].
pub const I2C_INTERFACES: [&str; 3] = ["I2C1", "I2C2", "I2C3"];

/// One serial port as the part carries it: the instance, and the table it answers from.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SerialPort {
    /// The instance, as the vendor names it.
    pub instance: &'static str,
    /// Which of chapter 30's two tables it has, table 148.
    pub kind: Kind,
}

/// The three converters of chapter 13, in the manual's order, which is the order of [`Stm32f427::adc`].
pub const CONVERTERS: [&str; 3] = ["ADC1", "ADC2", "ADC3"];
/// The converters' common block, 13.13.15 to 13.13.17, as ST's file names it.
pub const ADC_COMMON: &str = "C_ADC";

/// The eight serial ports of chapter 30, which is the order of [`Stm32f427::usart`]: the six with every
/// register, then the two ST's file gives the shorter table.
pub const SERIAL_PORTS: [SerialPort; 8] = [
    SerialPort {
        instance: "USART1",
        kind: Kind::Usart,
    },
    SerialPort {
        instance: "USART2",
        kind: Kind::Usart,
    },
    SerialPort {
        instance: "USART3",
        kind: Kind::Usart,
    },
    SerialPort {
        instance: "USART6",
        kind: Kind::Usart,
    },
    SerialPort {
        instance: "UART7",
        kind: Kind::Usart,
    },
    SerialPort {
        instance: "UART8",
        kind: Kind::Usart,
    },
    SerialPort {
        instance: "UART4",
        kind: Kind::Uart,
    },
    SerialPort {
        instance: "UART5",
        kind: Kind::Uart,
    },
];

/// One timer of chapter 17 or 18 as the part wires it: how wide it counts, RM0090 rev 22 sections 17.2
/// and 18.2, which is the whole of what separates the four of chapter 18.
#[derive(Debug, Clone, Copy)]
pub struct Timer {
    /// The instance, as the vendor names it.
    pub instance: &'static str,
    /// What it counts in, 18.2.
    pub counter: Counter,
}

/// Every timer of chapter 18, in the manual's order, which is the order of [`Stm32f427::tim`].
///
/// ST's file gives each of the four a layout of its own, and the four are two: TIM2 and TIM5 carry
/// an option register the sixteen-bit pair doesn't have, and within each pair the tables are
/// identical. So the part points each timer at the layout of its pair, `memory_map.rs` chooses
/// which by the counter, and `tim.rs` records the one register that differs inside the wide pair.
/// Chapter 17's two are [`ADVANCED_TIMERS`], the same model through its `Advanced` family. Chapters 19
/// and 20's are a different shape, and the part has no model for them.
pub const TIMERS: [Timer; 4] = [
    Timer {
        instance: "TIM2",
        counter: Counter::Wide,
    },
    Timer {
        instance: "TIM3",
        counter: Counter::Narrow,
    },
    Timer {
        instance: "TIM4",
        counter: Counter::Narrow,
    },
    Timer {
        instance: "TIM5",
        counter: Counter::Wide,
    },
];

/// The two timers of chapter 17, in the manual's order, which is the order of [`Stm32f427::advanced`].
/// Both count in sixteen bits, 17.2, and both answer from the one layout ST's file gives them.
pub const ADVANCED_TIMERS: [Timer; 2] = [
    Timer {
        instance: "TIM1",
        counter: Counter::Narrow,
    },
    Timer {
        instance: "TIM8",
        counter: Counter::Narrow,
    },
];

/// One direct memory access controller as the part wires it: RM0090 rev 22 tables 43 and 44 for the
/// requests that reach it, and the note under figure 34 for whether its peripheral port is on the bus
/// matrix, which is what decides whether its streams can move memory to memory.
#[derive(Debug)]
pub struct Controller {
    /// The instance, as the vendor names it.
    pub instance: &'static str,
    /// Which peripheral request reaches which of its channels and streams.
    pub wiring: &'static [Wire],
    /// Which peripheral line is the last-data signal of section 10.3.15, and the streams it ends.
    pub last_data: &'static [Wire],
    /// Whether its peripheral port reaches the bus matrix.
    pub reaches_memory: bool,
}

/// The two controllers of chapter 10, in the order of [`Stm32f427::dma`].
///
/// The note under figure 34 is the whole of the difference between them: "The DMA1 controller AHB
/// peripheral port is not connected to the bus matrix like in the case of the DMA2 controller, thus only
/// DMA2 streams are able to perform memory-to-memory transfers."
pub static CONTROLLERS: [Controller; 2] = [
    Controller {
        instance: "DMA1",
        wiring: &DMA1_REQUESTS,
        last_data: &[],
        reaches_memory: false,
    },
    Controller {
        instance: "DMA2",
        wiring: &DMA2_REQUESTS,
        last_data: &DMA2_LAST_DATA,
        reaches_memory: true,
    },
];

/// RM0090 rev 22 section 10.3.15: the one peripheral "able to signal the end of the transfer" is the card
/// interface, and 31.3.2 step 4d has a firmware make it the flow controller of the stream it uses. The
/// signal arrives where its request does, on channel 4 of streams 3 and 6.
static DMA2_LAST_DATA: [Wire; 1] = [Wire {
    instance: "SDIO",
    request: sdio::LAST_DATA_REQUEST,
    channel: 4,
    streams: &[3, 6],
}];

/// RM0090 rev 22 table 43, for every request an instance this part models can drive.
///
/// A cell of that table names a peripheral request, and its row and column name the channel and the
/// stream the request reaches. This is the same statement the way a controller needs it. Only
/// instances that really drive a request are here, because a row for one that doesn't would name an
/// output no model has. Here that's the serial ports, the serial interfaces and the inter-integrated
/// circuit interfaces, and [`DMA2_REQUESTS`] adds the converters and the card interface. The timers
/// drive their request outputs too, and their rows are left out, so no stream serves a timer yet.
static DMA1_REQUESTS: [Wire; 23] = [
    Wire {
        instance: "I2C1",
        request: i2c::RECEIVE_REQUEST,
        channel: 1,
        streams: &[0, 5],
    },
    Wire {
        instance: "I2C1",
        request: i2c::TRANSMIT_REQUEST,
        channel: 1,
        streams: &[6, 7],
    },
    Wire {
        instance: "I2C3",
        request: i2c::RECEIVE_REQUEST,
        channel: 3,
        streams: &[2],
    },
    Wire {
        instance: "I2C3",
        request: i2c::TRANSMIT_REQUEST,
        channel: 3,
        streams: &[4],
    },
    Wire {
        instance: "I2C2",
        request: i2c::RECEIVE_REQUEST,
        channel: 7,
        streams: &[2, 3],
    },
    Wire {
        instance: "I2C2",
        request: i2c::TRANSMIT_REQUEST,
        channel: 7,
        streams: &[7],
    },
    Wire {
        instance: "UART5",
        request: usart::RECEIVE_REQUEST,
        channel: 4,
        streams: &[0],
    },
    Wire {
        instance: "USART3",
        request: usart::RECEIVE_REQUEST,
        channel: 4,
        streams: &[1],
    },
    Wire {
        instance: "UART4",
        request: usart::RECEIVE_REQUEST,
        channel: 4,
        streams: &[2],
    },
    Wire {
        instance: "USART3",
        request: usart::TRANSMIT_REQUEST,
        channel: 4,
        streams: &[3],
    },
    Wire {
        instance: "UART4",
        request: usart::TRANSMIT_REQUEST,
        channel: 4,
        streams: &[4],
    },
    Wire {
        instance: "USART2",
        request: usart::RECEIVE_REQUEST,
        channel: 4,
        streams: &[5],
    },
    Wire {
        instance: "USART2",
        request: usart::TRANSMIT_REQUEST,
        channel: 4,
        streams: &[6],
    },
    Wire {
        instance: "UART5",
        request: usart::TRANSMIT_REQUEST,
        channel: 4,
        streams: &[7],
    },
    Wire {
        instance: "UART8",
        request: usart::TRANSMIT_REQUEST,
        channel: 5,
        streams: &[0],
    },
    Wire {
        instance: "UART7",
        request: usart::TRANSMIT_REQUEST,
        channel: 5,
        streams: &[1],
    },
    Wire {
        instance: "UART7",
        request: usart::RECEIVE_REQUEST,
        channel: 5,
        streams: &[3],
    },
    Wire {
        instance: "UART8",
        request: usart::RECEIVE_REQUEST,
        channel: 5,
        streams: &[6],
    },
    Wire {
        instance: "USART3",
        request: usart::TRANSMIT_REQUEST,
        channel: 7,
        streams: &[4],
    },
    Wire {
        instance: "SPI3",
        request: spi::RECEIVE_REQUEST,
        channel: 0,
        streams: &[0, 2],
    },
    Wire {
        instance: "SPI3",
        request: spi::TRANSMIT_REQUEST,
        channel: 0,
        streams: &[5, 7],
    },
    Wire {
        instance: "SPI2",
        request: spi::RECEIVE_REQUEST,
        channel: 0,
        streams: &[3],
    },
    Wire {
        instance: "SPI2",
        request: spi::TRANSMIT_REQUEST,
        channel: 0,
        streams: &[4],
    },
];

/// RM0090 rev 22 table 44, read as [`DMA1_REQUESTS`] reads table 43.
static DMA2_REQUESTS: [Wire; 20] = [
    Wire {
        instance: "ADC1",
        request: adc::DMA_REQUEST,
        channel: 0,
        streams: &[0, 4],
    },
    Wire {
        instance: "ADC2",
        request: adc::DMA_REQUEST,
        channel: 1,
        streams: &[2, 3],
    },
    Wire {
        instance: "ADC3",
        request: adc::DMA_REQUEST,
        channel: 2,
        streams: &[0, 1],
    },
    Wire {
        instance: "USART1",
        request: usart::RECEIVE_REQUEST,
        channel: 4,
        streams: &[2, 5],
    },
    Wire {
        instance: "USART1",
        request: usart::TRANSMIT_REQUEST,
        channel: 4,
        streams: &[7],
    },
    Wire {
        instance: "USART6",
        request: usart::RECEIVE_REQUEST,
        channel: 5,
        streams: &[1, 2],
    },
    Wire {
        instance: "USART6",
        request: usart::TRANSMIT_REQUEST,
        channel: 5,
        streams: &[6, 7],
    },
    // Table 44 puts the card interface on channel 4, in the columns of streams 3 and 6. One line
    // for both directions, because one transfer runs at a time and `DTDIR` is what says which way
    // it goes.
    Wire {
        instance: "SDIO",
        request: sdio::TRANSFER_REQUEST,
        channel: 4,
        streams: &[3, 6],
    },
    Wire {
        instance: "SPI6",
        request: spi::TRANSMIT_REQUEST,
        channel: 1,
        streams: &[5],
    },
    Wire {
        instance: "SPI6",
        request: spi::RECEIVE_REQUEST,
        channel: 1,
        streams: &[6],
    },
    Wire {
        instance: "SPI5",
        request: spi::RECEIVE_REQUEST,
        channel: 2,
        streams: &[3],
    },
    Wire {
        instance: "SPI5",
        request: spi::TRANSMIT_REQUEST,
        channel: 2,
        streams: &[4],
    },
    Wire {
        instance: "SPI1",
        request: spi::RECEIVE_REQUEST,
        channel: 3,
        streams: &[0, 2],
    },
    Wire {
        instance: "SPI1",
        request: spi::TRANSMIT_REQUEST,
        channel: 3,
        streams: &[3, 5],
    },
    Wire {
        instance: "SPI4",
        request: spi::RECEIVE_REQUEST,
        channel: 4,
        streams: &[0],
    },
    Wire {
        instance: "SPI4",
        request: spi::TRANSMIT_REQUEST,
        channel: 4,
        streams: &[1],
    },
    Wire {
        instance: "SPI4",
        request: spi::RECEIVE_REQUEST,
        channel: 5,
        streams: &[3],
    },
    Wire {
        instance: "SPI4",
        request: spi::TRANSMIT_REQUEST,
        channel: 5,
        streams: &[4],
    },
    Wire {
        instance: "SPI5",
        request: spi::RECEIVE_REQUEST,
        channel: 7,
        streams: &[5],
    },
    Wire {
        instance: "SPI5",
        request: spi::TRANSMIT_REQUEST,
        channel: 7,
        streams: &[6],
    },
];

/// The ports of chapter 8, in the order their bases run, which is the order of [`Stm32f427::gpio`].
///
/// They're one layout. ST's file declares three, because RM0090 rev 22 sections 8.4.1, 8.4.3
/// and 8.4.4 give ports A and B reset values of their own, and a reset value belongs to the
/// instance rather than the layout. The part's memory map points every port at the one
/// table and states each one's reset values as corrections, so this model answers for all eleven.
pub const PORTS: [&str; 11] = [
    "GPIOA", "GPIOB", "GPIOC", "GPIOD", "GPIOE", "GPIOF", "GPIOG", "GPIOH", "GPIOI", "GPIOJ",
    "GPIOK",
];

/// Every field this part's models declare because the vendor's file omits it or splits it.
///
/// A generated table is ST's file transcribed and stays that way, so a field ST omits or splits is
/// declared by the model that needs it. A check that asks what the part declares has to
/// ask here as well as of the tables, and one that asks only the tables reads a hole where there's
/// none.
pub fn declared_fields() -> impl Iterator<Item = &'static FieldSpec> {
    [rcc::DECLARED, pwr::DECLARED, dbg::DECLARED, flash::DECLARED]
        .into_iter()
        .flatten()
        .copied()
}

store!(Stm32f427 {
    values: [
        rcc, pwr, gpio, flash, adc, adc_common, tim, advanced, otg, rtc, dbg, iwdg, dwt,
    ],
    parts: [spi, usart, i2c, dma, sdio, bus],
    built: [wiring, slots],
});

impl Stm32f427 {
    /// The part out of reset: every model fresh, running on the internal oscillator, nothing on its pins.
    ///
    /// Fails only if the part's own description is wrong: a field whose instance the tables don't
    /// carry, or a field wired to a slot whose layout it wasn't written for.
    pub fn new() -> Result<Self, Error> {
        let bus = super::memory_map::builder().build()?;
        let mut wiring = vec![Field::None; bus.slots().len()].into_boxed_slice();
        let mut slots = Slots {
            rcc: 0,
            pwr: 0,
            gpio: [0; PORTS.len()],
            spi: [0; SERIAL_INTERFACES.len()],
            usart: [0; SERIAL_PORTS.len()],
            i2c: [0; I2C_INTERFACES.len()],
            flash: 0,
            adc: [0; CONVERTERS.len()],
            adc_common: 0,
            tim: [0; TIMERS.len()],
            advanced: [0; ADVANCED_TIMERS.len()],
            dma: [0; CONTROLLERS.len()],
            otg: 0,
            sdio: 0,
            rtc: 0,
            dbg: 0,
            iwdg: 0,
            dwt: 0,
        };
        for field in Field::all() {
            let instance = field.instance();
            let slot = bus.slot(instance)?;
            wiring[slot] = field;
            match field {
                Field::Rcc => slots.rcc = slot,
                Field::Pwr => slots.pwr = slot,
                Field::Gpio(nth) => slots.gpio[nth] = slot,
                Field::Spi(nth) => slots.spi[nth] = slot,
                Field::Usart(nth) => slots.usart[nth] = slot,
                Field::I2c(nth) => slots.i2c[nth] = slot,
                Field::Flash => slots.flash = slot,
                Field::Adc(nth) => slots.adc[nth] = slot,
                Field::AdcCommon => slots.adc_common = slot,
                Field::Tim(nth) => slots.tim[nth] = slot,
                Field::Advanced(nth) => slots.advanced[nth] = slot,
                Field::Dma(nth) => slots.dma[nth] = slot,
                Field::Otg => slots.otg = slot,
                Field::Sdio => slots.sdio = slot,
                Field::Rtc => slots.rtc = slot,
                Field::Dbg => slots.dbg = slot,
                Field::Iwdg => slots.iwdg = slot,
                Field::Dwt => slots.dwt = slot,
                Field::None => unreachable!("Field::all names no unmodeled slot"),
            }
        }
        let adc_common = AdcCommon::with_clock(RESET_BUS_HZ);
        let mut mcu = Self {
            rcc: Rcc::new(),
            pwr: Pwr::new(),
            gpio: std::array::from_fn(|_| Gpio::default()),
            spi: std::array::from_fn(|_| Spi::with_clock(RESET_BUS_HZ)),
            usart: std::array::from_fn(|nth| {
                Usart::with_clock(SERIAL_PORTS[nth].kind, RESET_BUS_HZ)
            }),
            i2c: std::array::from_fn(|_| I2c::with_clock(RESET_BUS_HZ)),
            flash: Flash::with_clock(RESET_BUS_HZ),
            adc: std::array::from_fn(|_| Adc::with_clock(adc_common.driven_hz())),
            adc_common,
            tim: std::array::from_fn(|nth| Tim::with_clock(RESET_BUS_HZ, TIMERS[nth].counter)),
            advanced: std::array::from_fn(|nth| {
                Tim::with_clock(RESET_BUS_HZ, ADVANCED_TIMERS[nth].counter)
                    .breaks_on("RCC", rcc::CLOCK_FAILURE)
            }),
            dma: std::array::from_fn(|nth| {
                Dma::new(
                    CONTROLLERS[nth].wiring,
                    CONTROLLERS[nth].last_data,
                    CONTROLLERS[nth].reaches_memory,
                )
            }),
            otg: Otg,
            // The 48 MHz domain is the PLL's Q tap, section 6.3.2, and the PLL is off at reset.
            sdio: Sdio::with_clock(0),
            rtc: Rtc,
            dbg: Dbg,
            iwdg: Iwdg::new(),
            // The counter counts the core clock, which at reset is the same HSI the buses run on
            // because `RCC_CFGR.HPRE` resets to a divider of one, 6.3.3.
            dwt: Dwt::with_clock(RESET_BUS_HZ),
            bus,
            wiring,
            slots,
        };
        mcu.check()?;
        Ok(mcu)
    }
}

/// A model and the register file it keeps half its state in, paired by the slot resolved at
/// construction. Every accessor below is this with the field named, so the reaching is written once
/// whether the part has one of something or six. This is what a board drives a part through:
/// `mcu.power()` rather than a name and a downcast, and it can't fail.
fn with_registers<'a, M>(
    model: &'a mut M,
    bus: &'a mut Bus,
    slot: usize,
) -> (&'a mut M, &'a mut RegisterFile) {
    (model, bus.slot_mut(slot).registers_mut())
}

/// Drives an input of one at `at`, an input the bus doesn't carry: it gets its registers and a
/// context as on a bus access, so it may schedule and raise. This is the door a board's own parts
/// come through.
fn driving<M, T>(
    model: &mut M,
    bus: &mut Bus,
    slot: usize,
    at: VirtualNanos,
    input: impl FnOnce(&mut M, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
) -> T {
    let (registers, mut context) = bus.drive(at, slot);
    input(model, registers, &mut context)
}

/// Copies `registers` of the instance at `slot` from `old` into `fresh`, for what a system reset
/// carries over rather than clearing: the calendar, `RCC_BDCR`, and the debug component's own three.
/// `old` and `fresh` share the same slot for one instance because `fresh` is always built by the same
/// deterministic bus as `old` was.
fn keep<L: Layout>(
    old: &Bus,
    fresh: &mut Bus,
    slot: usize,
    registers: impl IntoIterator<Item = L>,
) {
    for register in registers {
        let value = old.slots()[slot].registers().get(register);
        fresh.slot_mut(slot).registers_mut().set(register, value);
    }
}

impl Stm32f427 {
    /// The clock tree and the registers it keeps its state in.
    pub fn clocks(&mut self) -> (&mut Rcc, &mut RegisterFile) {
        let Self {
            rcc, bus, slots, ..
        } = self;
        with_registers(rcc, bus, slots.rcc)
    }

    /// Drives an input of the clock tree at `at`, an input the bus doesn't carry.
    pub fn drive_clocks<T>(
        &mut self,
        at: VirtualNanos,
        input: impl FnOnce(&mut Rcc, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
    ) -> T {
        let Self {
            rcc, bus, slots, ..
        } = self;
        driving(rcc, bus, slots.rcc, at, input)
    }

    /// The regulator and the registers it keeps its state in.
    pub fn power(&mut self) -> (&mut Pwr, &mut RegisterFile) {
        let Self {
            pwr, bus, slots, ..
        } = self;
        with_registers(pwr, bus, slots.pwr)
    }

    /// The board's supply rail, in millivolts, fed to every instance that reads it: the regulator's
    /// own brownout detector, RM0090 rev 22 section 5.5.2, and the flash interface's `LATENCY` check
    /// against table 12, section 3.5.1. One board input, one setter, rather than a board or a reset
    /// calling `Pwr::set_supply` and `Flash::set_supply` apart and one of the two going unset.
    pub fn set_supply(&mut self, millivolts: u32) {
        let (power, registers) = self.power();
        power.set_supply(millivolts, registers);
        if let Some(millivolts) = NonZeroU32::new(millivolts) {
            self.flash.set_supply(millivolts);
        }
    }

    /// Drives an input of the regulator at `at`, an input the bus doesn't carry.
    pub fn drive_power<T>(
        &mut self,
        at: VirtualNanos,
        input: impl FnOnce(&mut Pwr, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
    ) -> T {
        let Self {
            pwr, bus, slots, ..
        } = self;
        driving(pwr, bus, slots.pwr, at, input)
    }
    /// The nth port of [`PORTS`], with the registers it keeps its state in.
    pub fn port(&mut self, nth: usize) -> (&mut Gpio, &mut RegisterFile) {
        let Self {
            gpio, bus, slots, ..
        } = self;
        with_registers(&mut gpio[nth], bus, slots.gpio[nth])
    }

    /// Drives an input of the nth port at `at`, an input the bus doesn't carry.
    pub fn drive_port<T>(
        &mut self,
        at: VirtualNanos,
        nth: usize,
        input: impl FnOnce(&mut Gpio, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
    ) -> T {
        let Self {
            gpio, bus, slots, ..
        } = self;
        driving(&mut gpio[nth], bus, slots.gpio[nth], at, input)
    }

    /// The nth serial interface of [`SERIAL_INTERFACES`], with the registers it keeps its state in.
    pub fn serial(&mut self, nth: usize) -> (&mut Spi, &mut RegisterFile) {
        let Self {
            spi, bus, slots, ..
        } = self;
        with_registers(&mut spi[nth], bus, slots.spi[nth])
    }

    /// Drives an input of the nth serial interface at `at`, an input the bus doesn't carry.
    pub fn drive_serial<T>(
        &mut self,
        at: VirtualNanos,
        nth: usize,
        input: impl FnOnce(&mut Spi, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
    ) -> T {
        let Self {
            spi, bus, slots, ..
        } = self;
        driving(&mut spi[nth], bus, slots.spi[nth], at, input)
    }

    /// The nth serial port of [`SERIAL_PORTS`], with the registers it keeps its state in.
    pub fn serial_port(&mut self, nth: usize) -> (&mut Usart, &mut RegisterFile) {
        let Self {
            usart, bus, slots, ..
        } = self;
        with_registers(&mut usart[nth], bus, slots.usart[nth])
    }

    /// Drives an input of the nth serial port at `at`, an input the bus doesn't carry.
    pub fn drive_serial_port<T>(
        &mut self,
        at: VirtualNanos,
        nth: usize,
        input: impl FnOnce(&mut Usart, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
    ) -> T {
        let Self {
            usart, bus, slots, ..
        } = self;
        driving(&mut usart[nth], bus, slots.usart[nth], at, input)
    }

    /// The nth converter of [`CONVERTERS`], with the registers it keeps its state in.
    pub fn converter(&mut self, nth: usize) -> (&mut Adc, &mut RegisterFile) {
        let Self {
            adc, bus, slots, ..
        } = self;
        with_registers(&mut adc[nth], bus, slots.adc[nth])
    }

    /// The nth timer of [`TIMERS`], with the registers it keeps its state in.
    pub fn timer(&mut self, nth: usize) -> (&mut Tim<General>, &mut RegisterFile) {
        let Self {
            tim, bus, slots, ..
        } = self;
        with_registers(&mut tim[nth], bus, slots.tim[nth])
    }

    /// Drives an input of the nth timer at `at`, an input the bus doesn't carry.
    pub fn drive_timer<T>(
        &mut self,
        at: VirtualNanos,
        nth: usize,
        input: impl FnOnce(&mut Tim<General>, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
    ) -> T {
        let Self {
            tim, bus, slots, ..
        } = self;
        driving(&mut tim[nth], bus, slots.tim[nth], at, input)
    }

    /// The nth advanced-control timer of [`ADVANCED_TIMERS`], with the registers it keeps its state in.
    pub fn advanced_timer(&mut self, nth: usize) -> (&mut Tim<Advanced>, &mut RegisterFile) {
        let Self {
            advanced,
            bus,
            slots,
            ..
        } = self;
        with_registers(&mut advanced[nth], bus, slots.advanced[nth])
    }

    /// Drives an input of the nth advanced-control timer at `at`, an input the bus doesn't carry.
    pub fn drive_advanced_timer<T>(
        &mut self,
        at: VirtualNanos,
        nth: usize,
        input: impl FnOnce(&mut Tim<Advanced>, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
    ) -> T {
        let Self {
            advanced,
            bus,
            slots,
            ..
        } = self;
        driving(&mut advanced[nth], bus, slots.advanced[nth], at, input)
    }

    /// The nth controller of [`CONTROLLERS`], with the registers it keeps its state in.
    pub fn controller(&mut self, nth: usize) -> (&mut Dma, &mut RegisterFile) {
        let Self {
            dma, bus, slots, ..
        } = self;
        with_registers(&mut dma[nth], bus, slots.dma[nth])
    }

    /// Drives an input of the nth controller at `at`, an input the bus doesn't carry.
    pub fn drive_controller<T>(
        &mut self,
        at: VirtualNanos,
        nth: usize,
        input: impl FnOnce(&mut Dma, &mut RegisterFile, &mut DeviceContext<'_>) -> T,
    ) -> T {
        let Self {
            dma, bus, slots, ..
        } = self;
        driving(&mut dma[nth], bus, slots.dma[nth], at, input)
    }

    /// The USB core and the registers it keeps its state in.
    ///
    /// There's no `drive_` beside this one: the core has no input the bus doesn't carry until a
    /// host is on the far end of it.
    pub fn usb(&mut self) -> (&mut Otg, &mut RegisterFile) {
        let Self {
            otg, bus, slots, ..
        } = self;
        with_registers(otg, bus, slots.otg)
    }

    /// The card interface and the registers it keeps its state in.
    pub fn cards(&mut self) -> (&mut Sdio, &mut RegisterFile) {
        let Self {
            sdio, bus, slots, ..
        } = self;
        with_registers(sdio, bus, slots.sdio)
    }

    /// The flash interface and the registers it keeps its state in.
    pub fn program(&mut self) -> (&mut Flash, &mut RegisterFile) {
        let Self {
            flash, bus, slots, ..
        } = self;
        with_registers(flash, bus, slots.flash)
    }
}

impl Stm32f427 {
    /// Tells every chip a controller carried through a reset at `at` that its part restarted, with
    /// that controller's timeline, since the events it scheduled went with the old bus.
    fn chips_restarted(&mut self, at: VirtualNanos) {
        let Self {
            spi,
            usart,
            i2c,
            sdio,
            bus,
            slots,
            ..
        } = self;
        for (spi, &slot) in spi.iter_mut().zip(&slots.spi) {
            driving(spi, bus, slot, at, |spi, _, context| {
                spi.chips_restarted(context);
            });
        }
        for (usart, &slot) in usart.iter_mut().zip(&slots.usart) {
            driving(usart, bus, slot, at, |usart, _, context| {
                usart.chips_restarted(context);
            });
        }
        for (i2c, &slot) in i2c.iter_mut().zip(&slots.i2c) {
            driving(i2c, bus, slot, at, |i2c, _, context| {
                i2c.chips_restarted(context);
            });
        }
        driving(sdio, bus, slots.sdio, at, |sdio, _, context| {
            sdio.chips_restarted(context);
        });
    }
}

impl Mcu for Stm32f427 {
    fn bus(&self) -> &Bus {
        &self.bus
    }

    /// A system reset, RM0090 rev 22 section 6.1.1: a fresh part with what the board put on its
    /// pins still there, the reset flags carrying `cause`'s own flag beside the ones before, and
    /// the backup domain as it was. Section 6.1.3 keeps that domain through every reset but its
    /// own: the calendar, the twenty backup registers, the clock controller's `BDCR` and the backup
    /// regulator's enable. Sections 38.16.3 to 38.16.5 keep the debug component's three read-write
    /// registers through the same reset: a debugger's configuration of the part is a power-on
    /// reset's to clear, not this one's. The flash interface keeps its option bytes as the last
    /// commit left them, and the clock controller the LSI's calibrated rate. Regions and windows a
    /// board added to the bus stay.
    fn reset(&mut self, at: VirtualNanos, cause: ResetCause) {
        let mut fresh = Self::new().expect("a part that assembled once assembles again");
        let flags = self.bus.slots()[self.slots.rcc]
            .registers()
            .get(super::generated::rcc::Register::Csr);
        let (clocks, registers) = fresh.clocks();
        clocks.restarted(cause, flags, registers);
        let regulator = self.bus.slots()[self.slots.pwr]
            .registers()
            .get(super::generated::pwr::Register::Csr);
        let (power, registers) = fresh.power();
        power.keep_backup_regulator(regulator, registers);
        let (hse_hz, lse_hz) = self.rcc.crystals();
        fresh.rcc.attach_crystals(hse_hz, lse_hz);
        fresh.rcc.calibrate_lsi(self.rcc.lsi_hz());
        fresh.set_supply(self.pwr.supply());
        for (fresh, old) in fresh.spi.iter_mut().zip(&mut self.spi) {
            fresh.inherit(old);
        }
        for (fresh, old) in fresh.usart.iter_mut().zip(&mut self.usart) {
            fresh.inherit(old);
        }
        for (fresh, old) in fresh.i2c.iter_mut().zip(&mut self.i2c) {
            fresh.inherit(old);
        }
        for (fresh, old) in fresh.adc.iter_mut().zip(&self.adc) {
            fresh.inherit(old);
        }
        fresh.sdio.inherit(&mut self.sdio);
        let (optcr, optcr1) = self.flash.committed_options();
        let (flash, registers) = fresh.program();
        flash.keep_options(optcr, optcr1, registers);
        keep(
            &self.bus,
            &mut fresh.bus,
            self.slots.rtc,
            super::generated::rtc::Register::ALL,
        );
        keep(
            &self.bus,
            &mut fresh.bus,
            self.slots.rcc,
            [super::generated::rcc::Register::Bdcr],
        );
        keep(
            &self.bus,
            &mut fresh.bus,
            self.slots.dbg,
            [
                super::generated::dbg::Register::DbgmcuCr,
                super::generated::dbg::Register::DbgmcuApb1Fz,
                super::generated::dbg::Register::DbgmcuApb2Fz,
            ],
        );
        fresh
            .bus
            .keep_added(&self.bus)
            .expect("a part rebuilt from its own description");
        *self = fresh;
        self.chips_restarted(at);
    }

    /// [`Mcu::poll`] for the USARTs alone, the only models here with anything outside: a host on
    /// the wire, or a chip with words to send. Every other model's poll does nothing, and a stop
    /// comes often enough that asking each of them costs.
    // ceiling: a model of this part that looks outside must be listed here; upgrade when one
    // besides the USART does.
    fn poll(&mut self, now: VirtualNanos) {
        for slot in 0..self.wiring.len() {
            let Field::Usart(nth) = self.wiring[slot] else {
                continue;
            };
            let (carried, mut context) = self.bus.call(now, slot);
            self.usart[nth].poll(carried.registers_mut(), &mut context);
        }
    }

    fn split(&mut self, slot: usize) -> (&mut Bus, Option<&mut dyn ErasedDevice>) {
        let Self {
            rcc,
            pwr,
            gpio,
            spi,
            usart,
            i2c,
            flash,
            adc,
            adc_common,
            tim,
            advanced,
            dma,
            otg,
            sdio,
            rtc,
            dbg,
            iwdg,
            dwt,
            bus,
            wiring,
            ..
        } = self;
        // A window a board added has a slot past the part's own, and the board's model for it.
        let field = wiring.get(slot).copied().unwrap_or(Field::None);
        let model: Option<&mut dyn ErasedDevice> = match field {
            Field::None => None,
            Field::Rcc => Some(rcc),
            Field::Pwr => Some(pwr),
            Field::Gpio(nth) => Some(&mut gpio[nth]),
            Field::Spi(nth) => Some(&mut spi[nth]),
            Field::Usart(nth) => Some(&mut usart[nth]),
            Field::I2c(nth) => Some(&mut i2c[nth]),
            Field::Flash => Some(flash),
            Field::Adc(nth) => Some(&mut adc[nth]),
            Field::AdcCommon => Some(adc_common),
            Field::Tim(nth) => Some(&mut tim[nth]),
            Field::Advanced(nth) => Some(&mut advanced[nth]),
            Field::Dma(nth) => Some(&mut dma[nth]),
            Field::Otg => Some(otg),
            Field::Sdio => Some(sdio),
            Field::Rtc => Some(rtc),
            Field::Dbg => Some(dbg),
            Field::Iwdg => Some(iwdg),
            Field::Dwt => Some(dwt),
        };
        (bus, model)
    }

    fn bus_mut(&mut self) -> &mut Bus {
        &mut self.bus
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::BTreeMap;

    use crate::soc::{Fault, Peripheral, RegisterSpec};

    /// Every instance of `layout` the part carries.
    fn instances_of(layout: &'static [RegisterSpec]) -> impl Iterator<Item = &'static Peripheral> {
        super::super::generated::PERIPHERALS
            .iter()
            .filter(move |peripheral| std::ptr::eq(peripheral.registers, layout))
    }

    /// Memory a board fits on the external memory interface's first SDRAM bank, RM0090 rev 22
    /// section 37.4 and figure 457.
    const BOARD_SDRAM: crate::soc::Region = crate::soc::Region::ram("sdram", 0xC000_0000, 16 << 20);

    /// A part with a board's worth on its pins and inside its backup domain, a timer running and a clock
    /// enabled: what a reset has to sort into kept and gone.
    fn a_part_with_a_board_on_it() -> Stm32f427 {
        use crate::chip::{memory_card, sd, uart};
        use crate::soc::stm32f427::generated::dbg::{
            Register as DbgRegister, dbgmcu_apb1_fz, dbgmcu_apb2_fz, dbgmcu_cr,
        };
        use crate::soc::stm32f427::generated::pwr::{
            Register as PwrRegister, cr as pwr_cr, csr as pwr_csr,
        };
        use crate::soc::stm32f427::generated::rcc::{
            Register as RccRegister, apb1enr, apb2enr, bdcr,
        };
        use crate::soc::stm32f427::generated::rtc::Register as RtcRegister;
        use crate::soc::stm32f427::generated::tim2::{Register as TimRegister, cr1};
        use crate::soc::stm32f427::generated::{DBG, RCC, TIM2};
        use crate::soc::{Layout, Width};

        let mut mcu = Stm32f427::new().expect("the part assembles");
        mcu.rcc.attach_crystals(24_000_000, 32_768);
        mcu.rcc.calibrate_lsi(29_000);
        mcu.set_supply(3300);
        mcu.spi[0].attach(crate::chip::spi::Pattern::default());
        mcu.usart[1].attach(uart::Pattern::default());
        mcu.usart[6].attach(uart::TcpPeer::listen(0).expect("a port is free"));
        mcu.sdio
            .attach(memory_card::MemoryCard::holding(&[0; sd::BLOCK]));
        mcu.adc[0].set_reference(3300);
        mcu.adc[0].set_input(adc::Channel::new(2).expect("a pin channel"), 1650);
        mcu.bus_mut()
            .add_region(BOARD_SDRAM)
            .expect("the first SDRAM bank is free");
        mcu.bus_mut()
            .add_window(super::super::NOR_PSRAM[3])
            .expect("NE4 is free");
        let at = VirtualNanos(0);
        let register = |base: u64, offset: u32| base + u64::from(offset);
        let enables = register(RCC.base, RccRegister::Apb2enr.spec().offset);
        mcu.write(at, enables, Width::W32, apb2enr::ADC1EN.mask())
            .expect("the enable takes the write");
        let (rtc, rcc, pwr) = (mcu.slots.rtc, mcu.slots.rcc, mcu.slots.pwr);
        mcu.bus_mut()
            .slot_mut(pwr)
            .registers_mut()
            .set(PwrRegister::Cr, pwr_cr::DBP.mask());
        mcu.bus_mut()
            .slot_mut(pwr)
            .registers_mut()
            .set(PwrRegister::Csr, pwr_csr::BRE.mask() | pwr_csr::BRR.mask());
        mcu.bus_mut()
            .slot_mut(rtc)
            .registers_mut()
            .set(RtcRegister::Bkp19r, 0x5EB0_0755);
        mcu.bus_mut()
            .slot_mut(rcc)
            .registers_mut()
            .set(RccRegister::Bdcr, bdcr::RTCEN.mask() | bdcr::LSEON.mask());
        mcu.write(
            at,
            register(RCC.base, RccRegister::Apb1enr.spec().offset),
            Width::W32,
            apb1enr::TIM2EN.mask(),
        )
        .expect("the enable takes the write");
        mcu.write(
            at,
            register(TIM2.base, TimRegister::Cr1.spec().offset),
            Width::W32,
            cr1::CEN.mask(),
        )
        .expect("the timer takes the write");
        assert!(
            mcu.next_event().is_some(),
            "the running timer scheduled its update"
        );
        // 38.16.3, 38.16.4, 38.16.5: a debugger's configuration, which a system reset must not undo.
        mcu.write(
            at,
            register(DBG.base, DbgRegister::DbgmcuCr.spec().offset),
            Width::W32,
            dbgmcu_cr::DBG_STOP.mask(),
        )
        .expect("the debug component takes the write");
        mcu.write(
            at,
            register(DBG.base, DbgRegister::DbgmcuApb1Fz.spec().offset),
            Width::W32,
            dbgmcu_apb1_fz::DBG_TIM5_STOP.mask(),
        )
        .expect("the debug component takes the write");
        mcu.write(
            at,
            register(DBG.base, DbgRegister::DbgmcuApb2Fz.spec().offset),
            Width::W32,
            dbgmcu_apb2_fz::DBG_TIM1_STOP.mask(),
        )
        .expect("the debug component takes the write");
        mcu
    }

    /// A reset from the pin, section 6.1.1's external reset, leaves `PADRSTF` beside the flags the part
    /// had and not the software's, and the core's own request then adds `SFTRSTF`.
    #[test]
    fn a_reset_from_the_pin_leaves_its_own_flag_and_not_the_softwares() {
        use crate::soc::stm32f427::generated::RCC;
        use crate::soc::stm32f427::generated::rcc::{Register as RccRegister, csr};
        use crate::soc::{Layout, Width};

        let at = VirtualNanos(0);
        let flags = RCC.base + u64::from(RccRegister::Csr.spec().offset);
        let mut mcu = a_part_with_a_board_on_it();
        mcu.write(at, flags, Width::W32, csr::RMVF.mask())
            .expect("the flags take the write");
        mcu.reset(at, ResetCause::Pin);
        let value = mcu.read(at, flags, Width::W32).expect("the flags answer");
        assert!(csr::PADRSTF.is_set(value));
        assert!(!csr::SFTRSTF.is_set(value) && !csr::WDGRSTF.is_set(value));
        mcu.reset(at, ResetCause::Core);
        let value = mcu.read(at, flags, Width::W32).expect("the flags answer");
        assert!(csr::PADRSTF.is_set(value) && csr::SFTRSTF.is_set(value));
    }

    /// A system reset rebuilds the part and keeps what the board put on its pins and what the
    /// backup domain holds: the chips on the buses, the card, the crystals, the rail, the
    /// converter's inputs, the calendar's registers, `BDCR` and the backup regulator's enable, and
    /// what a debugger left in the debug component's freeze registers. The flash interface keeps its
    /// option bytes as the last commit left them, and the clock controller the LSI's calibrated rate.
    /// The reset flags say why the part restarted. Every other register is back at its reset value
    /// and nothing is scheduled.
    #[test]
    fn a_reset_keeps_the_pins_and_the_backup_domain_and_nothing_else() {
        use crate::soc::stm32f427::generated::adc1::{Register as AdcRegister, cr2, sqr3, sr};
        use crate::soc::stm32f427::generated::dbg::{
            Register as DbgRegister, dbgmcu_apb1_fz, dbgmcu_apb2_fz, dbgmcu_cr,
        };
        use crate::soc::stm32f427::generated::pwr::{Register as PwrRegister, csr as pwr_csr};
        use crate::soc::stm32f427::generated::rcc::{Register as RccRegister, apb2enr, bdcr, csr};
        use crate::soc::stm32f427::generated::rtc::Register as RtcRegister;
        use crate::soc::stm32f427::generated::{ADC1, DBG, RCC, RTC};
        use crate::soc::{Layout, Width};

        let at = VirtualNanos(0);
        let register = |base: u64, offset: u32| base + u64::from(offset);
        let enables = register(RCC.base, RccRegister::Apb2enr.spec().offset);
        let mut mcu = a_part_with_a_board_on_it();
        mcu.reset(at, ResetCause::Core);
        assert_eq!(
            mcu.read(at, enables, Width::W32)
                .expect("the enables answer"),
            0,
            "every register is at its reset value"
        );
        assert_eq!(mcu.next_event(), None);
        assert_eq!(mcu.rcc.crystals(), (24_000_000, 32_768));
        assert_eq!(mcu.bus().memory().last(), Some(&BOARD_SDRAM));
        let ne4 = super::super::NOR_PSRAM[3].base;
        assert!(
            matches!(
                mcu.read(at, ne4, Width::W16),
                Err(Fault::Gated {
                    instance: "NE4",
                    ..
                })
            ),
            "the board's window is still there, behind its gate"
        );
        assert_eq!(
            mcu.rcc.lsi_hz(),
            29_000,
            "a board's LSI calibration is the board's, not a register's"
        );
        assert_eq!(mcu.pwr.supply(), 3300);
        assert!(mcu.spi[0].attached() && mcu.usart[1].attached() && mcu.usart[6].attached());
        assert!(!mcu.spi[1].attached());
        assert!(mcu.sdio.attached());
        // Half the rail on channel 2 converts to 2047 after fifteen cycles at the reset 8 MHz, 13.5.
        mcu.write(at, enables, Width::W32, apb2enr::ADC1EN.mask())
            .expect("the enable takes the write");
        let adc = |register: AdcRegister| ADC1.base + u64::from(register.spec().offset);
        mcu.write(at, adc(AdcRegister::Sqr3), Width::W32, sqr3::SQ1.set(0, 2))
            .expect("the converter takes the write");
        mcu.write(at, adc(AdcRegister::Cr2), Width::W32, cr2::ADON.mask())
            .expect("the converter takes the write");
        mcu.write(
            at,
            adc(AdcRegister::Cr2),
            Width::W32,
            cr2::ADON.mask() | cr2::SWSTART.mask(),
        )
        .expect("the converter takes the write");
        let converted = VirtualNanos(1_875);
        mcu.advance_to(converted);
        assert!(
            sr::EOC.is_set(
                mcu.read(converted, adc(AdcRegister::Sr), Width::W32)
                    .expect("the converter answers")
            )
        );
        assert_eq!(
            mcu.read(converted, adc(AdcRegister::Dr), Width::W32)
                .expect("the converter answers"),
            2047,
            "the pin's voltage is still there"
        );
        let backup = register(RTC.base, RtcRegister::Bkp19r.spec().offset);
        assert_eq!(
            mcu.read(at, backup, Width::W32)
                .expect("the backup domain answers"),
            0x5EB0_0755
        );
        let domain = mcu
            .registers("RCC")
            .expect("an instance")
            .get(RccRegister::Bdcr);
        assert!(bdcr::RTCEN.is_set(domain) && bdcr::LSEON.is_set(domain));
        let flags = mcu
            .registers("RCC")
            .expect("an instance")
            .get(RccRegister::Csr);
        assert!(
            csr::SFTRSTF.is_set(flags) && csr::PADRSTF.is_set(flags) && csr::PORRSTF.is_set(flags),
            "the software reset's flag joins the power-on ones the part started with: {flags:#x}"
        );
        let regulator = mcu
            .registers("PWR")
            .expect("an instance")
            .get(PwrRegister::Csr);
        assert!(
            pwr_csr::BRE.is_set(regulator) && pwr_csr::BRR.is_set(regulator),
            "the backup regulator is still on: {regulator:#x}"
        );
        let debug_read = |mcu: &mut Stm32f427, offset: u32| {
            mcu.read(at, register(DBG.base, offset), Width::W32)
                .expect("the debug component answers")
        };
        assert!(
            dbgmcu_cr::DBG_STOP.is_set(debug_read(&mut mcu, DbgRegister::DbgmcuCr.spec().offset)),
            "38.16.3: a system reset does not touch the debug component"
        );
        assert!(
            dbgmcu_apb1_fz::DBG_TIM5_STOP.is_set(debug_read(
                &mut mcu,
                DbgRegister::DbgmcuApb1Fz.spec().offset
            )),
            "38.16.4: a system reset does not touch the debug component"
        );
        assert!(
            dbgmcu_apb2_fz::DBG_TIM1_STOP.is_set(debug_read(
                &mut mcu,
                DbgRegister::DbgmcuApb2Fz.spec().offset
            )),
            "38.16.5: a system reset does not touch the debug component"
        );
    }

    /// A bank of the external memory interface answers only once `FMC_BCRx.MBKEN` enables it,
    /// section 37.3, and then reaches whatever the board put there, which here is nothing.
    #[test]
    fn a_nor_psram_bank_answers_only_once_its_control_register_enables_it() {
        use crate::soc::stm32f427::generated::FMC;
        use crate::soc::stm32f427::generated::fmc::{Register as FmcRegister, bcr1};
        use crate::soc::{Gate, Layout, Width};

        let at = VirtualNanos(0);
        let mut mcu = Stm32f427::new().expect("the part assembles");
        for bank in super::super::NOR_PSRAM {
            mcu.bus_mut().add_window(bank).expect("the banks are free");
        }
        let ne3 = super::super::NOR_PSRAM[2].base;
        assert_eq!(
            mcu.read(at, ne3, Width::W16),
            Err(Fault::Gated {
                instance: "NE3",
                register: "window",
                by: Gate::by("FMC", "BCR3", "MBKEN"),
            })
        );
        let bcr3 = FMC.base + u64::from(FmcRegister::Bcr3.spec().offset);
        mcu.write(at, bcr3, Width::W32, bcr1::MBKEN.mask())
            .expect("the control register answers");
        assert_eq!(
            mcu.read(at, ne3, Width::W16),
            Err(Fault::Unmapped { address: ne3 })
        );
    }

    /// Every model that keeps time runs on an output of the tree, and nothing else does: the description
    /// is where the wiring is written, and a model built with a rate and never wired keeps it forever.
    #[test]
    fn every_model_that_keeps_time_runs_on_a_clock_the_tree_drives() {
        let mcu = Stm32f427::new().unwrap();
        for field in Field::all() {
            let keeps_time = matches!(
                field,
                Field::Spi(_)
                    | Field::Usart(_)
                    | Field::I2c(_)
                    | Field::Flash
                    | Field::Adc(_)
                    | Field::AdcCommon
                    | Field::Tim(_)
                    | Field::Advanced(_)
                    | Field::Sdio
                    | Field::Iwdg
                    | Field::Dwt
            );
            let clock = mcu.bus().clock_of(field.instance());
            assert_eq!(clock.is_some(), keeps_time, "{}", field.instance());
            // A converter runs on its common block's output, 13.3.2, and the block on the tree.
            let driver = if matches!(field, Field::Adc(_)) {
                ADC_COMMON
            } else {
                "RCC"
            };
            if let Some(clock) = clock {
                assert_eq!(clock.instance, driver, "{}", field.instance());
            }
        }
    }

    /// Every field a model declares is in the `DECLARED` beside it.
    ///
    /// The lists are written by hand and nothing else needs them complete, so a field left out of one is
    /// silent: it reads as a hole in ST's file wherever anything asks the part what it declares. The
    /// module's own source is the second witness, read the way `tests/conformance.rs` reads the
    /// firmware's, because the declaration and the list that carries it are two statements of one fact.
    #[test]
    fn every_field_a_model_declares_is_in_the_list_beside_it() {
        const SOURCES: [(&str, &str, &[&FieldSpec]); 3] = [
            ("rcc", include_str!("peripherals/rcc.rs"), rcc::DECLARED),
            ("pwr", include_str!("peripherals/pwr.rs"), pwr::DECLARED),
            ("dbg", include_str!("peripherals/dbg.rs"), dbg::DECLARED),
        ];

        for (model, source, declared) in SOURCES {
            let written: Vec<&str> = source
                .lines()
                .filter_map(|line| line.trim().strip_prefix("pub static "))
                .filter_map(|rest| rest.split_once(": FieldSpec"))
                .map(|(name, _)| name)
                .collect();
            assert!(
                !written.is_empty(),
                "{model} declares none, so this reads nothing"
            );
            let listed: Vec<&str> = declared.iter().map(|field| field.name).collect();
            let forgotten: Vec<&&str> = written
                .iter()
                .filter(|name| !listed.contains(*name))
                .collect();
            assert!(
                forgotten.is_empty(),
                "{model} declares {forgotten:?} and leaves them out of its DECLARED"
            );
        }
    }

    /// Every test a model's coverage table names is a test that exists.
    ///
    /// The last column of the table at the top of each model is the whole claim that a behavior is
    /// proved, and each name in it is written by hand against a function in another file. Renaming that
    /// function, or dropping it, leaves the table asserting something nobody runs. This is the two files
    /// held against each other, the same shape as the check above.
    ///
    /// Only the four-column tables are read: the three-column one beside them says what a model leaves
    /// out, and it names sections rather than tests.
    #[test]
    fn every_test_a_models_table_names_is_a_test_that_exists() {
        /// Every file a test named by a table may live in. A file missing from this list makes a
        /// test look absent, which fails loudly. It can't make an absent one look present.
        const WHERE_TESTS_LIVE: [&str; 30] = [
            include_str!("../../../tests/advanced_tim.rs"),
            include_str!("../../../tests/ak8963.rs"),
            include_str!("../../../tests/dbg.rs"),
            include_str!("../../../tests/dps310.rs"),
            include_str!("../../../tests/flash.rs"),
            include_str!("../../../tests/fram.rs"),
            include_str!("../../../tests/i2c.rs"),
            include_str!("../../../tests/icm20608.rs"),
            include_str!("../../../tests/icm42605.rs"),
            include_str!("../../../tests/icm42688p.rs"),
            include_str!("../../../tests/lis3mdl.rs"),
            include_str!("../../../tests/mpu9250.rs"),
            include_str!("../../../tests/ms5611.rs"),
            include_str!("../../../tests/qmc5883l.rs"),
            include_str!("memory_map.rs"),
            include_str!("../../../tests/dwt.rs"),
            include_str!("peripherals.rs"),
            include_str!("../../../tests/dma.rs"),
            include_str!("../../../tests/gpio.rs"),
            include_str!("../../../tests/iwdg.rs"),
            include_str!("../../../tests/otg.rs"),
            include_str!("../../../tests/pwr.rs"),
            include_str!("../../../tests/rcc.rs"),
            include_str!("../../../tests/rtc.rs"),
            include_str!("../../../tests/sdio.rs"),
            include_str!("../../../tests/soc.rs"),
            include_str!("../../../tests/spi.rs"),
            include_str!("../../../tests/tim.rs"),
            include_str!("../../../tests/usart.rs"),
            include_str!("../../../tests/adc.rs"),
        ];
        const MODELS: [(&str, &str); 28] = [
            ("adc", include_str!("peripherals/adc.rs")),
            ("dbg", include_str!("peripherals/dbg.rs")),
            ("dps310", include_str!("../../chip/dps310.rs")),
            ("nmea", include_str!("../../chip/nmea.rs")),
            ("memory_card", include_str!("../../chip/memory_card.rs")),
            ("ak8963", include_str!("../../chip/ak8963.rs")),
            ("flash", include_str!("peripherals/flash.rs")),
            ("fram", include_str!("../../chip/fram.rs")),
            ("i2c", include_str!("peripherals/i2c.rs")),
            ("icm20608", include_str!("../../chip/icm20608.rs")),
            ("icm42605", include_str!("../../chip/icm42605.rs")),
            ("icm42688p", include_str!("../../chip/icm42688p.rs")),
            ("lis3mdl", include_str!("../../chip/lis3mdl.rs")),
            ("mpu9250", include_str!("../../chip/mpu9250.rs")),
            ("ms5611", include_str!("../../chip/ms5611.rs")),
            ("qmc5883l", include_str!("../../chip/qmc5883l.rs")),
            ("dma", include_str!("peripherals/dma.rs")),
            ("dwt", include_str!("../../cpu/armv7m.rs")),
            ("gpio", include_str!("peripherals/gpio.rs")),
            ("iwdg", include_str!("peripherals/iwdg.rs")),
            ("otg", include_str!("peripherals/otg.rs")),
            ("pwr", include_str!("peripherals/pwr.rs")),
            ("rcc", include_str!("peripherals/rcc.rs")),
            ("rtc", include_str!("peripherals/rtc.rs")),
            ("sdio", include_str!("peripherals/sdio.rs")),
            ("spi", include_str!("peripherals/spi.rs")),
            ("tim", include_str!("peripherals/tim.rs")),
            ("usart", include_str!("peripherals/usart.rs")),
        ];

        let mut named = 0;
        let mut missing = Vec::new();
        for (model, source) in MODELS {
            let sources: Vec<&str> = WHERE_TESTS_LIVE.into_iter().chain([source]).collect();
            let rows = source
                .lines()
                .filter_map(|line| line.strip_prefix("//! |"))
                .filter(|row| !row.starts_with("---"))
                .map(|row| row.split('|').collect::<Vec<&str>>())
                .filter(|cells| cells.len() == 5);
            for cells in rows {
                for name in cells[3].split('`').skip(1).step_by(2) {
                    named += 1;
                    let defined = format!("fn {name}(");
                    if !sources.iter().any(|source| source.contains(&defined)) {
                        missing.push(format!("{model}: {name}"));
                    }
                }
            }
        }
        assert!(named > MODELS.len(), "the tables read as empty");
        assert!(
            missing.is_empty(),
            "a coverage table names a test nothing defines: {}",
            missing.join(", ")
        );
    }

    /// Every request the part wires names a channel and streams the controller has, RM0090 rev 22
    /// section 10.3.3, and an instance the part carries.
    ///
    /// The wiring is a hand-written reading of tables 43 and 44, and a stream or a channel out of range
    /// would otherwise be a panic the first time that peripheral drove a request, in the middle of a run.
    #[test]
    fn every_request_the_part_wires_names_a_channel_and_streams_the_controller_has() {
        use dma::{CHANNELS, STREAMS};

        let soc = super::super::memory_map::builder()
            .build()
            .expect("the part assembles");
        for controller in &CONTROLLERS {
            assert!(
                soc.peripheral(controller.instance).is_some(),
                "{} is not an instance",
                controller.instance
            );
            for wire in controller.wiring {
                assert!(
                    wire.channel < CHANNELS,
                    "{}'s request {} arrives on channel {}",
                    wire.instance,
                    wire.request,
                    wire.channel
                );
                assert!(
                    wire.streams.iter().all(|stream| *stream < STREAMS),
                    "{}'s request {} reaches {:?}",
                    wire.instance,
                    wire.request,
                    wire.streams
                );
                assert!(
                    Field::all()
                        .into_iter()
                        .any(|field| field.instance() == wire.instance),
                    "{} drives a request and is not an instance this part models",
                    wire.instance
                );
            }
        }
    }

    /// [`declared_fields`] is every model's, not the RCC's alone.
    ///
    /// One name from each model that declares any, so dropping a model from that chain is caught rather
    /// than leaving its fields to read as holes in ST's file. The PWR's two are the ones with no other
    /// witness: no firmware names them, so nothing else here would notice them going missing.
    #[test]
    fn the_part_declares_what_each_of_its_models_declares() {
        let names: Vec<&str> = declared_fields().map(|field| field.name).collect();
        for model in ["SW", "GPIOKEN", "MRUDS", "LPUDS"] {
            assert!(
                names.contains(&model),
                "{model} is a model's own and the part does not declare it: {names:?}"
            );
        }
    }

    /// The bit a named field of `RCC_AHB1ENR` occupies, taken from the generated table or from what
    /// a model declares where ST's file leaves the field out. RM0090 rev 22 section 6.3.10.
    fn enable_bit(name: &str) -> u64 {
        use crate::soc::stm32f427::generated::rcc;

        rcc::REGISTERS
            .iter()
            .find(|register| register.name == "AHB1ENR")
            .expect("the clock controller carries it")
            .fields
            .iter()
            .chain(declared_fields())
            .find(|field| field.name == name)
            .unwrap_or_else(|| panic!("{name} is a field nothing declares"))
            .mask()
    }

    /// Turns on all eleven port clocks the way a firmware does, over the bus, since the part gates
    /// each port on its own bit of `RCC_AHB1ENR`. RM0090 rev 22 sections 2.1.11 and 6.3.10.
    fn open_every_port_clock(mcu: &mut Stm32f427) {
        use crate::soc::stm32f427::generated::{RCC, rcc};
        use crate::soc::{Layout, Width};

        let at = RCC.base + u64::from(rcc::Register::Ahb1enr.spec().offset);
        let enables = PORTS
            .iter()
            .fold(0, |all, port| all | enable_bit(&format!("{port}EN")));
        mcu.write(VirtualNanos(0), at, Width::W32, enables)
            .expect("the clock controller holds every enable and nothing gates it");
    }

    /// Every port the part carries has a clock enable, a reset and a sleep-mode enable, at the bit its
    /// place in [`PORTS`] gives. RM0090 rev 22 sections 6.3.10, 6.3.5, and 6.3.15.
    ///
    /// It reads the RCC's table **and** what the models declare, which is the whole point: ST's file
    /// declares ports A to I and stops, so ports J and K are the model's and a check that asked only the
    /// tables would report a part with nine ports and eleven port models.
    #[test]
    fn every_port_has_its_clock_enable_its_reset_and_its_sleep_enable() {
        let mcu = Stm32f427::new().expect("the part assembles");
        let mut declared: BTreeMap<&str, (u8, u8)> = mcu
            .bus()
            .peripheral("RCC")
            .expect("RCC is an instance")
            .registers
            .iter()
            .flat_map(|register| register.fields)
            .map(|field| (field.name, (field.bit, field.width)))
            .collect();
        declared.extend(declared_fields().map(|field| (field.name, (field.bit, field.width))));

        let mut missing = Vec::new();
        for (nth, port) in PORTS.iter().enumerate() {
            let letter = port
                .strip_prefix("GPIO")
                .expect("a port is named for its letter");
            let bit = u8::try_from(nth).expect("eleven ports");
            for suffix in ["EN", "RST", "LPEN"] {
                let name = format!("GPIO{letter}{suffix}");
                if declared.get(name.as_str()) != Some(&(bit, 1)) {
                    missing.push(format!(
                        "{name} at bit {bit}: {:?}",
                        declared.get(name.as_str())
                    ));
                }
            }
        }
        assert!(
            missing.is_empty(),
            "the part carries {} ports and declares fewer sets of RCC bits: {}",
            PORTS.len(),
            missing.join(", ")
        );
    }

    /// Every instance the part models answers behind a clock, except the clock controller, the
    /// backup domain, the debug component, the processor's cycle counter, the flash interface and
    /// the independent watchdog.
    ///
    /// RM0090 rev 22 section 2.1.11 excepts the SRAM and the flash interface, and section 6.2.9
    /// clocks the watchdog from the LSI with no bus enable. So a model added to this part without a
    /// gate beside it is a peripheral that answers before its clock does.
    /// The table of gates is in `memory_map.rs`. This asks the built part rather than that table,
    /// so adding one without the other is what it catches.
    #[test]
    fn every_modeled_instance_but_the_clock_controller_answers_behind_a_clock() {
        use crate::soc::{Fault, Width};

        let mut mcu = Stm32f427::new().expect("the part assembles");
        for field in Field::all() {
            let instance = field.instance();
            let base = mcu
                .bus()
                .peripheral(instance)
                .unwrap_or_else(|| panic!("{instance} is an instance"))
                .base;
            let answered = mcu.read(VirtualNanos(0), base, Width::W32);
            if instance == crate::cpu::armv7m::DWT || instance == "DBG" {
                // Section 6.3 gates what ST built around the core. The processor's own blocks and
                // the debug component, on the core's own private peripheral bus, aren't
                // in it and have no enable to be behind, which is why both answer with the tree
                // untouched.
                assert!(
                    answered.is_ok(),
                    "a core-adjacent block is not on the part's clock tree: {answered:?}"
                );
            } else if instance == "RTC" {
                // Section 5.5.1 bit 8 and section 26.3.5 protect the backup domain against
                // parasitic *write* access. Neither takes its registers dark. `memory_map.rs` gates
                // its writes on `DBP` for that reason and leaves reads alone, which is the same
                // reading the clock controller's own `BDCR` already gets. ArduPilot is the witness:
                // it reads all twenty backup registers with `RTCEN` still clear, and a read gate
                // here would refuse it.
                assert!(
                    answered.is_ok(),
                    "the backup domain is write-protected, not gated: {answered:?}"
                );
            } else if instance == "RCC" {
                assert!(
                    answered.is_ok(),
                    "the clock controller holds every enable, so nothing can gate it: {answered:?}"
                );
            } else if instance == "IWDG" {
                // Sections 6.2.9 and 6.3: the LSI clocks the watchdog, and no AHB or APB enable gates it.
                assert!(
                    answered.is_ok(),
                    "the independent watchdog has no clock gate: {answered:?}"
                );
            } else if instance == "FLASH" {
                assert!(
                    answered.is_ok(),
                    "2.1.11 excepts the flash memory interface as well as the SRAM: {answered:?}"
                );
            } else {
                assert!(
                    matches!(answered, Err(Fault::Gated { .. })),
                    "{instance} answers with every clock still off: {answered:?}"
                );
            }
        }
    }

    /// Each port is its own port: what one drives, no other reads, and what one stores, no other holds.
    ///
    /// The eleven share a layout now, so [`Operate::check`] can't tell one from another. It compares
    /// the model's layout to the slot's and they all match. This is what can: it drives a pin
    /// through one port's own model and reads every port back over the bus. So a `split` handing
    /// over the wrong element, or a slot paired with the wrong register file, shows up as the level
    /// or the value landing somewhere else.
    #[test]
    fn a_port_drives_and_holds_only_its_own() {
        use crate::device::Level;
        use crate::soc::stm32f427::generated::gpioa::Register;
        use crate::soc::{Layout, Width};
        use gpio::Pin;

        let pin = Pin::new(0).expect("a port has a pin zero");
        let idr = u64::from(Register::Idr.spec().offset);
        for (nth, driven) in PORTS.iter().enumerate() {
            let mut mcu = Stm32f427::new().expect("the part assembles");
            open_every_port_clock(&mut mcu);
            mcu.drive_port(VirtualNanos(0), nth, |port, registers, context| {
                port.drive(pin, Some(Level::High), registers, context);
            });
            let sentinel = 1 << nth;
            mcu.port(nth).1.set(Register::Odr, sentinel);
            for (other, name) in PORTS.iter().enumerate() {
                let base = mcu
                    .bus()
                    .peripheral(name)
                    .expect("a port is an instance")
                    .base;
                let read = mcu
                    .read(VirtualNanos(0), base + idr, Width::W32)
                    .expect("IDR answers at its own offset");
                assert_eq!(
                    read & 1,
                    u64::from(other == nth),
                    "{name} reads a pin driven on {driven}"
                );
                let held = mcu
                    .registers(name)
                    .expect("a port is an instance")
                    .get(Register::Odr);
                assert_eq!(
                    held,
                    if other == nth { sentinel } else { 0 },
                    "{name} holds what was stored on {driven}"
                );
            }
        }
    }

    #[test]
    fn every_field_answers_for_the_one_instance_it_is_named_for() {
        let mut mcu = Stm32f427::new().expect("the part assembles");
        let slots = mcu.bus().slots().len();
        let mut answered: Vec<(Field, &'static str)> = (0..slots)
            .filter_map(|slot| {
                let field = mcu.wiring[slot];
                let name = mcu.bus().slots()[slot].peripheral().name;
                mcu.split(slot).1.map(|_| (field, name))
            })
            .collect();
        answered.sort_by_key(|(_, name)| *name);
        let mut expected: Vec<(Field, &'static str)> = Field::all()
            .into_iter()
            .map(|field| (field, field.instance()))
            .collect();
        expected.sort_by_key(|(_, name)| *name);
        assert_eq!(
            answered, expected,
            "every field the part has answers for exactly the instance it is named for"
        );
    }

    #[test]
    fn the_part_answers_for_every_serial_interface_and_neither_extended_block() {
        let carried: Vec<&str> = instances_of(&super::super::generated::spi1::REGISTERS)
            .map(|one| one.name)
            .collect();
        for instance in SERIAL_INTERFACES {
            assert!(
                carried.contains(&instance),
                "{instance} is not an instance of the serial interface's layout"
            );
        }
        // Section 28.4.2 gives these the I2S's job, so the part doesn't answer for them.
        for extended in ["I2S2ext", "I2S3ext"] {
            assert!(carried.contains(&extended));
            assert!(!SERIAL_INTERFACES.contains(&extended));
        }
    }

    #[test]
    fn the_part_says_how_much_of_itself_it_models() {
        let mut mcu = Stm32f427::new().expect("the part assembles");
        let instances = mcu.bus().slots().len();
        let modeled = (0..instances)
            .filter(|&slot| mcu.split(slot).1.is_some())
            .count();
        assert_eq!(modeled, Field::all().len());
        assert!(modeled < instances);
        println!("{modeled} of {instances} instances carry a model");
    }
}