gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  * Authors: Ali Saidi
41  * Andreas Sandberg
42  */
43 
44 #include "dev/arm/pl011.hh"
45 
46 #include "base/trace.hh"
47 #include "debug/Checkpoint.hh"
48 #include "debug/Uart.hh"
49 #include "dev/arm/amba_device.hh"
50 #include "dev/arm/base_gic.hh"
51 #include "mem/packet.hh"
52 #include "mem/packet_access.hh"
53 #include "params/Pl011.hh"
54 #include "sim/sim_exit.hh"
55 
56 Pl011::Pl011(const Pl011Params *p)
57  : Uart(p, 0x1000),
58  intEvent([this]{ generateInterrupt(); }, name()),
59  control(0x300), fbrd(0), ibrd(0), lcrh(0), ifls(0x12),
60  imsc(0), rawInt(0),
61  gic(p->gic), endOnEOT(p->end_on_eot), intNum(p->int_num),
62  intDelay(p->int_delay)
63 {
64 }
65 
66 Tick
68 {
69  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
70 
71  Addr daddr = pkt->getAddr() - pioAddr;
72 
73  DPRINTF(Uart, " read register %#x size=%d\n", daddr, pkt->getSize());
74 
75  // use a temporary data since the uart registers are read/written with
76  // different size operations
77  //
78  uint32_t data = 0;
79 
80  switch(daddr) {
81  case UART_DR:
82  data = 0;
83  if (device->dataAvailable()) {
84  data = device->readData();
85  // Since we don't simulate a FIFO for incoming data, we
86  // assume it's empty and clear RXINTR and RTINTR.
88  if (device->dataAvailable()) {
89  DPRINTF(Uart, "Re-raising interrupt due to more data "
90  "after UART_DR read\n");
91  dataAvailable();
92  }
93  }
94  break;
95  case UART_RSR:
96  data = 0x0; // We never have errors
97  break;
98  case UART_FR:
99  data =
100  UART_FR_CTS | // Clear To Send
101  // Given we do not simulate a FIFO we are either empty or full.
103  UART_FR_TXFE; // TX FIFO empty
104 
105  DPRINTF(Uart,
106  "Reading FR register as %#x rawInt=0x%x "
107  "imsc=0x%x maskInt=0x%x\n",
108  data, rawInt, imsc, maskInt());
109  break;
110  case UART_CR:
111  data = control;
112  break;
113  case UART_IBRD:
114  data = ibrd;
115  break;
116  case UART_FBRD:
117  data = fbrd;
118  break;
119  case UART_LCRH:
120  data = lcrh;
121  break;
122  case UART_IFLS:
123  data = ifls;
124  break;
125  case UART_IMSC:
126  data = imsc;
127  break;
128  case UART_RIS:
129  data = rawInt;
130  DPRINTF(Uart, "Reading Raw Int status as 0x%x\n", rawInt);
131  break;
132  case UART_MIS:
133  DPRINTF(Uart, "Reading Masked Int status as 0x%x\n", maskInt());
134  data = maskInt();
135  break;
136  case UART_DMACR:
137  warn("PL011: DMA not supported\n");
138  data = 0x0; // DMA never enabled
139  break;
140  default:
141  if (readId(pkt, AMBA_ID, pioAddr)) {
142  // Hack for variable size accesses
143  data = pkt->getLE<uint32_t>();
144  break;
145  }
146 
147  panic("Tried to read PL011 at offset %#x that doesn't exist\n", daddr);
148  break;
149  }
150 
151  switch(pkt->getSize()) {
152  case 1:
153  pkt->setLE<uint8_t>(data);
154  break;
155  case 2:
156  pkt->setLE<uint16_t>(data);
157  break;
158  case 4:
159  pkt->setLE<uint32_t>(data);
160  break;
161  default:
162  panic("Uart read size too big?\n");
163  break;
164  }
165 
166 
167  pkt->makeAtomicResponse();
168  return pioDelay;
169 }
170 
171 Tick
173 {
174 
175  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
176 
177  Addr daddr = pkt->getAddr() - pioAddr;
178 
179  DPRINTF(Uart, " write register %#x value %#x size=%d\n", daddr,
180  pkt->getLE<uint8_t>(), pkt->getSize());
181 
182  // use a temporary data since the uart registers are read/written with
183  // different size operations
184  //
185  uint32_t data = 0;
186 
187  switch(pkt->getSize()) {
188  case 1:
189  data = pkt->getLE<uint8_t>();
190  break;
191  case 2:
192  data = pkt->getLE<uint16_t>();
193  break;
194  case 4:
195  data = pkt->getLE<uint32_t>();
196  break;
197  default:
198  panic("Uart write size too big?\n");
199  break;
200  }
201 
202 
203  switch (daddr) {
204  case UART_DR:
205  if ((data & 0xFF) == 0x04 && endOnEOT)
206  exitSimLoop("UART received EOT", 0);
207 
208  device->writeData(data & 0xFF);
209  // We're supposed to clear TXINTR when this register is
210  // written to, however. since we're also infinitely fast, we
211  // need to immediately raise it again.
214  break;
215  case UART_ECR: // clears errors, ignore
216  break;
217  case UART_CR:
218  control = data;
219  break;
220  case UART_IBRD:
221  ibrd = data;
222  break;
223  case UART_FBRD:
224  fbrd = data;
225  break;
226  case UART_LCRH:
227  lcrh = data;
228  break;
229  case UART_IFLS:
230  ifls = data;
231  break;
232  case UART_IMSC:
233  DPRINTF(Uart, "Setting interrupt mask 0x%x\n", data);
234  setInterruptMask(data);
235  break;
236 
237  case UART_ICR:
238  DPRINTF(Uart, "Clearing interrupts 0x%x\n", data);
239  clearInterrupts(data);
240  if (device->dataAvailable()) {
241  DPRINTF(Uart, "Re-raising interrupt due to more data after "
242  "UART_ICR write\n");
243  dataAvailable();
244  }
245  break;
246  case UART_DMACR:
247  // DMA is not supported, so panic if anyome tries to enable it.
248  // Bits 0, 1, 2 enables DMA on RX, TX, ERR respectively, others res0.
249  if (data & 0x7) {
250  panic("Tried to enable DMA on PL011\n");
251  }
252  warn("PL011: DMA not supported\n");
253  break;
254  default:
255  panic("Tried to write PL011 at offset %#x that doesn't exist\n", daddr);
256  break;
257  }
258  pkt->makeAtomicResponse();
259  return pioDelay;
260 }
261 
262 void
264 {
265  /*@todo ignore the fifo, just say we have data now
266  * We might want to fix this, or we might not care */
267  DPRINTF(Uart, "Data available, scheduling interrupt\n");
269 }
270 
271 void
273 {
274  DPRINTF(Uart, "Generate Interrupt: imsc=0x%x rawInt=0x%x maskInt=0x%x\n",
275  imsc, rawInt, maskInt());
276 
277  if (maskInt()) {
278  gic->sendInt(intNum);
279  DPRINTF(Uart, " -- Generated\n");
280  }
281 }
282 
283 void
284 Pl011::setInterrupts(uint16_t ints, uint16_t mask)
285 {
286  const bool old_ints(!!maskInt());
287 
288  imsc = mask;
289  rawInt = ints;
290 
291  if (!old_ints && maskInt()) {
292  if (!intEvent.scheduled())
294  } else if (old_ints && !maskInt()) {
295  gic->clearInt(intNum);
296  }
297 }
298 
299 
300 
301 void
303 {
304  DPRINTF(Checkpoint, "Serializing Arm PL011\n");
310 
311  // Preserve backwards compatibility by giving these silly names.
312  paramOut(cp, "imsc_serial", imsc);
313  paramOut(cp, "rawInt_serial", rawInt);
314 }
315 
316 void
318 {
319  DPRINTF(Checkpoint, "Unserializing Arm PL011\n");
320 
326 
327  // Preserve backwards compatibility by giving these silly names.
328  paramIn(cp, "imsc_serial", imsc);
329  paramIn(cp, "rawInt_serial", rawInt);
330 }
331 
332 Pl011 *
333 Pl011Params::create()
334 {
335  return new Pl011(this);
336 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:229
static const int UART_IFLS
Definition: pl011.hh:133
static const int UART_FBRD
Definition: pl011.hh:130
static const int UART_FR_TXFE
Definition: pl011.hh:128
uint16_t ibrd
integer baud rate divisor.
Definition: pl011.hh:160
static const int UART_RIS
Definition: pl011.hh:135
virtual void clearInt(uint32_t num)=0
Clear an interrupt from a device that is connected to the GIC.
uint16_t lcrh
Line control register.
Definition: pl011.hh:164
virtual uint8_t readData()=0
Read a character from the device.
static const int UART_IBRD
Definition: pl011.hh:129
static const uint16_t UART_RTINTR
Definition: pl011.hh:146
uint16_t ifls
interrupt fifo level register.
Definition: pl011.hh:168
static const int UART_FR_CTS
Definition: pl011.hh:124
static const int UART_IMSC
Definition: pl011.hh:134
void setInterruptMask(uint16_t mask)
Convenience function to update the interrupt mask.
Definition: pl011.hh:96
static const uint64_t AMBA_ID
Definition: pl011.hh:119
Definition: cprintf.cc:42
static const int UART_FR_RXFE
Definition: pl011.hh:125
const int intNum
Interrupt number to generate.
Definition: pl011.hh:184
void setLE(T v)
Set the value in the data pointer to v as little endian.
SerialDevice * device
Definition: uart.hh:53
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: pl011.cc:317
virtual void writeData(uint8_t c)=0
Transmit a character from the host interface to the device.
void clearInterrupts(uint16_t ints)
Convenience function to clear interrupts.
Definition: pl011.hh:110
unsigned getSize() const
Definition: packet.hh:736
static const uint16_t UART_RXINTR
Definition: pl011.hh:144
uint16_t maskInt() const
Masked interrupt status register.
Definition: pl011.hh:113
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:645
static const int UART_ICR
Definition: pl011.hh:137
Tick curTick()
The current simulated tick.
Definition: core.hh:47
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:385
void setInterrupts(uint16_t ints, uint16_t mask)
Assign new interrupt values and update interrupt signals.
Definition: pl011.cc:284
Addr pioSize
Size that the device&#39;s address range.
Definition: io_device.hh:160
const Tick intDelay
Delay before interrupting.
Definition: pl011.hh:187
This is a base class for AMBA devices that have to respond to Device and Implementer ID calls...
virtual void sendInt(uint32_t num)=0
Post an interrupt from a device that is connected to the GIC.
Definition: pl011.hh:58
void makeAtomicResponse()
Definition: packet.hh:949
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: pl011.cc:302
uint64_t Tick
Tick count type.
Definition: types.hh:63
uint16_t rawInt
raw interrupt status register
Definition: pl011.hh:174
uint16_t control
Definition: pl011.hh:152
static const int UART_ECR
Definition: pl011.hh:122
void paramOut(CheckpointOut &cp, const string &name, ExtMachInst const &machInst)
Definition: types.cc:40
void raiseInterrupts(uint16_t ints)
Convenience function to raise a new interrupt.
Definition: pl011.hh:103
static const int UART_DR
Definition: pl011.hh:120
static const int UART_FR
Definition: pl011.hh:123
Addr getAddr() const
Definition: packet.hh:726
Implementiation of a PL011 UART.
BaseGic *const gic
Gic to use for interrupting.
Definition: pl011.hh:178
bool readId(PacketPtr pkt, uint64_t amba_id, Addr pio_addr)
Definition: amba_device.cc:74
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
virtual const std::string name() const
Definition: sim_object.hh:120
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:643
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:90
Base class for ARM GIC implementations.
static const uint16_t UART_TXINTR
Definition: pl011.hh:145
Pl011(const Pl011Params *p)
Definition: pl011.cc:56
Declaration of the Packet class.
uint16_t imsc
interrupt mask register.
Definition: pl011.hh:171
std::ostream CheckpointOut
Definition: serialize.hh:68
void generateInterrupt()
Function to generate interrupt.
Definition: pl011.cc:272
EventFunctionWrapper intEvent
Wrapper to create an event out of the thing.
Definition: pl011.hh:116
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:163
void schedule(Event &event, Tick when)
Definition: eventq.hh:744
static const int UART_FR_RXFF
Definition: pl011.hh:127
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
Definition: types.cc:71
static const int UART_MIS
Definition: pl011.hh:136
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: pl011.cc:172
void dataAvailable() override
Inform the uart that there is data available.
Definition: pl011.cc:263
Bitfield< 3, 0 > mask
Definition: types.hh:64
static const int UART_RSR
Definition: pl011.hh:121
static const int UART_DMACR
Definition: pl011.hh:138
#define warn(...)
Definition: logging.hh:212
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: pl011.cc:67
uint16_t fbrd
fractional baud rate divisor.
Definition: pl011.hh:156
Definition: uart.hh:48
Bitfield< 0 > p
const bool endOnEOT
Should the simulation end on an EOT.
Definition: pl011.hh:181
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:157
const char data[]
virtual bool dataAvailable() const =0
Check if there is pending data from the serial device.
static const int UART_CR
Definition: pl011.hh:132
static const int UART_LCRH
Definition: pl011.hh:131

Generated on Fri Feb 28 2020 16:27:00 for gem5 by doxygen 1.8.13