/* This is a very mangled version of Vadc__main.cpp as generated by Verilator. */

// Verilated -*- C++ -*-
// DESCRIPTION: main() calling loop, created with Verilator --main

#include "verilated.h"
#include "Vlng.h"

#include "ngspice/cmtypes.h" // For Digital_t
#include "ngspice/cosim.h"   // For struct co_info and prototypes

//======================

/* Structure for the input table. */

struct input {
  const char   *name;
  unsigned int  offset;
  unsigned int  count;
};

/* This VL_DATA macro is used in header files inputs.h, outputs.h and inouts.h
 * to write functions accept_input() and step().
 * The macro is used several times with different definitions.
 */

/* Generate the previous values table used by step(). */

#define VL_DATA(size, name, msb, lsb) + msb - lsb + 1
static const unsigned int outs = 0
#include "outputs.h"
  ;
static const unsigned int inouts = 0
#include "inouts.h"
  ;

static unsigned char previous_output[outs + inouts];

#undef VL_DATA

/* The input function: it should ignore out-of-range values of index. */

#define VL_DATA(size, name, msb, lsb)     \
  if (index >= msb - lsb + 1) {           \
    index -= msb - lsb + 1;               \
  } else if (msb == 0 && lsb == 0) {      \
    topp->name = val ? 1 : 0;             \
    return;                               \
  } else {                                \
    if (val)                              \
      topp->name |= (1 << (msb - index)); \
    else                                  \
      topp->name &= (1 << (msb - index)); \
    return;                               \
  }

static void accept_input(struct co_info *pinfo,
			 unsigned int index, Digital_t *vp)
{
    Vlng          *topp = (Vlng *)pinfo->handle;
    unsigned int   val, offset;

    val = vp->state;
    if (val == UNKNOWN)
        return;    // Verilator simulations are two-state.

#include "inputs.h"

    /* For inout ports the new value must be stored to detect changes. */

    offset = outs;
#undef VL_DATA
#define VL_DATA(size, name, msb, lsb)      \
  if (index >= msb - lsb + 1) {            \
    index -= msb - lsb + 1;                \
    offset += msb - lsb + 1;               \
  } else if (msb == 0 && lsb == 0) {       \
    topp->name = val ? 1 : 0;              \
    previous_output[index + offset] = val; \
    return;                                \
  } else {                                 \
    if (val) 				   \
      topp->name | (1 << (msb - index));   \
    else                                   \
      topp->name &= (1 << (msb - index));  \
    previous_output[index + offset] = val; \
    return;                                \
  }

#include "inouts.h"
}
#undef VL_DATA

/* The step function that calls the Verilator code. */

#define VL_DATA(size, name, msb, lsb)        \
  for (i = msb; i >= lsb; --i) {             \
    if (topp->name & (1 << i))               \
      bit = 1;                               \
    else                                     \
      bit = 0;                               \
    if (bit ^ previous_output[index]) {      \
      previous_output[index] = bit;          \
      oval.state = (Digital_State_t)bit;     \
      (*pinfo->out_fn)(pinfo, index, &oval); \
    }                                        \
    ++index;                                 \
  }
      
static void step(struct co_info *pinfo)
{
    static Digital_t  oval = {ZERO, STRONG};
    Vlng             *topp;
    int               index, i;
    unsigned char     bit;

    topp = (Vlng *)pinfo->handle;
    topp->eval();

    /* Now scan the outputs for changes. */

    index = 0;
#include "outputs.h"
#include "inouts.h"
}
#undef VL_DATA

extern "C" void Cosim_setup(struct co_info *pinfo)
{
    int i;

    // Setup context, and defaults

    Verilated::debug(0);
    const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};

    // Construct the Verilated model, from Vtop.h generated from Verilating

    Vlng *topp{new Vlng{contextp.get()}};

    /* Return information to caller. */

    pinfo->handle = topp;
    pinfo->step = step;

#define VL_DATA(size, name, msb, lsb) i += msb - lsb + 1; // Count ports

    i = 0;
#include "inputs.h"
    pinfo->in_count = i;

    pinfo->out_count = outs;
    pinfo->inout_count = inouts;
    pinfo->in_fn = accept_input;
    pinfo->method = After_input;  // Verilator requires input to advance.
}
#undef VL_DATA
