Merge branch 'master' into Extra-VAXen

Conflicts:
	makefile
This commit is contained in:
Mark Pizzolato 2011-11-10 09:04:42 -08:00
commit 3e10dfbd95
25 changed files with 2029 additions and 1269 deletions

View file

@ -5,6 +5,9 @@ Theory of operation.
Features.
- Optional Use. Build with or without SIM_ASYNCH_IO defined and
simulators will still build and perform correctly when run.
Additionmally, a simulator built with SIM_ASYNCH_IO defined can
dynamically disable and reenable asynchronous operation with
the scp commands SET NOASYNCH and SET ASYNCH respectively.
- Consistent Save/Restore state. The state of a simulator saved
on a simulator with (or without) Asynch support can be restored
on any simulator of the same version with or without Asynch

View file

@ -43,9 +43,9 @@ bridge, or route TAP devices for you.
Integrated Universal TUN/TAP support can be used for host<->simulator network
traffic (on the platforms where it is available) by using the SIMH command:
"attach xq tap:tapN" (i.e. attach xq tap:tap0). Platforms that this has been
tested on include: Linux, FreeBSD, OpenBSD, NetBSD. Each of these platforms
has some way to create a tap pseudo device and then bridge it with a physical
network interface.
tested on include: Linux, FreeBSD, OpenBSD, NetBSD and OSX. Each of these
platforms has some way to create a tap pseudo device (and possibly then to
bridge it with a physical network interface).
The following steps were performed to get a working SIMH vax simulator
sharing a physical NIC and allowing Host<->SIMH vax communications:
@ -117,6 +117,53 @@ NetBSD (NetBSD 5.0.2)
# Run simulator and "attach xq tap:tap0"
OSX (Snow Leopard)
OSX Does NOT have native support for tun/tap interfaces. It also does not have native
support for bridging.
Mattias Nissler has created tun/tap functionality available at http://tuntaposx,sourceforge.net/
We'll punt on bridging for the sake of this example and move on to use a basic tap
based internal network so a host and guest can communicate directly.
Download the install package from:
http://sourceforge.net/projects/tuntaposx/files/tuntap/20090913/tuntap_20090913.tar.gz
Expand the tarball to a directory.
Invoke the package installer tuntap_20090913.pkg
Click through the various prompts accepting things and eventually installing the package.
# Build and Run simulator and:
sim> attach xq tap:tap0
sim> ! ifconfig tap0 192.168.6.1 netmask 255.255.255.0
Simulated system uses IP address 192.168.6.2 and host uses 192.167.6.1
and things work.
You must run as root for this to work.
-------------------------------------------------------------------------------
An alternative to direct pcap and tun/tap networking on *nix environments is
VDE (Virtual Distributed Ethernet).
Note 1: Using vde based networking is likely more flexible, but it isn't
nearly as efficient. Host OS overhead will always be higher when
vde networking is used as compared to native pcap and/or tun/tap
networking.
Note 2: Root access will likely be needed to configure or start the vde
environment prior to starting a simulator which may use it.
Note 3: Simulators running using VDE networking can run without root
privilege.
Linux (Ubuntu 10.04):
apt-get install libvdeplug-dev
apt-get install vde2
vde_switch -s /tmp/switch1 -tap tap0 -m 666
ifconfig tap0 192.168.6.1 netmask 255.255.255.0 up
# Build and Run simulator and:
sim> attach xq vde:/tmp/switch1 #simulator uses IP address 192.168.6.2
-------------------------------------------------------------------------------
Windows notes:
@ -134,6 +181,11 @@ Windows notes:
Building on Windows:
Building with MinGW can use the provided makefile following the instructions
below. Alternatively, you can use the free Visual C++ Express 2008 or 2010
interactive development environments. Read the file
".\Visual Studio Projects\0ReadMe_Projects.txt" for details.
1. Install WinPCAP 4.x runtime and the WinPCAP Developer's kit.
2. Put the required .h files (bittypes,devioctl,ip6_misc,pcap,pcap-stdinc
@ -159,8 +211,11 @@ Linux, {Free|Net|Open}BSD, OS/X, and Un*x notes:
----- WARNING ----- WARNING ----- WARNING ----- WARNING ----- WARNING -----
Sim_Ether has been reworked to be more universal; because of this, you will
need to get a version of libpcap that is 0.9 or greater. This can be
downloaded from www.tcpdump.org - see the comments at the top of Sim_ether.c
need to get a version of libpcap that is 0.9 or greater. All current Linux
distributions provide a libpcap-dev package which has the needed version
of libpcap and the required components to build applications using it.
If you are running an older Linux OS, you can download and build the required
library from www.tcpdump.org - see the comments at the top of Sim_ether.c
for details.
----- WARNING ----- WARNING ----- WARNING ----- WARNING ----- WARNING -----
@ -187,11 +242,13 @@ for details.
will be welcomed.
2. If you want to use TAP devices, and any surrounding system network/bridge
setup must be done before running SIMH.
setup must be done before running SIMH. However, once that is done
(possibly at system boot time), using the TAP devices can be done without
root privileges.
Building on Linux, {Free|Net|Open}BSD, OS/X, Un*x:
1. Get/make/install the libpcap package for your operating system. Sources:
1. Get/make/install the libpcap-dev package for your operating system. Sources:
All : http://www.tcpdump.org/
Older versions of libpcap can be found, for various systems, at:
Linux : search for your variant on http://rpmfind.net
@ -214,7 +271,7 @@ Building on Linux, {Free|Net|Open}BSD, OS/X, Un*x:
-------------------------------------------------------------------------------
OpenVMS Alpha notes:
OpenVMS Alpha and OpenVMS Integrety (IA64) notes:
1. Ethernet support will only work on Alpha VMS 7.3-1 or later, which is
when required VCI promiscuous mode support was added. Hobbyists can
get the required version of VMS from the OpenVMS Alpha Hobbyist Kit 3.0.
@ -247,10 +304,10 @@ OpenVMS Alpha notes:
adapter prior trying to connect with SIMH, or the host may crash.
The execlet is not written to create an I/O structure for the device.
Building on OpenVMS Alpha:
Building on OpenVMS Alpha and OpenVMS Integrety (IA64):
The current descrip.mms file will build simulators capable of using
Ethernet support with them automatically. These currently are: VAX,
PDP11, and PDP10. The descrip.mms driven builds will also build the
VAX780, and PDP11. The descrip.mms driven builds will also build the
pcap library and build and install the VCI execlet.
1. Fetch the VMS-PCAP zip file from:
@ -321,6 +378,17 @@ Dave
Change Log
===============================================================================
30-Oct-11 MP Added support for vde (Virtual Distributed Ethernet) networking
29-Oct-11 MP Added support for integrated Tap networking interfaces on OSX
17-Aug-11 RMS Fix from Sergey Oboguev relating to XU and XQ Auto Config and
vector assignments
12-Aug-11 MP Cleaned up payload length determination
Fixed race condition detecting reflections when threaded
reading and writing is enabled
07-Jul-11 MB VMS Pcap (from Mike Burke)
- Fixed Alpha issues
- Added OpenVMS Integrety support
20-Apr-11 MP Fixed save/restore behavior
12-Jan-11 DTH Added SHOW XU FILTERS modifier
11-Jan-11 DTH Corrected DEUNA/DELUA SELFTEST command, enabling use by
VMS 3.7, VMS 4.7, and Ultrix 1.1

View file

@ -469,7 +469,7 @@ den = GET_DEN (tutc); /* get density */
uptr = tu_dev.units + drv; /* get unit */
if (DEBUG_PRS (tu_dev)) {
fprintf (sim_deb, ">>TU%d STRT: fnc=%s, fc=%06o, fs=%06o, er=%06o, pos=",
drv, tu_fname[fnc], tufc, tufs, tuer, uptr->pos);
drv, tu_fname[fnc], tufc, tufs, tuer);
fprint_val (sim_deb, uptr->pos, 10, T_ADDR_W, PV_LEFT);
fprintf (sim_deb, "\n");
}

View file

@ -2584,6 +2584,7 @@ t_stat xq_attach(UNIT* uptr, char* cptr)
if (xq->var->poll == 0) {
status = eth_set_async(xq->var->etherface, xq->var->coalesce_latency_ticks);
if (status != SCPE_OK) {
eth_close(xq->var->etherface);
free(tptr);
free(xq->var->etherface);
xq->var->etherface = NULL;

View file

@ -87,7 +87,7 @@ extern int32 int_req[IPL_HLVL];
#define XQ_QUE_MAX 500 /* read queue size in packets */
#define XQ_FILTER_MAX 14 /* number of filters allowed */
#if defined SIM_ASYNCH_IO
#if defined(SIM_ASYNCH_IO) && defined(USE_READER_THREAD)
#define XQ_SERVICE_INTERVAL 0 /* polling interval - No Polling with Asynch I/O */
#else
#define XQ_SERVICE_INTERVAL 100 /* polling interval - X per second */

View file

@ -1,6 +1,6 @@
/* pdp8_fpp.c: PDP-8 floating point processor (FPP8A)
Copyright (c) 2007-2011, Robert M Supnik
Copyright (c) 2007-2010, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* pdp8_sys.c: PDP-8 simulator interface
Copyright (c) 1993-2011, Robert M Supnik
Copyright (c) 1993-2009, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -24,7 +24,7 @@
in this Software without prior written authorization from Robert M Supnik.
24-Mar-09 RMS Added link to FPP
24-Jun-08 RMS Fixed bug in new rim loader (Don North)
24-Jun-08 RMS Fixed bug in new rim loader (found by Don North)
24-May-08 RMS Fixed signed/unsigned declaration inconsistency
03-Sep-07 RMS Added FPP8 support
Rewrote rim and binary loaders

View file

@ -28,6 +28,7 @@
td TD8E/TU56 DECtape
23-Mar-11 RMS Fixed SDLC to clear AC (from Dave Gesswein)
23-Jun-06 RMS Fixed switch conflict in ATTACH
16-Aug-05 RMS Fixed C++ declaration and cast problems
09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR
@ -302,6 +303,7 @@ switch (pulse) {
if (td_newsa (td_cmd)) /* new command */
return AC | (IORETURN (td_stopoffr, STOP_DTOFF) << IOT_V_REASON);
}
AC = 0;
break;
case 05: /* SDLD */

View file

@ -30,11 +30,34 @@
todr TODR clock
tmr interval timer
28-Sep-11 MP Generalized setting TODR for all OSes.
Unbound the TODR value from the 100hz clock tick
interrupt. TODR now behaves like the original
battery backed-up clock and runs with the wall
clock, not the simulated instruction clock.
Two operational modes are available:
- Default VMS mode, which is similar to the previous
behavior in that without initializing the TODR it
would default to the value VMS would set it to if
VMS knew the correct time. This would be correct
almost all the time unless a VMS disk hadn't been
booted from for more than a year. This mode
produces strange time results for non VMS OSes on
each system boot.
- OS Agnostic mode. This mode behaves precisely like
the VAX780 TODR and works correctly for all OSes.
This mode is enabled by attaching the TODR to a
battery backup state file for the TOY clock
(i.e. sim> attach TODR TOY_CLOCK). When operating
in OS Agnostic mode, the TODR will initially start
counting from 0 and be adjusted differently when an
OS specifically writes to the TODR. VMS will prompt
to set the time on each boot unless the SYSGEN
parameter TIMEPROMPTWAIT is set to 0.
29-Mar-2011 MB First Version
*/
#include "vax_defs.h"
#include <time.h>
/* Terminal definitions */
@ -159,6 +182,11 @@ int32 clk_tps = 100; /* ticks/second */
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
int32 tmr_poll = CLK_DELAY; /* pgm timer poll */
int32 todr_reg = 0; /* TODR register */
struct todr_battery_info {
uint32 toy_gmtbase; /* GMT base of set value */
uint32 toy_gmtbasemsec; /* The milliseconds of the set value */
};
typedef struct todr_battery_info TOY;
int32 td_swait = 100; /* seek, per block */
int32 td_cwait = 150; /* command time */
@ -187,6 +215,8 @@ t_stat tmr_svc (UNIT *uptr);
t_stat tti_reset (DEVICE *dptr);
t_stat tto_reset (DEVICE *dptr);
t_stat clk_reset (DEVICE *dptr);
t_stat clk_attach (UNIT *uptr, char *cptr);
t_stat clk_detach (UNIT *uptr);
t_stat tmr_reset (DEVICE *dptr);
t_stat td_svc (UNIT *uptr);
t_stat td_reset (DEVICE *dptr);
@ -269,7 +299,7 @@ DEVICE tto_dev = {
/* TODR and TMR data structures */
UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 0), CLK_DELAY }; /* 100Hz */
UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE+UNIT_FIX, sizeof(TOY)), CLK_DELAY };/* 100Hz */
REG clk_reg[] = {
{ DRDATA (TODR, todr_reg, 32), PV_LEFT },
@ -280,9 +310,9 @@ REG clk_reg[] = {
DEVICE clk_dev = {
"TODR", &clk_unit, clk_reg, NULL,
1, 0, 0, 0, 0, 0,
1, 0, 8, 1, 0, 0,
NULL, NULL, &clk_reset,
NULL, NULL, NULL,
NULL, &clk_attach, &clk_detach,
NULL, 0
};
@ -763,7 +793,6 @@ t_stat clk_svc (UNIT *uptr)
tmr_poll = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
sim_activate (&clk_unit, tmr_poll); /* reactivate unit */
tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */
todr_reg = todr_reg + 1; /* incr TODR */
if ((tmr_iccs & TMR_CSR_RUN) && tmr_use_100hz) /* timer on, std intvl? */
tmr_incr (TMR_INC); /* do timer service */
return SCPE_OK;
@ -836,9 +865,44 @@ t_stat clk_reset (DEVICE *dptr)
tmr_poll = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init 100Hz timer */
sim_activate_abs (&clk_unit, tmr_poll); /* activate 100Hz unit */
tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */
if (clk_unit.filebuf == NULL) { /* make sure the TODR is initialized */
clk_unit.filebuf = calloc(sizeof(TOY), 1);
if (clk_unit.filebuf == NULL)
return SCPE_MEM;
todr_resync ();
}
return SCPE_OK;
}
/* CLK attach */
t_stat clk_attach (UNIT *uptr, char *cptr)
{
t_stat r;
uptr->flags = uptr->flags | (UNIT_ATTABLE | UNIT_BUFABLE);
memset (uptr->filebuf, 0, (size_t)uptr->capac);
r = attach_unit (uptr, cptr);
if (r != SCPE_OK)
uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);
else
uptr->hwmark = (uint32) uptr->capac;
return r;
}
/* CLK detach */
t_stat clk_detach (UNIT *uptr)
{
t_stat r;
r = detach_unit (uptr);
if ((uptr->flags & UNIT_ATT) == 0)
uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);
return r;
}
/* Interval timer reset */
t_stat tmr_reset (DEVICE *dptr)
@ -857,32 +921,58 @@ return SCPE_OK;
int32 todr_rd (void)
{
return todr_reg;
TOY *toy = (TOY *)clk_unit.filebuf;
struct timespec base, now, val;
clock_gettime(CLOCK_REALTIME, &now); /* get curr time */
base.tv_sec = toy->toy_gmtbase;
base.tv_nsec = toy->toy_gmtbasemsec * 1000000;
sim_timespec_diff (&val, &now, &base);
return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */
}
void todr_wr (int32 data)
{
todr_reg = data;
return;
TOY *toy = (TOY *)clk_unit.filebuf;
struct timespec now, val, base;
/* Save the GMT time when set value was 0 to record the base for future
read operations in "battery backed-up" state */
if (-1 == clock_gettime(CLOCK_REALTIME, &now)) /* get curr time */
return; /* error? */
val.tv_sec = ((uint32)data) / 100;
val.tv_nsec = (((uint32)data) % 100) * 10000000;
sim_timespec_diff (&base, &now, &val); /* base = now - data */
toy->toy_gmtbase = base.tv_sec;
toy->toy_gmtbasemsec = base.tv_nsec/1000000;
}
t_stat todr_resync (void)
{
uint32 base;
time_t curr;
struct tm *ctm;
TOY *toy = (TOY *)clk_unit.filebuf;
curr = time (NULL); /* get curr time */
if (curr == (time_t) -1) /* error? */
if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX780 */
if (!toy->toy_gmtbase) /* Never set? */
todr_wr (0); /* Start ticking from 0 */
}
else { /* Not-Attached means */
uint32 base; /* behave like simh VMS default */
time_t curr;
struct tm *ctm;
curr = time (NULL); /* get curr time */
if (curr == (time_t) -1) /* error? */
return SCPE_NOFNC;
ctm = localtime (&curr); /* decompose */
if (ctm == NULL) /* error? */
ctm = localtime (&curr); /* decompose */
if (ctm == NULL) /* error? */
return SCPE_NOFNC;
base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */
base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */
ctm->tm_hour) * 60) +
ctm->tm_min) * 60) +
ctm->tm_sec;
todr_reg = (base * 100) + 0x10000000; /* cvt to VAX form */
todr_wr ((base * 100) + 0x10000000); /* use VMS form */
}
return SCPE_OK;
}

View file

@ -29,6 +29,30 @@
todr TODR clock
tmr interval timer
28-Sep-11 MP Generalized setting TODR for all OSes.
Unbound the TODR value from the 100hz clock tick
interrupt. TODR now behaves like the original
battery backed-up clock and runs with the wall
clock, not the simulated instruction clock.
Two operational modes are available:
- Default VMS mode, which is similar to the previous
behavior in that without initializing the TODR it
would default to the value VMS would set it to if
VMS knew the correct time. This would be correct
almost all the time unless a VMS disk hadn't been
booted from for more than a year. This mode
produces strange time results for non VMS OSes on
each system boot.
- OS Agnostic mode. This mode behaves precisely like
the VAX780 TODR and works correctly for all OSes.
This mode is enabled by attaching the TODR to a
battery backup state file for the TOY clock
(i.e. sim> attach TODR TOY_CLOCK). When operating
in OS Agnostic mode, the TODR will initially start
counting from 0 and be adjusted differently when an
OS specifically writes to the TODR. VMS will prompt
to set the time on each boot unless the SYSGEN
parameter TIMEPROMPTWAIT is set to 0.
21-Mar-11 RMS Added reboot capability
17-Aug-08 RMS Resync TODR on any clock reset
18-Jun-07 RMS Added UNIT_IDLE flag to console input, clock
@ -56,7 +80,7 @@
*/
#include "vax_defs.h"
#include <time.h>
/* Terminal definitions */
@ -171,6 +195,11 @@ int32 clk_tps = 100; /* ticks/second */
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
int32 tmr_poll = CLK_DELAY; /* pgm timer poll */
int32 todr_reg = 0; /* TODR register */
struct todr_battery_info {
uint32 toy_gmtbase; /* GMT base of set value */
uint32 toy_gmtbasemsec; /* The milliseconds of the set value */
};
typedef struct todr_battery_info TOY;
int32 fl_fnc = 0; /* function */
int32 fl_esr = 0; /* error status */
@ -197,6 +226,8 @@ t_stat tmr_svc (UNIT *uptr);
t_stat tti_reset (DEVICE *dptr);
t_stat tto_reset (DEVICE *dptr);
t_stat clk_reset (DEVICE *dptr);
t_stat clk_attach (UNIT *uptr, char *cptr);
t_stat clk_detach (UNIT *uptr);
t_stat tmr_reset (DEVICE *dptr);
t_stat fl_svc (UNIT *uptr);
t_stat fl_reset (DEVICE *dptr);
@ -281,7 +312,7 @@ DEVICE tto_dev = {
/* TODR and TMR data structures */
UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 0), CLK_DELAY }; /* 100Hz */
UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE+UNIT_FIX, sizeof(TOY)), CLK_DELAY };/* 100Hz */
REG clk_reg[] = {
{ DRDATA (TODR, todr_reg, 32), PV_LEFT },
@ -296,9 +327,9 @@ REG clk_reg[] = {
DEVICE clk_dev = {
"TODR", &clk_unit, clk_reg, NULL,
1, 0, 0, 0, 0, 0,
1, 0, 8, 1, 0, 0,
NULL, NULL, &clk_reset,
NULL, NULL, NULL,
NULL, &clk_attach, &clk_detach,
NULL, 0
};
@ -578,7 +609,6 @@ tmr_poll = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
sim_activate (&clk_unit, tmr_poll); /* reactivate unit */
tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */
AIO_SET_INTERRUPT_LATENCY(tmr_poll*clk_tps); /* set interrrupt latency */
todr_reg = todr_reg + 1; /* incr TODR */
if ((tmr_iccs & TMR_CSR_RUN) && tmr_use_100hz) /* timer on, std intvl? */
tmr_incr (TMR_INC); /* do timer service */
return SCPE_OK;
@ -651,9 +681,44 @@ t_stat clk_reset (DEVICE *dptr)
tmr_poll = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init 100Hz timer */
sim_activate_abs (&clk_unit, tmr_poll); /* activate 100Hz unit */
tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */
if (clk_unit.filebuf == NULL) { /* make sure the TODR is initialized */
clk_unit.filebuf = calloc(sizeof(TOY), 1);
if (clk_unit.filebuf == NULL)
return SCPE_MEM;
todr_resync ();
}
return SCPE_OK;
}
/* CLK attach */
t_stat clk_attach (UNIT *uptr, char *cptr)
{
t_stat r;
uptr->flags = uptr->flags | (UNIT_ATTABLE | UNIT_BUFABLE);
memset (uptr->filebuf, 0, (size_t)uptr->capac);
r = attach_unit (uptr, cptr);
if (r != SCPE_OK)
uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);
else
uptr->hwmark = (uint32) uptr->capac;
return r;
}
/* CLK detach */
t_stat clk_detach (UNIT *uptr)
{
t_stat r;
r = detach_unit (uptr);
if ((uptr->flags & UNIT_ATT) == 0)
uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);
return r;
}
/* Interval timer reset */
t_stat tmr_reset (DEVICE *dptr)
@ -672,32 +737,59 @@ return SCPE_OK;
int32 todr_rd (void)
{
return todr_reg;
TOY *toy = (TOY *)clk_unit.filebuf;
struct timespec base, now, val;
clock_gettime(CLOCK_REALTIME, &now); /* get curr time */
base.tv_sec = toy->toy_gmtbase;
base.tv_nsec = toy->toy_gmtbasemsec * 1000000;
sim_timespec_diff (&val, &now, &base);
return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */
}
void todr_wr (int32 data)
{
todr_reg = data;
return;
TOY *toy = (TOY *)clk_unit.filebuf;
struct timespec now, val, base;
/* Save the GMT time when set value was 0 to record the base for future
read operations in "battery backed-up" state */
if (-1 == clock_gettime(CLOCK_REALTIME, &now)) /* get curr time */
return; /* error? */
val.tv_sec = ((uint32)data) / 100;
val.tv_nsec = (((uint32)data) % 100) * 10000000;
sim_timespec_diff (&base, &now, &val); /* base = now - data */
toy->toy_gmtbase = base.tv_sec;
toy->toy_gmtbasemsec = base.tv_nsec/1000000;
}
t_stat todr_resync (void)
{
uint32 base;
time_t curr;
struct tm *ctm;
TOY *toy = (TOY *)clk_unit.filebuf;
curr = time (NULL); /* get curr time */
if (curr == (time_t) -1) /* error? */
if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX780 */
if (!toy->toy_gmtbase) /* Never set? */
todr_wr (0); /* Start ticking from 0 */
}
else { /* Not-Attached means */
uint32 base; /* behave like simh VMS default */
time_t curr;
struct tm *ctm;
curr = time (NULL); /* get curr time */
if (curr == (time_t) -1) /* error? */
return SCPE_NOFNC;
ctm = localtime (&curr); /* decompose */
if (ctm == NULL) /* error? */
ctm = localtime (&curr); /* decompose */
if (ctm == NULL) /* error? */
return SCPE_NOFNC;
base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */
base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */
ctm->tm_hour) * 60) +
ctm->tm_min) * 60) +
ctm->tm_sec;
todr_reg = (base * 100) + 0x10000000; /* cvt to VAX form */
todr_wr ((base * 100) + 0x10000000); /* use VMS form */
}
return SCPE_OK;
}

View file

@ -27,6 +27,31 @@
tto terminal output
clk 100Hz and TODR clock
28-Sep-11 MP Generalized setting TODR for all OSes.
Unbound the TODR value from the 100hz clock tick
interrupt. TODR now behaves like the original
battery backed-up clock and runs with the wall
clock, not the simulated instruction clock
(except when running ROM diagnostics).
Two operational modes are available:
- Default VMS mode, which is similar to the previous
behavior in that without initializing the TODR it
would default to the value VMS would set it to if
VMS knew the correct time. This would be correct
almost all the time unless a VMS disk hadn't been
booted from for more than a year. This mode
produces strange time results for non VMS OSes on
each system boot.
- OS Agnostic mode. This mode behaves precisely like
the VAX780 TODR and works correctly for all OSes.
This mode is enabled by attaching the TODR to a
battery backup state file for the TOY clock
(i.e. sim> attach TODR TOY_CLOCK). When operating
in OS Agnostic mode, the TODR will initially start
counting from 0 and be adjusted differently when an
OS specifically writes to the TODR. VMS will prompt
to set the time on each boot unless the SYSGEN
parameter TIMEPROMPTWAIT is set to 0.
05-Jan-11 MP Added Asynch I/O support
17-Aug-08 RMS Resync TODR on any clock reset
18-Jun-07 RMS Added UNIT_IDLE flag to console input, clock
@ -70,6 +95,11 @@ int32 clk_csr = 0; /* control/status */
int32 clk_tps = 100; /* ticks/second */
int32 todr_reg = 0; /* TODR register */
int32 todr_blow = 1; /* TODR battery low */
struct todr_battery_info {
uint32 toy_gmtbase; /* GMT base of set value */
uint32 toy_gmtbasemsec; /* The milliseconds of the set value */
};
typedef struct todr_battery_info TOY;
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
int32 tmr_poll = CLK_DELAY; /* pgm timer poll */
@ -79,9 +109,12 @@ t_stat clk_svc (UNIT *uptr);
t_stat tti_reset (DEVICE *dptr);
t_stat tto_reset (DEVICE *dptr);
t_stat clk_reset (DEVICE *dptr);
t_stat clk_attach (UNIT *uptr, char *cptr);
t_stat clk_detach (UNIT *uptr);
t_stat todr_resync (void);
extern int32 sysd_hlt_enb (void);
extern int32 fault_PC;
/* TTI data structures
@ -168,7 +201,7 @@ DEVICE tto_dev = {
DIB clk_dib = { 0, 0, NULL, NULL, 1, IVCL (CLK), SCB_INTTIM, { NULL } };
UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 0), CLK_DELAY };
UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE+UNIT_FIX, sizeof(TOY)), CLK_DELAY };/* 100Hz */
REG clk_reg[] = {
{ HRDATA (CSR, clk_csr, 16) },
@ -180,6 +213,7 @@ REG clk_reg[] = {
{ DRDATA (POLL, tmr_poll, 24), REG_NZ + PV_LEFT + REG_HRO },
{ DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT },
#if defined (SIM_ASYNCH_IO)
{ DRDATA (ASYNCH, sim_asynch_enabled, 1), PV_LEFT },
{ DRDATA (LATENCY, sim_asynch_latency, 32), PV_LEFT },
{ DRDATA (INST_LATENCY, sim_asynch_inst_latency, 32), PV_LEFT },
#endif
@ -193,16 +227,15 @@ MTAB clk_mod[] = {
DEVICE clk_dev = {
"CLK", &clk_unit, clk_reg, clk_mod,
1, 0, 0, 0, 0, 0,
1, 0, 8, 1, 0, 0,
NULL, NULL, &clk_reset,
NULL, NULL, NULL,
NULL, &clk_attach, &clk_detach,
&clk_dib, 0
};
/* Clock and terminal MxPR routines
iccs_rd/wr interval timer
todr_rd/wr time of year clock
rxcs_rd/wr input control/status
rxdb_rd input buffer
txcs_rd/wr output control/status
@ -214,11 +247,6 @@ int32 iccs_rd (void)
return (clk_csr & CLKCSR_IMP);
}
int32 todr_rd (void)
{
return todr_reg;
}
int32 rxcs_rd (void)
{
return (tti_csr & TTICSR_IMP);
@ -247,14 +275,6 @@ clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
return;
}
void todr_wr (int32 data)
{
todr_reg = data;
if (data)
todr_blow = 0;
return;
}
void rxcs_wr (int32 data)
{
if ((data & CSR_IE) == 0)
@ -357,7 +377,8 @@ return SCPE_OK;
clk_svc process event (clock tick)
clk_reset process reset
todr_powerup powerup for TODR (get date from system)
todr_rd/wr time of year clock
todr_resync powerup for TODR (get date from system)
*/
t_stat clk_svc (UNIT *uptr)
@ -370,8 +391,8 @@ t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
sim_activate (&clk_unit, t); /* reactivate unit */
tmr_poll = t; /* set tmr poll */
tmxr_poll = t * TMXR_MULT; /* set mux poll */
if (!todr_blow) /* incr TODR */
todr_reg = todr_reg + 1;
if (!todr_blow && todr_reg) /* if running? */
todr_reg = todr_reg + 1; /* incr TODR */
return SCPE_OK;
}
@ -385,26 +406,80 @@ t = sim_is_active (&clk_unit);
return (t? t - 1: wait);
}
int32 todr_rd (void)
{
TOY *toy = (TOY *)clk_unit.filebuf;
struct timespec base, now, val;
if ((fault_PC&0xFFFE0000) == 0x20040000) /* running from ROM? */
return todr_reg; /* return counted value for ROM diags */
if (0 == todr_reg) /* clock running? */
return todr_reg;
/* Maximum number of seconds which can be represented as 10ms ticks
in the 32bit TODR. This is the 33bit value 0x100000000/100 to get seconds */
#define TOY_MAX_SECS (0x40000000/25)
clock_gettime(CLOCK_REALTIME, &now); /* get curr time */
base.tv_sec = toy->toy_gmtbase;
base.tv_nsec = toy->toy_gmtbasemsec * 1000000;
sim_timespec_diff (&val, &now, &base);
if (val.tv_sec >= TOY_MAX_SECS) /* todr overflowed? */
return todr_reg = 0; /* stop counting */
return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */
}
void todr_wr (int32 data)
{
TOY *toy = (TOY *)clk_unit.filebuf;
struct timespec now, val, base;
/* Save the GMT time when set value was 0 to record the base for future
read operations in "battery backed-up" state */
if (-1 == clock_gettime(CLOCK_REALTIME, &now)) /* get curr time */
return; /* error? */
val.tv_sec = ((uint32)data) / 100;
val.tv_nsec = (((uint32)data) % 100) * 10000000;
sim_timespec_diff (&base, &now, &val); /* base = now - data */
toy->toy_gmtbase = base.tv_sec;
toy->toy_gmtbasemsec = base.tv_nsec/1000000;
todr_reg = data;
if (data)
todr_blow = 0;
}
/* TODR resync routine */
t_stat todr_resync (void)
{
uint32 base;
time_t curr;
struct tm *ctm;
TOY *toy = (TOY *)clk_unit.filebuf;
curr = time (NULL); /* get curr time */
if (curr == (time_t) -1) /* error? */
if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX780 */
if (!toy->toy_gmtbase) /* Never set? */
todr_wr (0); /* Start ticking from 0 */
}
else { /* Not-Attached means */
uint32 base; /* behave like simh VMS default */
time_t curr;
struct tm *ctm;
curr = time (NULL); /* get curr time */
if (curr == (time_t) -1) /* error? */
return SCPE_NOFNC;
ctm = localtime (&curr); /* decompose */
if (ctm == NULL) /* error? */
ctm = localtime (&curr); /* decompose */
if (ctm == NULL) /* error? */
return SCPE_NOFNC;
base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */
base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */
ctm->tm_hour) * 60) +
ctm->tm_min) * 60) +
ctm->tm_sec;
todr_reg = (base * 100) + 0x10000000; /* cvt to VAX form */
todr_blow = 0;
todr_wr ((base * 100) + 0x10000000); /* use VMS form */
}
return SCPE_OK;
}
@ -414,13 +489,46 @@ t_stat clk_reset (DEVICE *dptr)
{
int32 t;
todr_resync (); /* resync clock */
clk_csr = 0;
CLR_INT (CLK);
t = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init timer */
sim_activate_abs (&clk_unit, t); /* activate unit */
tmr_poll = t; /* set tmr poll */
tmxr_poll = t * TMXR_MULT; /* set mux poll */
if (clk_unit.filebuf == NULL) { /* make sure the TODR is initialized */
clk_unit.filebuf = calloc(sizeof(TOY), 1);
if (clk_unit.filebuf == NULL)
return SCPE_MEM;
todr_resync ();
}
return SCPE_OK;
}
/* CLK attach */
t_stat clk_attach (UNIT *uptr, char *cptr)
{
t_stat r;
uptr->flags = uptr->flags | (UNIT_ATTABLE | UNIT_BUFABLE);
memset (uptr->filebuf, 0, (size_t)uptr->capac);
r = attach_unit (uptr, cptr);
if (r != SCPE_OK)
uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);
else
uptr->hwmark = (uint32) uptr->capac;
return r;
}
/* CLK detach */
t_stat clk_detach (UNIT *uptr)
{
t_stat r;
r = detach_unit (uptr);
if ((uptr->flags & UNIT_ATT) == 0)
uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);
return r;
}

View file

@ -134,7 +134,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
AdditionalIncludeDirectories="./;../;../VAX/;../pdp11/;../../winpcap/Wpdpack/Include;&quot;../../pthreads/Pre-built.2/include&quot;"
PreprocessorDefinitions="USE_INT64;USE_ADDR64;VM_VAX;VAX_730;USE_SHARED;_CRT_SECURE_NO_WARNINGS;USE_READER_THREAD"
PreprocessorDefinitions="USE_INT64;USE_ADDR64;VM_VAX;VAX_730;USE_SHARED;_CRT_SECURE_NO_WARNINGS;USE_READER_THREAD;SIM_ASYNCH_IO"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"

View file

@ -27,7 +27,7 @@
<Tool
Name="VCPreBuildEventTool"
Description="Build Dependent ROM include File(s)"
CommandLine="pushd ..&#x0D;&#x0A;$(TargetDir)BuildROMs&#x0D;&#x0A;popd"
CommandLine="pushd ..&#x0D;&#x0A;$(TargetDir)BuildROMs&#x0D;&#x0A;popd&#x0D;&#x0A;"
/>
<Tool
Name="VCCustomBuildTool"
@ -112,7 +112,7 @@
<Tool
Name="VCPreBuildEventTool"
Description="Build Dependent ROM include File(s)"
CommandLine="pushd ..&#x0D;&#x0A;$(TargetDir)BuildROMs&#x0D;&#x0A;popd"
CommandLine="pushd ..&#x0D;&#x0A;$(TargetDir)BuildROMs&#x0D;&#x0A;popd&#x0D;&#x0A;"
/>
<Tool
Name="VCCustomBuildTool"
@ -134,7 +134,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
AdditionalIncludeDirectories="./;../;../VAX/;../pdp11/;../../winpcap/Wpdpack/Include;&quot;../../pthreads/Pre-built.2/include&quot;"
PreprocessorDefinitions="USE_INT64;USE_ADDR64;VM_VAX;VAX_780;USE_SHARED;_CRT_SECURE_NO_WARNINGS;USE_READER_THREAD"
PreprocessorDefinitions="USE_INT64;USE_ADDR64;VM_VAX;VAX_780;USE_SHARED;_CRT_SECURE_NO_WARNINGS;USE_READER_THREAD;SIM_ASYNCH_IO"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"

View file

@ -57,8 +57,8 @@
#
# MMK/MACRO=(NOASYNCH=1)
#
# On AXP the AXP PCAP components are built and used to provide network
# support for the VAX and PDP11 simulators.
# On AXP and IA64 the VMS PCAP components are built and used to provide
# network support for the VAX and PDP11 simulators.
#
# The AXP PCAP components can only be built using a version of the
# DEC/Compaq/HP Compiler version V6.5-001 or later. To build using an

View file

@ -13,6 +13,7 @@
#
ifeq ($(WIN32),)
#*nix Environments (&& cygwin)
GCC = gcc
ifeq (SunOS,$(shell uname))
TEST = /bin/test
else
@ -23,16 +24,20 @@ ifeq ($(WIN32),)
else
ifeq (Linux,$(shell uname))
LIBEXT = so
else
ifeq (SunOS,$(shell uname))
LIBEXT = so
else
LIBEXT = a
endif
endif
endif
OS_CCDEFS = -D_GNU_SOURCE
ifeq (libm,$(shell if $(TEST) -e /usr/lib/libm.$(LIBEXT); then echo libm; fi))
ifeq (libm,$(shell if $(TEST) -e /usr/lib/libm.$(LIBEXT) -o -e /usr/lib64/libm.$(LIBEXT); then echo libm; fi))
OS_LDFLAGS += -lm
endif
ifeq (SunOS,$(shell uname))
OS_CCDEFS += -I/opt/sfw/include
OS_CCDEFS += -I/opt/sfw/include -DSIM_ASYNCH_IO -DUSE_READER_THREAD
OS_LDFLAGS += -lsocket -lnsl -lrt -lm -lpthread -L/opt/sfw/lib -R/opt/sfw/lib
endif
ifeq (cygwin,$(findstring cygwin,$(OSTYPE)))
@ -46,29 +51,41 @@ ifeq ($(WIN32),)
OS_LDFLAGS += -lpthread
endif
ifeq (readline,$(shell if $(TEST) -e /usr/lib/libreadline.$(LIBEXT) -o -e /usr/lib64/libreadline.$(LIBEXT) -o -e /opt/sfw/lib/libreadline.a; then echo readline; fi))
ifeq (readline_h,$(shell if $(TEST) -e /usr/include/readline/readline.h -o -e /usr/include/readline.h; then echo readline_h; fi))
ifeq (readline_h,$(shell if $(TEST) -e /usr/include/readline/readline.h -o -e /usr/include/readline.h -o -e /opt/sfw/include/readline/readline.h; then echo readline_h; fi))
# Use Locally installed and available readline support
ifeq (ncurses,$(shell if $(TEST) -e /usr/lib/libncurses.$(LIBEXT) -o -e /opt/sfw/lib/libncurses.a; then echo ncurses; fi))
OS_CCDEFS += -DHAVE_READLINE
OS_LDFLAGS += -lreadline -lncurses
else
ifeq (curses,$(shell if $(TEST) -e /usr/lib/libcurses.$(LIBEXT); then echo curses; fi))
OS_CCDEFS += -DHAVE_READLINE
OS_LDFLAGS += -lreadline -lcurses
else
ifeq (solaris_readline,$(shell if $(TEST) ! -e /opt/sfw/lib/libreadline.a; then echo solaris_readline; fi))
OS_CCDEFS += -DHAVE_READLINE
OS_LDFLAGS += -lreadline
endif
endif
endif
endif
endif
ifeq (pcap,$(shell if $(TEST) -e /usr/include/pcap.h -o -e /opt/sfw/include/pcap.h; then echo pcap; fi))
# Use Locally installed and available pcap support
NETWORK_CCDEFS = -DUSE_NETWORK
NETWORK_LDFLAGS = -lpcap
endif
ifeq (vde,$(shell if $(TEST) -e /usr/include/libvdeplug.h -a \( -e /usr/lib/libvdeplug.$(LIBEXT) -o -e /usr/lib64/libvdeplug.$(LIBEXT) \); then echo vde; fi))
# Provide support for vde networking
NETWORK_CCDEFS += -DUSE_VDE_NETWORK
NETWORK_LDFLAGS += -lvdeplug
endif
ifeq (tuntap,$(shell if $(TEST) -e /usr/include/linux/if_tun.h; then echo tuntap; fi))
# Provide support for Tap networking on Linux
NETWORK_TAP_CCDEFS = -DUSE_TAP_NETWORK
NETWORK_CCDEFS += -DUSE_TAP_NETWORK
endif
ifeq (bsdtuntap,$(shell if $(TEST) -e /usr/include/net/if_tun.h; then echo bsdtuntap; fi))
ifeq (bsdtuntap,$(shell if $(TEST) -e /usr/include/net/if_tun.h -o -e /Library/Extensions/tap.kext; then echo bsdtuntap; fi))
# Provide support for Tap networking
NETWORK_TAP_CCDEFS = -DUSE_TAP_NETWORK -DUSE_BSDTUNTAP
NETWORK_CCDEFS += -DUSE_TAP_NETWORK -DUSE_BSDTUNTAP
endif
ifneq (binexists,$(shell if $(TEST) -e BIN; then echo binexists; fi))
MKDIRBIN = if $(TEST) ! -e BIN; then mkdir BIN; fi
@ -79,6 +96,7 @@ ifeq ($(WIN32),)
endif
else
#Win32 Environments (via MinGW32)
GCC = gcc
GCC_Path := $(dir $(shell where gcc.exe))
ifeq ($(NOASYNCH),)
ifeq (pthreads,$(shell if exist ..\pthreads\Pre-built.2\include\pthread.h echo pthreads))
@ -119,7 +137,7 @@ else
endif
CC = gcc -std=c99 -U__STRICT_ANSI__ -g -I . $(NETWORK_CCDEFS) $(NETWORK_TAP_CCDEFS) $(OS_CCDEFS) $(ROMS_OPT)
CC = $(GCC) -std=c99 -U__STRICT_ANSI__ -g -I . $(NETWORK_CCDEFS) $(OS_CCDEFS) $(ROMS_OPT)
LDFLAGS = $(OS_LDFLAGS) $(NETWORK_LDFLAGS)
#

107
scp.c
View file

@ -23,6 +23,17 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
25-Sep-11 MP Added the ability for a simulator built with
SIM_ASYNCH_IO to change whether I/O is actually done
asynchronously by the new scp command SET ASYNCH and
SET NOASYNCH
22-Sep-11 MP Added signal catching of SIGHUP and SIGTERM to cause
simulator STOP. This allows an externally signalled
event (i.e. system shutdown, or logoff) to signal a
running simulator of these events and to allow
reasonable actions to be taken. This will facilitate
running a simulator as a 'service' on *nix platforms,
given a sufficiently flexible simulator .ini file.
20-Apr-11 MP Added expansion of %STATUS% and %TSTATUS% in do command
arguments. STATUS is the numeric value of the last
command error status and TSTATUS is the text message
@ -271,6 +282,7 @@ pthread_mutex_t sim_asynch_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t sim_asynch_wake = PTHREAD_COND_INITIALIZER;
pthread_t sim_asynch_main_threadid;
struct sim_unit *sim_asynch_queue = NULL;
t_bool sim_asynch_enabled = TRUE;
int32 sim_asynch_check;
int32 sim_asynch_latency = 4000; /* 4 usec interrupt latency */
int32 sim_asynch_inst_latency = 20; /* assume 5 mip simulator */
@ -387,6 +399,7 @@ t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr,
t_stat step_svc (UNIT *ptr);
void sub_args (char *instr, char *tmpbuf, int32 maxstr, char *do_arg[]);
t_stat set_on (int32 flag, char *cptr);
t_stat set_asynch (int32 flag, char *cptr);
/* Global data */
@ -603,8 +616,11 @@ static CTAB cmd_table[] = {
"set console NODEBUG disable console debugging\n"
"set break <list> set breakpoints\n"
"set nobreak <list> clear breakpoints\n"
"set throttle x{M|K|%%} set simulation rate\n"
"set throttle {x{M|K|%}}|{x/t}\n"
" set simulation rate\n"
"set nothrottle set simulation rate to maximum\n"
"set asynch enable asynchronous I/O\n"
"set noasynch disable asynchronous I/O\n"
"set <dev> OCT|DEC|HEX set device display radix\n"
"set <dev> ENABLED enable device\n"
"set <dev> DISABLED disable device\n"
@ -628,6 +644,7 @@ static CTAB cmd_table[] = {
"sh{ow} q{ueue} show event queue\n"
"sh{ow} ti{me} show simulated time\n"
"sh{ow} th{rottle} show simulation rate\n"
"sh{ow} a{synch} show asynchronouse I/O state\n"
"sh{ow} ve{rsion} show simulator version\n"
"sh{ow} <dev> RADIX show device display radix\n"
"sh{ow} <dev> DEBUG show device debug flags\n"
@ -1006,13 +1023,6 @@ do {
(cmdp->action != &on_cmd) &&
(cmdp->action != &echo_cmd)))
sim_last_cmd_stat = stat; /* save command error status */
staying = (stat != SCPE_EXIT) && /* decide if staying */
(stat != SCPE_AFAIL) &&
(!errabort || (stat < SCPE_BASE) || (stat == SCPE_STEP));
if ((stat == SCPE_AFAIL) && /* handle special case AFAIL */
sim_on_check[sim_do_depth] && /* and use trap action if defined */
sim_on_actions[sim_do_depth][stat]) /* otherwise exit */
staying = TRUE;
if ((stat >= SCPE_BASE) && (stat != SCPE_EXIT) && /* error from cmd? */
(stat != SCPE_STEP)) {
if (!echo && !sim_quiet && /* report if not echoing */
@ -1023,8 +1033,23 @@ do {
}
stat = stat & ~SCPE_DOFAILED; /* remove possible flag */
}
switch (stat) {
case SCPE_OK:
case SCPE_STEP:
break;
case SCPE_AFAIL:
staying = (sim_on_check[sim_do_depth] && /* if trap action defined */
sim_on_actions[sim_do_depth][stat]); /* use it, otherwise exit */
break;
case SCPE_EXIT:
staying = FALSE;
break;
default:
staying = sim_on_check[sim_do_depth];
break;
}
if ((staying || !interactive) && /* report error if staying */
(stat >= SCPE_BASE)) { /* or in cmdline file */
(stat >= SCPE_BASE) && !isdo) { /* or in cmdline file */
printf ("%s\n", sim_error_text (stat));
if (sim_log)
fprintf (sim_log, "%s\n", sim_error_text (stat));
@ -1033,7 +1058,7 @@ do {
(sim_on_check[sim_do_depth]) &&
(stat != SCPE_OK) &&
(stat != SCPE_STEP))
if (sim_on_actions[sim_do_depth][stat])
if ((stat <= SCPE_MAX_ERR) && sim_on_actions[sim_do_depth][stat])
sim_brk_act[sim_do_depth] = sim_on_actions[sim_do_depth][stat];
else
sim_brk_act[sim_do_depth] = sim_on_actions[sim_do_depth][0];
@ -1281,6 +1306,61 @@ if ((sim_do_depth != 0) &&
return SCPE_OK;
}
/* Set asynch/noasynch routine */
t_stat sim_set_asynch (int32 flag, char *cptr)
{
if (cptr && (*cptr != 0)) /* now eol? */
return SCPE_2MARG;
#ifdef SIM_ASYNCH_IO
if (flag == sim_asynch_enabled) /* already set correctly? */
return SCPE_OK;
sim_asynch_enabled = flag;
if (1) {
uint32 i, j;
DEVICE *dptr;
UNIT *uptr;
/* Call unit flush routines to report asynch status change to device layer */
for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* flush attached files */
for (j = 0; j < dptr->numunits; j++) { /* if not buffered in mem */
uptr = dptr->units + j;
if ((uptr->flags & UNIT_ATT) && /* attached, */
!(uptr->flags & UNIT_BUF) && /* not buffered, */
(uptr->fileref)) /* real file, */
if (uptr->io_flush) /* unit specific flush routine */
uptr->io_flush (uptr);
}
}
}
if (!sim_quiet)
printf ("Asynchronous I/O %sabled\n", sim_asynch_enabled ? "en" : "dis");
if (sim_log)
fprintf (sim_log, "Asynchronous I/O %sabled\n", sim_asynch_enabled ? "en" : "dis");
return SCPE_OK;
#else
if (!sim_quiet)
printf ("Asynchronous I/O is not available in this simulator\n");
if (sim_log)
fprintf (sim_log, "Asynchronous I/O is not available in this simulator\n");
return SCPE_NOFNC;
#endif
}
/* Show asynch routine */
t_stat sim_show_asynch (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
{
if (cptr && (*cptr != 0))
return SCPE_2MARG;
#ifdef SIM_ASYNCH_IO
fprintf (st, "Asynchronous I/O is %sabled\n", (sim_asynch_enabled) ? "en" : "dis");
#else
fprintf (st, "Asynchronous I/O is not available in this simulator\n");
#endif
return SCPE_OK;
}
/* Set command */
t_stat set_cmd (int32 flag, char *cptr)
@ -1305,6 +1385,8 @@ static CTAB set_glob_tab[] = {
{ "NODEBUG", &sim_set_deboff, 0 }, /* deprecated */
{ "THROTTLE", &sim_set_throt, 1 },
{ "NOTHROTTLE", &sim_set_throt, 0 },
{ "ASYNCH", &sim_set_asynch, 1 },
{ "NOASYNCH", &sim_set_asynch, 0 },
{ "ON", &set_on, 1 },
{ "NOON", &set_on, 0 },
{ NULL, NULL, 0 }
@ -1570,6 +1652,7 @@ static SHTAB show_glob_tab[] = {
{ "TELNET", &sim_show_telnet, 0 }, /* deprecated */
{ "DEBUG", &sim_show_debug, 0 }, /* deprecated */
{ "THROTTLE", &sim_show_throt, 0 },
{ "ASYNCH", &sim_show_asynch, 0 },
{ "ON", &show_on, 0 },
{ NULL, NULL, 0 }
};
@ -2878,7 +2961,9 @@ for (j=0, r = SCPE_OK; j<attcnt; j++) {
if (r == SCPE_OK) {
dptr = find_dev_from_unit (attunits[j]);
sim_switches = attswitches[j];
r = scp_attach_unit (dptr, attunits[j], attnames[j]); /* reattach unit */
r = scp_attach_unit (dptr, attunits[j], attnames[j]);/* reattach unit */
if (r != SCPE_OK)
printf ("Error Attaching %s to %s\n", sim_dname (dptr), attnames[j]);
}
free (attnames[j]);
}

View file

@ -130,7 +130,7 @@ fprintf (iFile, "#define ROM_%s_H 0\n", rom_array_name);
fprintf (iFile, "/*\n");
fprintf (iFile, " %s produced at %s", include_filename, ctime(&now));
fprintf (iFile, " from %s which was last modified at %s", rom_filename, ctime(&statb.st_mtime));
fprintf (iFile, " file size: %d (0x%X)\n", statb.st_size, statb.st_size);
fprintf (iFile, " file size: %d (0x%X)\n", (int)statb.st_size, (int)statb.st_size);
fprintf (iFile, "*/\n");
fprintf (iFile, "unsigned char %s[] = {", rom_array_name);
for (bytes_written=0;bytes_written<statb.st_size; ++bytes_written) {

View file

@ -424,7 +424,8 @@ while (*cptr != 0) { /* do all mods */
*cvptr++ = 0;
get_glyph (gbuf, gbuf, 0); /* modifier to UC */
if (isdigit (*gbuf)) {
if (sim_con_tmxr.master) return SCPE_ALATT; /* already open? */
if (sim_con_tmxr.master) /* already open? */
sim_set_notelnet (0, NULL); /* close first */
return tmxr_open_master (&sim_con_tmxr, gbuf); /* open master socket */
}
else
@ -633,8 +634,12 @@ if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) { /* connected or buffered
tmxr_poll_rx (&sim_con_tmxr); /* poll (check disconn) */
if (sim_con_ldsc.conn || sim_con_ldsc.txbfd) { /* still connected? */
if (!sim_con_ldsc.conn) {
printf ("Running with Buffered Console\n"); /* print transition */
printf ("Running with Buffered Console\r\n"); /* print transition */
fflush (stdout);
if (sim_log) { /* log file? */
fprintf (sim_log, "Running with Buffered Console\n");
fflush (sim_log);
}
}
return SCPE_OK;
}
@ -643,8 +648,12 @@ for (i = 0; i < sec; i++) { /* loop */
if (tmxr_poll_conn (&sim_con_tmxr) >= 0) { /* poll connect */
sim_con_ldsc.rcve = 1; /* rcv enabled */
if (i) { /* if delayed */
printf ("Running\n"); /* print transition */
printf ("Running\r\n"); /* print transition */
fflush (stdout);
if (sim_log) { /* log file? */
fprintf (sim_log, "Running\n");
fflush (sim_log);
}
}
return SCPE_OK; /* ready to proceed */
}
@ -652,8 +661,12 @@ for (i = 0; i < sec; i++) { /* loop */
if ((c == SCPE_STOP) || stop_cpu)
return SCPE_STOP;
if ((i % 10) == 0) { /* Status every 10 sec */
printf ("Waiting for console Telnet connection\n");
printf ("Waiting for console Telnet connection\r\n");
fflush (stdout);
if (sim_log) { /* log file? */
fprintf (sim_log, "Waiting for console Telnet connection\n");
fflush (sim_log);
}
}
sim_os_sleep (1); /* wait 1 second */
}

View file

@ -565,6 +565,7 @@ extern pthread_cond_t sim_asynch_wake;
extern pthread_t sim_asynch_main_threadid;
extern struct sim_unit *sim_asynch_queue;
extern t_bool sim_idle_wait;
extern t_bool sim_asynch_enabled;
extern int32 sim_asynch_check;
extern int32 sim_asynch_latency;
extern int32 sim_asynch_inst_latency;

View file

@ -408,15 +408,17 @@ return SCPE_NOFNC;
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
pthread_attr_t attr;
ctx->asynch_io = 1;
ctx->asynch_io = sim_asynch_enabled;
ctx->asynch_io_latency = latency;
pthread_mutex_init (&ctx->io_lock, NULL);
pthread_cond_init (&ctx->io_cond, NULL);
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_create (&ctx->io_thread, &attr, _disk_io, (void *)uptr);
pthread_attr_destroy(&attr);
uptr->a_check_completion = _disk_completion_dispatch;
if (ctx->asynch_io) {
pthread_mutex_init (&ctx->io_lock, NULL);
pthread_cond_init (&ctx->io_cond, NULL);
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_create (&ctx->io_thread, &attr, _disk_io, (void *)uptr);
pthread_attr_destroy(&attr);
uptr->a_check_completion = _disk_completion_dispatch;
}
#endif
return SCPE_OK;
}
@ -723,7 +725,8 @@ uint32 f = DK_GET_FMT (uptr);
#if defined (SIM_ASYNCH_IO)
sim_disk_clr_async (uptr);
sim_disk_set_async (uptr, 0);
if (sim_asynch_enabled)
sim_disk_set_async (uptr, 0);
#endif
switch (f) { /* case on format */
case DKUF_F_STD: /* Simh */
@ -1332,7 +1335,7 @@ if (strchr (openmode, 'r'))
DesiredAccess |= GENERIC_READ;
if (strchr (openmode, 'w') || strchr (openmode, '+'))
DesiredAccess |= GENERIC_WRITE;
Handle = CreateFileA (rawdevicename, DesiredAccess, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
Handle = CreateFileA (rawdevicename, DesiredAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS|FILE_FLAG_WRITE_THROUGH, NULL);
if (Handle == INVALID_HANDLE_VALUE) {
_set_errno_from_status (GetLastError ());
return NULL;
@ -1418,8 +1421,11 @@ static t_stat sim_os_disk_unload_raw (FILE *Disk)
{
#ifdef IOCTL_STORAGE_EJECT_MEDIA
DWORD BytesReturned;
uint32 Removable = FALSE;
if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */
sim_os_disk_info_raw (Disk, NULL, &Removable);
if (Removable) {
if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */
IOCTL_STORAGE_EJECT_MEDIA, /* dwIoControlCode */
NULL, /* lpInBuffer */
0, /* nInBufferSize */
@ -1430,6 +1436,7 @@ if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */
_set_errno_from_status (GetLastError ());
return SCPE_IOERR;
}
}
return SCPE_OK;
#else
return SCPE_NOFNC;
@ -1440,8 +1447,11 @@ static t_bool sim_os_disk_isavailable_raw (FILE *Disk)
{
#ifdef IOCTL_STORAGE_EJECT_MEDIA
DWORD BytesReturned;
uint32 Removable = FALSE;
if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */
sim_os_disk_info_raw (Disk, NULL, &Removable);
if (Removable) {
if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */
IOCTL_STORAGE_CHECK_VERIFY, /* dwIoControlCode */
NULL, /* lpInBuffer */
0, /* nInBufferSize */
@ -1452,6 +1462,7 @@ if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */
_set_errno_from_status (GetLastError ());
return FALSE;
}
}
#endif
return TRUE;
}
@ -2646,6 +2657,7 @@ if (SizeInBytes > ((uint64)(1024*1024*1024))*2040) {
}
if (File = sim_fopen (szVHDPath, "rb")) {
fclose (File);
File = NULL;
Status = EEXIST;
goto Cleanup_Return;
}
@ -2773,7 +2785,8 @@ if (WriteFilePosition(File,
Cleanup_Return:
free (BAT);
fclose (File);
if (File)
fclose (File);
if (Status) {
if (Status != EEXIST)
remove (szVHDPath);

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,7 @@
Modification history:
30-Oct-11 MP Added support for vde (Virtual Distributed Ethernet) networking
18-Apr-11 MP Fixed race condition with self loopback packets in
multithreaded environments
09-Dec-10 MP Added support to determine if network address conflicts exist
@ -89,13 +90,13 @@
#if defined (USE_READER_THREAD)
#if defined (USE_SETNONBLOCK)
#undef USE_SETNONBLOCK
#endif
#endif /* USE_SETNONBLOCK */
#undef PCAP_READ_TIMEOUT
#define PCAP_READ_TIMEOUT 15
#if !defined (xBSD) && !defined(_WIN32) && !defined(VMS)
#define MUST_DO_SELECT
#endif
#if (!defined (xBSD) && !defined(_WIN32) && !defined(VMS)) || defined (USE_TAP_NETWORK) || defined (USE_VDE_NETWORK)
#define MUST_DO_SELECT 1
#endif
#endif /* USE_READER_THREAD */
/*
USE_BPF is defined to let this code leverage the libpcap/OS kernel provided
@ -175,7 +176,10 @@ struct eth_device {
char* name; /* name of ethernet device */
void* handle; /* handle of implementation-specific device */
int fd_handle; /* fd to kernel device (where needed) */
int pcap_mode; /* Flag indicating if pcap API are being used to move packets */
int eth_api; /* Designator for which API is being used to move packets */
#define ETH_API_PCAP 0 /* Pcap API in use */
#define ETH_API_TAP 1 /* tun/tap API in use */
#define ETH_API_VDE 2 /* VDE API in use */
ETH_PCALLBACK read_callback; /* read callback function */
ETH_PCALLBACK write_callback; /* write callback function */
ETH_PACK* read_packet; /* read packet */

View file

@ -320,14 +320,16 @@ return SCPE_NOFNC;
struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
pthread_attr_t attr;
ctx->asynch_io = 1;
ctx->asynch_io = sim_asynch_enabled;
ctx->asynch_io_latency = latency;
pthread_mutex_init (&ctx->io_lock, NULL);
pthread_cond_init (&ctx->io_cond, NULL);
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_create (&ctx->io_thread, &attr, _tape_io, (void *)uptr);
pthread_attr_destroy(&attr);
if (ctx->asynch_io) {
pthread_mutex_init (&ctx->io_lock, NULL);
pthread_cond_init (&ctx->io_cond, NULL);
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_create (&ctx->io_thread, &attr, _tape_io, (void *)uptr);
pthread_attr_destroy(&attr);
}
uptr->a_check_completion = _tape_completion_dispatch;
#endif
return SCPE_OK;
@ -362,7 +364,8 @@ static void _sim_tape_io_flush (UNIT *uptr)
{
#if defined (SIM_ASYNCH_IO)
sim_tape_clr_async (uptr);
sim_tape_set_async (uptr, 0);
if (sim_asynch_enabled)
sim_tape_set_async (uptr, 0);
#endif
fflush (uptr->fileref);
}

View file

@ -23,6 +23,28 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
21-Oct-11 MP Fixed throttling in several ways:
- Sleep for the observed clock tick size while throttling
- Recompute the throttling wait once every 10 seconds
to account for varying instruction mixes during
different phases of a simulator execution or to
accommodate the presence of other load on the host
system.
- Each of the pre-existing throttling modes (Kcps,
Mcps, and %) all compute the appropriate throttling
interval dynamically. These dynamic computations
assume that 100% of the host CPU is dedicated to
the current simulator during this computation.
This assumption may not always be true and under
certain conditions may never provide a way to
correctly determine the appropriate throttling
wait. An additional throttling mode has been added
which allows the simulator operator to explicitly
state the desired throttling wait parameters.
These are specified by:
SET THROT insts/delay
where 'insts' is the number of instructions to
execute before sleeping for 'delay' milliseconds.
22-Apr-11 MP Fixed Asynch I/O support to reasonably account cycles
when an idle wait is terminated by an external event
05-Jan-11 MP Added Asynch I/O support
@ -67,6 +89,7 @@ static uint32 sim_throt_ms_stop = 0;
static uint32 sim_throt_type = 0;
static uint32 sim_throt_val = 0;
static uint32 sim_throt_state = 0;
static uint32 sim_throt_sleep_time = 0;
static int32 sim_throt_wait = 0;
extern int32 sim_interval, sim_switches;
extern FILE *sim_log;
@ -152,8 +175,7 @@ return sim_os_msec () - stime;
}
#if defined(SIM_ASYNCH_IO)
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 1
#ifdef NEED_CLOCK_GETTIME
int clock_gettime(int clk_id, struct timespec *tp)
{
uint32 secs, ns, tod[2], unixbase[2] = {0xd53e8000, 0x019db1de};
@ -225,12 +247,13 @@ Sleep (msec);
return sim_os_msec () - stime;
}
#if !defined(CLOCK_REALTIME) && defined (SIM_ASYNCH_IO)
#define CLOCK_REALTIME 1
#if defined(NEED_CLOCK_GETTIME)
int clock_gettime(int clk_id, struct timespec *tp)
{
t_uint64 now, unixbase;
if (clk_id != CLOCK_REALTIME)
return -1;
unixbase = 116444736;
unixbase *= 1000000000;
GetSystemTimeAsFileTime((FILETIME*)&now);
@ -315,8 +338,7 @@ treq.tv_nsec = (milliseconds % MILLIS_PER_SEC) * NANOS_PER_MILLI;
return sim_os_msec () - stime;
}
#if !defined(CLOCK_REALTIME) && defined (SIM_ASYNCH_IO)
#define CLOCK_REALTIME 1
#if defined(NEED_CLOCK_GETTIME)
int clock_gettime(int clk_id, struct timespec *tp)
{
struct timeval cur;
@ -377,8 +399,7 @@ if (tim > SIM_IDLE_MAX)
return tim;
}
#if !defined(_POSIX_SOURCE) && defined(SIM_ASYNCH_IO)
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 1
#ifdef NEED_CLOCK_GETTIME
typedef int clockid_t;
int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
@ -408,6 +429,21 @@ return sim_os_msec () - stime;
#endif
/* diff = min - sub */
void
sim_timespec_diff (struct timespec *diff, struct timespec *min, struct timespec *sub)
{
/* move the minuend value to the difference and operate there. */
*diff = *min;
/* Borrow as needed for the nsec value */
if (sub->tv_nsec > min->tv_nsec) {
--diff->tv_sec;
diff->tv_nsec += 1000000000;
}
diff->tv_nsec -= sub->tv_nsec;
diff->tv_sec -= sub->tv_sec;
}
#if defined(SIM_ASYNCH_IO)
uint32 sim_idle_ms_sleep (unsigned int msec)
{
@ -628,8 +664,11 @@ return SCPE_OK;
t_stat sim_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc)
{
if (sim_idle_enab)
fprintf (st, "idle enabled, stability wait = %ds, minimum sleep resolution = %dms", sim_idle_stable, sim_idle_rate_ms);
if (sim_idle_enab) {
fprintf (st, "idle enabled");
if (sim_switches & SWMASK ('D'))
fprintf (st, ", stability wait = %ds, minimum sleep resolution = %dms", sim_idle_stable, sim_idle_rate_ms);
}
else fputs ("idle disabled", st);
return SCPE_OK;
}
@ -639,7 +678,7 @@ return SCPE_OK;
t_stat sim_set_throt (int32 arg, char *cptr)
{
char *tptr, c;
t_value val;
t_value val, val2;
if (arg == 0) {
if ((cptr != 0) && (*cptr != 0))
@ -653,8 +692,11 @@ else {
val = strtotv (cptr, &tptr, 10);
if (cptr == tptr)
return SCPE_ARG;
sim_throt_sleep_time = sim_idle_rate_ms;
c = toupper (*tptr++);
if (*tptr != 0)
if (c == '/')
val2 = strtotv (tptr, &tptr, 10);
if ((*tptr != 0) || (val == 0))
return SCPE_ARG;
if (c == 'M')
sim_throt_type = SIM_THROT_MCYC;
@ -662,6 +704,9 @@ else {
sim_throt_type = SIM_THROT_KCYC;
else if ((c == '%') && (val > 0) && (val < 100))
sim_throt_type = SIM_THROT_PCT;
else if ((c == '/') && (val2 != 0)) {
sim_throt_type = SIM_THROT_SPC;
}
else return SCPE_ARG;
if (sim_idle_enab) {
printf ("Idling disabled\n");
@ -670,6 +715,14 @@ else {
sim_clr_idle (NULL, 0, NULL, NULL);
}
sim_throt_val = (uint32) val;
if (sim_throt_type == SIM_THROT_SPC) {
if (val2 >= sim_idle_rate_ms)
sim_throt_sleep_time = (uint32) val2;
else {
sim_throt_sleep_time = (uint32) (val2 * sim_idle_rate_ms);
sim_throt_val = (uint32) (val * sim_idle_rate_ms);
}
}
}
return SCPE_OK;
}
@ -693,13 +746,17 @@ else {
fprintf (st, "Throttle = %d%%\n", sim_throt_val);
break;
case SIM_THROT_SPC:
fprintf (st, "Throttle = %d ms every %d cycles\n", sim_throt_sleep_time, sim_throt_val);
break;
default:
fprintf (st, "Throttling disabled\n");
break;
}
if (sim_switches & SWMASK ('D')) {
fprintf (st, "Wait rate = %d ms\n", sim_idle_rate_ms);
fprintf (st, "minimum sleep resolution = %d ms\n", sim_idle_rate_ms);
if (sim_throt_type != 0)
fprintf (st, "Throttle interval = %d cycles\n", sim_throt_wait);
}
@ -712,7 +769,6 @@ void sim_throt_sched (void)
sim_throt_state = 0;
if (sim_throt_type)
sim_activate (&sim_throt_unit, SIM_THROT_WINIT);
return;
}
void sim_throt_cancel (void)
@ -722,7 +778,8 @@ sim_cancel (&sim_throt_unit);
/* Throttle service
Throttle service has three distinct states
Throttle service has three distinct states used while dynamically
determining a throttling interval:
0 take initial measurement
1 take final measurement, calculate wait values
@ -734,12 +791,16 @@ t_stat sim_throt_svc (UNIT *uptr)
uint32 delta_ms;
double a_cps, d_cps;
if (sim_throt_type == SIM_THROT_SPC) { /* Non dynamic? */
sim_throt_state = 2; /* force state */
sim_throt_wait = sim_throt_val;
}
switch (sim_throt_state) {
case 0: /* take initial reading */
sim_throt_ms_start = sim_os_msec ();
sim_throt_wait = SIM_THROT_WST;
sim_throt_state++; /* next state */
sim_throt_state = 1; /* next state */
break; /* reschedule */
case 1: /* take final reading */
@ -761,24 +822,32 @@ switch (sim_throt_state) {
d_cps = (double) sim_throt_val * 1000.0;
else d_cps = (a_cps * ((double) sim_throt_val)) / 100.0;
if (d_cps >= a_cps) {
sim_throt_state = 0;
sim_throt_sched (); /* start over */
return SCPE_OK;
}
sim_throt_wait = (int32) /* time between waits */
((a_cps * d_cps * ((double) sim_idle_rate_ms)) /
(1000.0 * (a_cps - d_cps)));
if (sim_throt_wait < SIM_THROT_WMIN) { /* not long enough? */
sim_throt_state = 0;
sim_throt_sched (); /* start over */
return SCPE_OK;
}
sim_throt_state++;
sim_throt_ms_start = sim_throt_ms_stop;
sim_throt_state = 2;
// fprintf (stderr, "Throttle values a_cps = %f, d_cps = %f, wait = %d\n",
// a_cps, d_cps, sim_throt_wait);
}
break;
case 2: /* throttling */
sim_os_ms_sleep (1);
sim_os_ms_sleep (sim_throt_sleep_time);
delta_ms = sim_os_msec () - sim_throt_ms_start;
if ((sim_throt_type != SIM_THROT_SPC) && /* when dynamic throttling */
(delta_ms >= 10000)) { /* recompute every 10 sec */
sim_throt_ms_start = sim_os_msec ();
sim_throt_wait = SIM_THROT_WST;
sim_throt_state = 1; /* next state */
}
break;
}

View file

@ -31,6 +31,26 @@
#ifndef _SIM_TIMER_H_
#define _SIM_TIMER_H_ 0
#include <time.h>
#if defined (__APPLE__)
#define HAVE_STRUCT_TIMESPEC 1 /* OSX defined the structure but doesn't tell us */
#endif
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 1
#define NEED_CLOCK_GETTIME 1
#ifndef HAVE_STRUCT_TIMESPEC
#define HAVE_STRUCT_TIMESPEC 1
struct timespec {
long tv_sec;
long tv_nsec;
};
#endif /* HAVE_STRUCT_TIMESPEC */
int clock_gettime(int clock_id, struct timespec *tp);
#endif
#define SIM_NTIMERS 8 /* # timers */
#define SIM_TMAX 500 /* max timer makeup */
@ -46,11 +66,13 @@
#define SIM_THROT_WMIN 100 /* min wait */
#define SIM_THROT_MSMIN 10 /* min for measurement */
#define SIM_THROT_NONE 0 /* throttle parameters */
#define SIM_THROT_MCYC 1
#define SIM_THROT_KCYC 2
#define SIM_THROT_PCT 3
#define SIM_THROT_MCYC 1 /* MegaCycles Per Sec */
#define SIM_THROT_KCYC 2 /* KiloCycles Per Sec */
#define SIM_THROT_PCT 3 /* Max Percent of host CPU */
#define SIM_THROT_SPC 4 /* Specific periodic Delay */
t_bool sim_timer_init (void);
void sim_timespec_diff (struct timespec *diff, struct timespec *min, struct timespec *sub);
int32 sim_rtcn_init (int32 time, int32 tmr);
void sim_rtcn_init_all (void);
int32 sim_rtcn_calb (int32 ticksper, int32 tmr);