Add a client implementation corresponding to the server so people who want to utilize the server have an example. Change-Id: Idf1a8f5a406271bbcbe0b338e709e89b1512c8a8 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/61050 Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com>
118 lines
4.5 KiB
C++
118 lines
4.5 KiB
C++
/*
|
|
* Copyright 2022 Google, Inc.
|
|
*
|
|
* 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 <iomanip>
|
|
#include <iostream>
|
|
#include <random>
|
|
#include <string>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "shared_memory_client.hh"
|
|
|
|
/**
|
|
* Consider that
|
|
* 1. you have a SimpleMemory that spans from 0x0 to 0x10000
|
|
* 2. you have a SharedMemoryServer with server_path=ram.sock
|
|
* 3. The SHM server and the Mem is under the same System
|
|
*
|
|
* You should see a unix socket m5out/ram.sock, and you should be able to run
|
|
* our example with commands like:
|
|
* `./shared_memory_client_example m5out/ram.sock 0x1000 0x1010`
|
|
*
|
|
* The example will use the client to map the range 0x1000-0x1010 of the
|
|
* SimpleMemory into the address space of the example. As a result, the example
|
|
* will be able to access the backing store of the SimpleMemory with just a
|
|
* normal pointer.
|
|
*/
|
|
|
|
static void PrintAsHexString(char *buffer, uint64_t size);
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
if (argc != 4) {
|
|
std::cerr << "Usage: " << argv[0] << " <shm_sock_path> <start> <end>"
|
|
<< std::endl;
|
|
return 1;
|
|
}
|
|
|
|
// Each SharedMemoryServer in gem5 will create a unix socket at the
|
|
// location specified in its server_path parameter, and the socket can be
|
|
// used by the client to communicate with the server.
|
|
gem5::util::memory::SharedMemoryClient shm_client(argv[1]);
|
|
|
|
// Before request access to the simulated physical memory in gem5, we need
|
|
// to first determine what's the range we'd like to access.
|
|
uint64_t start = std::stoull(argv[2], nullptr, 0);
|
|
uint64_t end = std::stoull(argv[3], nullptr, 0);
|
|
|
|
// One thing important is that, non-align request is not supported now, so
|
|
// we'll need to ensure the start address is on page boundary.
|
|
long page_size = sysconf(_SC_PAGESIZE);
|
|
if (page_size < 0) {
|
|
std::cerr << "Cannot determine page size" << std::endl;
|
|
return 1;
|
|
}
|
|
if (start % page_size != 0) {
|
|
std::cerr << "Start address must be aligned" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
// The Map request, if success, will return a void* pointer, which can then
|
|
// be used as a backdoor to the physical memory range in gem5. If there's
|
|
// any error, nullptr will be returned.
|
|
char *mem = reinterpret_cast<char *>(shm_client.MapMemory(start, end));
|
|
uint64_t size = end - start + 1;
|
|
if (mem == nullptr) {
|
|
std::cerr << "Unable to map memory" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
// A simple use case that print and randomly fill the memory.
|
|
std::cout << "Content was: ";
|
|
PrintAsHexString(mem, size);
|
|
// Override content with random value.
|
|
std::random_device rand_dev;
|
|
std::uniform_int_distribution<int> rand_dist(0, 255);
|
|
for (uint64_t i = 0; i < size; ++i) {
|
|
mem[i] = rand_dist(rand_dev);
|
|
}
|
|
std::cout << "Content is: ";
|
|
PrintAsHexString(mem, size);
|
|
}
|
|
|
|
static void
|
|
PrintAsHexString(char *buffer, uint64_t size)
|
|
{
|
|
for (uint64_t i = 0; i < size; ++i) {
|
|
std::cout << std::setw(2) << std::setfill('0') << std::hex
|
|
<< (static_cast<int>(buffer[i]) & 0xff);
|
|
}
|
|
std::cout << std::endl;
|
|
}
|