Skip to content

Commit

Permalink
[sc] Separate global SC from module resets
Browse files Browse the repository at this point in the history
  • Loading branch information
kostorr committed Nov 11, 2020
1 parent 6687896 commit 74f3a33
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 39 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ The services are DIM RPC services. Every RPC is called with a string and expects
* An SCA command and data pair (e.g. `0x0000f00d,0x0000cafe`)
* A wait operation (e.g. `30,wait`) in ms, defaults to 3
* An SCA connect operation (e.g. `connect`)
* An SCA reset operation (e.g. `reset`)
* An SCA reset operation (`reset`)
* An SC global reset operation (`sc_reset`)
* An instruction to execute the sequence atomically (`lock` - needs to lead the sequence)
* Returns:
* Sequence of SCA output as follows:
* SCA command and SCA read pairs
* Wait confirmations with time waited
* Connect confirmations made up of a "connect" string
* No entries for `reset` directives
* No entries for `lock` directives
* No entries for `reset`, `sc_reset`, and `lock` directives

* Example:
* DIM input: `0x00000010,0x00000011\n3\n0x000000020,0x00000021`
Expand All @@ -101,21 +101,21 @@ The services are DIM RPC services. Every RPC is called with a string and expects
* Sequence of SWT word and operation pairs as follows:
* Operations may be:
* `write` with SWT prefix (e.g. `0x0000f00d,write`)
* `reset` (without SWT word)
* `sc_reset` without prefix, is global
* `read` with optional TimeOut prefix (e.g. `2,read`)
* `wait` with optional WaitTime prefix in ms (e.g. `5,wait`), defaults to 3
* `lock` which instructs ALF to execute the sequence atomically (needs to lead the sequence)
* Returns:
* Sequence of SWT output as follows:
* `write` always retuns `0`
* `read` returns the SWT words present in the CRU SWT FIFO
* `reset` returns nothing
* `sc_reset` returns nothing
* `wait` returns time waited
* `lock` returns nothing

* Example:
* DIM input `reset\n0x0000000000badc0ffee,write\nread\n0xbadf00d,write\n4,read`
* DIM input (atomic) `lock\nreset\n0x0000000000badc0ffee,write\nread\n0xbadf00d,write\n4,read`
* DIM input `sc_reset\n0x0000000000badc0ffee,write\nread\n0xbadf00d,write\n4,read`
* DIM input (atomic) `lock\nsc_reset\n0x0000000000badc0ffee,write\nread\n0xbadf00d,write\n4,read`
* DIM output `0\n0x0000000000badc0ffee\n0\n0x000000000000badf00d\n`

##### IC_SEQUENCE
Expand Down Expand Up @@ -216,7 +216,7 @@ The services are DIM RPC services. Every RPC is called with a string and expects
## Slow Control library
ALF can also be used as a C++ library to access the Slow Control interface of the CRU. The three available interfaces (IC, SCA & SWT) can be accessed through single operations, or sequences of operations.

For each Slow Control (SC) class a handle can be acquired by passing the card ID as an `std::string` argument and, optionally, the SC channel to use as an `int`. Constructors have no side-effects; an SC reset would need to be performed manually before starting operations (e.g. `swt.reset()`).
For each Slow Control (SC) class a handle can be acquired by passing the card ID as an `std::string` argument and, optionally, the SC channel to use as an `int`. Constructors have no side-effects; an SC reset would need to be performed manually before starting operations (e.g. `swt.scReset()`).

### Single operations
Depending on the type, an SC class offers a different interface for single operation execution. `SWT` and `IC` offer `read()` and `write()` standalone operations, while `SCA` only offers `executeCommand()`.
Expand All @@ -226,7 +226,7 @@ All the above offer **no implicit locking** and should be manually locked throug
### Sequences of operations
All SC classes offer a function to execute a sequence of their respective operations. This function receives an `std::vector`, consisting of an `std::pair` made up of the compatible SC operation and SC data, as these are defined in their headers.

For example, `SWT` offers `Read, Write, Wait, and Reset` operations which expect a `TimeOut`, an `SwtWord`, a `WaitTime`, and no argument, respectively.
For example, `SWT` offers `Read, Write, Wait, and SCReset` operations which expect a `TimeOut`, an `SwtWord`, a `WaitTime`, and no argument, respectively.

```
typedef int TimeOut;
Expand All @@ -239,7 +239,7 @@ typedef boost::variant<boost::blank, TimeOut, WaitTime, SwtWord, std::string> Da
enum Operation { Read,
Write,
Wait,
Reset,
SCReset,
Error };
std::vector<std::pair<Operation, Data>> executeSequence(const std::vector<std::pair<Operation, Data>>& operations, bool lock = false);
Expand Down
5 changes: 3 additions & 2 deletions apps/AlfClient.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class AlfClient : public AliceO2::Common::Program
if (mOptions.swt) {
auto swtOut = swtSequence.write({ std::make_pair("", "lock"),
std::make_pair("0x0000000000000000000", "write"),
std::make_pair("", "reset"),
std::make_pair("", "sc_reset"),
std::make_pair("0x0000000000000000000", "write"),
std::make_pair("0x000000001234", "write"),
std::make_pair("", "read"),
Expand Down Expand Up @@ -189,7 +189,8 @@ class AlfClient : public AliceO2::Common::Program
}

if (mOptions.sca) {
auto scaOut = scaSequence.write({ std::make_pair("", "reset"),
auto scaOut = scaSequence.write({ std::make_pair("", "sc_reset"),
std::make_pair("", "reset"),
std::make_pair("", "connect"),
std::make_pair("1000", "wait"),
std::make_pair("0x00010002", "0xff000000"),
Expand Down
18 changes: 11 additions & 7 deletions apps/AlfLibClient.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,11 @@ class AlfLibClient : public AliceO2::Common::Program
if (mOptions.sca) {
std::cout << "Running SCA test" << std::endl;
auto sca = Sca(roc::SerialId{ mOptions.serial, mOptions.endpoint }, mOptions.link);
sca.reset();
sca.scReset();

std::cout << "Running simple SCA operations" << std::endl;
try {
sca.reset();
sca.connect();
auto scaOut = sca.executeCommand({ 0x00010002, 0xff000000 });
std::cout << scaOut.command << " " << scaOut.data << std::endl;
Expand All @@ -80,7 +81,8 @@ class AlfLibClient : public AliceO2::Common::Program
std::cout << "Running an SCA sequence" << std::endl;
std::vector<std::pair<Sca::Operation, Sca::Data>> ops;
sca.setChannel(1);
ops.push_back({ Sca::Operation::Reset , {} });
ops.push_back({ Sca::Operation::SCReset, {} });
ops.push_back({ Sca::Operation::Reset, {} });
ops.push_back({ Sca::Operation::Connect, {} });
ops.push_back({ Sca::Operation::Command, Sca::CommandData{ 0x00100002, 0xff000000 } });
ops.push_back({ Sca::Operation::Command, Sca::CommandData{ 0x00100003, 0xff000000 } });
Expand All @@ -94,6 +96,8 @@ class AlfLibClient : public AliceO2::Common::Program
std::cout << "Wait: " << std::dec << boost::get<Sca::WaitTime>(out.second) << std::endl;
} else if (out.first == Sca::Operation::Reset) {
std::cout << "Reset" << std::endl;
} else if (out.first == Sca::Operation::SCReset) {
std::cout << "SC Reset" << std::endl;
} else if (out.first == Sca::Operation::Connect) {
std::cout << "Connect " << std::endl;
} else if (out.first == Sca::Operation::Error) {
Expand All @@ -110,7 +114,7 @@ class AlfLibClient : public AliceO2::Common::Program

std::cout << "Running simple SWT operations" << std::endl;
try {
swt.reset();
swt.scReset();
swt.write({ 0xcafe, 0x41d, 0x0 });
swt.write({ 0xb00f, 0x42, 0x88 });
swt.write({ 0xb00f, 0x42, 0x88 });
Expand All @@ -128,7 +132,7 @@ class AlfLibClient : public AliceO2::Common::Program
std::vector<std::pair<Swt::Operation, Swt::Data>> ops;
swt = Swt(roc::SerialId{ mOptions.serial, mOptions.endpoint });
swt.setChannel(1);
ops.push_back({ Swt::Operation::Reset, {} });
ops.push_back({ Swt::Operation::SCReset, {} });
ops.push_back({ Swt::Operation::Write, SwtWord{ 0xcafe, 0x41d, 0x0 } });
ops.push_back({ Swt::Operation::Write, SwtWord{ 0xb00f, 0x42, 0x88, SwtWord::Size::High } });
ops.push_back({ Swt::Operation::Write, SwtWord{ 0xb00f, 0x42, 0x88 } });
Expand All @@ -149,8 +153,8 @@ class AlfLibClient : public AliceO2::Common::Program
std::cout << "Write | " << boost::get<SwtWord>(out.second) << std::endl;
} else if (out.first == Swt::Operation::Read) {
std::cout << "Read | " << boost::get<SwtWord>(out.second) << std::endl;
} else if (out.first == Swt::Operation::Reset) {
std::cout << "Reset |" /* boost::blank here */ << std::endl;
} else if (out.first == Swt::Operation::SCReset) {
std::cout << "SC Reset |" /* boost::blank here */ << std::endl;
} else if (out.first == Swt::Operation::Wait) {
std::cout << "Wait | " << std::dec << boost::get<int>(out.second) << std::endl;
} else if (out.first == Swt::Operation::Error) {
Expand All @@ -164,7 +168,7 @@ class AlfLibClient : public AliceO2::Common::Program
if (mOptions.ic) {
std::cout << "Running IC test" << std::endl;
auto ic = Ic(roc::SerialId{ mOptions.serial, mOptions.endpoint }, mOptions.link);
ic.reset();
ic.scReset();

std::cout << "Running Simple IC operations" << std::endl;
try {
Expand Down
2 changes: 1 addition & 1 deletion include/Alf/Ic.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class Ic
void checkChannelSet();

/// Executes an SC reset
void reset();
void scReset();

/// Performs an IC read
/// \param address IC address to read from
Expand Down
4 changes: 4 additions & 0 deletions include/Alf/Sca.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Sca
/// Enum for the different SCA operation types as seen from DIM RPCs
enum Operation { Command,
Wait,
SCReset,
Reset,
Connect,
Error,
Expand Down Expand Up @@ -79,6 +80,9 @@ class Sca
/// \throws o2::alf::ScaException if no SCA channel selected
void checkChannelSet();

/// Executes a global SC reset
void scReset();

/// Executes an SCA reset
void reset();

Expand Down
4 changes: 2 additions & 2 deletions include/Alf/Swt.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Swt
/// Enum for the different SWT operation types
enum Operation { Read,
Write,
Reset,
SCReset,
Wait,
Error,
Lock };
Expand Down Expand Up @@ -85,7 +85,7 @@ class Swt
void checkChannelSet();

/// Executes an SC reset
void reset();
void scReset();

/// Writes an SWT word
/// \param swtWord The SWT word to write
Expand Down
12 changes: 9 additions & 3 deletions src/AlfServer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,12 @@ std::pair<Sca::Operation, Sca::Data> AlfServer::stringToScaPair(const std::strin
BOOST_THROW_EXCEPTION(
AlfException() << ErrorInfo::Message("Too many arguments for RESET operation"));
}
} else if (scaPair[scaPair.size() - 1] == "sc_reset") {
operation = Sca::Operation::SCReset;
if (scaPair.size() != 1) {
BOOST_THROW_EXCEPTION(
AlfException() << ErrorInfo::Message("Too many arguments for SC RESET operation"));
}
} else if (scaPair[scaPair.size() - 1] == "connect") {
operation = Sca::Operation::Connect;
if (scaPair.size() != 1) {
Expand Down Expand Up @@ -348,11 +354,11 @@ std::pair<Swt::Operation, Swt::Data> AlfServer::stringToSwtPair(const std::strin
BOOST_THROW_EXCEPTION(
AlfException() << ErrorInfo::Message("Too few arguments for WRITE operation"));
}
} else if (swtPair[swtPair.size() - 1] == "reset") {
operation = Swt::Operation::Reset;
} else if (swtPair[swtPair.size() - 1] == "sc_reset") {
operation = Swt::Operation::SCReset;
if (swtPair.size() == 2) {
BOOST_THROW_EXCEPTION(
AlfException() << ErrorInfo::Message("Too many arguments for RESET operation"));
AlfException() << ErrorInfo::Message("Too many arguments for SC RESET operation"));
}
} else if (swtPair[swtPair.size() - 1] == "wait") {
operation = Swt::Operation::Wait;
Expand Down
4 changes: 2 additions & 2 deletions src/Ic.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ static constexpr roc::Register IC_RD_DATA(IC_BASE.address + 0x30);

Ic::Ic(AlfLink link) : mBar2(link.bar), mLink(link)
{
reset();
scReset();

// Set CFG to 0x3 by default
barWrite(ic_regs::IC_WR_CFG.index, 0x3);
Expand Down Expand Up @@ -117,7 +117,7 @@ void Ic::checkChannelSet()
}
}

void Ic::reset()
void Ic::scReset()
{
barWrite(sc_regs::SC_RESET.index, 0x1);
barWrite(sc_regs::SC_RESET.index, 0x0); //void cmd to sync clocks
Expand Down
17 changes: 12 additions & 5 deletions src/Sca.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -96,20 +96,22 @@ void Sca::checkChannelSet()
}
}

void Sca::scReset()
{
barWrite(sc_regs::SC_RESET.index, 0x1);
barWrite(sc_regs::SC_RESET.index, 0x0); //void cmd to sync clocks
}

void Sca::reset()
{
barWrite(sc_regs::SCA_WR_CTRL.index, 0x1);
barWrite(sc_regs::SCA_WR_CTRL.index, 0x0);
/* DO I NEED THIS?
waitOnBusyClear(); */
}

void Sca::connect()
{
barWrite(sc_regs::SCA_WR_CTRL.index, 0x2);
barWrite(sc_regs::SCA_WR_CTRL.index, 0x0);
/* DO I NEED THIS?
waitOnBusyClear(); */
}

Sca::CommandData Sca::executeCommand(uint32_t command, uint32_t data, bool lock)
Expand Down Expand Up @@ -299,6 +301,9 @@ std::vector<std::pair<Sca::Operation, Sca::Data>> Sca::executeSequence(const std
} else if (operation == Operation::Reset) {
reset();
ret.push_back({ Operation::Reset, {} });
} else if (operation == Operation::SCReset) {
scReset();
ret.push_back({ Operation::SCReset, {} });
} else if (operation == Operation::Connect) {
connect();
ret.push_back({ Operation::Connect, {} });
Expand All @@ -315,6 +320,8 @@ std::vector<std::pair<Sca::Operation, Sca::Data>> Sca::executeSequence(const std
meaningfulMessage = (boost::format("SCA_SEQUENCE WAIT waitTime=%d serialId=%s link=%d error='%s'") % boost::get<WaitTime>(data) % mLink.serialId % mLink.linkId % e.what()).str();
} else if (operation == Operation::Reset) {
meaningfulMessage = (boost::format("SCA_SEQUENCE RESET serialId=%s link=%d error='%s'") % mLink.serialId % mLink.linkId % e.what()).str();
} else if (operation == Operation::SCReset) {
meaningfulMessage = (boost::format("SCA_SEQUENCE SC RESET serialId=%s link=%d error='%s'") % mLink.serialId % mLink.linkId % e.what()).str();
} else if (operation == Operation::Connect) {
meaningfulMessage = (boost::format("SCA_SEQUENCE CONNECT serialId=%s link=%d error='%s'") % mLink.serialId % mLink.linkId % e.what()).str();
} else {
Expand Down Expand Up @@ -345,7 +352,7 @@ std::string Sca::writeSequence(const std::vector<std::pair<Operation, Data>>& op
resultBuffer << data << "\n"; // "[cmd],[data]\n"
} else if (operation == Operation::Wait) {
resultBuffer << std::dec << data << "\n"; // "[time]\n"
} else if (operation == Operation::Reset) {
} else if (operation == Operation::Reset || operation == Operation::SCReset) {
/* DO NOTHING */
} else if (operation == Operation::Connect) {
resultBuffer << "connect\n"; // echo
Expand Down
14 changes: 7 additions & 7 deletions src/Swt.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void Swt::setChannel(int gbtChannel)
barWrite(sc_regs::SC_LINK.index, mLink.rawLinkId);
}

void Swt::reset()
void Swt::scReset()
{
barWrite(sc_regs::SC_RESET.index, 0x1);
barWrite(sc_regs::SC_RESET.index, 0x0); //void cmd to sync clocks
Expand Down Expand Up @@ -207,9 +207,9 @@ std::vector<std::pair<Swt::Operation, Swt::Data>> Swt::executeSequence(std::vect
write(word);
ret.push_back({ Operation::Write, word });
//ret.push_back({ Operation::Write, {} }); // TODO: Is it better to return {} ?
} else if (operation == Operation::Reset) {
reset();
ret.push_back({ Operation::Reset, {} });
} else if (operation == Operation::SCReset) {
scReset();
ret.push_back({ Operation::SCReset, {} });
} else if (operation == Operation::Wait) {
int waitTime;
try {
Expand All @@ -229,8 +229,8 @@ std::vector<std::pair<Swt::Operation, Swt::Data>> Swt::executeSequence(std::vect
meaningfulMessage = (boost::format("SWT_SEQUENCE READ timeout=%d serialId=%s link=%d, error='%s'") % boost::get<TimeOut>(data) % mLink.serialId % mLink.linkId % e.what()).str();
} else if (operation == Operation::Write) {
meaningfulMessage = (boost::format("SWT_SEQUENCE WRITE data=%s serialId=%s link=%d, error='%s'") % boost::get<SwtWord>(data) % mLink.serialId % mLink.linkId % e.what()).str();
} else if (operation == Operation::Reset) {
meaningfulMessage = (boost::format("SWT_SEQUENCE RESET serialId=%d link=%s, error='%s'") % mLink.serialId % mLink.linkId % e.what()).str();
} else if (operation == Operation::SCReset) {
meaningfulMessage = (boost::format("SWT_SEQUENCE SC RESET serialId=%d link=%s, error='%s'") % mLink.serialId % mLink.linkId % e.what()).str();
} else if (operation == Operation::Wait) {
meaningfulMessage = (boost::format("SWT_SEQUENCE WAIT waitTime=%d serialId=%s link=%d error='%s'") % boost::get<WaitTime>(data) % mLink.serialId % mLink.linkId % e.what()).str();
} else {
Expand Down Expand Up @@ -261,7 +261,7 @@ std::string Swt::writeSequence(std::vector<std::pair<Operation, Data>> sequence,
resultBuffer << data << "\n";
} else if (operation == Operation::Write) {
resultBuffer << "0\n";
} else if (operation == Operation::Reset) {
} else if (operation == Operation::SCReset) {
/* DO NOTHING */
} else if (operation == Operation::Wait) {
resultBuffer << std::dec << data << "\n";
Expand Down

0 comments on commit 74f3a33

Please sign in to comment.