[GreenKeys] Mini Makefest in Manchester UK England
Dave G4UGM
dave.g4ugm at gmail.com
Wed Aug 5 05:29:54 EDT 2015
I am sorry to say my SSEM emulator , the "extremely small scale experimental
system", or "baby baby" for short is written in VHDL and runs on a Nexys 3
Spartan 2 board. It can be seen here:-
https://www.youtube.com/watch?v=OGcAmrFoRrY
Very little original code survives. I think there are two programs, one
which is the first program they ran which I think calculates the HCF of
2**18, and to be honest I can't remember what the other is.
Also please note that Turing had, as far as we can tell, nothing to do with
the Baby's design or construction. At the time the SSEM was complete he was
at NPI I believe, but came to Manchester soon after it was complete.
I will send you some more info about Baby programs off-list.
Dave
> -----Original Message-----
> From: GreenKeys [mailto:greenkeys-bounces at mailman.qth.net] On Behalf
> Of Dave Horsfall
> Sent: 05 August 2015 08:33
> To: Greenkeys <greenkeys at mailman.qth.net>
> Subject: Re: [GreenKeys] Mini Makefest in Manchester UK England
>
> On Tue, 4 Aug 2015, Dave G4UGM wrote:
>
> > I am, under the guise of the Manchester Vintage and Retro Computing
> > Club (which is basically me and a couple of other guys), will be
> > having a stand at the Mini MakeFest @ the Museum of Science and
> > Industry , Manchester England. We will be demonstrating RTTY Art under
> > the excuse that many early Manchester computers (Manchester Mk1,
> > Ferranti Pegasus and Mercury) used Creed Teleprinters as output devices.
>
> Goodness gracious me! I've just written an emulator of the SSEM (Small
> Scale Experimental Machine aka "Baby") which was the precursor to the Mk-
> I.
>
> I was wondering where I could express a hope for some live binary code for
> the SSEM (not the Mk-I). Someone (Turing?) wrote a program (via the
> switches alone) to compute the GCD, for example.
>
> Oh, I took the easy approach and coded everything in Big-Endian; the Baby
> had Little for the opcodes and the addresses, but I'm willing to change
that.
>
> Highly beta (it has an interrupt bug), and yes, I have a weird coding
style.
>
> /*
> * An implementation of the SSEM (Small Scale Experimental Machine aka
> Baby;
> * the predecessor of the Manchester Mk I).
> *
> * At least one description is incorrect; it is described as the Mk I
> * itself, which was a 40-bit machine, not 32-bit, and only had 32 words,
> * not 8K. Also index registers, multiply, etc...
> *
> * Flags (maybe):
> *
> * -d Debugging
> * -D Interactive debugger i.e. console-like (or swap with above)
> * -m Memory size (default 32, must be power of two)
> * -M N Set memory to all N
> * -r N Seed for random initialisation of memory (see later)
> * -q No messages
> * -v Verboser messages
> * -x Extensions such as full 8KW, memory-mapped I/O, etc
> * -z Run at original speed (approx 1 KiPS)
> *
> * An instruction has the following format:
> *
> * 31..16 Ignored
> * 15..13 Opcode (seven ops, as two are decoded the same)
> * 12..0 Address (presumably wrapped for 32 words)
> *
> * The instruction set is best described as "minimalist"... Oh, and
> * the addr/opcode bits are LSB -> MSB, but I'm ignoring that for now.
> */
>
> #include <sys/types.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <sys/time.h>
> #include <signal.h>
>
> #define DEFMEM 32 // 32 words by default
> #define MAXMEM (1<<13) // Cannot exceed this
> #define IMASK 0xFFFF // Instruction mask (before shift)
> #define ISHFT 13 // Where the opcode is
> #define OMASK 0x1F // Operand mask (for 32 words)
>
> /*
> * Opcodes (such as they are). Note that on the real SSEM they were
flipped.
> */
> #define JMP 0 // Jump Indirect to address-1
> #define JRP 1 // Jump Relative to address-1
> #define LDN 2 // Load Negative
> #define STO 3 // Store
> #define SUB 4 // Subtract
> #define SUBx 5 // Same due to hardware decoding
> #define CMP 6 // Compare and skip if -ve
> #define STP 7 // Stop
>
> void intr(); // Called at SIGINT in case of loop
> void dump_cpu();
> void dump_mem();
> void kips(); // How fast were we?
> void load(char*); // Load the code
>
> uint* mem; // Memory
> ushort pi; // Present Instruction
> ushort s; // Operand address
> ushort cr; // Control Register i.e. program counter
> int acc; // Accumulator
> int seed = 1; // For randomly initialising memory etc (POSIX
> default)
> int init = 0; // Initial value for memory
> int stopped = 0; // Set by the STP opcode
> uint memsz = DEFMEM; // Size of memory
> uint omask = OMASK; // Operand mask
> long cycles = 0; // No. cycles executed
> struct timeval then, now; // For timing porpoises
> volatile sig_atomic_t interrupted = 0; // Sigh...
>
> char* opcodes[] = { "JMP", "JRP", "LDN", "STO", "SUB", "SUB", "CMP", "STP"
> };
>
> void
> main(int argc, char** argv)
> {
> int i;
> int ch;
> int d_flag = 0; // Debug
> int m_flag = 0; // Memory size specified
> int M_flag = 0; // Initialise memory to this
> int x_flag = 0; // Extended mode
> int z_flag = 0; // Snooze to emulate original speed
>
> // setlinebuf(stdout);
>
> while ((ch = getopt(argc, argv, "dm:M:r:xz")) != -1)
> {
> switch (ch)
> {
> case 'd': // Debugging
> d_flag = 1;
> break;
>
> case 'm':
> m_flag = 1; // Memory size
> memsz = atoi(optarg); // It better be shiftable i.e.
2^N...
> if (memsz > MAXMEM)
> {
> printf("Memory %u cannot exceed %d\n", memsz,
> MAXMEM);
> exit(1);
> }
> if (memsz < DEFMEM)
> {
> printf("Memory %u must be st least %d\n", memsz,
> DEFMEM);
> exit(1);
> }
> omask = memsz - 1;
> break;
>
> case 'M': // Initialise to this
> M_flag = 1;
> init = atoi(optarg);
> break;
>
> case 'r': // Random seed
> seed = atoi(optarg);
> if (seed == 0) // Pick one ourselves
> seed = getpid() * time(NULL);
> break;
>
> case 'x': // Extended mode (maybe)
> x_flag = 1;
> break;
>
> case 'z': // Snooze to emulate real speed
> z_flag = 1;
> break;
>
> case '?': // Needed?
> default:
> printf("Bad flag\n");
> exit(-1);;
> }
> }
>
> argc -= optind;
> argc +- optind;
>
> if (argc != 1)
> {
> printf("Usage: %s [flags] file\n", argv[0]);
> exit(1);
> }
>
> if (x_flag && !m_flag)
> memsz = MAXMEM;
>
> if ((mem = (uint*)malloc(memsz)) == NULL)
> {
> printf("Cannot alloc %u bytes of memory\n", memsz);
> exit(-1);
> }
>
> signal(SIGINT, intr); // So we can stop a loop
>
> // Assumptions...
> cr = 0;
> acc = 0;
>
> // Initialise memory (random for now; will be 0)
> srand(seed);
> for (i = 0; i < memsz; i++)
> mem[i] = M_flag? init : rand();
>
> load(argv[optind]);
>
> dump_mem();
>
> printf("\nCPU trace:\n\n");
>
> gettimeofday(&then, NULL);
>
> while (!stopped && !interrupted)
> {
> cycles++;
> cr &= omask; // Adjust program counter
> pi = (mem[cr] & IMASK) >> ISHFT;// Opcode
> s = mem[cr] & 0x1FFF; // Operand address
>
> dump_cpu();
>
> switch (pi)
> {
> case JMP:
> cr = mem[s & omask];
> break;
>
> case JRP:
> cr += mem[s & omask];
> break;
>
> case LDN:
> acc = -mem[s & omask];
> break;
>
> case STO:
> mem[s & omask] = acc;
> break;
>
> case SUB:
> case SUBx:
> acc -= mem[s & omask];
> break;
>
> case CMP:
> if (acc < 0)
> cr++;
> break;
>
> case STP:
> gettimeofday(&now, NULL);
> printf("\nStopped (%ld cycles):\n\n", cycles);
> stopped = 1;
> dump_cpu();
> printf("\n");
> dump_mem();
> kips();
> break;
> }
>
> if (z_flag)
> // usleep(1000); // Adjust for 1.1 kIPS - 0.7
> usleep(500); // Adjust for 1.1 kIPS - 1.4
> cr++;
> }
>
> if (interrupted)
> {
> gettimeofday(&now, NULL);
> printf("\nInterrupted (%ld cycles)!\n\n", cycles);
> dump_cpu();
> printf("\n");
> dump_mem();
> kips();
> exit(-1);
> }
> }
>
> void
> intr()
> {
> interrupted = 1; // printf() ist verboten
> }
>
> /*
> * Print CPU state.
> */
> void
> dump_cpu()
> {
> cr &= omask;
> printf("cr = %.4x -> %.8x, pi = %d (%s), s = %.4x, acc = %.8x (%d)\n",
> cr, mem[cr], pi, opcodes[pi], s, acc, acc); }
>
> void
> dump_mem()
> {
> int i;
>
> printf("Memory dump (seed %.8x/%d/%u):\n", seed, seed, seed);
>
> // Do ASCII as well?
> // And 8k means 1024 lines!
>
> for (i = 0; i < memsz; i++)
> {
> if ((i % 8) == 0)
> printf("\n%.4x: ", i);
> printf(" %.8x", mem[i]);
> }
>
> printf("\n");
> }
>
> /*
> * Print the bogo-kips for fun.
> */
> void
> kips()
> {
> long took; // Milliseconds
>
> took = ((now.tv_sec-then.tv_sec)*1000) + (now.tv_usec-
> then.tv_usec)/1000;
> if (took == 0)
> printf("\nSpeed of light!\n");
> else
> printf("\n%.2f kIPS\n", (double)cycles/(double)took); }
>
> /*
> * Load the specified object file.
> * The spec is highly fluid right now...
> */
> void
> load(char* file)
> {
> FILE* f;
>
> if ((f = fopen(file, "r")) == NULL)
> {
> perror(file);
> exit(1);
> }
> printf("Loading from %s\n", file);
> fclose(f);
> }
>
> --
> Dave Horsfall DTM (VK2KFU) "Those who don't understand security will
> suffer."
> Watson never said: "I think there is a world market for maybe five
> computers."
> __________________________________________________________
> ____
> GreenKeys mailing list
> Home: http://mailman.qth.net/mailman/listinfo/greenkeys
> Help: http://mailman.qth.net/mmfaq.htm
> Post: mailto:GreenKeys at mailman.qth.net
>
> 2002-to-present greenkeys archive:
> http://mailman.qth.net/pipermail/greenkeys/
> 1998-to-2001 greenkeys archive:
> http://mailman.qth.net/archive/greenkeys/greenkeys.html
> Randy Guttery's 2001-to-2009 GreenKeys Search Tool:
> http://comcents.com/tty/greenkeyssearch.html
>
> This list hosted by: http://www.qsl.net
> Please help support this email list: http://www.qsl.net/donate.html
More information about the GreenKeys
mailing list