gem5  v20.1.0.0
pl011.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, 2015 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2005 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 #include "dev/arm/pl011.hh"
42 
43 #include "base/trace.hh"
44 #include "debug/Checkpoint.hh"
45 #include "debug/Uart.hh"
46 #include "dev/arm/amba_device.hh"
47 #include "dev/arm/base_gic.hh"
48 #include "mem/packet.hh"
49 #include "mem/packet_access.hh"
50 #include "params/Pl011.hh"
51 #include "sim/sim_exit.hh"
52 
53 Pl011::Pl011(const Pl011Params *p)
54  : Uart(p, 0x1000),
55  intEvent([this]{ generateInterrupt(); }, name()),
56  control(0x300), fbrd(0), ibrd(0), lcrh(0), ifls(0x12),
57  imsc(0), rawInt(0),
58  endOnEOT(p->end_on_eot), interrupt(p->interrupt->get()),
59  intDelay(p->int_delay)
60 {
61 }
62 
63 Tick
65 {
66  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
67 
68  Addr daddr = pkt->getAddr() - pioAddr;
69 
70  DPRINTF(Uart, " read register %#x size=%d\n", daddr, pkt->getSize());
71 
72  // use a temporary data since the uart registers are read/written with
73  // different size operations
74  //
75  uint32_t data = 0;
76 
77  switch(daddr) {
78  case UART_DR:
79  data = 0;
80  if (device->dataAvailable()) {
81  data = device->readData();
82  // Since we don't simulate a FIFO for incoming data, we
83  // assume it's empty and clear RXINTR and RTINTR.
85  if (device->dataAvailable()) {
86  DPRINTF(Uart, "Re-raising interrupt due to more data "
87  "after UART_DR read\n");
88  dataAvailable();
89  }
90  }
91  break;
92  case UART_RSR:
93  data = 0x0; // We never have errors
94  break;
95  case UART_FR:
96  data =
97  UART_FR_CTS | // Clear To Send
98  // Given we do not simulate a FIFO we are either empty or full.
100  UART_FR_TXFE; // TX FIFO empty
101 
102  DPRINTF(Uart,
103  "Reading FR register as %#x rawInt=0x%x "
104  "imsc=0x%x maskInt=0x%x\n",
105  data, rawInt, imsc, maskInt());
106  break;
107  case UART_CR:
108  data = control;
109  break;
110  case UART_IBRD:
111  data = ibrd;
112  break;
113  case UART_FBRD:
114  data = fbrd;
115  break;
116  case UART_LCRH:
117  data = lcrh;
118  break;
119  case UART_IFLS:
120  data = ifls;
121  break;
122  case UART_IMSC:
123  data = imsc;
124  break;
125  case UART_RIS:
126  data = rawInt;
127  DPRINTF(Uart, "Reading Raw Int status as 0x%x\n", rawInt);
128  break;
129  case UART_MIS:
130  DPRINTF(Uart, "Reading Masked Int status as 0x%x\n", maskInt());
131  data = maskInt();
132  break;
133  case UART_DMACR:
134  warn("PL011: DMA not supported\n");
135  data = 0x0; // DMA never enabled
136  break;
137  default:
138  if (readId(pkt, AMBA_ID, pioAddr)) {
139  // Hack for variable size accesses
140  data = pkt->getUintX(ByteOrder::little);
141  break;
142  }
143 
144  panic("Tried to read PL011 at offset %#x that doesn't exist\n", daddr);
145  break;
146  }
147 
148  switch(pkt->getSize()) {
149  case 1:
150  pkt->setLE<uint8_t>(data);
151  break;
152  case 2:
153  pkt->setLE<uint16_t>(data);
154  break;
155  case 4:
156  pkt->setLE<uint32_t>(data);
157  break;
158  default:
159  panic("Uart read size too big?\n");
160  break;
161  }
162 
163 
164  pkt->makeAtomicResponse();
165  return pioDelay;
166 }
167 
168 Tick
170 {
171 
172  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
173 
174  Addr daddr = pkt->getAddr() - pioAddr;
175 
176  DPRINTF(Uart, " write register %#x value %#x size=%d\n", daddr,
177  pkt->getLE<uint8_t>(), pkt->getSize());
178 
179  // use a temporary data since the uart registers are read/written with
180  // different size operations
181  //
182  uint32_t data = 0;
183 
184  switch(pkt->getSize()) {
185  case 1:
186  data = pkt->getLE<uint8_t>();
187  break;
188  case 2:
189  data = pkt->getLE<uint16_t>();
190  break;
191  case 4:
192  data = pkt->getLE<uint32_t>();
193  break;
194  default:
195  panic("Uart write size too big?\n");
196  break;
197  }
198 
199 
200  switch (daddr) {
201  case UART_DR:
202  if ((data & 0xFF) == 0x04 && endOnEOT)
203  exitSimLoop("UART received EOT", 0);
204 
205  device->writeData(data & 0xFF);
206  // We're supposed to clear TXINTR when this register is
207  // written to, however. since we're also infinitely fast, we
208  // need to immediately raise it again.
211  break;
212  case UART_ECR: // clears errors, ignore
213  break;
214  case UART_CR:
215  control = data;
216  break;
217  case UART_IBRD:
218  ibrd = data;
219  break;
220  case UART_FBRD:
221  fbrd = data;
222  break;
223  case UART_LCRH:
224  lcrh = data;
225  break;
226  case UART_IFLS:
227  ifls = data;
228  break;
229  case UART_IMSC:
230  DPRINTF(Uart, "Setting interrupt mask 0x%x\n", data);
232  break;
233 
234  case UART_ICR:
235  DPRINTF(Uart, "Clearing interrupts 0x%x\n", data);
237  if (device->dataAvailable()) {
238  DPRINTF(Uart, "Re-raising interrupt due to more data after "
239  "UART_ICR write\n");
240  dataAvailable();
241  }
242  break;
243  case UART_DMACR:
244  // DMA is not supported, so panic if anyome tries to enable it.
245  // Bits 0, 1, 2 enables DMA on RX, TX, ERR respectively, others res0.
246  if (data & 0x7) {
247  panic("Tried to enable DMA on PL011\n");
248  }
249  warn("PL011: DMA not supported\n");
250  break;
251  default:
252  panic("Tried to write PL011 at offset %#x that doesn't exist\n", daddr);
253  break;
254  }
255  pkt->makeAtomicResponse();
256  return pioDelay;
257 }
258 
259 void
261 {
262  /*@todo ignore the fifo, just say we have data now
263  * We might want to fix this, or we might not care */
264  DPRINTF(Uart, "Data available, scheduling interrupt\n");
266 }
267 
268 void
270 {
271  DPRINTF(Uart, "Generate Interrupt: imsc=0x%x rawInt=0x%x maskInt=0x%x\n",
272  imsc, rawInt, maskInt());
273 
274  if (maskInt()) {
275  interrupt->raise();
276  DPRINTF(Uart, " -- Generated\n");
277  }
278 }
279 
280 void
281 Pl011::setInterrupts(uint16_t ints, uint16_t mask)
282 {
283  const bool old_ints(!!maskInt());
284 
285  imsc = mask;
286  rawInt = ints;
287 
288  if (!old_ints && maskInt()) {
289  if (!intEvent.scheduled())
291  } else if (old_ints && !maskInt()) {
292  interrupt->clear();
293  }
294 }
295 
296 
297 
298 void
300 {
301  DPRINTF(Checkpoint, "Serializing Arm PL011\n");
307 
308  // Preserve backwards compatibility by giving these silly names.
309  paramOut(cp, "imsc_serial", imsc);
310  paramOut(cp, "rawInt_serial", rawInt);
311 }
312 
313 void
315 {
316  DPRINTF(Checkpoint, "Unserializing Arm PL011\n");
317 
323 
324  // Preserve backwards compatibility by giving these silly names.
325  paramIn(cp, "imsc_serial", imsc);
326  paramIn(cp, "rawInt_serial", rawInt);
327 }
328 
329 Pl011 *
330 Pl011Params::create()
331 {
332  return new Pl011(this);
333 }
Pl011::ifls
uint16_t ifls
interrupt fifo level register.
Definition: pl011.hh:165
Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:460
Pl011::UART_RTINTR
static const uint16_t UART_RTINTR
Definition: pl011.hh:143
Packet::makeAtomicResponse
void makeAtomicResponse()
Definition: packet.hh:1016
BasicPioDevice::pioAddr
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:154
warn
#define warn(...)
Definition: logging.hh:239
Pl011::UART_FBRD
static const int UART_FBRD
Definition: pl011.hh:127
data
const char data[]
Definition: circlebuf.test.cc:42
Pl011::AMBA_ID
static const uint64_t AMBA_ID
Definition: pl011.hh:116
Pl011::ibrd
uint16_t ibrd
integer baud rate divisor.
Definition: pl011.hh:157
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:797
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
Pl011::setInterruptMask
void setInterruptMask(uint16_t mask)
Convenience function to update the interrupt mask.
Definition: pl011.hh:93
Pl011::UART_RIS
static const int UART_RIS
Definition: pl011.hh:132
Pl011::UART_IFLS
static const int UART_IFLS
Definition: pl011.hh:130
ArmInterruptPin::clear
virtual void clear()=0
Clear a signalled interrupt.
amba_device.hh
Pl011::lcrh
uint16_t lcrh
Line control register.
Definition: pl011.hh:161
base_gic.hh
ArmInterruptPin::raise
virtual void raise()=0
Signal an interrupt.
Pl011::UART_FR_CTS
static const int UART_FR_CTS
Definition: pl011.hh:121
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
Pl011::UART_IBRD
static const int UART_IBRD
Definition: pl011.hh:126
Packet::getSize
unsigned getSize() const
Definition: packet.hh:764
Pl011::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: pl011.cc:314
Pl011::maskInt
uint16_t maskInt() const
Masked interrupt status register.
Definition: pl011.hh:110
Pl011::setInterrupts
void setInterrupts(uint16_t ints, uint16_t mask)
Assign new interrupt values and update interrupt signals.
Definition: pl011.cc:281
sim_exit.hh
Pl011::intDelay
const Tick intDelay
Delay before interrupting.
Definition: pl011.hh:180
paramOut
void paramOut(CheckpointOut &cp, const string &name, ExtMachInst const &machInst)
Definition: types.cc:38
packet.hh
Pl011::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: pl011.cc:299
Pl011::UART_IMSC
static const int UART_IMSC
Definition: pl011.hh:131
Pl011::UART_ECR
static const int UART_ECR
Definition: pl011.hh:119
Pl011::UART_DR
static const int UART_DR
Definition: pl011.hh:117
cp
Definition: cprintf.cc:40
Pl011::rawInt
uint16_t rawInt
raw interrupt status register
Definition: pl011.hh:171
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1005
Uart
Definition: uart.hh:46
Pl011::UART_FR_RXFE
static const int UART_FR_RXFE
Definition: pl011.hh:122
Pl011::clearInterrupts
void clearInterrupts(uint16_t ints)
Convenience function to clear interrupts.
Definition: pl011.hh:107
Pl011::UART_FR
static const int UART_FR
Definition: pl011.hh:120
Packet::getUintX
uint64_t getUintX(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness and zero-extended to 64 bits.
Definition: packet.cc:350
Pl011::UART_ICR
static const int UART_ICR
Definition: pl011.hh:134
SerialDevice::dataAvailable
virtual bool dataAvailable() const =0
Check if there is pending data from the serial device.
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
Uart::device
SerialDevice * device
Definition: uart.hh:51
Pl011::UART_RXINTR
static const uint16_t UART_RXINTR
Definition: pl011.hh:141
exitSimLoop
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition: sim_events.cc:88
AmbaDevice::readId
bool readId(PacketPtr pkt, uint64_t amba_id, Addr pio_addr)
Definition: amba_device.cc:72
BasicPioDevice::pioSize
Addr pioSize
Size that the device's address range.
Definition: io_device.hh:157
Pl011::imsc
uint16_t imsc
interrupt mask register.
Definition: pl011.hh:168
Pl011::UART_TXINTR
static const uint16_t UART_TXINTR
Definition: pl011.hh:142
SerialDevice::readData
virtual uint8_t readData()=0
Read a character from the device.
Pl011::raiseInterrupts
void raiseInterrupts(uint16_t ints)
Convenience function to raise a new interrupt.
Definition: pl011.hh:100
Pl011::control
uint16_t control
Definition: pl011.hh:149
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
Pl011::interrupt
ArmInterruptPin *const interrupt
Definition: pl011.hh:177
pl011.hh
name
const std::string & name()
Definition: trace.cc:50
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:790
packet_access.hh
Packet::getLE
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Definition: packet_access.hh:75
Pl011::UART_FR_RXFF
static const int UART_FR_RXFF
Definition: pl011.hh:124
Pl011::fbrd
uint16_t fbrd
fractional baud rate divisor.
Definition: pl011.hh:153
Pl011::dataAvailable
void dataAvailable() override
Inform the uart that there is data available.
Definition: pl011.cc:260
Pl011::write
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: pl011.cc:169
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
Pl011::UART_RSR
static const int UART_RSR
Definition: pl011.hh:118
paramIn
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
Definition: types.cc:69
Pl011::generateInterrupt
void generateInterrupt()
Function to generate interrupt.
Definition: pl011.cc:269
BasicPioDevice::pioDelay
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:160
Packet::setLE
void setLE(T v)
Set the value in the data pointer to v as little endian.
Definition: packet_access.hh:105
CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:63
SerialDevice::writeData
virtual void writeData(uint8_t c)=0
Transmit a character from the host interface to the device.
Pl011::Pl011
Pl011(const Pl011Params *p)
Definition: pl011.cc:53
Pl011::endOnEOT
const bool endOnEOT
Should the simulation end on an EOT.
Definition: pl011.hh:175
trace.hh
Pl011::UART_CR
static const int UART_CR
Definition: pl011.hh:129
Pl011::UART_LCRH
static const int UART_LCRH
Definition: pl011.hh:128
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
Pl011::intEvent
EventFunctionWrapper intEvent
Wrapper to create an event out of the thing.
Definition: pl011.hh:113
CheckpointIn
Definition: serialize.hh:67
Pl011::UART_FR_TXFE
static const int UART_FR_TXFE
Definition: pl011.hh:125
Pl011
Definition: pl011.hh:55
Pl011::UART_DMACR
static const int UART_DMACR
Definition: pl011.hh:135
Pl011::read
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: pl011.cc:64
ArmISA::mask
Bitfield< 28, 24 > mask
Definition: miscregs_types.hh:711
Pl011::UART_MIS
static const int UART_MIS
Definition: pl011.hh:133
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45

Generated on Wed Sep 30 2020 14:02:10 for gem5 by doxygen 1.8.17