Subject: Re: Visual Frameworks vs. Cells compared to Flow-Based Programming
From: rpw3@rpw3.org (Rob Warnock)
Date: Sun, 01 Jun 2008 21:31:40 -0500
Newsgroups: comp.lang.lisp
Message-ID: <EMqdnW8xmqMRxt7VnZ2dnUVZ_j6dnZ2d@speakeasy.net>
Paul Tarvydas  <tarvydas@visualframeworksinc.com> wrote:
+---------------
| Our variant doesn't even need the @SERVICE call - everything tends
| to be coded as state machines and the code snippets that are executed
| during transitions/entries/exits are all very short.  
+---------------

To some extent IBM's PARS (Programmed Airline Reservation System)
[later broken into APPS and ACP ("Airline Control Program"), the
latter later renamed TCP ("Transaction Processing Facility")]
used many of the same principles, see:

    http://en.wikipedia.org/wiki/Airlines_Control_Program
    http://www.blackbeard.com/tpf/tpfhist.htm

[For many years Bank of America and other banks used TPF to run
the centralized part of their ATM applications.]

+---------------
| Our original problem was that "polling" was way too inefficient.
| PLC's (employing periodic polling) were being using on injection
| molding machines, but a certain event ("cut-over") occurred in
| such a short time span that polling strategies would completely
| miss the events.
+---------------

That's what was nice about @SERVICE: you just stuck it in someplace
where you already needed a CLA [which happens a lot in PDP-8 code,
since there is no LOAD -- you have to clear (CLA) then add (TAD)],
and if there was no pending interrupt request then it was "free".
[Well, nearly; it cost 3 cycles instead of true CLA's 1 cycle.]

+---------------
| We had to bolt fairly complicated code directly onto interrupts -
| then we discovered that the code would be better-structured if we
| used state charts, then we discovered that we might as well do all
| of the code that way, regardless of whether it was bolted to an
| interrupt or to another piece (chain) of software.
+---------------

Well, much of our code *was* state machines, with the edges sometimes
being new events and sometimes being just the continuations resulting
from the required @SERVICE points [recall that I said at least one was
mandatory in every indefinite-length loop].

+---------------
| An RTOS had been bought in, but we eventually ignored it,
| since all of the real code was written below the RTOS.
+---------------

Heh! Our WSCHED *was* the "RTOS", if you're going to use those terms.
Someday I should do a full write-up of WSCHED, but here are some
salient points:

- The "Bus Window" MMU redefined the first 64 words of each PDP-8
  "field" [4 kwords] as being virtual memory: 8 pages (we called
  them "chunks") of 8 words each. The virtual mapping for each field
  was the *same*, so if you put some data into the virtually-addressed
  area and did a cross-field subroutine call the data was still there
  in the same relative locations in the target field, which made
  cross-field calls *much* faster. *Only* the first 64 words of
  each field were virtual; all other addresses remained as before.

- The "page table" was thus itself an 8-word chunk and by software
  convention was always mapped into the first virtual page (loc. 0-7)
  [trivially done by having word 0 of each page table contain the
  page number of that page table itself], so that you could change
  the currently-active mappings for locations #o10-#o77 by depositing
  the new mappings directly into locations 1-7. [The MMU snooped such
  stores and copied them into its TLB automagically.]

- This 8-word chunkiness was pervasive throughout the data structures
  of the system. *All* dynamic data was organized in chunk-sized pieces,
  and linked lists were constructed by having word 7 of a chunk contain
  the chunk (page) number of the next chunk in the list. If a chunk in
  such a list was currently mapped in (virtual) locations #o70-77, one
  could remap those locations to the next chunk in the list with only
  two instructions [assuming the AC was clear, almost always the case] --
  "TAD 77 ; DCA 7". That took word 7 of the current chunk and slammed it
  into the 7th mapping of the current page table. Et voila!

- The application (data communications) layer of WSCHED was organized
  around the MMU as a sort of "software crossbar" between some input
  device (say, UART#73) and some output device (say, network trunk #5
  logical channel #17). Virtual pages 1-3 were owned by the "source",
  while pages 4-6 were owned by the "destination". [Page 7 was universally
  a "scratch" page, mainly used as a temp for linked-list traversals,
  as above.] A reverse mapping -- flipping the roles of "source" and
  "destination" always existed at a fixed place in the "destination"
  area, so one could flip roles in two instructions -- "TAD 46; WENABL".

  [Aside: When an device was not "connected" in the software crossbar,
  by convention it was mapped to itself. This meant that one could
  create a crossbar connection with only a six load/store pairs to
  swap the "destination" mappings of the two devices, whereupon they
  were suddenly "connected" as above.]

- Associated with each multi-unit device controller was a vector of
  page tables (called "contexts") for the units of that controller.
  So all you had to do to process some input was add the unit number
  of the interrupting device to the base of the page tables for that
  controller and "light the context" with a WENABL instruction, then
  call the "source" input-handling subroutine whose address was at
  a fixed address in the "context" (virtual area).

Anyway, not to go on *too* long [though I probably have already!],
the point being that scheduled-task control blocks were built out
of these same "chunks". When you ran a task (or a continuation from
an @SERVICE) you simply "lit its context" and then did a subroutine
return into the saved PC stored *in* the context [at yet another
fixed location in the now-active virtual memory]. Input-data-driven
"software crossbar" data flow, event-driven, state-driven, or timed
scheduled tasks -- all of these models co-existed within WSCHED and
all used the *same* dispatch mechanism! The whole thing meshed together
*quite* nicely, thank you very much.  ;-}  ;-}


-Rob

p.s. I have replicated the WSCHED style a number of times over the
years in various embedded network applications, except using "source"
and "destination" base or index registers (now that CPUS *have* such
things -- the PDP-8 didn't!) instead of a special-purpose MMU [starting
with the Zilog Z-80, in which we used the X & Y registers for "source"
and "destination"]. The "software crossbar" style is still quite useful,
as is the interrupt-off "very-light-weight RTOS" style.

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607