[casper] Suggested convention for writing registers

2015-03-20 Thread James Smith
Hello all,

I've given some thought to the topic of writing (and reading) registers on
the ROACH using the python corr module. Often in a design a single register
may be sliced into many bits to control various things. The way I've
normally seen such a register written in python looks something like this:

fpga.write_int('control',19|110|025|12|13)

My feeling is that this approach is difficult to maintain - inheriting code
from someone else (or even from one's self 6 months down the line) is
likely to bring about some confusion in this case, and lead to a fair
amount of spelunking through the Simulink model in order to figure out what
bit 9 and bit 10 etc. do. On top of this, it places limitations on changing
one of the bits later without modifying the other ones - bitwise or
functions work well enough when you're over-writing zeros, but if there's
something there already it might not work so well.

With this in mind, I would like to suggest a convention which I worked out.
It uses python modules struct and construct to make code a bit easier
to read.
(For reference if anyone is unfamiliar:
struct - https://docs.python.org/2/library/struct.html
construct - http://construct.readthedocs.org/en/latest/ )

In the design I'm working on at the moment (a wideband spectrometer), I
wrote a python module with the following in it:

# Bitstruct to control the control register on the ROACH
control_reg_bitstruct = construct.BitStruct('control_reg',
construct.Padding(4),   #28-31
construct.BitField('debug_snap_select',3),  #25-27
construct.Padding(3),   #22-24
construct.Flag('fine_tvg_en'),  #21
construct.Flag('adc_tvg'),  #20
construct.Flag('fd_fs_tvg'),#19
construct.Flag('packetiser_tvg'),   #18
construct.Flag('ct_tvg'),   #17
construct.Flag('tvg_en'),   #16
construct.Padding(4),   #12-15
construct.Flag('fancy_en'), #11
construct.Flag('adc_protect_disable'),  #10
construct.Flag('gbe_enable'),   #09
construct.Flag('gbe_rst'),  #08
construct.Padding(4),   #04-07
construct.Flag('clr_status'),   #03
construct.Flag('arm'),  #02
construct.Flag('man_sync'), #01
construct.Flag('sys_rst') ) #00

This BitStruct makes the code a little bit more readable, tells you what
each bit does, and if you've done this declaration right once, then you
don't need to worry about whether you'e shifting numbers by the right
amount of bits. For the BitFields where several bits are passed, I used a
dictionary to make remembering things (and reading the code) easier as well:

# Dictionary for selecting the debug_snap_select bit
debug_snap_select = {
'coarse_72':   0,
'fine_128':1,
'quant_16':2,
'ct_64':   3,
'xaui_128':4,
'gbetx0_128':  5,
'buffer_72':   6,
'finepfb_72':  7 }

So writing to the register for the first time works like this:

control_reg = avn.control_reg_bitstruct.parse('\x00\x00\x00\x00') # Create
a blank one to use...
# Pulse arm and clr_status high, along with setting gbe_enable and
adc_protect_disable high
control_reg.gbe_enable = True
control_reg.adc_protect_disable = True
control_reg.clr_status = True
control_reg.arm = True
fpga.write_int('control', struct.unpack('I',
avn.control_reg_bitstruct.build(control_reg))[0]) # The [0] is necessary
because the fpga.write_int function wants an integer datatype, and
struct.unpack returns a tuple for some reason.
# Bring arm and clr_status low again.
control_reg.clr_status = False
control_reg.arm = False
fpga.write_int('control',
struct.unpack('I',avn.control_reg_bitstruct.build(control_reg))[0])

Then, for example if you're controlling something with a function and you
need to change only one part of what's in the register and leave the rest
unaffected, this is quite easy as well:

control_reg =
control_reg_bitstruct.parse(struct.pack('I',fpga.read_uint('control'))) #
Read the data that's in the register already
control_reg.debug_snap_select = debug_snap_select['coarse_72'] # Update
the desired bit (or bits, using the conveniently provided dictionary in
this case)
fpga.write_int('control', struct.unpack('I',
control_reg_bitstruct.build(control_reg))[0]) # Write the new data back.

Does anyone have any thoughts? Would this perhaps help with maintainability
and debugging, or is it a bit of overkill, solving a problem that wasn't
really there in the first place? I'm eager to hear any feedback from others
who may have walked this path before.

I've formatted the python code portions of the above message to a
fixed-width font, I hope it comes through on the mailing list...


Re: [casper] Suggested convention for writing registers

2015-03-20 Thread James Smith
Hi Paul,

Thanks for the link. I looked through the code a bit and it doesn't seem as
though the corr library at all. Have I been using the wrong tool for the
job?

Would you be able to point me to which file I should start with to get a
handle on how the casperfpga package works?

Regards,
James


On Fri, Mar 20, 2015 at 9:22 AM, Paul Prozesky paul.proze...@gmail.com
wrote:

 Morning James

 We do this in already in the casperfpga package:
 https://github.com/ska-sa/casperfpga

 It turns out construct is pretty slow, so we just do the conversions and
 shifts manually. I think currently the fpg files that are automatically
 parsed by casperfpga are only generated for ROACH2, but it would be easy to
 add ROACH support.

 Cheers
 Paul




 On 20 March 2015 at 09:08, James Smith jsm...@ska.ac.za wrote:

 Hello all,

 I've given some thought to the topic of writing (and reading) registers
 on the ROACH using the python corr module. Often in a design a single
 register may be sliced into many bits to control various things. The way
 I've normally seen such a register written in python looks something like
 this:

 fpga.write_int('control',19|110|025|12|13)

 My feeling is that this approach is difficult to maintain - inheriting
 code from someone else (or even from one's self 6 months down the line) is
 likely to bring about some confusion in this case, and lead to a fair
 amount of spelunking through the Simulink model in order to figure out what
 bit 9 and bit 10 etc. do. On top of this, it places limitations on changing
 one of the bits later without modifying the other ones - bitwise or
 functions work well enough when you're over-writing zeros, but if there's
 something there already it might not work so well.

 With this in mind, I would like to suggest a convention which I worked
 out. It uses python modules struct and construct to make code a bit
 easier to read.
 (For reference if anyone is unfamiliar:
 struct - https://docs.python.org/2/library/struct.html
 construct - http://construct.readthedocs.org/en/latest/ )

 In the design I'm working on at the moment (a wideband spectrometer), I
 wrote a python module with the following in it:

 # Bitstruct to control the control register on the ROACH
 control_reg_bitstruct = construct.BitStruct('control_reg',
 construct.Padding(4),   #28-31
 construct.BitField('debug_snap_select',3),  #25-27
 construct.Padding(3),   #22-24
 construct.Flag('fine_tvg_en'),  #21
 construct.Flag('adc_tvg'),  #20
 construct.Flag('fd_fs_tvg'),#19
 construct.Flag('packetiser_tvg'),   #18
 construct.Flag('ct_tvg'),   #17
 construct.Flag('tvg_en'),   #16
 construct.Padding(4),   #12-15
 construct.Flag('fancy_en'), #11
 construct.Flag('adc_protect_disable'),  #10
 construct.Flag('gbe_enable'),   #09
 construct.Flag('gbe_rst'),  #08
 construct.Padding(4),   #04-07
 construct.Flag('clr_status'),   #03
 construct.Flag('arm'),  #02
 construct.Flag('man_sync'), #01
 construct.Flag('sys_rst') ) #00

 This BitStruct makes the code a little bit more readable, tells you what
 each bit does, and if you've done this declaration right once, then you
 don't need to worry about whether you'e shifting numbers by the right
 amount of bits. For the BitFields where several bits are passed, I used a
 dictionary to make remembering things (and reading the code) easier as well:

 # Dictionary for selecting the debug_snap_select bit
 debug_snap_select = {
 'coarse_72':   0,
 'fine_128':1,
 'quant_16':2,
 'ct_64':   3,
 'xaui_128':4,
 'gbetx0_128':  5,
 'buffer_72':   6,
 'finepfb_72':  7 }

 So writing to the register for the first time works like this:

 control_reg = avn.control_reg_bitstruct.parse('\x00\x00\x00\x00') #
 Create a blank one to use...
 # Pulse arm and clr_status high, along with setting gbe_enable and
 adc_protect_disable high
 control_reg.gbe_enable = True
 control_reg.adc_protect_disable = True
 control_reg.clr_status = True
 control_reg.arm = True
 fpga.write_int('control', struct.unpack('I',
 avn.control_reg_bitstruct.build(control_reg))[0]) # The [0] is necessary
 because the fpga.write_int function wants an integer datatype, and
 struct.unpack returns a tuple for some reason.
 # Bring arm and clr_status low again.
 control_reg.clr_status = False
 control_reg.arm = False
 fpga.write_int('control',
 struct.unpack('I',avn.control_reg_bitstruct.build(control_reg))[0])

 Then, for example if you're controlling something with a function and you
 need to change only one part of what's 

Re: [casper] Suggested convention for writing registers

2015-03-20 Thread Paul Prozesky
Morning James

We do this in already in the casperfpga package:
https://github.com/ska-sa/casperfpga

It turns out construct is pretty slow, so we just do the conversions and
shifts manually. I think currently the fpg files that are automatically
parsed by casperfpga are only generated for ROACH2, but it would be easy to
add ROACH support.

Cheers
Paul




On 20 March 2015 at 09:08, James Smith jsm...@ska.ac.za wrote:

 Hello all,

 I've given some thought to the topic of writing (and reading) registers on
 the ROACH using the python corr module. Often in a design a single register
 may be sliced into many bits to control various things. The way I've
 normally seen such a register written in python looks something like this:

 fpga.write_int('control',19|110|025|12|13)

 My feeling is that this approach is difficult to maintain - inheriting
 code from someone else (or even from one's self 6 months down the line) is
 likely to bring about some confusion in this case, and lead to a fair
 amount of spelunking through the Simulink model in order to figure out what
 bit 9 and bit 10 etc. do. On top of this, it places limitations on changing
 one of the bits later without modifying the other ones - bitwise or
 functions work well enough when you're over-writing zeros, but if there's
 something there already it might not work so well.

 With this in mind, I would like to suggest a convention which I worked
 out. It uses python modules struct and construct to make code a bit
 easier to read.
 (For reference if anyone is unfamiliar:
 struct - https://docs.python.org/2/library/struct.html
 construct - http://construct.readthedocs.org/en/latest/ )

 In the design I'm working on at the moment (a wideband spectrometer), I
 wrote a python module with the following in it:

 # Bitstruct to control the control register on the ROACH
 control_reg_bitstruct = construct.BitStruct('control_reg',
 construct.Padding(4),   #28-31
 construct.BitField('debug_snap_select',3),  #25-27
 construct.Padding(3),   #22-24
 construct.Flag('fine_tvg_en'),  #21
 construct.Flag('adc_tvg'),  #20
 construct.Flag('fd_fs_tvg'),#19
 construct.Flag('packetiser_tvg'),   #18
 construct.Flag('ct_tvg'),   #17
 construct.Flag('tvg_en'),   #16
 construct.Padding(4),   #12-15
 construct.Flag('fancy_en'), #11
 construct.Flag('adc_protect_disable'),  #10
 construct.Flag('gbe_enable'),   #09
 construct.Flag('gbe_rst'),  #08
 construct.Padding(4),   #04-07
 construct.Flag('clr_status'),   #03
 construct.Flag('arm'),  #02
 construct.Flag('man_sync'), #01
 construct.Flag('sys_rst') ) #00

 This BitStruct makes the code a little bit more readable, tells you what
 each bit does, and if you've done this declaration right once, then you
 don't need to worry about whether you'e shifting numbers by the right
 amount of bits. For the BitFields where several bits are passed, I used a
 dictionary to make remembering things (and reading the code) easier as well:

 # Dictionary for selecting the debug_snap_select bit
 debug_snap_select = {
 'coarse_72':   0,
 'fine_128':1,
 'quant_16':2,
 'ct_64':   3,
 'xaui_128':4,
 'gbetx0_128':  5,
 'buffer_72':   6,
 'finepfb_72':  7 }

 So writing to the register for the first time works like this:

 control_reg = avn.control_reg_bitstruct.parse('\x00\x00\x00\x00') # Create
 a blank one to use...
 # Pulse arm and clr_status high, along with setting gbe_enable and
 adc_protect_disable high
 control_reg.gbe_enable = True
 control_reg.adc_protect_disable = True
 control_reg.clr_status = True
 control_reg.arm = True
 fpga.write_int('control', struct.unpack('I',
 avn.control_reg_bitstruct.build(control_reg))[0]) # The [0] is necessary
 because the fpga.write_int function wants an integer datatype, and
 struct.unpack returns a tuple for some reason.
 # Bring arm and clr_status low again.
 control_reg.clr_status = False
 control_reg.arm = False
 fpga.write_int('control',
 struct.unpack('I',avn.control_reg_bitstruct.build(control_reg))[0])

 Then, for example if you're controlling something with a function and you
 need to change only one part of what's in the register and leave the rest
 unaffected, this is quite easy as well:

 control_reg =
 control_reg_bitstruct.parse(struct.pack('I',fpga.read_uint('control'))) #
 Read the data that's in the register already
 control_reg.debug_snap_select = debug_snap_select['coarse_72'] #
 Update the desired bit (or bits, using the conveniently provided dictionary
 in this case)
 

Re: [casper] Suggested convention for writing registers

2015-03-20 Thread Marc Welz
On Fri, Mar 20, 2015 at 7:08 AM, James Smith jsm...@ska.ac.za wrote:

 Hello all,

 I've given some thought to the topic of writing (and reading) registers on
 the ROACH using the python corr module. Often in a design a single register
 may be sliced into many bits to control various things. The way I've
 normally seen such a register written in python looks something like this:

 fpga.write_int('control',19|110|025|12|13)

 My feeling is that this approach is difficult to maintain - inheriting
 code from someone else (or even from one's self 6 months down the line) is
 likely to bring about some confusion in this case, and lead to a fair
 amount of spelunking through the Simulink model in order to figure out what
 bit 9 and bit 10 etc. do. On top of this, it places limitations on changing
 one of the bits later without modifying the other ones - bitwise or
 functions work well enough when you're over-writing zeros, but if there's
 something there already it might not work so well.


So it turns out that it is possible to define registers which aren't full
word sizes long in tcpborphserver itself - and then the powerpc will do the
shifts for you - this is particularly useful,
for writes as that then cuts out a network operation (which would be needed
to fetch the adjacent bits so that they aren't clobbered by the write).

In the fpg file (or on the telnet connection), use optional [:bits] after
an offset or a length to define the register - it is fine if such a
register overlaps with something else, as long as the name is unique.

The downside of all this: It isn't tested at all, as nobody is using it
yet. And the code to make it work is a bit tricky - search for the
read/write functions in
https://github.com/ska-sa/katcp_devel/blob/master/tcpborphserver3/raw.c,
for example write_cmd

regards

marc


Re: [casper] Suggested convention for writing registers

2015-03-20 Thread James Smith
Hello Marc,

Thanks for the comments - I've just sat down with Paul and he's mentioned
similar things to what you have.

The only challenge with that is tcpborphserver3 doesn't run on ROACH yet,
only ROACH2 as I understand. I'm going to have a bit of a go at using the
casperfpga library anyway and seeing if I can get it to work with ROACH
using a work-around which Paul suggested. I'll post my findings to the
mailing list next week sometime.

Regards,
James


On Fri, Mar 20, 2015 at 10:01 AM, Marc Welz m...@ska.ac.za wrote:



 On Fri, Mar 20, 2015 at 7:08 AM, James Smith jsm...@ska.ac.za wrote:

 Hello all,

 I've given some thought to the topic of writing (and reading) registers
 on the ROACH using the python corr module. Often in a design a single
 register may be sliced into many bits to control various things. The way
 I've normally seen such a register written in python looks something like
 this:

 fpga.write_int('control',19|110|025|12|13)

 My feeling is that this approach is difficult to maintain - inheriting
 code from someone else (or even from one's self 6 months down the line) is
 likely to bring about some confusion in this case, and lead to a fair
 amount of spelunking through the Simulink model in order to figure out what
 bit 9 and bit 10 etc. do. On top of this, it places limitations on changing
 one of the bits later without modifying the other ones - bitwise or
 functions work well enough when you're over-writing zeros, but if there's
 something there already it might not work so well.


 So it turns out that it is possible to define registers which aren't full
 word sizes long in tcpborphserver itself - and then the powerpc will do the
 shifts for you - this is particularly useful,
 for writes as that then cuts out a network operation (which would be
 needed to fetch the adjacent bits so that they aren't clobbered by the
 write).

 In the fpg file (or on the telnet connection), use optional [:bits] after
 an offset or a length to define the register - it is fine if such a
 register overlaps with something else, as long as the name is unique.

 The downside of all this: It isn't tested at all, as nobody is using it
 yet. And the code to make it work is a bit tricky - search for the
 read/write functions in
 https://github.com/ska-sa/katcp_devel/blob/master/tcpborphserver3/raw.c,
 for example write_cmd

 regards

 marc