OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gen_or1k_isa/] [sources/] [gen_or1k_isa.c] - Rev 1773

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 * $Log: not supported by cvs2svn $
 * Revision 1.10  2003/01/28 03:49:24  lampret
 * Added cvs log keywords
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define NO_RELOC 20
#define RELOC_32 1
#define RELOC_8 2
#define RELOC_CONST 3
#define RELOC_CONSTH 4
 
#define EX_NONE		"None"
#define EX_NA_N		"N"
#define EX_NA_A		"A"
#define EX_RANGE	"Range Exception"
#define EX_TRAP		"Trap Exception"
#define EX_TLB		"TLB miss"
#define EX_PAGE		"Page fault"
#define EX_BUSER	"Bus error"
 
#include "opcode/or32.h"
#include "or1k_isadesc.h"
 
/* types of data in encoding field. */
typedef enum { opcode, reserved, operand } encfld_types;
 
/* encoding transformed for TeX output */
struct {
	int bitpos[33];
	int fldcnt;
	int insn_size;
	struct {
		encfld_types type;
		int value;
		int bitsize;
	} field[50];
} decoded;
 
struct info {
	struct or1k_isa *desc;
	struct or32_opcode *opcode;
} info;
 
void transform_tex(char *input, char *output)
{
/*	printf("\n\ninput: %s\n", input); */
	while (*input != '\0') {
		if (strncmp(input, "vector/floating-point", strlen("vector/floating-point")) == 0) {
			strcpy(output, "general-purpose");
			output += strlen("general-purpose");
			input += strlen("vector/floating-point") - 1;
		} else if (strncmp(input, "vfr", 3) == 0) {
			*output++ = 'r';
			input += 2;
		} else if (*input == '[') {
			*output++ = '{';
			*output++ = '[';
			*output++ = '}';
		} else if (*input == ']') {
			*output++ = '{';
			*output++ = ']';
			*output++ = '}';
		} else if (*input == '%') {
			*output++ = '\\';
			*output++ = '%';
		} else if (*input == '\\') {
			*output++ = '\\';
			*output++ = '\\';
		} else if (*input == '_') {
			*output++ = '\\';
			*output++ = '_';
		} else if (*input == '\t') {
			*output++ = '\\';
			*output++ = 'i';
			*output++ = 'n';
			*output++ = 'd';
			*output++ = 'e';
			*output++ = 'n';
			*output++ = 't';
			*output++ = ' ';
		} else if (*input == '<') {
			*output++ = '$';
			*output++ = '<';
			*output++ = '$';
		} else if (*input == '&' && *(input + 1) == '&') {
			*output++ = '\\';*output++ = '&';
			*output++ = '\\';*output++ = '&';
			/**output++ = 'v';*output++ = 'e';*output++ = 'r';*output++ = 'b';
			*output++ = '*';*output++ = '&';*output++ = '&';*output++ = '*';*/ input++;
		} else
			*output++ = *input;
		input++;
	}
	*output = '\0';
/*	printf("output: %s\n\n", output); */
}
void eliminate_slash(char *input, char *output)
{
	while (*input != '\0') {
		if (*input == '\\') {
			*output++ = '\n';
			*output++ = '\n';
		}
		else
			*output++ = *input;
		input++;
	}
	*output = '\0';
}
void eliminate_crcr(char *input, char *output)
{
	while (*input != '\0') {
		if (*input == '\\') {
/*			*output++ = '{';
			*output++ = '[';*/
		} else
			*output++ = *input;
		input++;
	}
	*output = '\0';
}
 
void print_encoding()
{
	int i, j;
 
	printf("\\vspace{10mm}\n");
	printf("{\\centering \\begin{tabular}{");
 
	/* organization of the table */
	for(i = 1; i <= decoded.fldcnt; i++) {
		printf("|");
		for(j = 0; j < decoded.field[i].bitsize; j++)
			if (j == 0)
				printf("l");
			else if (j+1 == decoded.field[i].bitsize)
				printf("r");
			else
				printf("c");
	}
	printf("|}\n\\hline\n");
 
	/* print first row of the table */
	for(i = decoded.insn_size - 1; i > 0; i--)
		if (decoded.bitpos[i]) 
			printf("{\\footnotesize\\hspace{-0.5mm}\\hfil%d\\hfil}&\n", i);
		else
			printf("{\\footnotesize\\hspace{-1.5mm}\\hfil.\\hfil}&\n");
	printf("0\\\\\n\\hline\n");
 
	/* print second row of the table */
	for(i = 1; i <= decoded.fldcnt; i++) {
		if (decoded.field[i].type == opcode) {
			printf("\\multicolumn{%d}{", decoded.field[i].bitsize);
			printf("%s", (i == 1 ? "|":""));
			printf("c|}{\\small{opcode 0x%x}}", decoded.field[i].value);
		} else if (decoded.field[i].type == operand) {
			printf("\\multicolumn{%d}{", decoded.field[i].bitsize);
			printf("%s", (i == 1 ? "|":""));
			printf("c|}{\\small{%c }}", decoded.field[i].value);
		} else if (decoded.field[i].type == reserved) {
			printf("\\multicolumn{%d}{", decoded.field[i].bitsize);
			printf("%s", (i == 1 ? "|":""));
			printf("c|}{\\small{reserved}}", decoded.field[i].value);
		}
		if (i == decoded.fldcnt)
			printf("\\\\\n");
		else
			printf("&\n");
	}
	printf("\n\\hline\n");
 
	/* print third row of the table */
	for(i = 1; i < decoded.fldcnt; i++) {
		printf("\\multicolumn{%d}", decoded.field[i].bitsize);
		printf("{%sc|}{\\small{%d bits}}&\n", (i == 1 ? "|":""), decoded.field[i].bitsize);
	}
        printf("\\multicolumn{%d}", decoded.field[i].bitsize);
        printf("{%sc|}{\\small{%d}bits}\\\\\n", (i == 1 ? "|":""), decoded.field[i].bitsize);
	printf("\n\\hline\n");
/*	printf("\\multicolumn{32}");
/*	printf("{|c|}{\\textcolor{white}{XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX ");
	printf("XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX}}\\\\\n");*/
        printf("\\end{tabular}\\par}\n");	
}
 
void transform_except(char *input, char *output)
{
	char *pTmp = NULL;
 
	pTmp = (char*)strtok(input, "\\");
	while (pTmp) {
		if (strcmp(pTmp, EX_RANGE) == 0) *output++ = 'R';
		if (strcmp(pTmp, EX_NA_N)  == 0) *output++ = '-';
		if (strcmp(pTmp, EX_NA_A)  == 0) *output++ = '-';
		if (strcmp(pTmp, EX_TRAP)  == 0) *output++ = 'T';
		if (strcmp(pTmp, EX_TLB)   == 0) *output++ = 'M';
		if (strcmp(pTmp, EX_PAGE)  == 0) *output++ = 'P';
		if (strcmp(pTmp, EX_BUSER) == 0) *output++ = 'B';
 
		pTmp = (char*)strtok(NULL, "\\");
	}
	*output = '\0';
}
 
void print_reference(int newtable, struct or32_opcode *insn, struct or1k_isa *info)
{
        char tmp[2000];
	char tmp2[2000];
        int i,j;
 
        if (newtable) {
		printf("\\footnotesize\n");
		printf("\\begin{longtable}[t]{|p{2.3cm}|p{2cm}|p{6cm}|p{6cm}|p{0.6cm}|}\n");
		printf("\\hline\n");
		printf("\\normalsize ISN &\n");
		printf("\\normalsize Name &\n");
		printf("\\normalsize Description &\n");
		/*printf("\\normalsize Usage &\n");*/
		printf("\\normalsize Action &\n");
		printf("\\normalsize ex. \\\\\n");
		printf("\\hline\n");
		printf("\\endhead\n");
		printf("\\hline\n");
		printf("\\endfoot\n");
        }
        else {
		transform_tex(insn->name, tmp);
		transform_tex(insn->args, tmp2);
		printf("{\n\n\\raggedright %s %s} &\n", tmp, tmp2);
		transform_tex(info->title, tmp);
		printf("\\raggedright %s &\n", tmp);
		transform_tex(info->desc, tmp);
		printf("%s &\n", tmp);
		/*
		  transform_tex(insn->args, tmp);	
		  transform_tex(insn->name, tmp2);	
		  printf("%s %s &\n", tmp2, tmp);	
		*/
		eliminate_slash(info->oper32, tmp);
		transform_tex(tmp, tmp2);
		printf("{\n");
		printf("%s} &\n", tmp2);
		/*
		transform_tex(info->oper64, tmp);
		printf("{\n");
		printf("%s} &\n", tmp);
		*/
		tmp[0] = 0;
		strcpy(tmp2, info->except);
		transform_except(tmp2, tmp);
		printf("%s \\\\\n", tmp);
 
		printf("\\hline\n");
        }
}
 
void print_summary(int newtable, struct or32_opcode *insn, struct or1k_isa *info)
{
	char tmp[2000];
	char tmp2[2000];
	int i, j, k;
 
 
	if (newtable) {
 
		printf("{\\centering \\begin{tabular}{|l");
 
		/* organization of the table */
		for(i = 1; i <= decoded.fldcnt; i++) {
			printf("|");
			for(j = 0; j < decoded.field[i].bitsize; j++)
				if (j == 0)
					printf("l");
				else if (j+1 == decoded.field[i].bitsize)
					printf("r");
				else
					printf("c");
		}
		printf("|}\n");
		printf("Insn&\n");
 
		/* print first row of the table */
		for(i = decoded.insn_size - 1; i > 0; i--)
			if (decoded.bitpos[i])
				printf("%d&\n", i);
			else
				printf("%d&\n");
		printf("0\\\\\n");
	}
	else {
		printf("\\multicolumn{1}{|c}{}&\n");
		k = 31;
		for(i = 1; i <= decoded.fldcnt; i++) {
			for(j = 0; j < decoded.field[i].bitsize; j++) {
				if (j == 0)
					printf("\\multicolumn{1}{|l");
				else if (j+1 == decoded.field[i].bitsize)
					printf("\\multicolumn{1}{|r");
				else
					printf("\\multicolumn{1}{|c");
				if (k)
					printf("}{%d}&\n", k);
				else
					printf("}{%d}\\\\\n", k);				
				k--;
			}
		}
	}
 
	printf("\\multicolumn{1}{|l|}{");
	transform_tex(info->name, tmp);
	printf("%s}&\n", tmp);
 
	/* print second row of the table */
	for(i = 1; i <= decoded.fldcnt; i++) {
		if (decoded.field[i].type == opcode) {
			printf("\\multicolumn{%d}{", decoded.field[i].bitsize);
			printf("%s", (i == 1 ? "|":""));
			printf("c|}{opcode 0x%x}", decoded.field[i].value);
		} else if (decoded.field[i].type == operand) {
			printf("\\multicolumn{%d}{", decoded.field[i].bitsize);
			printf("%s", (i == 1 ? "|":""));
			printf("c|}{%c}", decoded.field[i].value);
		} else if (decoded.field[i].type == reserved) {
			printf("\\multicolumn{%d}{", decoded.field[i].bitsize);
			printf("%s", (i == 1 ? "|":""));
			printf("c|}{reserved}", decoded.field[i].value);
		}
		if (i == decoded.fldcnt)
			printf("\\\\\n");
		else
			printf("&\n");
	}
	printf("\n");
 
	/* print third row of the table */
/*	printf("\\multicolumn{10}{|c|}{");
	transform_tex(info->name, tmp);
	printf("%s ", tmp);
	transform_tex(insn->args, tmp);
	printf("%s}&\n", tmp);
	printf("\\multicolumn{22}{c|}{");
	eliminate_crcr(info->desc, tmp2);
	transform_tex(tmp2, tmp);
	printf("%s}\\\\\n", tmp); */
 
 
}
 
void decode(struct or32_opcode *insn)
{
        int opc_pos = 0;
        char *enc;
        encfld_types last;
        char lastoperand;
        int tmp;
 
	if (!insn) {
		printf("internal error: insn pointer NULL\n");
		return;
	}
 
	memset(&decoded, 0, sizeof(decoded));
 
	if ((insn->name[0] == 'h') && (insn->name[1] == '.'))
	        decoded.insn_size = opc_pos = 16;
	else
		decoded.insn_size = opc_pos = 32;
 
	last = -1;
 
        for (enc = insn->encoding; *enc != '\0'; )
                if ((*enc == '0') && (*(enc+1) == 'x')) {
                        int tmp = strtol(enc, NULL, 16);
                        if (last != opcode) {
                        	decoded.bitpos[opc_pos] = 1;
                        	decoded.bitpos[opc_pos - 1] = 1;
                        	decoded.field[++decoded.fldcnt].type = opcode;
			}
                       	decoded.field[decoded.fldcnt].value <<= 4;
                       	decoded.field[decoded.fldcnt].value += tmp;
                        decoded.field[decoded.fldcnt].bitsize += 4;
                        opc_pos -= 4;
                        enc += 3;
                        last = opcode;
                }
                else if (*enc == '0') {
                       if (last != opcode) {
                        	decoded.bitpos[opc_pos] = 1;
                        	decoded.bitpos[opc_pos - 1] = 1;
                        	decoded.field[++decoded.fldcnt].type = opcode;
			}
                       	decoded.field[decoded.fldcnt].value <<= 1;
                        decoded.field[decoded.fldcnt].bitsize += 1;
                	opc_pos--;
                        enc++;
                        last = opcode;
                }
                else if (*enc == '-') {
                       if (last != reserved) {
                        	decoded.bitpos[opc_pos] = 1;
                        	decoded.bitpos[opc_pos - 1] = 1;
                        	decoded.field[++decoded.fldcnt].type = reserved;
                        }
                       	decoded.field[decoded.fldcnt].value <<= 1;
                        decoded.field[decoded.fldcnt].bitsize += 1;
                        opc_pos--;
                        enc++;
                        last = reserved;
                }
                else if (*enc == '1') {
                       if (last != opcode) {
                        	decoded.bitpos[opc_pos] = 1;
                        	decoded.bitpos[opc_pos - 1] = 1;
                        	decoded.field[++decoded.fldcnt].type = opcode;
                        }
                       	decoded.field[decoded.fldcnt].value <<= 1;
                       	decoded.field[decoded.fldcnt].value += 1;
                        decoded.field[decoded.fldcnt].bitsize += 1;                
                        opc_pos--;
                        enc++;
                        last = opcode;
                }
                else if (isalpha(*enc)) {
                       if ((last != operand) || (lastoperand != *enc)) {
                        	decoded.bitpos[opc_pos] = 1;
                        	decoded.bitpos[opc_pos - 1] = 1;
                        	decoded.field[++decoded.fldcnt].type = operand;
                        }
                        decoded.field[decoded.fldcnt].value = *enc;
                        decoded.field[decoded.fldcnt].bitsize += 1;                
                        opc_pos--;
                        lastoperand = *enc;
                        enc++;
                        last = operand;
                }
                else
                        enc++;
}
 
void print_header(struct or32_opcode *insn, struct or1k_isa *info)
{
	char tmp[2000];
 
	printf("\n\n\\pagebreak\n");
	printf("\\vspace{10mm}\n");
	/* printf("\\section{Appendix A}\n"); */
	printf("\\lyxline{\\small}\\vspace{-1\\parskip}\n");
	printf("\\vspace{10mm}\n");	
	printf("{\\centering \\begin{tabular}{ccc}\n");
	printf("\\textbf{\\textcolor{white}{\\small Left}}\\textcolor{white}{\\small }&\n");
	printf("\\textcolor{white}{\\small }\\textbf{\\textcolor{white}{\\small Middle \n");
	printf("Middle Middle Middle Middle ");
	printf("Middle Middle Middle Middle ");
	printf("Middle}} \\textcolor{white}{\\small }&\n");
	printf("\\textcolor{white}{\\small }\\textbf{\\textcolor{white}{\\small Right}}\\\\\n");
	transform_tex(insn->name, tmp);
	printf("\\textbf{\\Large %s}&\n", tmp);
	transform_tex(info->title, tmp);
	printf("\\multicolumn{1}{c}{\\textbf{\\Large %s}}&\n", tmp);
	transform_tex(insn->name, tmp);
	printf("\\textbf{\\Large %s}\\\\\n", tmp);
	printf("\\end{tabular}\\par}\n\\bigskip{}\n\n");
}
 
struct or1k_isa *get_or1k_isa(unsigned long classes, struct info *info)
{
	int i;
	struct or1k_isa	*tmp;
 
	while (1) {
		/* Pick first instruction that wasn't printed yet and meets current class constraint */
		for (i = 0; strlen(or1k_isa_info[i].name); i++)
			if ((!or1k_isa_info[i].printed) && ((1<<or1k_isa_info[i].class)>>1 & classes))
				break;
 
		/* Don't return any instruction if they were all already processed or don't meet
		   class constraint. */
		if (strlen(or1k_isa_info[i].name) == 0) {
			fprintf(stderr, "All instructions that meet class constraint %x were processed.\n", classes);
			return NULL;
		}
 
		tmp = &or1k_isa_info[i];
 
		/* Check if tmp instruction is first in order to be processed. If preceeding
		   instructions are found, they are used instead. */
		for (i = 0; strlen(or1k_isa_info[i].name); i++)
			if ((!or1k_isa_info[i].printed) && ((1<<or1k_isa_info[i].class)>>1 & classes) &&
			    (strcmp(or1k_isa_info[i].name, tmp->name) < 0))
				tmp = &or1k_isa_info[i];
 
		tmp->printed = 1;
 
		/* Find matching encoding. */
		for (i = 0; strlen(or32_opcodes[i].name); i++)
			if (strcmp(tmp->name, or32_opcodes[i].name) == 0) {
				fprintf(stderr, "PROCESSING: %s\n", tmp->name);
				info->desc = tmp;
				info->opcode = (struct or32_opcode *) &or32_opcodes[i];
				return tmp;
			}
	}
 
	return NULL;
}
 
void cross_ref_check()
{
	int i, j;
 
	for (i = 0; strlen(or32_opcodes[i].name); i++) {
		for (j = 0; strlen(or1k_isa_info[j].name); j++)
			if (strcmp(or32_opcodes[i].name, or1k_isa_info[j].name) == 0)
				break;
		if (strlen(or1k_isa_info[j].name) == 0)
			fprintf(stderr, "Description for %s missing.\n", or32_opcodes[i].name);
	}
 
	for (i = 0; strlen(or1k_isa_info[i].name); i++) {
		for (j = 0; strlen(or32_opcodes[j].name); j++)
			if (strcmp(or1k_isa_info[i].name, or32_opcodes[j].name) == 0)
				break;
		if (strlen(or32_opcodes[j].name) == 0)
			fprintf(stderr, "Encoding for %s missing.\n", or1k_isa_info[i].name);
	}
}
 
void print_body(struct or32_opcode *insn, struct or1k_isa *info)
{
	char tmp[2000];
 
	printf("\\vspace{15mm}\n");
 
	printf("{\\par \\raggedright \\textbf{\\large Format:}\\large \\par}\n");
	printf("\\vspace{5mm}\n");
	printf("\\begin{quotation}\n");
	transform_tex(info->name, tmp);
	printf("\\texttt{\\large %s\\ ", tmp);
	transform_tex(insn->args, tmp);
	printf("%s}{\\large \\par}\n", tmp);
	printf("\\end{quotation}\n");
	printf("\\vspace{10mm}\n");
 
	printf("\\textbf{\\large Description:}{\\large \\par}\n");
	printf("\\vspace{5mm}\n");
	printf("\\begin{quotation}\n");
	transform_tex(info->desc, tmp);
	printf("%s\n", tmp);
	printf("\\end{quotation}\n");
	printf("\\vspace{10mm}\n");
 
	printf("\\textbf{\\large 32-bit Implementation:}{\\large \\par}\n");
	printf("\\vspace{5mm}\n");
	/*printf("\\begin{flushleft}\n");*/
	printf("\\begin{quotation}\n");
	transform_tex(info->oper32, tmp);
	printf("\\texttt{\\large %s}{\\large \\par}\n", tmp);
	printf("\\end{quotation}\n");
	/*printf("\\end{flushleft}\n");*/
	printf("\\vspace{10mm}\n");
 
	printf("\\textbf{\\large 64-bit Implementation:}{\\large \\par}\n");
	printf("\\vspace{5mm}\n");
	/*printf("\\begin{flushleft}\n");*/
	printf("\\begin{quotation}\n");
	transform_tex(info->oper64, tmp);
	printf("\\texttt{\\large %s}{\\large \\par}\n", tmp);
	printf("\\end{quotation}\n");
	/*printf("\\end{flushleft}\n");*/
	printf("\\vspace{10mm}\n");
 
	printf("\\textbf{\\large Exceptions:}{\\large \\par}\n");
	printf("\\vspace{5mm}\n");
	/*printf("\\begin{flushleft}\n");*/
	printf("\\begin{quotation}\n");
	transform_tex(info->except, tmp);
	printf("\\texttt{\\large %s}{\\large \\par}\n",tmp);
	printf("\\end{quotation}\n");
	/*printf("\\end{flushleft}\n");*/
	printf("\\vspace{10mm}\n");
 
	/*printf("\\textbf{\\large Notes:}{\\large \\par}\n");
	printf("\\vspace{5mm}\n");
	printf("\\begin{quotation}\n");
	printf("\n");
	printf("\\end{quotation}\n");
	printf("\\vspace{10mm}\n");*/
 
	printf("\\vfill\n");
	printf("{\\centering \\begin{tabular}{cc}\n");
	printf("Instruction Class&\n");
	printf(" \\\\\n");
	transform_tex(or1k_isa_classes[info->class].table, tmp);
	printf("%s\n", tmp);
	printf("\\end{tabular}\\par}\n");
 
/*
	printf("\\vfill\n");
	printf("{\\centering \\begin{tabular}{|c|c|}\n");
	printf("\\hline\n");
	printf("Instruction Class&\n");
	printf(" \\\\\n");
	printf("\\hline\n");
	transform_tex(or1k_isa_classes[info->class].table, tmp);
	printf("%s\\hline\n", tmp);
	printf("\\end{tabular}\\par}\n");
*/
 
	printf("\n");
}
 
int main(int argc, char *argv[])
{
	int i, j;
	int mode = 0;
	long classes = -1;
 
	if ((argc >= 2) && (strcmp(argv[1], "-s") == 0))
		mode = 1;
 
	if ((argc >= 2) && (strcmp(argv[1], "-r") == 0))
		mode = 2;
 
	if (argc == 3)
		classes = strtol(argv[2], NULL, 0);
 
	cross_ref_check();
	switch (mode) {
	case 0:
	case 1:
	  printf("\n\\begin{document}\n\\vspace{50mm}");
	  break;
	case 2:
	  printf("\\documentclass[10pt,a4paper,onepage]{article}\n");
	  printf("\\setlength{\\topmargin}{-0.5in}\n");
	  printf("\\setlength{\\textheight}{9.5in}\n");
	  printf("\\setlength{\\evensidemargin}{-1.5cm}\n");
	  printf("\\setlength{\\oddsidemargin}{-1.5cm}\n");
	  printf("\\usepackage{longtable}\n");
	  printf("\\begin{document}\n");
	  printf("\\pagestyle{empty}\n");
	  printf("\\hspace{-3cm}\\noindent\n");
	}
 
	for(i = 0; strlen(or1k_order[i].title); i++) {
		printf("\\section{%s}\n \n \n", or1k_order[i].title);
		j= 0;
 
		while (get_or1k_isa(or1k_order[i].classes, &info)) {
			if (((1 << info.desc->class) & classes) == 0)
				continue;
 
			switch (mode) {
			case 1:
				decode(info.opcode);
				if (j && ((j % 100) == 0))
				        printf("\\end{tabular}\\par}\n");
				print_summary(((j % 100) == 0), info.opcode, info.desc);
				break;
			case 2:
			        decode(info.opcode);
			        print_reference((j == 0), info.opcode, info.desc);
			        break;
			case 0:
				print_header(info.opcode, info.desc);
				decode(info.opcode);
				print_encoding();
				print_body(info.opcode, info.desc);
			}
			j++;
		}
		if ( (mode == 1) && j)
			printf("\\end{tabular}\\par}\n");
		if ( (mode == 2) && j)
		        printf("\\end{longtable}\n");
	}
 
	printf("\n\\end{document}\n");
	return 0;
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.