rv_ctrl.cc revision 11011
17584SAli.Saidi@arm.com/* 211011SAndreas.Sandberg@ARM.com * Copyright (c) 2010,2013,2015 ARM Limited 37584SAli.Saidi@arm.com * All rights reserved 47584SAli.Saidi@arm.com * 57584SAli.Saidi@arm.com * The license below extends only to copyright in the software and shall 67584SAli.Saidi@arm.com * not be construed as granting a license to any other intellectual 77584SAli.Saidi@arm.com * property including but not limited to intellectual property relating 87584SAli.Saidi@arm.com * to a hardware implementation of the functionality of the software 97584SAli.Saidi@arm.com * licensed hereunder. You may use the software subject to the license 107584SAli.Saidi@arm.com * terms below provided that you ensure that this notice is replicated 117584SAli.Saidi@arm.com * unmodified and in its entirety in all distributions of the software, 127584SAli.Saidi@arm.com * modified or unmodified, in source code or in binary form. 137584SAli.Saidi@arm.com * 147584SAli.Saidi@arm.com * Redistribution and use in source and binary forms, with or without 157584SAli.Saidi@arm.com * modification, are permitted provided that the following conditions are 167584SAli.Saidi@arm.com * met: redistributions of source code must retain the above copyright 177584SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer; 187584SAli.Saidi@arm.com * redistributions in binary form must reproduce the above copyright 197584SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer in the 207584SAli.Saidi@arm.com * documentation and/or other materials provided with the distribution; 217584SAli.Saidi@arm.com * neither the name of the copyright holders nor the names of its 227584SAli.Saidi@arm.com * contributors may be used to endorse or promote products derived from 237584SAli.Saidi@arm.com * this software without specific prior written permission. 247584SAli.Saidi@arm.com * 257584SAli.Saidi@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 267584SAli.Saidi@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 277584SAli.Saidi@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 287584SAli.Saidi@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 297584SAli.Saidi@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 307584SAli.Saidi@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 317584SAli.Saidi@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 327584SAli.Saidi@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 337584SAli.Saidi@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347584SAli.Saidi@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 357584SAli.Saidi@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 367584SAli.Saidi@arm.com * 377584SAli.Saidi@arm.com * Authors: Ali Saidi 387584SAli.Saidi@arm.com */ 397584SAli.Saidi@arm.com 407584SAli.Saidi@arm.com#include "base/trace.hh" 419958Smatt.evans@arm.com#include "debug/RVCTRL.hh" 427584SAli.Saidi@arm.com#include "dev/arm/rv_ctrl.hh" 437584SAli.Saidi@arm.com#include "mem/packet.hh" 447584SAli.Saidi@arm.com#include "mem/packet_access.hh" 4511011SAndreas.Sandberg@ARM.com#include "sim/voltage_domain.hh" 467584SAli.Saidi@arm.com 477584SAli.Saidi@arm.comRealViewCtrl::RealViewCtrl(Params *p) 489958Smatt.evans@arm.com : BasicPioDevice(p, 0xD4), flags(0), scData(0) 497584SAli.Saidi@arm.com{ 507584SAli.Saidi@arm.com} 517584SAli.Saidi@arm.com 527584SAli.Saidi@arm.comTick 537584SAli.Saidi@arm.comRealViewCtrl::read(PacketPtr pkt) 547584SAli.Saidi@arm.com{ 557584SAli.Saidi@arm.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 567584SAli.Saidi@arm.com assert(pkt->getSize() == 4); 577584SAli.Saidi@arm.com Addr daddr = pkt->getAddr() - pioAddr; 587584SAli.Saidi@arm.com 597584SAli.Saidi@arm.com switch(daddr) { 608524SAli.Saidi@ARM.com case ProcId0: 618524SAli.Saidi@ARM.com pkt->set(params()->proc_id0); 628524SAli.Saidi@ARM.com break; 638524SAli.Saidi@ARM.com case ProcId1: 648524SAli.Saidi@ARM.com pkt->set(params()->proc_id1); 657584SAli.Saidi@arm.com break; 667584SAli.Saidi@arm.com case Clock24: 677584SAli.Saidi@arm.com Tick clk; 689004Skoansin.tan@gmail.com clk = SimClock::Float::MHz * curTick() * 24; 697584SAli.Saidi@arm.com pkt->set((uint32_t)(clk)); 707584SAli.Saidi@arm.com break; 718060SAli.Saidi@ARM.com case Clock100: 728060SAli.Saidi@ARM.com Tick clk100; 739004Skoansin.tan@gmail.com clk100 = SimClock::Float::MHz * curTick() * 100; 748060SAli.Saidi@ARM.com pkt->set((uint32_t)(clk100)); 758060SAli.Saidi@ARM.com break; 767584SAli.Saidi@arm.com case Flash: 777584SAli.Saidi@arm.com pkt->set<uint32_t>(0); 787584SAli.Saidi@arm.com break; 797950SAli.Saidi@ARM.com case Clcd: 807950SAli.Saidi@ARM.com pkt->set<uint32_t>(0x00001F00); 817950SAli.Saidi@ARM.com break; 827950SAli.Saidi@ARM.com case Osc0: 837950SAli.Saidi@ARM.com pkt->set<uint32_t>(0x00012C5C); 847950SAli.Saidi@ARM.com break; 857950SAli.Saidi@ARM.com case Osc1: 867950SAli.Saidi@ARM.com pkt->set<uint32_t>(0x00002CC0); 877950SAli.Saidi@ARM.com break; 887950SAli.Saidi@ARM.com case Osc2: 897950SAli.Saidi@ARM.com pkt->set<uint32_t>(0x00002C75); 907950SAli.Saidi@ARM.com break; 917950SAli.Saidi@ARM.com case Osc3: 927950SAli.Saidi@ARM.com pkt->set<uint32_t>(0x00020211); 937950SAli.Saidi@ARM.com break; 947950SAli.Saidi@ARM.com case Osc4: 957950SAli.Saidi@ARM.com pkt->set<uint32_t>(0x00002C75); 967950SAli.Saidi@ARM.com break; 977950SAli.Saidi@ARM.com case Lock: 987950SAli.Saidi@ARM.com pkt->set<uint32_t>(sysLock); 997950SAli.Saidi@ARM.com break; 1008281SAli.Saidi@ARM.com case Flags: 1018281SAli.Saidi@ARM.com pkt->set<uint32_t>(flags); 1028281SAli.Saidi@ARM.com break; 1038299Schander.sudanthi@arm.com case IdReg: 1048299Schander.sudanthi@arm.com pkt->set<uint32_t>(params()->idreg); 1058299Schander.sudanthi@arm.com break; 1068870SAli.Saidi@ARM.com case CfgStat: 1078870SAli.Saidi@ARM.com pkt->set<uint32_t>(1); 1088988SAli.Saidi@ARM.com break; 1099958Smatt.evans@arm.com case CfgData: 1109958Smatt.evans@arm.com pkt->set<uint32_t>(scData); 1119958Smatt.evans@arm.com DPRINTF(RVCTRL, "Read %#x from SCReg\n", scData); 1129958Smatt.evans@arm.com break; 1139958Smatt.evans@arm.com case CfgCtrl: 1149958Smatt.evans@arm.com pkt->set<uint32_t>(0); // not busy 1159958Smatt.evans@arm.com DPRINTF(RVCTRL, "Read 0 from CfgCtrl\n"); 1169958Smatt.evans@arm.com break; 1177584SAli.Saidi@arm.com default: 1188299Schander.sudanthi@arm.com warn("Tried to read RealView I/O at offset %#x that doesn't exist\n", 1198299Schander.sudanthi@arm.com daddr); 1209958Smatt.evans@arm.com pkt->set<uint32_t>(0); 1217584SAli.Saidi@arm.com break; 1227584SAli.Saidi@arm.com } 1237584SAli.Saidi@arm.com pkt->makeAtomicResponse(); 1247584SAli.Saidi@arm.com return pioDelay; 1257584SAli.Saidi@arm.com 1267584SAli.Saidi@arm.com} 1277584SAli.Saidi@arm.com 1287584SAli.Saidi@arm.comTick 1297584SAli.Saidi@arm.comRealViewCtrl::write(PacketPtr pkt) 1307584SAli.Saidi@arm.com{ 1317584SAli.Saidi@arm.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 1327584SAli.Saidi@arm.com 1337584SAli.Saidi@arm.com Addr daddr = pkt->getAddr() - pioAddr; 1347584SAli.Saidi@arm.com switch (daddr) { 1357584SAli.Saidi@arm.com case Flash: 1367950SAli.Saidi@ARM.com case Clcd: 1377950SAli.Saidi@ARM.com case Osc0: 1387950SAli.Saidi@ARM.com case Osc1: 1397950SAli.Saidi@ARM.com case Osc2: 1407950SAli.Saidi@ARM.com case Osc3: 1417950SAli.Saidi@ARM.com case Osc4: 1427950SAli.Saidi@ARM.com break; 1437950SAli.Saidi@ARM.com case Lock: 1447950SAli.Saidi@ARM.com sysLock.lockVal = pkt->get<uint16_t>(); 1457584SAli.Saidi@arm.com break; 1468281SAli.Saidi@ARM.com case Flags: 1478281SAli.Saidi@ARM.com flags = pkt->get<uint32_t>(); 1488281SAli.Saidi@ARM.com break; 1498524SAli.Saidi@ARM.com case FlagsClr: 1508524SAli.Saidi@ARM.com flags = 0; 1518524SAli.Saidi@ARM.com break; 1529958Smatt.evans@arm.com case CfgData: 1539958Smatt.evans@arm.com scData = pkt->get<uint32_t>(); 1549958Smatt.evans@arm.com break; 1559958Smatt.evans@arm.com case CfgCtrl: { 1569958Smatt.evans@arm.com // A request is being submitted to read/write the system control 1579958Smatt.evans@arm.com // registers. See 1589958Smatt.evans@arm.com // http://infocenter.arm.com/help/topic/com.arm.doc.dui0447h/CACDEFGH.html 15911011SAndreas.Sandberg@ARM.com CfgCtrlReg req = pkt->get<uint32_t>(); 16011011SAndreas.Sandberg@ARM.com if (!req.start) { 16111011SAndreas.Sandberg@ARM.com DPRINTF(RVCTRL, "SCReg: write %#x to ctrl but not starting\n", 16211011SAndreas.Sandberg@ARM.com req); 16311011SAndreas.Sandberg@ARM.com break; 16411011SAndreas.Sandberg@ARM.com } 1659958Smatt.evans@arm.com 16611011SAndreas.Sandberg@ARM.com auto it_dev(devices.find(req & CFG_CTRL_ADDR_MASK)); 16711011SAndreas.Sandberg@ARM.com if (it_dev == devices.end()) { 16811011SAndreas.Sandberg@ARM.com warn_once("SCReg: Access to unknown device " 16911011SAndreas.Sandberg@ARM.com "dcc%d:site%d:pos%d:fn%d:dev%d\n", 17011011SAndreas.Sandberg@ARM.com req.dcc, req.site, req.pos, req.func, req.dev); 17111011SAndreas.Sandberg@ARM.com break; 17211011SAndreas.Sandberg@ARM.com } 17311011SAndreas.Sandberg@ARM.com 17411011SAndreas.Sandberg@ARM.com // Service the request as a read or write depending on the 17511011SAndreas.Sandberg@ARM.com // wr bit in the control register. 17611011SAndreas.Sandberg@ARM.com Device &dev(*it_dev->second); 17711011SAndreas.Sandberg@ARM.com if (req.wr) { 17811011SAndreas.Sandberg@ARM.com DPRINTF(RVCTRL, "SCReg: Writing %#x (ctrlWr %#x)\n", 17911011SAndreas.Sandberg@ARM.com scData, req); 18011011SAndreas.Sandberg@ARM.com dev.write(scData); 18111011SAndreas.Sandberg@ARM.com 1829958Smatt.evans@arm.com } else { 18311011SAndreas.Sandberg@ARM.com scData = dev.read(); 18411011SAndreas.Sandberg@ARM.com DPRINTF(RVCTRL, "SCReg: Reading %#x (ctrlRd %#x)\n", 18511011SAndreas.Sandberg@ARM.com scData, req); 1869958Smatt.evans@arm.com } 1879958Smatt.evans@arm.com } break; 1889958Smatt.evans@arm.com case CfgStat: // Weird to write this 1897584SAli.Saidi@arm.com default: 1909958Smatt.evans@arm.com warn("Tried to write RVIO at offset %#x (data %#x) that doesn't exist\n", 1919958Smatt.evans@arm.com daddr, pkt->get<uint32_t>()); 1927584SAli.Saidi@arm.com break; 1937584SAli.Saidi@arm.com } 1947584SAli.Saidi@arm.com pkt->makeAtomicResponse(); 1957584SAli.Saidi@arm.com return pioDelay; 1967584SAli.Saidi@arm.com} 1977584SAli.Saidi@arm.com 1987584SAli.Saidi@arm.comvoid 19910905Sandreas.sandberg@arm.comRealViewCtrl::serialize(CheckpointOut &cp) const 2007584SAli.Saidi@arm.com{ 2018281SAli.Saidi@ARM.com SERIALIZE_SCALAR(flags); 2027584SAli.Saidi@arm.com} 2037584SAli.Saidi@arm.com 2047584SAli.Saidi@arm.comvoid 20510905Sandreas.sandberg@arm.comRealViewCtrl::unserialize(CheckpointIn &cp) 2067584SAli.Saidi@arm.com{ 2078281SAli.Saidi@ARM.com UNSERIALIZE_SCALAR(flags); 2087584SAli.Saidi@arm.com} 2097584SAli.Saidi@arm.com 21011011SAndreas.Sandberg@ARM.comvoid 21111011SAndreas.Sandberg@ARM.comRealViewCtrl::registerDevice(DeviceFunc func, uint8_t site, uint8_t pos, 21211011SAndreas.Sandberg@ARM.com uint8_t dcc, uint16_t dev, 21311011SAndreas.Sandberg@ARM.com Device *handler) 21411011SAndreas.Sandberg@ARM.com{ 21511011SAndreas.Sandberg@ARM.com CfgCtrlReg addr = 0; 21611011SAndreas.Sandberg@ARM.com addr.func = func; 21711011SAndreas.Sandberg@ARM.com addr.site = site; 21811011SAndreas.Sandberg@ARM.com addr.pos = pos; 21911011SAndreas.Sandberg@ARM.com addr.dcc = dcc; 22011011SAndreas.Sandberg@ARM.com addr.dev = dev; 22111011SAndreas.Sandberg@ARM.com 22211011SAndreas.Sandberg@ARM.com if (devices.find(addr) != devices.end()) { 22311011SAndreas.Sandberg@ARM.com fatal("Platform device dcc%d:site%d:pos%d:fn%d:dev%d " 22411011SAndreas.Sandberg@ARM.com "already registered.", 22511011SAndreas.Sandberg@ARM.com addr.dcc, addr.site, addr.pos, addr.func, addr.dev); 22611011SAndreas.Sandberg@ARM.com } 22711011SAndreas.Sandberg@ARM.com 22811011SAndreas.Sandberg@ARM.com devices[addr] = handler; 22911011SAndreas.Sandberg@ARM.com} 23011011SAndreas.Sandberg@ARM.com 23111011SAndreas.Sandberg@ARM.com 23211011SAndreas.Sandberg@ARM.comRealViewOsc::RealViewOsc(RealViewOscParams *p) 23311011SAndreas.Sandberg@ARM.com : ClockDomain(p, p->voltage_domain), 23411011SAndreas.Sandberg@ARM.com RealViewCtrl::Device(*p->parent, RealViewCtrl::FUNC_OSC, 23511011SAndreas.Sandberg@ARM.com p->site, p->position, p->dcc, p->device) 23611011SAndreas.Sandberg@ARM.com{ 23711011SAndreas.Sandberg@ARM.com if (SimClock::Float::s / p->freq > UINT32_MAX) { 23811011SAndreas.Sandberg@ARM.com fatal("Oscillator frequency out of range: %f\n", 23911011SAndreas.Sandberg@ARM.com SimClock::Float::s / p->freq / 1E6); 24011011SAndreas.Sandberg@ARM.com } 24111011SAndreas.Sandberg@ARM.com 24211011SAndreas.Sandberg@ARM.com _clockPeriod = p->freq; 24311011SAndreas.Sandberg@ARM.com} 24411011SAndreas.Sandberg@ARM.com 24511011SAndreas.Sandberg@ARM.comvoid 24611011SAndreas.Sandberg@ARM.comRealViewOsc::startup() 24711011SAndreas.Sandberg@ARM.com{ 24811011SAndreas.Sandberg@ARM.com // Tell dependent object to set their clock frequency 24911011SAndreas.Sandberg@ARM.com for (auto m : members) 25011011SAndreas.Sandberg@ARM.com m->updateClockPeriod(); 25111011SAndreas.Sandberg@ARM.com} 25211011SAndreas.Sandberg@ARM.com 25311011SAndreas.Sandberg@ARM.comvoid 25411011SAndreas.Sandberg@ARM.comRealViewOsc::serialize(CheckpointOut &cp) const 25511011SAndreas.Sandberg@ARM.com{ 25611011SAndreas.Sandberg@ARM.com SERIALIZE_SCALAR(_clockPeriod); 25711011SAndreas.Sandberg@ARM.com} 25811011SAndreas.Sandberg@ARM.com 25911011SAndreas.Sandberg@ARM.comvoid 26011011SAndreas.Sandberg@ARM.comRealViewOsc::unserialize(CheckpointIn &cp) 26111011SAndreas.Sandberg@ARM.com{ 26211011SAndreas.Sandberg@ARM.com UNSERIALIZE_SCALAR(_clockPeriod); 26311011SAndreas.Sandberg@ARM.com} 26411011SAndreas.Sandberg@ARM.com 26511011SAndreas.Sandberg@ARM.comvoid 26611011SAndreas.Sandberg@ARM.comRealViewOsc::clockPeriod(Tick clock_period) 26711011SAndreas.Sandberg@ARM.com{ 26811011SAndreas.Sandberg@ARM.com panic_if(clock_period == 0, "%s has a clock period of zero\n", name()); 26911011SAndreas.Sandberg@ARM.com 27011011SAndreas.Sandberg@ARM.com // Align all members to the current tick 27111011SAndreas.Sandberg@ARM.com for (auto m : members) 27211011SAndreas.Sandberg@ARM.com m->updateClockPeriod(); 27311011SAndreas.Sandberg@ARM.com 27411011SAndreas.Sandberg@ARM.com _clockPeriod = clock_period; 27511011SAndreas.Sandberg@ARM.com 27611011SAndreas.Sandberg@ARM.com // inform any derived clocks they need to updated their period 27711011SAndreas.Sandberg@ARM.com for (auto m : children) 27811011SAndreas.Sandberg@ARM.com m->updateClockPeriod(); 27911011SAndreas.Sandberg@ARM.com} 28011011SAndreas.Sandberg@ARM.com 28111011SAndreas.Sandberg@ARM.comuint32_t 28211011SAndreas.Sandberg@ARM.comRealViewOsc::read() const 28311011SAndreas.Sandberg@ARM.com{ 28411011SAndreas.Sandberg@ARM.com const uint32_t freq(SimClock::Float::s / _clockPeriod); 28511011SAndreas.Sandberg@ARM.com DPRINTF(RVCTRL, "Reading OSC frequency: %f MHz\n", freq / 1E6); 28611011SAndreas.Sandberg@ARM.com return freq; 28711011SAndreas.Sandberg@ARM.com} 28811011SAndreas.Sandberg@ARM.com 28911011SAndreas.Sandberg@ARM.comvoid 29011011SAndreas.Sandberg@ARM.comRealViewOsc::write(uint32_t freq) 29111011SAndreas.Sandberg@ARM.com{ 29211011SAndreas.Sandberg@ARM.com DPRINTF(RVCTRL, "Setting new OSC frequency: %f MHz\n", freq / 1E6); 29311011SAndreas.Sandberg@ARM.com clockPeriod(SimClock::Float::s / freq); 29411011SAndreas.Sandberg@ARM.com} 29511011SAndreas.Sandberg@ARM.com 29611011SAndreas.Sandberg@ARM.com 29711011SAndreas.Sandberg@ARM.com 2987584SAli.Saidi@arm.comRealViewCtrl * 2997584SAli.Saidi@arm.comRealViewCtrlParams::create() 3007584SAli.Saidi@arm.com{ 3017584SAli.Saidi@arm.com return new RealViewCtrl(this); 3027584SAli.Saidi@arm.com} 30311011SAndreas.Sandberg@ARM.com 30411011SAndreas.Sandberg@ARM.comRealViewOsc * 30511011SAndreas.Sandberg@ARM.comRealViewOscParams::create() 30611011SAndreas.Sandberg@ARM.com{ 30711011SAndreas.Sandberg@ARM.com return new RealViewOsc(this); 30811011SAndreas.Sandberg@ARM.com} 309