Browse Source
Add the support files for co-simulation with Verilog code
Add the support files for co-simulation with Verilog code
compiled by Verilator. Also add script files to Visual Studio builds that are already installed by the Makefile builds.pre-master-46
11 changed files with 689 additions and 13 deletions
-
10examples/xspice/verilator/README.txt
-
103examples/xspice/verilator/adc.cir
-
45examples/xspice/verilator/adc.v
-
12src/xspice/Makefile.am
-
1src/xspice/verilog/MSVC.CMD
-
3src/xspice/verilog/README.txt
-
13src/xspice/verilog/verilator_main.cpp
-
157src/xspice/verilog/verilator_shim.cpp
-
316src/xspice/verilog/vlnggen
-
21visualc/make-install-vngspice.bat
-
21visualc/make-install-vngspiced.bat
@ -0,0 +1,10 @@ |
|||||
|
The circuit adc.cir in this directory illustrates the use of the d_cosim |
||||
|
XSPICE code model as a container for a Verilog simulation. Before the |
||||
|
simulation can be run, the Verilog code must be compiled by Verilator |
||||
|
using the command: |
||||
|
|
||||
|
ngspice vlnggen adc.v |
||||
|
|
||||
|
That should create a shared library file, adc.so (or adc.DLL on Windows) |
||||
|
that will be loaded by the d_cosim code model. The compiled Verilog code that |
||||
|
it contains will be executed during simulation. |
||||
@ -0,0 +1,103 @@ |
|||||
|
Simulation of a switched-capacitor SAR ADC with Verilator and d_cosim |
||||
|
|
||||
|
.subckt sar_adc input vref start valid d5 d4 d3 d2 d1 d0 clk |
||||
|
|
||||
|
* A transmission gate connects the input to the capacitor set. |
||||
|
|
||||
|
xsample input iin sample vref tgate |
||||
|
rin iin test_v 1k |
||||
|
|
||||
|
* Capacitors and controlling inverters |
||||
|
|
||||
|
xb5 test_v vref d5 ccap c=1p |
||||
|
xb4 test_v vref d4 ccap c={1p / 2} |
||||
|
xb3 test_v vref d3 ccap c={1p / 4} |
||||
|
xb2 test_v vref d2 ccap c={1p / 8} |
||||
|
xb1 test_v vref d1 ccap c={1p / 16} |
||||
|
xb0 test_v vref d0 ccap c={1p / 32} |
||||
|
clast test_v 0 {1p / 32} |
||||
|
|
||||
|
* An XSPICE ADC bridge functions as a comparator. |
||||
|
|
||||
|
acomp [%vd(test_v vref)] [comp] comparator |
||||
|
.model comparator adc_bridge in_low=0 in_high=0 |
||||
|
|
||||
|
* The digital portion of the circuit is specified in compiled Verilog. |
||||
|
* Outputs inverted to cancel the inverter in subcircuit ccap, |
||||
|
* and produce the correct numerical output value. |
||||
|
|
||||
|
adut [ Clk Comp Start] [Sample Valid ~d5 ~d4 ~d3 ~d2 ~d1 ~d0] null dut |
||||
|
.model dut d_cosim simulation="./adc.so" |
||||
|
.ends // SUBCKT sar_adc |
||||
|
|
||||
|
* Some MOS transistors complete the circuit. |
||||
|
* Models from https://homepages.rpi.edu/~sawyes/AIMSPICE_TutorialManual.pdf |
||||
|
|
||||
|
.model p1 pmos |
||||
|
+ level=2 vto=-0.5 kp=8.5e-6 gamma=0.4 phi=0.65 lambda=0.05 xj=0.5e-6 |
||||
|
.model n1 nmos |
||||
|
+ level=2 vto=0.5 kp=24e-6 gamma=0.15 phi=0.65 lambda=0.015 xj=0.5e-6 |
||||
|
|
||||
|
* Use those for an inverter. |
||||
|
|
||||
|
.subckt ainv in out vdd |
||||
|
mn out in 0 0 n1 |
||||
|
mp out in vdd vdd p1 |
||||
|
.ends |
||||
|
|
||||
|
* A transmission gate modelled by a switch. |
||||
|
|
||||
|
.subckt mos_tgate a b ctl vdd |
||||
|
mn a ctl b b n1 |
||||
|
xinv ctl ictl vdd ainv |
||||
|
mp b ictl a a p1 |
||||
|
.ends |
||||
|
|
||||
|
.subckt tgate a b ctl vdd |
||||
|
switch a b ctl 0 tg |
||||
|
.model tg sw vt=1.5 ron=2k |
||||
|
.ends |
||||
|
|
||||
|
* The per-bit subcircuit in the adc |
||||
|
|
||||
|
.subckt ccap in vcc ctl c=10p |
||||
|
xinv ctl tail vcc ainv |
||||
|
cb in tail {c} |
||||
|
.ends |
||||
|
|
||||
|
**** End of the ADC and its subcircuits. Begin test circuit **** |
||||
|
|
||||
|
.param vcc=3.3 |
||||
|
vcc vcc 0 {vcc} |
||||
|
|
||||
|
* Digital clock signal |
||||
|
|
||||
|
aclock 0 clk clock |
||||
|
.model clock d_osc cntl_array=[-1 1] freq_array=[1Meg 1Meg] |
||||
|
|
||||
|
* A simple DAC so that the result may be compared to the input. |
||||
|
|
||||
|
r5 d5 sum 2 |
||||
|
r4 d4 sum 4 |
||||
|
r3 d3 sum 8 |
||||
|
r2 d2 sum 16 |
||||
|
r1 d1 sum 32 |
||||
|
r0 d0 sum 64 |
||||
|
|
||||
|
vamm sum 0 0 |
||||
|
|
||||
|
* Pulse the Start signal high for 1.3uS each 10uS |
||||
|
|
||||
|
Vpulse Start 0 PULSE 0 {vcc} 0.2u 10n 10n 1.3u 10u |
||||
|
Vtest input 0 PULSE 0 3 0 200u 200u 1u 401u |
||||
|
|
||||
|
* The ADC for testing |
||||
|
|
||||
|
xtest input vcc start valid d5 d4 d3 d2 d1 d0 clk sar_adc |
||||
|
|
||||
|
|
||||
|
.control |
||||
|
tran 100n 250u |
||||
|
plot input xtest.test_v vamm#branch clk/2 start/3 xtest.sample/3 valid |
||||
|
.endc |
||||
|
.end |
||||
@ -0,0 +1,45 @@ |
|||||
|
// Digital control for a successive approximation ADC with switched capacitors. |
||||
|
|
||||
|
module adc(Clk, Comp, Start, Sample, Done, Result); |
||||
|
input wire Clk, Comp, Start; |
||||
|
output reg Sample, Done; |
||||
|
output reg [Bits - 1 : 0] Result; |
||||
|
|
||||
|
parameter Bits=6; |
||||
|
|
||||
|
reg [Bits - 1 : 0] SR; |
||||
|
reg Running; |
||||
|
|
||||
|
initial begin |
||||
|
$display("ADC simulation starting"); |
||||
|
Done = 0; |
||||
|
Sample = 0; |
||||
|
Result = 0; |
||||
|
Running = 0; |
||||
|
end |
||||
|
|
||||
|
always @(posedge(Clk)) begin |
||||
|
if (Running) begin |
||||
|
if (Sample) begin |
||||
|
Sample <= 0; |
||||
|
SR[Bits - 1] = 1; |
||||
|
Result[Bits - 1] = 1; |
||||
|
end else if (SR != 0) begin |
||||
|
if (Comp) |
||||
|
Result &= ~SR; |
||||
|
SR >>= 1; |
||||
|
Result |= SR; |
||||
|
if (SR == 0) begin |
||||
|
Running <= 0; |
||||
|
Done <= 1; |
||||
|
end |
||||
|
end |
||||
|
end else if (Start) begin |
||||
|
Running <= 1; |
||||
|
Sample <= 1; |
||||
|
Done <= 0; |
||||
|
SR = 0; |
||||
|
Result = 0; |
||||
|
end |
||||
|
end |
||||
|
endmodule |
||||
@ -0,0 +1 @@ |
|||||
|
CL /O2 /LD /EHsc /Fe..\adc.DLL /I. /IC:\mingw64\share\verilator\include\vltstd /IC:\mingw64\share\verilator\include Vlng__ALL.cpp verilator_shim.cpp C:\mingw64\share\verilator\include\verilated.cpp C:\mingw64\share\verilator\include\verilated_threads.cpp /link /DLL /EXPORT:Cosim_setup |
||||
@ -0,0 +1,3 @@ |
|||||
|
This directory contains Ngspice scripts and other files used to prepare |
||||
|
Verilog (and possibly VHDL) code to be included in an Ngspice simulation. |
||||
|
An example circuit can be found in examples/xspice/verilator. |
||||
@ -0,0 +1,13 @@ |
|||||
|
/* Dummy main() for Verilator. */ |
||||
|
|
||||
|
#include "ngspice/cmtypes.h" // For Digital_t
|
||||
|
#include "ngspice/cosim.h" // For struct co_info and prototypes
|
||||
|
|
||||
|
int main(int argc, char** argv, char**) { |
||||
|
struct co_info info; |
||||
|
|
||||
|
Cosim_setup(&info); |
||||
|
for (;;) |
||||
|
(*info.step)(&info); |
||||
|
return 0; |
||||
|
} |
||||
@ -0,0 +1,157 @@ |
|||||
|
/* 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
|
||||
@ -0,0 +1,316 @@ |
|||||
|
*ng_script_with_params |
||||
|
// This Ngspice interpreter script accepts arbitrary argiments to |
||||
|
// the Verilator compiler (Verilog to C++) and builds a shared library |
||||
|
// or DLL that can be loaded by the d_cosim XSPICE code model. |
||||
|
// Instances of the model are then digital circuit elements whose |
||||
|
// behaviour is controlled by the Verilog source. |
||||
|
|
||||
|
set bad=0 |
||||
|
if $?argc = 0 |
||||
|
set bad=1 |
||||
|
end |
||||
|
|
||||
|
if $argc <= 0 |
||||
|
set bad=1 |
||||
|
end |
||||
|
|
||||
|
if $bad |
||||
|
echo Arguments acceptable to Verilator are required. |
||||
|
quit |
||||
|
end |
||||
|
|
||||
|
// Disable special processing of '{'. |
||||
|
|
||||
|
set noglob |
||||
|
|
||||
|
// Set parameters for Windows or Unix-like OS. |
||||
|
// For setting CFLAGS (passed to Verilator) it is somewhat arbitrarily |
||||
|
// assumed that if Ngspice was compiled with VisualC++, then that is |
||||
|
// the compiler to be used with Verilator. Edit to change. |
||||
|
|
||||
|
// Compilation option for C/C++: -fpic is required by GCC for a shared library |
||||
|
|
||||
|
if $oscompiled = 8 // VisualC++ - Verilator is a Perl script |
||||
|
setcs cflags="--CFLAGS -fpic --compiler msvc" |
||||
|
else |
||||
|
setcs cflags="--CFLAGS -fpic" // For g++ |
||||
|
end |
||||
|
|
||||
|
if $oscompiled = 2 | $oscompiled = 3 | $oscompiled = 8 // Windows |
||||
|
set windows=1 |
||||
|
set dirsep1="\\" |
||||
|
set dirsep2="/" |
||||
|
set vloc="C:/mingw64/bin/verilator" // Expected location on Windows |
||||
|
set run_verilator="perl $vloc" |
||||
|
else |
||||
|
set windows=0 |
||||
|
set dirsep1="/" |
||||
|
set run_verilator=verilator |
||||
|
end |
||||
|
|
||||
|
if $oscompiled = 7 // MacOS |
||||
|
set macos=1 |
||||
|
setcs cflags="$cflags --compiler clang" |
||||
|
else |
||||
|
set macos=0 |
||||
|
end |
||||
|
|
||||
|
// Loop through the arguments to find Verilog source: some_path/xxxx.v |
||||
|
// The output file will have the same base name. |
||||
|
|
||||
|
let index=1 |
||||
|
set off=1 // Avoid error in dowhile |
||||
|
repeat $argc |
||||
|
set base="$argv[$&index]" |
||||
|
let index = index + 1 |
||||
|
strstr l "$base" "" |
||||
|
if $l > 2 // Look for xxxx.v |
||||
|
strslice tail "$base" -2 2 |
||||
|
strcmp bad "$tail" ".v" |
||||
|
if $bad <> 0 |
||||
|
set base="" |
||||
|
continue |
||||
|
end |
||||
|
let l = $l - 2 |
||||
|
strslice base "$base" 0 $&l |
||||
|
else |
||||
|
set base="" |
||||
|
continue |
||||
|
end |
||||
|
|
||||
|
dowhile $off >= 0 // Strip leading directories |
||||
|
strstr off "$base" "$dirsep1" |
||||
|
if $windows |
||||
|
if $off < 0 |
||||
|
strstr off "$base" "$dirsep2" |
||||
|
end |
||||
|
end |
||||
|
if $off >= 0 |
||||
|
let off=$off+1 |
||||
|
strslice base "$base" $&off $l |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
strstr l "$base" "" // Check for zero-length string |
||||
|
if $l > 0 |
||||
|
break |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
if index - 1 > $argc |
||||
|
set base=verilated // Default name |
||||
|
end |
||||
|
|
||||
|
// Define working directory for Verilator |
||||
|
|
||||
|
set tail="_obj_dir" |
||||
|
setcs objdir="$base$tail" |
||||
|
|
||||
|
// Default base name of output file. |
||||
|
|
||||
|
if $windows |
||||
|
setcs tail=".DLL" |
||||
|
else |
||||
|
setcs tail=".so" |
||||
|
end |
||||
|
setcs soname="$base$tail" |
||||
|
|
||||
|
// First convert to C++, PREFIX determines the file names. |
||||
|
|
||||
|
setcs prefix="Vlng" |
||||
|
|
||||
|
// Run Verilator on the given input files. |
||||
|
|
||||
|
shell $run_verilator --Mdir $objdir --prefix $prefix $cflags --cc $argv |
||||
|
|
||||
|
// Parse the primary interface Class definition for members representing |
||||
|
// the ports of the top-level Verilog module. |
||||
|
// Example conversion: VL_IN8(&Clk,0,0); ==> VL_DATA(8,Clk,0,0) |
||||
|
|
||||
|
cd $objdir |
||||
|
echo "/* Generated code: do not edit. */" > inouts.h |
||||
|
echo "/* Generated code: do not edit. */" > inputs.h |
||||
|
echo "/* Generated code: do not edit. */" > outputs.h |
||||
|
|
||||
|
// This loop is intended to have the same effect as: |
||||
|
// sed --quiet -e 's/VL_IN\([0-9]*\)(&\(.*\);/VL_DATA(\1,\2/p' \ |
||||
|
// obj_dir/${PREFIX}.h >> inputs.h |
||||
|
|
||||
|
set htail=".h" |
||||
|
setcs inout="VL_INOUT" |
||||
|
setcs in="VL_IN" |
||||
|
setcs out="VL_OUT" |
||||
|
|
||||
|
set fn="$prefix$htail" // Like foo-obj_dir/Vlng.h |
||||
|
fopen fh $fn |
||||
|
if $fh < 0 |
||||
|
quit |
||||
|
end |
||||
|
|
||||
|
while 1 |
||||
|
fread line $fh l |
||||
|
if $l < 0 |
||||
|
break |
||||
|
end |
||||
|
|
||||
|
// Does it contain a closing parenthesis? |
||||
|
|
||||
|
strstr off "$line" ")" |
||||
|
if $off < 0 |
||||
|
continue // No ")", ignore. |
||||
|
end |
||||
|
let off = $off + 1 |
||||
|
strslice line "$line" 0 $&off // Slice off tail. |
||||
|
|
||||
|
// Is it an inout port definition? |
||||
|
|
||||
|
strstr off "$line" $inout |
||||
|
if $off >= 0 // Match found |
||||
|
let off = $off + 8 // strlen("VL_INOUT") == 8 |
||||
|
strslice line "$line" $&off $l |
||||
|
strstr off "$line" "(" |
||||
|
strslice size "$line" 0 $off |
||||
|
let off = $off + 2 // strlen("(&") == 2 |
||||
|
strslice line "$line" $&off $l |
||||
|
echo VL_DATA($size,$line >> inouts.h // New macro invocation |
||||
|
continue |
||||
|
end |
||||
|
|
||||
|
// Input port? |
||||
|
|
||||
|
strstr off "$line" $in |
||||
|
if $off >= 0 // Match found |
||||
|
let off = $off + 5 // strlen("VL_IN") == 5 |
||||
|
strslice line "$line" $&off $l |
||||
|
strstr off "$line" "(" |
||||
|
strslice size "$line" 0 $off |
||||
|
let off = $off + 2 // strlen("(&") == 2 |
||||
|
strslice line "$line" $&off $l |
||||
|
echo VL_DATA($size,$line >> inputs.h // New macro invocation |
||||
|
continue |
||||
|
end |
||||
|
|
||||
|
// Output port? |
||||
|
|
||||
|
strstr off "$line" $out |
||||
|
if $off >= 0 // Match found |
||||
|
let off = $off + 6 // strlen("VL_OUT") == 6 |
||||
|
strslice line "$line" $&off $l |
||||
|
strstr off "$line" "(" |
||||
|
strslice size "$line" 0 $off |
||||
|
let off = $off + 2 // strlen("(&") == 2 |
||||
|
strslice line "$line" $&off $l |
||||
|
echo VL_DATA($size,$line >> outputs.h // New macro invocation |
||||
|
continue |
||||
|
end |
||||
|
end |
||||
|
fclose $fh |
||||
|
cd .. |
||||
|
|
||||
|
// The shared library/DLL contains some ngspice source code as |
||||
|
// well as that created by Verilator. Find it by scanning $sourcepath. |
||||
|
|
||||
|
set shimfile=verilator_shim.cpp |
||||
|
set shimobj=verilator_shim.o |
||||
|
set mainfile=verilator_main.cpp |
||||
|
set srcdir=src |
||||
|
set silent_fileio // Silences fopen complaints |
||||
|
|
||||
|
let i=1 |
||||
|
repeat $#sourcepath |
||||
|
set stem="$sourcepath[$&i]" |
||||
|
let i = i + 1 |
||||
|
set fn="$stem$dirsep1$shimfile" |
||||
|
fopen fh $fn |
||||
|
if $fh > 0 |
||||
|
break |
||||
|
end |
||||
|
set stem="$stem$dirsep1$srcdir" |
||||
|
set fn="$stem$dirsep1$shimfile" |
||||
|
fopen fh $fn |
||||
|
if $fh > 0 |
||||
|
break |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
if $fh > 0 |
||||
|
fclose $fh |
||||
|
set fn_main="$stem$dirsep1$mainfile" |
||||
|
else |
||||
|
echo Can not find C++ source file $shimfile |
||||
|
quit |
||||
|
end |
||||
|
|
||||
|
if $windows |
||||
|
// Verilator makes a mess of absolute include paths passed by --CFLAGS. |
||||
|
// Copy the files instead. |
||||
|
|
||||
|
set incdir=ngspice |
||||
|
shell xcopy /i "$stem$dirsep1$incdir" "$objdir$dirsep1$incdir" |
||||
|
setcs include="--CFLAGS -I." |
||||
|
|
||||
|
// Copy verilator_shim.cpp for MSVC.CMD. |
||||
|
|
||||
|
shell copy "$fn" "$objdir" |
||||
|
else |
||||
|
// Some header files are with the source. |
||||
|
|
||||
|
strstr off "$stem" "." |
||||
|
if $off <> 0 |
||||
|
setcs include="--CFLAGS -I$stem" |
||||
|
else |
||||
|
setcs include="--CFLAGS -I..$dirsep1$stem" // Relative path |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
|
||||
|
// Compile the code. Verilator only does that when building an executable, |
||||
|
// so include verilator_main.cpp. |
||||
|
|
||||
|
shell $run_verilator --Mdir $objdir --prefix $prefix $include $cflags |
||||
|
+ --cc --build --exe |
||||
|
+ $fn_main $fn $argv |
||||
|
|
||||
|
strcmp bad "$shellstatus" "0" |
||||
|
|
||||
|
if $bad = 0 |
||||
|
// g++ must be available: make a shared library/DLL. |
||||
|
|
||||
|
set v_objs="$objdir$dirsep1$shimobj $objdir/verilated.o $objdir/verilated_threads.o" |
||||
|
setcs tail="__ALL.a" |
||||
|
setcs v_lib="$objdir/$prefix$tail" // Like Vlng__ALL.a |
||||
|
|
||||
|
shell g++ --shared $v_objs $v_lib -pthread -lpthread -o $soname |
||||
|
else |
||||
|
// Assume we have CL.EXE and use that. A script avoids multiple \escapes. |
||||
|
|
||||
|
if $windows = 0 |
||||
|
quit |
||||
|
end |
||||
|
|
||||
|
// Look for MSVC.CMD |
||||
|
|
||||
|
set msvcfile=MSVC.CMD |
||||
|
let i=1 |
||||
|
repeat $#sourcepath |
||||
|
set stem="$sourcepath[$&i]" |
||||
|
let i = i + 1 |
||||
|
set fn="$stem$dirsep1$msvcfile" |
||||
|
fopen fh $fn |
||||
|
if $fh > 0 |
||||
|
break |
||||
|
end |
||||
|
end |
||||
|
if $fh > 0 |
||||
|
fclose $fh |
||||
|
else |
||||
|
echo Can not find bulid file $msvcfile |
||||
|
quit |
||||
|
end |
||||
|
|
||||
|
echo Building with MSVC compiler, CL.EXE. |
||||
|
cd $objdir |
||||
|
shell $fn |
||||
|
cd .. |
||||
|
end |
||||
|
quit |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue