Subject: any SKED users out there?

From: [email-masked] (Jon Krueger)
Date: 25 Sep 92 21:06:38 GMT

My experience with 8's was mostly in connection with SKED.
Any SKED users out there?

-- Jon

Jon Krueger  [email-masked]

---

From: [email-masked] (Charles Lasner)
Date: Sat, 26 Sep 1992 05:42:10 GMT

I may have a SKED manual somewhere, but I never used it, because the real-time
stuff I had to do outclassed SKED, and the non-real-time isn't what SKED is
for.

SKED really doesn't give you much of a PDP-8-specific viewpoint; it could have
been written for about anything, but just happened to be an early -8 program
that was available for a limited audience that could make use of it.

A lot of PDP-8 users really expected that off-the-shelf software was going to
somehow do what they wanted.  Much of my work was based upon fixing up for the
mistakes of that notion, etc.

cjl

---

From: [email-masked] (Jon Krueger)
Date: 26 Sep 92 19:59:20 GMT

Charles Lasner writes:
> SKED really doesn't give you much of a PDP-8-specific viewpoint

True, it gives you a state language viewpoint.

Had it given you more of a PDP-8-specific viewpoint,
its users probably wouldn't have been able to master it,
and their programs probably would have been either trivial
or incorrect.  The nice thing about SKED was how it made
realtime data acquisition and process control of multiple
concurrent processes accessible to nonprogrammers through
use of the state language.  It could and later did run
on other machines.

Still, SKED's historical and technical connection to 8's is
well established.  The 8 was reliable and affordable enough
for a lab to buy one of its very own.  It's hard to explain
to youngsters what a revolution that was.  You couldn't do
realtime stuff with your slice of the department's timesharing
machine.  Suddenly, you could afford to buy a machine to
dedicate to automating Skinner boxes.  The 8 was also fast
enough to do reasonable amounts of I/O getting and putting
things from your lab device.  DEC documented enough of the
hardware, interfaces, and operating system that you could
write a system like SKED.  They kept the 8 standardized
enough that most 8 programs ran on most 8's, a property
found only in the mainframe world up until then.  And they
sold enough that you weren't on your own.  Hard to explain
to folks now how amazing that was too -- "you have an 8?
Wow!  We have an 8."

-- Jon
--

---

From: [email-masked] (Charles Lasner)
Date: Sun, 27 Sep 1992 00:29:30 GMT

>True, it gives you a state language viewpoint.

Yes, at much sacrifice of certain kinds of capability, which was a necessary
requirement at many other installations.  More power if you could "live" under
SKED; we and the other places I consulted for could not.

>use of the state language.  It could and later did run

Users didn't write the programs at the installations I worked for; I did.

>to folks now how amazing that was too -- "you have an 8?

That's true; and it also allowed me to take the guts of my code from one
machine to another where the "application layer" of the real-time code
was all that was different, since the interrupt-level is constrained to
be nearly identical in each case.

The only variance has to do with whether the Lab clock was to be put into
whichever of its several modes made more sense for the application.  BTW,
some of the applications were beyond the capabilities of the hardware
provided in the LAB-8/e series, and required the addition of non-standard
modifications to the clock to allow two clock board sets.  Additionally,
multiple D-A converters were often needed to display certain real-time
calculations.

My main point is that the -8 was used for lots of real-time applications,
including certain things where SKED would literally get in the way.  There's
a world of difference between caring about 10's of microseconds versus
10's of milliseconds.  A lot of ornate programming is needed to get the
performance out of the machine that it's capable of.

Real-time is what you make of it; some people were happy with the limited
world of LAB-8/e BASIC, and others were happy with the "canned" packages
provided by DEC that were, as far as I/m concerned, glorified demo programs,
such as the "Time Interval Histogram" program and its ilk.  Moreover, the
quality of the code in some of these programs was quite below "par" compared
to the code myself and others wrote both before and since these programs
became available.

Some of what I refer to is the so-called "skip chain" interrupt handling.
This is an inefficient technique whereby actual SKP instructions are used to
skip over jumps (perhaps indirect to make them even slower) where the SKP's
are themselves skipped over should a device flag be raised.  Perhaps it's
insignificantly easier to follow, or it conforms to someone's notion of
"structure" but regardless, it unnecessarily raises the interrupt latency.
Moreover, some programs require an aspect of unavailable API, namely that
an interrupt routine needs to be interruptable lest a higher-priority
device be interrupting.  In this case, a "recursive" interrupt handler is
required so that after the device has been "tamed", the rest of the device
servicing is guaranteed to be a lower priority than a potential interrupt
from another device.  Priority can't be finely controlled, but you can do
things like make sure that a trivial and unimportant blurb printing routine
outputting to the terminal on interrupt doesn't materially slow down the
ability for the clock to give you clock-counter readouts from the clock buffer
at crucial times, or to get additional A-D channels started soon enough before
the sampling rate exhibits a jitter, etc.  (Ever debug a real-time program
with an oscilloscope?  I have.  I had to ensure that tasks that "woke up"
periodically didn't impact negatively on sampling rate by inducing jitter, etc.
and the best way was to watch the automatic a-d start pulse generated by the 
clock, etc.)

Yes, SKED has a place in applications for the -8, but hardly in the
realm of certain "faster" real-time applications.  User flexibility can
mean program impossibility sometimes.

cjl

---

From: [email-masked] (Jon Krueger)
Date: 27 Sep 92 05:05:16 GMT

Charles Lasner writes:
> There's a world of difference between caring about 10's of
> microseconds versus 10's of milliseconds.

You bet.  But not to recording behavior of intact
organisms. That's what SKED was designed for.
10 millisecond resolution was what its applications
needed and what it gave.

Realtime isn't notably "do this as fast as you can".
It's "do this and guarantee you will complete within
time T".  Sometimes T is measured in milliseconds, 
sometimes microseconds, nanoseconds, or hours.

> A lot of ornate programming is needed to get the

True.  But ornate can also mean impossible to validate.
SKED had advantages to those who wanted to write a
variety of nontrivial realtime programs and have
confidence that they were correct.

SKED's "tick" was configurable, by the way.  The default
was 10 msec, but you could set it as low as 1 msec (on
8's) or as high as you wanted and run more stations.

-- Jon

---

From: [email-masked] (Charles Lasner)
Date: Sun, 27 Sep 1992 13:54:08 GMT

>10 millisecond resolution was what its applications

I agree; the applications I did needed more, although some of them did
qualify for the word "intact" but some could argue that it was just barely so.

>sometimes microseconds, nanoseconds, or hours.

Exactly.  This is what bothers me about certain other programs hawked by
certain vendors.  They aren't capable of anything but relatively slower
units, yet use the "banner" of "real-time" application to get unwanted
praise.  Moreover, someone once defined real-time as either "fixed" or
"floating".  Clearly we're talking about the fixed kind, which is always more
difficult to pull off.  My level was into the instruction/cycle counting kind.
This has been known to be done on other machines as well, such as when people
found out that overly stripped down CPU's didn't function as expected (thinking
LAB-1103 here; someone wound up building DMA peripherals for more functions
than anticipated because the CPU was the bottleneck as compared to other
models).

Moreover, there is an industry of hardware people willing to ride on this
bandwagon.  Thus we would always get our time wasted looking through brochures
for A-D convertors when we wanted fast convertors (either continuous or
at least successive-approximation types) and instead were getting glossies
about the latest and greatest dual-slope integrator type A-D convertors. (These
are fine if your application is 3 orders of magnitude slower than ours; it's
intended for applications like digital voltmeters, etc., not fairly fast
real-time; yet these companies hear about applications that monitor liquid
levels in tanks, or super-slow chemical reactions done in so-called real-time
and assume that anyone in a real-time situation is to be lumped in, thus
we are an appropriate audience for this slow stuff :-(.)

>confidence that they were correct.

This is also true, but irrelevant.  Sometimes the intrusion of code that is
present merely to validate what's being done guarantees that it can't.  Merely
getting an I/O error on our disk was "fatal" to the application, so the error
routines indicated aborting the run.  Fortunately there was enough time to
check for the errors, because the disk handler itself was run by DMA as well
as the DMA that wrote the data out (during the sampling, etc.).

BTW, there is another level of task interaction that comes up here: too-fast
disks that need to be "throttled back" to allow enough cycles to get the
job done.  While one constraint is the disk being fast enough on average to
keep up with the aggregate sampling rate, another constraint is that when the
disk is actually transferring, it doesn't take too many CPU cycles that the
sampling routines (on clock interrupt) are adversely affected.  All too often,
a disk transfers all of its data at once, and can be granted virtually every
buss cycle for a brief period, which should it coincide with an interrupt
handling routine that has a short critical window, means that the application
has failed to keep up with the data.  By slowing down the transfer rate, 
this can be avoided.

For one such application, there was a better solution: an inter-processor
buffer (DB8E).  This allowed one machine to carry out the real-time application
while the other machine (with the too-fast disk) acted as a disk server.  When
both machines are available, the DB8E transfers words quite quickly in the
background.  The background code is interrupted as necessary by the clock-
driven events.  Most of the time is spent in the background shoveling 12-bit
words at the disk server machine.  Periodically, the disk server is not
available as its cycles are taken away by the fast disk, which can afford to 
get certain kinds of errors and yet, through multiple buffers still keep up
if the recovery is successful after at most 2 retries.  But usually, the
disk server is available in the real-time sense.  Thus each CPU's need to
service some higher-priority task doesn't interfere with the other's.  As 
long as both machines were available to each other 60% of the time, the
data transfer was successful.

I mentioned a few articles back about the need for two clocks.  The reason
for this only tends to come up when the data rate is high:  You need to
put the clock into the mode that schedules the first of N A-D conversions
when the clock overflows, and then auto-reloads the clock counter from the
clock buffer/preset register.  The interrupt handler for the clock does a
blind read of the A-D buffer because sufficient microseconds have gone by
since the clock overflow interrupt which is what's checked for in the
interrupt routine.  Then, additional channels are scheduled, etc.  This
all works fine if that's all you want to do.

However, we also needed to use the Schmitt trigger hardware to put the
clock into the mode that dumps the clock counter into the buffer register
to count frequency of the events hooked up there.  Needless to say we were
running the clock at the 1 microsecond/tick rate at the time.  This can
be done only with two clocks, each doing one of the operations.  It was
once tried with one clock:

You have the clock overflow, and you load the buffer-preset register with
the new value of the clock counter for next time.  The problem is that
the single register is the only avenue of loading the clock counter, so
it's necessary to do it this way.  The instructions are either AC -> clock
buffer, or AC -> clock buffer -> clock counter; there is no way to leave
undisturbed the buffer register.  So, you run the clock in that mode that
reloads the clock from the buffer every time the counter overflows and
interrupts.  So far so good.  But, you also enable the Schmitt trigger
inputs, thus they also interrupt occasionally.  Perhaps even relatively
infrequently (not in our applications when data was at the expected highest
value of valid data, but the problem exists even if the data is slower).
When the Schmitt trigger interrupt occurs, what we want to do is to load the
clock buffer with what's currently in the clock right now, and then read it
into the AC.  (This is what the instruction does; the basic problem is that
there is only one path in and out of the clock counter for all functions.)
Then we quickly want to restore the constant reload factor back to the buffer
so it's correct for when the clock overflows (usually in awhile) so it will
reload correctly at that time.  (Again, this is reasonable because the 
instruction used is AC -> clock buffer only.)

But there is an insidious problem:  what if the clock is nearly ready to
overflow?  You have just dumped out the clock counter into the buffer register
and could have a clock count of something like -20 through -1.  If this is the
case, the clock will in just a few CPU instruction times be overflowing and
before you can do anything about it start reloading itself from this unintended
buffer value.  The worst case is if the clock count is -1, because it means 
that the clock is now repeatedly going -1, 0, -1, 0, -1, 0, etc. and there's
nothing you can do about it :-(.  By the time you have reloaded the buffer
with the larger number intended to be there (such as -800) some semi-unknown
amount of cycles may have gone by where the clock was out of control causing
multiple overflow/auto-reload events.  If a DMA disk is stealing cycles during
this worst-case event, the results aren't even fully predictable.  Thus, the
overall effect is a "creeping" loss of real-time :-(.  The only reliable
solution is to redesign the clock.  In our case, we did by using two clocks
to avoid the interaction.  There was enough program time available to service
the two interrupts.

BTW, there is a logistic problem in modifying the DK8EP hardware: they never
intended the clock to be anything other than device 13, whereas most cards
have spare device codes or even free-choice in a six-bit range.  We had to
hack on the logic to make it respond to device 14 :-(.

>8's) or as high as you wanted and run more stations.

We just had one faster station.

cjl