86 #include "pgm_overlay.h"
87 #include "pgm_controller.h"
92 #include "callbacks.h"
95 using namespace r_code;
137 using namespace std::chrono;
141 InputLessPGMOverlay::InputLessPGMOverlay() : Overlay() {
144 InputLessPGMOverlay::InputLessPGMOverlay(Controller *c) : Overlay(c) {
149 InputLessPGMOverlay::~InputLessPGMOverlay() {
152 void InputLessPGMOverlay::reset() {
158 patch_indices_.clear();
159 value_commit_index_ = 0;
161 productions_.clear();
166 IPGMContext c(get_object()->get_reference(0), get_view(), code_, index,
this);
170 void InputLessPGMOverlay::patch_tpl_args() {
171 uint16 tpl_arg_set_index = code_[PGM_TPL_ARGS].asIndex();
172 uint16 arg_count = code_[tpl_arg_set_index].getAtomCount();
173 uint16 ipgm_arg_set_index = get_object()->code(IPGM_ARGS).asIndex();
174 for (uint16 i = 1; i <= arg_count; ++i) {
176 Atom &skel_iptr = code_[code_[tpl_arg_set_index + i].asIndex() + 1];
177 uint16 pgm_code_index = code_[tpl_arg_set_index + i].asIndex();
179 patch_tpl_code(pgm_code_index, get_object()->code(ipgm_arg_set_index + i).asIndex());
180 skel_iptr = Atom::IPGMPointer(ipgm_arg_set_index + i);
184 void InputLessPGMOverlay::patch_tpl_code(uint16 pgm_code_index, uint16 ipgm_code_index) {
186 uint16 atom_count = code_[pgm_code_index].getAtomCount();
187 for (uint16 j = 1; j <= atom_count; ++j) {
189 switch (code_[pgm_code_index + j].getDescriptor()) {
191 code_[pgm_code_index + j] = Atom::IPGMPointer(ipgm_code_index + j);
193 case Atom::T_WILDCARD:
196 patch_tpl_code(code_[pgm_code_index + j].asIndex(), get_object()->code(ipgm_code_index + j).asIndex());
204 void InputLessPGMOverlay::patch_input_code(uint16 pgm_code_index, uint16 input_index, uint16 input_code_index, int16 parent_index) {
207 bool InputLessPGMOverlay::inject_productions() {
212 IPGMContext prods(get_object()->get_reference(0), get_view(), code_, code_[PGM_PRODS].asIndex(),
this);
213 if (prods[0].getDescriptor() != Atom::SET) {
216 if (!prods.evaluate()) {
219 productions_.clear();
222 prods = prods.dereference();
224 uint16 production_count = prods.get_children_count();
225 uint16 cmd_count = 0;
226 for (uint16 i = 1; i <= production_count; ++i) {
228 IPGMContext cmd = prods.get_child_deref(i);
229 if (!in_red && !cmd.evaluate()) {
232 productions_.clear();
235 IPGMContext
function = cmd.get_child_deref(1);
252 IPGMContext args = cmd.get_child_deref(2);
253 if (cmd[0].asOpcode() == Opcodes::ICmd) {
255 if (
function[0].asOpcode() == Opcodes::Inject ||
256 function[0].asOpcode() == Opcodes::Eject) {
259 IPGMContext arg1 = args.get_child(1);
260 uint16 index = arg1.getIndex();
261 arg1 = arg1.dereference();
262 if (arg1.is_reference())
263 productions_.push_back(arg1.get_object());
266 object = _Mem::Get()->build_object(arg1[0]);
267 arg1.copy(
object, 0);
268 productions_.push_back(_Mem::Get()->check_existence(
object));
270 patch_code(index, Atom::ProductionPointer(productions_.size() - 1));
273 }
else if (
function[0].asOpcode() != Opcodes::Mod &&
274 function[0].asOpcode() != Opcodes::Set &&
275 function[0].asOpcode() != Opcodes::Prb)
279 if (cmd[0].asOpcode() == Opcodes::Cmd)
286 uint16 ntf_grp_count = get_view()->get_host()->get_ntf_grp_count();
289 uint16 mk_rdx_prod_index;
291 if (ntf_grp_count && cmd_count && (get_object()->code(IPGM_NFR).asBoolean())) {
293 mk_rdx = get_mk_rdx(write_index);
294 mk_rdx_prod_index = write_index;
295 mk_rdx->code(write_index++) = Atom::Set(cmd_count);
296 extent_index = write_index + cmd_count;
300 for (uint16 i = 1; i <= production_count; ++i) {
302 IPGMContext cmd = prods.get_child_deref(i);
303 IPGMContext
function = cmd.get_child_deref(1);
306 IPGMContext args = cmd.get_child_deref(2);
307 if (cmd[0].asOpcode() == Opcodes::ICmd) {
309 if (
function[0].asOpcode() == Opcodes::Inject) {
311 IPGMContext arg1 = args.get_child(1);
312 arg1.dereference_once();
313 Code *
object = args.get_child_deref(1).get_object();
314 IPGMContext _view = args.get_child_deref(2);
315 if (_view[0].getAtomCount() != 0) {
317 View *view =
new View();
319 view->set_object(
object);
321 view->references_[1] = get_view()->get_host();
322 view->code(VIEW_ORG) = Atom::RPointer(1);
324 _Mem::Get()->inject(view);
328 mk_rdx->code(write_index++) = Atom::IPointer(extent_index);
329 prods.get_child_deref(i).copy(mk_rdx, extent_index, extent_index);
333 }
else if (
function[0].asOpcode() == Opcodes::Eject) {
335 Code *
object = args.get_child_deref(1).get_object();
337 IPGMContext _view = args.get_child_deref(2);
338 View *view =
new View();
340 view->set_object(
object);
342 IPGMContext node = args.get_child_deref(3);
344 _Mem::Get()->eject(view, node[0].getNodeID());
348 mk_rdx->code(write_index++) = Atom::IPointer(extent_index);
349 prods.get_child_deref(i).copy(mk_rdx, extent_index, extent_index);
351 }
else if (
function[0].asOpcode() == Opcodes::Mod) {
354 IPGMContext::ObjectType object_type;
357 args.get_child(1).getMember(
object, view_oid, object_type, member_index);
361 float32 value = args.get_child_deref(2)[0].asFloat();
362 switch (object_type) {
363 case IPGMContext::TYPE_VIEW: {
365 Group *g = (Group *)
object;
367 g->pending_operations_.push_back(
new Group::Mod(view_oid, member_index, value));
370 }
case IPGMContext::TYPE_OBJECT:
371 ((
Code *)
object)->mod(member_index, value);
373 case IPGMContext::TYPE_GROUP:
374 ((Group *)
object)->enter();
375 ((Group *)
object)->mod(member_index, value);
376 ((Group *)
object)->leave();
380 productions_.clear();
384 }
else if (
function[0].asOpcode() == Opcodes::Set) {
387 IPGMContext::ObjectType object_type;
390 args.get_child(1).getMember(
object, view_oid, object_type, member_index);
394 float32 value = args.get_child_deref(2)[0].asFloat();
395 switch (object_type) {
396 case IPGMContext::TYPE_VIEW: {
398 Group *g = (Group *)
object;
400 g->pending_operations_.push_back(
new Group::Set(view_oid, member_index, value));
403 }
case IPGMContext::TYPE_OBJECT:
404 ((
Code *)
object)->set(member_index, value);
406 case IPGMContext::TYPE_GROUP:
407 ((Group *)
object)->enter();
408 ((Group *)
object)->set(member_index, value);
409 ((Group *)
object)->leave();
413 }
else if (
function[0].asOpcode() == Opcodes::NewClass) {
415 }
else if (
function[0].asOpcode() == Opcodes::DelClass) {
417 }
else if (
function[0].asOpcode() == Opcodes::LDC) {
419 }
else if (
function[0].asOpcode() == Opcodes::Swap) {
421 }
else if (
function[0].asOpcode() == Opcodes::Prb) {
423 float32 probe_lvl = args.get_child_deref(1)[0].asFloat();
424 if (probe_lvl < _Mem::Get()->get_probe_level()) {
426 std::string callback_name = Utils::GetString(&args.get_child_deref(2)[0]);
428 Callbacks::Callback callback = Callbacks::Get(callback_name);
431 std::string msg = Utils::GetString(&args.get_child_deref(3)[0]);
432 IPGMContext _objects = args.get_child_deref(4);
434 uint8 object_count = _objects[0].getAtomCount();
435 Code **objects = NULL;
438 objects =
new Code *[object_count];
439 for (uint8 i = 1; i <= object_count; ++i)
440 objects[i - 1] = _objects.get_child_deref(i).get_object();
443 callback(duration_cast<microseconds>(now - Utils::GetTimeReference()),
false, msg.c_str(), object_count, objects);
448 }
else if (
function[0].asOpcode() == Opcodes::Stop) {
454 productions_.clear();
457 }
else if (cmd[0].asOpcode() == Opcodes::Cmd) {
459 P<Code> command = _Mem::Get()->build_object(cmd[0]);
460 cmd.copy((
Code*)command, 0);
462 Code* executed_command = _Mem::Get()->eject(command);
468 auto relative_time = duration_cast<microseconds>(now - Utils::GetTimeReference());
469 auto frame_start = now - (relative_time % _Mem::Get()->get_sampling_period());
470 auto after = max(now, frame_start + 2 * Utils::GetTimeTolerance());
471 auto before = frame_start + _Mem::Get()->get_sampling_period();
473 if (executed_command) {
475 fact =
new Fact(executed_command, after, before, 1, 1);
476 View *view =
new View(View::SYNC_ONCE, now, 1, 1, _Mem::Get()->get_stdin(), get_view()->get_host(), fact);
477 _Mem::Get()->inject(view);
478 string mk_rdx_info =
"";
479 #ifdef WITH_DETAIL_OID
482 mk_rdx_info =
" mk.rdx(" + to_string(mk_rdx->get_detail_oid()) +
"):";
484 OUTPUT_LINE(IO_DEVICE_INJ_EJT, Utils::RelativeTime(Now()) << mk_rdx_info <<
" I/O device eject " << fact->get_oid());
488 fact =
new AntiFact(command, after, before, 1, 1);
493 mk_rdx->code(write_index++) = Atom::IPointer(extent_index);
494 prods.get_child_deref(i).copy(mk_rdx, extent_index, extent_index);
496 mk_rdx->code(write_index++) = Atom::RPointer(mk_rdx->references_size());
497 mk_rdx->add_reference(fact);
504 mk_rdx->code(mk_rdx_prod_index) = Atom::Set(cmd_count);
505 for (uint16 i = 1; i <= ntf_grp_count; ++i) {
507 NotificationView *v =
new NotificationView(get_view()->get_host(), get_view()->get_host()->get_ntf_grp(i), mk_rdx);
508 _Mem::Get()->inject_notification(v,
true);
511 OUTPUT_LINE((TraceLevel)0, Utils::RelativeTime(Now()) <<
" pgm " << controller_->get_object()->get_oid() <<
512 " -> mk.rdx " << mk_rdx->get_oid());
518 Code *InputLessPGMOverlay::get_mk_rdx(uint16 &extent_index)
const {
520 uint16 write_index = 0;
521 extent_index = MK_RDX_ARITY + 1;
525 mk_rdx->code(write_index++) = Atom::Marker(Opcodes::MkRdx, MK_RDX_ARITY);
526 mk_rdx->code(write_index++) = Atom::RPointer(0);
527 mk_rdx->add_reference(get_object());
528 mk_rdx->code(write_index++) = Atom::IPointer(extent_index);
529 mk_rdx->code(extent_index++) = Atom::Set(0);
530 mk_rdx->code(write_index++) = Atom::IPointer(extent_index);
531 mk_rdx->code(write_index++) = Atom::Float(1);
538 PGMOverlay::PGMOverlay(Controller *c) : InputLessPGMOverlay(c) {
540 is_volatile_ = c->get_object()->code(IPGM_RES).asBoolean();
544 PGMOverlay::PGMOverlay(PGMOverlay *original, uint16 last_input_index, uint16 value_commit_index) : InputLessPGMOverlay() {
546 controller_ = original->controller_;
548 input_pattern_indices_ = original->input_pattern_indices_;
549 input_pattern_indices_.push_back(last_input_index);
550 for (uint16 i = 0; i < original->input_views_.size() - 1; ++i)
551 input_views_.push_back(original->input_views_[i]);
553 code_size_ = original->code_size_;
555 memcpy(code_, original->code_, code_size_ *
sizeof(
r_code::Atom));
557 Atom *original_code = &get_object()->get_reference(0)->code(0);
558 for (uint16 i = 0; i < original->patch_indices_.size(); ++i)
559 code_[original->patch_indices_[i]] = original_code[original->patch_indices_[i]];
561 value_commit_index_ = value_commit_index;
562 for (uint16 i = 0; i < value_commit_index; ++i)
563 values_.push_back(original->values_[i]);
565 is_volatile_ = original->is_volatile_;
566 birth_time_ = original->birth_time_;
569 PGMOverlay::~PGMOverlay() {
572 void PGMOverlay::init() {
575 uint16 pattern_set_index = code_[PGM_INPUTS].asIndex();
576 uint16 pattern_count = code_[pattern_set_index].getAtomCount();
577 for (uint16 i = 1; i <= pattern_count; ++i)
578 input_pattern_indices_.push_back(code_[pattern_set_index + i].asIndex());
580 birth_time_ = Timestamp(seconds(0));
583 bool PGMOverlay::is_invalidated() {
587 for (uint32 i = 0; i < input_views_.size(); ++i) {
589 if (input_views_[i]->object_->is_invalidated())
590 return (invalidated_ = 1);
594 return invalidated_ == 1;
597 Code *PGMOverlay::dereference_in_ptr(
Atom a) {
599 switch (a.getDescriptor()) {
600 case Atom::IN_OBJ_PTR:
601 return getInputObject(a.asInputIndex());
602 case Atom::D_IN_OBJ_PTR: {
603 Atom ptr = code_[a.asRelativeIndex()];
604 Code *parent = dereference_in_ptr(ptr);
605 return parent->get_reference(parent->code(ptr.asIndex()).asIndex());
612 void PGMOverlay::patch_input_code(uint16 pgm_code_index, uint16 input_index, uint16 input_code_index, int16 parent_index) {
614 uint16 atom_count = code_[pgm_code_index].getAtomCount();
618 if (parent_index < 0)
619 head = code_[pgm_code_index] = Atom::InObjPointer(input_index, input_code_index);
621 head = code_[pgm_code_index] = Atom::DInObjPointer(parent_index, input_code_index);
622 patch_indices_.push_back(pgm_code_index);
625 for (uint16 j = 1; j <= atom_count; ++j) {
627 uint16 patch_index = pgm_code_index + j;
628 switch (code_[patch_index].getDescriptor()) {
629 case Atom::T_WILDCARD:
633 if (parent_index < 0)
634 code_[patch_index] = Atom::InObjPointer(input_index, input_code_index + j);
636 code_[patch_index] = Atom::DInObjPointer(parent_index, input_code_index + j);
637 patch_indices_.push_back(patch_index);
641 uint16 indirection = code_[patch_index].asIndex();
643 if (parent_index < 0)
644 code_[patch_index] = Atom::InObjPointer(input_index, input_code_index + j);
646 code_[patch_index] = Atom::DInObjPointer(parent_index, input_code_index + j);
647 patch_indices_.push_back(patch_index);
648 switch (dereference_in_ptr(head)->code(input_code_index + j).getDescriptor()) {
652 patch_input_code(indirection, input_index, dereference_in_ptr(head)->code(input_code_index + j).asIndex(), parent_index);
656 patch_input_code(indirection, input_index, 0, patch_index);
673 switch (match(input, input_index)) {
675 if (input_pattern_indices_.size() == 0) {
677 if (check_guards() && inject_productions()) {
679 ((PGMController *)controller_)->notify_reduction();
680 PGMOverlay *offspring =
new PGMOverlay(
this, input_index, value_commit_index_);
685 PGMOverlay *offspring =
new PGMOverlay(
this, input_index, value_commit_index_);
691 PGMOverlay *offspring =
new PGMOverlay(
this, input_index, value_commit_index_);
693 if (birth_time_.time_since_epoch().count() == 0)
706 PGMOverlay::MatchResult PGMOverlay::match(
r_exec::View *input, uint16 &input_index) {
708 input_views_.push_back(input);
711 for (it = input_pattern_indices_.begin(); it != input_pattern_indices_.end(); ++it) {
713 MatchResult r = _match(input, *it);
717 input_pattern_indices_.erase(it);
726 input_views_.pop_back();
727 return failed ? FAILURE : IMPOSSIBLE;
730 PGMOverlay::MatchResult PGMOverlay::_match(
r_exec::View *input, uint16 pattern_index) {
732 if (code_[pattern_index].asOpcode() == Opcodes::AntiPtn) {
734 IPGMContext input_object = IPGMContext::GetContextFromInput(input,
this);
735 IPGMContext pattern_skeleton(get_object()->get_reference(0), get_view(), code_, code_[pattern_index + 1].asIndex(),
this);
736 if (!pattern_skeleton.match(input_object))
738 MatchResult r =
__match(input, pattern_index);
746 }
else if (code_[pattern_index].asOpcode() == Opcodes::Ptn) {
748 IPGMContext input_object = IPGMContext::GetContextFromInput(input,
this);
749 IPGMContext pattern_skeleton(get_object()->get_reference(0), get_view(), code_, code_[pattern_index + 1].asIndex(),
this);
750 if (!pattern_skeleton.match(input_object))
752 return __match(input, pattern_index);
760 patch_input_code(code_[pattern_index + 1].asIndex(), input_views_.size() - 1, 0);
762 uint16 guard_set_index = code_[pattern_index + 2].asIndex();
764 IPGMContext c(get_object()->get_reference(0), get_view(), code_, guard_set_index,
this);
767 if (c.dereference()[0].isBooleanFalse())
773 bool PGMOverlay::check_guards() {
775 uint16 guard_set_index = code_[PGM_GUARDS].asIndex();
776 uint16 guard_count = code_[guard_set_index].getAtomCount();
777 for (uint16 i = 1; i <= guard_count; ++i) {
780 IPGMContext c(get_object()->get_reference(0), get_view(), code_, guard_set_index + i,
this);
783 if (c.dereference()[0].isBooleanFalse())
790 Code *PGMOverlay::get_mk_rdx(uint16 &extent_index)
const {
792 uint16 write_index = 0;
793 extent_index = MK_RDX_ARITY + 1;
797 mk_rdx->code(write_index++) = Atom::Marker(Opcodes::MkRdx, MK_RDX_ARITY);
798 mk_rdx->code(write_index++) = Atom::RPointer(0);
799 mk_rdx->add_reference(get_object());
800 mk_rdx->code(write_index++) = Atom::IPointer(extent_index);
801 mk_rdx->code(extent_index++) = Atom::Set(input_views_.size());
802 for (uint16 i = 0; i < input_views_.size(); ++i) {
804 mk_rdx->code(extent_index++) = Atom::RPointer(i + 1);
805 mk_rdx->add_reference(input_views_[i]->object_);
807 mk_rdx->code(write_index++) = Atom::IPointer(extent_index);
808 mk_rdx->code(write_index++) = Atom::Float(1);
815 AntiPGMOverlay::~AntiPGMOverlay() {
821 switch (match(input, input_index)) {
823 if (input_pattern_indices_.size() == 0) {
825 if (check_guards()) {
827 ((AntiPGMController *)controller_)->restart();
835 AntiPGMOverlay *offspring =
new AntiPGMOverlay(
this, input_index, value_commit_index_);