diff options
Diffstat (limited to 'dev/alpha_console.cc')
-rw-r--r-- | dev/alpha_console.cc | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc new file mode 100644 index 000000000..6a1e2b169 --- /dev/null +++ b/dev/alpha_console.cc @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * 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. + */ + +/* @file + * System Console Definition + */ + +#include <stddef.h> +#include <stdio.h> + +#include <string> + +#include "alpha_console.hh" +#include "base_cpu.hh" +#include "console.hh" +#include "exec_context.hh" +#include "memory_control.hh" +#include "simple_disk.hh" +#include "tlaser_clock.hh" +#include "system.hh" +#include "trace.hh" +#include "inifile.hh" +#include "str.hh" // for to_number() + +using namespace std; + +AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, + SimpleDisk *d, int size, System *system, + BaseCPU *cpu, TlaserClock *clock, int num_cpus, + Addr addr, Addr mask, MemoryController *mmu) + : MmapDevice(name, addr, mask, mmu), disk(d), console(cons) +{ + consoleData = new uint8_t[size]; + memset(consoleData, 0, size); + + alphaAccess->last_offset = size - 1; + alphaAccess->kernStart = system->getKernelStart(); + alphaAccess->kernEnd = system->getKernelEnd(); + alphaAccess->entryPoint = system->getKernelEntry(); + + alphaAccess->version = ALPHA_ACCESS_VERSION; + alphaAccess->numCPUs = num_cpus; + alphaAccess->mem_size = system->physmem->getSize(); + alphaAccess->cpuClock = cpu->getFreq() / 1000000; + alphaAccess->intrClockFrequency = clock->frequency(); + + alphaAccess->diskUnit = 1; +} + +Fault +AlphaConsole::read(MemReqPtr req, uint8_t *data) +{ + memset(data, 0, req->size); + + if (req->size == sizeof(uint32_t)) { + Addr daddr = req->paddr & addr_mask; + *(uint32_t *)data = *(uint32_t *)(consoleData + daddr); + +#if 0 + DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", + daddr, *(uint32_t *)data); +#endif + } + + return No_Fault; +} + +Fault +AlphaConsole::write(MemReqPtr req, const uint8_t *data) +{ + uint64_t val; + + switch (req->size) { + case sizeof(uint32_t): + val = *(uint32_t *)data; + break; + case sizeof(uint64_t): + val = *(uint64_t *)data; + break; + default: + return Machine_Check_Fault; + } + + Addr paddr = req->paddr & addr_mask; + + if (paddr == offsetof(AlphaAccess, diskUnit)) { + alphaAccess->diskUnit = val; + return No_Fault; + } + + if (paddr == offsetof(AlphaAccess, diskCount)) { + alphaAccess->diskCount = val; + return No_Fault; + } + + if (paddr == offsetof(AlphaAccess, diskPAddr)) { + alphaAccess->diskPAddr = val; + return No_Fault; + } + + if (paddr == offsetof(AlphaAccess, diskBlock)) { + alphaAccess->diskBlock = val; + return No_Fault; + } + + if (paddr == offsetof(AlphaAccess, diskOperation)) { + if (val == 0x13) + disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock, + alphaAccess->diskCount); + else + panic("Invalid disk operation!"); + + return No_Fault; + } + + if (paddr == offsetof(AlphaAccess, outputChar)) { + console->simple((char)(val & 0xff)); + return No_Fault; + } + + if (paddr == offsetof(AlphaAccess, bootStrapImpure)) { + alphaAccess->bootStrapImpure = val; + return No_Fault; + } + + if (paddr == offsetof(AlphaAccess, bootStrapCPU)) { + warn("%d: Trying to launch another CPU!", curTick); + int cpu = val; + assert(cpu > 0 && "Must not access primary cpu"); + + ExecContext *other_xc = req->xc->system->xc_array[cpu]; + other_xc->regs.intRegFile[16] = cpu; + other_xc->regs.ipr[TheISA::IPR_PALtemp16] = cpu; + other_xc->regs.intRegFile[0] = cpu; + other_xc->regs.intRegFile[30] = alphaAccess->bootStrapImpure; + other_xc->setStatus(ExecContext::Active); //Start the cpu + return No_Fault; + } + + return No_Fault; +} + +void +AlphaConsole::serialize() +{ + nameOut(); + // assumes full AlphaAccess size + // might have unnecessary fields here + paramOut("last_offset",alphaAccess->last_offset); + paramOut("version",alphaAccess->version); + paramOut("numCPUs",alphaAccess->numCPUs); + paramOut("mem_size",alphaAccess->mem_size); + paramOut("cpuClock",alphaAccess->cpuClock); + paramOut("intrClockFrequency",alphaAccess->intrClockFrequency); + paramOut("kernStart",alphaAccess->kernStart); + paramOut("kernEnd",alphaAccess->kernEnd); + paramOut("entryPoint",alphaAccess->entryPoint); + paramOut("diskUnit",alphaAccess->diskUnit); + paramOut("diskCount",alphaAccess->diskCount); + paramOut("diskPAddr",alphaAccess->diskPAddr); + paramOut("diskBlock",alphaAccess->diskBlock); + paramOut("diskOperation",alphaAccess->diskOperation); + paramOut("outputChar",alphaAccess->outputChar); + paramOut("bootStrapImpure",alphaAccess->bootStrapImpure); + paramOut("bootStrapCPU",alphaAccess->bootStrapCPU); +} + +void +AlphaConsole::unserialize(IniFile &db, const std::string &category, + ConfigNode *node) +{ + string data; + db.findDefault(category,"last_offset",data); + to_number(data,alphaAccess->last_offset); + db.findDefault(category,"version",data); + to_number(data,alphaAccess->version); + db.findDefault(category,"numCPUs",data); + to_number(data,alphaAccess->numCPUs); + db.findDefault(category,"mem_size",data); + to_number(data,alphaAccess->mem_size); + db.findDefault(category,"cpuClock",data); + to_number(data,alphaAccess->cpuClock); + db.findDefault(category,"intrClockFrequency",data); + to_number(data,alphaAccess->intrClockFrequency); + db.findDefault(category,"kernStart",data); + to_number(data,alphaAccess->kernStart); + db.findDefault(category,"kernEnd",data); + to_number(data,alphaAccess->kernEnd); + db.findDefault(category,"entryPoint",data); + to_number(data,alphaAccess->entryPoint); + db.findDefault(category,"diskUnit",data); + to_number(data,alphaAccess->diskUnit); + db.findDefault(category,"diskCount",data); + to_number(data,alphaAccess->diskCount); + db.findDefault(category,"diskPAddr",data); + to_number(data,alphaAccess->diskPAddr); + db.findDefault(category,"diskBlock",data); + to_number(data,alphaAccess->diskBlock); + db.findDefault(category,"diskOperation",data); + to_number(data,alphaAccess->diskOperation); + db.findDefault(category,"outputChar",data); + to_number(data,alphaAccess->outputChar); + db.findDefault(category,"bootStrapImpure",data); + to_number(data,alphaAccess->bootStrapImpure); + db.findDefault(category,"bootStrapCPU",data); + to_number(data,alphaAccess->bootStrapCPU); + +} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) + + SimObjectParam<SimConsole *> sim_console; + SimObjectParam<SimpleDisk *> disk; + Param<int> size; + Param<int> num_cpus; + SimObjectParam<MemoryController *> mmu; + Param<Addr> addr; + Param<Addr> mask; + SimObjectParam<System *> system; + SimObjectParam<BaseCPU *> cpu; + SimObjectParam<TlaserClock *> clock; + +END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) + +BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole) + + INIT_PARAM(sim_console, "The Simulator Console"), + INIT_PARAM(disk, "Simple Disk"), + INIT_PARAM_DFLT(size, "AlphaConsole size", sizeof(AlphaAccess)), + INIT_PARAM_DFLT(num_cpus, "Number of CPU's", 1), + INIT_PARAM(mmu, "Memory Controller"), + INIT_PARAM(addr, "Device Address"), + INIT_PARAM(mask, "Address Mask"), + INIT_PARAM(system, "system object"), + INIT_PARAM(cpu, "Processor"), + INIT_PARAM(clock, "Turbolaser Clock") + +END_INIT_SIM_OBJECT_PARAMS(AlphaConsole) + +CREATE_SIM_OBJECT(AlphaConsole) +{ + return new AlphaConsole(getInstanceName(), sim_console, + disk, size, system, + cpu, clock, num_cpus, + addr, mask, mmu); +} + +REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole) |