diff --git a/sim/erc32/Makefile.in b/sim/erc32/Makefile.in index 108e8b6..d2579a4 100644 --- a/sim/erc32/Makefile.in +++ b/sim/erc32/Makefile.in @@ -21,7 +21,10 @@ TERMCAP_LIB = @TERMCAP@ READLINE_LIB = @READLINE@ -SIM_OBJS = exec.o erc32.o func.o help.o float.o interf.o +# `sis' doesn't need interf.o. +SIS_OFILES = exec.o erc32.o func.o help.o float.o grlib.o leon3.o + +SIM_OBJS = $(SIS_OFILES) interf.o SIM_RUN_OBJS = sis.o SIM_EXTRA_LIBS = $(READLINE_LIB) $(TERMCAP_LIB) -lm SIM_EXTRA_ALL = sis @@ -35,9 +38,6 @@ SIM_EXTRA_CFLAGS = -DFAST_UART -I$(srcroot) ## COMMON_POST_CONFIG_FRAG -# `sis' doesn't need interf.o. -SIS_OFILES = exec.o erc32.o func.o help.o float.o - sis: sis.o $(SIS_OFILES) $(COMMON_OBJS) $(LIBDEPS) $(CC) $(ALL_CFLAGS) -o sis \ sis.o $(SIS_OFILES) $(COMMON_OBJS) $(EXTRA_LIBS) diff --git a/sim/erc32/README.leon3 b/sim/erc32/README.leon3 new file mode 100644 index 0000000..f6701a5 --- /dev/null +++ b/sim/erc32/README.leon3 @@ -0,0 +1,53 @@ + +1. LEON3 emulation + +The file 'leon3.c' contains a model of simple LEON3 sub-system. It +contains 16 Mbyte ROM and 16 Mbyte RAM. Standard peripherals +such as interrupt controller, UART and timer are provided. +The model can execute leon3 binaries that do not require an +MMU. + +To start sis in Leon3 mode, add the -leon3 switch. In gdb, +use 'target sim -leon3' . + +1.1 UART + +The UART emulates an APBUART and is located at address 0x80000100. +The following registers are implemeted: + +- UART RX and TX register (0x80000100) +- UART status register (0x80000104) + +The UART generates interrupt 3. + +1.2 Timer unit (GPTIMER) + +The GPTIMER programmable counter is emulated and located at +address 0x80000300. It is configured with two timers and separate +interrupts (8 and 9). + +1.3 Interrupt controller + +The IRQMP interrupt controller is implemented as described in the +GRLIB IP manual, with the exception of the interrupt level register. +Extended interrupts are not supported. The registers are located +at address 0x80000200. + +1.5 Memory interface + +The following memory areas are valid for the Leon3 simulator: + +0x00000000 - 0x01000000 ROM (16 Mbyte, loaded at start-up) +0x40000000 - 0x41000000 RAM (16 Mbyte, loaded at start-up) +0x80000000 - 0x81000000 APB bus, including plug&play +0xFFFFF000 - 0xFFFFFFFF AHB plug&play area + +Access to non-existing memory will result in a memory exception trap. + +1.8 Power-down mode + +The Leon3 power-down feature (%asr19) is supported. When power-down is +entered, time is skipped forward until the next event in the event queue. +However, if the simulator event queue is empty, power-down mode is not +entered since no interrupt would be generated to exit from the mode. A +Ctrl-C in the simulator window will exit the power-down mode. diff --git a/sim/erc32/README.sis b/sim/erc32/README.sis index b119f03..124e577 100644 --- a/sim/erc32/README.sis +++ b/sim/erc32/README.sis @@ -1,10 +1,10 @@ -SIS - Sparc Instruction Simulator README file (v2.0, 05-02-1996) +SIS - Sparc Instruction Simulator README file (v2.8, 10-11-2014) ------------------------------------------------------------------- 1. Introduction -The SIS is a SPARC V7 architecture simulator. It consist of two parts, +The SIS is a SPARC V7/V8 architecture simulator. It consist of two parts, the simulator core and a user defined memory module. The simulator core executes the instructions while the memory module emulates memory and peripherals. @@ -13,28 +13,28 @@ and peripherals. The simulator is started as follows: -sis [-uart1 uart_device1] [-uart2 uart_device2] +sis [-leon3] [-uart1 uart_device1] [-uart2 uart_device2] [-nfp] [-freq frequency] [-c batch_file] [files] -The default uart devices for SIS are /dev/ptypc and /dev/ptypd. The --uart[1,2] switch can be used to connect the uarts to other devices. -Use 'tip /dev/ttypc' to connect a terminal emulator to the uarts. +By default, SIS emulates an ERC32 system. The -leon3 switch +enables emulation of a LEON3 SOC system. + +The emulated console uart is connected to stdin/stdout. The -uart[1,2] +switch can be used to connect the uarts to other devices. + The '-nfp' will disable the simulated FPU, so each FPU instruction will generate a FPU disabled trap. The '-freq' switch can be used to define which "frequency" the simulator runs at. This is used by the 'perf' command to calculated the MIPS figure for a particular configuration. -The give frequency must be an integer indicating the frequency in MHz. +The frequency must be an integer indicating the frequency in MHz. The -c option indicates that sis commands should be read from 'batch_file' at startup. -Files to be loaded must be in one of the supported formats (see INSTALLATION), -and will be loaded into the simulated memory. The file formats are -automatically recognised. +Files to be loaded must be in one of the supported formats (elf, a.out, srec), +and will be loaded into the simulated memory. -The script 'startsim' will start the simulator in one xterm window and -open a terminal emulator (tip) connected to the UART A in a second -xterm window. Below is description of commands that are recognized by +Below is description of commands that are recognized by the simulator. The command-line is parsed using GNU readline. A command history of 64 commands is maintained. Use the up/down arrows to recall previous commands. For more details, see the readline documentation. @@ -77,8 +77,8 @@ Prints the FPU registers go
[inst_count] The go command will set pc to and npc to + 4, and start -execution. No other initialisation will be done. If inst_count is given, -execution will stop after the specified number of instructions. +execution. If inst_count is given, execution will stop after the specified +number of instructions. help @@ -146,14 +146,20 @@ interpreted as 'cont'. 3. Simulator core -The SIS emulates the behavior of the 90C601E and 90C602E sparc IU and -FPU from Matra MHS. These are roughly equivalent to the Cypress C601 -and C602. The simulator is cycle true, i.e a simulator time is -maintained and inremented according the IU and FPU instruction timing. +In ERC32 mode, SIS emulates the behavior of the 90C601E and 90C602E +sparc IU and FPU from Matra MHS. These are roughly equivalent to the +Cypress C601 and C602. The simulator is cycle true, i.e a simulator time is +maintained and incremented according the IU and FPU instruction timing. The parallel execution between the IU and FPU is modelled, as well as -stalls due to operand dependencies (FPU). The core interacts with the -user-defined memory modules through a number of functions. The memory -module must provide the following functions: +stalls due to operand dependencies (FPU). + +In Leon3 mode, the core emulates the Leon3 SPARC V8 core from +Gaisler Research. All SPARC V8 instructions are supported but +emulation is not fully cycle-true as the cache is not emulated. + +The core interacts with the user-defined memory modules through +a number of functions. The memory module must provide the following +functions: int memory_read(asi,addr,data,ws) int asi; @@ -272,7 +278,7 @@ See 'erc32.c' for examples on how to use events and interrupts. 5. Memory module -The supplied memory module (erc32.c) emulates the functions of memory and +The ERC32 memory module (erc32.c) emulates the functions of memory and the MEC asic developed for the 90C601/2. It includes the following functions: * UART A & B @@ -284,28 +290,27 @@ the MEC asic developed for the 90C601/2. It includes the following functions: * 512 Kbyte ROM * 4 Mbyte RAM -See README.erc32 on how the MEC functions are emulated. For a detailed MEC -specification, look at the ERC32 home page at URL: +See README.erc32 on how the MEC functions are emulated. -http://www.estec.esa.nl/wsmwww/erc32 +The Leon3 memory module (leon3.c) emulates on-chip peripherals and +external memory for a simple Leon3 system. The modules includes the +following functions: -6. Compile and linking programs +* AHB and APB buses with plug&play +* UART (APBUART) +* Interrupt controller (IRQMP) +* Timer unit with two timers (GPTIMER) +* PROM/SRAM memory controller (SRCTRL) +* 16 Mbyte PROM, 16 Mbyte SRAM -The directory 'examples' contain some code fragments for SIS. -The script gccx indicates how the native sunos gcc and linker can be used -to produce executables for the simulator. To compile and link the provided -'hello.c', type 'gccx hello.c'. This will build the executable 'hello'. -Start the simulator by running 'startsim hello', and issue the command 'run. -After the program is terminated, the IU will be force to error mode through -a software trap and halt. +See README.leon3 for further details on Leon3 emulation. -The programs are linked with a start-up file, srt0.S. This file includes -the traptable and window underflow/overflow trap routines. +6. Compile and linking programs 7. IU and FPU instruction timing. -The simulator provides cycle true simulation. The following table shows -the emulated instruction timing for 90C601E & 90C602E: +The simulator provides cycle true simulation for ERC32. The following table +shows the emulated instruction timing for 90C601E & 90C602E: Instructions Cycles diff --git a/sim/erc32/erc32.c b/sim/erc32/erc32.c index 01bbab8..9bf710a 100644 --- a/sim/erc32/erc32.c +++ b/sim/erc32/erc32.c @@ -1620,19 +1620,16 @@ memory_iread (uint32 addr, uint32 *data, int32 *ws) } static int -memory_read(asi, addr, data, sz, ws) - int32 asi; - uint32 addr; - uint32 *data; - int32 sz; - int32 *ws; +memory_read (uint32 addr, uint32 *data, int32 sz, int32 *ws) { int32 mexc; + int32 asi; #ifdef ERRINJ if (errmec) { if (sis_verbose) printf("Inserted MEC error %d\n",errmec); + asi = (sregs.psr & 0x080) ? 11 : 10; set_sfsr(errmec, addr, asi, 1); if (errmec == 5) mecparerror(); if (errmec == 6) iucomperr(); @@ -1646,6 +1643,7 @@ memory_read(asi, addr, data, sz, ws) *ws = mem_ramr_ws; return 0; } else if ((addr >= MEC_START) && (addr < MEC_END)) { + asi = (sregs.psr & 0x080) ? 11 : 10; mexc = mec_read(addr, asi, data); if (mexc) { set_sfsr(MEC_ACC, addr, asi, 1); @@ -1685,18 +1683,20 @@ memory_read(asi, addr, data, sz, ws) if (sis_verbose) printf ("Memory exception at %x (illegal address)\n", addr); + asi = (sregs.psr & 0x080) ? 11 : 10; set_sfsr(UIMP_ACC, addr, asi, 1); *ws = MEM_EX_WS; return 1; } static int -memory_write(asi, addr, data, sz, ws) - int32 asi; - uint32 addr; - uint32 *data; - int32 sz; - int32 *ws; +memory_read_asi (int32 asi, uint32 addr, uint32 *data, int32 sz, int32 *ws) +{ + return memory_read (addr, data, sz, ws); +} + +static int +memory_write (uint32 addr, uint32 *data, int32 sz, int32 *ws) { uint32 byte_addr; uint32 byte_mask; @@ -1705,11 +1705,13 @@ memory_write(asi, addr, data, sz, ws) int32 mexc; int i; int wphit[2]; + int asi; #ifdef ERRINJ if (errmec) { if (sis_verbose) printf("Inserted MEC error %d\n",errmec); + asi = (sregs.psr & 0x080) ? 11 : 10; set_sfsr(errmec, addr, asi, 0); if (errmec == 5) mecparerror(); if (errmec == 6) iucomperr(); @@ -1722,6 +1724,7 @@ memory_write(asi, addr, data, sz, ws) if (mem_accprot) { waddr = (addr & 0x7fffff) >> 2; + asi = (sregs.psr & 0x080) ? 11 : 10; for (i = 0; i < 2; i++) wphit[i] = (((asi == 0xa) && (mec_wpr[i] & 1)) || @@ -1743,6 +1746,7 @@ memory_write(asi, addr, data, sz, ws) store_bytes (ramb, waddr, data, sz, ws); return 0; } else if ((addr >= MEC_START) && (addr < MEC_END)) { + asi = (sregs.psr & 0x080) ? 11 : 10; if ((sz != 2) || (asi != 0xb)) { set_sfsr(MEC_ACC, addr, asi, 0); *ws = MEM_EX_WS; @@ -1799,10 +1803,17 @@ memory_write(asi, addr, data, sz, ws) } *ws = MEM_EX_WS; + asi = (sregs.psr & 0x080) ? 11 : 10; set_sfsr(UIMP_ACC, addr, asi, 0); return 1; } +static int +memory_write_asi (int32 asi, uint32 addr, uint32 *data, int32 sz, int32 *ws) +{ + return memory_write (addr, data, sz, ws); +} + static unsigned char * get_mem_ptr(addr, size) uint32 addr; @@ -1846,6 +1857,14 @@ sis_memory_read(addr, data, length) uint32 length; { char *mem; + int ws; + int w4; + + if (length == 4) { + memory_read (addr, &w4, length, &ws); + memcpy(data, &w4, length); + return 4; + } if ((mem = get_mem_ptr(addr, length)) == ((char *) -1)) return 0; @@ -1854,7 +1873,7 @@ sis_memory_read(addr, data, length) return length; } -void +static void boot_init (void) { mec_write(MEC_WCR, 0); /* zero waitstates */ @@ -1878,7 +1897,10 @@ const struct memsys erc32sys = { restore_stdio, memory_iread, memory_read, + memory_read_asi, memory_write, + memory_write_asi, sis_memory_write, - sis_memory_read + sis_memory_read, + boot_init }; diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c index 000e939..27bceef 100644 --- a/sim/erc32/exec.c +++ b/sim/erc32/exec.c @@ -1065,17 +1065,17 @@ dispatch_instruction(sregs) *rdd = sregs->psr; break; case RDY: - if (!sparclite) + if ((!sparclite) && (cputype != CPU_LEON3)) *rdd = sregs->y; else { int rs1_is_asr = (sregs->inst >> 14) & 0x1f; if ( 0 == rs1_is_asr ) *rdd = sregs->y; - else if ( 17 == rs1_is_asr ) + else if ( 17 == rs1_is_asr ) { *rdd = sregs->asr17; + } else { sregs->trap = TRAP_UNIMP; - break; } } break; @@ -1121,13 +1121,19 @@ dispatch_instruction(sregs) ((rs1 ^ operand2) & 0xfffff000); break; case WRY: - if (!sparclite) + if ((!sparclite) && (cputype != CPU_LEON3)) sregs->y = (rs1 ^ operand2); else { if ( 0 == rd ) sregs->y = (rs1 ^ operand2); - else if ( 17 == rd ) - sregs->asr17 = (rs1 ^ operand2); + else if ( 17 == rd ) { + if (sparclite) + sregs->asr17 = (rs1 ^ operand2); + } + else if ( 19 == rd ) { + if (cputype == CPU_LEON3) + wait_for_irq(); + } else { sregs->trap = TRAP_UNIMP; break; @@ -1227,6 +1233,32 @@ dispatch_instruction(sregs) switch (op3) { case LDDA: if (!chk_asi(sregs, &asi, op3)) break; + if (address & 0x7) { + sregs->trap = TRAP_UNALI; + break; + } + if (rd & 1) { + rd &= 0x1e; + if (rd > 7) + rdd = &(sregs->r[(cwp + rd) & 0x7f]); + else + rdd = &(sregs->g[rd]); + } + mexc = ms->memory_read_asi (asi, address, ddata, 2, &ws); + sregs->hold += ws; + mexc |= ms->memory_read_asi (asi, address+4, &ddata[1], 2, &ws); + sregs->hold += ws; + sregs->icnt = T_LDD; + if (mexc) + sregs->trap = TRAP_DEXC; + else { + rdd[0] = ddata[0]; + rdd[1] = ddata[1]; +#ifdef STAT + sregs->nload++; /* Double load counts twice */ +#endif + } + break; case LDD: if (address & 0x7) { sregs->trap = TRAP_UNALI; @@ -1239,9 +1271,9 @@ dispatch_instruction(sregs) else rdd = &(sregs->g[rd]); } - mexc = ms->memory_read (asi, address, ddata, 2, &ws); + mexc = ms->memory_read (address, ddata, 2, &ws); sregs->hold += ws; - mexc |= ms->memory_read (asi, address+4, &ddata[1], 2, &ws); + mexc |= ms->memory_read (address+4, &ddata[1], 2, &ws); sregs->hold += ws; sregs->icnt = T_LDD; if (mexc) { @@ -1257,12 +1289,23 @@ dispatch_instruction(sregs) case LDA: if (!chk_asi(sregs, &asi, op3)) break; + if (address & 0x3) { + sregs->trap = TRAP_UNALI; + break; + } + mexc = ms->memory_read_asi (asi, address, &data, 2, &ws); + sregs->hold += ws; + if (mexc) + sregs->trap = TRAP_DEXC; + else + *rdd = data; + break; case LD: if (address & 0x3) { sregs->trap = TRAP_UNALI; break; } - mexc = ms->memory_read (asi, address, &data, 2, &ws); + mexc = ms->memory_read (address, &data, 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1272,8 +1315,26 @@ dispatch_instruction(sregs) break; case LDSTUBA: if (!chk_asi(sregs, &asi, op3)) break; + mexc = ms->memory_read_asi (asi, address, &data, 0, &ws); + sregs->hold += ws; + sregs->icnt = T_LDST; + if (mexc) { + sregs->trap = TRAP_DEXC; + break; + } + data = extract_byte (data, address); + *rdd = data; + data = 0x0ff; + mexc = ms->memory_write_asi (asi, address, &data, 0, &ws); + sregs->hold += ws; + if (mexc) + sregs->trap = TRAP_DEXC; +#ifdef STAT + sregs->nload++; +#endif + break; case LDSTUB: - mexc = ms->memory_read (asi, address, &data, 0, &ws); + mexc = ms->memory_read (address, &data, 0, &ws); sregs->hold += ws; sregs->icnt = T_LDST; if (mexc) { @@ -1283,7 +1344,7 @@ dispatch_instruction(sregs) data = extract_byte (data, address); *rdd = data; data = 0x0ff; - mexc = ms->memory_write (asi, address, &data, 0, &ws); + mexc = ms->memory_write (address, &data, 0, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1295,9 +1356,21 @@ dispatch_instruction(sregs) case LDSBA: case LDUBA: if (!chk_asi(sregs, &asi, op3)) break; + mexc = ms->memory_read_asi (asi, address, &data, 0, &ws); + sregs->hold += ws; + if (mexc) { + sregs->trap = TRAP_DEXC; + break; + } + if (op3 == LDSB) + data = extract_byte_signed (data, address); + else + data = extract_byte (data, address); + *rdd = data; + break; case LDSB: case LDUB: - mexc = ms->memory_read (asi, address, &data, 0, &ws); + mexc = ms->memory_read (address, &data, 0, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1312,13 +1385,29 @@ dispatch_instruction(sregs) case LDSHA: case LDUHA: if (!chk_asi(sregs, &asi, op3)) break; + if (address & 0x1) { + sregs->trap = TRAP_UNALI; + break; + } + mexc = ms->memory_read_asi (asi, address, &data, 1, &ws); + sregs->hold += ws; + if (mexc) { + sregs->trap = TRAP_DEXC; + break; + } + if (op3 == LDSH) + data = extract_short_signed (data, address); + else + data = extract_short (data, address); + *rdd = data; + break; case LDSH: case LDUH: if (address & 0x1) { sregs->trap = TRAP_UNALI; break; } - mexc = ms->memory_read (asi, address, &data, 1, &ws); + mexc = ms->memory_read (address, &data, 1, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1344,7 +1433,7 @@ dispatch_instruction(sregs) (sregs->frs2 == rd)) sregs->fhold += (sregs->ftime - ebase.simtime); } - mexc = ms->memory_read (asi, address, &data, 2, &ws); + mexc = ms->memory_read (address, &data, 2, &ws); sregs->hold += ws; sregs->flrd = rd; sregs->ltime = ebase.simtime + sregs->icnt + FLSTHOLD + @@ -1370,9 +1459,9 @@ dispatch_instruction(sregs) ((sregs->frs2 >> 1) == (rd >> 1))) sregs->fhold += (sregs->ftime - ebase.simtime); } - mexc = ms->memory_read (asi, address, ddata, 2, &ws); + mexc = ms->memory_read (address, ddata, 2, &ws); sregs->hold += ws; - mexc |= ms->memory_read (asi, address+4, &ddata[1], 2, &ws); + mexc |= ms->memory_read (address+4, &ddata[1], 2, &ws); sregs->hold += ws; sregs->icnt = T_LDD; if (mexc) { @@ -1401,7 +1490,7 @@ dispatch_instruction(sregs) sregs->trap = TRAP_UNALI; break; } - mexc = ms->memory_read (asi, address, &data, 2, &ws); + mexc = ms->memory_read (address, &data, 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1423,7 +1512,7 @@ dispatch_instruction(sregs) if (ebase.simtime < sregs->ftime) { sregs->fhold += (sregs->ftime - ebase.simtime); } - mexc = ms->memory_write (asi, address, &sregs->fsr, 2, &ws); + mexc = ms->memory_write (address, &sregs->fsr, 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1432,12 +1521,21 @@ dispatch_instruction(sregs) case STA: if (!chk_asi(sregs, &asi, op3)) break; + if (address & 0x3) { + sregs->trap = TRAP_UNALI; + break; + } + mexc = ms->memory_write_asi (asi, address, rdd, 2, &ws); + sregs->hold += ws; + if (mexc) + sregs->trap = TRAP_DEXC; + break; case ST: if (address & 0x3) { sregs->trap = TRAP_UNALI; break; } - mexc = ms->memory_write (asi, address, rdd, 2, &ws); + mexc = ms->memory_write (address, rdd, 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1445,8 +1543,13 @@ dispatch_instruction(sregs) break; case STBA: if (!chk_asi(sregs, &asi, op3)) break; + mexc = ms->memory_write_asi (asi, address, rdd, 0, &ws); + sregs->hold += ws; + if (mexc) + sregs->trap = TRAP_DEXC; + break; case STB: - mexc = ms->memory_write (asi, address, rdd, 0, &ws); + mexc = ms->memory_write (address, rdd, 0, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1454,6 +1557,28 @@ dispatch_instruction(sregs) break; case STDA: if (!chk_asi(sregs, &asi, op3)) break; + if (address & 0x7) { + sregs->trap = TRAP_UNALI; + break; + } + if (rd & 1) { + rd &= 0x1e; + if (rd > 7) + rdd = &(sregs->r[(cwp + rd) & 0x7f]); + else + rdd = &(sregs->g[rd]); + } + mexc = ms->memory_write_asi (asi, address, rdd, 3, &ws); + sregs->hold += ws; + sregs->icnt = T_STD; +#ifdef STAT + sregs->nstore++; /* Double store counts twice */ +#endif + if (mexc) { + sregs->trap = TRAP_DEXC; + break; + } + break; case STD: if (address & 0x7) { sregs->trap = TRAP_UNALI; @@ -1466,7 +1591,7 @@ dispatch_instruction(sregs) else rdd = &(sregs->g[rd]); } - mexc = ms->memory_write (asi, address, rdd, 3, &ws); + mexc = ms->memory_write (address, rdd, 3, &ws); sregs->hold += ws; sregs->icnt = T_STD; #ifdef STAT @@ -1495,7 +1620,7 @@ dispatch_instruction(sregs) break; } rdd = &(sregs->fpq[0]); - mexc = ms->memory_write (asi, address, rdd, 3, &ws); + mexc = ms->memory_write (address, rdd, 3, &ws); sregs->hold += ws; sregs->icnt = T_STD; #ifdef STAT @@ -1511,12 +1636,21 @@ dispatch_instruction(sregs) break; case STHA: if (!chk_asi(sregs, &asi, op3)) break; + if (address & 0x1) { + sregs->trap = TRAP_UNALI; + break; + } + mexc = ms->memory_write_asi (asi, address, rdd, 1, &ws); + sregs->hold += ws; + if (mexc) + sregs->trap = TRAP_DEXC; + break; case STH: if (address & 0x1) { sregs->trap = TRAP_UNALI; break; } - mexc = ms->memory_write (asi, address, rdd, 1, &ws); + mexc = ms->memory_write (address, rdd, 1, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1535,7 +1669,7 @@ dispatch_instruction(sregs) if (sregs->frd == rd) sregs->fhold += (sregs->ftime - ebase.simtime); } - mexc = ms->memory_write (asi, address, &sregs->fsi[rd], 2, &ws); + mexc = ms->memory_write (address, &sregs->fsi[rd], 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; @@ -1555,7 +1689,7 @@ dispatch_instruction(sregs) if ((sregs->frd == rd) || (sregs->frd + 1 == rd)) sregs->fhold += (sregs->ftime - ebase.simtime); } - mexc = ms->memory_write (asi, address, &sregs->fsi[rd], 3, &ws); + mexc = ms->memory_write (address, &sregs->fsi[rd], 3, &ws); sregs->hold += ws; sregs->icnt = T_STD; #ifdef STAT @@ -1567,18 +1701,40 @@ dispatch_instruction(sregs) break; case SWAPA: if (!chk_asi(sregs, &asi, op3)) break; + if (address & 0x3) { + sregs->trap = TRAP_UNALI; + break; + } + mexc = ms->memory_read_asi (asi, address, &data, 2, &ws); + sregs->hold += ws; + if (mexc) { + sregs->trap = TRAP_DEXC; + break; + } + mexc = ms->memory_write_asi (asi, address, rdd, 2, &ws); + sregs->hold += ws; + sregs->icnt = T_LDST; + if (mexc) { + sregs->trap = TRAP_DEXC; + break; + } else + *rdd = data; +#ifdef STAT + sregs->nload++; +#endif + break; case SWAP: if (address & 0x3) { sregs->trap = TRAP_UNALI; break; } - mexc = ms->memory_read (asi, address, &data, 2, &ws); + mexc = ms->memory_read (address, &data, 2, &ws); sregs->hold += ws; if (mexc) { sregs->trap = TRAP_DEXC; break; } - mexc = ms->memory_write (asi, address, rdd, 2, &ws); + mexc = ms->memory_write (address, rdd, 2, &ws); sregs->hold += ws; sregs->icnt = T_LDST; if (mexc) { @@ -1814,7 +1970,7 @@ fpexec(op3, rd, rs1, rs2, sregs) sregs->ftime += T_FDIVd; break; case FMOVs: - sregs->fs[rd] = sregs->fs[rs2]; + sregs->fsi[rd] = sregs->fsi[rs2]; sregs->ftime += T_FMOVs; sregs->frs1 = 32; /* rs1 ignored */ break; @@ -1996,7 +2152,7 @@ execute_trap(sregs) sregs->pc = sregs->tbr; sregs->npc = sregs->tbr + 4; - if ( 0 != (1 & sregs->asr17) ) { + if ( 0 != (1 & (sregs->asr17 >> 13)) ) { /* single vector trapping! */ sregs->pc = sregs->tbr & 0xfffff000; sregs->npc = sregs->pc + 4; @@ -2043,7 +2199,10 @@ init_regs(sregs) sregs->npc = 4; sregs->trap = 0; sregs->psr &= 0x00f03fdf; - sregs->psr |= 0x11000080; /* Set supervisor bit */ + if (cputype == CPU_LEON3) + sregs->psr |= 0xF3000080; /* Set supervisor bit */ + else + sregs->psr |= 0x11000080; /* Set supervisor bit */ sregs->breakpoint = 0; sregs->annul = 0; sregs->fpstate = FP_EXE_MODE; @@ -2072,4 +2231,8 @@ init_regs(sregs) sregs->rett_err = 0; sregs->jmpltime = 0; + if (cputype == CPU_LEON3) { + sregs->asr17 = 0x107; + if (!nfp) sregs->asr17 |= (3 << 10); /* Meiko FPU */ + } } diff --git a/sim/erc32/func.c b/sim/erc32/func.c index 74c3820..86e7a0a 100644 --- a/sim/erc32/func.c +++ b/sim/erc32/func.c @@ -41,7 +41,7 @@ struct irqcell irqarr[16]; int ctrl_c = 0; int sis_verbose = 0; -char *sis_version = "2.7.5"; +char *sis_version = "2.8"; int nfp = 0; int ift = 0; int wrp = 0; @@ -56,6 +56,7 @@ uint32 last_load_addr = 0; int nouartrx = 0; host_callback *sim_callback; const struct memsys *ms = &erc32sys; +int cputype = 0; /* 0 = erc32, 3 = leon3 */ #ifdef ERRINJ uint32 errcnt = 0; @@ -467,7 +468,7 @@ exec_cmd(struct pstate *sregs, const char *cmd) sregs->pc = len & ~3; sregs->npc = sregs->pc + 4; if ((sregs->pc != 0) && (ebase.simtime == 0)) - boot_init(); + ms->boot_init (); printf("resuming at 0x%08x\n",sregs->pc); if ((cmd2 = strtok(NULL, " \t\n\r")) != NULL) { stat = run_sim(sregs, VAL(cmd2), 0); @@ -543,6 +544,11 @@ exec_cmd(struct pstate *sregs, const char *cmd) ebase.simtime = 0; reset_all(); reset_stat(sregs); + if (last_load_addr != 0) { + sregs->pc = last_load_addr & ~3; + sregs->npc = sregs->pc + 4; + } + if ((sregs->pc != 0) && (ebase.simtime == 0)) ms->boot_init (); if ((cmd1 = strtok(NULL, " \t\n\r")) == NULL) { stat = run_sim(sregs, UINT64_MAX, 0); } else { @@ -596,6 +602,11 @@ exec_cmd(struct pstate *sregs, const char *cmd) ebase.simtime = 0; reset_all(); reset_stat(sregs); + if (last_load_addr != 0) { + sregs->pc = last_load_addr & ~3; + sregs->npc = sregs->pc + 4; + } + if ((sregs->pc != 0) && (ebase.simtime == 0)) ms->boot_init (); sregs->tlimit = limcalc(sregs->freq); stat = run_sim(sregs, UINT64_MAX, 0); daddr = sregs->pc; @@ -633,8 +644,8 @@ void show_stat(sregs) struct pstate *sregs; { - uint32 iinst; - uint32 stime; + uint64 iinst; + uint64 stime; if (sregs->tottime == 0.0) sregs->tottime += 1E-6; @@ -649,37 +660,37 @@ show_stat(sregs) printf(" Instructions : %9" PRIu64 "\n", sregs->ninst); #ifdef STAT - printf(" integer : %9.2f %%\n", 100.0 * (float) iinst / (float) sregs->ninst); + printf (" integer : %9.2f %%\n", 100.0 * (double) iinst / (double) sregs->ninst); printf(" load : %9.2f %%\n", - 100.0 * (float) sregs->nload / (float) sregs->ninst); + 100.0 * (double) sregs->nload / (double) sregs->ninst); printf(" store : %9.2f %%\n", - 100.0 * (float) sregs->nstore / (float) sregs->ninst); + 100.0 * (double) sregs->nstore / (double) sregs->ninst); printf(" branch : %9.2f %%\n", - 100.0 * (float) sregs->nbranch / (float) sregs->ninst); + 100.0 * (double) sregs->nbranch / (double) sregs->ninst); printf(" float : %9.2f %%\n", - 100.0 * (float) sregs->finst / (float) sregs->ninst); + 100.0 * (double) sregs->finst / (double) sregs->ninst); printf(" Integer CPI : %9.2f\n", - ((float) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst)) + ((double) (stime - sregs->pwdtime - sregs->fholdt - sregs->finst)) / - (float) (sregs->ninst - sregs->finst)); + (double) (sregs->ninst - sregs->finst)); printf(" Float CPI : %9.2f\n", - ((float) sregs->fholdt / (float) sregs->finst) + 1.0); + ((double) sregs->fholdt / (double) sregs->finst) + 1.0); #endif printf(" Overall CPI : %9.2f\n", - (float) (stime - sregs->pwdtime) / (float) sregs->ninst); - printf("\n ERC32 performance (%4.1f MHz): %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n", - sregs->freq, sregs->freq * (float) sregs->ninst / (float) (stime - sregs->pwdtime), - sregs->freq * (float) (sregs->ninst - sregs->finst) / - (float) (stime - sregs->pwdtime), - sregs->freq * (float) sregs->finst / (float) (stime - sregs->pwdtime)); - printf(" Simulated ERC32 time : %.2f s\n", - (float) (ebase.simtime - sregs->simstart) / 1000000.0 / sregs->freq); + (double) (stime - sregs->pwdtime) / (double) sregs->ninst); + printf ("\n CPU performance (%4.1f MHz) : %5.2f MOPS (%5.2f MIPS, %5.2f MFLOPS)\n", + sregs->freq, sregs->freq * (double) sregs->ninst / (double) (stime - sregs->pwdtime), + sregs->freq * (double) (sregs->ninst - sregs->finst) / + (double) (stime - sregs->pwdtime), + sregs->freq * (double) sregs->finst / (double) (stime - sregs->pwdtime)); + printf (" Simulated CPU time : %.2f s\n", + (double) (ebase.simtime - sregs->simstart) / 1000000.0 / sregs->freq); printf(" Processor utilisation : %.2f %%\n", - 100.0 * (1.0 - ((float) sregs->pwdtime / (float) stime))); + 100.0 * (1.0 - ((double) sregs->pwdtime / (double) stime))); printf(" Real-time performance : %.2f %%\n", - 100.0 / (sregs->tottime / ((double) (stime) / (sregs->freq * 1.0E6)))); + 100.0 / (sregs->tottime / ((double) (stime) / (sregs->freq * 1.0E6)))); printf(" Simulator performance : %.2f MIPS\n", - (double)(sregs->ninst) / sregs->tottime / 1E6); + (double)(sregs->ninst) / sregs->tottime / 1E6); printf(" Used time (sys + user) : %.2f s\n\n", sregs->tottime); } diff --git a/sim/erc32/grlib.c b/sim/erc32/grlib.c new file mode 100644 index 0000000..9cd3b9f --- /dev/null +++ b/sim/erc32/grlib.c @@ -0,0 +1,101 @@ +/* + * This file is part of SIS. + * + * SIS, SPARC instruction simulator. Copyright (C) 2014 Jiri Gaisler + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see