From: rpw3@rigden.wpd.sgi.com (Rob Warnock)
Newsgroups: comp.lang.verilog
Subject: Re: Simulating processor architectures
Date: 21 Aug 92 04:22:52 GMT
Organization: Silicon Graphics, Inc.  Mountain View, CA

kuttanna@eemips.tamu.edu (Belliappa Kuttanna) writes:
+---------------
|  the gnu CC compiler can generate code using this instruction set.
|  However, I do not know how to generate the Verilog input from the
|  a.out or the assembly code file, without having to develop some 
|  software specifically for this purpose.
+---------------

Actually, the easiest thing would be to "develop some software specifically
for this purpose". That's what I did. I wrote a hack about a year ago I
call "o2rmh", that takes a couple of formats of COFF files (AMD 29000
standard and gas/29k) and writes files suitable for reading into Verilog
with $readmemh(). You use it like this:

	% cat foo.s
	; test 29030 I-cache -- XXX stub only

		.include "std0.h"

		mtsrim CFG, 0           ; enable cache
		mtsrim CPS, 0x73        ; leave FZ mode
		nop                     ; don't jump back here (erratum #4)
		nop

		nop			; ditto
		nop
		nop
		const   v0, 0x1234
	loop:
		jmp     loop            ; tight loop [note "store" in dly slot]
		 store  0, 0, v0, 0x98  ; i.e. loc 98 gets 1234
		nop
		nop

		nop                     ; filler for prefetch
		nop
		nop
		nop

		.end

	% gas29 -o foo.o foo.s

	% o2rmh -o foo.rmh foo.o
	'foo.o': GNU .o/a.out format

	% cat foo.rmh
	// [generated by o2rmh]

	04000300 04000273 70400101 70400101 
	70400101 70400101 70400101 03126034 
	a0000000 1f006098 70400101 70400101 
	70400101 70400101 70400101 70400101 

Then in your Verilog simulation you just $readmemh("foo.rmh", instruction_mem).

Attached below find the source for "o2rmh.c". It's an ugly hack, is missing
many features (relocation, etc.), and may not do what you want, but what do
you expect? I threw it together in an hour or two.

Note: I have *not* included the required AMD-specific include file "coff.h"
(which probably contains licensed AT&T Unix material), so you will have to
fix that part up for yourself. [Hint: Just rip out (or fix) the part that
starts with "if (fh->f_magic == SIPFBOMAGIC)". The demo output above uses
the GNU assembler format, which *is* included.

In any case, you should be able to modify it easily for your format...


-Rob

-----
Rob Warnock, MS-9U/510		rpw3@sgi.com
Silicon Graphics, Inc.		(415)390-1673
2011 N. Shoreline Blvd.
Mountain View, CA  94043


============== attachment ===============================================
/*
** Copyright 1991, 1992 Silicon Graphics Inc.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appears in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation, and that the name of SGI not be used in advertising
** or publicity pertaining to distribution of the software without specific,
** written prior permission.  SGI makes no representations about the
** suitability of this software for any purpose.  It is provided "as is"
** without express or implied warranty.
**
** SGI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SGI
** BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
** WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
** OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
** CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**
**
** Author: Rob Warnock <rpw3@sgi.com>
*/

#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <malloc.h>
#include <string.h>
#include "coff.h"		/* Note: 29000 version of COFF */

struct gnuhdr			/* simpler to copy than include */
{
  u_long a_info;		/* Use macros N_MAGIC, etc for access */
#define GNUOBJMAGIC 0407
  u_long a_text;		/* length of text, in bytes */
  u_long a_data;		/* length of data, in bytes */
  u_long a_bss;			/* length of bss, in bytes */
  u_long a_syms;		/* length of sym tab data in file, in bytes */
  u_long a_entry;		/* start address */
  u_long a_trsize;		/* length of reloc info for text, in bytes */
  u_long a_drsize;		/* length of reloc info for data, in bytes */
};

extern char *optarg;
extern int optind, opterr;
char	*myname;

int	fd;

/*
 * error message routine (non-varargs version):
 * fatal(printf_args...) ==> fprintf(stderr,printf_args...), then exit(errno).
 */

fatal(fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
char * fmt;
int x0,x1,x2,x3,x4,x5,x6,x7,x8,x9;
{
	char real_fmt[1024];
	extern int errno;

	sprintf(real_fmt, "%s: %s\n", myname, fmt);
	fprintf(stderr, real_fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
	exit(errno?errno:EINVAL);
}

/*
 * the usual main program template...
 */
main(int argc, char **argv)
{
	int c, i, n, errs = 0;

	if ((myname = strrchr(argv[0], '/') + 1) == ((char*)NULL) + 1)
		myname = argv[0];

	while ((c = getopt(argc, argv, "o:")) != EOF) switch (c) {
	case 'o':
		if (freopen(optarg, "w", stdout) == NULL)
			fatal("cannot open output file '%s'", optarg);
		break;
	case '?':
	default:  ++errs;
	}
	if (argc - optind < 1 || errs) {
	    fprintf(stderr, "usage: o2rmh [-o outputfile] obj_file(s)...\n");
	    exit(1);
	}

	while (argc - optind > 0)
		read_and_load(argv[optind++]);
	exit(0);
}

/*
 * This version of read_and_load() is about as subtle as a 20 kton nuke
 */
read_and_load(char *fname)
{
#define MONGO (262144 + 20000)		/* max SRAM + room for some syms */
	int fd2 = open(fname, 0);
	static void *fbuf;
	int len;
	struct filehdr	*fh;		/* AMD COFF header */
	struct aouthdr	*ah;
	struct scnhdr	*sh;
	struct gnuhdr	*gh;		/* GNU a.out header */
	u_char		*txtp;
	int		tlen;

	if (fd2 < 0) {
		fatal("Can't open file '%s': %s (%d)\n",
			fname, sys_errlist[errno], errno);
	}
	if (!fbuf && !(fbuf = malloc(MONGO))) {
		fatal("read_and_load: Can't get enough memory\n");
	}
	if ((len = read(fd2, fbuf, MONGO)) < 0) {
		fatal("Error reading file '%s': %s (%d)\n",
			fname, sys_errlist[errno], errno);
	}
	if (len == MONGO) {
		fatal("File '%s' too large\n", fname);
	}
	/*
	 * alias to various possibilities of .o formats
	 */
	fh = (struct filehdr *)fbuf;
	gh = (struct gnuhdr *)fbuf;
	if (fh->f_magic == SIPFBOMAGIC) {	/* first try AMD COFF format */
	    fprintf(stderr, "'%s': COFF .o/a.out format\n", fname);
	    sh = (struct scnhdr *)((u_long)fbuf + sizeof(*fh));
	    if (fh->f_opthdr) {
		ah = (struct aouthdr *)sh;
		sh = (struct scnhdr *)((u_long)sh + fh->f_opthdr);
	    } else
		ah = 0;
	    if (!(sh->s_flags & STYP_TEXT)) {
		fatal("File '%s' 1st section type (%x) not executable text\n",
			fname, sh->s_flags);
	    }
	    txtp = (u_char *)fbuf + sh->s_scnptr;
	    tlen = sh->s_size;
	} else if (gh->a_info == GNUOBJMAGIC) {	/* how about GNU .o? */
	    fprintf(stderr, "'%s': GNU .o/a.out format\n", fname);
	    txtp = (u_char *)fbuf + sizeof(*gh);
	    tlen = gh->a_text;
	} else {
		fatal("File '%s' bad magic number %x, no known Am29000 .o format\n",
			fname, fh->f_magic);
	}
	if (tlen % sizeof(u_long)) {
		fatal("File '%s' text section size (%d) not whole words\n",
			fname, tlen);
	}
	do_dma(txtp, /*opt_LoadAddr,*/ tlen);
	/* opt_LoadAddr += tlen; */		/* assert: tlen%4 == 0 */
}

/*
 * Output image in $readmemh() format.
 * (Historical name, from when the object file
 * would actually get downloaded at this point...)
 */
do_dma(u_char *p, int n)
{
	int i;

	printf("// [generated by o2rmh]\n\n");
	for (i = 0, n/= 4; i < n; ++i) {
		printf("%8.8x ", ((u_long *)p)[i]);
		if (i%4 == 3)
			printf("\n");
	}
	printf("\n");
}
Newsgroups: comp.lang.verilog