⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isp8asm.c

📁 Lattice 超精简8位软核CPU--Mico8
💻 C
📖 第 1 页 / 共 2 页
字号:
		case 't':
			nc = '\t';
			break;
		default:
			break;
		}
	}
	if (GETC() != '\'') {
		error_exit("invalis character constant");
	}
	return nc;
}

/* parse constant */
static uint32 parse_const()
{
	char nc;
	char token[MAX_TOKEN_SIZE];
	stab *esym;

	nc = GETC();
	UNGETC();
	if (isdigit(nc) || nc == '+' || nc == '-') {
		return parse_num();
	}
	if (nc == '\'') {
		return parse_char();
	}
	if (nc == '$') {
		GETC(); /* skip the $ */
		return loc_counter;
	}
	/* must be an equate; lookit up */
	get_token(token,"\n");
	if (!(esym = sym_find(token,SYM_EQU))) {
		error_exit("expected constant or equated symbol, found %s",
			   token);
	}
	return esym->value;
}

/* parse registers */
static uint32 parse_reg(uint32 maxreg)
{
	char nc;
	uint32 regno;

	nc = skip_space();
	if (toupper(nc) != 'R') {
		error_exit("excpected register");
	}
	GETC(); /* skip r */
	regno = parse_num();
	if (regno >= maxreg) {
		error_exit("invalid register number :"
			   " expected reg number < R%d",maxreg-1);
	}
	return regno;
}

/* parse instructions */
static int parse_instr()
{
	char nc;	
	itab *itabp;
	int  ops = 0;
	int fopcode = 0 ;
	int  rd = 0 , rb = 0 ;
	uint32  konst = 0, port = 0;
	stab *label = NULL;

	nc = skip_space();
	if (!nc) return 0;
	nc = get_token(token,"\n:");
	if (!isspace(nc)) {
		UNGETC();
	}

	/* if next character is a ':' then this is
	   a label definition */
	nc = skip_space();
	if (nc == ':') {
		parse_label_def(token);
		return 1;
	} else {
		UNGETC();
	}

	if ((itabp = itab_find(token)) == NULL) {
		error_exit("unrecognized instruction mnemonic '%s'",token);
		return 0;
	}
	
	/* found instruction entry */
	for (ops = 0 ; ops < itabp->nops ; ops++) {
		switch (itabp->optypes[ops]) {
		case OP_REGD:
			rd = parse_reg(MAX_REG);
			break;
		case OP_REGB:
			rb = parse_reg(MAX_REG);
			break;
		case OP_CONST:
			konst = parse_const();
			fopcode |= 1 << 13;
			break;
		case OP_LABEL:
			label = parse_label_ref();
			fopcode |= 1 << 13;
			break;
		case OP_PORT:
			port = parse_const();
			break;
		}
		/* if not last then separator must be present */
		if (ops  != (itabp->nops - 1)) {
			nc = skip_space();
			if (nc != ',') {
				error_exit("expected ',' after first operand");
			}
			GETC();
			nc = skip_space();
		}
	}
	fopcode |= itabp->opcode;
	fopcode |= (rd & 0x1f) << 8;
	fopcode |= (rb & 0x1f) << 3;
	fopcode |= (konst & 0xff);
	fopcode |= (port & 0x01f) << 3;

	code_insert(itabp, fopcode, rd, rb, konst, label, NULL, port, 0);
	return 1;
}

/* go thru the code and resolve
   all label references */
static void resolve_labels()
{
	code *codep = croot;

	while (codep) {
		if (codep->label_ref) {
			int diff;
                        if (codep->label_ref->loc_counter == -1) {
				error_exit("undefined label %s", 
					   codep->label_ref->name);
			}
			diff = (codep->label_ref->loc_counter - codep->loc_counter);
			if ((codep->opcode == 0X00033000) || (codep->opcode == 0X00037000)) {
                           // unconditional branch/call
			   if ((diff > 2047) || (diff < -2048)) {
					line_no = codep->line_no;
					error_exit("branch out of range; must be"
						   " within +2047/-2048 instructions");
			   }
				codep->opcode |= ((codep->label_ref->loc_counter -
				   codep->loc_counter) & 0xFFF);
			}
			else {
			   if ((diff > 511) || (diff < -512)) {
					line_no = codep->line_no;
					error_exit("branch out of range; must be"
						   " within +511/-512 instructions");
			   }
				codep->opcode |= ((codep->label_ref->loc_counter -
				   codep->loc_counter) & 0x3FF);
			}
		}
		codep = codep->next;
	}
}

static void print18bits(uint32 val, FILE *of)
{
	int i;

	for (i = 0 ; i < 18; i++) {
		fprintf(of,"%c", (val & (1 << 17)) ? '1' : '0');
		val <<= 1;
	}
}

static void print_listing(code *codep)
{
	int i;

	fprintf(lfile,"0x%04X\t",codep->loc_counter);
	if (codep->flags & CODE_ISLDEF) {
		fprintf(lfile,"\t%s:\n",codep->label_def->name);		
		return ;
	}
	fprintf(lfile,"0x%05X\t",codep->opcode);
	print18bits(codep->opcode,lfile);
	if (codep->flags & CODE_ISDATA) {
		fprintf(lfile,"\t.data\t%d\n",codep->opcode);
		return ;
	}
	fprintf(lfile,"\t%s\t",codep->itabp->opname);
	
	for (i = 0 ; i < codep->itabp->nops; i++) {
		switch (codep->itabp->optypes[i]) {
		case OP_REGD:
			fprintf(lfile,"R%02d",codep->rd);
			break;
		case OP_REGB:
			fprintf(lfile,"R%02d",codep->rb);
			break;
		case OP_CONST:
			fprintf(lfile,"0x%02X",codep->konst & 0xff);
			break;
		case OP_LABEL:
			fprintf(lfile,"%s",codep->label_ref->name);
			break;
		case OP_PORT:
			fprintf(lfile,"#%d",codep->port);
			break;
		}
		/* if not last then separator must be present */
		if (i  != (codep->itabp->nops - 1)) {
			fprintf(lfile,",");
		}
	}
	fprintf(lfile,"\n");
}

static void print_code(int opcode)
{
	if (omode == OBIN) {
		print18bits(opcode,ofile);
		fprintf(ofile,"\n");
	} else if (omode == OHEX) {
		fprintf(ofile,"%05X\n",opcode);
	} else {
		// push it into the stack , printed later
		// in output_code()
		vmstack[vmsp++] = opcode; 
	}
}

static void output_verilog()
{
	int i, j;

	if (vmsp % 16) {
		error_exit("prom size must be multiple of 16. %d",vmsp - 1);
	}
	
	fprintf(ofile,"`ifdef INIT_DEFPARAM\n");
	// output def param first
	for (i = 0, j = 0; i < vmsp; i += 16 ) {		
		int k;
		fprintf(ofile,"\tdefparam prom_0_0_0.INITVAL_%02X = 320'h",j);
		for (k = i+15 ; k >= i ; k--) {
			fprintf(ofile,"%05X",vmstack[k]);
		}
		fprintf(ofile,";\n");
		j++;
	}
	fprintf(ofile,"`endif\n");

	fprintf(ofile,"`ifdef INIT_SYNTHESIS\n");
	// synthesis initvals
	for (i = 0, j = 0; i < vmsp; i += 16 ) {		
		int k;
		fprintf(ofile,"\t/* synthesis INITVAL_%02X=\"0x",j);
		for (k = i+15 ; k >= i ; k--) {
			fprintf(ofile,"%05X",vmstack[k]);
		}
		fprintf(ofile,"\" */\n");
		j++;
	}
	fprintf(ofile,"`endif\n");
	
	// exemplar initvals
	fprintf(ofile,"`ifdef INIT_EXEMPLAR\n");	
	for (i = 0, j = 0; i < vmsp; i += 16 ) {		
		int k;
		fprintf(ofile,"\t// exemplar attribute prom_0_0_0 INITVAL_%02X ",j);
		for (k = i+15 ; k >= i ; k--) {
			fprintf(ofile,"%05X",vmstack[k]);
		}
		fprintf(ofile,"\n");
		j++;
	}
	fprintf(ofile,"`endif\n");
	
	// synplicity bug patch edif file
	if (eifile && eofile) {
		static char ebuff[MAX_LINE_SIZE];
		char *neof = NULL;
		// copy to output file till first 'property INITVAL_" string
		while ((neof = fgets(ebuff,MAX_LINE_SIZE,eifile))) {
			if (strstr(ebuff,"property INITVAL_")) break;
			fputs(ebuff,eofile);
		}
		if (neof) {
			for (i = 0, j = 0; i < vmsp; i += 16 ) {		
				int k;
				fprintf(eofile,
					"\t(property INITVAL_%02X (string \"0x",j);
				for (k = i+15 ; k >= i ; k--) {
					fprintf(eofile,"%05X",vmstack[k]);
				}
				fprintf(eofile,"\"))\n");
				j++;
			}
			// skip thru rest of INITVALs
			while (fgets(ebuff,MAX_LINE_SIZE,eifile)) {
				if (strstr(ebuff,"property INITVAL_")) continue;
				break;
			}
			// copy rest of it to output
			do {
				fputs(ebuff,eofile);
			} while (fgets(ebuff,MAX_LINE_SIZE,eifile));
		}
	}
}

static void output_vhdl()
{
	int i, j;

	if (vmsp % 16) {
		error_exit("prom size must be multiple of 16. %d",vmsp - 1);
	}
	
	/* attribute values */
	fprintf(ofile,"library ieee;\n");
	fprintf(ofile,"use ieee.std_logic_1164;\n");
	fprintf(ofile,"package prominitpackage is\n");
	for (i = 0, j = 0; i < vmsp; i += 16 ) {		
		int k;
		fprintf(ofile,"\tconstant INITVAL_%02X_str : string := \"0x",j);
		for (k = i+15 ; k >= i ; k--) {
			fprintf(ofile,"%05X",vmstack[k]);
		}
		fprintf(ofile,"\";\n");
		j++;
	}
	fprintf(ofile,"end prominitpackage;\n");
}

static void output_code()
{
	code *codep ;
	int last_lc = 0;

	if (lfile) {
		fprintf(lfile,"Loc\tOpcode\tOpcode\t\n");
		fprintf(lfile,"Counter\t(Hex)\t(Bin)\n");
	}
	/* allocate space for vhdl/verilog init */
	vmstack = (int *) malloc((sizeof(int))*prom_size);
	for (codep = croot; codep; codep = codep->next) {
		if (lfile) {
			print_listing(codep);
		}
		if (codep->flags & CODE_ISLDEF) continue;
		if ((codep->loc_counter - last_lc) > 1) {
			/* fill with zero */
			while ((codep->loc_counter - 1) > last_lc) {
				last_lc++;
				print_code(0);
			}
		}
		print_code(codep->opcode);
		last_lc = codep->loc_counter;
	}
	/* fill the rest of program rom with zeros */
	for (;last_lc < prom_size - 1; last_lc++) {
		print_code(0);
	}

	if (omode == OVER) {		
		output_verilog();
	} else if (omode == OVHD) {
		output_vhdl();
	}
}

static void parse_line()
{
	char nc;
	
	nc = skip_space();	
	if (nc == COMMENT_CHAR) return ;
	if (nc == '\n') return;
	GETC();
	/* must be something recognizable.
	   instruction or directive */
	if (nc == '.') {
		parse_direct();
	} else {
		UNGETC();
		parse_instr();
	}	
}

static void print_usage(char *pname)
{
	printf("%s Usage : [options] input-file-name\n", pname);
	printf("options:\n");
	printf("\t[-o <filename>] : output filename (default STDOUT)\n");
	printf("\t[-s <size>] : program rom size (default 512)\n");
	printf("\t[-l <filename>] : generate assembler listing\n");
	printf("\t[-vx] : output hexadecimal data(default)\n");
	printf("\t[-vb] : output binary data\n");
        printf("\t[-vm] : output Lattice memory format\n");
	printf("\t[-ve] : output verilog init format\n");
	printf("\t[-vh] : output vhdl init format>\n");
	printf("\t-? <this message>\n");
}

int main(int argc, char *argv[])
{
	int i;

	if (argc < 1 ) {
		print_usage(argv[0]);
		exit(-1);
	}

	for (i = 1 ; i < argc; i++) {
		if (argv[i][0] == '-') {
			switch(argv[i][1]) {
			case 'o':
				i++;
				ofilename = strdup(argv[i]);
				break;
			case 'l':
                                i++;
                                lfilename = strdup(argv[i]);
				lgen = 1;				
				break;
			case 's':
				i++;
				sscanf(argv[i],"%d",&prom_size);
				break;
			case 'v':
				switch (argv[i][2]) {
				case 'x':
					omode = OHEX;
					break;
				case 'b':
					omode = OBIN;
					break;
				case 'e':
					omode = OVER;
					break;
				case 'h':
					omode = OVHD;
					break;
				default:
					fprintf(stderr,
						"invalid output option\n"
						"\t-vx - hex, -vb binary, -vh - vhdl, -ve verilog\n");
				}
				break;
			case 'e':
				switch (argv[i][2]) {
				case 'i':
					i++;
					if (!(eifile=fopen(argv[i],"r"))) {
						fprintf(stderr,"cannot open input edif file\n");
						exit(-1);
					}
					break;
				case 'o':
					i++;
					if (!(eofile=fopen(argv[i],"w"))) {
						fprintf(stderr,"cannot open output edif file\n");
						exit(-1);
					}
					break;
				}
				break;
			case '?':
				print_usage(argv[0]);
				exit(0);
				break;
			default:
				fprintf(stderr,"invalid option %s\n",argv[i]);
				print_usage(argv[0]);
				break;
			}
		} else {
			/* assume it is the input file */
			ifilename = (char *) strdup(argv[i]);
			if (!(infile = fopen(ifilename,"r"))) {
				error_exit("unable to open file %s\n",ifilename);
			}
		}
	}
	if ((eifile && !eifile) || (!eifile && eofile)) {
		fprintf(stderr,"both input and output edif files must be provided\n");
		exit(-1);
	}
	if (!ifilename) {
		fprintf(stderr,"input file name missing\n");
		print_usage(argv[0]);
		exit(-1);
	}

	if (ofilename) {
		if (!(ofile=fopen(ofilename,"w"))) {
			error_exit("unable to open output file %s",ofilename);
		}
	} else {
		ofile = stdout;
	}
	if (lgen) {
		if (!(lfile=fopen(lfilename,"w"))) {
			error_exit("unable to open listing file %s",lfilename);
		}
	} else {
		lfile = NULL;
	}

	while (get_line()) {
		parse_line();
	}
	resolve_labels();	
	output_code();

	if (lfile) fclose(lfile);
        return(0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -