/* Copyright 2008 Suraj N. Kurapati See the file named LICENSE for details. */ #include "user.h" #include "util.h" #include "binding.h" #include <ruby.h> static VALUE RubyVPI_user_require_impl(VALUE aPath) { return rb_require((char*)aPath); } static VALUE RubyVPI_user_require(char* aPath) { int error = 0; VALUE result = rb_protect(RubyVPI_user_require_impl, (VALUE)aPath, &error); if (error) { RubyVPI_util_error("rb_require('%s') failed with status %d", aPath, error); } return result; } /// /// Body of the ruby thread which runs the user code. /// static VALUE RubyVPI_user_body(char* aUserScript) { RubyVPI_util_debug("Ruby: BEGIN synchronized with simulator"); RubyVPI_user_require(aUserScript); // blocks until user script is finished RubyVPI_util_debug("Ruby: END"); // don't wait for anyone to resume me anymore return Qnil; } static VALUE RubyVPI_user__module_RubyVPI = Qnil; static ID RubyVPI_user__symbol_resume = 0; void RubyVPI_user_init() { // mailbox init RubyVPI_util_debug("User: mailbox init"); RubyVPI_user_require("ruby-vpi/boot/relay"); // ruby thread init RubyVPI_util_debug("User: ruby thread init"); rb_thread_create(RubyVPI_user_body, "ruby-vpi/boot/loader"); // wait for thread to pause RubyVPI_util_debug("User: calling RubyVPI.attach"); RubyVPI_user__module_RubyVPI = rb_const_get(rb_cObject, rb_intern("RubyVPI")); rb_funcall(RubyVPI_user__module_RubyVPI, rb_intern("attach"), 0); RubyVPI_util_debug("User: calling RubyVPI.attach DONE"); RubyVPI_util_debug("User: ruby thread is active & ran once"); RubyVPI_user__symbol_resume = rb_intern("resume"); } void RubyVPI_user_fini() { RubyVPI_user__module_RubyVPI = Qnil; // Ruby will garbage collect everything else } PLI_INT32 RubyVPI_user_resume(p_cb_data aCallback) { RubyVPI_util_debug("Main: callback = %p", aCallback); RubyVPI_util_debug("Main: callback.user_data = %p", aCallback ? aCallback->user_data : 0); RubyVPI_util_debug("Main: calling RubyVPI.resume"); // pass VPI callback to user code as Ruby object rb_funcall(RubyVPI_user__module_RubyVPI, RubyVPI_user__symbol_resume, 1, RubyVPI_binding_rubify_callback(aCallback)); return 0; }