renode/renode-docs

Document how to debug C# modules

xobs opened this issue · 4 comments

xobs commented

Writing C# modules unlocks a lot of functionality in Renode, however it's very difficult to debug these modules.

For example, in this module:

using System;
using Antmicro.Renode.Core;
using Antmicro.Renode.Peripherals.Bus;
using Antmicro.Renode.Time;
using Antmicro.Renode.Logging;
using System.Threading;

namespace Antmicro.Renode.Peripherals.Timers
{
    public class SimpleTicker : IDoubleWordPeripheral
    {
        public SimpleTicker(ulong periodInMs, Machine machine)
        {
            machine.ClockSource.AddClockEntry(new ClockEntry(periodInMs, ClockEntry.FrequencyToRatio(this, 1000), OnTick, this, String.Empty));
        }
       // ...
    }
}

It's difficult to know:

  1. What properties there are on machine
  2. Where Machine is defined (which package does it come from?)
  3. What do each of the parameters in that function mean?
  4. What is a ClockSource and how does it work?
  5. What other properties are there in Antmicro.Renode.Peripherals?
  6. What is the interface required to implement IDoubleWordPeripheral?
  7. Does this even compile?

Many of these questions could be answered by connecting this .cs file to an IDE of some sort. I'm not sure how 2 could be answered, because I gather that's a feature of C#. 7 can only be answered by restarting Renode.

With C# modules being documented, it would also be nice to know how to implement modules and debug issues within them.

xobs commented

I'm starting to understand how to integrate this with Omnisharp.

I now have this:

image

Note the gray up top, indicating I'm not using particular modules. Also, note that mouseover gives information on arguments.

I get full autocomplete:
image

And if I control-click on a symbol, it brings me to a useful screen describing it:

image

In order to get this, create a .csproj file somewhere in the directory and point it to Renode. In my case, this file looks like:

Click to show `peripherals.csproj`
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <PlatformTarget>AMD64</PlatformTarget>
    <RenodePath>..\..\..\..\Software\Renode\bin</RenodePath>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="AdvancedLoggerViewerPlugin">
      <HintPath>$(RenodePath)/AdvancedLoggerViewerPlugin.dll</HintPath>
    </Reference>
    <Reference Include="AntShell">
      <HintPath>$(RenodePath)/AntShell.dll</HintPath>
    </Reference>
    <Reference Include="AsyncIO">
      <HintPath>$(RenodePath)/AsyncIO.dll</HintPath>
    </Reference>
    <Reference Include="CookComputing.XmlRpcV2">
      <HintPath>$(RenodePath)/CookComputing.XmlRpcV2.dll</HintPath>
    </Reference>
    <Reference Include="cores-arm">
      <HintPath>$(RenodePath)/cores-arm.dll</HintPath>
    </Reference>
    <Reference Include="cores-arm-m">
      <HintPath>$(RenodePath)/cores-arm-m.dll</HintPath>
    </Reference>
    <Reference Include="cores-i386">
      <HintPath>$(RenodePath)/cores-i386.dll</HintPath>
    </Reference>
    <Reference Include="cores-ppc">
      <HintPath>$(RenodePath)/cores-ppc.dll</HintPath>
    </Reference>
    <Reference Include="cores-ppc64">
      <HintPath>$(RenodePath)/cores-ppc64.dll</HintPath>
    </Reference>
    <Reference Include="cores-riscv">
      <HintPath>$(RenodePath)/cores-riscv.dll</HintPath>
    </Reference>
    <Reference Include="cores-riscv64">
      <HintPath>$(RenodePath)/cores-riscv64.dll</HintPath>
    </Reference>
    <Reference Include="cores-sparc">
      <HintPath>$(RenodePath)/cores-sparc.dll</HintPath>
    </Reference>
    <Reference Include="CxxDemangler">
      <HintPath>$(RenodePath)/CxxDemangler.dll</HintPath>
    </Reference>
    <Reference Include="Dynamitey">
      <HintPath>$(RenodePath)/Dynamitey.dll</HintPath>
    </Reference>
    <Reference Include="ELFSharp">
      <HintPath>$(RenodePath)/ELFSharp.dll</HintPath>
    </Reference>
    <Reference Include="Emulator">
      <HintPath>$(RenodePath)/Emulator.dll</HintPath>
    </Reference>
    <Reference Include="Extensions">
      <HintPath>$(RenodePath)/Extensions.dll</HintPath>
    </Reference>
    <Reference Include="FdtSharp">
      <HintPath>$(RenodePath)/FdtSharp.dll</HintPath>
    </Reference>
    <Reference Include="IronPython">
      <HintPath>$(RenodePath)/IronPython.dll</HintPath>
    </Reference>
    <Reference Include="IronPython.Modules">
      <HintPath>$(RenodePath)/IronPython.Modules.dll</HintPath>
    </Reference>
    <Reference Include="libtftp">
      <HintPath>$(RenodePath)/libtftp.dll</HintPath>
    </Reference>
    <Reference Include="LLVMDisassembler">
      <HintPath>$(RenodePath)/LLVMDisassembler.dll</HintPath>
    </Reference>
    <Reference Include="Lucene.Net">
      <HintPath>$(RenodePath)/Lucene.Net.dll</HintPath>
    </Reference>
    <Reference Include="LZ4">
      <HintPath>$(RenodePath)/LZ4.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Dynamic">
      <HintPath>$(RenodePath)/Microsoft.Dynamic.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Scripting">
      <HintPath>$(RenodePath)/Microsoft.Scripting.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Scripting.Metadata">
      <HintPath>$(RenodePath)/Microsoft.Scripting.Metadata.dll</HintPath>
    </Reference>
    <Reference Include="Migrant">
      <HintPath>$(RenodePath)/Migrant.dll</HintPath>
    </Reference>
    <Reference Include="Mono.Cecil">
      <HintPath>$(RenodePath)/Mono.Cecil.dll</HintPath>
    </Reference>
    <Reference Include="NetMQ">
      <HintPath>$(RenodePath)/NetMQ.dll</HintPath>
    </Reference>
    <Reference Include="Nini">
      <HintPath>$(RenodePath)/Nini.dll</HintPath>
    </Reference>
    <Reference Include="OptionsParser">
      <HintPath>$(RenodePath)/OptionsParser.dll</HintPath>
    </Reference>
    <Reference Include="PacketDotNet">
      <HintPath>$(RenodePath)/PacketDotNet.dll</HintPath>
    </Reference>
    <Reference Include="Renode">
      <HintPath>$(RenodePath)/Renode.exe</HintPath>
    </Reference>
    <Reference Include="Renode-peripherals">
      <HintPath>$(RenodePath)/Renode-peripherals.dll</HintPath>
    </Reference>
    <Reference Include="SampleCommandPlugin">
      <HintPath>$(RenodePath)/SampleCommandPlugin.dll</HintPath>
    </Reference>
    <Reference Include="Sprache">
      <HintPath>$(RenodePath)/Sprache.dll</HintPath>
    </Reference>
    <Reference Include="TermSharp">
      <HintPath>$(RenodePath)/TermSharp.dll</HintPath>
    </Reference>
    <Reference Include="TracePlugin">
      <HintPath>$(RenodePath)/TracePlugin.dll</HintPath>
    </Reference>
    <Reference Include="UI">
      <HintPath>$(RenodePath)/UI.dll</HintPath>
    </Reference>
    <Reference Include="VerilatorPlugin">
      <HintPath>$(RenodePath)/VerilatorPlugin.dll</HintPath>
    </Reference>
    <Reference Include="WiresharkPlugin">
      <HintPath>$(RenodePath)/WiresharkPlugin.dll</HintPath>
    </Reference>
    <Reference Include="Xwt">
      <HintPath>$(RenodePath)/Xwt.dll</HintPath>
    </Reference>
    <Reference Include="Xwt.WPF">
      <HintPath>$(RenodePath)/Xwt.WPF.dll</HintPath>
    </Reference>
  </ItemGroup>

</Project>

This obviously has a lot of platform-specific cruft. And I'm not sure on the <TargetFramework>netstandard2.0</TargetFramework> value -- isn't it a different version on Windows?

At any rate, this gives me syntax checking, autocomplete, and rudimentary documentation. It also doesn't require me to compile Renode, since I'm just using the binaries directly.

Edit: The csproj file was updated to parameterize it to include RenodePath as a build variable, and to add forward slashes. I'd appreciate seeing if this works on non-Windows platforms, and if so perhaps this could be put forward as an official solution to the issue.

xobs commented

Also, one can mouseover the arguments to figure out which package they come from. For example, now I know that Machine comes from Antmicro.Renode.Core:

image

xobs commented

I updated the peripherals.csproj file in original comment to make it more cross-platform and less unwieldy. I'd appreciate someone else giving it a try to see if it works for them.

Hey @xobs, this is really cool.

We'll take a look internally and then maybe we'd be able to somehow include it in our packages, so that everyone can use it with simple instructions (like cp this file to your dir, start vscode, install omnisharp, voila)