ID |
Date |
Author |
Topic |
Subject |
2074
|
13 Jan 2021 |
Stefan Ritt | Forum | poll_event() is very slow. | Something must be wrong on your side. If you take the example frontend under
midas/examples/experiment/frontend.cxx
and let it run to produce dummy events, you get about 90 Hz. This is because we have a
ss_sleep(10);
in the read_trigger_event() routine to throttle things down. If you remove that sleep,
you get an event rate of about 500'000 Hz. So the framework is really quick.
Probably your routine which looks for a 'lam' takes really long and should be fixed.
Stefan |
Draft
|
13 Jan 2021 |
Pierre-Andre Amaudruz | Forum | poll_event() is very slow. | > Hi all,
>
> I'm currently trying to see if I can speed up polling in a frontend I'm testing.
> Currently it seems like I can't get 'lam's to happen faster than 120 times/second.
> There must be a way to make this faster. From what I understand, changing the poll
> time (500ms by default) won't affect the frequency of polling just the 'lam'
> period.
>
> Any suggestions?
>
> Thanks for your help!
>
> Isaac
Hi,
How many equipment do you have and of what type?
What is the measured readout time of your equipment?
As you mentioned the polling time define the maximum time you spend in the in polling call before checking other equipment and system activities. But as soon as you get a LAM during the polling loop, the event is readout. The readout time of this equipment is obviously to be considered as well.
In case you have multiple equipment, the readout time of the other equipment is to be taken in account as you wont return to your polling prior the completion of them. |
2072
|
13 Jan 2021 |
Konstantin Olchanski | Forum | poll_event() is very slow. | >
> I'm currently trying to see if I can speed up polling in a frontend I'm testing.
> Currently it seems like I can't get 'lam's to happen faster than 120 times/second.
> There must be a way to make this faster. From what I understand, changing the poll
> time (500ms by default) won't affect the frequency of polling just the 'lam'
> period.
>
> Any suggestions?
>
You could switch from the traditional midas mfe.c frontend to the C++ TMFE frontend,
where all this "lam" and "poll" business is removed.
At the moment, there are two example programs using the C++ TMFE frontend,
single threaded (progs/fetest_tmfe.cxx) and multithreaed (progs/fetest_tmfe_thread.cxx).
K.O. |
2071
|
13 Jan 2021 |
Isaac Labrie Boulay | Forum | poll_event() is very slow. | Hi all,
I'm currently trying to see if I can speed up polling in a frontend I'm testing.
Currently it seems like I can't get 'lam's to happen faster than 120 times/second.
There must be a way to make this faster. From what I understand, changing the poll
time (500ms by default) won't affect the frequency of polling just the 'lam'
period.
Any suggestions?
Thanks for your help!
Isaac
Hi,
What is the actual readout time, event size?
Do you have multiple equipment and of what type if any?
PAA |
2070
|
08 Jan 2021 |
Stefan Ritt | Forum | history and variables confusion | We kind of agreed to rewrite the slow control system in C++. Each device will have its own driver derived from a common base class implementing the general communication. The reason we need a "system" and not only a "hand-written" driver is because we want:
- glue many device drivers together for a single equipment
- have a dedicated readout thread for every device, in order not to block other devices
- have a common error reporting scheme working with several threads
- being able to disable/enable individual devices without changing the history system each time
- having a common naming scheme for all devices (like "enforce" /Equipment/<name>/Settings/Names xxx) which is needed by the history system
- ...
Will see when we have time for that.
Stefan |
2069
|
06 Jan 2021 |
Isaac Labrie Boulay | Info | Recovering a corrupted ODB using odbinit. | Hi all,
I am currently trying to recover my corrupted ODB using odbinit and I am still
getting issues after doing 'odbinit --cleanup' and trying to reload the saved
ODB (last.json). Here is the output:
************************************************
(odbinit cleanup) Note* the ERROR in system.cxx
************************************************
[caendaq@cu332 ANIS]$ odbinit --cleanup
Checking environment... experiment name is "ANIS", remote hostname is ""
Checking command line... experiment "ANIS", cleanup 1, dry_run 0, create_exptab
0, create_env 0
Checking MIDASSYS....../home/caendaq/packages/midas
Checking exptab... experiments defined in exptab file "/home/caendaq/ANIS/exptab
":
0: "ANIS" <-- selected experiment
Checking exptab... selected experiment "ANIS", experiment directory "/home/caend
aq/ANIS/"
Checking experiment directory "/home/caendaq/ANIS/"
Found existing ODB save file: "/home/caendaq/ANIS/.ODB.SHM"
Checking shared memory...
Deleting old ODB shared memory...
[system.cxx:1052:ss_shm_delete,ERROR] shm_unlink(/1001_ANIS_ODB__home_caendaq_AN
IS_) errno 2 (No such file or directory)
Good: no ODB shared memory
Deleting old ODB semaphore...
Deleting old ODB semaphore... create status 1, delete status 1
Preserving old ODB save file /home/caendaq/ANIS/.ODB.SHM" to "/home/caendaq/ANIS
/.ODB.SHM.1609951022"
Checking ODB size...
Requested ODB size is 0 bytes (0.00B)
ODB size file is "/home/caendaq/ANIS//.ODB_SIZE.TXT"
Saved ODB size from "/home/caendaq/ANIS//.ODB_SIZE.TXT" is 1048576 bytes (1.05MB
)
We will initialize ODB for experiment "ANIS" on host "" with size 1048576 bytes
(1.05MB)
Creating ODB...
Creating ODB... db_open_database() status 302
Saving ODB...
Saving ODB... db_close_database() status 1
Connecting to experiment...
Connected to ODB for experiment "ANIS" on host "" with size 1048576 bytes (1.05M
B)
Checking experiment name... status 1, found "ANIS"
Disconnecting from experiment...
Done
****************************************
(Loading the last copy of my ODB)
*************************************
[caendaq@cu332 data]$ odbedit
[local:ANIS:S]/>load last.json
[ODBEdit,INFO] Reloading RPC hosts access control list via hotlink callback
[ODBEdit,INFO] Reloading RPC hosts access control list via hotlink callback
[ODBEdit,INFO] Reloading RPC hosts access control list via hotlink callback
[ODBEdit,INFO] Reloading RPC hosts access control list via hotlink callback
[ODBEdit,INFO] Reloading RPC hosts access control list via hotlink callback
[ODBEdit,INFO] Reloading RPC hosts access control list via hotlink callback
[ODBEdit,INFO] Reloading RPC hosts access control list via hotlink callback
[ODBEdit,INFO] Reloading RPC hosts access control list via hotlink callback
[ODBEdit,INFO] Reloading RPC hosts access control list via hotlink callback
[ODBEdit,INFO] Reloading RPC hosts access control list via hotlink callback
11:38:12 [ODBEdit,INFO] Reloading RPC hosts access control list via hotlink
callback
11:38:12 [ODBEdit,INFO] Reloading RPC hosts access control list via hotlink
callback
11:38:12 [ODBEdit,INFO] Reloading RPC hosts access control list via hotlink
callback
11:38:12 [ODBEdit,INFO] Reloading RPC hosts access control list via hotlink
callback
11:38:12 [ODBEdit,INFO] Reloading RPC hosts access control list via hotlink
callback
11:38:12 [ODBEdit,INFO] Reloading RPC hosts access control list via hotlink
callback
11:38:12 [ODBEdit,INFO] Reloading RPC hosts access control list via hotlink
callback
11:38:12 [ODBEdit,INFO] Reloading RPC hosts access control list via hotlink
callback
11:38:12 [ODBEdit,INFO] Reloading RPC hosts access control list via hotlink
callback
11:38:12 [ODBEdit,INFO] Reloading RPC hosts access control list via hotlink
callback
**********************************************
(Now trying to run my frontend and analyzer)
*********************************************
[caendaq@cu332 ANIS]$ ./start_daq.sh
mlogger: no process found
fevme: no process found
manalyzer.exe: no process found
manalyzer_example_cxx.exe: no process found
roody: no process found
[ODBEdit,ERROR] [midas.cxx:6616:bm_open_buffer,ERROR] Buffer "SYSTEM" is
corrupted, mismatch of buffer name in shared memory ""
11:38:30 [ODBEdit,ERROR] [midas.cxx:6616:bm_open_buffer,ERROR] Buffer "SYSTEM"
is corrupted, mismatch of buffer name in shared memory ""
Becoming a daemon...
Becoming a daemon...
Please point your web browser to http://localhost:8081
To look at live histograms, run: roody -Hlocalhost
Or run: mozilla http://localhost:8081
[caendaq@cu332 ANIS]$ Frontend name : fevme
Event buffer size : 1048576
User max event size : 204800
User max frag. size : 1048576
# of events per buffer : 5
Connect to experiment ANIS...
OK
[fevme,ERROR] [midas.cxx:6616:bm_open_buffer,ERROR] Buffer "SYSTEM" is
corrupted, mismatch of buffer name in shared memory ""
[fevme,ERROR] [mfe.cxx:596:register_equipment,ERROR] Cannot open event buffer
"SYSTEM" size 33554432, bm_open_buffer() status 219
Has anyone ever encountered these issues?
Thanks for your time.
Isaac |
2068
|
06 Jan 2021 |
Isaac Labrie Boulay | Bug Report | Logger: Disk nearly full. | > The logger simple requests the disk free space level from the operating system in the same
> way as the "df" command does. Can you do a "df" on your system? I have seen that some file
> systems free up space not immediately if you delete files, but some times later (like 24h).
>
> Stefan
Thanks Stefan. Yes the files were still held open by some processes. It's solved now.
Cheers.
Isaac |
2067
|
06 Jan 2021 |
Stefan Ritt | Suggestion | Improving variable functionality in Sequencer? | I guess you use a wrong pattern here. There is no need to copy ODB values to local variables,
then change them, then write them back. You can rather directly write values to the ODB. We run
all our experiments in that way and we can do what we want. So most of our scripts have sections
like
ODBSUBDIR "/Equipment/Laser/Variables"
ODBSET "Setting[*]", 0, 0
ODBSET "Output[1]", 0, 0
ODBSET "Output[2]", 1, 0
ODBSET "Output[3]", 0, 0
ODBSET "Output[4]", 1, 1
ENDODBSUBDIR
Note that both the path and the indices can contain wild cards, making this pattern more
flexible. Wildcards are however not (yet) supported for local variables, that's why we use
directly the ODBSET directive.
I attach a larger example from the MEG experiment here for your reference.
Stefan |
Attachment 1: laser.msl
|
COMMENT "TC laser run"
# include XEC setting script
INCLUDE xec_settings
RUNDESCRIPTION "TC laser run"
SET Nrun, 1
SET Freq, 1200
ODBSET "/Experiment/Run Parameters/SQL/SPX/SPXConfId", 79, 0
ODBGET "/Sequencer/Variables/Freq", Freq
ODBSET "/Sequencer/Variables/Freq", 1200, 1
SET Power, 12
SET Temp, 15
SET LaserFreq, 40
SET Nevent, 3000
ODBGET "/Sequencer/Variables/Nevent", Nevent
ODBSET "/Sequencer/Variables/Nevent", 3000, 1
SET Gain, 100
SET PzcLevel, 7
# Reset XEC setting
CALL setup_ADC, 0
CALL setup_DRS, 0
ODBSUBDIR "/Equipment/Trigger/Settings/WaveDAQ/"
ODBSET "AUXCrate/AUX-13/SamplingFrequency", $Freq, 0
ODBSET "AUXCrate/AUX-13/FrontendPzcLevel", 3, 0
ODBSET "AUXCrate/AUX-13/FrontendGain[14]", 1, 0
ODBSET "AUXCrate/AUX-13/FrontendPzc[14]", n, 0
ODBSET "AUXCrate/AUX-13/FrontendGain[15]", 1, 0
ODBSET "AUXCrate/AUX-13/FrontendPzc[15]", y, 0
ODBSET "AUXCrate/AUX-13/DRSChannelTxEnable", 0x3FFFFx,0
ODBSET "AUXCrate/AUX-13/ZeroSuppressionEnable", n, 0
ODBSET "TCUS1Crate/TU1-*/SamplingFrequency", $Freq, 0
ODBSET "TCUS1Crate/TU1-*/FrontendPzcLevel", $PzcLevel, 0
ODBSET "TCUS1Crate/TU1-*/FrontendPzc[*]", y, 0
ODBSET "TCUS1Crate/TU1-*/DRSChannelTxEnable", 0x3FFFF,0
ODBSET "TCUS1Crate/TU1-*/ZeroSuppressionEnable", n, 0
ODBSET "TCUS1Crate/TU1-*/FrontendGain[*]", $Gain, 0
ODBSET "TCUS1Crate/TU1-6/FrontendGain[*]", 50, 0
ODBSET "TCUS1Crate/TU1-*/TDCChannelTxEnable", 0,0
ENDODBSUBDIR
ODBSUBDIR "/Equipment/Trigger/Settings/WaveDAQ"
ODBSET "Trigger/MASTER/TriggerPrescaling[*]", 0, 0
ODBSET "Trigger/MASTER/TriggerEnable[*]", n, 0
ODBSET "Trigger/MASTER/TriggerPrescaling[63]", 1, 0
ODBSET "Trigger/MASTER/TriggerEnable[63]", y, 0
ODBSET "Trigger/MASTER/Write TRGC", y, 0
ODBSET "Trigger/MASTER/Write TGEN", y, 0
ODBSET "Trigger/MASTER/Write XEC", n, 0
ODBSet "Trigger/TC/Write SPX", n, 0
ENDODBSUBDIR
ODBSUBDIR ""
ENDODBSUBDIR
ODBSET "/Equipment/Trigger/Settings/Reload all", y, 1
WAIT ODBValue, "/Equipment/Trigger/Variables/Config busy", ==, 0
WAIT seconds, 2
ODBSUBDIR "/Equipment/Trigger/Settings/WaveDAQ"
ODBSET "Trigger/MASTER/TriggerPrescaling[*]", 0, 0
ODBSET "Trigger/MASTER/TriggerEnable[*]", n, 0
ODBSET "Trigger/MASTER/TriggerPrescaling[63]", 100, 0
ODBSET "Trigger/MASTER/TriggerEnable[63]", y, 1
ENDODBSUBDIR
ODBSUBDIR ""
ENDODBSUBDIR
CAT description, "TC pedestal"
ODBSET "/Experiment/Run Parameters/Run description", $description, 1
LOOP $Nrun
TRANSITION start
WAIT events, 1000
TRANSITION stop
ENDLOOP
ODBSUBDIR "/Equipment/Trigger/Settings/WaveDAQ"
ODBSET "Trigger/MASTER/TriggerPrescaling[*]", 0, 0
ODBSET "Trigger/MASTER/TriggerEnable[*]", n, 0
ODBSET "Trigger/MASTER/TriggerPrescaling[23]", 1, 0
ODBSET "Trigger/MASTER/TriggerEnable[23]", y, 1
ENDODBSUBDIR
ODBSUBDIR "/Equipment/Laser/Variables/"
ODBSET "Output[0]", $LaserFreq, 0
ODBSET "Output[1]", 1, 0
ODBSET "Output[2]", 1, 0
ODBSET "Output[3]", 1, 0
ODBSET "Output[4]", 0, 1
ENDODBSUBDIR
WAIT seconds, 10
ODBSUBDIR ""
ENDODBSUBDIR
CAT description, "Laser run, sector: 4, frequency: ", $Freq, ", clock: square, power: ", $Power, ", attenuator: 0, temperature: ", $Temp
ODBSET "/Experiment/Run Parameters/Run description", $description, 1
LOOP $Nrun
TRANSITION start
WAIT events, $Nevent
TRANSITION stop
ENDLOOP
ODBSUBDIR "/Equipment/Laser/Variables/"
ODBSET "Output[1]", 1, 0
ODBSET "Output[2]", 0, 0
ODBSET "Output[3]", 0, 0
ODBSET "Output[4]", 1, 1
ENDODBSUBDIR
WAIT seconds, 10
ODBSUBDIR ""
ENDODBSUBDIR
CAT description, "Laser run, sector: 5, frequency: ", $Freq, ", clock: square, power: ", $Power, ", attenuator: 0, temperature: ", $Temp
ODBSET "/Experiment/Run Parameters/Run description", $description, 1
LOOP $Nrun
TRANSITION start
WAIT events, $Nevent
TRANSITION stop
ENDLOOP
ODBSUBDIR "/Equipment/Laser/Variables"
ODBSET "Output[1]", 0, 0
ODBSET "Output[2]", 1, 0
ODBSET "Output[3]", 0, 0
ODBSET "Output[4]", 1, 1
ENDODBSUBDIR
WAIT seconds, 10
ODBSUBDIR ""
ENDODBSUBDIR
CAT description, "Laser run, sector: 6, frequency: ", $Freq, ", clock: square, power: ", $Power, ", attenuator: 0, temperature: ", $Temp
ODBSET "/Experiment/Run Parameters/Run description", $description, 1
LOOP $Nrun
TRANSITION start
WAIT events, $Nevent
TRANSITION stop
ENDLOOP
ODBSUBDIR "/Equipment/Laser/Variables"
ODBSET "Output[1]", 1, 0
ODBSET "Output[2]", 1, 0
ODBSET "Output[3]", 0, 0
ODBSET "Output[4]", 1, 1
ENDODBSUBDIR
WAIT seconds, 10
ODBSUBDIR ""
ENDODBSUBDIR
CAT description, "Laser run, sector: 7, frequency: ", $Freq, ", clock: square, power: ", $Power, ", attenuator: 0, temperature: ", $Temp
ODBSET "/Experiment/Run Parameters/Run description", $description, 1
LOOP $Nrun
TRANSITION start
WAIT events, $Nevent
TRANSITION stop
ENDLOOP
ODBSUBDIR "/Equipment/Laser/Variables"
ODBSET "Output[0]", 0, 0
ODBSET "Output[1]", 1, 0
ODBSET "Output[2]", 0, 0
ODBSET "Output[3]", 0, 0
ODBSET "Output[4]", 0, 1
ENDODBSUBDIR
ODBSUBDIR "/Equipment/Trigger/Settings/WaveDAQ"
ODBSET "AUXCrate/AUX-13/SamplingFrequency", 1200, 0
ODBSET "AUXCrate/AUX-13/FrontendPzcLevel", 7, 0
ODBSET "AUXCrate/AUX-13/FrontendGain[14]", 1, 0
ODBSET "AUXCrate/AUX-13/FrontendPzc[14]", n, 0
ODBSET "AUXCrate/AUX-13/FrontendGain[15]", 1, 0
ODBSET "AUXCrate/AUX-13/FrontendPzc[15]", n, 1
ENDODBSUBDIR
|
2066
|
06 Jan 2021 |
Stefan Ritt | Bug Report | Logger: Disk nearly full. | The logger simple requests the disk free space level from the operating system in the same
way as the "df" command does. Can you do a "df" on your system? I have seen that some file
systems free up space not immediately if you delete files, but some times later (like 24h).
Stefan |
2065
|
05 Jan 2021 |
Amy Roberts | Suggestion | Improving variable functionality in Sequencer? | Hello, just wanted to re-ping on this question now that folks are starting to get back from
the holidays. |
2064
|
05 Jan 2021 |
Isaac Labrie Boulay | Bug Report | Logger: Disk nearly full. | Hi all,
I've ran into a problem where my experiment gets interrupted with a message from
the logger saying that my disk is nearly full. This does not make sense to me
because I have deleted almost all the data files from my data directory. I'm
guessing that somewhere the ODB perceives that the directory is full when in
reality its not.
Here is the exact message:
[ODBEdit,INFO] Run #252 stopped
09:22:19 [Logger,TALK] disk nearly full, stopping the run
09:22:19 [Logger,ERROR] [mlogger.cxx:4475:log_write,ERROR] Disk '/home/caendaq/A
NIS/data/run00252.mid.lz4' is almost full: 81 MiBytes free out of 922497 MiBytes
, stopping the run
Does any body have a solution for this? Thanks so much.
Isaac |
2063
|
04 Jan 2021 |
Stefan Ritt | Suggestion | Code formatting | After pondering over the holidays, I decided to use the widely used LLVM code formatting,
just adapted slightly for 3 spaces and "case" indentation in a "switch" statement. This
formatting is now very close to our original one. Nevertheless, I did not reformat all
existing code, since that would screw up the git repository, and you cannot see then anymore
who wrote which line of code. But having the .clang-format file now in the midas root, all
NEW files fill follow that standard.
The CLion editor automatically picks up the .clang-format file if your enable ClangFomrat
via Preferences -> Code Style -> General -> Enable ClangFormat.
EMACS can also use this file by adding following lines to your .emacs:
(load "<path-to-clang>/tools/clang-format/clang-format.el")
(global-set-key [C-M-tab] 'clang-format-region)
One problem left is if you check out midas on a new machine, you might not have there your
personal .emacs file. If there is a way to ship a .emacs with midas, which gets
automatically loaded, I would be happy to put this into the distribution.
Stefan |
Attachment 1: .clang-format
|
# Generated from CLion C/C++ Code Style settings
BasedOnStyle: LLVM
AccessModifierOffset: -3
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignOperands: false
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: MultiLine
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 0
CompactNamespaces: false
ContinuationIndentWidth: 3
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 3
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Right
ReflowComments: false
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 0
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 3
UseTab: Never
|
2062
|
18 Dec 2020 |
Stefan Ritt | Suggestion | Code formatting | May I ask for your quick opinion on code formatting. MIDAS had a coding style
which pretty much followed the ROOT coding style described at
https://root.cern/contribute/coding_conventions/
so we followed the "3 spaces indent" convention, braces according to Kernigham &
Ritchie and a few other things. I see however that code written by different
people still is formatted differently, like spaces before and after comparators
etc. I wonder if it would make sense to keep a consistent code formatting through
the whole midas repository.
Looking again at what the ROOT guys doe (see link above), they have a ClangFormat
file, which I attached to this post. Putting this file into the root of midas
ensures that all files are formatted in exactly the same way, which would increase
readability largely.
The nice thing with ClangFormat is that can be integrated into my editor (Clion) as
well as in emacs and vim:
https://clang.llvm.org/docs/ClangFormat.html
This would also make the emacs settings in our files obsolete:
/* emacs
* Local Variables:
* tab-width: 8
* c-basic-offset: 3
* indent-tabs-mode: nil
* End:
*/
I don't like these because they are only for people using emacs. If everybody would
put statements into the files with their favourite editor, all our source files
would be cluttered quite a bit.
So the question is now how style to use? I attached different trials with a simple
file from the distribution, so you can see the differences. They use the style from
- LLVM
- ROOT
- GNU
- Google
I consciously skipped the "Microsoft" style ;-)
Which one should we settle on? Any opinion? If I don't hear anything, I will pick a
style at the end of this year 2020. I have a slight favour of the ROOT style, although
I don't like that the "case" is not indented there under the opening brace of the
switch statement which seems inconsistent to me. The only one doing that right is the
Google format, but that one has an indentation of 2 chars instead our usual 3 chars.
At the end of the day I think it's not so important on which style we agree, as long
as we DO have a common style for all midas files.
Best,
Stefan |
Attachment 1: .clang-format
|
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -3
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
# This would be nice to have but seems to also (mis)align function parameters
AlignConsecutiveDeclarations: true
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
# This option is "deprecated and is retained for backwards compatibility."
# AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 3
ContinuationIndentWidth: 3
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^("|<)T'
Priority: 4
- Regex: '^("|<)ROOT/'
Priority: 5
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 6
IndentCaseLabels: false
IndentWidth: 3
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 3
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60000
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 3
UseTab: Never
...
|
Attachment 2: cnaf_callback_llvm.cxx
|
/********************************************************************\
Name: cnaf_callback.c
Created by: Stefan Ritt
Created by: moved here from mfe.c by Konstantin Olchanski
Contents: The system part of the MIDAS frontend. Has to be
linked with user code to form a complete frontend
$Id$
\********************************************************************/
#include <stdio.h>
#include <assert.h>
#include "midas.h"
#include "msystem.h"
#include "mcstd.h"
/*------------------------------------------------------------------*/
static int cnaf_debug = 0;
INT cnaf_callback(INT index, void *prpc_param[]) {
DWORD cmd, b, c, n, a, f, *pdword, *size, *x, *q, dtemp;
WORD *pword, *pdata, temp;
INT i, count;
/* Decode parameters */
cmd = CDWORD(0);
b = CDWORD(1);
c = CDWORD(2);
n = CDWORD(3);
a = CDWORD(4);
f = CDWORD(5);
pdword = CPDWORD(6);
pword = CPWORD(6);
pdata = CPWORD(6);
size = CPDWORD(7);
x = CPDWORD(8);
q = CPDWORD(9);
/* determine repeat count */
if (index == RPC_CNAF16)
count = *size / sizeof(WORD); /* 16 bit */
else
count = *size / sizeof(DWORD); /* 24 bit */
switch (cmd) {
/*---- special commands ----*/
case CNAF_INHIBIT_SET: cam_inhibit_set(c);
break;
case CNAF_INHIBIT_CLEAR: cam_inhibit_clear(c);
break;
case CNAF_CRATE_CLEAR: cam_crate_clear(c);
break;
case CNAF_CRATE_ZINIT: cam_crate_zinit(c);
break;
case CNAF_TEST: break;
case CNAF:
if (index == RPC_CNAF16) {
for (i = 0; i < count; i++)
if (f < 16)
cam16i_q(c, n, a, f, pword++, (int *) x, (int *) q);
else if (f < 24)
cam16o_q(c, n, a, f, pword[i], (int *) x, (int *) q);
else
cam16i_q(c, n, a, f, &temp, (int *) x, (int *) q);
} else {
for (i = 0; i < count; i++)
if (f < 16)
cam24i_q(c, n, a, f, pdword++, (int *) x, (int *) q);
else if (f < 24)
cam24o_q(c, n, a, f, pdword[i], (int *) x, (int *) q);
else
cam24i_q(c, n, a, f, &dtemp, (int *) x, (int *) q);
}
break;
case CNAF_nQ:
if (index == RPC_CNAF16) {
if (f < 16) {
cam16i_rq(c, n, a, f, &pword, count);
*size = (POINTER_T) pword - (POINTER_T) pdata;
}
} else {
if (f < 16) {
cam24i_rq(c, n, a, f, &pdword, count);
*size = (POINTER_T) pdword - (POINTER_T) pdata;
}
}
/* return reduced return size */
break;
default: printf("cnaf: Unknown command 0x%X\n", (unsigned int) cmd);
}
if (cnaf_debug) {
if (index == RPC_CNAF16)
printf("cmd=%d r=%d c=%d n=%d a=%d f=%d d=%X x=%d q=%d\n", (int) cmd, (int) count, (int) c, (int) n, (int) a,
(int) f, (int) pword[0], (int) *x, (int) *q);
else if (index == RPC_CNAF24)
printf("cmd=%d r=%d c=%d n=%d a=%d f=%d d=%X x=%d q=%d\n", (int) cmd, (int) count, (int) c, (int) n, (int) a,
(int) f, (int) pdword[0], (int) *x, (int) *q);
}
return RPC_SUCCESS;
}
void register_cnaf_callback(int debug) {
cnaf_debug = debug;
/* register CNAF callback */
cm_register_function(RPC_CNAF16, cnaf_callback);
cm_register_function(RPC_CNAF24, cnaf_callback);
}
/* end file */
|
Attachment 3: cnaf_callback_root.cxx
|
/********************************************************************\
Name: cnaf_callback.c
Created by: Stefan Ritt
Created by: moved here from mfe.c by Konstantin Olchanski
Contents: The system part of the MIDAS frontend. Has to be
linked with user code to form a complete frontend
$Id$
\********************************************************************/
#include <stdio.h>
#include <assert.h>
#include "midas.h"
#include "msystem.h"
#include "mcstd.h"
/*------------------------------------------------------------------*/
static int cnaf_debug = 0;
INT cnaf_callback(INT index, void *prpc_param[])
{
DWORD cmd, b, c, n, a, f, *pdword, *size, *x, *q, dtemp;
WORD *pword, *pdata, temp;
INT i, count;
/* Decode parameters */
cmd = CDWORD(0);
b = CDWORD(1);
c = CDWORD(2);
n = CDWORD(3);
a = CDWORD(4);
f = CDWORD(5);
pdword = CPDWORD(6);
pword = CPWORD(6);
pdata = CPWORD(6);
size = CPDWORD(7);
x = CPDWORD(8);
q = CPDWORD(9);
/* determine repeat count */
if (index == RPC_CNAF16)
count = *size / sizeof(WORD); /* 16 bit */
else
count = *size / sizeof(DWORD); /* 24 bit */
switch (cmd) {
/*---- special commands ----*/
case CNAF_INHIBIT_SET: cam_inhibit_set(c); break;
case CNAF_INHIBIT_CLEAR: cam_inhibit_clear(c); break;
case CNAF_CRATE_CLEAR: cam_crate_clear(c); break;
case CNAF_CRATE_ZINIT: cam_crate_zinit(c); break;
case CNAF_TEST: break;
case CNAF:
if (index == RPC_CNAF16) {
for (i = 0; i < count; i++)
if (f < 16)
cam16i_q(c, n, a, f, pword++, (int *)x, (int *)q);
else if (f < 24)
cam16o_q(c, n, a, f, pword[i], (int *)x, (int *)q);
else
cam16i_q(c, n, a, f, &temp, (int *)x, (int *)q);
} else {
for (i = 0; i < count; i++)
if (f < 16)
cam24i_q(c, n, a, f, pdword++, (int *)x, (int *)q);
else if (f < 24)
cam24o_q(c, n, a, f, pdword[i], (int *)x, (int *)q);
else
cam24i_q(c, n, a, f, &dtemp, (int *)x, (int *)q);
}
break;
case CNAF_nQ:
if (index == RPC_CNAF16) {
if (f < 16) {
cam16i_rq(c, n, a, f, &pword, count);
*size = (POINTER_T)pword - (POINTER_T)pdata;
}
} else {
if (f < 16) {
cam24i_rq(c, n, a, f, &pdword, count);
*size = (POINTER_T)pdword - (POINTER_T)pdata;
}
}
/* return reduced return size */
break;
default: printf("cnaf: Unknown command 0x%X\n", (unsigned int)cmd);
}
if (cnaf_debug) {
if (index == RPC_CNAF16)
printf("cmd=%d r=%d c=%d n=%d a=%d f=%d d=%X x=%d q=%d\n", (int)cmd, (int)count, (int)c, (int)n, (int)a,
(int)f, (int)pword[0], (int)*x, (int)*q);
else if (index == RPC_CNAF24)
printf("cmd=%d r=%d c=%d n=%d a=%d f=%d d=%X x=%d q=%d\n", (int)cmd, (int)count, (int)c, (int)n, (int)a,
(int)f, (int)pdword[0], (int)*x, (int)*q);
}
return RPC_SUCCESS;
}
void register_cnaf_callback(int debug)
{
cnaf_debug = debug;
/* register CNAF callback */
cm_register_function(RPC_CNAF16, cnaf_callback);
cm_register_function(RPC_CNAF24, cnaf_callback);
}
/* end file */
|
Attachment 4: cnaf_callback_gnu.cxx
|
/********************************************************************\
Name: cnaf_callback.c
Created by: Stefan Ritt
Created by: moved here from mfe.c by Konstantin Olchanski
Contents: The system part of the MIDAS frontend. Has to be
linked with user code to form a complete frontend
$Id$
\********************************************************************/
#include <stdio.h>
#include <assert.h>
#include "midas.h"
#include "msystem.h"
#include "mcstd.h"
/*------------------------------------------------------------------*/
static int cnaf_debug = 0;
INT cnaf_callback (INT index, void *prpc_param[])
{
DWORD cmd, b, c, n, a, f, *pdword, *size, *x, *q, dtemp;
WORD *pword, *pdata, temp;
INT i, count;
/* Decode parameters */
cmd = CDWORD(0);
b = CDWORD(1);
c = CDWORD(2);
n = CDWORD(3);
a = CDWORD(4);
f = CDWORD(5);
pdword = CPDWORD(6);
pword = CPWORD(6);
pdata = CPWORD(6);
size = CPDWORD(7);
x = CPDWORD(8);
q = CPDWORD(9);
/* determine repeat count */
if (index == RPC_CNAF16)
count = *size / sizeof (WORD); /* 16 bit */
else
count = *size / sizeof (DWORD); /* 24 bit */
switch (cmd)
{
/*---- special commands ----*/
case CNAF_INHIBIT_SET: cam_inhibit_set (c);
break;
case CNAF_INHIBIT_CLEAR: cam_inhibit_clear (c);
break;
case CNAF_CRATE_CLEAR: cam_crate_clear (c);
break;
case CNAF_CRATE_ZINIT: cam_crate_zinit (c);
break;
case CNAF_TEST: break;
case CNAF:
if (index == RPC_CNAF16)
{
for (i = 0; i < count; i++)
if (f < 16)
cam16i_q (c, n, a, f, pword++, (int *) x, (int *) q);
else if (f < 24)
cam16o_q (c, n, a, f, pword[i], (int *) x, (int *) q);
else
cam16i_q (c, n, a, f, &temp, (int *) x, (int *) q);
}
else
{
for (i = 0; i < count; i++)
if (f < 16)
cam24i_q (c, n, a, f, pdword++, (int *) x, (int *) q);
else if (f < 24)
cam24o_q (c, n, a, f, pdword[i], (int *) x, (int *) q);
else
cam24i_q (c, n, a, f, &dtemp, (int *) x, (int *) q);
}
break;
case CNAF_nQ:
if (index == RPC_CNAF16)
{
if (f < 16)
{
cam16i_rq (c, n, a, f, &pword, count);
*size = (POINTER_T) pword - (POINTER_T) pdata;
}
}
else
{
if (f < 16)
{
cam24i_rq (c, n, a, f, &pdword, count);
*size = (POINTER_T) pdword - (POINTER_T) pdata;
}
}
/* return reduced return size */
break;
default: printf ("cnaf: Unknown command 0x%X\n", (unsigned int) cmd);
}
if (cnaf_debug)
{
if (index == RPC_CNAF16)
printf ("cmd=%d r=%d c=%d n=%d a=%d f=%d d=%X x=%d q=%d\n", (int) cmd, (int) count, (int) c, (int) n, (int) a,
(int) f, (int) pword[0], (int) *x, (int) *q);
else if (index == RPC_CNAF24)
printf ("cmd=%d r=%d c=%d n=%d a=%d f=%d d=%X x=%d q=%d\n", (int) cmd, (int) count, (int) c, (int) n, (int) a,
(int) f, (int) pdword[0], (int) *x, (int) *q);
}
return RPC_SUCCESS;
}
void register_cnaf_callback (int debug)
{
cnaf_debug = debug;
/* register CNAF callback */
cm_register_function (RPC_CNAF16, cnaf_callback);
cm_register_function (RPC_CNAF24, cnaf_callback);
}
/* end file */
|
Attachment 5: cnaf_callback_google.cxx
|
/********************************************************************\
Name: cnaf_callback.c
Created by: Stefan Ritt
Created by: moved here from mfe.c by Konstantin Olchanski
Contents: The system part of the MIDAS frontend. Has to be
linked with user code to form a complete frontend
$Id$
\********************************************************************/
#include <stdio.h>
#include <assert.h>
#include "midas.h"
#include "msystem.h"
#include "mcstd.h"
/*------------------------------------------------------------------*/
static int cnaf_debug = 0;
INT cnaf_callback(INT index, void *prpc_param[]) {
DWORD cmd, b, c, n, a, f, *pdword, *size, *x, *q, dtemp;
WORD *pword, *pdata, temp;
INT i, count;
/* Decode parameters */
cmd = CDWORD(0);
b = CDWORD(1);
c = CDWORD(2);
n = CDWORD(3);
a = CDWORD(4);
f = CDWORD(5);
pdword = CPDWORD(6);
pword = CPWORD(6);
pdata = CPWORD(6);
size = CPDWORD(7);
x = CPDWORD(8);
q = CPDWORD(9);
/* determine repeat count */
if (index == RPC_CNAF16)
count = *size / sizeof(WORD); /* 16 bit */
else
count = *size / sizeof(DWORD); /* 24 bit */
switch (cmd) {
/*---- special commands ----*/
case CNAF_INHIBIT_SET: cam_inhibit_set(c);
break;
case CNAF_INHIBIT_CLEAR: cam_inhibit_clear(c);
break;
case CNAF_CRATE_CLEAR: cam_crate_clear(c);
break;
case CNAF_CRATE_ZINIT: cam_crate_zinit(c);
break;
case CNAF_TEST: break;
case CNAF:
if (index == RPC_CNAF16) {
for (i = 0; i < count; i++)
if (f < 16)
cam16i_q(c, n, a, f, pword++, (int *) x, (int *) q);
else if (f < 24)
cam16o_q(c, n, a, f, pword[i], (int *) x, (int *) q);
else
cam16i_q(c, n, a, f, &temp, (int *) x, (int *) q);
} else {
for (i = 0; i < count; i++)
if (f < 16)
cam24i_q(c, n, a, f, pdword++, (int *) x, (int *) q);
else if (f < 24)
cam24o_q(c, n, a, f, pdword[i], (int *) x, (int *) q);
else
cam24i_q(c, n, a, f, &dtemp, (int *) x, (int *) q);
}
break;
case CNAF_nQ:
if (index == RPC_CNAF16) {
if (f < 16) {
cam16i_rq(c, n, a, f, &pword, count);
*size = (POINTER_T) pword - (POINTER_T) pdata;
}
} else {
if (f < 16) {
cam24i_rq(c, n, a, f, &pdword, count);
*size = (POINTER_T) pdword - (POINTER_T) pdata;
}
}
/* return reduced return size */
break;
default: printf("cnaf: Unknown command 0x%X\n", (unsigned int) cmd);
}
if (cnaf_debug) {
if (index == RPC_CNAF16)
printf("cmd=%d r=%d c=%d n=%d a=%d f=%d d=%X x=%d q=%d\n", (int) cmd, (int) count, (int) c, (int) n, (int) a,
(int) f, (int) pword[0], (int) *x, (int) *q);
else if (index == RPC_CNAF24)
printf("cmd=%d r=%d c=%d n=%d a=%d f=%d d=%X x=%d q=%d\n", (int) cmd, (int) count, (int) c, (int) n, (int) a,
(int) f, (int) pdword[0], (int) *x, (int) *q);
}
return RPC_SUCCESS;
}
void register_cnaf_callback(int debug) {
cnaf_debug = debug;
/* register CNAF callback */
cm_register_function(RPC_CNAF16, cnaf_callback);
cm_register_function(RPC_CNAF24, cnaf_callback);
}
/* end file */
|
2061
|
17 Dec 2020 |
Amy Roberts | Suggestion | Improving variable functionality in Sequencer? | We're using the sequencer to manage runs, and this typically looks something like:
1. save ODB keys to variables via ODBGET
2. set ODB keys to new values for a "pre-run" process
3. return ODB keys to values created in line 1
4. take data
The problem I'm running into is that the list of ODB keys to save is pretty
unwieldy. I'm wondering if there are sequencer features that exist or that I could
request that might make this easier.
For example, having a way to list ODB keys, save ODB directories, and load ODB
directories would be much more concise way for me to write my script.
Another option might be to have some version of the ODBSET wildcards for ODBGET.
Although for this, setting the variable names might be tricky.
In any case, even being able to ODBGET an array and set that to one variable name
would be a big improvement. |
2060
|
16 Dec 2020 |
Isaac Labrie Boulay | Forum | Issues building banks. | > > This is very hard to do using the mfe.c frontend. (the main reason I wrote the TMFE C++ frontend class).
>
> Actually that's not true. Just look at
>
> midas/examples/mtfe/mtfe.c
>
> this is an example for a frontend with equipment with the EQ_USER flag, which allows you easily to run a separate
> thread (or more) for event collection and processing. Of course all old-fashioned C style (code is from 2007) but it
> works.
>
> Stefan
Thank you sir I'll give it a look.
Cheers
Isaac |
2059
|
16 Dec 2020 |
Stefan Ritt | Forum | Issues building banks. | > This is very hard to do using the mfe.c frontend. (the main reason I wrote the TMFE C++ frontend class).
Actually that's not true. Just look at
midas/examples/mtfe/mtfe.c
this is an example for a frontend with equipment with the EQ_USER flag, which allows you easily to run a separate
thread (or more) for event collection and processing. Of course all old-fashioned C style (code is from 2007) but it
works.
Stefan |
2058
|
16 Dec 2020 |
Isaac Labrie Boulay | Forum | Issues building banks. | > > > > I'm currently trying to build events through doing block transfers.
> > >
> > > I am confused by your question. I assume you read a CAEN V792 ADC, but I do not know what VME master you
> > > use. The restrictions on data alignment come from the VME master.
> > > I am mostly familiar with restrictions of UniverseII and tsi148 PCI-VME bridges.
> > > I think there is no restriction for USB-VME bridges and similar.
> > >
> > > Anyhow. Which block transfer do you use? 32-bit block transfer (BLT32)? 64-bit block transfer (MBLT64)?
> > > (no 128-bit 2eVME/2eSST transfers from the V792). Maybe the "simulated block transfer" (DMA engine uses
> > > single-word reads instead of block transfer)?
> >
> > I read a single CAEN V792n QDC, 18 words, and a single CAEN V1190 TDC, 2 channels so 8 words. When I poll, I
> > read on every poll_event() and read whatever data is in whatever module (TDC_dataready || QDC_dataready). The
> > VME master that I'm using to talk to the modules is a CAEN V1718. I am trying to read data by BLT32. Sorry for
> > the confusing question (Can you tell I'm an intern?).
> >
>
> Ok, I see. Using the normal mfe.c structure, you will not be able to read the VME modules
> at maximum speed. This is because you must have two concurrent activities happening at the same time:
>
I am using the mfe.cxx backend thread, I'm guessing that this is the file you are referring to.
> (1) tell the VME bridge to read data,
> (2) package this data into midas banks and events and write it to the MIDAS event buffer.
>
> If you do these tasks sequentially, obviously the VME bus will be idle during step (2),
> and unless (2) takes 0 seconds (it does not) you will have a slow down.
>
I see.
> So for maximum data rate, I prefer to have 3 threads:
>
> thread 1: run the VME transfers, store data in circular buffer (today it would be std::deque<std::vector<char>>)
> thread 2: encode the data into midas banks and midas events, store completed events in a circular buffer
> (std::deque<EVENT_HEADER*>).
> thread 3: write data to midas event buffer (call bm_send_event(), etc)
>
> This is very hard to do using the mfe.c frontend. (the main reason I wrote the TMFE C++ frontend class).
Yes it seems like a bit of work
> >
> > Okay so transferring 18 + 6 words should give me close to 40kHz repetition rate. That's good news. I will just
> > stick to 1 word transfers.
> >
>
> I do not know the timing of CAEN V1718 single-word transfers. It may be significantly longer than 1 us:
>
> V7865: DWORD read - CPU - PCI bus - tsi148 - VME
> V1718: encode request as USB packet - CPU - PCI bus - USB hub - USB bus - USB asic - FPGA - VME (on the way back,
> "extract data from USB packet")
I found the following information in the CAEN V1718 manual:
"Transfer Rate = ~30MByte/s. Transfer rate supported in MBLT read cycles (block size = 32 kb), using a PC host with
Windows XP or Linux and High Speed USB"
I'm guessing the sentence simply means that the rate increases with multiplexed block transfers. If the transfer rate
is 30MBytes/s I should be able to write words at a transfer rate of 7500000 words per second.
>
> >
> > The way that transfers are done in the fevme.cxx requires iterating through 16 word arrays a number of time (3
> > times I believe if you include the iterations taking place in v792_EventRead()). Does that not pose a
> > significant deadtime concern?
> >
>
> Hmm... I am not sure what fevme you refer to. I guess I can find version of fevme.cxx where data is read at
> maximum VME speed if you want it.
This is the VME C++ frontend example in the directory /midas/examples/Triumf/c++/
If you can find a faster version of this code I would definitely like to check it out!
>
> K.O.
Thanks again.
Isaac |
2057
|
16 Dec 2020 |
Konstantin Olchanski | Forum | Issues building banks. | > > > I'm currently trying to build events through doing block transfers.
> >
> > I am confused by your question. I assume you read a CAEN V792 ADC, but I do not know what VME master you
> > use. The restrictions on data alignment come from the VME master.
> > I am mostly familiar with restrictions of UniverseII and tsi148 PCI-VME bridges.
> > I think there is no restriction for USB-VME bridges and similar.
> >
> > Anyhow. Which block transfer do you use? 32-bit block transfer (BLT32)? 64-bit block transfer (MBLT64)?
> > (no 128-bit 2eVME/2eSST transfers from the V792). Maybe the "simulated block transfer" (DMA engine uses
> > single-word reads instead of block transfer)?
>
> I read a single CAEN V792n QDC, 18 words, and a single CAEN V1190 TDC, 2 channels so 8 words. When I poll, I
> read on every poll_event() and read whatever data is in whatever module (TDC_dataready || QDC_dataready). The
> VME master that I'm using to talk to the modules is a CAEN V1718. I am trying to read data by BLT32. Sorry for
> the confusing question (Can you tell I'm an intern?).
>
Ok, I see. Using the normal mfe.c structure, you will not be able to read the VME modules
at maximum speed. This is because you must have two concurrent activities happening at the same time:
(1) tell the VME bridge to read data,
(2) package this data into midas banks and events and write it to the MIDAS event buffer.
If you do these tasks sequentially, obviously the VME bus will be idle during step (2),
and unless (2) takes 0 seconds (it does not) you will have a slow down.
So for maximum data rate, I prefer to have 3 threads:
thread 1: run the VME transfers, store data in circular buffer (today it would be std::deque<std::vector<char>>)
thread 2: encode the data into midas banks and midas events, store completed events in a circular buffer
(std::deque<EVENT_HEADER*>).
thread 3: write data to midas event buffer (call bm_send_event(), etc)
This is very hard to do using the mfe.c frontend. (the main reason I wrote the TMFE C++ frontend class).
>
> Okay so transferring 18 + 6 words should give me close to 40kHz repetition rate. That's good news. I will just
> stick to 1 word transfers.
>
I do not know the timing of CAEN V1718 single-word transfers. It may be significantly longer than 1 us:
V7865: DWORD read - CPU - PCI bus - tsi148 - VME
V1718: encode request as USB packet - CPU - PCI bus - USB hub - USB bus - USB asic - FPGA - VME (on the way back,
"extract data from USB packet")
>
> The way that transfers are done in the fevme.cxx requires iterating through 16 word arrays a number of time (3
> times I believe if you include the iterations taking place in v792_EventRead()). Does that not pose a
> significant deadtime concern?
>
Hmm... I am not sure what fevme you refer to. I guess I can find version of fevme.cxx where data is read at
maximum VME speed if you want it.
K.O. |
2056
|
16 Dec 2020 |
Isaac Labrie Boulay | Forum | Issues building banks. | Thanks for the quick reply,
> > I'm currently trying to build events through doing block transfers.
>
> I am confused by your question. I assume you read a CAEN V792 ADC, but I do not know what VME master you
> use. The restrictions on data alignment come from the VME master.
> I am mostly familiar with restrictions of UniverseII and tsi148 PCI-VME bridges.
> I think there is no restriction for USB-VME bridges and similar.
>
> Anyhow. Which block transfer do you use? 32-bit block transfer (BLT32)? 64-bit block transfer (MBLT64)?
> (no 128-bit 2eVME/2eSST transfers from the V792). Maybe the "simulated block transfer" (DMA engine uses
> single-word reads instead of block transfer)?
I read a single CAEN V792n QDC, 18 words, and a single CAEN V1190 TDC, 2 channels so 8 words. When I poll, I
read on every poll_event() and read whatever data is in whatever module (TDC_dataready || QDC_dataready). The
VME master that I'm using to talk to the modules is a CAEN V1718. I am trying to read data by BLT32. Sorry for
the confusing question (Can you tell I'm an intern?).
> > The worry was that organizing and packaging bank data into an array would produce too much dead time
> causing too many missed events.
>
> Valid concerns.
>
> > I'm running into all sorts of issues such as unaligned transfers where the QDC events are unaligned, or
> improperly aligned banks.
>
> You should not see any problems with unaligned transfers if you give the DMA engine
> correct memory addresses as required by the hardware:
>
> - always aligned to 32-bit (4 bytes, last two address bits set to 0)
> - aligned to 64-bits for MBLT64 64-bit transfers, this would be the normal case for the V792 (8 bytes,
> last 3 address bits set to 0)
> - aligned to 128-bits for 2eVME/2eSST transfers (16 bytes, last 4 bits of address are zero).
>
> You also need to specify correct amount of data to read: number of bytes should be multiple of 4 for 32-
> bit transfers, multiple to 8 for 64-bit transfers and multiple of 16 for 128-bit transfers (2eVME/2eSST).
I am transferring 32-bit words. Transferring 32-bit words should always read multiples of 4 bytes so that's
good.
> Very often this requires reading "extra" data words. Most VME modules can generate extra pad words to
> align event length to DMA restrictions. Sometimes you need to
> enable this in a control register (V792, V1190).
>
> > Giving me a headache.
>
> Me too. MIDAS recently introduced the QWORD 64-bit data type, banks of this type
> should have correct alignment for 64-bit VME block transfers. But for 2eVME/2eSST
> transfers, I still have to ensure alignment "by hand" (SIS3820, VF48, etc).
>
> With QWORD banks, you need to use bk_init32a() instead of bk_init32().
>
> > My question is, if I were to revert back to simple 32 bit read cycles
>
> Yes, I always test with single-word reads first, with the 32-bit block transfer second and try the 64-bit
> block transfer last.
>
> Sometimes there are unrelated problems (with the VME modules, VME bus, etc, or
> with bugs in the frontend, etc) and this approach helps to identify the source
> of trouble.
>
> > and using
> > the fevme.cxx template's method of organizing data before sending them to the
> > buffer, what kind of deadtime should I expect? Am I wrong to assume that this
> > would result in deadtime at all? I'm using a CAEN V792n 16 channel QDC and the hit
> > frequency that I'm using to test is 20kHz.
>
> Yes, with asynchronous read using 64-bit block transfer, 20 kHz should be achievable.
>
> The old fevme frontend is based on the mfe.c framework and implementing
> async readout requires special contortions. The structure of the new TMFE C++ frontend
> class is supposed to make it easier, but I do not have an example TMFE based fevme yet.
>
> P.S. Without using block transfer, your max rate is limited to:
>
> 16 channels, 1 word per channel, plus 1 header and 1 footer = 18 words (by luck, 64-bit aligned for
> correct BLT64 block read).
>
> using VME single-word read at 1 us per transfer, 18 us per event = 55 kHz repetition rate.
>
> (you do not say if you have any other VME modules you have to read)
>
Okay so transferring 18 + 6 words should give me close to 40kHz repetition rate. That's good news. I will just
stick to 1 word transfers.
The way that transfers are done in the fevme.cxx requires iterating through 16 word arrays a number of time (3
times I believe if you include the iterations taking place in v792_EventRead()). Does that not pose a
significant deadtime concern?
> K.O.
Thanks again for taking the time to help me out!
Cheers.
Isaac |
2055
|
16 Dec 2020 |
Konstantin Olchanski | Forum | Issues building banks. | > I'm currently trying to build events through doing block transfers.
I am confused by your question. I assume you read a CAEN V792 ADC, but I do not know what VME master you
use. The restrictions on data alignment come from the VME master.
I am mostly familiar with restrictions of UniverseII and tsi148 PCI-VME bridges.
I think there is no restriction for USB-VME bridges and similar.
Anyhow. Which block transfer do you use? 32-bit block transfer (BLT32)? 64-bit block transfer (MBLT64)?
(no 128-bit 2eVME/2eSST transfers from the V792). Maybe the "simulated block transfer" (DMA engine uses
single-word reads instead of block transfer)?
> The worry was that organizing and packaging bank data into an array would produce too much dead time
causing too many missed events.
Valid concerns.
> I'm running into all sorts of issues such as unaligned transfers where the QDC events are unaligned, or
improperly aligned banks.
You should not see any problems with unaligned transfers if you give the DMA engine
correct memory addresses as required by the hardware:
- always aligned to 32-bit (4 bytes, last two address bits set to 0)
- aligned to 64-bits for MBLT64 64-bit transfers, this would be the normal case for the V792 (8 bytes,
last 3 address bits set to 0)
- aligned to 128-bits for 2eVME/2eSST transfers (16 bytes, last 4 bits of address are zero).
You also need to specify correct amount of data to read: number of bytes should be multiple of 4 for 32-
bit transfers, multiple to 8 for 64-bit transfers and multiple of 16 for 128-bit transfers (2eVME/2eSST).
Very often this requires reading "extra" data words. Most VME modules can generate extra pad words to
align event length to DMA restrictions. Sometimes you need to
enable this in a control register (V792, V1190).
> Giving me a headache.
Me too. MIDAS recently introduced the QWORD 64-bit data type, banks of this type
should have correct alignment for 64-bit VME block transfers. But for 2eVME/2eSST
transfers, I still have to ensure alignment "by hand" (SIS3820, VF48, etc).
With QWORD banks, you need to use bk_init32a() instead of bk_init32().
> My question is, if I were to revert back to simple 32 bit read cycles
Yes, I always test with single-word reads first, with the 32-bit block transfer second and try the 64-bit
block transfer last.
Sometimes there are unrelated problems (with the VME modules, VME bus, etc, or
with bugs in the frontend, etc) and this approach helps to identify the source
of trouble.
> and using
> the fevme.cxx template's method of organizing data before sending them to the
> buffer, what kind of deadtime should I expect? Am I wrong to assume that this
> would result in deadtime at all? I'm using a CAEN V792n 16 channel QDC and the hit
> frequency that I'm using to test is 20kHz.
Yes, with asynchronous read using 64-bit block transfer, 20 kHz should be achievable.
The old fevme frontend is based on the mfe.c framework and implementing
async readout requires special contortions. The structure of the new TMFE C++ frontend
class is supposed to make it easier, but I do not have an example TMFE based fevme yet.
P.S. Without using block transfer, your max rate is limited to:
16 channels, 1 word per channel, plus 1 header and 1 footer = 18 words (by luck, 64-bit aligned for
correct BLT64 block read).
using VME single-word read at 1 us per transfer, 18 us per event = 55 kHz repetition rate.
(you do not say if you have any other VME modules you have to read)
K.O. |
|