resources: Merge branch 'master' into develop
Change-Id: I7d4259b8337f29c4dc64428a3b1fa3906bde5245
diff --git a/README.md b/README.md
index 7f6be9b..ed11cec 100755
--- a/README.md
+++ b/README.md
@@ -206,62 +206,87 @@
<http://dist.gem5.org/dist/v20/test-progs/insttest/bin/riscv/linux/insttest-rv64m>
-# Resource: PThreads
+# Resource: simple
-## Compilation
+Simple single source file per executable userland or baremetal examples.
-The PThreads executables are compiled to aarch32, aarch64, riscv64, and x86.
+The toplevel executables under `src/simple` can be built for any ISA that we
+have a cross compiler for as mentioned under [Requirements](#requirements).
-### aarch32
+Examples that build only for some ISAs specific ones are present under
+`src/simple/<ISA>` subdirs, e.g. `src/simple/aarch64/`,
-To compile PThreads to aarch32 the [GNU ARM-32 Toolchain](
-#gnu-arm_32-bit-toolchain) must be installed.
+The ISA names are meant to match `uname -m`, e.g.:
-To compile:
+- `aarch64`
+- `arm`
+- `riscv`
+- `x86_64`
-```
-cd src/pthreads
-make -f Makefile.aarch32
-```
+You have to specify the path to the gem5 source code with `GEM5_ROOT` variable so that
+m5ops can be used from there. For example for a native build:
-The binaries can be found in the `src/pthreads/bin.aarch32` directory.
+ cd src/simple
+ make -j`nproc` GEM5_ROOT=../../../
-### aarch64
+The default of that variable is such that if you place this repository and the gem5
+repository in the same directory:
-To compile PThreads to aarch64 the [GNU ARM-64 Toolchain](
-#gnu-arm_64-bit-toolchain) must be installed.
+ ./gem5/
+ ./gem5-resources/
-To compile:
+you can omit that variable and build just with:
-```
-cd src/pthreads
-make -f Makefile.aarch64
-```
+ make
-The binaries can be found in the `src/pthreads/bin.aarch64` directory.
+After the building, the generated files are located under:
-### riscv64
+ ./out/<ISA>/
-To compile PThreads to RISCV64, the [RISCV GNU Compiler](
-#risc_v-gnu-compiler-toolchain) must be install
+For example, some of the userland executables built on x86 are:
-```
-cd src/pthreads
-make -f Makefile.riscv
-```
+ ./out/x86_64/user/hello.out
+ ./out/x86_64/user/x86_64/mwait.out
-The binaries can be found in the `src/pthreads/bin.riscv` directory.
+Or if you build for a different ISA:
-### x86
+ make ISA=aarch64
-To compile:
+some of the executables would be:
-```
-cd src/pthreads
-make -f Makefile.x86
-```
+ ./out/aarch64/user/hello.out
+ ./out/aarch64/user/aarch64/futex_ldxr_stxr.out
-The binaries can be found in the `src/pthreads/bin.x86` directory.
+By default, only userland executables are built. You can build just the baremetal
+ones instead with:
+
+ make ISA=aarch64 bare
+
+or both userland and baremetal with:
+
+ make ISA=aarch64 all
+
+A sample baremetal executable generated by this is:
+
+ out/aarch64/bare/m5_exit.out
+
+Only ISAs that have a corresponding `src/simple/bootloader/` file can build for
+baremetal, e.g. `src/simple/bootloader/aarch64.S`.
+
+Note that a some C source files can produce both a baremetal and an userland.
+For example `m5_exit.c` produces both:
+
+ out/aarch64/bare/m5_exit.out
+ out/aarch64/user/m5_exit.out
+
+However, since the regular userland toolchain is used rather than a more
+specialized baremetal toolchain, the C standard library is not available.
+Therefore, only very few C examples can build for baremetal, notably the ones
+that use m5ops.
+
+There are also examples that can only build for baremetal, e.g.
+`aarch64/semihost_exit` only builds for baremetal, as semihosting is not
+available on userland.
## Pre-build binaries
@@ -429,12 +454,41 @@
The instructions to build the boot-tests disk image (`boot-exit`), the Linux binaries, and how to use gem5 run scripts to run boot-tests are available in this [README](src/boot-tests/README.md) file.
+# Resource: Insttest
+
+The Insttests test SPARC instructions.
+
+Creating the SPARC Insttest binary requires a SPARC cross compile. Instructions
+on creating a cross compiler can be found [here](
+https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler).
+
+## Compilation
+
+To compile:
+
+```
+cd src/insttest
+make
+```
+
+We provide a docker image with a pre-loaded SPARC cross compiler. To use:
+
+```
+cd src/insttest
+docker run --volume $(pwd):$(pwd) -w $(pwd) --rm gcr.io/gem5-test/sparc64-gnu-cross:latest make
+```
+
+The compiled binary can be found in `src/insttest/bin`.
+
+## Prebuild Binary
+
+<http://dist.gem5.org/dist/v20/test-progs/insttest/bin/sparc/linux/insttest>
+
# Resource: Linux Kernel Binary
Contains scripts to create a Linux kernel binary.
Instructions on how to use the scripts can be found here `src/linux-kernel/README.md`.
-
# Licensing
Each project under the `src` is under a different license. Before using
@@ -442,8 +496,6 @@
project's license.
* **riscv-tests** : `src/riscv-tests/LICENSE`.
-* **insttests** : Consult individual copyright notices of source files in
-`src/insttests`.
* **pthreads**: Consult individual copyright notices of source files in
`src/pthreads`.
* **square**: Consult individual copyright notices of source files in
@@ -464,6 +516,7 @@
`src/npb`. The NAS Parallel Benchmarks utilize a permissive BSD-style license.
* **boot-tests**: Consult individual copyright notices of source files in
`src/boot-tests`.
+* **insttest**: Consult individual copyright notices of source files in
+`src/insttest`.
* **linux-kernel**: Consult individual copyright notices of source files in
`src/linux-kernel`.
-
diff --git a/src/boot-exit/configs/system/MESI_Two_Level.py b/src/boot-exit/configs/system/MESI_Two_Level.py
index ef9ec64..4feef12 100755
--- a/src/boot-exit/configs/system/MESI_Two_Level.py
+++ b/src/boot-exit/configs/system/MESI_Two_Level.py
@@ -86,9 +86,9 @@
icache = self.controllers[i].L1Icache,
dcache = self.controllers[i].L1Dcache,
clk_domain = self.controllers[i].clk_domain,
- pio_master_port = iobus.slave,
- mem_master_port = iobus.slave,
- pio_slave_port = iobus.master
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
slave = port)
@@ -113,22 +113,21 @@
# Set up a proxy port for the system_port. Used for load binaries and
# other functional-only things.
self.sys_port_proxy = RubyPortProxy()
- system.system_port = self.sys_port_proxy.slave
- self.sys_port_proxy.pio_master_port = iobus.slave
+ system.system_port = self.sys_port_proxy.in_ports
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
# Connect the cpu's cache, interrupt, and TLB ports to Ruby
for i,cpu in enumerate(cpus):
- cpu.icache_port = self.sequencers[i].slave
- cpu.dcache_port = self.sequencers[i].slave
+ cpu.icache_port = self.sequencers[i].in_ports
+ cpu.dcache_port = self.sequencers[i].in_ports
isa = buildEnv['TARGET_ISA']
if isa == 'x86':
- cpu.interrupts[0].pio = self.sequencers[i].master
- cpu.interrupts[0].int_master = self.sequencers[i].slave
- cpu.interrupts[0].int_slave = self.sequencers[i].master
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
+ cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
if isa == 'x86' or isa == 'arm':
- cpu.itb.walker.port = self.sequencers[i].slave
- cpu.dtb.walker.port = self.sequencers[i].slave
-
+ cpu.itb.walker.port = self.sequencers[i].in_ports
+ cpu.dtb.walker.port = self.sequencers[i].in_ports
class L1Cache(L1Cache_Controller):
@@ -193,18 +192,18 @@
"""
self.mandatoryQueue = MessageBuffer()
self.requestFromL1Cache = MessageBuffer()
- self.requestFromL1Cache.master = ruby_system.network.slave
+ self.requestFromL1Cache.out_port = ruby_system.network.in_port
self.responseFromL1Cache = MessageBuffer()
- self.responseFromL1Cache.master = ruby_system.network.slave
+ self.responseFromL1Cache.out_port = ruby_system.network.in_port
self.unblockFromL1Cache = MessageBuffer()
- self.unblockFromL1Cache.master = ruby_system.network.slave
+ self.unblockFromL1Cache.out_port = ruby_system.network.in_port
self.optionalQueue = MessageBuffer()
self.requestToL1Cache = MessageBuffer()
- self.requestToL1Cache.slave = ruby_system.network.master
+ self.requestToL1Cache.in_port = ruby_system.network.out_port
self.responseToL1Cache = MessageBuffer()
- self.responseToL1Cache.slave = ruby_system.network.master
+ self.responseToL1Cache.in_port = ruby_system.network.out_port
class L2Cache(L2Cache_Controller):
@@ -239,17 +238,17 @@
"""Connect all of the queues for this controller.
"""
self.DirRequestFromL2Cache = MessageBuffer()
- self.DirRequestFromL2Cache.master = ruby_system.network.slave
+ self.DirRequestFromL2Cache.out_port = ruby_system.network.in_port
self.L1RequestFromL2Cache = MessageBuffer()
- self.L1RequestFromL2Cache.master = ruby_system.network.slave
+ self.L1RequestFromL2Cache.out_port = ruby_system.network.in_port
self.responseFromL2Cache = MessageBuffer()
- self.responseFromL2Cache.master = ruby_system.network.slave
+ self.responseFromL2Cache.out_port = ruby_system.network.in_port
self.unblockToL2Cache = MessageBuffer()
- self.unblockToL2Cache.slave = ruby_system.network.master
+ self.unblockToL2Cache.in_port = ruby_system.network.out_port
self.L1RequestToL2Cache = MessageBuffer()
- self.L1RequestToL2Cache.slave = ruby_system.network.master
+ self.L1RequestToL2Cache.in_port = ruby_system.network.out_port
self.responseToL2Cache = MessageBuffer()
- self.responseToL2Cache.slave = ruby_system.network.master
+ self.responseToL2Cache.in_port = ruby_system.network.out_port
class DirController(Directory_Controller):
@@ -271,16 +270,16 @@
self.ruby_system = ruby_system
self.directory = RubyDirectoryMemory()
# Connect this directory to the memory side.
- self.memory = mem_ctrls[0].port
+ self.memory_out_port = mem_ctrls[0].port
self.connectQueues(ruby_system)
def connectQueues(self, ruby_system):
self.requestToDir = MessageBuffer()
- self.requestToDir.slave = ruby_system.network.master
+ self.requestToDir.in_port = ruby_system.network.out_port
self.responseToDir = MessageBuffer()
- self.responseToDir.slave = ruby_system.network.master
+ self.responseToDir.in_port = ruby_system.network.out_port
self.responseFromDir = MessageBuffer()
- self.responseFromDir.master = ruby_system.network.slave
+ self.responseFromDir.out_port = ruby_system.network.in_port
self.requestToMemory = MessageBuffer()
self.responseFromMemory = MessageBuffer()
@@ -301,9 +300,9 @@
def connectQueues(self, ruby_system):
self.mandatoryQueue = MessageBuffer()
self.responseFromDir = MessageBuffer(ordered = True)
- self.responseFromDir.slave = ruby_system.network.master
+ self.responseFromDir.in_port = ruby_system.network.out_port
self.requestToDir = MessageBuffer()
- self.requestToDir.master = ruby_system.network.slave
+ self.requestToDir.out_port = ruby_system.network.in_port
class MyNetwork(SimpleNetwork):
diff --git a/src/boot-exit/configs/system/MI_example_caches.py b/src/boot-exit/configs/system/MI_example_caches.py
index 2a7e975..8aa08ea 100755
--- a/src/boot-exit/configs/system/MI_example_caches.py
+++ b/src/boot-exit/configs/system/MI_example_caches.py
@@ -87,9 +87,9 @@
icache = self.controllers[i].cacheMemory,
dcache = self.controllers[i].cacheMemory,
clk_domain = self.controllers[i].clk_domain,
- pio_master_port = iobus.slave,
- mem_master_port = iobus.slave,
- pio_slave_port = iobus.master
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
slave = port)
@@ -113,21 +113,21 @@
# Set up a proxy port for the system_port. Used for load binaries and
# other functional-only things.
self.sys_port_proxy = RubyPortProxy()
- system.system_port = self.sys_port_proxy.slave
- self.sys_port_proxy.pio_master_port = iobus.slave
+ system.system_port = self.sys_port_proxy.in_ports
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
# Connect the cpu's cache, interrupt, and TLB ports to Ruby
for i,cpu in enumerate(cpus):
- cpu.icache_port = self.sequencers[i].slave
- cpu.dcache_port = self.sequencers[i].slave
+ cpu.icache_port = self.sequencers[i].in_ports
+ cpu.dcache_port = self.sequencers[i].in_ports
isa = buildEnv['TARGET_ISA']
if isa == 'x86':
- cpu.interrupts[0].pio = self.sequencers[i].master
- cpu.interrupts[0].int_master = self.sequencers[i].slave
- cpu.interrupts[0].int_slave = self.sequencers[i].master
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
+ cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
if isa == 'x86' or isa == 'arm':
- cpu.itb.walker.port = self.sequencers[i].slave
- cpu.dtb.walker.port = self.sequencers[i].slave
+ cpu.itb.walker.port = self.sequencers[i].in_ports
+ cpu.dtb.walker.port = self.sequencers[i].in_ports
class L1Cache(L1Cache_Controller):
@@ -177,13 +177,13 @@
"""
self.mandatoryQueue = MessageBuffer()
self.requestFromCache = MessageBuffer(ordered = True)
- self.requestFromCache.master = ruby_system.network.slave
+ self.requestFromCache.out_port = ruby_system.network.in_port
self.responseFromCache = MessageBuffer(ordered = True)
- self.responseFromCache.master = ruby_system.network.slave
+ self.responseFromCache.out_port = ruby_system.network.in_port
self.forwardToCache = MessageBuffer(ordered = True)
- self.forwardToCache.slave = ruby_system.network.master
+ self.forwardToCache.in_port = ruby_system.network.out_port
self.responseToCache = MessageBuffer(ordered = True)
- self.responseToCache.slave = ruby_system.network.master
+ self.responseToCache.in_port = ruby_system.network.out_port
class DirController(Directory_Controller):
@@ -204,21 +204,21 @@
self.ruby_system = ruby_system
self.directory = RubyDirectoryMemory()
# Connect this directory to the memory side.
- self.memory = mem_ctrls[0].port
+ self.memory_out_port = mem_ctrls[0].port
self.connectQueues(ruby_system)
def connectQueues(self, ruby_system):
self.requestToDir = MessageBuffer(ordered = True)
- self.requestToDir.slave = ruby_system.network.master
+ self.requestToDir.in_port = ruby_system.network.out_port
self.dmaRequestToDir = MessageBuffer(ordered = True)
- self.dmaRequestToDir.slave = ruby_system.network.master
+ self.dmaRequestToDir.in_port = ruby_system.network.out_port
self.responseFromDir = MessageBuffer()
- self.responseFromDir.master = ruby_system.network.slave
+ self.responseFromDir.out_port = ruby_system.network.in_port
self.dmaResponseFromDir = MessageBuffer(ordered = True)
- self.dmaResponseFromDir.master = ruby_system.network.slave
+ self.dmaResponseFromDir.out_port = ruby_system.network.in_port
self.forwardFromDir = MessageBuffer()
- self.forwardFromDir.master = ruby_system.network.slave
+ self.forwardFromDir.out_port = ruby_system.network.in_port
self.requestToMemory = MessageBuffer()
self.responseFromMemory = MessageBuffer()
@@ -239,9 +239,9 @@
def connectQueues(self, ruby_system):
self.mandatoryQueue = MessageBuffer()
self.requestToDir = MessageBuffer()
- self.requestToDir.master = ruby_system.network.slave
+ self.requestToDir.out_port = ruby_system.network.in_port
self.responseFromDir = MessageBuffer(ordered = True)
- self.responseFromDir.slave = ruby_system.network.master
+ self.responseFromDir.in_port = ruby_system.network.out_port
class MyNetwork(SimpleNetwork):
diff --git a/src/boot-exit/configs/system/MOESI_CMP_directory.py b/src/boot-exit/configs/system/MOESI_CMP_directory.py
index 1af5cca..5aa49ba 100755
--- a/src/boot-exit/configs/system/MOESI_CMP_directory.py
+++ b/src/boot-exit/configs/system/MOESI_CMP_directory.py
@@ -87,9 +87,9 @@
icache = self.controllers[i].L1Icache,
dcache = self.controllers[i].L1Dcache,
clk_domain = self.controllers[i].clk_domain,
- pio_master_port = iobus.slave,
- mem_master_port = iobus.slave,
- pio_slave_port = iobus.master
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
slave = port)
@@ -114,21 +114,21 @@
# Set up a proxy port for the system_port. Used for load binaries and
# other functional-only things.
self.sys_port_proxy = RubyPortProxy()
- system.system_port = self.sys_port_proxy.slave
- self.sys_port_proxy.pio_master_port = iobus.slave
+ system.system_port = self.sys_port_proxy.in_ports
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
# Connect the cpu's cache, interrupt, and TLB ports to Ruby
for i,cpu in enumerate(cpus):
- cpu.icache_port = self.sequencers[i].slave
- cpu.dcache_port = self.sequencers[i].slave
+ cpu.icache_port = self.sequencers[i].in_ports
+ cpu.dcache_port = self.sequencers[i].in_ports
isa = buildEnv['TARGET_ISA']
if isa == 'x86':
- cpu.interrupts[0].pio = self.sequencers[i].master
- cpu.interrupts[0].int_master = self.sequencers[i].slave
- cpu.interrupts[0].int_slave = self.sequencers[i].master
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
+ cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
if isa == 'x86' or isa == 'arm':
- cpu.itb.walker.port = self.sequencers[i].slave
- cpu.dtb.walker.port = self.sequencers[i].slave
+ cpu.itb.walker.port = self.sequencers[i].in_ports
+ cpu.dtb.walker.port = self.sequencers[i].in_ports
class L1Cache(L1Cache_Controller):
@@ -196,13 +196,13 @@
"""
self.mandatoryQueue = MessageBuffer()
self.requestFromL1Cache = MessageBuffer()
- self.requestFromL1Cache.master = ruby_system.network.slave
+ self.requestFromL1Cache.out_port = ruby_system.network.in_port
self.responseFromL1Cache = MessageBuffer()
- self.responseFromL1Cache.master = ruby_system.network.slave
+ self.responseFromL1Cache.out_port = ruby_system.network.in_port
self.requestToL1Cache = MessageBuffer()
- self.requestToL1Cache.slave = ruby_system.network.master
+ self.requestToL1Cache.in_port = ruby_system.network.out_port
self.responseToL1Cache = MessageBuffer()
- self.responseToL1Cache.slave = ruby_system.network.master
+ self.responseToL1Cache.in_port = ruby_system.network.out_port
self.triggerQueue = MessageBuffer(ordered = True)
class L2Cache(L2Cache_Controller):
@@ -240,18 +240,18 @@
"""Connect all of the queues for this controller.
"""
self.GlobalRequestFromL2Cache = MessageBuffer()
- self.GlobalRequestFromL2Cache.master = ruby_system.network.slave
+ self.GlobalRequestFromL2Cache.out_port = ruby_system.network.in_port
self.L1RequestFromL2Cache = MessageBuffer()
- self.L1RequestFromL2Cache.master = ruby_system.network.slave
+ self.L1RequestFromL2Cache.out_port = ruby_system.network.in_port
self.responseFromL2Cache = MessageBuffer()
- self.responseFromL2Cache.master = ruby_system.network.slave
+ self.responseFromL2Cache.out_port = ruby_system.network.in_port
self.GlobalRequestToL2Cache = MessageBuffer()
- self.GlobalRequestToL2Cache.slave = ruby_system.network.master
+ self.GlobalRequestToL2Cache.in_port = ruby_system.network.out_port
self.L1RequestToL2Cache = MessageBuffer()
- self.L1RequestToL2Cache.slave = ruby_system.network.master
+ self.L1RequestToL2Cache.in_port = ruby_system.network.out_port
self.responseToL2Cache = MessageBuffer()
- self.responseToL2Cache.slave = ruby_system.network.master
+ self.responseToL2Cache.in_port = ruby_system.network.out_port
self.triggerQueue = MessageBuffer(ordered = True)
@@ -275,18 +275,18 @@
self.ruby_system = ruby_system
self.directory = RubyDirectoryMemory()
# Connect this directory to the memory side.
- self.memory = mem_ctrls[0].port
+ self.memory_out_port = mem_ctrls[0].port
self.connectQueues(ruby_system)
def connectQueues(self, ruby_system):
self.requestToDir = MessageBuffer()
- self.requestToDir.slave = ruby_system.network.master
+ self.requestToDir.in_port = ruby_system.network.out_port
self.responseToDir = MessageBuffer()
- self.responseToDir.slave = ruby_system.network.master
+ self.responseToDir.in_port = ruby_system.network.out_port
self.responseFromDir = MessageBuffer()
- self.responseFromDir.master = ruby_system.network.slave
+ self.responseFromDir.out_port = ruby_system.network.in_port
self.forwardFromDir = MessageBuffer()
- self.forwardFromDir.master = ruby_system.network.slave
+ self.forwardFromDir.out_port = ruby_system.network.in_port
self.requestToMemory = MessageBuffer()
self.responseFromMemory = MessageBuffer()
@@ -307,11 +307,11 @@
def connectQueues(self, ruby_system):
self.mandatoryQueue = MessageBuffer()
self.responseFromDir = MessageBuffer()
- self.responseFromDir.slave = ruby_system.network.master
+ self.responseFromDir.in_port = ruby_system.network.out_port
self.reqToDir = MessageBuffer()
- self.reqToDir.master = ruby_system.network.slave
+ self.reqToDir.out_port = ruby_system.network.in_port
self.respToDir = MessageBuffer()
- self.respToDir.master = ruby_system.network.slave
+ self.respToDir.out_port = ruby_system.network.in_port
self.triggerQueue = MessageBuffer(ordered = True)
diff --git a/src/boot-exit/configs/system/caches.py b/src/boot-exit/configs/system/caches.py
index abc0b31..813c6b5 100755
--- a/src/boot-exit/configs/system/caches.py
+++ b/src/boot-exit/configs/system/caches.py
@@ -64,7 +64,7 @@
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
def connectCPU(self, cpu):
"""Connect this cache's port to a CPU-side port
@@ -116,13 +116,13 @@
Note: This creates a new crossbar
"""
self.mmubus = L2XBar()
- self.cpu_side = self.mmubus.master
+ self.cpu_side = self.mmubus.mem_side_ports
for tlb in [cpu.itb, cpu.dtb]:
- self.mmubus.slave = tlb.walker.port
+ self.mmubus.cpu_side_ports = tlb.walker.port
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L2Cache(PrefetchCache):
"""Simple L2 Cache with default values"""
@@ -141,7 +141,7 @@
super(L2Cache, self).__init__()
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
diff --git a/src/boot-exit/configs/system/fs_tools.py b/src/boot-exit/configs/system/fs_tools.py
index 22a43d2..5e5e2df 100755
--- a/src/boot-exit/configs/system/fs_tools.py
+++ b/src/boot-exit/configs/system/fs_tools.py
@@ -33,7 +33,7 @@
def __init__(self, filename):
super(CowDisk, self).__init__()
- self.driveID = 'master'
+ self.driveID = 'device0'
self.image = CowDiskImage(child=RawDiskImage(read_only=True),
read_only=False)
self.image.child.image_file = filename
diff --git a/src/boot-exit/configs/system/ruby_system.py b/src/boot-exit/configs/system/ruby_system.py
index 778743a..e7c1135 100755
--- a/src/boot-exit/configs/system/ruby_system.py
+++ b/src/boot-exit/configs/system/ruby_system.py
@@ -80,7 +80,7 @@
from .MOESI_CMP_directory import MOESICMPDirCache
self.caches = MOESICMPDirCache()
self.caches.setup(self, self.cpu, self.mem_cntrls,
- [self.pc.south_bridge.ide.dma, self.iobus.master],
+ [self.pc.south_bridge.ide.dma, self.iobus.mem_side_ports],
self.iobus)
if self._host_parallel:
@@ -133,7 +133,7 @@
def _createMemoryControllers(self, num, cls):
self.mem_cntrls = [
- cls(range = self.mem_ranges[0])
+ MemCtrl(dram = cls(range = self.mem_ranges[0]))
for i in range(num)
]
diff --git a/src/boot-exit/configs/system/system.py b/src/boot-exit/configs/system/system.py
index 58e37b8..95d0147 100755
--- a/src/boot-exit/configs/system/system.py
+++ b/src/boot-exit/configs/system/system.py
@@ -56,7 +56,7 @@
self.membus.default = Self.badaddr_responder.pio
# Set up the system port for functional access from the simulator
- self.system_port = self.membus.slave
+ self.system_port = self.membus.cpu_side_ports
self.initFS(self.membus, num_cpus)
@@ -163,9 +163,9 @@
# For x86 only, connect interrupts to the memory
# Note: these are directly connected to the memory bus and
# not cached
- cpu.interrupts[0].pio = self.membus.master
- cpu.interrupts[0].int_master = self.membus.slave
- cpu.interrupts[0].int_slave = self.membus.master
+ cpu.interrupts[0].pio = self.membus.mem_side_ports
+ cpu.interrupts[0].int_requestor = self.membus.cpu_side_ports
+ cpu.interrupts[0].int_responder = self.membus.mem_side_ports
def createMemoryControllersDDR3(self):
@@ -173,8 +173,8 @@
def _createMemoryControllers(self, num, cls):
self.mem_cntrls = [
- cls(range = self.mem_ranges[0],
- port = self.membus.master)
+ MemCtrl(dram = cls(range = self.mem_ranges[0]),
+ port = self.membus.mem_side_ports)
for i in range(num)
]
@@ -192,8 +192,8 @@
# North Bridge
self.iobus = IOXBar()
self.bridge = Bridge(delay='50ns')
- self.bridge.master = self.iobus.slave
- self.bridge.slave = membus.master
+ self.bridge.mem_side_port = self.iobus.cpu_side_ports
+ self.bridge.cpu_side_port = membus.mem_side_ports
# Allow the bridge to pass through:
# 1) kernel configured PCI device memory map address: address range
# [0xC0000000, 0xFFFF0000). (The upper 64kB are reserved for m5ops.)
@@ -213,8 +213,8 @@
# Create a bridge from the IO bus to the memory bus to allow access
# to the local APIC (two pages)
self.apicbridge = Bridge(delay='50ns')
- self.apicbridge.slave = self.iobus.master
- self.apicbridge.master = membus.slave
+ self.apicbridge.cpu_side_port = self.iobus.mem_side_ports
+ self.apicbridge.mem_side_port = membus.cpu_side_ports
self.apicbridge.ranges = [AddrRange(interrupts_address_space_base,
interrupts_address_space_base +
cpus * APIC_range_size
@@ -233,8 +233,8 @@
size = '1kB',
tgts_per_mshr = 12,
addr_ranges = self.mem_ranges)
- self.iocache.cpu_side = self.iobus.master
- self.iocache.mem_side = self.membus.slave
+ self.iocache.cpu_side = self.iobus.mem_side_ports
+ self.iocache.mem_side = self.membus.cpu_side_ports
self.intrctrl = IntrControl()
diff --git a/src/hack-back/README.md b/src/hack-back/README.md
new file mode 100755
index 0000000..e2c2b1e
--- /dev/null
+++ b/src/hack-back/README.md
@@ -0,0 +1,63 @@
+# Hack Back Checkpointing Disk Image
+
+This document provides instructions to create a disk image with `hack_back_ckpt.rcS` script (located in `gem5/configs/boot/`) installed.
+This script creates a checkpoint once the Linux system boots up.
+Using environment variables the script makes sure that the checkpoint is not created if one already exists.
+On restoring the simulation from the checkpoint, a new script can be provided to execute the desired applications.
+
+**Note:** The instructions in this README are based on experiments with gem5-20.
+
+We assume the following directory structure while following the instructions in this README file:
+
+```
+npb/
+ |___ gem5/ # gem5 source code
+ |
+ |___ disk-image/
+ | |___ shared/ # Auxiliary files needed for disk creation
+ | |___ hack-back/
+ | |___ hack-back-image/ # Will be created once the disk is generated
+ | | |___ hack-back # The generated disk image
+ | |___ hack-back.json # The Packer script to build the disk image
+ | |___ hack_back_ckpt.rcS # Main script responsible for checkpointing
+ | |___ post-installation.sh # Moves hack_back_ckpt.rcS to guest's .bashrc
+ |
+ |
+ |___ README.md # This README file
+```
+
+## Disk Image
+
+Assuming that you are in the `src/hack-back/` directory (the directory containing this README), first build `m5` (which is needed to create the disk image):
+
+```sh
+git clone https://gem5.googlesource.com/public/gem5
+cd gem5/util/m5
+scons build/x86/out/m5
+```
+
+Next,
+
+```sh
+cd disk-image
+# if packer is not already installed
+wget https://releases.hashicorp.com/packer/1.6.0/packer_1.6.0_linux_amd64.zip
+unzip packer_1.6.0_linux_amd64.zip
+
+# validate the packer script
+./packer validate hack-back/hack-back.json
+# build the disk image
+./packer build hack-back/hack-back.json
+```
+
+Once this process succeeds, the created disk image can be found on `hack-back/hack-back-image/hack-back`.
+
+## Using this Disk Image
+
+The details of how to use this disk image are following:
+
+- On starting a gem5 simulation using this disk image, after the kernel boot, the hack back script is the first thing which will run and exit the simulation with an `exit_event` cause of `checkpoint`.
+- Your gem5 run script should be able to recognize this `exit_event` and take a checkpoint using `m5.checkpoint(m5.options.outdir)`.
+- Later, on restoring the simulation from the checkpoint, you should be able to pass a new script to run your benchmarks, which will start simulating your benchmarks right from the point where the checkpoint was taken.
+- To restore from the checkpoint (assuming that it is in the gem5 outdir), use `m5.instantiate(m5.options.outdir)`.
+- Your benchmark script can be passed using `system.readfile=[path to the script]` in your gem5 run script.
diff --git a/src/hack-back/disk-image/hack-back/hack-back.json b/src/hack-back/disk-image/hack-back/hack-back.json
new file mode 100755
index 0000000..e4d2607
--- /dev/null
+++ b/src/hack-back/disk-image/hack-back/hack-back.json
@@ -0,0 +1,99 @@
+{
+ "_author": "Hoa Nguyen <hoanguyen@ucdavis.edu>, Ayaz Akram <yazakram@ucdavis.edu>",
+ "_license": "Copyright (c) 2020 The Regents of the University of California. SPDX-License-Identifier: BSD 3-Clause",
+ "builders":
+ [
+ {
+ "type": "qemu",
+ "format": "raw",
+ "accelerator": "kvm",
+ "boot_command":
+ [
+ "{{ user `boot_command_prefix` }}",
+ "debian-installer={{ user `locale` }} auto locale={{ user `locale` }} kbd-chooser/method=us ",
+ "file=/floppy/{{ user `preseed` }} ",
+ "fb=false debconf/frontend=noninteractive ",
+ "hostname={{ user `hostname` }} ",
+ "/install/vmlinuz noapic ",
+ "initrd=/install/initrd.gz ",
+ "keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ",
+ "keyboard-configuration/variant=USA console-setup/ask_detect=false ",
+ "passwd/user-fullname={{ user `ssh_fullname` }} ",
+ "passwd/user-password={{ user `ssh_password` }} ",
+ "passwd/user-password-again={{ user `ssh_password` }} ",
+ "passwd/username={{ user `ssh_username` }} ",
+ "-- <enter>"
+ ],
+ "cpus": "{{ user `vm_cpus`}}",
+ "disk_size": "{{ user `image_size` }}",
+ "floppy_files":
+ [
+ "shared/{{ user `preseed` }}"
+ ],
+ "headless": "{{ user `headless` }}",
+ "http_directory": "shared/",
+ "iso_checksum": "{{ user `iso_checksum_type` }}:{{ user `iso_checksum` }}",
+ "iso_urls": [ "{{ user `iso_url` }}" ],
+ "memory": "{{ user `vm_memory`}}",
+ "output_directory": "hack-back/{{ user `image_name` }}-image",
+ "qemuargs":
+ [
+ [ "-cpu", "host" ],
+ [ "-display", "none" ]
+ ],
+ "qemu_binary":"/usr/bin/qemu-system-x86_64",
+ "shutdown_command": "echo '{{ user `ssh_password` }}'|sudo -S shutdown -P now",
+ "ssh_password": "{{ user `ssh_password` }}",
+ "ssh_username": "{{ user `ssh_username` }}",
+ "ssh_wait_timeout": "60m",
+ "vm_name": "{{ user `image_name` }}"
+ }
+ ],
+ "provisioners":
+ [
+ {
+ "type": "file",
+ "source": "../gem5/util/m5/build/x86/out/m5",
+ "destination": "/home/gem5/"
+ },
+ {
+ "type": "file",
+ "source": "shared/serial-getty@.service",
+ "destination": "/home/gem5/"
+ },
+ {
+ "type": "file",
+ "source": "hack-back/hack_back_ckpt.rcS",
+ "destination": "/home/gem5/"
+ },
+ {
+ "type": "shell",
+ "execute_command": "echo '{{ user `ssh_password` }}' | {{.Vars}} sudo -E -S bash '{{.Path}}'",
+ "scripts":
+ [
+ "hack-back/post-installation.sh"
+ ]
+ }
+ ],
+ "variables":
+ {
+ "boot_command_prefix": "<enter><wait><f6><esc><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "desktop": "false",
+ "image_size": "12000",
+ "headless": "true",
+ "iso_checksum": "34416ff83179728d54583bf3f18d42d2",
+ "iso_checksum_type": "md5",
+ "iso_name": "ubuntu-18.04.2-server-amd64.iso",
+ "iso_url": "http://old-releases.ubuntu.com/releases/18.04.2/ubuntu-18.04.2-server-amd64.iso",
+ "locale": "en_US",
+ "preseed" : "preseed.cfg",
+ "hostname": "gem5",
+ "ssh_fullname": "gem5",
+ "ssh_password": "12345",
+ "ssh_username": "gem5",
+ "vm_cpus": "4",
+ "vm_memory": "8192",
+ "image_name": "hack-back"
+ }
+
+}
diff --git a/src/hack-back/disk-image/hack-back/hack_back_ckpt.rcS b/src/hack-back/disk-image/hack-back/hack_back_ckpt.rcS
new file mode 100755
index 0000000..51ca6a3
--- /dev/null
+++ b/src/hack-back/disk-image/hack-back/hack_back_ckpt.rcS
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+#
+# This is a tricky script to understand. When run in M5, it creates
+# a checkpoint after Linux boot up, but before any benchmarks have
+# been run. By playing around with environment variables, we can
+# detect whether the checkpoint has been taken.
+# - If the checkpoint hasn't been taken, the script allows M5 to checkpoint the system,
+# re-read this script into a new tmp file, and re-run it. On the
+# second execution of this script (checkpoint has been taken), the
+# environment variable is already set, so the script will exit the
+# simulation
+# - When we restore the simulation from a checkpoint, we can
+# specify a new script for M5 to execute in the full-system simulation,
+# and it will be executed as if a checkpoint had just been taken.
+#
+# Author:
+# Joel Hestness, hestness@cs.utexas.edu
+# while at AMD Research and Advanced Development Lab
+# Date:
+# 10/5/2010
+#
+
+# Test if the RUNSCRIPT_VAR environment variable is already set
+
+if [ "${RUNSCRIPT_VAR+set}" != set ]
+then
+ # Signal our future self that it's safe to continue
+ export RUNSCRIPT_VAR=1
+else
+ # We've already executed once, so we should exit
+ /sbin/m5 exit
+fi
+
+# Checkpoint the first execution
+echo "Checkpointing simulation..."
+/sbin/m5 checkpoint
+
+# Test if we previously okayed ourselves to run this script
+if [ "$RUNSCRIPT_VAR" -eq 1 ]
+then
+
+ # Signal our future self not to recurse infinitely
+ export RUNSCRIPT_VAR=2
+
+ # Read the script for the checkpoint restored execution
+ echo "Loading new script..."
+ /sbin/m5 readfile > /tmp/runscript
+ chmod 755 /tmp/runscript
+
+ # Execute the new runscript
+ if [ -s /tmp/runscript ]
+ then
+ exec /tmp/runscript
+ else
+ echo "Script not specified. Dropping into shell..."
+ /bin/bash
+ fi
+
+fi
+
+echo "Fell through script. Exiting..."
+/sbin/m5 exit
diff --git a/src/hack-back/disk-image/hack-back/post-installation.sh b/src/hack-back/disk-image/hack-back/post-installation.sh
new file mode 100755
index 0000000..d04ef94
--- /dev/null
+++ b/src/hack-back/disk-image/hack-back/post-installation.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# Copyright (c) 2020 The Regents of the University of California.
+# SPDX-License-Identifier: BSD 3-Clause
+
+echo 'Post Installation Started'
+
+mv /home/gem5/serial-getty@.service /lib/systemd/system/
+
+mv /home/gem5/m5 /sbin
+ln -s /sbin/m5 /sbin/gem5
+
+# copy and run outside (host) script after booting
+cat /home/gem5/hack_back_ckpt.rcS >> /root/.bashrc
+
+echo 'Post Installation Done'
diff --git a/src/hack-back/disk-image/shared/preseed.cfg b/src/hack-back/disk-image/shared/preseed.cfg
new file mode 100755
index 0000000..b5cd8a7
--- /dev/null
+++ b/src/hack-back/disk-image/shared/preseed.cfg
@@ -0,0 +1,96 @@
+# Copyright (c) 2020 The Regents of the University of California.
+# SPDX-License-Identifier: BSD 3-Clause
+
+# Choosing keyboard layout
+d-i debian-installer/locale string en_US
+d-i console-setup/ask_detect boolean false
+d-i keyboard-configuration/xkb-keymap select us
+
+# Choosing network interface
+d-i netcfg/choose_interface select auto
+
+# Assigning hostname and domain
+d-i netcfg/get_hostname string gem5-host
+d-i netcfg/get_domain string gem5-domain
+
+d-i netcfg/wireless_wep string
+
+# https://unix.stackexchange.com/q/216348
+# The above link says there's no way to not to set a mirror
+# Should choose a local minor
+d-i mirror/country string manual
+d-i mirror/http/hostname string archive.ubuntu.com
+d-i mirror/http/directory string /ubuntu
+d-i mirror/http/proxy string
+
+# Setting up `root` password
+d-i passwd/root-login boolean false
+
+# Creating a normal user account. This account has sudo permission.
+d-i passwd/user-fullname string gem5
+d-i passwd/username string gem5
+d-i passwd/user-password password 12345
+d-i passwd/user-password-again password 12345
+d-i user-setup/allow-password-weak boolean true
+
+# No home folder encryption
+d-i user-setup/encrypt-home boolean false
+
+# Choosing the clock timezone
+d-i clock-setup/utc boolean true
+d-i time/zone string US/Eastern
+d-i clock-setup/ntp boolean true
+
+# Choosing partition scheme
+# This setting should result in MBR
+# gem5 doesn't work with logical volumes
+d-i partman-auto/method string regular
+d-i partman-lvm/device_remove_lvm boolean true
+d-i partman-md/device_remove_md boolean true
+d-i partman-lvm/confirm boolean true
+d-i partman-lvm/confirm_nooverwrite boolean true
+
+# Ignoring an option to set the home folder in another partition
+d-i partman-auto/choose_recipe select atomic
+
+# Finishing disk partition settings
+d-i partman-md/confirm boolean true
+d-i partman-partitioning/confirm_write_new_label boolean true
+d-i partman/choose_partition select finish
+d-i partman/confirm boolean true
+d-i partman/confirm_nooverwrite boolean true
+
+# Installing standard packages and ubuntu-server packages
+# More details about ubuntu standard packages:
+# https://packages.ubuntu.com/bionic/ubuntu-standard
+# More details about ubuntu-server packages:
+# https://packages.ubuntu.com/bionic/ubuntu-server
+tasksel tasksel/first multiselect standard, ubuntu-server
+
+# openssh-server is required for communicating with Packer
+# build-essential has standard compiling tools, could be removed
+d-i pkgsel/include string openssh-server build-essential
+# No package upgrade
+d-i pkgsel/upgrade select none
+
+# Updating packages automatically is unnecessary
+d-i pkgsel/update-policy select none
+
+# Choosing not to report installed software to some servers
+popularity-contest popularity-contest/participate boolean false
+
+# Installing grub
+d-i grub-installer/only_debian boolean true
+
+# Specifying which partition to boot
+d-i grub-installer/bootdev string /dev/sda
+
+# Install to the above partition
+d-i grub-installer/bootdev string default
+
+# Answering the prompt saying the installation is finished
+d-i finish-install/reboot_in_progress note
+
+# Answering the prompt saying no bootloader is installed
+# This will appear if grub is not installed
+nobootloader nobootloader/confirmation_common note
diff --git a/src/hack-back/disk-image/shared/serial-getty@.service b/src/hack-back/disk-image/shared/serial-getty@.service
new file mode 100644
index 0000000..b0424f0
--- /dev/null
+++ b/src/hack-back/disk-image/shared/serial-getty@.service
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Serial Getty on %I
+Documentation=man:agetty(8) man:systemd-getty-generator(8)
+Documentation=http://0pointer.de/blog/projects/serial-console.html
+BindsTo=dev-%i.device
+After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target
+After=rc-local.service
+
+# If additional gettys are spawned during boot then we should make
+# sure that this is synchronized before getty.target, even though
+# getty.target didn't actually pull it in.
+Before=getty.target
+IgnoreOnIsolate=yes
+
+# IgnoreOnIsolate causes issues with sulogin, if someone isolates
+# rescue.target or starts rescue.service from multi-user.target or
+# graphical.target.
+Conflicts=rescue.service
+Before=rescue.service
+
+[Service]
+# The '-o' option value tells agetty to replace 'login' arguments with an
+# option to preserve environment (-p), followed by '--' for safety, and then
+# the entered username.
+ExecStart=-/sbin/agetty --autologin root --keep-baud 115200,38400,9600 %I $TERM
+Type=idle
+Restart=always
+UtmpIdentifier=%I
+TTYPath=/dev/%I
+TTYReset=yes
+TTYVHangup=yes
+KillMode=process
+IgnoreSIGPIPE=no
+SendSIGHUP=yes
+
+[Install]
+WantedBy=getty.target
diff --git a/src/insttest/.gitignore b/src/insttest/.gitignore
index 5e56e04..ba077a4 100644
--- a/src/insttest/.gitignore
+++ b/src/insttest/.gitignore
@@ -1 +1 @@
-/bin
+bin
diff --git a/src/insttest/Makefile b/src/insttest/Makefile
index bfe7e66..786f7aa 100644
--- a/src/insttest/Makefile
+++ b/src/insttest/Makefile
@@ -1,4 +1,4 @@
-# Copyright (c) 2016 The University of Virginia
+# Copyright (c) 2020 The Regents of the University of California
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -23,30 +23,22 @@
# 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.
-#
-# Authors: Alec Roelke
-CXX=riscv64-unknown-linux-gnu-g++
-CFLAGS=-std=gnu++11 -O3 -static -march=rv64gc
+CC := sparc64-linux-gcc
+CCFLAGS = -O3 -static
-TARGETS=rv64i rv64m rv64a rv64f rv64d rv64c
-PREFIX=bin
-BINARY=insttest
+BIN_DIR = ./bin
-all: $(TARGETS)
+TESTS = insttest
-$(TARGETS):
- -mkdir -p $(PREFIX)
- $(CXX) $< $(CFLAGS) -o $(PREFIX)/$(BINARY)-$@
+all: $(addprefix $(BIN_DIR)/,$(TESTS))
-rv64i: rv64i.cpp
-rv64m: rv64m.cpp
-rv64a: rv64a.cpp
-rv64f: rv64f.cpp
-rv64d: rv64d.cpp
-rv64c: rv64c.cpp
+$(BIN_DIR)/%: %.c
+ @mkdir -p $(BIN_DIR)
+ $(CC) -o $@ $(CCFLAGS) $^
clean:
- -rm -r $(PREFIX)
+ $(RM) -r $(BIN_DIR)
.PHONY: all clean
+
diff --git a/src/insttest/insttest.c b/src/insttest/insttest.c
new file mode 100644
index 0000000..eef1c1c
--- /dev/null
+++ b/src/insttest/insttest.c
@@ -0,0 +1,205 @@
+#include <stdio.h>
+#include <stdint.h>
+
+void check(int pass) { printf(pass ? "Passed\n" : "Failed\n"); }
+
+void
+ldstubTest()
+{
+ printf("LDSTUB:\t\t");
+
+ uint8_t volatile mem = 0x11;
+ uint8_t rd = 0;
+ uint8_t mem_o = mem, rd_o = rd;
+
+ // Load one byte of memory into rd, zero extended, and set that byte in
+ // memory to all ones.
+ asm volatile ("ldstub [%[address]], %[rd]"
+ : [rd] "=r" (rd)
+ : [address] "r" (&mem));
+
+ check(mem == 0xff && rd == mem_o);
+}
+
+void
+swapTest()
+{
+ printf("SWAP:\t\t");
+
+ uint32_t volatile mem = 0x01234567;
+ uint32_t rd = 0x89ABCDEF;
+ uint32_t mem_o = mem, rd_o = rd;
+
+ // Swap the lower 32 bits of rd with a word of memory. Zero the upper
+ // 32 bits of rd.
+ asm volatile ("swap [%[address]], %[rd]"
+ : [rd] "+r" (rd)
+ : [address] "r" (&mem));
+
+ check(mem == rd_o && rd == mem_o);
+}
+
+void
+casFailTest()
+{
+ printf("CAS FAIL:\t");
+
+ uint32_t rd = 0x00112233;
+ uint32_t volatile mem = 0xffeeddcc;
+ uint32_t rs2 = 0;
+ uint32_t rd_o = rd, mem_o = mem, rs2_o = rs2;
+
+ // Compare the lower 32 bits of rs2 with a word of memory. Since they are
+ // different, leave memory unchanged and put the contents of memory in
+ // rd, zero extended.
+ asm volatile ("cas [%[address]], %[rs2], %[rd]"
+ : [rd] "+r" (rd)
+ : [address] "r" (&mem), [rs2] "r" (rs2));
+
+ check(mem == mem_o && rd == mem_o);
+}
+
+void
+casWorkTest()
+{
+ printf("CAS WORK:\t");
+
+ uint32_t rd = 0x00112233;
+ uint32_t volatile mem = 0xffeeddcc;
+ uint32_t rs2 = 0xffeeddcc;
+ uint32_t rd_o = rd, mem_o = mem, rs2_o = rs2;
+
+ // Compare the lower 32 bits of rs2 with a word of memory. Since they are
+ // equal, swap the value in lower 32 bits of rd with that word of memory.
+ // Zero the upper 32 bits of rd.
+ asm volatile ("cas [%[address]], %[rs2], %[rd]"
+ : [rd] "+r" (rd)
+ : [address] "r" (&mem), [rs2] "r" (rs2));
+
+ check(mem == rd_o && rd == mem_o);
+}
+
+void
+casxFailTest()
+{
+ printf("CASX FAIL:\t");
+
+ uint64_t rd = 0x0011223344556677;
+ uint64_t volatile mem = 0xffeeddccbbaa9988;
+ uint64_t rs2 = 0;
+ uint64_t rd_o = rd, mem_o = mem, rs2_o = rs2;
+
+ // Compare rs2 with a doubleword of memory. Since they are different, leave
+ // memory unchanged and put the contets of memory in rd.
+ asm volatile ("casx [%[address]], %[rs2], %[rd]"
+ : [rd] "+r" (rd)
+ : [address] "r" (&mem), [rs2] "r" (rs2));
+
+ check(mem == mem_o && rd == mem_o);
+}
+
+void
+casxWorkTest()
+{
+ printf("CASX WORK:\t");
+
+ uint64_t rd = 0x0011223344556677;
+ uint64_t volatile mem = 0xffeeddccbbaa9988;
+ uint64_t rs2 = 0xffeeddccbbaa9988;
+ uint64_t rd_o = rd, mem_o = mem, rs2_o = rs2;
+
+ // Compare rs2 with a doubleword of memory. Since they are equal, swap rd
+ // with that doubleword of memory.
+ asm volatile ("casx [%[address]], %[rs2], %[rd]"
+ : [rd] "+r" (rd)
+ : [address] "r" (&mem), [rs2] "r" (rs2));
+
+ check(mem == rd_o && rd == mem_o);
+}
+
+void
+ldtxTest()
+{
+ printf("LDTX:\t\t");
+
+ uint64_t volatile mem[2] __attribute__((aligned(16))) = {
+ 0xffeeddccbbaa9988, 0x0011223344556677 };
+ uint64_t rd1 = 0, rd2 = 0;
+ uint64_t mem_o[2] = { mem[0], mem[1] };
+
+ // LDDA will normally load a doubleword of memory into a register pair,
+ // but when told to use ASI e2 (ASI_TWINX_PRIMARY) it will load two
+ // doublewords which it will put into the register pair.
+ asm volatile (
+ "ldda [%[address]]0xe2, %%g2\n"
+ "mov %%g2, %[rd1]\n"
+ "mov %%g3, %[rd2]\n"
+ : [rd1] "=r" (rd1), [rd2] "=r" (rd2)
+ : [address] "r" (&mem[0])
+ : "%g2", "%g3");
+
+ check(rd1 == mem_o[0] && rd2 == mem_o[1]);
+}
+
+void
+ldtwTest()
+{
+ printf("LDTW:\t\t");
+
+ uint32_t volatile mem[2] __attribute__((aligned(8))) = {
+ 0x89abcdef, 0x01234567 };
+ uint32_t rd1 = 0, rd2 = 0;
+ uint64_t mem_o[2] = { mem[0], mem[1] };
+
+ // Load two adjacent words from memory into the lower 32 bits of a pair
+ // of registers, and zero their upper 32 bits.
+ asm volatile (
+ "ldd [%[address]], %%g2\n"
+ "mov %%g2, %[rd1]\n"
+ "mov %%g3, %[rd2]\n"
+ : [rd1] "=r" (rd1), [rd2] "=r" (rd2)
+ : [address] "r" (&mem[0])
+ : "%g2", "%g3");
+ check(rd1 == mem_o[0] && rd2 == mem_o[1]);
+}
+
+void
+sttwTest()
+{
+ printf("STTW:\t\t");
+
+ uint32_t volatile mem[2] __attribute__((aligned(8))) = { 0, 0 };
+ uint64_t rd1 = 0x89abcdef, rd2 = 0x1234567;
+ uint64_t rd1_o = rd1, rd2_o = rd2;
+
+ // Store the lower 32 bits of a pair of registers into a single doubleword
+ // of memory.
+ asm volatile (
+ "mov %[rd1], %%g2\n"
+ "mov %[rd2], %%g3\n"
+ "std %%g2, [%[address]]"
+ :
+ : [rd1] "r" (rd1), [rd2] "r" (rd2), [address] "r" (&mem[0])
+ : "%g2", "%g3");
+
+ check(mem[0] == rd1_o && mem[1] == rd2_o);
+}
+
+int
+main()
+{
+ printf("Begining test of difficult SPARC instructions...\n");
+
+ ldstubTest();
+ swapTest();
+ casFailTest();
+ casWorkTest();
+ casxFailTest();
+ casxWorkTest();
+ ldtxTest();
+ ldtwTest();
+ sttwTest();
+
+ printf("Done\n");
+ return 0;
+}
diff --git a/src/insttest/insttest.h b/src/insttest/insttest.h
deleted file mode 100644
index be1b86e..0000000
--- a/src/insttest/insttest.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#pragma once
-
-#include <cmath>
-#include <cstdlib>
-#include <functional>
-#include <iostream>
-#include <string>
-
-#define IOP(inst, rd, rs1, imm) \
- asm volatile(inst " %0,%1,%2" : "=r" (rd) : "r" (rs1), "i" (imm))
-
-#define ROP(inst, rd, rs1, rs2) \
- asm volatile(inst " %0,%1,%2" : "=r" (rd) : "r" (rs1), "r" (rs2))
-
-#define FROP(inst, fd, fs1, fs2) \
- asm volatile(inst " %0,%1,%2" : "=f" (fd) : "f" (fs1), "f" (fs2))
-
-#define FR4OP(inst, fd, fs1, fs2, fs3) \
- asm volatile(inst " %0,%1,%2,%3" \
- : "=f" (fd) \
- : "f" (fs1), "f" (fs2), "f" (fs3))
-
-template<typename A, typename B> std::ostream&
-operator<<(std::ostream& os, const std::pair<A, B>& p)
-{
- return os << '(' << p.first << ", " << p.second << ')';
-}
-
-namespace insttest
-{
-
-template<typename T> void
-expect(const T& expected, std::function<T()> func,
- const std::string& test)
-{
- using namespace std;
-
- T result = func();
- cout << test << ": ";
- if (result == expected) {
- cout << "PASS" << endl;
- } else {
- cout << "\033[1;31mFAIL\033[0m (expected " << expected << "; found " <<
- result << ")" << endl;
- }
-}
-
-} // namespace insttest
diff --git a/src/insttest/rv64a.cpp b/src/insttest/rv64a.cpp
deleted file mode 100644
index a6e226c..0000000
--- a/src/insttest/rv64a.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#include <cstdint>
-#include <limits>
-
-#include "insttest.h"
-#include "rv64a.h"
-
-int main()
-{
- using namespace std;
- using namespace insttest;
-
- // Memory (LR.W, SC.W)
- expect<pair<int64_t, int64_t>>({-1, 256}, []{
- int32_t mem = -1;
- int64_t rs2 = 256;
- int64_t rd;
- pair<int64_t, uint64_t> result;
- do {
- rd = A::lr_w(mem);
- result = A::sc_w(rs2, mem);
- } while (result.second == 1);
- return pair<int64_t, uint64_t>(rd, result.first);
- }, "lr.w/sc.w");
- expect<pair<bool, int64_t>>({true, 200}, []{
- int32_t mem = 200;
- pair<int64_t, uint64_t> result = A::sc_w(50, mem);
- return pair<bool, int64_t>(result.second == 1, mem);
- }, "sc.w, no preceding lr.d");
-
- // AMOSWAP.W
- expect<pair<int64_t, int64_t>>({65535, 255},
- []{return A::amoswap_w(255, 65535);}, "amoswap.w");
- expect<pair<int64_t, int64_t>>({0xFFFFFFFF, -1},
- []{return A::amoswap_w(0xFFFFFFFF, 0xFFFFFFFF);},
- "amoswap.w, sign extend");
- expect<pair<int64_t, int64_t>>({0x0000000180000000LL, -1},
- []{return A::amoswap_w(0x00000001FFFFFFFFLL,
- 0x7FFFFFFF80000000LL);},
- "amoswap.w, truncate");
-
- // AMOADD.W
- expect<pair<int64_t, int64_t>>({256, 255},
- []{return A::amoadd_w(255, 1);}, "amoadd.w");
- expect<pair<int64_t, int64_t>>({0, -1},
- []{return A::amoadd_w(0xFFFFFFFF, 1);},
- "amoadd.w, truncate/overflow");
- expect<pair<int64_t, int64_t>>({0xFFFFFFFF, 0x7FFFFFFF},
- []{return A::amoadd_w(0x7FFFFFFF, 0x80000000);},
- "amoadd.w, sign extend");
-
- // AMOXOR.W
- expect<pair<uint64_t, uint64_t>>({0xFFFFFFFFAAAAAAAALL, -1},
- []{return A::amoxor_w(-1, 0x5555555555555555LL);},
- "amoxor.w, truncate");
- expect<pair<uint64_t, uint64_t>>({0x80000000, -1},
- []{return A::amoxor_w(0xFFFFFFFF, 0x7FFFFFFF);},
- "amoxor.w, sign extend");
-
- // AMOAND.W
- expect<pair<uint64_t, uint64_t>>({0xFFFFFFFF00000000LL, -1},
- []{return A::amoand_w(-1, 0);}, "amoand.w, truncate");
- expect<pair<uint64_t, uint64_t>>({0x0000000080000000LL, -1},
- []{return A::amoand_w(0xFFFFFFFF,numeric_limits<int32_t>::min());},
- "amoand.w, sign extend");
-
- // AMOOR.W
- expect<pair<uint64_t, uint64_t>>({0x00000000FFFFFFFFLL, 0},
- []{return A::amoor_w(0, -1);}, "amoor.w, truncate");
- expect<pair<uint64_t, uint64_t>>({0x0000000080000000LL, 0},
- []{return A::amoor_w(0, numeric_limits<int32_t>::min());},
- "amoor.w, sign extend");
-
- // AMOMIN.W
- expect<pair<int64_t, int64_t>>({0x7FFFFFFF00000001LL, 1},
- []{return A::amomin_w(0x7FFFFFFF00000001LL, 0xFFFFFFFF000000FF);},
- "amomin.w, truncate");
- expect<pair<int64_t, int64_t>>({0x00000000FFFFFFFELL, -1},
- []{return A::amomin_w(0xFFFFFFFF, -2);}, "amomin.w, sign extend");
-
- // AMOMAX.W
- expect<pair<int64_t, int64_t>>({0x70000000000000FFLL, 1},
- []{return A::amomax_w(0x7000000000000001LL,0x7FFFFFFF000000FFLL);},
- "amomax.w, truncate");
- expect<pair<int64_t, int64_t>>({-1, numeric_limits<int32_t>::min()},
- []{return A::amomax_w(numeric_limits<int32_t>::min(), -1);},
- "amomax.w, sign extend");
-
- // AMOMINU.W
- expect<pair<uint64_t, uint64_t>>({0x0FFFFFFF000000FFLL, -1},
- []{return A::amominu_w(0x0FFFFFFFFFFFFFFFLL, 0xFFFFFFFF000000FF);},
- "amominu.w, truncate");
- expect<pair<uint64_t, uint64_t>>({0x0000000080000000LL, -1},
- []{return A::amominu_w(0x00000000FFFFFFFFLL, 0x80000000);},
- "amominu.w, sign extend");
-
- // AMOMAXU.W
- expect<pair<uint64_t, uint64_t>>({-1, 0},
- []{return A::amomaxu_w(0xFFFFFFFF00000000LL,
- 0x00000000FFFFFFFFLL);},
- "amomaxu.w, truncate");
- expect<pair<uint64_t, uint64_t>>(
- {0xFFFFFFFF, numeric_limits<int32_t>::min()},
- []{return A::amomaxu_w(0x80000000, 0xFFFFFFFF);},
- "amomaxu.w, sign extend");
-
- // Memory (LR.D, SC.D)
- expect<pair<int64_t, int64_t>>({-1, 256}, []{
- int64_t mem = -1;
- int64_t rs2 = 256;
- int64_t rd;
- pair<int64_t, uint64_t> result;
- do {
- rd = A::lr_d(mem);
- result = A::sc_d(rs2, mem);
- } while (result.second == 1);
- return pair<int64_t, uint64_t>(rd, result.first);
- }, "lr.d/sc.d");
- expect<pair<bool, int64_t>>({true, 200}, []{
- int64_t mem = 200;
- pair<int64_t, uint64_t> result = A::sc_d(50, mem);
- return pair<bool, int64_t>(result.second == 1, mem);
- }, "sc.d, no preceding lr.d");
-
- // AMOSWAP.D
- expect<pair<int64_t, int64_t>>({1, -1}, []{return A::amoswap_d(-1, 1);},
- "amoswap.d");
-
- // AMOADD.D
- expect<pair<int64_t, int64_t>>({0x7000000000000000LL,0x0FFFFFFFFFFFFFFFLL},
- []{return A::amoadd_d(0x0FFFFFFFFFFFFFFFLL,0x6000000000000001LL);},
- "amoadd.d");
- expect<pair<int64_t, int64_t>>({0, 0x7FFFFFFFFFFFFFFFLL},
- []{return A::amoadd_d(0x7FFFFFFFFFFFFFFFLL,0x8000000000000001LL);},
- "amoadd.d, overflow");
-
- // AMOXOR.D
- expect<pair<int64_t, int64_t>>({-1, 0xAAAAAAAAAAAAAAAALL},
- []{return A::amoxor_d(0xAAAAAAAAAAAAAAAALL,0x5555555555555555LL);},
- "amoxor.d (1)");
- expect<pair<int64_t, int64_t>>({0, 0xAAAAAAAAAAAAAAAALL},
- []{return A::amoxor_d(0xAAAAAAAAAAAAAAAALL,0xAAAAAAAAAAAAAAAALL);},
- "amoxor.d (0)");
-
- // AMOAND.D
- expect<pair<int64_t, int64_t>>({0xAAAAAAAAAAAAAAAALL, -1},
- []{return A::amoand_d(-1, 0xAAAAAAAAAAAAAAAALL);}, "amoand.d");
-
- // AMOOR.D
- expect<pair<int64_t, int64_t>>({-1, 0xAAAAAAAAAAAAAAAALL},
- []{return A::amoor_d(0xAAAAAAAAAAAAAAAALL, 0x5555555555555555LL);},
- "amoor.d");
-
- // AMOMIN.D
- expect<pair<int64_t, int64_t>>({-1, -1},
- []{return A::amomin_d(-1, 0);}, "amomin.d");
-
- // AMOMAX.D
- expect<pair<int64_t, int64_t>>({0, -1}, []{return A::amomax_d(-1, 0);},
- "amomax.d");
-
- // AMOMINU.D
- expect<pair<uint64_t, uint64_t>>({0, -1},
- []{return A::amominu_d(-1, 0);}, "amominu.d");
-
- // AMOMAXU.D
- expect<pair<uint64_t, uint64_t>>({-1, -1}, []{return A::amomaxu_d(-1, 0);},
- "amomaxu.d");
-
- return 0;
-}
diff --git a/src/insttest/rv64a.h b/src/insttest/rv64a.h
deleted file mode 100644
index cfd1fd8..0000000
--- a/src/insttest/rv64a.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#pragma once
-
-#include <cstdint>
-#include <tuple>
-
-#include "insttest.h"
-
-namespace A
-{
-
-inline int64_t
-lr_w(int32_t& mem)
-{
- int64_t r = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("lr.w %0,(%1)" : "=r" (r) : "r" (addr) : "memory");
- return r;
-}
-
-inline std::pair<int64_t, uint64_t>
-sc_w(int64_t rs2, int32_t& mem)
-{
- uint64_t addr = (uint64_t)&mem;
- uint64_t rd = -1;
- asm volatile("sc.w %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<int64_t, int64_t>
-amoswap_w(int64_t mem, int64_t rs2)
-{
- int64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amoswap.w %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<int64_t, int64_t>
-amoadd_w(int64_t mem, int64_t rs2)
-{
- int64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amoadd.w %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<uint64_t, uint64_t>
-amoxor_w(uint64_t mem, uint64_t rs2)
-{
- uint64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amoxor.w %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<uint64_t, uint64_t>
-amoand_w(uint64_t mem, uint64_t rs2)
-{
- uint64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amoand.w %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<uint64_t, uint64_t>
-amoor_w(uint64_t mem, uint64_t rs2)
-{
- uint64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amoor.w %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<int64_t, int64_t>
-amomin_w(int64_t mem, int64_t rs2)
-{
- int64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amomin.w %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<int64_t, int64_t>
-amomax_w(int64_t mem, int64_t rs2)
-{
- int64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amomax.w %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<uint64_t, uint64_t>
-amominu_w(uint64_t mem, uint64_t rs2)
-{
- uint64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amominu.w %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<uint64_t, uint64_t>
-amomaxu_w(uint64_t mem, uint64_t rs2)
-{
- uint64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amomaxu.w %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline int64_t
-lr_d(int64_t& mem)
-{
- int64_t r = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("lr.d %0,(%1)" : "=r" (r) : "r" (addr) : "memory");
- return r;
-}
-
-inline std::pair<int64_t, uint64_t>
-sc_d(int64_t rs2, int64_t& mem)
-{
- uint64_t addr = (uint64_t)&mem;
- uint64_t rd = -1;
- asm volatile("sc.d %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<int64_t, int64_t>
-amoswap_d(int64_t mem, int64_t rs2)
-{
- int64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amoswap.d %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<int64_t, int64_t>
-amoadd_d(int64_t mem, int64_t rs2)
-{
- int64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amoadd.d %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<uint64_t, uint64_t>
-amoxor_d(uint64_t mem, uint64_t rs2)
-{
- uint64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amoxor.d %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<uint64_t, uint64_t>
-amoand_d(uint64_t mem, uint64_t rs2)
-{
- uint64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amoand.d %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<uint64_t, uint64_t>
-amoor_d(uint64_t mem, uint64_t rs2)
-{
- uint64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amoor.d %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<int64_t, int64_t>
-amomin_d(int64_t mem, int64_t rs2)
-{
- int64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amomin.d %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<int64_t, int64_t>
-amomax_d(int64_t mem, int64_t rs2)
-{
- int64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amomax.d %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<uint64_t, uint64_t>
-amominu_d(uint64_t mem, uint64_t rs2)
-{
- uint64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amominu.d %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-inline std::pair<uint64_t, uint64_t>
-amomaxu_d(uint64_t mem, uint64_t rs2)
-{
- uint64_t rd = 0;
- uint64_t addr = (uint64_t)&mem;
- asm volatile("amomaxu.d %0,%2,(%1)"
- : "=r" (rd)
- : "r" (addr), "r" (rs2)
- : "memory");
- return {mem, rd};
-}
-
-} // namespace A
diff --git a/src/insttest/rv64c.cpp b/src/insttest/rv64c.cpp
deleted file mode 100644
index 869784d..0000000
--- a/src/insttest/rv64c.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (c) 2017 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#include <limits>
-
-#include "insttest.h"
-#include "rv64c.h"
-#include "rv64d.h"
-
-int main()
-{
- using namespace insttest;
- using namespace std;
-
- // C.LWSP
- expect<bool>(true, []{
- uint64_t lw = 0, lwsp = -1;
- int64_t i = 16;
- asm volatile("lw %0,%2(sp);"
- "c.lwsp %1,%2(sp);"
- : "=r" (lw), "=r" (lwsp)
- : "i" (i));
- return lw == lwsp;
- }, "c.lwsp");
-
- // C.LDSP
- expect<bool>(true, []{
- uint64_t ld = 0, ldsp = -1;
- int64_t i = 8;
- asm volatile("ld %0,%2(sp);"
- "c.ldsp %1,%2(sp);"
- : "=r" (ld), "=r" (ldsp)
- : "i" (i));
- return ld == ldsp;
- }, "c.ldsp");
-
- // C.FLDSP
- expect<bool>(true, []{
- double fld = 0.0, fldsp = -1.0;
- int64_t i = 32;
- asm volatile("fld %0,%2(sp);"
- "c.fldsp %1,%2(sp);"
- : "=f" (fld), "=f" (fldsp)
- : "i" (i));
- return D::bits(fld) == D::bits(fldsp);
- }, "c.fldsp");
-
- // C.SWSP
- expect<bool>(true, []{
- int64_t value = -1, result = 0;
- asm volatile("addi sp,sp,-8;"
- "c.swsp %1,8(sp);"
- "lw %0,8(sp);"
- "addi sp,sp,8;"
- : "=r" (result)
- : "r" (value)
- : "memory");
- return value == result;
- }, "c.swsp");
-
- // C.SDSP
- expect<bool>(true, []{
- int64_t value = -1, result = 0;
- asm volatile("addi sp,sp,-8;"
- "c.sdsp %1,8(sp);"
- "ld %0,8(sp);"
- "addi sp,sp,8;"
- : "=r" (result)
- : "r" (value)
- : "memory");
- return value == result;
- }, "c.sdsp");
-
- // C.FSDSP
- expect<bool>(true, []{
- double value = 0.1, result = numeric_limits<double>::signaling_NaN();
- asm volatile("addi sp,sp,-8;"
- "c.fsdsp %1,8(sp);"
- "fld %0,8(sp);"
- "addi sp,sp,8;"
- : "=f" (result)
- : "f" (value)
- : "memory");
- return value == result;
- }, "c.fsdsp");
-
- // C.LW, C.LD, C.FLD
- expect<int64_t>(458752,
- []{return C::c_load<int32_t, int64_t>(0x00070000);},
- "c.lw, positive");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return C::c_load<int32_t, int64_t>(0x80000000);},
- "c.lw, negative");
- expect<int64_t>(30064771072,
- []{return C::c_load<int64_t, int64_t>(30064771072);}, "c.ld");
- expect<double>(3.1415926, []{return C::c_load<double, double>(3.1415926);},
- "c.fld");
-
- // C.SW, C.SD, C.FSD
- expect<uint32_t>(0xFFFFFFFF, []{return C::c_store<int32_t>(-1);}, "c.sw");
- expect<uint64_t>(-1, []{return C::c_store<int64_t>(-1);}, "c.sd");
- expect<double>(1.61803398875,
- []{return C::c_store<double>(1.61803398875);}, "c.fsd");
-
- // C.J, C.JR, C.JALR
- expect<bool>(true, []{return C::c_j();}, "c.j");
- expect<bool>(true, []{return C::c_jr();}, "c.jr");
- expect<bool>(true, []{return C::c_jalr();}, "c.jalr");
-
- // C.BEQZ
- expect<bool>(true, []{return C::c_beqz(0);}, "c.beqz, zero");
- expect<bool>(false, []{return C::c_beqz(7);}, "c.beqz, not zero");
-
- // C.BNEZ
- expect<bool>(true, []{return C::c_bnez(15);}, "c.bnez, not zero");
- expect<bool>(false, []{return C::c_bnez(0);}, "c.bnez, zero");
-
- // C.LI
- expect<int64_t>(1, []{return C::c_li(1);}, "c.li");
- expect<int64_t>(-1, []{return C::c_li(-1);}, "c.li, sign extend");
-
- // C.LUI
- expect<int64_t>(4096, []{return C::c_lui(1);}, "c.lui");
- // Note that sign extension can't be tested here because apparently the
- // compiler doesn't allow the 6th (sign) bit of the immediate to be 1
-
- // C.ADDI
- expect<int64_t>(15, []{return C::c_addi(7, 8);}, "c.addi");
-
- // C.ADDIW
- expect<int64_t>(15, []{return C::c_addiw(8, 7);}, "c.addiw");
- expect<int64_t>(1, []{return C::c_addiw(0xFFFFFFFF, 2);},
- "c.addiw, overflow");
- expect<int64_t>(1, []{return C::c_addiw(0x100000001, 0);},
- "c.addiw, truncate");
-
- // C.ADDI16SP
- expect<bool>(true, []{
- uint64_t sp = 0, rd = 0;
- const int16_t i = 4;
- asm volatile("mv %0,sp;"
- "c.addi16sp sp,%2;"
- "mv %1,sp;"
- "mv sp,%0;"
- : "+r" (sp), "=r" (rd)
- : "i" (i*16));
- return rd == sp + i*16;
- }, "c.addi16sp");
-
- // C.ADDI4SPN
- expect<bool>(true, []{
- uint64_t sp = 0, rd = 0;
- const int16_t i = 3;
- asm volatile("mv %0,sp;"
- "c.addi4spn %1,sp,%2;"
- : "=r" (sp), "=r" (rd)
- : "i" (i*4));
- return rd == sp + i*4;
- }, "c.addi4spn");
-
- // C.SLLI
- expect<uint64_t>(16, []{return C::c_slli(1, 4);}, "c.slli");
- expect<uint64_t>(0, []{return C::c_slli(8, 61);}, "c.slli, overflow");
-
- // C.SRLI
- expect<uint64_t>(4, []{return C::c_srli(128, 5);}, "c.srli");
- expect<uint64_t>(0, []{return C::c_srli(128, 8);}, "c.srli, overflow");
- expect<uint64_t>(1, []{return C::c_srli(-1, 63);}, "c.srli, -1");
-
- // C.SRAI
- expect<uint64_t>(4, []{return C::c_srai(128, 5);}, "c.srai");
- expect<uint64_t>(0, []{return C::c_srai(128, 8);}, "c.srai, overflow");
- expect<uint64_t>(-1, []{return C::c_srai(-2, 63);}, "c.srai, -1");
-
- // C.ANDI
- expect<uint64_t>(0, []{return C::c_andi(-1, 0);}, "c.andi (0)");
- expect<uint64_t>(0x1234567812345678ULL,
- []{return C::c_andi(0x1234567812345678ULL, -1);}, "c.andi (1)");
-
- // C.MV
- expect<int64_t>(1024, []{return C::c_mv(1024);}, "c.mv");
-
- // C.ADD
- expect<int64_t>(15, []{return C::c_add(10, 5);}, "c.add");
-
- // C.AND
- expect<uint64_t>(0, []{return C::c_and(-1, 0);}, "c.and (0)");
- expect<uint64_t>(0x1234567812345678ULL,
- []{return C::c_and(0x1234567812345678ULL, -1);}, "c.and (-1)");
-
- // C.OR
- expect<uint64_t>(-1,
- []{return C::c_or(0xAAAAAAAAAAAAAAAAULL,
- 0x5555555555555555ULL);},
- "c.or (1)");
- expect<uint64_t>(0xAAAAAAAAAAAAAAAAULL,
- []{return C::c_or(0xAAAAAAAAAAAAAAAAULL,
- 0xAAAAAAAAAAAAAAAAULL);},
- "c.or (A)");
-
- // C.XOR
- expect<uint64_t>(-1,
- []{return C::c_xor(0xAAAAAAAAAAAAAAAAULL,
- 0x5555555555555555ULL);},
- "c.xor (1)");
- expect<uint64_t>(0,
- []{return C::c_xor(0xAAAAAAAAAAAAAAAAULL,
- 0xAAAAAAAAAAAAAAAAULL);},
- "c.xor (0)");
-
- // C.SUB
- expect<int64_t>(65535, []{return C::c_sub(65536, 1);}, "c.sub");
-
- // C.ADDW
- expect<int64_t>(1073742078, []{return C::c_addw(0x3FFFFFFF, 255);},
- "c.addw");
- expect<int64_t>(-1, []{return C::c_addw(0x7FFFFFFF, 0x80000000);},
- "c.addw, overflow");
- expect<int64_t>(65536, []{return C::c_addw(0xFFFFFFFF0000FFFFLL, 1);},
- "c.addw, truncate");
-
- // C.SUBW
- expect<int64_t>(65535, []{return C::c_subw(65536, 1);}, "c.subw");
- expect<int64_t>(-1, []{return C::c_subw(0x7FFFFFFF, 0x80000000);},
- "c.subw, \"overflow\"");
- expect<int64_t>(0,
- []{return C::c_subw(0xAAAAAAAAFFFFFFFFULL,0x55555555FFFFFFFFULL);},
- "c.subw, truncate");
-}
\ No newline at end of file
diff --git a/src/insttest/rv64c.h b/src/insttest/rv64c.h
deleted file mode 100644
index 26d9009..0000000
--- a/src/insttest/rv64c.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (c) 2017 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#pragma once
-
-#include <cstdint>
-#include <type_traits>
-
-#include "insttest.h"
-
-#define CIOP(op, r, imm) asm volatile(op " %0,%1" : "+r" (r) : "i" (imm));
-#define CROP(op, rd, rs) asm volatile(op " %0,%1" : "+r" (rd) : "r" (rs))
-
-namespace C
-{
-
-inline int64_t
-c_li(const int8_t imm)
-{
- int64_t rd = 0;
- CIOP("c.li", rd, imm);
- return rd;
-}
-
-inline int64_t
-c_lui(const int8_t imm)
-{
- int64_t rd = 0;
- CIOP("c.lui", rd, imm);
- return rd;
-}
-
-inline int64_t
-c_addi(int64_t r, const int8_t imm)
-{
- CIOP("c.addi", r, imm);
- return r;
-}
-
-inline int64_t
-c_addiw(int64_t r, const int8_t imm)
-{
- CIOP("c.addiw", r, imm);
- return r;
-}
-
-inline uint64_t
-c_addi4spn(const int16_t imm)
-{
- uint64_t rd = 0;
- asm volatile("c.addi4spn %0,sp,%1" : "=r" (rd) : "i" (imm));
- return rd;
-}
-
-inline uint64_t
-c_slli(uint64_t r, uint8_t shamt)
-{
- CIOP("c.slli", r, shamt);
- return r;
-}
-
-inline uint64_t
-c_srli(uint64_t r, uint8_t shamt)
-{
- CIOP("c.srli", r, shamt);
- return r;
-}
-
-inline int64_t
-c_srai(int64_t r, uint8_t shamt)
-{
- CIOP("c.srai", r, shamt);
- return r;
-}
-
-inline uint64_t
-c_andi(uint64_t r, uint8_t imm)
-{
- CIOP("c.andi", r, imm);
- return r;
-}
-
-inline int64_t
-c_mv(int64_t rs)
-{
- int64_t rd = 0;
- CROP("c.mv", rd, rs);
- return rd;
-}
-
-inline int64_t
-c_add(int64_t rd, int64_t rs)
-{
- CROP("c.add", rd, rs);
- return rd;
-}
-
-inline uint64_t
-c_and(int64_t rd, int64_t rs)
-{
- CROP("c.and", rd, rs);
- return rd;
-}
-
-inline uint64_t
-c_or(int64_t rd, int64_t rs)
-{
- CROP("c.or", rd, rs);
- return rd;
-}
-
-inline uint64_t
-c_xor(int64_t rd, int64_t rs)
-{
- CROP("c.xor", rd, rs);
- return rd;
-}
-
-inline int64_t
-c_sub(int64_t rd, int64_t rs)
-{
- CROP("c.sub", rd, rs);
- return rd;
-}
-
-inline int64_t
-c_addw(int64_t rd, int64_t rs)
-{
- CROP("c.addw", rd, rs);
- return rd;
-}
-
-inline int64_t
-c_subw(int64_t rd, int64_t rs)
-{
- CROP("c.subw", rd, rs);
- return rd;
-}
-
-template<typename M, typename R> inline R
-c_load(M m)
-{
- R r = 0;
- switch (sizeof(M))
- {
- case 4:
- asm volatile("c.lw %0,0(%1)" : "=r" (r) : "r" (&m) : "memory");
- break;
- case 8:
- if (std::is_floating_point<M>::value)
- asm volatile("c.fld %0,0(%1)" : "=f" (r) : "r" (&m) : "memory");
- else
- asm volatile("c.ld %0,0(%1)" : "=r" (r) : "r" (&m) : "memory");
- break;
- }
- return r;
-}
-
-template<typename M> inline M
-c_store(const M& rs)
-{
- M mem = 0;
- switch (sizeof(M))
- {
- case 4:
- asm volatile("c.sw %0,0(%1)" : : "r" (rs), "r" (&mem) : "memory");
- break;
- case 8:
- if (std::is_floating_point<M>::value)
- asm volatile("c.fsd %0,0(%1)" : : "f" (rs), "r" (&mem) : "memory");
- else
- asm volatile("c.sd %0,0(%1)" : : "r" (rs), "r" (&mem) : "memory");
- break;
- }
- return mem;
-}
-
-inline bool
-c_j()
-{
- asm volatile goto("c.j %l[jallabel]" : : : : jallabel);
- return false;
- jallabel:
- return true;
-}
-
-inline bool
-c_jr()
-{
- uint64_t a = 0;
- asm volatile("auipc %0,0;"
- "c.addi %0,12;"
- "c.jr %0;"
- "addi %0,zero,0;"
- "addi %0,%0,0;"
- : "+r" (a));
- return a > 0;
-}
-
-inline bool
-c_jalr()
-{
- int64_t a = 0;
- asm volatile("auipc %0,0;"
- "c.addi %0,12;"
- "c.jalr %0;"
- "addi %0,zero,0;"
- "sub %0,ra,%0;"
- : "+r" (a)
- :
- : "ra");
- return a == -4;
-}
-
-inline bool
-c_beqz(int64_t a)
-{
- asm volatile goto("c.beqz %0,%l[beqlabel]"
- :
- : "r" (a)
- :
- : beqlabel);
- return false;
- beqlabel:
- return true;
-}
-
-inline bool
-c_bnez(int64_t a)
-{
- asm volatile goto("c.bnez %0,%l[beqlabel]"
- :
- : "r" (a)
- :
- : beqlabel);
- return false;
- beqlabel:
- return true;
-}
-
-} // namespace C
\ No newline at end of file
diff --git a/src/insttest/rv64d.cpp b/src/insttest/rv64d.cpp
deleted file mode 100644
index adb62d2..0000000
--- a/src/insttest/rv64d.cpp
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#include <cstdint>
-#include <limits>
-
-#include "insttest.h"
-#include "rv64d.h"
-#include "rv64f.h"
-
-int main()
-{
- using namespace std;
- using namespace insttest;
-
- // Memory (FLD, FSD)
- expect<double>(3.1415926, []{return D::load(3.1415926);}, "fld");
- expect<double>(1.61803398875, []{return D::store(1.61803398875);}, "fsd");
-
- // FMADD.D
- expect<double>(D::number(0x4019FD5AED13B1CEULL),
- []{return D::fmadd_d(3.1415926, 1.61803398875,1.41421356237);},
- "fmadd.d");
- expect<bool>(true, []{
- double fd = D::fmadd_d(numeric_limits<double>::quiet_NaN(), 3.14,
- 1.816);
- return D::isquietnan(fd);
- }, "fmadd.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fmadd_d(3.14,
- numeric_limits<double>::signaling_NaN(), 1.816);
- return D::isquietnan(fd);
- }, "fmadd.d, signaling NaN");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fmadd_d(3.14, numeric_limits<double>::infinity(),1.414);},
- "fmadd.d, infinity");
- expect<double>(-numeric_limits<double>::infinity(),
- []{return D::fmadd_d(3.14,-numeric_limits<double>::infinity(),1.414);},
- "fmadd.d, -infinity");
-
- // FMSUB.D
- expect<double>(D::number(0x400d5A1773A85E43ULL),
- []{return D::fmsub_d(3.1415926, 1.61803398875, 1.41421356237);},
- "fmsub.d");
- expect<bool>(true, []{
- double fd = D::fmsub_d(3.14, numeric_limits<double>::quiet_NaN(),
- 1.414);
- return D::isquietnan(fd);
- }, "fmsub.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fmsub_d(3.14, 1.816,
- numeric_limits<double>::signaling_NaN());
- return D::isquietnan(fd);
- }, "fmsub.d, signaling NaN");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fmsub_d(numeric_limits<double>::infinity(), 1.816,
- 1.414);},
- "fmsub.d, infinity");
- expect<double>(-numeric_limits<double>::infinity(),
- []{return D::fmsub_d(3.14, -numeric_limits<double>::infinity(),
- 1.414);},
- "fmsub.d, -infinity");
- expect<double>(-numeric_limits<double>::infinity(),
- []{return D::fmsub_d(3.14, 1.816,
- numeric_limits<double>::infinity());},
- "fmsub.d, subtract infinity");
-
- // FNMSUB.D
- expect<double>(D::number(0xC00D5A1773A85E43ULL),
- []{return D::fnmsub_d(3.1415926, 1.61803398875, 1.41421356237);},
- "fnmsub.d");
- expect<bool>(true, []{
- double fd = D::fnmsub_d(3.14, 1.816,
- numeric_limits<double>::quiet_NaN());
- return D::isquietnan(fd);
- }, "fnmsub.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fnmsub_d(numeric_limits<double>::signaling_NaN(),
- 1.816, 1.414);
- return D::isquietnan(fd);
- }, "fnmsub.d, signaling NaN");
- expect<double>(-numeric_limits<double>::infinity(),
- []{return D::fnmsub_d(numeric_limits<double>::infinity(), 1.816,
- 1.414);},
- "fnmsub.d, infinity");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fnmsub_d(3.14, -numeric_limits<double>::infinity(),
- 1.414);},
- "fnmsub.d, -infinity");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fnmsub_d(3.14, 1.816,
- numeric_limits<double>::infinity());},
- "fnmsub.d, subtract infinity");
-
- // FNMADD.D
- expect<double>(D::number(0xC019FD5AED13B1CEULL),
- []{return D::fnmadd_d(3.1415926, 1.61803398875, 1.41421356237);},
- "fnmadd.d");
- expect<bool>(true, []{
- double fd = D::fnmadd_d(numeric_limits<double>::quiet_NaN(), 3.14,
- 1.816);
- return D::isquietnan(fd);
- }, "fnmadd.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fnmadd_d(3.14,
- numeric_limits<double>::signaling_NaN(), 1.816);
- return D::isquietnan(fd);
- }, "fnmadd.d, signaling NaN");
- expect<double>(-numeric_limits<double>::infinity(),
- []{return D::fnmadd_d(3.14, numeric_limits<double>::infinity(),
- 1.414);},
- "fnmadd.d, infinity");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fnmadd_d(3.14, -numeric_limits<double>::infinity(),
- 1.414);},
- "fnmadd.d, -infinity");
-
- // FADD.D
- expect<double>(D::number(0x4012392540292D7CULL),
- []{return D::fadd_d(3.1415926, 1.41421356237);}, "fadd.d");
- expect<bool>(true, []{
- double fd = D::fadd_d(numeric_limits<double>::quiet_NaN(), 1.414);
- return D::isquietnan(fd);
- }, "fadd.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fadd_d(3.14,
- numeric_limits<double>::signaling_NaN());
- return D::isquietnan(fd);
- }, "fadd.d, signaling NaN");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fadd_d(3.14, numeric_limits<double>::infinity());},
- "fadd.d, infinity");
- expect<double>(-numeric_limits<double>::infinity(),
- []{return D::fadd_d(-numeric_limits<double>::infinity(), 1.816);},
- "fadd.d, -infinity");
-
- // FSUB.D
- expect<double>(D::number(0xBFFBA35833AB7AAEULL),
- []{return D::fsub_d(1.4142135623, 3.1415926);}, "fsub.d");
- expect<bool>(true, []{
- double fd = D::fsub_d(numeric_limits<double>::quiet_NaN(), 1.414);
- return D::isquietnan(fd);
- }, "fsub.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fsub_d(3.14,
- numeric_limits<double>::signaling_NaN());
- return D::isquietnan(fd);
- }, "fsub.d, signaling NaN");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fsub_d(numeric_limits<double>::infinity(), 3.14);},
- "fsub.d, infinity");
- expect<double>(-numeric_limits<double>::infinity(),
- []{return D::fsub_d(-numeric_limits<double>::infinity(), 3.14);},
- "fsub.d, -infinity");
- expect<double>(-numeric_limits<double>::infinity(),
- []{return D::fsub_d(1.414, numeric_limits<double>::infinity());},
- "fsub.d, subtract infinity");
-
- // FMUL.D
- expect<double>(D::number(0x40024E53B708ED9AULL),
- []{return D::fmul_d(1.61803398875, 1.4142135623);}, "fmul.d");
- expect<bool>(true, []{
- double fd = D::fmul_d(numeric_limits<double>::quiet_NaN(), 1.414);
- return D::isquietnan(fd);
- }, "fmul.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fmul_d(1.816,
- numeric_limits<double>::signaling_NaN());
- return D::isquietnan(fd);
- }, "fmul.d, signaling NaN");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fmul_d(numeric_limits<double>::infinity(), 2.718);},
- "fmul.d, infinity");
- expect<double>(-numeric_limits<double>::infinity(),
- []{return D::fmul_d(2.5966, -numeric_limits<double>::infinity());},
- "fmul.d, -infinity");
- expect<bool>(true, []{
- double fd = D::fmul_d(0.0, numeric_limits<double>::infinity());
- return D::isquietnan(fd);
- }, "fmul.d, 0*infinity");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fmul_d(numeric_limits<double>::max(), 2.0);},
- "fmul.d, overflow");
- expect<double>(0.0,
- []{return D::fmul_d(numeric_limits<double>::min(),
- numeric_limits<double>::min());},
- "fmul.d, underflow");
-
- // FDIV.D
- expect<double>(2.5, []{return D::fdiv_d(10.0, 4.0);}, "fdiv.d");
- expect<bool>(true, []{
- double fd = D::fdiv_d(numeric_limits<double>::quiet_NaN(), 4.0);
- return D::isquietnan(fd);
- }, "fdiv.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fdiv_d(10.0,
- numeric_limits<double>::signaling_NaN());
- return D::isquietnan(fd);
- }, "fdiv.d, signaling NaN");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fdiv_d(10.0, 0.0);}, "fdiv.d/0");
- expect<double>(0.0,
- []{return D::fdiv_d(10.0, numeric_limits<double>::infinity());},
- "fdiv.d/infinity");
- expect<bool>(true, []{
- double fd = D::fdiv_d(numeric_limits<double>::infinity(),
- numeric_limits<double>::infinity());
- return D::isquietnan(fd);
- }, "fdiv.d, infinity/infinity");
- expect<bool>(true, []{
- double fd = D::fdiv_d(0.0, 0.0);
- return D::isquietnan(fd);
- }, "fdiv.d, 0/0");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fdiv_d(numeric_limits<double>::infinity(), 0.0);},
- "fdiv.d, infinity/0");
- expect<double>(0.0,
- []{return D::fdiv_d(0.0, numeric_limits<double>::infinity());},
- "fdiv.d, 0/infinity");
- expect<double>(0.0,
- []{return D::fdiv_d(numeric_limits<double>::min(),
- numeric_limits<double>::max());},
- "fdiv.d, underflow");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fdiv_d(numeric_limits<double>::max(),
- numeric_limits<double>::min());},
- "fdiv.d, overflow");
-
- // FSQRT.D
- expect<double>(1e154, []{return D::fsqrt_d(1e308);}, "fsqrt.d");
- expect<bool>(true, []{
- double fd = D::fsqrt_d(-1.0);
- return D::isquietnan(fd);
- }, "fsqrt.d, NaN");
- expect<bool>(true, []{
- double fd = D::fsqrt_d(numeric_limits<double>::quiet_NaN());
- return D::isquietnan(fd);
- }, "fsqrt.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fsqrt_d(numeric_limits<double>::signaling_NaN());
- return D::isquietnan(fd);
- }, "fsqrt.d, signaling NaN");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fsqrt_d(numeric_limits<double>::infinity());},
- "fsqrt.d, infinity");
-
- // FSGNJ.D
- expect<double>(1.0, []{return D::fsgnj_d(1.0, 25.0);}, "fsgnj.d, ++");
- expect<double>(-1.0, []{return D::fsgnj_d(1.0, -25.0);}, "fsgnj.d, +-");
- expect<double>(1.0, []{return D::fsgnj_d(-1.0, 25.0);}, "fsgnj.d, -+");
- expect<double>(-1.0, []{return D::fsgnj_d(-1.0, -25.0);}, "fsgnj.d, --");
- expect<bool>(true, []{
- double fd = D::fsgnj_d(numeric_limits<double>::quiet_NaN(), -4.0);
- return D::isquietnan(fd);
- }, "fsgnj.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fsgnj_d(numeric_limits<double>::signaling_NaN(),
- -4.0);
- return D::issignalingnan(fd);
- }, "fsgnj.d, signaling NaN");
- expect<double>(4.0,
- []{return D::fsgnj_d(4.0, numeric_limits<double>::quiet_NaN());},
- "fsgnj.d, inject NaN");
- expect<double>(-4.0,
- []{return D::fsgnj_d(4.0, -numeric_limits<double>::quiet_NaN());},
- "fsgnj.d, inject -NaN");
-
- // FSGNJN.D
- expect<double>(-1.0, []{return D::fsgnjn_d(1.0, 25.0);}, "fsgnjn.d, ++");
- expect<double>(1.0, []{return D::fsgnjn_d(1.0, -25.0);}, "fsgnjn.d, +-");
- expect<double>(-1.0, []{return D::fsgnjn_d(-1.0, 25.0);}, "fsgnjn.d, -+");
- expect<double>(1.0, []{return D::fsgnjn_d(-1.0, -25.0);}, "fsgnjn.d, --");
- expect<bool>(true, []{
- double fd = D::fsgnjn_d(numeric_limits<double>::quiet_NaN(), -4.0);
- return D::isquietnan(fd);
- }, "fsgnjn.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fsgnjn_d(numeric_limits<double>::signaling_NaN(),
- -4.0);
- return D::issignalingnan(fd);
- }, "fsgnjn.d, signaling NaN");
- expect<double>(-4.0,
- []{return D::fsgnjn_d(4.0, numeric_limits<double>::quiet_NaN());},
- "fsgnjn.d, inject NaN");
- expect<double>(4.0,
- []{return D::fsgnjn_d(4.0, -numeric_limits<double>::quiet_NaN());},
- "fsgnjn.d, inject NaN");
-
- // FSGNJX.D
- expect<double>(1.0, []{return D::fsgnjx_d(1.0, 25.0);}, "fsgnjx.d, ++");
- expect<double>(-1.0, []{return D::fsgnjx_d(1.0, -25.0);}, "fsgnjx.d, +-");
- expect<double>(-1.0, []{return D::fsgnjx_d(-1.0, 25.0);}, "fsgnjx.d, -+");
- expect<double>(1.0, []{return D::fsgnjx_d(-1.0, -25.0);}, "fsgnjx.d, --");
- expect<bool>(true, []{
- double fd = D::fsgnjx_d(numeric_limits<double>::quiet_NaN(), -4.0);
- return D::isquietnan(fd);
- }, "fsgnjx.d, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fsgnjx_d(numeric_limits<double>::signaling_NaN(),
- -4.0);
- return D::issignalingnan(fd);
- }, "fsgnjx.d, signaling NaN");
- expect<double>(4.0,
- []{return D::fsgnjx_d(4.0, numeric_limits<double>::quiet_NaN());},
- "fsgnjx.d, inject NaN");
- expect<double>(-4.0,
- []{return D::fsgnjx_d(4.0, -numeric_limits<double>::quiet_NaN());},
- "fsgnjx.d, inject NaN");
-
- // FMIN.D
- expect<double>(2.718, []{return D::fmin_d(3.14, 2.718);}, "fmin.d");
- expect<double>(-numeric_limits<double>::infinity(),
- []{return D::fmin_d(-numeric_limits<double>::infinity(),
- numeric_limits<double>::min());},
- "fmin.d, -infinity");
- expect<double>(numeric_limits<double>::max(),
- []{return D::fmin_d(numeric_limits<double>::infinity(),
- numeric_limits<double>::max());},
- "fmin.d, infinity");
- expect<double>(-1.414,
- []{return D::fmin_d(numeric_limits<double>::quiet_NaN(), -1.414);},
- "fmin.d, quiet NaN first");
- expect<double>(2.718,
- []{return D::fmin_d(2.718, numeric_limits<double>::quiet_NaN());},
- "fmin.d, quiet NaN second");
- expect<bool>(true, []{
- double fd = D::fmin_d(numeric_limits<double>::quiet_NaN(),
- numeric_limits<double>::quiet_NaN());
- return D::isquietnan(fd);
- }, "fmin.d, quiet NaN both");
- expect<double>(3.14,
- []{return D::fmin_d(numeric_limits<double>::signaling_NaN(),
- 3.14);},
- "fmin.d, signaling NaN first");
- expect<double>(1.816,
- []{return D::fmin_d(1.816,
- numeric_limits<double>::signaling_NaN());},
- "fmin.d, signaling NaN second");
- expect<bool>(true, []{
- double fd = D::fmin_d(numeric_limits<double>::signaling_NaN(),
- numeric_limits<double>::signaling_NaN());
- return D::issignalingnan(fd);
- }, "fmin.d, signaling NaN both");
-
- // FMAX.D
- expect<double>(3.14, []{return D::fmax_d(3.14, 2.718);}, "fmax.d");
- expect<double>(numeric_limits<double>::min(),
- []{return D::fmax_d(-numeric_limits<double>::infinity(),
- numeric_limits<double>::min());},
- "fmax.d, -infinity");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fmax_d(numeric_limits<double>::infinity(),
- numeric_limits<double>::max());},
- "fmax.d, infinity");
- expect<double>(-1.414,
- []{return D::fmax_d(numeric_limits<double>::quiet_NaN(), -1.414);},
- "fmax.d, quiet NaN first");
- expect<double>(2.718,
- []{return D::fmax_d(2.718, numeric_limits<double>::quiet_NaN());},
- "fmax.d, quiet NaN second");
- expect<bool>(true, []{
- double fd = D::fmax_d(numeric_limits<double>::quiet_NaN(),
- numeric_limits<double>::quiet_NaN());
- return D::isquietnan(fd);
- }, "fmax.d, quiet NaN both");
- expect<double>(3.14,
- []{return D::fmax_d(numeric_limits<double>::signaling_NaN(),
- 3.14);},
- "fmax.d, signaling NaN first");
- expect<double>(1.816,
- []{return D::fmax_d(1.816,
- numeric_limits<double>::signaling_NaN());},
- "fmax.d, signaling NaN second");
- expect<bool>(true, []{
- double fd = D::fmax_d(numeric_limits<double>::signaling_NaN(),
- numeric_limits<double>::signaling_NaN());
- return D::issignalingnan(fd);
- }, "fmax.d, signaling NaN both");
-
- // FCVT.S.D
- expect<float>(4.0, []{return D::fcvt_s_d(4.0);}, "fcvt.s.d");
- expect<bool>(true, []{
- float fd = D::fcvt_s_d(numeric_limits<double>::quiet_NaN());
- return F::isquietnan(fd);
- }, "fcvt.s.d, quiet NaN");
- expect<bool>(true, []{
- float fd = D::fcvt_s_d(numeric_limits<double>::signaling_NaN());
- return F::isquietnan(fd);
- }, "fcvt.s.d, signaling NaN");
- expect<float>(numeric_limits<float>::infinity(),
- []{return D::fcvt_s_d(numeric_limits<double>::infinity());},
- "fcvt.s.d, infinity");
- expect<float>(numeric_limits<float>::infinity(),
- []{return D::fcvt_s_d(numeric_limits<double>::max());},
- "fcvt.s.d, overflow");
- expect<float>(0.0, []{return D::fcvt_s_d(numeric_limits<double>::min());},
- "fcvt.s.d, underflow");
-
- // FCVT.D.S
- expect<double>(D::number(0x4005BE76C0000000),
- []{return D::fcvt_d_s(2.718);}, "fcvt.d.s");
- expect<bool>(true, []{
- double fd = D::fcvt_d_s(numeric_limits<float>::quiet_NaN());
- return D::isquietnan(fd);
- }, "fcvt.d.s, quiet NaN");
- expect<bool>(true, []{
- double fd = D::fcvt_d_s(numeric_limits<float>::signaling_NaN());
- return D::isquietnan(fd);
- }, "fcvt.d.s, signaling NaN");
- expect<double>(numeric_limits<double>::infinity(),
- []{return D::fcvt_d_s(numeric_limits<float>::infinity());},
- "fcvt.d.s, infinity");
-
- // FEQ.D
- expect<bool>(true, []{return D::feq_d(1.414, 1.414);}, "feq.d, equal");
- expect<bool>(false,[]{return D::feq_d(2.718, 1.816);}, "feq.d, not equal");
- expect<bool>(true, []{return D::feq_d(0.0, -0.0);}, "feq.d, 0 == -0");
- expect<bool>(false,
- []{return D::feq_d(numeric_limits<double>::quiet_NaN(), -1.0);},
- "feq.d, quiet NaN first");
- expect<bool>(false,
- []{return D::feq_d(2.0, numeric_limits<double>::quiet_NaN());},
- "feq.d, quiet NaN second");
- expect<bool>(false,
- []{return D::feq_d(numeric_limits<double>::quiet_NaN(),
- numeric_limits<double>::quiet_NaN());},
- "feq.d, quiet NaN both");
- expect<bool>(false,
- []{return D::feq_d(numeric_limits<double>::signaling_NaN(),-1.0);},
- "feq.d, signaling NaN first");
- expect<bool>(false,
- []{return D::feq_d(2.0, numeric_limits<double>::signaling_NaN());},
- "feq.d, signaling NaN second");
- expect<bool>(false,
- []{return D::feq_d(numeric_limits<double>::signaling_NaN(),
- numeric_limits<double>::signaling_NaN());},
- "feq.d, signaling NaN both");
-
- // FLT.D
- expect<bool>(false, []{return D::flt_d(1.414, 1.414);}, "flt.d, equal");
- expect<bool>(true, []{return D::flt_d(1.816, 2.718);}, "flt.d, less");
- expect<bool>(false, []{return D::flt_d(2.718, 1.816);}, "flt.d, greater");
- expect<bool>(false,
- []{return D::flt_d(numeric_limits<double>::quiet_NaN(), -1.0);},
- "flt.d, quiet NaN first");
- expect<bool>(false,
- []{return D::flt_d(2.0, numeric_limits<double>::quiet_NaN());},
- "flt.d, quiet NaN second");
- expect<bool>(false,
- []{return D::flt_d(numeric_limits<double>::quiet_NaN(),
- numeric_limits<double>::quiet_NaN());},
- "flt.d, quiet NaN both");
- expect<bool>(false,
- []{return D::flt_d(numeric_limits<double>::signaling_NaN(),-1.0);},
- "flt.d, signaling NaN first");
- expect<bool>(false,
- []{return D::flt_d(2.0, numeric_limits<double>::signaling_NaN());},
- "flt.d, signaling NaN second");
- expect<bool>(false,
- []{return D::flt_d(numeric_limits<double>::signaling_NaN(),
- numeric_limits<double>::signaling_NaN());},
- "flt.d, signaling NaN both");
-
- // FLE.D
- expect<bool>(true, []{return D::fle_d(1.414, 1.414);}, "fle.d, equal");
- expect<bool>(true, []{return D::fle_d(1.816, 2.718);}, "fle.d, less");
- expect<bool>(false, []{return D::fle_d(2.718, 1.816);}, "fle.d, greater");
- expect<bool>(true, []{return D::fle_d(0.0, -0.0);}, "fle.d, 0 == -0");
- expect<bool>(false,
- []{return D::fle_d(numeric_limits<double>::quiet_NaN(), -1.0);},
- "fle.d, quiet NaN first");
- expect<bool>(false,
- []{return D::fle_d(2.0, numeric_limits<double>::quiet_NaN());},
- "fle.d, quiet NaN second");
- expect<bool>(false,
- []{return D::fle_d(numeric_limits<double>::quiet_NaN(),
- numeric_limits<double>::quiet_NaN());},
- "fle.d, quiet NaN both");
- expect<bool>(false,
- []{return D::fle_d(numeric_limits<double>::signaling_NaN(),-1.0);},
- "fle.d, signaling NaN first");
- expect<bool>(false,
- []{return D::fle_d(2.0, numeric_limits<double>::signaling_NaN());},
- "fle.d, signaling NaN second");
- expect<bool>(false,
- []{return D::fle_d(numeric_limits<double>::signaling_NaN(),
- numeric_limits<double>::signaling_NaN());},
- "fle.d, signaling NaN both");
-
- // FCLASS.D
- expect<uint64_t>(0x1,
- []{return D::fclass_d(-numeric_limits<double>::infinity());},
- "fclass.d, -infinity");
- expect<uint64_t>(0x2,
- []{return D::fclass_d(-3.14);}, "fclass.d, -normal");
- expect<uint64_t>(0x4,
- []{return D::fclass_d(D::number(0x800FFFFFFFFFFFFFULL));},
- "fclass.d, -subnormal");
- expect<uint64_t>(0x8, []{return D::fclass_d(-0.0);}, "fclass.d, -0.0");
- expect<uint64_t>(0x10, []{return D::fclass_d(0.0);}, "fclass.d, 0.0");
- expect<uint64_t>(0x20,
- []{return D::fclass_d(D::number(0x000FFFFFFFFFFFFFULL));},
- "fclass.d, subnormal");
- expect<uint64_t>(0x40, []{return D::fclass_d(1.816);}, "fclass.d, normal");
- expect<uint64_t>(0x80,
- []{return D::fclass_d(numeric_limits<double>::infinity());},
- "fclass.d, infinity");
- expect<uint64_t>(0x100,
- []{return D::fclass_d(numeric_limits<double>::signaling_NaN());},
- "fclass.d, signaling NaN");
- expect<uint64_t>(0x200,
- []{return D::fclass_d(numeric_limits<double>::quiet_NaN());},
- "fclass.s, quiet NaN");
-
- // FCVT.W.D
- expect<int64_t>(256, []{return D::fcvt_w_d(256.3);},
- "fcvt.w.d, truncate positive");
- expect<int64_t>(-256, []{return D::fcvt_w_d(-256.2);},
- "fcvt.w.d, truncate negative");
- expect<int64_t>(0, []{return D::fcvt_w_d(0.0);}, "fcvt.w.d, 0.0");
- expect<int64_t>(0, []{return D::fcvt_w_d(-0.0);}, "fcvt.w.d, -0.0");
- expect<int64_t>(numeric_limits<int32_t>::max(),
- []{return D::fcvt_w_d(numeric_limits<double>::max());},
- "fcvt.w.d, overflow");
- expect<int64_t>(0, []{return D::fcvt_w_d(numeric_limits<double>::min());},
- "fcvt.w.d, underflow");
- expect<int64_t>(numeric_limits<int32_t>::max(),
- []{return D::fcvt_w_d(numeric_limits<double>::infinity());},
- "fcvt.w.d, infinity");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return D::fcvt_w_d(-numeric_limits<double>::infinity());},
- "fcvt.w.d, -infinity");
- expect<int64_t>(numeric_limits<int32_t>::max(),
- []{return D::fcvt_w_d(numeric_limits<double>::quiet_NaN());},
- "fcvt.w.d, quiet NaN");
- expect<int64_t>(numeric_limits<int32_t>::max(),
- []{return D::fcvt_w_d(-numeric_limits<double>::quiet_NaN());},
- "fcvt.w.d, quiet -NaN");
- expect<int64_t>(numeric_limits<int32_t>::max(),
- []{return D::fcvt_w_d(numeric_limits<double>::signaling_NaN());},
- "fcvt.w.d, signaling NaN");
-
- // FCVT.WU.D
- expect<uint64_t>(256, []{return D::fcvt_wu_d(256.3);},
- "fcvt.wu.d, truncate positive");
- expect<uint64_t>(0, []{return D::fcvt_wu_d(-256.2);},
- "fcvt.wu.d, truncate negative");
- expect<uint64_t>(0, []{return D::fcvt_wu_d(0.0);}, "fcvt.wu.d, 0.0");
- expect<uint64_t>(0, []{return D::fcvt_wu_d(-0.0);}, "fcvt.wu.d, -0.0");
- expect<uint64_t>(numeric_limits<uint64_t>::max(),
- []{return D::fcvt_wu_d(numeric_limits<double>::max());},
- "fcvt.wu.d, overflow");
- expect<uint64_t>(0,[]{return D::fcvt_wu_d(numeric_limits<double>::min());},
- "fcvt.wu.d, underflow");
- expect<uint64_t>(numeric_limits<uint64_t>::max(),
- []{return D::fcvt_wu_d(numeric_limits<double>::infinity());},
- "fcvt.wu.d, infinity");
- expect<uint64_t>(0,
- []{return D::fcvt_wu_d(-numeric_limits<double>::infinity());},
- "fcvt.wu.d, -infinity");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return D::fcvt_wu_d(numeric_limits<double>::quiet_NaN());},
- "fcvt.wu.d, quiet NaN");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return D::fcvt_wu_d(-numeric_limits<double>::quiet_NaN());},
- "fcvt.wu.d, quiet -NaN");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return D::fcvt_wu_d(numeric_limits<double>::signaling_NaN());},
- "fcvt.wu.d, signaling NaN");
-
- // FCVT.D.W
- expect<double>(0.0, []{return D::fcvt_d_w(0);}, "fcvt.d.w, 0");
- expect<double>(-2147483648.0,
- []{return D::fcvt_d_w(numeric_limits<int32_t>::min());},
- "fcvt.d.w, negative");
- expect<double>(255.0, []{return D::fcvt_d_w(0xFFFFFFFF000000FFLL);},
- "fcvt.d.w, truncate");
-
- // FCVT.D.WU
- expect<double>(0.0, []{return D::fcvt_d_wu(0);}, "fcvt.d.wu, 0");
- expect<double>(2147483648.0,
- []{return D::fcvt_d_wu(numeric_limits<int32_t>::min());},
- "fcvt.d.wu");
- expect<double>(255.0,
- []{return D::fcvt_d_wu(0xFFFFFFFF000000FFLL);},
- "fcvt.d.wu, truncate");
-
- // FCVT.L.D
- expect<int64_t>(256, []{return D::fcvt_l_d(256.3);},
- "fcvt.l.d, truncate positive");
- expect<int64_t>(-256, []{return D::fcvt_l_d(-256.2);},
- "fcvt.l.d, truncate negative");
- expect<int64_t>(0, []{return D::fcvt_l_d(0.0);}, "fcvt.l.d, 0.0");
- expect<int64_t>(0, []{return D::fcvt_l_d(-0.0);}, "fcvt.l.d, -0.0");
- expect<int64_t>(-8589934592LL, []{return D::fcvt_l_d(-8589934592.0);},
- "fcvt.l.d, 32-bit overflow");
- expect<int64_t>(numeric_limits<int64_t>::max(),
- []{return D::fcvt_l_d(numeric_limits<double>::max());},
- "fcvt.l.d, overflow");
- expect<int64_t>(0, []{return D::fcvt_l_d(numeric_limits<double>::min());},
- "fcvt.l.d, underflow");
- expect<int64_t>(numeric_limits<int64_t>::max(),
- []{return D::fcvt_l_d(numeric_limits<double>::infinity());},
- "fcvt.l.d, infinity");
- expect<int64_t>(numeric_limits<int64_t>::min(),
- []{return D::fcvt_l_d(-numeric_limits<double>::infinity());},
- "fcvt.l.d, -infinity");
- expect<int64_t>(numeric_limits<int64_t>::max(),
- []{return D::fcvt_l_d(numeric_limits<double>::quiet_NaN());},
- "fcvt.l.d, quiet NaN");
- expect<int64_t>(numeric_limits<int64_t>::max(),
- []{return D::fcvt_l_d(-numeric_limits<double>::quiet_NaN());},
- "fcvt.l.d, quiet -NaN");
- expect<int64_t>(numeric_limits<int64_t>::max(),
- []{return D::fcvt_l_d(numeric_limits<double>::signaling_NaN());},
- "fcvt.l.d, signaling NaN");
-
- // FCVT.LU.D
- expect<uint64_t>(256, []{return D::fcvt_lu_d(256.3);},
- "fcvt.lu.d, truncate positive");
- expect<uint64_t>(0, []{return D::fcvt_lu_d(-256.2);},
- "fcvt.lu.d, truncate negative");
- expect<uint64_t>(0, []{return D::fcvt_lu_d(0.0);}, "fcvt.lu.d, 0.0");
- expect<uint64_t>(0, []{return D::fcvt_lu_d(-0.0);}, "fcvt.lu.d, -0.0");
- expect<uint64_t>(8589934592LL, []{return D::fcvt_lu_d(8589934592.0);},
- "fcvt.lu.d, 32-bit overflow");
- expect<uint64_t>(numeric_limits<uint64_t>::max(),
- []{return D::fcvt_lu_d(numeric_limits<double>::max());},
- "fcvt.lu.d, overflow");
- expect<uint64_t>(0,[]{return D::fcvt_lu_d(numeric_limits<double>::min());},
- "fcvt.lu.d, underflow");
- expect<uint64_t>(numeric_limits<uint64_t>::max(),
- []{return D::fcvt_lu_d(numeric_limits<double>::infinity());},
- "fcvt.lu.d, infinity");
- expect<uint64_t>(0,
- []{return D::fcvt_lu_d(-numeric_limits<double>::infinity());},
- "fcvt.lu.d, -infinity");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return D::fcvt_lu_d(numeric_limits<double>::quiet_NaN());},
- "fcvt.lu.d, quiet NaN");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return D::fcvt_lu_d(-numeric_limits<double>::quiet_NaN());},
- "fcvt.lu.d, quiet -NaN");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return D::fcvt_lu_d(numeric_limits<double>::signaling_NaN());},
- "fcvt.lu.d, signaling NaN");
-
- // FMV.X.D
- expect<uint64_t>(0x40091EB851EB851FULL, []{return D::fmv_x_d(3.14);},
- "fmv.x.d, positive");
- expect<uint64_t>(0xC0091EB851EB851FULL, []{return D::fmv_x_d(-3.14);},
- "fmv.x.d, negative");
- expect<uint64_t>(0x0000000000000000ULL, []{return D::fmv_x_d(0.0);},
- "fmv.x.d, 0.0");
- expect<uint64_t>(0x8000000000000000ULL, []{return D::fmv_x_d(-0.0);},
- "fmv.x.d, -0.0");
-
- // FCVT.D.L
- expect<double>(0.0, []{return D::fcvt_d_l(0);}, "fcvt.d.l, 0");
- expect<double>(D::number(0xC3E0000000000000),
- []{return D::fcvt_d_l(numeric_limits<int64_t>::min());},
- "fcvt.d.l, negative");
- expect<double>(D::number(0xC1EFFFFFE0200000),
- []{return D::fcvt_d_l(0xFFFFFFFF000000FFLL);},
- "fcvt.d.l, 32-bit truncate");
-
- // FCVT.D.LU
- expect<double>(0.0, []{return D::fcvt_d_lu(0);}, "fcvt.d.lu, 0");
- expect<double>(D::number(0x43E0000000000000),
- []{return D::fcvt_d_lu(numeric_limits<int64_t>::min());},
- "fcvt.d.lu");
- expect<double>(D::number(0x43EFFFFFFFE00000),
- []{return D::fcvt_d_lu(0xFFFFFFFF000000FFLL);},
- "fcvt.d.lu, 32-bit truncate");
-
- // FMV.D.X
- expect<double>(-numeric_limits<float>::infinity(),
- []{return D::fmv_d_x(0xFFF0000000000000ULL);}, "fmv.d.x");
-
- return 0;
-}
diff --git a/src/insttest/rv64d.h b/src/insttest/rv64d.h
deleted file mode 100644
index d2c5898..0000000
--- a/src/insttest/rv64d.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#pragma once
-
-#include <cstdint>
-#include <limits>
-
-#include "insttest.h"
-
-namespace D
-{
-
-constexpr inline uint64_t
-bits(double d)
-{
- return reinterpret_cast<uint64_t&>(d);
-}
-
-constexpr inline double
-number(uint64_t b)
-{
- return reinterpret_cast<double&>(b);
-}
-
-inline bool
-isquietnan(double f)
-{
- return std::isnan(f) && (bits(f)&0x0008000000000000ULL) != 0;
-}
-
-inline bool
-issignalingnan(double f)
-{
- return std::isnan(f) && (bits(f)&0x0008000000000000ULL) == 0;
-}
-
-inline double
-load(double mem)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- asm volatile("fld %0,%1"
- : "=f" (fd)
- : "m" (mem));
- return fd;
-}
-
-inline double
-store(double fs)
-{
- double mem = std::numeric_limits<double>::signaling_NaN();
- asm volatile("fsd %1,%0" : "=m" (mem) : "f" (fs));
- return mem;
-}
-
-inline double
-fmadd_d(double fs1, double fs2, double fs3)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FR4OP("fmadd.d", fd, fs1, fs2, fs3);
- return fd;
-}
-
-inline double
-fmsub_d(double fs1, double fs2, double fs3)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FR4OP("fmsub.d", fd, fs1, fs2, fs3);
- return fd;
-}
-
-inline double
-fnmsub_d(double fs1, double fs2, double fs3)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FR4OP("fnmsub.d", fd, fs1, fs2, fs3);
- return fd;
-}
-
-inline double
-fnmadd_d(double fs1, double fs2, double fs3)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FR4OP("fnmadd.d", fd, fs1, fs2, fs3);
- return fd;
-}
-
-inline double
-fadd_d(double fs1, double fs2)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FROP("fadd.d", fd, fs1, fs2);
- return fd;
-}
-
-inline double
-fsub_d(double fs1, double fs2)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FROP("fsub.d", fd, fs1, fs2);
- return fd;
-}
-
-inline double
-fmul_d(double fs1, double fs2)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FROP("fmul.d", fd, fs1, fs2);
- return fd;
-}
-
-inline double
-fdiv_d(double fs1, double fs2)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FROP("fdiv.d", fd, fs1, fs2);
- return fd;
-}
-
-inline double
-fsqrt_d(double fs1)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- asm volatile("fsqrt.d %0,%1" : "=f" (fd) : "f" (fs1));
- return fd;
-}
-
-inline double
-fsgnj_d(double fs1, double fs2)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FROP("fsgnj.d", fd, fs1, fs2);
- return fd;
-}
-
-inline double
-fsgnjn_d(double fs1, double fs2)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FROP("fsgnjn.d", fd, fs1, fs2);
- return fd;
-}
-
-inline double
-fsgnjx_d(double fs1, double fs2)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FROP("fsgnjx.d", fd, fs1, fs2);
- return fd;
-}
-
-inline double
-fmin_d(double fs1, double fs2)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FROP("fmin.d", fd, fs1, fs2);
- return fd;
-}
-
-inline double
-fmax_d(double fs1, double fs2)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- FROP("fmax.d", fd, fs1, fs2);
- return fd;
-}
-
-inline float
-fcvt_s_d(double fs1)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- asm volatile("fcvt.s.d %0,%1" : "=f" (fd) : "f" (fs1));
- return fd;
-}
-
-inline double
-fcvt_d_s(float fs1)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- asm volatile("fcvt.d.s %0,%1" : "=f" (fd) : "f" (fs1));
- return fd;
-}
-
-inline bool
-feq_d(double fs1, double fs2)
-{
- bool rd = false;
- asm volatile("feq.d %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2));
- return rd;
-}
-
-inline bool
-flt_d(double fs1, double fs2)
-{
- bool rd = false;
- asm volatile("flt.d %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2));
- return rd;
-}
-
-inline bool
-fle_d(double fs1, double fs2)
-{
- bool rd = false;
- asm volatile("fle.d %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2));
- return rd;
-}
-
-inline uint64_t
-fclass_d(double fs1)
-{
- uint64_t rd = -1;
- asm volatile("fclass.d %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline int64_t
-fcvt_w_d(double fs1)
-{
- int64_t rd = 0;
- asm volatile("fcvt.w.d %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline uint64_t
-fcvt_wu_d(double fs1)
-{
- uint64_t rd = 0;
- asm volatile("fcvt.wu.d %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline float
-fcvt_d_w(int64_t rs1)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- asm volatile("fcvt.d.w %0,%1" : "=f" (fd) : "r" (rs1));
- return fd;
-}
-
-inline double
-fcvt_d_wu(uint64_t rs1)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- asm volatile("fcvt.d.wu %0,%1" : "=f" (fd) : "r" (rs1));
- return fd;
-}
-
-inline int64_t
-fcvt_l_d(double fs1)
-{
- int64_t rd = 0;
- asm volatile("fcvt.l.d %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline uint64_t
-fcvt_lu_d(double fs1)
-{
- uint64_t rd = 0;
- asm volatile("fcvt.lu.d %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline uint64_t
-fmv_x_d(double fs1)
-{
- uint64_t rd = 0;
- asm volatile("fmv.x.d %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline double
-fcvt_d_l(int64_t rs1)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- asm volatile("fcvt.d.l %0,%1" : "=f" (fd) : "r" (rs1));
- return fd;
-}
-
-inline double
-fcvt_d_lu(uint64_t rs1)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- asm volatile("fcvt.d.lu %0,%1" : "=f" (fd) : "r" (rs1));
- return fd;
-}
-
-inline double
-fmv_d_x(uint64_t rs1)
-{
- double fd = std::numeric_limits<double>::signaling_NaN();
- asm volatile("fmv.d.x %0,%1" : "=f" (fd) : "r" (rs1));
- return fd;
-}
-
-} // namespace D
diff --git a/src/insttest/rv64f.cpp b/src/insttest/rv64f.cpp
deleted file mode 100644
index f8b79f4..0000000
--- a/src/insttest/rv64f.cpp
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#include <cstdint>
-#include <limits>
-
-#include "insttest.h"
-#include "rv64f.h"
-
-int main()
-{
- using namespace std;
- using namespace insttest;
-
- // FLAGS
- expect<uint64_t>(0, []{
- F::fsflags(0);
- return F::frflags();
- }, "clear fsflags");
-
- // Memory
- expect<float>(3.14, []{return F::load(3.14);}, "flw");
- expect<float>(1.816, []{return F::store(1.816);}, "fsw");
-
- // FMADD.S
- expect<float>(7.11624, []{return F::fmadd_s(3.14, 1.816, 1.414);},
- "fmadd.s");
- expect<bool>(true, []{
- float fd = F::fmadd_s(numeric_limits<float>::quiet_NaN(), 3.14,
- 1.816);
- return F::isquietnan(fd);
- }, "fmadd.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fmadd_s(3.14, numeric_limits<float>::signaling_NaN(),
- 1.816);
- return F::isquietnan(fd);
- }, "fmadd.s, signaling NaN");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fmadd_s(3.14, numeric_limits<float>::infinity(),
- 1.414);},
- "fmadd.s, infinity");
- expect<float>(-numeric_limits<float>::infinity(),
- []{return F::fmadd_s(3.14, -numeric_limits<float>::infinity(),
- 1.414);},
- "fmadd.s, -infinity");
-
- // FMSUB.S
- expect<float>(4.28824, []{return F::fmsub_s(3.14, 1.816, 1.414);},
- "fmsub.s");
- expect<bool>(true, []{
- float fd = F::fmsub_s(3.14, numeric_limits<float>::quiet_NaN(),
- 1.816);
- return F::isquietnan(fd);
- }, "fmsub.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fmsub_s(3.14, 1.816,
- numeric_limits<float>::signaling_NaN());
- return F::isquietnan(fd);
- }, "fmsub.s, signaling NaN");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fmsub_s(numeric_limits<float>::infinity(), 1.816,
- 1.414);},
- "fmsub.s, infinity");
- expect<float>(-numeric_limits<float>::infinity(),
- []{return F::fmsub_s(3.14, -numeric_limits<float>::infinity(),
- 1.414);},
- "fmsub.s, -infinity");
- expect<float>(-numeric_limits<float>::infinity(),
- []{return F::fmsub_s(3.14, 1.816,
- numeric_limits<float>::infinity());},
- "fmsub.s, subtract infinity");
-
- // FNMSUB.S
- expect<float>(-4.28824, []{return F::fnmsub_s(3.14, 1.816, 1.414);},
- "fnmsub.s");
- expect<bool>(true, []{
- float fd = F::fnmsub_s(3.14, 1.816,
- numeric_limits<float>::quiet_NaN());
- return F::isquietnan(fd);
- }, "fnmsub.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fnmsub_s(numeric_limits<float>::signaling_NaN(),
- 1.816, 1.414);
- return F::isquietnan(fd);
- }, "fnmsub.s, signaling NaN");
- expect<float>(-numeric_limits<float>::infinity(),
- []{return F::fnmsub_s(numeric_limits<float>::infinity(),
- 1.816, 1.414);},
- "fnmsub.s, infinity");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fnmsub_s(3.14, -numeric_limits<float>::infinity(),
- 1.414);},
- "fnmsub.s, -infinity");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fnmsub_s(3.14, 1.816,
- numeric_limits<float>::infinity());},
- "fnmsub.s, subtract infinity");
-
- // FNMADD.S
- expect<float>(-7.11624, []{return F::fnmadd_s(3.14, 1.816, 1.414);},
- "fnmadd.s");
- expect<bool>(true, []{
- float fd = F::fnmadd_s(numeric_limits<float>::quiet_NaN(), 3.14,
- 1.816);
- return F::isquietnan(fd);
- }, "fnmadd.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fnmadd_s(3.14,numeric_limits<float>::signaling_NaN(),
- 1.816);
- return F::isquietnan(fd);
- }, "fnmadd.s, signaling NaN");
- expect<float>(-numeric_limits<float>::infinity(),
- []{return F::fnmadd_s(3.14, numeric_limits<float>::infinity(),
- 1.414);},
- "fnmadd.s, infinity");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fnmadd_s(3.14, -numeric_limits<float>::infinity(),
- 1.414);},
- "fnmadd.s, -infinity");
-
- // FADD.S
- expect<float>(4.554, []{return F::fadd_s(3.14, 1.414);}, "fadd.s");
- expect<bool>(true, []{
- float fd = F::fadd_s(numeric_limits<float>::quiet_NaN(), 1.414);
- return F::isquietnan(fd);
- }, "fadd.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fadd_s(3.14, numeric_limits<float>::signaling_NaN());
- return F::isquietnan(fd);
- }, "fadd.s, signaling NaN");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fadd_s(3.14, numeric_limits<float>::infinity());},
- "fadd.s, infinity");
- expect<float>(-numeric_limits<float>::infinity(),
- []{return F::fadd_s(-numeric_limits<float>::infinity(), 1.816);},
- "fadd.s, -infinity");
-
- // FSUB.S
- expect<float>(F::number(0xbfdced92), []{return F::fsub_s(1.414, 3.14);},
- "fsub.s");
- expect<bool>(true, []{
- float fd = F::fsub_s(numeric_limits<float>::quiet_NaN(), 1.414);
- return F::isquietnan(fd);
- }, "fsub.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fsub_s(3.14, numeric_limits<float>::signaling_NaN());
- return F::isquietnan(fd);
- }, "fsub.s, signaling NaN");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fsub_s(numeric_limits<float>::infinity(), 3.14);},
- "fsub.s, infinity");
- expect<float>(-numeric_limits<float>::infinity(),
- []{return F::fsub_s(-numeric_limits<float>::infinity(), 3.14);},
- "fsub.s, -infinity");
- expect<float>(-numeric_limits<float>::infinity(),
- []{return F::fsub_s(1.414, numeric_limits<float>::infinity());},
- "fsub.s, subtract infinity");
-
- // FMUL.S
- expect<float>(F::number(0x4024573b), []{return F::fmul_s(1.816, 1.414);},
- "fmul.s");
- expect<bool>(true, []{
- float fd = F::fmul_s(numeric_limits<float>::quiet_NaN(), 1.414);
- return F::isquietnan(fd);
- }, "fmul.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fmul_s(1.816,
- numeric_limits<float>::signaling_NaN());
- return F::isquietnan(fd);
- }, "fmul.s, signaling NaN");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fmul_s(numeric_limits<float>::infinity(), 2.718);},
- "fmul.s, infinity");
- expect<float>(-numeric_limits<float>::infinity(),
- []{return F::fmul_s(2.5966, -numeric_limits<float>::infinity());},
- "fmul.s, -infinity");
- expect<bool>(true, []{
- float fd = F::fmul_s(0.0, numeric_limits<float>::infinity());
- return F::isquietnan(fd);
- }, "fmul.s, 0*infinity");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fmul_s(numeric_limits<float>::max(), 2.0);},
- "fmul.s, overflow");
- expect<float>(0.0,
- []{return F::fmul_s(numeric_limits<float>::min(),
- numeric_limits<float>::min());},
- "fmul.s, underflow");
-
- // FDIV.S
- expect<float>(2.5, []{return F::fdiv_s(10.0, 4.0);}, "fdiv.s");
- expect<bool>(true, []{
- float fd = F::fdiv_s(numeric_limits<float>::quiet_NaN(), 4.0);
- return F::isquietnan(fd);
- }, "fdiv.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fdiv_s(10.0, numeric_limits<float>::signaling_NaN());
- return F::isquietnan(fd);
- }, "fdiv.s, signaling NaN");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fdiv_s(10.0, 0.0);}, "fdiv.s/0");
- expect<float>(0.0,
- []{return F::fdiv_s(10.0, numeric_limits<float>::infinity());},
- "fdiv.s/infinity");
- expect<bool>(true, []{
- float fd = F::fdiv_s(numeric_limits<float>::infinity(),
- numeric_limits<float>::infinity());
- return F::isquietnan(fd);
- }, "fdiv.s, infinity/infinity");
- expect<bool>(true, []{
- float fd = F::fdiv_s(0.0, 0.0);
- return F::isquietnan(fd);
- }, "fdiv.s, 0/0");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fdiv_s(numeric_limits<float>::infinity(), 0.0);},
- "fdiv.s, infinity/0");
- expect<float>(0.0,
- []{return F::fdiv_s(0.0, numeric_limits<float>::infinity());},
- "fdiv.s, 0/infinity");
- expect<float>(0.0,
- []{return F::fdiv_s(numeric_limits<float>::min(),
- numeric_limits<float>::max());},
- "fdiv.s, underflow");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fdiv_s(numeric_limits<float>::max(),
- numeric_limits<float>::min());},
- "fdiv.s, overflow");
-
- // FSQRT.S
- expect<float>(0.3, []{return F::fsqrt_s(0.09);}, "fsqrt.s");
- expect<bool>(true, []{
- float fd = F::fsqrt_s(-1.0);
- return F::isquietnan(fd);
- }, "fsqrt.s, NaN");
- expect<bool>(true, []{
- float fd = F::fsqrt_s(numeric_limits<float>::quiet_NaN());
- return F::isquietnan(fd);
- }, "fsqrt.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fsqrt_s(numeric_limits<float>::signaling_NaN());
- return F::isquietnan(fd);
- }, "fsqrt.s, signaling NaN");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fsqrt_s(numeric_limits<float>::infinity());},
- "fsqrt.s, infinity");
-
- // FSGNJ.S
- expect<float>(1.0, []{return F::fsgnj_s(1.0, 25.0);}, "fsgnj.s, ++");
- expect<float>(-1.0, []{return F::fsgnj_s(1.0, -25.0);}, "fsgnj.s, +-");
- expect<float>(1.0, []{return F::fsgnj_s(-1.0, 25.0);}, "fsgnj.s, -+");
- expect<float>(-1.0, []{return F::fsgnj_s(-1.0, -25.0);}, "fsgnj.s, --");
- expect<bool>(true, []{
- float fd = F::fsgnj_s(numeric_limits<float>::quiet_NaN(), -4.0);
- return F::isquietnan(fd);
- }, "fsgnj.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fsgnj_s(numeric_limits<float>::signaling_NaN(),
- -4.0);
- return F::issignalingnan(fd);
- }, "fsgnj.s, signaling NaN");
- expect<float>(4.0, []{return F::fsgnj_s(4.0,
- numeric_limits<float>::quiet_NaN());}, "fsgnj.s, inject NaN");
- expect<float>(-4.0,
- []{return F::fsgnj_s(4.0, -numeric_limits<float>::quiet_NaN());},
- "fsgnj.s, inject -NaN");
-
- // FSGNJN.S
- expect<float>(-1.0, []{return F::fsgnjn_s(1.0, 25.0);}, "fsgnjn.s, ++");
- expect<float>(1.0, []{return F::fsgnjn_s(1.0, -25.0);}, "fsgnjn.s, +-");
- expect<float>(-1.0, []{return F::fsgnjn_s(-1.0, 25.0);}, "fsgnjn.s, -+");
- expect<float>(1.0, []{return F::fsgnjn_s(-1.0, -25.0);}, "fsgnjn.s, --");
- expect<bool>(true, []{
- float fd = F::fsgnjn_s(numeric_limits<float>::quiet_NaN(), -4.0);
- return F::isquietnan(fd);
- }, "fsgnjn.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fsgnjn_s(numeric_limits<float>::signaling_NaN(),
- -4.0);
- return F::issignalingnan(fd);
- }, "fsgnjn.s, signaling NaN");
- expect<float>(-4.0,
- []{return F::fsgnjn_s(4.0, numeric_limits<float>::quiet_NaN());},
- "fsgnjn.s, inject NaN");
- expect<float>(4.0,
- []{return F::fsgnjn_s(4.0, -numeric_limits<float>::quiet_NaN());},
- "fsgnjn.s, inject NaN");
-
- // FSGNJX.S
- expect<float>(1.0, []{return F::fsgnjx_s(1.0, 25.0);}, "fsgnjx.s, ++");
- expect<float>(-1.0, []{return F::fsgnjx_s(1.0, -25.0);}, "fsgnjx.s, +-");
- expect<float>(-1.0, []{return F::fsgnjx_s(-1.0, 25.0);}, "fsgnjx.s, -+");
- expect<float>(1.0, []{return F::fsgnjx_s(-1.0, -25.0);}, "fsgnjx.s, --");
- expect<bool>(true, []{
- float fd = F::fsgnjx_s(numeric_limits<float>::quiet_NaN(), -4.0);
- return F::isquietnan(fd);
- }, "fsgnjx.s, quiet NaN");
- expect<bool>(true, []{
- float fd = F::fsgnjx_s(numeric_limits<float>::signaling_NaN(),
- -4.0);
- return F::issignalingnan(fd);
- }, "fsgnjx.s, signaling NaN");
- expect<float>(4.0,
- []{return F::fsgnjx_s(4.0, numeric_limits<float>::quiet_NaN());},
- "fsgnjx.s, inject NaN");
- expect<float>(-4.0,
- []{return F::fsgnjx_s(4.0, -numeric_limits<float>::quiet_NaN());},
- "fsgnjx.s, inject -NaN");
-
- // FMIN.S
- expect<float>(2.718, []{return F::fmin_s(3.14, 2.718);}, "fmin.s");
- expect<float>(-numeric_limits<float>::infinity(),
- []{return F::fmin_s(-numeric_limits<float>::infinity(),
- numeric_limits<float>::min());},
- "fmin.s, -infinity");
- expect<float>(numeric_limits<float>::max(),
- []{return F::fmin_s(numeric_limits<float>::infinity(),
- numeric_limits<float>::max());},
- "fmin.s, infinity");
- expect<float>(-1.414,
- []{return F::fmin_s(numeric_limits<float>::quiet_NaN(), -1.414);},
- "fmin.s, quiet NaN first");
- expect<float>(2.718,
- []{return F::fmin_s(2.718, numeric_limits<float>::quiet_NaN());},
- "fmin.s, quiet NaN second");
- expect<bool>(true, []{
- float fd = F::fmin_s(numeric_limits<float>::quiet_NaN(),
- numeric_limits<float>::quiet_NaN());
- return F::isquietnan(fd);
- }, "fmin.s, quiet NaN both");
- expect<float>(3.14,
- []{return F::fmin_s(numeric_limits<float>::signaling_NaN(),
- 3.14);},
- "fmin.s, signaling NaN first");
- expect<float>(1.816,
- []{return F::fmin_s(1.816,
- numeric_limits<float>::signaling_NaN());},
- "fmin.s, signaling NaN second");
- expect<bool>(true, []{
- float fd = F::fmin_s(numeric_limits<float>::signaling_NaN(),
- numeric_limits<float>::signaling_NaN());
- return F::issignalingnan(fd);
- }, "fmin.s, signaling NaN both");
-
- // FMAX.S
- expect<float>(3.14, []{return F::fmax_s(3.14, 2.718);}, "fmax.s");
- expect<float>(numeric_limits<float>::min(),
- []{return F::fmax_s(-numeric_limits<float>::infinity(),
- numeric_limits<float>::min());},
- "fmax.s, -infinity");
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fmax_s(numeric_limits<float>::infinity(),
- numeric_limits<float>::max());},
- "fmax.s, infinity");
- expect<float>(-1.414,
- []{return F::fmax_s(numeric_limits<float>::quiet_NaN(), -1.414);},
- "fmax.s, quiet NaN first");
- expect<float>(2.718,
- []{return F::fmax_s(2.718, numeric_limits<float>::quiet_NaN());},
- "fmax.s, quiet NaN second");
- expect<bool>(true, []{
- float fd = F::fmax_s(numeric_limits<float>::quiet_NaN(),
- numeric_limits<float>::quiet_NaN());
- return F::isquietnan(fd);
- }, "fmax.s, quiet NaN both");
- expect<float>(3.14,
- []{return F::fmax_s(numeric_limits<float>::signaling_NaN(),
- 3.14);},
- "fmax.s, signaling NaN first");
- expect<float>(1.816, []{return F::fmax_s(1.816,
- numeric_limits<float>::signaling_NaN());},
- "fmax.s, signaling NaN second");
- expect<bool>(true, []{
- float fd = F::fmax_s(numeric_limits<float>::signaling_NaN(),
- numeric_limits<float>::signaling_NaN());
- return F::issignalingnan(fd);
- }, "fmax.s, signaling NaN both");
-
- // FCVT.W.S
- expect<int64_t>(256, []{return F::fcvt_w_s(256.3);},
- "fcvt.w.s, truncate positive");
- expect<int64_t>(-256, []{return F::fcvt_w_s(-256.2);},
- "fcvt.w.s, truncate negative");
- expect<int64_t>(0, []{return F::fcvt_w_s(0.0);}, "fcvt.w.s, 0.0");
- expect<int64_t>(0, []{return F::fcvt_w_s(-0.0);}, "fcvt.w.s, -0.0");
- expect<int64_t>(numeric_limits<int32_t>::max(),
- []{return F::fcvt_w_s(numeric_limits<float>::max());},
- "fcvt.w.s, overflow");
- expect<int64_t>(0, []{return F::fcvt_w_s(numeric_limits<float>::min());},
- "fcvt.w.s, underflow");
- expect<int64_t>(numeric_limits<int32_t>::max(),
- []{return F::fcvt_w_s(numeric_limits<float>::infinity());},
- "fcvt.w.s, infinity");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return F::fcvt_w_s(-numeric_limits<float>::infinity());},
- "fcvt.w.s, -infinity");
- expect<int64_t>(numeric_limits<int32_t>::max(),
- []{return F::fcvt_w_s(numeric_limits<float>::quiet_NaN());},
- "fcvt.w.s, quiet NaN");
- expect<int64_t>(numeric_limits<int32_t>::max(),
- []{return F::fcvt_w_s(-numeric_limits<float>::quiet_NaN());},
- "fcvt.w.s, quiet -NaN");
- expect<int64_t>(numeric_limits<int32_t>::max(),
- []{return F::fcvt_w_s(numeric_limits<float>::signaling_NaN());},
- "fcvt.w.s, signaling NaN");
-
- // FCVT.WU.S
- expect<uint64_t>(256, []{return F::fcvt_wu_s(256.3);},
- "fcvt.wu.s, truncate positive");
- expect<uint64_t>(0, []{return F::fcvt_wu_s(-256.2);},
- "fcvt.wu.s, truncate negative");
- expect<uint64_t>(0, []{return F::fcvt_wu_s(0.0);}, "fcvt.wu.s, 0.0");
- expect<uint64_t>(0, []{return F::fcvt_wu_s(-0.0);}, "fcvt.wu.s, -0.0");
- expect<uint64_t>(numeric_limits<uint64_t>::max(),
- []{return F::fcvt_wu_s(numeric_limits<float>::max());},
- "fcvt.wu.s, overflow");
- expect<uint64_t>(0, []{return F::fcvt_wu_s(numeric_limits<float>::min());},
- "fcvt.wu.s, underflow");
- expect<uint64_t>(numeric_limits<uint64_t>::max(),
- []{return F::fcvt_wu_s(numeric_limits<float>::infinity());},
- "fcvt.wu.s, infinity");
- expect<uint64_t>(0,
- []{return F::fcvt_wu_s(-numeric_limits<float>::infinity());},
- "fcvt.wu.s, -infinity");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return F::fcvt_wu_s(numeric_limits<float>::quiet_NaN());},
- "fcvt.wu.s, quiet NaN");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return F::fcvt_wu_s(-numeric_limits<float>::quiet_NaN());},
- "fcvt.wu.s, quiet -NaN");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return F::fcvt_wu_s(numeric_limits<float>::signaling_NaN());},
- "fcvt.wu.s, signaling NaN");
-
- // FMV.X.S
- expect<uint64_t>(0x000000004048F5C3ULL, []{return F::fmv_x_s(3.14);},
- "fmv.x.s, positive");
- expect<uint64_t>(0xFFFFFFFFC048F5C3ULL, []{return F::fmv_x_s(-3.14);},
- "fmv.x.s, negative");
- expect<uint64_t>(0x0000000000000000ULL, []{return F::fmv_x_s(0.0);},
- "fmv.x.s, 0.0");
- expect<uint64_t>(0xFFFFFFFF80000000ULL, []{return F::fmv_x_s(-0.0);},
- "fmv.x.s, -0.0");
-
- // FEQ.S
- expect<bool>(true, []{return F::feq_s(1.414, 1.414);}, "feq.s, equal");
- expect<bool>(false, []{return F::feq_s(2.718, 1.816);},
- "feq.s, not equal");
- expect<bool>(true, []{return F::feq_s(0.0, -0.0);}, "feq.s, 0 == -0");
- expect<bool>(false,
- []{return F::feq_s(numeric_limits<float>::quiet_NaN(), -1.0);},
- "feq.s, quiet NaN first");
- expect<bool>(false,
- []{return F::feq_s(2.0, numeric_limits<float>::quiet_NaN());},
- "feq.s, quiet NaN second");
- expect<bool>(false,
- []{return F::feq_s(numeric_limits<float>::quiet_NaN(),
- numeric_limits<float>::quiet_NaN());},
- "feq.s, quiet NaN both");
- expect<bool>(false,
- []{return F::feq_s(numeric_limits<float>::signaling_NaN(), -1.0);},
- "feq.s, signaling NaN first");
- expect<bool>(false,
- []{return F::feq_s(2.0, numeric_limits<float>::signaling_NaN());},
- "feq.s, signaling NaN second");
- expect<bool>(false,
- []{return F::feq_s(numeric_limits<float>::signaling_NaN(),
- numeric_limits<float>::signaling_NaN());},
- "feq.s, signaling NaN both");
-
- // FLT.S
- expect<bool>(false, []{return F::flt_s(1.414, 1.414);}, "flt.s, equal");
- expect<bool>(true, []{return F::flt_s(1.816, 2.718);}, "flt.s, less");
- expect<bool>(false, []{return F::flt_s(2.718, 1.816);}, "flt.s, greater");
- expect<bool>(false,
- []{return F::flt_s(numeric_limits<float>::quiet_NaN(), -1.0);},
- "flt.s, quiet NaN first");
- expect<bool>(false,
- []{return F::flt_s(2.0, numeric_limits<float>::quiet_NaN());},
- "flt.s, quiet NaN second");
- expect<bool>(false,
- []{return F::flt_s(numeric_limits<float>::quiet_NaN(),
- numeric_limits<float>::quiet_NaN());},
- "flt.s, quiet NaN both");
- expect<bool>(false,
- []{return F::flt_s(numeric_limits<float>::signaling_NaN(), -1.0);},
- "flt.s, signaling NaN first");
- expect<bool>(false,
- []{return F::flt_s(2.0, numeric_limits<float>::signaling_NaN());},
- "flt.s, signaling NaN second");
- expect<bool>(false,
- []{return F::flt_s(numeric_limits<float>::signaling_NaN(),
- numeric_limits<float>::signaling_NaN());},
- "flt.s, signaling NaN both");
-
- // FLE.S
- expect<bool>(true, []{return F::fle_s(1.414, 1.414);}, "fle.s, equal");
- expect<bool>(true, []{return F::fle_s(1.816, 2.718);}, "fle.s, less");
- expect<bool>(false, []{return F::fle_s(2.718, 1.816);}, "fle.s, greater");
- expect<bool>(true, []{return F::fle_s(0.0, -0.0);}, "fle.s, 0 == -0");
- expect<bool>(false,
- []{return F::fle_s(numeric_limits<float>::quiet_NaN(), -1.0);},
- "fle.s, quiet NaN first");
- expect<bool>(false,
- []{return F::fle_s(2.0, numeric_limits<float>::quiet_NaN());},
- "fle.s, quiet NaN second");
- expect<bool>(false,
- []{return F::fle_s(numeric_limits<float>::quiet_NaN(),
- numeric_limits<float>::quiet_NaN());},
- "fle.s, quiet NaN both");
- expect<bool>(false,
- []{return F::fle_s(numeric_limits<float>::signaling_NaN(), -1.0);},
- "fle.s, signaling NaN first");
- expect<bool>(false,
- []{return F::fle_s(2.0, numeric_limits<float>::signaling_NaN());},
- "fle.s, signaling NaN second");
- expect<bool>(false,
- []{return F::fle_s(numeric_limits<float>::signaling_NaN(),
- numeric_limits<float>::signaling_NaN());},
- "fle.s, signaling NaN both");
-
- // FCLASS.S
- expect<uint64_t>(0x1,
- []{return F::fclass_s(-numeric_limits<float>::infinity());},
- "fclass.s, -infinity");
- expect<uint64_t>(0x2, []{return F::fclass_s(-3.14);}, "fclass.s, -normal");
- expect<uint64_t>(0x4, []{return F::fclass_s(F::number(0x807FFFFF));},
- "fclass.s, -subnormal");
- expect<uint64_t>(0x8, []{return F::fclass_s(-0.0);}, "fclass.s, -0.0");
- expect<uint64_t>(0x10, []{return F::fclass_s(0.0);}, "fclass.s, 0.0");
- expect<uint64_t>(0x20, []{return F::fclass_s(F::number(0x007FFFFF));},
- "fclass.s, subnormal");
- expect<uint64_t>(0x40, []{return F::fclass_s(1.816);}, "fclass.s, normal");
- expect<uint64_t>(0x80,
- []{return F::fclass_s(numeric_limits<float>::infinity());},
- "fclass.s, infinity");
- expect<uint64_t>(0x100,
- []{return F::fclass_s(numeric_limits<float>::signaling_NaN());},
- "fclass.s, signaling NaN");
- expect<uint64_t>(0x200,
- []{return F::fclass_s(numeric_limits<float>::quiet_NaN());},
- "fclass.s, quiet NaN");
-
- // FCVT.S.W
- expect<float>(0.0, []{return F::fcvt_s_w(0);}, "fcvt.s.w, 0");
- expect<float>(-2147483648.0,
- []{return F::fcvt_s_w(numeric_limits<int32_t>::min());},
- "fcvt.s.w, negative");
- expect<float>(255.0, []{return F::fcvt_s_w(0xFFFFFFFF000000FFLL);},
- "fcvt.s.w, truncate");
-
- // FCVT.S.WU
- expect<float>(0.0, []{return F::fcvt_s_wu(0);}, "fcvt.s.wu, 0");
- expect<float>(2147483648.0,
- []{return F::fcvt_s_wu(numeric_limits<int32_t>::min());},
- "fcvt.s.wu");
- expect<float>(255.0, []{return F::fcvt_s_wu(0xFFFFFFFF000000FFLL);},
- "fcvt.s.wu, truncate");
-
- // FMV.S.X
- expect<float>(numeric_limits<float>::infinity(),
- []{return F::fmv_s_x(0x7F800000);}, "fmv.s.x");
- expect<float>(-0.0, []{return F::fmv_s_x(0xFFFFFFFF80000000ULL);},
- "fmv.s.x, truncate");
-
- // FCSR functions
- int rm = F::frrm();
- expect<uint64_t>(0x7, []{ // FSRM
- F::fsrm(-1);
- return F::frrm();
- }, "fsrm");
- expect<uint64_t>(0x1F, []{ // FSFLAGS
- F::fsflags(0);
- F::fsflags(-1);
- return F::frflags();
- }, "fsflags");
- expect<uint64_t>(0xFF, []{ // FSCSR
- F::fsflags(0);
- F::fsrm(0);
- F::fscsr(-1);
- return F::frcsr();
- }, "fscsr");
- expect<int>(rm << 5, [=]{
- F::fscsr(0);
- F::fsrm(rm);
- return F::frcsr();
- }, "restore initial round mode");
-
- F::fsflags(0);
-
- // FCVT.L.S
- expect<int64_t>(256, []{return F::fcvt_l_s(256.3);},
- "fcvt.l.s, truncate positive");
- expect<int64_t>(-256, []{return F::fcvt_l_s(-256.2);},
- "fcvt.l.s, truncate negative");
- expect<int64_t>(0, []{return F::fcvt_l_s(0.0);}, "fcvt.l.s, 0.0");
- expect<int64_t>(0, []{return F::fcvt_l_s(-0.0);}, "fcvt.l.s, -0.0");
- expect<int64_t>(-8589934592LL, []{return F::fcvt_l_s(-8589934592.0);},
- "fcvt.l.s, 32-bit overflow");
- expect<int64_t>(numeric_limits<int64_t>::max(),
- []{return F::fcvt_l_s(numeric_limits<float>::max());},
- "fcvt.l.s, overflow");
- expect<int64_t>(0, []{return F::fcvt_l_s(numeric_limits<float>::min());},
- "fcvt.l.s, underflow");
- expect<int64_t>(numeric_limits<int64_t>::max(),
- []{return F::fcvt_l_s(numeric_limits<float>::infinity());},
- "fcvt.l.s, infinity");
- expect<int64_t>(numeric_limits<int64_t>::min(),
- []{return F::fcvt_l_s(-numeric_limits<float>::infinity());},
- "fcvt.l.s, -infinity");
- expect<int64_t>(numeric_limits<int64_t>::max(),
- []{return F::fcvt_l_s(numeric_limits<float>::quiet_NaN());},
- "fcvt.l.s, quiet NaN");
- expect<int64_t>(numeric_limits<int64_t>::max(),
- []{return F::fcvt_l_s(-numeric_limits<float>::quiet_NaN());},
- "fcvt.l.s, quiet -NaN");
- expect<int64_t>(numeric_limits<int64_t>::max(),
- []{return F::fcvt_l_s(numeric_limits<float>::signaling_NaN());},
- "fcvt.l.s, signaling NaN");
-
- // FCVT.LU.S
- expect<uint64_t>(256, []{return F::fcvt_lu_s(256.3);},
- "fcvt.lu.s, truncate positive");
- expect<uint64_t>(0, []{return F::fcvt_lu_s(-256.2);},
- "fcvt.lu.s, truncate negative");
- expect<uint64_t>(0, []{return F::fcvt_lu_s(0.0);}, "fcvt.lu.s, 0.0");
- expect<uint64_t>(0, []{return F::fcvt_lu_s(-0.0);}, "fcvt.lu.s, -0.0");
- expect<uint64_t>(8589934592LL,
- []{return F::fcvt_lu_s(8589934592.0);},
- "fcvt.lu.s, 32-bit overflow");
- expect<uint64_t>(numeric_limits<uint64_t>::max(),
- []{return F::fcvt_lu_s(numeric_limits<float>::max());},
- "fcvt.lu.s, overflow");
- expect<uint64_t>(0, []{return F::fcvt_lu_s(numeric_limits<float>::min());},
- "fcvt.lu.s, underflow");
- expect<uint64_t>(numeric_limits<uint64_t>::max(),
- []{return F::fcvt_lu_s(numeric_limits<float>::infinity());},
- "fcvt.lu.s, infinity");
- expect<uint64_t>(0,
- []{return F::fcvt_lu_s(-numeric_limits<float>::infinity());},
- "fcvt.lu.s, -infinity");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return F::fcvt_lu_s(numeric_limits<float>::quiet_NaN());},
- "fcvt.lu.s, quiet NaN");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return F::fcvt_lu_s(-numeric_limits<float>::quiet_NaN());},
- "fcvt.lu.s, quiet -NaN");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
- []{return F::fcvt_lu_s(numeric_limits<float>::signaling_NaN());},
- "fcvt.lu.s, signaling NaN");
-
- // FCVT.S.L
- expect<float>(0.0, []{return F::fcvt_s_l(0);}, "fcvt.s.l, 0");
- expect<float>(-9.223372e18,
- []{return F::fcvt_s_l(numeric_limits<int64_t>::min());},
- "fcvt.s.l, negative");
- expect<float>(-4.29496704e9, []{return F::fcvt_s_l(0xFFFFFFFF000000FFLL);},
- "fcvt.s.l, 32-bit truncate");
-
- // FCVT.S.LU
- expect<float>(0.0, []{return F::fcvt_s_lu(0);}, "fcvt.s.lu, 0");
- expect<float>(9.223372e18,
- []{return F::fcvt_s_lu(numeric_limits<int64_t>::min());},
- "fcvt.s.lu");
- expect<float>(1.8446744e19, []{return F::fcvt_s_lu(0xFFFFFFFF000000FFLL);},
- "fcvt.s.lu, 32-bit truncate");
-
- return 0;
-}
diff --git a/src/insttest/rv64f.h b/src/insttest/rv64f.h
deleted file mode 100644
index 5a6798c..0000000
--- a/src/insttest/rv64f.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#pragma once
-
-#include <cstdint>
-#include <limits>
-
-#include "insttest.h"
-
-namespace F
-{
-
-constexpr inline uint32_t
-bits(float f)
-{
- return reinterpret_cast<uint32_t&>(f);
-}
-
-constexpr inline float
-number(uint32_t b)
-{
- return reinterpret_cast<float&>(b);
-}
-
-inline bool
-isquietnan(float f)
-{
- return std::isnan(f) && (bits(f)&0x00400000) != 0;
-}
-
-inline bool
-issignalingnan(float f)
-{
- return std::isnan(f) && (bits(f)&0x00400000) == 0;
-}
-
-inline float
-load(float mem)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- asm volatile("flw %0,%1"
- : "=f" (fd)
- : "m" (mem));
- return fd;
-}
-
-inline float
-store(float fs)
-{
- float mem = std::numeric_limits<float>::signaling_NaN();
- asm volatile("fsw %1,%0" : "=m" (mem) : "f" (fs));
- return mem;
-}
-
-inline uint64_t
-frflags()
-{
- uint64_t rd = -1;
- asm volatile("frflags %0" : "=r" (rd));
- return rd;
-}
-
-inline uint64_t
-fsflags(uint64_t rs1)
-{
- uint64_t rd = -1;
- asm volatile("fsflags %0,%1" : "=r" (rd) : "r" (rs1));
- return rd;
-}
-
-inline float
-fmadd_s(float fs1, float fs2, float fs3)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FR4OP("fmadd.s", fd, fs1, fs2, fs3);
- return fd;
-}
-
-inline float
-fmsub_s(float fs1, float fs2, float fs3)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FR4OP("fmsub.s", fd, fs1, fs2, fs3);
- return fd;
-}
-
-inline float
-fnmsub_s(float fs1, float fs2, float fs3)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FR4OP("fnmsub.s", fd, fs1, fs2, fs3);
- return fd;
-}
-
-inline float
-fnmadd_s(float fs1, float fs2, float fs3)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FR4OP("fnmadd.s", fd, fs1, fs2, fs3);
- return fd;
-}
-
-inline float
-fadd_s(float fs1, float fs2)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FROP("fadd.s", fd, fs1, fs2);
- return fd;
-}
-
-inline float
-fsub_s(float fs1, float fs2)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FROP("fsub.s", fd, fs1, fs2);
- return fd;
-}
-
-inline float
-fmul_s(float fs1, float fs2)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FROP("fmul.s", fd, fs1, fs2);
- return fd;
-}
-
-inline float
-fdiv_s(float fs1, float fs2)
-{
-
- float fd = 0.0;
- FROP("fdiv.s", fd, fs1, fs2);
- return fd;
-}
-
-inline float
-fsqrt_s(float fs1)
-{
- float fd = std::numeric_limits<float>::infinity();
- asm volatile("fsqrt.s %0,%1" : "=f" (fd) : "f" (fs1));
- return fd;
-}
-
-inline float
-fsgnj_s(float fs1, float fs2)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FROP("fsgnj.s", fd, fs1, fs2);
- return fd;
-}
-
-inline float
-fsgnjn_s(float fs1, float fs2)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FROP("fsgnjn.s", fd, fs1, fs2);
- return fd;
-}
-
-inline float
-fsgnjx_s(float fs1, float fs2)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FROP("fsgnjx.s", fd, fs1, fs2);
- return fd;
-}
-
-inline float
-fmin_s(float fs1, float fs2)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FROP("fmin.s", fd, fs1, fs2);
- return fd;
-}
-
-inline float
-fmax_s(float fs1, float fs2)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- FROP("fmax.s", fd, fs1, fs2);
- return fd;
-}
-
-inline int64_t
-fcvt_w_s(float fs1)
-{
- int64_t rd = 0;
- asm volatile("fcvt.w.s %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline uint64_t
-fcvt_wu_s(float fs1)
-{
- uint64_t rd = 0;
- asm volatile("fcvt.wu.s %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline uint64_t
-fmv_x_s(float fs1)
-{
- uint64_t rd = 0;
- asm volatile("fmv.x.s %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline bool
-feq_s(float fs1, float fs2)
-{
- bool rd = false;
- asm volatile("feq.s %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2));
- return rd;
-}
-
-inline bool
-flt_s(float fs1, float fs2)
-{
- bool rd = false;
- asm volatile("flt.s %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2));
- return rd;
-}
-
-inline bool
-fle_s(float fs1, float fs2)
-{
- bool rd = false;
- asm volatile("fle.s %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2));
- return rd;
-}
-
-inline uint64_t
-fclass_s(float fs1)
-{
- uint64_t rd = -1;
- asm volatile("fclass.s %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline float
-fcvt_s_w(int64_t rs1)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- asm volatile("fcvt.s.w %0,%1" : "=f" (fd) : "r" (rs1));
- return fd;
-}
-
-inline float
-fcvt_s_wu(uint64_t rs1)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- asm volatile("fcvt.s.wu %0,%1" : "=f" (fd) : "r" (rs1));
- return fd;
-}
-
-inline float
-fmv_s_x(uint64_t rs1)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- asm volatile("fmv.s.x %0,%1" : "=f" (fd) : "r" (rs1));
- return fd;
-}
-
-inline uint64_t
-frcsr()
-{
- uint64_t rd = -1;
- asm volatile("frcsr %0" : "=r" (rd));
- return rd;
-}
-
-inline uint64_t
-frrm()
-{
- uint64_t rd = -1;
- asm volatile("frrm %0" : "=r" (rd));
- return rd;
-}
-
-inline uint64_t
-fscsr(uint64_t rs1)
-{
- uint64_t rd = -1;
- asm volatile("fscsr %0,%1" : "=r" (rd) : "r" (rs1));
- return rd;
-}
-
-inline uint64_t
-fsrm(uint64_t rs1)
-{
- uint64_t rd = -1;
- asm volatile("fsrm %0,%1" : "=r" (rd) : "r" (rs1));
- return rd;
-}
-
-inline int64_t
-fcvt_l_s(float fs1)
-{
- int64_t rd = 0;
- asm volatile("fcvt.l.s %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline uint64_t
-fcvt_lu_s(float fs1)
-{
-
- int64_t rd = 0;
- asm volatile("fcvt.lu.s %0,%1" : "=r" (rd) : "f" (fs1));
- return rd;
-}
-
-inline float
-fcvt_s_l(int64_t rs1)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- asm volatile("fcvt.s.l %0,%1" : "=f" (fd) : "r" (rs1));
- return fd;
-}
-
-inline float
-fcvt_s_lu(uint64_t rs1)
-{
- float fd = std::numeric_limits<float>::signaling_NaN();
- asm volatile("fcvt.s.lu %0,%1" : "=f" (fd) : "r" (rs1));
- return fd;
-}
-
-} // namespace F
diff --git a/src/insttest/rv64i.cpp b/src/insttest/rv64i.cpp
deleted file mode 100644
index 22a5259..0000000
--- a/src/insttest/rv64i.cpp
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/times.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cstdint>
-#include <cstring>
-#include <iostream>
-#include <limits>
-
-#include "insttest.h"
-#include "rv64i.h"
-
-int main()
-{
- using namespace std;
- using namespace insttest;
-
- // LUI
- expect<int64_t>(4096, []{return I::lui(1);}, "lui");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return I::lui(0x80000);}, "lui, negative");
-
- // AUIPC
- expect<bool>(true, []{return I::auipc(3);}, "auipc");
-
- // Jump (JAL, JALR)
- expect<bool>(true, []{return I::jal();}, "jal");
- expect<bool>(true, []{return I::jalr();}, "jalr");
-
- // BEQ
- expect<bool>(true, []{return I::beq(5, 5);}, "beq, equal");
- expect<bool>(false, []{return I::beq(numeric_limits<int64_t>::max(),
- numeric_limits<int64_t>::min());}, "beq, not equal");
-
- // BNE
- expect<bool>(false, []{return I::bne(5, 5);}, "bne, equal");
- expect<bool>(true, []{return I::bne(numeric_limits<int64_t>::max(),
- numeric_limits<int64_t>::min());}, "bne, not equal");
-
- // BLT
- expect<bool>(true, []{return I::blt(numeric_limits<int64_t>::min(),
- numeric_limits<int64_t>::max());}, "blt, less");
- expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::min(),
- numeric_limits<int64_t>::min());}, "blt, equal");
- expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::max(),
- numeric_limits<int64_t>::min());}, "blt, greater");
-
- // BGE
- expect<bool>(false, []{return I::bge(numeric_limits<int64_t>::min(),
- numeric_limits<int64_t>::max());}, "bge, less");
- expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::min(),
- numeric_limits<int64_t>::min());}, "bge, equal");
- expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::max(),
- numeric_limits<int64_t>::min());}, "bge, greater");
-
- // BLTU
- expect<bool>(true, []{return I::blt(numeric_limits<int64_t>::min(),
- numeric_limits<int64_t>::max());}, "bltu, greater");
- expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::min(),
- numeric_limits<int64_t>::min());}, "bltu, equal");
- expect<bool>(false, []{return I::blt(numeric_limits<int64_t>::max(),
- numeric_limits<int64_t>::min());}, "bltu, less");
-
- // BGEU
- expect<bool>(false, []{return I::bge(numeric_limits<int64_t>::min(),
- numeric_limits<int64_t>::max());}, "bgeu, greater");
- expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::min(),
- numeric_limits<int64_t>::min());}, "bgeu, equal");
- expect<bool>(true, []{return I::bge(numeric_limits<int64_t>::max(),
- numeric_limits<int64_t>::min());}, "bgeu, less");
-
- // Load (LB, LH, LW, LBU, LHU)
- expect<int64_t>(7, []{return I::load<int8_t, int64_t>(0x07);},
- "lb, positive");
- expect<int64_t>(numeric_limits<int8_t>::min(),
- []{return I::load<int8_t, int64_t>(0x80);}, "lb, negative");
- expect<int64_t>(1792, []{return I::load<int16_t, int64_t>(0x0700);},
- "lh, positive");
- expect<int64_t>(numeric_limits<int16_t>::min(),
- []{return I::load<int16_t, int64_t>(0x8000);}, "lh, negative");
- expect<int64_t>(458752, []{return I::load<int32_t, int64_t>(0x00070000);},
- "lw, positive");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return I::load<int32_t, int64_t>(0x80000000);},
- "lw, negative");
- expect<uint64_t>(128, []{return I::load<uint8_t, uint64_t>(0x80);}, "lbu");
- expect<uint64_t>(32768, []{return I::load<uint16_t, uint64_t>(0x8000);},
- "lhu");
-
- // Store (SB, SH, SW)
- expect<uint8_t>(0xFF, []{return I::store<int8_t>(-1);}, "sb");
- expect<uint16_t>(0xFFFF, []{return I::store<int16_t>(-1);}, "sh");
- expect<uint32_t>(0xFFFFFFFF, []{return I::store<int32_t>(-1);}, "sw");
-
- // ADDI
- expect<int64_t>(1073742078, []{return I::addi(0x3FFFFFFF, 255);},
- "addi");
- expect<int64_t>(1, []{return I::addi(-1, 2);}, "addi, overflow");
-
- // SLTI
- expect<bool>(true, []{return I::slti(-1, 0);}, "slti, true");
- expect<bool>(false, []{return I::slti(0, -1);}, "slti, false");
-
- // SLTIU
- expect<bool>(false, []{return I::sltiu(-1, 0);}, "sltiu, false");
- expect<bool>(true, []{return I::sltiu(0, -1);}, "sltiu, true");
- expect<bool>(true, []{return I::sltiu(0xFFFF, -1);}, "sltiu, sext");
-
- // XORI
- expect<uint64_t>(0xFF, []{return I::xori(0xAA, 0x55);}, "xori (1)");
- expect<uint64_t>(0, []{return I::xori(0xAA, 0xAA);}, "xori (0)");
-
- // ORI
- expect<uint64_t>(0xFF, []{return I::ori(0xAA, 0x55);}, "ori (1)");
- expect<uint64_t>(0xAA, []{return I::ori(0xAA, 0xAA);}, "ori (A)");
-
- // ANDI
- expect<uint64_t>(0, []{return I::andi(-1, 0);}, "andi (0)");
- expect<uint64_t>(0x1234567812345678ULL,
- []{return I::andi(0x1234567812345678ULL, -1);}, "andi (1)");
-
- // SLLI
- expect<int64_t>(65280, []{return I::slli(255, 8);}, "slli, general");
- expect<int64_t>(numeric_limits<int64_t>::min(),
- []{return I::slli(255, 63);}, "slli, erase");
-
- // SRLI
- expect<int64_t>(255, []{return I::srli(65280, 8);}, "srli, general");
- expect<int64_t>(0, []{return I::srli(255, 8);}, "srli, erase");
- expect<int64_t>(1, []{return I::srli(numeric_limits<int64_t>::min(), 63);},
- "srli, negative");
-
- // SRAI
- expect<int64_t>(255, []{return I::srai(65280, 8);}, "srai, general");
- expect<int64_t>(0, []{return I::srai(255, 8);}, "srai, erase");
- expect<int64_t>(-1,
- []{return I::srai(numeric_limits<int64_t>::min(), 63);},
- "srai, negative");
-
- // ADD
- expect<int64_t>(1073742078, []{return I::add(0x3FFFFFFF, 255);}, "add");
- expect<int64_t>(-1,
- []{return I::add(0x7FFFFFFFFFFFFFFFLL, 0x8000000000000000LL);},
- "add, overflow");
-
- // SUB
- expect<int64_t>(65535, []{return I::sub(65536, 1);}, "sub");
- expect<int64_t>(-1,
- []{return I::sub(0x7FFFFFFFFFFFFFFFLL, 0x8000000000000000LL);},
- "sub, \"overflow\"");
-
- // SLL
- expect<int64_t>(65280, []{return I::sll(255, 8);}, "sll, general");
- expect<int64_t>(numeric_limits<int64_t>::min(),
- []{return I::sll(255, 63);}, "sll, erase");
-
- // SLT
- expect<bool>(true, []{return I::slt(-1, 0);}, "slt, true");
- expect<bool>(false, []{return I::slt(0, -1);}, "slt, false");
-
- // SLTU
- expect<bool>(false, []{return I::sltu(-1, 0);}, "sltu, false");
- expect<bool>(true, []{return I::sltu(0, -1);}, "sltu, true");
-
- // XOR
- expect<uint64_t>(-1,
- []{return I::xor_inst(0xAAAAAAAAAAAAAAAAULL,
- 0x5555555555555555ULL);},
- "xor (1)");
- expect<uint64_t>(0,
- []{return I::xor_inst(0xAAAAAAAAAAAAAAAAULL,
- 0xAAAAAAAAAAAAAAAAULL);},
- "xor (0)");
-
- // SRL
- expect<uint64_t>(255, []{return I::srl(65280, 8);}, "srl, general");
- expect<uint64_t>(0, []{return I::srl(255, 8);}, "srl, erase");
- expect<uint64_t>(1, []{return I::srl(numeric_limits<int64_t>::min(), 63);},
- "srl, negative");
-
- // SRA
- expect<int64_t>(255, []{return I::sra(65280, 8);}, "sra, general");
- expect<int64_t>(0, []{return I::sra(255, 8);}, "sra, erase");
- expect<int64_t>(-1, []{return I::sra(numeric_limits<int64_t>::min(), 63);},
- "sra, negative");
-
- // OR
- expect<uint64_t>(-1,
- []{return I::or_inst(0xAAAAAAAAAAAAAAAAULL,
- 0x5555555555555555ULL);},
- "or (1)");
- expect<uint64_t>(0xAAAAAAAAAAAAAAAAULL,
- []{return I::or_inst(0xAAAAAAAAAAAAAAAAULL,
- 0xAAAAAAAAAAAAAAAAULL);},
- "or (A)");
-
- // AND
- expect<uint64_t>(0, []{return I::and_inst(-1, 0);}, "and (0)");
- expect<uint64_t>(0x1234567812345678ULL,
- []{return I::and_inst(0x1234567812345678ULL, -1);}, "and (-1)");
-
- // FENCE/FENCE.I
- asm volatile("fence" : : );
- asm volatile("fence.i" : : );
-
- // ECALL
- char fname[] = "test.txt";
- char teststr[] = "this is a test";
- expect<bool>(true, [=]{
- int fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0644);
- if (fd < 0) {
- return false;
- }
- size_t n = write(fd, teststr, sizeof(teststr));
- cout << "Bytes written: " << n << endl;
- return close(fd) >= 0 && n > 0;
- }, "open, write");
- expect<int>(0, [=]{return access(fname, F_OK);}, "access F_OK");
- expect<int>(0, [=]{return access(fname, R_OK);}, "access R_OK");
- expect<int>(0, [=]{return access(fname, W_OK);}, "access W_OK");
- // gem5's implementation of access is incorrect; it should return
- // -1 on failure, not -errno. Account for this using an inequality.
- expect<bool>(true, [=]{return access(fname, X_OK) != 0;}, "access X_OK");
- expect<bool>(true, [=]{
- struct stat stat_buf, fstat_buf;
- int s = stat(fname, &stat_buf);
- if (s < 0) {
- return false;
- } else {
- cout << "stat:" << endl;
- cout << "\tst_dev =\t" << stat_buf.st_dev << endl;
- cout << "\tst_ino =\t" << stat_buf.st_ino << endl;
- cout << "\tst_mode =\t" << stat_buf.st_mode << endl;
- cout << "\tst_nlink =\t" << stat_buf.st_nlink << endl;
- cout << "\tst_uid =\t" << stat_buf.st_uid << endl;
- cout << "\tst_gid =\t" << stat_buf.st_gid << endl;
- cout << "\tst_rdev =\t" << stat_buf.st_rdev << endl;
- cout << "\tst_size =\t" << stat_buf.st_size << endl;
- cout << "\tst_blksize =\t" << stat_buf.st_blksize << endl;
- cout << "\tst_blocks =\t" << stat_buf.st_blocks << endl;
- }
- int fd = open(fname, O_RDONLY);
- if (fd < 0) {
- return false;
- }
- int f = fstat(fd, &fstat_buf);
- if (f >= 0) {
- cout << "fstat:" << endl;
- cout << "\tst_dev =\t" << fstat_buf.st_dev << endl;
- cout << "\tst_ino =\t" << fstat_buf.st_ino << endl;
- cout << "\tst_mode =\t" << fstat_buf.st_mode << endl;
- cout << "\tst_nlink =\t" << fstat_buf.st_nlink << endl;
- cout << "\tst_uid =\t" << fstat_buf.st_uid << endl;
- cout << "\tst_gid =\t" << fstat_buf.st_gid << endl;
- cout << "\tst_rdev =\t" << fstat_buf.st_rdev << endl;
- cout << "\tst_size =\t" << fstat_buf.st_size << endl;
- cout << "\tst_blksize =\t" << fstat_buf.st_blksize << endl;
- cout << "\tst_blocks =\t" << fstat_buf.st_blocks << endl;
- }
- return close(fd) >= 0 && f >= 0;
- }, "open, stat");
- expect<bool>(true, [=]{
- int fd = open(fname, O_RDONLY);
- if (fd < 0) {
- return false;
- }
- char in[128];
- size_t n = read(fd, in, sizeof(in));
- cout << "Bytes read: " << n << endl;
- cout << "String read: " << in << endl;
- int cl = close(fd);
- int un = unlink(fname);
- return n > 0 && cl >= 0 && un >= 0 && strcmp(teststr, in) == 0;
- }, "open, read, unlink");
- expect<bool>(true, []{
- struct tms buf;
- clock_t t = times(&buf);
- cout << "times:" << endl;
- cout << "\ttms_utime =\t" << buf.tms_utime << endl;
- cout << "\ttms_stime =\t" << buf.tms_stime << endl;
- cout << "\ttms_cutime =\t" << buf.tms_cutime << endl;
- cout << "\ttms_cstime =\t" << buf.tms_cstime << endl;
- return t > 0;
- }, "times");
- expect<int>(0, []{
- struct timeval time;
- int res = gettimeofday(&time, nullptr);
- cout << "timeval:" << endl;
- cout << "\ttv_sec =\t" << time.tv_sec << endl;
- cout << "\ttv_usec =\t" << time.tv_usec << endl;
- return res;
- }, "gettimeofday");
-
- // EBREAK not tested because it only makes sense in FS mode or when
- // using gdb
-
- // ERET not tested because it only makes sense in FS mode and will cause
- // a panic when used in SE mode
-
- // CSRs (RDCYCLE, RDTIME, RDINSTRET)
- expect<bool>(true, []{
- uint64_t cycles = 0;
- asm("rdcycle %0" : "=r" (cycles));
- cout << "Cycles: " << cycles << endl;
- return cycles > 0;
- }, "rdcycle");
- expect<bool>(true, []{
- uint64_t time = 0;
- asm("rdtime %0" : "=r" (time));
- return time > 0;
- }, "rdtime");
- expect<bool>(true, []{
- uint64_t instret = 0;
- asm("rdinstret %0" : "=r" (instret));
- cout << "Instructions Retired: " << instret << endl;
- return instret > 0;
- }, "rdinstret");
-
- // 64-bit memory (LWU, LD, SD)
- expect<int64_t>(0xFFFFFFFF, []{return I::load<uint32_t, uint64_t>(-1);},
- "lwu");
- expect<int64_t>(30064771072,
- []{return I::load<int64_t, int64_t>(30064771072);}, "ld");
- expect<uint64_t>(-1, []{return I::store<int64_t>(-1);}, "sd");
-
- // ADDIW
- expect<int64_t>(268435710, []{return I::addiw(0x0FFFFFFF, 255);}, "addiw");
- expect<int64_t>(-2147481602, []{return I::addiw(0x7FFFFFFF, 0x7FF);},
- "addiw, overflow");
- expect<int64_t>(0, []{return I::addiw(0x7FFFFFFFFFFFFFFFLL, 1);},
- "addiw, truncate");
-
- // SLLIW
- expect<int64_t>(65280, []{return I::slliw(255, 8);}, "slliw, general");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return I::slliw(255, 31);}, "slliw, erase");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return I::slliw(0xFFFFFFFF00800000LL, 8);}, "slliw, truncate");
-
- // SRLIW
- expect<int64_t>(255, []{return I::srliw(65280, 8);}, "srliw, general");
- expect<int64_t>(0, []{return I::srliw(255, 8);}, "srliw, erase");
- expect<int64_t>(1,
- []{return I::srliw(numeric_limits<int32_t>::min(), 31);},
- "srliw, negative");
- expect<int64_t>(1, []{return I::srliw(0xFFFFFFFF80000000LL, 31);},
- "srliw, truncate");
-
- // SRAIW
- expect<int64_t>(255, []{return I::sraiw(65280, 8);}, "sraiw, general");
- expect<int64_t>(0, []{return I::sraiw(255, 8);}, "sraiw, erase");
- expect<int64_t>(-1,
- []{return I::sraiw(numeric_limits<int32_t>::min(), 31);},
- "sraiw, negative");
- expect<int64_t>(-1, []{return I::sraiw(0x0000000180000000LL, 31);},
- "sraiw, truncate");
-
- // ADDW
- expect<int64_t>(1073742078, []{return I::addw(0x3FFFFFFF, 255);}, "addw");
- expect<int64_t>(-1, []{return I::addw(0x7FFFFFFF, 0x80000000);},
- "addw, overflow");
- expect<int64_t>(65536, []{return I::addw(0xFFFFFFFF0000FFFFLL, 1);},
- "addw, truncate");
-
- // SUBW
- expect<int64_t>(65535, []{return I::subw(65536, 1);}, "subw");
- expect<int64_t>(-1, []{return I::subw(0x7FFFFFFF, 0x80000000);},
- "subw, \"overflow\"");
- expect<int64_t>(0,
- []{return I::subw(0xAAAAAAAAFFFFFFFFULL, 0x55555555FFFFFFFFULL);},
- "subw, truncate");
-
- // SLLW
- expect<int64_t>(65280, []{return I::sllw(255, 8);}, "sllw, general");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return I::sllw(255, 31);}, "sllw, erase");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return I::sllw(0xFFFFFFFF00008000LL, 16);}, "sllw, truncate");
-
- // SRLW
- expect<uint64_t>(255, []{return I::srlw(65280, 8);}, "srlw, general");
- expect<uint64_t>(0, []{return I::srlw(255, 8);}, "srlw, erase");
- expect<uint64_t>(1,
- []{return I::srlw(numeric_limits<int32_t>::min(), 31);},
- "srlw, negative");
- expect<uint64_t>(1, []{return I::srlw(0x0000000180000000LL, 31);},
- "srlw, truncate");
-
- // SRAW
- expect<int64_t>(255, []{return I::sraw(65280, 8);}, "sraw, general");
- expect<int64_t>(0, []{return I::sraw(255, 8);}, "sraw, erase");
- expect<int64_t>(-1,
- []{return I::sraw(numeric_limits<int32_t>::min(), 31);},
- "sraw, negative");
- expect<int64_t>(1, []{return I::sraw(0xFFFFFFFF40000000LL, 30);},
- "sraw, truncate");
-
- return 0;
-}
diff --git a/src/insttest/rv64i.h b/src/insttest/rv64i.h
deleted file mode 100644
index 198fb36..0000000
--- a/src/insttest/rv64i.h
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#pragma once
-
-#include <cstdint>
-#include <iostream>
-
-#include "insttest.h"
-
-namespace I
-{
-
-inline uint64_t
-lui(const uint32_t imm)
-{
- int64_t rd = -1;
- asm volatile("lui %0,%1" : "=r" (rd) : "i" (imm));
- return rd;
-}
-
-inline bool
-auipc(const uint64_t imm)
-{
- int64_t rd = -1;
- asm volatile("auipc %0,%1" : "=r" (rd) : "i" (imm));
- std::cout << "auipc: 0x" << std::hex << std::uppercase << rd <<
- std::nouppercase << std::dec << std::endl;
- return rd >= imm;
-}
-
-inline bool
-jal()
-{
- asm volatile goto("jal zero,%l[jallabel]" : : : : jallabel);
- return false;
- jallabel:
- return true;
-}
-
-inline bool
-jalr()
-{
- int a = 0;
- asm volatile("auipc %0,0;"
- "jalr t0,%0,12;"
- "addi %0,zero,0;"
- "sub %0,t0,%0;"
- : "+r" (a)
- :
- : "t0");
- return a == 8;
-}
-
-inline bool
-beq(int64_t a, int64_t b)
-{
- asm volatile goto("beq %0,%1,%l[beqlabel]"
- :
- : "r" (a), "r" (b)
- :
- : beqlabel);
- return false;
- beqlabel:
- return true;
-}
-
-inline bool
-bne(int64_t a, int64_t b)
-{
- asm volatile goto("bne %0,%1,%l[bnelabel]"
- :
- : "r" (a), "r" (b)
- :
- : bnelabel);
- return false;
- bnelabel:
- return true;
-}
-
-inline bool
-blt(int64_t a, int64_t b)
-{
- asm volatile goto("blt %0,%1,%l[bltlabel]"
- :
- : "r" (a), "r" (b)
- :
- : bltlabel);
- return false;
- bltlabel:
- return true;
-}
-
-inline bool
-bge(int64_t a, int64_t b)
-{
- asm volatile goto("bge %0,%1,%l[bgelabel]"
- :
- : "r" (a), "r" (b)
- :
- : bgelabel);
- return false;
- bgelabel:
- return true;
-}
-
-inline bool
-bltu(uint64_t a, uint64_t b)
-{
- asm volatile goto("bltu %0,%1,%l[bltulabel]"
- :
- : "r" (a), "r" (b)
- :
- : bltulabel);
- return false;
- bltulabel:
- return true;
-}
-
-inline bool
-bgeu(uint64_t a, uint64_t b)
-{
- asm volatile goto("bgeu %0,%1,%l[bgeulabel]"
- :
- : "r" (a), "r" (b)
- :
- : bgeulabel);
- return false;
- bgeulabel:
- return true;
-}
-
-template<typename M, typename R> inline R
-load(const M& b)
-{
- R a = 0;
- switch(sizeof(M))
- {
- case 1:
- if (std::is_signed<M>::value) {
- asm volatile("lb %0,%1" : "=r" (a) : "m" (b));
- } else {
- asm volatile("lbu %0,%1" : "=r" (a) : "m" (b));
- }
- break;
- case 2:
- if (std::is_signed<M>::value) {
- asm volatile("lh %0,%1" : "=r" (a) : "m" (b));
- } else {
- asm volatile("lhu %0,%1" : "=r" (a) : "m" (b));
- }
- break;
- case 4:
- if (std::is_signed<M>::value) {
- asm volatile("lw %0,%1" : "=r" (a) : "m" (b));
- } else {
- asm volatile("lwu %0,%1" : "=r" (a) : "m" (b));
- }
- break;
- case 8:
- asm volatile("ld %0,%1" : "=r" (a) : "m" (b));
- break;
- }
- return a;
-}
-
-template<typename M> inline M
-store(const M& rs2)
-{
- M mem = 0;
- switch (sizeof(M))
- {
- case 1:
- asm volatile("sb %1,%0" : "=m" (mem) : "r" (rs2));
- break;
- case 2:
- asm volatile("sh %1,%0" : "=m" (mem) : "r" (rs2));
- break;
- case 4:
- asm volatile("sw %1,%0" : "=m" (mem) : "r" (rs2));
- break;
- case 8:
- asm volatile("sd %1,%0" : "=m" (mem) : "r" (rs2));
- break;
- }
- return mem;
-}
-
-inline int64_t
-addi(int64_t rs1, const int16_t imm)
-{
- int64_t rd = 0;
- IOP("addi", rd, rs1, imm);
- return rd;
-}
-
-inline bool
-slti(int64_t rs1, const int16_t imm)
-{
- bool rd = false;
- IOP("slti", rd, rs1, imm);
- return rd;
-}
-
-inline bool
-sltiu(uint64_t rs1, const uint16_t imm)
-{
- bool rd = false;
- IOP("sltiu", rd, rs1, imm);
- return rd;
-}
-
-inline uint64_t
-xori(uint64_t rs1, const uint16_t imm)
-{
- uint64_t rd = 0;
- IOP("xori", rd, rs1, imm);
- return rd;
-}
-
-inline uint64_t
-ori(uint64_t rs1, const uint16_t imm)
-{
- uint64_t rd = 0;
- IOP("ori", rd, rs1, imm);
- return rd;
-}
-
-inline uint64_t
-andi(uint64_t rs1, const uint16_t imm)
-{
- uint64_t rd = 0;
- IOP("andi", rd, rs1, imm);
- return rd;
-}
-
-inline int64_t
-slli(int64_t rs1, const uint16_t imm)
-{
- int64_t rd = 0;
- IOP("slli", rd, rs1, imm);
- return rd;
-}
-
-inline uint64_t
-srli(uint64_t rs1, const uint16_t imm)
-{
- uint64_t rd = 0;
- IOP("srli", rd, rs1, imm);
- return rd;
-}
-
-inline int64_t
-srai(int64_t rs1, const uint16_t imm)
-{
- int64_t rd = 0;
- IOP("srai", rd, rs1, imm);
- return rd;
-}
-
-inline int64_t
-add(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("add", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-sub(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("sub", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-sll(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("sll", rd, rs1, rs2);
- return rd;
-}
-
-inline bool
-slt(int64_t rs1, int64_t rs2)
-{
- bool rd = false;
- ROP("slt", rd, rs1, rs2);
- return rd;
-}
-
-inline bool
-sltu(uint64_t rs1, uint64_t rs2)
-{
- bool rd = false;
- ROP("sltu", rd, rs1, rs2);
- return rd;
-}
-
-inline uint64_t
-xor_inst(uint64_t rs1, uint64_t rs2)
-{
- uint64_t rd = 0;
- ROP("xor", rd, rs1, rs2);
- return rd;
-}
-
-inline uint64_t
-srl(uint64_t rs1, uint64_t rs2)
-{
- uint64_t rd = 0;
- ROP("srl", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-sra(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("sra", rd, rs1, rs2);
- return rd;
-}
-
-inline uint64_t
-or_inst(uint64_t rs1, uint64_t rs2)
-{
- uint64_t rd = 0;
- ROP("or", rd, rs1, rs2);
- return rd;
-}
-
-inline uint64_t
-and_inst(uint64_t rs1, uint64_t rs2)
-{
- uint64_t rd = 0;
- ROP("and", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-addiw(int64_t rs1, const int16_t imm)
-{
- int64_t rd = 0;
- IOP("addiw", rd, rs1, imm);
- return rd;
-}
-
-inline int64_t
-slliw(int64_t rs1, const uint16_t imm)
-{
- int64_t rd = 0;
- IOP("slliw", rd, rs1, imm);
- return rd;
-}
-
-inline uint64_t
-srliw(uint64_t rs1, const uint16_t imm)
-{
- uint64_t rd = 0;
- IOP("srliw", rd, rs1, imm);
- return rd;
-}
-
-inline int64_t
-sraiw(int64_t rs1, const uint16_t imm)
-{
- int64_t rd = 0;
- IOP("sraiw", rd, rs1, imm);
- return rd;
-}
-
-inline int64_t
-addw(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("addw", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-subw(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("subw", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-sllw(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("sllw", rd, rs1, rs2);
- return rd;
-}
-
-inline uint64_t
-srlw(uint64_t rs1, uint64_t rs2)
-{
- uint64_t rd = 0;
- ROP("srlw", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-sraw(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("sraw", rd, rs1, rs2);
- return rd;
-}
-
-} // namespace I
diff --git a/src/insttest/rv64m.cpp b/src/insttest/rv64m.cpp
deleted file mode 100644
index 836d771..0000000
--- a/src/insttest/rv64m.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#include <cstdint>
-#include <limits>
-
-#include "insttest.h"
-#include "rv64m.h"
-
-int main()
-{
- using namespace std;
- using namespace insttest;
-
- // MUL
- expect<int64_t>(39285, []{return M::mul(873, 45);}, "mul");
- expect<int64_t>(0, []{return M::mul(0x4000000000000000LL, 4);},
- "mul, overflow");
-
- // MULH
- expect<int64_t>(1, []{return M::mulh(0x4000000000000000LL, 4);}, "mulh");
- expect<int64_t>(-1, []{return M::mulh(numeric_limits<int64_t>::min(), 2);},
- "mulh, negative");
- expect<int64_t>(0, []{return M::mulh(-1, -1);}, "mulh, all bits set");
-
- // MULHSU
- expect<int64_t>(-1, []{return M::mulhsu(-1, -1);}, "mulhsu, all bits set");
- expect<int64_t>(-1,
- []{return M::mulhsu(numeric_limits<int64_t>::min(), 2);},\
- "mulhsu");
-
- // MULHU
- expect<uint64_t>(1, []{return M::mulhu(0x8000000000000000ULL, 2);},
- "mulhu");
- expect<uint64_t>(0xFFFFFFFFFFFFFFFEULL, []{return M::mulhu(-1, -1);},
- "mulhu, all bits set");
-
- // DIV
- expect<int64_t>(-7, []{return M::div(-59, 8);}, "div");
- expect<int64_t>(-1, []{return M::div(255, 0);}, "div/0");
- expect<int64_t>(numeric_limits<int64_t>::min(),
- []{return M::div(numeric_limits<int64_t>::min(), -1);},
- "div, overflow");
-
- // DIVU
- expect<uint64_t>(2305843009213693944LL, []{return M::divu(-59, 8);},
- "divu");
- expect<uint64_t>(numeric_limits<uint64_t>::max(),
- []{return M::divu(255, 0);}, "divu/0");
- expect<uint64_t>(0,
- []{return M::divu(numeric_limits<uint64_t>::min(), -1);},
- "divu, \"overflow\"");
-
- // REM
- expect<int64_t>(-3, []{return M::rem(-59, 8);}, "rem");
- expect<int64_t>(255, []{return M::rem(255, 0);}, "rem/0");
- expect<int64_t>(0, []{return M::rem(numeric_limits<int64_t>::min(), -1);},
- "rem, overflow");
-
- // REMU
- expect<uint64_t>(5, []{return M::remu(-59, 8);}, "remu");
- expect<uint64_t>(255, []{return M::remu(255, 0);}, "remu/0");
- expect<uint64_t>(0x8000000000000000ULL,
- []{return M::remu(0x8000000000000000ULL, -1);},
- "remu, \"overflow\"");
-
- // MULW
- expect<int64_t>(-100,
- []{return M::mulw(0x7FFFFFFF00000005LL, 0x80000000FFFFFFECLL);},
- "mulw, truncate");
- expect<int64_t>(0, []{return M::mulw(0x40000000, 4);}, "mulw, overflow");
-
- // DIVW
- expect<int64_t>(-7,
- []{return M::divw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);},
- "divw, truncate");
- expect<int64_t>(-1, []{return M::divw(65535, 0);}, "divw/0");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return M::divw(numeric_limits<int32_t>::min(), -1);},
- "divw, overflow");
-
- // DIVUW
- expect<int64_t>(536870904,
- []{return M::divuw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);},
- "divuw, truncate");
- expect<int64_t>(numeric_limits<uint64_t>::max(),
- []{return M::divuw(65535, 0);}, "divuw/0");
- expect<int64_t>(0,
- []{return M::divuw(numeric_limits<int32_t>::min(), -1);},
- "divuw, \"overflow\"");
- expect<int64_t>(-1,
- []{return M::divuw(numeric_limits<uint32_t>::max(), 1);},
- "divuw, sign extend");
-
- // REMW
- expect<int64_t>(-3,
- []{return M::remw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);},
- "remw, truncate");
- expect<int64_t>(65535, []{return M::remw(65535, 0);}, "remw/0");
- expect<int64_t>(0, []{return M::remw(numeric_limits<int32_t>::min(), -1);},
- "remw, overflow");
-
- // REMUW
- expect<int64_t>(5,
- []{return M::remuw(0x7FFFFFFFFFFFFFC5LL, 0xFFFFFFFF00000008LL);},
- "remuw, truncate");
- expect<int64_t>(65535, []{return M::remuw(65535, 0);}, "remuw/0");
- expect<int64_t>(numeric_limits<int32_t>::min(),
- []{return M::remuw(numeric_limits<int32_t>::min(), -1);},
- "remuw, \"overflow\"");
- expect<int64_t>(0xFFFFFFFF80000000,
- []{return M::remuw(0x80000000, 0xFFFFFFFF);},
- "remuw, sign extend");
-
- return 0;
-}
diff --git a/src/insttest/rv64m.h b/src/insttest/rv64m.h
deleted file mode 100644
index b93a7d6..0000000
--- a/src/insttest/rv64m.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2016 The University of Virginia
- * 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;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * 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
- * OWNER 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.
- *
- * Authors: Alec Roelke
- */
-
-#pragma once
-
-#include <cstdint>
-
-#include "insttest.h"
-
-namespace M
-{
-
-inline int64_t
-mul(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("mul", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-mulh(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("mulh", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-mulhsu(int64_t rs1, uint64_t rs2)
-{
- int64_t rd = 0;
- ROP("mulhsu", rd, rs1, rs2);
- return rd;
-}
-
-inline uint64_t
-mulhu(uint64_t rs1, uint64_t rs2)
-{
- uint64_t rd = 0;
- ROP("mulhu", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-div(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("div", rd, rs1, rs2);
- return rd;
-}
-
-inline uint64_t
-divu(uint64_t rs1, uint64_t rs2)
-{
- uint64_t rd = 0;
- ROP("divu", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-rem(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("rem", rd, rs1, rs2);
- return rd;
-}
-
-inline uint64_t
-remu(uint64_t rs1, uint64_t rs2)
-{
- uint64_t rd = 0;
- ROP("remu", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-mulw(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("mulw", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-divw(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("divw", rd, rs1, rs2);
- return rd;
-}
-
-inline uint64_t
-divuw(uint64_t rs1, uint64_t rs2)
-{
- uint64_t rd = 0;
- ROP("divuw", rd, rs1, rs2);
- return rd;
-}
-
-inline int64_t
-remw(int64_t rs1, int64_t rs2)
-{
- int64_t rd = 0;
- ROP("remw", rd, rs1, rs2);
- return rd;
-}
-
-inline uint64_t
-remuw(uint64_t rs1, uint64_t rs2)
-{
- uint64_t rd = 0;
- ROP("remuw", rd, rs1, rs2);
- return rd;
-}
-
-} // namespace M
diff --git a/src/npb/configs/system/MESI_Two_Level.py b/src/npb/configs/system/MESI_Two_Level.py
index 82d0bb8..1294445 100755
--- a/src/npb/configs/system/MESI_Two_Level.py
+++ b/src/npb/configs/system/MESI_Two_Level.py
@@ -34,9 +34,6 @@
"""
-
-
-
import math
from m5.defines import buildEnv
@@ -86,9 +83,9 @@
icache = self.controllers[i].L1Icache,
dcache = self.controllers[i].L1Dcache,
clk_domain = self.controllers[i].clk_domain,
- pio_master_port = iobus.slave,
- mem_master_port = iobus.slave,
- pio_slave_port = iobus.master
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
slave = port)
@@ -113,23 +110,22 @@
# Set up a proxy port for the system_port. Used for load binaries and
# other functional-only things.
self.sys_port_proxy = RubyPortProxy()
- system.system_port = self.sys_port_proxy.slave
- self.sys_port_proxy.pio_master_port = iobus.slave
+ system.system_port = self.sys_port_proxy.in_ports
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
# Connect the cpu's cache, interrupt, and TLB ports to Ruby
for i,cpu in enumerate(cpus):
- cpu.icache_port = self.sequencers[i].slave
- cpu.dcache_port = self.sequencers[i].slave
+ cpu.icache_port = self.sequencers[i].in_ports
+ cpu.dcache_port = self.sequencers[i].in_ports
cpu.createInterruptController()
isa = buildEnv['TARGET_ISA']
if isa == 'x86':
- cpu.interrupts[0].pio = self.sequencers[i].master
- cpu.interrupts[0].int_master = self.sequencers[i].slave
- cpu.interrupts[0].int_slave = self.sequencers[i].master
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
+ cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
if isa == 'x86' or isa == 'arm':
- cpu.itb.walker.port = self.sequencers[i].slave
- cpu.dtb.walker.port = self.sequencers[i].slave
-
+ cpu.itb.walker.port = self.sequencers[i].in_ports
+ cpu.dtb.walker.port = self.sequencers[i].in_ports
class L1Cache(L1Cache_Controller):
@@ -194,18 +190,18 @@
"""
self.mandatoryQueue = MessageBuffer()
self.requestFromL1Cache = MessageBuffer()
- self.requestFromL1Cache.master = ruby_system.network.slave
+ self.requestFromL1Cache.out_port = ruby_system.network.in_port
self.responseFromL1Cache = MessageBuffer()
- self.responseFromL1Cache.master = ruby_system.network.slave
+ self.responseFromL1Cache.out_port = ruby_system.network.in_port
self.unblockFromL1Cache = MessageBuffer()
- self.unblockFromL1Cache.master = ruby_system.network.slave
+ self.unblockFromL1Cache.out_port = ruby_system.network.in_port
self.optionalQueue = MessageBuffer()
self.requestToL1Cache = MessageBuffer()
- self.requestToL1Cache.slave = ruby_system.network.master
+ self.requestToL1Cache.in_port = ruby_system.network.out_port
self.responseToL1Cache = MessageBuffer()
- self.responseToL1Cache.slave = ruby_system.network.master
+ self.responseToL1Cache.in_port = ruby_system.network.out_port
class L2Cache(L2Cache_Controller):
@@ -240,17 +236,17 @@
"""Connect all of the queues for this controller.
"""
self.DirRequestFromL2Cache = MessageBuffer()
- self.DirRequestFromL2Cache.master = ruby_system.network.slave
+ self.DirRequestFromL2Cache.out_port = ruby_system.network.in_port
self.L1RequestFromL2Cache = MessageBuffer()
- self.L1RequestFromL2Cache.master = ruby_system.network.slave
+ self.L1RequestFromL2Cache.out_port = ruby_system.network.in_port
self.responseFromL2Cache = MessageBuffer()
- self.responseFromL2Cache.master = ruby_system.network.slave
+ self.responseFromL2Cache.out_port = ruby_system.network.in_port
self.unblockToL2Cache = MessageBuffer()
- self.unblockToL2Cache.slave = ruby_system.network.master
+ self.unblockToL2Cache.in_port = ruby_system.network.out_port
self.L1RequestToL2Cache = MessageBuffer()
- self.L1RequestToL2Cache.slave = ruby_system.network.master
+ self.L1RequestToL2Cache.in_port = ruby_system.network.out_port
self.responseToL2Cache = MessageBuffer()
- self.responseToL2Cache.slave = ruby_system.network.master
+ self.responseToL2Cache.in_port = ruby_system.network.out_port
class DirController(Directory_Controller):
@@ -272,16 +268,16 @@
self.ruby_system = ruby_system
self.directory = RubyDirectoryMemory()
# Connect this directory to the memory side.
- self.memory = mem_ctrls[0].port
+ self.memory_out_port = mem_ctrls[0].port
self.connectQueues(ruby_system)
def connectQueues(self, ruby_system):
self.requestToDir = MessageBuffer()
- self.requestToDir.slave = ruby_system.network.master
+ self.requestToDir.in_port = ruby_system.network.out_port
self.responseToDir = MessageBuffer()
- self.responseToDir.slave = ruby_system.network.master
+ self.responseToDir.in_port = ruby_system.network.out_port
self.responseFromDir = MessageBuffer()
- self.responseFromDir.master = ruby_system.network.slave
+ self.responseFromDir.out_port = ruby_system.network.in_port
self.requestToMemory = MessageBuffer()
self.responseFromMemory = MessageBuffer()
@@ -302,9 +298,9 @@
def connectQueues(self, ruby_system):
self.mandatoryQueue = MessageBuffer()
self.responseFromDir = MessageBuffer(ordered = True)
- self.responseFromDir.slave = ruby_system.network.master
+ self.responseFromDir.in_port = ruby_system.network.out_port
self.requestToDir = MessageBuffer()
- self.requestToDir.master = ruby_system.network.slave
+ self.requestToDir.out_port = ruby_system.network.in_port
class MyNetwork(SimpleNetwork):
diff --git a/src/npb/configs/system/MI_example_caches.py b/src/npb/configs/system/MI_example_caches.py
index 9558f58..ca69eab 100755
--- a/src/npb/configs/system/MI_example_caches.py
+++ b/src/npb/configs/system/MI_example_caches.py
@@ -38,9 +38,6 @@
"""
-
-
-
import math
from m5.defines import buildEnv
@@ -87,9 +84,9 @@
icache = self.controllers[i].cacheMemory,
dcache = self.controllers[i].cacheMemory,
clk_domain = self.controllers[i].clk_domain,
- pio_master_port = iobus.slave,
- mem_master_port = iobus.slave,
- pio_slave_port = iobus.master
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
slave = port)
@@ -113,22 +110,22 @@
# Set up a proxy port for the system_port. Used for load binaries and
# other functional-only things.
self.sys_port_proxy = RubyPortProxy()
- system.system_port = self.sys_port_proxy.slave
- self.sys_port_proxy.pio_master_port = iobus.slave
+ system.system_port = self.sys_port_proxy.in_ports
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
# Connect the cpu's cache, interrupt, and TLB ports to Ruby
for i,cpu in enumerate(cpus):
- cpu.icache_port = self.sequencers[i].slave
- cpu.dcache_port = self.sequencers[i].slave
+ cpu.icache_port = self.sequencers[i].in_ports
+ cpu.dcache_port = self.sequencers[i].in_ports
cpu.createInterruptController()
isa = buildEnv['TARGET_ISA']
if isa == 'x86':
- cpu.interrupts[0].pio = self.sequencers[i].master
- cpu.interrupts[0].int_master = self.sequencers[i].slave
- cpu.interrupts[0].int_slave = self.sequencers[i].master
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
+ cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
if isa == 'x86' or isa == 'arm':
- cpu.itb.walker.port = self.sequencers[i].slave
- cpu.dtb.walker.port = self.sequencers[i].slave
+ cpu.itb.walker.port = self.sequencers[i].in_ports
+ cpu.dtb.walker.port = self.sequencers[i].in_ports
class L1Cache(L1Cache_Controller):
@@ -178,13 +175,13 @@
"""
self.mandatoryQueue = MessageBuffer()
self.requestFromCache = MessageBuffer(ordered = True)
- self.requestFromCache.master = ruby_system.network.slave
+ self.requestFromCache.out_port = ruby_system.network.in_port
self.responseFromCache = MessageBuffer(ordered = True)
- self.responseFromCache.master = ruby_system.network.slave
+ self.responseFromCache.out_port = ruby_system.network.in_port
self.forwardToCache = MessageBuffer(ordered = True)
- self.forwardToCache.slave = ruby_system.network.master
+ self.forwardToCache.in_port = ruby_system.network.out_port
self.responseToCache = MessageBuffer(ordered = True)
- self.responseToCache.slave = ruby_system.network.master
+ self.responseToCache.in_port = ruby_system.network.out_port
class DirController(Directory_Controller):
@@ -205,21 +202,21 @@
self.ruby_system = ruby_system
self.directory = RubyDirectoryMemory()
# Connect this directory to the memory side.
- self.memory = mem_ctrls[0].port
+ self.memory_out_port = mem_ctrls[0].port
self.connectQueues(ruby_system)
def connectQueues(self, ruby_system):
self.requestToDir = MessageBuffer(ordered = True)
- self.requestToDir.slave = ruby_system.network.master
+ self.requestToDir.in_port = ruby_system.network.out_port
self.dmaRequestToDir = MessageBuffer(ordered = True)
- self.dmaRequestToDir.slave = ruby_system.network.master
+ self.dmaRequestToDir.in_port = ruby_system.network.out_port
self.responseFromDir = MessageBuffer()
- self.responseFromDir.master = ruby_system.network.slave
+ self.responseFromDir.out_port = ruby_system.network.in_port
self.dmaResponseFromDir = MessageBuffer(ordered = True)
- self.dmaResponseFromDir.master = ruby_system.network.slave
+ self.dmaResponseFromDir.out_port = ruby_system.network.in_port
self.forwardFromDir = MessageBuffer()
- self.forwardFromDir.master = ruby_system.network.slave
+ self.forwardFromDir.out_port = ruby_system.network.in_port
self.requestToMemory = MessageBuffer()
self.responseFromMemory = MessageBuffer()
@@ -240,9 +237,9 @@
def connectQueues(self, ruby_system):
self.mandatoryQueue = MessageBuffer()
self.requestToDir = MessageBuffer()
- self.requestToDir.master = ruby_system.network.slave
+ self.requestToDir.out_port = ruby_system.network.in_port
self.responseFromDir = MessageBuffer(ordered = True)
- self.responseFromDir.slave = ruby_system.network.master
+ self.responseFromDir.in_port = ruby_system.network.out_port
class MyNetwork(SimpleNetwork):
diff --git a/src/npb/configs/system/MOESI_CMP_directory.py b/src/npb/configs/system/MOESI_CMP_directory.py
index 372b792..5208e73 100755
--- a/src/npb/configs/system/MOESI_CMP_directory.py
+++ b/src/npb/configs/system/MOESI_CMP_directory.py
@@ -76,9 +76,9 @@
self.controllers = \
[L1Cache(system, self, cpu, self._numL2Caches) for cpu in cpus] + \
[L2Cache(system, self, self._numL2Caches) for num in \
- range(self._numL2Caches)] + \
- [DirController(self, system.mem_ranges, mem_ctrls)] + \
- [DMAController(self) for i in range(len(dma_ports))]
+ range(self._numL2Caches)] + [DirController(self, \
+ system.mem_ranges, mem_ctrls)] + [DMAController(self) for i \
+ in range(len(dma_ports))]
# Create one sequencer per CPU and dma controller.
# Sequencers for other controllers can be here here.
@@ -87,9 +87,9 @@
icache = self.controllers[i].L1Icache,
dcache = self.controllers[i].L1Dcache,
clk_domain = self.controllers[i].clk_domain,
- pio_master_port = iobus.slave,
- mem_master_port = iobus.slave,
- pio_slave_port = iobus.master
+ pio_request_port = iobus.cpu_side_ports,
+ mem_request_port = iobus.cpu_side_ports,
+ pio_response_port = iobus.mem_side_ports
) for i in range(len(cpus))] + \
[DMASequencer(version = i,
slave = port)
@@ -114,22 +114,22 @@
# Set up a proxy port for the system_port. Used for load binaries and
# other functional-only things.
self.sys_port_proxy = RubyPortProxy()
- system.system_port = self.sys_port_proxy.slave
- self.sys_port_proxy.pio_master_port = iobus.slave
+ system.system_port = self.sys_port_proxy.in_ports
+ self.sys_port_proxy.pio_request_port = iobus.cpu_side_ports
# Connect the cpu's cache, interrupt, and TLB ports to Ruby
for i,cpu in enumerate(cpus):
- cpu.icache_port = self.sequencers[i].slave
- cpu.dcache_port = self.sequencers[i].slave
+ cpu.icache_port = self.sequencers[i].in_ports
+ cpu.dcache_port = self.sequencers[i].in_ports
cpu.createInterruptController()
isa = buildEnv['TARGET_ISA']
if isa == 'x86':
- cpu.interrupts[0].pio = self.sequencers[i].master
- cpu.interrupts[0].int_master = self.sequencers[i].slave
- cpu.interrupts[0].int_slave = self.sequencers[i].master
+ cpu.interrupts[0].pio = self.sequencers[i].interrupt_out_port
+ cpu.interrupts[0].int_requestor = self.sequencers[i].in_ports
+ cpu.interrupts[0].int_responder = self.sequencers[i].interrupt_out_port
if isa == 'x86' or isa == 'arm':
- cpu.itb.walker.port = self.sequencers[i].slave
- cpu.dtb.walker.port = self.sequencers[i].slave
+ cpu.itb.walker.port = self.sequencers[i].in_ports
+ cpu.dtb.walker.port = self.sequencers[i].in_ports
class L1Cache(L1Cache_Controller):
@@ -197,13 +197,13 @@
"""
self.mandatoryQueue = MessageBuffer()
self.requestFromL1Cache = MessageBuffer()
- self.requestFromL1Cache.master = ruby_system.network.slave
+ self.requestFromL1Cache.out_port = ruby_system.network.in_port
self.responseFromL1Cache = MessageBuffer()
- self.responseFromL1Cache.master = ruby_system.network.slave
+ self.responseFromL1Cache.out_port = ruby_system.network.in_port
self.requestToL1Cache = MessageBuffer()
- self.requestToL1Cache.slave = ruby_system.network.master
+ self.requestToL1Cache.in_port = ruby_system.network.out_port
self.responseToL1Cache = MessageBuffer()
- self.responseToL1Cache.slave = ruby_system.network.master
+ self.responseToL1Cache.in_port = ruby_system.network.out_port
self.triggerQueue = MessageBuffer(ordered = True)
class L2Cache(L2Cache_Controller):
@@ -241,18 +241,18 @@
"""Connect all of the queues for this controller.
"""
self.GlobalRequestFromL2Cache = MessageBuffer()
- self.GlobalRequestFromL2Cache.master = ruby_system.network.slave
+ self.GlobalRequestFromL2Cache.out_port = ruby_system.network.in_port
self.L1RequestFromL2Cache = MessageBuffer()
- self.L1RequestFromL2Cache.master = ruby_system.network.slave
+ self.L1RequestFromL2Cache.out_port = ruby_system.network.in_port
self.responseFromL2Cache = MessageBuffer()
- self.responseFromL2Cache.master = ruby_system.network.slave
+ self.responseFromL2Cache.out_port = ruby_system.network.in_port
self.GlobalRequestToL2Cache = MessageBuffer()
- self.GlobalRequestToL2Cache.slave = ruby_system.network.master
+ self.GlobalRequestToL2Cache.in_port = ruby_system.network.out_port
self.L1RequestToL2Cache = MessageBuffer()
- self.L1RequestToL2Cache.slave = ruby_system.network.master
+ self.L1RequestToL2Cache.in_port = ruby_system.network.out_port
self.responseToL2Cache = MessageBuffer()
- self.responseToL2Cache.slave = ruby_system.network.master
+ self.responseToL2Cache.in_port = ruby_system.network.out_port
self.triggerQueue = MessageBuffer(ordered = True)
@@ -276,18 +276,18 @@
self.ruby_system = ruby_system
self.directory = RubyDirectoryMemory()
# Connect this directory to the memory side.
- self.memory = mem_ctrls[0].port
+ self.memory_out_port = mem_ctrls[0].port
self.connectQueues(ruby_system)
def connectQueues(self, ruby_system):
self.requestToDir = MessageBuffer()
- self.requestToDir.slave = ruby_system.network.master
+ self.requestToDir.in_port = ruby_system.network.out_port
self.responseToDir = MessageBuffer()
- self.responseToDir.slave = ruby_system.network.master
+ self.responseToDir.in_port = ruby_system.network.out_port
self.responseFromDir = MessageBuffer()
- self.responseFromDir.master = ruby_system.network.slave
+ self.responseFromDir.out_port = ruby_system.network.in_port
self.forwardFromDir = MessageBuffer()
- self.forwardFromDir.master = ruby_system.network.slave
+ self.forwardFromDir.out_port = ruby_system.network.in_port
self.requestToMemory = MessageBuffer()
self.responseFromMemory = MessageBuffer()
@@ -308,11 +308,11 @@
def connectQueues(self, ruby_system):
self.mandatoryQueue = MessageBuffer()
self.responseFromDir = MessageBuffer()
- self.responseFromDir.slave = ruby_system.network.master
+ self.responseFromDir.in_port = ruby_system.network.out_port
self.reqToDir = MessageBuffer()
- self.reqToDir.master = ruby_system.network.slave
+ self.reqToDir.out_port = ruby_system.network.in_port
self.respToDir = MessageBuffer()
- self.respToDir.master = ruby_system.network.slave
+ self.respToDir.out_port = ruby_system.network.in_port
self.triggerQueue = MessageBuffer(ordered = True)
diff --git a/src/npb/configs/system/caches.py b/src/npb/configs/system/caches.py
index 4630cea..0f03238 100755
--- a/src/npb/configs/system/caches.py
+++ b/src/npb/configs/system/caches.py
@@ -73,7 +73,7 @@
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
def connectCPU(self, cpu):
"""Connect this cache's port to a CPU-side port
@@ -137,13 +137,13 @@
Note: This creates a new crossbar
"""
self.mmubus = L2XBar()
- self.cpu_side = self.mmubus.master
+ self.cpu_side = self.mmubus.mem_side_ports
for tlb in [cpu.itb, cpu.dtb]:
- self.mmubus.slave = tlb.walker.port
+ self.mmubus.cpu_side_ports = tlb.walker.port
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L2Cache(PrefetchCache):
"""Simple L2 Cache with default values"""
@@ -168,10 +168,10 @@
self.size = opts.l2_size
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
class L3Cache(Cache):
"""Simple L3 Cache bank with default values
@@ -196,7 +196,7 @@
self.size = (opts.l3_size)
def connectCPUSideBus(self, bus):
- self.cpu_side = bus.master
+ self.cpu_side = bus.mem_side_ports
def connectMemSideBus(self, bus):
- self.mem_side = bus.slave
+ self.mem_side = bus.cpu_side_ports
diff --git a/src/npb/configs/system/fs_tools.py b/src/npb/configs/system/fs_tools.py
index 22a43d2..5e5e2df 100755
--- a/src/npb/configs/system/fs_tools.py
+++ b/src/npb/configs/system/fs_tools.py
@@ -33,7 +33,7 @@
def __init__(self, filename):
super(CowDisk, self).__init__()
- self.driveID = 'master'
+ self.driveID = 'device0'
self.image = CowDiskImage(child=RawDiskImage(read_only=True),
read_only=False)
self.image.child.image_file = filename
diff --git a/src/npb/configs/system/ruby_system.py b/src/npb/configs/system/ruby_system.py
index 98feef1..4d313bb 100755
--- a/src/npb/configs/system/ruby_system.py
+++ b/src/npb/configs/system/ruby_system.py
@@ -81,7 +81,8 @@
from .MOESI_CMP_directory import MOESICMPDirCache
self.caches = MOESICMPDirCache()
self.caches.setup(self, self.cpu, self.mem_cntrls,
- [self.pc.south_bridge.ide.dma, self.iobus.master],
+ [self.pc.south_bridge.ide.dma,
+ self.iobus.mem_side_ports],
self.iobus)
if self._host_parallel:
@@ -139,9 +140,9 @@
def _createMemoryControllers(self, num, cls):
self.mem_cntrls = [
- cls(range = self.mem_ranges[0])
+ MemCtrl(dram = cls(range = self.mem_ranges[0]))
for i in range(num)
- ]
+ ]
def initFS(self, cpus):
self.pc = Pc()
diff --git a/src/npb/configs/system/system.py b/src/npb/configs/system/system.py
index ff1fa5e..23b8b60 100755
--- a/src/npb/configs/system/system.py
+++ b/src/npb/configs/system/system.py
@@ -68,7 +68,7 @@
self.membus.default = Self.badaddr_responder.pio
# Set up the system port for functional access from the simulator
- self.system_port = self.membus.slave
+ self.system_port = self.membus.cpu_side_ports
self.initFS(self.membus, num_cpus)
@@ -207,9 +207,9 @@
# For x86 only, connect interrupts to the memory
# Note: these are directly connected to the memory bus and
# not cached
- cpu.interrupts[0].pio = self.membus.master
- cpu.interrupts[0].int_master = self.membus.slave
- cpu.interrupts[0].int_slave = self.membus.master
+ cpu.interrupts[0].pio = self.membus.mem_side_ports
+ cpu.interrupts[0].int_requestor = self.membus.cpu_side_ports
+ cpu.interrupts[0].int_responder = self.membus.mem_side_ports
# Memory latency: Using the smaller number from [3]: 96ns
def createMemoryControllersDDR4(self):
@@ -221,14 +221,14 @@
ranges = self._getInterleaveRanges(self.mem_ranges[-1], num, 7, 20)
self.mem_cntrls = [
- cls(range = ranges[i],
- port = self.membus.master)
+ MemCtrl(dram = cls(range = ranges[i]),
+ port = self.membus.mem_side_ports)
for i in range(num)
] + [kernel_controller]
def _createKernelMemoryController(self, cls):
- return cls(range = self.mem_ranges[0],
- port = self.membus.master)
+ return MemCtrl(dram = cls(range = self.mem_ranges[0]),
+ port = self.membus.mem_side_ports)
def _getInterleaveRanges(self, rng, num, intlv_low_bit, xor_low_bit):
from math import log
@@ -262,8 +262,8 @@
# North Bridge
self.iobus = IOXBar()
self.bridge = Bridge(delay='50ns')
- self.bridge.master = self.iobus.slave
- self.bridge.slave = membus.master
+ self.bridge.mem_side_port = self.iobus.cpu_side_ports
+ self.bridge.cpu_side_port = membus.mem_side_ports
# Allow the bridge to pass through:
# 1) kernel configured PCI device memory map address: address range
# [0xC0000000, 0xFFFF0000). (The upper 64kB are reserved for m5ops.)
@@ -283,8 +283,8 @@
# Create a bridge from the IO bus to the memory bus to allow access
# to the local APIC (two pages)
self.apicbridge = Bridge(delay='50ns')
- self.apicbridge.slave = self.iobus.master
- self.apicbridge.master = membus.slave
+ self.apicbridge.cpu_side_port = self.iobus.mem_side_ports
+ self.apicbridge.mem_side_port = membus.cpu_side_ports
self.apicbridge.ranges = [AddrRange(interrupts_address_space_base,
interrupts_address_space_base +
cpus * APIC_range_size
@@ -303,8 +303,8 @@
size = '1kB',
tgts_per_mshr = 12,
addr_ranges = self.mem_ranges)
- self.iocache.cpu_side = self.iobus.master
- self.iocache.mem_side = self.membus.slave
+ self.iocache.cpu_side = self.iobus.mem_side_ports
+ self.iocache.mem_side = self.membus.cpu_side_ports
self.intrctrl = IntrControl()
diff --git a/src/parsec/configs-mesi-two-level/system/fs_tools.py b/src/parsec/configs-mesi-two-level/system/fs_tools.py
index c5b07a8..91f6646 100755
--- a/src/parsec/configs-mesi-two-level/system/fs_tools.py
+++ b/src/parsec/configs-mesi-two-level/system/fs_tools.py
@@ -32,7 +32,7 @@
def __init__(self, filename):
super(CowDisk, self).__init__()
- self.driveID = 'master'
+ self.driveID = 'device0'
self.image = CowDiskImage(child=RawDiskImage(read_only=True),
read_only=False)
self.image.child.image_file = filename
diff --git a/src/parsec/configs-mesi-two-level/system/ruby_system.py b/src/parsec/configs-mesi-two-level/system/ruby_system.py
index 922a025..cea2c2a 100755
--- a/src/parsec/configs-mesi-two-level/system/ruby_system.py
+++ b/src/parsec/configs-mesi-two-level/system/ruby_system.py
@@ -27,6 +27,7 @@
#
import m5
+import math
from m5.objects import *
from m5.util import convert
from .fs_tools import *
@@ -131,10 +132,20 @@
self._createMemoryControllers(1, DDR3_1600_8x8)
def _createMemoryControllers(self, num, cls):
- self.mem_cntrls = [
- cls(range = self.mem_ranges[0])
- for i in range(num)
- ]
+ intlv_bits = int(math.log(num, 2))
+ mem_ctrls = []
+ for i in range(num):
+ interface = cls()
+ interface.range = AddrRange(self.mem_ranges[0].start,
+ size = self.mem_ranges[0].size(),
+ intlvHighBit = 7,
+ xorHighBit = 20,
+ intlvBits = intlv_bits,
+ intlvMatch = i)
+ ctrl = MemCtrl()
+ ctrl.dram = interface
+ mem_ctrls.append(ctrl)
+ self.mem_cntrls = mem_ctrls
def initFS(self, cpus):
self.pc = Pc()
diff --git a/src/parsec/configs/system/fs_tools.py b/src/parsec/configs/system/fs_tools.py
index c5b07a8..91f6646 100755
--- a/src/parsec/configs/system/fs_tools.py
+++ b/src/parsec/configs/system/fs_tools.py
@@ -32,7 +32,7 @@
def __init__(self, filename):
super(CowDisk, self).__init__()
- self.driveID = 'master'
+ self.driveID = 'device0'
self.image = CowDiskImage(child=RawDiskImage(read_only=True),
read_only=False)
self.image.child.image_file = filename
diff --git a/src/parsec/configs/system/system.py b/src/parsec/configs/system/system.py
index a9f2a8a..f2a5b4f 100644
--- a/src/parsec/configs/system/system.py
+++ b/src/parsec/configs/system/system.py
@@ -217,18 +217,24 @@
def _createMemoryControllers(self, num, cls):
kernel_controller = self._createKernelMemoryController(cls)
-
ranges = self._getInterleaveRanges(self.mem_ranges[-1], num, 7, 20)
-
- self.mem_cntrls = [
- cls(range = ranges[i],
- port = self.membus.master)
- for i in range(num)
- ] + [kernel_controller]
+ mem_ctrls = []
+ for i in range(num):
+ interface = cls()
+ interface.range = ranges[i]
+ ctrl = MemCtrl()
+ ctrl.dram = interface
+ ctrl.port = self.membus.master
+ mem_ctrls.append(ctrl)
+ self.mem_cntrls = mem_ctrls + [kernel_controller]
def _createKernelMemoryController(self, cls):
- return cls(range = self.mem_ranges[0],
- port = self.membus.master)
+ interface = cls()
+ interface.range = self.mem_ranges[0]
+ ctrl = MemCtrl()
+ ctrl.dram = interface
+ ctrl.port = self.membus.master
+ return ctrl
def _getInterleaveRanges(self, rng, num, intlv_low_bit, xor_low_bit):
from math import log
diff --git a/src/pthreads/.gitignore b/src/pthreads/.gitignore
deleted file mode 100644
index fc8c9b0..0000000
--- a/src/pthreads/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/bin.*
diff --git a/src/pthreads/Makefile.aarch32 b/src/pthreads/Makefile.aarch32
deleted file mode 100644
index 1acb097..0000000
--- a/src/pthreads/Makefile.aarch32
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (c) 2019 ARM Limited
-# All rights reserved.
-#
-# The license below extends only to copyright in the software and shall
-# not be construed as granting a license to any other intellectual
-# property including but not limited to intellectual property relating
-# to a hardware implementation of the functionality of the software
-# licensed hereunder. You may use the software subject to the license
-# terms below provided that you ensure that this notice is replicated
-# unmodified and in its entirety in all distributions of the software,
-# modified or unmodified, in source code or in binary form.
-#
-# 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;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# 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
-# OWNER 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.
-
-CROSS_COMPILE = arm-linux-gnueabihf-
-BIN_DIR = bin.aarch32
-
--include Makefile.common
diff --git a/src/pthreads/Makefile.aarch64 b/src/pthreads/Makefile.aarch64
deleted file mode 100644
index da30820..0000000
--- a/src/pthreads/Makefile.aarch64
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (c) 2019 ARM Limited
-# All rights reserved.
-#
-# The license below extends only to copyright in the software and shall
-# not be construed as granting a license to any other intellectual
-# property including but not limited to intellectual property relating
-# to a hardware implementation of the functionality of the software
-# licensed hereunder. You may use the software subject to the license
-# terms below provided that you ensure that this notice is replicated
-# unmodified and in its entirety in all distributions of the software,
-# modified or unmodified, in source code or in binary form.
-#
-# 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;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# 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
-# OWNER 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.
-
-CROSS_COMPILE = aarch64-linux-gnu-
-BIN_DIR = bin.aarch64
-
--include Makefile.common
diff --git a/src/pthreads/Makefile.common b/src/pthreads/Makefile.common
deleted file mode 100644
index a7385ce..0000000
--- a/src/pthreads/Makefile.common
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright (c) 2019 ARM Limited
-# All rights reserved.
-#
-# The license below extends only to copyright in the software and shall
-# not be construed as granting a license to any other intellectual
-# property including but not limited to intellectual property relating
-# to a hardware implementation of the functionality of the software
-# licensed hereunder. You may use the software subject to the license
-# terms below provided that you ensure that this notice is replicated
-# unmodified and in its entirety in all distributions of the software,
-# modified or unmodified, in source code or in binary form.
-#
-# 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;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# 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
-# OWNER 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.
-
-CC := $(CROSS_COMPILE)$(CC)
-CXX := $(CROSS_COMPILE)$(CXX)
-LD := $(CXX)
-CCFLAGS ?=
-CXXFLAGS ?= -g -O3 -static -std=c++11
-LDFLAGS ?= -pthread
-
-BIN_DIR ?= ./bin
-
-TESTS = test_pthread_create_seq \
- test_pthread_create_para \
- test_pthread_mutex \
- test_atomic \
- test_pthread_cond \
- test_std_thread \
- test_std_mutex \
- test_std_condition_variable
-
-all: $(addprefix $(BIN_DIR)/,$(TESTS))
-
-$(BIN_DIR)/%: src/%.cpp
- @mkdir -p $(BIN_DIR)
- $(CXX) -o $@ $(CCFLAGS) $(CXXFLAGS) $(LDFLAGS) $^
-
-clean:
- $(RM) -r $(BIN_DIR)
-
-.PHONY: all clean
-
diff --git a/src/pthreads/Makefile.riscv b/src/pthreads/Makefile.riscv
deleted file mode 100644
index ea486a7..0000000
--- a/src/pthreads/Makefile.riscv
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (c) 2019 ARM Limited
-# All rights reserved.
-#
-# The license below extends only to copyright in the software and shall
-# not be construed as granting a license to any other intellectual
-# property including but not limited to intellectual property relating
-# to a hardware implementation of the functionality of the software
-# licensed hereunder. You may use the software subject to the license
-# terms below provided that you ensure that this notice is replicated
-# unmodified and in its entirety in all distributions of the software,
-# modified or unmodified, in source code or in binary form.
-#
-# 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;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# 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
-# OWNER 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.
-
-CROSS_COMPILE = riscv64-unknown-linux-gnu-
-BIN_DIR = bin.riscv64
-
--include Makefile.common
diff --git a/src/pthreads/Makefile.x86 b/src/pthreads/Makefile.x86
deleted file mode 100644
index 90013cd..0000000
--- a/src/pthreads/Makefile.x86
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (c) 2019 ARM Limited
-# All rights reserved.
-#
-# The license below extends only to copyright in the software and shall
-# not be construed as granting a license to any other intellectual
-# property including but not limited to intellectual property relating
-# to a hardware implementation of the functionality of the software
-# licensed hereunder. You may use the software subject to the license
-# terms below provided that you ensure that this notice is replicated
-# unmodified and in its entirety in all distributions of the software,
-# modified or unmodified, in source code or in binary form.
-#
-# 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;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# 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
-# OWNER 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.
-
-CROSS_COMPILE =
-BIN_DIR = bin.x86
-
--include Makefile.common
diff --git a/src/simple/.gitignore b/src/simple/.gitignore
new file mode 100644
index 0000000..e2e7327
--- /dev/null
+++ b/src/simple/.gitignore
@@ -0,0 +1 @@
+/out
diff --git a/src/simple/Makefile b/src/simple/Makefile
new file mode 100644
index 0000000..f3113aa
--- /dev/null
+++ b/src/simple/Makefile
@@ -0,0 +1,179 @@
+# Copyright (c) 2020 ARM Limited
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder. You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# 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;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# 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
+# OWNER 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.
+#
+
+# Input files for each build type. We whitelist barmetal ones,
+# and blacklist
+BARE_INS = \
+ m5_exit \
+ m5_checkpoint
+USER_INS = $(basename $(foreach BASE_DIR, . $(ISA), $(foreach IN_EXT, \
+ $(IN_EXT_ASM) $(IN_EXT_C) $(IN_EXT_CXX), $(wildcard $(BASE_DIR)/*$(IN_EXT)))))
+
+# Input values.
+BOOTLOADER_SRC = bootloader/$(ISA)$(IN_EXT_ASM)
+BOOTLOADER_OBJ = $(OUT_DIR)/bootloader$(OBJ_EXT)
+CC = $(PREFIX)gcc
+CXX = $(PREFIX)g++
+GEM5_ROOT = $(CURDIR)/../../../gem5
+M5OP_OBJ = $(GEM5_ROOT)/util/m5/build/$(M5_ISA)/out/libm5.a
+# Common to USER and BARE.
+CFLAGS = $(CCFLAGS) -std=c11
+# Common to C and C++.
+CCFLAGS = \
+ -I $(GEM5_ROOT)/include/ \
+ -O3 \
+ -Wall \
+ -Werror \
+ -Wextra \
+ -fno-pie \
+ -ggdb3 \
+ -no-pie \
+ -pedantic \
+ -static \
+ $(CCFLAGS_ISA)
+# -Wl,--whole-archive allows C++ threads to work with -static.
+# https://stackoverflow.com/questions/35116327/when-g-static-link-pthread-cause-segmentation-fault-why
+LDFLAGS_USER = \
+ -lrt \
+ -pthread \
+ -Wl,--whole-archive \
+ -lpthread \
+ -Wl,--no-whole-archive
+CCFLAGS_BARE = $(CFLAGS) \
+ -T link.ld \
+ -Wl,--section-start=.text=0x80000000 \
+ -fno-asynchronous-unwind-tables \
+ -fno-unwind-tables \
+ -nostartfiles \
+ -nostdlib
+CFLAGS_USER = $(CFLAGS)
+CXXFLAGS = $(CCFLAGS) -std=c++11
+CXXFLAGS_BARE = $(CXXFLAGS)
+CXXFLAGS_USER = $(CXXFLAGS)
+IN_EXT_ASM = .S
+IN_EXT_C = .c
+IN_EXT_CXX = .cpp
+OUT_DIR_BASE = out
+OUT_DIR = $(OUT_DIR_BASE)/$(ISA)
+OUT_BARE_DIR = $(OUT_DIR)/bare
+OUT_USER_DIR = $(OUT_DIR)/user
+OBJ_EXT = .o
+OUT_EXT = .out
+
+ifeq ($(ISA),)
+ISA = $(shell uname -m)
+endif
+
+ifeq ($(ISA),x86_64)
+CCFLAGS_ISA = -msse3
+M5_ISA = x86
+PREFIX =
+else
+M5_ISA = $(ISA)
+ifeq ($(ISA),aarch64)
+CCFLAGS_ISA = -Xassembler -march=all
+# Input files just for this ISA.
+ISA_BARE_INS = semihost_exit
+# Exclude baremetal only builds.
+USER_INS := $(filter-out $(ISA)/semihost_exit, $(USER_INS))
+# Commented out for now because otherwise adds an
+# empty entry to the target list.
+#ISA_USER_INS =
+PREFIX = aarch64-linux-gnu-
+else
+ifeq ($(ISA),arm)
+PREFIX = arm-linux-gnueabihf-
+else
+ifeq ($(ISA),riscv)
+PREFIX = riscv64-linux-gnu-
+# riscv does not have an util/m5/m5op_
+M5OP_OBJ =
+USER_INS := $(filter-out ./m5_checkpoint ./m5_exit, $(USER_INS))
+else
+$(error unknown isa $(ISA))
+endif
+endif
+endif
+endif
+
+# Calculated values.
+BARE_OUTS = $(addprefix $(OUT_BARE_DIR)/, $(addsuffix $(OUT_EXT), $(BARE_INS) $(addprefix $(ISA)/,$(ISA_BARE_INS))))
+USER_OUTS = $(addprefix $(OUT_USER_DIR)/, $(addsuffix $(OUT_EXT), $(USER_INS)))
+
+.PHONY: all bare clean mkdir user
+
+user: mkdir-user $(USER_OUTS)
+
+bare: mkdir-bare $(BARE_OUTS)
+
+all: bare user
+
+user-show:
+ @echo $(USER_OUTS)
+
+$(OUT_BARE_DIR)/%$(OUT_EXT): %$(IN_EXT_ASM) $(M5OP_OBJ)
+ $(CC) $(CCFLAGS_BARE) -o '$@' $^
+
+$(OUT_USER_DIR)/%$(OUT_EXT): %$(IN_EXT_ASM) $(M5OP_OBJ)
+ $(CC) $(CFLAGS_USER) -o '$@' $^
+
+$(OUT_BARE_DIR)/%$(OUT_EXT): %$(IN_EXT_C) $(M5OP_OBJ) $(BOOTLOADER_OBJ)
+ $(CC) $(CCFLAGS_BARE) -o '$@' $^
+
+$(OUT_USER_DIR)/%$(OUT_EXT): %$(IN_EXT_C) $(M5OP_OBJ)
+ $(CC) $(CFLAGS_USER) -o '$@' $^ $(LDFLAGS_USER)
+
+$(OUT_BARE_DIR)/%$(OUT_EXT): %$(IN_EXT_CXX) $(M5OP_OBJ) $(BOOTLOADER_OBJ)
+ $(CXX) $(CXXFLAGS_BARE) -o '$@' $^
+
+$(OUT_USER_DIR)/%$(OUT_EXT): %$(IN_EXT_CXX) $(M5OP_OBJ)
+ $(CXX) $(CXXFLAGS_USER) -o '$@' $^ $(LDFLAGS_USER)
+
+$(BOOTLOADER_OBJ): $(BOOTLOADER_SRC)
+ $(CC) $(CFLAGS_USER) -c -o '$@' '$<'
+
+$(M5OP_OBJ):
+ cd $(GEM5_ROOT) && scons -C util/m5 build/$(M5_ISA)/out/m5
+
+clean:
+ rm -rf '$(OUT_DIR_BASE)'
+
+mkdir-bare:
+ mkdir -p '$(OUT_BARE_DIR)/$(ISA)'
+
+mkdir-user:
+ mkdir -p '$(OUT_USER_DIR)/$(ISA)'
+
diff --git a/src/simple/README.md b/src/simple/README.md
new file mode 100644
index 0000000..c6b1ced
--- /dev/null
+++ b/src/simple/README.md
@@ -0,0 +1,3 @@
+Simple single input source userland/baremetal executables in C/C++ etc.
+
+How to build explained in `make help`.
diff --git a/src/simple/aarch64/futex_ldxr_stxr.c b/src/simple/aarch64/futex_ldxr_stxr.c
new file mode 100644
index 0000000..b044494
--- /dev/null
+++ b/src/simple/aarch64/futex_ldxr_stxr.c
@@ -0,0 +1,126 @@
+/* Copyright (c) 2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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.
+ *
+ * Correct outcome:
+ * Exiting @ tick 18446744073709551615 because simulate() limit reached
+ * Incorrect behaviour due to: https://gem5.atlassian.net/browse/GEM5-537
+ * Exits successfully. */
+
+#define _GNU_SOURCE
+#include <assert.h>
+#include <inttypes.h>
+#include <linux/futex.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#define LDXR_OPS_SIZE 1024
+static int futex1 = 1;
+static int futex2 = 1;
+/* We do this to ensure that those two varibles are well separated.
+ * If they are too close (same cache line?), then the str to ldxr_done
+ * can make CPU1 lose the lock. */
+static uint64_t ldxr_ops[LDXR_OPS_SIZE];
+static uint64_t *ldxr_done = ldxr_ops;
+static uint64_t *ldxr_var = ldxr_ops + LDXR_OPS_SIZE - 1;
+
+void __attribute__ ((noinline)) busy_loop(
+ unsigned long long max,
+ unsigned long long max2
+) {
+ for (unsigned long long i = 0; i < max2; i++) {
+ for (unsigned long long j = 0; j < max; j++) {
+ __asm__ __volatile__ ("" : "+g" (i), "+g" (j) : :);
+ }
+ }
+}
+
+static int
+futex(int *uaddr, int futex_op, int val,
+ const struct timespec *timeout, int *uaddr2, int val3)
+{
+ register uint64_t x0 __asm__ ("x0") = (uint64_t)uaddr;
+ register uint64_t x1 __asm__ ("x1") = futex_op;
+ register uint64_t x2 __asm__ ("x2") = val;
+ register const struct timespec *x3 __asm__ ("x3") = timeout;
+ register int *x4 __asm__ ("x4") = uaddr2;
+ register uint64_t x5 __asm__ ("x5") = val3;
+ register uint64_t x8 __asm__ ("x8") = SYS_futex; /* syscall number */
+ __asm__ __volatile__ (
+ "svc 0;"
+ : "+r" (x0)
+ : "r" (x1), "r" (x2), "r" (x3), "r" (x4), "r" (x5), "r" (x8)
+ : "memory"
+ );
+ return x0;
+}
+
+void* thread_main(void *arg) {
+ (void)arg;
+ __asm__ __volatile__ (
+ "ldxr x0, [%[ldxr_var]];mov %[ldxr_done], 1"
+ : [ldxr_done] "=r" (*ldxr_done)
+ : [ldxr_var] "r" (ldxr_var)
+ : "x0", "memory"
+ );
+ futex(&futex1, FUTEX_WAIT, futex1, NULL, NULL, 0);
+ futex(&futex2, FUTEX_WAIT, futex2, NULL, NULL, 0);
+ return NULL;
+}
+
+int main(void) {
+ pthread_t thread;
+ pthread_create(&thread, NULL, thread_main, NULL);
+ while (!*ldxr_done) {}
+ /* Wait for thread1 to sleep on futex1. Works because */
+ busy_loop(1000, 1);
+ /* Try to wake up the thread with an LLSC event.
+ * It should not wake up in a correct implementation,
+ * but it used to happen in gem5 before it was fixed. */
+ __asm__ __volatile__ (
+ "mov x0, 1;ldxr x0, [%0]; stxr w1, x0, [%0]"
+ :
+ : "r" (ldxr_var) : "x0", "x1", "memory"
+ );
+ /* Wait for thread1 to sleep on futex2. */
+ busy_loop(1000, 1);
+ /* Before it was fixed in gem5, this would wrongly wake a futex2
+ * because the previous futex1 was woken up via LLSC. */
+ futex(&futex1, FUTEX_WAKE, 1, NULL, NULL, 0);
+ assert(!pthread_join(thread, NULL));
+}
diff --git a/src/simple/aarch64/semihost_exit.S b/src/simple/aarch64/semihost_exit.S
new file mode 100644
index 0000000..ace5b30
--- /dev/null
+++ b/src/simple/aarch64/semihost_exit.S
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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.
+ */
+
+.global _start
+_start:
+ /* 0x20026 == ADP_Stopped_ApplicationExit */
+ mov x1, 0x26
+ movk x1, 0x2, lsl 16
+ ldr x2, =.Lsemihost_args
+ str x1, [x2, 0]
+
+ /* Exit status code. */
+ mov x0, 0
+ str x0, [x2, 8]
+
+ /* Address of parameter block. */
+ mov x1, x2
+
+ /* SYS_EXIT */
+ mov w0, 0x18
+
+ /* Make the semihosting call. */
+ hlt 0xf000
+.Lsemihost_args:
+ .skip 16
diff --git a/src/simple/bootloader/aarch64.S b/src/simple/bootloader/aarch64.S
new file mode 100644
index 0000000..7cb4b6c
--- /dev/null
+++ b/src/simple/bootloader/aarch64.S
@@ -0,0 +1,6 @@
+.global _start
+_start:
+ ldr x0, =stack_top
+ mov sp, x0
+ mov x0, 0
+ bl main
diff --git a/src/simple/chdir_print.c b/src/simple/chdir_print.c
new file mode 100644
index 0000000..bed844e
--- /dev/null
+++ b/src/simple/chdir_print.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2011-2015 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/**
+ * # example test compile and run parameters
+ * # Note: the absolute path to the chdir-print binary should be specified
+ * # in the run command even if running from the same folder. This is needed
+ * # because chdir is executed before triggering a clone for the file read,
+ * # and the cloned process won't be able to find the executable if a relative
+ * # path is provided.
+ *
+ * # compile examples
+ * scons --default=X86 ./build/X86/gem5.opt PROTOCOL=MOESI_hammer
+ * scons --default=X86 ./build/X86/gem5.opt PROTOCOL=MESI_Three_Level
+ *
+ * # run parameters
+ * <GEM5_ROOT>/build/X86/gem5.opt <GEM5_ROOT>/configs/example/se.py -c \
+ * <GEM5_ROOT>/tests/test-progs/chdir-print/chdir-print -n2 --ruby
+ *
+ *
+ * # example successful output for MESI_Three_Level:
+ *
+ * <...>
+ *
+ * **** REAL SIMULATION ****
+ * info: Entering event queue @ 0. Starting simulation...
+ * warn: Replacement policy updates recently became the responsibility of
+ * SLICC state machines. Make sure to setMRU() near callbacks in .sm files!
+ * cwd: /proj/research_simu/users/jalsop/gem5-mem_dif_debug/tests/
+ * test-progs/chdir-print/
+ * cwd: /proc
+ *
+ * <...>
+ *
+ * processor : 0
+ * vendor_id : Generic
+ * cpu family : 0
+ * model : 0
+ * model name : Generic
+ * stepping : 0
+ * cpu MHz : 2000
+ * cache size: : 2048K
+ * physical id : 0
+ * siblings : 2
+ * core id : 0
+ * cpu cores : 2
+ * fpu : yes
+ * fpu exception : yes
+ * cpuid level : 1
+ * wp : yes
+ * flags : fpu
+ * cache alignment : 64
+ *
+ * processor : 1
+ * vendor_id : Generic
+ * cpu family : 0
+ * model : 0
+ * model name : Generic
+ * stepping : 0
+ * cpu MHz : 2000
+ * cache size: : 2048K
+ * physical id : 0
+ * siblings : 2
+ * core id : 1
+ * cpu cores : 2
+ * fpu : yes
+ * fpu exception : yes
+ * cpuid level : 1
+ * wp : yes
+ * flags : fpu
+ * cache alignment : 64
+ *
+ * SUCCESS
+ * Exiting @ tick 2694923000 because exiting with last active thread context
+ */
+
+#include <assert.h>
+#include <linux/limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+const int BUFFER_SIZE = 64;
+
+// Tests the functionality of RegisterFilesystem
+int main(void)
+{
+ char *cwd = getcwd(NULL, PATH_MAX);
+ printf("cwd: %s\n", cwd);
+ free(cwd);
+
+ assert(!chdir("/proc"));
+
+ cwd = getcwd(NULL, PATH_MAX);
+ printf("cwd: %s\n", cwd);
+ free(cwd);
+
+ FILE *fp;
+ char buffer[BUFFER_SIZE];
+
+ bool found_procline = false;
+ fp = popen("cat cpuinfo", "r");
+ if (fp != NULL) {
+ while (fgets(buffer, BUFFER_SIZE, fp) != NULL) {
+ printf("%s", buffer);
+ if (strstr(buffer, "processor")) {
+ found_procline = true;
+ }
+ }
+ pclose(fp);
+ }
+
+ if (found_procline) {
+ printf("SUCCESS\n");
+ return EXIT_SUCCESS;
+ }
+
+ printf("FAILURE\n");
+ return EXIT_FAILURE;
+}
diff --git a/src/simple/hello.c b/src/simple/hello.c
new file mode 100644
index 0000000..589b06e
--- /dev/null
+++ b/src/simple/hello.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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.
+ */
+
+#include <stdio.h>
+
+int main(void) {
+ puts("hello");
+}
diff --git a/src/simple/hello_cpp.cpp b/src/simple/hello_cpp.cpp
new file mode 100644
index 0000000..0cbf750
--- /dev/null
+++ b/src/simple/hello_cpp.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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.
+ */
+
+#include <iostream>
+
+int main() {
+ std::cout << "hello" << std::endl;
+}
diff --git a/src/simple/link.ld b/src/simple/link.ld
new file mode 100644
index 0000000..d3abb9e
--- /dev/null
+++ b/src/simple/link.ld
@@ -0,0 +1,17 @@
+ENTRY(_start)
+SECTIONS
+{
+ .text : {
+ */bootloader.o(.text)
+ *(.text)
+ *(.rodata)
+ *(.data)
+ *(COMMON)
+ }
+ .bss : { *(.bss) }
+ heap_low = .;
+ . = . + 0x1000000;
+ heap_top = .;
+ . = . + 0x1000000;
+ stack_top = .;
+}
diff --git a/src/simple/m5_checkpoint.c b/src/simple/m5_checkpoint.c
new file mode 100644
index 0000000..70bb6e7
--- /dev/null
+++ b/src/simple/m5_checkpoint.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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.
+ */
+
+#include <gem5/m5ops.h>
+
+int main(void) {
+ m5_checkpoint(0, 0);
+ m5_exit(0);
+}
diff --git a/src/simple/m5_exit.c b/src/simple/m5_exit.c
new file mode 100644
index 0000000..75932eb
--- /dev/null
+++ b/src/simple/m5_exit.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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
+ * OWNER 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.
+ */
+
+#include <gem5/m5ops.h>
+
+int main(void) {
+ m5_exit(0);
+}
diff --git a/src/simple/page_access_wrap.cpp b/src/simple/page_access_wrap.cpp
new file mode 100644
index 0000000..8d8b553
--- /dev/null
+++ b/src/simple/page_access_wrap.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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.
+ */
+
+#include <sys/mman.h>
+
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+
+int main(void)
+{
+ uint64_t page_size = 0x1000;
+ uint64_t num_pages = 0x10000;
+ uint64_t length = page_size * num_pages;
+
+ void *raw = mmap(NULL, length, PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
+ uint8_t *mem = reinterpret_cast<uint8_t*>(raw);
+
+ srand(0xABCD);
+
+ uint64_t last_byte = page_size - 1;
+ uint64_t page_boundaries = num_pages - 1;
+
+ for (int i = 0; i < 2000; i++) {
+ uint64_t random_boundary = rand() % page_boundaries;
+ uint64_t boundary_offset = random_boundary * page_size;
+ uint64_t boundary_last_byte = boundary_offset + last_byte;
+ uint32_t *poke = reinterpret_cast<uint32_t*>(mem + boundary_last_byte);
+ printf("%p\n", (void *)poke);
+ __asm__ __volatile__("" : "=r" (*poke) : : );
+ }
+
+ return 0;
+}
diff --git a/src/pthreads/src/test_atomic.cpp b/src/simple/pthread_atomic.cpp
similarity index 98%
rename from src/pthreads/src/test_atomic.cpp
rename to src/simple/pthread_atomic.cpp
index 68c94e4..3fc3aff 100644
--- a/src/pthreads/src/test_atomic.cpp
+++ b/src/simple/pthread_atomic.cpp
@@ -67,7 +67,7 @@
return nullptr;
}
-int main( int argc, const char* argv[] )
+int main()
{
int n_worker_threads = 0;
diff --git a/src/pthreads/src/test_pthread_cond.cpp b/src/simple/pthread_cond.cpp
similarity index 98%
rename from src/pthreads/src/test_pthread_cond.cpp
rename to src/simple/pthread_cond.cpp
index 5552f78..ae0d984 100644
--- a/src/pthreads/src/test_pthread_cond.cpp
+++ b/src/simple/pthread_cond.cpp
@@ -80,7 +80,7 @@
pthread_mutex_unlock( &mutex );
}
-int main( int argc, char* argv[] )
+int main(void)
{
size_t n_worker_threads = 0;
diff --git a/src/pthreads/src/test_pthread_create_para.cpp b/src/simple/pthread_create_para.cpp
similarity index 98%
rename from src/pthreads/src/test_pthread_create_para.cpp
rename to src/simple/pthread_create_para.cpp
index 1b10c9f..8604c7a 100644
--- a/src/pthreads/src/test_pthread_create_para.cpp
+++ b/src/simple/pthread_create_para.cpp
@@ -62,7 +62,7 @@
return nullptr;
}
-int main( int argc, const char* argv[] )
+int main()
{
int n_worker_threads = 0;
diff --git a/src/pthreads/src/test_pthread_create_seq.cpp b/src/simple/pthread_create_seq.cpp
similarity index 98%
rename from src/pthreads/src/test_pthread_create_seq.cpp
rename to src/simple/pthread_create_seq.cpp
index 2a5a571..755d252 100644
--- a/src/pthreads/src/test_pthread_create_seq.cpp
+++ b/src/simple/pthread_create_seq.cpp
@@ -61,7 +61,7 @@
return nullptr;
}
-int main( int argc, const char* argv[] )
+int main()
{
int n_worker_threads = 0;
diff --git a/src/pthreads/src/test_pthread_mutex.cpp b/src/simple/pthread_mutex.cpp
similarity index 98%
rename from src/pthreads/src/test_pthread_mutex.cpp
rename to src/simple/pthread_mutex.cpp
index 313539b..80b006d 100644
--- a/src/pthreads/src/test_pthread_mutex.cpp
+++ b/src/simple/pthread_mutex.cpp
@@ -75,7 +75,7 @@
return nullptr;
}
-int main( int argc, const char* argv[] )
+int main()
{
int n_worker_threads = 0;
diff --git a/src/pthreads/src/test_std_condition_variable.cpp b/src/simple/pthread_std_condition_variable.cpp
similarity index 96%
rename from src/pthreads/src/test_std_condition_variable.cpp
rename to src/simple/pthread_std_condition_variable.cpp
index b3d162d..de6703c 100644
--- a/src/pthreads/src/test_std_condition_variable.cpp
+++ b/src/simple/pthread_std_condition_variable.cpp
@@ -68,7 +68,7 @@
cv.notify_all();
}
-int main( int argc, char* argv[] )
+int main()
{
size_t n_worker_threads = 0;
@@ -86,7 +86,7 @@
std::cout << n_worker_threads << " threads ready to race...\n";
go(); // go!
- for (int i = 0; i < n_worker_threads; ++i) {
+ for (size_t i = 0; i < n_worker_threads; ++i) {
threads[i].join();
}
diff --git a/src/pthreads/src/test_std_mutex.cpp b/src/simple/pthread_std_mutex.cpp
similarity index 98%
rename from src/pthreads/src/test_std_mutex.cpp
rename to src/simple/pthread_std_mutex.cpp
index e81f60f..dedfd35 100644
--- a/src/pthreads/src/test_std_mutex.cpp
+++ b/src/simple/pthread_std_mutex.cpp
@@ -47,7 +47,7 @@
#define MAX_N_WORKER_THREADS 10
-int main( int argc, const char* argv[] )
+int main()
{
int n_worker_threads = 0;
diff --git a/src/pthreads/src/test_std_thread.cpp b/src/simple/pthread_std_thread.cpp
similarity index 98%
rename from src/pthreads/src/test_std_thread.cpp
rename to src/simple/pthread_std_thread.cpp
index 6634d90..c345fab 100644
--- a/src/pthreads/src/test_std_thread.cpp
+++ b/src/simple/pthread_std_thread.cpp
@@ -48,7 +48,7 @@
#define MAX_N_WORKER_THREADS 10
-int main( int argc, char* argv[] )
+int main(void)
{
int n_worker_threads = 0;
diff --git a/src/simple/stack_print.c b/src/simple/stack_print.c
new file mode 100644
index 0000000..ff431bf
--- /dev/null
+++ b/src/simple/stack_print.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2017 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * For use for simulation and test purposes only
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 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.
+ *
+ * Author: Brandon Potter
+ */
+
+#include <elf.h>
+#include <stdio.h>
+
+int main(int argc, char **argv, char **envp)
+{
+ int i;
+
+ printf("%p: argc: [%d]\n", (void*)&argc, argc);
+ printf("\n");
+
+ for (i = 0; i < argc; i++)
+ printf("%p: argv[%d]: [%s]\n", (void*)&argv[i], i, argv[i]);
+ printf("\n");
+
+ i = 0;
+ while (envp[i] != NULL) {
+ printf("%p: envp[%d]: [%s]\n", (void*)&envp[i], i, envp[i]);
+ i++;
+ }
+ printf("\n");
+
+ Elf64_auxv_t *auxv = (Elf64_auxv_t*)&envp[--i];
+ while (auxv++) {
+ char *type;
+ switch(auxv->a_type) {
+ case AT_IGNORE:
+ type = "AT_IGNORE";
+ break;
+ case AT_EXECFD:
+ type = "AT_EXECFD";
+ break;
+ case AT_PHDR:
+ type = "AT_PHDR";
+ break;
+ case AT_PHENT:
+ type = "AT_PHENT";
+ break;
+ case AT_PHNUM:
+ type = "AT_PHNUM";
+ break;
+ case AT_PAGESZ:
+ type = "AT_PAGESZ";
+ break;
+ case AT_BASE:
+ type = "AT_BASE";
+ break;
+ case AT_FLAGS:
+ type = "AT_FLAGS";
+ break;
+ case AT_ENTRY:
+ type = "AT_ENTRY";
+ break;
+ case AT_NOTELF:
+ type = "AT_NOTELF";
+ break;
+ case AT_UID:
+ type = "AT_UID";
+ break;
+ case AT_EUID:
+ type = "AT_EUID";
+ break;
+ case AT_GID:
+ type = "AT_GID";
+ break;
+ case AT_EGID:
+ type = "AT_EGID";
+ break;
+ case AT_CLKTCK:
+ type = "AT_CLKTCK";
+ break;
+ case AT_PLATFORM:
+ type = "AT_PLATFORM";
+ break;
+ case AT_HWCAP:
+ type = "AT_HWCAP";
+ break;
+ case AT_FPUCW:
+ type = "AT_FPUCW";
+ break;
+ case AT_DCACHEBSIZE:
+ type = "AT_DCACHEBSIZE";
+ break;
+ case AT_ICACHEBSIZE:
+ type = "AT_ICACHEBSIZE";
+ break;
+ case AT_UCACHEBSIZE:
+ type = "AT_UCACHEBSIZE";
+ break;
+ case AT_IGNOREPPC:
+ type = "AT_IGNOREPPC";
+ break;
+ case AT_SECURE:
+ type = "AT_SECURE";
+ break;
+ case AT_BASE_PLATFORM:
+ type = "AT_BASE_PLATFORM";
+ break;
+ case AT_RANDOM:
+ type = "AT_RANDOM";
+ break;
+ case AT_EXECFN:
+ type = "AT_EXECFN";
+ break;
+ case AT_SYSINFO:
+ type = "AT_SYSINFO";
+ break;
+ case AT_SYSINFO_EHDR:
+ type = "AT_SYSINFO_EHDR";
+ break;
+ case AT_L1I_CACHESHAPE:
+ type = "AT_L1I_CACHESHAPE";
+ break;
+ case AT_L1D_CACHESHAPE:
+ type = "AT_L1D_CACHESHAPE";
+ break;
+ case AT_L2_CACHESHAPE:
+ type = "AT_L2_CACHESHAPE";
+ break;
+ case AT_L3_CACHESHAPE:
+ type = "AT_L3_CACHESHAPE";
+ break;
+ case AT_NULL:
+ default:
+ printf("\n");
+ return 0;
+ }
+ printf("%p: %s: [%jx]\n", (void *)auxv, type, (uintmax_t)auxv->a_un.a_val);
+ }
+}
+
diff --git a/src/simple/std_thread.cpp b/src/simple/std_thread.cpp
new file mode 100644
index 0000000..b1e8468
--- /dev/null
+++ b/src/simple/std_thread.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2017 Jason Lowe-Power
+* 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;
+* neither the name of the copyright holders nor the names of its
+* contributors may be used to endorse or promote products derived from
+* this software without specific prior written permission.
+*
+* 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
+* OWNER 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.
+*/
+
+#include <iostream>
+#include <thread>
+
+using namespace std;
+
+/*
+ * c = a + b
+ */
+void array_add(int *a, int *b, int *c, int tid, int threads, int num_values)
+{
+ for (int i = tid; i < num_values; i += threads) {
+ c[i] = a[i] + b[i];
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ int num_values;
+ if (argc == 1) {
+ num_values = 100;
+ } else if (argc == 2) {
+ num_values = atoi(argv[1]);
+ if (num_values <= 0) {
+ cerr << "Usage: " << argv[0] << " [num_values]" << endl;
+ return 1;
+ }
+ } else {
+ cerr << "Usage: " << argv[0] << " [num_values]" << endl;
+ return 1;
+ }
+
+ int cpus = thread::hardware_concurrency();
+
+ cout << "Running on " << cpus << " cores. ";
+ cout << "with " << num_values << " values" << endl;
+
+ int *a, *b, *c;
+ a = new int[num_values];
+ b = new int[num_values];
+ c = new int[num_values];
+
+ if (!(a && b && c)) {
+ cerr << "Allocation error!" << endl;
+ return 2;
+ }
+
+ for (int i = 0; i < num_values; i++) {
+ a[i] = i;
+ b[i] = num_values - i;
+ c[i] = 0;
+ }
+
+ thread **threads = new thread*[cpus];
+
+ // NOTE: -1 is required for this to work in SE mode.
+ for (int i = 0; i < cpus - 1; i++) {
+ threads[i] = new thread(array_add, a, b, c, i, cpus, num_values);
+ }
+ // Execute the last thread with this thread context to appease SE mode
+ array_add(a, b, c, cpus - 1, cpus, num_values);
+
+ cout << "Waiting for other threads to complete" << endl;
+
+ for (int i = 0; i < cpus - 1; i++) {
+ threads[i]->join();
+ }
+
+ delete[] threads;
+
+ cout << "Validating..." << flush;
+
+ int num_valid = 0;
+ for (int i = 0; i < num_values; i++) {
+ if (c[i] == num_values) {
+ num_valid++;
+ } else {
+ cerr << "c[" << i << "] is wrong.";
+ cerr << " Expected " << num_values;
+ cerr << " Got " << c[i] << "." << endl;
+ }
+ }
+
+ if (num_valid == num_values) {
+ cout << "Success!" << endl;
+ return 0;
+ } else {
+ return 2;
+ }
+}
diff --git a/src/simple/x86_64/mwait.c b/src/simple/x86_64/mwait.c
new file mode 100644
index 0000000..62bf8c8
--- /dev/null
+++ b/src/simple/x86_64/mwait.c
@@ -0,0 +1,75 @@
+// author: Marc Orr
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define NUM_TRIES 1000
+
+// Make sure that flags and wait sit in different cache lines
+volatile int flags[10];
+volatile int wait[10];
+
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void *DoWork1(void *threadid)
+{
+ (void)threadid;
+ flags[0] = flags[0] + 1;
+ wait[0] = 0;
+ pthread_exit(0);
+}
+
+void *DoWork2(void *threadid)
+{
+ (void)threadid;
+ pthread_mutex_lock (&mutex);
+ flags[0] = flags[0] + 1;
+ pthread_mutex_unlock (&mutex);
+ pthread_exit(0);
+}
+
+//////////////////////////////////////////////////////////////////////
+// Program main
+//////////////////////////////////////////////////////////////////////
+int main(void)
+{
+ // stuff for thread
+ pthread_t threads[1];
+
+ // initialize global variables
+ flags[0] = 0;
+ wait[0] = 1;
+
+ // monitor (via gcc intrinsic)
+ __builtin_ia32_monitor ((void *)&flags, 0, 0);
+
+ // invalidate flags in this cpu's cache
+ pthread_create(&threads[0], NULL, DoWork1, NULL);
+ while (wait[0]);
+
+ // launch thread to invalidate address being monitored
+ pthread_create(&threads[0], NULL, DoWork2, NULL);
+
+ // wait for other thread to modify flags
+ int mwait_cnt = 0;
+ do {
+ pthread_mutex_lock (&mutex);
+ if (flags[0] != 2) {
+ pthread_mutex_unlock (&mutex);
+ __builtin_ia32_mwait(0, 0);
+ } else {
+ pthread_mutex_unlock (&mutex);
+ }
+ mwait_cnt++;
+ } while (flags[0] != 2 && mwait_cnt < NUM_TRIES);
+
+ // test may hang if mwait is not working
+ if (flags[0]==2) {
+ printf("mwait regression PASSED, flags[0] = %d\n", flags[0]);
+ } else {
+ printf("mwait regression FAILED, flags[0] = %d\n", flags[0]);
+ }
+
+ return 0;
+}