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 @@