• Please review our updated Terms and Rules here

Powertran Cortex

"How bizarre"
Indeed!

"is there anyway to download in bulk?"
Yes, if you select a check-in (either via the timeline menu, or by clicking on the link in the files view) you get to a screen where you can download a tarball or zip file (and view side-by-side diffs, etc.).

"Any thoughts?"
- Yes, my bad: I missed several files in the repo, I've just added those. I am pleased to hear to it seems to work with Cygwin: the source code uses the sbrk() function call, which is not supported by Windows itself; the Cygwin folks must have added emulation for that.
- You do not have to define __pdp11__. This was added by the bkunix project to deal with differences between big and little endian systems. I will clean those bits up in due course.
- I've also added out2lmc, which converts a runnable a.out file to an object file for downloading to the breadboard.

"Here's what I do"
That is correct. Once more my bad, I forgot to include the source for cc itself (now fixed). This little program does all the work that you now do by hand. Note that cc has hardcoded paths to the component programs, so be sure to update that.

Let me know how you get along.

Paul
 
"How bizarre"
"is there anyway to download in bulk?"

Yes, if you select a check-in (either via the timeline menu, or by clicking on the link in the files view) you get to a screen where you can download a tarball or zip file (and view side-by-side diffs, etc.).

Paul

Ahh, finally figured it out. You have to log-in (anonymously is fine) to get the link. Didn't know that!

OK, I'll give the latest a try. Typical isn't it? I decided to get involved 48 hours before it was ready...

Thanks again,

Dave.
 
Good progress Paul!

Floating point - the Cortex source code contains a set of floating point routines, if that's the sort of thing you're interested in. If you look in the Cortex source here [http://www.powertrancortex.com/basicandcdos/Cortex ROM Source.pdf], the main FP routines start on page 490.

Memory Management - the memory mapper chip lets you map each 4K block in the processor 64K address space to any 4K block in the extended 1M memory. I don't think the Cortex 'manages memory' so to speak - it is totally reliant on the programmer to control.

Disk - a simple solution might be to use Compact Flash. No DMA, but a doddle to connect (I've got one in my TM990 system) plus you can remove the disk and read/write to it on the PC.

Stuart.
 
Good progress Paul!
Disk - a simple solution might be to use Compact Flash. No DMA, but a doddle to connect (I've got one in my TM990 system) plus you can remove the disk and read/write to it on the PC.
No DMA is perhaps the way to go as another base camp on the way to the summit; it is certainly a simpler approach.
So far, all I have found on the web are interfaces with 8-10 ttl chips. Is that what you had in mind, or is there a solution with just a few chips?
 
No DMA is perhaps the way to go as another base camp on the way to the summit; it is certainly a simpler approach.
So far, all I have found on the web are interfaces with 8-10 ttl chips. Is that what you had in mind, or is there a solution with just a few chips?

Ah, to clarify, what I meant to say was an IDE interface then a CF card on a cheap little IDE-CF adaptor. You can treat the IDE I/F as a simple memory-mapped device so all you need is to sort out some address decoding for the chip selects. The design for my TM990 is here: http://www.avjd51.dsl.pipex.com/tm990/hardware_projects/tm_990_ide_interface_sch.pdf. You probably won't need the address and data bus buffers. U8 is only needed for the TMS9900 which always does a read-before-write so it needs different read and write port addresses - don't think you need that for the 9995. You can operate the IDE I/F on an 8-bit bus - all the IDE registers you need for basic operation are 8-bit, and to keep things simple you don't need to latch two bytes on/off the IDE 16-bit data bus, just use 8 bits. You'll lose half the capacity of the CF card because you're only using half of each 16-bit word, but you're hardly going to filling a whole CF card up.

I based my design on the information here: http://www.retroleum.co.uk/electronics-articles/an-8-bit-ide-interface/.
 
Last edited:
You can operate the IDE I/F on an 8-bit bus - all the IDE registers you need for basic operation are 8-bit, and to keep things simple you don't need to latch two bytes on/off the IDE 16-bit data bus, just use 8 bits.
Brilliant. That remark made me remember something that I had seen for a ZX81 a decade ago. Couldn't find that anymore, but it was similar to this:
http://piters.tripod.com/simpif.htm
I guess hooking up to the breadboard could be almost as simple. I have a CF-to-dual-header converter board, but that would still require a lot of wires to hook up to the breadboard. Perhaps I should order some of these:
http://www.vetco.net/catalog/product_info.php?cPath=72_225&products_id=13672

You'll lose half the capacity of the CF card because you're only using half of each 16-bit word, but you're hardly going to be filling a whole CF card up.
Yup. Back in '76 the system that Ritchie used had about 10MB of disk space actually used. Even a 32MB card would be large enough.

Paul
 
A disk for the breadboard

A disk for the breadboard

That CF card idea is really panning out. First, there is a breadboard friendly breakout board:
https://www.sparkfun.com/products/retired/493
Take a look at the schematics and circuit cellar article. Unfortunately, it has been retired, but this swedish web shop still has some (at a whopping 18 euros):
http://www.lawicel-shop.se/
I've ordered one, two more available.

The article does not make it quite clear, but CF cards operate in 1 of 3 modes. To get the IDE mode, pin 9 has to be grounded at power up. If that pin is left floating, it comes up in memory mode, an execptionally easy mode to interface:
http://xetexracing.com/page3/page39/files/Interfacing CF Memory.pdf
Also note that support for IDE mode was obligatory for CF cards, but is optional for CF+ cards. Memory mode is obligatory in both standards, and hence a safer bet. Best of all, memory mode allows 8 bit access to data as well, so the whole card can be used.

For those who want to have all the detail, here is the spec:
ftp://ftp.wintel.fi/manuals/General/CompactFlash.pdf

It would seem that indeed a CF card can be interfaced to the 9995 with just one or two TTL chips for address selection and alike.

Paul
 
To get the IDE mode, pin 9 has to be grounded at power up. If that pin is left floating, it comes up in memory mode.

Interesting, I did wonder how one controlled the mode, and never did find out. Pin 9 is /OE, and that isn't present on the IDE interface. So if using an IDE-CF adaptor, it's always going to be in IDE mode.

If one writes some data to a CF card on one system in memory mode, presumably one would read the same data from the card on a different system in IDE mode? Might be a point worth checking in case you were to offer TMS9995 code downloads to write to the CF card on a PC? (Would need a utility/app to write 'raw data' to the CF card on the PC of course, unless you were going to support FAT formatting or similar.)

Stuart.
 
I refer to Stuart's schematic for the breadboard. Attached an alternative page 2, page 1 is almost identical (note /reset, /int1 and /ram_oe). The 4 inverters and the 2 or gates are left over from page 1.

I think this should work and it still fits on 2 strips of breadboard. The 74hct688 could also be a 74hct138 with some loss of addressing precision. It has to be a hct part though, as CF cards are not TTL compatible. Choosing a '138 might make the wiring a bit easier. The card registers appear at memory location 0xfe00-0xfe07; this is chosen so that the timer register and nmi vector remain addressible.

The 9902(A) is selected when A3 is low; this should avoid conflict with the built-in flag register at cru address 0x1ee0. Connecting /int to /int1 is optional, it is only needed when running Xinu with buffered I/O (Xinu console I/O works with polling).

The remaining CF card connections are handled on the Sparkfun breakout board.

Any comments?
 

Attachments

  • schematic.pdf
    16 KB · Views: 1
Looks convincing. ;-)

You might need an HCT245 buffer for the data bus to the CF card? In practise I found on my TM990 system that the data buffers had to be HCT and all the other signals were fine with LS chips. YMMV according to board layout and how many chips you've got hanging off each signal?

Stuart.
 
1. Floating point

Operating system kernels normally don't need floating point, so I have no direct need to port this, but completing the compiler port is perhaps worthwhile in its own right. The pdp11 floating point instructions are rather different from those on the 99110 or the 990/12. I am tempted to emulate pdp11 style instructions and make the compiler porting work easier. Any alternative ideas? Any pointers to high speed floating routines for the 9995/99105?

Paul

I agree that the kernel itself wouldn't need FP support, but I think it would be nice to have it implemented in the Compiler for those who wish to use it.

Dave.
 
2. Memory management

I'd like to extend the little breadboard with some memory management. I am torn between doing something very simple and replicating the Powertran design. From the schematics alone I am not entirely sure how the Powertran manages memory. Who can tell me how it was designed to work?

Paul

As Stuart said, the memory mapper in the Cortex was really left up to the user to play with. Neither MDEX or Cortex Basic/CDOS use it. NOS probably does, but I still haven't got around to experimenting with that OS yet.

The mapper resides at 0xF100-0xF11E as 16 x 12-bit registers (but only 8 bits are used in the Cortex). Each register represents 4K of the 64K TMS9995 RAM, so 0xF100 is for 0x0000-0x0FFF all the way up to 0xF11E which is for 0xF000-0xFFFF. Each register can take the value of 0x00 to 0xFF where each value points to a 4K block of the (maximum) 1MB RAM. Thus if 0xF110 is set to 0x10, then TMS9995 RAM 0x8000-0x8FFF is mapped to 0x10000-0x10FFF. The mapper is turned on/off using the CKON/CKOF instructions.

The emulator implements this if you want to try it out.

Dave.
 
Note that cc has hard-coded paths to the component programs, so be sure to update that.

Let me know how you get along.

Paul

Thanks for updating the repository with the latest files. I got it all built and it works fine. I have a couple of questions:

1) Are you planning on any more changes (floating point perhaps)? I want to start tweaking it for Cortex use and don't want to deviate too from your 'masters' if there are more changes to come.

2) As you said, the paths in cc are hard coded. As supplied, they are set to './' which only works if you are working in the bin99 directory. If a path is set to bin99 or the files are copied to /usr/local/bin, then it errors saying it can't find ./cpp. So, if you are in ./myproject and do a 'cc -o prog prog.c, cc will execute fine but fail on the call to each sub-process. For now, I have added a -DINSTDIR /usr/local/bin to the makefile to build cc with the path defined. It would be nice to build cc so that the tool-chain can be run from any directory it is copied to (that has a path set to it). Any ideas on the best/proper way to do this?

Thanks again for all your work on this.

Dave.
 
Last edited:
I agree that the kernel itself wouldn't need FP support, but I think it would be nice to have it implemented in the Compiler for those who wish to use it.
Yes. I think I might do the FP port as well, but not right away. After week 8 doing the port started to feel like real work, and this is strictly hobby.

The Cortex FP routines are interesting: they use a 48-bit format, which is unusual, "one-and-a-half precision" so to speak. Other than that it appears to use the hex base format that is apparently the native format for the ti990 series. They don't look all that optimised at first glance.

Attached is a commented disassembly of the single precision FP routines from MDEX QBasic. They look like somebody thought about every clock tick in those routines: the conditional jumps seem organised such that the most common code path is fastest. One night I tried to understand the division algorithm but I could not grasp it; never found the time to sit down once more for another try. Anybody feel intrigued?

For clarity sake: there is a similar library with the double precision version of these routines on the MDEX QBasic disk.
 

Attachments

  • floating.txt
    8.6 KB · Views: 1
Thanks for updating the repository with the latest files. I got it all built and it works fine. I have a couple of questions:

1) Are you planning on any more changes (floating point perhaps)? I want to start tweaking it for Cortex use and don't want to deviate too from your 'masters' if there are more changes to come.

Happy to hear that you could replicate it. Yes, I'm planning more changes. However, I am accepting patches, so your version can stay current.

2) As you said, the paths in cc are hard coded. As supplied, they are set to './' which only works if you are working in the bin99 directory. If a path is set to bin99 or the files are copied to /usr/local/bin, then it errors saying it can't find ./cpp. So, if you are in ./myproject and do a 'cc -o prog prog.c, cc will execute fine but fail on the call to each sub-process. For now, I have added a -DINSTDIR /usr/local/bin to the makefile to build cc with the path defined. It would be nice to build cc so that the tool-chain can be run from any directory it is copied to (that has a path set to it). Any ideas on the best/proper way to do this?

Yeah, this needs to be fixed. On linux and osx the binaries need different names (cc99, ld99, etc.), because they would otherwise shadow the normal system programs of the same name. Rather than a fixed path, I was thinking to do a relative path, i.e. cc finds as and ld in the same directory as itself (e.g. /local/bin/) and c0, c1, crt0.o, etc. in "../lib" relative to its own directory. Finding out the full path of the current process is not standardised though, so would need some #ifdef'ing for each os.
http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe

Want to submit a patch that works with Cygwin? I'll do the patch for osx.

Paul
 
Want to submit a patch that works with Cygwin? I'll do the patch for osx.

Paul

I might give it a go with what little I know...

Is there a way of doing conditional assembly in 'as'? Your start.s builds what is effectively a ROM image, where I'd like to build a Cortex .cas cassette image like I did in C99. It strikes me beneficial to have both options in the start.s file, rather than two separate files. I know how to do this in the TI assemblers but not this unixified one!

Thanks,

Dave.
 
Last edited:
I might give it a go with what little I know...

Could you test for me that the following program indeed prints its own directory on Cygwin? It works on Linux, and professor Google tells me that Cygwin offers a Linux-like /proc pseudo file system.
Code:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/param.h>

char buf[MAXPATHLEN+1];

main()
{
	int n;
	char *p;

	n = readlink("/proc/self/exe", buf, MAXPATHLEN);
	if (n>0) {
		buf[n] = '\0';
		p = strrchr(buf,'/');
		if (p) p[1] = '\0';
		printf("%s\n", buf);
	}
	else {
		printf("readlink failed\n");
	}
}

Is there a way of doing conditional assembly in 'as'? Your start.s builds what is effectively a ROM image, where I'd like to build a Cortex .cas cassette image like I did in C99. It strikes me beneficial to have both options in the start.s file, rather than two separate files.

1. If you call 'as' via 'cc', the C preprocessor is invoked first, so you can use #ifdef, etc.

2. Richard Miller had .if & friends implemented, but I jettisoned that code. If you need it I can put it back. Also, I realise I need to do a documentation page for the assembler, otherwise everybody will feel lost.

3. Actually, I think that doing separate files for the startup code might be the better way to go. I'm currently in the process of building standard libraries and most of the code in the 'crt' directory will go into a /lib/libcrt.a file. Then 'crt0.o' will only contain 'start.s'. Your version of start.s (say 'crtx.s') would be placed in say 'crtx0.o' and 'cc' would be modified to use crtx0.o instead of crt0.o, depending on a compiler flag ('-c' and '-p' are taken, how about '-z'?). It could even automatically call your a.out to cassette conversion program as the last build step, if that -z flag is specified.

Under option 3, compiling a cassette file for the Cortex would be as easy as typing:
Code:
c99 -z -O -o main.cas main.c

Could you let me know (by private mail if it is lengthy) what changes you need to the Makefiles? I'd like to get it to a level where it builds for you 'out of the box'.

Paul
 
Could you test for me that the following program indeed prints its own directory on Cygwin? It works on Linux, and professor Google tells me that Cygwin offers a Linux-like /proc pseudo file system.
Code:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/param.h>

char buf[MAXPATHLEN+1];

main()
{
	int n;
	char *p;

	n = readlink("/proc/self/exe", buf, MAXPATHLEN);
	if (n>0) {
		buf[n] = '\0';
		p = strrchr(buf,'/');
		if (p) p[1] = '\0';
		printf("%s\n", buf);
	}
	else {
		printf("readlink failed\n");
	}
}


Paul

Hi Paul,

I ran this on Cygwin and it works great. Firstly I built it in a local directory and it reported that correctly. Then I moved it to /usr/local/bin (which of course there is a PATH to) and it reported that directory, even though I was still in the original local one. Good find!

Dave.
 
1. If you call 'as' via 'cc', the C preprocessor is invoked first, so you can use #ifdef, etc.

2. Richard Miller had .if & friends implemented, but I jettisoned that code. If you need it I can put it back. Also, I realise I need to do a documentation page for the assembler, otherwise everybody will feel lost.

3. Actually, I think that doing separate files for the startup code might be the better way to go. I'm currently in the process of building standard libraries and most of the code in the 'crt' directory will go into a /lib/libcrt.a file. Then 'crt0.o' will only contain 'start.s'. Your version of start.s (say 'crtx.s') would be placed in say 'crtx0.o' and 'cc' would be modified to use crtx0.o instead of crt0.o, depending on a compiler flag ('-c' and '-p' are taken, how about '-z'?). It could even automatically call your a.out to cassette conversion program as the last build step, if that -z flag is specified.

Under option 3, compiling a cassette file for the Cortex would be as easy as typing:
Code:
c99 -z -O -o main.cas main.c

Could you let me know (by private mail if it is lengthy) what changes you need to the Makefiles? I'd like to get it to a level where it builds for you 'out of the box'.

Paul

Email sent regarding my mods to the tool-chain.

No big deal if .if isn't added back in to 'as' but some kinda cheat-sheet could come in handy as it's significantly different to the TI standard (took me ages to figure out how .byte, .data and .bss worked!).

I like the sound of a -z option. I'd be happy to add that in once we get the build standardized etc.

Dave.
 
... but some kinda cheat-sheet could come in handy as it's significantly different to the TI standard (took me ages to figure out how .byte, .data and .bss worked!).

Have a look at this:
http://1587660.websites.xs4all.nl/cgi-bin/9995/doc/tip/doc/old-as.pdf
It is for Ritchie's pdp11 assembler, but Miller's assembler is a work alike. Some differences though: // to introduce a comment, numbers follow C syntax (decimal by default), .if not implemented, etc. I will use this text as the base for my to-be-done 'as99' documentation.

I've just commited the changes to 'cc99' to make it work with relative paths. I'm adding standard libraries, but that is work in progress. So that you don't get stuck, I've temporarily added stub libraries to the repo. Alternatively, you could just replace 'cc.c' and leave the rest the same. Let me know if it works for you.

Cleaning up the Makefiles is next.

Paul
 
Back
Top