+# sigh create little-ended versions of bitfield flags
+def botchify(bekls, lekls):
+ for attr in dir(bekls):
+ if attr[0] == '_':
+ continue
+ setattr(lekls, attr, 63-getattr(bekls, attr))
+
+
+# Can't think of a better place to put these functions.
+# Return an arbitrary subfield of a larger field.
+def field_slice(msb0_start, msb0_end, field_width=64):
+ """field_slice
+
+ Answers with a subfield slice of the signal r ("register"),
+ where the start and end bits use IBM "MSB 0" conventions.
+
+ see: https://en.wikipedia.org/wiki/Bit_numbering#MSB_0_bit_numbering
+
+ * assertion: msb0_start < msb0_end.
+ * The range specified is inclusive on both ends.
+ * field_width specifies the total number of bits (note: not bits-1)
+ """
+ if msb0_start >= msb0_end:
+ raise ValueError(
+ "start ({}) must be less than end ({})".format(msb0_start, msb0_end)
+ )
+ # sigh. MSB0 (IBM numbering) is inverted. converting to python
+ # we *swap names* so as not to get confused by having "end, start"
+ lsb0_end = (field_width-1) - msb0_start
+ lsb0_start = (field_width-1) - msb0_end
+
+ return slice(lsb0_start, lsb0_end + 1)
+
+
+def field(r, msb0_start, msb0_end=None, field_width=64):
+ """Answers with a subfield of the signal r ("register"), where
+ the start and end bits use IBM conventions. start < end, if
+ end is provided. The range specified is inclusive on both ends.
+
+ Answers with a subfield of the signal r ("register"),
+ where the start and end bits use IBM "MSB 0" conventions.
+ If end is not provided, a single bit subfield is returned.
+
+ see: https://en.wikipedia.org/wiki/Bit_numbering#MSB_0_bit_numbering
+
+ * assertion: msb0_start < msb0_end.
+ * The range specified is inclusive on both ends.
+ * field_width specifies the total number of bits (note: not bits-1)
+
+ Example usage:
+
+ comb += field(insn, 0, 6, field_width=32).eq(17)
+ # NOTE: NEVER DIRECTLY ACCESS OPCODE FIELDS IN INSTRUCTIONS.
+ # This example is purely for illustrative purposes only.
+ # Use self.fields.FormXYZ.etcetc instead.
+
+ comb += field(msr, MSRb.TEs, MSRb.TEe).eq(0)
+
+ Proof by substitution:
+
+ field(insn, 0, 6, field_width=32).eq(17)
+ == insn[field_slice(0, 6, field_width=32)].eq(17)
+ == insn[slice((31-6), (31-0)+1)].eq(17)
+ == insn[slice(25, 32)].eq(17)
+ == insn[25:32].eq(17)
+
+ field(msr, MSRb.TEs, MSRb.TEe).eq(0)
+ == field(msr, 53, 54).eq(0)
+ == msr[field_slice(53, 54)].eq(0)
+ == msr[slice((63-54), (63-53)+1)].eq(0) # note cross-over!
+ == msr[slice(9, 11)].eq(0)
+ == msr[9:11].eq(0)
+ """
+ if msb0_end is None:
+ return r[(field_width - 1) - msb0_start]
+ else:
+ return r[field_slice(msb0_start, msb0_end)]
+
+