renode icon indicating copy to clipboard operation
renode copied to clipboard

Support Control signals for SPIConnector

Open xobs opened this issue 3 years ago • 4 comments

I'm trying to connect a HOLD GPIO between two peripherals. This simulates a SPI peripheral that has a signal to indicate no more data should be transmitted.

In the Master side I have the block defined as:

namespace Antmicro.Renode.Peripherals.SPI
    public class BetrustedSocSpi : NullRegistrationPointPeripheralContainer<ISPIPeripheral>, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize
    {
        public BetrustedSocSpi(Machine machine) : base(machine)
        {
            IRQ = new GPIO();
            HOLD = new GPIO();
...
       }
    }
}

The Slave side is defined as:

namespace Antmicro.Renode.Peripherals.SPI
{
    public class BetrustedEcSpi : ISPIPeripheral, IDoubleWordPeripheral, IKnownSize, IGPIOSender
    {
        public BetrustedEcSpi(Machine machine)
        {
            HOLD = new GPIO();
        }
    }
}

How can I connect these two together? This does not appear to work:

(monitor) emulation CreateGPIOConnector "comhold"
(monitor) mach set "EC"
(EC) connector Connect com comhold
(EC) mach set "SoC"
(SoC) connector Connect com comhold
(SoC) start

This does not cause the HOLD GPIO inside the SoC to mirror the value set by the EC.

  1. Is there an example of how to connect extra peripheral lines?
  2. How do I tell Renode that HOLD is not an interrupt?
  3. How do I specify GPIOs when using connector Connect, because connector Connect com.HOLD comhold doesn't seem like valid syntax
  4. How do I specify identifiers with invalid strings? Initially my hold connection was called com-spi-hold but that doesn't seem to be able to be passed to connector Connect

xobs avatar Feb 12 '22 12:02 xobs

I believe I had a fundamental misunderstanding of how connections work. It seems like they do not allow making multiple connections between the same device.

The SPI connection I have contains two additional control lines: Interrupt and Hold.

The Hold line is tied to the FIFO on the peripheral -- the Hold line is true when the peripheral Tx (CIPO) FIFO is empty, and false when there is data. Thus, it is not enough to simply poll for data, the peripheral needs to be able to raise a GPIO.

The Interrupt line is also a GPIO and may be raised at any time by the Peripheral. It is independent of the FIFO state.

These lines need to be able to be controleld by the Peripheral and have their states reflected in the Machine.

xobs avatar Feb 13 '22 07:02 xobs

Hi @xobs, this is true that our SPI interface is strictly data centered at the moment.

I believe using the connector might do the trick, if we don't hit some synchronization issues (which is highly depending on the software itself).

The GPIOConnector requires a few steps.

Seeing your example, I see where we could improve the interface here. It looks what it does because we don't have the same parsing mechanism in the Monitor as in the repl files. There is a place for improvement, but in the current state it works as follows.

  • the connection is one way. If you want to have connections working two way, you need two connectors
  • one connector is for a single connection only, but you can have many connectors if needed
  • the sender has to implement INumberedGPIOOutput, so that we can select a pin by number
  • the receiver has to implement IGPIOReceiver, so that it has an OnGPIO method. It will be called whenever the sender pin is set.
  • there is no problem having both interfaces implemented for a two-way connection.

Assuming that we want to connect pin 0 from sender to pin 1 from receiver (the numbers are of course arbitrary):

(monitor) emulation CreateGPIOConnector "comhold"
(monitor) mach set "EC"
(EC) connector Connect sender comhold
(EC) connector SelectSourcePin sender 0
(EC) mach set "SoC"
(SoC) connector Connect receiver comhold
(SoC) connector SelectDestinationPin receiver 1
(SoC) start

Answering your other questions: 2. No difference for Renode, really 4. We'll double check that. It might be that we're able to name things in the way we can't address later on, but this should be an easy fix.

Please let me know if that helps!

PiotrZierhoffer avatar Feb 13 '22 22:02 PiotrZierhoffer

This does help, and it made me realise I was doing it the wrong way.

I ended up creating a completely new kind of connector with a corresponding CreateComConnector call. This call has external signals for HOLD and INTERRUPT. It's not the best, but it works: https://github.com/betrusted-io/xous-core/blob/main/emulation/peripherals/Com.cs

I do violate timing, but I think that's expected given the nature of the peripherals:

  1. Most SPI devices are dumb and only react when you talk to them.
  2. When you have two CPUs connected via SPI, they generally have a buffer of some sort
  3. The buffer data is usually communicated via external signals such as a HOLD or VALID line

In my implementation of the Com bus, the Peripheral writes data to its own FIFO. This FIFO is connected via an asynchronous HOLD GPIO that gets mapped into the device. It avoids doing controller.GetMachine().HandleTimeDomainEvent() because that creates ambiguity when there is bidirectional data.

Now that I can do that, the COM bus is working and both the EC and SoC processors are operating together.

xobs avatar Feb 14 '22 08:02 xobs

For the record, we have just released a new mode of emulation, that allows you not to synchronize IO - so you can use the same code and change the setting in runtime.

See https://github.com/renode/renode/blob/master/tests/unit-tests/emulation-mode.robot#L25

The line emulation Mode SynchronizedTimers (as opposed to SynchronizedIO) allows you to increase the responsiveness, if you're ok with reduced determinism. This, in fact, should allow you to use the standard connectors without any additional SPI interfaces (re #297).

But of course your current solution also makes a lot of sense!

PiotrZierhoffer avatar Feb 14 '22 21:02 PiotrZierhoffer

I think there's sufficient examples available now to be able to close this.

The solution is to use a fully-custom connector, which is apparently possible to do.

xobs avatar Dec 28 '23 10:12 xobs