Skip to content

Commit

Permalink
_Mem: Make eject return the executed command or NULL. Use it in injec…
Browse files Browse the repository at this point in the history
…t_productions. See issue #123.
  • Loading branch information
jefft0 committed Apr 14, 2021
1 parent 9b29077 commit a8495f2
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 30 deletions.
32 changes: 18 additions & 14 deletions AERA/test_mem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ TestMem<O, S>::findObject(std::vector<Code*> *objects, const char* name) {
return NULL;
}

template<class O, class S> void TestMem<O, S>::eject(Code *command) {
template<class O, class S> Code* TestMem<O, S>::eject(Code *command) {
uint16 function = (command->code(CMD_FUNCTION).atom_ >> 8) & 0x000000FF;

if (function == ready_opcode_) {
Expand All @@ -167,43 +167,44 @@ template<class O, class S> void TestMem<O, S>::eject(Code *command) {
if (!(command->code_size() >= 3 && command->code(args_set_index + 2).getDescriptor() == Atom::R_PTR &&
command->references_size() > command->code(args_set_index + 2).asIndex())) {
cout << "WARNING: Cannot get the object for ready \"ball\"" << endl;
return;
return NULL;
}
if (!velocity_y_property_) {
cout << "WARNING: Can't find the velocity_y property" << endl;
return;
return NULL;
}
if (!position_y_property_) {
cout << "WARNING: Can't find the position_y property" << endl;
return;
return NULL;
}

Code* obj = command->get_reference(command->code(args_set_index + 2).asIndex());
if (!position_y_obj_) {
// This is the first call. Remember the object whose position we're reporting.
position_y_obj_ = obj;
startTimeTickThread();
return command;
}
else {
if (position_y_obj_ != obj)
// For now, don't allow tracking multiple objects.
return;
return NULL;
}
}
else {
cout << "WARNING: Ignoring unrecognized ready command identifier: " << identifier << endl;
return;
return NULL;
}
}
}
else if (function == set_velocity_y_opcode_) {
if (!velocity_y_property_) {
cout << "WARNING: Can't find the velocity_y property" << endl;
return;
return NULL;
}
if (!position_y_property_) {
cout << "WARNING: Can't find the position_y property" << endl;
return;
return NULL;
}

auto now = r_exec::Now();
Expand All @@ -220,22 +221,23 @@ template<class O, class S> void TestMem<O, S>::eject(Code *command) {
else {
if (position_y_obj_ != obj)
// For now, don't allow tracking the velocity of multiple objects.
return;
return NULL;
}

velocity_y_ = command->code(args_set_index + 2).asFloat();
// Let onTimeTick inject the new velocity_y.
return command;
}
else if (function == move_y_plus_opcode_ ||
function == move_y_minus_opcode_) {
if (!position_property_) {
cout << "WARNING: Can't find the position property" << endl;
return;
return NULL;
}
for (int i = 0; i <= 9; ++i) {
if (!yEnt_[i]) {
cout << "WARNING: Can't find the entities y0, y1, etc." << endl;
return;
return NULL;
}
}

Expand All @@ -249,17 +251,16 @@ template<class O, class S> void TestMem<O, S>::eject(Code *command) {
discretePositionObj_ = obj;
discretePosition_ = yEnt_[0];
startTimeTickThread();
return;
}
else {
if (discretePositionObj_ != obj)
// For now, don't allow tracking multiple objects.
return;
return NULL;
}

if (nextDiscretePosition_)
// A previous move command is still pending execution.
return;
return NULL;

// nextDiscretePosition_ will become the position at the next sampling period.
lastCommandTime_ = now;
Expand All @@ -277,7 +278,10 @@ template<class O, class S> void TestMem<O, S>::eject(Code *command) {
}
}
// Let onTimeTick inject the new position.
return command;
}

return NULL;
}

template<class O, class S> void TestMem<O, S>::onTimeTick() {
Expand Down
7 changes: 6 additions & 1 deletion AERA/test_mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,13 @@ template<class O, class S> class TestMem :

/**
* Override eject to check for (cmd set_velocity_y ...) and other implemented commands.
* \param command The command from the Replicode (cmd ...).
* \return The given command if it is executed as-is, or a new command object of the command
* that is actually executed. The program controller will make a fact from the command and
* inject it as the efferent copy. However, if the command is not executed, then return NULL
* and the program controller will put an anti-fact of the command in the mk.rdx reduction.
*/
virtual void eject(r_code::Code *command);
virtual r_code::Code* eject(r_code::Code *command);

/**
* This is called when runInDiagnosticTime() updates the tickTime. Just call
Expand Down
3 changes: 2 additions & 1 deletion r_exec/mem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ void _Mem::pushTimeJob(TimeJob *j) {
void _Mem::eject(View *view, uint16 nodeID) {
}

void _Mem::eject(Code *command) {
r_code::Code* _Mem::eject(Code *command) {
// This is only for debugging
/*
uint16 function = (command->code(CMD_FUNCTION).atom_ >> 8) & 0x000000FF;
Expand All @@ -716,6 +716,7 @@ void _Mem::eject(Code *command) {
//command->trace();
}
*/
return NULL;
}

////////////////////////////////////////////////////////////////
Expand Down
13 changes: 10 additions & 3 deletions r_exec/mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -547,9 +547,16 @@ class r_exec_dll _Mem :
// To be redefined by object transport aware subcalsses.
virtual void eject(View *view, uint16 nodeID);

// From rMem to I/O device.
// To be redefined by object transport aware subcalsses.
virtual void eject(r_code::Code *command);
/**
* This is called by the program controller to eject a command from rMem to the
* I/O device. This method should be redefined by object transport-aware subclasses.
* \param command The command from the Replicode (cmd ...).
* \return The given command if it is executed as-is, or a new command object of the command
* that is actually executed. The program controller will make a fact from the command and
* inject it as the efferent copy. However, if the command is not executed, then return NULL
* and the program controller will put an anti-fact of the command in the mk.rdx reduction.
*/
virtual r_code::Code* eject(r_code::Code *command);

virtual r_code::Code *_build_object(Atom head) const = 0;
virtual r_code::Code *build_object(Atom head) const = 0;
Expand Down
28 changes: 17 additions & 11 deletions r_exec/pgm_overlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,25 +457,31 @@ bool InputLessPGMOverlay::inject_productions() {
}
} else if (cmd[0].asOpcode() == Opcodes::Cmd) { // command to an external device, build a cmd object and send it.

Code *command = _Mem::Get()->build_object(cmd[0]);
cmd.copy(command, 0);
P<Code> command = _Mem::Get()->build_object(cmd[0]);
cmd.copy((Code*)command, 0);

_Mem::Get()->eject(command);
Code* executedCommand = _Mem::Get()->eject(command);

// Build a fact of the command and inject it in stdin. Give the fact an uncertainty range since we don't know when
// it will be executed. Otherwise a fact with zero duration may not overlap a fact, making predictions fail.
// We offset the beginning of the uncertainty range by 2*GetTimeTolerance() (the same as SYNC_HOLD)
// so that CTPX::reduce will not fail due to "cause in sync with the premise".
Code *fact = new Fact(command, now + 2 * Utils::GetTimeTolerance(), now + _Mem::Get()->get_sampling_period(), 1, 1);
View *view = new View(View::SYNC_ONCE, now, 1, 1, _Mem::Get()->get_stdin(), getView()->get_host(), fact); // SYNC_ONCE, sln=1, res=1,
_Mem::Get()->inject(view);
string mk_rdx_info = "";
P<Code> fact;
if (executedCommand) {
fact = new Fact(command, now + 2 * Utils::GetTimeTolerance(), now + _Mem::Get()->get_sampling_period(), 1, 1);
View *view = new View(View::SYNC_ONCE, now, 1, 1, _Mem::Get()->get_stdin(), getView()->get_host(), fact); // SYNC_ONCE, sln=1, res=1,
_Mem::Get()->inject(view);
string mk_rdx_info = "";
#ifdef WITH_DEBUG_OID
if (mk_rdx)
// We don't know the mk.rdx OID yet, so use the debug OID.
mk_rdx_info = " mk.rdx(" + to_string(mk_rdx->get_debug_oid()) + "):";
if (mk_rdx)
// We don't know the mk.rdx OID yet, so use the debug OID.
mk_rdx_info = " mk.rdx(" + to_string(mk_rdx->get_debug_oid()) + "):";
#endif
OUTPUT_LINE(IO_DEVICE_INJ_EJT, Utils::RelativeTime(Now()) << mk_rdx_info << " I/O device eject " << fact->get_oid());
OUTPUT_LINE(IO_DEVICE_INJ_EJT, Utils::RelativeTime(Now()) << mk_rdx_info << " I/O device eject " << fact->get_oid());
}
else
// The command wasn't executed. Set fact to an anti-fact of the original command and record in the mk_rdx.
fact = new AntiFact(command, after, before, 1, 1);

if (mk_rdx) {

Expand Down

0 comments on commit a8495f2

Please sign in to comment.