diff --git a/tools/bifrost-assemble.py b/tools/bifrost-assemble.py index cfdc607d0430706c7b80958eb5d2f4c2373e7e0c..469c676d0fd7b4fa665cb8426fe2422cd04c7f07 100755 --- a/tools/bifrost-assemble.py +++ b/tools/bifrost-assemble.py @@ -956,18 +956,19 @@ class ImmediateSlot: return ConstantSrc(token.read_type == ImmediateToken.ReadType.HIGH64) def encode_contents(self): - return sum(Bits(length=t.bitlen, uint=t.value) for t in self.contents) + return sum(Bits(length=t.bitlen, uint=t.value) for t in + reversed(self.contents)) def encode_const_field(self): - return bitstring.pack('uint:1=0, uint:3, bits:4', - self.IDX_MAP[self.idx], - self.encode_contents()[60:64]) + encoded = BitArray(8) + encoded[1:4] = self.IDX_MAP[self.idx] + encoded[4:8] = self.encode_contents()[60:64] + return encoded def __repr__(self): return "" % ( self.idx, id(self), self.contents) - class Uniform: def __init__(self, idx): self.idx = idx @@ -1110,6 +1111,24 @@ class Clause: MAX_CONSTS_ALLOWED = 5 # FIXME: maybe make this 6 later? + QUADWORD_FORMATS = { + # (instructions, constants): pos + (1,0): 0x0, + (2,0): 0x1, + (4,0): 0x2, + (3,1): 0x3, + (5,1): 0x4, + (4,2): 0x5, + (7,0): 0x6, + (6,1): 0x7, + (5,3): 0x8, + (8,1): 0x9, + (7,2): 0xa, + (6,3): 0xb, + (8,3): 0xc, + (7,4): 0xd + } + def _header_flag(func): old_func = func def func(self, value): @@ -1426,6 +1445,11 @@ class Clause: # immediate zero slot. if inst.has_pending_immediates(): pending = inst.reg_file.const_port + # FIXME: it looks like the compiler makes some interesting + # decisions regarding where it puts dummy clauses, for some + # reason consts 8/9 are swapped with consts 10/11 when the + # last instruction is the one reusing the same constant twice + # (and thus only requiring that half the slot be filled) if all(t.value == 0 for t in pending): inst.resolve_immediates(self, ImmediateZeroSlot) elif pending.bitlen == 64: @@ -1451,6 +1475,7 @@ class Clause: first_inst.reg_file.add_reg_write(write.idx, stage) del self.__pending_writes + # Resolve any pending state in our instructions for inst in self.instructions: inst.reg_file.assign_reg_ports() @@ -1468,10 +1493,8 @@ class Clause: inst.resolve_immediates(self, slot) self.immediate_slots.append(slot) - # TODO: Make sure we return whether or not the last format we used - # contained an inline immediate @staticmethod - def _next_immediate_to_encode(cls, immediates): + def _next_immediate_to_encode(immediates): if immediates: return immediates.pop(0) else: @@ -1524,7 +1547,6 @@ class Clause: # Format 3 quadword = BitArray(128) i3 = instructions.pop(0) if instructions else None - used_fmt_3_2 = False if not i3: # Format 3.1 @@ -1538,9 +1560,8 @@ class Clause: quadword[15:45] = i2[3:33] quadword[60:120] = next_immediate[0:60] quadword[120:128] = tag - elif instructions: + elif len(instructions) == 1: # Format 3.2 - used_fmt_3_2 = True next_immediate = self._next_immediate_to_encode(immediates) tag = 0b10 @@ -1552,7 +1573,9 @@ class Clause: quadword[125:128] = i2[0:3] else: # Format 3.3 - if immediates: + if instructions: + tag = 0b00000001 + elif immediates: tag = 0b00000101 else: tag = 0b01000101 @@ -1565,14 +1588,14 @@ class Clause: encoded.append(quadword) if not instructions: - return encoded, packed_immediate + return encoded # Format 4 quadword = BitArray(128) i4 = instructions.pop(0) i5 = instructions.pop(0) if instructions else None - if used_fmt_3_2: + if not i5: # Format 4.1 if immediates: tag = 0b00010 @@ -1657,11 +1680,40 @@ class Clause: return encoded def encode(self): - encoded = BitString() immediates = [s.encode_contents() for s in self.immediate_slots] - # TODO: FINISH IT. - return self._encode_quadwords(immediates) + encoded = BitStream() + instructions = self._encode_quadwords(immediates) + encoded.append(instructions) + + # We may have managed to pack one of the constants into the previous + # quadword + if len(immediates) < len(self.immediate_slots): + immediate_count = 1 + else: + immediate_count = 0 + + instruction_count = len(self.instructions) + while immediates: + quadword = BitArray(128) + if len(immediates) > 2: + # More constants follow + tag = 0b0011 + else: + tag = 0b0111 + + quadword[60:120] = immediates.pop(0)[0:60] + if immediates: + quadword[0:60] = immediates.pop(0)[0:60] + + quadword[120:124] = tag + quadword[124:128] = self.QUADWORD_FORMATS[instruction_count, + immediate_count] + + encoded.append(quadword) + immediate_count += 2 + + return encoded def dump(self): print('Clause #%d' % self.idx)