Implementing an 8 bit fixed point register
Grant Edwards
grante at visi.com
Wed Jul 2 00:44:19 CEST 2008
On 2008-07-01, Terry Reedy <tjreedy at udel.edu> wrote:
>>> A bytearray subclass could enforce that all 'bits' (stored as
>>> bytes) are 0 or 1, have a customized representation to your
>>> taste, and add methods like .flipall().
>>
>> It seems like implementing ALU operations on such arrays would
>> be a lot more work than implementing bit-indexing on a type
>> derived on a more "integer" like base. I'm pretty fuzzy on how
>> one sub-classes basic things like integers, so maybe I'm all
>> wet, and adding __getitem__ and __setitem__ to an integer type
>> isn't even possible.
>
> If one only wants bit operations, then the array approach is
> easy. If one only wants int arithmetic and all-bits logic,
> then int approach is easy. OP did not completely specify
> needs.
He said he's writing a microprocessor simulator, so he's going
to want integer operations, all-bits logical operations, and
individual bit acess (by number and by name) and bit-slice
access.
> The problem with the int approach is that ints are immutable.
That dawned on me after I started googling around a little.
> Therefore, if one wants to subclass int to hide the bit
> masking for the bit operations, one must override *every*
> operation one might use, including all arithmetic and all-bits
> logic, even when the int operation gives the correct answer
> other than the class of the result.
Since we're doing fixed-width operations, Python's int
operations don't give the correct answer other than the class
of the result.
> class bits(int):
> ...
> def __add__(self,other):
> return bit(self+other)
> ...
>
> If one does not,
>
> a,b = bits(1),bits(2)
> c = a+b #c is now an int, not a bits
>
> So there is a tendency to not subclass and instead either leave the
> extra functionality unmasked in repeated code or to put it in functions
> instead.
>
> setters = (1,2,4,8,16,32,64, ..., 2147483648)# slightly pseudocode
> unsetters = (~1,~2,~4,...~2147483648) # ditto
> def bitset(n, bit): return n | setters[bit]
> def bitunset(n,bit): return n & unsetters[bit]
On a machine with a barrel shifter, it's probably faster to do
this:
def bitset(n,bit): return n | (1<<bit)
def bitclr(n,bit): return n & ~(1<<bit)
But, your approach could be easily modified to support slices:
import operator
masks = [(1<<n) for n in range(32)]
def mask(bits):
if type(bits) is slice:
return reduce(operator.__or__,masks[bits])
return masks[bits]
def bitset(n,bits):
return n | mask(bits)
Is there a literal syntax for a slice? This doesn't seem to
work:
bitset(n,0:4)
> thus not getting the nice reg[n] functionality, nor an easy
> display of individual bits without callings *another*
> function.
>
> One the other hand, with mutable arrays, setting bits is a
> mutation and so no override of __setitem__ is required unless
> one wants to be fancy and enforce setting to 0 or 1.
More importantly, I presume that slices are supported so when
you need values of bit-fields, you can do this:
op = instruction[6:8]
src = instruction[3:6]
dest = instruction[0:3]
The half-closed interval notation for slices is probably going
to drive the programmer up the wall because all of the
documentation that's being followed uses closed intervals.
> It is a trade-off.
And Python programmers are awfully spoiled. :)
--
Grant Edwards grante Yow! I think my career
at is ruined!
visi.com
More information about the Python-list
mailing list