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

Generated on Fri Jun 9 2017 13:03:45 for gem5 by doxygen 1.8.6