Files
fail/ovp/cortexM3/platform/platform.cc
hsc b70b6fb43a another directory rename: failstar -> fail
"failstar" sounds like a name for a cruise liner from the 80s.  As "*" isn't a
desirable part of directory names, just name the whole thing "fail/", the core
parts being stored in "fail/core/".

Additionally fixing two build system dependency issues:
 - missing jobserver -> protomessages dependency
 - broken bochs -> fail dependency (add_custom_target DEPENDS only allows plain
   file dependencies ... cmake for the win)


git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@956 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
2012-03-08 19:43:02 +00:00

363 lines
11 KiB
C++

/*
* Copyright (c) 2005-2011 Imperas Software Ltd., www.imperas.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include "platform.hpp"
#include "statreg.hpp"
#include "SAL/SALInst.hpp"
#include "icm/icmCpuManager.h"
#include "icm/icmQuery.h"
// enable relaxed scheduling for maximum performance
//#define SIM_ATTRS (ICM_ATTR_RELAXED_SCHED|ICM_ATTR_TRACE)
#define SIM_ATTRS (ICM_ATTR_RELAXED_SCHED)
// GDB port
#define GDB_PORT 1234
// Variables set by arguments
const char *variant = "Cortex-M3"; // the model variant
using namespace std;
ARM_Cortex_M3 arm;
ARM_Cortex_M3::ARM_Cortex_M3() {
}
ARM_Cortex_M3::~ARM_Cortex_M3() {
delete platform;
delete cpu;
delete attrList;
}
void ARM_Cortex_M3::init(bool gdb=false) {
// initialize OVPsim, enabling verbose mode to get statistics at end of execution
platform = new icmPlatform("CortexM3Platform", //name
ICM_VERBOSE|ICM_STOP_ON_CTRLC, //attributes
gdb ? "rsp" : 0, // optional protocol
gdb ? GDB_PORT : 0); // optional port number
// const char *armModel = icmGetVlnvString(NULL, "arm.ovpworld.org", "processor", "armm", "1.0", "model");
const char *armModel = "/srv/scratch/hoffmann/test/build/lib/libarmmModel.so";
const char *armSemihost = icmGetVlnvString(NULL, "arm.ovpworld.org", "semihosting", "armNewlib", "1.0", "model");
attrList = new icmAttrListObject();
attrList->addAttr("endian", "little");
attrList->addAttr("compatibility", "nopBKPT");
attrList->addAttr("variant", variant);
attrList->addAttr("UAL", "1");
attrList->addAttr("fail_salp", &sal::simulator);
char cpuname[64];
sprintf(cpuname,"cpu-%s", variant);
// create a processor instance
cpu = new icmProcessorObject(
cpuname, // CPU name
"armm", // CPU type
0, // CPU cpuId
0, // CPU model flags
32, // address bits
armModel, // model file
"modelAttrs", // morpher attributes
SIM_ATTRS, // attributes
attrList, // user-defined attributes
armSemihost, // semi-hosting file
"modelAttrs" // semi-hosting attributes
);
// Nominate this processor to be attached to a debugger
if(gdb) cpu->debugThisProcessor();
processorP = cpu->getProcessorP();
}
void ARM_Cortex_M3::createFullMMC(const char *vlnRoot=0) {
// TODO: ELF Groesse auslesen per OVP (hat funktionen) und dann den Bereich als MMC einrichten...
/* const char *mmc_model = icmGetVlnvString("/srv/scratch/sirozipp/build/lib", "ovpworld.org", "mmc", "failMMC", "1.0", "model");
if(mmc_model == NULL) {
std::cerr << "mmc_model not found!" << std::endl;
exit(1);
}
*/
const char *mmc_model = "/srv/scratch/sirozipp/build/lib/libflaky.so";
// create full MMCs
mmcInstr = new icmMmcObject("mmci", mmc_model, "modelAttrs", 0, False);
mmcData = new icmMmcObject("mmcd", mmc_model, "modelAttrs", 0, False);
// create processor instruction and data bus
instrBus = new icmBusObject("instrbus", 32);
dataBus = new icmBusObject("databus", 32);
// create processor main bus
mainBus = new icmBusObject("mainbus", 32);
// connect processor ports to their buses
cpu->connect(*instrBus, *dataBus);
// connect mmcs to buses
mmcInstr->connect(*instrBus, "sp1", False);
mmcData->connect(*dataBus, "sp1", False);
// connet master ports of mmc to main bus
mmcInstr->connect(*mainBus, "mp1", True);
mmcData->connect(*mainBus, "mp1", True);
// create simulated memory
Addr appHighAddr, appLowAddr;
appHighAddr = 0xFFFFFFFF;
appLowAddr = 0x0;
icmMem0 = new icmMemoryObject("mem1", ICM_PRIV_RWX, appHighAddr-appLowAddr);
// connect memory to main bus
icmMem0->connect("mp1", *mainBus, 0);
}
static ICM_MEM_READ_FN(extMemRead) {
unsigned char res[4];
// Int32 tmpres = *(Int32*)value;
// icmPrintf("EXTERNAL MEMORY: Reading 0x%08x from 0x%08x\n", *(Int32*)value, (Int32)address);
// *(Int32*) value = (Int32)arm.mem[(address-arm.offset)>>2];
sal::simulator.onMemoryAccessEvent(address, 4, false, ovpplatform.getPC());
res[0] = arm.mem[(address-arm.offset)+0];
res[1] = arm.mem[(address-arm.offset)+1];
res[2] = arm.mem[(address-arm.offset)+2];
res[3] = arm.mem[(address-arm.offset)+3];
// icmPrintf("Reading [0] 0x%08x, [1] 0x%08x, [2] 0x%08x, [3] 0x%08x\n", arm.mem[(address-arm.offset)+0], arm.mem[(address-arm.offset)+1], arm.mem[(address-arm.offset)+2], arm.mem[(address-arm.offset)+3]);
*(Int32*)value = (res[3] << 24) | (res[2] << 16) | (res[1] << 8) | res[0];
//
// icmPrintf("Reading: 0x%08x\n", (res[3] << 24) | (res[2] << 16) | (res[1] << 8) | res[0]);
// icmPrintf("Callback: Reading 0x%08x from mem[0x%08x] should be 0x%08x from [0x%08x]\n", *(Int32*)value, (Int32)(address-arm.offset), tmpres, (Int32) address);
}
static ICM_MEM_WRITE_FN(extMemWrite) {
// icmPrintf("EXTERNAL MEMORY: Writing 0x%08x to 0x%08x\n", (Int32)value, (Int32)address);
// icmPrintf("Callback: Writing 0x%08x to mem[0x%08x] should be 0x%08x from [0x%08x]\n", *(Int32*)value, (Int32)(address-arm.offset), *(Int32*) value, (Int32) address);
sal::simulator.onMemoryAccessEvent(address, 4, true, ovpplatform.getPC());
Int32 val = *(Int32*)value;
arm.mem[(address-arm.offset) + 0] = val & 0xFF;
arm.mem[(address-arm.offset) + 1] = (val >> 8) & 0xFF;
arm.mem[(address-arm.offset) + 2] = (val >> 16) & 0xFF;
arm.mem[(address-arm.offset) + 3] = (val >> 24) & 0xFF;
// icmPrintf("Writing [0] 0x%08x, [1] 0x%08x, [2] 0x%08x, [3] 0x%08x\n", val & 0xFF, (val >> 8) & 0xFF, (val >> 16) & 0xFF, (val >> 24) & 0xFF);
// icmPrintf("Writing [0] 0x%08x, [1] 0x%08x, [2] 0x%08x, [3] 0x%08x\n", arm.mem[(address-arm.offset)+0], arm.mem[(address-arm.offset)+1], arm.mem[(address-arm.offset)+2], arm.mem[(address-arm.offset)+3]);
// Int32 res = arm.mem[(address-arm.offset)+0] | arm.mem[(address-arm.offset)+1] << 8 | arm.mem[(address-arm.offset)+2] << 16 | arm.mem[(address-arm.offset)+3] << 24;
// icmPrintf("Callback: Writing 0x%08x to mem[0x%08x] should be 0x%08x to [0x%08x]\n", res, (Int32)(address-arm.offset), *(Int32*) value, (Int32) address);
// arm.mem[(address-arm.offset) >> 2] = *(Int32*) value;
}
static ICM_MEM_READ_FN(extTextRead) {
// Int16 val = *(Int16*)value;
*(Int16*) value = (Int16)arm.textmem[(address-arm.textOffset)>>1];
// icmPrintf("Callback: Reading 0x%04x from textmem[0x%08x] should be 0x%04x from [0x%08x]\n", *(Int16*)value, (Int32)(address-arm.textOffset), val, (Int32) address);
}
static ICM_MEM_WRITE_FN(extTextWrite) {
arm.textmem[(address-arm.textOffset) >> 1] = *(Int16*) value;
}
void ARM_Cortex_M3::mapMemToCallback() {
// create processor bus
mainBus = new icmBusObject("mainbus", 32);
// connect the processor bus
cpu->connect(*mainBus, *mainBus);
// create simulated memory
Addr appHighAddr, appLowAddr, textLowAddr, textHighAddr, LowAddr, LowAddrH, HighAddr, HighAddrL;
appLowAddr = offset;
appHighAddr = appLowAddr + memSize - 1;
textLowAddr = textOffset;
textHighAddr = textLowAddr + textMemSize - 1;
// check which section is first
if(appLowAddr < textLowAddr) {
LowAddr = appLowAddr;
LowAddrH = appHighAddr;
HighAddr = textHighAddr;
HighAddrL = textLowAddr;
} else {
LowAddr = textLowAddr;
LowAddrH = textHighAddr;
HighAddr = appHighAddr;
HighAddrL = appLowAddr;
}
// Memory from 0x0 to LowAddr
icmMem0 = new icmMemoryObject("mem0", ICM_PRIV_RWX, LowAddr - 1);
// Memory after callback mem to end
icmMem1 = new icmMemoryObject("mem1", ICM_PRIV_RWX, 0xFFFFFFFF - HighAddr - 1);
// Memory between text and other sections
icmMem2 = new icmMemoryObject("mem2", ICM_PRIV_RWX, HighAddrL - LowAddrH - 1 -1);
// map the adress range appLowAddr:appHighAddr externally to the processor
mainBus->mapExternalMemory("external", ICM_PRIV_RWX, appLowAddr, appHighAddr,
extMemRead, // read callback
extMemWrite, // write callback
0);
mainBus->mapExternalMemory("exttext", ICM_PRIV_RWX, textLowAddr, textHighAddr,
extTextRead,
extTextWrite,
0);
// just build memory before external memory if it's not at the beginning
if(LowAddr > 0x0) {
icmMem0->connect("mp1", *mainBus, 0x0);
}
if(HighAddr < 0xffffffff) {
icmMem1->connect("mp2", *mainBus, HighAddr+1);
}
if(LowAddrH != HighAddrL) {
icmMem2->connect("mp3", *mainBus, LowAddrH+1);
}
mainBus->printConnections();
}
void ARM_Cortex_M3::makeGPRegister() {
const string names[] = {"r0", "r1", "r2", "r3", "r4", "r5",
"r6", "r7", "r8", "r9", "r10", "r11", "r12"};
for(int i = 0; i <= 12; ++i) {
icmRegInfoP reg = icmGetRegByIndex(processorP, i);
sal::simulator.makeGPRegister(32, (void *)reg, names[i]);
}
// set SP pointer
// ARM Cortex M3: SP pointer is ID 13
icmRegInfoP sp_reg = icmGetRegByIndex(processorP, 13);
setSPReg(sp_reg);
}
void ARM_Cortex_M3::makeSTRegister() {
OVPStatusRegister *streg = new CortexM3StatusRegister();
sal::simulator.makeSTRegister(streg, "sp");
}
void ARM_Cortex_M3::makePCRegister() {
// ARM Cortex M3: PC pointer is ID 15
icmRegInfoP pc_reg = icmGetRegByIndex(processorP, 15);
sal::simulator.makePCRegister(32, (void *)pc_reg, "PC");
}
int ARM_Cortex_M3::startSimulation(const char *app) {
bool loadPhysical = true;
bool verbose = true;
bool useEntry = true;
if(!cpu->loadLocalMemory(app, loadPhysical, verbose, useEntry))
return -1;
// application is loaded, now fill the callback memory with program data
fillCallbackMemory();
// icmSimulatePlatform();
while(1) {
// save PC
Addr pc_ptr = cpu->getPC();
sal::simulator.onInstrPtrChanged(pc_ptr);
// simulate the platform
icmStopReason stopreason = cpu->simulate(1);
if(stopreason!=0x00) {
// was simulation interrupted or did it complete
if(stopreason==ICM_SR_INTERRUPT) {
icmPrintf("*** simulation interrupted\n");
}
break;
}
}
//icmTerminate();
return 0;
}
void ARM_Cortex_M3::makeCallbackMemory(size_t sizeText, size_t offText, size_t sizeMem, size_t offMem) {
mem = new unsigned char[sizeMem];
//mem = new Int32[sizeMem>>2];
textmem = new Int16[sizeText>>1];
offset = offMem;
textOffset = offText;
memSize = sizeMem;
textMemSize = sizeText;
}
int main(int argc, char **argv) {
if(argc != 2) {
std::cerr << "Usage: " << argv[0] << " application" << std::endl;
exit(1);
}
arm.init(false);
// arm.createFullMMC();
// arm.makeCallbackMemory(0x100, 0x20000000);
// arm.makeCallbackMemory(0x8034, 0x0, 0x11c, 0x82e8);
// arm.makeCallbackMemory(0x8034, 0x0, 0x940, 0x8040);
arm.makeCallbackMemory(0x802c, 0x0, 0x930, 0x8038);
arm.mapMemToCallback();
ovpplatform.setCpu((void *) &arm);
arm.makeGPRegister();
arm.makeSTRegister();
arm.makePCRegister();
sal::simulator.finishedRegisterCreation();
arm.startSimulation(argv[1]);
}