RAMComponent.h Source File

Back to the index.

RAMComponent.h
Go to the documentation of this file.
1 #ifndef RAMCOMPONENT_H
2 #define RAMCOMPONENT_H
3 
4 /*
5  * Copyright (C) 2008-2010 Anders Gavare. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  * derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 // COMPONENT(ram)
32 
33 
34 #include "AddressDataBus.h"
35 #include "MemoryMappedComponent.h"
36 
37 #include "UnitTest.h"
38 
39 #include <string.h>
40 #include <iomanip>
41 
42 
43 /**
44  * \brief A Random Access Memory Component.
45  *
46  * RAM is emulated by allocating large blocks of host memory (e.g. 4 MB
47  * per block), and simply forwarding all read and write requests to those
48  * memory blocks.
49  *
50  * The host memory blocks are not allocated until they are actually written to.
51  * Reading from uninitialized/unwritten emulated memory returns zeros. This
52  * allows e.g. an emulated machine to have, say, 1 TB RAM, even if the host
53  * only has 1 GB, as long as the emulated guest OS does not touch all of the
54  * emulated memory.
55  *
56  * In addition, host memory blocks are allocated as anonymous zero-filled
57  * memory using mmap(), so the blocks do not necessariliy use up host RAM
58  * unless they are touched.
59  *
60  * Note 1: This class does <i>not</i> handle unaligned access. It is up to the
61  * caller to make sure that e.g. ReadData(uint64_t&, Endianness) is only
62  * called when the selected address is 64-bit aligned.
63  *
64  * (The reason for this is that different emulated components want different
65  * semantics for unaligned access. For example, an x86 processor will
66  * transparently allow unaligned access, most RISC processors will cause
67  * an unaligned address exception, and some old ARM processors may even simply
68  * ignore the lowest bits of the address!)
69  *
70  * Note 2: The RAM component's size and base offset are defined by state
71  * variables in the MemoryMappedComponent base class.
72  */
74  : public MemoryMappedComponent
75  , public AddressDataBus
76  , public UnitTestable
77 {
78 public:
79  /**
80  * \brief Constructs a RAMComponent.
81  *
82  * @param visibleClassName The visible class name. Defaults to
83  * "ram". Useful alternatives may be "rom" or
84  * "vram" for video ram.
85  */
86  RAMComponent(const string& visibleClassName = "ram");
87 
88  virtual ~RAMComponent();
89 
90  /**
91  * \brief Creates a RAMComponent.
92  */
94 
95  virtual void ResetState();
96 
97  /**
98  * \brief Get attribute information about the RAMComponent class.
99  *
100  * @param attributeName The attribute name.
101  * @return A string representing the attribute value.
102  */
103  static string GetAttribute(const string& attributeName);
104 
105  virtual void GetMethodNames(vector<string>& names) const;
106 
107  virtual bool MethodMayBeReexecutedWithoutArgs(const string& methodName) const;
108 
109  virtual void ExecuteMethod(GXemul* gxemul,
110  const string& methodName,
111  const vector<string>& arguments);
112 
113  /**
114  * \brief Returns the component's AddressDataBus interface.
115  *
116  * @return A pointer to an AddressDataBus.
117  */
118  virtual AddressDataBus* AsAddressDataBus();
119 
120  /* Implementation of AddressDataBus: */
121  virtual void AddressSelect(uint64_t address);
122  virtual bool ReadData(uint8_t& data, Endianness endianness);
123  virtual bool ReadData(uint16_t& data, Endianness endianness);
124  virtual bool ReadData(uint32_t& data, Endianness endianness);
125  virtual bool ReadData(uint64_t& data, Endianness endianness);
126  virtual bool WriteData(const uint8_t& data, Endianness endianness);
127  virtual bool WriteData(const uint16_t& data, Endianness endianness);
128  virtual bool WriteData(const uint32_t& data, Endianness endianness);
129  virtual bool WriteData(const uint64_t& data, Endianness endianness);
130 
131 
132  /********************************************************************/
133 
134  static void RunUnitTests(int& nSucceeded, int& nFailures);
135 
136 private:
137  void ReleaseAllBlocks();
138 
139  void* AllocateBlock();
140 
141  class RAMDataHandler : public CustomStateVariableHandler
142  {
143  public:
144  RAMDataHandler(RAMComponent& ram)
145  : m_ram(ram)
146  {
147  }
148 
149  virtual ~RAMDataHandler()
150  {
151  }
152 
153  virtual void Serialize(ostream& ss) const
154  {
155  for (size_t i=0; i<m_ram.m_memoryBlocks.size(); ++i)
156  if (m_ram.m_memoryBlocks[i] != NULL)
157  SerializeMemoryBlock(ss, i, m_ram.m_memoryBlocks[i]);
158 
159  // End of data.
160  ss << ".";
161  }
162 
163  virtual bool Deserialize(const string& value)
164  {
165  m_ram.ReleaseAllBlocks();
166 
167  size_t p = 0;
168  size_t len = value.length();
169  const char *cstr = value.c_str();
170 
171  while (p < len) {
172  if (cstr[p] == '.') {
173  p++;
174  continue;
175  }
176 
177  // xxxxxxxxxxxxxxxx:yyyyyyyy:data.
178  // where x = address in the RAM component,
179  // y = length of data in bytes.
180  // data = hex dump.
181 
182  // Some margin... :) Yuck. This is ugly.
183  if (p + 40 > len) {
184  std::cerr << "deserialize ram: internal error\n";
185  throw std::exception();
186  }
187 
188  char s1[17];
189  char s2[9];
190  memcpy(s1, cstr + p, 16);
191  p += 17;
192  memcpy(s2, cstr + p, 8);
193  p += 9;
194  s1[16] = 0;
195  s2[8] = 0;
196  stringstream ss1;
197  ss1.flags(std::ios::hex);
198  ss1 << s1;
199  uint64_t addr;
200  ss1 >> addr;
201  stringstream ss2;
202  ss2.flags(std::ios::hex);
203  ss2 << s2;
204  uint32_t datalen;
205  ss2 >> datalen;
206  // p points to data.
207  if (p + 2*datalen < len) {
208  for (size_t i=0; i<datalen; i++) {
209  char c1 = cstr[p++];
210  char c2 = cstr[p++];
211 
212  if (c1 >= 'a' && c1 <= 'f')
213  c1 = (c1-'a') + 10;
214  else
215  c1 -= '0';
216 
217  if (c2 >= 'a' && c2 <= 'f')
218  c2 = (c2-'a') + 10;
219  else
220  c2 -= '0';
221 
222  uint8_t b = c1*16 + c2;
223 
224  m_ram.AddressSelect(i + addr);
225  m_ram.WriteData(b, BigEndian);
226  }
227  } else {
228  std::cerr << "deserialize ram: internal error\n";
229  throw std::exception();
230  }
231 
232  if (cstr[p] != '.') {
233  std::cerr << "deserialize ram: internal error: no dot\n";
234  throw std::exception();
235  }
236  }
237 
238  return true;
239  }
240 
241  virtual void CopyValueFrom(CustomStateVariableHandler* other)
242  {
243  // NOTE/TODO: Not space efficient, but works for now.
244 
245  stringstream ss;
246  other->Serialize(ss);
247  Deserialize(ss.str());
248  }
249 
250  private:
251  void SerializeMemoryBlock(ostream& ss, size_t blockNr, void *block) const
252  {
253  const size_t rowSize = 1024;
254  uint64_t addr = blockNr << m_ram.m_blockSizeShift;
255  uint64_t addrWithinBlock = 0;
256 
257  while (addrWithinBlock < m_ram.m_blockSize) {
258  uint8_t *data = (uint8_t*)block + addrWithinBlock;
259 
260  bool allZeroes = true;
261  for (size_t i=0; i<rowSize; i++)
262  if (data[i] != 0x00) {
263  allZeroes = false;
264  break;
265  }
266 
267  // Only output the row if it contains something
268  // which is non-zero.
269  if (!allZeroes)
270  SerializeRow(ss, addr, data, rowSize);
271 
272  addrWithinBlock += rowSize;
273  addr += rowSize;
274  }
275  }
276 
277  // NOTE/TODO: Not space efficient, but works for now.
278  void SerializeRow(ostream& ss, uint64_t addr, uint8_t* data, size_t rowSize) const
279  {
280  ss.flags(std::ios::hex);
281  ss << std::setw(16) << std::setfill('0') << addr << ":";
282  ss << std::setw(8) << std::setfill('0') << rowSize << ":";
283 
284  for (size_t i=0; i<rowSize; i++)
285  ss << std::setw(2) << std::setfill('0') << (int)data[i];
286 
287  ss << ".";
288  }
289 
290  private:
291  RAMComponent& m_ram;
292  };
293 
294 private:
295  const size_t m_blockSizeShift;// Host block size, in bit shift steps
296  const size_t m_blockSize; // Host block size, in bytes
297 
298  RAMDataHandler m_dataHandler;
299 
300  // State:
301  typedef vector<void *> BlockNrToMemoryBlockVector;
302  BlockNrToMemoryBlockVector m_memoryBlocks;
303  bool m_writeProtected;
304  uint64_t m_lastDumpAddr;
305 
306  // Cached/runtime state:
307  uint64_t m_addressSelect; // For AddressDataBus read/write
308  void * m_selectedHostMemoryBlock;
309  size_t m_selectedOffsetWithinBlock;
310 };
311 
312 
313 #endif // RAMCOMPONENT_H
data
u_short data
Definition: siireg.h:79
GXemul
The main emulator class.
Definition: GXemul.h:55
MemoryMappedComponent
A base-class for memory-mapped components.
Definition: MemoryMappedComponent.h:54
Component::Deserialize
static refcount_ptr< Component > Deserialize(ostream &messages, const string &str, size_t &pos)
Deserializes a string into a component tree.
Definition: Component.cc:1130
RAMComponent::AsAddressDataBus
virtual AddressDataBus * AsAddressDataBus()
Returns the component's AddressDataBus interface.
Definition: RAMComponent.cc:197
RAMComponent::RunUnitTests
static void RunUnitTests(int &nSucceeded, int &nFailures)
RAMComponent::RAMComponent
RAMComponent(const string &visibleClassName="ram")
Constructs a RAMComponent.
Definition: RAMComponent.cc:36
RAMComponent::AddressSelect
virtual void AddressSelect(uint64_t address)
Place an address on the bus.
Definition: RAMComponent.cc:203
refcount_ptr< Component >
RAMComponent::ResetState
virtual void ResetState()
Resets the state variables of this component.
Definition: RAMComponent.cc:85
RAMComponent::ExecuteMethod
virtual void ExecuteMethod(GXemul *gxemul, const string &methodName, const vector< string > &arguments)
Executes a method on the component.
Definition: RAMComponent.cc:111
RAMComponent::WriteData
virtual bool WriteData(const uint8_t &data, Endianness endianness)
Writes 8-bit data to the currently selected address.
Definition: RAMComponent.cc:309
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
RAMComponent::MethodMayBeReexecutedWithoutArgs
virtual bool MethodMayBeReexecutedWithoutArgs(const string &methodName) const
Returns whether a method name may be re-executed without args.
Definition: RAMComponent.cc:101
RAMComponent::~RAMComponent
virtual ~RAMComponent()
Definition: RAMComponent.cc:53
c1
vmrs fpscr vmrs mvfr1 vmrs fpexc fmrx fpinst fmrx fpinst2 c1
Definition: armreg.h:768
RAMComponent::GetAttribute
static string GetAttribute(const string &attributeName)
Get attribute information about the RAMComponent class.
Definition: RAMComponent.cc:76
Endianness
Endianness
Definition: misc.h:157
UnitTest.h
RAMComponent::GetMethodNames
virtual void GetMethodNames(vector< string > &names) const
Retrieves a component's implemented method names.
Definition: RAMComponent.cc:91
UnitTestable
Base class for unit testable classes.
Definition: UnitTest.h:75
MemoryMappedComponent.h
AddressDataBus
An interface for implementing components that read/write data via an address bus.
Definition: AddressDataBus.h:45
c2
vmrs fpscr vmrs mvfr1 vmrs fpexc fmrx fpinst fmrx fpinst2 c2
Definition: armreg.h:774
Component::Serialize
void Serialize(ostream &ss, SerializationContext &context) const
Serializes the Component into a string stream.
Definition: Component.cc:1070
AddressDataBus.h
CustomStateVariableHandler::Serialize
virtual void Serialize(ostream &ss) const =0
CustomStateVariableHandler
Definition: StateVariable.h:46
BigEndian
@ BigEndian
Definition: misc.h:158
RAMComponent::ReadData
virtual bool ReadData(uint8_t &data, Endianness endianness)
Reads 8-bit data from the currently selected address.
Definition: RAMComponent.cc:240
RAMComponent
A Random Access Memory Component.
Definition: RAMComponent.h:77
ComponentCreateArgs
Definition: Component.h:49
RAMComponent::Create
static refcount_ptr< Component > Create(const ComponentCreateArgs &args)
Creates a RAMComponent.
Definition: RAMComponent.cc:70

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18