Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forth - how to implement words to access bitfields in the hardware register?

I use Forth for interactive debugging and automatic initialization of the FPGA-based hardware (see https://github.com/wzab/AFCK_J1B_FORTH ). Last time I started to add the support for bitfields in the registers accessible via IPbus or Wishbone bus. Below is my implementation of the words used for reading and writing of the bitfields:

\ This file implements bitfield operations
\ It assumes, that we have the bus access
\ words:
\ wb@ ( address -- val )
\ wb! ( val address -- )
\ The bitfield is defined by its mask
\ (the ones correspond to the bits used by the field)
\ and by its shift (position of the LSB in the cell)

: bf@ ( address mask shift -- val )
  rot ( mask shift address )
  wb@ ( mask shift val )
  rot ( shift val mask )
  and ( shift val )
  swap ( val shift )
  rshift ( val )
;

: bf! ( val address mask shift -- )
  rot ( val mask shift address )
  >r ( val mask shift ) ( R: address )
  rot (  mask shift val ) ( R: address )
  swap (  mask val shift ) ( R: address )
  lshift ( mask val ) ( R: address )
  over ( mask val mask ) ( R: address )
  and ( mask val ) ( R: address )
  swap invert ( val ^mask ) ( R: address )
  r@ ( val ^mask address )  ( R: address )
  wb@ ( val ^mask oldval ) ( R: address )
  and ( val oldval-masked) ( R: address )
  or ( val ) ( R: address )
  r> ( val address )
  wb!
;

The above implementation seems to work, however I'm afraid it is not optimal. Can they be written in a smarter way? It is required, however, that the implementation must be compatible with the Swapforth running on J1B CPU.

like image 708
wzab Avatar asked Feb 02 '26 10:02

wzab


1 Answers

I'm not sure, what kind of improvement you expect. While probably faster, your definition of bf! is too monolithic to be forth-like and nothing I would like to maintain.

Starting from these assumptions:

  • Swapforth-compatibility means to do everything on the stacks without locals (if you mean someting else, please clarify)
  • The value and mask supplied are supplied in same right-aligned format (to assume the mask is already shifted creates lots of unreasonable combinations)
  • For my environment I stayed with @ and !, you need to replace them by wb@ and wb!

I arrived at the following code:

\ duplicate existing bitfield information on stack
: bf_dup ( n1 n2 n3 -- n1 n2 n3 n1 n2 n3) 
    2dup 2>r ( n1 n2 n3 R: n2 n3)
    rot dup >r -rot ( n1 n2 n3 R: n2 n3 n1)
    r> 2r> ;

: bf@ ( address mask shift -- val) 2>r @ r> rshift r> and ;

: (mask-old-value) ( addr mask shift -- val) lshift invert swap @ and ;

: (trim-shift-new) ( val addr mask shift -- addr new-value )
    2>r swap 2r> ( addr val mask shift)
    -rot and  ( addr shift val_masked)
   swap lshift ;

: bf! ( val address mask shift -- ) bf_dup (mask-old-value) >r
   (trim-shift-new)
   r> or swap ! ;

Testing and actually applying these words is much easier with the following definition:

  \ store address mask shift (zero-based) in this sequence
   : bitfield create rot , swap , , does> dup @ swap cell+ dup @ swap  cell+ @ ;
   hex 2018 7 3 ( address mask shift) bitfield mybitfield
like image 66
guidot Avatar answered Feb 05 '26 05:02

guidot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!