38 , m_blockSizeShift(22)
39 , m_blockSize(1 << m_blockSizeShift)
40 , m_dataHandler(*this)
41 , m_writeProtected(false)
44 , m_selectedHostMemoryBlock(NULL)
45 , m_selectedOffsetWithinBlock(0)
59 void RAMComponent::ReleaseAllBlocks()
61 for (
size_t i=0; i<m_memoryBlocks.size(); ++i) {
62 if (m_memoryBlocks[i] != NULL) {
63 munmap(m_memoryBlocks[i], m_blockSize);
64 m_memoryBlocks[i] = NULL;
78 if (attributeName ==
"stable")
81 if (attributeName ==
"description")
82 return "A generic RAM component.";
97 names.push_back(
"dump");
106 if (methodName ==
"dump")
115 const vector<string>& arguments)
117 if (methodName ==
"dump") {
118 uint64_t vaddr = m_lastDumpAddr;
120 if (arguments.size() > 1) {
125 if (arguments.size() == 1) {
131 ss.flags(std::ios::hex);
135 const int nRows = 16;
136 for (
int i=0; i<nRows; i++) {
137 const size_t len = 16;
138 unsigned char data[len];
142 ss.flags(std::ios::hex);
144 if (vaddr > 0xffffffff)
149 ss << std::setfill(
'0') << vaddr;
152 for (k=0; k<len; ++k) {
159 for (k=0; k<len; ++k) {
163 ss << std::setw(2) << std::setfill(
'0');
172 for (k=0; k<len; ++k) {
174 s[0] = data[k] >= 32 && data[k] < 127? data[k] :
'.';
190 m_lastDumpAddr = vaddr;
208 m_addressSelect = address;
210 uint64_t blockNr = address >> m_blockSizeShift;
212 if (blockNr+1 > m_memoryBlocks.size())
213 m_selectedHostMemoryBlock = NULL;
215 m_selectedHostMemoryBlock = m_memoryBlocks[blockNr];
217 m_selectedOffsetWithinBlock = address & (m_blockSize-1);
221 void* RAMComponent::AllocateBlock()
223 void * p = mmap(NULL, m_blockSize, PROT_WRITE | PROT_READ,
224 MAP_ANON | MAP_PRIVATE, -1, 0);
226 if (p == MAP_FAILED || p == NULL) {
227 std::cerr <<
"RAMComponent::AllocateBlock: Could not allocate " 228 << m_blockSize <<
" bytes. Aborting.\n";
229 throw std::exception();
232 uint64_t blockNr = m_addressSelect >> m_blockSizeShift;
234 if (blockNr+1 > m_memoryBlocks.size())
235 m_memoryBlocks.resize(blockNr + 1);
237 m_memoryBlocks[blockNr] = p;
245 if (m_selectedHostMemoryBlock == NULL)
248 data = (((uint8_t*)m_selectedHostMemoryBlock)
249 [m_selectedOffsetWithinBlock]);
257 assert((m_addressSelect & 1) == 0);
259 if (m_selectedHostMemoryBlock == NULL)
262 data = (((uint16_t*)m_selectedHostMemoryBlock)
263 [m_selectedOffsetWithinBlock >> 1]);
276 assert((m_addressSelect & 3) == 0);
278 if (m_selectedHostMemoryBlock == NULL)
281 data = (((uint32_t*)m_selectedHostMemoryBlock)
282 [m_selectedOffsetWithinBlock >> 2]);
295 assert((m_addressSelect & 7) == 0);
297 if (m_selectedHostMemoryBlock == NULL)
300 data = (((uint64_t*)m_selectedHostMemoryBlock)
301 [m_selectedOffsetWithinBlock >> 3]);
314 if (m_writeProtected)
317 if (m_selectedHostMemoryBlock == NULL)
318 m_selectedHostMemoryBlock = AllocateBlock();
320 (((uint8_t*)m_selectedHostMemoryBlock)
321 [m_selectedOffsetWithinBlock]) = data;
329 assert((m_addressSelect & 1) == 0);
331 if (m_writeProtected)
334 if (m_selectedHostMemoryBlock == NULL)
335 m_selectedHostMemoryBlock = AllocateBlock();
343 (((uint16_t*)m_selectedHostMemoryBlock)
344 [m_selectedOffsetWithinBlock >> 1]) = d;
352 assert((m_addressSelect & 3) == 0);
354 if (m_writeProtected)
357 if (m_selectedHostMemoryBlock == NULL)
358 m_selectedHostMemoryBlock = AllocateBlock();
366 (((uint32_t*)m_selectedHostMemoryBlock)
367 [m_selectedOffsetWithinBlock >> 2]) = d;
375 assert((m_addressSelect & 7) == 0);
377 if (m_writeProtected)
380 if (m_selectedHostMemoryBlock == NULL)
381 m_selectedHostMemoryBlock = AllocateBlock();
389 (((uint64_t*)m_selectedHostMemoryBlock)
390 [m_selectedOffsetWithinBlock >> 3]) = d;
403 static void Test_RAMComponent_IsStable()
409 static void Test_RAMComponent_AddressDataBus()
415 "AddressDataBus interface", bus != NULL);
418 static void Test_RAMComponent_InitiallyZero()
430 uint16_t data16 = 142;
434 uint32_t data32 = 342;
438 uint64_t data64 = 942;
461 static void Test_RAMComponent_WriteThenRead()
468 uint64_t data64 = ((uint64_t)0x1234567 << 32) | 0x89abcdef;
471 uint64_t data64_b = 0;
476 uint32_t data32_b = 0;
480 "in big endian mode", data32_b, data64 >> 32);
482 uint16_t data16_b = 0;
486 "in big endian mode", data16_b, data64 >> 48);
492 "in big endian mode", data8_b, data64 >> 56);
495 static void Test_RAMComponent_WriteThenRead_ReverseEndianness()
502 uint64_t data64 = ((uint64_t)0x1234567 << 32) | 0x89abcdef;
507 uint32_t data32_b = 0;
512 uint16_t data16_b = 0;
523 static void Test_RAMComponent_WriteProtect()
528 uint32_t data32 = 0x89abcdef;
533 uint16_t data16_a = 0;
563 static void Test_RAMComponent_ClearOnReset()
568 uint32_t data32 = 0x89abcdef;
572 uint16_t data16_a = 0;
579 uint16_t data16_b = 0;
585 static void Test_RAMComponent_Clone()
590 uint32_t data32 = 0x89abcdef;
594 uint16_t data16_a = 0x1234;
601 bus = clone->AsAddressDataBus();
614 static void Test_RAMComponent_ManualSerialization()
619 uint32_t data32 = 0x89abcde5;
623 uint16_t data16_a = 0x1235;
631 string result = ss.str();
633 stringstream messages;
648 static void Test_RAMComponent_Methods_Reexecutableness()
661 UNITTEST(Test_RAMComponent_IsStable);
662 UNITTEST(Test_RAMComponent_AddressDataBus);
663 UNITTEST(Test_RAMComponent_InitiallyZero);
664 UNITTEST(Test_RAMComponent_WriteThenRead);
665 UNITTEST(Test_RAMComponent_WriteThenRead_ReverseEndianness);
666 UNITTEST(Test_RAMComponent_WriteProtect);
667 UNITTEST(Test_RAMComponent_ClearOnReset);
669 UNITTEST(Test_RAMComponent_ManualSerialization);
670 UNITTEST(Test_RAMComponent_Methods_Reexecutableness);
virtual void ShowDebugMessage(const string &msg)=0
Shows a debug message.
static refcount_ptr< Component > Deserialize(ostream &messages, const string &str, size_t &pos)
Deserializes a string into a component tree.
virtual bool MethodMayBeReexecutedWithoutArgs(const string &methodName) const
Returns whether a method name may be re-executed without args.
RAMComponent(const string &visibleClassName="ram")
Constructs a RAMComponent.
static refcount_ptr< Component > CreateComponent(const string &componentNameAndOptionalArgs, GXemul *gxemul=NULL)
Creates a component given a short component name.
virtual AddressDataBus * AsAddressDataBus()
Returns the component's AddressDataBus interface.
virtual bool WriteData(const uint8_t &data, Endianness endianness)
Writes 8-bit data to the currently selected address.
bool AddCustomVariable(const string &name, CustomStateVariableHandler *variableHandler)
Adds a custom state variable to the Component.
virtual void ExecuteMethod(GXemul *gxemul, const string &methodName, const vector< string > &arguments)
Executes a method on the component.
bool AddVariable(const string &name, T *variablePointer)
Adds a state variable of type T to the Component.
virtual bool WriteData(const uint8_t &data, Endianness endianness=BigEndian)=0
Writes 8-bit data to the currently selected address.
An interface for implementing components that read/write data via an address bus. ...
static string GetAttribute(const string &attributeName)
Creates a Component.
#define UNITTESTS(class)
Helper for unit test case execution.
static refcount_ptr< Component > Create(const ComponentCreateArgs &args)
Creates a RAMComponent.
virtual bool MethodMayBeReexecutedWithoutArgs(const string &methodName) const
Returns whether a method name may be re-executed without args.
virtual void GetMethodNames(vector< string > &names) const
Retrieves a component's implemented method names.
static bool HasAttribute(const string &name, const string &attributeName)
Checks if a component has a specific attribute.
virtual void GetMethodNames(vector< string > &names) const
Retrieves a component's implemented method names.
A context used during serialization of objects.
virtual bool ReadData(uint8_t &data, Endianness endianness=BigEndian)=0
Reads 8-bit data from the currently selected address.
bool CheckConsistency() const
Checks consistency by serializing and deserializing the component (including all its child components...
static string GetAttribute(const string &attributeName)
Get attribute information about the RAMComponent class.
A Random Access Memory Component.
virtual bool ReadData(uint8_t &data, Endianness endianness)
Reads 8-bit data from the currently selected address.
void Serialize(ostream &ss, SerializationContext &context) const
Serializes the Component into a string stream.
virtual void ResetState()
Resets the state variables of this component.
virtual void AddressSelect(uint64_t address)
Place an address on the bus.
virtual void ExecuteMethod(GXemul *gxemul, const string &methodName, const vector< string > &arguments)
Executes a method on the component.
A base-class for memory-mapped components.
static void Assert(const string &strFailMessage, bool condition)
Asserts that a boolean condition is correct.
virtual void AddressSelect(uint64_t address)=0
Place an address on the bus.
bool SetVariableValue(const string &name, const string &expression)
Sets a variable to a new value.
refcount_ptr< Component > Clone() const
Clones the component and all its children.
virtual AddressDataBus * AsAddressDataBus()
Returns the component's AddressDataBus interface, if any.
void Reset()
Resets the state of this component and all its children.
UI * GetUI()
Gets a pointer to the GXemul instance' active UI.
#define UNITTEST(functionname)
Helper for unit test case execution.