aboutsummaryrefslogtreecommitdiffstats
path: root/bits.py
diff options
context:
space:
mode:
Diffstat (limited to 'bits.py')
-rw-r--r--bits.py52
1 files changed, 51 insertions, 1 deletions
diff --git a/bits.py b/bits.py
index 34284a2..dd49665 100644
--- a/bits.py
+++ b/bits.py
@@ -283,7 +283,7 @@ class LabelRef(WordBase):
Bitfield(0xa, 8)
"""
if self.label not in labels:
- raise ValueError("label '{}' unresolved".format(self.label))
+ raise ValueError("undefined label '{}'".format(self.label))
value = labels[self.label] + self.offset
@@ -404,3 +404,53 @@ def from_part(part):
val = int(part[0])
size = part[1]
return Bitfield(val, int(size))
+
+global_slice = slice
+ref_re = re.compile(r'^([^\[+-]+)(?:([+-]\d+))?$')
+slice_re = re.compile(r'^\[(\d+):(\d+)]$')
+
+def ref(val, default_slice=None):
+ """ add a default slice spec to labels if missing.
+
+ >>> ref(('label', 'imm12'))
+ LabelRef('label', 0, ('imm', 12), 11:0)
+ >>> ref(('label', 'imm12'), slice(12, 1))
+ LabelRef('label', 0, ('imm', 12), 12:1)
+ >>> ref(('label-4', 'imm12'), slice(12, 1))
+ LabelRef('label', -4, ('imm', 12), 12:1)
+ >>> ref(('label', 'imm12', '[14:3]'), slice(12, 1))
+ LabelRef('label', 0, ('imm', 12), 14:3)
+ >>> ref(('label+4', 'imm12', '[14:3]'), slice(12, 1))
+ LabelRef('label', 4, ('imm', 12), 14:3)
+ >>> ref(('label', 'imm12', '[14:3]'), slice(12, 1))
+ LabelRef('label', 0, ('imm', 12), 14:3)
+ >>> ref(('label', 'imm12', '[31:0]'), slice(11, 0))
+ Traceback (most recent call last):
+ ...
+ AssertionError: expected 12 bit slice, got label/imm12/[31:0]
+ """
+ slice = None
+ if len(val) == 3:
+ label_offset, mode, slice = val
+ elif len(val) == 2:
+ label_offset, mode = val
+ else:
+ raise ValueError("expected label reference, got {}".format(val))
+
+ match = ref_re.match(label_offset)
+ assert match, ValueError("invalid label reference")
+ label, offset = match.group(1), int(match.group(2) or 0)
+
+ if isinstance(slice, str):
+ match = slice_re.match(slice)
+ assert match, ValueError("invalid slice syntax")
+ a, b = match.groups()
+ slice = global_slice(int(a), int(b))
+
+ ref = LabelRef(label, offset, mode, slice or default_slice)
+
+ if default_slice:
+ expected = default_slice.start - default_slice.stop + 1
+ assert expected == ref.size, ValueError("expected {} bit slice, got {}".format(expected, ref))
+
+ return ref