Beispiel #1
0
static int shell_cmd_watch(ClientData cd, Tcl_Interp *interp,
                           int objc, Tcl_Obj *const objv[])
{
   const char *help =
      "watch - Trace changes to a signal\n"
      "\n"
      "Usage: watch SIGNALS...\n"
      "\n"
      "Prints a message every time an update occurs to a signal listed."
      "\n"
      "Examples:\n"
      "  watch [signals {clk}]  Trace updates to all signals named clk\n";

   if (show_help(objc, objv, help))
      return TCL_OK;

   if (objc == 1) {
      warnf("nothing to watch (try -help for usage)");
      return TCL_OK;
   }

   hash_t *decl_hash = (hash_t *)cd;

   for (int i = 1; i < objc; i++) {
      int length;
      if (Tcl_ListObjLength(interp, objv[i], &length) != TCL_OK)
         return TCL_ERROR;

      for (int j = 0; j < length; j++) {
         Tcl_Obj *obj;
         if (Tcl_ListObjIndex(interp, objv[i], j, &obj) != TCL_OK)
            return TCL_ERROR;

         const char *str = Tcl_GetString(obj);

         tree_t t = hash_get(decl_hash, ident_new(str));
         if (t == NULL)
            return tcl_error(interp, "object not found: %s", str);

         if (t == NULL)
            return tcl_error(interp, "object not found: %s", str);
         else if (tree_kind(t) != T_SIGNAL_DECL)
            return tcl_error(interp, "not a signal: %s", str);
         else if (type_is_array(tree_type(t)))
            return tcl_error(interp, "only scalar signals may be watched");
         // TODO: make this work for arrays

         slave_watch_msg_t msg = {
            .index = tree_index(t)
         };
         slave_post_msg(SLAVE_WATCH, &msg, sizeof(msg));
      }
   }

   return TCL_OK;
}
Beispiel #2
0
static int shell_cmd_unwatch(ClientData cd, Tcl_Interp *interp,
                             int objc, Tcl_Obj *const objv[])
{
   const char *help =
      "unwatch - Stop tracing signals\n"
      "\n"
      "Usage: unwatch SIGNALS...\n"
      "\n"
      "Clears any watch callback on SIGNALS. Note this will also stop any\n"
      "VCD or other waveform capture for these signals.\n"
      "\n"
      "Examples:\n"
      "  watch [signals {clk}]  Stop tracing updates to clk\n";

   if (show_help(objc, objv, help))
      return TCL_OK;

   if (objc == 1) {
      warnf("nothing to unwatch (try -help for usage)");
      return TCL_OK;
   }

   hash_t *decl_hash = (hash_t *)cd;

   // TODO: refactor this code to avoid duplication with "watch" and "show"
   for (int i = 1; i < objc; i++) {
      int length;
      if (Tcl_ListObjLength(interp, objv[i], &length) != TCL_OK)
         return TCL_ERROR;

      for (int j = 0; j < length; j++) {
         Tcl_Obj *obj;
         if (Tcl_ListObjIndex(interp, objv[i], j, &obj) != TCL_OK)
            return TCL_ERROR;

         const char *str = Tcl_GetString(obj);

         tree_t t = hash_get(decl_hash, ident_new(str));
         if (t == NULL)
            return tcl_error(interp, "object not found: %s", str);
         else if (tree_kind(t) != T_SIGNAL_DECL)
            return tcl_error(interp, "not a signal: %s", str);

         slave_unwatch_msg_t msg = {
            .index = tree_index(t)
         };
         slave_post_msg(SLAVE_UNWATCH, &msg, sizeof(msg));
      }
   }

   return TCL_OK;
}
Beispiel #3
0
static int shell_cmd_run(ClientData cd, Tcl_Interp *interp,
                         int objc, Tcl_Obj *const objv[])
{
   static bool sim_running = false;

   if (sim_running)
      return tcl_error(interp, "simulation already running");

   uint64_t stop_time = UINT64_MAX;
   if (objc == 3) {
      Tcl_WideInt base;
      int error = Tcl_GetWideIntFromObj(interp, objv[1], &base);
      if (error != TCL_OK || base <= 0)
         return tcl_error(interp, "invalid time");

      const char *unit = Tcl_GetString(objv[2]);

      uint64_t mult;
      if      (strcmp(unit, "fs") == 0) mult = 1;
      else if (strcmp(unit, "ps") == 0) mult = 1000;
      else if (strcmp(unit, "ns") == 0) mult = 1000000;
      else if (strcmp(unit, "us") == 0) mult = 1000000000;
      else if (strcmp(unit, "ms") == 0) mult = 1000000000000;
      else {
         fprintf(stderr, "invalid time unit %s", unit);
         return TCL_ERROR;
      }

      stop_time = rt_now(NULL) + (base * mult);
   }
   else if (objc != 1)
      return tcl_error(interp, "usage: run [time units]");

   sim_running = true;
   rt_run_interactive(stop_time);
   sim_running = false;

   return TCL_OK;
}
Beispiel #4
0
static int shell_cmd_now(ClientData cd, Tcl_Interp *interp,
                         int objc, Tcl_Obj *const objv[])
{
   const char *help =
      "now - Display current simulation time\n"
      "\n"
      "Usage: now [-q]\n"
      "\n"
      "Prints the current simulation time to the standard output unless -q\n"
      "is specified. Returns the time as a string.\n"
      "\n"
      "Examples:\n"
      "  now               Print current time\n"
      "  set n [now -q]    Store current time in a variable\n";

   if (show_help(objc, objv, help))
      return TCL_OK;

   bool quiet = false;

   for (int i = 1; i < objc; i++) {
      const char *what = Tcl_GetString(objv[i]);
      if (strcmp(what, "-q") == 0)
         quiet = true;
      else
         return tcl_error(interp, "invalid argument '%s' "
                          "(try -help for usage)", what);
   }

   slave_post_msg(SLAVE_NOW, NULL, 0);

   reply_now_msg_t reply;
   slave_get_reply(REPLY_NOW, &reply, sizeof(reply));

   if (!quiet)
      printf("%s\n", reply.text);

   Tcl_SetObjResult(interp, Tcl_NewIntObj(reply.now));
   return TCL_OK;
}
Beispiel #5
0
static int shell_cmd_now(ClientData cd, Tcl_Interp *interp,
                         int objc, Tcl_Obj *const objv[])
{
   const char *help =
      "now - Display current simulation time\n"
      "\n"
      "Usage: now [-q]\n"
      "\n"
      "Prints the current simulation time to the standard output unless -q\n"
      "is specified. Returns the time as a string.\n"
      "\n"
      "Examples:\n"
      "  now               Print current time\n"
      "  set n [now -q]    Store current time in a variable\n";

   if (show_help(objc, objv, help))
      return TCL_OK;

   bool quiet = false;

   for (int i = 1; i < objc; i++) {
      const char *what = Tcl_GetString(objv[i]);
      if (strcmp(what, "-q") == 0)
         quiet = true;
      else
         return tcl_error(interp, "invalid argument '%s' "
                          "(try -help for usage)", what);
   }

   const uint64_t now = rt_now(NULL);

   if (!quiet)
      printf("%s\n", fmt_time(now));

   Tcl_SetObjResult(interp, Tcl_NewIntObj(now));
   return TCL_OK;
}
Beispiel #6
0
static int shell_cmd_show(ClientData cd, Tcl_Interp *interp,
                          int objc, Tcl_Obj *const objv[])
{
   const char *help =
      "show - Display simulation objects\n"
      "\n"
      "Usage: show LIST...\n"
      "\n"
      "Prints a representation of each simulation object in LIST. Typically\n"
      "this will be a list of signal names and the output will show their\n"
      "current value.\n"
      "\n"
      "Examples:\n"
      "  show {:top:foo}      Print value of signal :top_foo\n"
      "  show [signals]       Print value of all signals\n";

   if (show_help(objc, objv, help))
      return TCL_OK;

   if (objc == 1) {
      warnf("nothing to show (try -help for usage)");
      return TCL_OK;
   }

   hash_t *decl_hash = (hash_t *)cd;

   for (int i = 1; i < objc; i++) {
      int length;
      if (Tcl_ListObjLength(interp, objv[i], &length) != TCL_OK)
         return TCL_ERROR;

      for (int j = 0; j < length; j++) {
         Tcl_Obj *obj;
         if (Tcl_ListObjIndex(interp, objv[i], j, &obj) != TCL_OK)
            return TCL_ERROR;

         const char *str = Tcl_GetString(obj);

         tree_t t = hash_get(decl_hash, ident_new(str));
         if (t == NULL)
            return tcl_error(interp, "object not found: %s", str);

         tree_kind_t kind = tree_kind(t);
         switch (kind) {
         case T_SIGNAL_DECL:
            {
               const size_t len = tree_nets(t);
               uint64_t *values LOCAL = xmalloc(len * sizeof(uint64_t));
               rt_signal_value(t, values, len);

               const char *type_str = type_pp(tree_type(t));
               const char *short_name = strrchr(type_str, '.');

               LOCAL_TEXT_BUF values_tb = pprint(t, values, len);
               printf("%-30s%-20s%s\n",
                      str,
                      (short_name != NULL ? short_name + 1 : type_str),
                      tb_get(values_tb));
            }
            break;

         default:
            return tcl_error(interp, "cannot show tree kind %s",
                             tree_kind_str(kind));
         }
      }
   }

   return TCL_OK;
}
Beispiel #7
0
static int shell_cmd_show(ClientData cd, Tcl_Interp *interp,
                          int objc, Tcl_Obj *const objv[])
{
   const char *help =
      "show - Display simulation objects\n"
      "\n"
      "Usage: show LIST...\n"
      "\n"
      "Prints a representation of each simulation object in LIST. Typically\n"
      "this will be a list of signal names and the output will show their\n"
      "current value.\n"
      "\n"
      "Examples:\n"
      "  show {:top:foo}      Print value of signal :top_foo\n"
      "  show [signals]       Print value of all signals\n";

   if (show_help(objc, objv, help))
      return TCL_OK;

   if (objc == 1) {
      warnf("nothing to show (try -help for usage)");
      return TCL_OK;
   }

   hash_t *decl_hash = (hash_t *)cd;

   for (int i = 1; i < objc; i++) {
      int length;
      if (Tcl_ListObjLength(interp, objv[i], &length) != TCL_OK)
         return TCL_ERROR;

      for (int j = 0; j < length; j++) {
         Tcl_Obj *obj;
         if (Tcl_ListObjIndex(interp, objv[i], j, &obj) != TCL_OK)
            return TCL_ERROR;

         const char *str = Tcl_GetString(obj);

         tree_t t = hash_get(decl_hash, ident_new(str));
         if (t == NULL)
            return tcl_error(interp, "object not found: %s", str);

         tree_kind_t kind = tree_kind(t);
         switch (kind) {
         case T_SIGNAL_DECL:
            {
               size_t len = 1;
               type_t type = tree_type(t);
               while (type_is_array(type)) {
                  int64_t low = 0, high = 0;
                  range_bounds(type_dim(type, 0), &low, &high);
                  len *= (high - low + 1);

                  type = type_elem(type);
               }

               slave_read_signal_msg_t msg = {
                  .index = tree_index(t),
                  .len   = len
               };
               slave_post_msg(SLAVE_READ_SIGNAL, &msg, sizeof(msg));

               const size_t rsz =
                  sizeof(reply_read_signal_msg_t)
                  + (msg.len * sizeof(uint64_t));
               reply_read_signal_msg_t *reply = xmalloc(rsz);
               slave_get_reply(REPLY_READ_SIGNAL, reply, rsz);

               const char *type_str = type_pp(type);
               const char *short_name = strrchr(type_str, '.');

               printf("%-30s%-20s%s\n",
                      str,
                      (short_name != NULL ? short_name + 1 : type_str),
                      pprint(t, reply->values, msg.len));

               free(reply);
            }
            break;

         default:
            return tcl_error(interp, "cannot show tree kind %s",
                             tree_kind_str(kind));
         }
      }
   }

   return TCL_OK;
}