You need to log in to create posts and topics.

External memory on mega2560

Howdy,

 

Congrats for this amazing piece of software., 
I was reading the docs and didn't find how it emulates the avr mega2560 , and if it does full emulaion of external memory support . Could you point me to the right documentation . 

 

Thanks in advanc.e, 

 

 

Hi.

Sorry but avr mega2560 external memory is not implemented.

Could you tell me what would take to do it (how hard it would be and what would be the road map)?<<
I'm a little lost on the source code .. 

 

Thanks ., 

Instructions reading and/or writing to RAM could not get executed in one go.
Instead they should be separated in steps adding all the external memory read/write steps with their timings, etc.
That would take a complete rewrite of AVR core.

Probably it would be faster to write a new implementation of AVR core from scratch.

 

Thanks for the reply.

 

I don't have that kind of knowlege. 

 

Anyway,. it's a great application. 

 

Best regards,

 

 

 

Howdy, 

did some tinkering, and got almost everything to work .,

implemented a proxyMemory to the avrcore so it would not disrupt anything, ,

it's mainly working, but i can't figure out why ALE, RD, WR do not update ,

my logs clearly show that it is  modifying the registers correctly,  but it never shows., 

and at this point, i don't know what i be looking for.

 

the fork is updated so it compiles and runs ok ., 
https://github.com/fredcwbr/SimulIDE-dev/tree/megaXMEM  --> git branch megaXMEM

 

Could you give some direction here?

 

[DATASPACE] writeReg invoked for Addr: 34 Val: 3 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 3 
[XMEM-DEBUG] PORTG set to: 3 Logic states -> RD: 1 WR: 1 ALE: 0 
[XMEM-PROXY] External XMEM Write at address: 9e00 Data: 22 
[XMEM-DEBUG] Entering Bus Cycle for Addr: 9e00 PORTG reg val: 3 PG0 connected: true PG1 connected: true PG2 connected: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 27 with value: ff 
[DATASPACE] writeReg invoked for Addr: 27 Val: ff HasSignal: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 21 with value: ff 
[DATASPACE] writeReg invoked for Addr: 21 Val: ff HasSignal: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 33 with value: 7 
[DATASPACE] writeReg invoked for Addr: 33 Val: 7 HasSignal: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 28 with value: 9e 
[DATASPACE] writeReg invoked for Addr: 28 Val: 9e HasSignal: true 
[AVRCORE-PORT-PORTC-CHANGED] outChanged(portC) addr: 28 with value: 9e 
[AVRCORE-PORT] writePortReg invoked for register addr: 22 with value: 0 
[DATASPACE] writeReg invoked for Addr: 22 Val: 0 HasSignal: true 
[AVRCORE-PORT-PORTA-CHANGED] outChanged(portA) addr: 22 with value: 0 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 7 
[DATASPACE] writeReg invoked for Addr: 34 Val: 7 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 7 
[XMEM-DEBUG] PORTG set to: 7 Logic states -> RD: 1 WR: 1 ALE: 1 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 3 
[DATASPACE] writeReg invoked for Addr: 34 Val: 3 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 3 
[XMEM-DEBUG] PORTG set to: 3 Logic states -> RD: 1 WR: 1 ALE: 0 
[AVRCORE-PORT] writePortReg invoked for register addr: 22 with value: 22 
[DATASPACE] writeReg invoked for Addr: 22 Val: 22 HasSignal: true 
[AVRCORE-PORT-PORTA-CHANGED] outChanged(portA) addr: 22 with value: 22 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 1 
[DATASPACE] writeReg invoked for Addr: 34 Val: 1 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 1 
[XMEM-DEBUG] PORTG set to: 1 Logic states -> RD: 1 WR: 0 ALE: 0 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 3 
[DATASPACE] writeReg invoked for Addr: 34 Val: 3 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 3 
[XMEM-DEBUG] PORTG set to: 3 Logic states -> RD: 1 WR: 1 ALE: 0 
[XMEM-PROXY] External XMEM Write at address: a000 Data: 57 
[XMEM-DEBUG] Entering Bus Cycle for Addr: a000 PORTG reg val: 3 PG0 connected: true PG1 connected: true PG2 connected: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 27 with value: ff 
[DATASPACE] writeReg invoked for Addr: 27 Val: ff HasSignal: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 21 with value: ff 
[DATASPACE] writeReg invoked for Addr: 21 Val: ff HasSignal: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 33 with value: 7 
[DATASPACE] writeReg invoked for Addr: 33 Val: 7 HasSignal: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 28 with value: a0 
[DATASPACE] writeReg invoked for Addr: 28 Val: a0 HasSignal: true 
[AVRCORE-PORT-PORTC-CHANGED] outChanged(portC) addr: 28 with value: a0 
[AVRCORE-PORT] writePortReg invoked for register addr: 22 with value: 0 
[DATASPACE] writeReg invoked for Addr: 22 Val: 0 HasSignal: true 
[AVRCORE-PORT-PORTA-CHANGED] outChanged(portA) addr: 22 with value: 0 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 7 
[DATASPACE] writeReg invoked for Addr: 34 Val: 7 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 7 
[XMEM-DEBUG] PORTG set to: 7 Logic states -> RD: 1 WR: 1 ALE: 1 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 3 
[DATASPACE] writeReg invoked for Addr: 34 Val: 3 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 3 
[XMEM-DEBUG] PORTG set to: 3 Logic states -> RD: 1 WR: 1 ALE: 0 
[AVRCORE-PORT] writePortReg invoked for register addr: 22 with value: 57 
[DATASPACE] writeReg invoked for Addr: 22 Val: 57 HasSignal: true 
[AVRCORE-PORT-PORTA-CHANGED] outChanged(portA) addr: 22 with value: 57 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 1 
[DATASPACE] writeReg invoked for Addr: 34 Val: 1 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 1 
[XMEM-DEBUG] PORTG set to: 1 Logic states -> RD: 1 WR: 0 ALE: 0 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 3 
[DATASPACE] writeReg invoked for Addr: 34 Val: 3 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 3 
[XMEM-DEBUG] PORTG set to: 3 Logic states -> RD: 1 WR: 1 ALE: 0 
[XMEM-PROXY] External XMEM Write at address: a200 Data: 99 
[XMEM-DEBUG] Entering Bus Cycle for Addr: a200 PORTG reg val: 3 PG0 connected: true PG1 connected: true PG2 connected: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 27 with value: ff 
[DATASPACE] writeReg invoked for Addr: 27 Val: ff HasSignal: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 21 with value: ff 
[DATASPACE] writeReg invoked for Addr: 21 Val: ff HasSignal: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 33 with value: 7 
[DATASPACE] writeReg invoked for Addr: 33 Val: 7 HasSignal: true 
[AVRCORE-PORT] writePortReg invoked for register addr: 28 with value: a2 
[DATASPACE] writeReg invoked for Addr: 28 Val: a2 HasSignal: true 
[AVRCORE-PORT-PORTC-CHANGED] outChanged(portC) addr: 28 with value: a2 
[AVRCORE-PORT] writePortReg invoked for register addr: 22 with value: 0 
[DATASPACE] writeReg invoked for Addr: 22 Val: 0 HasSignal: true 
[AVRCORE-PORT-PORTA-CHANGED] outChanged(portA) addr: 22 with value: 0 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 7 
[DATASPACE] writeReg invoked for Addr: 34 Val: 7 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 7 
[XMEM-DEBUG] PORTG set to: 7 Logic states -> RD: 1 WR: 1 ALE: 1 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 3 
[DATASPACE] writeReg invoked for Addr: 34 Val: 3 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 3 
[XMEM-DEBUG] PORTG set to: 3 Logic states -> RD: 1 WR: 1 ALE: 0 
[AVRCORE-PORT] writePortReg invoked for register addr: 22 with value: 99 
[DATASPACE] writeReg invoked for Addr: 22 Val: 99 HasSignal: true 
[AVRCORE-PORT-PORTA-CHANGED] outChanged(portA) addr: 22 with value: 99 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 1 
[DATASPACE] writeReg invoked for Addr: 34 Val: 1 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 1 
[XMEM-DEBUG] PORTG set to: 1 Logic states -> RD: 1 WR: 0 ALE: 0 
[AVRCORE-PORT] writePortReg invoked for register addr: 34 with value: 3 
[DATASPACE] writeReg invoked for Addr: 34 Val: 3 HasSignal: true 
[PORTG-DEBUG] portG pointer: 0x5608d88b5b60 
[AVRCORE-PORT-PORTG-CHANGED] outChanged(portG) addr: 34 with value: 3 
[XMEM-DEBUG] PORTG set to: 3 Logic states -> RD: 1 WR: 1 ALE: 0 

    Simulation Stopped  

-------------------------------------------------
  

Circuit Saved: 
 "/home/fred/Arduino/MegaMemTest/MegaExtMEMPortX.sim2" 

------------------------------------------------- 

 


        // 3. External Memory Space (> 0x21FF)
        if (isXmemEnabled()) {
            qDebug() << "[XMEM-PROXY] External XMEM Write at address:" << Qt::hex << address << "Data:" << value;
            uint8_t valToWrite = value;
            triggerBusCycle(address, valToWrite, true);
            m_externalRamSimulation[address & 0xFFFF] = value;
        }
    void triggerBusCycle(uint16_t address, uint8_t& data, bool isWrite) {
        uint8_t lowAddr = static_cast<uint8_t>(address & 0xFF);
        uint8_t highAddr = static_cast<uint8_t>((address >> 8) & 0xFF);

        if (!m_mcu || !m_avrCore) return;

	// --- DEBUG: Inspect Port G and its Pins before starting cycle ---
        McuPort* portG = m_mcu->getMcuPort("PORTG");
        if (portG) {
            McuPin* p0 = portG->getPinN(0); // /RD
            McuPin* p1 = portG->getPinN(1); // /WR
            McuPin* p2 = portG->getPinN(2); // ALE
            
            qDebug() << "[XMEM-DEBUG] Entering Bus Cycle for Addr:" << Qt::hex << address
                     << "PORTG reg val:" << m_ram[0x34]
                     << "PG0 connected:" << (p0 ? p0->isConnected() : false)
                     << "PG1 connected:" << (p1 ? p1->isConnected() : false)
                     << "PG2 connected:" << (p2 ? p2->isConnected() : false);
        }

        uint8_t waitStates = (address >= 0x8000) ? m_srw1 : m_srw0;

        // 1. Configure Port Directions (DDR)
        m_avrCore->writePortReg(0x27, 0xFF); // DDRC out
        m_avrCore->writePortReg(0x21, isWrite ? 0xFF : 0x00); // DDRA out/in

        uint8_t ddrg = m_ram[0x33];
        ddrg |= (1 << 0) | (1 << 1) | (1 << 2); // PG0(/RD), PG1(/WR), PG2(ALE)
        m_avrCore->writePortReg(0x33, ddrg);

        // 2. Drive Address Bus (High byte on PORTC, Low byte on PORTA)
        m_avrCore->writePortReg(0x28, highAddr);
        m_avrCore->writePortReg(0x22, 0); // Low byte address initially 0 for ALE

        uint8_t portgVal = m_ram[0x34];
        portgVal |= (1 << 0) | (1 << 1);
        portgVal &= ~(1 << 2);

	auto setPortG = [&](uint8_t val, int simulatedCycles ) {
            m_avrCore->writePortReg(0x34, val);
	    m_mcu->cyclesDone += simulatedCycles;
            qDebug() << "[XMEM-DEBUG] PORTG set to:" << Qt::hex << val 
                     << "Logic states -> RD:" << ((val & 1) ? 1 : 0) 
                     << "WR:" << ((val & 2) ? 1 : 0) 
                     << "ALE:" << ((val & 4) ? 1 : 0);
        };

        // --- Phase 1: ALE High & Low ---
        portgVal |= (1 << 2); // ALE High
        setPortG(portgVal,1);
	McuPin* alePin = m_mcu->getMcuPin("PG2"); // or verify exact pin ID
        if (alePin) {
	    alePin->setOutState(true);  // Drive high/low directly
	}

        portgVal &= ~(1 << 2); // ALE Low (Address Latched)
        setPortG(portgVal,1);

        // --- Phase 2: Strobe Activation ---
        if (isWrite) {
            m_avrCore->writePortReg(0x22, data); // Put data on PORTA
            portgVal &= ~(1 << 1); // /WR Low
            setPortG(portgVal,1);
        } else {
            m_avrCore->writePortReg(0x21, 0x00); // Input mode for read on DDRA
            portgVal &= ~(1 << 0); // /RD Low
            setPortG(portgVal,1);
        }

        m_mcu->cyclesDone += waitStates;

        // --- Phase 3: Strobe De-assertion ---
        portgVal |= (1 << 0) | (1 << 1); // Return /RD and /WR High
        setPortG(portgVal,1);

        if (!isWrite) {
            data = m_ram[0x20]; // Read from PORTA input pins register
            m_avrCore->writePortReg(0x21, 0xFF); // Restore DDRA
        }

        m_mcu->cyclesDone += 2;
    }

 

Uploaded files:

Seems that I missed last post...

Implementing external memory is not easy at all.
As I can see in your code all the memory access is done in one function call. So the circuit is "frozen" during that time.
That is why:

Instructions reading and/or writing to RAM could not get executed in one go.
Instead they should be separated in steps adding all the external memory read/write steps with their timings, etc.
That would take a complete rewrite of AVR core.

Probably it would be faster to write a new implementation of AVR core from scratch.

These steps must happen at the proper simulation time.
For example every event shown here must happen at the correct simulation time:

This requires a good understanding of how the simulator works.
As a reference you can have a look at 8051 MCU: src/microsim/cores/i51/i51core.cpp, it uses external memory almost the same than these AVRs.
Timing will be different and AVR  XMEM interface provides four different wait-states so a bit more complicated.

 

Some other issues I see:

This should be done once at constructor and be stored, then used in  each iteraction:

        McuPort* portG = m_mcu->getMcuPort("PORTG");
        if (portG) {
            McuPin* p0 = portG->getPinN(0); // /RD
            McuPin* p1 = portG->getPinN(1); // /WR
            McuPin* p2 = portG->getPinN(2); // ALE

 

Also I don't think that external memory controller writes to DDRx or PORTx registers.
Most probably it takes direct control of the ports not disturbing values stored in it's registers.

Thanks for these pointers, 
I'll look into them .,

as I said, .. way off my ball park.,  .. 

Just passing by, 
finally, all pins are toggling , and code is more or less working.

Going to move to test phase in order to verify if it at least looks like what is expected., 

]

Thanks for the support., 

 

 

WIP..