You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
6.3 KiB
231 lines
6.3 KiB
/* 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. */
|
|
|
|
#ifndef WITH_TIMING
|
|
/* The simple case is when the Verilog source contained no time delays,
|
|
* or was compiled with compiled with --no-timing.
|
|
*/
|
|
|
|
#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"
|
|
}
|
|
|
|
#else /* WITH_TIMING */
|
|
|
|
#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]) { \
|
|
stop = 1; \
|
|
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};
|
|
VerilatedContext *contextp;
|
|
Vlng *topp;
|
|
double tick;
|
|
uint64_t target, next;
|
|
int index, i, stop = 0;
|
|
unsigned char bit;
|
|
|
|
/* When Verilog source was compiled with --timing, run queued evants
|
|
* until the Verilog simulation catches up with SPICE.
|
|
*/
|
|
|
|
topp = (Vlng *)pinfo->handle;
|
|
contextp = topp->contextp();
|
|
tick = pow(10, contextp->timeprecision());
|
|
target = pinfo->vtime / tick;
|
|
|
|
/* Step the Verilog simulation towards the target time. */
|
|
|
|
do {
|
|
if (topp->eventsPending())
|
|
next = topp->nextTimeSlot();
|
|
else
|
|
next = target;
|
|
if (next >= target) {
|
|
stop = 1;
|
|
next = target;
|
|
}
|
|
contextp->time(next);
|
|
topp->eval();
|
|
|
|
/* Scan for output and stop early if found. */
|
|
|
|
index = 0;
|
|
#include "outputs.h"
|
|
#include "inouts.h"
|
|
} while (!stop);
|
|
|
|
/* Update the shared simulation time on early exit. */
|
|
|
|
if (next < target)
|
|
pinfo->vtime = next * tick;
|
|
}
|
|
|
|
#endif /* WITH_TIMING */
|
|
#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;
|
|
#ifdef WITH_TIMING
|
|
pinfo->method = Both; // There may be immediate results from input.
|
|
#else
|
|
pinfo->method = After_input; // Verilator requires input to advance.
|
|
#endif
|
|
}
|
|
#undef VL_DATA
|