Skip to content

Commit d77e697

Browse files
committed
moved value parser public and added strong parser for ALF-style parameter strings
1 parent a82f6a9 commit d77e697

File tree

3 files changed

+152
-78
lines changed

3 files changed

+152
-78
lines changed

include/ReadoutCard/PatternPlayer.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class PatternPlayer
3333
{
3434
public:
3535
struct Info {
36+
// as defined in https://gitlab.cern.ch/alice-cru/cru-fw/-/tree/pplayer/TTC#address-table
3637
uint128_t pat0= 0x0;
3738
uint128_t pat1 = 0x0;
3839
uint128_t pat2 = 0x0;
@@ -55,6 +56,19 @@ class PatternPlayer
5556
void play(PatternPlayer::Info info);
5657
PatternPlayer::Info read();
5758

59+
// helper function to fill Info fields from string
60+
// 128-bit string parser (both hex and decimal)
61+
// nBits specifies the maximum allowed bit width
62+
// name is used in the error message, if any
63+
// throws exception on error
64+
static uint128_t getValueFromString(const std::string &s, unsigned int nBits = 128, const std::string &name = "");
65+
66+
// parse a vector of strings into an Info struct
67+
// strings with # are considered as comments and not used
68+
// number of valid strings must match exactly number of parameters in struct
69+
// throws an exception on error
70+
static PatternPlayer::Info getInfoFromString(const std::vector<std::string> &parameters);
71+
5872
private:
5973
void configure(bool startConfig);
6074
void exePat1AtStart(bool enable = false);

src/CommandLineUtilities/ProgramPatternPlayer.cxx

Lines changed: 1 addition & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -32,82 +32,6 @@ using namespace o2::roc;
3232
namespace po = boost::program_options;
3333
using namespace boost::multiprecision;
3434

35-
// print uin128_t value as a readable hexa value
36-
void print_uint128(uint128_t v) {
37-
printf ("0x ");
38-
for (int k = 8; k > 0; k--) {
39-
printf("%04X ", (unsigned int)((v >> ((k-1)*16)) & 0xffff));
40-
}
41-
printf("\n");
42-
}
43-
44-
// 128-bit string parser (both hex and decimal)
45-
// nBits specifies the maximum allowed bit width
46-
// throws exception on error
47-
uint128_t parsePattern(const std::string &s, unsigned int nBits = 128, const std::string &name = "") {
48-
if (nBits > 128) {
49-
nBits = 128;
50-
}
51-
uint128_t v = 0;
52-
uint128_t vmax = (((uint128_t)1) << nBits) - 1;
53-
std::string error = "Parsing option " + name + " : ";
54-
auto addDigit = [&] (uint128_t digit, uint128_t base) {
55-
bool overflow = 0;
56-
if (digit >= base) {
57-
overflow =1;
58-
} else if (v > (vmax / base)) {
59-
overflow = 1;
60-
}
61-
v = v * ((uint128_t)base);
62-
if (v > vmax - ((uint128_t)digit)) {
63-
overflow = 1;
64-
}
65-
v = v + ((uint128_t)digit);
66-
if (v > vmax) {
67-
overflow = 1;
68-
}
69-
if (overflow) {
70-
BOOST_THROW_EXCEPTION(InvalidOptionValueException()
71-
<< ErrorInfo::Message(error + "Value exceeds " + std::to_string(nBits) + " bits"));
72-
}
73-
return;
74-
};
75-
if (!strncmp(s.c_str(), "0x", 2)) {
76-
// hexadecimal string
77-
for (unsigned int i=2; i<s.length(); i++) {
78-
uint8_t c = s[i];
79-
uint128_t x = 0;
80-
if ( ( c >= '0') && ( c <= '9')) {
81-
x = c - '0';
82-
} else if ( ( c >= 'A') && ( c <= 'F')) {
83-
x = 10 + c - 'A';
84-
} else if ( ( c >= 'a') && ( c <= 'f')) {
85-
x = 10 + c - 'a';
86-
} else {
87-
BOOST_THROW_EXCEPTION(InvalidOptionValueException()
88-
<< ErrorInfo::Message(error + "Value has wrong hexadecimal syntax"));
89-
}
90-
addDigit(x, (uint128_t)16);
91-
}
92-
} else {
93-
// decimal string
94-
for (unsigned int i=0; i<s.length(); i++) {
95-
uint8_t c = s[i];
96-
uint128_t x = 0;
97-
if ( ( c >= '0') && ( c <= '9')) {
98-
x = c - '0';
99-
} else {
100-
BOOST_THROW_EXCEPTION(InvalidOptionValueException()
101-
<< ErrorInfo::Message(error + "Value has wrong decimal syntax"));
102-
}
103-
addDigit(x, (uint128_t)10);
104-
}
105-
}
106-
return v;
107-
}
108-
109-
110-
11135

11236
class ProgramPatternPlayer : public Program
11337
{
@@ -153,7 +77,6 @@ class ProgramPatternPlayer : public Program
15377

15478
virtual void run(const boost::program_options::variables_map& map)
15579
{
156-
15780
auto cardId = Options::getOptionCardId(map);
15881
auto params = Parameters::makeParameters(cardId, 2);
15982
auto bar2 = ChannelFactory().getBar(params);
@@ -232,7 +155,7 @@ class ProgramPatternPlayer : public Program
232155
for(const auto &opt : optionValues) {
233156
if (opt.value.length()) {
234157
uint128_t v;
235-
v = parsePattern(opt.value, opt.bitWidth, opt.name);
158+
v = PatternPlayer::getValueFromString(opt.value, opt.bitWidth, opt.name);
236159
if (opt.type == OptionValue::OptionValueType::UINT32) {
237160
*(static_cast<uint32_t *>(opt.destination)) = (uint32_t)v;
238161
} else if (opt.type == OptionValue::OptionValueType::UINT128) {

src/Cru/PatternPlayer.cxx

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,5 +154,142 @@ void PatternPlayer::exePat2()
154154
mBar->modifyRegister(Cru::Registers::PATPLAYER_CFG.index, 4, 1, 0x0);
155155
}
156156

157+
uint128_t PatternPlayer::getValueFromString(const std::string &s, unsigned int nBits, const std::string &name) {
158+
if (nBits > 128) {
159+
nBits = 128;
160+
}
161+
uint128_t v = 0;
162+
uint128_t vmax = (((uint128_t)1) << nBits) - 1;
163+
std::string error = "Parsing parameter " + name + " : ";
164+
auto addDigit = [&] (uint128_t digit, uint128_t base) {
165+
bool overflow = 0;
166+
if (digit >= base) {
167+
overflow =1;
168+
} else if (v > (vmax / base)) {
169+
overflow = 1;
170+
}
171+
v = v * ((uint128_t)base);
172+
if (v > vmax - ((uint128_t)digit)) {
173+
overflow = 1;
174+
}
175+
v = v + ((uint128_t)digit);
176+
if (v > vmax) {
177+
overflow = 1;
178+
}
179+
if (overflow) {
180+
BOOST_THROW_EXCEPTION(InvalidOptionValueException()
181+
<< ErrorInfo::Message(error + "Value exceeds " + std::to_string(nBits) + " bits"));
182+
}
183+
return;
184+
};
185+
if (!strncmp(s.c_str(), "0x", 2)) {
186+
// hexadecimal string
187+
for (unsigned int i=2; i<s.length(); i++) {
188+
uint8_t c = s[i];
189+
uint128_t x = 0;
190+
if ( ( c >= '0') && ( c <= '9')) {
191+
x = c - '0';
192+
} else if ( ( c >= 'A') && ( c <= 'F')) {
193+
x = 10 + c - 'A';
194+
} else if ( ( c >= 'a') && ( c <= 'f')) {
195+
x = 10 + c - 'a';
196+
} else {
197+
BOOST_THROW_EXCEPTION(InvalidOptionValueException()
198+
<< ErrorInfo::Message(error + "Value has wrong hexadecimal syntax"));
199+
}
200+
addDigit(x, (uint128_t)16);
201+
}
202+
} else {
203+
// decimal string
204+
for (unsigned int i=0; i<s.length(); i++) {
205+
uint8_t c = s[i];
206+
uint128_t x = 0;
207+
if ( ( c >= '0') && ( c <= '9')) {
208+
x = c - '0';
209+
} else {
210+
BOOST_THROW_EXCEPTION(InvalidOptionValueException()
211+
<< ErrorInfo::Message(error + "Value has wrong decimal syntax"));
212+
}
213+
addDigit(x, (uint128_t)10);
214+
}
215+
}
216+
return v;
217+
}
218+
219+
PatternPlayer::Info PatternPlayer::getInfoFromString(const std::vector<std::string> &parameters) {
220+
roc::PatternPlayer::Info ppInfo;
221+
222+
int infoField = 0;
223+
for (const auto& parameter : parameters) {
224+
if (parameter.find('#') == std::string::npos) {
225+
infoField++;
226+
}
227+
}
228+
229+
if (infoField != 15) { // Test that we have enough non-comment parameters
230+
BOOST_THROW_EXCEPTION(InvalidOptionValueException() << ErrorInfo::Message("Wrong number of non-comment parameters for the Pattern Player: " + std::to_string(infoField) + "/15"));
231+
}
232+
233+
infoField = 0;
234+
for (const auto& parameter : parameters) {
235+
if (parameter.find('#') == std::string::npos) {
236+
switch (infoField) {
237+
bool boolValue;
238+
case 0:
239+
ppInfo.pat0 = PatternPlayer::getValueFromString(parameter, 80, "pat0");
240+
break;
241+
case 1:
242+
ppInfo.pat1 = PatternPlayer::getValueFromString(parameter, 80, "pat1");
243+
break;
244+
case 2:
245+
ppInfo.pat2 = PatternPlayer::getValueFromString(parameter, 80, "pat2");
246+
break;
247+
case 3:
248+
ppInfo.pat3 = PatternPlayer::getValueFromString(parameter, 80, "pat3");
249+
break;
250+
case 4:
251+
ppInfo.pat1Length = (uint32_t)PatternPlayer::getValueFromString(parameter, 32, "pat1Length");
252+
break;
253+
case 5:
254+
ppInfo.pat1Delay = (uint32_t)PatternPlayer::getValueFromString(parameter, 32, "pat1Delay");
255+
break;
256+
case 6:
257+
ppInfo.pat2Length = (uint32_t)PatternPlayer::getValueFromString(parameter, 32, "pat2Length");
258+
break;
259+
case 7:
260+
ppInfo.pat3Length = (uint32_t)PatternPlayer::getValueFromString(parameter, 32, "pat3Length");
261+
break;
262+
case 8:
263+
ppInfo.pat1TriggerSelect = (uint32_t)PatternPlayer::getValueFromString(parameter, 32, "pat1TriggerSelect");
264+
break;
265+
case 9:
266+
ppInfo.pat2TriggerSelect = (uint32_t)PatternPlayer::getValueFromString(parameter, 32, "pat2TriggerSelect");
267+
break;
268+
case 10:
269+
ppInfo.pat3TriggerSelect = (uint32_t)PatternPlayer::getValueFromString(parameter, 32, "pat3TriggerSelect");
270+
break;
271+
case 11:
272+
ppInfo.pat2TriggerTF = (uint32_t)PatternPlayer::getValueFromString(parameter, 32, "pat2TriggerTF");
273+
break;
274+
case 12:
275+
std::istringstream(parameter) >> std::boolalpha >> boolValue;
276+
ppInfo.exePat1AtStart = boolValue;
277+
break;
278+
case 13:
279+
std::istringstream(parameter) >> std::boolalpha >> boolValue;
280+
ppInfo.exePat1Now = boolValue;
281+
break;
282+
case 14:
283+
std::istringstream(parameter) >> std::boolalpha >> boolValue;
284+
ppInfo.exePat2Now = boolValue;
285+
break;
286+
}
287+
infoField++;
288+
}
289+
}
290+
return ppInfo;
291+
}
292+
293+
157294
} // namespace roc
158295
} // namespace o2

0 commit comments

Comments
 (0)