Skip to content

Commit d2ee0f5

Browse files
committed
Unify representations of bit positions.
We now use an enumeration for the bit positions used in the SKM instruction, and make use of this in the implementation of memory operations.
1 parent 28cf99e commit d2ee0f5

File tree

8 files changed

+323
-183
lines changed

8 files changed

+323
-183
lines changed

base/src/bitselect.rs

Lines changed: 114 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
1-
use super::onescomplement::unsigned::Unsigned36Bit;
1+
use std::fmt::{Display, Write};
22

3-
#[repr(u8)]
4-
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
5-
pub enum Quarter {
6-
Q1 = 0,
7-
Q2 = 1,
8-
Q3 = 2,
9-
Q4 = 3,
10-
}
3+
use super::onescomplement::unsigned::Unsigned36Bit;
4+
use super::quarters::Quarter;
115

126
#[repr(u8)]
13-
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
14-
pub enum QuarterBit {
7+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
8+
pub enum BitPos {
159
B1 = 0,
1610
B2 = 1,
1711
B3 = 2,
@@ -23,55 +17,100 @@ pub enum QuarterBit {
2317
B9 = 8,
2418
}
2519

26-
const fn bit_select_mask(quarter: Quarter, bit: QuarterBit) -> u64 {
27-
let shift = (quarter as u32) * 9 + (bit as u32);
28-
1_u64 << shift
20+
impl Display for BitPos {
21+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22+
f.write_char(match self {
23+
BitPos::B1 => '1',
24+
BitPos::B2 => '2',
25+
BitPos::B3 => '3',
26+
BitPos::B4 => '4',
27+
BitPos::B5 => '5',
28+
BitPos::B6 => '6',
29+
BitPos::B7 => '7',
30+
BitPos::B8 => '8',
31+
BitPos::B9 => '9',
32+
})
33+
}
34+
}
35+
36+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
37+
pub struct BitSelector {
38+
pub quarter: Quarter,
39+
/// `bitpos` values 1 to 9 inclusive are normal bit positions in a
40+
/// quarter. 0 is a valid value but not a valid bit (so a default
41+
/// will be used when SKM tests bit 0). 10 is the meta bit. 11
42+
/// is the parity bit stored in memory. 12 is the parity value
43+
/// computed from the bits stored in memory.
44+
pub bitpos: BitPos,
45+
}
46+
47+
impl BitSelector {
48+
pub const fn raw_mask(&self) -> u64 {
49+
let shift = (self.quarter as u32) * 9 + (self.bitpos as u32);
50+
1_u64 << shift
51+
}
52+
53+
pub fn mask(&self) -> Unsigned36Bit {
54+
Unsigned36Bit::try_from(self.raw_mask())
55+
.expect("bit selector mask values cannot be outside the range of Unsigned36Bit")
56+
}
57+
}
58+
59+
impl Display for BitSelector {
60+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61+
write!(f, "{}.{}", &self.quarter, &self.bitpos)
62+
}
63+
}
64+
65+
#[cfg(test)]
66+
const fn bit_select_mask(quarter: Quarter, bitpos: BitPos) -> u64 {
67+
BitSelector { quarter, bitpos }.raw_mask()
2968
}
3069

3170
#[test]
3271
fn test_bit_select_mask_q1() {
3372
assert_eq!(
34-
bit_select_mask(Quarter::Q1, QuarterBit::B1),
73+
bit_select_mask(Quarter::Q1, BitPos::B1),
3574
0o001_u64,
3675
"failed for bit 1.1"
3776
);
3877
assert_eq!(
39-
bit_select_mask(Quarter::Q1, QuarterBit::B2),
78+
bit_select_mask(Quarter::Q1, BitPos::B2),
4079
0o002_u64,
4180
"failed for bit 1.2"
4281
);
4382
assert_eq!(
44-
bit_select_mask(Quarter::Q1, QuarterBit::B3),
83+
bit_select_mask(Quarter::Q1, BitPos::B3),
4584
0o004_u64,
4685
"failed for bit 1.3"
4786
);
4887
assert_eq!(
49-
bit_select_mask(Quarter::Q1, QuarterBit::B4),
88+
bit_select_mask(Quarter::Q1, BitPos::B4),
5089
0o010_u64,
5190
"failed for bit 1.4"
5291
);
5392
assert_eq!(
54-
bit_select_mask(Quarter::Q1, QuarterBit::B5),
93+
bit_select_mask(Quarter::Q1, BitPos::B5),
5594
0o020_u64,
5695
"failed for bit 1.5"
5796
);
5897
assert_eq!(
59-
bit_select_mask(Quarter::Q1, QuarterBit::B6),
98+
bit_select_mask(Quarter::Q1, BitPos::B6),
6099
0o040_u64,
61100
"failed for bit 1.6"
62101
);
63102
assert_eq!(
64-
bit_select_mask(Quarter::Q1, QuarterBit::B7),
103+
bit_select_mask(Quarter::Q1, BitPos::B7),
65104
0o100_u64,
66105
"failed for bit 1.7"
67106
);
68107
assert_eq!(
69-
bit_select_mask(Quarter::Q1, QuarterBit::B8),
108+
bit_select_mask(Quarter::Q1, BitPos::B8),
70109
0o200_u64,
71110
"failed for bit 1.8"
72111
);
73112
assert_eq!(
74-
bit_select_mask(Quarter::Q1, QuarterBit::B9),
113+
bit_select_mask(Quarter::Q1, BitPos::B9),
75114
0o400_u64,
76115
"failed for bit 1.9"
77116
);
@@ -80,47 +119,47 @@ fn test_bit_select_mask_q1() {
80119
#[test]
81120
fn test_bit_select_mask_q2() {
82121
assert_eq!(
83-
bit_select_mask(Quarter::Q2, QuarterBit::B1),
122+
bit_select_mask(Quarter::Q2, BitPos::B1),
84123
0o001_000_u64,
85124
"failed for bit 2.1"
86125
);
87126
assert_eq!(
88-
bit_select_mask(Quarter::Q2, QuarterBit::B2),
127+
bit_select_mask(Quarter::Q2, BitPos::B2),
89128
0o002_000_u64,
90129
"failed for bit 2.2"
91130
);
92131
assert_eq!(
93-
bit_select_mask(Quarter::Q2, QuarterBit::B3),
132+
bit_select_mask(Quarter::Q2, BitPos::B3),
94133
0o004_000_u64,
95134
"failed for bit 2.3"
96135
);
97136
assert_eq!(
98-
bit_select_mask(Quarter::Q2, QuarterBit::B4),
137+
bit_select_mask(Quarter::Q2, BitPos::B4),
99138
0o010_000_u64,
100139
"failed for bit 2.4"
101140
);
102141
assert_eq!(
103-
bit_select_mask(Quarter::Q2, QuarterBit::B5),
142+
bit_select_mask(Quarter::Q2, BitPos::B5),
104143
0o020_000_u64,
105144
"failed for bit 2.5"
106145
);
107146
assert_eq!(
108-
bit_select_mask(Quarter::Q2, QuarterBit::B6),
147+
bit_select_mask(Quarter::Q2, BitPos::B6),
109148
0o040_000_u64,
110149
"failed for bit 2.6"
111150
);
112151
assert_eq!(
113-
bit_select_mask(Quarter::Q2, QuarterBit::B7),
152+
bit_select_mask(Quarter::Q2, BitPos::B7),
114153
0o100_000_u64,
115154
"failed for bit 2.7"
116155
);
117156
assert_eq!(
118-
bit_select_mask(Quarter::Q2, QuarterBit::B8),
157+
bit_select_mask(Quarter::Q2, BitPos::B8),
119158
0o200_000_u64,
120159
"failed for bit 2.8"
121160
);
122161
assert_eq!(
123-
bit_select_mask(Quarter::Q2, QuarterBit::B9),
162+
bit_select_mask(Quarter::Q2, BitPos::B9),
124163
0o400_000_u64,
125164
"failed for bit 2.9"
126165
);
@@ -129,47 +168,47 @@ fn test_bit_select_mask_q2() {
129168
#[test]
130169
fn test_bit_select_mask_q3() {
131170
assert_eq!(
132-
bit_select_mask(Quarter::Q3, QuarterBit::B1),
171+
bit_select_mask(Quarter::Q3, BitPos::B1),
133172
0o001_000_000_u64,
134173
"failed for bit 3.1"
135174
);
136175
assert_eq!(
137-
bit_select_mask(Quarter::Q3, QuarterBit::B2),
176+
bit_select_mask(Quarter::Q3, BitPos::B2),
138177
0o002_000_000_u64,
139178
"failed for bit 3.2"
140179
);
141180
assert_eq!(
142-
bit_select_mask(Quarter::Q3, QuarterBit::B3),
181+
bit_select_mask(Quarter::Q3, BitPos::B3),
143182
0o004_000_000_u64,
144183
"failed for bit 3.3"
145184
);
146185
assert_eq!(
147-
bit_select_mask(Quarter::Q3, QuarterBit::B4),
186+
bit_select_mask(Quarter::Q3, BitPos::B4),
148187
0o010_000_000_u64,
149188
"failed for bit 3.4"
150189
);
151190
assert_eq!(
152-
bit_select_mask(Quarter::Q3, QuarterBit::B5),
191+
bit_select_mask(Quarter::Q3, BitPos::B5),
153192
0o020_000_000_u64,
154193
"failed for bit 3.5"
155194
);
156195
assert_eq!(
157-
bit_select_mask(Quarter::Q3, QuarterBit::B6),
196+
bit_select_mask(Quarter::Q3, BitPos::B6),
158197
0o040_000_000_u64,
159198
"failed for bit 3.6"
160199
);
161200
assert_eq!(
162-
bit_select_mask(Quarter::Q3, QuarterBit::B7),
201+
bit_select_mask(Quarter::Q3, BitPos::B7),
163202
0o100_000_000_u64,
164203
"failed for bit 3.7"
165204
);
166205
assert_eq!(
167-
bit_select_mask(Quarter::Q3, QuarterBit::B8),
206+
bit_select_mask(Quarter::Q3, BitPos::B8),
168207
0o200_000_000_u64,
169208
"failed for bit 3.8"
170209
);
171210
assert_eq!(
172-
bit_select_mask(Quarter::Q3, QuarterBit::B9),
211+
bit_select_mask(Quarter::Q3, BitPos::B9),
173212
0o400_000_000_u64,
174213
"failed for bit 3.9"
175214
);
@@ -178,95 +217,94 @@ fn test_bit_select_mask_q3() {
178217
#[test]
179218
fn test_bit_select_mask_q4() {
180219
assert_eq!(
181-
bit_select_mask(Quarter::Q4, QuarterBit::B1),
220+
bit_select_mask(Quarter::Q4, BitPos::B1),
182221
0o001_000_000_000_u64,
183222
"failed for bit 4.1"
184223
);
185224
assert_eq!(
186-
bit_select_mask(Quarter::Q4, QuarterBit::B2),
225+
bit_select_mask(Quarter::Q4, BitPos::B2),
187226
0o002_000_000_000_u64,
188227
"failed for bit 4.2"
189228
);
190229
assert_eq!(
191-
bit_select_mask(Quarter::Q4, QuarterBit::B3),
230+
bit_select_mask(Quarter::Q4, BitPos::B3),
192231
0o004_000_000_000_u64,
193232
"failed for bit 4.3"
194233
);
195234
assert_eq!(
196-
bit_select_mask(Quarter::Q4, QuarterBit::B4),
235+
bit_select_mask(Quarter::Q4, BitPos::B4),
197236
0o010_000_000_000_u64,
198237
"failed for bit 4.4"
199238
);
200239
assert_eq!(
201-
bit_select_mask(Quarter::Q4, QuarterBit::B5),
240+
bit_select_mask(Quarter::Q4, BitPos::B5),
202241
0o020_000_000_000_u64,
203242
"failed for bit 4.5"
204243
);
205244
assert_eq!(
206-
bit_select_mask(Quarter::Q4, QuarterBit::B6),
245+
bit_select_mask(Quarter::Q4, BitPos::B6),
207246
0o040_000_000_000_u64,
208247
"failed for bit 4.6"
209248
);
210249
assert_eq!(
211-
bit_select_mask(Quarter::Q4, QuarterBit::B7),
250+
bit_select_mask(Quarter::Q4, BitPos::B7),
212251
0o100_000_000_000_u64,
213252
"failed for bit 4.7"
214253
);
215254
assert_eq!(
216-
bit_select_mask(Quarter::Q4, QuarterBit::B8),
255+
bit_select_mask(Quarter::Q4, BitPos::B8),
217256
0o200_000_000_000_u64,
218257
"failed for bit 4.8"
219258
);
220259
assert_eq!(
221-
bit_select_mask(Quarter::Q4, QuarterBit::B9),
260+
bit_select_mask(Quarter::Q4, BitPos::B9),
222261
0o400_000_000_000_u64,
223262
"failed for bit 4.9"
224263
);
225264
}
226265

227-
pub const fn bit_select(value: Unsigned36Bit, quarter: Quarter, bit: QuarterBit) -> bool {
228-
let mask = bit_select_mask(quarter, bit);
229-
value.bits & mask != 0
230-
}
231-
232266
#[cfg(test)]
233-
fn all_bit_selectors() -> Vec<(Quarter, QuarterBit)> {
267+
fn all_bit_selectors() -> Vec<BitSelector> {
234268
let mut result = Vec::with_capacity(36);
235-
for q in [Quarter::Q1, Quarter::Q2, Quarter::Q3, Quarter::Q4] {
236-
for b in [
237-
QuarterBit::B1,
238-
QuarterBit::B2,
239-
QuarterBit::B3,
240-
QuarterBit::B4,
241-
QuarterBit::B5,
242-
QuarterBit::B6,
243-
QuarterBit::B7,
244-
QuarterBit::B8,
245-
QuarterBit::B9,
269+
for quarter in [Quarter::Q1, Quarter::Q2, Quarter::Q3, Quarter::Q4] {
270+
for bitpos in [
271+
BitPos::B1,
272+
BitPos::B2,
273+
BitPos::B3,
274+
BitPos::B4,
275+
BitPos::B5,
276+
BitPos::B6,
277+
BitPos::B7,
278+
BitPos::B8,
279+
BitPos::B9,
246280
] {
247-
result.push((q, b));
281+
result.push(BitSelector { quarter, bitpos })
248282
}
249283
}
250284
result
251285
}
252286

287+
pub const fn bit_select(value: Unsigned36Bit, selector: BitSelector) -> bool {
288+
value.bits & selector.raw_mask() != 0
289+
}
290+
253291
#[test]
254292
fn test_bit_select() {
255-
for (bitpos, (quarter_of_bit_to_set, bit_to_set)) in all_bit_selectors().into_iter().enumerate()
256-
{
293+
for (bitpos, selector) in all_bit_selectors().into_iter().enumerate() {
257294
let just_that_bit: Unsigned36Bit =
258295
Unsigned36Bit::try_from(1_u64 << bitpos).expect("test bit should not be out of range");
259-
for (quarter_to_test, bit_to_test) in all_bit_selectors() {
260-
if (quarter_to_test, bit_to_test) == (quarter_of_bit_to_set, bit_to_set) {
296+
for selector_to_test in all_bit_selectors() {
297+
let found_value: bool = bit_select(just_that_bit, selector_to_test);
298+
if selector_to_test == selector {
261299
// The quarter and bit number is the one we had set, so the value should be 1.
262300
assert!(
263-
bit_select(just_that_bit, quarter_to_test, bit_to_test),
264-
"bit {quarter_to_test:?}.{bit_to_test:?} should be set in {just_that_bit:012o}"
301+
found_value,
302+
"bit {selector_to_test} should be set in {just_that_bit:012o}"
265303
);
266304
} else {
267305
assert!(
268-
!bit_select(just_that_bit, quarter_to_test, bit_to_test),
269-
"bit {quarter_to_test:?}.{bit_to_test:?} should be unset in {just_that_bit:012o}"
306+
!found_value,
307+
"bit {selector_to_test} should be unset in {just_that_bit:012o}"
270308
);
271309
}
272310
}

0 commit comments

Comments
 (0)