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

Subversion Repositories aor3000

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /aor3000
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/linux/.config
0,0 → 1,862
#
# Automatically generated file; DO NOT EDIT.
# Linux/mips 3.16.0 Kernel Configuration
#
CONFIG_MIPS=y
 
#
# Machine selection
#
# CONFIG_MIPS_ALCHEMY is not set
CONFIG_AOR3000=y
# CONFIG_AR7 is not set
# CONFIG_ATH79 is not set
# CONFIG_BCM47XX is not set
# CONFIG_BCM63XX is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_JZ4740 is not set
# CONFIG_LANTIQ is not set
# CONFIG_LASAT is not set
# CONFIG_MACH_LOONGSON is not set
# CONFIG_MACH_LOONGSON1 is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD3 is not set
# CONFIG_NEC_MARKEINS is not set
# CONFIG_MACH_VR41XX is not set
# CONFIG_NXP_STB220 is not set
# CONFIG_NXP_STB225 is not set
# CONFIG_PMC_MSP is not set
# CONFIG_RALINK is not set
# CONFIG_SGI_IP22 is not set
# CONFIG_SGI_IP27 is not set
# CONFIG_SGI_IP28 is not set
# CONFIG_SGI_IP32 is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CARMEL is not set
# CONFIG_SIBYTE_CRHONE is not set
# CONFIG_SIBYTE_RHONE is not set
# CONFIG_SIBYTE_SWARM is not set
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_SENTOSA is not set
# CONFIG_SIBYTE_BIGSUR is not set
# CONFIG_SNI_RM is not set
# CONFIG_MACH_TX39XX is not set
# CONFIG_MACH_TX49XX is not set
# CONFIG_MIKROTIK_RB532 is not set
# CONFIG_CAVIUM_OCTEON_SOC is not set
# CONFIG_NLM_XLR_BOARD is not set
# CONFIG_NLM_XLP_BOARD is not set
# CONFIG_MIPS_PARAVIRT is not set
# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_BOOT_RAW=y
# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
CONFIG_DMA_NONCOHERENT=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
# CONFIG_MIPS_MACHINE is not set
# CONFIG_NO_IOPORT_MAP is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set
CONFIG_IRQ_CPU=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
 
#
# CPU selection
#
CONFIG_CPU_R3000=y
CONFIG_SYS_HAS_CPU_R3000=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
 
#
# Kernel type
#
CONFIG_32BIT=y
# CONFIG_KVM_GUEST is not set
CONFIG_PAGE_SIZE_4KB=y
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
CONFIG_CPU_HAS_WB=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_COMPACTION=y
CONFIG_MIGRATION=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_NEED_PER_CPU_KM=y
# CONFIG_CLEANCACHE is not set
# CONFIG_FRONTSWAP is not set
# CONFIG_CMA is not set
# CONFIG_ZBUD is not set
# CONFIG_ZSMALLOC is not set
# CONFIG_HZ_48 is not set
CONFIG_HZ_100=y
# CONFIG_HZ_128 is not set
# CONFIG_HZ_250 is not set
# CONFIG_HZ_256 is not set
# CONFIG_HZ_1000 is not set
# CONFIG_HZ_1024 is not set
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_HZ=100
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
# CONFIG_SECCOMP is not set
# CONFIG_MIPS_O32_FP64_SUPPORT is not set
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_EXTABLE_SORT=y
 
#
# General setup
#
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_CROSS_COMPILE=""
# CONFIG_COMPILE_TEST is not set
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_DEFAULT_HOSTNAME="(none)"
CONFIG_SWAP=y
# CONFIG_SYSVIPC is not set
CONFIG_CROSS_MEMORY_ATTACH=y
# CONFIG_FHANDLE is not set
# CONFIG_USELIB is not set
 
#
# IRQ subsystem
#
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_GENERIC_CMOS_UPDATE=y
 
#
# Timers subsystem
#
CONFIG_HZ_PERIODIC=y
# CONFIG_NO_HZ_IDLE is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
 
#
# CPU/Task time and stats accounting
#
CONFIG_TICK_CPU_ACCOUNTING=y
# CONFIG_BSD_PROCESS_ACCT is not set
 
#
# RCU Subsystem
#
CONFIG_TINY_RCU=y
# CONFIG_PREEMPT_RCU is not set
# CONFIG_RCU_STALL_COMMON is not set
# CONFIG_TREE_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_CGROUPS is not set
# CONFIG_CHECKPOINT_RESTORE is not set
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
# CONFIG_USER_NS is not set
CONFIG_PID_NS=y
# CONFIG_SCHED_AUTOGROUP is not set
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="usr/sys-root usr/sys-files"
CONFIG_INITRAMFS_ROOT_UID=0
CONFIG_INITRAMFS_ROOT_GID=0
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_LZ4 is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
CONFIG_EXPERT=y
CONFIG_SGETMASK_SYSCALL=y
CONFIG_SYSFS_SYSCALL=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_EMBEDDED=y
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_PERF_USE_VMALLOC=y
 
#
# Kernel Performance Events And Counters
#
# CONFIG_PERF_EVENTS is not set
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_JUMP_LABEL is not set
# CONFIG_UPROBES is not set
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_HAVE_CC_STACKPROTECTOR=y
# CONFIG_CC_STACKPROTECTOR is not set
CONFIG_CC_STACKPROTECTOR_NONE=y
# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
# CONFIG_CC_STACKPROTECTOR_STRONG is not set
CONFIG_HAVE_CONTEXT_TRACKING=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_CLONE_BACKWARDS=y
 
#
# GCOV-based kernel profiling
#
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBDAF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_BSGLIB is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
# CONFIG_BLK_CMDLINE_PARSER is not set
 
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
CONFIG_EFI_PARTITION=y
 
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
# CONFIG_DEFAULT_DEADLINE is not set
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
CONFIG_INLINE_READ_UNLOCK=y
CONFIG_INLINE_READ_UNLOCK_IRQ=y
CONFIG_INLINE_WRITE_UNLOCK=y
CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
# CONFIG_FREEZER is not set
 
#
# Bus options (PCI, PCMCIA, EISA, ISA, TC)
#
CONFIG_MMU=y
# CONFIG_PCCARD is not set
 
#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_BINFMT_SCRIPT=y
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_COREDUMP=y
CONFIG_TRAD_SIGNALS=y
 
#
# Power management options
#
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_SUSPEND is not set
# CONFIG_HIBERNATION is not set
# CONFIG_PM_RUNTIME is not set
 
#
# CPU Power Management
#
 
#
# CPU Idle
#
# CONFIG_CPU_IDLE is not set
# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
# CONFIG_NET is not set
CONFIG_HAVE_BPF_JIT=y
 
#
# Device Drivers
#
 
#
# Generic Driver Options
#
# CONFIG_UEVENT_HELPER is not set
# CONFIG_DEVTMPFS is not set
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_EXTRA_FIRMWARE=""
CONFIG_FW_LOADER_USER_HELPER=y
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_GENERIC_CPU_DEVICES is not set
# CONFIG_DMA_SHARED_BUFFER is not set
 
#
# Bus devices
#
# CONFIG_MTD is not set
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
# CONFIG_PARPORT is not set
# CONFIG_BLK_DEV is not set
 
#
# Misc devices
#
# CONFIG_SENSORS_LIS3LV02D is not set
# CONFIG_DUMMY_IRQ is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_SRAM is not set
# CONFIG_C2PORT is not set
 
#
# EEPROM support
#
# CONFIG_EEPROM_93CX6 is not set
 
#
# Texas Instruments shared transport line discipline
#
 
#
# Altera FPGA firmware download module
#
 
#
# Intel MIC Host Driver
#
 
#
# Intel MIC Card Driver
#
# CONFIG_ECHO is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
 
#
# SCSI device support
#
CONFIG_SCSI_MOD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_NETLINK is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
 
#
# Input device support
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
# CONFIG_INPUT_POLLDEV is not set
# CONFIG_INPUT_SPARSEKMAP is not set
# CONFIG_INPUT_MATRIXKMAP is not set
 
#
# Userland interfaces
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
 
#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_ATKBD is not set
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_OPENCORES is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
 
#
# Hardware I/O ports
#
# CONFIG_SERIO is not set
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
# CONFIG_GAMEPORT is not set
 
#
# Character devices
#
CONFIG_TTY=y
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_TRACE_SINK is not set
# CONFIG_DEVKMEM is not set
 
#
# Serial drivers
#
# CONFIG_SERIAL_8250 is not set
 
#
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_SCCNXP is not set
CONFIG_SERIAL_ALTERA_JTAGUART=y
CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE=y
CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS=y
# CONFIG_SERIAL_ALTERA_UART is not set
# CONFIG_SERIAL_ARC is not set
# CONFIG_SERIAL_FSL_LPUART is not set
# CONFIG_TTY_PRINTK is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
# CONFIG_I2C is not set
# CONFIG_SPI is not set
# CONFIG_SPMI is not set
# CONFIG_HSI is not set
 
#
# PPS support
#
# CONFIG_PPS is not set
 
#
# PPS generators support
#
 
#
# PTP clock support
#
 
#
# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
#
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_POWER_AVS is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_WATCHDOG is not set
CONFIG_SSB_POSSIBLE=y
 
#
# Sonics Silicon Backplane
#
# CONFIG_SSB is not set
CONFIG_BCMA_POSSIBLE=y
 
#
# Broadcom specific AMBA
#
# CONFIG_BCMA is not set
 
#
# Multifunction device drivers
#
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_CROS_EC is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_KEMPLD is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_ABX500_CORE is not set
# CONFIG_MFD_SYSCON is not set
# CONFIG_MFD_TI_AM335X_TSCADC is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_REGULATOR is not set
# CONFIG_MEDIA_SUPPORT is not set
 
#
# Graphics support
#
 
#
# Direct Rendering Manager
#
# CONFIG_DRM is not set
 
#
# Frame buffer Devices
#
# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
# CONFIG_VGASTATE is not set
 
#
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
# CONFIG_SOUND is not set
 
#
# HID support
#
# CONFIG_HID is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
CONFIG_RTC_LIB=y
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_VIRT_DRIVERS is not set
 
#
# Virtio drivers
#
# CONFIG_VIRTIO_MMIO is not set
 
#
# Microsoft Hyper-V guest support
#
# CONFIG_STAGING is not set
 
#
# SOC (System On Chip) specific Drivers
#
 
#
# Hardware Spinlock drivers
#
# CONFIG_SH_TIMER_CMT is not set
# CONFIG_SH_TIMER_MTU2 is not set
# CONFIG_SH_TIMER_TMU is not set
# CONFIG_EM_TIMER_STI is not set
# CONFIG_MAILBOX is not set
# CONFIG_IOMMU_SUPPORT is not set
 
#
# Remoteproc drivers
#
# CONFIG_STE_MODEM_RPROC is not set
 
#
# Rpmsg drivers
#
# CONFIG_PM_DEVFREQ is not set
# CONFIG_EXTCON is not set
# CONFIG_MEMORY is not set
# CONFIG_IIO is not set
# CONFIG_PWM is not set
# CONFIG_IPACK_BUS is not set
# CONFIG_RESET_CONTROLLER is not set
# CONFIG_FMC is not set
 
#
# PHY Subsystem
#
# CONFIG_GENERIC_PHY is not set
# CONFIG_BCM_KONA_USB2_PHY is not set
# CONFIG_PHY_SAMSUNG_USB2 is not set
# CONFIG_POWERCAP is not set
# CONFIG_MCB is not set
 
#
# Firmware Drivers
#
# CONFIG_FIRMWARE_MEMMAP is not set
 
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_XFS_FS is not set
# CONFIG_BTRFS_FS is not set
# CONFIG_NILFS2_FS is not set
# CONFIG_FS_POSIX_ACL is not set
CONFIG_FILE_LOCKING=y
CONFIG_FSNOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_FANOTIFY is not set
# CONFIG_QUOTA is not set
# CONFIG_QUOTACTL is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
 
#
# Caches
#
# CONFIG_FSCACHE is not set
 
#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
 
#
# DOS/FAT/NT Filesystems
#
# CONFIG_MSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
 
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_KERNFS=y
CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
# CONFIG_MISC_FILESYSTEMS is not set
# CONFIG_NLS is not set
 
#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 
#
# printk and dmesg options
#
# CONFIG_PRINTK_TIME is not set
CONFIG_DEFAULT_MESSAGE_LOGLEVEL=7
# CONFIG_BOOT_PRINTK_DELAY is not set
 
#
# Compile-time checks and compiler options
#
# CONFIG_DEBUG_INFO is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_READABLE_ASM is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_SECTION_MISMATCH is not set
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_DEBUG_KERNEL=y
 
#
# Memory Debugging
#
# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
CONFIG_HAVE_DEBUG_KMEMLEAK=y
# CONFIG_DEBUG_KMEMLEAK is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_SHIRQ is not set
 
#
# Debug Lockups and Hangs
#
# CONFIG_LOCKUP_DETECTOR is not set
# CONFIG_DETECT_HUNG_TASK is not set
# CONFIG_PANIC_ON_OOPS is not set
CONFIG_PANIC_ON_OOPS_VALUE=0
CONFIG_PANIC_TIMEOUT=0
CONFIG_SCHED_DEBUG=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
 
#
# Lock Debugging (spinlocks, mutexes, etc...)
#
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_PROVE_LOCKING is not set
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_ATOMIC_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_LOCK_TORTURE_TEST is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_PI_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_DEBUG_CREDENTIALS is not set
 
#
# RCU Debugging
#
# CONFIG_SPARSE_RCU_POINTER is not set
# CONFIG_TORTURE_TEST is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_TRACE is not set
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_NOTIFIER_ERROR_INJECTION is not set
# CONFIG_FAULT_INJECTION is not set
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_TRACING_SUPPORT=y
# CONFIG_FTRACE is not set
 
#
# Runtime Testing
#
# CONFIG_TEST_LIST_SORT is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_RBTREE_TEST is not set
# CONFIG_ATOMIC64_SELFTEST is not set
# CONFIG_TEST_STRING_HELPERS is not set
# CONFIG_TEST_KSTRTOX is not set
# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_EARLY_PRINTK=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyJ0,115200"
# CONFIG_CMDLINE_OVERRIDE is not set
# CONFIG_RUNTIME_DEBUG is not set
 
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY_DMESG_RESTRICT is not set
# CONFIG_SECURITY is not set
# CONFIG_SECURITYFS is not set
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_DEFAULT_SECURITY=""
# CONFIG_CRYPTO is not set
# CONFIG_BINARY_PRINTF is not set
 
#
# Library routines
#
CONFIG_BITREVERSE=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_IO=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC32_SELFTEST is not set
CONFIG_CRC32_SLICEBY8=y
# CONFIG_CRC32_SLICEBY4 is not set
# CONFIG_CRC32_SARWATE is not set
# CONFIG_CRC32_BIT is not set
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
# CONFIG_CRC8 is not set
# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
# CONFIG_RANDOM32_SELFTEST is not set
CONFIG_ZLIB_INFLATE=y
# CONFIG_XZ_DEC is not set
# CONFIG_XZ_DEC_BCJ is not set
CONFIG_DECOMPRESS_GZIP=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HAS_DMA=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
# CONFIG_AVERAGE is not set
# CONFIG_CORDIC is not set
# CONFIG_DDR is not set
# CONFIG_VIRTUALIZATION is not set
/trunk/linux/usr/sys-root/init Cannot display: file marked as a binary type. svn:mime-type = application/x-executable
trunk/linux/usr/sys-root/init Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/x-executable \ No newline at end of property Index: trunk/linux/usr/sys-root/bin/dmesg =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/x-executable Index: trunk/linux/usr/sys-root/bin/dmesg =================================================================== --- trunk/linux/usr/sys-root/bin/dmesg (nonexistent) +++ trunk/linux/usr/sys-root/bin/dmesg (revision 2)
trunk/linux/usr/sys-root/bin/dmesg Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/x-executable \ No newline at end of property Index: trunk/linux/usr/sys-root/bin/cat =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/x-executable Index: trunk/linux/usr/sys-root/bin/cat =================================================================== --- trunk/linux/usr/sys-root/bin/cat (nonexistent) +++ trunk/linux/usr/sys-root/bin/cat (revision 2)
trunk/linux/usr/sys-root/bin/cat Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/x-executable \ No newline at end of property Index: trunk/linux/usr/sys-root/bin/ls =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/x-executable Index: trunk/linux/usr/sys-root/bin/ls =================================================================== --- trunk/linux/usr/sys-root/bin/ls (nonexistent) +++ trunk/linux/usr/sys-root/bin/ls (revision 2)
trunk/linux/usr/sys-root/bin/ls Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/x-executable \ No newline at end of property Index: trunk/linux/usr/sys-files =================================================================== --- trunk/linux/usr/sys-files (nonexistent) +++ trunk/linux/usr/sys-files (revision 2) @@ -0,0 +1,4 @@ +dir /dev 0755 0 0 +nod /dev/console 0600 0 0 c 5 1 +dir /root 0700 0 0 +dir /sbin 0755 0 0 Index: trunk/linux/arch/mips/Kbuild.platforms =================================================================== --- trunk/linux/arch/mips/Kbuild.platforms (nonexistent) +++ trunk/linux/arch/mips/Kbuild.platforms (revision 2) @@ -0,0 +1,36 @@ +# All platforms listed in alphabetic order + +platforms += alchemy +platforms += aor3000 +platforms += ar7 +platforms += ath79 +platforms += bcm47xx +platforms += bcm63xx +platforms += cavium-octeon +platforms += cobalt +platforms += dec +platforms += emma +platforms += jazz +platforms += jz4740 +platforms += lantiq +platforms += lasat +platforms += loongson +platforms += loongson1 +platforms += mti-malta +platforms += mti-sead3 +platforms += netlogic +platforms += paravirt +platforms += pmcs-msp71xx +platforms += pnx833x +platforms += ralink +platforms += rb532 +platforms += sgi-ip22 +platforms += sgi-ip27 +platforms += sgi-ip32 +platforms += sibyte +platforms += sni +platforms += txx9 +platforms += vr41xx + +# include the platform specific files +include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) Index: trunk/linux/arch/mips/Kconfig =================================================================== --- trunk/linux/arch/mips/Kconfig (nonexistent) +++ trunk/linux/arch/mips/Kconfig (revision 2) @@ -0,0 +1,2707 @@ +config MIPS + bool + default y + select ARCH_MIGHT_HAVE_PC_PARPORT + select ARCH_MIGHT_HAVE_PC_SERIO + select HAVE_CONTEXT_TRACKING + select HAVE_GENERIC_DMA_COHERENT + select HAVE_IDE + select HAVE_OPROFILE + select HAVE_PERF_EVENTS + select PERF_USE_VMALLOC + select HAVE_ARCH_KGDB + select HAVE_ARCH_SECCOMP_FILTER + select HAVE_ARCH_TRACEHOOK + select HAVE_BPF_JIT if !CPU_MICROMIPS + select ARCH_HAVE_CUSTOM_GPIO_H + select HAVE_FUNCTION_TRACER + select HAVE_FUNCTION_TRACE_MCOUNT_TEST + select HAVE_DYNAMIC_FTRACE + select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_C_RECORDMCOUNT + select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_KPROBES + select HAVE_KRETPROBES + select HAVE_DEBUG_KMEMLEAK + select HAVE_SYSCALL_TRACEPOINTS + select ARCH_BINFMT_ELF_RANDOMIZE_PIE + select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT + select RTC_LIB if !MACH_LOONGSON + select GENERIC_ATOMIC64 if !64BIT + select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE + select HAVE_DMA_ATTRS + select HAVE_DMA_API_DEBUG + select GENERIC_IRQ_PROBE + select GENERIC_IRQ_SHOW + select GENERIC_PCI_IOMAP + select HAVE_ARCH_JUMP_LABEL + select ARCH_WANT_IPC_PARSE_VERSION + select IRQ_FORCED_THREADING + select HAVE_MEMBLOCK + select HAVE_MEMBLOCK_NODE_MAP + select ARCH_DISCARD_MEMBLOCK + select GENERIC_SMP_IDLE_THREAD + select BUILDTIME_EXTABLE_SORT + select GENERIC_CLOCKEVENTS + select GENERIC_CMOS_UPDATE + select HAVE_MOD_ARCH_SPECIFIC + select VIRT_TO_BUS + select MODULES_USE_ELF_REL if MODULES + select MODULES_USE_ELF_RELA if MODULES && 64BIT + select CLONE_BACKWARDS + select HAVE_DEBUG_STACKOVERFLOW + select HAVE_CC_STACKPROTECTOR + select CPU_PM if CPU_IDLE + select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST + +menu "Machine selection" + +choice + prompt "System type" + default SGI_IP22 + +config MIPS_ALCHEMY + bool "Alchemy processor based machines" + select 64BIT_PHYS_ADDR + select CEVT_R4K + select CSRC_R4K + select IRQ_CPU + select DMA_MAYBE_COHERENT # Au1000,1500,1100 aren't, rest is + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_APM_EMULATION + select ARCH_REQUIRE_GPIOLIB + select SYS_SUPPORTS_ZBOOT + +config AOR3000 + bool "aoR3000 SoC" + select SYS_HAS_CPU_R3000 + select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select DMA_NONCOHERENT + select IRQ_CPU + select BOOT_RAW + +config AR7 + bool "Texas Instruments AR7" + select BOOT_ELF32 + select DMA_NONCOHERENT + select CEVT_R4K + select CSRC_R4K + select IRQ_CPU + select NO_EXCEPT_FILL + select SWAP_IO_SPACE + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_MIPS16 + select SYS_SUPPORTS_ZBOOT_UART16550 + select ARCH_REQUIRE_GPIOLIB + select VLYNQ + select HAVE_CLK + help + Support for the Texas Instruments AR7 System-on-a-Chip + family: TNETD7100, 7200 and 7300. + +config ATH79 + bool "Atheros AR71XX/AR724X/AR913X based boards" + select ARCH_REQUIRE_GPIOLIB + select BOOT_RAW + select CEVT_R4K + select CSRC_R4K + select DMA_NONCOHERENT + select HAVE_CLK + select CLKDEV_LOOKUP + select IRQ_CPU + select MIPS_MACHINE + select SYS_HAS_CPU_MIPS32_R2 + select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_MIPS16 + help + Support for the Atheros AR71XX/AR724X/AR913X SoCs. + +config BCM47XX + bool "Broadcom BCM47XX based boards" + select ARCH_WANT_OPTIONAL_GPIOLIB + select BOOT_RAW + select CEVT_R4K + select CSRC_R4K + select DMA_NONCOHERENT + select HW_HAS_PCI + select IRQ_CPU + select SYS_HAS_CPU_MIPS32_R1 + select NO_EXCEPT_FILL + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_MIPS16 + select SYS_HAS_EARLY_PRINTK + select USE_GENERIC_EARLY_PRINTK_8250 + help + Support for BCM47XX based boards + +config BCM63XX + bool "Broadcom BCM63XX based boards" + select BOOT_RAW + select CEVT_R4K + select CSRC_R4K + select DMA_NONCOHERENT + select IRQ_CPU + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_HAS_EARLY_PRINTK + select SWAP_IO_SPACE + select ARCH_REQUIRE_GPIOLIB + select HAVE_CLK + select MIPS_L1_CACHE_SHIFT_4 + help + Support for BCM63XX based boards + +config MIPS_COBALT + bool "Cobalt Server" + select CEVT_R4K + select CSRC_R4K + select CEVT_GT641XX + select DMA_NONCOHERENT + select HW_HAS_PCI + select I8253 + select I8259 + select IRQ_CPU + select IRQ_GT641XX + select PCI_GT64XXX_PCI0 + select PCI + select SYS_HAS_CPU_NEVADA + select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select USE_GENERIC_EARLY_PRINTK_8250 + +config MACH_DECSTATION + bool "DECstations" + select BOOT_ELF32 + select CEVT_DS1287 + select CEVT_R4K if CPU_R4X00 + select CSRC_IOASIC + select CSRC_R4K if CPU_R4X00 + select CPU_DADDI_WORKAROUNDS if 64BIT + select CPU_R4000_WORKAROUNDS if 64BIT + select CPU_R4400_WORKAROUNDS if 64BIT + select DMA_NONCOHERENT + select NO_IOPORT_MAP + select IRQ_CPU + select SYS_HAS_CPU_R3000 + select SYS_HAS_CPU_R4X00 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_128HZ + select SYS_SUPPORTS_256HZ + select SYS_SUPPORTS_1024HZ + select MIPS_L1_CACHE_SHIFT_4 + help + This enables support for DEC's MIPS based workstations. For details + see the Linux/MIPS FAQ on and the + DECstation porting pages on . + + If you have one of the following DECstation Models you definitely + want to choose R4xx0 for the CPU Type: + + DECstation 5000/50 + DECstation 5000/150 + DECstation 5000/260 + DECsystem 5900/260 + + otherwise choose R3000. + +config MACH_JAZZ + bool "Jazz family of machines" + select FW_ARC + select FW_ARC32 + select ARCH_MAY_HAVE_PC_FDC + select CEVT_R4K + select CSRC_R4K + select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN + select GENERIC_ISA_DMA + select HAVE_PCSPKR_PLATFORM + select IRQ_CPU + select I8253 + select I8259 + select ISA + select SYS_HAS_CPU_R4X00 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_100HZ + help + This a family of machines based on the MIPS R4030 chipset which was + used by several vendors to build RISC/os and Windows NT workstations. + Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and + Olivetti M700-10 workstations. + +config MACH_JZ4740 + bool "Ingenic JZ4740 based machines" + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_ZBOOT_UART16550 + select DMA_NONCOHERENT + select IRQ_CPU + select ARCH_REQUIRE_GPIOLIB + select SYS_HAS_EARLY_PRINTK + select HAVE_CLK + select GENERIC_IRQ_CHIP + +config LANTIQ + bool "Lantiq based platforms" + select DMA_NONCOHERENT + select IRQ_CPU + select CEVT_R4K + select CSRC_R4K + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_MIPS16 + select SYS_SUPPORTS_MULTITHREADING + select SYS_HAS_EARLY_PRINTK + select ARCH_REQUIRE_GPIOLIB + select SWAP_IO_SPACE + select BOOT_RAW + select HAVE_MACH_CLKDEV + select CLKDEV_LOOKUP + select USE_OF + select PINCTRL + select PINCTRL_LANTIQ + +config LASAT + bool "LASAT Networks platforms" + select CEVT_R4K + select CRC32 + select CSRC_R4K + select DMA_NONCOHERENT + select SYS_HAS_EARLY_PRINTK + select HW_HAS_PCI + select IRQ_CPU + select PCI_GT64XXX_PCI0 + select MIPS_NILE4 + select R5000_CPU_SCACHE + select SYS_HAS_CPU_R5000 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL if BROKEN + select SYS_SUPPORTS_LITTLE_ENDIAN + +config MACH_LOONGSON + bool "Loongson family of machines" + select SYS_SUPPORTS_ZBOOT + help + This enables the support of Loongson family of machines. + + Loongson is a family of general-purpose MIPS-compatible CPUs. + developed at Institute of Computing Technology (ICT), + Chinese Academy of Sciences (CAS) in the People's Republic + of China. The chief architect is Professor Weiwu Hu. + +config MACH_LOONGSON1 + bool "Loongson 1 family of machines" + select SYS_SUPPORTS_ZBOOT + help + This enables support for the Loongson 1 based machines. + + Loongson 1 is a family of 32-bit MIPS-compatible SoCs developed by + the ICT (Institute of Computing Technology) and the Chinese Academy + of Sciences. + +config MIPS_MALTA + bool "MIPS Malta board" + select ARCH_MAY_HAVE_PC_FDC + select BOOT_ELF32 + select BOOT_RAW + select CEVT_R4K + select CSRC_R4K + select CSRC_GIC + select DMA_MAYBE_COHERENT + select GENERIC_ISA_DMA + select HAVE_PCSPKR_PLATFORM + select IRQ_CPU + select IRQ_GIC + select HW_HAS_PCI + select I8253 + select I8259 + select MIPS_BONITO64 + select MIPS_CPU_SCACHE + select PCI_GT64XXX_PCI0 + select MIPS_MSC + select SWAP_IO_SPACE + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_MIPS32_R2 + select SYS_HAS_CPU_MIPS32_R3_5 + select SYS_HAS_CPU_MIPS64_R1 + select SYS_HAS_CPU_MIPS64_R2 + select SYS_HAS_CPU_NEVADA + select SYS_HAS_CPU_RM7000 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_MIPS_CMP + select SYS_SUPPORTS_MIPS_CPS + select SYS_SUPPORTS_MIPS16 + select SYS_SUPPORTS_MULTITHREADING + select SYS_SUPPORTS_SMARTMIPS + select SYS_SUPPORTS_ZBOOT + help + This enables support for the MIPS Technologies Malta evaluation + board. + +config MIPS_SEAD3 + bool "MIPS SEAD3 board" + select BOOT_ELF32 + select BOOT_RAW + select CEVT_R4K + select CSRC_R4K + select CSRC_GIC + select CPU_MIPSR2_IRQ_VI + select CPU_MIPSR2_IRQ_EI + select DMA_NONCOHERENT + select IRQ_CPU + select IRQ_GIC + select LIBFDT + select MIPS_MSC + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_MIPS32_R2 + select SYS_HAS_CPU_MIPS64_R1 + select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_SMARTMIPS + select SYS_SUPPORTS_MICROMIPS + select SYS_SUPPORTS_MIPS16 + select USB_EHCI_BIG_ENDIAN_DESC + select USB_EHCI_BIG_ENDIAN_MMIO + select USE_OF + help + This enables support for the MIPS Technologies SEAD3 evaluation + board. + +config NEC_MARKEINS + bool "NEC EMMA2RH Mark-eins board" + select SOC_EMMA2RH + select HW_HAS_PCI + help + This enables support for the NEC Electronics Mark-eins boards. + +config MACH_VR41XX + bool "NEC VR4100 series based machines" + select CEVT_R4K + select CSRC_R4K + select SYS_HAS_CPU_VR41XX + select SYS_SUPPORTS_MIPS16 + select ARCH_REQUIRE_GPIOLIB + +config NXP_STB220 + bool "NXP STB220 board" + select SOC_PNX833X + help + Support for NXP Semiconductors STB220 Development Board. + +config NXP_STB225 + bool "NXP 225 board" + select SOC_PNX833X + select SOC_PNX8335 + help + Support for NXP Semiconductors STB225 Development Board. + +config PMC_MSP + bool "PMC-Sierra MSP chipsets" + select CEVT_R4K + select CSRC_R4K + select DMA_NONCOHERENT + select SWAP_IO_SPACE + select NO_EXCEPT_FILL + select BOOT_RAW + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_MIPS16 + select IRQ_CPU + select SERIAL_8250 + select SERIAL_8250_CONSOLE + select USB_EHCI_BIG_ENDIAN_MMIO + select USB_EHCI_BIG_ENDIAN_DESC + help + This adds support for the PMC-Sierra family of Multi-Service + Processor System-On-A-Chips. These parts include a number + of integrated peripherals, interfaces and DSPs in addition to + a variety of MIPS cores. + +config RALINK + bool "Ralink based machines" + select CEVT_R4K + select CSRC_R4K + select BOOT_RAW + select DMA_NONCOHERENT + select IRQ_CPU + select USE_OF + select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_MIPS16 + select SYS_HAS_EARLY_PRINTK + select HAVE_MACH_CLKDEV + select CLKDEV_LOOKUP + select ARCH_HAS_RESET_CONTROLLER + select RESET_CONTROLLER + +config SGI_IP22 + bool "SGI IP22 (Indy/Indigo2)" + select FW_ARC + select FW_ARC32 + select BOOT_ELF32 + select CEVT_R4K + select CSRC_R4K + select DEFAULT_SGI_PARTITION + select DMA_NONCOHERENT + select HW_HAS_EISA + select I8253 + select I8259 + select IP22_CPU_SCACHE + select IRQ_CPU + select GENERIC_ISA_DMA_SUPPORT_BROKEN + select SGI_HAS_I8042 + select SGI_HAS_INDYDOG + select SGI_HAS_HAL2 + select SGI_HAS_SEEQ + select SGI_HAS_WD93 + select SGI_HAS_ZILOG + select SWAP_IO_SPACE + select SYS_HAS_CPU_R4X00 + select SYS_HAS_CPU_R5000 + # + # Disable EARLY_PRINTK for now since it leads to overwritten prom + # memory during early boot on some machines. + # + # See http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20091119164009.GA15038%40deprecation.cyrius.com + # for a more details discussion + # + # select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select MIPS_L1_CACHE_SHIFT_7 + help + This are the SGI Indy, Challenge S and Indigo2, as well as certain + OEM variants like the Tandem CMN B006S. To compile a Linux kernel + that runs on these, say Y here. + +config SGI_IP27 + bool "SGI IP27 (Origin200/2000)" + select FW_ARC + select FW_ARC64 + select BOOT_ELF64 + select DEFAULT_SGI_PARTITION + select DMA_COHERENT + select SYS_HAS_EARLY_PRINTK + select HW_HAS_PCI + select NR_CPUS_DEFAULT_64 + select SYS_HAS_CPU_R10000 + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_NUMA + select SYS_SUPPORTS_SMP + select MIPS_L1_CACHE_SHIFT_7 + help + This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics + workstations. To compile a Linux kernel that runs on these, say Y + here. + +config SGI_IP28 + bool "SGI IP28 (Indigo2 R10k)" + select FW_ARC + select FW_ARC64 + select BOOT_ELF64 + select CEVT_R4K + select CSRC_R4K + select DEFAULT_SGI_PARTITION + select DMA_NONCOHERENT + select GENERIC_ISA_DMA_SUPPORT_BROKEN + select IRQ_CPU + select HW_HAS_EISA + select I8253 + select I8259 + select SGI_HAS_I8042 + select SGI_HAS_INDYDOG + select SGI_HAS_HAL2 + select SGI_HAS_SEEQ + select SGI_HAS_WD93 + select SGI_HAS_ZILOG + select SWAP_IO_SPACE + select SYS_HAS_CPU_R10000 + # + # Disable EARLY_PRINTK for now since it leads to overwritten prom + # memory during early boot on some machines. + # + # See http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20091119164009.GA15038%40deprecation.cyrius.com + # for a more details discussion + # + # select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + help + This is the SGI Indigo2 with R10000 processor. To compile a Linux + kernel that runs on these, say Y here. + +config SGI_IP32 + bool "SGI IP32 (O2)" + select FW_ARC + select FW_ARC32 + select BOOT_ELF32 + select CEVT_R4K + select CSRC_R4K + select DMA_NONCOHERENT + select HW_HAS_PCI + select IRQ_CPU + select R5000_CPU_SCACHE + select RM7000_CPU_SCACHE + select SYS_HAS_CPU_R5000 + select SYS_HAS_CPU_R10000 if BROKEN + select SYS_HAS_CPU_RM7000 + select SYS_HAS_CPU_NEVADA + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + help + If you want this kernel to run on SGI O2 workstation, say Y here. + +config SIBYTE_CRHINE + bool "Sibyte BCM91120C-CRhine" + select BOOT_ELF32 + select DMA_COHERENT + select SIBYTE_BCM1120 + select SWAP_IO_SPACE + select SYS_HAS_CPU_SB1 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + +config SIBYTE_CARMEL + bool "Sibyte BCM91120x-Carmel" + select BOOT_ELF32 + select DMA_COHERENT + select SIBYTE_BCM1120 + select SWAP_IO_SPACE + select SYS_HAS_CPU_SB1 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + +config SIBYTE_CRHONE + bool "Sibyte BCM91125C-CRhone" + select BOOT_ELF32 + select DMA_COHERENT + select SIBYTE_BCM1125 + select SWAP_IO_SPACE + select SYS_HAS_CPU_SB1 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_HIGHMEM + select SYS_SUPPORTS_LITTLE_ENDIAN + +config SIBYTE_RHONE + bool "Sibyte BCM91125E-Rhone" + select BOOT_ELF32 + select DMA_COHERENT + select SIBYTE_BCM1125H + select SWAP_IO_SPACE + select SYS_HAS_CPU_SB1 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + +config SIBYTE_SWARM + bool "Sibyte BCM91250A-SWARM" + select BOOT_ELF32 + select DMA_COHERENT + select HAVE_PATA_PLATFORM + select SIBYTE_SB1250 + select SWAP_IO_SPACE + select SYS_HAS_CPU_SB1 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_HIGHMEM + select SYS_SUPPORTS_LITTLE_ENDIAN + select ZONE_DMA32 if 64BIT + +config SIBYTE_LITTLESUR + bool "Sibyte BCM91250C2-LittleSur" + select BOOT_ELF32 + select DMA_COHERENT + select HAVE_PATA_PLATFORM + select SIBYTE_SB1250 + select SWAP_IO_SPACE + select SYS_HAS_CPU_SB1 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_HIGHMEM + select SYS_SUPPORTS_LITTLE_ENDIAN + +config SIBYTE_SENTOSA + bool "Sibyte BCM91250E-Sentosa" + select BOOT_ELF32 + select DMA_COHERENT + select SIBYTE_SB1250 + select SWAP_IO_SPACE + select SYS_HAS_CPU_SB1 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + +config SIBYTE_BIGSUR + bool "Sibyte BCM91480B-BigSur" + select BOOT_ELF32 + select DMA_COHERENT + select NR_CPUS_DEFAULT_4 + select SIBYTE_BCM1x80 + select SWAP_IO_SPACE + select SYS_HAS_CPU_SB1 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_HIGHMEM + select SYS_SUPPORTS_LITTLE_ENDIAN + select ZONE_DMA32 if 64BIT + +config SNI_RM + bool "SNI RM200/300/400" + select FW_ARC if CPU_LITTLE_ENDIAN + select FW_ARC32 if CPU_LITTLE_ENDIAN + select FW_SNIPROM if CPU_BIG_ENDIAN + select ARCH_MAY_HAVE_PC_FDC + select BOOT_ELF32 + select CEVT_R4K + select CSRC_R4K + select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN + select DMA_NONCOHERENT + select GENERIC_ISA_DMA + select HAVE_PCSPKR_PLATFORM + select HW_HAS_EISA + select HW_HAS_PCI + select IRQ_CPU + select I8253 + select I8259 + select ISA + select SWAP_IO_SPACE if CPU_BIG_ENDIAN + select SYS_HAS_CPU_R4X00 + select SYS_HAS_CPU_R5000 + select SYS_HAS_CPU_R10000 + select R5000_CPU_SCACHE + select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_HIGHMEM + select SYS_SUPPORTS_LITTLE_ENDIAN + help + The SNI RM200/300/400 are MIPS-based machines manufactured by + Siemens Nixdorf Informationssysteme (SNI), parent company of Pyramid + Technology and now in turn merged with Fujitsu. Say Y here to + support this machine type. + +config MACH_TX39XX + bool "Toshiba TX39 series based machines" + +config MACH_TX49XX + bool "Toshiba TX49 series based machines" + +config MIKROTIK_RB532 + bool "Mikrotik RB532 boards" + select CEVT_R4K + select CSRC_R4K + select DMA_NONCOHERENT + select HW_HAS_PCI + select IRQ_CPU + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SWAP_IO_SPACE + select BOOT_RAW + select ARCH_REQUIRE_GPIOLIB + select MIPS_L1_CACHE_SHIFT_4 + help + Support the Mikrotik(tm) RouterBoard 532 series, + based on the IDT RC32434 SoC. + +config CAVIUM_OCTEON_SOC + bool "Cavium Networks Octeon SoC based boards" + select CEVT_R4K + select 64BIT_PHYS_ADDR + select DMA_COHERENT + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select EDAC_SUPPORT + select SYS_SUPPORTS_HOTPLUG_CPU + select SYS_HAS_EARLY_PRINTK + select SYS_HAS_CPU_CAVIUM_OCTEON + select SWAP_IO_SPACE + select HW_HAS_PCI + select ZONE_DMA32 + select HOLES_IN_ZONE + select ARCH_REQUIRE_GPIOLIB + select LIBFDT + select USE_OF + select ARCH_SPARSEMEM_ENABLE + select SYS_SUPPORTS_SMP + select NR_CPUS_DEFAULT_16 + help + This option supports all of the Octeon reference boards from Cavium + Networks. It builds a kernel that dynamically determines the Octeon + CPU type and supports all known board reference implementations. + Some of the supported boards are: + EBT3000 + EBH3000 + EBH3100 + Thunder + Kodama + Hikari + Say Y here for most Octeon reference boards. + +config NLM_XLR_BOARD + bool "Netlogic XLR/XLS based systems" + select BOOT_ELF32 + select NLM_COMMON + select SYS_HAS_CPU_XLR + select SYS_SUPPORTS_SMP + select HW_HAS_PCI + select SWAP_IO_SPACE + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select 64BIT_PHYS_ADDR + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_HIGHMEM + select DMA_COHERENT + select NR_CPUS_DEFAULT_32 + select CEVT_R4K + select CSRC_R4K + select IRQ_CPU + select ZONE_DMA32 if 64BIT + select SYNC_R4K + select SYS_HAS_EARLY_PRINTK + select SYS_SUPPORTS_ZBOOT + select SYS_SUPPORTS_ZBOOT_UART16550 + help + Support for systems based on Netlogic XLR and XLS processors. + Say Y here if you have a XLR or XLS based board. + +config NLM_XLP_BOARD + bool "Netlogic XLP based systems" + select BOOT_ELF32 + select NLM_COMMON + select SYS_HAS_CPU_XLP + select SYS_SUPPORTS_SMP + select HW_HAS_PCI + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select 64BIT_PHYS_ADDR + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_HIGHMEM + select DMA_COHERENT + select NR_CPUS_DEFAULT_32 + select CEVT_R4K + select CSRC_R4K + select IRQ_CPU + select ZONE_DMA32 if 64BIT + select SYNC_R4K + select SYS_HAS_EARLY_PRINTK + select USE_OF + select SYS_SUPPORTS_ZBOOT + select SYS_SUPPORTS_ZBOOT_UART16550 + help + This board is based on Netlogic XLP Processor. + Say Y here if you have a XLP based board. + +config MIPS_PARAVIRT + bool "Para-Virtualized guest system" + select CEVT_R4K + select CSRC_R4K + select DMA_COHERENT + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_SMP + select NR_CPUS_DEFAULT_4 + select SYS_HAS_EARLY_PRINTK + select SYS_HAS_CPU_MIPS32_R2 + select SYS_HAS_CPU_MIPS64_R2 + select SYS_HAS_CPU_CAVIUM_OCTEON + select HW_HAS_PCI + select SWAP_IO_SPACE + help + This option supports guest running under ???? + +endchoice + +source "arch/mips/alchemy/Kconfig" +source "arch/mips/ath79/Kconfig" +source "arch/mips/bcm47xx/Kconfig" +source "arch/mips/bcm63xx/Kconfig" +source "arch/mips/jazz/Kconfig" +source "arch/mips/jz4740/Kconfig" +source "arch/mips/lantiq/Kconfig" +source "arch/mips/lasat/Kconfig" +source "arch/mips/pmcs-msp71xx/Kconfig" +source "arch/mips/ralink/Kconfig" +source "arch/mips/sgi-ip27/Kconfig" +source "arch/mips/sibyte/Kconfig" +source "arch/mips/txx9/Kconfig" +source "arch/mips/vr41xx/Kconfig" +source "arch/mips/cavium-octeon/Kconfig" +source "arch/mips/loongson/Kconfig" +source "arch/mips/loongson1/Kconfig" +source "arch/mips/netlogic/Kconfig" +source "arch/mips/paravirt/Kconfig" + +endmenu + +config RWSEM_GENERIC_SPINLOCK + bool + default y + +config RWSEM_XCHGADD_ALGORITHM + bool + +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + +config GENERIC_HWEIGHT + bool + default y + +config GENERIC_CALIBRATE_DELAY + bool + default y + +config SCHED_OMIT_FRAME_POINTER + bool + default y + +# +# Select some configuration options automatically based on user selections. +# +config FW_ARC + bool + +config ARCH_MAY_HAVE_PC_FDC + bool + +config BOOT_RAW + bool + +config CEVT_BCM1480 + bool + +config CEVT_DS1287 + bool + +config CEVT_GT641XX + bool + +config CEVT_R4K + bool + +config CEVT_GIC + select MIPS_CM + bool + +config CEVT_SB1250 + bool + +config CEVT_TXX9 + bool + +config CSRC_BCM1480 + bool + +config CSRC_IOASIC + bool + +config CSRC_R4K + bool + +config CSRC_GIC + select MIPS_CM + bool + +config CSRC_SB1250 + bool + +config GPIO_TXX9 + select ARCH_REQUIRE_GPIOLIB + bool + +config FW_CFE + bool + +config ARCH_DMA_ADDR_T_64BIT + def_bool (HIGHMEM && 64BIT_PHYS_ADDR) || 64BIT + +config DMA_MAYBE_COHERENT + select DMA_NONCOHERENT + bool + +config DMA_COHERENT + bool + +config DMA_NONCOHERENT + bool + select NEED_DMA_MAP_STATE + +config NEED_DMA_MAP_STATE + bool + +config SYS_HAS_EARLY_PRINTK + bool + +config HOTPLUG_CPU + bool "Support for hot-pluggable CPUs" + depends on SMP && SYS_SUPPORTS_HOTPLUG_CPU + help + Say Y here to allow turning CPUs off and on. CPUs can be + controlled through /sys/devices/system/cpu. + (Note: power management support will enable this option + automatically on SMP systems. ) + Say N if you want to disable CPU hotplug. + +config SYS_SUPPORTS_HOTPLUG_CPU + bool + +config I8259 + bool + +config MIPS_BONITO64 + bool + +config MIPS_MSC + bool + +config MIPS_NILE4 + bool + +config SYNC_R4K + bool + +config MIPS_MACHINE + def_bool n + +config NO_IOPORT_MAP + def_bool n + +config GENERIC_ISA_DMA + bool + select ZONE_DMA if GENERIC_ISA_DMA_SUPPORT_BROKEN=n + select ISA_DMA_API + +config GENERIC_ISA_DMA_SUPPORT_BROKEN + bool + select GENERIC_ISA_DMA + +config ISA_DMA_API + bool + +config HOLES_IN_ZONE + bool + +# +# Endianness selection. Sufficiently obscure so many users don't know what to +# answer,so we try hard to limit the available choices. Also the use of a +# choice statement should be more obvious to the user. +# +choice + prompt "Endianness selection" + help + Some MIPS machines can be configured for either little or big endian + byte order. These modes require different kernels and a different + Linux distribution. In general there is one preferred byteorder for a + particular system but some systems are just as commonly used in the + one or the other endianness. + +config CPU_BIG_ENDIAN + bool "Big endian" + depends on SYS_SUPPORTS_BIG_ENDIAN + +config CPU_LITTLE_ENDIAN + bool "Little endian" + depends on SYS_SUPPORTS_LITTLE_ENDIAN + +endchoice + +config EXPORT_UASM + bool + +config SYS_SUPPORTS_APM_EMULATION + bool + +config SYS_SUPPORTS_BIG_ENDIAN + bool + +config SYS_SUPPORTS_LITTLE_ENDIAN + bool + +config SYS_SUPPORTS_HUGETLBFS + bool + depends on CPU_SUPPORTS_HUGEPAGES && 64BIT + default y + +config MIPS_HUGE_TLB_SUPPORT + def_bool HUGETLB_PAGE || TRANSPARENT_HUGEPAGE + +config IRQ_CPU + bool + +config IRQ_CPU_RM7K + bool + +config IRQ_MSP_SLP + bool + +config IRQ_MSP_CIC + bool + +config IRQ_TXX9 + bool + +config IRQ_GT641XX + bool + +config IRQ_GIC + select MIPS_CM + bool + +config PCI_GT64XXX_PCI0 + bool + +config NO_EXCEPT_FILL + bool + +config SOC_EMMA2RH + bool + select CEVT_R4K + select CSRC_R4K + select DMA_NONCOHERENT + select IRQ_CPU + select SWAP_IO_SPACE + select SYS_HAS_CPU_R5500 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + +config SOC_PNX833X + bool + select CEVT_R4K + select CSRC_R4K + select IRQ_CPU + select DMA_NONCOHERENT + select SYS_HAS_CPU_MIPS32_R2 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_MIPS16 + select CPU_MIPSR2_IRQ_VI + +config SOC_PNX8335 + bool + select SOC_PNX833X + +config SWAP_IO_SPACE + bool + +config SGI_HAS_INDYDOG + bool + +config SGI_HAS_HAL2 + bool + +config SGI_HAS_SEEQ + bool + +config SGI_HAS_WD93 + bool + +config SGI_HAS_ZILOG + bool + +config SGI_HAS_I8042 + bool + +config DEFAULT_SGI_PARTITION + bool + +config FW_ARC32 + bool + +config FW_SNIPROM + bool + +config BOOT_ELF32 + bool + +config MIPS_L1_CACHE_SHIFT_4 + bool + +config MIPS_L1_CACHE_SHIFT_5 + bool + +config MIPS_L1_CACHE_SHIFT_6 + bool + +config MIPS_L1_CACHE_SHIFT_7 + bool + +config MIPS_L1_CACHE_SHIFT + int + default "4" if MIPS_L1_CACHE_SHIFT_4 + default "5" if MIPS_L1_CACHE_SHIFT_5 + default "6" if MIPS_L1_CACHE_SHIFT_6 + default "7" if MIPS_L1_CACHE_SHIFT_7 + default "5" + +config HAVE_STD_PC_SERIAL_PORT + bool + +config ARC_CONSOLE + bool "ARC console support" + depends on SGI_IP22 || SGI_IP28 || (SNI_RM && CPU_LITTLE_ENDIAN) + +config ARC_MEMORY + bool + depends on MACH_JAZZ || SNI_RM || SGI_IP32 + default y + +config ARC_PROMLIB + bool + depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP28 || SGI_IP32 + default y + +config FW_ARC64 + bool + +config BOOT_ELF64 + bool + +menu "CPU selection" + +choice + prompt "CPU type" + default CPU_R4X00 + +config CPU_LOONGSON3 + bool "Loongson 3 CPU" + depends on SYS_HAS_CPU_LOONGSON3 + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + select CPU_SUPPORTS_HUGEPAGES + select WEAK_ORDERING + select WEAK_REORDERING_BEYOND_LLSC + help + The Loongson 3 processor implements the MIPS64R2 instruction + set with many extensions. + +config CPU_LOONGSON2E + bool "Loongson 2E" + depends on SYS_HAS_CPU_LOONGSON2E + select CPU_LOONGSON2 + help + The Loongson 2E processor implements the MIPS III instruction set + with many extensions. + + It has an internal FPGA northbridge, which is compatible to + bonito64. + +config CPU_LOONGSON2F + bool "Loongson 2F" + depends on SYS_HAS_CPU_LOONGSON2F + select CPU_LOONGSON2 + select ARCH_REQUIRE_GPIOLIB + help + The Loongson 2F processor implements the MIPS III instruction set + with many extensions. + + Loongson2F have built-in DDR2 and PCIX controller. The PCIX controller + have a similar programming interface with FPGA northbridge used in + Loongson2E. + +config CPU_LOONGSON1B + bool "Loongson 1B" + depends on SYS_HAS_CPU_LOONGSON1B + select CPU_LOONGSON1 + help + The Loongson 1B is a 32-bit SoC, which implements the MIPS32 + release 2 instruction set. + +config CPU_MIPS32_R1 + bool "MIPS32 Release 1" + depends on SYS_HAS_CPU_MIPS32_R1 + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + help + Choose this option to build a kernel for release 1 or later of the + MIPS32 architecture. Most modern embedded systems with a 32-bit + MIPS processor are based on a MIPS32 processor. If you know the + specific type of processor in your system, choose those that one + otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system. + Release 2 of the MIPS32 architecture is available since several + years so chances are you even have a MIPS32 Release 2 processor + in which case you should choose CPU_MIPS32_R2 instead for better + performance. + +config CPU_MIPS32_R2 + bool "MIPS32 Release 2" + depends on SYS_HAS_CPU_MIPS32_R2 + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + select CPU_SUPPORTS_MSA + select HAVE_KVM + help + Choose this option to build a kernel for release 2 or later of the + MIPS32 architecture. Most modern embedded systems with a 32-bit + MIPS processor are based on a MIPS32 processor. If you know the + specific type of processor in your system, choose those that one + otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system. + +config CPU_MIPS64_R1 + bool "MIPS64 Release 1" + depends on SYS_HAS_CPU_MIPS64_R1 + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + select CPU_SUPPORTS_HUGEPAGES + help + Choose this option to build a kernel for release 1 or later of the + MIPS64 architecture. Many modern embedded systems with a 64-bit + MIPS processor are based on a MIPS64 processor. If you know the + specific type of processor in your system, choose those that one + otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system. + Release 2 of the MIPS64 architecture is available since several + years so chances are you even have a MIPS64 Release 2 processor + in which case you should choose CPU_MIPS64_R2 instead for better + performance. + +config CPU_MIPS64_R2 + bool "MIPS64 Release 2" + depends on SYS_HAS_CPU_MIPS64_R2 + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + select CPU_SUPPORTS_HUGEPAGES + select CPU_SUPPORTS_MSA + help + Choose this option to build a kernel for release 2 or later of the + MIPS64 architecture. Many modern embedded systems with a 64-bit + MIPS processor are based on a MIPS64 processor. If you know the + specific type of processor in your system, choose those that one + otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system. + +config CPU_R3000 + bool "R3000" + depends on SYS_HAS_CPU_R3000 + select CPU_HAS_WB + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + help + Please make sure to pick the right CPU type. Linux/MIPS is not + designed to be generic, i.e. Kernels compiled for R3000 CPUs will + *not* work on R4000 machines and vice versa. However, since most + of the supported machines have an R4000 (or similar) CPU, R4x00 + might be a safe bet. If the resulting kernel does not work, + try to recompile with R3000. + +config CPU_TX39XX + bool "R39XX" + depends on SYS_HAS_CPU_TX39XX + select CPU_SUPPORTS_32BIT_KERNEL + +config CPU_VR41XX + bool "R41xx" + depends on SYS_HAS_CPU_VR41XX + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + help + The options selects support for the NEC VR4100 series of processors. + Only choose this option if you have one of these processors as a + kernel built with this option will not run on any other type of + processor or vice versa. + +config CPU_R4300 + bool "R4300" + depends on SYS_HAS_CPU_R4300 + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + help + MIPS Technologies R4300-series processors. + +config CPU_R4X00 + bool "R4x00" + depends on SYS_HAS_CPU_R4X00 + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HUGEPAGES + help + MIPS Technologies R4000-series processors other than 4300, including + the R4000, R4400, R4600, and 4700. + +config CPU_TX49XX + bool "R49XX" + depends on SYS_HAS_CPU_TX49XX + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HUGEPAGES + +config CPU_R5000 + bool "R5000" + depends on SYS_HAS_CPU_R5000 + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HUGEPAGES + help + MIPS Technologies R5000-series processors other than the Nevada. + +config CPU_R5432 + bool "R5432" + depends on SYS_HAS_CPU_R5432 + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HUGEPAGES + +config CPU_R5500 + bool "R5500" + depends on SYS_HAS_CPU_R5500 + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HUGEPAGES + help + NEC VR5500 and VR5500A series processors implement 64-bit MIPS IV + instruction set. + +config CPU_R6000 + bool "R6000" + depends on SYS_HAS_CPU_R6000 + select CPU_SUPPORTS_32BIT_KERNEL + help + MIPS Technologies R6000 and R6000A series processors. Note these + processors are extremely rare and the support for them is incomplete. + +config CPU_NEVADA + bool "RM52xx" + depends on SYS_HAS_CPU_NEVADA + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HUGEPAGES + help + QED / PMC-Sierra RM52xx-series ("Nevada") processors. + +config CPU_R8000 + bool "R8000" + depends on SYS_HAS_CPU_R8000 + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_64BIT_KERNEL + help + MIPS Technologies R8000 processors. Note these processors are + uncommon and the support for them is incomplete. + +config CPU_R10000 + bool "R10000" + depends on SYS_HAS_CPU_R10000 + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + select CPU_SUPPORTS_HUGEPAGES + help + MIPS Technologies R10000-series processors. + +config CPU_RM7000 + bool "RM7000" + depends on SYS_HAS_CPU_RM7000 + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + select CPU_SUPPORTS_HUGEPAGES + +config CPU_SB1 + bool "SB1" + depends on SYS_HAS_CPU_SB1 + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + select CPU_SUPPORTS_HUGEPAGES + select WEAK_ORDERING + +config CPU_CAVIUM_OCTEON + bool "Cavium Octeon processor" + depends on SYS_HAS_CPU_CAVIUM_OCTEON + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_64BIT_KERNEL + select WEAK_ORDERING + select CPU_SUPPORTS_HIGHMEM + select CPU_SUPPORTS_HUGEPAGES + select USB_EHCI_BIG_ENDIAN_MMIO + select MIPS_L1_CACHE_SHIFT_7 + help + The Cavium Octeon processor is a highly integrated chip containing + many ethernet hardware widgets for networking tasks. The processor + can have up to 16 Mips64v2 cores and 8 integrated gigabit ethernets. + Full details can be found at http://www.caviumnetworks.com. + +config CPU_BMIPS + bool "Broadcom BMIPS" + depends on SYS_HAS_CPU_BMIPS + select CPU_MIPS32 + select CPU_BMIPS32_3300 if SYS_HAS_CPU_BMIPS32_3300 + select CPU_BMIPS4350 if SYS_HAS_CPU_BMIPS4350 + select CPU_BMIPS4380 if SYS_HAS_CPU_BMIPS4380 + select CPU_BMIPS5000 if SYS_HAS_CPU_BMIPS5000 + select CPU_SUPPORTS_32BIT_KERNEL + select DMA_NONCOHERENT + select IRQ_CPU + select SWAP_IO_SPACE + select WEAK_ORDERING + select CPU_SUPPORTS_HIGHMEM + select CPU_HAS_PREFETCH + help + Support for BMIPS32/3300/4350/4380 and BMIPS5000 processors. + +config CPU_XLR + bool "Netlogic XLR SoC" + depends on SYS_HAS_CPU_XLR + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + select CPU_SUPPORTS_HUGEPAGES + select WEAK_ORDERING + select WEAK_REORDERING_BEYOND_LLSC + help + Netlogic Microsystems XLR/XLS processors. + +config CPU_XLP + bool "Netlogic XLP SoC" + depends on SYS_HAS_CPU_XLP + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + select WEAK_ORDERING + select WEAK_REORDERING_BEYOND_LLSC + select CPU_HAS_PREFETCH + select CPU_MIPSR2 + help + Netlogic Microsystems XLP processors. +endchoice + +config CPU_MIPS32_3_5_FEATURES + bool "MIPS32 Release 3.5 Features" + depends on SYS_HAS_CPU_MIPS32_R3_5 + depends on CPU_MIPS32_R2 + help + Choose this option to build a kernel for release 2 or later of the + MIPS32 architecture including features from the 3.5 release such as + support for Enhanced Virtual Addressing (EVA). + +config CPU_MIPS32_3_5_EVA + bool "Enhanced Virtual Addressing (EVA)" + depends on CPU_MIPS32_3_5_FEATURES + select EVA + default y + help + Choose this option if you want to enable the Enhanced Virtual + Addressing (EVA) on your MIPS32 core (such as proAptiv). + One of its primary benefits is an increase in the maximum size + of lowmem (up to 3GB). If unsure, say 'N' here. + +if CPU_LOONGSON2F +config CPU_NOP_WORKAROUNDS + bool + +config CPU_JUMP_WORKAROUNDS + bool + +config CPU_LOONGSON2F_WORKAROUNDS + bool "Loongson 2F Workarounds" + default y + select CPU_NOP_WORKAROUNDS + select CPU_JUMP_WORKAROUNDS + help + Loongson 2F01 / 2F02 processors have the NOP & JUMP issues which + require workarounds. Without workarounds the system may hang + unexpectedly. For more information please refer to the gas + -mfix-loongson2f-nop and -mfix-loongson2f-jump options. + + Loongson 2F03 and later have fixed these issues and no workarounds + are needed. The workarounds have no significant side effect on them + but may decrease the performance of the system so this option should + be disabled unless the kernel is intended to be run on 2F01 or 2F02 + systems. + + If unsure, please say Y. +endif # CPU_LOONGSON2F + +config SYS_SUPPORTS_ZBOOT + bool + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_BZIP2 + select HAVE_KERNEL_LZ4 + select HAVE_KERNEL_LZMA + select HAVE_KERNEL_LZO + select HAVE_KERNEL_XZ + +config SYS_SUPPORTS_ZBOOT_UART16550 + bool + select SYS_SUPPORTS_ZBOOT + +config CPU_LOONGSON2 + bool + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + select CPU_SUPPORTS_HUGEPAGES + +config CPU_LOONGSON1 + bool + select CPU_MIPS32 + select CPU_MIPSR2 + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + +config CPU_BMIPS32_3300 + select SMP_UP if SMP + bool + +config CPU_BMIPS4350 + bool + select SYS_SUPPORTS_SMP + select SYS_SUPPORTS_HOTPLUG_CPU + +config CPU_BMIPS4380 + bool + select SYS_SUPPORTS_SMP + select SYS_SUPPORTS_HOTPLUG_CPU + +config CPU_BMIPS5000 + bool + select MIPS_CPU_SCACHE + select SYS_SUPPORTS_SMP + select SYS_SUPPORTS_HOTPLUG_CPU + +config SYS_HAS_CPU_LOONGSON3 + bool + select CPU_SUPPORTS_CPUFREQ + +config SYS_HAS_CPU_LOONGSON2E + bool + +config SYS_HAS_CPU_LOONGSON2F + bool + select CPU_SUPPORTS_CPUFREQ + select CPU_SUPPORTS_ADDRWINCFG if 64BIT + select CPU_SUPPORTS_UNCACHED_ACCELERATED + +config SYS_HAS_CPU_LOONGSON1B + bool + +config SYS_HAS_CPU_MIPS32_R1 + bool + +config SYS_HAS_CPU_MIPS32_R2 + bool + +config SYS_HAS_CPU_MIPS32_R3_5 + bool + +config SYS_HAS_CPU_MIPS64_R1 + bool + +config SYS_HAS_CPU_MIPS64_R2 + bool + +config SYS_HAS_CPU_R3000 + bool + +config SYS_HAS_CPU_TX39XX + bool + +config SYS_HAS_CPU_VR41XX + bool + +config SYS_HAS_CPU_R4300 + bool + +config SYS_HAS_CPU_R4X00 + bool + +config SYS_HAS_CPU_TX49XX + bool + +config SYS_HAS_CPU_R5000 + bool + +config SYS_HAS_CPU_R5432 + bool + +config SYS_HAS_CPU_R5500 + bool + +config SYS_HAS_CPU_R6000 + bool + +config SYS_HAS_CPU_NEVADA + bool + +config SYS_HAS_CPU_R8000 + bool + +config SYS_HAS_CPU_R10000 + bool + +config SYS_HAS_CPU_RM7000 + bool + +config SYS_HAS_CPU_SB1 + bool + +config SYS_HAS_CPU_CAVIUM_OCTEON + bool + +config SYS_HAS_CPU_BMIPS + bool + +config SYS_HAS_CPU_BMIPS32_3300 + bool + select SYS_HAS_CPU_BMIPS + +config SYS_HAS_CPU_BMIPS4350 + bool + select SYS_HAS_CPU_BMIPS + +config SYS_HAS_CPU_BMIPS4380 + bool + select SYS_HAS_CPU_BMIPS + +config SYS_HAS_CPU_BMIPS5000 + bool + select SYS_HAS_CPU_BMIPS + +config SYS_HAS_CPU_XLR + bool + +config SYS_HAS_CPU_XLP + bool + +config MIPS_MALTA_PM + depends on MIPS_MALTA + depends on PCI + bool + default y + +# +# CPU may reorder R->R, R->W, W->R, W->W +# Reordering beyond LL and SC is handled in WEAK_REORDERING_BEYOND_LLSC +# +config WEAK_ORDERING + bool + +# +# CPU may reorder reads and writes beyond LL/SC +# CPU may reorder R->LL, R->LL, W->LL, W->LL, R->SC, R->SC, W->SC, W->SC +# +config WEAK_REORDERING_BEYOND_LLSC + bool +endmenu + +# +# These two indicate any level of the MIPS32 and MIPS64 architecture +# +config CPU_MIPS32 + bool + default y if CPU_MIPS32_R1 || CPU_MIPS32_R2 + +config CPU_MIPS64 + bool + default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 + +# +# These two indicate the revision of the architecture, either Release 1 or Release 2 +# +config CPU_MIPSR1 + bool + default y if CPU_MIPS32_R1 || CPU_MIPS64_R1 + +config CPU_MIPSR2 + bool + default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON + +config EVA + bool + +config SYS_SUPPORTS_32BIT_KERNEL + bool +config SYS_SUPPORTS_64BIT_KERNEL + bool +config CPU_SUPPORTS_32BIT_KERNEL + bool +config CPU_SUPPORTS_64BIT_KERNEL + bool +config CPU_SUPPORTS_CPUFREQ + bool +config CPU_SUPPORTS_ADDRWINCFG + bool +config CPU_SUPPORTS_HUGEPAGES + bool +config CPU_SUPPORTS_UNCACHED_ACCELERATED + bool +config MIPS_PGD_C0_CONTEXT + bool + default y if 64BIT && CPU_MIPSR2 && !CPU_XLP + +# +# Set to y for ptrace access to watch registers. +# +config HARDWARE_WATCHPOINTS + bool + default y if CPU_MIPSR1 || CPU_MIPSR2 + +menu "Kernel type" + +choice + prompt "Kernel code model" + help + You should only select this option if you have a workload that + actually benefits from 64-bit processing or if your machine has + large memory. You will only be presented a single option in this + menu if your system does not support both 32-bit and 64-bit kernels. + +config 32BIT + bool "32-bit kernel" + depends on CPU_SUPPORTS_32BIT_KERNEL && SYS_SUPPORTS_32BIT_KERNEL + select TRAD_SIGNALS + help + Select this option if you want to build a 32-bit kernel. +config 64BIT + bool "64-bit kernel" + depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL + help + Select this option if you want to build a 64-bit kernel. + +endchoice + +config KVM_GUEST + bool "KVM Guest Kernel" + depends on BROKEN_ON_SMP + help + Select this option if building a guest kernel for KVM (Trap & Emulate) mode + +config KVM_GUEST_TIMER_FREQ + int "Count/Compare Timer Frequency (MHz)" + depends on KVM_GUEST + default 100 + help + Set this to non-zero if building a guest kernel for KVM to skip RTC + emulation when determining guest CPU Frequency. Instead, the guest's + timer frequency is specified directly. + +choice + prompt "Kernel page size" + default PAGE_SIZE_4KB + +config PAGE_SIZE_4KB + bool "4kB" + depends on !CPU_LOONGSON2 && !CPU_LOONGSON3 + help + This option select the standard 4kB Linux page size. On some + R3000-family processors this is the only available page size. Using + 4kB page size will minimize memory consumption and is therefore + recommended for low memory systems. + +config PAGE_SIZE_8KB + bool "8kB" + depends on CPU_R8000 || CPU_CAVIUM_OCTEON + help + Using 8kB page size will result in higher performance kernel at + the price of higher memory consumption. This option is available + only on R8000 and cnMIPS processors. Note that you will need a + suitable Linux distribution to support this. + +config PAGE_SIZE_16KB + bool "16kB" + depends on !CPU_R3000 && !CPU_TX39XX + help + Using 16kB page size will result in higher performance kernel at + the price of higher memory consumption. This option is available on + all non-R3000 family processors. Note that you will need a suitable + Linux distribution to support this. + +config PAGE_SIZE_32KB + bool "32kB" + depends on CPU_CAVIUM_OCTEON + help + Using 32kB page size will result in higher performance kernel at + the price of higher memory consumption. This option is available + only on cnMIPS cores. Note that you will need a suitable Linux + distribution to support this. + +config PAGE_SIZE_64KB + bool "64kB" + depends on !CPU_R3000 && !CPU_TX39XX + help + Using 64kB page size will result in higher performance kernel at + the price of higher memory consumption. This option is available on + all non-R3000 family processor. Not that at the time of this + writing this option is still high experimental. + +endchoice + +config FORCE_MAX_ZONEORDER + int "Maximum zone order" + range 14 64 if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_64KB + default "14" if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_64KB + range 13 64 if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_32KB + default "13" if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_32KB + range 12 64 if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_16KB + default "12" if MIPS_HUGE_TLB_SUPPORT && PAGE_SIZE_16KB + range 11 64 + default "11" + help + The kernel memory allocator divides physically contiguous memory + blocks into "zones", where each zone is a power of two number of + pages. This option selects the largest power of two that the kernel + keeps in the memory allocator. If you need to allocate very large + blocks of physically contiguous memory, then you may need to + increase this value. + + This config option is actually maximum order plus one. For example, + a value of 11 means that the largest free memory block is 2^10 pages. + + The page size is not necessarily 4KB. Keep this in mind + when choosing a value for this option. + +config CEVT_GIC + bool "Use GIC global counter for clock events" + depends on IRQ_GIC && !MIPS_SEAD3 + help + Use the GIC global counter for the clock events. The R4K clock + event driver is always present, so if the platform ends up not + detecting a GIC, it will fall back to the R4K timer for the + generation of clock events. + +config BOARD_SCACHE + bool + +config IP22_CPU_SCACHE + bool + select BOARD_SCACHE + +# +# Support for a MIPS32 / MIPS64 style S-caches +# +config MIPS_CPU_SCACHE + bool + select BOARD_SCACHE + select MIPS_L1_CACHE_SHIFT_6 + +config R5000_CPU_SCACHE + bool + select BOARD_SCACHE + +config RM7000_CPU_SCACHE + bool + select BOARD_SCACHE + +config SIBYTE_DMA_PAGEOPS + bool "Use DMA to clear/copy pages" + depends on CPU_SB1 + help + Instead of using the CPU to zero and copy pages, use a Data Mover + channel. These DMA channels are otherwise unused by the standard + SiByte Linux port. Seems to give a small performance benefit. + +config CPU_HAS_PREFETCH + bool + +config CPU_GENERIC_DUMP_TLB + bool + default y if !(CPU_R3000 || CPU_R6000 || CPU_R8000 || CPU_TX39XX) + +config CPU_R4K_FPU + bool + default y if !(CPU_R3000 || CPU_R6000 || CPU_TX39XX || CPU_CAVIUM_OCTEON) + +config CPU_R4K_CACHE_TLB + bool + default y if !(CPU_R3000 || CPU_R8000 || CPU_SB1 || CPU_TX39XX || CPU_CAVIUM_OCTEON) + +config MIPS_MT_SMP + bool "MIPS MT SMP support (1 TC on each available VPE)" + depends on SYS_SUPPORTS_MULTITHREADING + select CPU_MIPSR2_IRQ_VI + select CPU_MIPSR2_IRQ_EI + select SYNC_R4K + select MIPS_GIC_IPI + select MIPS_MT + select SMP + select SMP_UP + select SYS_SUPPORTS_SMP + select SYS_SUPPORTS_SCHED_SMT + select MIPS_PERF_SHARED_TC_COUNTERS + help + This is a kernel model which is known as SMVP. This is supported + on cores with the MT ASE and uses the available VPEs to implement + virtual processors which supports SMP. This is equivalent to the + Intel Hyperthreading feature. For further information go to + . + +config MIPS_MT + bool + +config SCHED_SMT + bool "SMT (multithreading) scheduler support" + depends on SYS_SUPPORTS_SCHED_SMT + default n + help + SMT scheduler support improves the CPU scheduler's decision making + when dealing with MIPS MT enabled cores at a cost of slightly + increased overhead in some places. If unsure say N here. + +config SYS_SUPPORTS_SCHED_SMT + bool + +config SYS_SUPPORTS_MULTITHREADING + bool + +config MIPS_MT_FPAFF + bool "Dynamic FPU affinity for FP-intensive threads" + default y + depends on MIPS_MT_SMP + +config MIPS_VPE_LOADER + bool "VPE loader support." + depends on SYS_SUPPORTS_MULTITHREADING && MODULES + select CPU_MIPSR2_IRQ_VI + select CPU_MIPSR2_IRQ_EI + select MIPS_MT + help + Includes a loader for loading an elf relocatable object + onto another VPE and running it. + +config MIPS_VPE_LOADER_CMP + bool + default "y" + depends on MIPS_VPE_LOADER && MIPS_CMP + +config MIPS_VPE_LOADER_MT + bool + default "y" + depends on MIPS_VPE_LOADER && !MIPS_CMP + +config MIPS_VPE_LOADER_TOM + bool "Load VPE program into memory hidden from linux" + depends on MIPS_VPE_LOADER + default y + help + The loader can use memory that is present but has been hidden from + Linux using the kernel command line option "mem=xxMB". It's up to + you to ensure the amount you put in the option and the space your + program requires is less or equal to the amount physically present. + +config MIPS_VPE_APSP_API + bool "Enable support for AP/SP API (RTLX)" + depends on MIPS_VPE_LOADER + help + +config MIPS_VPE_APSP_API_CMP + bool + default "y" + depends on MIPS_VPE_APSP_API && MIPS_CMP + +config MIPS_VPE_APSP_API_MT + bool + default "y" + depends on MIPS_VPE_APSP_API && !MIPS_CMP + +config MIPS_CMP + bool "MIPS CMP framework support (DEPRECATED)" + depends on SYS_SUPPORTS_MIPS_CMP + select MIPS_GIC_IPI + select SYNC_R4K + select WEAK_ORDERING + default n + help + Select this if you are using a bootloader which implements the "CMP + framework" protocol (ie. YAMON) and want your kernel to make use of + its ability to start secondary CPUs. + + Unless you have a specific need, you should use CONFIG_MIPS_CPS + instead of this. + +config MIPS_CPS + bool "MIPS Coherent Processing System support" + depends on SYS_SUPPORTS_MIPS_CPS + select MIPS_CM + select MIPS_CPC + select MIPS_CPS_PM if HOTPLUG_CPU + select MIPS_GIC_IPI + select SMP + select SYNC_R4K if (CEVT_R4K || CSRC_R4K) + select SYS_SUPPORTS_HOTPLUG_CPU + select SYS_SUPPORTS_SMP + select WEAK_ORDERING + help + Select this if you wish to run an SMP kernel across multiple cores + within a MIPS Coherent Processing System. When this option is + enabled the kernel will probe for other cores and boot them with + no external assistance. It is safe to enable this when hardware + support is unavailable. + +config MIPS_CPS_PM + bool + +config MIPS_GIC_IPI + bool + +config MIPS_CM + bool + +config MIPS_CPC + bool + +config SB1_PASS_1_WORKAROUNDS + bool + depends on CPU_SB1_PASS_1 + default y + +config SB1_PASS_2_WORKAROUNDS + bool + depends on CPU_SB1 && (CPU_SB1_PASS_2_2 || CPU_SB1_PASS_2) + default y + +config SB1_PASS_2_1_WORKAROUNDS + bool + depends on CPU_SB1 && CPU_SB1_PASS_2 + default y + + +config 64BIT_PHYS_ADDR + bool + +config ARCH_PHYS_ADDR_T_64BIT + def_bool 64BIT_PHYS_ADDR + +config CPU_HAS_SMARTMIPS + depends on SYS_SUPPORTS_SMARTMIPS + bool "Support for the SmartMIPS ASE" + help + SmartMIPS is a extension of the MIPS32 architecture aimed at + increased security at both hardware and software level for + smartcards. Enabling this option will allow proper use of the + SmartMIPS instructions by Linux applications. However a kernel with + this option will not work on a MIPS core without SmartMIPS core. If + you don't know you probably don't have SmartMIPS and should say N + here. + +config CPU_MICROMIPS + depends on SYS_SUPPORTS_MICROMIPS + bool "Build kernel using microMIPS ISA" + help + When this option is enabled the kernel will be built using the + microMIPS ISA + +config CPU_HAS_MSA + bool "Support for the MIPS SIMD Architecture" + depends on CPU_SUPPORTS_MSA + default y + help + MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers + and a set of SIMD instructions to operate on them. When this option + is enabled the kernel will support allocating & switching MSA + vector register contexts. If you know that your kernel will only be + running on CPUs which do not support MSA or that your userland will + not be making use of it then you may wish to say N here to reduce + the size & complexity of your kernel. + + If unsure, say Y. + +config CPU_HAS_WB + bool + +config XKS01 + bool + +# +# Vectored interrupt mode is an R2 feature +# +config CPU_MIPSR2_IRQ_VI + bool + +# +# Extended interrupt mode is an R2 feature +# +config CPU_MIPSR2_IRQ_EI + bool + +config CPU_HAS_SYNC + bool + depends on !CPU_R3000 + default y + +# +# CPU non-features +# +config CPU_DADDI_WORKAROUNDS + bool + +config CPU_R4000_WORKAROUNDS + bool + select CPU_R4400_WORKAROUNDS + +config CPU_R4400_WORKAROUNDS + bool + +# +# - Highmem only makes sense for the 32-bit kernel. +# - The current highmem code will only work properly on physically indexed +# caches such as R3000, SB1, R7000 or those that look like they're virtually +# indexed such as R4000/R4400 SC and MC versions or R10000. So for the +# moment we protect the user and offer the highmem option only on machines +# where it's known to be safe. This will not offer highmem on a few systems +# such as MIPS32 and MIPS64 CPUs which may have virtual and physically +# indexed CPUs but we're playing safe. +# - We use SYS_SUPPORTS_HIGHMEM to offer highmem only for systems where we +# know they might have memory configurations that could make use of highmem +# support. +# +config HIGHMEM + bool "High Memory Support" + depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM && !CPU_MIPS32_3_5_EVA + +config CPU_SUPPORTS_HIGHMEM + bool + +config SYS_SUPPORTS_HIGHMEM + bool + +config SYS_SUPPORTS_SMARTMIPS + bool + +config SYS_SUPPORTS_MICROMIPS + bool + +config SYS_SUPPORTS_MIPS16 + bool + help + This option must be set if a kernel might be executed on a MIPS16- + enabled CPU even if MIPS16 is not actually being used. In other + words, it makes the kernel MIPS16-tolerant. + +config CPU_SUPPORTS_MSA + bool + +config ARCH_FLATMEM_ENABLE + def_bool y + depends on !NUMA && !CPU_LOONGSON2 + +config ARCH_DISCONTIGMEM_ENABLE + bool + default y if SGI_IP27 + help + Say Y to support efficient handling of discontiguous physical memory, + for architectures which are either NUMA (Non-Uniform Memory Access) + or have huge holes in the physical address space for other reasons. + See for more. + +config ARCH_SPARSEMEM_ENABLE + bool + select SPARSEMEM_STATIC + +config NUMA + bool "NUMA Support" + depends on SYS_SUPPORTS_NUMA + help + Say Y to compile the kernel to support NUMA (Non-Uniform Memory + Access). This option improves performance on systems with more + than two nodes; on two node systems it is generally better to + leave it disabled; on single node systems disable this option + disabled. + +config SYS_SUPPORTS_NUMA + bool + +config NODES_SHIFT + int + default "6" + depends on NEED_MULTIPLE_NODES + +config HW_PERF_EVENTS + bool "Enable hardware performance counter support for perf events" + depends on PERF_EVENTS && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP) + default y + help + Enable hardware performance counter support for perf events. If + disabled, perf events will use software events only. + +source "mm/Kconfig" + +config SMP + bool "Multi-Processing support" + depends on SYS_SUPPORTS_SMP + help + This enables support for systems with more than one CPU. If you have + a system with only one CPU, say N. If you have a system with more + than one CPU, say Y. + + If you say N here, the kernel will run on uni- and multiprocessor + machines, but will use only one CPU of a multiprocessor machine. If + you say Y here, the kernel will run on many, but not all, + uniprocessor machines. On a uniprocessor machine, the kernel + will run faster if you say N here. + + People using multiprocessor machines who say Y here should also say + Y to "Enhanced Real Time Clock Support", below. + + See also the SMP-HOWTO available at + . + + If you don't know what to do here, say N. + +config SMP_UP + bool + +config SYS_SUPPORTS_MIPS_CMP + bool + +config SYS_SUPPORTS_MIPS_CPS + bool + +config SYS_SUPPORTS_SMP + bool + +config NR_CPUS_DEFAULT_4 + bool + +config NR_CPUS_DEFAULT_8 + bool + +config NR_CPUS_DEFAULT_16 + bool + +config NR_CPUS_DEFAULT_32 + bool + +config NR_CPUS_DEFAULT_64 + bool + +config NR_CPUS + int "Maximum number of CPUs (2-256)" + range 2 256 + depends on SMP + default "4" if NR_CPUS_DEFAULT_4 + default "8" if NR_CPUS_DEFAULT_8 + default "16" if NR_CPUS_DEFAULT_16 + default "32" if NR_CPUS_DEFAULT_32 + default "64" if NR_CPUS_DEFAULT_64 + help + This allows you to specify the maximum number of CPUs which this + kernel will support. The maximum supported value is 32 for 32-bit + kernel and 64 for 64-bit kernels; the minimum value which makes + sense is 1 for Qemu (useful only for kernel debugging purposes) + and 2 for all others. + + This is purely to save memory - each supported CPU adds + approximately eight kilobytes to the kernel image. For best + performance should round up your number of processors to the next + power of two. + +config MIPS_PERF_SHARED_TC_COUNTERS + bool + +# +# Timer Interrupt Frequency Configuration +# + +choice + prompt "Timer frequency" + default HZ_250 + help + Allows the configuration of the timer frequency. + + config HZ_48 + bool "48 HZ" if SYS_SUPPORTS_48HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_100 + bool "100 HZ" if SYS_SUPPORTS_100HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_128 + bool "128 HZ" if SYS_SUPPORTS_128HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_250 + bool "250 HZ" if SYS_SUPPORTS_250HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_256 + bool "256 HZ" if SYS_SUPPORTS_256HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_1000 + bool "1000 HZ" if SYS_SUPPORTS_1000HZ || SYS_SUPPORTS_ARBIT_HZ + + config HZ_1024 + bool "1024 HZ" if SYS_SUPPORTS_1024HZ || SYS_SUPPORTS_ARBIT_HZ + +endchoice + +config SYS_SUPPORTS_48HZ + bool + +config SYS_SUPPORTS_100HZ + bool + +config SYS_SUPPORTS_128HZ + bool + +config SYS_SUPPORTS_250HZ + bool + +config SYS_SUPPORTS_256HZ + bool + +config SYS_SUPPORTS_1000HZ + bool + +config SYS_SUPPORTS_1024HZ + bool + +config SYS_SUPPORTS_ARBIT_HZ + bool + default y if !SYS_SUPPORTS_48HZ && !SYS_SUPPORTS_100HZ && \ + !SYS_SUPPORTS_128HZ && !SYS_SUPPORTS_250HZ && \ + !SYS_SUPPORTS_256HZ && !SYS_SUPPORTS_1000HZ && \ + !SYS_SUPPORTS_1024HZ + +config HZ + int + default 48 if HZ_48 + default 100 if HZ_100 + default 128 if HZ_128 + default 250 if HZ_250 + default 256 if HZ_256 + default 1000 if HZ_1000 + default 1024 if HZ_1024 + +source "kernel/Kconfig.preempt" + +config KEXEC + bool "Kexec system call" + help + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot + but it is independent of the system firmware. And like a reboot + you can start any kernel with it, not just Linux. + + The name comes from the similarity to the exec system call. + + It is an ongoing process to be certain the hardware in a machine + is properly shutdown, so do not be surprised if this code does not + initially work for you. As of this writing the exact hardware + interface is strongly in flux, so no good recommendation can be + made. + +config CRASH_DUMP + bool "Kernel crash dumps" + help + Generate crash dump after being started by kexec. + This should be normally only set in special crash dump kernels + which are loaded in the main kernel with kexec-tools into + a specially reserved region and then later executed after + a crash by kdump/kexec. The crash dump kernel must be compiled + to a memory address not used by the main kernel or firmware using + PHYSICAL_START. + +config PHYSICAL_START + hex "Physical address where the kernel is loaded" + default "0xffffffff84000000" if 64BIT + default "0x84000000" if 32BIT + depends on CRASH_DUMP + help + This gives the CKSEG0 or KSEG0 address where the kernel is loaded. + If you plan to use kernel for capturing the crash dump change + this value to start of the reserved region (the "X" value as + specified in the "crashkernel=YM@XM" command line boot parameter + passed to the panic-ed kernel). + +config SECCOMP + bool "Enable seccomp to safely compute untrusted bytecode" + depends on PROC_FS + default y + help + This kernel feature is useful for number crunching applications + that may need to compute untrusted bytecode during their + execution. By using pipes or other transports made available to + the process as file descriptors supporting the read/write + syscalls, it's possible to isolate those applications in + their own address space using seccomp. Once seccomp is + enabled via /proc//seccomp, it cannot be disabled + and the task is only allowed to execute a few safe syscalls + defined by each seccomp mode. + + If unsure, say Y. Only embedded should say N here. + +config MIPS_O32_FP64_SUPPORT + bool "Support for O32 binaries using 64-bit FP (EXPERIMENTAL)" + depends on 32BIT || MIPS32_O32 + help + When this is enabled, the kernel will support use of 64-bit floating + point registers with binaries using the O32 ABI along with the + EF_MIPS_FP64 ELF header flag (typically built with -mfp64). On + 32-bit MIPS systems this support is at the cost of increasing the + size and complexity of the compiled FPU emulator. Thus if you are + running a MIPS32 system and know that none of your userland binaries + will require 64-bit floating point, you may wish to reduce the size + of your kernel & potentially improve FP emulation performance by + saying N here. + + Although binutils currently supports use of this flag the details + concerning its effect upon the O32 ABI in userland are still being + worked on. In order to avoid userland becoming dependant upon current + behaviour before the details have been finalised, this option should + be considered experimental and only enabled by those working upon + said details. + + If unsure, say N. + +config USE_OF + bool + select OF + select OF_EARLY_FLATTREE + select IRQ_DOMAIN + +endmenu + +config LOCKDEP_SUPPORT + bool + default y + +config STACKTRACE_SUPPORT + bool + default y + +source "init/Kconfig" + +source "kernel/Kconfig.freezer" + +menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)" + +config HW_HAS_EISA + bool +config HW_HAS_PCI + bool + +config PCI + bool "Support for PCI controller" + depends on HW_HAS_PCI + select PCI_DOMAINS + select NO_GENERIC_PCI_IOPORT_MAP + help + Find out whether you have a PCI motherboard. PCI is the name of a + bus system, i.e. the way the CPU talks to the other stuff inside + your box. Other bus systems are ISA, EISA, or VESA. If you have PCI, + say Y, otherwise N. + +config HT_PCI + bool "Support for HT-linked PCI" + default y + depends on CPU_LOONGSON3 + select PCI + select PCI_DOMAINS + help + Loongson family machines use Hyper-Transport bus for inter-core + connection and device connection. The PCI bus is a subordinate + linked at HT. Choose Y for Loongson-3 based machines. + +config PCI_DOMAINS + bool + +source "drivers/pci/Kconfig" + +source "drivers/pci/pcie/Kconfig" + +# +# ISA support is now enabled via select. Too many systems still have the one +# or other ISA chip on the board that users don't know about so don't expect +# users to choose the right thing ... +# +config ISA + bool + +config EISA + bool "EISA support" + depends on HW_HAS_EISA + select ISA + select GENERIC_ISA_DMA + ---help--- + The Extended Industry Standard Architecture (EISA) bus was + developed as an open alternative to the IBM MicroChannel bus. + + The EISA bus provided some of the features of the IBM MicroChannel + bus while maintaining backward compatibility with cards made for + the older ISA bus. The EISA bus saw limited use between 1988 and + 1995 when it was made obsolete by the PCI bus. + + Say Y here if you are building a kernel for an EISA-based machine. + + Otherwise, say N. + +source "drivers/eisa/Kconfig" + +config TC + bool "TURBOchannel support" + depends on MACH_DECSTATION + help + TURBOchannel is a DEC (now Compaq (now HP)) bus for Alpha and MIPS + processors. TURBOchannel programming specifications are available + at: + + and: + + Linux driver support status is documented at: + + +config MMU + bool + default y + +config I8253 + bool + select CLKSRC_I8253 + select CLKEVT_I8253 + select MIPS_EXTERNAL_TIMER + +config ZONE_DMA + bool + +config ZONE_DMA32 + bool + +source "drivers/pcmcia/Kconfig" + +source "drivers/pci/hotplug/Kconfig" + +config RAPIDIO + tristate "RapidIO support" + depends on PCI + default n + help + If you say Y here, the kernel will include drivers and + infrastructure code to support RapidIO interconnect devices. + +source "drivers/rapidio/Kconfig" + +endmenu + +menu "Executable file formats" + +source "fs/Kconfig.binfmt" + +config TRAD_SIGNALS + bool + +config MIPS32_COMPAT + bool "Kernel support for Linux/MIPS 32-bit binary compatibility" + depends on 64BIT + help + Select this option if you want Linux/MIPS 32-bit binary + compatibility. Since all software available for Linux/MIPS is + currently 32-bit you should say Y here. + +config COMPAT + bool + depends on MIPS32_COMPAT + select ARCH_WANT_OLD_COMPAT_IPC + default y + +config SYSVIPC_COMPAT + bool + depends on COMPAT && SYSVIPC + default y + +config MIPS32_O32 + bool "Kernel support for o32 binaries" + depends on MIPS32_COMPAT + help + Select this option if you want to run o32 binaries. These are pure + 32-bit binaries as used by the 32-bit Linux/MIPS port. Most of + existing binaries are in this format. + + If unsure, say Y. + +config MIPS32_N32 + bool "Kernel support for n32 binaries" + depends on MIPS32_COMPAT + help + Select this option if you want to run n32 binaries. These are + 64-bit binaries using 32-bit quantities for addressing and certain + data that would normally be 64-bit. They are used in special + cases. + + If unsure, say N. + +config BINFMT_ELF32 + bool + default y if MIPS32_O32 || MIPS32_N32 + +endmenu + +menu "Power management options" + +config ARCH_HIBERNATION_POSSIBLE + def_bool y + depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP + +config ARCH_SUSPEND_POSSIBLE + def_bool y + depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP + +source "kernel/power/Kconfig" + +endmenu + +config MIPS_EXTERNAL_TIMER + bool + +menu "CPU Power Management" + +if CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER +source "drivers/cpufreq/Kconfig" +endif + +source "drivers/cpuidle/Kconfig" + +endmenu + +source "net/Kconfig" + +source "drivers/Kconfig" + +source "drivers/firmware/Kconfig" + +source "fs/Kconfig" + +source "arch/mips/Kconfig.debug" + +source "security/Kconfig" + +source "crypto/Kconfig" + +source "lib/Kconfig" + +source "arch/mips/kvm/Kconfig" Index: trunk/linux/arch/mips/include/asm/mach-aor3000/war.h =================================================================== --- trunk/linux/arch/mips/include/asm/mach-aor3000/war.h (nonexistent) +++ trunk/linux/arch/mips/include/asm/mach-aor3000/war.h (revision 2) @@ -0,0 +1,17 @@ +#ifndef __ASM_MACH_AOR3000_WAR_H +#define __ASM_MACH_AOR3000_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MACH_AOR3000_WAR_H */ Index: trunk/linux/arch/mips/aor3000/time.c =================================================================== --- trunk/linux/arch/mips/aor3000/time.c (nonexistent) +++ trunk/linux/arch/mips/aor3000/time.c (revision 2) @@ -0,0 +1,74 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include +#include +#include +#include + +#include + +#define SIMPLE_TIMER_IRQ_NUMBER 2 +#define SIMPLE_TIMER_ACK_ADDRESS 0xBFFFFFF8 + +static void simple_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + break; + case CLOCK_EVT_MODE_RESUME: + break; + } +} + +static struct clock_event_device simple_clockevent_device = { + .name = "simple-timer", + .features = CLOCK_EVT_FEAT_PERIODIC, + + /* .set_mode, .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */ + + .rating = 300, + .irq = SIMPLE_TIMER_IRQ_NUMBER, + .cpumask = cpu_all_mask, + .set_mode = simple_timer_set_mode, +}; + +static irqreturn_t simple_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *cd = dev_id; + + *(volatile u8 *)SIMPLE_TIMER_ACK_ADDRESS = 0; + + cd->event_handler(cd); + + return IRQ_HANDLED; +} + +static struct irqaction simple_timer_irqaction = { + .handler = simple_timer_interrupt, + .flags = IRQF_PERCPU | IRQF_TIMER, + .name = "simple-timer", +}; + +void __init plat_time_init(void) +{ + struct clock_event_device *cd = &simple_clockevent_device; + struct irqaction *action = &simple_timer_irqaction; + + clockevent_set_clock(cd, 100); + + clockevents_register_device(cd); + action->dev_id = cd; + setup_irq(SIMPLE_TIMER_IRQ_NUMBER, &simple_timer_irqaction); +} Index: trunk/linux/arch/mips/aor3000/Kconfig =================================================================== --- trunk/linux/arch/mips/aor3000/Kconfig (nonexistent) +++ trunk/linux/arch/mips/aor3000/Kconfig (revision 2) @@ -0,0 +1,3 @@ +if AOR3000 + +endif Index: trunk/linux/arch/mips/aor3000/early_printk.c =================================================================== --- trunk/linux/arch/mips/aor3000/early_printk.c (nonexistent) +++ trunk/linux/arch/mips/aor3000/early_printk.c (revision 2) @@ -0,0 +1,13 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +void prom_putchar(char c) +{ + volatile char *console_ptr = (volatile char *)0xBFFFFFFF; + (*console_ptr) = c; +} Index: trunk/linux/arch/mips/aor3000/Platform =================================================================== --- trunk/linux/arch/mips/aor3000/Platform (nonexistent) +++ trunk/linux/arch/mips/aor3000/Platform (revision 2) @@ -0,0 +1,3 @@ +core-$(CONFIG_AOR3000) += arch/mips/aor3000/ +cflags-$(CONFIG_AOR3000) += -I$(srctree)/arch/mips/include/asm/mach-aor3000 +load-$(CONFIG_AOR3000) += 0x80000000 Index: trunk/linux/arch/mips/aor3000/altera_jtaguart.c =================================================================== --- trunk/linux/arch/mips/aor3000/altera_jtaguart.c (nonexistent) +++ trunk/linux/arch/mips/aor3000/altera_jtaguart.c (revision 2) @@ -0,0 +1,39 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include +#include + +struct resource altera_jtaguart_resources[] = { + { + .start = 0x1FFFFFF0, + .end = 0x1FFFFFF7, + .flags = IORESOURCE_MEM, + }, { + .start = 3, + .end = 3, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device altera_jtaguart_device = { + .name = "altera_jtaguart", + .id = 0, + .resource = altera_jtaguart_resources, + .num_resources = ARRAY_SIZE(altera_jtaguart_resources), +}; + + +static int __init aor3000_platform_init(void) +{ + platform_device_register(&altera_jtaguart_device); + return 0; +} + +device_initcall(aor3000_platform_init); Index: trunk/linux/arch/mips/aor3000/wbflush.c =================================================================== --- trunk/linux/arch/mips/aor3000/wbflush.c (nonexistent) +++ trunk/linux/arch/mips/aor3000/wbflush.c (revision 2) @@ -0,0 +1,39 @@ +/* The code in this file is taken from the arch/mips/dec/wbflush.c. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998 Harald Koerfgen + * Copyright (C) 2002 Maciej W. Rozycki + * Copyright (C) 2014 Aleksander Osman + */ + +#include + +#include + +static void wbflush_r3000(void); + +void (*__wbflush) (void); + +void __init wbflush_setup(void) +{ + __wbflush = wbflush_r3000; +} + +/* + * For the aoR3000 the writeback buffer functions as part of Coprocessor 0. + */ +static void wbflush_r3000(void) +{ + asm(".set\tpush\n\t" + ".set\tnoreorder\n\t" + "1:\tbc0f\t1b\n\t" + "nop\n\t" + ".set\tpop"); +} + +#include + +EXPORT_SYMBOL(__wbflush); Index: trunk/linux/arch/mips/aor3000/irq.c =================================================================== --- trunk/linux/arch/mips/aor3000/irq.c (nonexistent) +++ trunk/linux/arch/mips/aor3000/irq.c (revision 2) @@ -0,0 +1,39 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include + +#include +#include + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending; + + pending = read_c0_cause() & read_c0_status() & ST0_IM; + + if (pending & CAUSEF_IP2) + do_IRQ(2); + else if (pending & CAUSEF_IP3) + do_IRQ(3); + else if (pending & CAUSEF_IP4) + do_IRQ(4); + else if (pending & CAUSEF_IP5) + do_IRQ(5); + else if (pending & CAUSEF_IP6) + do_IRQ(6); + else if (pending & CAUSEF_IP7) + do_IRQ(7); + else + spurious_interrupt(); +} + +void __init arch_init_irq(void) +{ + mips_cpu_irq_init(); +} Index: trunk/linux/arch/mips/aor3000/Makefile =================================================================== --- trunk/linux/arch/mips/aor3000/Makefile (nonexistent) +++ trunk/linux/arch/mips/aor3000/Makefile (revision 2) @@ -0,0 +1,3 @@ +obj-y := prom.o irq.o wbflush.o time.o altera_jtaguart.o + +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o Index: trunk/linux/arch/mips/aor3000/prom.c =================================================================== --- trunk/linux/arch/mips/aor3000/prom.c (nonexistent) +++ trunk/linux/arch/mips/aor3000/prom.c (revision 2) @@ -0,0 +1,35 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include +#include + +const char *get_system_type(void) +{ + return "aoR3000 SoC"; +} + +void __init plat_mem_setup(void) +{ + //set_io_port_base(KSEG1); + //ioport_resource.start, .end + + add_memory_region(PHYS_OFFSET, 0x08000000, BOOT_MEM_RAM); +} + +void __init prom_init(void) +{ + //clear_c0_status(ST0_IM | ST0_BEV); -- not needed, done later in trap initialization +} + +void __init prom_free_prom_memory(void) +{ +} Index: trunk/rtl/model/model_simple_dual_ram.v =================================================================== --- trunk/rtl/model/model_simple_dual_ram.v (nonexistent) +++ trunk/rtl/model/model_simple_dual_ram.v (revision 2) @@ -0,0 +1,30 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +module model_simple_dual_ram( + input clk, + + input [widthad-1:0] address_a, + output reg [width-1:0] q_a, + + input [widthad-1:0] address_b, + input wren_b, + input [width-1:0] data_b +); /* verilator public_module */ + +parameter width = 1; +parameter widthad = 1; + +reg [width-1:0] mem [(2**widthad)-1:0]; + +always @(posedge clk) begin + if(wren_b) mem[address_b] <= data_b; + + q_a <= mem[address_a]; +end + +endmodule Index: trunk/rtl/model/model_mult.v =================================================================== --- trunk/rtl/model/model_mult.v (nonexistent) +++ trunk/rtl/model/model_mult.v (revision 2) @@ -0,0 +1,41 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +module model_mult( + input clk, + input signed [widtha-1:0] a, + input signed [widthb-1:0] b, + output [widthp-1:0] out +); + +//------------------------------------------------------------------------------ + +parameter widtha = 1; +parameter widthb = 1; +parameter widthp = 2; + +//------------------------------------------------------------------------------ + +reg signed [widtha-1:0] a_reg; +reg signed [widthb-1:0] b_reg; +reg signed [widthp-1:0] out_1; + +assign out = out_1; + +wire signed [widthp-1:0] mult_out; +assign mult_out = a_reg * b_reg; + +always @ (posedge clk) +begin + a_reg <= a; + b_reg <= b; + out_1 <= mult_out; +end + +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/model/model_true_dual_ram.v =================================================================== --- trunk/rtl/model/model_true_dual_ram.v (nonexistent) +++ trunk/rtl/model/model_true_dual_ram.v (revision 2) @@ -0,0 +1,39 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +module model_true_dual_ram( + input clk, + + input [widthad-1:0] address_a, + input wren_a, + input [width-1:0] data_a, + output reg [width-1:0] q_a, + + input [widthad-1:0] address_b, + input wren_b, + input [width-1:0] data_b, + output reg [width-1:0] q_b +); /* verilator public_module */ + +parameter width = 1; +parameter widthad = 1; + +reg [width-1:0] mem [(2**widthad)-1:0]; + +always @(posedge clk) begin + if(wren_a) mem[address_a] <= data_a; + + q_a <= mem[address_a]; +end + +always @(posedge clk) begin + if(wren_b) mem[address_b] <= data_b; + + q_b <= mem[address_b]; +end + +endmodule Index: trunk/rtl/model/model_fifo.v =================================================================== --- trunk/rtl/model/model_fifo.v (nonexistent) +++ trunk/rtl/model/model_fifo.v (revision 2) @@ -0,0 +1,65 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +module model_fifo( + input clk, + input rst_n, + input sclr, + + input rdreq, + input wrreq, + input [width-1:0] data, + + output empty, + output reg full, + output [width-1:0] q, + output reg [widthu-1:0] usedw +); + +parameter width = 2; +parameter widthu = 2; + +reg [width-1:0] mem [(2**widthu)-1:0]; + +reg [widthu-1:0] rd_index = 0; +reg [widthu-1:0] wr_index = 0; + +assign q = mem[rd_index]; +assign empty= usedw == 0 && ~(full); + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) rd_index <= 0; + else if(sclr) rd_index <= 0; + else if(rdreq && ~(empty)) rd_index <= rd_index + { {widthu-1{1'b0}}, 1'b1 }; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) wr_index <= 0; + else if(sclr) wr_index <= 0; + else if(wrreq && (~(full) || rdreq)) wr_index <= wr_index + { {widthu-1{1'b0}}, 1'b1 }; +end + +always @(posedge clk) begin + if(wrreq && (~(full) || rdreq)) mem[wr_index] <= data; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) full <= 1'b0; + else if(sclr) full <= 1'b0; + else if(rdreq && ~(wrreq) && full) full <= 1'b0; + else if(~(rdreq) && wrreq && ~(full) && usedw == (2**widthu)-1) full <= 1'b1; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) usedw <= 0; + else if(sclr) usedw <= 0; + else if(rdreq && ~(wrreq) && ~(empty)) usedw <= usedw - { {widthu-1{1'b0}}, 1'b1 }; + else if(~(rdreq) && wrreq && ~(full)) usedw <= usedw + { {widthu-1{1'b0}}, 1'b1 }; + else if(rdreq && wrreq && empty) usedw <= { {widthu-1{1'b0}}, 1'b1 }; +end + +endmodule Index: trunk/rtl/defines.v =================================================================== --- trunk/rtl/defines.v (nonexistent) +++ trunk/rtl/defines.v (revision 2) @@ -0,0 +1,98 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +//------------------------------------------------------------------------------ + +`define TRUE 1'b1 +`define FALSE 1'b0 + +//------------------------------------------------------------------------------ + +`define CMD_null 7'd0 + +`define CMD_3arg_add 7'd1 +`define CMD_3arg_addu 7'd2 +`define CMD_3arg_and 7'd3 +`define CMD_3arg_nor 7'd4 +`define CMD_3arg_or 7'd5 +`define CMD_3arg_slt 7'd6 +`define CMD_3arg_sltu 7'd7 +`define CMD_3arg_sub 7'd8 +`define CMD_3arg_subu 7'd9 +`define CMD_3arg_xor 7'd10 +`define CMD_3arg_sllv 7'd11 +`define CMD_3arg_srav 7'd12 +`define CMD_3arg_srlv 7'd13 +`define CMD_sll 7'd14 +`define CMD_sra 7'd15 +`define CMD_srl 7'd16 +`define CMD_addi 7'd17 +`define CMD_addiu 7'd18 +`define CMD_andi 7'd19 +`define CMD_ori 7'd20 +`define CMD_slti 7'd21 +`define CMD_sltiu 7'd22 +`define CMD_xori 7'd23 +`define CMD_muldiv_mfhi 7'd24 +`define CMD_muldiv_mflo 7'd25 +`define CMD_muldiv_mthi 7'd26 +`define CMD_muldiv_mtlo 7'd27 +`define CMD_muldiv_mult 7'd28 +`define CMD_muldiv_multu 7'd29 +`define CMD_muldiv_div 7'd30 +`define CMD_muldiv_divu 7'd31 +`define CMD_lui 7'd32 +`define CMD_break 7'd33 +`define CMD_syscall 7'd34 +`define CMD_mtc0 7'd35 +`define CMD_mfc0 7'd36 +`define CMD_cfc1_detect 7'd37 +`define CMD_cp0_rfe 7'd38 +`define CMD_cp0_tlbp 7'd39 +`define CMD_cp0_tlbr 7'd40 +`define CMD_cp0_tlbwi 7'd41 +`define CMD_cp0_tlbwr 7'd42 +`define CMD_lb 7'd43 +`define CMD_lbu 7'd44 +`define CMD_lh 7'd45 +`define CMD_lhu 7'd46 +`define CMD_lw 7'd47 +`define CMD_lwl 7'd48 +`define CMD_lwr 7'd49 +`define CMD_sb 7'd50 +`define CMD_sh 7'd51 +`define CMD_sw 7'd52 +`define CMD_swl 7'd53 +`define CMD_swr 7'd54 +`define CMD_beq 7'd55 +`define CMD_bne 7'd56 +`define CMD_bgez 7'd57 +`define CMD_bgtz 7'd58 +`define CMD_blez 7'd59 +`define CMD_bltz 7'd60 +`define CMD_jr 7'd61 +`define CMD_bgezal 7'd62 +`define CMD_bltzal 7'd63 +`define CMD_jalr 7'd64 +`define CMD_jal 7'd65 +`define CMD_j 7'd66 +`define CMD_cp0_bc0f 7'd67 +`define CMD_cp0_bc0t 7'd68 +`define CMD_cp0_bc0_ign 7'd69 + +`define CMD_exc_coproc_unusable 7'd70 +`define CMD_exc_reserved_instr 7'd71 +`define CMD_exc_int_overflow 7'd72 +`define CMD_exc_load_addr_err 7'd73 +`define CMD_exc_store_addr_err 7'd74 +`define CMD_exc_load_tlb 7'd75 +`define CMD_exc_store_tlb 7'd76 +`define CMD_exc_tlb_load_miss 7'd77 +`define CMD_exc_tlb_store_miss 7'd78 +`define CMD_exc_tlb_modif 7'd79 + +//------------------------------------------------------------------------------ Index: trunk/rtl/pipeline/pipeline_rf.v =================================================================== --- trunk/rtl/pipeline/pipeline_rf.v (nonexistent) +++ trunk/rtl/pipeline/pipeline_rf.v (revision 2) @@ -0,0 +1,373 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module pipeline_rf( + input clk, + input rst_n, + + // + input exception_start, + + // + input if_exc_address_error, + input if_exc_tlb_inv, + input if_exc_tlb_miss, + input if_ready, + input [31:0] if_instr, + input [31:0] if_pc, + + // + output [6:0] rf_cmd, + output reg [31:0] rf_instr, + output reg [31:0] rf_pc_plus4, + output reg [31:0] rf_badvpn, + output [31:0] rf_a, + output [31:0] rf_b, + + // + input mem_stall, + + // + input [4:0] exe_result_index, + input [31:0] exe_result, + + input [4:0] mem_result_index, + input [31:0] mem_result, + + input [4:0] muldiv_result_index, + input [31:0] muldiv_result +); + +//------------------------------------------------------------------------------ + +wire rf_load = (if_ready || if_exc_address_error || if_exc_tlb_inv || if_exc_tlb_miss) && ~(mem_stall); + +//------------------------------------------------------------------------------ + +//rd <- rs OP rt +wire cmd_3arg_add = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100000; +wire cmd_3arg_addu = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100001; +wire cmd_3arg_and = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100100; +wire cmd_3arg_nor = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100111; +wire cmd_3arg_or = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100101; +wire cmd_3arg_slt = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b101010; +wire cmd_3arg_sltu = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b101011; +wire cmd_3arg_sub = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100010; +wire cmd_3arg_subu = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100011; +wire cmd_3arg_xor = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b100110; +wire cmd_3arg_sllv = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000100; +wire cmd_3arg_srav = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000111; +wire cmd_3arg_srlv = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000110; + +//rd <- rt OP imm +wire cmd_sll = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000000; +wire cmd_sra = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000011; +wire cmd_srl = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b000010; + +//rt <- rs OP imm +wire cmd_addi = rf_instr[31:26] == 6'b001000; +wire cmd_addiu = rf_instr[31:26] == 6'b001001; +wire cmd_andi = rf_instr[31:26] == 6'b001100; +wire cmd_ori = rf_instr[31:26] == 6'b001101; +wire cmd_slti = rf_instr[31:26] == 6'b001010; +wire cmd_sltiu = rf_instr[31:26] == 6'b001011; +wire cmd_xori = rf_instr[31:26] == 6'b001110; + +//rd <- hi,lo +wire cmd_muldiv_mfhi = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b010000; +wire cmd_muldiv_mflo = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b010010; + +//hi,lo <- rs +wire cmd_muldiv_mthi = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b010001 && rf_instr[15:11] == 5'b00000; +wire cmd_muldiv_mtlo = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b010011 && rf_instr[15:11] == 5'b00000; + +//hi,lo <- rs OP rt +wire cmd_muldiv_mult = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b011000 && rf_instr[15:11] == 5'b00000; +wire cmd_muldiv_multu = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b011001 && rf_instr[15:11] == 5'b00000; +wire cmd_muldiv_div = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b011010; +wire cmd_muldiv_divu = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b011011; + +//rt <- imm +wire cmd_lui = rf_instr[31:26] == 6'b001111; + +//exception +wire cmd_break = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b001101; +wire cmd_syscall = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b001100; + +wire cmd_unusable123 = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] != 2'b00 && ~(cmd_cfc1_detect); +wire cmd_lwc123 = rf_instr[31:28] == 4'b1100 && rf_instr[27:26] != 2'b00; +wire cmd_swc123 = rf_instr[31:28] == 4'b1110 && rf_instr[27:26] != 2'b00; + +//cmd_swc0, cmd_lwc0, cmd_cop0_inv: `CMD_exc_reserved_instr + +wire exc_coproc_unusable = cmd_unusable123 || cmd_lwc123 || cmd_swc123; + +// rt <- 0 +wire cmd_cfc1_detect = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b01 && rf_instr[25:21] == 5'b00010 && rf_instr[15:11] == 5'b00000; + +//rd_cp0 <- rt +wire cmd_mtc0 = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25:21] == 5'b00100; +//rt <- rd_cp0 +wire cmd_mfc0 = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25:21] == 5'b00000; + +wire cmd_bc0f = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25:21] == 5'b01000 && rf_instr[20:16] == 5'd0; +wire cmd_bc0t = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25:21] == 5'b01000 && rf_instr[20:16] == 5'd1; +wire cmd_bc0_ign = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25:21] == 5'b01000 && (rf_instr[20:16] == 5'd2 || rf_instr[20:16] == 5'd3); + +wire cmd_rfe = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25] == 1'b1 && rf_instr[5:0] == 6'b010000; +wire cmd_tlbp = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25] == 1'b1 && rf_instr[5:0] == 6'b001000; +wire cmd_tlbr = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25] == 1'b1 && rf_instr[5:0] == 6'b000001; +wire cmd_tlbwi = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25] == 1'b1 && rf_instr[5:0] == 6'b000010; +wire cmd_tlbwr = rf_instr[31:28] == 4'b0100 && rf_instr[27:26] == 2'b00 && rf_instr[25] == 1'b1 && rf_instr[5:0] == 6'b000110; + +//rt <- mem +wire cmd_lb = rf_instr[31:26] == 6'b100000; +wire cmd_lbu = rf_instr[31:26] == 6'b100100; +wire cmd_lh = rf_instr[31:26] == 6'b100001; +wire cmd_lhu = rf_instr[31:26] == 6'b100101; +wire cmd_lw = rf_instr[31:26] == 6'b100011; +wire cmd_lwl = rf_instr[31:26] == 6'b100010; +wire cmd_lwr = rf_instr[31:26] == 6'b100110; + +//mem <- rt +wire cmd_sb = rf_instr[31:26] == 6'b101000; +wire cmd_sh = rf_instr[31:26] == 6'b101001; +wire cmd_sw = rf_instr[31:26] == 6'b101011; +wire cmd_swl = rf_instr[31:26] == 6'b101010; +wire cmd_swr = rf_instr[31:26] == 6'b101110; + +//<- rs, rt +wire cmd_beq = rf_instr[31:26] == 6'b000100; +wire cmd_bne = rf_instr[31:26] == 6'b000101; +//<- rs +wire cmd_bgez = rf_instr[31:26] == 6'b000001 && rf_instr[20:16] == 5'b00001; +wire cmd_bgtz = rf_instr[31:26] == 6'b000111 && rf_instr[20:16] == 5'b00000; +wire cmd_blez = rf_instr[31:26] == 6'b000110 && rf_instr[20:16] == 5'b00000; +wire cmd_bltz = rf_instr[31:26] == 6'b000001 && rf_instr[20:16] == 5'b00000; +wire pre_jr = if_instr[31:26] == 6'b000000 && if_instr[5:0] == 6'b001000; +wire cmd_jr = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b001000 && rf_jr_check; +//r31 <- rs +wire cmd_bgezal = rf_instr[31:26] == 6'b000001 && rf_instr[20:16] == 5'b10001; +wire cmd_bltzal = rf_instr[31:26] == 6'b000001 && rf_instr[20:16] == 5'b10000; +//rd <- rs +wire cmd_jalr = rf_instr[31:26] == 6'b000000 && rf_instr[5:0] == 6'b001001; +//r31 <- +wire cmd_jal = rf_instr[31:26] == 6'b000011; +// +wire cmd_j = rf_instr[31:26] == 6'b000010; + +//------------------------------------------------------------------------------ + +assign rf_cmd = + (exception_start)? `CMD_null : + (rf_exc_address_error)? `CMD_exc_load_addr_err : + (rf_exc_tlb_inv)? `CMD_exc_load_tlb : + (rf_exc_tlb_miss)? `CMD_exc_tlb_load_miss : + (~(rf_ready))? `CMD_null : + (cmd_3arg_add)? `CMD_3arg_add : + (cmd_3arg_addu)? `CMD_3arg_addu : + (cmd_3arg_and)? `CMD_3arg_and : + (cmd_3arg_nor)? `CMD_3arg_nor : + (cmd_3arg_or)? `CMD_3arg_or : + (cmd_3arg_slt)? `CMD_3arg_slt : + (cmd_3arg_sltu)? `CMD_3arg_sltu : + (cmd_3arg_sub)? `CMD_3arg_sub : + (cmd_3arg_subu)? `CMD_3arg_subu : + (cmd_3arg_xor)? `CMD_3arg_xor : + (cmd_3arg_sllv)? `CMD_3arg_sllv : + (cmd_3arg_srav)? `CMD_3arg_srav : + (cmd_3arg_srlv)? `CMD_3arg_srlv : + (cmd_sll)? `CMD_sll : + (cmd_sra)? `CMD_sra : + (cmd_srl)? `CMD_srl : + (cmd_addi)? `CMD_addi : + (cmd_addiu)? `CMD_addiu : + (cmd_andi)? `CMD_andi : + (cmd_ori)? `CMD_ori : + (cmd_slti)? `CMD_slti : + (cmd_sltiu)? `CMD_sltiu : + (cmd_xori)? `CMD_xori : + (cmd_muldiv_mfhi)? `CMD_muldiv_mfhi : + (cmd_muldiv_mflo)? `CMD_muldiv_mflo : + (cmd_muldiv_mthi)? `CMD_muldiv_mthi : + (cmd_muldiv_mtlo)? `CMD_muldiv_mtlo : + (cmd_muldiv_mult)? `CMD_muldiv_mult : + (cmd_muldiv_multu)? `CMD_muldiv_multu : + (cmd_muldiv_div)? `CMD_muldiv_div : + (cmd_muldiv_divu)? `CMD_muldiv_divu : + (cmd_lui)? `CMD_lui : + (cmd_break)? `CMD_break : + (cmd_syscall)? `CMD_syscall : + (exc_coproc_unusable)? `CMD_exc_coproc_unusable : + (cmd_mtc0)? `CMD_mtc0 : + (cmd_mfc0)? `CMD_mfc0 : + (cmd_cfc1_detect)? `CMD_cfc1_detect : + (cmd_rfe)? `CMD_cp0_rfe : + (cmd_tlbp)? `CMD_cp0_tlbp : + (cmd_tlbr)? `CMD_cp0_tlbr : + (cmd_tlbwi)? `CMD_cp0_tlbwi : + (cmd_tlbwr)? `CMD_cp0_tlbwr : + (cmd_bc0f)? `CMD_cp0_bc0f : + (cmd_bc0t)? `CMD_cp0_bc0t : + (cmd_bc0_ign)? `CMD_cp0_bc0_ign : + (cmd_lb)? `CMD_lb : + (cmd_lbu)? `CMD_lbu : + (cmd_lh)? `CMD_lh : + (cmd_lhu)? `CMD_lhu : + (cmd_lw)? `CMD_lw : + (cmd_lwl)? `CMD_lwl : + (cmd_lwr)? `CMD_lwr : + (cmd_sb)? `CMD_sb : + (cmd_sh)? `CMD_sh : + (cmd_sw)? `CMD_sw : + (cmd_swl)? `CMD_swl : + (cmd_swr)? `CMD_swr : + (cmd_beq)? `CMD_beq : + (cmd_bne)? `CMD_bne : + (cmd_bgez)? `CMD_bgez : + (cmd_bgtz)? `CMD_bgtz : + (cmd_blez)? `CMD_blez : + (cmd_bltz)? `CMD_bltz : + (cmd_jr)? `CMD_jr : + (cmd_bgezal)? `CMD_bgezal : + (cmd_bltzal)? `CMD_bltzal : + (cmd_jalr)? `CMD_jalr : + (cmd_jal)? `CMD_jal : + (cmd_j)? `CMD_j : + `CMD_exc_reserved_instr; + +reg rf_exc_address_error; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) rf_exc_address_error <= `FALSE; + else if(exception_start) rf_exc_address_error <= `FALSE; + else if(rf_load) rf_exc_address_error <= if_exc_address_error; +end + +reg rf_exc_tlb_inv; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) rf_exc_tlb_inv <= `FALSE; + else if(exception_start) rf_exc_tlb_inv <= `FALSE; + else if(rf_load) rf_exc_tlb_inv <= if_exc_tlb_inv; +end + +reg rf_exc_tlb_miss; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) rf_exc_tlb_miss <= `FALSE; + else if(exception_start) rf_exc_tlb_miss <= `FALSE; + else if(rf_load) rf_exc_tlb_miss <= if_exc_tlb_miss; +end + +reg rf_ready; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) rf_ready <= `FALSE; + else if(exception_start) rf_ready <= `FALSE; + else if(rf_load && if_ready)rf_ready <= `TRUE; + else if(~(mem_stall)) rf_ready <= `FALSE; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) rf_instr <= 32'd0; + else if(rf_load) rf_instr <= if_instr; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) rf_pc_plus4 <= 32'd0; + else if(rf_load) rf_pc_plus4 <= if_pc + 32'd4; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) rf_badvpn <= 32'd0; + else if(rf_load) rf_badvpn <= if_pc; +end + +//------------------------------------------------------------------------------ + +wire [4:0] rf_instr_rs = rf_instr[25:21]; +wire [4:0] rf_instr_rt = rf_instr[20:16]; +wire [4:0] rf_instr_rd = rf_instr[15:11]; + +assign rf_a = + (exe_result_index != 5'd0 && rf_instr_rs == exe_result_index)? exe_result : + (muldiv_result_index != 5'd0 && rf_instr_rs == muldiv_result_index)? muldiv_result : + (mem_result_index != 5'd0 && rf_instr_rs == mem_result_index)? mem_result : + q_a_final; + +assign rf_b = + (exe_result_index != 5'd0 && rf_instr_rt == exe_result_index)? exe_result : + (muldiv_result_index != 5'd0 && rf_instr_rt == muldiv_result_index)? muldiv_result : + (mem_result_index != 5'd0 && rf_instr_rt == mem_result_index)? mem_result : + q_b_final; + +wire rf_jr_check = + (exe_result_index != 5'd0 && rf_instr_rd == exe_result_index)? exe_result == 32'd0 : + (muldiv_result_index != 5'd0 && rf_instr_rd == muldiv_result_index)? muldiv_result == 32'd0 : + (mem_result_index != 5'd0 && rf_instr_rd == mem_result_index)? mem_result == 32'd0 : + q_b_final == 32'd0; + +//------------------------------------------------------------------------------ + +reg [4:0] address_a_reg; +reg [4:0] address_b_reg; +reg [4:0] written_index_reg; +reg [31:0] written_data_reg; + +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) address_a_reg <= 5'd0; else if(~(mem_stall)) address_a_reg <= address_a; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) address_b_reg <= 5'd0; else if(~(mem_stall)) address_b_reg <= address_b; end + +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) written_data_reg <= 32'd0; else written_data_reg <= mem_result; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) written_index_reg <= 5'd0; else written_index_reg <= mem_result_index; end + +wire [31:0] q_a_final = (written_index_reg != 5'd0 && address_a_reg == written_index_reg)? written_data_reg : q_a; +wire [31:0] q_b_final = (written_index_reg != 5'd0 && address_b_reg == written_index_reg)? written_data_reg : q_b; + +//------------------------------------------------------------------------------ +wire [4:0] if_instr_rs = if_instr[25:21]; +wire [4:0] if_instr_rt = if_instr[20:16]; +wire [4:0] if_instr_rd = if_instr[15:11]; + +wire [4:0] address_a = if_instr_rs; +wire [4:0] address_b = (pre_jr)? if_instr_rd : if_instr_rt; + +wire [31:0] q_a; +wire [31:0] q_b; + +model_simple_dual_ram #( + .width (32), + .widthad (5) +) +regs_a_inst( + .clk (clk), + + .address_a ((mem_stall)? address_a_reg : address_a), + .q_a (q_a), + + .address_b (mem_result_index), + .wren_b (mem_result_index != 5'd0), + .data_b (mem_result) +); + +model_simple_dual_ram #( + .width (32), + .widthad (5) +) +regs_b_inst( + .clk (clk), + + .address_a ((mem_stall)? address_b_reg : address_b), + .q_a (q_b), + + .address_b (mem_result_index), + .wren_b (mem_result_index != 5'd0), + .data_b (mem_result) +); + + +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/pipeline/pipeline_if.v =================================================================== --- trunk/rtl/pipeline/pipeline_if.v (nonexistent) +++ trunk/rtl/pipeline/pipeline_if.v (revision 2) @@ -0,0 +1,348 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module pipeline_if( + input clk, + input rst_n, + + // + input config_kernel_mode, + input [5:0] entryhi_asid, + + // + input micro_flush_do, + + // + input exception_start, + input [31:0] exception_start_pc, + + // + input mem_stall, + + // + output if_exc_address_error, + output if_exc_tlb_inv, + output if_exc_tlb_miss, + output if_ready, + output [31:0] if_instr, + output reg [31:0] if_pc, + + // + input branch_start, + input [31:0] branch_address, + + // + output [8:0] fetch_cache_read_address, + input [53:0] fetch_cache_q, + + output [8:0] fetch_cache_write_address, + output fetch_cache_write_enable, + output [53:0] fetch_cache_data, + + // + output tlb_ram_fetch_start, + output [19:0] tlb_ram_fetch_vpn, + input tlb_ram_fetch_hit, + input [49:0] tlb_ram_fetch_result, + input tlb_ram_fetch_missed, + + // + output [31:0] ram_instr_address, + output ram_instr_req, + input ram_instr_ack, + + // + input [31:0] ram_result_address, + input ram_result_valid, + input ram_result_is_read_instr, + input [2:0] ram_result_burstcount, + input [31:0] ram_result +); /* verilator public_module */ + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +reg [31:0] branch_pc; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) branch_pc <= 32'h0; + else if(branch_start) branch_pc <= branch_address; +end + +reg branch_waiting; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) branch_waiting <= `FALSE; + else if(if_ready || exception_start) branch_waiting <= `FALSE; + else if(branch_start && ~(if_ready)) branch_waiting <= `TRUE; +end + +reg [31:0] exc_start_pc; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) exc_start_pc <= 32'hBFC00000; + else if(exception_start) exc_start_pc <= exception_start_pc; +end + +reg exc_waiting; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) exc_waiting <= `TRUE; + else if(exception_start) exc_waiting <= `TRUE; + else if(fetch_state == FETCH_IDLE) exc_waiting <= `FALSE; +end + +wire [31:0] if_pc_next = (exc_waiting)? exc_start_pc : (branch_start)? branch_address : (branch_waiting)? branch_pc : if_pc + 32'd4; + +wire if_pc_update = if_ready || (exc_waiting && fetch_state == FETCH_IDLE); + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) if_pc <= 32'h0; + else if(if_pc_update) if_pc <= if_pc_next; +end + +reg if_pc_updated; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) if_pc_updated <= `FALSE; + else if_pc_updated <= if_pc_update; +end + +//------------------------------------------------------------------------------ + +reg [19:0] if_pc_vpn_last; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) if_pc_vpn_last <= 20'd0; + else if_pc_vpn_last <= if_pc[31:12]; +end + +reg if_pc_vpn_changed; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) if_pc_vpn_changed <= `FALSE; + else if(fetch_state == FETCH_IDLE) if_pc_vpn_changed <= `FALSE; + else if(if_pc[31:12] != if_pc_vpn_last) if_pc_vpn_changed <= `TRUE; +end + +wire if_pc_vpn_change = if_pc[31:12] != if_pc_vpn_last || if_pc_vpn_changed; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +wire tlb_use_at_idle = fetch_state == FETCH_IDLE && (if_pc[31] == 1'b0 || if_pc[31:30] == 2'b11); + +wire [19:0] pfn_at_idle = + (~(tlb_use_at_idle))? { 3'b0, if_pc[28:12] } : + (micro_check_matched)? micro_check_result[39:20] : + tlb_ram_fetch_result[39:20]; + +reg [19:0] pfn_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) pfn_reg <= 20'd0; + else if(fetch_state == FETCH_IDLE) pfn_reg <= pfn_at_idle; + else if(fetch_tlb_tlb_ok_cache_bad) pfn_reg <= tlb_ram_fetch_result[39:20]; +end + +wire n_at_idle = + (~(tlb_use_at_idle))? if_pc[31:29] == 3'b101 : + (micro_check_matched)? micro_check_result[46] : + tlb_ram_fetch_result[46]; + +reg n_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) n_reg <= `FALSE; + else if(fetch_state == FETCH_IDLE) n_reg <= n_at_idle; + else if(fetch_tlb_tlb_ok_cache_bad) n_reg <= tlb_ram_fetch_result[46]; +end + +reg [53:0] fetch_cache_q_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) fetch_cache_q_reg <= 54'd0; + else if(fetch_state == FETCH_IDLE) fetch_cache_q_reg <= fetch_cache_q; +end + +//------------------------------------------------------------------------------ + +localparam [1:0] FETCH_IDLE = 2'd0; +localparam [1:0] FETCH_TLB = 2'd1; +localparam [1:0] FETCH_RESULT = 2'd2; +localparam [1:0] FETCH_STOPPED = 2'd3; + +reg [1:0] fetch_state; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) fetch_state <= FETCH_STOPPED; + + else if(fetch_state == FETCH_STOPPED && exc_waiting) fetch_state <= FETCH_IDLE; + + else if(fetch_idle_exc_address_error) fetch_state <= FETCH_STOPPED; + else if(fetch_idle_tlb_bad_exc_inv) fetch_state <= FETCH_STOPPED; + else if(fetch_idle_tlb_ok_cache_bad) fetch_state <= FETCH_RESULT; + else if(fetch_idle_tlb_wait) fetch_state <= FETCH_TLB; + + else if(fetch_tlb_tlb_ok_cache_ok) fetch_state <= FETCH_IDLE; + else if(fetch_tlb_tlb_bad_exc_inv || fetch_tlb_tlb_bad_exc_miss) fetch_state <= FETCH_STOPPED; + else if(fetch_tlb_tlb_ok_cache_bad) fetch_state <= FETCH_RESULT; + + else if(fetch_result_finished) fetch_state <= FETCH_IDLE; +end + +assign if_ready = ~(mem_stall) && ~(exc_waiting) && ( + fetch_idle_tlb_ok_cache_ok || + fetch_tlb_tlb_ok_cache_ok || + (ram_result_valid && ram_result_is_read_instr && ram_result_address[31:2] == { pfn_reg, if_pc[11:2] } && if_pc[1:0] == 2'b00 && ~(if_pc_vpn_change)) +); + +assign if_instr = + (fetch_idle_tlb_ok_cache_ok)? fetch_cache_q[31:0] : + (fetch_state == FETCH_TLB)? fetch_cache_q_reg[31:0] : + ram_result; + +assign ram_instr_req = fetch_idle_tlb_ok_cache_bad || fetch_tlb_tlb_ok_cache_bad || (fetch_state == FETCH_RESULT && ~(was_ram_ack) && ~(ram_instr_ack)); +assign ram_instr_address = (fetch_state == FETCH_IDLE)? { pfn_at_idle, if_pc[11:0] } : { pfn_reg, if_pc[11:0] }; + +assign if_exc_address_error = ~(exc_waiting) && (fetch_idle_exc_address_error || exception_reg == 2'd1); +assign if_exc_tlb_inv = ~(exc_waiting) && (fetch_idle_tlb_bad_exc_inv || fetch_tlb_tlb_bad_exc_inv || (fetch_tlb_tlb_bad_exc_miss && if_pc[31] == 1'b1) || exception_reg == 2'd2); +assign if_exc_tlb_miss = ~(exc_waiting) && ((fetch_tlb_tlb_bad_exc_miss && if_pc[31] == 1'b0) || exception_reg == 2'd3); + +reg [1:0] exception_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) exception_reg <= 2'd0; + else if(exception_start || exc_waiting) exception_reg <= 2'd0; + else if(if_exc_address_error) exception_reg <= 2'd1; + else if(if_exc_tlb_inv) exception_reg <= 2'd2; + else if(if_exc_tlb_miss) exception_reg <= 2'd3; +end + +//------------------------------------------------------------------------------ + +assign tlb_ram_fetch_start = if_pc_updated || (fetch_state == FETCH_IDLE && (~(tlb_ram_fetch_active) || tlb_ram_fetch_hit || tlb_ram_fetch_missed)) || (fetch_state == FETCH_TLB && ~(tlb_ram_fetch_active)); +assign tlb_ram_fetch_vpn = if_pc[31:12]; + +reg tlb_ram_fetch_active; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) tlb_ram_fetch_active <= `FALSE; + else if(tlb_ram_fetch_start) tlb_ram_fetch_active <= `TRUE; + else if(tlb_ram_fetch_hit || tlb_ram_fetch_missed) tlb_ram_fetch_active <= `FALSE; +end + +//------------------------------------------------------------------------------ state IDLE + +wire fetch_idle_no_addr_exc = if_pc[1:0] == 2'b00 && (config_kernel_mode || if_pc[31] == 1'b0); +wire fetch_idle_exc_address_error = fetch_state == FETCH_IDLE && ~(fetch_idle_no_addr_exc) && ~(exc_waiting); + +wire fetch_idle_tlb_ok_cache_ok = fetch_state == FETCH_IDLE && ~(exc_waiting) && fetch_cache_q[53] && ~(n_at_idle) && fetch_idle_no_addr_exc && ( + (~(tlb_use_at_idle) && fetch_cache_q[52:32] == { pfn_at_idle, if_pc[11] }) || //tlb not in use + (tlb_use_at_idle && micro_check_matched && micro_check_result[48] && fetch_cache_q[52:32] == {micro_check_result[39:20], if_pc[11]}) //tlb in micro +); + +wire fetch_idle_tlb_bad_exc_inv = fetch_state == FETCH_IDLE && ~(exc_waiting) && tlb_use_at_idle && fetch_idle_no_addr_exc && ( + (micro_check_matched && ~(micro_check_result[48])) //tlb in micro +); + +wire fetch_idle_tlb_ok_cache_bad = fetch_state == FETCH_IDLE && ~(exc_waiting) && fetch_idle_no_addr_exc && ( + (~(tlb_use_at_idle) && (~(fetch_cache_q[53]) || n_at_idle || fetch_cache_q[52:32] != { pfn_at_idle, if_pc[11] })) || //tlb not in use + (tlb_use_at_idle && micro_check_matched && micro_check_result[48] && (~(fetch_cache_q[53]) || n_at_idle || fetch_cache_q[52:32] != {micro_check_result[39:20], if_pc[11]})) //tlb in micro +); + +wire fetch_idle_tlb_wait = fetch_state == FETCH_IDLE && ~(exc_waiting) && fetch_idle_no_addr_exc && tlb_use_at_idle && ~(micro_check_matched); + +//------------------------------------------------------------------------------ state TLB + +wire fetch_tlb_tlb_ok_cache_ok = fetch_state == FETCH_TLB && tlb_ram_fetch_hit && tlb_ram_fetch_result[48] && fetch_cache_q_reg[53] && fetch_cache_q_reg[52:32] == { tlb_ram_fetch_result[39:20], if_pc[11] }; + +wire fetch_tlb_tlb_bad_exc_inv = fetch_state == FETCH_TLB && tlb_ram_fetch_hit && ~(tlb_ram_fetch_result[48]); +wire fetch_tlb_tlb_bad_exc_miss = fetch_state == FETCH_TLB && ~(tlb_ram_fetch_hit) && tlb_ram_fetch_missed; + +wire fetch_tlb_tlb_ok_cache_bad = fetch_state == FETCH_TLB && tlb_ram_fetch_hit && tlb_ram_fetch_result[48] && (~(fetch_cache_q_reg[53]) || fetch_cache_q_reg[52:32] != { tlb_ram_fetch_result[39:20], if_pc[11] }); + +//------------------------------------------------------------------------------ state RESULT + +reg was_ram_ack; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) was_ram_ack <= `FALSE; + else if(fetch_state != FETCH_RESULT) was_ram_ack <= `FALSE; + else if(ram_instr_ack) was_ram_ack <= `TRUE; +end + +reg is_ram_stalled; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) is_ram_stalled <= `FALSE; + else if(mem_stall && ram_result_valid && ram_result_is_read_instr && ram_result_burstcount == 3'd1) is_ram_stalled <= `TRUE; + else if(~(mem_stall)) is_ram_stalled <= `FALSE; +end + +wire fetch_result_finished = ~(mem_stall) && fetch_state == FETCH_RESULT && ((ram_result_valid && ram_result_is_read_instr && ram_result_burstcount == 3'd1) || is_ram_stalled); + +//------------------------------------------------------------------------------ cache +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +assign fetch_cache_read_address = (if_pc_update)? if_pc_next[10:2] : if_pc[10:2]; + +assign fetch_cache_write_address = ram_result_address[10:2]; + +assign fetch_cache_write_enable = (~(n_reg) && ram_result_valid && ram_result_is_read_instr); + +/* +[53] valid +[52:32] tag +[31:0] data +*/ +assign fetch_cache_data = { 1'b1, ram_result_address[31:11], ram_result }; //load + +//------------------------------------------------------------------------------ micro +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +/* +[19:0] vpn +[39:20] pfn +[45:40] asid +[46] n noncachable +[47] d dirty = write-enable +[48] v valid +[49] g global +*/ + +//input micro_check_matched, +//input [49:0] micro_check_result, + +wire micro_check_do = tlb_use_at_idle; +wire [19:0] micro_check_vpn = if_pc[31:12]; +wire [5:0] micro_check_asid = entryhi_asid; + +wire micro_write_do = tlb_ram_fetch_hit && fetch_state == FETCH_TLB; + +wire [49:0] micro_write_value = tlb_ram_fetch_result; + +wire micro_check_matched; +wire [49:0] micro_check_result; + +memory_instr_tlb_micro memory_instr_tlb_micro_inst( + .clk (clk), + .rst_n (rst_n), + + // + .micro_flush_do (micro_flush_do), //input + + // + .micro_write_do (micro_write_do), //input + .micro_write_value (micro_write_value), //input [49:0] + + // + .micro_check_do (micro_check_do), //input + .micro_check_vpn (micro_check_vpn), //input [19:0] + .micro_check_asid (micro_check_asid), //input [5:0] + .micro_check_matched(micro_check_matched), //output + .micro_check_result (micro_check_result) //output [49:0] +); + +//------------------------------------------------------------------------------ +// synthesis translate_off +wire _unused_ok = &{ 1'b0, ram_result_address[1:0], micro_check_result[49], micro_check_result[47], micro_check_result[45:40], micro_check_result[19:0], 1'b0 }; +// synthesis translate_on +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/pipeline/pipeline_mem.v =================================================================== --- trunk/rtl/pipeline/pipeline_mem.v (nonexistent) +++ trunk/rtl/pipeline/pipeline_mem.v (revision 2) @@ -0,0 +1,853 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module pipeline_mem( + input clk, + input rst_n, + + // + input [5:0] interrupt_vector, + + // + output mem_stall, + + // + output config_kernel_mode, + output config_switch_caches, + + // + input [6:0] exe_cmd, + input [31:0] exe_instr, + input [31:0] exe_pc_plus4, + input exe_pc_user_seg, + input [31:0] exe_badvpn, + input [31:0] exe_a, + input [31:0] exe_b, + input [1:0] exe_branched, + input [31:0] exe_branch_address, + input exe_cmd_cp0, + input exe_cmd_load, + input exe_cmd_store, + + // + input [4:0] exe_result_index, + input [31:0] exe_result, + + // + output reg [4:0] mem_result_index, + output [31:0] mem_result, + + // + output [4:0] muldiv_result_index, + output [31:0] muldiv_result, + + // + output tlb_ram_read_do, + output [5:0] tlb_ram_read_index, + input tlb_ram_read_result_ready, + input [49:0] tlb_ram_read_result, + + // + output tlb_ram_write_do, + output [5:0] tlb_ram_write_index, + output [49:0] tlb_ram_write_value, + + // + output tlb_ram_data_start, + output [19:0] tlb_ram_data_vpn, + input tlb_ram_data_hit, + input [5:0] tlb_ram_data_index, + input [49:0] tlb_ram_data_result, + input tlb_ram_data_missed, + + // + output exception_start, + output [31:0] exception_start_pc, + + // + output micro_flush_do, + output [5:0] entryhi_asid, + + // + input [31:0] data_address_next, + input [31:0] data_address, + + // + output [8:0] data_cache_read_address, + input [53:0] data_cache_q, + + output [8:0] data_cache_write_address, + output data_cache_write_enable, + output [53:0] data_cache_data, + + // + output ram_fifo_wrreq, + output [66:0] ram_fifo_data, + input ram_fifo_full, + + // + input [31:0] ram_result_address, + input ram_result_valid, + input ram_result_is_read_instr, + input [2:0] ram_result_burstcount, + input [31:0] ram_result +); /* verilator public_module */ + +//------------------------------------------------------------------------------ pipeline stall +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +assign mem_stall = ~(exception_start) && ( + muldiv_busy || + exe_cmd_tlbp || (tlbp_in_progress && ~(tlbp_update)) || + load_idle_tlb_ok_cache_bad_fifo_ok || load_idle_tlb_ok_cache_bad_fifo_bad || load_idle_tlb_wait || load_state != LOAD_IDLE || + store_idle_tlb_ok_fifo_bad || store_idle_tlb_wait || store_state != STORE_IDLE +); + +reg mem_stalled; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_stalled <= `FALSE; + else mem_stalled <= mem_stall; +end + +//------------------------------------------------------------------------------ instruction decoding +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +wire [4:0] exe_instr_rt = exe_instr[20:16]; +wire [4:0] exe_instr_rd = exe_instr[15:11]; + +wire mem_exc_coproc0_unusable = ~(config_coproc0_usable) && ~(config_kernel_mode) && exe_cmd_cp0; + +wire exe_cmd_mtc0 = ~(mem_exc_coproc0_unusable) && ~(exception_start) && ~(config_kernel_mode_exc_now) && exe_cmd == `CMD_mtc0; +wire exe_cmd_rfe = ~(mem_exc_coproc0_unusable) && ~(exception_start) && ~(config_kernel_mode_exc_now) && exe_cmd == `CMD_cp0_rfe; +wire exe_cmd_tlbr = ~(mem_exc_coproc0_unusable) && ~(exception_start) && ~(config_kernel_mode_exc_now) && exe_cmd == `CMD_cp0_tlbr; +wire exe_cmd_tlbp = ~(mem_exc_coproc0_unusable) && ~(exception_start) && ~(config_kernel_mode_exc_now) && exe_cmd == `CMD_cp0_tlbp; +wire exe_cmd_tlbwi = ~(mem_exc_coproc0_unusable) && ~(exception_start) && ~(config_kernel_mode_exc_now) && exe_cmd == `CMD_cp0_tlbwi; +wire exe_cmd_tlbwr = ~(mem_exc_coproc0_unusable) && ~(exception_start) && ~(config_kernel_mode_exc_now) && exe_cmd == `CMD_cp0_tlbwr; + +wire exe_cmd_load_do = ~(exception_start) && ~(config_kernel_mode_exc_now) && exe_cmd_load; +wire exe_cmd_store_do = ~(exception_start) && ~(config_kernel_mode_exc_now) && exe_cmd_store; + +//------------------------------------------------------------------------------ next pipeline stage +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +reg config_kernel_mode_last; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) config_kernel_mode_last <= `TRUE; + else config_kernel_mode_last <= config_kernel_mode; +end + +reg config_kernel_mode_changed; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) config_kernel_mode_changed <= `FALSE; + else if(config_kernel_mode) config_kernel_mode_changed <= `FALSE; + else if(config_kernel_mode_exc_wait) config_kernel_mode_changed <= `TRUE; + else if(exe_cmd != `CMD_null) config_kernel_mode_changed <= `FALSE; +end + +wire config_kernel_mode_exc_now = (config_kernel_mode_changed || (config_kernel_mode_last && ~(config_kernel_mode))) && exe_cmd != `CMD_null && exe_pc_user_seg; +wire config_kernel_mode_exc_wait = ~(config_kernel_mode_changed) && config_kernel_mode_last && ~(config_kernel_mode) && exe_cmd == `CMD_null; + +//------------------------------------------------------------------------------ + +wire [4:0] mem_result_index_next = + (exception_start || config_kernel_mode_exc_now)? 5'd0 : + (exe_cmd == `CMD_cfc1_detect && config_coproc1_usable)? exe_instr_rt : + (data_finished && load_idle_tlb_ok_finished)? exe_instr_rt : + (data_finished)? load_instr_rt_reg : + (muldiv_result_index != 5'd0)? muldiv_result_index : + (exe_cmd == `CMD_mfc0 && ~(mem_exc_coproc0_unusable))? exe_instr_rt : + exe_result_index; + +wire [31:0] mem_result_next = + (exe_cmd == `CMD_cfc1_detect && config_coproc1_usable)? 32'd0 : + (muldiv_result_index != 5'd0)? muldiv_result : + (exe_cmd == `CMD_mfc0 && ~(mem_exc_coproc0_unusable))? coproc0_output : + exe_result; + +wire [6:0] mem_cmd_next = + (exception_start)? `CMD_null : + (config_kernel_mode_exc_now)? `CMD_exc_load_addr_err : + (exe_cmd == `CMD_cfc1_detect && ~(config_coproc1_usable))? `CMD_exc_coproc_unusable : + (mem_exc_coproc0_unusable)? `CMD_exc_coproc_unusable : + (store_idle_tlb_bad_exc_modif || store_tlb_tlb_bad_exc_modif)? `CMD_exc_tlb_modif : + (load_idle_tlb_bad_exc_inv || load_tlb_tlb_bad_exc_inv || (load_tlb_tlb_bad_exc_miss && data_address_reg[31] == 1'b1))? `CMD_exc_load_tlb : + (store_idle_tlb_bad_exc_inv || store_tlb_tlb_bad_exc_inv || (store_tlb_tlb_bad_exc_miss && data_address_reg[31] == 1'b1))? `CMD_exc_store_tlb : + (load_tlb_tlb_bad_exc_miss && data_address_reg[31] == 1'b0)? `CMD_exc_tlb_load_miss : + (store_tlb_tlb_bad_exc_miss && data_address_reg[31] == 1'b0)? `CMD_exc_tlb_store_miss : + exe_cmd; +wire [31:0] mem_badvpn_next = + (exe_cmd_load_do || exe_cmd_store_do)? { data_address[31:2], ((exe_instr[27:26] == 2'b10)? 2'b00 : data_address[1:0]) } : + (load_state != LOAD_IDLE || store_state != STORE_IDLE)? { data_address_reg[31:2], ((mem_left_right == 2'b10)? 2'b00 : data_address_reg[1:0]) } : + exe_badvpn; + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_result_index <= 5'd0; + else mem_result_index <= mem_result_index_next; +end + +reg [31:0] mem_result_nodata; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_result_nodata <= 32'd0; + else mem_result_nodata <= mem_result_next; +end + +reg [31:0] mem_result_data; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_result_data <= 32'd0; + else mem_result_data <= data_finished_value; +end + +reg mem_data_finished; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_data_finished <= `FALSE; + else mem_data_finished <= data_finished; +end + +assign mem_result = (mem_data_finished)? mem_result_data : mem_result_nodata; + +//------------------------------------------------------------------------------ + + +reg [6:0] mem_cmd; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_cmd <= `CMD_null; + else mem_cmd <= mem_cmd_next; +end + +reg [31:0] mem_branch_address; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_branch_address <= 32'd0; + else mem_branch_address <= exe_branch_address; +end + +reg [31:0] mem_instr; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_instr <= 32'd0; + else mem_instr <= exe_instr; +end + +reg [31:0] mem_badvpn; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_badvpn <= 32'd0; + else mem_badvpn <= mem_badvpn_next; +end + +reg [1:0] mem_branched; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_branched <= 2'd0; + else if(~(mem_stalled)) mem_branched <= exe_branched; +end + +reg [31:0] mem_pc_plus4; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_pc_plus4 <= 32'd0; + else if(~(mem_stalled)) mem_pc_plus4 <= exe_pc_plus4; +end + +//------------------------------------------------------------------------------ tlb +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//input tlb_ram_data_hit, +//input [5:0] tlb_ram_data_index, +//input [49:0] tlb_ram_data_result, +//input tlb_ram_data_missed + +assign tlb_ram_write_do = exe_cmd_tlbwi || exe_cmd_tlbwr; +assign tlb_ram_write_index = tlbw_index; +assign tlb_ram_write_value = tlbw_value; + +assign tlb_ram_read_do = exe_cmd_tlbr; +assign tlb_ram_read_index = tlbr_index; + +assign tlb_ram_data_start = exe_cmd_tlbp || exe_cmd_load_do || exe_cmd_store_do; + +assign tlb_ram_data_vpn = + (exe_cmd_tlbp || tlbp_in_progress)? tlbw_value[19:0] : + (exe_cmd_load_do || exe_cmd_store_do)? data_address[31:12] : + data_address_reg[31:12]; + +//------------------------------------------------------------------------------ tlb probe + +reg tlbp_in_progress; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) tlbp_in_progress <= `FALSE; + else if(exe_cmd_tlbp) tlbp_in_progress <= `TRUE; + else if(tlbp_update) tlbp_in_progress <= `FALSE; +end + +wire tlbp_update = tlbp_in_progress && (tlb_ram_data_hit || tlb_ram_data_missed); +wire tlbp_hit = tlb_ram_data_hit; +wire [5:0] tlbp_index = tlb_ram_data_index; + +//------------------------------------------------------------------------------ load / store common +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +wire tlb_use_at_idle = (exe_cmd_load_do || exe_cmd_store_do) && (data_address[31] == 1'b0 || data_address[31:30] == 2'b11); + +wire [19:0] pfn_at_idle = + (~(tlb_use_at_idle))? { 3'b0, data_address[28:12] } : + (micro_check_matched)? micro_check_result[39:20] : + tlb_ram_data_result[39:20]; + +reg [19:0] pfn_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) pfn_reg <= 20'd0; + else if(exe_cmd_load_do || exe_cmd_store_do) pfn_reg <= pfn_at_idle; + else if(load_tlb_tlb_ok_cache_bad || store_tlb_tlb_ok) pfn_reg <= tlb_ram_data_result[39:20]; +end + +wire n_at_idle = + (~(tlb_use_at_idle))? data_address[31:29] == 3'b101 : + (micro_check_matched)? micro_check_result[46] : + tlb_ram_data_result[46]; + +reg n_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) n_reg <= `FALSE; + else if(exe_cmd_load_do || exe_cmd_store_do) n_reg <= n_at_idle; + else if(load_tlb_tlb_ok_cache_bad || store_tlb_tlb_ok) n_reg <= tlb_ram_data_result[46]; +end + +wire [3:0] byte_byteenable = + (data_address[1:0] == 2'b00)? 4'b0001 : + (data_address[1:0] == 2'b01)? 4'b0010 : + (data_address[1:0] == 2'b10)? 4'b0100 : + 4'b1000; +wire [3:0] halfword_byteenable = + (data_address[1:0] == 2'b00)? 4'b0011 : + 4'b1100; +wire [3:0] lwl_byteenable = + (data_address[1:0] == 2'b00)? 4'b0001 : + (data_address[1:0] == 2'b01)? 4'b0011 : + (data_address[1:0] == 2'b10)? 4'b0111 : + 4'b1111; +wire [3:0] lwr_byteenable = + (data_address[1:0] == 2'b00)? 4'b1111 : + (data_address[1:0] == 2'b01)? 4'b1110 : + (data_address[1:0] == 2'b10)? 4'b1100 : + 4'b1000; +wire [3:0] data_byteenable = + (load_idle_cmd_lb || load_idle_cmd_lbu || load_idle_cmd_sb)? byte_byteenable : + (load_idle_cmd_lh || load_idle_cmd_lhu || load_idle_cmd_sh)? halfword_byteenable : + (load_idle_cmd_lwl || load_idle_cmd_swl)? lwl_byteenable : + (load_idle_cmd_lwr || load_idle_cmd_swr)? lwr_byteenable : + 4'b1111; + +reg [3:0] data_byteenable_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) data_byteenable_reg <= 4'b0; + else if(exe_cmd_load_do) data_byteenable_reg <= load_idle_byteenable; + else if(exe_cmd_store_do) data_byteenable_reg <= data_byteenable; +end + +reg [53:0] data_cache_q_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) data_cache_q_reg <= 54'd0; + else if(exe_cmd_load_do) data_cache_q_reg <= data_cache_q; + else if(exe_cmd_store_do) data_cache_q_reg <= { data_cache_q[53:32], store_idle_data }; +end + +reg [31:0] data_address_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) data_address_reg <= 32'b0; + else if(exe_cmd_load_do || exe_cmd_store_do) data_address_reg <= data_address; +end + +reg [1:0] mem_left_right; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_left_right <= 2'b0; + else if(exe_cmd_load_do || exe_cmd_store_do) mem_left_right <= exe_instr[27:26]; +end + +//------------------------------------------------------------------------------ load +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +localparam [1:0] LOAD_IDLE = 2'd0; +localparam [1:0] LOAD_TLB = 2'd1; +localparam [1:0] LOAD_FIFO = 2'd2; +localparam [1:0] LOAD_RESULT = 2'd3; + +reg [1:0] load_state; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) load_state <= LOAD_IDLE; + else if(load_idle_tlb_ok_cache_bad_fifo_ok) load_state <= LOAD_RESULT; + else if(load_idle_tlb_ok_cache_bad_fifo_bad) load_state <= LOAD_FIFO; + else if(load_idle_tlb_wait) load_state <= LOAD_TLB; + else if(load_tlb_tlb_ok_finished) load_state <= LOAD_IDLE; + else if(load_tlb_tlb_bad_exc_inv || load_tlb_tlb_bad_exc_miss) load_state <= LOAD_IDLE; + else if(load_tlb_tlb_ok_cache_bad_fifo_ok) load_state <= LOAD_RESULT; + else if(load_tlb_tlb_ok_cache_bad_fifo_bad) load_state <= LOAD_FIFO; + else if(load_fifo_end) load_state <= LOAD_RESULT; + else if(load_state == LOAD_RESULT && ram_result_valid && ~(ram_result_is_read_instr) && ram_result_burstcount == 3'd1) load_state <= LOAD_IDLE; +end + +wire sr_cm_clear = config_isolate_cache && (load_idle_tlb_ok_cache_ok || load_tlb_tlb_ok_cache_ok); +wire sr_cm_set = config_isolate_cache && (load_idle_tlb_ok_cache_isolate || load_tlb_tlb_ok_cache_isolate); + +wire data_finished = load_idle_tlb_ok_finished || load_tlb_tlb_ok_finished || (ram_result_valid && ~(ram_result_is_read_instr) && ram_result_address[31:2] == { pfn_reg, data_address_reg[11:2] }); +wire [31:0] data_finished_value = (load_idle_tlb_ok_finished)? load_idle_result[31:0] : load_result_value; + +//------------------------------------------------------------------------------ state IDLE + +wire load_idle_cmd_lb = exe_instr[28:26] == 3'b000; +wire load_idle_cmd_lbu = exe_instr[28:26] == 3'b100; +wire load_idle_cmd_lh = exe_instr[28:26] == 3'b001; +wire load_idle_cmd_lhu = exe_instr[28:26] == 3'b101; +wire load_idle_cmd_lw = exe_instr[28:26] == 3'b011; +wire load_idle_cmd_lwl = exe_instr[28:26] == 3'b010; +wire load_idle_cmd_lwr = exe_instr[28:26] == 3'b110; + +wire load_idle_cmd_sb = exe_instr[28:26] == 3'b000; +wire load_idle_cmd_sh = exe_instr[28:26] == 3'b001; +//not used: wire load_idle_cmd_sw = exe_instr[28:26] == 3'b011; +wire load_idle_cmd_swl = exe_instr[28:26] == 3'b010; +wire load_idle_cmd_swr = exe_instr[28:26] == 3'b110; + +wire [31:0] load_idle_rt = (exe_instr_rt == mem_result_index)? mem_result : exe_b; + +wire [7:0] load_idle_byte = + (data_address[1:0] == 2'd0)? data_cache_q[7:0] : + (data_address[1:0] == 2'd1)? data_cache_q[15:8] : + (data_address[1:0] == 2'd2)? data_cache_q[23:16] : + data_cache_q[31:24]; +wire [15:0] load_idle_halfword = + (data_address[1:0] == 2'd0)? data_cache_q[15:0] : + data_cache_q[31:16]; + +wire [31:0] load_idle_lwl = + (data_address[1:0] == 2'd0)? { data_cache_q[7:0], load_idle_rt[23:0] } : + (data_address[1:0] == 2'd1)? { data_cache_q[15:0], load_idle_rt[15:0] } : + (data_address[1:0] == 2'd2)? { data_cache_q[23:0], load_idle_rt[7:0] } : + data_cache_q[31:0]; + +wire [31:0] load_idle_lwr = + (data_address[1:0] == 2'd0)? data_cache_q[31:0] : + (data_address[1:0] == 2'd1)? { load_idle_rt[31:24], data_cache_q[31:8] } : + (data_address[1:0] == 2'd2)? { load_idle_rt[31:16], data_cache_q[31:16] } : + { load_idle_rt[31:8], data_cache_q[31:24] }; + +wire [31:0] load_idle_result = + (load_idle_cmd_lb)? { {24{load_idle_byte[7]}}, load_idle_byte } : + (load_idle_cmd_lbu)? { 24'd0, load_idle_byte } : + (load_idle_cmd_lh)? { {16{load_idle_halfword[15]}}, load_idle_halfword } : + (load_idle_cmd_lhu)? { 16'd0, load_idle_halfword } : + (load_idle_cmd_lw)? data_cache_q[31:0] : + (load_idle_cmd_lwl)? load_idle_lwl : + load_idle_lwr; + +wire [3:0] load_idle_byteenable = (~(n_at_idle))? 4'hF : data_byteenable; + +reg [2:0] load_cmd_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) load_cmd_reg <= 3'b0; + else if(exe_cmd_load_do) load_cmd_reg <= exe_instr[28:26]; +end + +reg [4:0] load_instr_rt_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) load_instr_rt_reg <= 5'b0; + else if(exe_cmd_load_do) load_instr_rt_reg <= exe_instr_rt; +end + +reg [31:0] load_rt_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) load_rt_reg <= 32'd0; + else if(exe_cmd_load_do) load_rt_reg <= load_idle_rt; +end + +wire load_idle_tlb_ok_cache_ok = exe_cmd_load_do && data_cache_q[53] && ~(n_at_idle) && ( + (~(tlb_use_at_idle) && data_cache_q[52:32] == { pfn_at_idle, data_address[11] }) || //tlb not in use + (tlb_use_at_idle && micro_check_matched && micro_check_result[48] && data_cache_q[52:32] == {micro_check_result[39:20], data_address[11]}) //tlb in micro +); + +wire load_idle_tlb_ok_cache_isolate = exe_cmd_load_do && config_isolate_cache && ( + ~(tlb_use_at_idle) || //tlb not in use + (tlb_use_at_idle && micro_check_matched && micro_check_result[48]) //tlb in micro +); + +wire load_idle_tlb_ok_finished = load_idle_tlb_ok_cache_ok || load_idle_tlb_ok_cache_isolate; + +wire load_idle_tlb_bad_exc_inv = exe_cmd_load_do && tlb_use_at_idle && ( + (micro_check_matched && ~(micro_check_result[48])) //tlb in micro +); + +wire load_idle_tlb_ok_cache_bad = exe_cmd_load_do && ( + (~(tlb_use_at_idle) && (~(data_cache_q[53]) || n_at_idle || data_cache_q[52:32] != { pfn_at_idle, data_address[11] })) || //tlb not in use + (tlb_use_at_idle && micro_check_matched && micro_check_result[48] && (~(data_cache_q[53]) || n_at_idle || data_cache_q[52:32] != { micro_check_result[39:20], data_address[11] })) //tlb in micro +); +wire load_idle_tlb_ok_cache_bad_fifo_ok = load_idle_tlb_ok_cache_bad && ~(ram_fifo_full); +wire load_idle_tlb_ok_cache_bad_fifo_bad = load_idle_tlb_ok_cache_bad && ram_fifo_full; + +wire load_idle_tlb_wait = exe_cmd_load_do && tlb_use_at_idle && ~(micro_check_matched); + +//------------------------------------------------------------------------------ state TLB + +wire load_tlb_tlb_ok_cache_ok = load_state == LOAD_TLB && tlb_ram_data_hit && tlb_ram_data_result[48] && data_cache_q_reg[53] && data_cache_q_reg[52:32] == { tlb_ram_data_result[39:20], data_address_reg[11] }; +wire load_tlb_tlb_ok_cache_isolate = load_state == LOAD_TLB && tlb_ram_data_hit && tlb_ram_data_result[48] && config_isolate_cache; + +wire load_tlb_tlb_ok_finished = load_tlb_tlb_ok_cache_ok || load_tlb_tlb_ok_cache_isolate; + +wire load_tlb_tlb_bad_exc_inv = load_state == LOAD_TLB && tlb_ram_data_hit && ~(tlb_ram_data_result[48]); +wire load_tlb_tlb_bad_exc_miss= load_state == LOAD_TLB && ~(tlb_ram_data_hit) && tlb_ram_data_missed; + +wire load_tlb_tlb_ok_cache_bad = + load_state == LOAD_TLB && tlb_ram_data_hit && tlb_ram_data_result[48] && (~(data_cache_q_reg[53]) || data_cache_q_reg[52:32] != { tlb_ram_data_result[39:20], data_address_reg[11] }); + +wire load_tlb_tlb_ok_cache_bad_fifo_ok = load_tlb_tlb_ok_cache_bad && ~(ram_fifo_full); +wire load_tlb_tlb_ok_cache_bad_fifo_bad = load_tlb_tlb_ok_cache_bad && ram_fifo_full; + +//------------------------------------------------------------------------------ state FIFO + +wire load_fifo_end = load_state == LOAD_FIFO && ~(ram_fifo_full); + +//------------------------------------------------------------------------------ state TLB or RESULT + +wire load_result_cmd_lb = load_cmd_reg == 3'b000; +wire load_result_cmd_lbu = load_cmd_reg == 3'b100; +wire load_result_cmd_lh = load_cmd_reg == 3'b001; +wire load_result_cmd_lhu = load_cmd_reg == 3'b101; +wire load_result_cmd_lw = load_cmd_reg == 3'b011; +wire load_result_cmd_lwl = load_cmd_reg == 3'b010; +//not used: wire load_result_cmd_lwr = load_cmd_reg == 3'b110; + +wire [31:0] load_result_data = (load_state == LOAD_TLB)? data_cache_q_reg[31:0] : ram_result; + +wire [7:0] load_result_byte = + (data_address_reg[1:0] == 2'd0)? load_result_data[7:0] : + (data_address_reg[1:0] == 2'd1)? load_result_data[15:8] : + (data_address_reg[1:0] == 2'd2)? load_result_data[23:16] : + load_result_data[31:24]; +wire [15:0] load_result_halfword = + (data_address_reg[1:0] == 2'd0)? load_result_data[15:0] : + load_result_data[31:16]; + +wire [31:0] load_result_lwl = + (data_address_reg[1:0] == 2'd0)? { load_result_data[7:0], load_rt_reg[23:0] } : + (data_address_reg[1:0] == 2'd1)? { load_result_data[15:0], load_rt_reg[15:0] } : + (data_address_reg[1:0] == 2'd2)? { load_result_data[23:0], load_rt_reg[7:0] } : + load_result_data; + +wire [31:0] load_result_lwr = + (data_address_reg[1:0] == 2'd0)? load_result_data : + (data_address_reg[1:0] == 2'd1)? { load_rt_reg[31:24], load_result_data[31:8] } : + (data_address_reg[1:0] == 2'd2)? { load_rt_reg[31:16], load_result_data[31:16] } : + { load_rt_reg[31:8], load_result_data[31:24] }; + +wire [31:0] load_result_value = + (load_result_cmd_lb)? { {24{load_result_byte[7]}}, load_result_byte } : + (load_result_cmd_lbu)? { 24'd0, load_result_byte } : + (load_result_cmd_lh)? { {16{load_result_halfword[15]}}, load_result_halfword } : + (load_result_cmd_lhu)? { 16'd0, load_result_halfword } : + (load_result_cmd_lw)? load_result_data : + (load_result_cmd_lwl)? load_result_lwl : + load_result_lwr; + +//------------------------------------------------------------------------------ store +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +/* +Possible store states: + + State STORE_IDLE: + - store_idle_tlb_ok_fifo_ok -> stay at IDLE; write fifo / cache / micro + - store_idle_tlb_exc -> stay at IDLE; exception + - store_idle_tlb_ok_fifo_bad -> goto FIFO; write micro + - store_idle_tlb_wait -> goto TLB + + State STORE_FIFO: + - store_fifo_end -> goto IDLE; write fifo / cache + + State STORE_TLB: + - store_tlb_tlb_ok_fifo_ok -> goto IDLE; write fifo / cache / micro + - store_tlb_tlb_ok_fifo_bad -> goto FIFO; write micro +*/ + +localparam [1:0] STORE_IDLE = 2'd0; +localparam [1:0] STORE_FIFO = 2'd1; +localparam [1:0] STORE_TLB = 2'd2; + +reg [1:0] store_state; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) store_state <= STORE_IDLE; + else if(store_idle_tlb_ok_fifo_bad) store_state <= STORE_FIFO; + else if(store_fifo_end) store_state <= STORE_IDLE; + else if(store_idle_tlb_wait) store_state <= STORE_TLB; + else if(store_tlb_tlb_ok_fifo_ok) store_state <= STORE_IDLE; + else if(store_tlb_tlb_ok_fifo_bad) store_state <= STORE_FIFO; + else if(store_tlb_tlb_bad_exc_miss || store_tlb_tlb_bad_exc_modif || store_tlb_tlb_bad_exc_inv) store_state <= STORE_IDLE; +end + +//------------------------------------------------------------------------------ IDLE state + +wire store_idle_tlb_ok = exe_cmd_store_do && ( + ~(tlb_use_at_idle) || //tlb not in use + (tlb_use_at_idle && micro_check_matched && micro_check_result[48:47] == 2'b11) //tlb in micro +); + +wire store_idle_tlb_ok_fifo_ok = store_idle_tlb_ok && ~(ram_fifo_full); +wire store_idle_tlb_ok_fifo_bad= store_idle_tlb_ok && ram_fifo_full; + +wire [31:0] store_idle_data_zero = + (load_idle_cmd_swl && data_address[1:0] == 2'b00)? { 24'd0, exe_b[31:24] } : + (load_idle_cmd_swl && data_address[1:0] == 2'b01)? { 16'd0, exe_b[31:16] } : + (load_idle_cmd_swl && data_address[1:0] == 2'b10)? { 8'd0, exe_b[31:8] } : + (load_idle_cmd_swl && data_address[1:0] == 2'b11)? exe_b : + (load_idle_cmd_swr && data_address[1:0] == 2'b00)? exe_b : + (load_idle_cmd_swr && data_address[1:0] == 2'b01)? { exe_b[23:0], 8'd0 } : + (load_idle_cmd_swr && data_address[1:0] == 2'b10)? { exe_b[15:0], 16'd0 } : + (load_idle_cmd_swr && data_address[1:0] == 2'b11)? { exe_b[7:0], 24'd0 } : + (data_address[1:0] == 2'b00)? exe_b : + (data_address[1:0] == 2'b01)? { exe_b[23:0], 8'd0 } : + (data_address[1:0] == 2'b10)? { exe_b[15:0], 16'd0 } : + { exe_b[7:0], 24'd0 }; + +wire [31:0] store_idle_data = { + ({8{data_byteenable[3]}} & store_idle_data_zero[31:24]) | (~({8{data_byteenable[3]}}) & data_cache_q[31:24]), + ({8{data_byteenable[2]}} & store_idle_data_zero[23:16]) | (~({8{data_byteenable[2]}}) & data_cache_q[23:16]), + ({8{data_byteenable[1]}} & store_idle_data_zero[15:8]) | (~({8{data_byteenable[1]}}) & data_cache_q[15:8]), + ({8{data_byteenable[0]}} & store_idle_data_zero[7:0]) | (~({8{data_byteenable[0]}}) & data_cache_q[7:0]) +}; + +wire store_idle_tlb_bad_exc_modif = + exe_cmd_store_do && tlb_use_at_idle && micro_check_matched && micro_check_result[48:47] == 2'b10; +wire store_idle_tlb_bad_exc_inv = + exe_cmd_store_do && tlb_use_at_idle && micro_check_matched && micro_check_result[48] == 1'b0; + +wire store_idle_tlb_wait = exe_cmd_store_do && tlb_use_at_idle && ~(micro_check_matched); + +//------------------------------------------------------------------------------ FIFO state + +wire store_fifo_end = store_state == STORE_FIFO && ~(ram_fifo_full); + +//------------------------------------------------------------------------------ TLB state + +wire store_tlb_tlb_ok = store_state == STORE_TLB && tlb_ram_data_hit && tlb_ram_data_result[48:47] == 2'b11; + +wire store_tlb_tlb_ok_fifo_ok = store_tlb_tlb_ok && ~(ram_fifo_full); +wire store_tlb_tlb_ok_fifo_bad= store_tlb_tlb_ok && ram_fifo_full; + +wire store_tlb_tlb_bad_exc_miss = store_state == STORE_TLB && ~(tlb_ram_data_hit) && tlb_ram_data_missed; +wire store_tlb_tlb_bad_exc_modif = store_state == STORE_TLB && tlb_ram_data_hit && tlb_ram_data_result[48:47] == 2'b10; +wire store_tlb_tlb_bad_exc_inv = store_state == STORE_TLB && tlb_ram_data_hit && tlb_ram_data_result[48] == 1'b0; + +//------------------------------------------------------------------------------ cache +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//input [31:0] data_address_next, +//input [31:0] data_address, + +//input [31:0] ram_result_address, +//input ram_result_valid, +//input ram_result_is_read_instr, +//input [2:0] ram_result_burstcount, +//input [31:0] ram_result, + +//input [53:0] data_cache_q, + +assign data_cache_write_enable = + (~(n_reg) && ram_result_valid && ~(ram_result_is_read_instr)) || + (store_idle_tlb_ok_fifo_ok && ~(n_at_idle) && (data_byteenable == 4'hF || (data_cache_q[53] && data_cache_q[52:32] == { pfn_at_idle, data_address[11]}))) || + (store_fifo_end && ~(n_reg) && (data_byteenable_reg == 4'hF || (data_cache_q_reg[53] && data_cache_q_reg[52:32] == { pfn_reg, data_address_reg[11]}))) || + (store_tlb_tlb_ok_fifo_ok && ~(tlb_ram_data_result[46]) && (data_byteenable_reg == 4'hF || (data_cache_q_reg[53] && data_cache_q_reg[52:32] == { tlb_ram_data_result[39:20], data_address_reg[11]}))); + +assign data_cache_write_address = (store_idle_tlb_ok_fifo_ok)? data_address[10:2] : data_address_reg[10:2]; + +assign data_cache_read_address = data_address_next[10:2]; + +/* +[53] valid +[52:32] tag +[31:0] data +*/ +assign data_cache_data = + (store_idle_tlb_ok_fifo_ok)? { ~(config_isolate_cache) || data_byteenable == 4'hF, pfn_at_idle, data_address[11], store_idle_data } : + (store_fifo_end)? { ~(config_isolate_cache) || data_byteenable_reg == 4'hF, pfn_reg, data_address_reg[11], data_cache_q_reg[31:0] } : + (store_tlb_tlb_ok_fifo_ok)? { ~(config_isolate_cache) || data_byteenable_reg == 4'hF, tlb_ram_data_result[39:20], data_address_reg[11], data_cache_q_reg[31:0] } : + { 1'b1, pfn_reg, data_address_reg[11], ram_result }; //load + +//------------------------------------------------------------------------------ data fifo +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//input ram_fifo_full, + +assign ram_fifo_wrreq = + load_idle_tlb_ok_cache_bad_fifo_ok || load_tlb_tlb_ok_cache_bad_fifo_ok || load_fifo_end || + (~(config_isolate_cache) && (store_idle_tlb_ok_fifo_ok || store_tlb_tlb_ok_fifo_ok || store_fifo_end)); + +//{ [66] 1'b is_write, [65:36] 30'b address, [35:4] 32'b value, [3:0] 4'b byteena (4'b0000 - can burst 4 words) } +assign ram_fifo_data = + (load_idle_tlb_ok_cache_bad_fifo_ok)? { 1'b0, pfn_at_idle, data_address[11:2], 32'd0, load_idle_byteenable } : + (load_tlb_tlb_ok_cache_bad_fifo_ok)? { 1'b0, tlb_ram_data_result[39:20], data_address_reg[11:2], 32'd0, data_byteenable_reg } : + (load_fifo_end)? { 1'b0, pfn_reg, data_address_reg[11:2], 32'd0, data_byteenable_reg } : + (store_idle_tlb_ok_fifo_ok)? { 1'b1, pfn_at_idle, data_address[11:2], store_idle_data, data_byteenable } : + (store_fifo_end)? { 1'b1, pfn_reg, data_address_reg[11:2], data_cache_q_reg[31:0], data_byteenable_reg } : + { 1'b1, tlb_ram_data_result[39:20], data_address_reg[11:2], data_cache_q_reg[31:0], data_byteenable_reg }; //store_tlb_tlb_ok_fifo_ok + +//------------------------------------------------------------------------------ micro tlb +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +//input micro_check_matched, +/* +[19:0] vpn +[39:20] pfn +[45:40] asid +[46] n noncachable +[47] d dirty = write-enable +[48] v valid +[49] g global +*/ +//input [49:0] micro_check_result, + +wire micro_check_do = tlb_use_at_idle; +wire [19:0] micro_check_vpn = data_address[31:12]; +wire [5:0] micro_check_asid = entryhi_asid; + +wire micro_write_do = tlb_ram_data_hit && (load_state == LOAD_TLB || store_state == STORE_TLB); + +wire [49:0] micro_write_value = tlb_ram_data_result; + +wire micro_check_matched; +wire [49:0] micro_check_result; + +memory_data_tlb_micro memory_data_tlb_micro_inst( + .clk (clk), + .rst_n (rst_n), + + // + .micro_flush_do (micro_flush_do), //input + + // + .micro_write_do (micro_write_do), //input + .micro_write_value (micro_write_value), //input [49:0] + + // + .micro_check_do (micro_check_do), //input + .micro_check_vpn (micro_check_vpn), //input [19:0] + .micro_check_asid (micro_check_asid), //input [5:0] + .micro_check_matched(micro_check_matched), //output + .micro_check_result (micro_check_result) //output [49:0] +); + +//------------------------------------------------------------------------------ muldiv +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +wire muldiv_busy; + +wire [6:0] exe_cmd_for_muldiv = (exception_start || config_kernel_mode_exc_now)? `CMD_null : exe_cmd; + +block_muldiv block_muldiv_inst( + .clk (clk), + .rst_n (rst_n), + + .exe_cmd_for_muldiv (exe_cmd_for_muldiv), //input [6:0] + .exe_a (exe_a), //input [31:0] + .exe_b (exe_b), //input [31:0] + .exe_instr_rd (exe_instr_rd), //input [4:0] + + .muldiv_busy (muldiv_busy), //output + + .muldiv_result_index(muldiv_result_index), //output [4:0] + .muldiv_result (muldiv_result) //output [31:0] +); + +//------------------------------------------------------------------------------ coprocessor 0 +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +wire [31:0] coproc0_output; + +wire config_isolate_cache; +wire config_coproc0_usable; +wire config_coproc1_usable; + +wire [5:0] tlbw_index; +wire [49:0] tlbw_value; +wire [5:0] tlbr_index; + +block_cp0 block_cp0_inst( + .clk (clk), + .rst_n (rst_n), + + // + .config_switch_caches (config_switch_caches), //output + .config_isolate_cache (config_isolate_cache), //output + .config_coproc0_usable (config_coproc0_usable), //output + .config_coproc1_usable (config_coproc1_usable), //output + .config_kernel_mode (config_kernel_mode), //output + + // + .exe_cmd_mtc0 (exe_cmd_mtc0), //input + .exe_instr (exe_instr), //input [31:0] + .exe_b (exe_b), //input [31:0] + + .exe_cmd_rfe (exe_cmd_rfe), //input + .exe_cmd_tlbr (exe_cmd_tlbr), //input + .exe_cmd_tlbwi (exe_cmd_tlbwi), //input + .exe_cmd_tlbwr (exe_cmd_tlbwr), //input + + // + .coproc0_output (coproc0_output), //output [31:0] + + // + .tlbw_index (tlbw_index), //output [5:0] + .tlbw_value (tlbw_value), //output [49:0] + + // + .tlbr_index (tlbr_index), //output [5:0] + .tlb_ram_read_result_ready (tlb_ram_read_result_ready), //input + .tlb_ram_read_result (tlb_ram_read_result), //input [49:0] + + // + .tlbp_update (tlbp_update), //input + .tlbp_hit (tlbp_hit), //input + .tlbp_index (tlbp_index), //input [5:0] + + // + .micro_flush_do (micro_flush_do), //output + .entryhi_asid (entryhi_asid), //output [5:0] + + // + .sr_cm_set (sr_cm_set), //input + .sr_cm_clear (sr_cm_clear), //input + + // + .interrupt_vector (interrupt_vector), //input [5:0] + + // + .exception_start (exception_start), //output + .exception_start_pc (exception_start_pc), //output [31:0] + + // + .mem_stalled (mem_stalled), //input + .mem_cmd (mem_cmd), //input [6:0] + .mem_instr (mem_instr), //input [31:0] + .mem_pc_plus4 (mem_pc_plus4), //input [31:0] + .mem_branched (mem_branched), //input [1:0] + .mem_branch_address (mem_branch_address), //input [31:0] + .mem_badvpn (mem_badvpn) //input [31:0] +); + +//------------------------------------------------------------------------------ +// synthesis translate_off +wire _unused_ok = &{ 1'b0, data_address_next[31:11], data_address_next[1:0], ram_result_address[1:0], micro_check_result[49], micro_check_result[45:40], micro_check_result[19:0], 1'b0 }; +// synthesis translate_on +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/pipeline/pipeline_exe.v =================================================================== --- trunk/rtl/pipeline/pipeline_exe.v (nonexistent) +++ trunk/rtl/pipeline/pipeline_exe.v (revision 2) @@ -0,0 +1,243 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module pipeline_exe( + input clk, + input rst_n, + + // + input config_kernel_mode, + + // + input exception_start, + + // + input mem_stall, + + // + input [6:0] rf_cmd, + input [31:0] rf_instr, + input [31:0] rf_pc_plus4, + input [31:0] rf_badvpn, + input [31:0] rf_a, + input [31:0] rf_b, + + // + output reg [6:0] exe_cmd, + output reg [31:0] exe_instr, + output reg [31:0] exe_pc_plus4, + output reg exe_pc_user_seg, + output reg [31:0] exe_badvpn, + output reg [31:0] exe_a, + output reg [31:0] exe_b, + output reg [1:0] exe_branched, + output reg [31:0] exe_branch_address, + output reg exe_cmd_cp0, + output reg exe_cmd_load, + output reg exe_cmd_store, + + // + output [4:0] exe_result_index, + output reg [31:0] exe_result, + + // + output [31:0] data_address_next, + output reg [31:0] data_address, + + // + output branch_start, + output [31:0] branch_address, + + // + input [4:0] write_buffer_counter +); /* verilator public_module */ + +//------------------------------------------------------------------------------ + +wire exc_int_overflow = + ((rf_cmd == `CMD_3arg_add || rf_cmd == `CMD_addi) && ( + (rf_a[31] == 1'b1 && rf_b_imm[31] == 1'b1 && result_sum[31] == 1'b0) || + (rf_a[31] == 1'b0 && rf_b_imm[31] == 1'b0 && result_sum[31] == 1'b1))) || + (rf_cmd == `CMD_3arg_sub && ( + (rf_a[31] == 1'b1 && rf_b[31] == 1'b0 && result_sub[31] == 1'b0) || + (rf_a[31] == 1'b0 && rf_b[31] == 1'b1 && result_sub[31] == 1'b1))); + +wire [6:0] exe_cmd_next = + (mem_stall || exception_start)? `CMD_null : + (exc_load_address_error)? `CMD_exc_load_addr_err : + (exc_store_address_error)? `CMD_exc_store_addr_err : + (exc_int_overflow)? `CMD_exc_int_overflow : + rf_cmd; + +wire exe_cmd_cp0_next = ~(mem_stall) && ~(exception_start) && ( + rf_cmd == `CMD_mtc0 || rf_cmd == `CMD_cp0_rfe || rf_cmd == `CMD_cp0_tlbr || rf_cmd == `CMD_cp0_tlbp || + rf_cmd == `CMD_cp0_tlbwi || rf_cmd == `CMD_cp0_tlbwr || rf_cmd == `CMD_mfc0 +); + +wire cmd_load = + rf_cmd == `CMD_lb || rf_cmd == `CMD_lbu || rf_cmd == `CMD_lh || rf_cmd == `CMD_lhu || + rf_cmd == `CMD_lw || rf_cmd == `CMD_lwl || rf_cmd == `CMD_lwr; + +wire cmd_store = + rf_cmd == `CMD_sb || rf_cmd == `CMD_sh || rf_cmd == `CMD_sw || rf_cmd == `CMD_swl || rf_cmd == `CMD_swr; + +wire exe_cmd_load_next = ~(mem_stall) && ~(exception_start) && cmd_load && ~(exc_load_address_error); + +wire exe_cmd_store_next = ~(mem_stall) && ~(exception_start) && cmd_store && ~(exc_store_address_error); + +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) exe_cmd <= `CMD_null; else exe_cmd <= exe_cmd_next; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) exe_cmd_cp0 <= `FALSE; else exe_cmd_cp0 <= exe_cmd_cp0_next; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) exe_cmd_load <= `FALSE; else exe_cmd_load <= exe_cmd_load_next; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) exe_cmd_store <= `FALSE; else exe_cmd_store <= exe_cmd_store_next; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) exe_result <= 32'd0; else exe_result <= result; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) exe_instr <= 32'd0; else exe_instr <= rf_instr; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) exe_pc_plus4 <= 32'd0; else exe_pc_plus4 <= rf_pc_plus4; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) exe_pc_user_seg <= `FALSE; else exe_pc_user_seg <= rf_pc_plus4 > 32'h80000000; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) exe_a <= 32'd0; else exe_a <= rf_a; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) exe_b <= 32'd0; else exe_b <= rf_b; end + +wire [4:0] rf_instr_rt = rf_instr[20:16]; +wire [4:0] rf_instr_rd = rf_instr[15:11]; + +wire exe_cmd_next_is_rd = + rf_cmd == `CMD_3arg_add || rf_cmd == `CMD_3arg_addu || rf_cmd == `CMD_3arg_and || rf_cmd == `CMD_3arg_nor || + rf_cmd == `CMD_3arg_or || rf_cmd == `CMD_3arg_slt || rf_cmd == `CMD_3arg_sltu || rf_cmd == `CMD_3arg_sub || + rf_cmd == `CMD_3arg_subu || rf_cmd == `CMD_3arg_xor || rf_cmd == `CMD_3arg_sllv || rf_cmd == `CMD_3arg_srav || + rf_cmd == `CMD_3arg_srlv || rf_cmd == `CMD_sll || rf_cmd == `CMD_sra || rf_cmd == `CMD_srl || + rf_cmd == `CMD_jalr; + +wire exe_cmd_next_is_rt = + rf_cmd == `CMD_addi || rf_cmd == `CMD_addiu || rf_cmd == `CMD_andi || rf_cmd == `CMD_ori || + rf_cmd == `CMD_slti || rf_cmd == `CMD_sltiu || rf_cmd == `CMD_xori || rf_cmd == `CMD_lui; + +wire exe_cmd_next_is_r31 = rf_cmd == `CMD_bgezal || rf_cmd == `CMD_bltzal || rf_cmd == `CMD_jal; + +wire [4:0] exe_result_index_next = + (exe_cmd_next_is_rd)? rf_instr_rd : + (exe_cmd_next_is_rt)? rf_instr_rt : + (exe_cmd_next_is_r31)? 5'd31 : + 5'd0; + +reg [4:0] exe_result_index_pre; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) exe_result_index_pre <= 5'd0; + else exe_result_index_pre <= exe_result_index_next; +end + +reg exe_result_valid; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) exe_result_valid <= `FALSE; + else exe_result_valid <= ~(mem_stall) && ~(exception_start) && ~(exc_int_overflow); +end + +assign exe_result_index = (exe_result_valid)? exe_result_index_pre : 5'd0; + +//------------------------------------------------------------------------------ + +assign data_address_next = rf_a + { {16{rf_instr[15]}}, rf_instr[15:0] }; + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) data_address <= 32'd0; + else data_address <= data_address_next; +end + +wire exc_load_address_error = + ((rf_cmd == `CMD_lh || rf_cmd == `CMD_lhu) && data_address_next[0]) || + (rf_cmd == `CMD_lw && data_address_next[1:0] != 2'b00) || + (cmd_load && ~(config_kernel_mode) && data_address_next[31]); + +wire exc_store_address_error = + (rf_cmd == `CMD_sh && data_address_next[0]) || + (rf_cmd == `CMD_sw && data_address_next[1:0] != 2'b00) || + (cmd_store && ~(config_kernel_mode) && data_address_next[31]); + +//------------------------------------------------------------------------------ + +wire write_buffer_empty = ~(exe_cmd_store) && write_buffer_counter == 5'd0; + +assign branch_start = ~(mem_stall) && ( + rf_cmd == `CMD_jr || rf_cmd == `CMD_j || rf_cmd == `CMD_jal || rf_cmd == `CMD_jalr || + (rf_cmd == `CMD_beq && rf_a == rf_b) || + (rf_cmd == `CMD_bne && rf_a != rf_b) || + (rf_cmd == `CMD_bgez && rf_a[31] == 1'b0) || + (rf_cmd == `CMD_bgtz && rf_a[31] == 1'b0 && rf_a != 32'd0) || + (rf_cmd == `CMD_blez && (rf_a[31] == 1'b1 || rf_a == 32'd0)) || + (rf_cmd == `CMD_bltz && rf_a[31] == 1'b1) || + (rf_cmd == `CMD_bgezal && rf_a[31] == 1'b0) || + (rf_cmd == `CMD_bltzal && rf_a[31] == 1'b1) || + (rf_cmd == `CMD_cp0_bc0t && write_buffer_empty) || + (rf_cmd == `CMD_cp0_bc0f && ~(write_buffer_empty)) +); + +assign branch_address = + (rf_cmd == `CMD_jal || rf_cmd == `CMD_j)? { rf_pc_plus4[31:28], rf_instr[25:0], 2'b00 } : + (rf_cmd == `CMD_jr || rf_cmd == `CMD_jalr)? rf_a : + rf_pc_plus4 + { {14{rf_instr[15]}}, rf_instr[15:0], 2'b00 }; + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) exe_branched <= 2'd0; + else if(branch_start) exe_branched <= 2'd1; + else if(exe_cmd != `CMD_null && exe_branched == 2'd1) exe_branched <= 2'd2; + else if(exe_cmd != `CMD_null) exe_branched <= 2'd0; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) exe_branch_address <= 32'd0; + else if(branch_start) exe_branch_address <= branch_address; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) exe_badvpn <= 32'd0; + else exe_badvpn <= rf_badvpn; +end + +//------------------------------------------------------------------------------ + +wire [31:0] rf_b_imm = (rf_cmd == `CMD_addi || rf_cmd == `CMD_addiu || rf_cmd == `CMD_slti || rf_cmd == `CMD_sltiu)? { {16{rf_instr[15]}}, rf_instr[15:0] } : rf_b; + +wire [31:0] result_sum = rf_a + rf_b_imm; +wire [32:0] result_sub = rf_a - rf_b_imm; + +wire [31:0] result = + (rf_cmd == `CMD_3arg_add || rf_cmd == `CMD_addi || rf_cmd == `CMD_addiu || rf_cmd == `CMD_3arg_addu)? result_sum : + (rf_cmd == `CMD_3arg_and)? rf_a & rf_b : + (rf_cmd == `CMD_andi)? { 16'd0, rf_a[15:0] & rf_instr[15:0] } : + (rf_cmd == `CMD_3arg_nor)? ~(rf_a | rf_b) : + (rf_cmd == `CMD_3arg_or)? rf_a | rf_b : + (rf_cmd == `CMD_ori)? { rf_a[31:16], rf_a[15:0] | rf_instr[15:0] } : + (rf_cmd == `CMD_sll || rf_cmd == `CMD_3arg_sllv)? shift_left : + (rf_cmd == `CMD_sra || rf_cmd == `CMD_3arg_srav || rf_cmd == `CMD_srl || rf_cmd == `CMD_3arg_srlv)? shift_right : + (rf_cmd == `CMD_3arg_slt || rf_cmd == `CMD_slti)? { 31'b0, (rf_a[31] ^ rf_b_imm[31])? rf_a[31] : result_sub[31] } : + (rf_cmd == `CMD_3arg_sltu || rf_cmd == `CMD_sltiu)? { 31'b0, result_sub[32] } : + (rf_cmd == `CMD_3arg_sub || rf_cmd == `CMD_3arg_subu)? result_sub[31:0] : + (rf_cmd == `CMD_3arg_xor)? rf_a ^ rf_b : + (rf_cmd == `CMD_xori)? rf_a ^ { 16'd0, rf_instr[15:0] } : + (rf_cmd == `CMD_lui)? { rf_instr[15:0], 16'd0 } : + rf_pc_plus4 + 32'd4; //cmd_bgezal, cmd_bltzal, cmd_jal, cmd_jalr + +//------------------------------------------------------------------------------ shift +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +wire [31:0] shift_left; +wire [31:0] shift_right; + +block_shift block_shift_inst( + .rf_cmd (rf_cmd), //input [6:0] + .rf_instr (rf_instr), //input [31:0] + .rf_a (rf_a), //input [31:0] + .rf_b (rf_b), //input [31:0] + + .shift_left (shift_left), //output [31:0] + .shift_right (shift_right) //output [31:0] +); + +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/memory/memory_data_tlb_micro.v =================================================================== --- trunk/rtl/memory/memory_data_tlb_micro.v (nonexistent) +++ trunk/rtl/memory/memory_data_tlb_micro.v (revision 2) @@ -0,0 +1,143 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module memory_data_tlb_micro( + input clk, + input rst_n, + + //0-cycle; always accepted; highest priority + input micro_flush_do, + + //0-cycle; always accepted; lower priority + input micro_write_do, + input [49:0] micro_write_value, + + //0-cycle output; if together with flush, then no match + input micro_check_do, + input [19:0] micro_check_vpn, + input [5:0] micro_check_asid, + output micro_check_matched, + output [49:0] micro_check_result +); + +//------------------------------------------------------------------------------ + +/* +[19:0] vpn +[39:20] pfn +[45:40] asid +[46] n noncachable +[47] d dirty = write-enable +[48] v valid +[49] g global + +[50] loaded +*/ + +//------------------------------------------------------------------------------ + +reg [50:0] micro00; reg [50:0] micro01; reg [50:0] micro02; reg [50:0] micro03; +reg [50:0] micro04; reg [50:0] micro05; reg [50:0] micro06; reg [50:0] micro07; + +wire sel00 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro00[19:0] && micro00[50] && (micro00[49] || micro_check_asid == micro00[45:40]); +wire sel01 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro01[19:0] && micro01[50] && (micro01[49] || micro_check_asid == micro01[45:40]); +wire sel02 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro02[19:0] && micro02[50] && (micro02[49] || micro_check_asid == micro02[45:40]); +wire sel03 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro03[19:0] && micro03[50] && (micro03[49] || micro_check_asid == micro03[45:40]); +wire sel04 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro04[19:0] && micro04[50] && (micro04[49] || micro_check_asid == micro04[45:40]); +wire sel05 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro05[19:0] && micro05[50] && (micro05[49] || micro_check_asid == micro05[45:40]); +wire sel06 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro06[19:0] && micro06[50] && (micro06[49] || micro_check_asid == micro06[45:40]); +wire sel07 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro07[19:0] && micro07[50] && (micro07[49] || micro_check_asid == micro07[45:40]); + +assign micro_check_matched = sel00 || sel01 || sel02 || sel03 || sel04 || sel05 || sel06 || sel07; + +assign micro_check_result = + (sel00)? micro00[49:0] : + (sel01)? micro01[49:0] : + (sel02)? micro02[49:0] : + (sel03)? micro03[49:0] : + (sel04)? micro04[49:0] : + (sel05)? micro05[49:0] : + (sel06)? micro06[49:0] : + micro07[49:0]; + +wire ena00 = `TRUE; +wire ena01 = ena00 && micro00[50]; +wire ena02 = ena01 && micro01[50]; +wire ena03 = ena02 && micro02[50]; +wire ena04 = ena03 && micro03[50]; +wire ena05 = ena04 && micro04[50]; +wire ena06 = ena05 && micro05[50]; +wire ena07 = ena06 && micro06[50]; +wire full = ena07 && micro07[50]; + +wire write00 = micro_write_do && ((~(micro00[50]) && ena00) || (full && ~(plru[0]) && ~(plru[1]) && ~(plru[3]))); +wire write01 = micro_write_do && ((~(micro01[50]) && ena01) || (full && ~(plru[0]) && ~(plru[1]) && (plru[3]))); +wire write02 = micro_write_do && ((~(micro02[50]) && ena02) || (full && ~(plru[0]) && (plru[1]) && ~(plru[4]))); +wire write03 = micro_write_do && ((~(micro03[50]) && ena03) || (full && ~(plru[0]) && (plru[1]) && (plru[4]))); +wire write04 = micro_write_do && ((~(micro04[50]) && ena04) || (full && (plru[0]) && ~(plru[2]) && ~(plru[5]))); +wire write05 = micro_write_do && ((~(micro05[50]) && ena05) || (full && (plru[0]) && ~(plru[2]) && (plru[5]))); +wire write06 = micro_write_do && ((~(micro06[50]) && ena06) || (full && (plru[0]) && (plru[2]) && ~(plru[6]))); +wire write07 = micro_write_do && ((~(micro07[50]) && ena07) || (full && (plru[0]) && (plru[2]) && (plru[6]))); + +/* Tree pseudo LRU + * [0] + * [1] [2] + * [3] [4] [5] [6] + * 0 1 2 3 4 5 6 7 + * + */ + +localparam [6:0] MICRO_07_MASK = 7'b1000101; //0,2,6 +localparam [6:0] MICRO_07_VALUE = 7'b0000000; //0,2,6 + +localparam [6:0] MICRO_06_MASK = 7'b1000101; //0,2,6 +localparam [6:0] MICRO_06_VALUE = 7'b1000000; //0,2,6 + +localparam [6:0] MICRO_05_MASK = 7'b0100101; //0,2,5 +localparam [6:0] MICRO_05_VALUE = 7'b0000100; //0,2,5 + +localparam [6:0] MICRO_04_MASK = 7'b0100101; //0,2,5 +localparam [6:0] MICRO_04_VALUE = 7'b0100100; //0,2,5 + +localparam [6:0] MICRO_03_MASK = 7'b0010011; //0,1,4 +localparam [6:0] MICRO_03_VALUE = 7'b0000001; //0,1,4 + +localparam [6:0] MICRO_02_MASK = 7'b0010011; //0,1,4 +localparam [6:0] MICRO_02_VALUE = 7'b0010001; //0,1,4 + +localparam [6:0] MICRO_01_MASK = 7'b0001011; //0,1,3 +localparam [6:0] MICRO_01_VALUE = 7'b0000011; //0,1,3 + +localparam [6:0] MICRO_00_MASK = 7'b0001011; //0,1,3 +localparam [6:0] MICRO_00_VALUE = 7'b0001011; //0,1,3 + +reg [6:0] plru; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) plru <= 7'd0; + else if(micro_flush_do) plru <= 7'd0; + else if(write00 || sel00) plru <= (plru & ~(MICRO_00_MASK)) | MICRO_00_VALUE; + else if(write01 || sel01) plru <= (plru & ~(MICRO_01_MASK)) | MICRO_01_VALUE; + else if(write02 || sel02) plru <= (plru & ~(MICRO_02_MASK)) | MICRO_02_VALUE; + else if(write03 || sel03) plru <= (plru & ~(MICRO_03_MASK)) | MICRO_03_VALUE; + else if(write04 || sel04) plru <= (plru & ~(MICRO_04_MASK)) | MICRO_04_VALUE; + else if(write05 || sel05) plru <= (plru & ~(MICRO_05_MASK)) | MICRO_05_VALUE; + else if(write06 || sel06) plru <= (plru & ~(MICRO_06_MASK)) | MICRO_06_VALUE; + else if(write07 || sel07) plru <= (plru & ~(MICRO_07_MASK)) | MICRO_07_VALUE; +end + +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro00 <= 51'd0; else if(micro_flush_do) micro00 <= 51'd0; else if(write00) micro00 <= { 1'b1, micro_write_value }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro01 <= 51'd0; else if(micro_flush_do) micro01 <= 51'd0; else if(write01) micro01 <= { 1'b1, micro_write_value }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro02 <= 51'd0; else if(micro_flush_do) micro02 <= 51'd0; else if(write02) micro02 <= { 1'b1, micro_write_value }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro03 <= 51'd0; else if(micro_flush_do) micro03 <= 51'd0; else if(write03) micro03 <= { 1'b1, micro_write_value }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro04 <= 51'd0; else if(micro_flush_do) micro04 <= 51'd0; else if(write04) micro04 <= { 1'b1, micro_write_value }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro05 <= 51'd0; else if(micro_flush_do) micro05 <= 51'd0; else if(write05) micro05 <= { 1'b1, micro_write_value }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro06 <= 51'd0; else if(micro_flush_do) micro06 <= 51'd0; else if(write06) micro06 <= { 1'b1, micro_write_value }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro07 <= 51'd0; else if(micro_flush_do) micro07 <= 51'd0; else if(write07) micro07 <= { 1'b1, micro_write_value }; end + +endmodule Index: trunk/rtl/memory/memory_instr_tlb_micro.v =================================================================== --- trunk/rtl/memory/memory_instr_tlb_micro.v (nonexistent) +++ trunk/rtl/memory/memory_instr_tlb_micro.v (revision 2) @@ -0,0 +1,104 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module memory_instr_tlb_micro( + input clk, + input rst_n, + + //0-cycle; always accepted; highest priority + input micro_flush_do, + + //0-cycle; always accepted; lower priority + input micro_write_do, + input [49:0] micro_write_value, + + //0-cycle output; if together with flush, then no match + input micro_check_do, + input [19:0] micro_check_vpn, + input [5:0] micro_check_asid, + output micro_check_matched, + output [49:0] micro_check_result +); + +//------------------------------------------------------------------------------ + +/* +[19:0] vpn +[39:20] pfn +[45:40] asid +[46] n noncachable +[47] d dirty = write-enable +[48] v valid +[49] g global + +[50] loaded +*/ + +//------------------------------------------------------------------------------ + +reg [50:0] micro00; reg [50:0] micro01; reg [50:0] micro02; reg [50:0] micro03; + +wire sel00 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro00[19:0] && micro00[50] && (micro00[49] || micro_check_asid == micro00[45:40]); +wire sel01 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro01[19:0] && micro01[50] && (micro01[49] || micro_check_asid == micro01[45:40]); +wire sel02 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro02[19:0] && micro02[50] && (micro02[49] || micro_check_asid == micro02[45:40]); +wire sel03 = micro_check_do && ~(micro_flush_do) && micro_check_vpn == micro03[19:0] && micro03[50] && (micro03[49] || micro_check_asid == micro03[45:40]); + +assign micro_check_matched = sel00 || sel01 || sel02 || sel03; + +assign micro_check_result = + (sel00)? micro00[49:0] : + (sel01)? micro01[49:0] : + (sel02)? micro02[49:0] : + micro03[49:0]; + +wire ena00 = `TRUE; +wire ena01 = ena00 && micro00[50]; +wire ena02 = ena01 && micro01[50]; +wire ena03 = ena02 && micro02[50]; +wire full = ena03 && micro03[50]; + +wire write00 = micro_write_do && ((~(micro00[50]) && ena00) || (full && ~(plru[0]) && ~(plru[1]))); +wire write01 = micro_write_do && ((~(micro01[50]) && ena01) || (full && ~(plru[0]) && (plru[1]))); +wire write02 = micro_write_do && ((~(micro02[50]) && ena02) || (full && (plru[0]) && ~(plru[2]))); +wire write03 = micro_write_do && ((~(micro03[50]) && ena03) || (full && (plru[0]) && (plru[2]))); + +/* Tree pseudo LRU + * [0] + * [1] [2] + * 0 1 2 3 + */ + +localparam [2:0] MICRO_03_MASK = 3'b101; //0,2 +localparam [2:0] MICRO_03_VALUE = 3'b000; //0,2 + +localparam [2:0] MICRO_02_MASK = 3'b101; //0,2 +localparam [2:0] MICRO_02_VALUE = 3'b100; //0,2 + +localparam [2:0] MICRO_01_MASK = 3'b011; //0,1 +localparam [2:0] MICRO_01_VALUE = 3'b001; //0,1 + +localparam [2:0] MICRO_00_MASK = 3'b011; //0,1 +localparam [2:0] MICRO_00_VALUE = 3'b011; //0,1 + +reg [2:0] plru; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) plru <= 3'd0; + else if(micro_flush_do) plru <= 3'd0; + else if(write00 || sel00) plru <= (plru & ~(MICRO_00_MASK)) | MICRO_00_VALUE; + else if(write01 || sel01) plru <= (plru & ~(MICRO_01_MASK)) | MICRO_01_VALUE; + else if(write02 || sel02) plru <= (plru & ~(MICRO_02_MASK)) | MICRO_02_VALUE; + else if(write03 || sel03) plru <= (plru & ~(MICRO_03_MASK)) | MICRO_03_VALUE; +end + +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro00 <= 51'd0; else if(micro_flush_do) micro00 <= 51'd0; else if(write00) micro00 <= { 1'b1, micro_write_value }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro01 <= 51'd0; else if(micro_flush_do) micro01 <= 51'd0; else if(write01) micro01 <= { 1'b1, micro_write_value }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro02 <= 51'd0; else if(micro_flush_do) micro02 <= 51'd0; else if(write02) micro02 <= { 1'b1, micro_write_value }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) micro03 <= 51'd0; else if(micro_flush_do) micro03 <= 51'd0; else if(write03) micro03 <= { 1'b1, micro_write_value }; end + +endmodule Index: trunk/rtl/memory/memory_ram.v =================================================================== --- trunk/rtl/memory/memory_ram.v (nonexistent) +++ trunk/rtl/memory/memory_ram.v (revision 2) @@ -0,0 +1,180 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module memory_ram( + input clk, + input rst_n, + + // + input config_switch_caches, + + // + input [8:0] fetch_cache_read_address, + output [53:0] fetch_cache_q, + + input [8:0] fetch_cache_write_address, + input fetch_cache_write_enable, + input [53:0] fetch_cache_data, + + // + input [8:0] data_cache_read_address, + output [53:0] data_cache_q, + + input [8:0] data_cache_write_address, + input data_cache_write_enable, + input [53:0] data_cache_data, + + // + input ram_fifo_rdreq, + input ram_fifo_wrreq, + input [66:0] ram_fifo_data, + + output ram_fifo_empty, + output ram_fifo_full, + output [66:0] ram_fifo_q, + + // + output reg [4:0] write_buffer_counter +); + +//------------------------------------------------------------------------------ + +/* +vpn/pfn offset +------20------ ---12--- +tag index +------21------- --9-- -2- + +[53] valid +[52:32] tag +[31:0] data +*/ + +wire [8:0] address_1_r = (config_switch_caches)? fetch_cache_read_address : data_cache_read_address; +wire [8:0] address_1_w = (config_switch_caches)? fetch_cache_write_address : data_cache_write_address; + +wire [8:0] address_2_r = (config_switch_caches)? data_cache_read_address : fetch_cache_read_address; +wire [8:0] address_2_w = (config_switch_caches)? data_cache_write_address : fetch_cache_write_address; + +wire wren_1 = (config_switch_caches)? fetch_cache_write_enable : data_cache_write_enable; +wire wren_2 = (config_switch_caches)? data_cache_write_enable : fetch_cache_write_enable; + +wire [53:0] data_1 = (config_switch_caches)? fetch_cache_data : data_cache_data; +wire [53:0] data_2 = (config_switch_caches)? data_cache_data : fetch_cache_data; + +wire [53:0] q_1; +wire [53:0] q_2; + +model_simple_dual_ram #( + .width (54), + .widthad (9) +) +cache_1_inst( + .clk (clk), + + // + .address_a (address_1_r), //input [9:0] + .q_a (q_1), //output [53:0] + + // + .address_b (address_1_w), //input [9:0] + .wren_b (wren_1), //input + .data_b (data_1) //input [53:0] +); + +model_simple_dual_ram #( + .width (54), + .widthad (9) +) +cache_2_inst( + .clk (clk), + + // + .address_a (address_2_r), //input [9:0] + .q_a (q_2), //output [53:0] + + // + .address_b (address_2_w), //input [9:0] + .wren_b (wren_2), //input + .data_b (data_2) //input [53:0] +); + +reg [8:0] address_1_w_reg; +reg [8:0] address_1_r_reg; +reg [8:0] address_2_w_reg; +reg [8:0] address_2_r_reg; +reg wren_1_reg; +reg wren_2_reg; +reg config_switch_caches_reg; +reg [53:0] data_1_reg; +reg [53:0] data_2_reg; + +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) address_1_w_reg <= 9'd0; else address_1_w_reg <= address_1_w; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) address_1_r_reg <= 9'd0; else address_1_r_reg <= address_1_r; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) address_2_w_reg <= 9'd0; else address_2_w_reg <= address_2_w; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) address_2_r_reg <= 9'd0; else address_2_r_reg <= address_2_r; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) wren_1_reg <= `FALSE; else wren_1_reg <= wren_1; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) wren_2_reg <= `FALSE; else wren_2_reg <= wren_2; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) config_switch_caches_reg <= `FALSE; else config_switch_caches_reg <= config_switch_caches; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) data_1_reg <= 54'd0; else data_1_reg <= data_1; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) data_2_reg <= 54'd0; else data_2_reg <= data_2; end + +assign fetch_cache_q = + (config_switch_caches_reg && wren_1_reg && address_1_r_reg == address_1_w_reg)? data_1_reg : + (config_switch_caches_reg)? q_1 : + (wren_2_reg && address_2_r_reg == address_2_w_reg)? data_2_reg : + q_2; + +assign data_cache_q = + (config_switch_caches_reg && wren_2_reg && address_2_r_reg == address_2_w_reg)? data_2_reg : + (config_switch_caches_reg)? q_2 : + (wren_1_reg && address_1_r_reg == address_1_w_reg)? data_1_reg : + q_1; + +//------------------------------------------------------------------------------ + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) write_buffer_counter <= 5'd0; + else if(ram_fifo_wrreq && ram_fifo_data[66] && (ram_fifo_empty || ~(ram_fifo_rdreq) || (ram_fifo_rdreq && ~(ram_fifo_q[66])))) write_buffer_counter <= write_buffer_counter + 5'd1; + else if((~(ram_fifo_wrreq) || ~(ram_fifo_data[66])) && ram_fifo_rdreq && ram_fifo_q[66]) write_buffer_counter <= write_buffer_counter - 5'd1; +end + +//------------------------------------------------------------------------------ + +wire [3:0] ram_fifo_usedw; + +//{ [66] 1'b is_write, [65:36] 30'b address, [35:4] 32'b value, [3:0] 4'b byteena (4'b0000 - can burst 4 words) } + +model_fifo #( + .width (67), + .widthu (4) +) +ram_fifo_inst( + .clk (clk), + .rst_n (rst_n), + + .sclr (`FALSE), + + .rdreq (ram_fifo_rdreq), //input + .wrreq (ram_fifo_wrreq), //input + .data (ram_fifo_data), //input [66:0] + + .empty (ram_fifo_empty), //output + .full (ram_fifo_full), //output + .q (ram_fifo_q), //output [66:0] + .usedw (ram_fifo_usedw) //output [3:0] +); + +//------------------------------------------------------------------------------ +// synthesis translate_off +wire _unused_ok = &{ 1'b0, ram_fifo_usedw, 1'b0 }; +// synthesis translate_on +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/memory/memory_avalon.v =================================================================== --- trunk/rtl/memory/memory_avalon.v (nonexistent) +++ trunk/rtl/memory/memory_avalon.v (revision 2) @@ -0,0 +1,158 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module memory_avalon( + input clk, + input rst_n, + + //{ [66] 1'b is_write, [65:36] 30'b address, [35:4] 32'b value, [3:0] 4'b byteena (4'b0000 - can burst 4 words) } + input [66:0] ram_fifo_q, + input ram_fifo_empty, + output ram_fifo_rdreq, + + //address and req must be held till ack; on ack address can change + input [31:0] ram_instr_address, + input ram_instr_req, + output reg ram_instr_ack, + + output reg [31:0] ram_result_address, + output reg ram_result_valid, + output reg ram_result_is_read_instr, + output reg [2:0] ram_result_burstcount, + output reg [31:0] ram_result, + + //Avalon master interface + output reg [31:0] avm_address, + output reg [31:0] avm_writedata, + output reg [3:0] avm_byteenable, + output reg [2:0] avm_burstcount, + output reg avm_write, + output reg avm_read, + + input avm_waitrequest, + input avm_readdatavalid, + input [31:0] avm_readdata +); + +//------------------------------------------------------------------------------ state machine + +localparam [1:0] STATE_IDLE = 2'd0; +localparam [1:0] STATE_WRITE = 2'd1; +localparam [1:0] STATE_READ = 2'd2; + +wire start_write = (state == STATE_IDLE || ~(avm_waitrequest)) && ~(ram_fifo_empty) && ram_fifo_q[66] == 1'b1; +wire start_read = (state == STATE_IDLE || ~(avm_waitrequest)) && ~(ram_fifo_empty) && ram_fifo_q[66] == 1'b0 && readp_possible; +wire start_instr_read = (state == STATE_IDLE || ~(avm_waitrequest)) && ~(start_write) && ~(start_read) && ram_instr_req && readp_possible; + +assign ram_fifo_rdreq = start_read || start_write; + +reg [1:0] state; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) state <= STATE_IDLE; + else if(start_write) state <= STATE_WRITE; + else if(start_read || start_instr_read) state <= STATE_READ; + else if(~(avm_waitrequest)) state <= STATE_IDLE; +end + +//------------------------------------------------------------------------------ pipeline read + +//[33] is_read_instr [32:30] burstcount [29:0] address + +wire readp_0_update = (start_read || start_instr_read) && readp_2[32:30] == 3'd0 && readp_1[32:30] == 3'd0 && (readp_0[32:30] == 3'd0 || readp_chain); +wire readp_1_update = ~(readp_0_update) && (start_read || start_instr_read) && readp_2[32:30] == 3'd0 && (readp_1[32:30] == 3'd0 || readp_chain); +wire readp_2_update = ~(readp_1_update) && ~(readp_0_update) && (start_read || start_instr_read) && (readp_2[32:30] == 3'd0 || readp_chain); + +wire readp_chain = readp_0[32:30] == 3'd1 && avm_readdatavalid; + +wire [2:0] readp_0_burstcount = readp_0[32:30] - 3'd1; +wire [29:0] readp_0_address = readp_0[29:0] + 30'd1; + +wire [2:0] read_burstcount = (ram_fifo_q[3:0] == 4'h0)? 3'd4 : 3'd1; + +wire [33:0] readp_value = (start_read)? { 1'b0, read_burstcount, ram_fifo_q[65:36] } : { 1'b1, 3'd4, ram_instr_address[31:2] }; + +reg [33:0] readp_0; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) readp_0 <= 34'd0; + else if(readp_0_update) readp_0 <= readp_value; + else if(readp_chain) readp_0 <= readp_1; + else if(readp_0[32:30] > 3'd0 && avm_readdatavalid) readp_0 <= { readp_0[33], readp_0_burstcount, readp_0_address }; +end + +reg [33:0] readp_1; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) readp_1 <= 34'd0; + else if(readp_1_update) readp_1 <= readp_value; + else if(readp_chain) readp_1 <= readp_2; +end + +reg [33:0] readp_2; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) readp_2 <= 34'd0; + else if(readp_2_update) readp_2 <= readp_value; + else if(readp_chain) readp_2 <= 34'd0; +end + +wire readp_possible = readp_2[32:30] == 3'd0 || readp_1[32:30] == 3'd0 || readp_0[32:30] == 3'd0 || (readp_0[32:30] == 3'd1 && avm_readdatavalid); + +//------------------------------------------------------------------------------ avalon bus control + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) avm_address <= 32'd0; + else if(start_write || start_read) avm_address <= { ram_fifo_q[65:36], 2'b00 }; + else if(start_instr_read) avm_address <= { ram_instr_address[31:2], 2'b00 }; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) avm_writedata <= 32'd0; + else if(start_write) avm_writedata <= ram_fifo_q[35:4]; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) avm_byteenable <= 4'd0; + else if(start_write || start_read) avm_byteenable <= (ram_fifo_q[3:0] == 4'h0)? 4'hF : ram_fifo_q[3:0]; + else if(start_instr_read) avm_byteenable <= 4'hF; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) avm_burstcount <= 3'd0; + else if(start_write) avm_burstcount <= 3'd1; + else if(start_read) avm_burstcount <= read_burstcount; + else if(start_instr_read) avm_burstcount <= 3'd4; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) avm_read <= 1'b0; + else if(start_read || start_instr_read) avm_read <= 1'b1; + else if(~(avm_waitrequest)) avm_read <= 1'b0; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) avm_write <= 1'b0; + else if(start_write) avm_write <= 1'b1; + else if(~(avm_waitrequest)) avm_write <= 1'b0; +end + +//------------------------------------------------------------------------------ results + +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) ram_instr_ack <= `FALSE; else ram_instr_ack <= start_instr_read; end + +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) ram_result_address <= 32'd0; else ram_result_address <= { readp_0[29:0], 2'b00 }; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) ram_result_valid <= `FALSE; else ram_result_valid <= avm_readdatavalid; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) ram_result_burstcount <= 3'd0; else ram_result_burstcount <= readp_0[32:30]; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) ram_result_is_read_instr <= 1'b0; else ram_result_is_read_instr <= readp_0[33]; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) ram_result <= 32'd0; else ram_result <= avm_readdata; end + +//------------------------------------------------------------------------------ +// synthesis translate_off +wire _unused_ok = &{ 1'b0, ram_instr_address[1:0], 1'b0 }; +// synthesis translate_on +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/memory/memory_tlb_ram.v =================================================================== --- trunk/rtl/memory/memory_tlb_ram.v (nonexistent) +++ trunk/rtl/memory/memory_tlb_ram.v (revision 2) @@ -0,0 +1,267 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module memory_tlb_ram( + input clk, + input rst_n, + + // + input tlb_ram_read_do, + input [5:0] tlb_ram_read_index, + output reg tlb_ram_read_result_ready, + output [49:0] tlb_ram_read_result, + + // + input tlb_ram_write_do, + input [5:0] tlb_ram_write_index, + input [49:0] tlb_ram_write_value, + + // + input [5:0] entryhi_asid, + + // + input tlb_ram_data_start, + input [19:0] tlb_ram_data_vpn, + output reg tlb_ram_data_hit, + output reg [5:0] tlb_ram_data_index, + output reg [49:0] tlb_ram_data_result, + output tlb_ram_data_missed, + + // + input tlb_ram_fetch_start, + input [19:0] tlb_ram_fetch_vpn, + output reg tlb_ram_fetch_hit, + output reg [49:0] tlb_ram_fetch_result, + output tlb_ram_fetch_missed +); /* verilator public_module */ + +//------------------------------------------------------------------------------ + +/* +[19:0] vpn +[39:20] pfn +[45:40] asid +[46] n noncachable +[47] d dirty = write-enable +[48] v valid +[49] g global +*/ + +//------------------------------------------------------------------------------ + +reg invalid_ram_q; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) invalid_ram_q <= `FALSE; + else invalid_ram_q <= tlb_ram_read_do || tlb_ram_write_do; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) tlb_ram_read_result_ready <= `FALSE; + else tlb_ram_read_result_ready <= tlb_ram_read_do; +end + +//------------------------------------------------------------------------------ + +reg [2:0] index; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) index <= 3'd0; + else index <= index_next; +end + +wire [2:0] index_next = (tlb_ram_read_do || tlb_ram_write_do)? index : index + 3'd1; + +wire [2:0] read_index = (tlb_ram_read_do)? tlb_ram_read_index[5:3] : index_next; + +//------------------------------------------------------------------------------ + +wire [49:0] tlb0_q_a; +wire [49:0] tlb0_q_b; +wire [49:0] tlb1_q_a; +wire [49:0] tlb1_q_b; +wire [49:0] tlb2_q_a; +wire [49:0] tlb2_q_b; +wire [49:0] tlb3_q_a; +wire [49:0] tlb3_q_b; + +reg [2:0] read_index_part; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) read_index_part <= 3'd0; + else read_index_part <= tlb_ram_read_index[2:0]; +end + +assign tlb_ram_read_result = + (read_index_part == 3'd0)? tlb0_q_a[49:0] : + (read_index_part == 3'd1)? tlb0_q_b[49:0] : + (read_index_part == 3'd2)? tlb1_q_a[49:0] : + (read_index_part == 3'd3)? tlb1_q_b[49:0] : + (read_index_part == 3'd4)? tlb2_q_a[49:0] : + (read_index_part == 3'd5)? tlb2_q_b[49:0] : + (read_index_part == 3'd6)? tlb3_q_a[49:0] : + tlb3_q_b[49:0]; + +//------------------------------------------------------------------------------ + +wire match_data0 = tlb_ram_data_vpn == tlb0_q_a[19:0] && (tlb0_q_a[49] || entryhi_asid == tlb0_q_a[45:40]); +wire match_data1 = tlb_ram_data_vpn == tlb0_q_b[19:0] && (tlb0_q_b[49] || entryhi_asid == tlb0_q_b[45:40]); +wire match_data2 = tlb_ram_data_vpn == tlb1_q_a[19:0] && (tlb1_q_a[49] || entryhi_asid == tlb1_q_a[45:40]); +wire match_data3 = tlb_ram_data_vpn == tlb1_q_b[19:0] && (tlb1_q_b[49] || entryhi_asid == tlb1_q_b[45:40]); +wire match_data4 = tlb_ram_data_vpn == tlb2_q_a[19:0] && (tlb2_q_a[49] || entryhi_asid == tlb2_q_a[45:40]); +wire match_data5 = tlb_ram_data_vpn == tlb2_q_b[19:0] && (tlb2_q_b[49] || entryhi_asid == tlb2_q_b[45:40]); +wire match_data6 = tlb_ram_data_vpn == tlb3_q_a[19:0] && (tlb3_q_a[49] || entryhi_asid == tlb3_q_a[45:40]); +wire match_data7 = tlb_ram_data_vpn == tlb3_q_b[19:0] && (tlb3_q_b[49] || entryhi_asid == tlb3_q_b[45:40]); + +wire match_fetch0 = tlb_ram_fetch_vpn == tlb0_q_a[19:0] && (tlb0_q_a[49] || entryhi_asid == tlb0_q_a[45:40]); +wire match_fetch1 = tlb_ram_fetch_vpn == tlb0_q_b[19:0] && (tlb0_q_b[49] || entryhi_asid == tlb0_q_b[45:40]); +wire match_fetch2 = tlb_ram_fetch_vpn == tlb1_q_a[19:0] && (tlb1_q_a[49] || entryhi_asid == tlb1_q_a[45:40]); +wire match_fetch3 = tlb_ram_fetch_vpn == tlb1_q_b[19:0] && (tlb1_q_b[49] || entryhi_asid == tlb1_q_b[45:40]); +wire match_fetch4 = tlb_ram_fetch_vpn == tlb2_q_a[19:0] && (tlb2_q_a[49] || entryhi_asid == tlb2_q_a[45:40]); +wire match_fetch5 = tlb_ram_fetch_vpn == tlb2_q_b[19:0] && (tlb2_q_b[49] || entryhi_asid == tlb2_q_b[45:40]); +wire match_fetch6 = tlb_ram_fetch_vpn == tlb3_q_a[19:0] && (tlb3_q_a[49] || entryhi_asid == tlb3_q_a[45:40]); +wire match_fetch7 = tlb_ram_fetch_vpn == tlb3_q_b[19:0] && (tlb3_q_b[49] || entryhi_asid == tlb3_q_b[45:40]); + +wire tlb_ram_data_hit_next = (data_cnt > 4'd0) && (match_data0 || match_data1 || match_data2 || match_data3 || match_data4 || match_data5 || match_data6 || match_data7); +wire tlb_ram_fetch_hit_next = (fetch_cnt > 4'd0 && ~(invalid_ram_q)) && (match_fetch0 || match_fetch1 || match_fetch2 || match_fetch3 || match_fetch4 || match_fetch5 || match_fetch6 || match_fetch7); + +wire [5:0] tlb_ram_data_index_next = + (match_data0)? { index, 3'd0 } : + (match_data1)? { index, 3'd1 } : + (match_data2)? { index, 3'd2 } : + (match_data3)? { index, 3'd3 } : + (match_data4)? { index, 3'd4 } : + (match_data5)? { index, 3'd5 } : + (match_data6)? { index, 3'd6 } : + { index, 3'd7 }; + +wire [49:0] tlb_ram_data_result_next = + (match_data0)? tlb0_q_a : + (match_data1)? tlb0_q_b : + (match_data2)? tlb1_q_a : + (match_data3)? tlb1_q_b : + (match_data4)? tlb2_q_a : + (match_data5)? tlb2_q_b : + (match_data6)? tlb3_q_a : + tlb3_q_b; + +wire [49:0] tlb_ram_fetch_result_next = + (match_fetch0)? tlb0_q_a : + (match_fetch1)? tlb0_q_b : + (match_fetch2)? tlb1_q_a : + (match_fetch3)? tlb1_q_b : + (match_fetch4)? tlb2_q_a : + (match_fetch5)? tlb2_q_b : + (match_fetch6)? tlb3_q_a : + tlb3_q_b; + +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tlb_ram_data_hit <= `FALSE; else tlb_ram_data_hit <= tlb_ram_data_hit_next; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tlb_ram_fetch_hit <= `FALSE; else tlb_ram_fetch_hit <= tlb_ram_fetch_hit_next; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tlb_ram_data_index <= 6'd0; else tlb_ram_data_index <= tlb_ram_data_index_next; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tlb_ram_data_result <= 50'd0; else tlb_ram_data_result <= tlb_ram_data_result_next; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) tlb_ram_fetch_result <= 50'd0; else tlb_ram_fetch_result <= tlb_ram_fetch_result_next; end + +//------------------------------------------------------------------------------ + +reg [3:0] data_cnt; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) data_cnt <= 4'd0; + else if(tlb_ram_data_start) data_cnt <= 4'd1; + else if(tlb_ram_data_hit) data_cnt <= 4'd0; + else if(data_cnt == 4'd9) data_cnt <= 4'd0; + else if(data_cnt > 4'd0) data_cnt <= data_cnt + 4'd1; +end +assign tlb_ram_data_missed = data_cnt == 4'd9 && ~(tlb_ram_data_hit); + +//------------------------------------------------------------------------------ + +reg [3:0] fetch_cnt; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) fetch_cnt <= 4'd0; + else if(tlb_ram_fetch_start) fetch_cnt <= 4'd1; + else if(tlb_ram_fetch_hit) fetch_cnt <= 4'd0; + else if(fetch_cnt == 4'd9) fetch_cnt <= 4'd0; + else if(fetch_cnt > 4'd0 && ~(invalid_ram_q)) fetch_cnt <= fetch_cnt + 4'd1; +end +assign tlb_ram_fetch_missed = fetch_cnt == 4'd9 && ~(tlb_ram_fetch_hit); + +//------------------------------------------------------------------------------ + +model_true_dual_ram #( + .width (50), + .widthad (4) +) +tlb0_inst( + .clk (clk), + + .address_a (tlb_ram_write_do? { 1'b0, tlb_ram_write_index[5:3] } : { 1'b0, read_index }), + .wren_a (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd0), + .data_a (tlb_ram_write_value), + .q_a (tlb0_q_a), + + .address_b (tlb_ram_write_do? { 1'b1, tlb_ram_write_index[5:3] } : { 1'b1, read_index }), + .wren_b (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd1), + .data_b (tlb_ram_write_value), + .q_b (tlb0_q_b) +); + +model_true_dual_ram #( + .width (50), + .widthad (4) +) +tlb1_inst( + .clk (clk), + + .address_a (tlb_ram_write_do? { 1'b0, tlb_ram_write_index[5:3] } : { 1'b0, read_index }), + .wren_a (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd2), + .data_a (tlb_ram_write_value), + .q_a (tlb1_q_a), + + .address_b (tlb_ram_write_do? { 1'b1, tlb_ram_write_index[5:3] } : { 1'b1, read_index }), + .wren_b (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd3), + .data_b (tlb_ram_write_value), + .q_b (tlb1_q_b) +); + +model_true_dual_ram #( + .width (50), + .widthad (4) +) +tlb2_inst( + .clk (clk), + + .address_a (tlb_ram_write_do? { 1'b0, tlb_ram_write_index[5:3] } : { 1'b0, read_index }), + .wren_a (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd4), + .data_a (tlb_ram_write_value), + .q_a (tlb2_q_a), + + .address_b (tlb_ram_write_do? { 1'b1, tlb_ram_write_index[5:3] } : { 1'b1, read_index }), + .wren_b (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd5), + .data_b (tlb_ram_write_value), + .q_b (tlb2_q_b) +); + +model_true_dual_ram #( + .width (50), + .widthad (4) +) +tlb3_inst( + .clk (clk), + + .address_a (tlb_ram_write_do? { 1'b0, tlb_ram_write_index[5:3] } : { 1'b0, read_index }), + .wren_a (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd6), + .data_a (tlb_ram_write_value), + .q_a (tlb3_q_a), + + .address_b (tlb_ram_write_do? { 1'b1, tlb_ram_write_index[5:3] } : { 1'b1, read_index }), + .wren_b (tlb_ram_write_do && tlb_ram_write_index[2:0] == 3'd7), + .data_b (tlb_ram_write_value), + .q_b (tlb3_q_b) +); + +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/aoR3000.v =================================================================== --- trunk/rtl/aoR3000.v (nonexistent) +++ trunk/rtl/aoR3000.v (revision 2) @@ -0,0 +1,503 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module aoR3000( + input clk, + input rst_n, + + // + input [5:0] interrupt_vector, + + // + output [31:0] avm_address, + output [31:0] avm_writedata, + output [3:0] avm_byteenable, + output [2:0] avm_burstcount, + output avm_write, + output avm_read, + + input avm_waitrequest, + input avm_readdatavalid, + input [31:0] avm_readdata +); + +//------------------------------------------------------------------------------ + +wire if_exc_address_error; +wire if_exc_tlb_inv; +wire if_exc_tlb_miss; + +wire if_ready; +wire [31:0] if_instr; +wire [31:0] if_pc; + +wire [8:0] fetch_cache_read_address; +wire [8:0] fetch_cache_write_address; +wire fetch_cache_write_enable; +wire [53:0] fetch_cache_data; + +wire tlb_ram_fetch_start; +wire [19:0] tlb_ram_fetch_vpn; + +wire [31:0] ram_instr_address; +wire ram_instr_req; + + +pipeline_if pipeline_if_inst( + .clk (clk), + .rst_n (rst_n), + + // + .config_kernel_mode (config_kernel_mode), //input + .entryhi_asid (entryhi_asid), //input [5:0] + + // + .micro_flush_do (micro_flush_do), //input + + // + .exception_start (exception_start), //input + .exception_start_pc (exception_start_pc), //input [31:0] + + // + .mem_stall (mem_stall), //input + + // + .if_exc_address_error (if_exc_address_error), //output + .if_exc_tlb_inv (if_exc_tlb_inv), //output + .if_exc_tlb_miss (if_exc_tlb_miss), //output + .if_ready (if_ready), //output + .if_instr (if_instr), //output [31:0] + .if_pc (if_pc), //output [31:0] + + // + .branch_start (branch_start), //input + .branch_address (branch_address), //input [31:0] + + // + .fetch_cache_read_address (fetch_cache_read_address), //output [8:0] + .fetch_cache_q (fetch_cache_q), //input [53:0] + + .fetch_cache_write_address (fetch_cache_write_address),//output [8:0] + .fetch_cache_write_enable (fetch_cache_write_enable), //output + .fetch_cache_data (fetch_cache_data), //output [53:0] + + + // + .tlb_ram_fetch_start (tlb_ram_fetch_start), //output + .tlb_ram_fetch_vpn (tlb_ram_fetch_vpn), //output [19:0] + .tlb_ram_fetch_hit (tlb_ram_fetch_hit), //input + .tlb_ram_fetch_result (tlb_ram_fetch_result), //input [49:0] + .tlb_ram_fetch_missed (tlb_ram_fetch_missed), //input + + // + .ram_instr_address (ram_instr_address), //output [31:0] + .ram_instr_req (ram_instr_req), //output + .ram_instr_ack (ram_instr_ack), //input + + // + .ram_result_address (ram_result_address), //input [31:0] + .ram_result_valid (ram_result_valid), //input + .ram_result_is_read_instr (ram_result_is_read_instr), //input + .ram_result_burstcount (ram_result_burstcount), //input [2:0] + .ram_result (ram_result) //input [31:0] +); + + +//------------------------------------------------------------------------------ + +wire [6:0] rf_cmd; +wire [31:0] rf_instr; +wire [31:0] rf_pc_plus4; +wire [31:0] rf_badvpn; +wire [31:0] rf_a; +wire [31:0] rf_b; + +pipeline_rf pipeline_rf_inst( + .clk (clk), + .rst_n (rst_n), + + // + .exception_start (exception_start), //input + + // + .if_exc_address_error (if_exc_address_error), //input + .if_exc_tlb_inv (if_exc_tlb_inv), //input + .if_exc_tlb_miss (if_exc_tlb_miss), //input + .if_ready (if_ready), //input + .if_instr (if_instr), //input [31:0] + .if_pc (if_pc), //input [31:0] + + // + .rf_cmd (rf_cmd), //output [6:0] + .rf_instr (rf_instr), //output [31:0] + .rf_pc_plus4 (rf_pc_plus4), //output [31:0] + .rf_badvpn (rf_badvpn), //output [31:0] + .rf_a (rf_a), //output [31:0] + .rf_b (rf_b), //output [31:0] + + // + .mem_stall (mem_stall), //input + + // + .exe_result_index (exe_result_index), //input [4:0] + .exe_result (exe_result), //input [31:0] + + .mem_result_index (mem_result_index), //input [4:0] + .mem_result (mem_result), //input [31:0] + + .muldiv_result_index (muldiv_result_index), //input [4:0] + .muldiv_result (muldiv_result) //input [31:0] +); + +//------------------------------------------------------------------------------ + +wire [6:0] exe_cmd; +wire [31:0] exe_instr; +wire [31:0] exe_pc_plus4; +wire exe_pc_user_seg; +wire [31:0] exe_badvpn; +wire [31:0] exe_a; +wire [31:0] exe_b; +wire [1:0] exe_branched; +wire [31:0] exe_branch_address; +wire exe_cmd_cp0; +wire exe_cmd_load; +wire exe_cmd_store; + +wire [4:0] exe_result_index; +wire [31:0] exe_result; + +wire [31:0] data_address_next; +wire [31:0] data_address; + +wire branch_start; +wire [31:0] branch_address; + +pipeline_exe pipeline_exe_inst( + .clk (clk), + .rst_n (rst_n), + + // + .config_kernel_mode (config_kernel_mode), //input + + // + .exception_start (exception_start), //input + + // + .mem_stall (mem_stall), //input + + // + .rf_cmd (rf_cmd), //input [6:0] + .rf_instr (rf_instr), //input [31:0] + .rf_pc_plus4 (rf_pc_plus4), //input [31:0] + .rf_badvpn (rf_badvpn), //input [31:0] + .rf_a (rf_a), //input [31:0] + .rf_b (rf_b), //input [31:0] + + // + .exe_cmd (exe_cmd), //output [6:0] + .exe_instr (exe_instr), //output [31:0] + .exe_pc_plus4 (exe_pc_plus4), //output [31:0] + .exe_pc_user_seg (exe_pc_user_seg), //output + .exe_badvpn (exe_badvpn), //output [31:0] + .exe_a (exe_a), //output [31:0] + .exe_b (exe_b), //output [31:0] + .exe_branched (exe_branched), //output [1:0] + .exe_branch_address (exe_branch_address), //output [31:0] + .exe_cmd_cp0 (exe_cmd_cp0), //output + .exe_cmd_load (exe_cmd_load), //output + .exe_cmd_store (exe_cmd_store), //output + + // + .exe_result_index (exe_result_index), //output [4:0] + .exe_result (exe_result), //output [31:0] + + // + .data_address_next (data_address_next), //output [31:0] + .data_address (data_address), //output [31:0] + + // + .branch_start (branch_start), //output + .branch_address (branch_address), //output [31:0] + + // + .write_buffer_counter (write_buffer_counter) //input [4:0] +); + +//------------------------------------------------------------------------------ + +wire mem_stall; + +wire config_kernel_mode; +wire config_switch_caches; + +wire [4:0] mem_result_index; +wire [31:0] mem_result; + +wire tlb_ram_read_do; +wire [5:0] tlb_ram_read_index; + +wire tlb_ram_write_do; +wire [5:0] tlb_ram_write_index; +wire [49:0] tlb_ram_write_value; + +wire tlb_ram_data_start; +wire [19:0] tlb_ram_data_vpn; + +wire micro_flush_do; +wire [5:0] entryhi_asid; + +wire exception_start; +wire [31:0] exception_start_pc; + +wire [8:0] data_cache_read_address; +wire [8:0] data_cache_write_address; +wire data_cache_write_enable; +wire [53:0] data_cache_data; + +wire ram_fifo_wrreq; +wire [66:0] ram_fifo_data; + +wire [4:0] muldiv_result_index; +wire [31:0] muldiv_result; + +pipeline_mem pipeline_mem_inst( + .clk (clk), + .rst_n (rst_n), + + // + .interrupt_vector (interrupt_vector), //input [5:0] + + // + .mem_stall (mem_stall), //output + + // + .config_kernel_mode (config_kernel_mode), //output + .config_switch_caches (config_switch_caches), //output + + // + .exe_cmd (exe_cmd), //input [6:0] + .exe_instr (exe_instr), //input [31:0] + .exe_pc_plus4 (exe_pc_plus4), //input [31:0] + .exe_pc_user_seg (exe_pc_user_seg), //input + .exe_badvpn (exe_badvpn), //input [31:0] + .exe_a (exe_a), //input [31:0] + .exe_b (exe_b), //input [31:0] + .exe_branched (exe_branched), //input [1:0] + .exe_branch_address (exe_branch_address), //input [31:0] + .exe_cmd_cp0 (exe_cmd_cp0), //input + .exe_cmd_load (exe_cmd_load), //input + .exe_cmd_store (exe_cmd_store), //input + + // + .exe_result_index (exe_result_index), //input [4:0] + .exe_result (exe_result), //input [31:0] + + // + .mem_result_index (mem_result_index), //output [4:0] + .mem_result (mem_result), //output [31:0] + + // + .muldiv_result_index (muldiv_result_index), //output [4:0] + .muldiv_result (muldiv_result), //output [31:0] + + // + .tlb_ram_read_do (tlb_ram_read_do), //output + .tlb_ram_read_index (tlb_ram_read_index), //output [5:0] + .tlb_ram_read_result_ready (tlb_ram_read_result_ready),//input + .tlb_ram_read_result (tlb_ram_read_result), //input [49:0] + + // + .tlb_ram_write_do (tlb_ram_write_do), //output + .tlb_ram_write_index (tlb_ram_write_index), //output [5:0] + .tlb_ram_write_value (tlb_ram_write_value), //output [49:0] + + // + .tlb_ram_data_start (tlb_ram_data_start), //output + .tlb_ram_data_vpn (tlb_ram_data_vpn), //output [19:0] + .tlb_ram_data_hit (tlb_ram_data_hit), //input + .tlb_ram_data_index (tlb_ram_data_index), //input [5:0] + .tlb_ram_data_result (tlb_ram_data_result), //input [49:0] + .tlb_ram_data_missed (tlb_ram_data_missed), //input + + // + .exception_start (exception_start), //output + .exception_start_pc (exception_start_pc), //output [31:0] + + // + .micro_flush_do (micro_flush_do), //output + .entryhi_asid (entryhi_asid), //output [5:0] + + // + .data_address_next (data_address_next), //input [31:0] + .data_address (data_address), //input [31:0] + + // + .data_cache_read_address (data_cache_read_address), //output [8:0] + .data_cache_q (data_cache_q), //input [53:0] + + .data_cache_write_address (data_cache_write_address), //output [8:0] + .data_cache_write_enable (data_cache_write_enable), //output + .data_cache_data (data_cache_data), //output [53:0] + + // + .ram_fifo_wrreq (ram_fifo_wrreq), //output + .ram_fifo_data (ram_fifo_data), //output [66:0] + .ram_fifo_full (ram_fifo_full), //input + + // + .ram_result_address (ram_result_address), //input [31:0] + .ram_result_valid (ram_result_valid), //input + .ram_result_is_read_instr (ram_result_is_read_instr), //input + .ram_result_burstcount (ram_result_burstcount), //input [2:0] + .ram_result (ram_result) //input [31:0] +); + +//------------------------------------------------------------------------------ + +wire [53:0] fetch_cache_q; + +wire [53:0] data_cache_q; + +wire ram_fifo_empty; +wire ram_fifo_full; +wire [66:0] ram_fifo_q; + +wire [4:0] write_buffer_counter; + +memory_ram memory_ram_inst( + .clk (clk), + .rst_n (rst_n), + + // + .config_switch_caches (config_switch_caches), //input + + // + .fetch_cache_read_address (fetch_cache_read_address), //input [8:0] + .fetch_cache_q (fetch_cache_q), //input [53:0] + + .fetch_cache_write_address (fetch_cache_write_address),//input [8:0] + .fetch_cache_write_enable (fetch_cache_write_enable), //input + .fetch_cache_data (fetch_cache_data), //input [53:0] + + // + .data_cache_read_address (data_cache_read_address), //input [8:0] + .data_cache_q (data_cache_q), //output [53:0] + + .data_cache_write_address (data_cache_write_address), //input [8:0] + .data_cache_write_enable (data_cache_write_enable), //input + .data_cache_data (data_cache_data), //input [53:0] + + //ram_fifo + .ram_fifo_rdreq (ram_fifo_rdreq), //input + .ram_fifo_wrreq (ram_fifo_wrreq), //input + .ram_fifo_data (ram_fifo_data), //input [66:0] + + .ram_fifo_empty (ram_fifo_empty), //output + .ram_fifo_full (ram_fifo_full), //output + .ram_fifo_q (ram_fifo_q), //output [66:0] + + .write_buffer_counter (write_buffer_counter) //output [4:0] +); + +//------------------------------------------------------------------------------ + +wire tlb_ram_read_result_ready; +wire [49:0] tlb_ram_read_result; + +wire tlb_ram_data_hit; +wire [5:0] tlb_ram_data_index; +wire [49:0] tlb_ram_data_result; +wire tlb_ram_data_missed; + +wire tlb_ram_fetch_hit; +wire [49:0] tlb_ram_fetch_result; +wire tlb_ram_fetch_missed; + +memory_tlb_ram memory_tlb_ram_inst( + .clk (clk), + .rst_n (rst_n), + + // + .tlb_ram_read_do (tlb_ram_read_do), //input + .tlb_ram_read_index (tlb_ram_read_index), //input [5:0] + .tlb_ram_read_result_ready (tlb_ram_read_result_ready),//output + .tlb_ram_read_result (tlb_ram_read_result), //output [49:0] + + // + .tlb_ram_write_do (tlb_ram_write_do), //input + .tlb_ram_write_index (tlb_ram_write_index), //input [5:0] + .tlb_ram_write_value (tlb_ram_write_value), //input [49:0] + + // + .entryhi_asid (entryhi_asid), //input [5:0] + + // + .tlb_ram_data_start (tlb_ram_data_start), //input + .tlb_ram_data_vpn (tlb_ram_data_vpn), //input [19:0] + .tlb_ram_data_hit (tlb_ram_data_hit), //output + .tlb_ram_data_index (tlb_ram_data_index), //output [5:0] + .tlb_ram_data_result (tlb_ram_data_result), //output [49:0] + .tlb_ram_data_missed (tlb_ram_data_missed), //output + + // + .tlb_ram_fetch_start (tlb_ram_fetch_start), //input + .tlb_ram_fetch_vpn (tlb_ram_fetch_vpn), //input [19:0] + .tlb_ram_fetch_hit (tlb_ram_fetch_hit), //output + .tlb_ram_fetch_result (tlb_ram_fetch_result), //output [49:0] + .tlb_ram_fetch_missed (tlb_ram_fetch_missed) //output +); + +//------------------------------------------------------------------------------ + +wire ram_fifo_rdreq; + +wire [31:0] ram_result_address; +wire ram_result_valid; +wire ram_result_is_read_instr; +wire [2:0] ram_result_burstcount; +wire [31:0] ram_result; + +wire ram_instr_ack; + +memory_avalon memory_avalon_inst( + .clk (clk), + .rst_n (rst_n), + + .ram_fifo_q (ram_fifo_q), //input [66:0] + .ram_fifo_empty (ram_fifo_empty), //input + .ram_fifo_rdreq (ram_fifo_rdreq), //output + + // + .ram_instr_address (ram_instr_address), //input [31:0] + .ram_instr_req (ram_instr_req), //input + .ram_instr_ack (ram_instr_ack), //output + + .ram_result_address (ram_result_address), //output [31:0] + .ram_result_valid (ram_result_valid), //output + .ram_result_is_read_instr (ram_result_is_read_instr), //output + .ram_result_burstcount (ram_result_burstcount), //output [2:0] + .ram_result (ram_result), //output [31:0] + + // + .avm_address (avm_address), //output [31:0] + .avm_writedata (avm_writedata), //output [31:0] + .avm_byteenable (avm_byteenable), //output [3:0] + .avm_burstcount (avm_burstcount), //output [2:0] + .avm_write (avm_write), //output + .avm_read (avm_read), //output + + .avm_waitrequest (avm_waitrequest), //input + .avm_readdatavalid (avm_readdatavalid), //input + .avm_readdata (avm_readdata) //input [31:0] +); + +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/block/block_long_div.v =================================================================== --- trunk/rtl/block/block_long_div.v (nonexistent) +++ trunk/rtl/block/block_long_div.v (revision 2) @@ -0,0 +1,82 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +module block_long_div( + input clk, + input rst_n, + + input start, + input [32:0] dividend, + input [32:0] divisor, + + output ready, + output [31:0] quotient, + output [31:0] remainder +); + +//------------------------------------------------------------------------------ + +reg [5:0] div_counter; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_counter <= 6'd0; + else if(start) div_counter <= 6'd33; + else if(div_counter != 6'd0) div_counter <= div_counter - 6'd1; +end + +wire div_working = div_counter > 6'd1; + +wire [64:0] div_diff = { 32'd0, div_dividend } - div_divisor; + +reg [31:0] div_dividend; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_dividend <= 32'd0; + else if(start && dividend[32] == 1'b0) div_dividend <= dividend[31:0]; + else if(start && dividend[32] == 1'b1) div_dividend <= -dividend[31:0]; + else if(div_working && div_diff[64] == 1'b0) div_dividend <= div_diff[31:0]; +end + +wire [32:0] divisor_neg = -divisor; + +reg [63:0] div_divisor; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_divisor <= 64'd0; + else if(start && divisor[32] == 1'b0) div_divisor <= { 1'b0, divisor[31:0], 31'd0 }; + else if(start && divisor[32] == 1'b1) div_divisor <= { 1'b0, divisor_neg[31:0], 31'd0 }; + else if(div_working) div_divisor <= { 1'b0, div_divisor[63:1] }; +end + +reg [31:0] div_quotient; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_quotient <= 32'd0; + else if(start) div_quotient <= 32'd0; + else if(div_working && div_diff[64] == 1'b0) div_quotient <= { div_quotient[30:0], 1'b1 }; + else if(div_working && div_diff[64] == 1'b1) div_quotient <= { div_quotient[30:0], 1'b0 }; +end + +reg div_quotient_neg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_quotient_neg <= 1'b0; + else if(start) div_quotient_neg <= dividend[32] ^ divisor[32]; +end + +reg div_remainder_neg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_remainder_neg <= 1'b0; + else if(start) div_remainder_neg <= dividend[32]; +end + +assign ready = div_counter == 6'd1; +assign quotient = (div_quotient_neg)? -div_quotient[31:0] : div_quotient[31:0]; +assign remainder = (div_remainder_neg)? -div_dividend[31:0] : div_dividend[31:0]; + +//------------------------------------------------------------------------------ +// synthesis translate_off +wire _unused_ok = &{ 1'b0, div_diff[63:32], divisor_neg[32], 1'b0 }; +// synthesis translate_on +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/block/block_cp0.v =================================================================== --- trunk/rtl/block/block_cp0.v (nonexistent) +++ trunk/rtl/block/block_cp0.v (revision 2) @@ -0,0 +1,329 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module block_cp0( + input clk, + input rst_n, + + // + output reg config_switch_caches, + output reg config_isolate_cache, + output config_coproc0_usable, + output config_coproc1_usable, + output config_kernel_mode, + + // + input exe_cmd_mtc0, + input [31:0] exe_instr, + input [31:0] exe_b, + + input exe_cmd_rfe, + input exe_cmd_tlbr, + input exe_cmd_tlbwi, + input exe_cmd_tlbwr, + + // + output [31:0] coproc0_output, + + // + output [5:0] tlbw_index, + output [49:0] tlbw_value, + + // + output reg [5:0] tlbr_index, + + input tlb_ram_read_result_ready, + input [49:0] tlb_ram_read_result, + + // + input tlbp_update, + input tlbp_hit, + input [5:0] tlbp_index, + + // + output micro_flush_do, + output reg [5:0] entryhi_asid, + + // + input sr_cm_set, + input sr_cm_clear, + + // + input [5:0] interrupt_vector, + + // + output exception_start, + output [31:0] exception_start_pc, + + // + input mem_stalled, + input [6:0] mem_cmd, + input [31:0] mem_instr, + input [31:0] mem_pc_plus4, + input [1:0] mem_branched, + input [31:0] mem_branch_address, + input [31:0] mem_badvpn +); /* verilator public_module */ + +//------------------------------------------------------------------------------ + +reg [5:0] sr_ku_ie; //kernel/user and interrupt enable +reg sr_bev; //boot exception vector +reg sr_cm; //last d-cache load hit; used in d-cache isolated +reg [7:0] sr_im; //interrupt mask +reg [3:0] sr_coproc_usable; //coprocessor usable +reg sr_reverse_endian; +reg sr_tlb_shutdown; +reg sr_parity_error; +reg sr_parity_zero; + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) sr_ku_ie <= 6'b0; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_ku_ie <= exe_b[5:0]; + else if(exe_cmd_rfe) sr_ku_ie <= { sr_ku_ie[5:4], sr_ku_ie[5:2] }; + else if(exception_start) sr_ku_ie <= { sr_ku_ie[3:0], 2'b00 }; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) sr_cm <= `FALSE; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_cm <= exe_b[19]; + else if(sr_cm_clear) sr_cm <= `FALSE; //first sr_cm_clear important + else if(sr_cm_set) sr_cm <= `TRUE; +end + +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_coproc_usable <= 4'b0; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_coproc_usable <= exe_b[31:28]; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_reverse_endian <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_reverse_endian <= exe_b[25]; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_bev <= `TRUE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_bev <= exe_b[22]; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_tlb_shutdown <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_tlb_shutdown <= exe_b[21]; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_parity_error <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_parity_error <= exe_b[20]; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_parity_zero <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_parity_zero <= exe_b[18]; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) config_switch_caches <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) config_switch_caches <= exe_b[17]; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) config_isolate_cache <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) config_isolate_cache <= exe_b[16]; end +always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_im <= 8'h00; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_im <= exe_b[15:8]; end + +assign config_kernel_mode = ~(sr_ku_ie[1]); +assign config_coproc0_usable = sr_coproc_usable[0]; +assign config_coproc1_usable = sr_coproc_usable[1]; + +//------------------------------------------------------------------------------ + +reg cause_bd; //branch delay +reg [1:0] cause_ce; //coproc error +reg [1:0] cause_ip_writable; //interrupt pending ([1:0] writable) +reg [4:0] cause_exccode; //exccode +reg [31:0] epc; +reg [31:0] badvaddr; + +reg [5:0] interrupt_vector_reg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) interrupt_vector_reg <= 6'd0; + else interrupt_vector_reg <= interrupt_vector; +end + +wire [7:0] cause_ip = { interrupt_vector_reg, cause_ip_writable }; + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) cause_bd <= `FALSE; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd13) cause_bd <= exe_b[31]; + else if(exception_start) cause_bd <= (exception_not_interrupt && mem_branched == 2'd2) || (exception_interrupt && mem_branched == 2'd1); +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) cause_ce <= 2'd0; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd13) cause_ce <= exe_b[29:28]; + else if(exception_coprocessor_error) cause_ce <= mem_instr[27:26]; + else if(exception_start) cause_ce <= 2'd0; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) cause_ip_writable <= 2'd0; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd13) cause_ip_writable <= exe_b[9:8]; + else if(exception_start) cause_ip_writable <= 2'd0; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) cause_exccode <= 5'd31; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd13) cause_exccode <= exe_b[6:2]; + else if(exception_start) cause_exccode <= exception_cause; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) epc <= 32'd0; + else if(exception_start) epc <= exception_epc; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) badvaddr <= 32'd0; + else if(exception_badvaddr_update) badvaddr <= mem_badvpn; +end + +//------------------------------------------------------------------------------ + +reg tlb_probe; +reg [5:0] tlb_random; +reg [10:0] tlb_ptebase; +reg [18:0] tlb_badvpn; + +reg [19:0] entryhi_vpn; +reg [19:0] entrylo_pfn; +reg entrylo_n; +reg entrylo_d; +reg entrylo_v; +reg entrylo_g; + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) entryhi_vpn <= 20'd0; + else if(exception_badvaddr_update) entryhi_vpn <= mem_badvpn[31:12]; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd10) entryhi_vpn <= exe_b[31:12]; + else if(tlb_ram_read_result_ready) entryhi_vpn <= tlb_ram_read_result[19:0]; +end +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) entryhi_asid <= 6'd0; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd10) entryhi_asid <= exe_b[11:6]; + else if(tlb_ram_read_result_ready) entryhi_asid <= tlb_ram_read_result[45:40]; +end +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) entrylo_pfn <= 20'd0; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd2) entrylo_pfn <= exe_b[31:12]; + else if(tlb_ram_read_result_ready) entrylo_pfn <= tlb_ram_read_result[39:20]; +end +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) entrylo_n <= `FALSE; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd2) entrylo_n <= exe_b[11]; + else if(tlb_ram_read_result_ready) entrylo_n <= tlb_ram_read_result[46]; +end +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) entrylo_d <= `FALSE; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd2) entrylo_d <= exe_b[10]; + else if(tlb_ram_read_result_ready) entrylo_d <= tlb_ram_read_result[47]; +end +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) entrylo_v <= `FALSE; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd2) entrylo_v <= exe_b[9]; + else if(tlb_ram_read_result_ready) entrylo_v <= tlb_ram_read_result[48]; +end +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) entrylo_g <= `FALSE; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd2) entrylo_g <= exe_b[8]; + else if(tlb_ram_read_result_ready) entrylo_g <= tlb_ram_read_result[49]; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) tlb_ptebase <= 11'd0; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd4) tlb_ptebase <= exe_b[31:21]; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) tlb_badvpn <= 19'd0; + else if(exception_badvaddr_update) tlb_badvpn <= mem_badvpn[30:12]; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) tlbr_index <= 6'd0; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd0) tlbr_index <= exe_b[13:8]; + else if(tlbp_update) tlbr_index <= (tlbp_hit)? tlbp_index : 6'd0; +end +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) tlb_probe <= `FALSE; + else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd0) tlb_probe <= exe_b[31]; + else if(tlbp_update) tlb_probe <= ~(tlbp_hit); +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) tlb_random <= 6'd63; + else if(exe_cmd_tlbwr) tlb_random <= (tlb_random <= 6'd08)? 6'd63 : tlb_random - 6'd1; +end + +reg [5:0] entryhi_asid_last; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) entryhi_asid_last <= 6'd0; + else entryhi_asid_last <= entryhi_asid; +end + +assign micro_flush_do = (entryhi_asid_last != entryhi_asid) || exe_cmd_tlbwi || exe_cmd_tlbwr; + +assign tlbw_index = (exe_cmd_tlbwi)? tlbr_index : tlb_random; +assign tlbw_value = (tlb_ram_read_result_ready)? + { tlb_ram_read_result[49], tlb_ram_read_result[48], tlb_ram_read_result[47], tlb_ram_read_result[46], tlb_ram_read_result[45:40], tlb_ram_read_result[39:20], tlb_ram_read_result[19:0] } : + { entrylo_g, entrylo_v, entrylo_d, entrylo_n, entryhi_asid, entrylo_pfn, entryhi_vpn }; + +//------------------------------------------------------------------------------ + +assign coproc0_output = + (tlb_ram_read_result_ready && exe_instr[15:11] == 5'd2)? + { tlb_ram_read_result[39:20], tlb_ram_read_result[46], tlb_ram_read_result[47], tlb_ram_read_result[48], tlb_ram_read_result[49], 8'd0 } : //entry low just after tlbr + (tlb_ram_read_result_ready && exe_instr[15:11] == 5'd10)? + { tlb_ram_read_result[19:0], tlb_ram_read_result[45:40], 6'd0 } : //entry high just after tlbr + + (exe_instr[15:11] == 5'd0)? { tlb_probe, 17'd0, tlbr_index, 8'd0 } : //tlb index + (exe_instr[15:11] == 5'd1)? { 18'd0, tlb_random, 8'd0 } : //tlb random + (exe_instr[15:11] == 5'd2)? { entrylo_pfn, entrylo_n, entrylo_d, entrylo_v, entrylo_g, 8'd0 } : //entry low + (exe_instr[15:11] == 5'd4)? { tlb_ptebase, tlb_badvpn, 2'b0 } : //tlb context + (exe_instr[15:11] == 5'd8)? badvaddr : //bad vaddr + (exe_instr[15:11] == 5'd10)? { entryhi_vpn, entryhi_asid, 6'd0 } : //entry high + (exe_instr[15:11] == 5'd12)? { sr_coproc_usable, 2'b0, sr_reverse_endian, 2'b0, sr_bev, sr_tlb_shutdown, sr_parity_error, sr_cm, sr_parity_zero, + config_switch_caches, config_isolate_cache, sr_im, 2'b0, sr_ku_ie } : //SR + (exe_instr[15:11] == 5'd13)? { cause_bd, 1'b0, cause_ce, 12'd0, cause_ip, 1'b0, cause_exccode, 2'b0 } : //cause + (exe_instr[15:11] == 5'd14)? epc : //epc + (exe_instr[15:11] == 5'd15)? { 16'd0, 8'h02, 8'h30 } : //PRId + 32'd0; + +//------------------------------------------------------------------------------ + +//input [6:0] mem_cmd, +//input mem_branched, +//input [31:0] mem_badvpn + +reg mem_stalled_last; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mem_stalled_last <= `FALSE; + else mem_stalled_last <= mem_stalled; +end + +wire exception_interrupt = sr_ku_ie[0] && (cause_ip & sr_im) != 8'd0 && (mem_cmd != `CMD_null || (mem_stalled_last && ~(mem_stalled))) && ~(exception_not_interrupt) && ~(mem_stalled); +wire exception_badvaddr_update = mem_cmd == `CMD_exc_load_tlb || mem_cmd == `CMD_exc_store_tlb || mem_cmd == `CMD_exc_tlb_load_miss || mem_cmd == `CMD_exc_tlb_store_miss || mem_cmd == `CMD_exc_tlb_modif; +wire exception_coprocessor_error = mem_cmd == `CMD_exc_coproc_unusable; + +wire exception_not_interrupt = exception_coprocessor_error || exception_badvaddr_update || mem_cmd == `CMD_exc_int_overflow || mem_cmd == `CMD_break || mem_cmd == `CMD_syscall || + mem_cmd == `CMD_exc_load_addr_err || mem_cmd == `CMD_exc_store_addr_err || mem_cmd == `CMD_exc_reserved_instr; + +assign exception_start = exception_not_interrupt || exception_interrupt; + +wire [31:0] exception_epc = + (exception_interrupt && mem_branched == 2'd2)? mem_branch_address : + (exception_interrupt && mem_branched == 2'd0)? mem_pc_plus4 : + (mem_branched == 2'd2)? mem_pc_plus4 - 32'd8 : + mem_pc_plus4 - 32'd4; + +wire [4:0] exception_cause = + (mem_cmd == `CMD_exc_tlb_modif)? 5'd1 : + (mem_cmd == `CMD_exc_load_tlb || mem_cmd == `CMD_exc_tlb_load_miss)? 5'd2 : + (mem_cmd == `CMD_exc_store_tlb || mem_cmd == `CMD_exc_tlb_store_miss)? 5'd3 : + (mem_cmd == `CMD_exc_load_addr_err)? 5'd4 : + (mem_cmd == `CMD_exc_store_addr_err)? 5'd5 : + (mem_cmd == `CMD_syscall)? 5'd8 : + (mem_cmd == `CMD_break)? 5'd9 : + (mem_cmd == `CMD_exc_reserved_instr)? 5'd10 : + (mem_cmd == `CMD_exc_coproc_unusable)? 5'd11 : + (mem_cmd == `CMD_exc_int_overflow)? 5'd12 : + 5'd0; //interrupt + +assign exception_start_pc = + (sr_bev && (mem_cmd == `CMD_exc_tlb_load_miss || mem_cmd == `CMD_exc_tlb_store_miss))? 32'hBFC00100 : + (mem_cmd == `CMD_exc_tlb_load_miss || mem_cmd == `CMD_exc_tlb_store_miss)? 32'h80000000 : + (sr_bev)? 32'hBFC00180 : + 32'h80000080; + +//------------------------------------------------------------------------------ +// synthesis translate_off +wire _unused_ok = &{ 1'b0, exe_instr[31:16], exe_instr[10:0], exe_cmd_tlbr, exe_cmd_tlbwr, mem_instr[31:28], mem_instr[25:0], 1'b0 }; +// synthesis translate_on +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/block/block_shift.v =================================================================== --- trunk/rtl/block/block_shift.v (nonexistent) +++ trunk/rtl/block/block_shift.v (revision 2) @@ -0,0 +1,101 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module block_shift( + input [6:0] rf_cmd, + input [31:0] rf_instr, + input [31:0] rf_a, + input [31:0] rf_b, + + output [31:0] shift_left, + output [31:0] shift_right +); + +//------------------------------------------------------------------------------ + +wire [4:0] shift_left_index = (rf_cmd == `CMD_3arg_sllv)? rf_a[4:0] : rf_instr[10:6]; + +assign shift_left = + (shift_left_index == 5'd0)? rf_b : + (shift_left_index == 5'd1)? { rf_b[30:0], 1'b0 } : + (shift_left_index == 5'd2)? { rf_b[29:0], 2'b0 } : + (shift_left_index == 5'd3)? { rf_b[28:0], 3'b0 } : + (shift_left_index == 5'd4)? { rf_b[27:0], 4'b0 } : + (shift_left_index == 5'd5)? { rf_b[26:0], 5'b0 } : + (shift_left_index == 5'd6)? { rf_b[25:0], 6'b0 } : + (shift_left_index == 5'd7)? { rf_b[24:0], 7'b0 } : + (shift_left_index == 5'd8)? { rf_b[23:0], 8'b0 } : + (shift_left_index == 5'd9)? { rf_b[22:0], 9'b0 } : + (shift_left_index == 5'd10)? { rf_b[21:0], 10'b0 } : + (shift_left_index == 5'd11)? { rf_b[20:0], 11'b0 } : + (shift_left_index == 5'd12)? { rf_b[19:0], 12'b0 } : + (shift_left_index == 5'd13)? { rf_b[18:0], 13'b0 } : + (shift_left_index == 5'd14)? { rf_b[17:0], 14'b0 } : + (shift_left_index == 5'd15)? { rf_b[16:0], 15'b0 } : + (shift_left_index == 5'd16)? { rf_b[15:0], 16'b0 } : + (shift_left_index == 5'd17)? { rf_b[14:0], 17'b0 } : + (shift_left_index == 5'd18)? { rf_b[13:0], 18'b0 } : + (shift_left_index == 5'd19)? { rf_b[12:0], 19'b0 } : + (shift_left_index == 5'd20)? { rf_b[11:0], 20'b0 } : + (shift_left_index == 5'd21)? { rf_b[10:0], 21'b0 } : + (shift_left_index == 5'd22)? { rf_b[9:0], 22'b0 } : + (shift_left_index == 5'd23)? { rf_b[8:0], 23'b0 } : + (shift_left_index == 5'd24)? { rf_b[7:0], 24'b0 } : + (shift_left_index == 5'd25)? { rf_b[6:0], 25'b0 } : + (shift_left_index == 5'd26)? { rf_b[5:0], 26'b0 } : + (shift_left_index == 5'd27)? { rf_b[4:0], 27'b0 } : + (shift_left_index == 5'd28)? { rf_b[3:0], 28'b0 } : + (shift_left_index == 5'd29)? { rf_b[2:0], 29'b0 } : + (shift_left_index == 5'd30)? { rf_b[1:0], 30'b0 } : + { rf_b[0], 31'b0 }; + +wire shift_right_arith = rf_cmd == `CMD_3arg_srav || rf_cmd == `CMD_sra; +wire [4:0] shift_right_index = (rf_cmd == `CMD_3arg_srav || rf_cmd == `CMD_3arg_srlv)? rf_a[4:0] : rf_instr[10:6]; + +assign shift_right = + (shift_right_index == 5'd0)? rf_b : + (shift_right_index == 5'd1)? { {1 {shift_right_arith & rf_b[31]}}, rf_b[31:1] } : + (shift_right_index == 5'd2)? { {2 {shift_right_arith & rf_b[31]}}, rf_b[31:2] } : + (shift_right_index == 5'd3)? { {3 {shift_right_arith & rf_b[31]}}, rf_b[31:3] } : + (shift_right_index == 5'd4)? { {4 {shift_right_arith & rf_b[31]}}, rf_b[31:4] } : + (shift_right_index == 5'd5)? { {5 {shift_right_arith & rf_b[31]}}, rf_b[31:5] } : + (shift_right_index == 5'd6)? { {6 {shift_right_arith & rf_b[31]}}, rf_b[31:6] } : + (shift_right_index == 5'd7)? { {7 {shift_right_arith & rf_b[31]}}, rf_b[31:7] } : + (shift_right_index == 5'd8)? { {8 {shift_right_arith & rf_b[31]}}, rf_b[31:8] } : + (shift_right_index == 5'd9)? { {9 {shift_right_arith & rf_b[31]}}, rf_b[31:9] } : + (shift_right_index == 5'd10)? { {10{shift_right_arith & rf_b[31]}}, rf_b[31:10] } : + (shift_right_index == 5'd11)? { {11{shift_right_arith & rf_b[31]}}, rf_b[31:11] } : + (shift_right_index == 5'd12)? { {12{shift_right_arith & rf_b[31]}}, rf_b[31:12] } : + (shift_right_index == 5'd13)? { {13{shift_right_arith & rf_b[31]}}, rf_b[31:13] } : + (shift_right_index == 5'd14)? { {14{shift_right_arith & rf_b[31]}}, rf_b[31:14] } : + (shift_right_index == 5'd15)? { {15{shift_right_arith & rf_b[31]}}, rf_b[31:15] } : + (shift_right_index == 5'd16)? { {16{shift_right_arith & rf_b[31]}}, rf_b[31:16] } : + (shift_right_index == 5'd17)? { {17{shift_right_arith & rf_b[31]}}, rf_b[31:17] } : + (shift_right_index == 5'd18)? { {18{shift_right_arith & rf_b[31]}}, rf_b[31:18] } : + (shift_right_index == 5'd19)? { {19{shift_right_arith & rf_b[31]}}, rf_b[31:19] } : + (shift_right_index == 5'd20)? { {20{shift_right_arith & rf_b[31]}}, rf_b[31:20] } : + (shift_right_index == 5'd21)? { {21{shift_right_arith & rf_b[31]}}, rf_b[31:21] } : + (shift_right_index == 5'd22)? { {22{shift_right_arith & rf_b[31]}}, rf_b[31:22] } : + (shift_right_index == 5'd23)? { {23{shift_right_arith & rf_b[31]}}, rf_b[31:23] } : + (shift_right_index == 5'd24)? { {24{shift_right_arith & rf_b[31]}}, rf_b[31:24] } : + (shift_right_index == 5'd25)? { {25{shift_right_arith & rf_b[31]}}, rf_b[31:25] } : + (shift_right_index == 5'd26)? { {26{shift_right_arith & rf_b[31]}}, rf_b[31:26] } : + (shift_right_index == 5'd27)? { {27{shift_right_arith & rf_b[31]}}, rf_b[31:27] } : + (shift_right_index == 5'd28)? { {28{shift_right_arith & rf_b[31]}}, rf_b[31:28] } : + (shift_right_index == 5'd29)? { {29{shift_right_arith & rf_b[31]}}, rf_b[31:29] } : + (shift_right_index == 5'd30)? { {30{shift_right_arith & rf_b[31]}}, rf_b[31:30] } : + { {31{shift_right_arith & rf_b[31]}}, rf_b[31] }; + +//------------------------------------------------------------------------------ +// synthesis translate_off +wire _unused_ok = &{ 1'b0, rf_instr[31:11], rf_instr[5:0], rf_a[31:5], 1'b0 }; +// synthesis translate_on +//------------------------------------------------------------------------------ + +endmodule Index: trunk/rtl/block/block_muldiv.v =================================================================== --- trunk/rtl/block/block_muldiv.v (nonexistent) +++ trunk/rtl/block/block_muldiv.v (revision 2) @@ -0,0 +1,136 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +`include "defines.v" + +module block_muldiv( + input clk, + input rst_n, + + input [6:0] exe_cmd_for_muldiv, + input [31:0] exe_a, + input [31:0] exe_b, + input [4:0] exe_instr_rd, + + output muldiv_busy, + + output [4:0] muldiv_result_index, + output [31:0] muldiv_result +); /* verilator public_module */ + +//------------------------------------------------------------------------------ lo, hi, busy + +reg [31:0] hi; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) hi <= 32'd0; + else if(exe_cmd_for_muldiv == `CMD_muldiv_mthi) hi <= exe_a; + else if(mult_ready) hi <= mult_result[63:32]; + else if(div_ready && div_busy) hi <= div_remainder; +end + +reg [31:0] lo; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) lo <= 32'd0; + else if(exe_cmd_for_muldiv == `CMD_muldiv_mtlo) lo <= exe_a; + else if(mult_ready) lo <= mult_result[31:0]; + else if(div_ready && div_busy) lo <= div_quotient; +end + +reg busy; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) busy <= `FALSE; + else if(exe_cmd_for_muldiv == `CMD_muldiv_mfhi || exe_cmd_for_muldiv == `CMD_muldiv_mflo || busy) busy <= mult_busy || div_busy; +end + +wire muldiv_busy_start = ((exe_cmd_for_muldiv == `CMD_muldiv_mfhi || exe_cmd_for_muldiv == `CMD_muldiv_mflo) && (mult_busy || div_busy)); + +assign muldiv_busy = muldiv_busy_start || busy; + +reg [4:0] muldiv_index_value; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) muldiv_index_value <= 5'd0; + else if(muldiv_busy_start) muldiv_index_value <= exe_instr_rd; + else if(~(mult_busy) && ~(div_busy)) muldiv_index_value <= 5'd0; +end + +reg muldiv_index_type_is_lo; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) muldiv_index_type_is_lo <= `FALSE; + else if(exe_cmd_for_muldiv == `CMD_muldiv_mfhi || exe_cmd_for_muldiv == `CMD_muldiv_mflo) muldiv_index_type_is_lo <= exe_cmd_for_muldiv == `CMD_muldiv_mflo; +end + +assign muldiv_result_index = + (muldiv_busy && (~(busy) || mult_busy || div_busy))? 5'd0 : + (exe_cmd_for_muldiv == `CMD_muldiv_mfhi || exe_cmd_for_muldiv == `CMD_muldiv_mflo)? exe_instr_rd : + muldiv_index_value; +assign muldiv_result = + (exe_cmd_for_muldiv == `CMD_muldiv_mfhi)? hi : + (exe_cmd_for_muldiv == `CMD_muldiv_mflo)? lo : + (muldiv_index_type_is_lo)? lo : + hi; + +//------------------------------------------------------------------------------ multiply + +wire mult_busy = mult_counter > 2'd0; +wire mult_ready= mult_counter == 2'd1; + +reg [1:0] mult_counter; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) mult_counter <= 2'd0; + else if(exe_cmd_for_muldiv == `CMD_muldiv_mult || exe_cmd_for_muldiv == `CMD_muldiv_multu) mult_counter <= 2'd2; + else if(mult_counter != 2'd0) mult_counter <= mult_counter - 2'd1; +end + +wire [65:0] mult_result; + +model_mult +#( + .widtha (33), + .widthb (33), + .widthp (66) +) +model_mult_inst( + .clk (clk), + .a ((exe_cmd_for_muldiv == `CMD_muldiv_mult)? { exe_a[31], exe_a[31:0] } : { 1'b0, exe_a[31:0] }), + .b ((exe_cmd_for_muldiv == `CMD_muldiv_mult)? { exe_b[31], exe_b[31:0] } : { 1'b0, exe_b[31:0] }), + .out (mult_result) +); + +//------------------------------------------------------------------------------ divide + +reg div_busy; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_busy <= `FALSE; + else if(exe_cmd_for_muldiv ==`CMD_muldiv_div || exe_cmd_for_muldiv == `CMD_muldiv_divu) div_busy <= `TRUE; + else if(div_ready) div_busy <= `FALSE; +end + +wire div_ready; +wire [31:0] div_quotient; +wire [31:0] div_remainder; + +block_long_div block_long_div_inst( + .clk (clk), + .rst_n (rst_n), + + .start (exe_cmd_for_muldiv == `CMD_muldiv_div || exe_cmd_for_muldiv == `CMD_muldiv_divu), //input + .dividend ({ exe_cmd_for_muldiv == `CMD_muldiv_div & exe_a[31], exe_a[31:0] }), //input [32:0] + .divisor ({ exe_cmd_for_muldiv == `CMD_muldiv_div & exe_b[31], exe_b[31:0] }), //input [32:0] + + .ready (div_ready), //output + .quotient (div_quotient), //output [31:0] + .remainder (div_remainder) //output [31:0] +); + +//------------------------------------------------------------------------------ +// synthesis translate_off +wire _unused_ok = &{ 1'b0, mult_result[65:64], 1'b0 }; +// synthesis translate_on +//------------------------------------------------------------------------------ + + +endmodule Index: trunk/LICENSE =================================================================== --- trunk/LICENSE (nonexistent) +++ trunk/LICENSE (revision 2) @@ -0,0 +1,33 @@ +> +> Most of the files in this project are under the BSD license: +> + +Copyright (c) 2014, Aleksander Osman +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +> +> A few files are under the GPL license. These files are: +> * all files in the sim/vmips/ directory; +> * all files in the linux/ directory; +> Index: trunk/sim/div-test/main.cpp =================================================================== --- trunk/sim/div-test/main.cpp (nonexistent) +++ trunk/sim/div-test/main.cpp (revision 2) @@ -0,0 +1,120 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "Vmain.h" +#include "verilated.h" +#include "verilated_vcd_c.h" + +//------------------------------------------------------------------------------ + +typedef unsigned int uint32; +typedef unsigned char uint8; +typedef unsigned long long uint64; + +//------------------------------------------------------------------------------ + + +int main(int argc, char **argv) { + + //-------------------------------------------------------------------------- + + Verilated::commandArgs(argc, argv); + + Verilated::traceEverOn(true); + VerilatedVcdC* tracer = new VerilatedVcdC; + + Vmain *top = new Vmain(); + top->trace (tracer, 99); + //tracer->rolloverMB(1000000); + tracer->open("main.vcd"); + + //reset + top->clk = 0; top->rst_n = 1; top->eval(); + top->clk = 1; top->rst_n = 1; top->eval(); + top->clk = 1; top->rst_n = 0; top->eval(); + top->clk = 0; top->rst_n = 0; top->eval(); + top->clk = 0; top->rst_n = 1; top->eval(); + + //-------------------------------------------------------------------------- + + bool dump_enabled = true; + + int cycle = 0; + + int pnom[] = { 0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,-2,-1, 0,1,-2,-1, 0, 1,-2,-1, 0, 1,-2,-1 }; + int pden[] = { 0,0,0,0, 1,1,1,1, 2,2,2,2, 3,3,3,3, 0,0, 0, 0, 1,1, 1, 1, -2,-2,-2,-2, -1,-1,-1,-1 }; + + int nom[] = { 0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,4|2,4|3, 0,1,4|2,4|3, 0, 1, 4|2,4|3, 0, 1, 4|2,4|3 }; + int denom[] = { 0,0,0,0, 1,1,1,1, 2,2,2,2, 3,3,3,3, 0,0,0, 0, 1,1,1, 1, 4|2,4|2,4|2,4|2, 4|2,4|2,4|2,4|2 }; + + int index = 0; + bool running = false; + + while(!Verilated::gotFinish()) { + + top->start = 0; + top->dividend = 0; + top->divisor = 0; + + if(running == false) { + top->start = 1; + top->dividend = nom[index]; + top->divisor = denom[index]; + running = true; + } + + if(top->ready) { + printf("%02d / %02d = q: %02d r: %02d\n", pnom[index], pden[index], top->quotient, top->remainder); + running = false; + index++; + + if(index == 32) { + printf("END\n"); + break; + } + } + + top->clk = 0; + top->eval(); + + cycle++; + if(dump_enabled) tracer->dump(cycle); + + top->clk = 1; + top->eval(); + + cycle++; + if(dump_enabled) tracer->dump(cycle); + + tracer->flush(); + //usleep(1); + } + delete top; + return 0; +} + +/* + input clk, + input rst_n, + + input start, + input [2:0] dividend, + input [2:0] divisor, + + output ready, + output [1:0] quotient, + output [1:0] remainder +*/ Index: trunk/sim/div-test/main.v =================================================================== --- trunk/sim/div-test/main.v (nonexistent) +++ trunk/sim/div-test/main.v (revision 2) @@ -0,0 +1,82 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +module main( + input clk, + input rst_n, + + input start, + input [2:0] dividend, + input [2:0] divisor, + + output ready, + output [1:0] quotient, + output [1:0] remainder +); + +//------------------------------------------------------------------------------ + +reg [5:0] div_counter; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_counter <= 6'd0; + else if(start) div_counter <= 6'd3; + else if(div_counter != 6'd0) div_counter <= div_counter - 6'd1; +end + +wire div_working = div_counter > 6'd1; + +wire [4:0] div_diff = { 2'd0, div_dividend } - div_divisor; + +reg [1:0] div_dividend; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_dividend <= 2'd0; + else if(start && dividend[2] == 1'b0) div_dividend <= dividend[1:0]; + else if(start && dividend[2] == 1'b1) div_dividend <= -dividend[1:0]; + else if(div_working && div_diff[4] == 1'b0) div_dividend <= div_diff[1:0]; +end + +wire [2:0] divisor_neg = -divisor; + +reg [3:0] div_divisor; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_divisor <= 4'd0; + else if(start && divisor[2] == 1'b0) div_divisor <= { 1'b0, divisor[1:0], 1'd0 }; + else if(start && divisor[2] == 1'b1) div_divisor <= { 1'b0, divisor_neg[1:0], 1'd0 }; + else if(div_working) div_divisor <= { 1'b0, div_divisor[3:1] }; +end + +reg [1:0] div_quotient; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_quotient <= 2'd0; + else if(start) div_quotient <= 2'd0; + else if(div_working && div_diff[4] == 1'b0) div_quotient <= { div_quotient[0], 1'b1 }; + else if(div_working && div_diff[4] == 1'b1) div_quotient <= { div_quotient[0], 1'b0 }; +end + +reg div_quotient_neg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_quotient_neg <= 1'b0; + else if(start) div_quotient_neg <= dividend[2] ^ divisor[2]; +end + +reg div_remainder_neg; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) div_remainder_neg <= 1'b0; + else if(start) div_remainder_neg <= dividend[2]; +end + +assign ready = div_counter == 6'd1; +assign quotient = (div_quotient_neg)? -div_quotient[1:0] : div_quotient[1:0]; +assign remainder = (div_remainder_neg)? -div_dividend[1:0] : div_dividend[1:0]; + +//------------------------------------------------------------------------------ + +wire _unused_ok = &{ 1'b0, div_diff[3:2], divisor_neg[2], 1'b0 }; + +//------------------------------------------------------------------------------ + +endmodule Index: trunk/sim/div-test/Makefile =================================================================== --- trunk/sim/div-test/Makefile (nonexistent) +++ trunk/sim/div-test/Makefile (revision 2) @@ -0,0 +1,3 @@ +all: + verilator --trace -Wall -CFLAGS "-O3" -LDFLAGS "-O3" --cc main.v --exe main.cpp + cd obj_dir && make -f Vmain.mk Index: trunk/sim/aoR3000/main_linux.cpp =================================================================== --- trunk/sim/aoR3000/main_linux.cpp (nonexistent) +++ trunk/sim/aoR3000/main_linux.cpp (revision 2) @@ -0,0 +1,293 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "VaoR3000.h" +#include "VaoR3000_aoR3000.h" +#include "VaoR3000_pipeline_rf.h" +#include "VaoR3000_pipeline_if.h" +#include "VaoR3000_pipeline_mem.h" +#include "VaoR3000_block_muldiv.h" +#include "VaoR3000_memory_tlb_ram.h" +#include "VaoR3000_block_cp0.h" +#include "VaoR3000_pipeline_exe.h" +#include "VaoR3000_model_true_dual_ram__W32_WB4.h" +#include "VaoR3000_model_simple_dual_ram__W20_WB5.h" + +#include "verilated.h" +#include "verilated_vcd_c.h" + +#include "shared_mem.h" + +//------------------------------------------------------------------------------ + +volatile shared_mem_t *shared_ptr = NULL; + +//------------------------------------------------------------------------------ + +void usleep_or_finish() { + if(shared_ptr->test_finished) { + printf("Finishing.\n"); + exit(0); + } + usleep(1); +} + +//128MB +#define MAX_MEMORY 0x08000000 +#define RESET_VECTOR 0x1FC00000 + +//------------------------------------------------------------------------------ + +int main(int argc, char **argv) { + + //map shared memory + int fd = open("./../tester/shared_mem.dat", O_RDWR, S_IRUSR | S_IWUSR); + + if(fd == -1) { + perror("open() failed for shared_mem.dat"); + return -1; + } + + shared_ptr = (shared_mem_t *)mmap(NULL, sizeof(shared_mem_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if(shared_ptr == MAP_FAILED) { + perror("mmap() failed"); + close(fd); + return -2; + } + + //-------------------------------------------------------------------------- + + Verilated::commandArgs(argc, argv); + + Verilated::traceEverOn(true); + VerilatedVcdC* tracer = new VerilatedVcdC; + + VaoR3000 *top = new VaoR3000(); + top->trace (tracer, 99); + //tracer->rolloverMB(1000000); + tracer->open("aoR3000.vcd"); + + bool dump_enabled = false; + + //reset + vluint64_t halfcycle = 0; + + top->clk = 0; top->rst_n = 1; top->eval(); if(dump_enabled) { tracer->dump(halfcycle); } halfcycle++; + top->clk = 0; top->rst_n = 0; top->eval(); if(dump_enabled) { tracer->dump(halfcycle); } halfcycle++; + top->rst_n = 1; + + printf("Waiting for initialize..."); fflush(stdout); + while(shared_ptr->proc_ao.initialize_do == false) usleep_or_finish(); + + shared_ptr->proc_ao.initialize_do = false; + printf("done\n"); + + //-------------------------------------------------------------------------- + + uint32 event_counter = 0; + + struct read_t { + uint32 count; + uint32 byteenable; + uint32 address; + }; + read_t read[5]; + uint32 read_list_count = sizeof(read) / sizeof(read_t); + memset(read, 0, sizeof(read)); + + bool stall_wait = false; + bool stall_state = false; + + bool is_exception_waiting = false; + + while(!Verilated::gotFinish()) { + + //---------------------------------------------------------------------- avalon master + + top->avm_waitrequest = 0; + top->avm_readdatavalid = 0; + top->avm_readdata = 0; + + if(top->avm_read) { + bool found = false; + for(uint32 i=0; iavm_address & 0xFFFFFFFC; + read[i].byteenable = top->avm_byteenable; + read[i].count = top->avm_burstcount; + + found = true; + break; + } + } + if(found == false) { + printf("[aoR3000]: read fatal error: too many reads.\n"); + exit(-1); + } + } + else if(read[0].count > 0) { + top->avm_readdatavalid = 1; + + if(read[0].address < MAX_MEMORY) { + top->avm_readdata = shared_ptr->mem.ints[read[0].address/4]; + } + else if(read[0].address >= RESET_VECTOR && read[0].address < RESET_VECTOR + sizeof(shared_ptr->reset_vector)) { + top->avm_readdata = shared_ptr->reset_vector[(read[0].address - RESET_VECTOR)/4]; + } + else { + shared_ptr->proc_ao.read_address = read[0].address & 0xFFFFFFFC; + shared_ptr->proc_ao.read_byteenable = read[0].byteenable; + shared_ptr->proc_ao.read_do = true; + + while(shared_ptr->proc_ao.read_do) usleep_or_finish(); + + top->avm_readdata = shared_ptr->proc_ao.read_data; + } + read[0].address += 4; + read[0].count--; + + if(read[0].count == 0) { + memmove(&read[0], &read[1], sizeof(read) - sizeof(read_t)); + } + } + + //---------------------------------------------------------------------- + + if(stall_state == true) stall_state = ((top->v->pipeline_mem_inst->__PVT__mem_stall & 1) == 0)? false : true; + + uint32 cmd = top->v->pipeline_mem_inst->__PVT__mem_cmd & 0x7F; + + bool stall_start = cmd != 0 && stall_state == true; + bool stall_end = stall_wait && stall_state == false; + + uint32 was_instruction = ((cmd != 0) && stall_state == false) || stall_end; + uint32 was_pc = top->v->pipeline_mem_inst->__PVT__mem_pc_plus4; + + if(stall_start) { + stall_wait = true; + } + else if(stall_end) { + stall_wait = false; + } + + if(stall_state == false) stall_state = ((top->v->pipeline_mem_inst->__PVT__mem_stall & 1) == 0)? false : true; + + //---------------------------------------------------------------------- + + bool dump_enabled = false; //event_counter > 40565500; + + //---------------------------------------------------------------------- interrupt + + bool irq2_enable = ((was_instruction && stall_end == false && (event_counter + 1) == shared_ptr->irq2_at_event)) || ((event_counter + 1) > shared_ptr->irq2_at_event); + bool irq3_enable = ((was_instruction && stall_end == false && (event_counter + 1) == shared_ptr->irq3_at_event)) || ((event_counter + 1) > shared_ptr->irq3_at_event); + top->interrupt_vector = ((irq2_enable)? 1 : 0) | ((irq3_enable)? 2 : 0); + + if(dump_enabled) { + printf("[%d]: ena2: %d ena3: %d cmd: %d at2: %d at3: %d stall_state: %d stall_start: %d stall_end: %d\n", + event_counter, (uint32)irq2_enable, (uint32)irq3_enable, cmd, shared_ptr->irq2_at_event, shared_ptr->irq3_at_event, stall_state, (uint32)stall_start, (uint32)stall_end); + fflush(stdout); + } + + //---------------------------------------------------------------------- clock + top->clk = 0; + top->eval(); + + if(dump_enabled) tracer->dump(halfcycle); + halfcycle++; + + top->clk = 1; + top->eval(); + + if(dump_enabled) tracer->dump(halfcycle); + halfcycle++; + + tracer->flush(); + + //---------------------------------------------------------------------- + if(top->avm_write) { + if(top->avm_burstcount != 1) { + printf("[avalon master error]: top->avm_burstcount(%d) != 1\n", top->avm_burstcount); + exit(-1); + } + + uint32 mask = 0; + uint32 byteena = top->avm_byteenable; + for(uint32 i=0; i<4; i++) { + if(byteena & 1) mask |= (0xFF << (i*8)); + byteena >>= 1; + } + + shared_ptr->proc_ao.write_address = top->avm_address & 0xFFFFFFFC; + shared_ptr->proc_ao.write_byteenable = top->avm_byteenable; + shared_ptr->proc_ao.write_data = top->avm_writedata & mask; + shared_ptr->proc_ao.write_do = true; + + while(shared_ptr->proc_ao.write_do) usleep_or_finish(); + } + + uint32 is_exception = (top->v->pipeline_if_inst->__PVT__exc_waiting & 1); + + //interrupt after stalled instruction ignored + + if((is_exception && was_instruction && (event_counter > 0 || halfcycle >= (4*2))) || was_instruction) { + + if(dump_enabled) { printf("inc: %d, exception: %d\n", event_counter, is_exception); fflush(stdout); } + + shared_ptr->proc_ao.report.counter = event_counter; + + if(shared_ptr->check_at_event == event_counter) { + shared_ptr->proc_ao.check_do = true; + + while(shared_ptr->proc_ao.check_do) usleep_or_finish(); + } + + event_counter++; + } + + is_exception_waiting = is_exception; + } + + top->final(); + delete top; + return 0; +} + +//------------------------------------------------------------------------------ + +/* +module aoR3000( + input clk, + input rst_n, + + // + input [5:0] interrupt_vector, + + // + output [31:0] avm_address, + output [31:0] avm_writedata, + output [3:0] avm_byteenable, + output [2:0] avm_burstcount, + output avm_write, + output avm_read, + + input avm_waitrequest, + input avm_readdatavalid, + input [31:0] avm_readdata +); +*/ + +//------------------------------------------------------------------------------ Index: trunk/sim/aoR3000/main_tester.cpp =================================================================== --- trunk/sim/aoR3000/main_tester.cpp (nonexistent) +++ trunk/sim/aoR3000/main_tester.cpp (revision 2) @@ -0,0 +1,452 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "VaoR3000.h" +#include "VaoR3000_aoR3000.h" +#include "VaoR3000_pipeline_rf.h" +#include "VaoR3000_pipeline_if.h" +#include "VaoR3000_pipeline_mem.h" +#include "VaoR3000_block_muldiv.h" +#include "VaoR3000_memory_tlb_ram.h" +#include "VaoR3000_block_cp0.h" +#include "VaoR3000_pipeline_exe.h" +#include "VaoR3000_model_true_dual_ram__W32_WB4.h" +#include "VaoR3000_model_simple_dual_ram__W20_WB5.h" + +#include "verilated.h" +#include "verilated_vcd_c.h" + +#include "shared_mem.h" + +//------------------------------------------------------------------------------ + +volatile shared_mem_t *shared_ptr = NULL; + +//------------------------------------------------------------------------------ + +#define GET(field, mask) \ + (shared_ptr->initial.field & mask) + +void initialize(VaoR3000 *top) { + + top->v->pipeline_rf_inst->regs_a_inst->__PVT__mem[0] = top->v->pipeline_rf_inst->regs_b_inst->__PVT__mem[0] = 0; + for(int i=1; i<32; i++) top->v->pipeline_rf_inst->regs_a_inst->__PVT__mem[i] = top->v->pipeline_rf_inst->regs_b_inst->__PVT__mem[i] = GET(reg[i-1], 0xFFFFFFFF); + + top->v->pipeline_if_inst->__PVT__exc_start_pc = GET(pc, 0xFFFFFFFF); + //not compared: top->v->pipeline_mem_inst->block_muldiv_inst->__PVT__hi = GET(hi, 0xFFFFFFFF); + //not compared: top->v->pipeline_mem_inst->block_muldiv_inst->__PVT__lo = GET(lo, 0xFFFFFFFF); + + for(int i=0; i<64; i++) { +/* +[19:0] vpn +[39:20] pfn +[45:40] asid +[46] n noncachable +[47] d dirty = write-enable +[48] v valid +[49] g global +*/ + uint64 entry = 0; + entry |= (uint64)(GET(tlb[i].vpn, 0xFFFFF)) << 0; + entry |= (uint64)(GET(tlb[i].asid, 0x3F)) << 40; + entry |= (uint64)(GET(tlb[i].pfn, 0xFFFFF)) << 20; + entry |= (uint64)(GET(tlb[i].n, 0x1)) << 46; + entry |= (uint64)(GET(tlb[i].d, 0x1)) << 47; + entry |= (uint64)(GET(tlb[i].v, 0x1)) << 48; + entry |= (uint64)(GET(tlb[i].g, 0x1)) << 49; + + if((i % 8) == 0) top->v->memory_tlb_ram_inst->tlb0_inst->__PVT__mem[i/8] = entry; + if((i % 8) == 1) top->v->memory_tlb_ram_inst->tlb0_inst->__PVT__mem[8+(i/8)] = entry; + if((i % 8) == 2) top->v->memory_tlb_ram_inst->tlb1_inst->__PVT__mem[i/8] = entry; + if((i % 8) == 3) top->v->memory_tlb_ram_inst->tlb1_inst->__PVT__mem[8+(i/8)] = entry; + if((i % 8) == 4) top->v->memory_tlb_ram_inst->tlb2_inst->__PVT__mem[i/8] = entry; + if((i % 8) == 5) top->v->memory_tlb_ram_inst->tlb2_inst->__PVT__mem[8+(i/8)] = entry; + if((i % 8) == 6) top->v->memory_tlb_ram_inst->tlb3_inst->__PVT__mem[i/8] = entry; + if((i % 8) == 7) top->v->memory_tlb_ram_inst->tlb3_inst->__PVT__mem[8+(i/8)] = entry; + } + + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_probe = GET(index_p, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlbr_index = GET(index_index, 0x3F); + + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_random = GET(random, 0x3F); + + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_pfn = GET(entrylo_pfn, 0xFFFFF); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_n = GET(entrylo_n, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_d = GET(entrylo_d, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_v = GET(entrylo_v, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_g = GET(entrylo_g, 0x1); + + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_ptebase = GET(context_ptebase, 0x7FF); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_badvpn = GET(context_badvpn, 0x7FFFF); + + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__badvaddr = GET(bad_vaddr, 0xFFFFFFFF); + + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_vpn = GET(entryhi_vpn, 0xFFFFF); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_asid = GET(entryhi_asid, 0x3F); + + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_coproc_usable = GET(sr_cp_usable, 0xF); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_reverse_endian = GET(sr_rev_endian, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_bev = GET(sr_bootstrap_vec, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_tlb_shutdown = GET(sr_tlb_shutdown, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_parity_error = GET(sr_parity_err, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_cm = GET(sr_cache_miss, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_parity_zero = GET(sr_parity_zero, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__config_switch_caches = GET(sr_switch_cache, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__config_isolate_cache = GET(sr_isolate_cache, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_im = GET(sr_irq_mask, 0xFF); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_ku_ie = GET(sr_ku_ie, 0x3F); + + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_bd = GET(cause_branch_delay, 0x1); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_ce = GET(cause_cp_error, 0x3); + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_ip_writable = GET(cause_irq_pending, 0x3); //only 2 lowest bits + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_exccode = GET(cause_exc_code, 0x1F); + + top->v->pipeline_mem_inst->block_cp0_inst->__PVT__epc = GET(epc, 0xFFFFFFFF); +} + +//------------------------------------------------------------------------------ + +#define PUT(field, val, mask) \ + shared_ptr->proc_ao.report.state.field = (val) & mask + +void report(VaoR3000 *top, bool is_cp0_update, bool is_tlbr) { + + for(int i=1; i<32; i++) PUT(reg[i-1], top->v->pipeline_rf_inst->regs_a_inst->__PVT__mem[i], 0xFFFFFFFF); + + PUT(pc, top->v->pipeline_if_inst->__PVT__if_pc, 0xFFFFFFFF); + //not compared: PUT(hi, top->v->pipeline_mem_inst->block_muldiv_inst->__PVT__hi, 0xFFFFFFFF); + //not compared: PUT(lo, top->v->pipeline_mem_inst->block_muldiv_inst->__PVT__lo, 0xFFFFFFFF); + + if(is_tlbr) { + PUT(entrylo_pfn, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_pfn, 0xFFFFF); + PUT(entrylo_n, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_n, 0x1); + PUT(entrylo_d, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_d, 0x1); + PUT(entrylo_v, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_v, 0x1); + PUT(entrylo_g, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_g, 0x1); + + PUT(entryhi_vpn, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_vpn, 0xFFFFF); + PUT(entryhi_asid, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_asid, 0x3F); + } + + if(is_cp0_update == false) return; + + for(int i=0; i<64; i++) { + uint64 entry = 0; + if((i % 8) == 0) entry = top->v->memory_tlb_ram_inst->tlb0_inst->__PVT__mem[i/8]; + if((i % 8) == 1) entry = top->v->memory_tlb_ram_inst->tlb0_inst->__PVT__mem[8+(i/8)]; + if((i % 8) == 2) entry = top->v->memory_tlb_ram_inst->tlb1_inst->__PVT__mem[i/8]; + if((i % 8) == 3) entry = top->v->memory_tlb_ram_inst->tlb1_inst->__PVT__mem[8+(i/8)]; + if((i % 8) == 4) entry = top->v->memory_tlb_ram_inst->tlb2_inst->__PVT__mem[i/8]; + if((i % 8) == 5) entry = top->v->memory_tlb_ram_inst->tlb2_inst->__PVT__mem[8+(i/8)]; + if((i % 8) == 6) entry = top->v->memory_tlb_ram_inst->tlb3_inst->__PVT__mem[i/8]; + if((i % 8) == 7) entry = top->v->memory_tlb_ram_inst->tlb3_inst->__PVT__mem[8+(i/8)]; +/* +[19:0] vpn +[39:20] pfn +[45:40] asid +[46] n noncachable +[47] d dirty = write-enable +[48] v valid +[49] g global +*/ + PUT(tlb[i].vpn, entry >> 0, 0xFFFFF); + PUT(tlb[i].asid, entry >> 40, 0x3F); + + PUT(tlb[i].pfn, entry >> 20, 0xFFFFF); + PUT(tlb[i].n, entry >> 46, 0x1); + PUT(tlb[i].d, entry >> 47, 0x1); + PUT(tlb[i].v, entry >> 48, 0x1); + PUT(tlb[i].g, entry >> 49, 0x1); + } + + PUT(index_p, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_probe, 0x1); + PUT(index_index, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlbr_index, 0x3F); + + PUT(random, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_random, 0x3F); + + PUT(entrylo_pfn, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_pfn, 0xFFFFF); + PUT(entrylo_n, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_n, 0x1); + PUT(entrylo_d, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_d, 0x1); + PUT(entrylo_v, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_v, 0x1); + PUT(entrylo_g, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_g, 0x1); + + PUT(context_ptebase, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_ptebase, 0x7FF); + PUT(context_badvpn, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_badvpn, 0x7FFFF); + + PUT(bad_vaddr, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__badvaddr, 0xFFFFFFFF); + + PUT(entryhi_vpn, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_vpn, 0xFFFFF); + PUT(entryhi_asid, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_asid, 0x3F); + + PUT(sr_cp_usable, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_coproc_usable, 0xF); + PUT(sr_rev_endian, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_reverse_endian, 0x1); + PUT(sr_bootstrap_vec, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_bev, 0x1); + PUT(sr_tlb_shutdown, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_tlb_shutdown, 0x1); + PUT(sr_parity_err, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_parity_error, 0x1); + PUT(sr_cache_miss, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_cm, 0x1); + PUT(sr_parity_zero, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_parity_zero, 0x1); + PUT(sr_switch_cache, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__config_switch_caches, 0x1); + PUT(sr_isolate_cache, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__config_isolate_cache, 0x1); + PUT(sr_irq_mask, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_im, 0xFF); + PUT(sr_ku_ie, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_ku_ie, 0x3F); + + PUT(cause_branch_delay, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_bd, 0x1); + PUT(cause_cp_error, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_ce, 0x3); + PUT(cause_irq_pending, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_ip_writable, 0x3); //only 2 lowest bits + PUT(cause_exc_code, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_exccode, 0x1F); + + PUT(epc, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__epc, 0xFFFFFFFF); +} + +//------------------------------------------------------------------------------ + +void usleep_or_finish() { + if(shared_ptr->test_finished) { + printf("Finishing.\n"); + exit(0); + } + usleep(1); +} + +//------------------------------------------------------------------------------ + +int main(int argc, char **argv) { + + //map shared memory + int fd = open("./../tester/shared_mem.dat", O_RDWR, S_IRUSR | S_IWUSR); + + if(fd == -1) { + perror("open() failed for shared_mem.dat"); + return -1; + } + + shared_ptr = (shared_mem_t *)mmap(NULL, sizeof(shared_mem_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if(shared_ptr == MAP_FAILED) { + perror("mmap() failed"); + close(fd); + return -2; + } + + //-------------------------------------------------------------------------- + + Verilated::commandArgs(argc, argv); + + Verilated::traceEverOn(true); + VerilatedVcdC* tracer = new VerilatedVcdC; + + VaoR3000 *top = new VaoR3000(); + top->trace (tracer, 99); + //tracer->rolloverMB(1000000); + tracer->open("aoR3000.vcd"); + + bool dump_enabled = true; + + //reset + vluint64_t halfcycle = 0; + + top->clk = 0; top->rst_n = 1; top->eval(); if(dump_enabled) { tracer->dump(halfcycle); } halfcycle++; + top->clk = 0; top->rst_n = 0; top->eval(); if(dump_enabled) { tracer->dump(halfcycle); } halfcycle++; + top->rst_n = 1; + + printf("Waiting for initialize..."); fflush(stdout); + while(shared_ptr->proc_ao.initialize_do == false) usleep_or_finish(); + + initialize(top); + shared_ptr->proc_ao.initialize_do = false; + printf("done\n"); + + + //-------------------------------------------------------------------------- + + uint32 event_counter = 0; + + struct read_t { + uint32 count; + uint32 byteenable; + uint32 address; + }; + read_t read[5]; + uint32 read_list_count = sizeof(read) / sizeof(read_t); + memset(read, 0, sizeof(read)); + + bool stall_wait = false; + uint32 stall_pc = 0; + uint32 stall_branched = 0; + bool stall_state = false; + + while(!Verilated::gotFinish()) { + + //---------------------------------------------------------------------- avalon master + + top->avm_waitrequest = 0; + top->avm_readdatavalid = 0; + top->avm_readdata = 0; + + if(top->avm_read) { + bool found = false; + for(uint32 i=0; iavm_address & 0xFFFFFFFC; + read[i].byteenable = top->avm_byteenable; + read[i].count = top->avm_burstcount; + + found = true; + break; + } + } + if(found == false) { + printf("[aoR3000]: read fatal error: too many reads.\n"); + exit(-1); + } + } + else if(read[0].count > 0) { + top->avm_readdatavalid = 1; + + if(read[0].address < 0x08000000) { + top->avm_readdata = shared_ptr->mem.ints[read[0].address/4]; + } + else { + shared_ptr->proc_ao.read_address = read[0].address & 0xFFFFFFFC; + shared_ptr->proc_ao.read_byteenable = read[0].byteenable; + shared_ptr->proc_ao.read_do = true; + + while(shared_ptr->proc_ao.read_do) usleep_or_finish(); + + top->avm_readdata = shared_ptr->proc_ao.read_data; + } + read[0].address += 4; + read[0].count--; + + if(read[0].count == 0) { + memmove(&read[0], &read[1], sizeof(read) - sizeof(read_t)); + } + } + + //---------------------------------------------------------------------- + + uint32 cmd = top->v->pipeline_mem_inst->__PVT__mem_cmd & 0x7F; + + bool stall_start = cmd != 0 && stall_state == true; + bool stall_end = stall_wait && stall_state == false; + + uint32 was_instruction = ((cmd != 0) && stall_state == false) || stall_end; + uint32 was_pc = top->v->pipeline_mem_inst->__PVT__mem_pc_plus4; + + if(stall_start) { + stall_wait = true; + stall_pc = was_pc; + } + else if(stall_end) { + stall_wait = false; + } + + stall_state = (top->v->pipeline_mem_inst->__PVT__mem_stall & 1) != 0; + + report(top, true, false); + + //---------------------------------------------------------------------- interrupt + + top->interrupt_vector = (was_instruction && shared_ptr->irq2_at_event == (event_counter + 1))? 0x1 : 0; + + //---------------------------------------------------------------------- clock + top->clk = 0; + top->eval(); + + if(dump_enabled) tracer->dump(halfcycle); + halfcycle++; + + top->clk = 1; + top->eval(); + + if(dump_enabled) tracer->dump(halfcycle); + halfcycle++; + + tracer->flush(); + + //---------------------------------------------------------------------- + if(top->avm_write) { + if(top->avm_burstcount != 1) { + printf("[avalon master error]: top->avm_burstcount(%d) != 1\n", top->avm_burstcount); + exit(-1); + } + + uint32 mask = 0; + uint32 byteena = top->avm_byteenable; + for(uint32 i=0; i<4; i++) { + if(byteena & 1) mask |= (0xFF << (i*8)); + byteena >>= 1; + } + + shared_ptr->proc_ao.write_address = top->avm_address & 0xFFFFFFFC; + shared_ptr->proc_ao.write_byteenable = top->avm_byteenable; + shared_ptr->proc_ao.write_data = top->avm_writedata & mask; + shared_ptr->proc_ao.write_do = true; + + while(shared_ptr->proc_ao.write_do) usleep_or_finish(); + } + + uint32 is_exception = top->v->pipeline_if_inst->__PVT__exc_waiting & 1; + + if((is_exception && (event_counter > 0 || halfcycle >= (4*2))) || was_instruction) { + + was_pc = (stall_end)? stall_pc : was_pc; + + report(top, is_exception, cmd == 40); //TLBR + shared_ptr->proc_ao.report.counter = event_counter; + shared_ptr->proc_ao.report.exception = (is_exception)? 1 : 0; + + if(is_exception) PUT(pc, top->v->pipeline_if_inst->__PVT__exc_start_pc, 0xFFFFFFFF); + else PUT(pc, was_pc, 0xFFFFFFFF); + + shared_ptr->proc_ao.report_do = true; + + while(shared_ptr->proc_ao.report_do) usleep_or_finish(); + + event_counter++; + } + } + + top->final(); + delete top; + return 0; +} + +//------------------------------------------------------------------------------ + +/* +module aoR3000( + input clk, + input rst_n, + + // + input [5:0] interrupt_vector, + + // + output [31:0] avm_address, + output [31:0] avm_writedata, + output [3:0] avm_byteenable, + output [2:0] avm_burstcount, + output avm_write, + output avm_read, + + input avm_waitrequest, + input avm_readdatavalid, + input [31:0] avm_readdata +); +*/ + +//------------------------------------------------------------------------------ Index: trunk/sim/aoR3000/Makefile =================================================================== --- trunk/sim/aoR3000/Makefile (nonexistent) +++ trunk/sim/aoR3000/Makefile (revision 2) @@ -0,0 +1,7 @@ +tester: + verilator --trace -Wall -CFLAGS "-O3 -I./../../tester/" -LDFLAGS "-O3" --cc ./../../rtl/aoR3000.v --exe main_tester.cpp -I./../../rtl -I./../../rtl/block -I./../../rtl/memory -I./../../rtl/model -I./../../rtl/pipeline + cd obj_dir && make -f VaoR3000.mk + +linux: + verilator --trace -Wall -CFLAGS "-O3 -I./../../tester/" -LDFLAGS "-O3" --cc ./../../rtl/aoR3000.v --exe main_linux.cpp -I./../../rtl -I./../../rtl/block -I./../../rtl/memory -I./../../rtl/model -I./../../rtl/pipeline + cd obj_dir && make -f VaoR3000.mk Index: trunk/sim/tester/test_other.cpp =================================================================== --- trunk/sim/tester/test_other.cpp (nonexistent) +++ trunk/sim/tester/test_other.cpp (revision 2) @@ -0,0 +1,23 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include "tests.h" + +//------------------------------------------------------------------------------ + +uint32 rand_uint32() { + return ((rand() & 0xFFFF) << 16) | (rand() & 0xFFFF); +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ Index: trunk/sim/tester/test_tlb_commands.cpp =================================================================== --- trunk/sim/tester/test_tlb_commands.cpp (nonexistent) +++ trunk/sim/tester/test_tlb_commands.cpp (revision 2) @@ -0,0 +1,111 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include "tests.h" + +//------------------------------------------------------------------------------ + +void tlb_commands_till_exc_init(tst_t *tst, shared_mem_t *shared_ptr) { + + for(int i=1; i<32; i++) shared_ptr->initial.reg[i-1] = rand_uint32(); + + shared_ptr->initial.pc = 0xA0001000; + + for(int i=0; i<64; i++) shared_ptr->initial.tlb[i].vpn = rand() & 0xFFFFF; + + shared_ptr->initial.index_p = rand() & 0x1; + shared_ptr->initial.index_index = rand() & 0x3F; + + shared_ptr->initial.random = rand() & 0x3F; + + shared_ptr->initial.entrylo_pfn = rand() & 0xFFFFF; + shared_ptr->initial.entrylo_n = rand() & 0x1; + shared_ptr->initial.entrylo_d = rand() & 0x1; + shared_ptr->initial.entrylo_v = rand() & 0x1; + shared_ptr->initial.entrylo_g = rand() & 0x1; + + shared_ptr->initial.context_ptebase = rand() & 0x7FF; + shared_ptr->initial.context_badvpn = rand() & 0x7FFFF; + + shared_ptr->initial.bad_vaddr = rand_uint32(); + + shared_ptr->initial.entryhi_vpn = rand() & 0xFFFFF; + shared_ptr->initial.entryhi_asid = rand() & 0x3F; + + shared_ptr->initial.sr_cp_usable = rand() & 0xF; + shared_ptr->initial.sr_rev_endian = rand() & 0x1; + shared_ptr->initial.sr_bootstrap_vec = rand() & 0x1; + shared_ptr->initial.sr_tlb_shutdown = rand() & 0x1; + shared_ptr->initial.sr_parity_err = rand() & 0x1; + shared_ptr->initial.sr_cache_miss = rand() & 0x1; + shared_ptr->initial.sr_parity_zero = rand() & 0x1; + shared_ptr->initial.sr_switch_cache = rand() & 0x1; + shared_ptr->initial.sr_isolate_cache = rand() & 0x1; + shared_ptr->initial.sr_irq_mask = rand() & 0xFF; + shared_ptr->initial.sr_ku_ie = rand() & 0x3F; + + shared_ptr->initial.cause_branch_delay = rand() & 0x1; + shared_ptr->initial.cause_cp_error = rand() & 0x3; + shared_ptr->initial.cause_irq_pending = 0; + shared_ptr->initial.cause_exc_code = rand() & 0x1F; + + shared_ptr->initial.epc = rand_uint32(); + + // + shared_ptr->irq2_at_event = 0xFFFFFFFF; + shared_ptr->irq3_at_event = 0xFFFFFFFF; + + // + uint32 *ptr = &shared_ptr->mem.ints[(shared_ptr->initial.pc & 0x1FFFFFFF) / 4]; + + for(int i=0; i<100; i++) { + + uint32 type = rand() % 5; + + if(type == 0) { //RFE + (*ptr) = rand() & 0x01FFFFC0; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b1 << 25) | (0b010000 << 0); + } + else if(type == 1) { //TLBWR + (*ptr) = rand() & 0x01FFFFC0; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b1 << 25) | (0b000110 << 0); + + ptr++; + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + } + else if(type == 2) { //TLBWI + (*ptr) = rand() & 0x01FFFFC0; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b1 << 25) | (0b000010 << 0); + + ptr++; + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + } + else if(type == 3) { //TLBR + (*ptr) = rand() & 0x01FFFFC0; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b1 << 25) | (0b000001 << 0); + } + else if(type == 4) { //TLBP + (*ptr) = rand() & 0x01FFFFC0; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b1 << 25) | (0b001000 << 0); + } + + ptr++; + } + + for(int i=0; i<5; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } +} + +//------------------------------------------------------------------------------ Index: trunk/sim/tester/main_linux.cpp =================================================================== --- trunk/sim/tester/main_linux.cpp (nonexistent) +++ trunk/sim/tester/main_linux.cpp (revision 2) @@ -0,0 +1,444 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "shared_mem.h" + +//------------------------------------------------------------------------------ + +volatile shared_mem_t *shared_ptr = NULL; + +//------------------------------------------------------------------------------ + +//128MB +#define MAX_MEMORY 0x8000000 +#define RESET_VECTOR 0x1FC00000 + +int main(int argc, char **argv) { + + if(argc != 2) { + printf("Error: missing argument: path to vmlinux.bin file !\n"); + return -1; + } + + int int_ret; + + //open file with truncate + FILE *fp = fopen("shared_mem.dat", "wb"); + if(fp == NULL) { + perror("Can not truncate file shared_mem.dat"); + return -1; + } + uint8 *buf = new uint8[sizeof(shared_mem_t)]; + memset(buf, 0, sizeof(shared_mem_t)); + + int_ret = fwrite(buf, sizeof(shared_mem_t), 1, fp); + delete buf; + if(int_ret != 1) { + perror("Can not zero-fill file shared_mem.dat"); + fclose(fp); + return -2; + } + fclose(fp); + + //-------------------------------------------------------------------------- + + //map shared memory + int fd = open("./shared_mem.dat", O_RDWR, S_IRUSR | S_IWUSR); + + if(fd == -1) { + perror("open() failed for shared_mem.dat"); + return -3; + } + + shared_ptr = (shared_mem_t *)mmap(NULL, sizeof(shared_mem_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if(shared_ptr == MAP_FAILED) { + perror("mmap() failed"); + close(fd); + return -4; + } + + //-------------------------------------------------------------------------- + + srand(0); + + //---------------------------------------------------------------------- + memset((void *)shared_ptr, 0, sizeof(shared_mem_t)); + + //load linux kernel binary from address 0 + FILE *kernel_fp = fopen(argv[1], "rb"); + if(kernel_fp == NULL) { + printf("Error: can not open file: %s\n", argv[1]); + return -1; + } + uint8 *kernel_ptr = (uint8 *)shared_ptr->mem.bytes; + while(true) { + int_ret = fread(kernel_ptr, 1, 8192, kernel_fp); + if(int_ret == 0) break; + kernel_ptr += int_ret; + } + fclose(kernel_fp); + + printf("loaded linux kernel size: %d bytes.\n", (kernel_ptr - shared_ptr->mem.bytes)); + + //---------------------------------------------------------------------- + + uint32 *reset_ptr = (uint32 *)shared_ptr->reset_vector; + + reset_ptr[0] = (0b000000 << 26) | (0 << 21) | (1 << 16) | (1 << 11) | (0b00000 << 6) | (0b100100); //AND R1,R0,R1 -- clear R1 + reset_ptr[1] = (0b001111 << 26) | (0 << 21) | (1 << 16) | 0x8000; //LUI R1,0x8000 + reset_ptr[2] = (0b001101 << 26) | (1 << 21) | (1 << 16) | 0x0400; //ORI R1,R1,0x400 + reset_ptr[3] = (0b000000 << 26) | (1 << 21) | (0 << 16) | (0 << 11) | (0 << 6) | (0b001000); //JR R1 + reset_ptr[4] = 0; //NOP + + shared_ptr->check_at_event = 10000; + + //---------------------------------------------------------------------- + + FILE *early_console_fp = fopen("early_console.txt", "wb"); + FILE *jtag_console_fp = fopen("jtag_console.txt", "wb"); + + //---------------------------------------------------------------------- + + int master_fd = 0, slave_fd = 0; + char slave_name[256]; + memset(slave_name, 0, sizeof(slave_name)); + + int_ret = openpty(&master_fd, &slave_fd, slave_name, NULL, NULL); + if(int_ret != 0) { + printf("Can not openpty().\n"); + return -1; + } + printf("slave pty: %s\n", slave_name); + + //---------------------------------------------------------------------- + + pid_t proc_vmips = fork(); + if(proc_vmips == 0) { + system("cd ./../vmips && ./main_linux > ./vmips_output.txt"); + return 0; + } + + pid_t proc_ao = fork(); + if(proc_ao == 0) { + system("cd ./../aoR3000 && ./obj_dir/VaoR3000 > ./ao_output.txt"); + return 0; + } + + //---------------------------------------------------------------------- + + printf("Waiting for init of vmips..."); fflush(stdout); + shared_ptr->proc_vmips.initialize_do = true; + + while(shared_ptr->proc_vmips.initialize_do) usleep(1); + printf("done\n"); + + printf("Waiting for init of aoR3000..."); fflush(stdout); + shared_ptr->proc_ao.initialize_do = true; + + while(shared_ptr->proc_ao.initialize_do) usleep(1); + printf("done\n"); + + //irq setup + shared_ptr->irq2_at_event = 0; + shared_ptr->irq3_at_event = 0xFFFFFFFF; + + //jtag data + bool jtag_read_irq_enable = false; + bool jtag_write_irq_enable = false; + + uint64 loop = 0; + + struct pollfd master_poll; + memset(&master_poll, 0, sizeof(master_poll)); + master_poll.fd = master_fd; + master_poll.events = POLLIN; + + std::deque jtag_deque; + + while(true) { + loop++; + if((loop % 100000000) == 0) printf("loop: %lld, vmips: %d ao: %d\n", loop, shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter); + + //---------------------------------------------------------------------- + + if((loop % 10000) == 0) { + int_ret = poll(&master_poll, 1, 0); + if(int_ret < 0) { + printf("Error: poll() failed.\n"); + shared_ptr->test_finished = true; + return -1; + } + + if(int_ret == 1 && (master_poll.revents & POLLIN)) { + char read_char = 0; + int_ret = read(master_fd, &read_char, 1); + + jtag_deque.push_back(read_char); + printf("read: %c\n", read_char); + } + } + + //---------------------------------------------------------------------- + + uint32 retry = 0; + while(shared_ptr->proc_vmips.check_do || shared_ptr->proc_ao.check_do) { + if(shared_ptr->proc_vmips.check_do && shared_ptr->proc_ao.check_do) { + + //printf("check[%d, %d]\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter); + + if(shared_ptr->proc_vmips.report.counter != shared_ptr->proc_ao.report.counter) { + printf("check counter mismatch: vmips: %d != %d\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter); + getchar(); + } + + shared_ptr->check_at_event += 10000; + + if(jtag_write_irq_enable == false) { + if(jtag_deque.empty()) { + if(shared_ptr->irq3_at_event != 0xFFFFFFFF) { + printf("jtag: disabling irq\n"); + shared_ptr->irq3_at_event = 0xFFFFFFFF; + } + } + else { + shared_ptr->irq3_at_event = shared_ptr->proc_vmips.report.counter + 10; + printf("jtag: enabling irq\n"); + } + } + + shared_ptr->proc_vmips.check_do = false; + shared_ptr->proc_ao.check_do = false; + } + else { + usleep(10); + retry++; + + if(retry == 500000) { + printf("vmips: %08x %01x %08x\n", shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data); + printf("ao: %08x %01x %08x\n", shared_ptr->proc_ao.write_address, shared_ptr->proc_ao.write_byteenable, shared_ptr->proc_ao.write_data); + + printf("\nTEST FAILED. WAITING FOR CHECK [vmips: %d, ao: %d]\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter); + shared_ptr->test_finished = true; + return -1; + } + } + } + + retry = 0; + while(shared_ptr->proc_vmips.write_do || shared_ptr->proc_ao.write_do) { + if(shared_ptr->proc_vmips.write_do && shared_ptr->proc_ao.write_do) { + if( shared_ptr->proc_vmips.write_address == shared_ptr->proc_ao.write_address && + shared_ptr->proc_vmips.write_byteenable == shared_ptr->proc_ao.write_byteenable && + shared_ptr->proc_vmips.write_data == shared_ptr->proc_ao.write_data) + { + //printf("write[%d]: %08x %01x %08x\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data); + + if(shared_ptr->proc_vmips.report.counter != shared_ptr->proc_ao.report.counter) { + printf("write instruction counter mismatch: vmips: %d != %d\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter); + getchar(); + } + + uint32 address = shared_ptr->proc_vmips.write_address; + uint32 byteena = shared_ptr->proc_vmips.write_byteenable; + uint32 value = shared_ptr->proc_vmips.write_data; + + if(address < MAX_MEMORY) { + for(uint32 i=0; i<4; i++) { + if(byteena & 1) shared_ptr->mem.bytes[shared_ptr->proc_vmips.write_address + i] = value & 0xFF; + value >>= 8; + byteena >>= 1; + } + } + else if(address >= RESET_VECTOR && address < RESET_VECTOR + sizeof(shared_ptr->reset_vector)) { + for(uint32 i=0; i<4; i++) { + uint8 *vector = (uint8 *)shared_ptr->reset_vector; + if(byteena & 1) vector[address - RESET_VECTOR + i] = value & 0xFF; + value >>= 8; + byteena >>= 1; + } + } + else if(address == 0x1FFFFFFC && byteena == 8) { + fprintf(early_console_fp, "%c", (value >> 24) & 0xFF); + fflush(early_console_fp); + } + else if(address == 0x1FFFFFF8 && byteena == 1) { + printf("timer irq ack\n"); + shared_ptr->irq2_at_event = shared_ptr->proc_vmips.report.counter + 500000; + } + else if(address == 0x1FFFFFF0 && byteena == 0xF) { + printf("write jtaguart data: %08x\n", value); + + char byte_to_write = (value & 0xFF); + + fprintf(jtag_console_fp, "%c", byte_to_write); + fflush(jtag_console_fp); + + write(master_fd, &byte_to_write, 1); + } + else if(address == 0x1FFFFFF4 && byteena == 0xF) { + printf("write jtaguart control: %08x\n", value); + + jtag_read_irq_enable = (value & 0x1)? true : false; + jtag_write_irq_enable = (value & 0x2)? true : false; + + if(jtag_write_irq_enable || (jtag_read_irq_enable && jtag_deque.size() > 0)) shared_ptr->irq3_at_event = shared_ptr->proc_vmips.report.counter + 10; + else shared_ptr->irq3_at_event = 0xFFFFFFFF; + } + else { + printf("vmips: %08x %01x %08x\n", shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data); + printf("ao: %08x %01x %08x\n", shared_ptr->proc_ao.write_address, shared_ptr->proc_ao.write_byteenable, shared_ptr->proc_ao.write_data); + + printf("\nTEST FAILED. MEM WRITE TO UNKNOWN.\n"); + shared_ptr->test_finished = true; + return -1; + } + + shared_ptr->proc_vmips.write_do = false; + shared_ptr->proc_ao.write_do = false; + } + else { + printf("vmips: %08x %01x %08x\n", shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data); + printf("ao: %08x %01x %08x\n", shared_ptr->proc_ao.write_address, shared_ptr->proc_ao.write_byteenable, shared_ptr->proc_ao.write_data); + + printf("\nTEST FAILED. MEM WRITE DIFF [%d].\n", shared_ptr->proc_vmips.report.counter); + shared_ptr->test_finished = true; + return -1; + } + } + else { + usleep(10); + retry++; + + if(retry == 500000) { + printf("vmips: %08x %01x %08x\n", shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data); + printf("ao: %08x %01x %08x\n", shared_ptr->proc_ao.write_address, shared_ptr->proc_ao.write_byteenable, shared_ptr->proc_ao.write_data); + + printf("\nTEST FAILED. WAITING FOR WRITE [vmips: %d, ao: %d]\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter); + shared_ptr->test_finished = true; + return -1; + } + } + } + + retry = 0; + while(shared_ptr->proc_vmips.read_do || shared_ptr->proc_ao.read_do) { + if(shared_ptr->proc_vmips.read_do && shared_ptr->proc_ao.read_do) { + if( shared_ptr->proc_vmips.read_address == shared_ptr->proc_ao.read_address && + shared_ptr->proc_vmips.read_byteenable == shared_ptr->proc_ao.read_byteenable) + { + printf("read: %08x %01x\n", shared_ptr->proc_vmips.read_address, shared_ptr->proc_vmips.read_byteenable); + + if(shared_ptr->proc_vmips.report.counter != shared_ptr->proc_ao.report.counter) { + printf("read instruction counter mismatch: vmips: %d != %d\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter); + getchar(); + } + + uint32 address = shared_ptr->proc_vmips.read_address; + uint32 byteena = shared_ptr->proc_vmips.read_byteenable; + uint32 value = 0xFFFFFFFF; + + if(address == 0x1FFFFFF0 && byteena == 0xF) { + if(jtag_deque.empty()) value = 0; + else { + value = + (jtag_deque.front() & 0xFF) | + (1 << 15) | + (((jtag_deque.size() - 1) & 0xFFFF) << 16); + + jtag_deque.pop_front(); + } + + if(jtag_write_irq_enable == false) { + if(jtag_deque.empty()) { + shared_ptr->irq3_at_event = 0xFFFFFFFF; + printf("jtag: disabling irq\n"); + } + else { + shared_ptr->irq3_at_event = shared_ptr->proc_vmips.report.counter + 10; + printf("jtag: enabling irq\n"); + } + } + + printf("read jtaguart data: %08x\n", value); + } + else if(address == 0x1FFFFFF4 && byteena == 0xF) { + value = + ((jtag_read_irq_enable)? 1 : 0) | + ((jtag_write_irq_enable)? 2 : 0) | + (((jtag_deque.empty())? 0 : 1) << 8) | //read irq pending + (1 << 9) | //write irq pending + (1 << 10) | //active + (0xFF << 16); //spaces left in write fifo + + printf("read jtaguart control: %08x\n", value); + } + else + { + printf("vmips: %08x %01x\n", shared_ptr->proc_vmips.read_address, shared_ptr->proc_vmips.read_byteenable); + printf("ao: %08x %01x\n", shared_ptr->proc_ao.read_address, shared_ptr->proc_ao.read_byteenable); + + printf("\nRUN FAILED. MEM READ FROM UNKNOWN.\n"); + shared_ptr->test_finished = true; + return -1; + + } + + shared_ptr->proc_vmips.read_data = value; + shared_ptr->proc_ao.read_data = value; + + shared_ptr->proc_vmips.read_do = false; + shared_ptr->proc_ao.read_do = false; + } + else { + printf("vmips: %08x %01x\n", shared_ptr->proc_vmips.read_address, shared_ptr->proc_vmips.read_byteenable, shared_ptr->proc_vmips.read_data); + printf("ao: %08x %01x\n", shared_ptr->proc_ao.read_address, shared_ptr->proc_ao.read_byteenable, shared_ptr->proc_ao.read_data); + + printf("\nRUN FAILED. MEM READ DIFF.\n"); + shared_ptr->test_finished = true; + return -1; + } + } + else { + usleep(10); + retry++; + + if(retry == 500000) { + printf("vmips: %08x %01x\n", shared_ptr->proc_vmips.read_address, shared_ptr->proc_vmips.read_byteenable, shared_ptr->proc_vmips.read_data); + printf("ao: %08x %01x\n", shared_ptr->proc_ao.read_address, shared_ptr->proc_ao.read_byteenable, shared_ptr->proc_ao.read_data); + + printf("\nTEST FAILED. WAITING FOR READ.\n"); + shared_ptr->test_finished = true; + return -1; + } + } + } + } + + //---------------------------------------------------------------------- wait for process end + waitpid(proc_vmips, NULL, 0); + waitpid(proc_ao, NULL, 0); + + return 0; +} + +//------------------------------------------------------------------------------ Index: trunk/sim/tester/test_arithmetic_logic.cpp =================================================================== --- trunk/sim/tester/test_arithmetic_logic.cpp (nonexistent) +++ trunk/sim/tester/test_arithmetic_logic.cpp (revision 2) @@ -0,0 +1,159 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include "tests.h" + +//------------------------------------------------------------------------------ + +void put_instruction(uint32 *ptr, bool &was_mul, bool &was_div) { + + uint32 instr_special[] = { + 0b000000, //SSL + 0b000010, //SRL + 0b000011, //SRA + 0b000100, //SLLV + 0b000110, //SRLV + 0b000111, //SRAV + 0b010000, //MFHI + 0b010001, //MTHI i + 0b010010, //MFLO + 0b010011, //MTLO i + 0b011000, //MULT i + 0b011001, //MULTU i + 0b011010, //DIV + 0b011011, //DIVU + 0b100000, //ADD e + 0b100001, //ADDU + 0b100010, //SUB e + 0b100011, //SUBU + 0b100100, //AND + 0b100101, //OR + 0b100110, //XOR + 0b100111, //NOR + 0b101010, //SLT + 0b101011, //SLTU + }; + uint32 instr_imm[] = { + 0b001000, //ADDI e + 0b001001, //ADDIU + 0b001010, //SLTI + 0b001011, //SLTIU + 0b001100, //ANDI + 0b001101, //ORI + 0b001110, //XORI + 0b001111, //LUI + }; + + while(true) { + uint32 instr = rand() & 0x03FFFFFF; + uint32 count = (sizeof(instr_special) + sizeof(instr_imm)) / sizeof(uint32); + uint32 index = rand() % count; + + //sequences not generated: + //mul* -> mt*; mul* -> div* + //div* -> mt*; div* -> mul* + //mul* and div* finish after mf* + + if(was_div == false && (index == 10 || index == 11)) was_mul = true; + if(was_mul == false && (index == 12 || index == 13)) was_div = true; + if(was_div && (index == 10 || index == 11)) continue; + if(was_mul && (index == 12 || index == 13)) continue; + if((was_div || was_mul) && (index == 7 || index == 9)) continue; + if((index == 6 || index == 8)) was_div = was_mul = false; + + if(index >= (sizeof(instr_special) / sizeof(uint32))) { + index -= (sizeof(instr_special) / sizeof(uint32)); + instr |= instr_imm[index] << 26; + + if(index == 7 || index == 9 || index == 10 || index == 11) if((rand() % 3) != 0) instr &= 0xFFFF07FF; + } + else { + instr &= 0xFFFFFFC0; + instr |= instr_special[index]; + } + (*ptr) = instr; + break; + } +} + +void arith_logic_till_exc_init(tst_t *tst, shared_mem_t *shared_ptr) { + + for(int i=1; i<32; i++) shared_ptr->initial.reg[i-1] = rand_uint32(); + + shared_ptr->initial.pc = 0xA0001000; + + //tlb left zero + + shared_ptr->initial.index_p = rand() & 0x1; + shared_ptr->initial.index_index = rand() & 0x3F; + + shared_ptr->initial.random = rand() & 0x3F; + + shared_ptr->initial.entrylo_pfn = rand() & 0xFFFFF; + shared_ptr->initial.entrylo_n = rand() & 0x1; + shared_ptr->initial.entrylo_d = rand() & 0x1; + shared_ptr->initial.entrylo_v = rand() & 0x1; + shared_ptr->initial.entrylo_g = rand() & 0x1; + + shared_ptr->initial.context_ptebase = rand() & 0x7FF; + shared_ptr->initial.context_badvpn = rand() & 0x7FFFF; + + shared_ptr->initial.bad_vaddr = rand_uint32(); + + shared_ptr->initial.entryhi_vpn = rand() & 0xFFFFF; + shared_ptr->initial.entryhi_asid = rand() & 0x3F; + + shared_ptr->initial.sr_cp_usable = rand() & 0xF; + shared_ptr->initial.sr_rev_endian = rand() & 0x1; + shared_ptr->initial.sr_bootstrap_vec = rand() & 0x1; + shared_ptr->initial.sr_tlb_shutdown = rand() & 0x1; + shared_ptr->initial.sr_parity_err = rand() & 0x1; + shared_ptr->initial.sr_cache_miss = rand() & 0x1; + shared_ptr->initial.sr_parity_zero = rand() & 0x1; + shared_ptr->initial.sr_switch_cache = rand() & 0x1; + shared_ptr->initial.sr_isolate_cache = rand() & 0x1; + shared_ptr->initial.sr_irq_mask = rand() & 0xFF; + shared_ptr->initial.sr_ku_ie = rand() & 0x3F; + + shared_ptr->initial.cause_branch_delay = rand() & 0x1; + shared_ptr->initial.cause_cp_error = rand() & 0x3; + shared_ptr->initial.cause_irq_pending = 0; + shared_ptr->initial.cause_exc_code = rand() & 0x1F; + + shared_ptr->initial.epc = rand_uint32(); + + // + shared_ptr->irq2_at_event = 0xFFFFFFFF; + shared_ptr->irq3_at_event = 0xFFFFFFFF; + + // + bool was_mul = false; + bool was_div = false; + + // + uint32 *ptr = &shared_ptr->mem.ints[(shared_ptr->initial.pc & 0x1FFFFFFF) / 4]; + for(int i=0; i<5; i++) { + put_instruction(ptr, was_mul, was_div); + ptr++; + } + + //finish with SYSCALL or BREAK + (*ptr) = rand() & 0x03FFFFC0; + if(rand() % 2) (*ptr) |= 0b001100; + else (*ptr) |= 0b001101; +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ Index: trunk/sim/tester/tests.h =================================================================== --- trunk/sim/tester/tests.h (nonexistent) +++ trunk/sim/tester/tests.h (revision 2) @@ -0,0 +1,247 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#ifndef __TESTS_H +#define __TESTS_H + +#include "shared_mem.h" + +//------------------------------------------------------------------------------ + +struct tst_t; + +typedef void (*func_init) (tst_t *tst, shared_mem_t *shared_ptr); + + +struct tst_t { + func_init init; +}; + +//------------------------------------------------------------------------------ + +uint32 rand_uint32(); + +//------------------------------------------------------------------------------ + +void arith_logic_till_exc_init (tst_t *tst, shared_mem_t *shared_ptr); +void exception_till_exc_init (tst_t *tst, shared_mem_t *shared_ptr); +void tlb_commands_till_exc_init (tst_t *tst, shared_mem_t *shared_ptr); +void branch_till_exc_init (tst_t *tst, shared_mem_t *shared_ptr); +void data_till_exc_init (tst_t *tst, shared_mem_t *shared_ptr); +void interrupt_till_exc_init (tst_t *tst, shared_mem_t *shared_ptr); +void tlb_fetch_till_exc_init (tst_t *tst, shared_mem_t *shared_ptr); +void tlb_data_till_exc_init (tst_t *tst, shared_mem_t *shared_ptr); + +//------------------------------------------------------------------------------ + +/* + +000000 . SPECIAL + [5:0] + 000000 SLL + 000001 + 000010 SRL + 000011 SRA + 000100 SLLV + 000101 + 000110 SRLV + 000111 SRAV + + 001000 JR + 001001 JALR + 001010 + 001011 + 001100 SYSCALL + 001101 BREAK + 001110 + 001111 + + 010000 MFHI + 010001 MTHI + 010010 MFLO + 010011 MTLO + 010100 + 010101 + 010110 + 010111 + + 011000 MULT + 011001 MULTU + 011010 DIV + 011011 DIVU + 011100 + 011101 + 011110 + 011111 + + 100000 ADD + 100001 ADDU + 100010 SUB + 100011 SUBU + 100100 AND + 100101 OR + 100110 XOR + 100111 NOR + + 101000 + 101001 + 101010 SLT + 101011 SLTU + 101100 + 101101 + 101110 + 101111 + + 110000 + 110001 + 110010 + 110011 + 110100 + 110101 + 110110 + 110111 + + 111000 + 111001 + 111010 + 111011 + 111100 + 111101 + 111110 + 111111 +000001 . + [20:16] + 00000 BLTZ + 00001 BGEZ + 10000 BLTZAL + 10001 BGEZAL + +000010 J +000011 JAL +000100 BEQ +000101 BNE +000110 BLEZ rt must be 0 +000111 BGTZ rt must be 0 + +001000 ADDI +001001 ADDIU +001010 SLTI +001011 SLTIU +001100 ANDI +001101 ORI +001110 XORI +001111 LUI + +010000 . +010001 . +010010 . +010011 . + [25:21] + 00000 MFCz + 00001 + 00010 CFCz + 00011 + 00100 MTCz + 00101 + 00110 CTCz + 00111 + 01000 . BC0 + [20:16] + 00000 BC0F + 00001 BC0T + 00010 ign + 00011 ign + other Reserved Instruction + 01001 + 01010 + 01011 + 01100 + 01101 + 01110 + 01111 + 10000 . + 10001 . + 10010 . + 10011 . + 10100 . + 10101 . + 10110 . + 10111 . + 11000 . + 11001 . + 11010 . + 11011 . + 11100 . + 11101 . + 11110 . + 11111 . + COPz + [5:0] for COP0 + 000001 TLBR + 000010 TLBWI + 000110 TLBWR + 001000 TLBP + 010000 RFE + other Reserved Instruction +010100 +010101 +010110 +010111 + +011000 +011001 +011010 +011011 +011100 +011101 +011110 +011111 + +100000 LB +100001 LH +100010 LWL +100011 LW +100100 LBU +100101 LHU +100110 LWR +100111 + +101000 SB +101001 SH +101010 SWL +101011 SW +101100 +101101 +101110 SWR +101111 + +110000 . +110001 . +110010 . +110011 . + LWCz + +110100 +110101 +110110 +110111 + +111000 . +111001 . +111010 . +111011 . + SWCz + +111100 +111101 +111110 +111111 +*/ + +//------------------------------------------------------------------------------ + +#endif //__TESTS_H Index: trunk/sim/tester/test_data.cpp =================================================================== --- trunk/sim/tester/test_data.cpp (nonexistent) +++ trunk/sim/tester/test_data.cpp (revision 2) @@ -0,0 +1,167 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include "tests.h" + +//------------------------------------------------------------------------------ + +void data_till_exc_init(tst_t *tst, shared_mem_t *shared_ptr) { + + for(int i=1; i<32; i++) shared_ptr->initial.reg[i-1] = rand_uint32(); + + shared_ptr->initial.pc = 0xA0001000; + + //tlb left zero + + shared_ptr->initial.index_p = rand() & 0x1; + shared_ptr->initial.index_index = rand() & 0x3F; + + shared_ptr->initial.random = rand() & 0x3F; + + shared_ptr->initial.entrylo_pfn = rand() & 0xFFFFF; + shared_ptr->initial.entrylo_n = rand() & 0x1; + shared_ptr->initial.entrylo_d = rand() & 0x1; + shared_ptr->initial.entrylo_v = rand() & 0x1; + shared_ptr->initial.entrylo_g = rand() & 0x1; + + shared_ptr->initial.context_ptebase = rand() & 0x7FF; + shared_ptr->initial.context_badvpn = rand() & 0x7FFFF; + + shared_ptr->initial.bad_vaddr = rand_uint32(); + + shared_ptr->initial.entryhi_vpn = rand() & 0xFFFFF; + shared_ptr->initial.entryhi_asid = rand() & 0x3F; + + shared_ptr->initial.sr_cp_usable = rand() & 0xF; + shared_ptr->initial.sr_rev_endian = rand() & 0x1; + shared_ptr->initial.sr_bootstrap_vec = rand() & 0x1; + shared_ptr->initial.sr_tlb_shutdown = rand() & 0x1; + shared_ptr->initial.sr_parity_err = rand() & 0x1; + shared_ptr->initial.sr_cache_miss = rand() & 0x1; + shared_ptr->initial.sr_parity_zero = rand() & 0x1; + shared_ptr->initial.sr_switch_cache = 0; //rand() & 0x1; + shared_ptr->initial.sr_isolate_cache = 0; //rand() & 0x1; + shared_ptr->initial.sr_irq_mask = rand() & 0xFF; + shared_ptr->initial.sr_ku_ie = rand() & 0x3F; + + shared_ptr->initial.cause_branch_delay = rand() & 0x1; + shared_ptr->initial.cause_cp_error = rand() & 0x3; + shared_ptr->initial.cause_irq_pending = 0; + shared_ptr->initial.cause_exc_code = rand() & 0x1F; + + shared_ptr->initial.epc = rand_uint32(); + + // + shared_ptr->irq2_at_event = 0xFFFFFFFF; + shared_ptr->irq3_at_event = 0xFFFFFFFF; + + // + uint32 *ptr = &shared_ptr->mem.ints[(shared_ptr->initial.pc & 0x1FFFFFFF) / 4]; + + bool cacheable = rand() % 2; + uint32 base = (cacheable)? 0x81000000 : 0xA1000000; + uint32 scope = (cacheable)? 10 : 65536; + + uint32 loading_reg = 0; + + shared_ptr->initial.reg[0] = base; + + for(int operation=0; operation<100; operation++) { + + uint32 type = rand() % 12; + + uint32 storing_reg = 2 + (rand() % 30); + while(storing_reg == loading_reg) storing_reg = 2 + (rand() % 30); + + if(type == 0) { //LB + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100000 << 26) | (1 << 21) | (loading_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 1) { //LBU + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100100 << 26) | (1 << 21) | (loading_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 2) { //LH + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100001 << 26) | (1 << 21) | (loading_reg << 16) | ((rand() % scope) & 0xFFFE) | (((rand() % 5) == 0)? 1 : 0); + ptr++; + } + else if(type == 3) { //LHU + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100101 << 26) | (1 << 21) | (loading_reg << 16) | ((rand() % scope) & 0xFFFE) | (((rand() % 5) == 0)? 1 : 0); + ptr++; + } + else if(type == 4) { //LW + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100011 << 26) | (1 << 21) | (loading_reg << 16) | ((rand() % scope) & 0xFFFC) | (((rand() % 5) == 0)? (1 + (rand() % 3)) : 0); + ptr++; + } + else if(type == 5) { //LWL + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100010 << 26) | (1 << 21) | (loading_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 6) { //LWR + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100110 << 26) | (1 << 21) | (loading_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 7) { //SB + loading_reg = 0; + + (*ptr) = (0b101000 << 26) | (1 << 21) | (storing_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 8) { //SH + loading_reg = 0; + + (*ptr) = (0b101001 << 26) | (1 << 21) | (storing_reg << 16) | ((rand() % scope) & 0xFFFE) | (((rand() % 5) == 0)? 1 : 0); + ptr++; + } + else if(type == 9) { //SW + loading_reg = 0; + + (*ptr) = (0b101011 << 26) | (1 << 21) | (storing_reg << 16) | ((rand() % scope) & 0xFFFC) | (((rand() % 5) == 0)? (1 + (rand() % 3)) : 0); + ptr++; + } + else if(type == 10) { //SWL + loading_reg = 0; + + (*ptr) = (0b101010 << 26) | (1 << 21) | (storing_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 11) { //SWR + loading_reg = 0; + + (*ptr) = (0b101110 << 26) | (1 << 21) | (storing_reg << 16) | (rand() % scope); + ptr++; + } + } + + base &= 0x1FFFFFFF; + for(uint32 i=base - 32768; imem.ints[i/4] = rand_uint32(); + } + + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; +} + +//------------------------------------------------------------------------------ Index: trunk/sim/tester/test_tlb_data.cpp =================================================================== --- trunk/sim/tester/test_tlb_data.cpp (nonexistent) +++ trunk/sim/tester/test_tlb_data.cpp (revision 2) @@ -0,0 +1,187 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include "tests.h" + +//------------------------------------------------------------------------------ + +void tlb_data_till_exc_init(tst_t *tst, shared_mem_t *shared_ptr) { + + for(int i=1; i<32; i++) shared_ptr->initial.reg[i-1] = rand_uint32(); + + shared_ptr->initial.pc = (rand() % 2)? 0x00091000 : 0xF0001000; + + shared_ptr->initial.index_p = rand() & 0x1; + shared_ptr->initial.index_index = rand() & 0x3F; + + shared_ptr->initial.random = rand() & 0x3F; + + shared_ptr->initial.entrylo_pfn = rand() & 0xFFFFF; + shared_ptr->initial.entrylo_n = rand() & 0x1; + shared_ptr->initial.entrylo_d = rand() & 0x1; + shared_ptr->initial.entrylo_v = rand() & 0x1; + shared_ptr->initial.entrylo_g = rand() & 0x1; + + shared_ptr->initial.context_ptebase = rand() & 0x7FF; + shared_ptr->initial.context_badvpn = rand() & 0x7FFFF; + + shared_ptr->initial.bad_vaddr = rand_uint32(); + + shared_ptr->initial.entryhi_vpn = rand() & 0xFFFFF; + shared_ptr->initial.entryhi_asid = rand() & 0x3F; + + shared_ptr->initial.sr_cp_usable = rand() & 0xF; + shared_ptr->initial.sr_rev_endian = rand() & 0x1; + shared_ptr->initial.sr_bootstrap_vec = rand() & 0x1; + shared_ptr->initial.sr_tlb_shutdown = rand() & 0x1; + shared_ptr->initial.sr_parity_err = rand() & 0x1; + shared_ptr->initial.sr_cache_miss = rand() & 0x1; + shared_ptr->initial.sr_parity_zero = rand() & 0x1; + shared_ptr->initial.sr_switch_cache = 0; //rand() & 0x1; + shared_ptr->initial.sr_isolate_cache = 0; //rand() & 0x1; + shared_ptr->initial.sr_irq_mask = rand() & 0xFF; + shared_ptr->initial.sr_ku_ie = rand() & 0x3F; + + shared_ptr->initial.cause_branch_delay = rand() & 0x1; + shared_ptr->initial.cause_cp_error = rand() & 0x3; + shared_ptr->initial.cause_irq_pending = 0; + shared_ptr->initial.cause_exc_code = rand() & 0x1F; + + shared_ptr->initial.epc = rand_uint32(); + + // + shared_ptr->irq2_at_event = 0xFFFFFFFF; + shared_ptr->irq3_at_event = 0xFFFFFFFF; + + //pc + uint32 vaddr_pc = shared_ptr->initial.pc; + uint32 paddr_pc = 0x5000; + + shared_ptr->initial.tlb[55].vpn = (vaddr_pc >> 12) & 0xFFFFF; + shared_ptr->initial.tlb[55].asid = ((rand() % 5) == 0)? (rand() % 0x1F) : shared_ptr->initial.entryhi_asid; + shared_ptr->initial.tlb[55].pfn = (paddr_pc >> 12) & 0xFFFFF; + shared_ptr->initial.tlb[55].n = rand() % 2; + shared_ptr->initial.tlb[55].d = rand() % 2; + shared_ptr->initial.tlb[55].v = rand() % 2; + shared_ptr->initial.tlb[55].g = rand() % 2; + + uint32 *ptr = &shared_ptr->mem.ints[paddr_pc / 4]; + + //data + uint32 vaddr_data = (rand() % 2)? 0x000C1000 : 0xF01C1000; + uint32 paddr_data = 0x000A0000; + + for(uint32 i=0; i<14; i++) { //14 * 4096 - virtual memory + shared_ptr->initial.tlb[5+i].vpn = ((vaddr_data - ((8-i)*4096)) >> 12) & 0xFFFFF; + shared_ptr->initial.tlb[5+i].asid = ((rand() % 5) == 0)? (rand() % 0x1F) : shared_ptr->initial.entryhi_asid; + shared_ptr->initial.tlb[5+i].pfn = ((paddr_data - ((8-i)*4096)) >> 12) & 0xFFFFF; + shared_ptr->initial.tlb[5+i].n = rand() % 2; + shared_ptr->initial.tlb[5+i].d = rand() % 2; + shared_ptr->initial.tlb[5+i].v = rand() % 2; + shared_ptr->initial.tlb[5+i].g = rand() % 2; + } + + uint32 scope = 65536; + + uint32 loading_reg = 0; + + shared_ptr->initial.reg[0] = vaddr_data; + + for(int operation=0; operation<100; operation++) { + + uint32 type = rand() % 12; + + uint32 storing_reg = 2 + (rand() % 30); + while(storing_reg == loading_reg) storing_reg = 2 + (rand() % 30); + + if(type == 0) { //LB + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100000 << 26) | (1 << 21) | (loading_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 1) { //LBU + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100100 << 26) | (1 << 21) | (loading_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 2) { //LH + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100001 << 26) | (1 << 21) | (loading_reg << 16) | ((rand() % scope) & 0xFFFE) | (((rand() % 5) == 0)? 1 : 0); + ptr++; + } + else if(type == 3) { //LHU + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100101 << 26) | (1 << 21) | (loading_reg << 16) | ((rand() % scope) & 0xFFFE) | (((rand() % 5) == 0)? 1 : 0); + ptr++; + } + else if(type == 4) { //LW + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100011 << 26) | (1 << 21) | (loading_reg << 16) | ((rand() % scope) & 0xFFFC) | (((rand() % 5) == 0)? (1 + (rand() % 3)) : 0); + ptr++; + } + else if(type == 5) { //LWL + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100010 << 26) | (1 << 21) | (loading_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 6) { //LWR + loading_reg = 2 + (rand() % 30); + + (*ptr) = (0b100110 << 26) | (1 << 21) | (loading_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 7) { //SB + loading_reg = 0; + + (*ptr) = (0b101000 << 26) | (1 << 21) | (storing_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 8) { //SH + loading_reg = 0; + + (*ptr) = (0b101001 << 26) | (1 << 21) | (storing_reg << 16) | ((rand() % scope) & 0xFFFE) | (((rand() % 5) == 0)? 1 : 0); + ptr++; + } + else if(type == 9) { //SW + loading_reg = 0; + + (*ptr) = (0b101011 << 26) | (1 << 21) | (storing_reg << 16) | ((rand() % scope) & 0xFFFC) | (((rand() % 5) == 0)? (1 + (rand() % 3)) : 0); + ptr++; + } + else if(type == 10) { //SWL + loading_reg = 0; + + (*ptr) = (0b101010 << 26) | (1 << 21) | (storing_reg << 16) | (rand() % scope); + ptr++; + } + else if(type == 11) { //SWR + loading_reg = 0; + + (*ptr) = (0b101110 << 26) | (1 << 21) | (storing_reg << 16) | (rand() % scope); + ptr++; + } + } + + for(uint32 i=paddr_data - 32768; imem.ints[i/4] = rand_uint32(); + } + + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; +} + +//------------------------------------------------------------------------------ Index: trunk/sim/tester/shared_mem.h =================================================================== --- trunk/sim/tester/shared_mem.h (nonexistent) +++ trunk/sim/tester/shared_mem.h (revision 2) @@ -0,0 +1,133 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#ifndef __SHARED_MEM_H +#define __SHARED_MEM_H + +//------------------------------------------------------------------------------ + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef unsigned long uint64; + +typedef char int8; +typedef short int16; +typedef int int32; +typedef long int64; + +//------------------------------------------------------------------------------ + +union memory_t { + uint8 bytes [134217728]; + uint16 shorts[67108864]; + uint32 ints [33554432]; +}; + +struct tlb_t { + uint32 vpn; + uint32 asid; + uint32 pfn; + uint32 n; + uint32 d; + uint32 v; + uint32 g; +}; + +struct processor_state_t { + uint32 reg[31]; + uint32 pc; + //lo, hi not compared + + tlb_t tlb[64]; + + uint32 index_p; + uint32 index_index; + + uint32 random; + + uint32 entrylo_pfn; + uint32 entrylo_n; + uint32 entrylo_d; + uint32 entrylo_v; + uint32 entrylo_g; + + uint32 context_ptebase; + uint32 context_badvpn; + + uint32 bad_vaddr; + + uint32 entryhi_vpn; + uint32 entryhi_asid; + + uint32 sr_cp_usable; + uint32 sr_rev_endian; + uint32 sr_bootstrap_vec; + uint32 sr_tlb_shutdown; + uint32 sr_parity_err; + uint32 sr_cache_miss; + uint32 sr_parity_zero; + uint32 sr_switch_cache; + uint32 sr_isolate_cache; + uint32 sr_irq_mask; + uint32 sr_ku_ie; + + uint32 cause_branch_delay; + uint32 cause_cp_error; + uint32 cause_irq_pending; + uint32 cause_exc_code; + + uint32 epc; +}; + +struct report_t { + uint32 counter; + uint32 exception; + processor_state_t state; +}; + +struct processor_t { + uint32 initialize_do; + + uint32 read_do; + uint32 read_address; + uint32 read_byteenable; + uint32 read_data; + + uint32 write_do; + uint32 write_address; + uint32 write_byteenable; + uint32 write_data; + + uint32 check_do; + + uint32 report_do; + report_t report; +}; + +struct shared_mem_t { + memory_t mem; + + uint32 reset_vector[1024]; + + processor_state_t initial; + + uint32 test_finished; + + uint32 irq2_at_event; + + uint32 irq3_at_event; + + uint32 check_at_event; + + processor_t proc_ao; + processor_t proc_vmips; +}; + +//------------------------------------------------------------------------------ + +#endif //__SHARED_MEM_H Index: trunk/sim/tester/test_tlb_fetch.cpp =================================================================== --- trunk/sim/tester/test_tlb_fetch.cpp (nonexistent) +++ trunk/sim/tester/test_tlb_fetch.cpp (revision 2) @@ -0,0 +1,106 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include "tests.h" + +//------------------------------------------------------------------------------ + +void tlb_fetch_till_exc_init(tst_t *tst, shared_mem_t *shared_ptr) { + + for(int i=1; i<32; i++) shared_ptr->initial.reg[i-1] = rand_uint32(); + + shared_ptr->initial.pc = (rand() % 2)? 0x00091000 : 0xF0001000; + + shared_ptr->initial.index_p = rand() & 0x1; + shared_ptr->initial.index_index = rand() & 0x3F; + + shared_ptr->initial.random = rand() & 0x3F; + + shared_ptr->initial.entrylo_pfn = rand() & 0xFFFFF; + shared_ptr->initial.entrylo_n = rand() & 0x1; + shared_ptr->initial.entrylo_d = rand() & 0x1; + shared_ptr->initial.entrylo_v = rand() & 0x1; + shared_ptr->initial.entrylo_g = rand() & 0x1; + + shared_ptr->initial.context_ptebase = rand() & 0x7FF; + shared_ptr->initial.context_badvpn = rand() & 0x7FFFF; + + shared_ptr->initial.bad_vaddr = rand_uint32(); + + shared_ptr->initial.entryhi_vpn = rand() & 0xFFFFF; + shared_ptr->initial.entryhi_asid = rand() & 0x3F; + + shared_ptr->initial.sr_cp_usable = rand() & 0xF; + shared_ptr->initial.sr_rev_endian = rand() & 0x1; + shared_ptr->initial.sr_bootstrap_vec = rand() & 0x1; + shared_ptr->initial.sr_tlb_shutdown = rand() & 0x1; + shared_ptr->initial.sr_parity_err = rand() & 0x1; + shared_ptr->initial.sr_cache_miss = rand() & 0x1; + shared_ptr->initial.sr_parity_zero = rand() & 0x1; + shared_ptr->initial.sr_switch_cache = 0; //rand() & 0x1; + shared_ptr->initial.sr_isolate_cache = 0; //rand() & 0x1; + shared_ptr->initial.sr_irq_mask = rand() & 0xFF; + shared_ptr->initial.sr_ku_ie = rand() & 0x3F; + + shared_ptr->initial.cause_branch_delay = rand() & 0x1; + shared_ptr->initial.cause_cp_error = rand() & 0x3; + shared_ptr->initial.cause_irq_pending = 0; + shared_ptr->initial.cause_exc_code = rand() & 0x1F; + + shared_ptr->initial.epc = rand_uint32(); + + // + uint32 vaddr_pc = shared_ptr->initial.pc; + uint32 paddr_pc = 0x5000; + + shared_ptr->initial.tlb[55].vpn = (vaddr_pc >> 12) & 0xFFFFF; + shared_ptr->initial.tlb[55].asid = ((rand() % 5) == 0)? (rand() % 0x1F) : shared_ptr->initial.entryhi_asid; + shared_ptr->initial.tlb[55].pfn = (paddr_pc >> 12) & 0xFFFFF; + shared_ptr->initial.tlb[55].n = rand() % 2; + shared_ptr->initial.tlb[55].d = rand() % 2; + shared_ptr->initial.tlb[55].v = rand() % 2; + shared_ptr->initial.tlb[55].g = rand() % 2; + + // + shared_ptr->initial.reg[0] = 5; + + // + shared_ptr->irq2_at_event = 0xFFFFFFFF; + shared_ptr->irq3_at_event = 0xFFFFFFFF; + + // + uint32 *ptr = &shared_ptr->mem.ints[paddr_pc / 4]; + + for(int i=0; i<10; i++) { + (*ptr) = 0; + ptr++; + } + + (*ptr) = (0b001000 << 26) | (0b00001 << 21) | (0b00001 << 16) | 0xFFFF; //SUB 1 from reg[0] (reg1) + ptr++; + + (*ptr) = (0b000100 << 26) | (0b00000 << 21) | (0b00001 << 16) | 2; //BEQ + ptr++; + + (*ptr) = 0; //delay slot + ptr++; + + (*ptr) = (0b000010 << 26) | ((vaddr_pc >> 2) & 0x3FFFFFF); //J back + ptr++; + + (*ptr) = 0; //delay slot + ptr++; + + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; +} + +//------------------------------------------------------------------------------ Index: trunk/sim/tester/main_tester.cpp =================================================================== --- trunk/sim/tester/main_tester.cpp (nonexistent) +++ trunk/sim/tester/main_tester.cpp (revision 2) @@ -0,0 +1,339 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "shared_mem.h" +#include "tests.h" + +//------------------------------------------------------------------------------ + +volatile shared_mem_t *shared_ptr = NULL; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +tst_t tst_instr_fetch_tlb_invalid_exc = { .init = NULL }; +tst_t tst_arith_logic_till_exc = { .init = arith_logic_till_exc_init }; +tst_t tst_exception_till_exc = { .init = exception_till_exc_init }; +tst_t tst_tlb_commands_till_exc = { .init = tlb_commands_till_exc_init}; +tst_t tst_branch_till_exc = { .init = branch_till_exc_init }; +tst_t tst_data_till_exc = { .init = data_till_exc_init }; +tst_t tst_interrupt_till_exc = { .init = interrupt_till_exc_init }; +tst_t tst_tlb_fetch_till_exc = { .init = tlb_fetch_till_exc_init }; +tst_t tst_tlb_data_till_exc = { .init = tlb_data_till_exc_init }; + +//------------------------------------------------------------------------------ + +tst_t *tst_current = &tst_tlb_data_till_exc; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +bool is_diff(volatile report_t *vmips, volatile report_t *ao) { + char buf[65536]; + memset(buf, 0, sizeof(buf)); + char *ptr = buf; + + bool diff; + bool show = false; + + ptr += sprintf(ptr, "name |d| vmips | ao \n"); + ptr += sprintf(ptr, "------------------------------------------\n"); + + diff = vmips->counter != ao->counter; show = show || diff; + ptr += sprintf(ptr, "counter |%c| %08x | %08x \n", (diff)? '*' : ' ', vmips->counter, ao->counter); + + diff = vmips->exception != ao->exception; show = show || diff; + ptr += sprintf(ptr, "exception |%c| %08x | %08x \n", (diff)? '*' : ' ', vmips->exception, ao->exception); + + for(int i=1; i<32; i++) { + diff = vmips->state.reg[i-1] != ao->state.reg[i-1]; show = show || diff; + ptr += sprintf(ptr, "reg[%02d] |%c| %08x | %08x \n", i, (diff)? '*' : ' ', vmips->state.reg[i-1], ao->state.reg[i-1]); + } + + diff = vmips->state.pc != ao->state.pc; show = show || diff; + ptr += sprintf(ptr, "pc |%c| %08x | %08x \n", (diff)? '*' : ' ', vmips->state.pc, ao->state.pc); + + //not comapred: diff = vmips->state.lo != ao->state.lo; show = show || diff; + //not comapred: ptr += sprintf(ptr, "lo |%c| %08x | %08x \n", (diff)? '*' : ' ', vmips->state.lo, ao->state.lo); + + //not comapred: diff = vmips->state.hi != ao->state.hi; show = show || diff; + //not comapred: ptr += sprintf(ptr, "hi |%c| %08x | %08x \n", (diff)? '*' : ' ', vmips->state.hi, ao->state.hi); + + diff = vmips->state.index_p != ao->state.index_p; show = show || diff; + ptr += sprintf(ptr, "index_p |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.index_p, ao->state.index_p); + + diff = vmips->state.index_index != ao->state.index_index; show = show || diff; + ptr += sprintf(ptr, "index_index |%c| %02x | %02x \n", (diff)? '*' : ' ', vmips->state.index_index, ao->state.index_index); + + diff = vmips->state.random != ao->state.random; show = show || diff; + ptr += sprintf(ptr, "random |%c| %02x | %02x \n", (diff)? '*' : ' ', vmips->state.random, ao->state.random); + + diff = vmips->state.entrylo_pfn != ao->state.entrylo_pfn; show = show || diff; + ptr += sprintf(ptr, "entrylo_pfn |%c| %05x | %05x \n", (diff)? '*' : ' ', vmips->state.entrylo_pfn, ao->state.entrylo_pfn); + + diff = vmips->state.entrylo_n != ao->state.entrylo_n; show = show || diff; + ptr += sprintf(ptr, "entrylo_n |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.entrylo_n, ao->state.entrylo_n); + + diff = vmips->state.entrylo_d != ao->state.entrylo_d; show = show || diff; + ptr += sprintf(ptr, "entrylo_d |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.entrylo_d, ao->state.entrylo_d); + + diff = vmips->state.entrylo_v != ao->state.entrylo_v; show = show || diff; + ptr += sprintf(ptr, "entrylo_v |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.entrylo_v, ao->state.entrylo_v); + + diff = vmips->state.entrylo_g != ao->state.entrylo_g; show = show || diff; + ptr += sprintf(ptr, "entrylo_g |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.entrylo_g, ao->state.entrylo_g); + + diff = vmips->state.context_ptebase != ao->state.context_ptebase; show = show || diff; + ptr += sprintf(ptr, "context_ptebase |%c| %03x | %03x \n", (diff)? '*' : ' ', vmips->state.context_ptebase, ao->state.context_ptebase); + + diff = vmips->state.context_badvpn != ao->state.context_badvpn; show = show || diff; + ptr += sprintf(ptr, "context_badvpn |%c| %05x | %05x \n", (diff)? '*' : ' ', vmips->state.context_badvpn, ao->state.context_badvpn); + + diff = vmips->state.bad_vaddr != ao->state.bad_vaddr; show = show || diff; + ptr += sprintf(ptr, "bad_vaddr |%c| %08x | %08x \n", (diff)? '*' : ' ', vmips->state.bad_vaddr, ao->state.bad_vaddr); + + diff = vmips->state.entryhi_vpn != ao->state.entryhi_vpn; show = show || diff; + ptr += sprintf(ptr, "entryhi_vpn |%c| %05x | %05x \n", (diff)? '*' : ' ', vmips->state.entryhi_vpn, ao->state.entryhi_vpn); + + diff = vmips->state.entryhi_asid != ao->state.entryhi_asid; show = show || diff; + ptr += sprintf(ptr, "entryhi_asid |%c| %02x | %02x \n", (diff)? '*' : ' ', vmips->state.entryhi_asid, ao->state.entryhi_asid); + + diff = vmips->state.sr_cp_usable != ao->state.sr_cp_usable; show = show || diff; + ptr += sprintf(ptr, "sr_cp_usable |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.sr_cp_usable, ao->state.sr_cp_usable); + + diff = vmips->state.sr_rev_endian != ao->state.sr_rev_endian; show = show || diff; + ptr += sprintf(ptr, "sr_rev_endian |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.sr_rev_endian, ao->state.sr_rev_endian); + + diff = vmips->state.sr_bootstrap_vec != ao->state.sr_bootstrap_vec; show = show || diff; + ptr += sprintf(ptr, "sr_bootstrap_vec |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.sr_bootstrap_vec, ao->state.sr_bootstrap_vec); + + diff = vmips->state.sr_tlb_shutdown != ao->state.sr_tlb_shutdown; show = show || diff; + ptr += sprintf(ptr, "sr_tlb_shutdown |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.sr_tlb_shutdown, ao->state.sr_tlb_shutdown); + + diff = vmips->state.sr_parity_err != ao->state.sr_parity_err; show = show || diff; + ptr += sprintf(ptr, "sr_parity_err |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.sr_parity_err, ao->state.sr_parity_err); + + diff = vmips->state.sr_cache_miss != ao->state.sr_cache_miss; show = show || diff; + ptr += sprintf(ptr, "sr_cache_miss |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.sr_cache_miss, ao->state.sr_cache_miss); + + diff = vmips->state.sr_parity_zero != ao->state.sr_parity_zero; show = show || diff; + ptr += sprintf(ptr, "sr_parity_zero |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.sr_parity_zero, ao->state.sr_parity_zero); + + diff = vmips->state.sr_switch_cache != ao->state.sr_switch_cache; show = show || diff; + ptr += sprintf(ptr, "sr_switch_cache |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.sr_switch_cache, ao->state.sr_switch_cache); + + diff = vmips->state.sr_isolate_cache != ao->state.sr_isolate_cache; show = show || diff; + ptr += sprintf(ptr, "sr_isolate_cache |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.sr_isolate_cache, ao->state.sr_isolate_cache); + + diff = vmips->state.sr_irq_mask != ao->state.sr_irq_mask; show = show || diff; + ptr += sprintf(ptr, "sr_irq_mask |%c| %02x | %02x \n", (diff)? '*' : ' ', vmips->state.sr_irq_mask, ao->state.sr_irq_mask); + + diff = vmips->state.sr_ku_ie != ao->state.sr_ku_ie; show = show || diff; + ptr += sprintf(ptr, "sr_ku_ie |%c| %02x | %02x \n", (diff)? '*' : ' ', vmips->state.sr_ku_ie, ao->state.sr_ku_ie); + + diff = vmips->state.cause_branch_delay != ao->state.cause_branch_delay; show = show || diff; + ptr += sprintf(ptr, "cause_branch_delay |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.cause_branch_delay, ao->state.cause_branch_delay); + + diff = vmips->state.cause_cp_error != ao->state.cause_cp_error; show = show || diff; + ptr += sprintf(ptr, "cause_cp_error |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.cause_cp_error, ao->state.cause_cp_error); + + diff = vmips->state.cause_irq_pending != ao->state.cause_irq_pending; show = show || diff; + ptr += sprintf(ptr, "cause_irq_pending |%c| %01x | %01x \n", (diff)? '*' : ' ', vmips->state.cause_irq_pending, ao->state.cause_irq_pending); + + diff = vmips->state.cause_exc_code != ao->state.cause_exc_code; show = show || diff; + ptr += sprintf(ptr, "cause_exc_code |%c| %02x | %02x \n", (diff)? '*' : ' ', vmips->state.cause_exc_code, ao->state.cause_exc_code); + + diff = vmips->state.epc != ao->state.epc; show = show || diff; + ptr += sprintf(ptr, "epc |%c| %08x | %08x \n", (diff)? '*' : ' ', vmips->state.epc, ao->state.epc); + + for(int i=0; i<64; i++) { + diff = vmips->state.tlb[i].vpn != ao->state.tlb[i].vpn; show = show || diff; + ptr += sprintf(ptr, "tlb[%02d].vpn |%c| %05x | %05x \n", i, (diff)? '*' : ' ', vmips->state.tlb[i].vpn, ao->state.tlb[i].vpn); + + diff = vmips->state.tlb[i].asid != ao->state.tlb[i].asid; show = show || diff; + ptr += sprintf(ptr, "tlb[%02d].asid |%c| %02x | %02x \n", i, (diff)? '*' : ' ', vmips->state.tlb[i].asid, ao->state.tlb[i].asid); + + diff = vmips->state.tlb[i].pfn != ao->state.tlb[i].pfn; show = show || diff; + ptr += sprintf(ptr, "tlb[%02d].pfn |%c| %05x | %05x \n", i, (diff)? '*' : ' ', vmips->state.tlb[i].pfn, ao->state.tlb[i].pfn); + + diff = vmips->state.tlb[i].n != ao->state.tlb[i].n; show = show || diff; + ptr += sprintf(ptr, "tlb[%02d].n |%c| %01x | %01x \n", i, (diff)? '*' : ' ', vmips->state.tlb[i].n, ao->state.tlb[i].n); + + diff = vmips->state.tlb[i].d != ao->state.tlb[i].d; show = show || diff; + ptr += sprintf(ptr, "tlb[%02d].d |%c| %01x | %01x \n", i, (diff)? '*' : ' ', vmips->state.tlb[i].d, ao->state.tlb[i].d); + + diff = vmips->state.tlb[i].v != ao->state.tlb[i].v; show = show || diff; + ptr += sprintf(ptr, "tlb[%02d].v |%c| %01x | %01x \n", i, (diff)? '*' : ' ', vmips->state.tlb[i].v, ao->state.tlb[i].v); + + diff = vmips->state.tlb[i].g != ao->state.tlb[i].g; show = show || diff; + ptr += sprintf(ptr, "tlb[%02d].g |%c| %01x | %01x \n", i, (diff)? '*' : ' ', vmips->state.tlb[i].g, ao->state.tlb[i].g); + } + + if(show) { + printf("%s", buf); + return true; + } + return false; +} + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ + +int main(int argc, char **argv) { + + int int_ret; + + //open file with truncate + FILE *fp = fopen("shared_mem.dat", "wb"); + if(fp == NULL) { + perror("Can not truncate file shared_mem.dat"); + return -1; + } + uint8 *buf = new uint8[sizeof(shared_mem_t)]; + memset(buf, 0, sizeof(shared_mem_t)); + + int_ret = fwrite(buf, sizeof(shared_mem_t), 1, fp); + delete buf; + if(int_ret != 1) { + perror("Can not zero-fill file shared_mem.dat"); + fclose(fp); + return -2; + } + fclose(fp); + + //-------------------------------------------------------------------------- + + //map shared memory + int fd = open("./shared_mem.dat", O_RDWR, S_IRUSR | S_IWUSR); + + if(fd == -1) { + perror("open() failed for shared_mem.dat"); + return -3; + } + + shared_ptr = (shared_mem_t *)mmap(NULL, sizeof(shared_mem_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if(shared_ptr == MAP_FAILED) { + perror("mmap() failed"); + close(fd); + return -4; + } + + //-------------------------------------------------------------------------- + + srand(0); + + while(true) { + //---------------------------------------------------------------------- + memset((void *)shared_ptr, 0, sizeof(shared_mem_t)); + + //---------------------------------------------------------------------- run init function + + if(tst_current->init != NULL) tst_current->init(tst_current, (shared_mem_t *)shared_ptr); + + //---------------------------------------------------------------------- + + pid_t proc_vmips = fork(); + if(proc_vmips == 0) { + system("cd ./../vmips && ./main_tester > ./vmips_output.txt"); + return 0; + } + + pid_t proc_ao = fork(); + if(proc_ao == 0) { + system("cd ./../aoR3000 && ./obj_dir/VaoR3000 > ./ao_output.txt"); + return 0; + } + + //---------------------------------------------------------------------- + + printf("Waiting for init of vmips..."); fflush(stdout); + shared_ptr->proc_vmips.initialize_do = true; + + while(shared_ptr->proc_vmips.initialize_do) usleep(1); + printf("done\n"); + + printf("Waiting for init of aoR3000..."); fflush(stdout); + shared_ptr->proc_ao.initialize_do = true; + + while(shared_ptr->proc_ao.initialize_do) usleep(1); + printf("done\n"); + + while(true) { + if(shared_ptr->proc_vmips.report_do && shared_ptr->proc_ao.report_do) { + bool diff = is_diff(&(shared_ptr->proc_vmips.report), &(shared_ptr->proc_ao.report)); + if(diff) { + printf("\nTEST FAILED. DIFF.\n"); + shared_ptr->test_finished = true; + return -1; + } + if(shared_ptr->proc_vmips.report.exception == 1 && shared_ptr->proc_ao.report.exception == 1) { + printf("\nTEST OK.\n"); + shared_ptr->test_finished = true; + break; + } + + shared_ptr->proc_vmips.report_do = shared_ptr->proc_ao.report_do = false; + printf("check ok\n"); + } + + while(shared_ptr->proc_vmips.write_do || shared_ptr->proc_ao.write_do) { + if(shared_ptr->proc_vmips.write_do && shared_ptr->proc_ao.write_do) { + + if( shared_ptr->proc_vmips.write_address == shared_ptr->proc_ao.write_address && + shared_ptr->proc_vmips.write_byteenable == shared_ptr->proc_ao.write_byteenable && + shared_ptr->proc_vmips.write_data == shared_ptr->proc_ao.write_data) + { + printf("write: %08x %01x %08x\n", shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data); + + uint32 byteena = shared_ptr->proc_vmips.write_byteenable; + uint32 value = shared_ptr->proc_vmips.write_data; + + for(uint32 i=0; i<4; i++) { + if(byteena & 1) shared_ptr->mem.bytes[shared_ptr->proc_vmips.write_address + i] = value & 0xFF; + value >>= 8; + byteena >>= 1; + } + + shared_ptr->proc_vmips.write_do = false; + shared_ptr->proc_ao.write_do = false; + } + else { + printf("vmips: %08x %01x %08x\n", shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data); + printf("ao: %08x %01x %08x\n", shared_ptr->proc_ao.write_address, shared_ptr->proc_ao.write_byteenable, shared_ptr->proc_ao.write_data); + + printf("\nTEST FAILED. MEM WRITE DIFF.\n"); + shared_ptr->test_finished = true; + return -1; + } + } + } + } + + //---------------------------------------------------------------------- wait for process end + waitpid(proc_vmips, NULL, 0); + waitpid(proc_ao, NULL, 0); + } + return 0; +} + +//------------------------------------------------------------------------------ Index: trunk/sim/tester/test_interrupt.cpp =================================================================== --- trunk/sim/tester/test_interrupt.cpp (nonexistent) +++ trunk/sim/tester/test_interrupt.cpp (revision 2) @@ -0,0 +1,83 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include "tests.h" + +//------------------------------------------------------------------------------ + +void interrupt_till_exc_init(tst_t *tst, shared_mem_t *shared_ptr) { + + for(int i=1; i<32; i++) shared_ptr->initial.reg[i-1] = rand_uint32(); + + shared_ptr->initial.pc = 0xA0001000; + + //tlb left zero + + shared_ptr->initial.index_p = rand() & 0x1; + shared_ptr->initial.index_index = rand() & 0x3F; + + shared_ptr->initial.random = rand() & 0x3F; + + shared_ptr->initial.entrylo_pfn = rand() & 0xFFFFF; + shared_ptr->initial.entrylo_n = rand() & 0x1; + shared_ptr->initial.entrylo_d = rand() & 0x1; + shared_ptr->initial.entrylo_v = rand() & 0x1; + shared_ptr->initial.entrylo_g = rand() & 0x1; + + shared_ptr->initial.context_ptebase = rand() & 0x7FF; + shared_ptr->initial.context_badvpn = rand() & 0x7FFFF; + + shared_ptr->initial.bad_vaddr = rand_uint32(); + + shared_ptr->initial.entryhi_vpn = rand() & 0xFFFFF; + shared_ptr->initial.entryhi_asid = rand() & 0x3F; + + shared_ptr->initial.sr_cp_usable = rand() & 0xF; + shared_ptr->initial.sr_rev_endian = rand() & 0x1; + shared_ptr->initial.sr_bootstrap_vec = rand() & 0x1; + shared_ptr->initial.sr_tlb_shutdown = rand() & 0x1; + shared_ptr->initial.sr_parity_err = rand() & 0x1; + shared_ptr->initial.sr_cache_miss = rand() & 0x1; + shared_ptr->initial.sr_parity_zero = rand() & 0x1; + shared_ptr->initial.sr_switch_cache = rand() & 0x1; + shared_ptr->initial.sr_isolate_cache = rand() & 0x1; + shared_ptr->initial.sr_irq_mask = rand() & 0xFF; + shared_ptr->initial.sr_ku_ie = rand() & 0x3F; + + shared_ptr->initial.cause_branch_delay = rand() & 0x1; + shared_ptr->initial.cause_cp_error = rand() & 0x3; + shared_ptr->initial.cause_irq_pending = 0; + shared_ptr->initial.cause_exc_code = rand() & 0x1F; + + shared_ptr->initial.epc = rand_uint32(); + + // + uint32 *ptr = &shared_ptr->mem.ints[(shared_ptr->initial.pc & 0x1FFFFFFF) / 4]; + + (*ptr) = 0; + ptr++; + + (*ptr) = 0; + ptr++; + + (*ptr) = 0; + ptr++; + + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + + // + bool irq3 = (rand() % 2) == 0; + shared_ptr->irq2_at_event = (irq3)? 0xFFFFFFFF : 1; + shared_ptr->irq3_at_event = (irq3)? 1 : 0xFFFFFFFF; +} + +//------------------------------------------------------------------------------ Index: trunk/sim/tester/test_branch.cpp =================================================================== --- trunk/sim/tester/test_branch.cpp (nonexistent) +++ trunk/sim/tester/test_branch.cpp (revision 2) @@ -0,0 +1,264 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include "tests.h" + +//------------------------------------------------------------------------------ + +void branch_till_exc_init(tst_t *tst, shared_mem_t *shared_ptr) { + + for(int i=1; i<32; i++) shared_ptr->initial.reg[i-1] = rand_uint32(); + + shared_ptr->initial.pc = 0xA0001000; + + //tlb left zero + + shared_ptr->initial.index_p = rand() & 0x1; + shared_ptr->initial.index_index = rand() & 0x3F; + + shared_ptr->initial.random = rand() & 0x3F; + + shared_ptr->initial.entrylo_pfn = rand() & 0xFFFFF; + shared_ptr->initial.entrylo_n = rand() & 0x1; + shared_ptr->initial.entrylo_d = rand() & 0x1; + shared_ptr->initial.entrylo_v = rand() & 0x1; + shared_ptr->initial.entrylo_g = rand() & 0x1; + + shared_ptr->initial.context_ptebase = rand() & 0x7FF; + shared_ptr->initial.context_badvpn = rand() & 0x7FFFF; + + shared_ptr->initial.bad_vaddr = rand_uint32(); + + shared_ptr->initial.entryhi_vpn = rand() & 0xFFFFF; + shared_ptr->initial.entryhi_asid = rand() & 0x3F; + + shared_ptr->initial.sr_cp_usable = rand() & 0xF; + shared_ptr->initial.sr_rev_endian = rand() & 0x1; + shared_ptr->initial.sr_bootstrap_vec = rand() & 0x1; + shared_ptr->initial.sr_tlb_shutdown = rand() & 0x1; + shared_ptr->initial.sr_parity_err = rand() & 0x1; + shared_ptr->initial.sr_cache_miss = rand() & 0x1; + shared_ptr->initial.sr_parity_zero = rand() & 0x1; + shared_ptr->initial.sr_switch_cache = rand() & 0x1; + shared_ptr->initial.sr_isolate_cache = rand() & 0x1; + shared_ptr->initial.sr_irq_mask = rand() & 0xFF; + shared_ptr->initial.sr_ku_ie = rand() & 0x3F; + + shared_ptr->initial.cause_branch_delay = rand() & 0x1; + shared_ptr->initial.cause_cp_error = rand() & 0x3; + shared_ptr->initial.cause_irq_pending = 0; + shared_ptr->initial.cause_exc_code = rand() & 0x1F; + + shared_ptr->initial.epc = rand_uint32(); + + // + shared_ptr->irq2_at_event = 0xFFFFFFFF; + shared_ptr->irq3_at_event = 0xFFFFFFFF; + + // + uint32 *ptr = &shared_ptr->mem.ints[(shared_ptr->initial.pc & 0x1FFFFFFF) / 4]; + + uint32 type = rand() % 12; + uint32 after = rand() % 3; +/* +0 - branch, no exception in delay slot +1 - no branch +2 - branch, exception in delay slot +*/ + if(type == 0) { //BEQ + shared_ptr->initial.reg[0] = 1; + shared_ptr->initial.reg[1] = (after == 0)? 1 : (after == 1)? 2 : 1; + + (*ptr) = (0b000100 << 26) | (1 << 21) | (2 << 16) | (1 + (rand() % 10)); + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 1) { //BGEZ + shared_ptr->initial.reg[0] = (after == 0)? 1 : (after == 1)? 0x80000000 : 1; + + (*ptr) = (0b000001 << 26) | (1 << 21) | (0b00001 << 16) | (1 + (rand() % 10)); + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 2) { //BGEZAL + shared_ptr->initial.reg[0] = (after == 0)? 0 : (after == 1)? 0x80000000 : 1; + + (*ptr) = (0b000001 << 26) | (1 << 21) | (0b10001 << 16) | (1 + (rand() % 10)); + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 3) { //BGTZ + shared_ptr->initial.reg[0] = (after == 0)? 1 : (after == 1)? ((rand() % 2)? 0 : 0x80000000) : 1; + + (*ptr) = (0b000111 << 26) | (1 << 21) | ((rand() % 3 == 0)? rand() & 0x1F : 0b00000) << 16 | (1 + (rand() % 10)); + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 4) { //BLEZ + shared_ptr->initial.reg[0] = (after == 0)? 0x80000000 : (after == 1)? 1 : 0; + + (*ptr) = (0b000110 << 26) | (1 << 21) | ((rand() % 3 == 0)? rand() & 0x1F : 0b00000) << 16 | (1 + (rand() % 10)); + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 5) { //BLTZ + shared_ptr->initial.reg[0] = (after == 0)? 0x80000000 : (after == 1)? ((rand() % 2)? 0 : 1) : 0xFFFFFFFF; + + (*ptr) = (0b000001 << 26) | (1 << 21) | (0b00000 << 16) | (1 + (rand() % 10)); + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 6) { //BLTZAL + shared_ptr->initial.reg[0] = (after == 0)? 0x80000000 : (after == 1)? ((rand() % 2)? 0 : 1) : 0xFFFFFFFF; + + (*ptr) = (0b000001 << 26) | (1 << 21) | (0b10000 << 16) | (1 + (rand() % 10)); + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 7) { //BNE + shared_ptr->initial.reg[0] = 1; + shared_ptr->initial.reg[1] = (after == 0)? 2 : (after == 1)? 1 : 3; + + (*ptr) = (0b000101 << 26) | (1 << 21) | (2 << 16) | (1 + (rand() % 10)); + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 8) { //J + uint32 dest = (((0xA0001000) >> 2) & 0x3FFFFFF) | (1 + (rand() % 10)); + + (*ptr) = (0b000010 << 26) | dest; + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 9) { //JAL + uint32 dest = (((0xA0001000) >> 2) & 0x3FFFFFF) | (1 + (rand() % 10)); + + (*ptr) = (0b000011 << 26) | dest; + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 10) { //JALR + uint32 dest = 0xA0001000 | ((1 + (rand() % 10)) << 2) | (((rand() % 2) == 0)? 1 : 0); + + shared_ptr->initial.reg[0] = dest; + + (*ptr) = (0b000000 << 26) | (1 << 21) | ((rand() & 0x1F) << 16) | ((rand() & 0x1F) << 11) | ((rand() & 0x1F) << 6) | 0b001001; + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } + else if(type == 11) { //JR + uint32 dest = 0xA0001000 | ((1 + (rand() % 10)) << 2) | (((rand() % 3) == 0)? 1 : 0); + + shared_ptr->initial.reg[0] = dest; + shared_ptr->initial.reg[1] = (after == 1)? 1 : 0; + + (*ptr) = (0b000000 << 26) | (1 << 21) | ((rand() & 0x1F) << 16) | (2 << 11) | ((rand() & 0x1F) << 6) | 0b001000; + ptr++; + + (*ptr) = (after == 2)? 0b001100 /*SYSCALL*/: 0; //delay slot + ptr++; + + for(int i=0; i<10; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } + } +} + +//------------------------------------------------------------------------------ Index: trunk/sim/tester/Makefile =================================================================== --- trunk/sim/tester/Makefile (nonexistent) +++ trunk/sim/tester/Makefile (revision 2) @@ -0,0 +1,5 @@ +tester: + g++ -o main_tester -O2 main_tester.cpp test_arithmetic_logic.cpp test_exception.cpp test_tlb_commands.cpp test_branch.cpp test_data.cpp test_interrupt.cpp test_tlb_fetch.cpp test_tlb_data.cpp test_other.cpp + +linux: + g++ -o main_linux -O2 -lutil main_linux.cpp Index: trunk/sim/tester/test_exception.cpp =================================================================== --- trunk/sim/tester/test_exception.cpp (nonexistent) +++ trunk/sim/tester/test_exception.cpp (revision 2) @@ -0,0 +1,151 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include + +#include "tests.h" + +//------------------------------------------------------------------------------ + +void exception_till_exc_init(tst_t *tst, shared_mem_t *shared_ptr) { + + for(int i=1; i<32; i++) shared_ptr->initial.reg[i-1] = rand_uint32(); + + shared_ptr->initial.pc = 0xA0001000; + + //tlb left zero + + shared_ptr->initial.index_p = rand() & 0x1; + shared_ptr->initial.index_index = rand() & 0x3F; + + shared_ptr->initial.random = rand() & 0x3F; + + shared_ptr->initial.entrylo_pfn = rand() & 0xFFFFF; + shared_ptr->initial.entrylo_n = rand() & 0x1; + shared_ptr->initial.entrylo_d = rand() & 0x1; + shared_ptr->initial.entrylo_v = rand() & 0x1; + shared_ptr->initial.entrylo_g = rand() & 0x1; + + shared_ptr->initial.context_ptebase = rand() & 0x7FF; + shared_ptr->initial.context_badvpn = rand() & 0x7FFFF; + + shared_ptr->initial.bad_vaddr = rand_uint32(); + + shared_ptr->initial.entryhi_vpn = rand() & 0xFFFFF; + shared_ptr->initial.entryhi_asid = rand() & 0x3F; + + shared_ptr->initial.sr_cp_usable = rand() & 0xF; + shared_ptr->initial.sr_rev_endian = rand() & 0x1; + shared_ptr->initial.sr_bootstrap_vec = rand() & 0x1; + shared_ptr->initial.sr_tlb_shutdown = rand() & 0x1; + shared_ptr->initial.sr_parity_err = rand() & 0x1; + shared_ptr->initial.sr_cache_miss = rand() & 0x1; + shared_ptr->initial.sr_parity_zero = rand() & 0x1; + shared_ptr->initial.sr_switch_cache = rand() & 0x1; + shared_ptr->initial.sr_isolate_cache = rand() & 0x1; + shared_ptr->initial.sr_irq_mask = rand() & 0xFF; + shared_ptr->initial.sr_ku_ie = rand() & 0x3F; + + shared_ptr->initial.cause_branch_delay = rand() & 0x1; + shared_ptr->initial.cause_cp_error = rand() & 0x3; + shared_ptr->initial.cause_irq_pending = 0; + shared_ptr->initial.cause_exc_code = rand() & 0x1F; + + shared_ptr->initial.epc = rand_uint32(); + + // + shared_ptr->irq2_at_event = 0xFFFFFFFF; + shared_ptr->irq3_at_event = 0xFFFFFFFF; + + // + uint32 *ptr = &shared_ptr->mem.ints[(shared_ptr->initial.pc & 0x1FFFFFFF) / 4]; + + uint32 type = rand() % 14; + + if(type == 0) { //SYSCALL + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; + } + else if(type == 1) { //BREAK + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001101; + } + else if(type == 2) { //CFCz + (*ptr) = rand() & 0x0C1FFFFF; + (*ptr) |= (0b0100 << 28) | (0b00010 << 21); + } + else if(type == 3) { //CTCz + (*ptr) = rand() & 0x0C1FFFFF; + (*ptr) |= (0b0100 << 28) | (0b00110 << 21); + } + else if(type == 4) { //LWCz + (*ptr) = rand() & 0x0FFFFFFF; + (*ptr) |= (0b1100 << 28); + } + else if(type == 5) { //SWCz + (*ptr) = rand() & 0x0FFFFFFF; + (*ptr) |= (0b1110 << 28); + } + else if(type == 6) { //CFC1_detect + (*ptr) = rand() & 0x001F07FF; + (*ptr) |= (0b0100 << 28) | (0b01 << 26) | (0b00010 << 21) | (0b00000 << 11); + } + else if(type == 7) { //MFC0123 random + (*ptr) = rand() & 0x0C1FFFFF; + (*ptr) |= (0b0100 << 28) | (0b00000 << 21); + } + else if(type == 8) { //MFC0 + (*ptr) = rand() & 0x001FFFFF; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b00000 << 21); + } + else if(type == 9) { //MTC0123 random + (*ptr) = rand() & 0x0C1FFFFF; + (*ptr) |= (0b0100 << 28) | (0b00100 << 21); + } + else if(type == 10) { //MTC0 + (*ptr) = rand() & 0x001FFFFF; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b00100 << 21); + } + else if(type == 11) { //COP0123 random + (*ptr) = rand() & 0x0DFFFFFF; + (*ptr) |= (0b0100 << 28) | (0b1 << 25); + } + else if(type == 12) { //COP0 + (*ptr) = rand() & 0x01FFFFFF; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b1 << 25); + } + else if(type == 13) { //RFE + (*ptr) = rand() & 0x01FFFFC0; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b1 << 25) | (0b010000 << 0); + } + else if(type == 14) { //bc0f + (*ptr) = rand() & 0x00000000; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b01000 << 21) | (0b00000 << 16) | (rand() % 5); + } + else if(type == 15) { //bc0t + (*ptr) = rand() & 0x00000000; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b01000 << 21) | (0b00001 << 16) | (rand() % 5); + } + else if(type == 15) { //bc0_ign + (*ptr) = rand() & 0x0000FFFF; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b01000 << 21) | (((rand() % 2)? 0b00010 : 0b00011) << 16); + } + else if(type == 15) { //bc0 reserved + (*ptr) = rand() & 0x0000FFFF; + (*ptr) |= (0b0100 << 28) | (0b00 << 26) | (0b01000 << 21) | ((4 + (rand() % 28)) << 16); + } + + ptr++; + for(int i=0; i<5; i++) { + (*ptr) = rand() & 0x03FFFFC0; + (*ptr) |= 0b001100; //SYSCALL + ptr++; + } +} + +//------------------------------------------------------------------------------ Index: trunk/sim/vmips/main_linux.cpp =================================================================== --- trunk/sim/vmips/main_linux.cpp (nonexistent) +++ trunk/sim/vmips/main_linux.cpp (revision 2) @@ -0,0 +1,253 @@ +/* + * This file is subject to the terms and conditions of the GPL License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "shared_mem.h" +#include "vmips_emulator.h" + +//------------------------------------------------------------------------------ + +volatile shared_mem_t *shared_ptr = NULL; + +//------------------------------------------------------------------------------ + +void CPZero::initialize() { +} + +void CPU::initialize() { +} + +//------------------------------------------------------------------------------ + +void CPZero::report() { +} + +void CPU::report() { +} + +//------------------------------------------------------------------------------ + +CPU *cpu = NULL; +uint32 event_counter = 0; + +void usleep_or_finish() { + if(shared_ptr->test_finished) { + printf("Finishing.\n"); + exit(0); + } + usleep(1); +} + +//128MB +#define MAX_MEMORY 0x08000000 +#define RESET_VECTOR 0x1FC00000 + +uint32 isolated_cache[512]; + +uint32 ao_interrupts() { + return ((event_counter >= shared_ptr->irq2_at_event)? 1 << 10 : 0) | ((event_counter >= shared_ptr->irq3_at_event)? 2 << 10 : 0); +} + +uint8 ao_fetch_byte(uint32 addr, bool cacheable, bool isolated) { + //DBE IBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + if(isolated) return + ((addr %4) == 0)? ((isolated_cache[(addr >> 2)&0x1FF] >> 0) & 0xFF) : + ((addr %4) == 1)? ((isolated_cache[(addr >> 2)&0x1FF] >> 8) & 0xFF) : + ((addr %4) == 2)? ((isolated_cache[(addr >> 2)&0x1FF] >> 16) & 0xFF) : + ((isolated_cache[(addr >> 2)&0x1FF] >> 24) & 0xFF); + + if(addr < MAX_MEMORY) { + return shared_ptr->mem.bytes[addr]; + } + + shared_ptr->proc_vmips.read_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.read_byteenable = ((addr % 4) == 0)? 0x1 : ((addr % 4) == 1)? 0x2 : ((addr % 4) == 2)? 0x3 : 0x4; + shared_ptr->proc_vmips.read_do = true; + + while(shared_ptr->proc_vmips.read_do) usleep_or_finish(); + + return (shared_ptr->proc_vmips.read_data >> ( ((addr % 4) == 0)? 0 : ((addr % 4) == 1)? 8 : ((addr % 4) == 2)? 16 : 24 )) & 0xFF; +} + +uint16 ao_fetch_halfword(uint32 addr, bool cacheable, bool isolated) { + //AdE + if (addr % 2 != 0) { + cpu->exception(AdEL,DATALOAD); + return 0xffff; + } + + //DBE IBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + if(isolated) return + ((addr %4) == 0)? ((isolated_cache[(addr >> 2)&0x1FF] >> 0) & 0xFFFF) : + ((isolated_cache[(addr >> 2)&0x1FF] >> 16) & 0xFFFF); + + if(addr < MAX_MEMORY) { + return shared_ptr->mem.shorts[addr/2]; + } + + shared_ptr->proc_vmips.read_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.read_byteenable = ((addr % 4) == 0)? 0x3 : 0xC; + shared_ptr->proc_vmips.read_do = true; + + while(shared_ptr->proc_vmips.read_do) usleep_or_finish(); + + return (shared_ptr->proc_vmips.read_data >> ( ((addr % 4) == 0)? 0 : 16 )) & 0xFFFF; +} + +uint32 ao_fetch_word(uint32 addr, int32 mode, bool cacheable, bool isolated) { + //AdE + if (addr % 4 != 0) { + cpu->exception(AdEL,mode); + return 0xffffffff; + } + + //DBE IBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + if(isolated && mode == DATALOAD) return ((isolated_cache[(addr >> 2)&0x1FF] >> 0) & 0xFFFFFFFF); + + if(addr < MAX_MEMORY) { + return shared_ptr->mem.ints[addr/4]; + } + else if(addr >= RESET_VECTOR && addr < RESET_VECTOR + sizeof(shared_ptr->reset_vector)) { + return shared_ptr->reset_vector[(addr - RESET_VECTOR)/4]; + } + + shared_ptr->proc_vmips.read_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.read_byteenable = 0xF; + shared_ptr->proc_vmips.read_do = true; + + while(shared_ptr->proc_vmips.read_do) usleep_or_finish(); + + return (shared_ptr->proc_vmips.read_data) & 0xFFFFFFFF; +} + +void ao_store_byte(uint32 addr, uint8 data, bool cacheable, bool isolated) { + //DBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + if(isolated) return; + + shared_ptr->proc_vmips.write_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.write_byteenable = ((addr % 4) == 0)? 0x1 : ((addr % 4) == 1)? 0x2 : ((addr % 4) == 2)? 0x4 : 0x8; + shared_ptr->proc_vmips.write_data = ((addr % 4) == 0)? data : ((addr % 4) == 1)? data << 8 : ((addr % 4) == 2)? data << 16 : data << 24; + shared_ptr->proc_vmips.write_do = true; + + while(shared_ptr->proc_vmips.write_do) usleep_or_finish(); +} + +void ao_store_halfword(uint32 addr, uint16 data, bool cacheable, bool isolated) { + //AdE + if (addr % 2 != 0) { + cpu->exception(AdES,DATASTORE); + return; + } + + //DBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + if(isolated) return; + + shared_ptr->proc_vmips.write_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.write_byteenable = ((addr % 4) == 0)? 0x3 : 0xC; + shared_ptr->proc_vmips.write_data = ((addr % 4) == 0)? data : data << 16; + shared_ptr->proc_vmips.write_do = true; + + while(shared_ptr->proc_vmips.write_do) usleep_or_finish(); +} + +void ao_store_word(uint32 addr, uint32 data, bool cacheable, bool isolated, uint32 byteenable) { + //AdE + if (addr % 4 != 0) { + cpu->exception(AdES,DATASTORE); + return; + } + + //DBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + if(isolated) { + isolated_cache[(addr >> 2)&0x1FF] = data; + return; + } + + shared_ptr->proc_vmips.write_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.write_byteenable = byteenable; + shared_ptr->proc_vmips.write_data = data; + shared_ptr->proc_vmips.write_do = true; + + while(shared_ptr->proc_vmips.write_do) usleep_or_finish(); +} + +void fatal_error(const char *error, ...) { + printf("[fatal_error]: %s\n", error); + exit(-1); +} + +//------------------------------------------------------------------------------ + + +int main() { + //map shared memory + int fd = open("./../tester/shared_mem.dat", O_RDWR, S_IRUSR | S_IWUSR); + + if(fd == -1) { + perror("open() failed for shared_mem.dat"); + return -1; + } + + shared_ptr = (shared_mem_t *)mmap(NULL, sizeof(shared_mem_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if(shared_ptr == MAP_FAILED) { + perror("mmap() failed"); + close(fd); + return -2; + } + + cpu = new CPU(); + cpu->reset(); + + printf("Waiting for initialize..."); fflush(stdout); + while(shared_ptr->proc_vmips.initialize_do == false) usleep_or_finish(); + + cpu->initialize(); + shared_ptr->proc_vmips.initialize_do = false; + printf("done\n"); + + while(true) { + bool do_debug = false;//event_counter > 40565500; + + int exception_pending = cpu->step(do_debug); + fflush(stdout); + + shared_ptr->proc_vmips.report.counter = event_counter; + + if(shared_ptr->check_at_event == event_counter) { + shared_ptr->proc_vmips.check_do = true; + + while(shared_ptr->proc_vmips.check_do) usleep_or_finish(); + } + + event_counter++; + } + return 0; +} + +//------------------------------------------------------------------------------ Index: trunk/sim/vmips/vmips_emulator.cpp =================================================================== --- trunk/sim/vmips/vmips_emulator.cpp (nonexistent) +++ trunk/sim/vmips/vmips_emulator.cpp (revision 2) @@ -0,0 +1,1657 @@ +/* + * This file is subject to the terms and conditions of the GPL License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include +#include + +#include "shared_mem.h" +#include "vmips_emulator.h" + +//------------------------------------------------------------------------------ Code from vmips-1.4.1 project under the GPL license +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +/* MIPS R3000 CPU emulation. + Copyright 2001, 2002, 2003, 2004 Brian R. Gaeke. + +This file is part of VMIPS. + +VMIPS 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 2 of the License, or (at your +option) any later version. + +VMIPS 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 VMIPS; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +//------------------------------------------------------------------------------ cpzero.cc + +static uint32 read_masks[] = { + Index_MASK, Random_MASK, EntryLo_MASK, 0, Context_MASK, + PageMask_MASK, Wired_MASK, Error_MASK, BadVAddr_MASK, Count_MASK, + EntryHi_MASK, Compare_MASK, Status_MASK, Cause_MASK, EPC_MASK, + PRId_MASK, Config_MASK, LLAddr_MASK, WatchLo_MASK, WatchHi_MASK, + 0, 0, 0, 0, 0, 0, ECC_MASK, CacheErr_MASK, TagLo_MASK, TagHi_MASK, + ErrorEPC_MASK, 0 +}; + +static uint32 write_masks[] = { + Index_MASK, 0, EntryLo_MASK, 0, Context_MASK & ~Context_BadVPN_MASK, + PageMask_MASK, Wired_MASK, Error_MASK, 0, Count_MASK, + EntryHi_MASK, Compare_MASK, Status_MASK, + Cause_MASK & ~Cause_IP_Ext_MASK, 0, 0, Config_MASK, LLAddr_MASK, + WatchLo_MASK, WatchHi_MASK, 0, 0, 0, 0, 0, 0, ECC_MASK, + CacheErr_MASK, TagLo_MASK, TagHi_MASK, ErrorEPC_MASK, 0 +}; + +CPZero::CPZero(CPU *m) : cpu (m) { } + +/* Reset (warm or cold) */ +void +CPZero::reset(void) +{ + int r; + for (r = 0; r < 16; r++) { + reg[r] = 0; + } + /* Turn off any randomly-set pending-interrupt bits, as these + * can impact correctness. */ + reg[Cause] &= ~Cause_IP_MASK; + /* Reset Random register to upper bound (8<=Random<=63) */ + reg[Random] = Random_UPPER_BOUND << 8; + /* Reset Status register: clear KUc, IEc, SwC (i.e., caches are not + * switched), TS (TLB shutdown has not occurred), and set + * BEV (Bootstrap exception vectors ARE in effect). + */ + reg[Status] = (reg[Status] | Status_DS_BEV_MASK) & + ~(Status_KUc_MASK | Status_IEc_MASK | Status_DS_SwC_MASK | + Status_DS_TS_MASK); + reg[PRId] = 0x00000230; /* MIPS R3000A */ +} + +/* Yow!! Are we in KERNEL MODE yet?? ...Read the Status register. */ +bool +CPZero::kernel_mode(void) const +{ + return !(reg[Status] & Status_KUc_MASK); +} + +/* Request for address translation (possibly using the TLB). */ +uint32 +CPZero::address_trans(uint32 vaddr, int mode, bool *cacheable, bool *cache_isolated) +{ + (*cache_isolated) = caches_isolated(); + + if (kernel_mode()) { + switch(vaddr & KSEG_SELECT_MASK) { + case KSEG0: + *cacheable = true; + return vaddr - KSEG0_CONST_TRANSLATION; + case KSEG1: + *cacheable = false; + return vaddr - KSEG1_CONST_TRANSLATION; + case KSEG2: + case KSEG2_top: + return tlb_translate(KSEG2, vaddr, mode, cacheable); + default: /* KUSEG */ + return tlb_translate(KUSEG, vaddr, mode, cacheable); + } + } + + /* user mode */ + if (vaddr & KERNEL_SPACE_MASK) { + /* Can't go there. */ + cpu->exception(mode == DATASTORE ? AdES : AdEL, mode); + return 0xffffffff; + } else /* user space address */ { + return tlb_translate(KUSEG, vaddr, mode, cacheable); + } +} + +void +CPZero::load_addr_trans_excp_info(uint32 va, uint32 vpn, TLBEntry *match) +{ + reg[BadVAddr] = va; + reg[Context] = (reg[Context] & ~Context_BadVPN_MASK) | ((va & 0x7ffff000) >> 10); + reg[EntryHi] = (va & EntryHi_VPN_MASK) | (reg[EntryHi] & ~EntryHi_VPN_MASK); +} + +int +CPZero::find_matching_tlb_entry(uint32 vpn, uint32 asid) +{ + for (uint16 x = 0; x < TLB_ENTRIES; x++) + if (tlb[x].vpn() == vpn && (tlb[x].global() || tlb[x].asid() == asid)) + return x; + return -1; +} + +uint32 +CPZero::tlb_translate(uint32 seg, uint32 vaddr, int mode, bool *cacheable) +{ + uint32 asid = reg[EntryHi] & EntryHi_ASID_MASK; + uint32 vpn = vaddr & EntryHi_VPN_MASK; + int index = find_matching_tlb_entry(vpn, asid); + TLBEntry *match = (index == -1) ? 0 : &tlb[index]; + tlb_miss_user = false; + if (match && match->valid()) { + if (mode == DATASTORE && !match->dirty()) { + /* TLB Mod exception - write to page not marked "dirty" */ + load_addr_trans_excp_info(vaddr,vpn,match); + cpu->exception(Mod, DATASTORE); + return 0xffffffff; + } else { + /* We have a matching TLB entry which is valid. */ + *cacheable = !match->noncacheable(); + return match->pfn() | (vaddr & ~EntryHi_VPN_MASK); + } + } + // If we got here, then there was no matching tlb entry, or it wasn't valid. + // Use special refill handler vector for user TLB miss. + tlb_miss_user = (seg == KUSEG && !match); + load_addr_trans_excp_info(vaddr,vpn,match); + //fprintf(stderr, "TLB: Miss for vaddr=%x (vpn=%x)\n", vaddr, (vaddr>>12)); + cpu->exception(mode == DATASTORE ? TLBS : TLBL, mode); + return 0xffffffff; +} + +uint32 CPZero::read_reg(const uint16 r) { + // This ensures that non-existent CP0 registers read as zero. + return reg[r] & read_masks[r]; +} + +void CPZero::write_reg(const uint16 r, const uint32 data) { + // This preserves the bits which are readable but not writable, and writes + // the bits which are writable with new data, thus making it suitable + // for mtc0-type operations. If you want to write all the bits which + // are _connected_, use: reg[r] = new_data & write_masks[r]; . + reg[r] = (reg[r] & (read_masks[r] & ~write_masks[r])) + | (data & write_masks[r]); +} + +void +CPZero::mfc0_emulate(uint32 instr, uint32 pc) +{ + cpu->put_reg (CPU::rt (instr), read_reg (CPU::rd (instr))); +} + +void +CPZero::mtc0_emulate(uint32 instr, uint32 pc) +{ + write_reg (CPU::rd (instr), cpu->get_reg (CPU::rt (instr))); +} + +void +CPZero::bc0x_emulate(uint32 instr, uint32 pc) +{ + uint16 condition = CPU::rt (instr); + switch (condition) { + case 0: /* bc0f */ if (! cpCond ()) { cpu->branch (instr, pc); } break; + case 1: /* bc0t */ if (cpCond ()) { cpu->branch (instr, pc); } break; + case 2: /* bc0fl - not valid, but not reserved(A-17, H&K) - no-op. */ break; + case 3: /* bc0tl - not valid, but not reserved(A-21, H&K) - no-op. */ break; + default: cpu->exception (RI); break; /* reserved */ + } +} + +void +CPZero::tlbr_emulate(uint32 instr, uint32 pc) +{ + reg[EntryHi] = (tlb[(reg[Index] & Index_Index_MASK) >> 8].entryHi) & + write_masks[EntryHi]; + reg[EntryLo] = (tlb[(reg[Index] & Index_Index_MASK) >> 8].entryLo) & + write_masks[EntryLo]; +} + +void +CPZero::tlb_write(unsigned index) +{ + tlb[index].entryHi = read_reg(EntryHi); + tlb[index].entryLo = read_reg(EntryLo); +} + +void +CPZero::tlbwi_emulate(uint32 instr, uint32 pc) +{ + tlb_write ((reg[Index] & Index_Index_MASK) >> 8); +} + +void +CPZero::tlbwr_emulate(uint32 instr, uint32 pc) +{ + tlb_write ((reg[Random] & Random_Random_MASK) >> 8); + + adjust_random(); +} + +void +CPZero::tlbp_emulate(uint32 instr, uint32 pc) +{ + uint32 vpn = reg[EntryHi] & EntryHi_VPN_MASK; + uint32 asid = reg[EntryHi] & EntryHi_ASID_MASK; + int idx = find_matching_tlb_entry (vpn, asid); + if (idx != -1) + reg[Index] = (idx << 8); + else + reg[Index] = (1 << 31); +} + +void +CPZero::rfe_emulate(uint32 instr, uint32 pc) +{ + reg[Status] = (reg[Status] & 0xfffffff0) | ((reg[Status] >> 2) & 0x0f); +} + +void +CPZero::cpzero_emulate(uint32 instr, uint32 pc) +{ + uint16 rs = CPU::rs (instr); + if (CPU::rs (instr) > 15) { + switch (CPU::funct (instr)) { + case 1: tlbr_emulate (instr, pc); break; + case 2: tlbwi_emulate (instr, pc); break; + case 6: tlbwr_emulate (instr, pc); break; + case 8: tlbp_emulate (instr, pc); break; + case 16: rfe_emulate (instr, pc); break; + default: cpu->exception (RI, ANY, 0); break; + } + } else { + switch (rs) { + case 0: mfc0_emulate (instr, pc); break; + case 2: cpu->exception (RI, ANY, 0); break; /* cfc0 - reserved */ + case 4: mtc0_emulate (instr, pc); break; + case 6: cpu->exception (RI, ANY, 0); break; /* ctc0 - reserved */ + case 8: bc0x_emulate (instr,pc); break; + default: cpu->exception (RI, ANY, 0); break; + } + } +} + +void +CPZero::adjust_random(void) +{ +//ao modified + int32 r = (int32) (reg[Random] >> 8); + if(r <= 8) r = 63; else r--; + reg[Random] = (uint32) (r << 8); +} + +uint32 +CPZero::getIP(void) +{ + return (reg[Cause] & Cause_IP_SW_MASK) | ao_interrupts(); +} + +void +CPZero::enter_exception(uint32 pc, uint32 excCode, uint32 ce, bool dly) +{ + /* Save exception PC in EPC. */ + reg[EPC] = pc; + /* Disable interrupts and enter Kernel mode. */ + reg[Status] = (reg[Status] & ~Status_KU_IE_MASK) | + ((reg[Status] & Status_KU_IE_MASK) << 2); + /* Clear Cause register BD, CE, and ExcCode fields. */ + reg[Cause] &= ~(Cause_BD_MASK|Cause_CE_MASK|Cause_ExcCode_MASK); + /* Set Cause register CE field if this is a Coprocessor + * Unusable exception. (If we are passed ce=-1 we don't want + * to toggle bits in Cause.) */ + if (excCode == CpU) { + reg[Cause] |= ((ce & 0x3) << 28); + } + /* Update IP, BD, ExcCode fields of Cause register. */ + reg[Cause] &= ~Cause_IP_MASK; + reg[Cause] |= getIP () | (dly << 31) | (excCode << 2); +} + +bool +CPZero::use_boot_excp_address(void) +{ + return (reg[Status] & Status_DS_BEV_MASK); +} + +bool +CPZero::caches_isolated(void) +{ + return (reg[Status] & Status_DS_IsC_MASK); +} + +bool +CPZero::caches_swapped(void) +{ + return (reg[Status] & Status_DS_SwC_MASK); +} + +bool +CPZero::cop_usable(int coprocno) +{ + switch (coprocno) { + case 3: return (reg[Status] & Status_CU3_MASK); + case 2: return (reg[Status] & Status_CU2_MASK); + case 1: return (reg[Status] & Status_CU1_MASK); + case 0: return (reg[Status] & Status_CU0_MASK); + default: fatal_error ("Bad coprocno passed to CPZero::cop_usable()"); + }; +} + +bool +CPZero::interrupts_enabled(void) const +{ + return (reg[Status] & Status_IEc_MASK); +} + +bool +CPZero::interrupt_pending(void) +{ + if (! interrupts_enabled()) + return false; /* Can't very well argue with IEc == 0... */ + /* Mask IP with the interrupt mask, and return true if nonzero: */ + return ((getIP () & (reg[Status] & Status_IM_MASK)) != 0); +} + +//------------------------------------------------------------------------------ cpu.cc + +/* certain fixed register numbers which are handy to know */ +static const int reg_zero = 0; /* always zero */ +static const int reg_sp = 29; /* stack pointer */ +static const int reg_ra = 31; /* return address */ + +/* pointer to CPU method returning void and taking two uint32's */ +typedef void (CPU::*emulate_funptr)(uint32, uint32); + +CPU::CPU () : last_epc (0), last_prio (0), + cpzero (new CPZero (this)), delay_state (NORMAL) +{ + reg[reg_zero] = 0; +} + +CPU::~CPU() { +} + +void CPU::reset () { + reg[reg_zero] = 0; + pc = 0xbfc00000; + cpzero->reset(); +} + +int +CPU::exception_priority(uint16 excCode, int mode) const +{ + /* See doc/excprio for an explanation of this table. */ + static const struct excPriority prio[] = { + {1, AdEL, INSTFETCH}, + {2, TLBL, INSTFETCH}, {2, TLBS, INSTFETCH}, + {3, IBE, ANY}, + {4, Ov, ANY}, {4, Tr, ANY}, {4, Sys, ANY}, + {4, Bp, ANY}, {4, RI, ANY}, {4, CpU, ANY}, + {5, AdEL, DATALOAD}, {5, AdES, ANY}, + {6, TLBL, DATALOAD}, {6, TLBS, DATALOAD}, + {6, TLBL, DATASTORE}, {6, TLBS, DATASTORE}, + {7, Mod, ANY}, + {8, DBE, ANY}, + {9, Int, ANY}, + {0, ANY, ANY} /* catch-all */ + }; + const struct excPriority *p; + + for (p = prio; p->priority != 0; p++) { + if (excCode == p->excCode || p->excCode == ANY) { + if (mode == p->mode || p->mode == ANY) { + return p->priority; + } + } + } + return 0; +} + +void +CPU::exception(uint16 excCode, int mode /* = ANY */, int coprocno /* = -1 */) +{ +printf("Exception: code: 0x%x, mode: %x, coprocno: %x\n", (uint32)excCode, mode, coprocno); + int prio; + uint32 base, vector, epc; + bool delaying = (delay_state == DELAYSLOT); + + /* step() ensures that next_epc will always contain the correct + * EPC whenever exception() is called. + */ + epc = next_epc; + + /* Prioritize exception -- if the last exception to occur _also_ was + * caused by this EPC, only report this exception if it has a higher + * priority. Otherwise, exception handling terminates here, + * because only one exception will be reported per instruction + * (as per MIPS RISC Architecture, p. 6-35). Note that this only + * applies IFF the previous exception was caught during the current + * _execution_ of the instruction at this EPC, so we check that + * EXCEPTION_PENDING is true before aborting exception handling. + * (This flag is reset by each call to step().) + */ + prio = exception_priority(excCode, mode); + if (epc == last_epc) { + if (prio <= last_prio && exception_pending) { + return; + } else { + last_prio = prio; + } + } + last_epc = epc; + + /* Set processor to Kernel mode, disable interrupts, and save + * exception PC. + */ + cpzero->enter_exception(epc,excCode,coprocno,delaying); + + /* Calculate the exception handler address; this is of the form BASE + + * VECTOR. The BASE is determined by whether we're using boot-time + * exception vectors, according to the BEV bit in the CP0 Status register. + */ + if (cpzero->use_boot_excp_address()) { + base = 0xbfc00100; + } else { + base = 0x80000000; + } + + /* Do we have a User TLB Miss exception? If so, jump to the + * User TLB Miss exception vector, otherwise jump to the + * common exception vector. + */ + if ((excCode == TLBL || excCode == TLBS) && (cpzero->tlb_miss_user)) { + vector = 0x000; + } else { + vector = 0x080; + } + + pc = base + vector; + exception_pending = true; +} + +/* emulation of instructions */ +void +CPU::cpzero_emulate(uint32 instr, uint32 pc) +{ + cpzero->cpzero_emulate(instr, pc); +} + +/* Called when the program wants to use coprocessor COPROCNO, and there + * isn't any implementation for that coprocessor. + * Results in a Coprocessor Unusable exception, along with an error + * message being printed if the coprocessor is marked usable in the + * CP0 Status register. + */ +void +CPU::cop_unimpl (int coprocno, uint32 instr, uint32 pc) +{ + exception (CpU, ANY, coprocno); +} + +void +CPU::cpone_emulate(uint32 instr, uint32 pc) +{ + /* If it's a cfc1 , $0 then we copy 0 into reg, + * which is supposed to mean there is NO cp1... + * for now, though, ANYTHING else asked of cp1 results + * in the default "unimplemented" behavior. */ + if (cpzero->cop_usable (1) && rs (instr) == 2 + && rd (instr) == 0) { + reg[rt (instr)] = 0; /* No cp1. */ + } else { + cop_unimpl (1, instr, pc); + } +} + +void +CPU::cptwo_emulate(uint32 instr, uint32 pc) +{ + cop_unimpl (2, instr, pc); +} + +void +CPU::cpthree_emulate(uint32 instr, uint32 pc) +{ + cop_unimpl (3, instr, pc); +} + +void +CPU::control_transfer (uint32 new_pc) +{ + delay_state = DELAYING; + delay_pc = new_pc; +} + +/// calc_jump_target - Calculate the address to jump to as a result of +/// the J-format (jump) instruction INSTR at address PC. (PC is the address +/// of the jump instruction, and INSTR is the jump instruction word.) +/// +uint32 +CPU::calc_jump_target (uint32 instr, uint32 pc) +{ + // Must use address of delay slot (pc + 4) to calculate. + return ((pc + 4) & 0xf0000000) | (jumptarg(instr) << 2); +} + +void +CPU::jump(uint32 instr, uint32 pc) +{ + control_transfer (calc_jump_target (instr, pc)); +} + +void +CPU::j_emulate(uint32 instr, uint32 pc) +{ + jump (instr, pc); +} + +void +CPU::jal_emulate(uint32 instr, uint32 pc) +{ + jump (instr, pc); + // RA gets addr of instr after delay slot (2 words after this one). + reg[reg_ra] = pc + 8; +} + +/// calc_branch_target - Calculate the address to jump to for the +/// PC-relative branch for which the offset is specified by the immediate field +/// of the branch instruction word INSTR, with the program counter equal to PC. +/// +uint32 +CPU::calc_branch_target(uint32 instr, uint32 pc) +{ + return (pc + 4) + (s_immed(instr) << 2); +} + +void +CPU::branch(uint32 instr, uint32 pc) +{ + control_transfer (calc_branch_target (instr, pc)); +} + +void +CPU::beq_emulate(uint32 instr, uint32 pc) +{ + if (reg[rs(instr)] == reg[rt(instr)]) + branch (instr, pc); +} + +void +CPU::bne_emulate(uint32 instr, uint32 pc) +{ + if (reg[rs(instr)] != reg[rt(instr)]) + branch (instr, pc); +} + +void +CPU::blez_emulate(uint32 instr, uint32 pc) +{ + if (rt(instr) != 0) { + exception(RI); + return; + } + if (reg[rs(instr)] == 0 || (reg[rs(instr)] & 0x80000000)) + branch(instr, pc); +} + +void +CPU::bgtz_emulate(uint32 instr, uint32 pc) +{ + if (rt(instr) != 0) { + exception(RI); + return; + } + if (reg[rs(instr)] != 0 && (reg[rs(instr)] & 0x80000000) == 0) + branch(instr, pc); +} + +void +CPU::addi_emulate(uint32 instr, uint32 pc) +{ + int32 a, b, sum; + + a = (int32)reg[rs(instr)]; + b = s_immed(instr); + sum = a + b; + if ((a < 0 && b < 0 && !(sum < 0)) || (a >= 0 && b >= 0 && !(sum >= 0))) { + exception(Ov); + return; + } else { + reg[rt(instr)] = (uint32)sum; + } +} + +void +CPU::addiu_emulate(uint32 instr, uint32 pc) +{ + int32 a, b, sum; + + a = (int32)reg[rs(instr)]; + b = s_immed(instr); + sum = a + b; + reg[rt(instr)] = (uint32)sum; +} + +void +CPU::slti_emulate(uint32 instr, uint32 pc) +{ + int32 s_rs = reg[rs(instr)]; + + if (s_rs < s_immed(instr)) { + reg[rt(instr)] = 1; + } else { + reg[rt(instr)] = 0; + } +} + +void +CPU::sltiu_emulate(uint32 instr, uint32 pc) +{ + if (reg[rs(instr)] < (uint32)(int32)s_immed(instr)) { + reg[rt(instr)] = 1; + } else { + reg[rt(instr)] = 0; + } +} + +void +CPU::andi_emulate(uint32 instr, uint32 pc) +{ + reg[rt(instr)] = (reg[rs(instr)] & 0x0ffff) & immed(instr); +} + +void +CPU::ori_emulate(uint32 instr, uint32 pc) +{ + reg[rt(instr)] = reg[rs(instr)] | immed(instr); +} + +void +CPU::xori_emulate(uint32 instr, uint32 pc) +{ + reg[rt(instr)] = reg[rs(instr)] ^ immed(instr); +} + +void +CPU::lui_emulate(uint32 instr, uint32 pc) +{ + reg[rt(instr)] = immed(instr) << 16; +} + +void +CPU::lb_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, base; + int8 byte; + int32 offset; + bool cacheable, isolated; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(virt, DATALOAD, &cacheable, &isolated); + if (exception_pending) return; + + /* Fetch byte. + * Because it is assigned to a signed variable (int32 byte) + * it will be sign-extended. + */ + byte = ao_fetch_byte(phys, cacheable, isolated); + if (exception_pending) return; + + /* Load target register with data. */ + reg[rt(instr)] = byte; +} + +void +CPU::lh_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, base; + int16 halfword; + int32 offset; + bool cacheable, isolated; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + + /* This virtual address must be halfword-aligned. */ + if (virt % 2 != 0) { + exception(AdEL,DATALOAD); + return; + } + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(virt, DATALOAD, &cacheable, &isolated); + if (exception_pending) return; + + /* Fetch halfword. + * Because it is assigned to a signed variable (int32 halfword) + * it will be sign-extended. + */ + halfword = ao_fetch_halfword(phys, cacheable, isolated); + if (exception_pending) return; + + /* Load target register with data. */ + reg[rt(instr)] = halfword; +} + +/* The lwr and lwl algorithms here are taken from SPIM 6.0, + * since I didn't manage to come up with a better way to write them. + * Improvements are welcome. + */ +uint32 +CPU::lwr(uint32 regval, uint32 memval, uint8 offset) +{ + switch (offset) + { + /* The SPIM source claims that "The description of the + * little-endian case in Kane is totally wrong." The fact + * that I ripped off the LWR algorithm from them could be + * viewed as a sort of passive assumption that their claim + * is correct. + */ + case 0: /* 3 in book */ + return memval; + case 1: /* 0 in book */ + return (regval & 0xff000000) | ((memval & 0xffffff00) >> 8); + case 2: /* 1 in book */ + return (regval & 0xffff0000) | ((memval & 0xffff0000) >> 16); + case 3: /* 2 in book */ + return (regval & 0xffffff00) | ((memval & 0xff000000) >> 24); + } + fatal_error("Invalid offset %x passed to lwr\n", offset); +} + +uint32 +CPU::lwl(uint32 regval, uint32 memval, uint8 offset) +{ + switch (offset) + { + case 0: return (memval & 0xff) << 24 | (regval & 0xffffff); + case 1: return (memval & 0xffff) << 16 | (regval & 0xffff); + case 2: return (memval & 0xffffff) << 8 | (regval & 0xff); + case 3: return memval; + } + fatal_error("Invalid offset %x passed to lwl\n", offset); +} + +void +CPU::lwl_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, wordvirt, base, memword; + uint8 which_byte; + int32 offset; + bool cacheable, isolated; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + /* We request the word containing the byte-address requested. */ + wordvirt = virt & ~0x03UL; + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(wordvirt, DATALOAD, &cacheable, &isolated); + if (exception_pending) return; + + /* Fetch word. */ + memword = ao_fetch_word(phys, DATALOAD, cacheable, isolated); + if (exception_pending) return; + + /* Insert bytes into the left side of the register. */ + which_byte = virt & 0x03; + reg[rt(instr)] = lwl(reg[rt(instr)], memword, which_byte); +} + +void +CPU::lw_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, base, word; + int32 offset; + bool cacheable, isolated; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + + /* This virtual address must be word-aligned. */ + if (virt % 4 != 0) { + exception(AdEL,DATALOAD); + return; + } + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(virt, DATALOAD, &cacheable, &isolated); + if (exception_pending) return; + + /* Fetch word. */ + word = ao_fetch_word(phys, DATALOAD, cacheable, isolated); + if (exception_pending) return; + + /* Load target register with data. */ + reg[rt(instr)] = word; +} + +void +CPU::lbu_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, base, byte; + int32 offset; + bool cacheable, isolated; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(virt, DATALOAD, &cacheable, &isolated); + if (exception_pending) return; + + /* Fetch byte. */ + byte = ao_fetch_byte(phys, cacheable, isolated) & 0x000000ff; + if (exception_pending) return; + + /* Load target register with data. */ + reg[rt(instr)] = byte; +} + +void +CPU::lhu_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, base, halfword; + int32 offset; + bool cacheable, isolated; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + + /* This virtual address must be halfword-aligned. */ + if (virt % 2 != 0) { + exception(AdEL,DATALOAD); + return; + } + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(virt, DATALOAD, &cacheable, &isolated); + if (exception_pending) return; + + /* Fetch halfword. */ + halfword = ao_fetch_halfword(phys, cacheable, isolated) & 0x0000ffff; + if (exception_pending) return; + + /* Load target register with data. */ + reg[rt(instr)] = halfword; +} + +void +CPU::lwr_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, wordvirt, base, memword; + uint8 which_byte; + int32 offset; + bool cacheable, isolated; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + /* We request the word containing the byte-address requested. */ + wordvirt = virt & ~0x03UL; + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(wordvirt, DATALOAD, &cacheable, &isolated); + if (exception_pending) return; + + /* Fetch word. */ + memword = ao_fetch_word(phys, DATALOAD, cacheable, isolated); + if (exception_pending) return; + + /* Insert bytes into the left side of the register. */ + which_byte = virt & 0x03; + reg[rt(instr)] = lwr(reg[rt(instr)], memword, which_byte); +} + +void +CPU::sb_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, base; + uint8 data; + int32 offset; + bool cacheable, isolated; + + /* Load data from register. */ + data = reg[rt(instr)] & 0x0ff; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(virt, DATASTORE, &cacheable, &isolated); + if (exception_pending) return; + + /* Store byte. */ + ao_store_byte(phys, data, cacheable, isolated); +} + +void +CPU::sh_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, base; + uint16 data; + int32 offset; + bool cacheable, isolated; + + /* Load data from register. */ + data = reg[rt(instr)] & 0x0ffff; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + + /* This virtual address must be halfword-aligned. */ + if (virt % 2 != 0) { + exception(AdES,DATASTORE); + return; + } + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(virt, DATASTORE, &cacheable, &isolated); + if (exception_pending) return; + + /* Store halfword. */ + ao_store_halfword(phys, data, cacheable, isolated); +} + +uint32 +CPU::swl(uint32 regval, uint32 memval, uint8 offset) +{ + switch (offset) { + case 0: return (memval & 0xffffff00) | (regval >> 24 & 0xff); + case 1: return (memval & 0xffff0000) | (regval >> 16 & 0xffff); + case 2: return (memval & 0xff000000) | (regval >> 8 & 0xffffff); + case 3: return regval; + } + fatal_error("Invalid offset %x passed to swl\n", offset); +} + +uint32 +CPU::swr(uint32 regval, uint32 memval, uint8 offset) +{ + switch (offset) { + case 0: return regval; + case 1: return ((regval << 8) & 0xffffff00) | (memval & 0xff); + case 2: return ((regval << 16) & 0xffff0000) | (memval & 0xffff); + case 3: return ((regval << 24) & 0xff000000) | (memval & 0xffffff); + } + fatal_error("Invalid offset %x passed to swr\n", offset); +} + +void +CPU::swl_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, wordvirt, base, regdata, memdata; + int32 offset; + uint8 which_byte; + bool cacheable, isolated; + + /* Load data from register. */ + regdata = reg[rt(instr)]; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + /* We request the word containing the byte-address requested. */ + wordvirt = virt & ~0x03UL; + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(wordvirt, DATASTORE, &cacheable, &isolated); + if (exception_pending) return; + + /* Read data from memory. */ + //memdata = ao_fetch_word(phys, DATASTORE, cacheable); + //if (exception_pending) return; + + /* Write back the left side of the register. */ + which_byte = virt & 0x03UL; + //ao_store_word(phys, swl(regdata, memdata, which_byte), cacheable); + uint32 store_value = + (which_byte == 0)? (regdata >> 24 & 0xff) : + (which_byte == 1)? (regdata >> 16 & 0xffff) : + (which_byte == 2)? (regdata >> 8 & 0xffffff) : + regdata; + uint32 store_byteena = + (which_byte == 0)? 0b0001 : + (which_byte == 1)? 0b0011 : + (which_byte == 2)? 0b0111 : + 0b1111; + ao_store_word(phys, store_value, cacheable, isolated, store_byteena); +} + +void +CPU::sw_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, base, data; + int32 offset; + bool cacheable, isolated; + + /* Load data from register. */ + data = reg[rt(instr)]; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + + /* This virtual address must be word-aligned. */ + if (virt % 4 != 0) { + exception(AdES,DATASTORE); + return; + } + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(virt, DATASTORE, &cacheable, &isolated); + if (exception_pending) return; + + /* Store word. */ + ao_store_word(phys, data, cacheable, isolated); +} + +void +CPU::swr_emulate(uint32 instr, uint32 pc) +{ + uint32 phys, virt, wordvirt, base, regdata, memdata; + int32 offset; + uint8 which_byte; + bool cacheable, isolated; + + /* Load data from register. */ + regdata = reg[rt(instr)]; + + /* Calculate virtual address. */ + base = reg[rs(instr)]; + offset = s_immed(instr); + virt = base + offset; + /* We request the word containing the byte-address requested. */ + wordvirt = virt & ~0x03UL; + + /* Translate virtual address to physical address. */ + phys = cpzero->address_trans(wordvirt, DATASTORE, &cacheable, &isolated); + if (exception_pending) return; + + /* Read data from memory. */ + //memdata = ao_fetch_word(phys, DATASTORE, cacheable); + //if (exception_pending) return; + + /* Write back the right side of the register. */ + which_byte = virt & 0x03UL; + //ao_store_word(phys, swr(regdata, memdata, which_byte), cacheable); + + uint32 store_value = + (which_byte == 0)? regdata : + (which_byte == 1)? ((regdata << 8) & 0xffffff00) : + (which_byte == 2)? ((regdata << 16) & 0xffff0000) : + ((regdata << 24) & 0xff000000); + uint32 store_byteena = + (which_byte == 0)? 0b1111 : + (which_byte == 1)? 0b1110 : + (which_byte == 2)? 0b1100 : + 0b1000; + ao_store_word(phys, store_value, cacheable, isolated, store_byteena); +} + +void +CPU::lwc1_emulate(uint32 instr, uint32 pc) +{ + cop_unimpl (1, instr, pc); +} + +void +CPU::lwc2_emulate(uint32 instr, uint32 pc) +{ + cop_unimpl (2, instr, pc); +} + +void +CPU::lwc3_emulate(uint32 instr, uint32 pc) +{ + cop_unimpl (3, instr, pc); +} + +void +CPU::swc1_emulate(uint32 instr, uint32 pc) +{ + cop_unimpl (1, instr, pc); +} + +void +CPU::swc2_emulate(uint32 instr, uint32 pc) +{ + cop_unimpl (2, instr, pc); +} + +void +CPU::swc3_emulate(uint32 instr, uint32 pc) +{ + cop_unimpl (3, instr, pc); +} + +void +CPU::sll_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = reg[rt(instr)] << shamt(instr); +} + +int32 +srl(int32 a, int32 b) +{ + if (b == 0) { + return a; + } else if (b == 32) { + return 0; + } else { + return (a >> b) & ((1 << (32 - b)) - 1); + } +} + +int32 +sra(int32 a, int32 b) +{ + if (b == 0) { + return a; + } else { + return (a >> b) | (((a >> 31) & 0x01) * (((1 << b) - 1) << (32 - b))); + } +} + +void +CPU::srl_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = srl(reg[rt(instr)], shamt(instr)); +} + +void +CPU::sra_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = sra(reg[rt(instr)], shamt(instr)); +} + +void +CPU::sllv_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = reg[rt(instr)] << (reg[rs(instr)] & 0x01f); +} + +void +CPU::srlv_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = srl(reg[rt(instr)], reg[rs(instr)] & 0x01f); +} + +void +CPU::srav_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = sra(reg[rt(instr)], reg[rs(instr)] & 0x01f); +} + +void +CPU::jr_emulate(uint32 instr, uint32 pc) +{ + if (reg[rd(instr)] != 0) { + exception(RI); + return; + } + control_transfer (reg[rs(instr)]); +} + +void +CPU::jalr_emulate(uint32 instr, uint32 pc) +{ + control_transfer (reg[rs(instr)]); + /* RA gets addr of instr after delay slot (2 words after this one). */ + reg[rd(instr)] = pc + 8; +} + +void +CPU::syscall_emulate(uint32 instr, uint32 pc) +{ + exception(Sys); +} + +void +CPU::break_emulate(uint32 instr, uint32 pc) +{ + exception(Bp); +} + +void +CPU::mfhi_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = hi; +} + +void +CPU::mthi_emulate(uint32 instr, uint32 pc) +{ + if (rd(instr) != 0) { + exception(RI); + return; + } + hi = reg[rs(instr)]; +} + +void +CPU::mflo_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = lo; +} + +void +CPU::mtlo_emulate(uint32 instr, uint32 pc) +{ + if (rd(instr) != 0) { + exception(RI); + return; + } + lo = reg[rs(instr)]; +} + +void +CPU::mult_emulate(uint32 instr, uint32 pc) +{ + if (rd(instr) != 0) { + exception(RI); + return; + } + mult64s(&hi, &lo, reg[rs(instr)], reg[rt(instr)]); +} + +void +CPU::mult64(uint32 *hi, uint32 *lo, uint32 n, uint32 m) +{ + uint64 result; + result = ((uint64)n) * ((uint64)m); + *hi = (uint32) (result >> 32); + *lo = (uint32) result; +} + +void +CPU::mult64s(uint32 *hi, uint32 *lo, int32 n, int32 m) +{ + int64 result; + result = ((int64)n) * ((int64)m); + *hi = (uint32) (result >> 32); + *lo = (uint32) result; +} + +void +CPU::multu_emulate(uint32 instr, uint32 pc) +{ + if (rd(instr) != 0) { + exception(RI); + return; + } + mult64(&hi, &lo, reg[rs(instr)], reg[rt(instr)]); +} + +void +CPU::div_emulate(uint32 instr, uint32 pc) +{ + int32 signed_rs = (int32)reg[rs(instr)]; + int32 signed_rt = (int32)reg[rt(instr)]; + + if(signed_rt == 0) { + lo = (signed_rs >= 0)? 0xFFFFFFFF : 0x00000001; + hi = signed_rs; + } + else { + lo = signed_rs / signed_rt; + hi = signed_rs % signed_rt; + } +} + +void +CPU::divu_emulate(uint32 instr, uint32 pc) +{ + if(reg[rt(instr)] == 0) { + lo = 0xFFFFFFFF; + hi = reg[rs(instr)]; + } + else { + lo = reg[rs(instr)] / reg[rt(instr)]; + hi = reg[rs(instr)] % reg[rt(instr)]; + } +} + +void +CPU::add_emulate(uint32 instr, uint32 pc) +{ + int32 a, b, sum; + a = (int32)reg[rs(instr)]; + b = (int32)reg[rt(instr)]; + sum = a + b; + if ((a < 0 && b < 0 && !(sum < 0)) || (a >= 0 && b >= 0 && !(sum >= 0))) { + exception(Ov); + return; + } else { + reg[rd(instr)] = (uint32)sum; + } +} + +void +CPU::addu_emulate(uint32 instr, uint32 pc) +{ + int32 a, b, sum; + a = (int32)reg[rs(instr)]; + b = (int32)reg[rt(instr)]; + sum = a + b; + reg[rd(instr)] = (uint32)sum; +} + +void +CPU::sub_emulate(uint32 instr, uint32 pc) +{ + int32 a, b, diff; + a = (int32)reg[rs(instr)]; + b = (int32)reg[rt(instr)]; + diff = a - b; + if ((a < 0 && !(b < 0) && !(diff < 0)) || (!(a < 0) && b < 0 && diff < 0)) { + exception(Ov); + return; + } else { + reg[rd(instr)] = (uint32)diff; + } +} + +void +CPU::subu_emulate(uint32 instr, uint32 pc) +{ + int32 a, b, diff; + a = (int32)reg[rs(instr)]; + b = (int32)reg[rt(instr)]; + diff = a - b; + reg[rd(instr)] = (uint32)diff; +} + +void +CPU::and_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = reg[rs(instr)] & reg[rt(instr)]; +} + +void +CPU::or_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = reg[rs(instr)] | reg[rt(instr)]; +} + +void +CPU::xor_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = reg[rs(instr)] ^ reg[rt(instr)]; +} + +void +CPU::nor_emulate(uint32 instr, uint32 pc) +{ + reg[rd(instr)] = ~(reg[rs(instr)] | reg[rt(instr)]); +} + +void +CPU::slt_emulate(uint32 instr, uint32 pc) +{ + int32 s_rs = (int32)reg[rs(instr)]; + int32 s_rt = (int32)reg[rt(instr)]; + if (s_rs < s_rt) { + reg[rd(instr)] = 1; + } else { + reg[rd(instr)] = 0; + } +} + +void +CPU::sltu_emulate(uint32 instr, uint32 pc) +{ + if (reg[rs(instr)] < reg[rt(instr)]) { + reg[rd(instr)] = 1; + } else { + reg[rd(instr)] = 0; + } +} + +void +CPU::bltz_emulate(uint32 instr, uint32 pc) +{ + if ((int32)reg[rs(instr)] < 0) + branch(instr, pc); +} + +void +CPU::bgez_emulate(uint32 instr, uint32 pc) +{ + if ((int32)reg[rs(instr)] >= 0) + branch(instr, pc); +} + +/* As with JAL, BLTZAL and BGEZAL cause RA to get the address of the + * instruction two words after the current one (pc + 8). + */ +void +CPU::bltzal_emulate(uint32 instr, uint32 pc) +{ + reg[reg_ra] = pc + 8; + if ((int32)reg[rs(instr)] < 0) + branch(instr, pc); +} + +void +CPU::bgezal_emulate(uint32 instr, uint32 pc) +{ + reg[reg_ra] = pc + 8; + if ((int32)reg[rs(instr)] >= 0) + branch(instr, pc); +} + +/* reserved instruction */ +void +CPU::RI_emulate(uint32 instr, uint32 pc) +{ + exception(RI); +} + +/* dispatching */ +int +CPU::step(bool debug) +{ + // Table of emulation functions. + static const emulate_funptr opcodeJumpTable[] = { + &CPU::funct_emulate, &CPU::regimm_emulate, &CPU::j_emulate, + &CPU::jal_emulate, &CPU::beq_emulate, &CPU::bne_emulate, + &CPU::blez_emulate, &CPU::bgtz_emulate, &CPU::addi_emulate, + &CPU::addiu_emulate, &CPU::slti_emulate, &CPU::sltiu_emulate, + &CPU::andi_emulate, &CPU::ori_emulate, &CPU::xori_emulate, + &CPU::lui_emulate, &CPU::cpzero_emulate, &CPU::cpone_emulate, + &CPU::cptwo_emulate, &CPU::cpthree_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, &CPU::lb_emulate, + &CPU::lh_emulate, &CPU::lwl_emulate, &CPU::lw_emulate, + &CPU::lbu_emulate, &CPU::lhu_emulate, &CPU::lwr_emulate, + &CPU::RI_emulate, &CPU::sb_emulate, &CPU::sh_emulate, + &CPU::swl_emulate, &CPU::sw_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::swr_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::lwc1_emulate, &CPU::lwc2_emulate, + &CPU::lwc3_emulate, &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::swc1_emulate, &CPU::swc2_emulate, &CPU::swc3_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate + }; + + // Clear exception_pending flag if it was set by a prior instruction. + exception_pending = false; + + // Decrement Random register every clock cycle. + //changed only after tlbwr + //cpzero->adjust_random(); + + // Save address of instruction responsible for exceptions which may occur. + if (delay_state != DELAYSLOT) + next_epc = pc; + + bool cacheable, isolated; + uint32 real_pc; + + //AdE + if (pc % 4 != 0) { + exception(AdEL,INSTFETCH); + goto out; + } + + // Get physical address of next instruction. + real_pc = cpzero->address_trans(pc,INSTFETCH,&cacheable,&isolated); + if (exception_pending) { + goto out; + } + + // Fetch next instruction. + instr = ao_fetch_word(real_pc,INSTFETCH,cacheable,isolated); + if (exception_pending) { + goto out; + } + + //interrupt check moved below + + // Emulate the instruction by jumping to the appropriate emulation method. + +static uint32 instr_cnt = 0; +if(debug) { + printf("[%d] table: %d instr: %08x pc: %08x\n", instr_cnt, opcode(instr), instr, pc); + for(int i=1; i<32; i++) printf("%08x ", reg[i]); printf("\n"); +} +instr_cnt++; + + (this->*opcodeJumpTable[opcode(instr)])(instr, pc); + +out: + // Force register zero to contain zero. + reg[reg_zero] = 0; + + // If an exception is pending, then the PC has already been changed to + // contain the exception vector. Return now, so that we don't clobber it. + if (exception_pending) { + // Instruction at beginning of exception handler is NOT in delay slot, + // no matter what the last instruction was. + delay_state = NORMAL; + return 1; + } + + // Recall the delay_state values: 0=NORMAL, 1=DELAYING, 2=DELAYSLOT. + // This is what the delay_state values mean (at this point in the code): + // DELAYING: The last instruction caused a branch to be taken. + // The next instruction is in the delay slot. + // The next instruction EPC will be PC - 4. + // DELAYSLOT: The last instruction was executed in a delay slot. + // The next instruction is on the other end of the branch. + // The next instruction EPC will be PC. + // NORMAL: No branch was executed; next instruction is at PC + 4. + // Next instruction EPC is PC. + + // Update the pc and delay_state values. + pc += 4; + was_delayed_transfer = false; + if (delay_state == DELAYSLOT) { + was_delayed_transfer = true; + was_delayed_pc = pc; + + pc = delay_pc; + } + delay_state = (delay_state << 1) & 0x03; // 0->0, 1->2, 2->0 + + // Check for a (hardware or software) interrupt. + if (cpzero->interrupt_pending()) { + if(delay_state != DELAYSLOT) next_epc = pc; + + exception(Int); + delay_state = NORMAL; + return 2; + } + + return 0; +} + +void +CPU::funct_emulate(uint32 instr, uint32 pc) +{ + static const emulate_funptr functJumpTable[] = { + &CPU::sll_emulate, &CPU::RI_emulate, + &CPU::srl_emulate, &CPU::sra_emulate, + &CPU::sllv_emulate, &CPU::RI_emulate, + &CPU::srlv_emulate, &CPU::srav_emulate, + &CPU::jr_emulate, &CPU::jalr_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::syscall_emulate, &CPU::break_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::mfhi_emulate, &CPU::mthi_emulate, + &CPU::mflo_emulate, &CPU::mtlo_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::mult_emulate, &CPU::multu_emulate, + &CPU::div_emulate, &CPU::divu_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::add_emulate, &CPU::addu_emulate, + &CPU::sub_emulate, &CPU::subu_emulate, + &CPU::and_emulate, &CPU::or_emulate, + &CPU::xor_emulate, &CPU::nor_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::slt_emulate, &CPU::sltu_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate, + &CPU::RI_emulate, &CPU::RI_emulate + }; + (this->*functJumpTable[funct(instr)])(instr, pc); +} + +void +CPU::regimm_emulate(uint32 instr, uint32 pc) +{ + switch(rt(instr)) + { + case 0: bltz_emulate(instr, pc); break; + case 1: bgez_emulate(instr, pc); break; + case 16: bltzal_emulate(instr, pc); break; + case 17: bgezal_emulate(instr, pc); break; + default: exception(RI); break; /* reserved instruction */ + } +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ Index: trunk/sim/vmips/main_tester.cpp =================================================================== --- trunk/sim/vmips/main_tester.cpp (nonexistent) +++ trunk/sim/vmips/main_tester.cpp (revision 2) @@ -0,0 +1,346 @@ +/* + * This file is subject to the terms and conditions of the GPL License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "shared_mem.h" +#include "vmips_emulator.h" + +//------------------------------------------------------------------------------ + +volatile shared_mem_t *shared_ptr = NULL; + +//------------------------------------------------------------------------------ + + +#define GET(field, mask) \ + (shared_ptr->initial.field & mask) + +void CPZero::initialize() { + for(int i=0; i<64; i++) { + tlb[i].entryHi = 0; + tlb[i].entryHi |= GET(tlb[i].vpn, 0xFFFFF) << 12; + tlb[i].entryHi |= GET(tlb[i].asid, 0x3F) << 6; + + tlb[i].entryLo = 0; + tlb[i].entryLo |= GET(tlb[i].pfn, 0xFFFFF) << 12; + tlb[i].entryLo |= GET(tlb[i].n, 0x1) << 11; + tlb[i].entryLo |= GET(tlb[i].d, 0x1) << 10; + tlb[i].entryLo |= GET(tlb[i].v, 0x1) << 9; + tlb[i].entryLo |= GET(tlb[i].g, 0x1) << 8; + } + for(int i=0; i<32; i++) reg[i] = 0; //cp0 regs + + reg[0] |= GET(index_p, 0x1) << 31; + reg[0] |= GET(index_index, 0x3F) << 8; + + reg[1] |= GET(random, 0x3F) << 8; + + reg[2] |= GET(entrylo_pfn, 0xFFFFF) << 12; + reg[2] |= GET(entrylo_n, 0x1) << 11; + reg[2] |= GET(entrylo_d, 0x1) << 10; + reg[2] |= GET(entrylo_v, 0x1) << 9; + reg[2] |= GET(entrylo_g, 0x1) << 8; + + reg[4] |= GET(context_ptebase, 0x7FF) << 21; + reg[4] |= GET(context_badvpn, 0x7FFFF) << 2; + + reg[8] |= GET(bad_vaddr, 0xFFFFFFFF); + + reg[10] |= GET(entryhi_vpn, 0xFFFFF) << 12; + reg[10] |= GET(entryhi_asid, 0x3F) << 6; + + reg[12] |= GET(sr_cp_usable, 0xF) << 28; + reg[12] |= GET(sr_rev_endian, 0x1) << 25; + reg[12] |= GET(sr_bootstrap_vec, 0x1) << 22; + reg[12] |= GET(sr_tlb_shutdown, 0x1) << 21; + reg[12] |= GET(sr_parity_err, 0x1) << 20; + reg[12] |= GET(sr_cache_miss, 0x1) << 19; + reg[12] |= GET(sr_parity_zero, 0x1) << 18; + reg[12] |= GET(sr_switch_cache, 0x1) << 17; + reg[12] |= GET(sr_isolate_cache, 0x1) << 16; + reg[12] |= GET(sr_irq_mask, 0xFF) << 8; + reg[12] |= GET(sr_ku_ie, 0x3F) << 0; + + reg[13] |= GET(cause_branch_delay, 0x1) << 31; + reg[13] |= GET(cause_cp_error, 0x3) << 28; + reg[13] |= GET(cause_irq_pending, 0x3) << 8; //only 2 lowest bits + reg[13] |= GET(cause_exc_code, 0x1F) << 2; + + reg[14] |= GET(epc, 0xFFFFFFFF); + + reg[15] |= 0x00000230; /* MIPS R3000A */ +} + +void CPU::initialize() { + + put_reg(0, 0); + for(int i=1; i<32; i++) { put_reg(i, GET(reg[i-1], 0xFFFFFFFF)); } + + pc = GET(pc, 0xFFFFFFFF); + //not comapred: hi = GET(hi, 0xFFFFFFFF); + //not compared: lo = GET(lo, 0xFFFFFFFF); + + cpzero->initialize(); +} + +//------------------------------------------------------------------------------ + +#define PUT(field, val, mask) \ + shared_ptr->proc_vmips.report.state.field = (val) & mask + +void CPZero::report() { + for(int i=0; i<64; i++) { + PUT(tlb[i].vpn, tlb[i].entryHi >> 12, 0xFFFFF); + PUT(tlb[i].asid, tlb[i].entryHi >> 6, 0x3F); + + PUT(tlb[i].pfn, tlb[i].entryLo >> 12, 0xFFFFF); + PUT(tlb[i].n, tlb[i].entryLo >> 11, 0x1); + PUT(tlb[i].d, tlb[i].entryLo >> 10, 0x1); + PUT(tlb[i].v, tlb[i].entryLo >> 9, 0x1); + PUT(tlb[i].g, tlb[i].entryLo >> 8, 0x1); + } + + PUT(index_p, reg[0] >> 31, 0x1); + PUT(index_index, reg[0] >> 8, 0x3F); + + PUT(random, reg[1] >> 8, 0x3F); + + PUT(entrylo_pfn, reg[2] >> 12, 0xFFFFF); + PUT(entrylo_n, reg[2] >> 11, 0x1); + PUT(entrylo_d, reg[2] >> 10, 0x1); + PUT(entrylo_v, reg[2] >> 9, 0x1); + PUT(entrylo_g, reg[2] >> 8, 0x1); + + PUT(context_ptebase, reg[4] >> 21, 0x7FF); + PUT(context_badvpn, reg[4] >> 2, 0x7FFFF); + + PUT(bad_vaddr, reg[8], 0xFFFFFFFF); + + PUT(entryhi_vpn, reg[10] >> 12, 0xFFFFF); + PUT(entryhi_asid, reg[10] >> 6, 0x3F); + + PUT(sr_cp_usable, reg[12] >> 28, 0xF); + PUT(sr_rev_endian, reg[12] >> 25, 0x1); + PUT(sr_bootstrap_vec, reg[12] >> 22, 0x1); + PUT(sr_tlb_shutdown, reg[12] >> 21, 0x1); + PUT(sr_parity_err, reg[12] >> 20, 0x1); + PUT(sr_cache_miss, reg[12] >> 19, 0x1); + PUT(sr_parity_zero, reg[12] >> 18, 0x1); + PUT(sr_switch_cache, reg[12] >> 17, 0x1); + PUT(sr_isolate_cache, reg[12] >> 16, 0x1); + PUT(sr_irq_mask, reg[12] >> 8, 0xFF); + PUT(sr_ku_ie, reg[12] >> 0, 0x3F); + + PUT(cause_branch_delay, reg[13] >> 31, 0x1); + PUT(cause_cp_error, reg[13] >> 28, 0x3); + PUT(cause_irq_pending, reg[13] >> 8, 0x3); //only 2 lowest bits + PUT(cause_exc_code, reg[13] >> 2, 0x1F); + + PUT(epc, reg[14], 0xFFFFFFFF); +} + +void CPU::report() { + for(int i=1; i<32; i++) PUT(reg[i-1], get_reg(i), 0xFFFFFFFF); + + PUT(pc, pc, 0xFFFFFFFF); + //not compared: PUT(hi, hi, 0xFFFFFFFF); + //not compared: PUT(lo, lo, 0xFFFFFFFF); + + cpzero->report(); +} + +//------------------------------------------------------------------------------ + +CPU *cpu = NULL; +uint32 event_counter = 0; + +void usleep_or_finish() { + if(shared_ptr->test_finished) { + printf("Finishing.\n"); + exit(0); + } + usleep(1); +} + +uint32 ao_interrupts() { + return (shared_ptr->irq2_at_event == event_counter)? 1 << 10 : 0; +} + +uint8 ao_fetch_byte(uint32 addr, bool cacheable, bool isolated) { + //DBE IBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + if(addr < 0x8000000) { + return shared_ptr->mem.bytes[addr]; + } + + shared_ptr->proc_vmips.read_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.read_byteenable = ((addr % 4) == 0)? 0x1 : ((addr % 4) == 1)? 0x2 : ((addr % 4) == 2)? 0x3 : 0x4; + shared_ptr->proc_vmips.read_do = true; + + while(shared_ptr->proc_vmips.read_do) usleep_or_finish(); + + return (shared_ptr->proc_vmips.read_data >> ( ((addr % 4) == 0)? 0 : ((addr % 4) == 1)? 8 : ((addr % 4) == 2)? 16 : 24 )) & 0xFF; +} + +uint16 ao_fetch_halfword(uint32 addr, bool cacheable, bool isolated) { + //AdE + if (addr % 2 != 0) { + cpu->exception(AdEL,DATALOAD); + return 0xffff; + } + + //DBE IBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + if(addr < 0x8000000) { + return shared_ptr->mem.shorts[addr/2]; + } + + shared_ptr->proc_vmips.read_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.read_byteenable = ((addr % 4) == 0)? 0x3 : 0xC; + shared_ptr->proc_vmips.read_do = true; + + while(shared_ptr->proc_vmips.read_do) usleep_or_finish(); + + return (shared_ptr->proc_vmips.read_data >> ( ((addr % 4) == 0)? 0 : 16 )) & 0xFFFF; +} + +uint32 ao_fetch_word(uint32 addr, int32 mode, bool cacheable, bool isolated) { + //AdE + if (addr % 4 != 0) { + cpu->exception(AdEL,mode); + return 0xffffffff; + } + + //DBE IBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + if(addr < 0x8000000) { + return shared_ptr->mem.ints[addr/4]; + } + + shared_ptr->proc_vmips.read_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.read_byteenable = 0xF; + shared_ptr->proc_vmips.read_do = true; + + while(shared_ptr->proc_vmips.read_do) usleep_or_finish(); + + return (shared_ptr->proc_vmips.read_data) & 0xFFFFFFFF; +} + +void ao_store_byte(uint32 addr, uint8 data, bool cacheable, bool isolated) { + //DBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + shared_ptr->proc_vmips.write_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.write_byteenable = ((addr % 4) == 0)? 0x1 : ((addr % 4) == 1)? 0x2 : ((addr % 4) == 2)? 0x4 : 0x8; + shared_ptr->proc_vmips.write_data = ((addr % 4) == 0)? data : ((addr % 4) == 1)? data << 8 : ((addr % 4) == 2)? data << 16 : data << 24; + shared_ptr->proc_vmips.write_do = true; + + while(shared_ptr->proc_vmips.write_do) usleep_or_finish(); +} + +void ao_store_halfword(uint32 addr, uint16 data, bool cacheable, bool isolated) { + //AdE + if (addr % 2 != 0) { + cpu->exception(AdES,DATASTORE); + return; + } + + //DBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + shared_ptr->proc_vmips.write_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.write_byteenable = ((addr % 4) == 0)? 0x3 : 0xC; + shared_ptr->proc_vmips.write_data = ((addr % 4) == 0)? data : data << 16; + shared_ptr->proc_vmips.write_do = true; + + while(shared_ptr->proc_vmips.write_do) usleep_or_finish(); +} + +void ao_store_word(uint32 addr, uint32 data, bool cacheable, bool isolated, uint32 byteenable) { + //AdE + if (addr % 4 != 0) { + cpu->exception(AdES,DATASTORE); + return; + } + + //DBE + //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode); + + shared_ptr->proc_vmips.write_address = addr & 0xFFFFFFFC; + shared_ptr->proc_vmips.write_byteenable = byteenable; + shared_ptr->proc_vmips.write_data = data; + shared_ptr->proc_vmips.write_do = true; + + while(shared_ptr->proc_vmips.write_do) usleep_or_finish(); +} + +void fatal_error(const char *error, ...) { + printf("[fatal_error]: %s\n", error); + exit(-1); +} + +//------------------------------------------------------------------------------ + + +int main() { + //map shared memory + int fd = open("./../tester/shared_mem.dat", O_RDWR, S_IRUSR | S_IWUSR); + + if(fd == -1) { + perror("open() failed for shared_mem.dat"); + return -1; + } + + shared_ptr = (shared_mem_t *)mmap(NULL, sizeof(shared_mem_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if(shared_ptr == MAP_FAILED) { + perror("mmap() failed"); + close(fd); + return -2; + } + + cpu = new CPU(); + cpu->reset(); + + printf("Waiting for initialize..."); fflush(stdout); + while(shared_ptr->proc_vmips.initialize_do == false) usleep_or_finish(); + + cpu->initialize(); + shared_ptr->proc_vmips.initialize_do = false; + printf("done\n"); + + while(true) { + int exception_pending = cpu->step(); + + cpu->report(); + shared_ptr->proc_vmips.report.counter = event_counter; + shared_ptr->proc_vmips.report.exception = (exception_pending > 0)? 1 : 0; + + if(cpu->was_delayed_transfer && exception_pending == 0) shared_ptr->proc_vmips.report.state.pc = cpu->was_delayed_pc; + + shared_ptr->proc_vmips.report_do = true; + + while(shared_ptr->proc_vmips.report_do) usleep_or_finish(); + + event_counter++; + } + return 0; +} + +//------------------------------------------------------------------------------ Index: trunk/sim/vmips/vmips_emulator.h =================================================================== --- trunk/sim/vmips/vmips_emulator.h (nonexistent) +++ trunk/sim/vmips/vmips_emulator.h (revision 2) @@ -0,0 +1,567 @@ +/* + * This file is subject to the terms and conditions of the GPL License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +#ifndef __VMIPS_EMULATOR_H + +#define __VMIPS_EMULATOR_H + +//------------------------------------------------------------------------------ + +uint32 ao_interrupts (); +uint8 ao_fetch_byte (uint32 addr, bool cacheable, bool isolated); +uint16 ao_fetch_halfword (uint32 addr, bool cacheable, bool isolated); +uint32 ao_fetch_word (uint32 addr, int32 mode, bool cacheable, bool isolated); +void ao_store_byte (uint32 addr, uint8 data, bool cacheable, bool isolated); +void ao_store_halfword (uint32 addr, uint16 data, bool cacheable, bool isolated); +void ao_store_word (uint32 addr, uint32 data, bool cacheable, bool isolated, uint32 byteenable = 0xF); + +void fatal_error(const char *error, ...); + +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ Code from vmips-1.4.1 project under the GPL license +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +/* MIPS R3000 CPU emulation. + Copyright 2001, 2002, 2003, 2004 Brian R. Gaeke. + +This file is part of VMIPS. + +VMIPS 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 2 of the License, or (at your +option) any later version. + +VMIPS 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 VMIPS; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +//------------------------------------------------------------------------------ excnames.h + +/* Exceptions - Cause register ExcCode field */ +#define Int 0 /* Interrupt */ +#define Mod 1 /* TLB modification exception */ +#define TLBL 2 /* TLB exception (load or instruction fetch) */ +#define TLBS 3 /* TLB exception (store) */ +#define AdEL 4 /* Address error exception (load or instruction fetch) */ +#define AdES 5 /* Address error exception (store) */ +#define IBE 6 /* Instruction bus error */ +#define DBE 7 /* Data (load or store) bus error */ +#define Sys 8 /* SYSCALL exception */ +#define Bp 9 /* Breakpoint exception (BREAK instruction) */ +#define RI 10 /* Reserved instruction exception */ +#define CpU 11 /* Coprocessor Unusable */ +#define Ov 12 /* Arithmetic Overflow */ +#define Tr 13 /* Trap (R4k/R6k only) */ +#define NCD 14 /* LDCz or SDCz to uncached address (R6k) */ +#define VCEI 14 /* Virtual Coherency Exception (instruction) (R4k) */ +#define MV 15 /* Machine check exception (R6k) */ +#define FPE 15 /* Floating-point exception (R4k) */ +/* 16-22 - reserved */ +#define WATCH 23 /* Reference to WatchHi/WatchLo address detected (R4k) */ +/* 24-30 - reserved */ +#define VCED 31 /* Virtual Coherency Exception (data) (R4k) */ + +//------------------------------------------------------------------------------ accesstypes.h + +/* Three kinds of memory accesses are possible. + * There are two kinds of load and one kind of store: + * INSTFETCH is a memory access due to an instruction fetch. + * DATALOAD is a memory access due to a load instruction, + * e.g., lw, lh, lb. + * DATASTORE is a memory access due to a store instruction, + * e.g., sw, sh, sb. + * + * ANY is a catch-all used in exception prioritizing which + * implies that none of the kinds of memory accesses applies, + * or that the type of memory access otherwise doesn't matter. + */ +#define INSTFETCH 0 +#define DATALOAD 1 +#define DATASTORE 2 +#define ANY 3 + +/* add_core_mapping and friends maintain a set of protection + * bits which define allowable access to memory. These do + * not have anything to do with the virtual memory privilege + * bits that a kernel would maintain; they are used to + * distinguish between, for example, ROM and RAM, and between + * readable and unreadable words of a memory-mapped device. + */ +#define MEM_READ 0x01 +#define MEM_WRITE 0x02 +#define MEM_READ_WRITE 0x03 + +//------------------------------------------------------------------------------ cpzeroreg.h + +/* Constants for virtual address translation. + * + * Some of these are used as masks and some are used as constant + * translations (i.e., the address of something is the address of + * something else plus or minus a translation). The desired effect is + * to reduce the number of random "magic numbers" floating around... + */ + +#define KSEG_SELECT_MASK 0xe0000000 /* bits of address which determine seg. */ +#define KUSEG 0 /* not really a mask, but user space begins here */ +#define KERNEL_SPACE_MASK 0x80000000 /* beginning of kernel space */ +#define KSEG0 0x80000000 /* beginning of unmapped cached kernel segment */ +#define KSEG0_CONST_TRANSLATION 0x80000000 /* kseg0 v->p address difference */ +#define KSEG1 0xa0000000 /* beginning of unmapped uncached kernel segment */ +#define KSEG1_CONST_TRANSLATION 0xa0000000 /* kseg1 v->p address difference */ +#define KSEG2 0xc0000000 /* beginning of mapped cached kernel segment */ +#define KSEG2_top 0xe0000000 /* 2nd half of mapped cached kernel segment */ + +/* CP0 register names and masks + * + * A table of names for CP0's registers follows. After that follow a + * series of masks by which fields of these registers can be isolated. + * The masks are convenient for Boolean flags but are slightly less so + * for numbers being extracted from the middle of a word because they + * still need to be shifted. At least, it makes clear which field is + * being accessed, and the bit numbers are clearly indicated in every mask + * below. The naming convention is as follows: Mumble is the name of some + * CP0 register, Mumble_MASK is the bit mask which controls reading and + * writing of the register (0 -> bit is always zero and ignores writes, + * 1 -> normal read/write) and Mumble_Field_MASK is the mask used to + * access the "Field" portion of register Mumble. For more information + * on these fields consult "MIPS RISC Architecture", chapters 4 and 6. + */ + +#define Index 0 /* selects TLB entry for r/w ops & shows probe success */ +#define Random 1 /* continuously decrementing number (range 8..63) */ +#define EntryLo 2 /* low word of a TLB entry */ +#define EntryLo0 2 /* R4k uses this for even-numbered virtual pages */ +#define EntryLo1 3 /* R4k uses this for odd-numbered virtual pages */ +#define Context 4 /* TLB refill handler's kernel PTE entry pointer */ +#define PageMask 5 /* R4k page number bit mask (impl. variable page sizes) */ +#define Wired 6 /* R4k lower bnd for Random (controls randomness of TLB) */ +#define Error 7 /* R6k status/control register for parity checking */ +#define BadVAddr 8 /* "bad" virt. addr (VA of last failed v->p translation) */ +#define Count 9 /* R4k r/w reg - continuously incrementing counter */ +#define EntryHi 10 /* High word of a TLB entry */ +#define ASID 10 /* R6k uses this to store the ASID (only) */ +#define Compare 11 /* R4k traps when this register equals Count */ +#define Status 12 /* Kernel/User mode, interrupt enb., & diagnostic states */ +#define Cause 13 /* Cause of last exception */ +#define EPC 14 /* Address to return to after processing this exception */ +#define PRId 15 /* Processor revision identifier */ +#define Config 16 /* R4k config options for caches, etc. */ +#define LLAdr 17 /* R4k last instruction read by a Load Linked */ +#define LLAddr 17 /* Inconsistencies in naming... sigh. */ +#define WatchLo 18 /* R4k hardware watchpoint data */ +#define WatchHi 19 /* R4k hardware watchpoint data */ +/* 20-25 - reserved */ +#define ECC 26 /* R4k cache Error Correction Code */ +#define CacheErr 27 /* R4k read-only cache error codes */ +#define TagLo 28 /* R4k primary or secondary cache tag and parity */ +#define TagHi 29 /* R4k primary or secondary cache tag and parity */ +#define ErrorEPC 30 /* R4k cache error EPC */ +/* 31 - reserved */ + +/* (0) Index fields */ +#define Index_P_MASK 0x80000000 /* Last TLB Probe instr failed (31) */ +#define Index_Index_MASK 0x00003f00 /* TLB entry to read/write next (13-8) */ +#define Index_MASK 0x80003f00 + +/* (1) Random fields */ +#define Random_Random_MASK 0x00003f00 /* TLB entry to replace next (13-8) */ +#define Random_MASK 0x00003f00 +/* Random register upper and lower bounds (R3000) */ +#define Random_UPPER_BOUND 63 +#define Random_LOWER_BOUND 8 + +/* (2) EntryLo fields */ +#define EntryLo_PFN_MASK 0xfffff000 /* Page frame number (31-12) */ +#define EntryLo_N_MASK 0x00000800 /* Noncacheable (11) */ +#define EntryLo_D_MASK 0x00000400 /* Dirty (10) */ +#define EntryLo_V_MASK 0x00000200 /* Valid (9) */ +#define EntryLo_G_MASK 0x00000100 /* Global (8) */ +#define EntryLo_MASK 0xffffff00 + +/* (4) Context fields */ +#define Context_PTEBase_MASK 0xffe00000 /* Page Table Base (31-21) */ +#define Context_BadVPN_MASK 0x001ffffc /* Bad Virtual Page num. (20-2) */ +#define Context_MASK 0xfffffffc + +/* (5) PageMask is only on the R4k */ +#define PageMask_MASK 0x00000000 + +/* (6) Wired is only on the R4k */ +#define Wired_MASK 0x00000000 + +/* (7) Error is only on the R6k */ +#define Error_MASK 0x00000000 + +/* (8) BadVAddr has only one field */ +#define BadVAddr_MASK 0xffffffff + +/* (9) Count is only on the R4k */ +#define Count_MASK 0x00000000 + +/* (10) EntryHi fields */ +#define EntryHi_VPN_MASK 0xfffff000 /* Virtual page no. (31-12) */ +#define EntryHi_ASID_MASK 0x00000fc0 /* Current ASID (11-6) */ +#define EntryHi_MASK 0xffffffc0 + +/* (11) Compare is only on the R4k */ +#define Compare_MASK 0x00000000 + +/* (12) Status fields */ +#define Status_CU_MASK 0xf0000000 /* Coprocessor (3..0) Usable (31-28) */ +#define Status_CU3_MASK 0x80000000 /* Coprocessor 3 Usable (31) */ +#define Status_CU2_MASK 0x40000000 /* Coprocessor 2 Usable (30) */ +#define Status_CU1_MASK 0x20000000 /* Coprocessor 1 Usable (29) */ +#define Status_CU0_MASK 0x10000000 /* Coprocessor 0 Usable (28) */ +#define Status_RE_MASK 0x02000000 /* Reverse Endian (R3000A/R6000) (25) */ +#define Status_DS_MASK 0x01ff0000 /* Diagnostic Status (24-16) */ +#define Status_DS_BEV_MASK 0x00400000 /* Bootstrap Exception Vector (22) */ +#define Status_DS_TS_MASK 0x00200000 /* TLB Shutdown (21) */ +#define Status_DS_PE_MASK 0x00100000 /* Cache Parity Error (20) */ +#define Status_DS_CM_MASK 0x00080000 /* Cache miss (19) */ +#define Status_DS_PZ_MASK 0x00040000 /* Cache parity forced to zero (18) */ +#define Status_DS_SwC_MASK 0x00020000 /* Data/Inst cache switched (17) */ +#define Status_DS_IsC_MASK 0x00010000 /* Cache isolated (16) */ +#define Status_IM_MASK 0x0000ff00 /* Interrupt Mask (15-8) */ +#define Status_IM_Ext_MASK 0x0000fc00 /* Extrn. (HW) Interrupt Mask (15-10) */ +#define Status_IM_SW_MASK 0x00000300 /* Software Interrupt Mask (9-8) */ +#define Status_KU_IE_MASK 0x0000003f /* Kernel/User & Int Enable bits (5-0) */ +#define Status_KUo_MASK 0x00000020 /* Old Kernel/User status (5) */ +#define Status_IEo_MASK 0x00000010 /* Old Interrupt Enable status (4) */ +#define Status_KUp_MASK 0x00000008 /* Previous Kernel/User status (3) */ +#define Status_IEp_MASK 0x00000004 /* Previous Interrupt Enable status (2) */ +#define Status_KUc_MASK 0x00000002 /* Current Kernel/User status (1) */ +#define Status_IEc_MASK 0x00000001 /* Current Interrupt Enable status (0) */ +#define Status_MASK 0xf27fff3f + +/* (13) Cause fields */ +#define Cause_BD_MASK 0x80000000 /* Branch Delay (31) */ +#define Cause_CE_MASK 0x30000000 /* Coprocessor Error (29-28) */ +#define Cause_IP_MASK 0x0000ff00 /* Interrupt Pending (15-8) */ +#define Cause_IP_Ext_MASK 0x0000fc00 /* External (HW) ints IP(7-2) (15-10) */ +#define Cause_IP_SW_MASK 0x00000300 /* Software ints IP(1-0) (9-8) */ +#define Cause_ExcCode_MASK 0x0000007c /* Exception Code (6-2) */ +#define Cause_MASK 0xb000ff7c + +/* (14) EPC has only one field */ +#define EPC_MASK 0xffffffff + +/* (15) PRId fields */ +#define PRId_Imp_MASK 0x0000ff00 /* Implementation (15-8) */ +#define PRId_Rev_MASK 0x000000ff /* Revision (7-0) */ +#define PRId_MASK 0x0000ffff + +/* (16) Config is only on the R4k */ +#define Config_MASK 0x00000000 + +/* (17) LLAddr is only on the R4k */ +#define LLAddr_MASK 0x00000000 + +/* (18) WatchLo is only on the R4k */ +#define WatchLo_MASK 0x00000000 + +/* (19) WatchHi is only on the R4k */ +#define WatchHi_MASK 0x00000000 + +/* (20-25) reserved */ + +/* (26) ECC is only on the R4k */ +#define ECC_MASK 0x00000000 + +/* (27) CacheErr is only on the R4k */ +#define CacheErr_MASK 0x00000000 + +/* (28) TagLo is only on the R4k */ +#define TagLo_MASK 0x00000000 + +/* (29) TagHi is only on the R4k */ +#define TagHi_MASK 0x00000000 + +/* (30) ErrorEPC is only on the R4k */ +#define ErrorEPC_MASK 0x00000000 + +/* (31) reserved */ + +//------------------------------------------------------------------------------ tlbentry.h + +class TLBEntry { +public: + uint32 entryHi; + uint32 entryLo; + TLBEntry () { + } + uint32 vpn() const { return (entryHi & EntryHi_VPN_MASK); } + uint16 asid() const { return (entryHi & EntryHi_ASID_MASK); } + uint32 pfn() const { return (entryLo & EntryLo_PFN_MASK); } + bool noncacheable() const { return (entryLo & EntryLo_N_MASK); } + bool dirty() const { return (entryLo & EntryLo_D_MASK); } + bool valid() const { return (entryLo & EntryLo_V_MASK); } + bool global() const { return (entryLo & EntryLo_G_MASK); } +}; + +//------------------------------------------------------------------------------ cpzero.h + +class CPU; + +#define TLB_ENTRIES 64 + +class CPZero +{ + TLBEntry tlb[TLB_ENTRIES]; + uint32 reg[32]; + CPU *cpu; + + // Return TRUE if interrupts are enabled, FALSE otherwise. + bool interrupts_enabled(void) const; + + // Return TRUE if the cpu is running in kernel mode, FALSE otherwise. + bool kernel_mode(void) const; + + // Return the currently pending interrupts. + uint32 getIP(void); + + void mfc0_emulate(uint32 instr, uint32 pc); + void mtc0_emulate(uint32 instr, uint32 pc); + void bc0x_emulate(uint32 instr, uint32 pc); + void tlbr_emulate(uint32 instr, uint32 pc); + void tlbwi_emulate(uint32 instr, uint32 pc); + void tlbwr_emulate(uint32 instr, uint32 pc); + void tlbp_emulate(uint32 instr, uint32 pc); + void rfe_emulate(uint32 instr, uint32 pc); + void load_addr_trans_excp_info(uint32 va, uint32 vpn, TLBEntry *match); + int find_matching_tlb_entry(uint32 vpn, uint32 asid); + uint32 tlb_translate(uint32 seg, uint32 vaddr, int mode, bool *cacheable); + +public: + bool tlb_miss_user; + + // Write TLB entry number INDEX with the contents of the EntryHi + // and EntryLo registers. + void tlb_write(unsigned index); + + // Return the contents of the readable bits of register REG. + uint32 read_reg(const uint16 regno); + + // Change the contents of the writable bits of register REG to NEW_DATA. + void write_reg(const uint16 regno, const uint32 new_data); + + /* Convention says that CP0's condition is TRUE if the memory + write-back buffer is empty. Because memory writes are fast as far + as the emulation is concerned, the write buffer is always empty + for CP0. */ + bool cpCond() const { return true; } + + CPZero(CPU *m); + void reset(void); + + //initialize from shared memory + void initialize(); + //report to shared memory + void report(); + + /* Request to translate virtual address VADDR, while the processor is + in mode MODE to a physical address. CLIENT is the entity that will + recieve any interrupts generated by the attempted translation. On + return CACHEABLE will be set to TRUE if the returned address is + cacheable, it will be set to FALSE otherwise. Returns the physical + address corresponding to VADDR if such a translation is possible, + otherwise an interrupt is raised with CLIENT and the return value + is undefined. */ + uint32 address_trans(uint32 vaddr, int mode, bool *cacheable, bool *cache_isolated); + + void enter_exception(uint32 pc, uint32 excCode, uint32 ce, bool dly); + bool use_boot_excp_address(void); + bool caches_isolated(void); + + /* Return TRUE if the instruction and data caches are swapped, + FALSE otherwise. */ + bool caches_swapped(void); + + bool cop_usable (int coprocno); + void cpzero_emulate(uint32 instr, uint32 pc); + + /* Change the CP0 random register after an instruction step. */ + void adjust_random(void); + + /* Return TRUE if there is an interrupt which should be handled + at the next available opportunity, FALSE otherwise. */ + bool interrupt_pending(void); +}; + +//------------------------------------------------------------------------------ cpu.h + +/* states of the delay-slot state machine -- see CPU::step() */ +static const int NORMAL = 0, DELAYING = 1, DELAYSLOT = 2; + +/* Exception priority information -- see exception_priority(). */ +struct excPriority { + int priority; + int excCode; + int mode; +}; + +class CPU { + + // Important registers: + uint32 pc; // Program counter + uint32 reg[32]; // General-purpose registers + uint32 instr; // The current instruction + uint32 hi, lo; // Division and multiplication results + + // Exception bookkeeping data. + uint32 last_epc; + int last_prio; + uint32 next_epc; + + // Other components of the VMIPS machine. + CPZero *cpzero; + + // Delay slot handling. + int delay_state; + uint32 delay_pc; + + // Miscellaneous shared code. + void control_transfer(uint32 new_pc); + void jump(uint32 instr, uint32 pc); + uint32 calc_jump_target(uint32 instr, uint32 pc); + uint32 calc_branch_target(uint32 instr, uint32 pc); + void mult64(uint32 *hi, uint32 *lo, uint32 n, uint32 m); + void mult64s(uint32 *hi, uint32 *lo, int32 n, int32 m); + void cop_unimpl (int coprocno, uint32 instr, uint32 pc); + + // Unaligned load/store support. + uint32 lwr(uint32 regval, uint32 memval, uint8 offset); + uint32 lwl(uint32 regval, uint32 memval, uint8 offset); + uint32 swl(uint32 regval, uint32 memval, uint8 offset); + uint32 swr(uint32 regval, uint32 memval, uint8 offset); + + // Emulation of specific instructions. + void funct_emulate(uint32 instr, uint32 pc); + void regimm_emulate(uint32 instr, uint32 pc); + void j_emulate(uint32 instr, uint32 pc); + void jal_emulate(uint32 instr, uint32 pc); + void beq_emulate(uint32 instr, uint32 pc); + void bne_emulate(uint32 instr, uint32 pc); + void blez_emulate(uint32 instr, uint32 pc); + void bgtz_emulate(uint32 instr, uint32 pc); + void addi_emulate(uint32 instr, uint32 pc); + void addiu_emulate(uint32 instr, uint32 pc); + void slti_emulate(uint32 instr, uint32 pc); + void sltiu_emulate(uint32 instr, uint32 pc); + void andi_emulate(uint32 instr, uint32 pc); + void ori_emulate(uint32 instr, uint32 pc); + void xori_emulate(uint32 instr, uint32 pc); + void lui_emulate(uint32 instr, uint32 pc); + void cpzero_emulate(uint32 instr, uint32 pc); + void cpone_emulate(uint32 instr, uint32 pc); + void cptwo_emulate(uint32 instr, uint32 pc); + void cpthree_emulate(uint32 instr, uint32 pc); + void lb_emulate(uint32 instr, uint32 pc); + void lh_emulate(uint32 instr, uint32 pc); + void lwl_emulate(uint32 instr, uint32 pc); + void lw_emulate(uint32 instr, uint32 pc); + void lbu_emulate(uint32 instr, uint32 pc); + void lhu_emulate(uint32 instr, uint32 pc); + void lwr_emulate(uint32 instr, uint32 pc); + void sb_emulate(uint32 instr, uint32 pc); + void sh_emulate(uint32 instr, uint32 pc); + void swl_emulate(uint32 instr, uint32 pc); + void sw_emulate(uint32 instr, uint32 pc); + void swr_emulate(uint32 instr, uint32 pc); + void lwc1_emulate(uint32 instr, uint32 pc); + void lwc2_emulate(uint32 instr, uint32 pc); + void lwc3_emulate(uint32 instr, uint32 pc); + void swc1_emulate(uint32 instr, uint32 pc); + void swc2_emulate(uint32 instr, uint32 pc); + void swc3_emulate(uint32 instr, uint32 pc); + void sll_emulate(uint32 instr, uint32 pc); + void srl_emulate(uint32 instr, uint32 pc); + void sra_emulate(uint32 instr, uint32 pc); + void sllv_emulate(uint32 instr, uint32 pc); + void srlv_emulate(uint32 instr, uint32 pc); + void srav_emulate(uint32 instr, uint32 pc); + void jr_emulate(uint32 instr, uint32 pc); + void jalr_emulate(uint32 instr, uint32 pc); + void syscall_emulate(uint32 instr, uint32 pc); + void break_emulate(uint32 instr, uint32 pc); + void mfhi_emulate(uint32 instr, uint32 pc); + void mthi_emulate(uint32 instr, uint32 pc); + void mflo_emulate(uint32 instr, uint32 pc); + void mtlo_emulate(uint32 instr, uint32 pc); + void mult_emulate(uint32 instr, uint32 pc); + void multu_emulate(uint32 instr, uint32 pc); + void div_emulate(uint32 instr, uint32 pc); + void divu_emulate(uint32 instr, uint32 pc); + void add_emulate(uint32 instr, uint32 pc); + void addu_emulate(uint32 instr, uint32 pc); + void sub_emulate(uint32 instr, uint32 pc); + void subu_emulate(uint32 instr, uint32 pc); + void and_emulate(uint32 instr, uint32 pc); + void or_emulate(uint32 instr, uint32 pc); + void xor_emulate(uint32 instr, uint32 pc); + void nor_emulate(uint32 instr, uint32 pc); + void slt_emulate(uint32 instr, uint32 pc); + void sltu_emulate(uint32 instr, uint32 pc); + void bltz_emulate(uint32 instr, uint32 pc); + void bgez_emulate(uint32 instr, uint32 pc); + void bltzal_emulate(uint32 instr, uint32 pc); + void bgezal_emulate(uint32 instr, uint32 pc); + void RI_emulate(uint32 instr, uint32 pc); + + // Exception prioritization. + int exception_priority(uint16 excCode, int mode) const; + + // + bool exception_pending; + +public: + // Instruction decoding. + static uint16 opcode(const uint32 i) { return (i >> 26) & 0x03f; } + static uint16 rs(const uint32 i) { return (i >> 21) & 0x01f; } + static uint16 rt(const uint32 i) { return (i >> 16) & 0x01f; } + static uint16 rd(const uint32 i) { return (i >> 11) & 0x01f; } + static uint16 immed(const uint32 i) { return i & 0x0ffff; } + static short s_immed(const uint32 i) { return i & 0x0ffff; } + static uint16 shamt(const uint32 i) { return (i >> 6) & 0x01f; } + static uint16 funct(const uint32 i) { return i & 0x03f; } + static uint32 jumptarg(const uint32 i) { return i & 0x03ffffff; } + + // Constructor & destructor. + CPU (); + virtual ~CPU (); + + // Register file accessors. + uint32 get_reg (const unsigned regno) { return reg[regno]; } + void put_reg (const unsigned regno, const uint32 new_data) { + reg[regno] = new_data; + } + //initialize from shared memory + void initialize(); + //report to shared memory + void report(); + // + uint32 get_delay_state() { return delay_state; } + + bool was_delayed_transfer; + uint32 was_delayed_pc; + + // Control-flow methods. + int step (bool debug=false); + void reset (); + + // Methods which are only for use by the CPU and its coprocessors. + void branch (uint32 instr, uint32 pc); + void exception (uint16 excCode, int mode = ANY, int coprocno = -1); +}; + +#endif //__VMIPS_EMULATOR_H Index: trunk/sim/vmips/Makefile =================================================================== --- trunk/sim/vmips/Makefile (nonexistent) +++ trunk/sim/vmips/Makefile (revision 2) @@ -0,0 +1,5 @@ +tester: + g++ -o main_tester -O2 vmips_emulator.cpp main_tester.cpp -I./../tester/ + +linux: + g++ -o main_linux -O2 vmips_emulator.cpp main_linux.cpp -I./../tester/ Index: trunk/syn/aoR3000/aoR3000.qpf =================================================================== --- trunk/syn/aoR3000/aoR3000.qpf (nonexistent) +++ trunk/syn/aoR3000/aoR3000.qpf (revision 2) @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, the Altera Quartus II License Agreement, +# the Altera MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Altera and sold by Altera or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 14.0.0 Build 200 06/17/2014 SJ Web Edition +# Date created = 20:51:00 July 29, 2014 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "14.0" +DATE = "20:51:00 July 29, 2014" + +# Revisions + +PROJECT_REVISION = "aoR3000" Index: trunk/syn/aoR3000/aoR3000.qsf =================================================================== --- trunk/syn/aoR3000/aoR3000.qsf (nonexistent) +++ trunk/syn/aoR3000/aoR3000.qsf (revision 2) @@ -0,0 +1,82 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, the Altera Quartus II License Agreement, +# the Altera MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Altera and sold by Altera or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 14.0.0 Build 200 06/17/2014 SJ Web Edition +# Date created = 20:51:00 July 29, 2014 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# aoR3000_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + +set_global_assignment -name FAMILY "Cyclone IV E" +set_global_assignment -name DEVICE EP4CE115F29C7 +set_global_assignment -name TOP_LEVEL_ENTITY aoR3000 +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 14.0 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "20:51:00 JULY 29, 2014" +set_global_assignment -name LAST_QUARTUS_VERSION 14.0 +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 +set_global_assignment -name NOMINAL_CORE_SUPPLY_VOLTAGE 1.2V +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name VERILOG_FILE ../../rtl/memory/memory_data_tlb_micro.v +set_global_assignment -name VERILOG_FILE ../../rtl/memory/memory_instr_tlb_micro.v +set_global_assignment -name VERILOG_FILE ../../rtl/block/block_shift.v +set_global_assignment -name VERILOG_FILE ../../rtl/block/block_muldiv.v +set_global_assignment -name VERILOG_FILE ../../rtl/block/block_cp0.v +set_global_assignment -name VERILOG_FILE ../../rtl/block/block_long_div.v +set_global_assignment -name VERILOG_FILE ../../rtl/memory/memory_tlb_ram.v +set_global_assignment -name VERILOG_FILE ../../rtl/memory/memory_ram.v +set_global_assignment -name VERILOG_FILE ../../rtl/memory/memory_avalon.v +set_global_assignment -name VERILOG_FILE ../../rtl/model/model_true_dual_ram.v +set_global_assignment -name VERILOG_FILE ../../rtl/model/model_simple_dual_ram.v +set_global_assignment -name VERILOG_FILE ../../rtl/model/model_mult.v +set_global_assignment -name VERILOG_FILE ../../rtl/model/model_fifo.v +set_global_assignment -name VERILOG_FILE ../../rtl/pipeline/pipeline_rf.v +set_global_assignment -name VERILOG_FILE ../../rtl/pipeline/pipeline_mem.v +set_global_assignment -name VERILOG_FILE ../../rtl/pipeline/pipeline_if.v +set_global_assignment -name VERILOG_FILE ../../rtl/pipeline/pipeline_exe.v +set_global_assignment -name VERILOG_FILE ../../rtl/defines.v +set_global_assignment -name VERILOG_FILE ../../rtl/aoR3000.v +set_global_assignment -name SDC_FILE aoR3000.sdc +set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS" +set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE BALANCED +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name SEARCH_PATH /home/alek/aktualne/github/aoR3000/rtl +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file Index: trunk/syn/aoR3000/aoR3000.sdc =================================================================== --- trunk/syn/aoR3000/aoR3000.sdc (nonexistent) +++ trunk/syn/aoR3000/aoR3000.sdc (revision 2) @@ -0,0 +1,41 @@ +#************************************************************ +# THIS IS A WIZARD-GENERATED FILE. +# +# Version 14.0.0 Build 200 06/17/2014 SJ Web Edition +# +#************************************************************ + +# Copyright (C) 1991-2014 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, the Altera Quartus II License Agreement, +# the Altera MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Altera and sold by Altera or its +# authorized distributors. Please refer to the applicable +# agreement for further details. + + + +# Clock constraints + +create_clock -name "clk" -period 20.000ns [get_ports {clk}] + + +# Automatically constrain PLL and other generated clocks +derive_pll_clocks -create_base_clocks + +# Automatically calculate clock uncertainty to jitter and other effects. +derive_clock_uncertainty + +# tsu/th constraints + +# tco constraints + +# tpd constraints + Index: trunk/syn/aoR3000/aoR3000.qws =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/syn/aoR3000/aoR3000.qws =================================================================== --- trunk/syn/aoR3000/aoR3000.qws (nonexistent) +++ trunk/syn/aoR3000/aoR3000.qws (revision 2)
trunk/syn/aoR3000/aoR3000.qws Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/syn/soc/system_onchip_memory.hex =================================================================== --- trunk/syn/soc/system_onchip_memory.hex (nonexistent) +++ trunk/syn/soc/system_onchip_memory.hex (revision 2) @@ -0,0 +1,1025 @@ +:040000003C08BFC039 +:0400010025080010BE +:0400020001000008F1 +:0400030000000000F9 +:040004003C08BFC035 +:04000500250801D0F9 +:040006003C09BFC032 +:04000700252901D0D6 +:0400080011090005D5 +:0400090000000000F3 +:04000A00AD00000045 +:04000B0025080004C0 +:04000C001509FFFDD6 +:04000D0000000000EF +:04000E003C1DBFC016 +:04000F0037BD1000E9 +:040010000BF0003AB7 +:0400110000000000EB +:0400120000000000EA +:0400130000000000E9 +:0400140027BDFFF80D +:04001500AFBE000476 +:0400160003A0F02132 +:04001700AFC400086A +:040018000BF0002FBA +:0400190000000000E3 +:04001A0000000000E2 +:04001B003C02BFC024 +:04001C008C4201C051 +:04001D0000000000DF +:04001E002442000474 +:04001F008C4300000E +:040020003C02FFFFA0 +:040021000062102445 +:040022001040FFF893 +:0400230000000000D9 +:040024003C02BFC01B +:040025008C4201C048 +:040026008FC300087C +:0400270000000000D5 +:0400280080630000F1 +:0400290000000000D3 +:04002A00AC430000E3 +:04002B008FC2000878 +:04002C0000000000D0 +:04002D002442000168 +:04002E00AFC2000855 +:04002F008FC2000874 +:0400300000000000CC +:040031008042000009 +:0400320000000000CA +:040033001440FFE690 +:0400340000000000C8 +:0400350003C0E821FB +:040036008FBE000475 +:0400370027BD0008D9 +:0400380003E00008D9 +:0400390000000000C3 +:04003A0027BDFFE0FF +:04003B00AFBF001C37 +:04003C00AFBE00183B +:04003D0003A0F0210B +:04003E003C02BFC001 +:04003F0024440180D4 +:040040000FF00014A9 +:0400410000000000BB +:0400420000000000BA +:040043003C02BFC0FC +:040044008C4201C029 +:0400450000000000B7 +:040046008C420000E8 +:0400470000000000B5 +:0400480030428000C2 +:040049001040FFF96B +:04004A0000000000B2 +:04004B003C02BFC0F4 +:04004C00244401A4A3 +:04004D000FF000149C +:04004E0000000000AE +:04004F003C028000EF +:040050003442040032 +:04005100AFC200102A +:040052008FC2001049 +:0400530000000000A9 +:040054000040F80967 +:0400550000000000A7 +:040056000BF0005655 +:0400570000000000A5 +:040058003000030071 +:0400590000000000A3 +:04005A0000000000A2 +:04005B0000000000A1 +:04005C0000000000A0 +:04005D00000000009F +:04005E00000000009E +:04005F00000000009D +:040060007365725002 +:040061006E61207339 +:04006200656B207931 +:040063006F7420791D +:040064006F6F622038 +:04006500656B207433 +:040066006C656E72E5 +:040067000A2E2E2E01 +:040068000000000094 +:04006900746F6F42FF +:04006A0020676E6934 +:04006B006E72656BE1 +:04006C002E2E6C6563 +:04006D0000000A2E57 +:04006E00000000008E +:04006F00000000008D +:04007000BFFFFFF0DF +:04007100000000008B +:04007200000000008A +:040073000000000089 +:040074000000000088 +:040075000000000087 +:040076000000000086 +:040077000000000085 +:040078000000000084 +:040079000000000083 +:04007A000000000082 +:04007B000000000081 +:04007C000000000080 +:04007D00000000007F +:04007E00000000007E +:04007F00000000007D +:04008000000000007C +:04008100000000007B +:04008200000000007A +:040083000000000079 +:040084000000000078 +:040085000000000077 +:040086000000000076 +:040087000000000075 +:040088000000000074 +:040089000000000073 +:04008A000000000072 +:04008B000000000071 +:04008C000000000070 +:04008D00000000006F +:04008E00000000006E +:04008F00000000006D +:04009000000000006C +:04009100000000006B +:04009200000000006A +:040093000000000069 +:040094000000000068 +:040095000000000067 +:040096000000000066 +:040097000000000065 +:040098000000000064 +:040099000000000063 +:04009A000000000062 +:04009B000000000061 +:04009C000000000060 +:04009D00000000005F +:04009E00000000005E +:04009F00000000005D +:0400A000000000005C +:0400A100000000005B +:0400A200000000005A +:0400A3000000000059 +:0400A4000000000058 +:0400A5000000000057 +:0400A6000000000056 +:0400A7000000000055 +:0400A8000000000054 +:0400A9000000000053 +:0400AA000000000052 +:0400AB000000000051 +:0400AC000000000050 +:0400AD00000000004F +:0400AE00000000004E +:0400AF00000000004D +:0400B000000000004C +:0400B100000000004B +:0400B200000000004A +:0400B3000000000049 +:0400B4000000000048 +:0400B5000000000047 +:0400B6000000000046 +:0400B7000000000045 +:0400B8000000000044 +:0400B9000000000043 +:0400BA000000000042 +:0400BB000000000041 +:0400BC000000000040 +:0400BD00000000003F +:0400BE00000000003E +:0400BF00000000003D +:0400C000000000003C +:0400C100000000003B +:0400C200000000003A +:0400C3000000000039 +:0400C4000000000038 +:0400C5000000000037 +:0400C6000000000036 +:0400C7000000000035 +:0400C8000000000034 +:0400C9000000000033 +:0400CA000000000032 +:0400CB000000000031 +:0400CC000000000030 +:0400CD00000000002F +:0400CE00000000002E +:0400CF00000000002D +:0400D000000000002C +:0400D100000000002B +:0400D200000000002A +:0400D3000000000029 +:0400D4000000000028 +:0400D5000000000027 +:0400D6000000000026 +:0400D7000000000025 +:0400D8000000000024 +:0400D9000000000023 +:0400DA000000000022 +:0400DB000000000021 +:0400DC000000000020 +:0400DD00000000001F +:0400DE00000000001E +:0400DF00000000001D +:0400E000000000001C +:0400E100000000001B +:0400E200000000001A +:0400E3000000000019 +:0400E4000000000018 +:0400E5000000000017 +:0400E6000000000016 +:0400E7000000000015 +:0400E8000000000014 +:0400E9000000000013 +:0400EA000000000012 +:0400EB000000000011 +:0400EC000000000010 +:0400ED00000000000F +:0400EE00000000000E +:0400EF00000000000D +:0400F000000000000C +:0400F100000000000B +:0400F200000000000A +:0400F3000000000009 +:0400F4000000000008 +:0400F5000000000007 +:0400F6000000000006 +:0400F7000000000005 +:0400F8000000000004 +:0400F9000000000003 +:0400FA000000000002 +:0400FB000000000001 +:0400FC000000000000 +:0400FD0000000000FF +:0400FE0000000000FE +:0400FF0000000000FD +:0401000000000000FB +:0401010000000000FA +:0401020000000000F9 +:0401030000000000F8 +:0401040000000000F7 +:0401050000000000F6 +:0401060000000000F5 +:0401070000000000F4 +:0401080000000000F3 +:0401090000000000F2 +:04010A0000000000F1 +:04010B0000000000F0 +:04010C0000000000EF +:04010D0000000000EE +:04010E0000000000ED +:04010F0000000000EC +:0401100000000000EB +:0401110000000000EA +:0401120000000000E9 +:0401130000000000E8 +:0401140000000000E7 +:0401150000000000E6 +:0401160000000000E5 +:0401170000000000E4 +:0401180000000000E3 +:0401190000000000E2 +:04011A0000000000E1 +:04011B0000000000E0 +:04011C0000000000DF +:04011D0000000000DE +:04011E0000000000DD +:04011F0000000000DC +:0401200000000000DB +:0401210000000000DA +:0401220000000000D9 +:0401230000000000D8 +:0401240000000000D7 +:0401250000000000D6 +:0401260000000000D5 +:0401270000000000D4 +:0401280000000000D3 +:0401290000000000D2 +:04012A0000000000D1 +:04012B0000000000D0 +:04012C0000000000CF +:04012D0000000000CE +:04012E0000000000CD +:04012F0000000000CC +:0401300000000000CB +:0401310000000000CA +:0401320000000000C9 +:0401330000000000C8 +:0401340000000000C7 +:0401350000000000C6 +:0401360000000000C5 +:0401370000000000C4 +:0401380000000000C3 +:0401390000000000C2 +:04013A0000000000C1 +:04013B0000000000C0 +:04013C0000000000BF +:04013D0000000000BE +:04013E0000000000BD +:04013F0000000000BC +:0401400000000000BB +:0401410000000000BA +:0401420000000000B9 +:0401430000000000B8 +:0401440000000000B7 +:0401450000000000B6 +:0401460000000000B5 +:0401470000000000B4 +:0401480000000000B3 +:0401490000000000B2 +:04014A0000000000B1 +:04014B0000000000B0 +:04014C0000000000AF +:04014D0000000000AE +:04014E0000000000AD +:04014F0000000000AC +:0401500000000000AB +:0401510000000000AA +:0401520000000000A9 +:0401530000000000A8 +:0401540000000000A7 +:0401550000000000A6 +:0401560000000000A5 +:0401570000000000A4 +:0401580000000000A3 +:0401590000000000A2 +:04015A0000000000A1 +:04015B0000000000A0 +:04015C00000000009F +:04015D00000000009E +:04015E00000000009D +:04015F00000000009C +:04016000000000009B +:04016100000000009A +:040162000000000099 +:040163000000000098 +:040164000000000097 +:040165000000000096 +:040166000000000095 +:040167000000000094 +:040168000000000093 +:040169000000000092 +:04016A000000000091 +:04016B000000000090 +:04016C00000000008F +:04016D00000000008E +:04016E00000000008D +:04016F00000000008C +:04017000000000008B +:04017100000000008A +:040172000000000089 +:040173000000000088 +:040174000000000087 +:040175000000000086 +:040176000000000085 +:040177000000000084 +:040178000000000083 +:040179000000000082 +:04017A000000000081 +:04017B000000000080 +:04017C00000000007F +:04017D00000000007E +:04017E00000000007D +:04017F00000000007C +:04018000000000007B +:04018100000000007A +:040182000000000079 +:040183000000000078 +:040184000000000077 +:040185000000000076 +:040186000000000075 +:040187000000000074 +:040188000000000073 +:040189000000000072 +:04018A000000000071 +:04018B000000000070 +:04018C00000000006F +:04018D00000000006E +:04018E00000000006D +:04018F00000000006C +:04019000000000006B +:04019100000000006A +:040192000000000069 +:040193000000000068 +:040194000000000067 +:040195000000000066 +:040196000000000065 +:040197000000000064 +:040198000000000063 +:040199000000000062 +:04019A000000000061 +:04019B000000000060 +:04019C00000000005F +:04019D00000000005E +:04019E00000000005D +:04019F00000000005C +:0401A000000000005B +:0401A100000000005A +:0401A2000000000059 +:0401A3000000000058 +:0401A4000000000057 +:0401A5000000000056 +:0401A6000000000055 +:0401A7000000000054 +:0401A8000000000053 +:0401A9000000000052 +:0401AA000000000051 +:0401AB000000000050 +:0401AC00000000004F +:0401AD00000000004E +:0401AE00000000004D +:0401AF00000000004C +:0401B000000000004B +:0401B100000000004A +:0401B2000000000049 +:0401B3000000000048 +:0401B4000000000047 +:0401B5000000000046 +:0401B6000000000045 +:0401B7000000000044 +:0401B8000000000043 +:0401B9000000000042 +:0401BA000000000041 +:0401BB000000000040 +:0401BC00000000003F +:0401BD00000000003E +:0401BE00000000003D +:0401BF00000000003C +:0401C000000000003B +:0401C100000000003A +:0401C2000000000039 +:0401C3000000000038 +:0401C4000000000037 +:0401C5000000000036 +:0401C6000000000035 +:0401C7000000000034 +:0401C8000000000033 +:0401C9000000000032 +:0401CA000000000031 +:0401CB000000000030 +:0401CC00000000002F +:0401CD00000000002E +:0401CE00000000002D +:0401CF00000000002C +:0401D000000000002B +:0401D100000000002A +:0401D2000000000029 +:0401D3000000000028 +:0401D4000000000027 +:0401D5000000000026 +:0401D6000000000025 +:0401D7000000000024 +:0401D8000000000023 +:0401D9000000000022 +:0401DA000000000021 +:0401DB000000000020 +:0401DC00000000001F +:0401DD00000000001E +:0401DE00000000001D +:0401DF00000000001C +:0401E000000000001B +:0401E100000000001A +:0401E2000000000019 +:0401E3000000000018 +:0401E4000000000017 +:0401E5000000000016 +:0401E6000000000015 +:0401E7000000000014 +:0401E8000000000013 +:0401E9000000000012 +:0401EA000000000011 +:0401EB000000000010 +:0401EC00000000000F +:0401ED00000000000E +:0401EE00000000000D +:0401EF00000000000C +:0401F000000000000B +:0401F100000000000A +:0401F2000000000009 +:0401F3000000000008 +:0401F4000000000007 +:0401F5000000000006 +:0401F6000000000005 +:0401F7000000000004 +:0401F8000000000003 +:0401F9000000000002 +:0401FA000000000001 +:0401FB000000000000 +:0401FC0000000000FF +:0401FD0000000000FE +:0401FE0000000000FD +:0401FF0000000000FC +:0402000000000000FA +:0402010000000000F9 +:0402020000000000F8 +:0402030000000000F7 +:0402040000000000F6 +:0402050000000000F5 +:0402060000000000F4 +:0402070000000000F3 +:0402080000000000F2 +:0402090000000000F1 +:04020A0000000000F0 +:04020B0000000000EF +:04020C0000000000EE +:04020D0000000000ED +:04020E0000000000EC +:04020F0000000000EB +:0402100000000000EA +:0402110000000000E9 +:0402120000000000E8 +:0402130000000000E7 +:0402140000000000E6 +:0402150000000000E5 +:0402160000000000E4 +:0402170000000000E3 +:0402180000000000E2 +:0402190000000000E1 +:04021A0000000000E0 +:04021B0000000000DF +:04021C0000000000DE +:04021D0000000000DD +:04021E0000000000DC +:04021F0000000000DB +:0402200000000000DA +:0402210000000000D9 +:0402220000000000D8 +:0402230000000000D7 +:0402240000000000D6 +:0402250000000000D5 +:0402260000000000D4 +:0402270000000000D3 +:0402280000000000D2 +:0402290000000000D1 +:04022A0000000000D0 +:04022B0000000000CF +:04022C0000000000CE +:04022D0000000000CD +:04022E0000000000CC +:04022F0000000000CB +:0402300000000000CA +:0402310000000000C9 +:0402320000000000C8 +:0402330000000000C7 +:0402340000000000C6 +:0402350000000000C5 +:0402360000000000C4 +:0402370000000000C3 +:0402380000000000C2 +:0402390000000000C1 +:04023A0000000000C0 +:04023B0000000000BF +:04023C0000000000BE +:04023D0000000000BD +:04023E0000000000BC +:04023F0000000000BB +:0402400000000000BA +:0402410000000000B9 +:0402420000000000B8 +:0402430000000000B7 +:0402440000000000B6 +:0402450000000000B5 +:0402460000000000B4 +:0402470000000000B3 +:0402480000000000B2 +:0402490000000000B1 +:04024A0000000000B0 +:04024B0000000000AF +:04024C0000000000AE +:04024D0000000000AD +:04024E0000000000AC +:04024F0000000000AB +:0402500000000000AA +:0402510000000000A9 +:0402520000000000A8 +:0402530000000000A7 +:0402540000000000A6 +:0402550000000000A5 +:0402560000000000A4 +:0402570000000000A3 +:0402580000000000A2 +:0402590000000000A1 +:04025A0000000000A0 +:04025B00000000009F +:04025C00000000009E +:04025D00000000009D +:04025E00000000009C +:04025F00000000009B +:04026000000000009A +:040261000000000099 +:040262000000000098 +:040263000000000097 +:040264000000000096 +:040265000000000095 +:040266000000000094 +:040267000000000093 +:040268000000000092 +:040269000000000091 +:04026A000000000090 +:04026B00000000008F +:04026C00000000008E +:04026D00000000008D +:04026E00000000008C +:04026F00000000008B +:04027000000000008A +:040271000000000089 +:040272000000000088 +:040273000000000087 +:040274000000000086 +:040275000000000085 +:040276000000000084 +:040277000000000083 +:040278000000000082 +:040279000000000081 +:04027A000000000080 +:04027B00000000007F +:04027C00000000007E +:04027D00000000007D +:04027E00000000007C +:04027F00000000007B +:04028000000000007A +:040281000000000079 +:040282000000000078 +:040283000000000077 +:040284000000000076 +:040285000000000075 +:040286000000000074 +:040287000000000073 +:040288000000000072 +:040289000000000071 +:04028A000000000070 +:04028B00000000006F +:04028C00000000006E +:04028D00000000006D +:04028E00000000006C +:04028F00000000006B +:04029000000000006A +:040291000000000069 +:040292000000000068 +:040293000000000067 +:040294000000000066 +:040295000000000065 +:040296000000000064 +:040297000000000063 +:040298000000000062 +:040299000000000061 +:04029A000000000060 +:04029B00000000005F +:04029C00000000005E +:04029D00000000005D +:04029E00000000005C +:04029F00000000005B +:0402A000000000005A +:0402A1000000000059 +:0402A2000000000058 +:0402A3000000000057 +:0402A4000000000056 +:0402A5000000000055 +:0402A6000000000054 +:0402A7000000000053 +:0402A8000000000052 +:0402A9000000000051 +:0402AA000000000050 +:0402AB00000000004F +:0402AC00000000004E +:0402AD00000000004D +:0402AE00000000004C +:0402AF00000000004B +:0402B000000000004A +:0402B1000000000049 +:0402B2000000000048 +:0402B3000000000047 +:0402B4000000000046 +:0402B5000000000045 +:0402B6000000000044 +:0402B7000000000043 +:0402B8000000000042 +:0402B9000000000041 +:0402BA000000000040 +:0402BB00000000003F +:0402BC00000000003E +:0402BD00000000003D +:0402BE00000000003C +:0402BF00000000003B +:0402C000000000003A +:0402C1000000000039 +:0402C2000000000038 +:0402C3000000000037 +:0402C4000000000036 +:0402C5000000000035 +:0402C6000000000034 +:0402C7000000000033 +:0402C8000000000032 +:0402C9000000000031 +:0402CA000000000030 +:0402CB00000000002F +:0402CC00000000002E +:0402CD00000000002D +:0402CE00000000002C +:0402CF00000000002B +:0402D000000000002A +:0402D1000000000029 +:0402D2000000000028 +:0402D3000000000027 +:0402D4000000000026 +:0402D5000000000025 +:0402D6000000000024 +:0402D7000000000023 +:0402D8000000000022 +:0402D9000000000021 +:0402DA000000000020 +:0402DB00000000001F +:0402DC00000000001E +:0402DD00000000001D +:0402DE00000000001C +:0402DF00000000001B +:0402E000000000001A +:0402E1000000000019 +:0402E2000000000018 +:0402E3000000000017 +:0402E4000000000016 +:0402E5000000000015 +:0402E6000000000014 +:0402E7000000000013 +:0402E8000000000012 +:0402E9000000000011 +:0402EA000000000010 +:0402EB00000000000F +:0402EC00000000000E +:0402ED00000000000D +:0402EE00000000000C +:0402EF00000000000B +:0402F000000000000A +:0402F1000000000009 +:0402F2000000000008 +:0402F3000000000007 +:0402F4000000000006 +:0402F5000000000005 +:0402F6000000000004 +:0402F7000000000003 +:0402F8000000000002 +:0402F9000000000001 +:0402FA000000000000 +:0402FB0000000000FF +:0402FC0000000000FE +:0402FD0000000000FD +:0402FE0000000000FC +:0402FF0000000000FB +:0403000000000000F9 +:0403010000000000F8 +:0403020000000000F7 +:0403030000000000F6 +:0403040000000000F5 +:0403050000000000F4 +:0403060000000000F3 +:0403070000000000F2 +:0403080000000000F1 +:0403090000000000F0 +:04030A0000000000EF +:04030B0000000000EE +:04030C0000000000ED +:04030D0000000000EC +:04030E0000000000EB +:04030F0000000000EA +:0403100000000000E9 +:0403110000000000E8 +:0403120000000000E7 +:0403130000000000E6 +:0403140000000000E5 +:0403150000000000E4 +:0403160000000000E3 +:0403170000000000E2 +:0403180000000000E1 +:0403190000000000E0 +:04031A0000000000DF +:04031B0000000000DE +:04031C0000000000DD +:04031D0000000000DC +:04031E0000000000DB +:04031F0000000000DA +:0403200000000000D9 +:0403210000000000D8 +:0403220000000000D7 +:0403230000000000D6 +:0403240000000000D5 +:0403250000000000D4 +:0403260000000000D3 +:0403270000000000D2 +:0403280000000000D1 +:0403290000000000D0 +:04032A0000000000CF +:04032B0000000000CE +:04032C0000000000CD +:04032D0000000000CC +:04032E0000000000CB +:04032F0000000000CA +:0403300000000000C9 +:0403310000000000C8 +:0403320000000000C7 +:0403330000000000C6 +:0403340000000000C5 +:0403350000000000C4 +:0403360000000000C3 +:0403370000000000C2 +:0403380000000000C1 +:0403390000000000C0 +:04033A0000000000BF +:04033B0000000000BE +:04033C0000000000BD +:04033D0000000000BC +:04033E0000000000BB +:04033F0000000000BA +:0403400000000000B9 +:0403410000000000B8 +:0403420000000000B7 +:0403430000000000B6 +:0403440000000000B5 +:0403450000000000B4 +:0403460000000000B3 +:0403470000000000B2 +:0403480000000000B1 +:0403490000000000B0 +:04034A0000000000AF +:04034B0000000000AE +:04034C0000000000AD +:04034D0000000000AC +:04034E0000000000AB +:04034F0000000000AA +:0403500000000000A9 +:0403510000000000A8 +:0403520000000000A7 +:0403530000000000A6 +:0403540000000000A5 +:0403550000000000A4 +:0403560000000000A3 +:0403570000000000A2 +:0403580000000000A1 +:0403590000000000A0 +:04035A00000000009F +:04035B00000000009E +:04035C00000000009D +:04035D00000000009C +:04035E00000000009B +:04035F00000000009A +:040360000000000099 +:040361000000000098 +:040362000000000097 +:040363000000000096 +:040364000000000095 +:040365000000000094 +:040366000000000093 +:040367000000000092 +:040368000000000091 +:040369000000000090 +:04036A00000000008F +:04036B00000000008E +:04036C00000000008D +:04036D00000000008C +:04036E00000000008B +:04036F00000000008A +:040370000000000089 +:040371000000000088 +:040372000000000087 +:040373000000000086 +:040374000000000085 +:040375000000000084 +:040376000000000083 +:040377000000000082 +:040378000000000081 +:040379000000000080 +:04037A00000000007F +:04037B00000000007E +:04037C00000000007D +:04037D00000000007C +:04037E00000000007B +:04037F00000000007A +:040380000000000079 +:040381000000000078 +:040382000000000077 +:040383000000000076 +:040384000000000075 +:040385000000000074 +:040386000000000073 +:040387000000000072 +:040388000000000071 +:040389000000000070 +:04038A00000000006F +:04038B00000000006E +:04038C00000000006D +:04038D00000000006C +:04038E00000000006B +:04038F00000000006A +:040390000000000069 +:040391000000000068 +:040392000000000067 +:040393000000000066 +:040394000000000065 +:040395000000000064 +:040396000000000063 +:040397000000000062 +:040398000000000061 +:040399000000000060 +:04039A00000000005F +:04039B00000000005E +:04039C00000000005D +:04039D00000000005C +:04039E00000000005B +:04039F00000000005A +:0403A0000000000059 +:0403A1000000000058 +:0403A2000000000057 +:0403A3000000000056 +:0403A4000000000055 +:0403A5000000000054 +:0403A6000000000053 +:0403A7000000000052 +:0403A8000000000051 +:0403A9000000000050 +:0403AA00000000004F +:0403AB00000000004E +:0403AC00000000004D +:0403AD00000000004C +:0403AE00000000004B +:0403AF00000000004A +:0403B0000000000049 +:0403B1000000000048 +:0403B2000000000047 +:0403B3000000000046 +:0403B4000000000045 +:0403B5000000000044 +:0403B6000000000043 +:0403B7000000000042 +:0403B8000000000041 +:0403B9000000000040 +:0403BA00000000003F +:0403BB00000000003E +:0403BC00000000003D +:0403BD00000000003C +:0403BE00000000003B +:0403BF00000000003A +:0403C0000000000039 +:0403C1000000000038 +:0403C2000000000037 +:0403C3000000000036 +:0403C4000000000035 +:0403C5000000000034 +:0403C6000000000033 +:0403C7000000000032 +:0403C8000000000031 +:0403C9000000000030 +:0403CA00000000002F +:0403CB00000000002E +:0403CC00000000002D +:0403CD00000000002C +:0403CE00000000002B +:0403CF00000000002A +:0403D0000000000029 +:0403D1000000000028 +:0403D2000000000027 +:0403D3000000000026 +:0403D4000000000025 +:0403D5000000000024 +:0403D6000000000023 +:0403D7000000000022 +:0403D8000000000021 +:0403D9000000000020 +:0403DA00000000001F +:0403DB00000000001E +:0403DC00000000001D +:0403DD00000000001C +:0403DE00000000001B +:0403DF00000000001A +:0403E0000000000019 +:0403E1000000000018 +:0403E2000000000017 +:0403E3000000000016 +:0403E4000000000015 +:0403E5000000000014 +:0403E6000000000013 +:0403E7000000000012 +:0403E8000000000011 +:0403E9000000000010 +:0403EA00000000000F +:0403EB00000000000E +:0403EC00000000000D +:0403ED00000000000C +:0403EE00000000000B +:0403EF00000000000A +:0403F0000000000009 +:0403F1000000000008 +:0403F2000000000007 +:0403F3000000000006 +:0403F4000000000005 +:0403F5000000000004 +:0403F6000000000003 +:0403F7000000000002 +:0403F8000000000001 +:0403F9000000000000 +:0403FA0000000000FF +:0403FB0000000000FE +:0403FC0000000000FD +:0403FD0000000000FC +:0403FE0000000000FB +:0403FF0000000000FA +:00000001FF Index: trunk/syn/soc/system.qsys =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/xml Index: trunk/syn/soc/system.qsys =================================================================== --- trunk/syn/soc/system.qsys (nonexistent) +++ trunk/syn/soc/system.qsys (revision 2)
trunk/syn/soc/system.qsys Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/xml \ No newline at end of property Index: trunk/syn/soc/system.sopcinfo =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/xml Index: trunk/syn/soc/system.sopcinfo =================================================================== --- trunk/syn/soc/system.sopcinfo (nonexistent) +++ trunk/syn/soc/system.sopcinfo (revision 2)
trunk/syn/soc/system.sopcinfo Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/xml \ No newline at end of property Index: trunk/syn/soc/simple_clock_hw.tcl =================================================================== --- trunk/syn/soc/simple_clock_hw.tcl (nonexistent) +++ trunk/syn/soc/simple_clock_hw.tcl (revision 2) @@ -0,0 +1,134 @@ +# TCL File Generated by Component Editor 14.0 +# Sat Aug 09 21:23:31 CEST 2014 +# DO NOT MODIFY + + +# +# simple_clock "simple_clock" v1.0 +# 2014.08.09.21:23:31 +# +# + +# +# request TCL package from ACDS 14.0 +# +package require -exact qsys 14.0 + + +# +# module simple_clock +# +set_module_property DESCRIPTION "" +set_module_property NAME simple_clock +set_module_property VERSION 1.0 +set_module_property INTERNAL false +set_module_property OPAQUE_ADDRESS_MAP true +set_module_property AUTHOR "" +set_module_property DISPLAY_NAME simple_clock +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property EDITABLE true +set_module_property REPORT_TO_TALKBACK false +set_module_property ALLOW_GREYBOX_GENERATION false +set_module_property REPORT_HIERARCHY false + + +# +# file sets +# +add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" "" +set_fileset_property QUARTUS_SYNTH TOP_LEVEL simple_clock +set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false +set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false +add_fileset_file simple_clock.v VERILOG PATH simple_clock/simple_clock.v TOP_LEVEL_FILE + + +# +# parameters +# + + +# +# display items +# + + +# +# connection point clock +# +add_interface clock clock end +set_interface_property clock clockRate 0 +set_interface_property clock ENABLED true +set_interface_property clock EXPORT_OF "" +set_interface_property clock PORT_NAME_MAP "" +set_interface_property clock CMSIS_SVD_VARIABLES "" +set_interface_property clock SVD_ADDRESS_GROUP "" + +add_interface_port clock clk clk Input 1 + + +# +# connection point avalon_slave_0 +# +add_interface avalon_slave_0 avalon end +set_interface_property avalon_slave_0 addressUnits WORDS +set_interface_property avalon_slave_0 associatedClock clock +set_interface_property avalon_slave_0 associatedReset reset_sink +set_interface_property avalon_slave_0 bitsPerSymbol 8 +set_interface_property avalon_slave_0 burstOnBurstBoundariesOnly false +set_interface_property avalon_slave_0 burstcountUnits WORDS +set_interface_property avalon_slave_0 explicitAddressSpan 0 +set_interface_property avalon_slave_0 holdTime 0 +set_interface_property avalon_slave_0 linewrapBursts false +set_interface_property avalon_slave_0 maximumPendingReadTransactions 0 +set_interface_property avalon_slave_0 maximumPendingWriteTransactions 0 +set_interface_property avalon_slave_0 readLatency 0 +set_interface_property avalon_slave_0 readWaitTime 1 +set_interface_property avalon_slave_0 setupTime 0 +set_interface_property avalon_slave_0 timingUnits Cycles +set_interface_property avalon_slave_0 writeWaitTime 0 +set_interface_property avalon_slave_0 ENABLED true +set_interface_property avalon_slave_0 EXPORT_OF "" +set_interface_property avalon_slave_0 PORT_NAME_MAP "" +set_interface_property avalon_slave_0 CMSIS_SVD_VARIABLES "" +set_interface_property avalon_slave_0 SVD_ADDRESS_GROUP "" + +add_interface_port avalon_slave_0 avs_write write Input 1 +add_interface_port avalon_slave_0 avs_writedata writedata Input 32 +set_interface_assignment avalon_slave_0 embeddedsw.configuration.isFlash 0 +set_interface_assignment avalon_slave_0 embeddedsw.configuration.isMemoryDevice 0 +set_interface_assignment avalon_slave_0 embeddedsw.configuration.isNonVolatileStorage 0 +set_interface_assignment avalon_slave_0 embeddedsw.configuration.isPrintableDevice 0 + + +# +# connection point reset_sink +# +add_interface reset_sink reset end +set_interface_property reset_sink associatedClock clock +set_interface_property reset_sink synchronousEdges DEASSERT +set_interface_property reset_sink ENABLED true +set_interface_property reset_sink EXPORT_OF "" +set_interface_property reset_sink PORT_NAME_MAP "" +set_interface_property reset_sink CMSIS_SVD_VARIABLES "" +set_interface_property reset_sink SVD_ADDRESS_GROUP "" + +add_interface_port reset_sink rst_n reset_n Input 1 + + +# +# connection point interrupt_sender +# +add_interface interrupt_sender interrupt end +set_interface_property interrupt_sender associatedAddressablePoint "" +set_interface_property interrupt_sender associatedClock clock +set_interface_property interrupt_sender associatedReset reset_sink +set_interface_property interrupt_sender bridgedReceiverOffset "" +set_interface_property interrupt_sender bridgesToReceiver "" +set_interface_property interrupt_sender ENABLED true +set_interface_property interrupt_sender EXPORT_OF "" +set_interface_property interrupt_sender PORT_NAME_MAP "" +set_interface_property interrupt_sender CMSIS_SVD_VARIABLES "" +set_interface_property interrupt_sender SVD_ADDRESS_GROUP "" + +add_interface_port interrupt_sender irq irq Output 1 + Index: trunk/syn/soc/aoR3000_hw.tcl =================================================================== --- trunk/syn/soc/aoR3000_hw.tcl (nonexistent) +++ trunk/syn/soc/aoR3000_hw.tcl (revision 2) @@ -0,0 +1,155 @@ +# TCL File Generated by Component Editor 14.0 +# Sun Aug 10 02:45:47 CEST 2014 +# DO NOT MODIFY + + +# +# aoR3000 "aoR3000" v1.0 +# 2014.08.10.02:45:47 +# +# + +# +# request TCL package from ACDS 14.0 +# +package require -exact qsys 14.0 + + +# +# module aoR3000 +# +set_module_property DESCRIPTION "" +set_module_property NAME aoR3000 +set_module_property VERSION 1.0 +set_module_property INTERNAL false +set_module_property OPAQUE_ADDRESS_MAP true +set_module_property AUTHOR "" +set_module_property DISPLAY_NAME aoR3000 +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property EDITABLE true +set_module_property REPORT_TO_TALKBACK false +set_module_property ALLOW_GREYBOX_GENERATION false +set_module_property REPORT_HIERARCHY false + + +# +# file sets +# +add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" "" +set_fileset_property QUARTUS_SYNTH TOP_LEVEL aoR3000 +set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false +set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false +add_fileset_file aoR3000.v VERILOG PATH ../../rtl/aoR3000.v TOP_LEVEL_FILE +add_fileset_file defines.v VERILOG PATH ../../rtl/defines.v +add_fileset_file block_cp0.v VERILOG PATH ../../rtl/block/block_cp0.v +add_fileset_file block_long_div.v VERILOG PATH ../../rtl/block/block_long_div.v +add_fileset_file block_muldiv.v VERILOG PATH ../../rtl/block/block_muldiv.v +add_fileset_file block_shift.v VERILOG PATH ../../rtl/block/block_shift.v +add_fileset_file memory_avalon.v VERILOG PATH ../../rtl/memory/memory_avalon.v +add_fileset_file memory_data_tlb_micro.v VERILOG PATH ../../rtl/memory/memory_data_tlb_micro.v +add_fileset_file memory_instr_tlb_micro.v VERILOG PATH ../../rtl/memory/memory_instr_tlb_micro.v +add_fileset_file memory_ram.v VERILOG PATH ../../rtl/memory/memory_ram.v +add_fileset_file memory_tlb_ram.v VERILOG PATH ../../rtl/memory/memory_tlb_ram.v +add_fileset_file model_fifo.v VERILOG PATH ../../rtl/model/model_fifo.v +add_fileset_file model_mult.v VERILOG PATH ../../rtl/model/model_mult.v +add_fileset_file model_simple_dual_ram.v VERILOG PATH ../../rtl/model/model_simple_dual_ram.v +add_fileset_file model_true_dual_ram.v VERILOG PATH ../../rtl/model/model_true_dual_ram.v +add_fileset_file pipeline_exe.v VERILOG PATH ../../rtl/pipeline/pipeline_exe.v +add_fileset_file pipeline_if.v VERILOG PATH ../../rtl/pipeline/pipeline_if.v +add_fileset_file pipeline_mem.v VERILOG PATH ../../rtl/pipeline/pipeline_mem.v +add_fileset_file pipeline_rf.v VERILOG PATH ../../rtl/pipeline/pipeline_rf.v + + +# +# parameters +# + + +# +# display items +# + + +# +# connection point clock +# +add_interface clock clock end +set_interface_property clock clockRate 0 +set_interface_property clock ENABLED true +set_interface_property clock EXPORT_OF "" +set_interface_property clock PORT_NAME_MAP "" +set_interface_property clock CMSIS_SVD_VARIABLES "" +set_interface_property clock SVD_ADDRESS_GROUP "" + +add_interface_port clock clk clk Input 1 + + +# +# connection point avalon_master_0 +# +add_interface avalon_master_0 avalon start +set_interface_property avalon_master_0 addressUnits SYMBOLS +set_interface_property avalon_master_0 associatedClock clock +set_interface_property avalon_master_0 associatedReset reset_sink +set_interface_property avalon_master_0 bitsPerSymbol 8 +set_interface_property avalon_master_0 burstOnBurstBoundariesOnly false +set_interface_property avalon_master_0 burstcountUnits WORDS +set_interface_property avalon_master_0 doStreamReads false +set_interface_property avalon_master_0 doStreamWrites false +set_interface_property avalon_master_0 holdTime 0 +set_interface_property avalon_master_0 linewrapBursts false +set_interface_property avalon_master_0 maximumPendingReadTransactions 0 +set_interface_property avalon_master_0 maximumPendingWriteTransactions 0 +set_interface_property avalon_master_0 readLatency 0 +set_interface_property avalon_master_0 readWaitTime 1 +set_interface_property avalon_master_0 setupTime 0 +set_interface_property avalon_master_0 timingUnits Cycles +set_interface_property avalon_master_0 writeWaitTime 0 +set_interface_property avalon_master_0 ENABLED true +set_interface_property avalon_master_0 EXPORT_OF "" +set_interface_property avalon_master_0 PORT_NAME_MAP "" +set_interface_property avalon_master_0 CMSIS_SVD_VARIABLES "" +set_interface_property avalon_master_0 SVD_ADDRESS_GROUP "" + +add_interface_port avalon_master_0 avm_writedata writedata Output 32 +add_interface_port avalon_master_0 avm_byteenable byteenable Output 4 +add_interface_port avalon_master_0 avm_burstcount burstcount Output 3 +add_interface_port avalon_master_0 avm_write write Output 1 +add_interface_port avalon_master_0 avm_read read Output 1 +add_interface_port avalon_master_0 avm_waitrequest waitrequest Input 1 +add_interface_port avalon_master_0 avm_readdatavalid readdatavalid Input 1 +add_interface_port avalon_master_0 avm_readdata readdata Input 32 +add_interface_port avalon_master_0 avm_address address Output 32 + + +# +# connection point reset_sink +# +add_interface reset_sink reset end +set_interface_property reset_sink associatedClock clock +set_interface_property reset_sink synchronousEdges DEASSERT +set_interface_property reset_sink ENABLED true +set_interface_property reset_sink EXPORT_OF "" +set_interface_property reset_sink PORT_NAME_MAP "" +set_interface_property reset_sink CMSIS_SVD_VARIABLES "" +set_interface_property reset_sink SVD_ADDRESS_GROUP "" + +add_interface_port reset_sink rst_n reset_n Input 1 + + +# +# connection point interrupt_receiver +# +add_interface interrupt_receiver interrupt start +set_interface_property interrupt_receiver associatedAddressablePoint "" +set_interface_property interrupt_receiver associatedClock clock +set_interface_property interrupt_receiver associatedReset reset_sink +set_interface_property interrupt_receiver irqScheme INDIVIDUAL_REQUESTS +set_interface_property interrupt_receiver ENABLED true +set_interface_property interrupt_receiver EXPORT_OF "" +set_interface_property interrupt_receiver PORT_NAME_MAP "" +set_interface_property interrupt_receiver CMSIS_SVD_VARIABLES "" +set_interface_property interrupt_receiver SVD_ADDRESS_GROUP "" + +add_interface_port interrupt_receiver interrupt_vector irq Input 6 + Index: trunk/syn/soc/simple_clock/simple_clock.v =================================================================== --- trunk/syn/soc/simple_clock/simple_clock.v (nonexistent) +++ trunk/syn/soc/simple_clock/simple_clock.v (revision 2) @@ -0,0 +1,36 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +/* Generated an interrupt every 500000 cycles. + * If the clock is 50 MHz, the interrupt will be at a frequency of 100 Hz. + * Any write acknowledges the interrupt. + */ + +module simple_clock( + input clk, + input rst_n, + + output reg irq, + + input avs_write, + input [31:0] avs_writedata +); + +reg [18:0] counter; +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) counter <= 19'd0; + else if(counter == 19'd499999) counter <= 19'd0; + else counter <= counter + 13'd1; +end + +always @(posedge clk or negedge rst_n) begin + if(rst_n == 1'b0) irq <= 1'd0; + else if(counter == 19'd499999) irq <= 1'd1; + else if(avs_write) irq <= 1'd0; +end + +endmodule Index: trunk/syn/soc/pll/pll.qip =================================================================== --- trunk/syn/soc/pll/pll.qip (nonexistent) +++ trunk/syn/soc/pll/pll.qip (revision 2) @@ -0,0 +1,5 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "14.0" +set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone IV E}" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] Index: trunk/syn/soc/pll/pll.v =================================================================== --- trunk/syn/soc/pll/pll.v (nonexistent) +++ trunk/syn/soc/pll/pll.v (revision 2) @@ -0,0 +1,310 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 14.0.0 Build 200 06/17/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation. All rights reserved. +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, the Altera Quartus II License Agreement, +//the Altera MegaCore Function License Agreement, or other +//applicable license agreement, including, without limitation, +//that your use is for the sole purpose of programming logic +//devices manufactured by Altera and sold by Altera or its +//authorized distributors. Please refer to the applicable +//agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + inclk0, + c0, + locked); + + input inclk0; + output c0; + output locked; + + wire [0:0] sub_wire2 = 1'h0; + wire [4:0] sub_wire3; + wire sub_wire5; + wire sub_wire0 = inclk0; + wire [1:0] sub_wire1 = {sub_wire2, sub_wire0}; + wire [0:0] sub_wire4 = sub_wire3[0:0]; + wire c0 = sub_wire4; + wire locked = sub_wire5; + + altpll altpll_component ( + .inclk (sub_wire1), + .clk (sub_wire3), + .locked (sub_wire5), + .activeclock (), + .areset (1'b0), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 1, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 1, + altpll_component.clk0_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 20000, + altpll_component.intended_device_family = "Cyclone IV E", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_UNUSED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_UNUSED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "50.000000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "50.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20000" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON Index: trunk/syn/soc/pll/pll.ppf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/xml Index: trunk/syn/soc/pll/pll.ppf =================================================================== --- trunk/syn/soc/pll/pll.ppf (nonexistent) +++ trunk/syn/soc/pll/pll.ppf (revision 2)
trunk/syn/soc/pll/pll.ppf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/xml \ No newline at end of property Index: trunk/syn/soc/soc.v =================================================================== --- trunk/syn/soc/soc.v (nonexistent) +++ trunk/syn/soc/soc.v (revision 2) @@ -0,0 +1,57 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +module soc( + input CLOCK_50, + + //SDRAM + output [12:0] DRAM_ADDR, + output [1:0] DRAM_BA, + output DRAM_CAS_N, + output DRAM_CKE, + output DRAM_CLK, + output DRAM_CS_N, + inout [31:0] DRAM_DQ, + output [3:0] DRAM_DQM, + output DRAM_RAS_N, + output DRAM_WE_N +); + +//------------------------------------------------------------------------------ + +assign DRAM_CLK = clk_sys; + +//------------------------------------------------------------------------------ + +wire clk_sys; + +wire rst_n; + +pll pll_inst( + .inclk0 (CLOCK_50), + .c0 (clk_sys), + .locked (rst_n) +); + +system u0 ( + .clk_clk (clk_sys), + .reset_reset_n (rst_n), + + .sdram_wire_addr (DRAM_ADDR), + .sdram_wire_ba (DRAM_BA), + .sdram_wire_cas_n (DRAM_CAS_N), + .sdram_wire_cke (DRAM_CKE), + .sdram_wire_cs_n (DRAM_CS_N), + .sdram_wire_dq (DRAM_DQ), + .sdram_wire_dqm (DRAM_DQM), + .sdram_wire_ras_n (DRAM_RAS_N), + .sdram_wire_we_n (DRAM_WE_N) +); + +//------------------------------------------------------------------------------ + +endmodule Index: trunk/syn/soc/soc.qpf =================================================================== --- trunk/syn/soc/soc.qpf (nonexistent) +++ trunk/syn/soc/soc.qpf (revision 2) @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, the Altera Quartus II License Agreement, +# the Altera MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Altera and sold by Altera or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 14.0.0 Build 200 06/17/2014 SJ Web Edition +# Date created = 20:14:12 August 09, 2014 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "14.0" +DATE = "20:14:12 August 09, 2014" + +# Revisions + +PROJECT_REVISION = "soc" Index: trunk/syn/soc/firmware/hex2mif.cpp =================================================================== --- trunk/syn/soc/firmware/hex2mif.cpp (nonexistent) +++ trunk/syn/soc/firmware/hex2mif.cpp (revision 2) @@ -0,0 +1,60 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +/* This is a very simple converter from a ihex file generated by the GNU + * toolchain to a Altera MIF file. + */ + +#include +#include +#include + +int main() { + char line[256]; + + int depth = 1024; + + printf("WIDTH=32;\n"); + printf("DEPTH=%d;\n", depth); + printf("ADDRESS_RADIX=HEX;\n"); + printf("DATA_RADIX=HEX;\n"); + printf("CONTENT BEGIN\n"); + + int address = 0; + while(1) { + char *ret_ptr = fgets(line, sizeof(line), stdin); + if(ret_ptr == NULL) break; + + int len = strlen(line); + if(len > 0 && line[0] == ':') { //hex line + int hex_len, type; + sscanf(line+1, "%02x", &hex_len); + sscanf(line+7, "%02x", &type); + + if(type == 0) { //data type + if((hex_len % 4) != 0) { + fprintf(stderr, "Error: data entry size not multiple of 4.\n"); + return -1; + } + for(int i=0; i> 24) & 0xFF) | ((val >> 8) & 0xFF00) | ((val << 8) & 0xFF0000) | ((val << 24) & 0xFF000000); + printf("%03x : %08x;\n", address++, val); + } + while((hex_len/4) < 4) { + printf("%03x : %08x;\n", address++, 0); + hex_len += 4; + } + } + } + } + while(address < depth) printf("%03x : %08x;\n", address++, 0); + printf("END;\n"); + return 0; +} + Index: trunk/syn/soc/firmware/header.S =================================================================== --- trunk/syn/soc/firmware/header.S (nonexistent) +++ trunk/syn/soc/firmware/header.S (revision 2) @@ -0,0 +1,24 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + + la $t0, 0f + jr $t0 +0: + + la $t0, __bss_start # clear .bss + la $t1, __bss_stop + beq $t0, $t1, 2f + +1: + sw $zero, ($t0) + addiu $t0, 4 + bne $t0, $t1, 1b + +2: + li $sp, 0xBFC01000 # setup $sp and jump to C code + j start_bootloader + nop Index: trunk/syn/soc/firmware/linker.x =================================================================== --- trunk/syn/soc/firmware/linker.x (nonexistent) +++ trunk/syn/soc/firmware/linker.x (revision 2) @@ -0,0 +1,13 @@ +MEMORY +{ + ram : ORIGIN = 0xBFC00000, LENGTH = 4096 +} + +SECTIONS +{ + .text : { *(.text) } > ram + .data : { *(.data) } > ram + __bss_start = .; + .bss : { *(.bss) } > ram + __bss_stop = .; +} Index: trunk/syn/soc/firmware/bootloader.c =================================================================== --- trunk/syn/soc/firmware/bootloader.c (nonexistent) +++ trunk/syn/soc/firmware/bootloader.c (revision 2) @@ -0,0 +1,31 @@ +/* + * This file is subject to the terms and conditions of the BSD License. See + * the file "LICENSE" in the main directory of this archive for more details. + * + * Copyright (C) 2014 Aleksander Osman + */ + +volatile unsigned int *jtag = (unsigned int *)0xBFFFFFF0; + +void jtag_print(char *ptr) { + + while((*ptr) != 0) { + while((jtag[1] & 0xFFFF0000) == 0) { ; } + jtag[0] = (*ptr); + ptr++; + } +} + +void start_bootloader() { + jtag_print("Press any key to boot kernel...\n"); + + while((jtag[0] & 0x8000) == 0) { ; } + + jtag_print("Booting kernel...\n"); + + void (*boot_func)(void) = (void (*)(void))0x80000400; + + boot_func(); + + while(1) { ; } +} Index: trunk/syn/soc/firmware/Makefile =================================================================== --- trunk/syn/soc/firmware/Makefile (nonexistent) +++ trunk/syn/soc/firmware/Makefile (revision 2) @@ -0,0 +1,7 @@ +all: hex2mif + mipsel-unknown-linux-gnu-gcc -mips1 -o system_onchip_memory.hex -nostdlib -T linker.x -mno-abicalls -Wl,--oformat=ihex header.S bootloader.c + ./hex2mif < system_onchip_memory.hex > system_onchip_memory.mif + mif2hex system_onchip_memory.mif ./../system_onchip_memory.hex + +hex2mif: hex2mif.cpp + g++ -o hex2mif -O2 hex2mif.cpp Index: trunk/syn/soc/soc.qsf =================================================================== --- trunk/syn/soc/soc.qsf (nonexistent) +++ trunk/syn/soc/soc.qsf (revision 2) @@ -0,0 +1,183 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, the Altera Quartus II License Agreement, +# the Altera MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Altera and sold by Altera or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 14.0.0 Build 200 06/17/2014 SJ Web Edition +# Date created = 20:14:12 August 09, 2014 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# soc_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + +set_global_assignment -name FAMILY "Cyclone IV E" +set_global_assignment -name DEVICE EP4CE115F29C7 +set_global_assignment -name TOP_LEVEL_ENTITY soc +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 14.0 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "20:14:12 AUGUST 09, 2014" +set_global_assignment -name LAST_QUARTUS_VERSION 14.0 +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 +set_global_assignment -name NOMINAL_CORE_SUPPLY_VOLTAGE 1.2V +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name QIP_FILE pll/pll.qip +set_global_assignment -name QIP_FILE system/synthesis/system.qip +set_global_assignment -name VERILOG_FILE soc.v + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLOCK_50 +set_location_assignment PIN_Y2 -to CLOCK_50 + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_BA[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_BA[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQM[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQM[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQM[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQM[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_RAS_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CAS_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CKE +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_WE_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CS_N +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[12] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[13] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[14] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[15] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[16] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[17] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[18] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[19] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[20] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[21] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[22] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[23] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[24] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[25] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[26] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[27] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[28] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[29] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[30] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[31] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[12] +set_location_assignment PIN_U1 -to DRAM_DQ[31] +set_location_assignment PIN_U4 -to DRAM_DQ[30] +set_location_assignment PIN_T3 -to DRAM_DQ[29] +set_location_assignment PIN_R3 -to DRAM_DQ[28] +set_location_assignment PIN_R2 -to DRAM_DQ[27] +set_location_assignment PIN_R1 -to DRAM_DQ[26] +set_location_assignment PIN_R7 -to DRAM_DQ[25] +set_location_assignment PIN_U5 -to DRAM_DQ[24] +set_location_assignment PIN_M8 -to DRAM_DQ[16] +set_location_assignment PIN_L8 -to DRAM_DQ[17] +set_location_assignment PIN_P2 -to DRAM_DQ[18] +set_location_assignment PIN_N3 -to DRAM_DQ[19] +set_location_assignment PIN_N4 -to DRAM_DQ[20] +set_location_assignment PIN_M4 -to DRAM_DQ[21] +set_location_assignment PIN_M7 -to DRAM_DQ[22] +set_location_assignment PIN_L7 -to DRAM_DQ[23] +set_location_assignment PIN_Y3 -to DRAM_DQ[8] +set_location_assignment PIN_Y4 -to DRAM_DQ[9] +set_location_assignment PIN_AB1 -to DRAM_DQ[10] +set_location_assignment PIN_AA3 -to DRAM_DQ[11] +set_location_assignment PIN_AB2 -to DRAM_DQ[12] +set_location_assignment PIN_AC1 -to DRAM_DQ[13] +set_location_assignment PIN_AB3 -to DRAM_DQ[14] +set_location_assignment PIN_AC2 -to DRAM_DQ[15] +set_location_assignment PIN_W3 -to DRAM_DQ[0] +set_location_assignment PIN_W2 -to DRAM_DQ[1] +set_location_assignment PIN_V4 -to DRAM_DQ[2] +set_location_assignment PIN_W1 -to DRAM_DQ[3] +set_location_assignment PIN_V3 -to DRAM_DQ[4] +set_location_assignment PIN_V2 -to DRAM_DQ[5] +set_location_assignment PIN_V1 -to DRAM_DQ[6] +set_location_assignment PIN_U3 -to DRAM_DQ[7] +set_location_assignment PIN_W4 -to DRAM_DQM[1] +set_location_assignment PIN_K8 -to DRAM_DQM[2] +set_location_assignment PIN_U2 -to DRAM_DQM[0] +set_location_assignment PIN_N8 -to DRAM_DQM[3] +set_location_assignment PIN_U6 -to DRAM_RAS_N +set_location_assignment PIN_V7 -to DRAM_CAS_N +set_location_assignment PIN_AA6 -to DRAM_CKE +set_location_assignment PIN_V6 -to DRAM_WE_N +set_location_assignment PIN_T4 -to DRAM_CS_N +set_location_assignment PIN_U7 -to DRAM_BA[0] +set_location_assignment PIN_R4 -to DRAM_BA[1] +set_location_assignment PIN_Y7 -to DRAM_ADDR[12] +set_location_assignment PIN_AA5 -to DRAM_ADDR[11] +set_location_assignment PIN_R5 -to DRAM_ADDR[10] +set_location_assignment PIN_Y6 -to DRAM_ADDR[9] +set_location_assignment PIN_Y5 -to DRAM_ADDR[8] +set_location_assignment PIN_AA7 -to DRAM_ADDR[7] +set_location_assignment PIN_W7 -to DRAM_ADDR[6] +set_location_assignment PIN_W8 -to DRAM_ADDR[5] +set_location_assignment PIN_V5 -to DRAM_ADDR[4] +set_location_assignment PIN_R6 -to DRAM_ADDR[0] +set_location_assignment PIN_V8 -to DRAM_ADDR[1] +set_location_assignment PIN_U8 -to DRAM_ADDR[2] +set_location_assignment PIN_P1 -to DRAM_ADDR[3] +set_location_assignment PIN_AE5 -to DRAM_CLK + +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name SDC_FILE soc.sdc +set_global_assignment -name CDF_FILE output_files/Chain2.cdf +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE output_files/debug_1.stp +set_global_assignment -name SIGNALTAP_FILE output_files/debug_1.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file Index: trunk/syn/soc/soc.sdc =================================================================== --- trunk/syn/soc/soc.sdc (nonexistent) +++ trunk/syn/soc/soc.sdc (revision 2) @@ -0,0 +1,41 @@ +#************************************************************ +# THIS IS A WIZARD-GENERATED FILE. +# +# Version 14.0.0 Build 200 06/17/2014 SJ Web Edition +# +#************************************************************ + +# Copyright (C) 1991-2014 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, the Altera Quartus II License Agreement, +# the Altera MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Altera and sold by Altera or its +# authorized distributors. Please refer to the applicable +# agreement for further details. + + + +# Clock constraints + +create_clock -name "CLOCK_50" -period 20.000ns [get_ports {CLOCK_50}] + + +# Automatically constrain PLL and other generated clocks +derive_pll_clocks -create_base_clocks + +# Automatically calculate clock uncertainty to jitter and other effects. +derive_clock_uncertainty + +# tsu/th constraints + +# tco constraints + +# tpd constraints + Index: trunk/syn/soc/soc.qws =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/syn/soc/soc.qws =================================================================== --- trunk/syn/soc/soc.qws (nonexistent) +++ trunk/syn/soc/soc.qws (revision 2)
trunk/syn/soc/soc.qws Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/README.md =================================================================== --- trunk/README.md (nonexistent) +++ trunk/README.md (revision 2) @@ -0,0 +1,207 @@ +### aoR3000 + +The aoR3000 is a MIPS R3000A compatible core capable of booting the Linux kernel version 3.16 in about 3 seconds and with a rating of 48.74 BogoMIPS. It features a compatible MMU, but no FPU. + +### Current status +- 11 August 2014 - initial version 1.0. + +### Features + +The aoR3000 soft processor core has the following features: +- 5 stage pipeline (single-issue, in-order, forwarding, hazard detection); +- implements all MIPS I instructions (this includes the privileged coprocessor 0 instructions); +- the MMU in coprocessor 0 is compatible with the R3000A but has more micro-TLB entries: 64 TLB entries, 8 micro-TLB entries for data, 4 micro-TLB entries for instructions; +- 2 kB instruction cache (direct map); +- 2 kB data cache (direct map); +- all exceptions are implemented (bus error exceptions are not issued, exceptions in branch delays are supported); +- the core has one combined instruction/data Altera Avalon MM master interface (with burst and pipelined instruction reads, pipelined data reads); +- multiplication implemented in hardware using vendor-independent modules (Altera Quartus II infers embedded multipliers); +- division implemented in hardware using long division (33 clock cycles required); +- the core uses 7700 LE and runs at 50 MHz on a Altera Cyclone IV EP4CE115F29C7; +- the core is modeled in a vendor-independent subset of Verilog consistent with the requirements of Verilator (fully synchronous design, no vendor specific module instances); +- a Verilator generated executable C++ model is available; +- the core was tested and compared with the vmips software R3000 emulator; +- the core is chosen to be little-endian and can not be changed by software; + +### Resource usage +The following table shows the result of synthesis using a balanced area/speed optimization: + + +---------------------------------------------------------------------------------+ + ; Flow Summary ; + +------------------------------------+--------------------------------------------+ + ; Flow Status ; Successful - Mon Aug 11 21:46:48 2014 ; + ; Quartus II 64-Bit Version ; 14.0.0 Build 200 06/17/2014 SJ Web Edition ; + ; Revision Name ; aoR3000 ; + ; Top-level Entity Name ; aoR3000 ; + ; Family ; Cyclone IV E ; + ; Device ; EP4CE115F29C7 ; + ; Timing Models ; Final ; + ; Total logic elements ; 7,660 / 114,480 ( 7 % ) ; + ; Total combinational functions ; 7,174 / 114,480 ( 6 % ) ; + ; Dedicated logic registers ; 2,633 / 114,480 ( 2 % ) ; + ; Total registers ; 2633 ; + ; Total pins ; 115 / 529 ( 22 % ) ; + ; Total virtual pins ; 0 ; + ; Total memory bits ; 61,616 / 3,981,312 ( 2 % ) ; + ; Embedded Multiplier 9-bit elements ; 8 / 532 ( 2 % ) ; + ; Total PLLs ; 0 / 4 ( 0 % ) ; + +------------------------------------+--------------------------------------------+ + + +-------------------------------------------------+ + ; Slow 1200mV 85C Model Fmax Summary ; + +-----------+-----------------+------------+------+ + ; Fmax ; Restricted Fmax ; Clock Name ; Note ; + +-----------+-----------------+------------+------+ + ; 52.58 MHz ; 52.58 MHz ; clk ; ; + +-----------+-----------------+------------+------+ + +### Implemented instructions + +All the MIPS I instructions are implemented: +- ADD, ADDI, ADDIU, ADDU, AND, ANDI, NOR, OR, ORI, SLL, SLLV, SLT, SLTI, SLTIU, SLTU, SRA, SRAV, SRL, SRLV, SUB, SUBU, XOR, XORI, LUI; +- DIV, DIVU, MULT, MULTU, MTHI, MTLO, MFHI, MFLO; +- BREAK, SYSCALL; +- CFCz, CTCz, LWCz, SWCz; +- MFCz, MTCz; +- COPz, RFE, TLBP, TLBR, TLBWI, TLBWR; +- BEQ, BGEZ, BGEZAL, BGTZ, BLEZ, BLTZ, BLTZAL, BNE, J, JAL, JALR, JR; +- LB, LBU, LH, LHU, LW, LWL, LWR, SB, SH, SW, SWL, SWR; + +### Running the tests +The aoR3000 core can be converted by Verilator to a C++ executable model. This executable model was compared with the vmips software R3000 emulator (http://vmips.sourceforge.net/) in simulation. +All instructions were simulated with random register and memory contents. After every instruction the register contents are compared. + +To run the test the following steps have to be taken: +- compile the vmips emulator in sim/vmips/ by 'make tester'; +- compile the Verilator aoR3000 model in sim/aoR3000/ by 'make tester'; +- choose the test to be run in sim/tester/main_tester.cpp by setting the pointer 'tst_t *tst_current ='; +- compile the tester in sim/tester/ by 'make tester'; +- run the tester in sim/tester/ by './main_tester'; + +### GNU toolchain +To run programs on the aoR3000 a standard GNU toolchain in required. I used the following options during compilation of the toolchain: +- for GNU binutils: './../binutils-2.24.51/configure --prefix= --target=mipsel-unknown-linux-gnu'; +- for GCC: './../gcc-4.9.1/configure --prefix= --target=mipsel-unknown-linux-gnu --enable-languages=c --disable-threads --disable-shared --disable-libssp --disable-libquadmath --disable-libgomp --disable-libatomic'; + +The target 'mipsel-unknown-elf' can also be used, but more changes are required to the Linux kernel in that case. + +### Building a minimal Linux kernel +In the directory linux/ there is a minimal set of files required to add the aoR3000 SoC platform to the kernel sources version 3.16. To compile the kernel with these changes just copy/overwrite the files in +a Linux source tree. After that 'make ARCH=mips CROSS_COMPILE=mipsel-unknown-linux-gnu- vmlinux.bin' to build the kernel. + +### Booting the Linux kernel in simulation on a Verilator executable model of the aoR3000 +The booting of the Linux kernel is performed in a similar method like the tests described above. The Verilator executable model of the aoR3000 is run together with the vmips R3000 software simulator to verify +the correctness of the aoR3000. Every write to memory is checked to confirm that both of the models write the same data at the same time and in the same order. + +To boot the Linux kernel in simulation the following steps have to be taken: +- compile the vmips emulator in sim/vmips/ by 'make linux'; +- compile the Verilator aoR3000 model in sim/aoR3000/ by 'make linux'; +- compile the tester in sim/tester/ by 'make linux'; +- compile the Linux kernel to get the 'vmlinux.bin' file in the arch/mips/boot/ directory; +- run the tester in sim/tester/ by './main_linux '; + +The booting of the Linux kernel takes about 12 minutes on a modern PC (more than 46 milion instructions have to be executed/simulated). + +The tester simulates the following hardware devices: +- an eary Linux console that outputs the data written to that console to the file 'tester/early_console.txt'; +- a simple hardware time interrupt device that signals IRQ 0 every 10 miliseconds; +- an Altera JTAG UART connected to a pseudo terminal (Unix PTY). The terminal name is printed just after executing the tester (for example: 'slave pty: /dev/pts/9'); + +To connect to this terminal one can use the following command: 'picocom --nolock /dev/pts/9'. Data can be read and written to this terminal. + +### Booting the Linux kernel on a FPGA with a synthesized aoR3000 +Together with the aoR3000 core there is also a example SoC in the syn/soc/ directory. It consists of: +- the aoR3000 core; +- an Altera JTAG UART; +- an Altera SDRAM controller; +- a simple time interrupt device; +- onchip memory for the boot code of the aoR3000; +- a Altera JTAG to Avalon Master Bridge to upload the Linux kernel; + +The SoC is designed for the Terasic DE2-115 board. + +To compile the SoC the following steps have to be taken: +- open the Altera Quartus II project in syn/soc/; +- open the Qsys tool and generate the HDL; +- compile the project; +- program the FPGA with the compiled project; +- in the Altera Nios2 Command Shell enter the directory arch/mips/boot/ of the Linux kernel and run 'system-console -cli'; +- load the Linux kernel binary using the system-console by entering the following TCL commands at the system-console prompt: + +--- + set srv [claim_service "master" [lindex [get_service_paths "master"] 0] ""]; + master_write_from_file $srv vmlinux.bin 0; + close_service master $srv; +--- + +- open the nios2-terminal in a Altera Nios2 Command Shell; +- verify that the following text is displayed in the terminal: 'Press any key to boot kernel...'; +- press any key to boot the kernel; + +The kernel is booted with the following output displayed on the nios2-terminal: + +--- + Press any key to boot kernel... + Booting kernel... + console [ttyJ0] enabled + bootconsole [early0] disabled + Freeing unused kernel memory: 176K (80204000 - 80230000) + # +--- + +A shell is run as init in the early root-fs. The early root-fs is the compiled klibc project. + +After running the command dmesg the following output is displayed: + +--- + Linux version 3.16.0 (alek@duke) (gcc version 4.9.1 (GCC) ) #4 Mon Aug 11 23:49:07 CEST 2014 + bootconsole [early0] enabled + CPU0 revision is: 00000230 (R3000A) + Determined physical RAM map: + memory: 08000000 @ 00000000 (usable) + Initrd not found or empty - disabling initrd + Zone ranges: + Normal [mem 0x00000000-0x07ffffff] + Movable zone start for each node + Early memory node ranges + node 0: [mem 0x00000000-0x07ffffff] + On node 0 totalpages: 32768 + free_area_init_node: node 0, pgdat 80203600, node_mem_map 81000000 + Normal zone: 256 pages used for memmap + Normal zone: 0 pages reserved + Normal zone: 32768 pages, LIFO batch:7 + Primary instruction cache 2kB, linesize 4 bytes. + Primary data cache 2kB, linesize 4 bytes. + pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768 + pcpu-alloc: [0] 0 + Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32512 + Kernel command line: console=ttyJ0,115200 + PID hash table entries: 512 (order: -1, 2048 bytes) + Dentry cache hash table entries: 16384 (order: 4, 65536 bytes) + Inode-cache hash table entries: 8192 (order: 3, 32768 bytes) + Memory: 127492K/131072K available (1741K kernel code, 101K rwdata, 212K rodata, 176K init, 171K bss, 3580K reserved) + SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 + NR_IRQS:128 + Console: colour dummy device 80x25 + Calibrating delay loop... 48.74 BogoMIPS (lpj=243712) + pid_max: default: 32768 minimum: 301 + Mount-cache hash table entries: 1024 (order: 0, 4096 bytes) + Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes) + futex hash table entries: 256 (order: -1, 3072 bytes) + io scheduler noop registered + io scheduler deadline registered + io scheduler cfq registered (default) + ttyJ0 at MMIO 0x1ffffff0 (irq = 3, base_baud = 0) is a Altera JTAG UART + console [ttyJ0] enabled + bootconsole [early0] disabled + Freeing unused kernel memory: 176K (80204000 - 80230000) +--- + +### License +Most of the files in this project are under the BSD license. All the Verilog code for the aoR3000 core is under the BSD license. + +A few files are under the GPL license. These files are: +- all files in the sim/vmips/ directory; +- all files in the linux/ directory; + +See the LICENSE file for details.

powered by: WebSVN 2.1.0

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