Hi *,

The PINx register is not correctly updated in the (VCD) traceer, when a
pin is driven *by a different portpin or even another device* (multicore
simulation). It is correctly traced, when the source is a portpin of the
same HWPort.

In the attached example, PB1 is periodically toggled and it is connected
to PD2, thus the PIND register should change. Compile and run the
example like so:

> avr-gcc -g -mmcu=atmega644 -std=gnu11 -O2 -Wall -Wextra -Werror -o main.elf 
> main.c
> ./run_simulator.py

The attached patch fixes this issue by adding an additional member to
Pin, that points to the IOReg<HWPort> owning that Pin. This allows to
report-back/update the tracer when the pin changes. (much like pinOfPort
does)

Patch, minimum working example, and screenshots attached.

Cheers,
panic
>From 60056018674044a049aba44aa2f1ac545b589475 Mon Sep 17 00:00:00 2001
From: panic <li...@xandea.de>
Date: Sun, 11 Jun 2017 18:37:43 +0200
Subject: [PATCH] fix trace of PINx register when driven from another port or
 second device

---
 src/hwport.cpp | 4 ++++
 src/pin.cpp    | 8 ++++++++
 src/pin.h      | 3 +++
 3 files changed, 15 insertions(+)

diff --git a/src/hwport.cpp b/src/hwport.cpp
index ab4c4f8..5d5f26b 100644
--- a/src/hwport.cpp
+++ b/src/hwport.cpp
@@ -61,6 +61,10 @@ HWPort::HWPort(AvrDevice *core, const string &name, bool portToggle, int size):
         RegisterTraceValue(pintrace[tt]);
     }
 
+    for (unsigned int idx = 0; idx < portSize; ++idx) {
+        p[idx].pinOfPort = &pin;
+        p[idx].pinregOfPort = &pin_reg;
+    }
     Reset();
 }
 
diff --git a/src/pin.cpp b/src/pin.cpp
index 0c52157..2f3dc4a 100644
--- a/src/pin.cpp
+++ b/src/pin.cpp
@@ -28,6 +28,7 @@
 
 #include "pin.h"
 #include "net.h"
+#include "rwmem.h"
 
 float AnalogValue::getA(float vcc) {
     switch(dState) {
@@ -69,6 +70,8 @@ void Pin::SetInState(const Pin &p) {
         } else { 
             *pinOfPort &= 0xff - mask;
         }
+        if (pinregOfPort != 0)
+            pinregOfPort->hardwareChange(*pinOfPort);
     }
 
     std::vector<HasPinNotifyFunction*>::iterator ii;
@@ -91,6 +94,7 @@ bool Pin::CalcPin(void) {
 
 Pin::Pin(T_Pinstate ps) { 
     pinOfPort = 0; 
+    pinregOfPort = 0;
     connectedTo = NULL;
     mask = 0;
     
@@ -120,6 +124,7 @@ Pin::Pin(T_Pinstate ps) {
 
 Pin::Pin() { 
     pinOfPort = 0; 
+    pinregOfPort = 0;
     connectedTo = NULL;
     mask = 0;
     
@@ -133,6 +138,7 @@ Pin::~Pin() {
 
 Pin::Pin( unsigned char *parentPin, unsigned char _mask) { 
     pinOfPort = parentPin;
+    pinregOfPort = 0;
     mask = _mask;
     connectedTo = NULL;
     
@@ -141,6 +147,7 @@ Pin::Pin( unsigned char *parentPin, unsigned char _mask) {
 
 Pin::Pin(const Pin& p) {
     pinOfPort = 0; // don't take over HWPort connection!
+    pinregOfPort = 0;
     connectedTo = NULL; // don't take over Net instance!
     mask = 0;
     
@@ -151,6 +158,7 @@ Pin::Pin(const Pin& p) {
 Pin::Pin(float analog) {
     mask = 0;
     pinOfPort = 0;
+    pinregOfPort = 0;
     connectedTo = NULL;
     analogVal.setA(analog);
 
diff --git a/src/pin.h b/src/pin.h
index 06d1eb0..26ff637 100644
--- a/src/pin.h
+++ b/src/pin.h
@@ -31,6 +31,8 @@
 #include "pinnotify.h"
 
 class Net;
+class HWPort;
+template<typename T> class IOReg;
 
 #define REL_FLOATING_POTENTIAL 0.55
 
@@ -97,6 +99,7 @@ class Pin {
     
     protected:
         unsigned char *pinOfPort; //!< points to HWPort::pin or NULL
+        IOReg<HWPort> *pinregOfPort;
         unsigned char mask; //!< byte mask for HWPort::pin
         AnalogValue analogVal; //!< "real" analog voltage value
 
-- 
2.1.4

Attachment: fail.vcd
Description: application/vnd.gtkwave-vcd

#include <avr/io.h>
#include <inttypes.h>

int
main(void)
{
  DDRB = _BV(PB1);
  for (uint8_t i = 0; i < 10; ++i)
    PORTB ^= _BV(PB1);
  return 0;
}

Attachment: pass.vcd
Description: application/vnd.gtkwave-vcd

#!/usr/bin/env python

import pysimulavr

def main():
    elffile = "main.elf"
    vcdfile = "trace.vcd"

    dman = pysimulavr.DumpManager.Instance()
    dman.SetSingleDeviceApp()

    # get systemclock instance
    sc = pysimulavr.SystemClock.Instance()
    clkper = long(1e9/1.0e6) # period in ns, 1.0 MHz

    print("Create device")
    dev = pysimulavr.AvrFactory.instance().makeDevice("atmega644")
    dev.Load(elffile)
    dev.SetClockFreq(clkper) # clock period in ns!
    sc.Add(dev)

    print("Connect pins: PB1 --> PD2")
    n = pysimulavr.Net()
    n.Add(dev.GetPin("B1"))
    n.Add(dev.GetPin("D2"))

    print("Setup VCD Tracer")
    signals = [ "+ PORTB.B1-Out", "+ PORTD.PIN" ]
    dman.addDumpVCD(vcdfile, "\n".join(signals), "ns", False, False)

    dev.RegisterTerminationSymbol("exit")

    print("Starting simulation...")
    dman.start()
    sc.Run(int(1e8))
    dman.stopApplication()

    now = sc.GetCurrentTime()
    print("Done after {:d} ns ({:.3f} s)".format(now, now/1e9))

if __name__ == "__main__":
    main()
_______________________________________________
Simulavr-devel mailing list
Simulavr-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/simulavr-devel

Reply via email to