diff --git a/MAC/APL/RTCCommon/include/APL/RTCCommon/RegisterState.h b/MAC/APL/RTCCommon/include/APL/RTCCommon/RegisterState.h index 705008b3f87ba0a368d0a54559f33519ebce593d..6efd4db0194ba7417fba3b78ad90c28b3a840503 100644 --- a/MAC/APL/RTCCommon/include/APL/RTCCommon/RegisterState.h +++ b/MAC/APL/RTCCommon/include/APL/RTCCommon/RegisterState.h @@ -38,11 +38,14 @@ namespace LOFAR { public: typedef enum State { - UNDEFINED = 0, - NOT_MODIFIED = 1, - MODIFIED = 2, - APPLIED = 3, - CONFIRMED = 4, + UNDEFINED = 0, + IDLE, + CHECK, + WRITE, + READ, + WRITE_ERROR, + READ_ERROR, + DONE, }; explicit RegisterState(State state = UNDEFINED) @@ -56,109 +59,56 @@ namespace LOFAR { } - /** + /** * RegisterState state machine. + * read_error + * +---> READ_ERROR + * reset read | + * \ +---------------> READ ------+ read_ack + * \ | * | + * * | schedule_|read * clear + * UNDEFINED ---> IDLE + <---+ | DONE --------------->+ + * ^ | not_|modified | ^ | + * | | | | | | + * | +--> CHECK------> WRITE ------+ | + * | check write | write_ack | + * | +---> WRITE_ERROR | + * | write_error | + * +---------------<-------------------------------------+ * - * modified - * reset ---* NOT_MODIFIED ---------------* MODIFIED *----- modified - * * / | - * | /------------------/ |applied - * clear | / confirmed | - * | * * - * CONFIRMED *----------------- APPLIED - * confirmed * * Rationale: - * When a register is modified, it transitions to the MODIFIED - * state. It can only return to NOT_MODIFIED when cleared from - * the CONFIRMED state. The CONFIRMED state can only be reached - * from the MODIFIED state (with confirmed signal) or via the - * APPLIED state. + * At each update cycle all registers should be in the IDLE state. + * All registers are then moved to the READ or CHEC state depending + * on whether they are R (read) or W (write) registers. + * + * States: + * UNDEFINED, IDLE, CHECK, WRITE, READ, WRITE_ERROR, READ_ERROR, DONE * - * A register that is written and read consequently to check that - * the data was written correctly would therefor transition from - * NOT_MODIFIED, to MODIFIED, the to APPLIED (after the write - * has completed) and then to CONFIRMED when the read result - * matches what was actually written. Only then can the register - * state be cleared to NOT_MODIFIED. + * Signals: + * read, check, unmodified, write, schedule_read, read_ack, write_ack, read_error, write_error, clear, reset */ + void resize(int n) { m_state.resize(n); - m_state = NOT_MODIFIED; + m_state = IDLE; } - void modified(int i = -1) - { - if (i < 0) { - for (int j = 0; j < m_state.extent(blitz::firstDim); j++) { - m_state(j) = MODIFIED; - } - return; - } - ASSERT(i >= 0 && i < m_state.extent(blitz::firstDim)); - m_state(i) = MODIFIED; - } + void tran(State source, State target, int i); - void reset(int i = -1) - { - if (i < 0) { - for (int j = 0; j < m_state.extent(blitz::firstDim); j++) { - m_state(j) = NOT_MODIFIED; - } - return; - } - ASSERT(i >= 0 && i < m_state.extent(blitz::firstDim)); - m_state(i) = NOT_MODIFIED; - } + void read (int i = -1) { tran(IDLE, READ, i); } + void check (int i = -1) { tran(IDLE, CHECK, i); } + void unmodified (int i = -1) { tran(CHECK, IDLE, i); } + void write (int i = -1) { tran(CHECK, WRITE, i); } + void schedule_read(int i = -1) { tran(WRITE, READ, i); } + void read_ack (int i = -1) { tran(READ, DONE, i); } + void write_ack (int i = -1) { tran(WRITE, DONE, i); } + void read_error (int i = -1) { tran(READ, READ_ERROR, i); } + void write_error (int i = -1) { tran(WRITE, WRITE_ERROR, i); } - void applied(int i = -1) - { - if (i < 0) { - for (int j = 0; j < m_state.extent(blitz::firstDim); j++) { - if (MODIFIED == m_state(j)) { - m_state(j) = APPLIED; - } - } - return; - } - ASSERT(i >= 0 && i < m_state.extent(blitz::firstDim)); - if (MODIFIED == m_state(i)) { - m_state(i) = APPLIED; - } - } - - void confirmed(int i = -1) - { - if (i < 0) { - for (int j = 0; j < m_state.extent(blitz::firstDim); j++) { - if (MODIFIED == m_state(j) || APPLIED == m_state(j)) { - m_state(j) = CONFIRMED; - } - } - return; - } - ASSERT(i >= 0 && i < m_state.extent(blitz::firstDim)); - if (MODIFIED == m_state(i) || APPLIED == m_state(i)) { - m_state(i) = CONFIRMED; - } - } - - void clear(int i = -1) - { - if (i < 0) { - for (int j = 0; j < m_state.extent(blitz::firstDim); j++) { - if (CONFIRMED == m_state(j) || UNDEFINED == m_state(j)) { - m_state(j) = NOT_MODIFIED; - } - } - return; - } - ASSERT(i >= 0 && i < m_state.extent(blitz::firstDim)); - if (CONFIRMED == m_state(i)) { - m_state(i) = NOT_MODIFIED; - } - } + void clear(int i = -1); + void reset(int i = -1); State get(int i) { ASSERT(i >= 0 && i < m_state.extent(blitz::firstDim)); @@ -167,16 +117,17 @@ namespace LOFAR { void print(std::ostream& out) const { for (int i = 0; i < m_state.extent(blitz::firstDim); i++) { - char c; switch (m_state(i)) { - case UNDEFINED: c = '?'; break; - case NOT_MODIFIED: c = '.'; break; - case MODIFIED: c = 'M'; break; - case APPLIED: c = 'A'; break; - case CONFIRMED: c = 'C'; break; - default: c = 'X'; break; + case UNDEFINED: out << "? "; break; + case IDLE: out << ". "; break; + case CHECK: out << "C "; break; + case WRITE: out << "W "; break; + case READ: out << "R "; break; + case READ_ERROR: out << "ER"; break; + case WRITE_ERROR: out << "EW"; break; + case DONE: out << "* "; break; + default: out << "X "; break; } - out << c; } out << "$" << endl; } @@ -184,13 +135,13 @@ namespace LOFAR { public: /* marshalling methods */ unsigned int getSize() { - return MSH_ARRAY_SIZE(m_state, RegisterState); + return MSH_ARRAY_SIZE(m_state, State); } unsigned int pack(void* buffer) { unsigned int offset = 0; - MSH_PACK_ARRAY(buffer, offset, m_state, RegisterState); + MSH_PACK_ARRAY(buffer, offset, m_state, State); return offset; } @@ -198,7 +149,7 @@ namespace LOFAR { unsigned int unpack(void* buffer) { unsigned int offset = 0; - MSH_UNPACK_ARRAY(buffer, offset, m_state, RegisterState, 1); + MSH_UNPACK_ARRAY(buffer, offset, m_state, State, 1); return offset; } diff --git a/MAC/APL/RTCCommon/src/Makefile.am b/MAC/APL/RTCCommon/src/Makefile.am index d4490ba808e7db9b7d7381eb85317a083762f3bb..8bf4baff3fa37c1db383c5838da4e9712ae1f067 100644 --- a/MAC/APL/RTCCommon/src/Makefile.am +++ b/MAC/APL/RTCCommon/src/Makefile.am @@ -26,7 +26,8 @@ lib_LTLIBRARIES = librtccommon.la libgnuplot_i.la librtccommon_la_SOURCES = \ Timestamp.cc \ Subject.cc \ - daemonize.c + daemonize.c \ + RegisterState.cc libgnuplot_i_la_SOURCES = \ gnuplot_i.cc diff --git a/MAC/APL/RTCCommon/src/RegisterState.cc b/MAC/APL/RTCCommon/src/RegisterState.cc new file mode 100644 index 0000000000000000000000000000000000000000..e3ab1f3e9c7b00533eb0aedd218ff16460767eb3 --- /dev/null +++ b/MAC/APL/RTCCommon/src/RegisterState.cc @@ -0,0 +1,89 @@ +//# -*- mode: c++ -*- +//# +//# RegisterState.cc: implementation of RegisterState class. +//# +//# Copyright (C) 2002-2004 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id$ + +#include <APL/RTCCommon/RegisterState.h> + +using namespace std; +using namespace LOFAR; +using namespace RTC; + +void RegisterState::tran(State source, State target, int i) +{ + int lb = 0, ub = 0; + if (i < 0) { + lb = 0; + ub = m_state.extent(blitz::firstDim); + } else { + ASSERT(i >= 0 && i < m_state.extent(blitz::firstDim)); + lb = ub = i; + } + + for (int j = lb; j < ub; j++) { + if (source == m_state(j)) { + m_state(j) = target; + } else if (target != m_state(j)) { + LOG_ERROR_STR("tran(" << source << ", " << target << ") failed, current state = " << m_state(j)); + } + } +} + +// transition from DONE -> IDLE +// from READ_ERROR -> READ +// from WRITE_ERROR -> WRITE +void RegisterState::clear(int i) +{ + int lb = 0, ub = 0; + if (i < 0) { + lb = 0; + ub = m_state.extent(blitz::firstDim); + } else { + ASSERT(i >= 0 && i < m_state.extent(blitz::firstDim)); + lb = ub = i; + } + + for (int j = lb; j < ub; j++) { + if (DONE == m_state(j)) { + m_state(j) = IDLE; + } else if (READ_ERROR == m_state(j)) { + m_state(j) = READ; + } else if (WRITE_ERROR == m_state(j)) { + m_state(j) = WRITE; + } else { + LOG_ERROR_STR("clear tran from " << m_state(j) << " failed"); + } + } +} + +void RegisterState::reset(int i) +{ + if (i < 0) { + for (int j = 0; j < m_state.extent(blitz::firstDim); j++) { + m_state(j) = IDLE; + } + return; + } + ASSERT(i >= 0 && i < m_state.extent(blitz::firstDim)); + m_state(i) = IDLE; +} +