b-em PDP11 tube processor

want to talk about MESS/model b/beebem/b-em/electrem/elkulator? do it here!
Post Reply
Coeus
Posts: 1334
Joined: Mon Jul 25, 2016 11:05 am
Contact:

b-em PDP11 tube processor

Post by Coeus » Fri Sep 13, 2019 1:26 am

Cribbed from the PiTubeDirect project, I now have a branch of b-em with a PDP11 co-processor:
pdp.png
https://github.com/stardot/b-em/tree/sf/pdp11

I did come across a couple of interesting things along the way.

1. The routine loop0 in the PDP11 core (pdp11.c) would execute as long as tubeContinueRunning() returned true. For integration into b-em I had defined this as:

Code: Select all

static inline int tubeContinueRunning() {return tubecycles > 0;}
when I added the 6809. The 6809 also calls tubeUseCycles() which I had defined as:

Code: Select all

static inline void tubeUseCycles(int c) {tubecycles -= c;}
so together these would implement a scheme where the CPU runs for an allowed number of cycles and then lets something else to have a go. It doesn't look like the PDP11 makes any calls to tubeUseCycles, in fact it looks like it does do cycle accounting at all so instead I have hacked loop0 to use one cycle per instruction. This was necessary because if loop0 never returns the host 6502 never runs and therefore the PDP11 is stuck waiting for a tube register that never changes. So a question for hoglet mainly, is there a standard interface here between a core and the rest of PiTubeDirect?

2. The interrupt handling seems odd. The PDP11 core defines a routine pdp11_interrupt() so I had the tube ULA interrupt code call this when R4 was written to. This almost worked in that the first write to R4 for a host->parasite transfer generates the interrupt on the parasite side but then so did each subsequent write to R4, i.e. the transfer address etc. Looking more closely it seems some "glue code" in the PiTubeDirect copro-pdp11 is checking the PDP11's interrupt priority mask before calling pdp11_interrupt(). This is what seems a little strange - normally I would expect a processor to check it's own interrupt mask/priority before accepting an interrupt. Is this a drop off in the PDP11 core or is the PDP11 odd?

3. The PDP11 client ROM fails to defend against it's own data areas being overwritten by incoming data from the tube. This means it crashes with MOS 3.50 because this transfers a (useless to the PDP11) version of BASIC across that is being relocated to run in high memory (on the 6502) and therefore sits just below the ROM on the 6502 co-pro and on top of workspace on the PDP11. It works fine on MOS 3.20 and the non-master OSes.

On this last point I had a previous discussion with JGH. His view was that the host should be able to transfer to any address in the parasite but it seems to me this is not possible. If the host crashes the parasite by overwriting the workspace of the code that is receiving the transfer then the tranfer will fail just as surely as if the parasite had chosen to ignore the incoming data with the additional anoyance of crashing the parasite so having the client ROM check the incoming address and simply discard anything that would overwrite it seems like the best solution to me. If an OS want to replace the client ROM and use its own drivers for the tube hardware then it would need to transfer to a lower address initially and then relocate itself.

User avatar
jgharston
Posts: 3640
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: b-em PDP11 tube processor

Post by jgharston » Fri Sep 13, 2019 10:43 am

Coeus wrote:
Fri Sep 13, 2019 1:26 am
3. The PDP11 client ROM fails to defend against it's own data areas being overwritten by incoming data from the tube. This means it crashes with MOS 3.50 because this transfers a (useless to the PDP11) version of BASIC across that is being relocated to run in high memory (on the 6502) and therefore sits just below the ROM on the 6502 co-pro and on top of workspace on the PDP11. It works fine on MOS 3.20 and the non-master OSes.
Same thing happens with the Z80 CoPro - the MOS 3.50 sends HiBasic across to B800-F800 trashing the Client code. There's nothing the Client can do to stop this. And if you want to be able to load over the Client, as with the CP/M BIOS, it's essential. Plus, that's the defined API, the host is allowed to fling whatever it wants to the client regardless of the effects on the client. It's annoying, but the solution to "my arm hurts when I do this" is "don't do it" not "chop your arm off".

The "correct" solution is for the host to examine the Client and determine that it is the correct target for what it wants to fling over, and refuse if it doesn't match. Unfortunately there's no API for this, but with Z80, 6809 and PDP11 BASIC* I worked out a close-enough workaround - read the byte at &FFF7 from the Client and only proceed if it is the correct 'JP' opcode for the CPU you are targetting. Not perfect as there's a slight chance of a false positive if the Client has a more than 64K of memory and &0000FFF7 just happens to contain the correct byte, eg an ARM CoPro where something has done ?&FFF7=&C3 would make it "look like" a Z80.

*Actually, generic code that can be used with any language ROM. link, source

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
jgharston
Posts: 3640
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: b-em PDP11 tube processor

Post by jgharston » Fri Sep 13, 2019 10:50 am

Coeus wrote:
Fri Sep 13, 2019 1:26 am
If the host crashes the parasite by overwriting the workspace of the code that is receiving the transfer then the tranfer will fail just as surely as if the parasite had chosen to ignore the incoming data with the additional anoyance of crashing the parasite so having the client ROM check the incoming address and simply discard anything that would overwrite it seems like the best solution to me.
Same thing happens on the 6502 if you load over &00F0-&00FF. The 6502 Client doesn't do anything to stop you the user trashing the system. The whole Acorn philosophy is that it is ***YOUR*** responsibility what **YOU** do to **YOUR** system.

As an eample, the Torch systems and the ETI 6809 systems reaaaalllyyy piss me off as they are implemented as "we, in our divine towers, shall only allow you to ask the host for this small handful of actions that *we* deem that you lowly plebs shall ever consider ever thinking of using". OSBYTE 128, yeah, we'll let you do that. Maybe. OSBYTE 128,7? No. OSWORD 163? Bugger off. OSFILE anything? Pah!, you're joking. The proper approach is the Acorn approach - here's the API, do with it as you will, the *HOST* determines if a action is appropriate or not, ***NOT***** the Client. The Client has no ability and no authority to chose to determine what a valid action is or is not. PLOT 240? Nah, I'm not going to let you do that because ***I**** think that PLOT 240 is not something you should never be allowed to use.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
hoglet
Posts: 8439
Joined: Sat Oct 13, 2012 6:21 pm
Location: Bristol
Contact:

Re: b-em PDP11 tube processor

Post by hoglet » Fri Sep 13, 2019 12:59 pm

Coeus wrote:
Fri Sep 13, 2019 1:26 am
So a question for hoglet mainly, is there a standard interface here between a core and the rest of PiTubeDirect?
There is, but it's at a much higher level:

Code: Select all

extern void copro_pdp11_emulator();
i.e. the wrapper class for each Co Pro is really the implementation of the standard one method API.

In PiTubeDirect, copro_pdp11_emulator() will run as the main program, only returning when another Co Pro is selected. The mechanism for this is a bit ugly, and involves looking for a change in a global variable (copro, which indicates the current co processor number).

The reason I did it this way was because I wanted to minimise the changes I had to make to each third-party CPU implementation, so it's less painful if a new verson of the third-party CPU implementation is released.
Coeus wrote:
Fri Sep 13, 2019 1:26 am
Looking more closely it seems some "glue code" in the PiTubeDirect copro-pdp11 is checking the PDP11's interrupt priority mask before calling pdp11_interrupt(). This is what seems a little strange - normally I would expect a processor to check it's own interrupt mask/priority before accepting an interrupt. Is this a drop off in the PDP11 core or is the PDP11 odd?
Again, I think it's done this way to minimise the changes I was making to third party code.

Some of the other Co Pro's use the same pattern (e.g. the 80x86)

Dave

Coeus
Posts: 1334
Joined: Mon Jul 25, 2016 11:05 am
Contact:

Re: b-em PDP11 tube processor

Post by Coeus » Fri Sep 13, 2019 3:03 pm

jgharston wrote:
Fri Sep 13, 2019 10:50 am
Same thing happens on the 6502 if you load over &00F0-&00FF. The 6502 Client doesn't do anything to stop you the user trashing the system. The whole Acorn philosophy is that it is ***YOUR*** responsibility what **YOU** do to **YOUR** system.
But the issue here is it is not me sat at the keyboard doing something silly to crash the system; it the the combination of OS and BASIC, as supplied by Acorn together in the 1Mbit ROM that are doing it. Without patching something the combination of MOS 3.5 and either Z80 or PDP11 is unusable as it will always crash immediately on boot before I get to type anything.

Yes, I agree that the host OS pushing over a completely useless language ROM is a defect in the tube start-up protocol. I'd even go as far as saying that the host probably shouldn't push anything at all and that, right from the start, the client processor should be requesting what it wants. That means a processor with a disc-based OS could go straight into requesting the boot file/sector etc. but hindsight is a wonderful thing.
Last edited by Coeus on Fri Sep 13, 2019 3:04 pm, edited 1 time in total.

Coeus
Posts: 1334
Joined: Mon Jul 25, 2016 11:05 am
Contact:

Re: b-em PDP11 tube processor

Post by Coeus » Fri Sep 13, 2019 3:39 pm

jgharston wrote:
Fri Sep 13, 2019 10:43 am
*Actually, generic code that can be used with any language ROM. link, source
Ok, having your PDP11 BASIC ROM loaded does seem to salvage the situation in that now PDP11 BASIC gets transferred instead and the PDP11 is quite happy to run that. That doesn't address the case where you are happy to drop into a simple command prompt in the client ROM to start some other OS. It also leaves me wondering how this language priority mechanism works.

Anyway, having got BASIC running, how fast should a PDP11 be? I currently get:
clocksp.png
I suspect that is probably a bit fast.
Last edited by Coeus on Fri Sep 13, 2019 3:40 pm, edited 2 times in total.

User avatar
dv8
Posts: 243
Joined: Mon Jun 22, 2009 9:07 pm
Contact:

Re: b-em PDP11 tube processor

Post by dv8 » Fri Sep 13, 2019 5:03 pm

Coeus wrote:
Fri Sep 13, 2019 3:39 pm
That doesn't address the case where you are happy to drop into a simple command prompt in the client ROM to start some other OS.
You could use *CONFIGURE to set the default language to an empty slot or a service-only ROM, e.g. *CONF.LANG 13

Ctrl+Break will then give 'This is not a language' and drop to a supervisor prompt.
Last edited by dv8 on Fri Sep 13, 2019 5:24 pm, edited 1 time in total.

Coeus
Posts: 1334
Joined: Mon Jul 25, 2016 11:05 am
Contact:

Re: b-em PDP11 tube processor

Post by Coeus » Fri Sep 13, 2019 6:57 pm

Coeus wrote:
Fri Sep 13, 2019 3:39 pm
It also leaves me wondering how this language priority mechanism works.
So it works by using a service call to retrospectively update the OSes cached ROM type byte to disable languages that are not for the correct processor.

That's quite clever.

Post Reply