From e88dfb3868f5746389bdf32134cd7dd5778c379d Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 17 Jun 2018 20:01:44 -0400 Subject: [PATCH] SCP Updated to current version. --- scp.c | 313 ++++++++++++++++++++++++++++++++++---------------- scp.h | 2 + sim_console.c | 6 +- sim_defs.h | 2 + sim_fio.c | 56 +++++++++ sim_fio.h | 2 + sim_timer.c | 57 ++++----- sim_tmxr.c | 116 +++++++++++-------- sim_tmxr.h | 7 +- 9 files changed, 382 insertions(+), 179 deletions(-) diff --git a/scp.c b/scp.c index 098fbb8..b42523c 100644 --- a/scp.c +++ b/scp.c @@ -519,7 +519,6 @@ t_stat do_cmd_label (int32 flag, CONST char *cptr, CONST char *label); void int_handler (int signal); t_stat set_prompt (int32 flag, CONST char *cptr); t_stat sim_set_asynch (int32 flag, CONST char *cptr); -t_stat sim_set_environment (int32 flag, CONST char *cptr); static const char *get_dbg_verb (uint32 dbits, DEVICE* dptr, UNIT *uptr); /* Global data */ @@ -582,7 +581,7 @@ static int32 sim_show_message = 1; /* the message display s static int32 sim_on_inherit = 0; /* the inherit status of on state and conditions when executing do files */ static int32 sim_do_depth = 0; static t_bool sim_cmd_echoed = FALSE; /* Command was emitted already prior to message output */ - +static char **sim_exp_argv = NULL; static int32 sim_on_check[MAX_DO_NEST_LVL+1]; static char *sim_on_actions[MAX_DO_NEST_LVL+1][SCPE_MAX_ERR+2]; #define ON_SIGINT_ACTION (SCPE_MAX_ERR+1) @@ -603,8 +602,34 @@ static DEBTAB sim_dflt_debug[] = { {0} }; -static UNIT sim_step_unit = { UDATA (&step_svc, 0, 0) }; -static UNIT sim_expect_unit = { UDATA (&expect_svc, 0, 0) }; +static const char *sim_int_step_description (DEVICE *dptr) +{ +return "Step/Next facility"; +} + +static UNIT sim_step_unit = { UDATA (&step_svc, 0, 0) }; +DEVICE sim_step_dev = { + "INT-STEP", &sim_step_unit, NULL, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, DEV_NOSAVE, 0, + NULL, NULL, NULL, NULL, NULL, NULL, + sim_int_step_description}; + +static const char *sim_int_expect_description (DEVICE *dptr) +{ +return "Expect facility"; +} + +static UNIT sim_expect_unit = { UDATA (&expect_svc, 0, 0) }; +DEVICE sim_expect_dev = { + "INT-EXPECT", &sim_expect_unit, NULL, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, DEV_NOSAVE, 0, + NULL, NULL, NULL, NULL, NULL, NULL, + sim_int_expect_description}; + #if defined USE_INT64 static const char *sim_si64 = "64b data"; #else @@ -2389,6 +2414,8 @@ sim_log = NULL; if (sim_emax <= 0) sim_emax = 1; sim_timer_init (); +sim_register_internal_device (&sim_expect_dev); +sim_register_internal_device (&sim_step_dev); if ((stat = sim_ttinit ()) != SCPE_OK) { fprintf (stderr, "Fatal terminal initialization error\n%s\n", @@ -2507,8 +2534,10 @@ while (stat != SCPE_EXIT) { /* in case exit */ if (sim_on_actions[sim_do_depth][ON_SIGINT_ACTION]) sim_brk_setact (sim_on_actions[sim_do_depth][ON_SIGINT_ACTION]); } - if ((cptr = sim_brk_getact (cbuf, sizeof(cbuf)))) /* pending action? */ - printf ("%s%s\n", sim_prompt, cptr); /* echo */ + if ((cptr = sim_brk_getact (cbuf, sizeof(cbuf)))) { /* pending action? */ + if (sim_do_echo) + printf ("%s+ %s\n", sim_prompt, cptr); /* echo */ + } else { if (sim_vm_read != NULL) { /* sim routine? */ printf ("%s", sim_prompt); /* prompt */ @@ -3347,6 +3376,7 @@ if (flag >= 0) { /* Only bump nesting fro } } +sim_debug (SIM_DBG_DO, sim_dflt_dev, "do_cmd_label(%d, flag=%d, '%s', '%s')\n", sim_do_depth, flag, fcptr, label ? label : ""); strlcpy( sim_do_filename[sim_do_depth], do_arg[0], sizeof (sim_do_filename[sim_do_depth])); /* stash away do file name for possible use by 'call' command */ sim_do_label[sim_do_depth] = label; /* stash away do label for possible use in messages */ @@ -3379,11 +3409,13 @@ do { sim_do_ocptr[sim_do_depth] = cptr = read_line (cbuf, sizeof(cbuf), fpin);/* get cmd line */ sim_goto_line[sim_do_depth] += 1; } - sim_sub_args (cbuf, sizeof(cbuf), do_arg); /* substitute args */ if (cptr == NULL) { /* EOF? */ stat = SCPE_OK; /* set good return */ break; } + sim_debug (SIM_DBG_DO, sim_dflt_dev, "Input Command: %s\n", cbuf); + sim_sub_args (cbuf, sizeof(cbuf), do_arg); /* substitute args */ + sim_debug (SIM_DBG_DO, sim_dflt_dev, "Expanded Command: %s\n", cbuf); if (*cptr == 0) /* ignore blank */ continue; if (echo) /* echo if -v */ @@ -3412,6 +3444,7 @@ do { } else stat = SCPE_UNK; /* bad cmd given */ + sim_debug (SIM_DBG_DO, sim_dflt_dev, "Command '%s', Result: 0x%X - %s\n", cmdp ? cmdp->name : "", stat, sim_error_text (stat)); echo = sim_do_echo; /* Allow for SET VERIFY */ stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */ stat_nomessage = stat_nomessage || (!sim_show_message);/* Apply global suppression */ @@ -3483,9 +3516,11 @@ if ((flag >= 0) || (!sim_on_inherit)) { } sim_on_check[sim_do_depth] = 0; /* clear on mode */ } -if (flag >= 0) +sim_debug (SIM_DBG_DO, sim_dflt_dev, "do_cmd_label - exiting - stat:%d (%d, flag=%d, '%s', '%s')\n", stat, sim_do_depth, flag, fcptr, label ? label : ""); +if (flag >= 0) { + sim_brk_clract (); /* defang breakpoint actions */ --sim_do_depth; /* unwind nesting */ -sim_brk_clract (); /* defang breakpoint actions */ + } if (cmdp && (cmdp->action == &return_cmd) && (0 != *cptr)) { /* return command with argument? */ sim_string_to_stat (cptr, &stat); sim_last_cmd_stat = stat; /* save explicit status as command error status */ @@ -3540,7 +3575,7 @@ return stat | SCPE_NOMESSAGE; /* suppress message sinc */ static const char * -_sim_get_env_special (const char *gbuf, char *rbuf, size_t rbuf_size) +_sim_gen_env_uplowcase (const char *gbuf, char *rbuf, size_t rbuf_size) { const char *ap; char tbuf[CBUFSIZE]; @@ -3548,11 +3583,23 @@ char tbuf[CBUFSIZE]; ap = getenv(gbuf); /* first try using the literal name */ if (!ap) { get_glyph (gbuf, tbuf, 0); /* now try using the upcased name */ - ap = getenv(tbuf); + if (strcmp (gbuf, tbuf)) /* upcase different? */ + ap = getenv(tbuf); /* lookup the upcase name */ } -if (ap) /* environment variable found? */ +if (ap) { /* environment variable found? */ strlcpy (rbuf, ap, rbuf_size); /* Return the environment value */ -else { /* otherwise, check for Special Names */ + ap = rbuf; + } +return ap; +} + +static const char * +_sim_get_env_special (const char *gbuf, char *rbuf, size_t rbuf_size) +{ +const char *ap; + +ap = _sim_gen_env_uplowcase (gbuf, rbuf, rbuf_size);/* Look for environment variable */ +if (!ap) { /* no environment variable found? */ time_t now = (time_t)cmd_time.tv_sec; struct tm *tmnow = localtime(&now); @@ -3718,6 +3765,22 @@ else { /* otherwise, check for Special Names */ return ap; } +/* Substitute_args - replace %n tokens in 'instr' with the do command's arguments + + Calling sequence + instr = input string + tmpbuf = temp buffer + maxstr = min (len (instr), len (tmpbuf)) + do_arg[10] = arguments + + Token "%0" represents the command file name. + + The input sequence "\%" represents a literal "%", and "\\" represents a + literal "\". All other character combinations are rendered literally. + + Omitted parameters result in null-string substitutions. +*/ + void sim_sub_args (char *instr, size_t instr_size, char *do_arg[]) { char gbuf[CBUFSIZE]; @@ -3728,6 +3791,7 @@ int i; size_t instr_off = 0; size_t outstr_off = 0; +sim_exp_argv = do_arg; clock_gettime(CLOCK_REALTIME, &cmd_time); tmpbuf = (char *)malloc(instr_size); op = tmpbuf; @@ -6377,6 +6441,8 @@ for (i = 0; i < start; i++) { return SCPE_IERR; } for (i = start; (dptr = sim_devices[i]) != NULL; i++) { + if (sim_switches & SWMASK('P')) + tmxr_add_debug (dptr); /* Add TMXR debug to MUX devices */ if (dptr->reset != NULL) { reason = dptr->reset (dptr); if (reason != SCPE_OK) @@ -6399,9 +6465,50 @@ static DEBTAB scp_debug[] = { {"QUEUE", SIM_DBG_AIO_QUEUE, "asynch event queue activities"}, {"EXPSTACK", SIM_DBG_EXP_STACK, "expression stack activities"}, {"EXPEVAL", SIM_DBG_EXP_EVAL, "expression evaluation activities"}, + {"ACTION", SIM_DBG_BRK_ACTION, "action activities"}, + {"DO", SIM_DBG_DO, "do activities"}, {0} }; +t_stat sim_add_debug_flags (DEVICE *dptr, DEBTAB *debflags) +{ +dptr->flags |= DEV_DEBUG; +if (!dptr->debflags) + dptr->debflags = debflags; +else { + DEBTAB *cdptr, *sdptr, *ndptr; + + for (sdptr = debflags; sdptr->name; sdptr++) { + for (cdptr = dptr->debflags; cdptr->name; cdptr++) { + if (sdptr->mask == cdptr->mask) + break; + } + if (sdptr->mask != cdptr->mask) { + int i, dcount = 0; + + for (cdptr = dptr->debflags; cdptr->name; cdptr++) + dcount++; + for (cdptr = debflags; cdptr->name; cdptr++) + dcount++; + ndptr = (DEBTAB *)calloc (1 + dcount, sizeof (*ndptr)); + for (dcount = 0, cdptr = dptr->debflags; cdptr->name; cdptr++) + ndptr[dcount++] = *cdptr; + for (cdptr = debflags; cdptr->name; cdptr++) { + for (i = 0; i < dcount; i++) { + if (cdptr->mask == ndptr[i].mask) + break; + } + if (i == dcount) + ndptr[dcount++] = *cdptr; + } + dptr->debflags = ndptr; + break; + } + } + } +return SCPE_OK; +} + /* Reset to powerup state Inputs: @@ -6418,42 +6525,8 @@ int32 old_sw = sim_switches; sim_switches = SWMASK ('P'); r = reset_all (start); sim_switches = old_sw; -if (sim_dflt_dev) { /* Make sure that SCP debug options are available */ - sim_dflt_dev->flags |= DEV_DEBUG; - if (!sim_dflt_dev->debflags) - sim_dflt_dev->debflags = scp_debug; - else { - DEBTAB *cdptr, *sdptr, *ndptr; - - for (sdptr = scp_debug; sdptr->name; sdptr++) { - for (cdptr = sim_dflt_dev->debflags; cdptr->name; cdptr++) { - if (sdptr->mask == cdptr->mask) - break; - } - if (sdptr->mask != cdptr->mask) { - int i, dcount = 0; - - for (cdptr = sim_dflt_dev->debflags; cdptr->name; cdptr++) - dcount++; - for (cdptr = scp_debug; cdptr->name; cdptr++) - dcount++; - ndptr = (DEBTAB *)calloc (1 + dcount, sizeof (*ndptr)); - for (dcount = 0, cdptr =sim_dflt_dev->debflags; cdptr->name; cdptr++) - ndptr[dcount++] = *cdptr; - for (cdptr = scp_debug; cdptr->name; cdptr++) { - for (i = 0; i < dcount; i++) { - if (cdptr->mask == ndptr[i].mask) - break; - } - if (i == dcount) - ndptr[dcount++] = *cdptr; - } - sim_dflt_dev->debflags = ndptr; - break; - } - } - } - } +if (sim_dflt_dev) /* Make sure that SCP debug options are available */ + sim_add_debug_flags (sim_dflt_dev, scp_debug); return r; } @@ -7828,6 +7901,7 @@ t_stat exdep_cmd (int32 flag, CONST char *cptr) char gbuf[CBUFSIZE]; CONST char *gptr; CONST char *tptr = NULL; +const char *ap; int32 opt; t_addr low, high; t_stat reason; @@ -7900,6 +7974,10 @@ for (gptr = gbuf, reason = SCPE_OK; continue; } + if ((ap = getenv (gptr))) { + strlcpy (gbuf, ap, sizeof (gbuf)); + gptr = gbuf; + } tptr = get_range (sim_dfdev, gptr, &low, &high, sim_dfdev->aradix, (((sim_dfunit->capac == 0) || (flag == EX_E))? 0: sim_dfunit->capac - sim_dfdev->aincr), 0); @@ -9326,12 +9404,12 @@ t_stat sim_register_internal_device (DEVICE *dptr) { uint32 i; -for (i = 0; (sim_devices[i] != NULL); i++) - if (sim_devices[i] == dptr) - return SCPE_OK; for (i = 0; i < sim_internal_device_count; i++) if (sim_internal_devices[i] == dptr) return SCPE_OK; +for (i = 0; (sim_devices[i] != NULL); i++) + if (sim_devices[i] == dptr) + return SCPE_OK; ++sim_internal_device_count; sim_internal_devices = (DEVICE **)realloc(sim_internal_devices, (sim_internal_device_count+1)*sizeof(*sim_internal_devices)); sim_internal_devices[sim_internal_device_count-1] = dptr; @@ -10339,14 +10417,18 @@ do { uptr->next = NULL; /* hygiene */ uptr->time = 0; if (sim_clock_queue != QUEUE_LIST_END) - sim_interval = sim_clock_queue->time; + sim_interval += sim_clock_queue->time; else sim_interval = noqueue_time = NOQUEUE_WAIT; - sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Processing Event for %s\n", sim_uname (uptr)); AIO_EVENT_BEGIN(uptr); - if (uptr->usecs_remaining) + if (uptr->usecs_remaining) { + sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Requeueing %s after %.0f usecs\n", sim_uname (uptr), uptr->usecs_remaining); reason = sim_timer_activate_after (uptr, uptr->usecs_remaining); + } else { + sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Processing Event for %s\n", sim_uname (uptr)); + if (uptr->uname && ((*uptr->uname == '\0') || (*uptr->uname == ' '))) + reason = SCPE_OK; /* do nothing breakpoint location */ if (uptr->action != NULL) reason = uptr->action (uptr); else @@ -10530,10 +10612,10 @@ AIO_CANCEL(uptr); AIO_UPDATE_QUEUE; if (sim_clock_queue == QUEUE_LIST_END) return SCPE_OK; -sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Canceling Event for %s\n", sim_uname(uptr)); UPDATE_SIM_TIME; /* update sim time */ if (!sim_is_active (uptr)) return SCPE_OK; +sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Canceling Event for %s\n", sim_uname(uptr)); nptr = QUEUE_LIST_END; if (sim_clock_queue == uptr) { @@ -11108,9 +11190,11 @@ if (ep != NULL) { /* if a semicolon is pre } else { strlcpy (buf, sim_brk_act[sim_do_depth], size); /* copy action */ + sim_brk_act[sim_do_depth] = NULL; /* mark as digested */ sim_brk_clract (); /* no more */ } sim_trim_endspc (buf); +sim_debug (SIM_DBG_BRK_ACTION, sim_dflt_dev, "sim_brk_getact(%d) - Returning: '%s'\n", sim_do_depth, buf); return buf; } @@ -11118,6 +11202,8 @@ return buf; char *sim_brk_clract (void) { +if (sim_brk_act[sim_do_depth]) + sim_debug (SIM_DBG_BRK_ACTION, sim_dflt_dev, "sim_brk_clract(%d) - Clearing: '%s'\n", sim_do_depth, sim_brk_act[sim_do_depth]); free (sim_brk_act_buf[sim_do_depth]); return sim_brk_act[sim_do_depth] = sim_brk_act_buf[sim_do_depth] = NULL; } @@ -11127,8 +11213,25 @@ return sim_brk_act[sim_do_depth] = sim_brk_act_buf[sim_do_depth] = NULL; void sim_brk_setact (const char *action) { if (action) { - sim_brk_act_buf[sim_do_depth] = (char *)realloc (sim_brk_act_buf[sim_do_depth], strlen (action) + 1); - strcpy (sim_brk_act_buf[sim_do_depth], action); + if (sim_brk_act[sim_do_depth] && (*sim_brk_act[sim_do_depth])) { + /* push new actions ahead of whatever is already pending */ + size_t old_size = strlen (sim_brk_act[sim_do_depth]); + size_t new_size = strlen (action) + old_size + 3; + char *old_action = (char *)malloc (1 + old_size); + + strlcpy (old_action, sim_brk_act[sim_do_depth], 1 + old_size); + sim_brk_act_buf[sim_do_depth] = (char *)realloc (sim_brk_act_buf[sim_do_depth], new_size); + strlcpy (sim_brk_act_buf[sim_do_depth], action, new_size); + strlcat (sim_brk_act_buf[sim_do_depth], "; ", new_size); + strlcat (sim_brk_act_buf[sim_do_depth], old_action, new_size); + sim_debug (SIM_DBG_BRK_ACTION, sim_dflt_dev, "sim_brk_setact(%d) - Pushed: '%s' ahead of: '%s'\n", sim_do_depth, action, old_action); + free (old_action); + } + else { + sim_brk_act_buf[sim_do_depth] = (char *)realloc (sim_brk_act_buf[sim_do_depth], strlen (action) + 1); + strcpy (sim_brk_act_buf[sim_do_depth], action); + sim_debug (SIM_DBG_BRK_ACTION, sim_dflt_dev, "sim_brk_setact(%d) - Set to: '%s'\n", sim_do_depth, action); + } sim_brk_act[sim_do_depth] = sim_brk_act_buf[sim_do_depth]; } else @@ -11721,6 +11824,9 @@ if (i != exp->size) { /* Found? */ ep->cnt, (ep->cnt == 1) ? "" : "es"); } else { + uint32 after = ep->after; + int32 switches = ep->switches; + if (ep->act && *ep->act) { sim_debug (exp->dbit, exp->dptr, "Initiating actions: %s\n", ep->act); } @@ -11735,9 +11841,9 @@ if (i != exp->size) { /* Found? */ sim_exp_clr_tab (exp, ep); /* delete it */ } sim_activate (&sim_expect_unit, /* schedule simulation stop when indicated */ - (ep->switches & EXP_TYP_TIME) ? - (int32)((sim_timer_inst_per_sec ()*ep->after)/1000000.0) : - ep->after); + (switches & EXP_TYP_TIME) ? + (int32)((sim_timer_inst_per_sec ()*after)/1000000.0) : + after); } /* Matched data is no longer available for future matching */ exp->buf_data = exp->buf_ins = 0; @@ -13505,17 +13611,17 @@ return !data; static t_svalue _op_log_and (t_svalue data1, t_svalue data2) { -return data1 && data2; +return data2 && data1; } static t_svalue _op_log_or (t_svalue data1, t_svalue data2) { -return data1 || data2; +return data2 || data1; } static t_svalue _op_bit_and (t_svalue data1, t_svalue data2) { -return data1 & data2; +return data2 & data1; } static t_svalue _op_bit_rsh (t_svalue shift, t_svalue data) @@ -13530,72 +13636,77 @@ return data << shift; static t_svalue _op_bit_or (t_svalue data1, t_svalue data2) { -return data1 | data2; +return data2 | data1; } static t_svalue _op_bit_xor (t_svalue data1, t_svalue data2) { -return data1 ^ data2; +return data2 ^ data1; } static t_svalue _op_eq (t_svalue data1, t_svalue data2) { -return data1 == data2; +return data2 == data1; } static t_svalue _op_ne (t_svalue data1, t_svalue data2) { -return data1 != data2; +return data2 != data1; } static t_svalue _op_le (t_svalue data1, t_svalue data2) { -return data1 <= data2; +return data2 <= data1; } static t_svalue _op_lt (t_svalue data1, t_svalue data2) { -return data1 < data2; +return data2 < data1; } static t_svalue _op_ge (t_svalue data1, t_svalue data2) { -return data1 >= data2; +return data2 >= data1; } static t_svalue _op_gt (t_svalue data1, t_svalue data2) { -return data1 > data2; +return data2 > data1; +} + +static int _i_strcmp (const char *s1, const char *s2) +{ +return ((sim_switches & SWMASK('I')) ? strcasecmp (s2, s1) : strcmp (s2, s1)); } static t_svalue _op_str_eq (const char *str1, const char *str2) { -return (0 == strcmp (str1, str2)); +return (0 == _i_strcmp (str2, str1)); } static t_svalue _op_str_ne (const char *str1, const char *str2) { -return (0 != strcmp (str1, str2)); +return (0 != _i_strcmp (str2, str1)); } static t_svalue _op_str_le (const char *str1, const char *str2) { -return (0 > strcmp (str1, str2)); +return (0 <= _i_strcmp (str2, str1)); } static t_svalue _op_str_lt (const char *str1, const char *str2) { -return (0 >= strcmp (str1, str2)); +return (0 < _i_strcmp (str2, str1)); } static t_svalue _op_str_ge (const char *str1, const char *str2) { -return (0 < strcmp (str1, str2)); +return (0 >= _i_strcmp (str2, str1)); } static t_svalue _op_str_gt (const char *str1, const char *str2) { -return (0 <= strcmp (str1, str2)); +return (0 > _i_strcmp (str2, str1)); } /* @@ -13644,7 +13755,7 @@ static const char BinaryDigits[] = "01"; *oper = NULL; while (isspace (*cptr)) ++cptr; -if (isalpha (*cptr)) { +if (isalpha (*cptr) || (*cptr == '_')) { while (isalnum (*cptr) || (*cptr == '.') || (*cptr == '_')) *buf++ = *cptr++; *buf = '\0'; @@ -13656,7 +13767,7 @@ else { memcpy (buf, cptr, 2); cptr += 2; buf += 2; - while (strchr (HexDigits, *cptr)) + while (*cptr && strchr (HexDigits, *cptr)) *buf++ = *cptr++; *buf = '\0'; } @@ -13666,13 +13777,13 @@ else { memcpy (buf, cptr, 2); cptr += 2; buf += 2; - while (strchr (BinaryDigits, *cptr)) + while (*cptr && strchr (BinaryDigits, *cptr)) *buf++ = *cptr++; *buf = '\0'; } else { if (*cptr == '0') { /* Octal Number */ - while (strchr (OctalDigits, *cptr)) + while (*cptr && strchr (OctalDigits, *cptr)) *buf++ = *cptr++; *buf = '\0'; } @@ -13820,8 +13931,9 @@ return cptr; /* return any unprocessed input */ static t_bool _value_of (const char *data, t_svalue *svalue, char *string, size_t string_size) { CONST char *gptr; +size_t data_size = strlen (data); -if (isalpha (*data)) { +if (isalpha (*data) || (*data == '_')) { REG *rptr = NULL; DEVICE *dptr = sim_dfdev; const char *dot; @@ -13842,30 +13954,38 @@ if (isalpha (*data)) { rptr = find_reg_glob (data, &gptr, &dptr); if (rptr) { *svalue = (t_svalue)get_rval (rptr, 0); - sprint_val (string + 1, *svalue, 10, string_size - 2, PV_LEFTSIGN); - *string = '"'; - strlcpy (&string[strlen (string)], "\"", string_size - strlen (string)); + sprint_val (string, *svalue, 10, string_size - 1, PV_LEFTSIGN); return TRUE; } - gptr = _sim_get_env_special (data, string + 1, string_size - 2); + gptr = _sim_get_env_special (data, string, string_size - 1); if (gptr) { - *svalue = strtotsv(string + 1, &gptr, 0); - *string = '"'; - strlcpy (&string[strlen (string)], "\"", string_size - strlen (string)); - return (*gptr == '\0'); + *svalue = strtotsv(string, &gptr, 0); + return ((*gptr == '\0') && (*string)); } - else + else { data = ""; + data_size = 0; + } } -*svalue = strtotsv(data, &gptr, 0); -snprintf (string, string_size - 1, "\"%s\"", data); -return (*gptr == '\0'); +string[0] = '\0'; +if ((data[0] == '\'') && (data_size > 1) && (data[data_size - 1] == '\'')) + snprintf (string, string_size - 1, "\"%*.*s\"", (int)(data_size - 2), (int)(data_size - 2), data + 1); +if ((data[0] == '"') && (data_size > 1) && (data[data_size - 1] == '"')) + strlcpy (string, data, string_size); +if (string[0] == '\0') { + *svalue = strtotsv(data, &gptr, 0); + return ((*gptr == '\0') && (*data)); + } +sim_sub_args (string, string_size, sim_exp_argv); +*svalue = strtotsv(string, &gptr, 0); +return ((*gptr == '\0') && (*string)); } /* * Evaluate a given stack1 containing a postfix expression */ -static t_svalue sim_eval_postfix (Stack *stack1, t_stat *stat) { +static t_svalue sim_eval_postfix (Stack *stack1, t_stat *stat) +{ Stack *stack2 = new_Stack(); /* local working stack2 which is holds the numbers operators */ char temp_data[CBUFSIZE]; /* Holds the items popped from the stack2 */ Operator *temp_op; @@ -13942,6 +14062,7 @@ const char *sim_eval_expression (const char *cptr, t_svalue *value, t_bool paren const char *iptr = cptr; Stack *postfix = new_Stack (); /* for the postfix expression */ +sim_debug (SIM_DBG_EXP_EVAL, sim_dflt_dev, "[Evaluate Expression: %s\n", cptr); *value = 0; cptr = sim_into_postfix (postfix, cptr, stat, parens_required); if (*stat != SCPE_OK) { diff --git a/scp.h b/scp.h index c83ded4..8d6fe6e 100644 --- a/scp.h +++ b/scp.h @@ -246,6 +246,7 @@ CONST char *get_glyph_cmd (const char *iptr, char *optr); t_value get_uint (const char *cptr, uint32 radix, t_value max, t_stat *status); CONST char *get_range (DEVICE *dptr, CONST char *cptr, t_addr *lo, t_addr *hi, uint32 rdx, t_addr max, char term); +t_stat sim_set_environment (int32 flag, CONST char *cptr); t_stat sim_decode_quoted_string (const char *iptr, uint8 *optr, uint32 *osize); char *sim_encode_quoted_string (const uint8 *iptr, uint32 size); void fprint_buffer_string (FILE *st, const uint8 *buf, uint32 size); @@ -304,6 +305,7 @@ CONST char *match_ext (CONST char *fnam, const char *ext); t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat set_dev_debug (DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat show_dev_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); +t_stat sim_add_debug_flags (DEVICE *dptr, DEBTAB *debflags); const char *sim_error_text (t_stat stat); t_stat sim_string_to_stat (const char *cptr, t_stat *cond); t_stat sim_cancel_step (void); diff --git a/sim_console.c b/sim_console.c index 8459d98..aa10ba6 100644 --- a/sim_console.c +++ b/sim_console.c @@ -2155,8 +2155,8 @@ t_stat sim_show_cons_speed (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONS { if (sim_con_ldsc.rxbps) { fprintf (st, "Speed = %d", sim_con_ldsc.rxbps); - if (sim_con_ldsc.bpsfactor != TMXR_BPS_UNIT_SCALE) - fprintf (st, "*%.0f", sim_con_ldsc.bpsfactor / TMXR_BPS_UNIT_SCALE); + if (sim_con_ldsc.bpsfactor != 1.0) + fprintf (st, "*%.0f", sim_con_ldsc.bpsfactor); fprintf (st, " bps\n"); } return SCPE_OK; @@ -2799,7 +2799,7 @@ if (!sim_rem_master_mode) { (sim_con_ldsc.serport == 0)) { /* and not serial? */ if (c && sim_con_ldsc.rxbps) /* got something && rate limiting? */ sim_con_ldsc.rxnexttime = /* compute next input time */ - floor (sim_gtime () + ((sim_con_ldsc.rxdelta * sim_timer_inst_per_sec ()) / sim_con_ldsc.bpsfactor)); + floor (sim_gtime () + ((sim_con_ldsc.rxdeltausecs * sim_timer_inst_per_sec ()) / USECS_PER_SECOND)); if (c) sim_debug (DBG_RCV, &sim_con_telnet, "sim_poll_kbd() returning: '%c' (0x%02X)\n", sim_isprint (c & 0xFF) ? c & 0xFF : '.', c); return c; /* in-window */ diff --git a/sim_defs.h b/sim_defs.h index 88cac8d..aeab12f 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -851,6 +851,8 @@ struct DEBTAB { #define SIM_DBG_AIO_QUEUE 0x040000 /* asynch event queue activities */ #define SIM_DBG_EXP_STACK 0x080000 /* expression stack activities */ #define SIM_DBG_EXP_EVAL 0x100000 /* expression evaluation activities */ +#define SIM_DBG_BRK_ACTION 0x200000 /* action activities */ +#define SIM_DBG_DO 0x400000 /* do activities */ /* Open File Reference */ struct FILEREF { diff --git a/sim_fio.c b/sim_fio.c index 1446f22..f1222a1 100644 --- a/sim_fio.c +++ b/sim_fio.c @@ -458,6 +458,16 @@ if (shmem->hMapping != INVALID_HANDLE_VALUE) free (shmem); } +int32 sim_shmem_atomic_add (int32 *p, int32 v) +{ +return InterlockedExchangeAdd ((volatile long *) p,v) + (v); +} + +t_bool sim_shmem_atomic_cas (int32 *ptr, int32 oldv, int32 newv) +{ +return (InterlockedCompareExchange ((LONG volatile *) ptr, newv, oldv) == oldv); +} + #else /* !defined(_WIN32) */ #include int sim_set_fsize (FILE *fptr, t_addr size) @@ -537,6 +547,7 @@ if ((stbuf.st_mode & S_IFIFO)) { return -1; } +#if defined (__linux__) || defined (__APPLE__) #include struct SHMEM { @@ -604,7 +615,52 @@ if (shmem->shm_fd != -1) free (shmem); } +int32 sim_shmem_atomic_add (int32 *p, int32 v) +{ +#if defined (HAVE_GCC_SYNC_BUILTINS) +return __sync_add_and_fetch((int *) p, v); +#else +return *p + v; #endif +} + +t_bool sim_shmem_atomic_cas (int32 *ptr, int32 oldv, int32 newv) +{ +#if defined (HAVE_GCC_SYNC_BUILTINS) +return __sync_bool_compare_and_swap (ptr, oldv, newv); +#else +if (*ptr == oldv) { + *ptr = newv; + return 1; + } +else + return 0; +#endif +} + +#else /* !(defined (__linux__) || defined (__APPLE__)) */ + +t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr) +{ +return SCPE_NOFNC; +} + +void sim_shmem_close (SHMEM *shmem) +{ +} + +int32 sim_shmem_atomic_add (int32 *p, int32 v) +{ +return -1; +} + +t_bool sim_shmem_atomic_cas (int32 *ptr, int32 oldv, int32 newv) +{ +return FALSE; +} + +#endif /* defined (__linux__) || defined (__APPLE__) */ +#endif /* defined (_WIN32) */ #if defined(__VAX) /* diff --git a/sim_fio.h b/sim_fio.h index 7d7feca..5f3b0e7 100644 --- a/sim_fio.h +++ b/sim_fio.h @@ -76,6 +76,8 @@ const char *sim_get_os_error_text (int error); typedef struct SHMEM SHMEM; t_stat sim_shmem_open (const char *name, size_t size, SHMEM **shmem, void **addr); void sim_shmem_close (SHMEM *shmem); +int32 sim_shmem_atomic_add (int32 *ptr, int32 val); +t_bool sim_shmem_atomic_cas (int32 *ptr, int32 oldv, int32 newv); extern t_bool sim_taddr_64; /* t_addr is > 32b and Large File Support available */ extern t_bool sim_toffset_64; /* Large File (>2GB) file I/O support */ diff --git a/sim_timer.c b/sim_timer.c index ae8d77a..27007b6 100644 --- a/sim_timer.c +++ b/sim_timer.c @@ -1037,6 +1037,7 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { sim_stop_unit.action = &sim_timer_stop_svc; SIM_INTERNAL_UNIT.flags = UNIT_IDLE; sim_register_internal_device (&sim_timer_dev); /* Register Clock Assist device */ +sim_register_internal_device (&sim_throttle_dev); /* Register Throttle Device */ sim_throttle_unit.action = &sim_throt_svc; sim_register_clock_unit_tmr (&SIM_INTERNAL_UNIT, SIM_INTERNAL_CLK); sim_idle_enab = FALSE; /* init idle off */ @@ -1477,6 +1478,7 @@ t_bool sim_idle (uint32 tmr, int sin_cyc) { uint32 w_ms, w_idle, act_ms; int32 act_cyc; +static t_bool in_nowait = FALSE; if (rtc_clock_catchup_pending[tmr]) { /* Catchup clock tick pending? */ sim_debug (DBG_CAL, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d) - accelerating pending catch-up tick before idling %s\n", tmr, sin_cyc, sim_uname (sim_clock_unit[tmr])); @@ -1545,9 +1547,12 @@ else w_idle = (w_ms * 1000) / sim_idle_rate_ms; /* 1000 * intervals to wait */ if (w_idle < 500) { /* shorter than 1/2 the interval? */ sim_interval -= sin_cyc; - sim_debug (DBG_IDL, &sim_timer_dev, "no wait\n"); + if (!in_nowait) + sim_debug (DBG_IDL, &sim_timer_dev, "no wait, too short: %d usecs\n", w_idle); + in_nowait = TRUE; return FALSE; } +in_nowait = FALSE; if (sim_clock_queue == QUEUE_LIST_END) sim_debug (DBG_IDL, &sim_timer_dev, "sleeping for %d ms - pending event in %d instructions\n", w_ms, sim_interval); else @@ -1556,10 +1561,7 @@ act_ms = sim_idle_ms_sleep (w_ms); /* wait */ rtc_clock_time_idled[tmr] += act_ms; act_cyc = act_ms * sim_idle_cyc_ms; act_cyc += (sim_idle_cyc_ms * sim_idle_rate_ms) / 2; /* account for half an interval's worth of cycles */ -if (sim_interval > act_cyc) - sim_interval = sim_interval - act_cyc; /* count down sim_interval */ -else - sim_interval = 0; /* or fire immediately */ +sim_interval = sim_interval - act_cyc; /* count down sim_interval to reflect idle period */ if (sim_clock_queue == QUEUE_LIST_END) sim_debug (DBG_IDL, &sim_timer_dev, "slept for %d ms - pending event in %d instructions\n", act_ms, sim_interval); else @@ -1670,7 +1672,6 @@ else { sim_throt_wait = sim_throt_val; } } -sim_register_internal_device (&sim_throttle_dev); /* Register Throttle Device */ if (sim_throt_type == SIM_THROT_SPC) /* Set initial value while correct one is determined */ sim_throt_cps = (int32)((1000.0 * sim_throt_val) / (double)sim_throt_sleep_time); else @@ -1974,7 +1975,7 @@ if ((stat == SCPE_OK) && if (fabs(skew) > fabs(rtc_clock_skew_max[tmr])) rtc_clock_skew_max[tmr] = skew; } - /* First gather the queued events that are scheduled for now */ + /* Gather any queued events which are scheduled for right now */ do { cptr = sim_clock_cosched_queue[tmr]; sim_clock_cosched_queue[tmr] = cptr->next; @@ -1996,11 +1997,11 @@ if ((stat == SCPE_OK) && cptr->cancel = NULL; cptr->time = 0; if (cptr->usecs_remaining) { - sim_debug (DBG_QUE, &sim_timer_dev, " remnant: %.0f - next %s after cosched interval: %d ticks\n", cptr->usecs_remaining, (sptr != QUEUE_LIST_END) ? sim_uname (sptr) : "", sim_cosched_interval[tmr]); + sim_debug (DBG_QUE, &sim_timer_dev, "Rescheduling %s after %.0f usecs %s%s\n", sim_uname (cptr), cptr->usecs_remaining, (sptr != QUEUE_LIST_END) ? "- next: " : "", (sptr != QUEUE_LIST_END) ? sim_uname (sptr) : ""); sim_timer_activate_after (cptr, cptr->usecs_remaining); } else { - sim_debug (DBG_QUE, &sim_timer_dev, " - next %s after cosched interval: %d ticks\n", (sptr != QUEUE_LIST_END) ? sim_uname (sptr) : "", sim_cosched_interval[tmr]); + sim_debug (DBG_QUE, &sim_timer_dev, "Activating %s now %s%s\n", sim_uname (cptr), (sptr != QUEUE_LIST_END) ? "- next: " : "", (sptr != QUEUE_LIST_END) ? sim_uname (sptr) : ""); _sim_activate (cptr, 0); } } @@ -2399,19 +2400,20 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { _sim_activate (sim_clock_unit[tmr], clock_time); } /* Move coscheduled units to the standard event queue */ - accum = 0; + /* scheduled to fire at the same time as the related */ + /* clock unit is to fire with excess time reflected in */ + /* the unit usecs_remaining value */ + accum = sim_cosched_interval[tmr]; while (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) { UNIT *cptr = sim_clock_cosched_queue[tmr]; - double usecs_remaining = cptr->usecs_remaining; - cptr->usecs_remaining = 0; sim_clock_cosched_queue[tmr] = cptr->next; cptr->next = NULL; cptr->cancel = NULL; accum += cptr->time; - sim_debug (DBG_QUE, &sim_timer_dev, "sim_stop_timer_services() - tmr=%d scheduling %s after %d\n", tmr, sim_uname (cptr), clock_time + accum*rtc_currd[tmr]); - _sim_activate (cptr, clock_time + accum*rtc_currd[tmr]); - cptr->usecs_remaining = usecs_remaining; + _sim_activate (cptr, clock_time); + cptr->usecs_remaining = cptr->usecs_remaining + floor(1000000.0 * (accum - ((accum > 0) ? 1 : 0)) * rtc_clock_tick_size[tmr]); + sim_debug (DBG_QUE, &sim_timer_dev, "sim_stop_timer_services() - tmr=%d scheduling %s after %d and %.0f usecs\n", tmr, sim_uname (cptr), clock_time, cptr->usecs_remaining); } sim_cosched_interval[tmr] = 0; } @@ -2501,12 +2503,13 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) } if (sim_is_active (uptr)) /* already active? */ return SCPE_OK; -uptr->usecs_remaining = 0; if (usec_delay <= 0.0) { - sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - invalid usec value\n", + sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - invalid usec value\n", sim_uname(uptr), usec_delay); + uptr->usecs_remaining = 0.0; return SCPE_ARG; } +uptr->usecs_remaining = 0.0; /* * Handle long delays by aligning with the calibrated timer's calibration * activities. Delays which would expire prior to the next calibration @@ -2528,19 +2531,20 @@ if ((sim_calb_tmr != -1) && (rtc_hz[sim_calb_tmr])) { /* Calibrated Timer int32 inst_til_calib = inst_til_tick + ((ticks_til_calib - 1) * rtc_currd[sim_calb_tmr]); uint32 usecs_til_calib = (uint32)ceil(inst_til_calib / inst_per_usec); - if (uptr != &sim_timer_units[sim_calb_tmr]) { /* Not scheduling calibrated timer? */ + if ((uptr != &sim_timer_units[sim_calb_tmr]) && /* Not scheduling calibrated timer */ + (inst_til_tick > 0)) { /* and tick not pending? */ if (inst_delay_d > (double)inst_til_calib) { /* long wait? */ stat = sim_clock_coschedule_tmr (uptr, sim_calb_tmr, ticks_til_calib - 1); uptr->usecs_remaining = (stat == SCPE_OK) ? usec_delay - usecs_til_calib : 0.0; - sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs, inst_til_tick=%d\n", - sim_uname(uptr), usec_delay, sim_calb_tmr, ticks_til_calib, uptr->usecs_remaining, inst_til_tick); + sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs, inst_til_tick=%d, ticks_til_calib=%d\n", + sim_uname(uptr), usec_delay, sim_calb_tmr, ticks_til_calib, uptr->usecs_remaining, inst_til_tick, ticks_til_calib); sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n", sim_uname(uptr), usec_delay, sim_timer_activate_time_usecs (ouptr), sim_timer_activate_time_usecs (uptr)); return stat; } if ((usec_delay > usecs_per_tick) && (ticks_til_calib > 1)) { /* long wait? */ - double usecs_til_tick = inst_til_tick / inst_per_usec; + double usecs_til_tick = floor (inst_til_tick / inst_per_usec); stat = sim_clock_coschedule_tmr (uptr, sim_calb_tmr, 0); uptr->usecs_remaining = (stat == SCPE_OK) ? usec_delay - usecs_til_tick : 0.0; @@ -2617,9 +2621,6 @@ if ((sim_asynch_timer) && } #endif stat = _sim_activate (uptr, inst_delay); /* queue it now */ -uptr->usecs_remaining = ((stat == SCPE_OK) && (0.0 < (usec_delay - ceil(inst_delay / inst_per_usec) ))) ? - usec_delay - floor(inst_delay / inst_per_usec) : - 0.0; sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queue addition at %d - remnant: %.0f\n", sim_uname(uptr), usec_delay, inst_delay, uptr->usecs_remaining); sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n", @@ -3018,7 +3019,7 @@ if (uptr->cancel == &_sim_coschedule_cancel) { accum += cptr->time; if (cptr == uptr) { result = uptr->usecs_remaining + ceil(1000000.0 * ((rtc_currd[tmr] * accum) + sim_activate_time (&sim_timer_units[tmr]) - 1) / sim_timer_inst_per_sec ()); - sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) coscheduled - %.0f usecs, inst_per_sec=%.0f, tmr=%d, ticksize=%d, ticks=%d, inst_til_tick=%d\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), tmr, rtc_currd[tmr], accum, sim_activate_time (&sim_timer_units[tmr]) - 1); + sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) coscheduled - %.0f usecs, inst_per_sec=%.0f, tmr=%d, ticksize=%d, ticks=%d, inst_til_tick=%d, usecs_remaining=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), tmr, rtc_currd[tmr], accum, sim_activate_time (&sim_timer_units[tmr]) - 1, uptr->usecs_remaining); return result; } } @@ -3027,17 +3028,17 @@ if (uptr->cancel == &_sim_coschedule_cancel) { for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { if ((uptr == sim_clock_unit[tmr]) && (uptr->next)) { result = sim_clock_unit[tmr]->usecs_remaining + (1000000.0 * (sim_activate_time (&sim_timer_units[tmr]) - 1)) / sim_timer_inst_per_sec (); - sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ()); + sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f, usecs_remaining=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), uptr->usecs_remaining); return result; } if ((uptr == &sim_timer_units[tmr]) && (uptr->next)){ result = uptr->usecs_remaining + (1000000.0 * (sim_activate_time (uptr) - 1)) / sim_timer_inst_per_sec (); - sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ()); + sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f, usecs_remaining=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), uptr->usecs_remaining); return result; } } result = uptr->usecs_remaining + (1000000.0 * (sim_activate_time (uptr) - 1)) / sim_timer_inst_per_sec (); -sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ()); +sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f, usecs_remaining=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), uptr->usecs_remaining); return result; /* Not found. */ } diff --git a/sim_tmxr.c b/sim_tmxr.c index 79549ef..f9cedeb 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -474,7 +474,7 @@ if (!lp->txbfd || lp->notelnet) /* if not buffered telne lp->txbpr = lp->txbpi = lp->txcnt = lp->txpcnt = 0; /* init transmit indexes */ lp->txdrp = lp->txstall = 0; tmxr_set_get_modem_bits (lp, 0, 0, NULL); -if ((!lp->mp->buffered) && (!lp->txbfd)) { +if (lp->mp && (!lp->mp->buffered) && (!lp->txbfd)) { lp->txbfd = 0; lp->txbsz = TMXR_MAXBUF; lp->txb = (char *)realloc (lp->txb, lp->txbsz); @@ -735,7 +735,7 @@ else { } } if ((written > 0) && (lp->txbps) && (sim_is_running)) - lp->txnexttime = floor (sim_gtime () + ((written * lp->txdelta * sim_timer_inst_per_sec ()) / lp->bpsfactor)); + lp->txnexttime = floor (sim_gtime () + ((written * lp->txdeltausecs * sim_timer_inst_per_sec ()) / USECS_PER_SECOND)); return written; } @@ -1784,9 +1784,9 @@ if (lp->rxbpi == lp->rxbpr) /* empty? zero ptrs */ lp->rxbpi = lp->rxbpr = 0; if (val) { /* Got something? */ if (lp->rxbps) - lp->rxnexttime = floor (sim_gtime () + ((lp->rxdelta * sim_timer_inst_per_sec ()) / lp->bpsfactor)); + lp->rxnexttime = floor (sim_gtime () + ((lp->rxdeltausecs * sim_timer_inst_per_sec ()) / USECS_PER_SECOND)); else - lp->rxnexttime = floor (sim_gtime () + ((lp->mp->uptr->wait * sim_timer_inst_per_sec ()) / TMXR_BPS_UNIT_SCALE)); + lp->rxnexttime = floor (sim_gtime () + ((lp->mp->uptr->wait * sim_timer_inst_per_sec ()) / USECS_PER_SECOND)); } tmxr_debug_return(lp, val); return val; @@ -2173,8 +2173,8 @@ if ((lp->txbfd && !lp->notelnet) || (TXBUF_AVAIL(lp) > 1)) {/* room for char (+ sim_exp_check (&lp->expect, chr); /* process expect rules as needed */ if (!sim_is_running) { /* attach message or other non simulation time message? */ tmxr_send_buffered_data (lp); /* put data on wire */ - sim_os_ms_sleep(((lp->txbps) && (lp->txdelta > 1000)) ? /* rate limiting output slower than 1000 cps */ - (lp->txdelta - 1000) / 1000 : + sim_os_ms_sleep(((lp->txbps) && (lp->txdeltausecs > 1000)) ? /* rate limiting output slower than 1000 cps */ + (lp->txdeltausecs - 1000) / 1000 : 10); /* wait an approximate character delay */ } return SCPE_OK; /* char sent */ @@ -2267,10 +2267,8 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ #endif if ((lp->xmte == 0) && ((lp->txbps == 0) || - (lp->txnexttime <= sim_gtime ()))) { + (lp->txnexttime <= sim_gtime ()))) lp->xmte = 1; /* enable line transmit */ - lp->txnexttime = 0.0; - } } } /* end for */ } @@ -2479,24 +2477,21 @@ if (*cptr == '*') { if (r != SCPE_OK) return r; - lp->bpsfactor = TMXR_BPS_UNIT_SCALE * bpsfactor; + lp->bpsfactor = bpsfactor; } if ((lp->serport) && (lp->bpsfactor != 0.0)) - lp->bpsfactor = TMXR_BPS_UNIT_SCALE; -lp->rxdelta = _tmln_speed_delta (speed); + lp->bpsfactor = 1.0; +lp->rxdeltausecs = (uint32)(_tmln_speed_delta (speed) / lp->bpsfactor); lp->rxnexttime = 0.0; uptr = lp->uptr; if ((!uptr) && (lp->mp)) uptr = lp->mp->uptr; if (uptr) - uptr->wait = lp->rxdelta; -if (lp->bpsfactor == 0.0) - lp->bpsfactor = TMXR_BPS_UNIT_SCALE; + uptr->wait = lp->rxdeltausecs; lp->txbps = lp->rxbps; -lp->txdelta = lp->rxdelta; -lp->txnexttime = lp->rxnexttime; +lp->txdeltausecs = lp->rxdeltausecs; if (lp->o_uptr) - lp->o_uptr->wait = lp->txdelta; + lp->o_uptr->wait = lp->txdeltausecs; return SCPE_OK; } @@ -2534,7 +2529,7 @@ for (i = 0; i < mp->lines; i++) { /* initialize lines */ lp->mp = mp; /* set the back pointer */ lp->modem_control = mp->modem_control; if (lp->bpsfactor == 0.0) - lp->bpsfactor = TMXR_BPS_UNIT_SCALE; + lp->bpsfactor = 1.0; } mp->ring_sock = INVALID_SOCKET; free (mp->ring_ipad); @@ -2658,7 +2653,9 @@ while (*tptr) { if ((NULL == cptr) || ('\0' == *cptr) || (_tmln_speed_delta (cptr) < 0)) return sim_messagef (SCPE_ARG, "Invalid Speed Specifier: %s\n", (cptr ? cptr : "")); - if (mp->port_speed_control && (_tmln_speed_delta (cptr) > 0) && (!(sim_switches & SIM_SW_REST))) + if (mp->port_speed_control && + ((_tmln_speed_delta (cptr) > 0) || (*cptr != '*')) && + (!(sim_switches & SIM_SW_REST))) return sim_messagef (SCPE_ARG, "%s simulator programmatically sets %sport speed\n", sim_name, dev_name); strlcpy (speed, cptr, sizeof(speed)); continue; @@ -3802,6 +3799,27 @@ else return SCPE_OK; } +static DEBTAB tmxr_debug[] = { + {"XMT", TMXR_DBG_XMT, "Transmit Data"}, + {"RCV", TMXR_DBG_RCV, "Received Data"}, + {"RET", TMXR_DBG_RET, "Returned Received Data"}, + {"MODEM", TMXR_DBG_MDM, "Modem Signals"}, + {"CONNECT", TMXR_DBG_CON, "Connection Activities"}, + {"ASYNC", TMXR_DBG_ASY, "Asynchronous Activities"}, + {"TRACE", TMXR_DBG_TRC, "trace routine calls"}, + {"XMTPKT", TMXR_DBG_PXMT, "Transmit Packet Data"}, + {"RCVPKT", TMXR_DBG_PRCV, "Received Packet Data"}, + {"EXPECT", TMXR_DBG_EXP, "Expect Activities"}, + {"SEND", TMXR_DBG_SEND, "Send Activities"}, + {0} +}; + +t_stat tmxr_add_debug (DEVICE *dptr) +{ +if (!(dptr->flags & DEV_MUX)) + return SCPE_OK; +return sim_add_debug_flags (dptr, tmxr_debug); +} /* Attach unit to master socket */ @@ -3917,8 +3935,8 @@ else { if (mp->lines == 1) { if (mp->ldsc->rxbps) { fprintf(st, ", Speed=%d", mp->ldsc->rxbps); - if (mp->ldsc->bpsfactor != TMXR_BPS_UNIT_SCALE) - fprintf(st, "*%.0f", mp->ldsc->bpsfactor / TMXR_BPS_UNIT_SCALE); + if (mp->ldsc->bpsfactor != 1.0) + fprintf(st, "*%.0f", mp->ldsc->bpsfactor); fprintf(st, " bps"); } } @@ -3946,13 +3964,13 @@ else { fprintf(st, ", Loopback"); if (lp->rxbps) { fprintf(st, ", Speed=%d", lp->rxbps); - if (lp->bpsfactor != TMXR_BPS_UNIT_SCALE) - fprintf(st, "*%.0f", lp->bpsfactor / TMXR_BPS_UNIT_SCALE); + if (lp->bpsfactor != 1.0) + fprintf(st, "*%.0f", lp->bpsfactor); fprintf(st, " bps"); } else { - if (lp->bpsfactor != TMXR_BPS_UNIT_SCALE) - fprintf(st, ", Speed=*%.0f bps", lp->bpsfactor / TMXR_BPS_UNIT_SCALE); + if (lp->bpsfactor != 1.0) + fprintf(st, ", Speed=*%.0f bps", lp->bpsfactor); } fprintf (st, "\n"); } @@ -4084,20 +4102,20 @@ for (i=0; ilines; i++) { if (lp->rxnexttime > sim_gtime_now) due = (int32)(lp->rxnexttime - sim_gtime_now); else - due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */ + due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */ sooner = MIN(sooner, due); } - if ((uptr == lp->o_uptr) && /* output completion unit? */ - (lp->txbps) && /* while rate limiting */ - (lp->txnexttime)) { /* with queued output data */ + if ((lp->conn) && /* Connected? */ + (uptr == lp->o_uptr) && /* output completion unit? */ + (lp->txbps)) { /* while rate limiting */ + if ((tmxr_tqln(lp)) && /* pending output data? */ + (lp->txnexttime < sim_gtime_now)) + tmxr_send_buffered_data (lp);/* flush it */ if (lp->txnexttime > sim_gtime_now) due = (int32)(lp->txnexttime - sim_gtime_now); else - due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */ - if (i == 0) - sooner = due; - else - sooner = MIN(sooner, due); + due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */ + sooner = MIN(sooner, due); } } return sooner; @@ -4113,18 +4131,18 @@ if (!(uptr->dynflags & UNIT_TM_POLL)) return _sim_activate (uptr, interval); /* Handle the non mux case */ sooner = _tmxr_activate_delay (uptr, interval); if (sooner != interval) { - sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions rather than %d instructions\n", sim_uname (uptr), sooner, interval); + sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s after %d instructions rather than %d instructions\n", sim_uname (uptr), sooner, interval); return _sim_activate (uptr, sooner); /* Handle the busy case */ } #if defined(SIM_ASYNCH_MUX) if (!sim_asynch_enabled) { - sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions\n", sim_uname (uptr), interval); + sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s after %d instructions\n", sim_uname (uptr), interval); return _sim_activate (uptr, interval); } -sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s asynchronously instead of %d instructions\n", sim_uname (uptr), interval); +sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s asynchronously instead of %d instructions\n", sim_uname (uptr), interval); return SCPE_OK; #else -sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions\n", sim_uname (uptr), interval); +sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s after %d instructions\n", sim_uname (uptr), interval); return _sim_activate (uptr, interval); #endif } @@ -4147,21 +4165,21 @@ if (!(uptr->dynflags & UNIT_TM_POLL)) sooner = _tmxr_activate_delay (uptr, 0x7FFFFFFF); if (sooner != 0x7FFFFFFF) { if (sooner < 0) { - sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s for %u usecs produced overflow interval %d instructions, sceduling for %d instructions\n", sim_uname (uptr), usecs_walltime, sooner, 0x7FFFFFFF); + sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s for %u usecs produced overflow interval %d instructions, sceduling for %d instructions\n", sim_uname (uptr), usecs_walltime, sooner, 0x7FFFFFFF); sooner = _tmxr_activate_delay (uptr, 0x7FFFFFFF); /* Breakpoint here on unexpected value */ } - sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions rather than %u usecs\n", sim_uname (uptr), sooner, usecs_walltime); + sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s after %d instructions rather than %u usecs\n", sim_uname (uptr), sooner, usecs_walltime); return _sim_activate (uptr, sooner); /* Handle the busy case directly */ } #if defined(SIM_ASYNCH_MUX) if (!sim_asynch_enabled) { - sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %u usecs\n", sim_uname (uptr), usecs_walltime); + sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s after %u usecs\n", sim_uname (uptr), usecs_walltime); return _sim_activate_after (uptr, (double)usecs_walltime); } -sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s asynchronously instead of %u usecs\n", sim_uname (uptr), usecs_walltime); +sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s asynchronously instead of %u usecs\n", sim_uname (uptr), usecs_walltime); return SCPE_OK; #else -sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %u usecs\n", sim_uname (uptr), usecs_walltime); +sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s after %.0f usecs\n", sim_uname (uptr), (double)usecs_walltime); return _sim_activate_after (uptr, (double)usecs_walltime); #endif } @@ -4197,17 +4215,17 @@ if (!(uptr->dynflags & UNIT_TM_POLL)) return sim_clock_coschedule_tmr (uptr, tmr, ticks); /* Handle the non mux case */ sooner = _tmxr_activate_delay (uptr, interval); if (sooner != interval) { - sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "scheduling %s after %d instructions rather than %d ticks (%d instructions)\n", sim_uname (uptr), sooner, ticks, interval); + sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_clock_coschedule_tmr(tmr=%d) - scheduling %s after %d instructions rather than %d ticks (%d instructions)\n", tmr, sim_uname (uptr), sooner, ticks, interval); return _sim_activate (uptr, sooner); /* Handle the busy case directly */ } #if defined(SIM_ASYNCH_MUX) if (!sim_asynch_enabled) { - sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "coscheduling %s after interval %d ticks\n", sim_uname (uptr), ticks); + sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_clock_coschedule_tmr(tmr=%d) - coscheduling %s after interval %d ticks\n", tmr, sim_uname (uptr), ticks); return sim_clock_coschedule (uptr, tmr, ticks); } return SCPE_OK; #else -sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "coscheduling %s after interval %d ticks\n", sim_uname (uptr), ticks); +sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_clock_coschedule_tmr(tmr=%d) - coscheduling %s after interval %d ticks\n", tmr, sim_uname (uptr), ticks); return sim_clock_coschedule_tmr (uptr, tmr, ticks); #endif } @@ -4653,8 +4671,8 @@ else { fprintf (st, " speed = %u", lp->rxbps); else fprintf (st, " speed = %u/%u", lp->rxbps, lp->txbps); - if (lp->bpsfactor / TMXR_BPS_UNIT_SCALE > 1.0) - fprintf (st, "*%.0f", lp->bpsfactor / TMXR_BPS_UNIT_SCALE); + if (lp->bpsfactor > 1.0) + fprintf (st, "*%.0f", lp->bpsfactor); fprintf (st, " bps\n"); } } diff --git a/sim_tmxr.h b/sim_tmxr.h index 4019e51..16953ee 100644 --- a/sim_tmxr.h +++ b/sim_tmxr.h @@ -170,11 +170,11 @@ struct tmln { uint32 rxpboffset; /* rcv packet buffer offset */ uint32 rxbps; /* rcv bps speed (0 - unlimited) */ double bpsfactor; /* receive speed factor (scaled to usecs) */ -#define TMXR_BPS_UNIT_SCALE 1000000.0 - uint32 rxdelta; /* rcv inter character min time (usecs) */ +#define USECS_PER_SECOND 1000000.0 + uint32 rxdeltausecs; /* rcv inter character min time (usecs) */ double rxnexttime; /* min time for next receive character */ uint32 txbps; /* xmt bps speed (0 - unlimited) */ - uint32 txdelta; /* xmt inter character min time (usecs) */ + uint32 txdeltausecs; /* xmt inter character min time (usecs) */ double txnexttime; /* min time for next transmit character */ uint8 *txpb; /* xmt packet buffer */ uint32 txpbsize; /* xmt packet buffer size */ @@ -309,6 +309,7 @@ void _tmxr_debug (uint32 dbits, TMLN *lp, const char *msg, char *buf, int bufsiz #define tmxr_debug_trace_line(lp, msg) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && (TMXR_DBG_TRC & (lp)->mp->dptr->dctrl)) sim_debug (TMXR_DBG_TRC, (lp)->mp->dptr, "Ln%d:%s\n", (int)((lp)-(lp)->mp->ldsc), (msg)); } while (0) #define tmxr_debug_connect(mp, msg) do {if (sim_deb && (mp)->dptr && (TMXR_DBG_CON & (mp)->dptr->dctrl)) sim_debug (TMXR_DBG_CON, mp->dptr, "%s\n", (msg)); } while (0) #define tmxr_debug_connect_line(lp, msg) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && (TMXR_DBG_CON & (lp)->mp->dptr->dctrl)) sim_debug (TMXR_DBG_CON, (lp)->mp->dptr, "Ln%d:%s\n", (int)((lp)-(lp)->mp->ldsc), (msg)); } while (0) +t_stat tmxr_add_debug (DEVICE *dptr); #if defined(SIM_ASYNCH_MUX) && !defined(SIM_ASYNCH_IO) #undef SIM_ASYNCH_MUX