Implementing an 8 bit fixed point register

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • nickooooola

    Implementing an 8 bit fixed point register

    Hello to all
    I'm about to write a simulator for a microcontroller in python
    (why python? because I love it!!!)

    but I have a problem.

    The registry of this processor are all 8 bit long (and 10 bit for some
    other strange register)
    and I need to simulate the fixed point behaviour of the register,
    and to access the single bit.

    f.x. (this is a pseudo python session, only for understanding)
    >>reg1 = fixed_int(8)
    >>reg2 = fixed_int(10)
    >>reg1[0].set()
    or
    >>reg1[0] = 1 # or True? how to rapresent a binary bit
    >>reg1[0]
    1
    >>reg1[1]
    0
    >>reg1[9]
    <exception .... blah blah not in range>
    >>reg2 = 0x7FE # in binary 11111111110 , or 11 bit long
    >>reg2
    0x7FE
    #or 1111111110, the memorization truncate the upper bits ( or perhaps
    generate an exception?)
    >>reg2 += 0x02 #the result is 10000000000, again not contained in 10 bit
    >>reg2
    0x00
    # truncated again
    >>myprocessor.f lags['z']
    1
    # or True? Z flag indicated an overflow in arithmetic operations

    Is possibile to do so in python?

    thanks
  • moogyd@yahoo.co.uk

    #2
    Re: Implementing an 8 bit fixed point register

    On 1 Jul, 08:57, nickooooola <nick83...@gmai l.comwrote:
    Hello to all
    I'm about to write a simulator for a microcontroller in python
    (why python? because I love it!!!)
    >
    but I have a problem.
    >
    The registry of this processor are all 8 bit long (and 10 bit for some
    other strange register)
    and I need to simulate the fixed point behaviour of the register,
    and to access the single bit.
    >
    f.x. (this is a pseudo python session, only for understanding)
    >
    >reg1 = fixed_int(8)
    >reg2 = fixed_int(10)
    >reg1[0].set()
    or
    >reg1[0] = 1 # or True? how to rapresent a binary bit
    >reg1[0]
    1
    >reg1[1]
    0
    >reg1[9]
    >
    <exception .... blah blah not in range>>>reg2 = 0x7FE # in binary 11111111110 , or 11 bit long
    >reg2
    >
    0x7FE
    #or 1111111110, the memorization truncate the upper bits ( or perhaps
    generate an exception?)>>re g2 += 0x02 #the result is 10000000000, again not contained in 10 bit
    >reg2
    >
    0x00
    # truncated again>>myproces sor.flags['z']
    >
    1
    # or True? Z flag indicated an overflow in arithmetic operations
    >
    Is possibile to do so in python?
    >
    thanks
    I am not sure if it is exactly what you are looking for (it may be a
    bit low level), but myHDL may be interesting. It provides low level H/
    W simulation capabilities.




    Steven

    Comment

    • Mel

      #3
      Re: Implementing an 8 bit fixed point register

      nickooooola wrote:
      Hello to all
      I'm about to write a simulator for a microcontroller in python
      (why python? because I love it!!!)
      [...]
      The registry of this processor are all 8 bit long (and 10 bit for some
      other strange register)
      and I need to simulate the fixed point behaviour of the register,
      and to access the single bit.
      >
      f.x. (this is a pseudo python session, only for understanding)
      >
      >>>reg1 = fixed_int(8)
      >>>reg2 = fixed_int(10)
      >>>reg1[0].set()
      or
      >>>reg1[0] = 1 # or True? how to rapresent a binary bit
      >>>reg1[0]
      1
      >>>reg1[1]
      0
      >>>reg1[9]
      <exception .... blah blah not in range>
      >>>reg2 = 0x7FE # in binary 11111111110 , or 11 bit long
      >>>reg2
      0x7FE
      #or 1111111110, the memorization truncate the upper bits ( or perhaps
      generate an exception?)
      >>>reg2 += 0x02 #the result is 10000000000, again not contained in 10 bit
      >>>reg2
      0x00
      # truncated again
      >>>myprocessor. flags['z']
      1
      # or True? Z flag indicated an overflow in arithmetic operations
      >
      Is possibile to do so in python?
      I did this for a PIC, and generally just used brute force, e.g.

      temp = reg2 + 0x02
      reg2 = temp & 0xFF
      if temp & 0x100:
      flags |= CARRY_MASK
      else:
      flags &= ~CARRY_MASK
      if temp & 0xFF:
      flags &= ~ZERO_MASK
      else:
      flags |= ZERO_MASK

      Since it was a PIC, and there were only a half-dozen arithmetic/logical
      operations, the code stayed in this form. With something bigger, it would
      have been attractive to wrap these operations up in a class, as you
      suggest.. (just a sketch) ..

      class fixed_register (object):
      def __init__ (self, size, val=0):
      self.mask = ~(-1 << size)
      self.ovfmask = 1 << size
      self.val = val & self.mask

      with appropriate __add__, __sub__, etc. Perhaps __getitem__, __setitem__ to
      manipulate bits.

      Good Luck, Mel.


      Comment

      • Grant Edwards

        #4
        Re: Implementing an 8 bit fixed point register

        On 2008-07-01, nickooooola <nick83ola@gmai l.comwrote:
        Hello to all
        I'm about to write a simulator for a microcontroller in python
        (why python? because I love it!!!)
        >
        but I have a problem.
        >
        The registry of this processor are all 8 bit long (and 10 bit
        for some other strange register) and I need to simulate the
        fixed point behaviour of the register,
        Somebody posted a class that impliments fixed-width integer
        types a while back.
        and to access the single bit.
        The bitwise operators &, |, ~, ^ all work just like they do in C.

        You can write methods to dip those in syntactic sugar if you
        want.
        f.x. (this is a pseudo python session, only for understanding)
        >
        >>>reg1 = fixed_int(8)
        >>>reg2 = fixed_int(10)
        >>>reg1[0].set()
        or
        >>>reg1[0] = 1 # or True? how to rapresent a binary bit
        >>>reg1[0]
        1
        >>>reg1[1]
        0
        >>>reg1[9]
        ><exception .... blah blah not in range>
        >>>reg2 = 0x7FE # in binary 11111111110 , or 11 bit long
        >>>reg2
        0x7FE
        #or 1111111110, the memorization truncate the upper bits ( or perhaps
        generate an exception?)
        >>>reg2 += 0x02 #the result is 10000000000, again not contained in 10 bit
        >>>reg2
        0x00
        # truncated again
        >>>myprocessor. flags['z']
        1
        # or True? Z flag indicated an overflow in arithmetic operations
        >
        Is possibile to do so in python?
        Yes. Everything shown above is possible. If you really want
        to get clever, you'll want to read up on the __setattr__,
        __getattr__, __getitem__, and __setitem__ object methods.

        They'll allow you to define special handling for the semantics
        below:

        foo.something = x # calls foo.__setattr__ _('something',x )
        x = foo.something # calls foo.__getattr__ _('something,)

        foo[n] = x # calls foo.__setitem__ (n,x)
        x = foo[n] # calls foo.__getitme__ (n)

        In the latter two cases, you can support slicing if you want.
        That could allows you to grab a "bitfield" out of a register:

        x = processor.regA[4:7] # get bits 4,5,6

        processor.regA[4:7] # set bits 4,5,6

        Just remember that in Python slices are traditionally half-open
        intervals -- they don't include the "right" endpoint. That's
        going to confuse people who are more used to reading processor
        data sheets where bit-ranges are traditionally closed
        intervals. You _could_ implment your __[sg]etitem__ slice
        handling so that they're treated as closed intervals. That will
        be a lot more intuitive to people used to dealing with
        microprocessor register definitions, but could confuse an
        experienced Python programmer.

        Writing methods for __setattr__ and __getattr__ is a little
        tricky. It's very easy to end up with infinite recursion. It's
        not that hard to fix/avoid, but it takes a while to get the
        hang of it.

        --
        Grant Edwards grante Yow!
        at
        visi.com

        Comment

        • nickooooola

          #5
          Re: Implementing an 8 bit fixed point register

          Thanks to all for the responses!

          to MEl: I also want to build a pic simulator, but I want to do this as
          "python for big project" learning exercise, I have used python in the
          past only for small script and now I want to use it for something more
          "big".
          do you have some code to share?

          myhdl seems interesting, I think that I can take a blick on its source
          code...I think that must have something like
          the 8 bit register class that I need somewhere

          I try what you people have said, and if it turns to be something
          useful, I report it to the community.

          Nicola

          Ps
          excuse me for my english...

          Comment

          • Terry Reedy

            #6
            Re: Implementing an 8 bit fixed point register



            nickooooola wrote:
            Hello to all
            I'm about to write a simulator for a microcontroller in python
            (why python? because I love it!!!)
            >
            but I have a problem.
            >
            The registry of this processor are all 8 bit long (and 10 bit for some
            other strange register)
            and I need to simulate the fixed point behaviour of the register,
            and to access the single bit.
            In Python3, I would use a (mutable) bytearray.

            IDLE 3.0b1
            >>reg1 = bytearray((0,)* 8) # or *10 for 10 bits
            >>reg1
            bytearray(b'\x0 0\x00\x00\x00\x 00\x00\x00\x00' )
            >>reg1[1]=1
            >>reg1[1]
            1
            >>tuple(reg1)
            (0, 1, 0, 0, 0, 0, 0, 0)

            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().

            The overhead of using 8 bytes instead of 1 to hold the object value is
            actually small compared to the minimum object size of 16 bytes (on Win32XP).
            >>sys.getsizeof (reg1)
            24

            In Python2.x, you can use the array module to make equivalent mutable
            arrays of chars.

            Terry Jan Reedy

            Comment

            • Grant Edwards

              #7
              Re: Implementing an 8 bit fixed point register

              On 2008-07-01, Terry Reedy <tjreedy@udel.e duwrote:
              >
              >
              nickooooola wrote:
              >Hello to all
              >I'm about to write a simulator for a microcontroller in python
              >(why python? because I love it!!!)
              >>
              >but I have a problem.
              >>
              >The registry of this processor are all 8 bit long (and 10 bit for some
              >other strange register)
              >and I need to simulate the fixed point behaviour of the register,
              >and to access the single bit.
              >
              In Python3, I would use a (mutable) bytearray.
              >
              IDLE 3.0b1
              >reg1 = bytearray((0,)* 8) # or *10 for 10 bits
              >reg1
              bytearray(b'\x0 0\x00\x00\x00\x 00\x00\x00\x00' )
              >reg1[1]=1
              >reg1[1]
              1
              >tuple(reg1)
              (0, 1, 0, 0, 0, 0, 0, 0)
              >
              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.

              --
              Grant Edwards grante Yow! Do you guys know we
              at just passed thru a BLACK
              visi.com HOLE in space?

              Comment

              • Terry Reedy

                #8
                Re: Implementing an 8 bit fixed point register



                Grant Edwards wrote:
                On 2008-07-01, Terry Reedy <tjreedy@udel.e duwrote:
                >>
                >nickooooola wrote:
                >>Hello to all
                >>I'm about to write a simulator for a microcontroller in python
                >>(why python? because I love it!!!)
                >>>
                >>but I have a problem.
                >>>
                >>The registry of this processor are all 8 bit long (and 10 bit for some
                >>other strange register)
                >>and I need to simulate the fixed point behaviour of the register,
                >>and to access the single bit.
                >In Python3, I would use a (mutable) bytearray.
                >>
                >IDLE 3.0b1
                >>>>reg1 = bytearray((0,)* 8) # or *10 for 10 bits
                >>>>reg1
                >bytearray(b'\x 00\x00\x00\x00\ x00\x00\x00\x00 ')
                >>>>reg1[1]=1
                >>>>reg1[1]
                >1
                >>>>tuple(reg 1)
                >(0, 1, 0, 0, 0, 0, 0, 0)
                >>
                >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.

                The problem with the int approach is that ints are immutable.
                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.

                class bits(int):
                ....
                def __add__(self,ot her):
                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,...~2 147483648) # ditto
                def bitset(n, bit): return n | setters[bit]
                def bitunset(n,bit) : return n & unsetters[bit]

                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.

                It is a trade-off.

                Terry Jan Reedy

                Comment

                • Grant Edwards

                  #9
                  Re: Implementing an 8 bit fixed point register

                  On 2008-07-01, Terry Reedy <tjreedy@udel.e duwrote:
                  >>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,ot her):
                  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,...~2 147483648) # 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

                  Comment

                  Working...