Skip to content

Commit 14d2d90

Browse files
Bugfixes
1 parent 9e2ccc0 commit 14d2d90

File tree

5 files changed

+99
-94
lines changed

5 files changed

+99
-94
lines changed

src/CommandLineUtilities/AliceLowlevelFrontend/AliceLowlevelFrontend.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ inline bool isFail(const std::string& string)
102102
inline std::string stripPrefix(const std::string& string)
103103
{
104104
if (string.length() < PREFIX_LENGTH) {
105-
printf("len=%ul str=%s\n", string.length(), string.c_str());
105+
printf("len=%lu str=%s\n", string.length(), string.c_str());
106106
BOOST_THROW_EXCEPTION(AlfException() << ErrorInfo::Message("string too short to contain prefix"));
107107
}
108108
return string.substr(PREFIX_LENGTH);
@@ -247,7 +247,7 @@ class RegisterWriteRpc: DimRpcInfoWrapper
247247

248248
void writeRegister(uint64_t registerAddress, uint32_t registerValue)
249249
{
250-
setString((boost::format("0x%x,0x%x") % registerAddress % registerValue).str());
250+
setString((boost::format("0x%x%s0x%x") % registerAddress % argumentSeparator() % registerValue).str());
251251
getString();
252252
}
253253
};
@@ -277,7 +277,7 @@ class ScaWriteRpc: DimRpcInfoWrapper
277277

278278
std::string write(uint32_t command, uint32_t data)
279279
{
280-
setString((boost::format("0x%x,0x%x") % command % data).str());
280+
setString((boost::format("0x%x%s0x%x") % command % scaPairSeparator() % data).str());
281281
return stripPrefix(getString());
282282
}
283283
};
@@ -330,9 +330,9 @@ class ScaWriteSequence: DimRpcInfoWrapper
330330
{
331331
std::stringstream buffer;
332332
for (size_t i = 0; i < sequence.size(); ++i) {
333-
buffer << sequence[i].first << ',' << sequence[i].second;
333+
buffer << sequence[i].first << scaPairSeparator() << sequence[i].second;
334334
if (i + 1 < sequence.size()) {
335-
buffer << '\n';
335+
buffer << argumentSeparator();
336336
}
337337
}
338338
return write(buffer.str());

src/CommandLineUtilities/AliceLowlevelFrontend/ProgramAliceLowlevelFrontendClient.cxx

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
/// \author Pascal Boeschoten ([email protected])
55

66
#include "CommandLineUtilities/Program.h"
7+
#include "Common/GuardFunction.h"
78
#include <iostream>
89
#include <thread>
910
#include <dim/dic.hxx>
@@ -43,7 +44,7 @@ class ProgramAliceLowlevelFrontendClient: public Program
4344
virtual Description getDescription() override
4445
{
4546
return {"ALF DIM Client example", "ALICE low-level front-end DIM Client example",
46-
"roc-alf-client --serial=12345"};
47+
"roc-alf-client --serial=12345 --link=42"};
4748
}
4849

4950
virtual void addOptions(boost::program_options::options_description& options) override
@@ -57,7 +58,8 @@ class ProgramAliceLowlevelFrontendClient: public Program
5758
{
5859
// Get DIM DNS node from environment
5960
if (getenv(std::string("DIM_DNS_NODE").c_str()) == nullptr) {
60-
BOOST_THROW_EXCEPTION(Alf::AlfException() << Alf::ErrorInfo::Message("Environment variable 'DIM_DNS_NODE' not set"));
61+
BOOST_THROW_EXCEPTION(
62+
Alf::AlfException() << Alf::ErrorInfo::Message("Environment variable 'DIM_DNS_NODE' not set"));
6163
}
6264

6365
cout << "Using serial=" << mSerialNumber << " link=" << mLink << '\n';
@@ -72,23 +74,41 @@ class ProgramAliceLowlevelFrontendClient: public Program
7274
Alf::ScaGpioReadRpc scaGpioReadRpc(names.scaGpioRead());
7375
Alf::ScaGpioWriteRpc scaGpioWriteRpc(names.scaGpioWrite());
7476
Alf::ScaWriteSequence scaWriteSequence(names.scaWriteSequence());
75-
Alf::PublishRegistersStartRpc publishRpc(names.publishRegistersStart());
76-
Alf::PublishScaSequenceStartRpc publishScaRpc(names.publishScaSequenceStart());
77+
Alf::PublishRegistersStartRpc publishRegistersStartRpc(names.publishRegistersStart());
78+
Alf::PublishRegistersStopRpc publishRegistersStopRpc(names.publishRegistersStop());
79+
Alf::PublishScaSequenceStartRpc publishScaSequenceStartRpc(names.publishScaSequenceStart());
80+
Alf::PublishScaSequenceStopRpc publishScaSequenceStopRpc(names.publishScaSequenceStop());
81+
82+
publishRegistersStartRpc.publish("TEST_1", 5.0, {0x1fc});
83+
publishRegistersStartRpc.publish("TEST_2", 5.0, {0x100, 0x104});
84+
publishScaSequenceStartRpc.publish("TEST_3", 2.5, {{0x0, 0x1}, {0x10, 0x11}});
7785

78-
publishRpc.publish("TEST_1", 1.0, {0x1fc});
79-
publishRpc.publish("TEST_2", 3.0, {0x100, 0x104, 0x108});
80-
publishScaRpc.publish("TEST_3", 1.0, {{0x0, 0x1}, {0x10, 0x11}});
86+
AliceO2::Common::GuardFunction publishStopper{
87+
[&]() {
88+
publishRegistersStopRpc.stop("TEST_1");
89+
publishRegistersStopRpc.stop("TEST_2");
90+
publishScaSequenceStopRpc.stop("TEST_3");
91+
}
92+
};
93+
94+
for (int i = 0; i < 3; ++i) {
95+
cout << "SCA write '" << i << "'" << endl;
96+
cout << " result: " << scaWriteRpc.write(0xabcdabcd, i) << endl;
97+
cout << "SCA read" << endl;
98+
cout << " result: " << scaReadRpc.read() << endl;
99+
}
81100

82-
for (int i = 0; i < 10; ++i) {
101+
for (int i = 0; i < 3; ++i) {
83102
cout << "SCA GPIO write '" << i << "'" << endl;
84103
cout << " result: " << scaGpioWriteRpc.write(i) << endl;
85104
cout << "SCA GPIO read" << endl;
86105
cout << " result: " << scaGpioReadRpc.read() << endl;
87106
}
88107

89108
{
90-
cout << "1k writes to 0x1fc..." << endl;
91-
for (int i = 0; i < 1000; ++i) {
109+
cout << "Reads & writes to 0x1fc..." << endl;
110+
for (int i = 0; i < 3; ++i) {
111+
writeRpc.writeRegister(0x1fc, 0x123);
92112
readRpc.readRegister(0x1fc);
93113
}
94114
cout << "Done!" << endl;
@@ -99,7 +119,7 @@ class ProgramAliceLowlevelFrontendClient: public Program
99119
cout << "Writing blob of " << numInts << " pairs of 32-bit ints..." << endl;
100120
std::vector<std::pair<uint32_t, uint32_t>> buffer(numInts);
101121
for (size_t i = 0; i < buffer.size(); ++i) {
102-
buffer[i] = {i * 2, i * 2 + 1};
122+
buffer[i] = {0xabcdab + i * 2, 0xabcdab + i * 2 + 1};
103123
}
104124

105125
std::string result = scaWriteSequence.write(buffer);
@@ -110,39 +130,23 @@ class ProgramAliceLowlevelFrontendClient: public Program
110130

111131
{
112132
cout << "Writing blob with comments..." << endl;
113-
std::string result = scaWriteSequence.write("# Hello!\n11,22\n33,44\n# Bye!");
133+
std::string result = scaWriteSequence.write("# Hello!\nabcdab11,22\nabcdab33,44\n# Bye!");
114134
cout << "Done!" << endl;
115135
cout << "Got result: \n";
116136
cout << " " << result << '\n';
117137
}
118138

139+
try {
140+
cout << "Writing bad blob..." << endl;
141+
std::string result = scaWriteSequence.write("I AM BAD\n11,22\n33,44\nAAAAAAAAaaaaa");
142+
} catch (const Alf::AlfException& e) {
143+
cout << "Successfully broke the server!\n";
144+
}
145+
119146
while (!isSigInt())
120147
{
121-
// cout << "-------------------------------------\n";
122-
// cout << "Temperature = " << gTemperature << endl;
123-
//
124-
// int writes = 10; //std::rand() % 50;
125-
// cout << "Write 0x1f8 = 0x1 times " << writes << endl;
126-
// for (int i = 0; i < writes; ++i) {
127-
// writeRpc.writeRegister(0x1f8, 0x1);
128-
// }
129-
//
130-
// cout << "Read 0x1fc = " << readRpc.readRegister(0x1fc) << endl;
131-
// cout << "Read 0x1ec = " << readRpc.readRegister(0x1ec) << endl;
132-
// cout << "Cmd 0x1f4 = 0x1" << endl;
133-
// writeRpc.writeRegister(0x1f4, 0x1);
134-
// cout << "Cmd 0x1f4 = 0x2" << endl;
135-
// writeRpc.writeRegister(0x1f4, 0x1);
136-
// cout << "Cmd 0x1f4 = 0x3" << endl;
137-
// writeRpc.writeRegister(0x1f4, 0x1);
138148
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
139149
}
140-
141-
Alf::PublishRegistersStopRpc publishRegistersStopRpc(names.publishRegistersStop());
142-
Alf::PublishScaSequenceStopRpc publishScaSequenceStopRpc(names.publishScaSequenceStop());
143-
publishRegistersStopRpc.stop("TEST_1");
144-
publishScaSequenceStopRpc.stop("TEST_2");
145-
publishScaSequenceStopRpc.stop("TEST_3");
146150
}
147151

148152
int mSerialNumber;

src/CommandLineUtilities/AliceLowlevelFrontend/ProgramAliceLowlevelFrontendServer.cxx

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ class StringRpcServer: public DimRpc
8585
};
8686

8787
/// Splits a string
88-
static std::vector<std::string> split(const std::string& string, const char* separators)
88+
static std::vector<std::string> split(const std::string& string, std::string separators)
8989
{
9090
std::vector<std::string> split;
91-
b::split(split, string, b::is_any_of(separators));
91+
b::split(split, string, b::is_any_of(separators.c_str()));
9292
return split;
9393
}
9494

@@ -203,6 +203,7 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
203203
} catch (const Exception& exception) {
204204
getLogger() << "Failed to get devices: " << exception.what() << endm;
205205
}
206+
// Add dummy card
206207
cardsFound.push_back(
207208
CardDescriptor{CardType::Dummy, ChannelFactory::getDummySerialNumber(), {"dummy", "dummy"}, {0, 0, 0}});
208209

@@ -375,15 +376,15 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
375376
/// Publish updated values
376377
void serviceUpdate(Service& service)
377378
{
378-
getLogger() << "Updating '" << service.description.dnsName << "':" << endm;
379+
getLogger() << "Updating '" << service.description.dnsName << "'" << endm;
379380

380381
Visitor::apply(service.description.type,
381382
[&](const ServiceDescription::Register& type){
382383
auto& bar0 = *(mBars.at(service.description.linkInfo.serial).at(0));
383384
for (size_t i = 0; i < type.addresses.size(); ++i) {
384385
auto index = type.addresses[i] / 4;
385386
auto value = bar0.readRegister(index);
386-
service.registerValues.at(i) = bar0.readRegister(index);
387+
service.registerValues.at(i) = value;
387388
}
388389
},
389390
[&](const ServiceDescription::ScaSequence& type){
@@ -435,34 +436,24 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
435436
checkAddress(address);
436437

437438
uint32_t value = channel->readRegister(address / 4);
438-
439439
getLogger() << "READ " << Common::makeRegisterString(address, value) << endm;
440-
441440
return (b::format("0x%x") % value).str();
442441
}
443442

444443
/// RPC handler for register writes
445444
static std::string registerWrite(const std::string& parameter, BarSharedPtr channel)
446445
{
447-
std::vector<std::string> params = split(parameter, argumentSeparator().c_str());
446+
std::vector<std::string> params = split(parameter, argumentSeparator());
448447

449448
if (params.size() != 2) {
450449
BOOST_THROW_EXCEPTION(AlfException() << ErrorInfo::Message("Write RPC call did not have 2 parameters"));
451450
}
452451

453-
auto address = convertHexString(params[0]);;
454-
auto value = convertHexString(params[1]);;
452+
auto address = convertHexString(params.at(0));;
453+
auto value = convertHexString(params.at(1));;
455454
checkAddress(address);
456455

457456
getLogger() << "WRITE " << Common::makeRegisterString(address, value) << endm;
458-
459-
if (address == 0x1f4) {
460-
// This is to the command register, we need to wait until the card indicates it's not busy before sending a
461-
// command
462-
while (!isSigInt() && (channel->readRegister(0x1f0 / 4) & 0x80000000)) {
463-
}
464-
}
465-
466457
channel->writeRegister(address / 4, value);
467458
return "";
468459
}
@@ -472,18 +463,27 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
472463
LinkInfo linkInfo)
473464
{
474465
getLogger() << "PUBLISH_REGISTERS_START: '" << parameter << "'" << endm;
475-
auto params = split(parameter, argumentSeparator().c_str());
476466

477-
size_t args = 2;
467+
auto params = split(parameter, argumentSeparator());
468+
auto dnsName = params.at(0);
469+
auto interval = params.at(1);
470+
471+
if (params.size() < 3) {
472+
BOOST_THROW_EXCEPTION(AlfException()
473+
<< ErrorInfo::Message("Not enough parameters given"));
474+
}
475+
476+
// Convert register string sequence to binary format
477+
size_t skip = 2; // First two arguments don't go in the array
478478
std::vector<uintptr_t> registers;
479-
for (size_t i = 0; (i + args) < params.size(); ++i) {
480-
registers.push_back(b::lexical_cast<uintptr_t >(i + args));
479+
for (size_t i = 0; (i + skip) < params.size(); ++i) {
480+
registers.push_back(b::lexical_cast<uintptr_t >(i + skip));
481481
}
482482

483483
auto command = std::make_unique<CommandQueue::Command>();
484484
command->start = true;
485-
command->description.dnsName = ServiceNames(linkInfo.serial, linkInfo.link).publishRegistersSubdir(params.at(0));
486-
command->description.interval = std::chrono::milliseconds(int64_t(b::lexical_cast<double>(params.at(1)) * 1000.0));
485+
command->description.dnsName = ServiceNames(linkInfo.serial, linkInfo.link).publishRegistersSubdir(dnsName);
486+
command->description.interval = std::chrono::milliseconds(int64_t(b::lexical_cast<double>(interval) * 1000.0));
487487
command->description.type = ServiceDescription::Register{std::move(registers)};
488488
command->description.linkInfo = linkInfo;
489489

@@ -497,31 +497,28 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
497497
{
498498
getLogger() << "PUBLISH_SCA_SEQUENCE_START: '" << parameter << "'" << endm;
499499

500-
auto params = split(parameter, argumentSeparator().c_str());
500+
auto params = split(parameter, argumentSeparator());
501+
auto dnsName = params.at(0);
502+
auto interval = params.at(1);
501503

502504
if (params.size() < 3) {
503505
BOOST_THROW_EXCEPTION(AlfException()
504506
<< ErrorInfo::Message("Not enough parameters given"));
505507
}
506508

507-
size_t args = 2; // Number of args to skip for the array
508-
std::vector<uintptr_t> registers;
509-
for (size_t i = args; (i + args) < params.size(); ++i) {
510-
registers.push_back(b::lexical_cast<uintptr_t >(i));
511-
}
512-
513509
// Convert command-data pair string sequence to binary format
510+
size_t skip = 2; // Number of arguments to skip for the array
514511
ServiceDescription::ScaSequence sca;
515-
sca.commandDataPairs.resize(params.size() - args);
516-
for (size_t i = 0; (i + args) < params.size(); ++i) {
517-
sca.commandDataPairs[i] = stringToScaCommandDataPair(params[i + args]);
512+
sca.commandDataPairs.resize(params.size() - skip);
513+
for (size_t i = 0; (i + skip) < params.size(); ++i) {
514+
sca.commandDataPairs[i] = stringToScaCommandDataPair(params[i + skip]);
518515
}
519516

520517
auto command = std::make_unique<CommandQueue::Command>();
521518
command->start = true;
522519
command->description.type = sca;
523-
command->description.dnsName = ServiceNames(linkInfo.serial, linkInfo.link).publishScaSequenceSubdir(params.at(0));
524-
command->description.interval = std::chrono::milliseconds(int64_t(b::lexical_cast<double>(params.at(1)) * 1000.0));
520+
command->description.dnsName = ServiceNames(linkInfo.serial, linkInfo.link).publishScaSequenceSubdir(dnsName);
521+
command->description.interval = std::chrono::milliseconds(int64_t(b::lexical_cast<double>(interval) * 1000.0));
525522
command->description.linkInfo = linkInfo;
526523

527524
tryAddToQueue(*queue, std::move(command));
@@ -574,7 +571,7 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
574571
static std::string scaWrite(const std::string& parameter, BarSharedPtr bar2, LinkInfo linkInfo)
575572
{
576573
getLogger() << "SCA_WRITE: '" << parameter << "'" << endm;
577-
auto params = split(parameter, argumentSeparator().c_str());
574+
auto params = split(parameter, scaPairSeparator());
578575
auto command = convertHexString(params.at(0));
579576
auto data = convertHexString(params.at(1));
580577
Sca(*bar2, bar2->getCardType(), linkInfo.link).write(command, data);
@@ -601,23 +598,19 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
601598
/// RPC handler for SCA blob write commands (sequence of commands)
602599
static std::string scaBlobWrite(const std::string& parameter, BarSharedPtr bar2, LinkInfo linkInfo)
603600
{
604-
getLogger() << "SCA_BLOB_WRITE size=" << parameter.size() << " bytes" << endm;
601+
getLogger() << "SCA_SEQUENCE size=" << parameter.size() << " bytes" << endm;
605602

606603
// We first split on \n to get the pairs of SCA command and SCA data
607-
// Since this can be an enormous list of pairs, we walk through it using the tokenizer
608-
using tokenizer = boost::tokenizer<boost::char_separator<char>>;
609-
// Drop '\n' delimiters, keep none
610-
boost::char_separator<char> sep(argumentSeparator().c_str(), "", boost::drop_empty_tokens);
604+
auto lines = split(parameter, argumentSeparator());
611605
std::stringstream resultBuffer;
612606
auto sca = Sca(*bar2, bar2->getCardType(), linkInfo.link);
613607

614-
for (const std::string& token : tokenizer(parameter, sep)) {
608+
for (const auto& line : lines) {
615609
// Walk through the tokens, these should be the pairs (or comments).
616-
if (token.find('#') == 0) {
617-
// We have a comment, skip this token
610+
if (isLineComment(line)) {
618611
continue;
619612
} else {
620-
auto commandData = stringToScaCommandDataPair(token);
613+
auto commandData = stringToScaCommandDataPair(line);
621614
try {
622615
sca.write(commandData);
623616
auto result = sca.read();
@@ -627,6 +620,9 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
627620
} catch (const ScaException &e) {
628621
// If an SCA error occurs, we stop executing the sequence of commands and return the results as far as we got
629622
// them, plus the error message.
623+
getLogger() << InfoLogger::InfoLogger::Error
624+
<< (b::format("SCA_SEQUENCE cmd=0x%x data=0x%x serial=%d link=%d error='%s'") % commandData.command
625+
% commandData.data % linkInfo.serial % linkInfo.link % e.what()).str() << endm;
630626
resultBuffer << e.what();
631627
break;
632628
}
@@ -636,6 +632,11 @@ class ProgramAliceLowlevelFrontendServer: public AliceO2::Common::Program
636632
return resultBuffer.str();
637633
}
638634

635+
static bool isLineComment(const std::string& line)
636+
{
637+
return line.find('#') == 0;
638+
}
639+
639640
static Sca::CommandData stringToScaCommandDataPair(const std::string& string)
640641
{
641642
// The pairs are comma-separated, so we split them.

0 commit comments

Comments
 (0)