summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Example/2-bit-inverter/2-bit-inverter.cir36
-rw-r--r--Example/2-bit-inverter/inverter.vhdl14
-rw-r--r--Example/bin_to_gray/bin_to_gray.vhdl21
-rw-r--r--Example/counter/counter.vhdl30
-rw-r--r--Example/counter/updown_counter.vhdl32
-rw-r--r--Example/decoder/decoder.vhdl50
-rw-r--r--Example/full_adder/full_adder_sl.vhdl19
-rw-r--r--Example/full_adder/full_adder_sl_slv.vhdl19
-rw-r--r--Example/full_adder/full_adder_slv.vhdl19
-rw-r--r--Example/full_adder/full_adder_structural.vhdl87
-rw-r--r--Example/half_adder/half_adder.vhdl18
-rw-r--r--Example/logic_gates/inverter_gate.vhdl14
-rw-r--r--Example/logic_gates/xor_gate.vhdl13
-rw-r--r--Example/mux-demux/demux.vhdl32
-rw-r--r--Example/mux-demux/mux.vhdl30
-rw-r--r--Example/xor/myxor.vhdl15
-rw-r--r--Example/xor/xor-test.cir45
-rw-r--r--Workflow.md102
-rw-r--r--ghdl-0.36.tar.gzbin0 -> 4333562 bytes
-rw-r--r--install list10
-rwxr-xr-xinstall-nghdl.sh258
-rw-r--r--nghdl_document.pdfbin0 -> 153016 bytes
-rw-r--r--ngspice-nghdl.tar.gzbin7019178 -> 8684202 bytes
-rw-r--r--src/createKicadLibrary.py23
-rwxr-xr-xsrc/ghdlserver/Vhpi_Package.vhdl16
-rw-r--r--src/ghdlserver/ghdlserver.c645
-rw-r--r--src/ghdlserver/ghdlserver.h3
-rw-r--r--src/model_generation.py241
-rwxr-xr-xsrc/ngspice_ghdl.py24
-rw-r--r--src/outitf.c891
30 files changed, 1792 insertions, 915 deletions
diff --git a/Example/2-bit-inverter/2-bit-inverter.cir b/Example/2-bit-inverter/2-bit-inverter.cir
deleted file mode 100644
index 88580dd..0000000
--- a/Example/2-bit-inverter/2-bit-inverter.cir
+++ /dev/null
@@ -1,36 +0,0 @@
-* analysis type *
-.tran 1n 100n
-*
-* input sources *
-v1 100 0 DC PWL ( 0n 0.0 5n 0.0 5.1n 2.0 10n 0.0 10.1n 2.0 15n 2.0 15.1n 2.0 20n 0 20.1n 2.0 25n 2.0 25.1n 2.0 30n 2.0 30.1n 2.0
- + 40n 0.0 50n 0.0 50.1n 2.0 60n 2.0 60.1n 0.0 70n 0.0 70.1n 2.0 80n 2.0 80.1n 0.0 90n 0.0 100n 2.0)
-
-v2 200 0 DC PWL ( 0n 2.0 5n 2.0 5.1n 0.0 10n 0.0 10.1n 2.0 15n 2.0 15.1n 0.0 20n 0 20.1n 2.0 25n 2.0 25.1n 0.0 30n 2.0 30.1n 2.0
- + 40n 0.0 50n 0.0 50.1n 2.0 60n 2.0 60.1n 0.0 70n 0.0 70.1n 2.0 80n 2.0 80.1n 0.0 90n 0.0 100n 2.0)
-
-* resistors to ground *
-r1 100 0 1k
-r2 200 0 1k
-
-rload1 300 0 10k
-rload2 400 0 10k
-*
-* adc_bridge blocks *
-aconverter1 [100 200] [1 2] adc_bridge1
-
-.model adc_bridge1 adc_bridge ( in_low =0.3 in_high =0.7
-+ rise_delay =1.0e-12 fall_delay =1.0e-12)
-
-ainverter [1 2] [10 20] inv1
-
-.model inv1 inverter(instance_id = 101 rise_delay = 1.0e-12 fall_delay = 1.0e-12 stop_time=90e-9)
-
-
-aconverter2 [10 20] [30 40] dac_bridge1
-
-.model dac_bridge1 dac_bridge( out_low=0.25 out_high=5.0
-+out_undef=1.8 t_rise=0.5e-9 t_fall=0.5e-9)
-
-.end
-
-
diff --git a/Example/2-bit-inverter/inverter.vhdl b/Example/2-bit-inverter/inverter.vhdl
deleted file mode 100644
index 9d65b8d..0000000
--- a/Example/2-bit-inverter/inverter.vhdl
+++ /dev/null
@@ -1,14 +0,0 @@
-library ieee;
-use ieee.std_logic_1164.all;
-
-entity inverter is
- port ( i: in std_logic_vector(1 downto 0);
- o: out std_logic_vector(1 downto 0));
-end inverter;
-
-architecture inverter_beh of inverter is
-begin
- o <= not i;
-end architecture;
-
-
diff --git a/Example/bin_to_gray/bin_to_gray.vhdl b/Example/bin_to_gray/bin_to_gray.vhdl
new file mode 100644
index 0000000..d6045e8
--- /dev/null
+++ b/Example/bin_to_gray/bin_to_gray.vhdl
@@ -0,0 +1,21 @@
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+
+entity bin_to_gray is
+port(
+ bin : in std_logic_vector(3 downto 0);
+ G : out std_logic_vector(3 downto 0)
+ );
+end bin_to_gray;
+
+
+architecture gate_level of bin_to_gray is
+
+begin
+
+G(3) <= bin(3);
+G(2) <= bin(3) xor bin(2);
+G(1) <= bin(2) xor bin(1);
+G(0) <= bin(1) xor bin(0);
+
+end gate_level; \ No newline at end of file
diff --git a/Example/counter/counter.vhdl b/Example/counter/counter.vhdl
new file mode 100644
index 0000000..ba14df8
--- /dev/null
+++ b/Example/counter/counter.vhdl
@@ -0,0 +1,30 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity counter is
+port(C : in std_logic;
+ CLR : in std_logic;
+ Q : out std_logic_vector(3 downto 0));
+end counter;
+
+architecture bhv of counter is
+
+ signal tmp: std_logic_vector(3 downto 0);
+ begin
+ process (C, CLR)
+
+ begin
+ if (CLR='1') then
+ tmp <= "0000";
+
+ elsif (C'event and C='1') then
+ tmp <= std_logic_vector(to_unsigned(1+to_integer(unsigned(tmp)), tmp'length));
+
+ end if;
+
+ end process;
+ Q <= tmp;
+
+end bhv; \ No newline at end of file
diff --git a/Example/counter/updown_counter.vhdl b/Example/counter/updown_counter.vhdl
new file mode 100644
index 0000000..922ee67
--- /dev/null
+++ b/Example/counter/updown_counter.vhdl
@@ -0,0 +1,32 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+
+
+entity updown_counter is
+ Port ( clk: in std_logic;
+ reset: in std_logic;
+ up_down: in std_logic;
+ counter: out std_logic_vector(3 downto 0)
+ );
+end updown_counter;
+
+architecture Behavioral of updown_counter is
+signal tmp: std_logic_vector(3 downto 0);
+begin
+
+process(clk,reset)
+begin
+ if(reset='1') then
+ tmp <= "0000";
+ elsif(clk'event and clk='1') then
+ if(up_down='1') then
+ tmp <= std_logic_vector(to_unsigned(to_integer(unsigned(tmp)-1), tmp'length));
+ else
+ tmp <= std_logic_vector(to_unsigned(to_integer(unsigned(tmp)+1), tmp'length));
+ end if;
+ end if;
+end process;
+ counter <= std_logic_vector(tmp);
+
+end Behavioral; \ No newline at end of file
diff --git a/Example/decoder/decoder.vhdl b/Example/decoder/decoder.vhdl
new file mode 100644
index 0000000..e429ec9
--- /dev/null
+++ b/Example/decoder/decoder.vhdl
@@ -0,0 +1,50 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity decoder is
+port (
+ p : in std_logic_vector(4 downto 0);
+ d : out std_logic_vector(31 downto 0)
+ );
+end decoder;
+
+architecture behav of decoder is
+
+begin
+
+with p select
+d<="00000000000000000000000000000001" when "00000",
+"00000000000000000000000000000010" when "00001",
+"00000000000000000000000000000100" when "00010",
+"00000000000000000000000000001000" when "00011",
+"00000000000000000000000000010000" when "00100",
+"00000000000000000000000000100000" when "00101",
+"00000000000000000000000001000000" when "00110",
+"00000000000000000000000010000000" when "00111",
+"00000000000000000000000100000000" when "01000",
+"00000000000000000000001000000000" when "01001",
+"00000000000000000000010000000000" when "01010",
+"00000000000000000000100000000000" when "01011",
+"00000000000000000001000000000000" when "01100",
+"00000000000000000010000000000000" when "01101",
+"00000000000000000100000000000000" when "01110",
+"00000000000000001000000000000000" when "01111",
+"00000000000000010000000000000000" when "10000",
+"00000000000000100000000000000000" when "10001",
+"00000000000001000000000000000000" when "10010",
+"00000000000010000000000000000000" when "10011",
+"00000000000100000000000000000000" when "10100",
+"00000000001000000000000000000000" when "10101",
+"00000000010000000000000000000000" when "10110",
+"00000000100000000000000000000000" when "10111",
+"00000001000000000000000000000000" when "11000",
+"00000010000000000000000000000000" when "11001",
+"00000100000000000000000000000000" when "11010",
+"00001000000000000000000000000000" when "11011",
+"00010000000000000000000000000000" when "11100",
+"00100000000000000000000000000000" when "11101",
+"01000000000000000000000000000000" when "11110",
+"10000000000000000000000000000000" when "11111",
+"00000000000000000000000000000000" when others;
+
+end behav;
diff --git a/Example/full_adder/full_adder_sl.vhdl b/Example/full_adder/full_adder_sl.vhdl
new file mode 100644
index 0000000..e830563
--- /dev/null
+++ b/Example/full_adder/full_adder_sl.vhdl
@@ -0,0 +1,19 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity full_adder_sl is
+ port (
+ i_bit1 : in std_logic;
+ i_bit2 : in std_logic;
+ i_bit3 : in std_logic;
+ o_sum : out std_logic;
+ o_carry : out std_logic
+ );
+end full_adder_sl;
+
+architecture rtl of full_adder_sl is
+begin
+ o_sum <= i_bit1 xor i_bit2 xor i_bit3;
+ o_carry <= (i_bit1 and i_bit2) or (i_bit2 and i_bit3) or (i_bit3 and i_bit1);
+end rtl; \ No newline at end of file
diff --git a/Example/full_adder/full_adder_sl_slv.vhdl b/Example/full_adder/full_adder_sl_slv.vhdl
new file mode 100644
index 0000000..7de9c1b
--- /dev/null
+++ b/Example/full_adder/full_adder_sl_slv.vhdl
@@ -0,0 +1,19 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity full_adder_sl_slv is
+ port (
+ i_bit1 : in std_logic;
+ i_bit2 : in std_logic;
+ i_bit3 : in std_logic_vector(0 downto 0);
+ o_sum : out std_logic;
+ o_carry : out std_logic_vector(0 downto 0)
+ );
+end full_adder_sl_slv;
+
+architecture rtl of full_adder_sl_slv is
+begin
+ o_sum <= i_bit1 xor i_bit2 xor i_bit3(0);
+ o_carry(0) <= (i_bit1 and i_bit2) or (i_bit2 and i_bit3(0)) or (i_bit3(0) and i_bit1);
+end rtl; \ No newline at end of file
diff --git a/Example/full_adder/full_adder_slv.vhdl b/Example/full_adder/full_adder_slv.vhdl
new file mode 100644
index 0000000..a0495f0
--- /dev/null
+++ b/Example/full_adder/full_adder_slv.vhdl
@@ -0,0 +1,19 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity full_adder_slv is
+ port (
+ i_bit1 : in std_logic_vector(0 downto 0);
+ i_bit2 : in std_logic_vector(0 downto 0);
+ i_bit3 : in std_logic_vector(0 downto 0);
+ o_sum : out std_logic_vector(0 downto 0);
+ o_carry : out std_logic_vector(0 downto 0)
+ );
+end full_adder_slv;
+
+architecture rtl of full_adder_slv is
+begin
+ o_sum <= i_bit1 xor i_bit2 xor i_bit3;
+ o_carry <= (i_bit1 and i_bit2) or (i_bit2 and i_bit3) or (i_bit3 and i_bit1);
+end rtl;
diff --git a/Example/full_adder/full_adder_structural.vhdl b/Example/full_adder/full_adder_structural.vhdl
new file mode 100644
index 0000000..eb06a3d
--- /dev/null
+++ b/Example/full_adder/full_adder_structural.vhdl
@@ -0,0 +1,87 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity full_adder_structural is
+port(a: in std_logic;
+ b: in std_logic;
+ cin: in std_logic;
+ sum: out std_logic;
+ carry: out std_logic);
+end full_adder_structural;
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity andgate is
+port(a: in std_logic;
+ b: in std_logic;
+ z: out std_logic);
+end andgate;
+
+architecture e1 of andgate is
+begin
+z <= a and b;
+end e1;
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity xorgate is
+port(a: in std_logic;
+ b: in std_logic;
+ z: out std_logic);
+end xorgate;
+
+architecture e2 of xorgate is
+begin
+z <= a xor b;
+end e2;
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity orgate is
+port(a: in std_logic;
+ b: in std_logic;
+ z: out std_logic);
+end orgate;
+
+architecture e3 of orgate is
+begin
+z <= a or b;
+end e3;
+
+
+
+architecture structural of full_adder_structural is
+
+component andgate
+port(a: in std_logic;
+ b: in std_logic;
+ z: out std_logic);
+end component;
+
+component xorgate
+port(a: in std_logic;
+ b: in std_logic;
+ z: out std_logic);
+end component;
+
+component orgate
+port(a: in std_logic;
+ b: in std_logic;
+ z: out std_logic);
+end component;
+
+signal c1,c2,c3: std_logic;
+
+begin
+
+u1 : xorgate port map(a,b,c1);
+u2 : xorgate port map(c1,cin,sum);
+u3 : andgate port map(c1,cin,c2);
+u4 : andgate port map(a,b,c3);
+u5 : orgate port map(c2,c3,carry);
+
+
+end structural; \ No newline at end of file
diff --git a/Example/half_adder/half_adder.vhdl b/Example/half_adder/half_adder.vhdl
new file mode 100644
index 0000000..71ef1cc
--- /dev/null
+++ b/Example/half_adder/half_adder.vhdl
@@ -0,0 +1,18 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity half_adder is
+ port (
+ i_bit0 : in std_logic_vector(0 downto 0);
+ i_bit1 : in std_logic_vector(0 downto 0);
+ o_sum : out std_logic_vector(0 downto 0);
+ o_carry : out std_logic_vector(0 downto 0)
+ );
+end half_adder;
+
+architecture rtl of half_adder is
+begin
+ o_sum <= i_bit0 xor i_bit1;
+ o_carry <= i_bit0 and i_bit1;
+end rtl;
diff --git a/Example/logic_gates/inverter_gate.vhdl b/Example/logic_gates/inverter_gate.vhdl
new file mode 100644
index 0000000..9825917
--- /dev/null
+++ b/Example/logic_gates/inverter_gate.vhdl
@@ -0,0 +1,14 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity inverter_gate is
+ port ( i: in std_logic;
+ o: out std_logic);
+end inverter_gate;
+
+architecture beh of inverter_gate is
+begin
+ o <= not i;
+end beh;
+
+
diff --git a/Example/logic_gates/xor_gate.vhdl b/Example/logic_gates/xor_gate.vhdl
new file mode 100644
index 0000000..da0da23
--- /dev/null
+++ b/Example/logic_gates/xor_gate.vhdl
@@ -0,0 +1,13 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity xor_gate is
+ port (a : in std_logic;
+ b : in std_logic;
+ c : out std_logic);
+end xor_gate;
+
+architecture rtl of xor_gate is
+ begin
+ c <= a xor b;
+end rtl;
diff --git a/Example/mux-demux/demux.vhdl b/Example/mux-demux/demux.vhdl
new file mode 100644
index 0000000..e73c196
--- /dev/null
+++ b/Example/mux-demux/demux.vhdl
@@ -0,0 +1,32 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+
+entity demux is
+ port(
+
+ F : in STD_LOGIC_vector(0 downto 0);
+ S0: in STD_LOGIC_vector(0 downto 0);
+ S1: in STD_LOGIC_vector(0 downto 0);
+ A: out STD_LOGIC_vector(0 downto 0);
+ B: out STD_LOGIC_vector(0 downto 0);
+ C: out STD_LOGIC_vector(0 downto 0);
+ D: out STD_LOGIC_vector(0 downto 0)
+ );
+end demux;
+
+architecture bhv of demux is
+begin
+process (F,S0,S1) is
+begin
+ if (S0 ="0" and S1 = "0") then
+ A <= F;
+ elsif (S0 ="1" and S1 = "0") then
+ B <= F;
+ elsif (S0 ="0" and S1 = "1") then
+ C <= F;
+ else
+ D <= F;
+ end if;
+
+end process;
+end bhv;
diff --git a/Example/mux-demux/mux.vhdl b/Example/mux-demux/mux.vhdl
new file mode 100644
index 0000000..b72e287
--- /dev/null
+++ b/Example/mux-demux/mux.vhdl
@@ -0,0 +1,30 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+
+entity mux is
+ port(A : in std_logic;
+ B : in std_logic;
+ C : in std_logic;
+ D : in std_logic;
+ S0 : in std_logic;
+ S1 : in std_logic;
+ Z: out std_logic);
+end mux;
+
+architecture bhv of mux is
+begin
+process (A,B,C,D,S0,S1) is
+begin
+ if (S0 ='0' and S1 = '0') then
+ Z <= A;
+ elsif (S0 ='0' and S1 = '1') then
+ Z <= B;
+ elsif (S0 ='1' and S1 = '0') then
+ Z <= C;
+ else
+ Z <= D;
+ end if;
+
+end process;
+end bhv;
+
diff --git a/Example/xor/myxor.vhdl b/Example/xor/myxor.vhdl
deleted file mode 100644
index b49f3ca..0000000
--- a/Example/xor/myxor.vhdl
+++ /dev/null
@@ -1,15 +0,0 @@
-library ieee;
-use ieee.std_logic_1164.all;
-
-entity myxor is
- port (a : in std_logic_vector(0 downto 0);
- b : in std_logic_vector(0 downto 0);
- c : out std_logic_vector(0 downto 0));
- end myxor;
-
- architecture rtl of myxor is
- begin
-
- c <= a xor b;
-
- end rtl;
diff --git a/Example/xor/xor-test.cir b/Example/xor/xor-test.cir
deleted file mode 100644
index 910839e..0000000
--- a/Example/xor/xor-test.cir
+++ /dev/null
@@ -1,45 +0,0 @@
-
-*** input sources ***
-
-v1 100 0 DC PWL ( 0n 0.0 5n 0.0 5.1n 2.0 10n 2.0 10.1n 2.0 15n 2.0 15.1n 0.0 20.0n 0.0 20.1n 2.0 25n 2.0 25.1n 0.0 30n 0.0 30.1n 2.0
- +40.0 2.0 40.1n 0.0 50n 0.0 50.1n 2.0 60n 2.0 60.1n 0.0 70n 0.0 70.1n 2.0 80n 2.0 80.1n 0.0 90n 0.0 100n 0.0)
-
-v2 200 0 DC PWL (0n 2.0 5n 2.0 10n 2.0 15n 2.0 15.1n 0.0 20n 0.0 25n 0.0 30n 0.0 30.1n 2.0 40n 2.0 40.1n 0.0 45n 0.0 45.1n 2.0
- + 50n 2.0 50.1n 0.0 60.0n 0.0 70n 0.0 80n 0.0 90n 0.0 95n 0.0 95.1n 2.0 100n 2.0)
-
-Vvdd vdd 0 DC 2.0
-
-*** resistors to ground ***
-r1 100 0 1k
-r2 200 0 1k
-
-
-*
-*** adc_bridge blocks ***
-aconverter1 [100 200 ] [1 2] adc
-
-
-axor [1] [2] [12] axors
-
-adac1 [12] [34] dac
-*************model***********
-
-.model axors myxor(instance_id = 112 rise_delay = 1.0e-10 fall_delay = 1.0e-10 stop_time=90n)
-
-.model adc adc_bridge ( in_low =0.5 in_high =1.0
-+ rise_delay =1.0e-10 fall_delay =1.0e-10)
-.model dac dac_bridge(out_low = 0.0 out_high = 2.0 out_undef = 1.0
-+ input_load = 5.0e-14 t_rise = 1.0e-10
-+ t_fall = 1.0e-10)
-
-
-.end
-
-
-
-.CONTROL
-
-option noopalter
-tran .1n 100n
-.ENDC
-
diff --git a/Workflow.md b/Workflow.md
new file mode 100644
index 0000000..1077d32
--- /dev/null
+++ b/Workflow.md
@@ -0,0 +1,102 @@
+1. When `nghdl` button clicked in `eSim` it calls the `ngspice_ghdl.py` from `nghdl` installed directory
+- `ngspice_ghdl.py` defines the UI for nghdl, and the functionality of each button
+- When `Upload` clicked, it calls `uploadModle` function from `ngspice_ghdl.py`
+- Similarly functions called on each button click defined
+- `uploadModle` inturn calls these 5 functions sequentially =>
+- - createModelDirectory()
+- - addingModelInModpath()
+- - createModelFiles()
+- - runMake()
+- - runMakeInstall()
+
+2. `createModelDirectory()`
+- Create directory for the specified file name at `~/ngspice-nghdl/src/xspice/icm/ghdl/`
+- The location where the directory is created in mentioned at `~/.nghdl/config.ini`, this config file is inside a hidden folder `.ngdhl`, created when nghdl is installed
+- If a folder of the same name exists, it asks to overwrite, then removes earlier folder, and writes new one
+
+3. `addingModelInModpath()`
+- This adds the name of the new model created to `modpath.lst` file
+- `modpath.lst` is located at `~/ngspice-nghdl/src/xspice/icm/ghdl`, this should contain name of all the models that the folder has
+- Similarly you can look at `~/ngspice-nghdl/src/xspice/icm/digital` which also contains a `modpath.list` for all the models in that folder
+- This `modpath.lst` is used in the `GNUMakefile` at `~/ngspice-nghdl/release/src/xspice/icm`
+- This file used to keep a track of all components created
+- If model already there it isn't added to the list
+
+4. `createModelFiles()`
+- Calls `model_generation.py` at the installed nghdl location under `src/model_generation.py`
+- Moves the generated `cfunc.mode` and `ifspec.ifs` files to `~/ngspice-nghdl/src/xspice/icm/ghdl/modelName`
+- Creates `DUTghdl` folder at `~/ngspice-nghdl/src/xspice/icm/ghdl/modelName`
+- Move `compile.sh`,`uthash.sh`,`ghdlserver.c`,`ghdlserver.h`,`Utility_Package.vhdl`,`Vhpi_Package.vhdl` to the `DUTghdl` folder
+- Copy `modelName.vhdl` file from source location to `DUTghdl` folder
+- Rum `compile.sh` which generates the object file for `ghdlserver.c`
+- Give permission to `start_server.sh` and `sock_pkg_create.sh` to execute _chod a+x_
+- Finally remove `compile.sh` and `ghdlserver.c`
+
+5. `model_generation.py`
+- Creates the following files =>
+- - `connection_info.txt`
+- - `cfunc.mod`
+- - `ifspec.ifs`
+- - `modelName_tb.vhdl` => testbench file for the model
+- - `start_server.sh`
+- - `sock_pkg_create.sh`
+- The above files can be found either at `~/ngspice-nghdl/src/xspice/icm/ghdl/modelName` or `DUTghdl` folder inside it
+
+6. `runMake()`
+- Runs the `Makefile` at `~/ngspice-nghdl/release`
+- Executing by running `make` command
+
+7. `runMakeInstall()`
+- Executes `make install`
+- Finally calls `createSchematicLib()`
+
+8. `createSchematicLib()`
+- Connects with `createKicadLibrary.py` file at `~/nghdl/src`
+- Generates the `lib` file for the model, to be used by `KiCad`
+- This is generated from a template stored at `Appconfig.py`
+- The generated `lib` is stored at `~/eSim_kicad.lib`
+- Also creates `xml` file for the model, which is stored at eSim under `eSimLoc/src/modelParamXML/Nghdl
+
+<br/>
+
+Finally all the relevant files are generated, now while executing ngspice, we need to make sure to run the ngspice, which is located at -
+- `~/ngspice-nghdl/install_dir/bin/ngspice` this has the binary for the ngspice,
+- And also the script at `~/ngspice-nghdl/install_dir/share/ngspice/scripts/spinit`
+= ` spinit` has the line `codemodel ...` mentioning a `cm` file to execute at runtime
+- This has mention of `ghdl.cm` which makes sure that our `cfunc.c` file is executed at runtime
+- You can see the `ghdl.cm` file is located at `~/ngspice-nghdl/release/src/xspice/icm/ghdl`
+- Also the `cfunc.c` files, located at `~/ngspice-nghdl/release/src/xspice/icm/ghdl/modelName`
+- These have mention of the `start_server.sh` file at `DUTghdl`, hence server is started and values passed as well
+- Also you can look at `~/ngspice-nghdl/release/src/xspice/icm/digital` it has `digital.cm` and the folders inside have `cfunc.c`
+- Also has `ifspec.c` which defines the interface
+
+<br/>
+
+- Note that, if you have ngspice currently installed remove it and genearate a softlink or command for the ngspice installed at -
+`~/ngspice-nghdl/install_dir/bin/ngspice`
+- `whereis ngspice`, run this to get the location from where `ngspice` is being executed currently
+<br/>
+
+- To generate softlink refer - [Creating softlink](https://askubuntu.com/questions/56339/how-to-create-a-soft-or-symbolic-link)i
+- Exeecute `ln -s ~/ngspice-nghdl/install_dir/bin/ngspice /usr/bin/ngspice`
+
+
+<br/>
+
+- Also the installation script doesn't install ghdl, you will have to do it manually, either through a `.deb` package or build it from [source](https://github.com/ghdl/ghdl)
+- Note that since we are using socket programming here, we require either the `llvm` architecture or `gcc`. Using `mcode` backend won't work here
+
+<br/>
+
+- To install ghdl from source, [this](https://github.com/ghdl/ghdl/issues/550) Github issue might be helpfu, the steps are -
+- - `sudo ./configure --with-llvm-config`
+- - sudo make
+- - sudo make install
+- Check [this](https://github.com/ghdl/ghdl/issues/166) Github issue for those building from `.deb` package
+- To check current version and architecure of ghdl use -
+- - `ghdl --version` command, it should have `llvm` code generator or `gcc`
+<br/>
+
+- Also once ghdl is installed, to check syntax of your vhdl files use -
+`ghdl -s <vhdl file location>`
+- Note that we need `std_vector_logic` as our ports here
diff --git a/ghdl-0.36.tar.gz b/ghdl-0.36.tar.gz
new file mode 100644
index 0000000..6df02cb
--- /dev/null
+++ b/ghdl-0.36.tar.gz
Binary files differ
diff --git a/install list b/install list
new file mode 100644
index 0000000..d28f23f
--- /dev/null
+++ b/install list
@@ -0,0 +1,10 @@
+libssl-dev - apt
+llvm - apt
+libxaw7-dev - apt
+libreadline6-dev - apt
+clang - apt
+zlib1g-dev - apt
+xterm - apt
+gnat-5 - apt
+ghdl
+./install-linux.sh --install --> esim \ No newline at end of file
diff --git a/install-nghdl.sh b/install-nghdl.sh
index eade469..f14116e 100755
--- a/install-nghdl.sh
+++ b/install-nghdl.sh
@@ -3,7 +3,9 @@
#
# FILE: install-nghdl.sh
#
-# USAGE: ./install-nghdl.sh
+# USAGE: ./install-nghdl.sh --install
+# or
+# ./install-nghdl.sh --uninstall
#
# DESCRIPTION: It is installation script for ngspice and ghdl work (nghdl).
#
@@ -11,13 +13,14 @@
# REQUIREMENTS: ---
# BUGS: ---
# NOTES: ---
-# AUTHOR: Fahim Khan , fahim.elex@gmail.com
+# AUTHOR: Fahim Khan, Rahul Paknikar
# ORGANIZATION: eSim, FOSSEE group at IIT Bombay
-# CREATED: Tuesday 02 December 2014 17:01
+# CREATED: Wednesday 23 October 2019 14:30
# REVISION: ---
#===============================================================================
ngspice="ngspice-nghdl"
+ghdl="ghdl-0.36"
config_dir="$HOME/.nghdl"
config_file="config.ini"
src_dir=`pwd`
@@ -28,29 +31,63 @@ timestamp=`echo $sysdate|awk '{print $3"_"$2"_"$6"_"$4 }'`
#All functions goes here
-function addghdlPPA
+function installDependency
{
- ghdlppa="pgavin/ghdl"
- #Checking if ghdl ppa is already exist
- grep -h "^deb.*$ghdlppa*" /etc/apt/sources.list.d/* > /dev/null 2>&1
- if [ $? -ne 0 ]
- then
- echo "Adding ghdl PPA to install latest ghdl version"
- sudo add-apt-repository -y ppa:pgavin/ghdl
- sudo apt-get update
+
+ echo "Updating indexes to install latest versions......"
+ sudo apt-get update
+
+ echo "Installing dependencies for ghdl-0.36 LLVM......."
+ echo "Installing make.................................."
+ sudo apt-get install -y make
+ echo "Installing gnat-5.................................."
+ sudo apt-get install -y gnat-5
+ echo "Installing llvm.................................."
+ sudo apt-get install -y llvm
+ echo "Installing clang.................................."
+ sudo apt-get install -y clang
+ echo "Installing zlib1g-dev.................................."
+ sudo apt-get install -y zlib1g-dev
+ echo "Installing xterm.................................."
+ sudo apt-get install -y xterm
+
+ grep -h "ghdl" /usr/local/bin/ghdl > /dev/null
+ if [ $? -ne 0 ]; then
+ tar -xzvf ghdl-0.36.tar.gz -C $HOME
+ if [ "$?" == 0 ]; then
+ echo "ghdl-0.36 LLVM successfully extracted to $HOME......"
+ echo "Changing directory to ghdl-0.36 LLVM installation..."
+ cd $HOME/ghdl-0.36
+ echo "Configuring ghdl-0.36 build as per requirements....."
+ #Other configure flags can be found at - https://github.com/ghdl/ghdl/blob/master/configure
+ sudo ./configure --with-llvm-config
+ echo "Building the install file for ghdl-0.36 LLVM....."
+ sudo make
+ echo "Installing ghdl-0.36 LLVM....."
+ sudo make install
+ echo "Removing unused part of ghdl-0.36 LLVM....."
+ sudo rm -rf ../ghdl-0.36
else
- echo "ghdl is available in synaptic"
+ echo "Unable to extract ghdl-0.36 LLVM"
+ echo "Exiting installation"
+ exit 1
fi
-}
-
-function installDependency
-{
- echo "Installing ghdl.................................."
- sudo apt-get install -y ghdl
- echo "Installing flex.................................."
- sudo apt-get install -y flex
- echo "Installing bison................................."
- sudo apt-get install -y bison
+ else
+ echo "ghdl already exists....."
+ echo "Leaving ghdl-0.36 LLVM installation"
+ fi
+
+ echo "Installing flex.................................."
+ sudo apt-get install -y flex
+ echo "Installing bison................................."
+ sudo apt-get install -y bison
+
+ # Specific dependency for nvidia graphic cards
+ echo "Installing graphics dependency for ngspice souce build"
+ echo "Installing libxaw7................................"
+ sudo apt-get install libxaw7
+ echo "Installing libxaw7-dev............................"
+ sudo apt-get install libxaw7-dev
}
@@ -59,15 +96,12 @@ function installNgspice
echo "Installing ngspice..................................."
#Checking if ngspice-nghdl directory is already present in Home directory
if [ -d $HOME/$ngspice ];then
- echo "$ngspice directory already exist"
+ echo "$ngspice directory already exists at $HOME"
echo "Leaving ngspice installation"
-
-
else
-
#Extracting Ngspice to Home Directory
+ cd $src_dir
tar -xzvf $ngspice.tar.gz -C $HOME
-
if [ "$?" == 0 ];then
echo "Ngspice extracted sucessfuly to $HOME "
#change to ngspice-nghdl directory
@@ -81,19 +115,34 @@ function installNgspice
echo "Installing Ngspice....."
echo "------------------------------------"
sleep 5
- ../configure --enable-xspice --disable-debug --prefix=$HOME/$ngspice/install_dir/ --exec-prefix=$HOME/$ngspice/install_dir/
-
- #dirty fix for adding patch to ngspice base code
- cp $src_dir/src/outitf.c $HOME/$ngspice/src/frontend
+ ../configure --enable-xspice --disable-debug --prefix=$HOME/$ngspice/install_dir/ --exec-prefix=$HOME/$ngspice/install_dir/
+
+ #dirty fix for adding patch to ngspice base code
+ cp $src_dir/src/outitf.c $HOME/$ngspice/src/frontend
make
make install
if [ "$?" == 0 ];then
- echo "Ngspice Installed sucessfully"
+ echo "Removing previously Installed Ngspice (if any)......"
+ sudo apt-get remove -y ngspice
+
+ echo "Ngspice Installed sucessfully......"
+ echo "Adding softlink for the installed ngspice......"
+
+ sudo ln -s $HOME/$ngspice/install_dir/bin/ngspice /usr/bin/ngspice
+ if [ "$?" == 0 ];then
+ echo "failed to add softlink"
+ echo "ngspice already installed at /usr/bin/ngspice..."
+ echo "Remove earlier installations and try again..."
+ else
+ echo "Added softlink for ngspice"
+ fi
+
else
echo "There was some error in installing ngspice"
fi
+
else
echo "Unable to extract ngspice tar file"
exit 1;
@@ -125,7 +174,6 @@ function createConfigFile
function createSoftLink
{
-
## Creating softlink
cd /usr/local/bin
if [[ -L nghdl ]];then
@@ -138,76 +186,92 @@ function createSoftLink
sudo ln -sf $src_dir/src/ngspice_ghdl.py nghdl
fi
cd $pwd
-
}
#####################################################################
# Script start from here #
#####################################################################
-echo "Enter proxy details if you are connected to internet thorugh proxy"
-
-echo -n "Is your internet connection behind proxy? (y/n): "
-read getProxy
-if [ $getProxy == "y" -o $getProxy == "Y" ];then
- echo -n 'Proxy hostname :'
- read proxyHostname
-
- echo -n 'Proxy Port :'
- read proxyPort
-
- echo -n username@$proxyHostname:$proxyPort :
- read username
-
- echo -n 'Password :'
- read -s passwd
-
- unset http_proxy
- unset https_proxy
- unset HTTP_PROXY
- unset HTTPS_PROXY
- unset ftp_proxy
- unset FTP_PROXY
-
- export http_proxy=http://$username:$passwd@$proxyHostname:$proxyPort
- export https_proxy=http://$username:$passwd@$proxyHostname:$proxyPort
- export HTTP_PROXY=http://$username:$passwd@$proxyHostname:$proxyPort
- export HTTPS_PROXY=http://$username:$passwd@$proxyHostname:$proxyPort
- export ftp_proxy=http://$username:$passwd@$proxyHostname:$proxyPort
- export FTP_PROXY=http://$username:$passwd@$proxyHostname:$proxyPort
-
- echo "Install with proxy"
- #Calling functions
- addghdlPPA
- installDependency
- if [ $? -ne 0 ];then
- echo -e "\n\n\nERROR: Unable to install required packages. Please check your internet connection.\n\n"
- exit 0
- fi
- installNgspice
- createConfigFile
- createSoftLink
-
-elif [ $getProxy == "n" -o $getProxy == "N" ];then
- echo "Install without proxy"
-
- #Calling functions
- addghdlPPA
- installDependency
- if [ $? -ne 0 ];then
- echo -e "\n\n\nERROR: Unable to install required packages. Please check your internet connection.\n\n"
- exit 0
- fi
- installNgspice
- createConfigFile
- createSoftLink
+###Checking if file is passsed as argument to script
+if [ "$#" -eq 1 ];then
+ option=$1
else
- echo "Please select the right option"
- exit 0
-
+ echo "USAGE : "
+ echo "./install.sh --install"
+ exit 1;
fi
-
-
-
+##Checking flags
+
+if [ $option == "--install" ];then
+ echo "Enter proxy details if you are connected to internet thorugh proxy"
+
+ echo -n "Is your internet connection behind proxy? (y/n): "
+ read getProxy
+ if [ $getProxy == "y" -o $getProxy == "Y" ];then
+ echo -n 'Proxy hostname :'
+ read proxyHostname
+
+ echo -n 'Proxy Port :'
+ read proxyPort
+
+ echo -n username@$proxyHostname:$proxyPort :
+ read username
+
+ echo -n 'Password :'
+ read -s passwd
+
+ unset http_proxy
+ unset https_proxy
+ unset HTTP_PROXY
+ unset HTTPS_PROXY
+ unset ftp_proxy
+ unset FTP_PROXY
+
+ export http_proxy=http://$username:$passwd@$proxyHostname:$proxyPort
+ export https_proxy=http://$username:$passwd@$proxyHostname:$proxyPort
+ export HTTP_PROXY=http://$username:$passwd@$proxyHostname:$proxyPort
+ export HTTPS_PROXY=http://$username:$passwd@$proxyHostname:$proxyPort
+ export ftp_proxy=http://$username:$passwd@$proxyHostname:$proxyPort
+ export FTP_PROXY=http://$username:$passwd@$proxyHostname:$proxyPort
+
+ echo "Install with proxy"
+ #Calling functions
+ installDependency
+ if [ $? -ne 0 ];then
+ echo -e "\n\n\nERROR: Unable to install required packages. Please check your internet connection.\n\n"
+ exit 0
+ fi
+ installNgspice
+ createConfigFile
+ createSoftLink
+
+ elif [ $getProxy == "n" -o $getProxy == "N" ];then
+ echo "Install without proxy"
+
+ #Calling functions
+ installDependency
+ if [ $? -ne 0 ];then
+ echo -e "\n\n\nERROR: Unable to install required packages. Please check your internet connection.\n\n"
+ exit 0
+ fi
+ installNgspice
+ createConfigFile
+ createSoftLink
+
+elif [ $option == "--uninstall" ];then
+ echo "Deleting Files............"
+ sudo rm -rf $HOME/ngspice-nghdl $HOME/.nghdl /usr/share/kicad/library/eSim_Nghdl.lib /usr/local/bin/nghdl /usr/bin/ngspice
+ echo "Removing gnat-5............"
+ sudo apt-get remove -y gnat-5
+ echo "Removing llvm............"
+ sudo apt-get remove -y llvm
+ echo "Removing ghdl............"
+ sudo rm -rf /usr/local/bin/ghdl /usr/local/lib/ghdl /usr/local/bin/ghdl1-llvm /usr/local/lib/libghdlvpi.so
+
+else
+ echo "Please select the proper operation."
+ echo "--install"
+ echo "--uninstall"
+fi \ No newline at end of file
diff --git a/nghdl_document.pdf b/nghdl_document.pdf
new file mode 100644
index 0000000..22e48fd
--- /dev/null
+++ b/nghdl_document.pdf
Binary files differ
diff --git a/ngspice-nghdl.tar.gz b/ngspice-nghdl.tar.gz
index 4996cdc..ac9262c 100644
--- a/ngspice-nghdl.tar.gz
+++ b/ngspice-nghdl.tar.gz
Binary files differ
diff --git a/src/createKicadLibrary.py b/src/createKicadLibrary.py
index bf520d1..b66d487 100644
--- a/src/createKicadLibrary.py
+++ b/src/createKicadLibrary.py
@@ -10,10 +10,10 @@ class AutoSchematic(QtGui.QWidget):
def __init__(self, modelname):
QtGui.QWidget.__init__(self)
self.modelname = modelname.split('.')[0]
- self.template = Appconfig.kicad_lib_template
+ self.template = Appconfig.kicad_lib_template.copy()
self.xml_loc = Appconfig.xml_loc
self.lib_loc = Appconfig.lib_loc
- self.kicad_nghdl_lib = 'eSim_kicad.lib'
+ self.kicad_nghdl_lib = '/usr/share/kicad/library/eSim_Nghdl.lib'
self.parser = Appconfig.parser_nghdl
def createKicadLibrary(self):
@@ -21,14 +21,15 @@ class AutoSchematic(QtGui.QWidget):
for root, dirs, files in os.walk(self.xml_loc):
if (str(self.modelname) + '.xml') in files:
xmlFound = root
+ print(xmlFound)
if (xmlFound == None):
self.getPortInformation()
self.createXML()
self.createLib()
- elif (xmlFound == self.xml_loc + 'Nghdl'):
+ elif (xmlFound == self.xml_loc + '/Nghdl'):
print 'Library already exists...'
ret = QtGui.QMessageBox.critical(self, "Critical",'''<b>The Libraries of this model already exist.Do you want to overwrite it?</b><br/>
- <b>If yes press ok else cancel it and change the name of your vhdl file</b>''', QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel)
+ <b>If yes, press ok else cancel it and change the name of your vhdl file</b>''', QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel)
if ret == QtGui.QMessageBox.Ok:
print "Overwriting existing libraries"
self.getPortInformation()
@@ -43,7 +44,7 @@ class AutoSchematic(QtGui.QWidget):
ret = QtGui.QMessageBox.critical(self, "Error",'''<b>A standard library already exists in this name.</b><br/>
<b>Please change the name of your vhdl file and upload it again</b>''', QtGui.QMessageBox.Ok)
- quit()
+ # quit()
def getPortInformation(self):
portInformation = PortInfo(self)
@@ -124,7 +125,7 @@ class AutoSchematic(QtGui.QWidget):
lib_file = open(self.kicad_nghdl_lib,"a")
line1 = self.template["start_def"]
line1 = line1.split()
- line1 = [w.replace('comp_name', self.modelname) for w in line1]
+ line1 = [w.replace('comp_name', self.modelname) for w in line1]
self.template["start_def"] = ' '.join(line1)
if os.stat(self.kicad_nghdl_lib).st_size == 0:
lib_file.write("EESchema-LIBRARY Version 2.3"+ "\n\n")
@@ -164,8 +165,14 @@ class AutoSchematic(QtGui.QWidget):
output_port = output_port.split()
inputs = self.portInfo[0: self.input_length]
outputs = self.portInfo[self.input_length:]
+
+ print "INPUTS AND OUTPUTS "
+ print inputs
+ print outputs
+
inputs = self.char_sum(inputs)
outputs= self.char_sum(outputs)
+
total = inputs+outputs
port_list = []
@@ -191,7 +198,7 @@ class AutoSchematic(QtGui.QWidget):
os.chdir(cwd)
print 'Leaving directory, ', self.lib_loc
- QtGui.QMessageBox.information(self, "Library added", '''Library details for this model is added to the <b>eSim-kicad.lib</b> in the home directory''', QtGui.QMessageBox.Ok)
+ QtGui.QMessageBox.information(self, "Library added", '''Library details for this model is added to the <b>eSim_Nghdl.lib</b> in the KiCad shared directory''', QtGui.QMessageBox.Ok)
class PortInfo:
@@ -225,5 +232,3 @@ class PortInfo:
self.input_len = len(self.bit_list)
for out_list in output_list:
self.bit_list.append(out_list[2])
-
-
diff --git a/src/ghdlserver/Vhpi_Package.vhdl b/src/ghdlserver/Vhpi_Package.vhdl
index 0c0baac..600804c 100755
--- a/src/ghdlserver/Vhpi_Package.vhdl
+++ b/src/ghdlserver/Vhpi_Package.vhdl
@@ -1,4 +1,8 @@
-- author: Madhav P. Desai
+-- modified: Rahul Paknikar
+-- -changed procedure of Vhpi_Initialize - 26.Sept.2019
+-- -removed procedure Vhpi_Close - 15.Oct.2019
+
library ieee;
use ieee.std_logic_1164.all;
library work;
@@ -8,12 +12,9 @@ package Vhpi_Foreign is
-----------------------------------------------------------------------------
-- foreign Vhpi function
-----------------------------------------------------------------------------
- procedure Vhpi_Initialize(sock_port : in integer);
+ procedure Vhpi_Initialize(sock_port : in integer; sock_ip : in VhpiString);
attribute foreign of Vhpi_Initialize : procedure is "VHPIDIRECT Vhpi_Initialize";
- procedure Vhpi_Close; -- close .
- attribute foreign of Vhpi_Close : procedure is "VHPIDIRECT Vhpi_Close";
-
procedure Vhpi_Listen;
attribute foreign of Vhpi_Listen : procedure is "VHPIDIRECT Vhpi_Listen";
@@ -36,16 +37,11 @@ package body Vhpi_Foreign is
-----------------------------------------------------------------------------
-- subprogram bodies for foreign vhpi routines. will never be called
-----------------------------------------------------------------------------
- procedure Vhpi_Initialize(sock_port: in integer) is
+ procedure Vhpi_Initialize(sock_port: in integer; sock_ip : in VhpiString) is
begin
assert false report "fatal: this should never be called" severity failure;
end Vhpi_Initialize;
- procedure Vhpi_Close is
- begin
- assert false report "fatal: this should never be called" severity failure;
- end Vhpi_Close;
-
procedure Vhpi_Listen is
begin
assert false report "fatal: this should never be called" severity failure;
diff --git a/src/ghdlserver/ghdlserver.c b/src/ghdlserver/ghdlserver.c
index 09514e1..e05a156 100644
--- a/src/ghdlserver/ghdlserver.c
+++ b/src/ghdlserver/ghdlserver.c
@@ -1,5 +1,24 @@
-/*************************************************************************
- * <ghdlserver.c> FOSSEE, IIT-Mumbai
+/**********************************************************************************
+ * <ghdlserver.c> FOSSEE, IIT-Bombay
+ **********************************************************************************
+ * 08.Nov.2019 - Rahul Paknikar - Switched to blocking sockets from non-blocking
+ * - Close previous used socket to prevent from
+ * generating too many socket descriptors
+ * - Enabled SO_REUSEPORT, SO_DONTROUTE socket options
+ * 26.Sept.2019 - Rahul Paknikar - Added reading of IP from a file to
+ * support multiple digital models
+ * - On exit, the test bench removes the
+ * NGHDL_COMMON_IP_<ngspice_pid> file, shared by all
+ * nghdl digital models and is stored in /tmp
+ * directory. It tracks the used IPs for existing
+ * digital models in current simulation.
+ * - Writes PID file in append mode.
+ * 5.July.2019 - Rahul Paknikar - Added loop to send all port values for
+ * a given event.
+ * - Removed bug to terminate multiple testbench
+ * instances in ngpsice windows.
+ **********************************************************************************
+ **********************************************************************************
* 24.Mar.2017 - Raj Mohan - Added signal handler for SIGUSR1, to handle an
* orphan test bench process.
* The test bench will now create a PID file in
@@ -21,8 +40,8 @@
* Added the following functions:
* o curtim()
* o print_hash_table()
- *************************************************************************
- */
+ *********************************************************************************/
+
#include <string.h>
#include "ghdlserver.h"
#include "uthash.h"
@@ -33,9 +52,10 @@
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
-#include <sys/socket.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
#include <sys/time.h>
-#include <netinet/in.h>
+#include <netinet/in.h>
#include <netdb.h>
#include <limits.h>
#include <time.h>
@@ -45,16 +65,10 @@
#define _XOPEN_SOURCE 500
#define MAX_NUMBER_PORT 100
-
#define NGSPICE "ngspice" // 17.Mar.2017 - RM
-extern char* __progname; // 26.Feb.2017 May not be portable to non-GNU systems.
-
-void Vhpi_Exit(int sig);
-
static FILE* pid_file;
static char pid_filename[80];
-
static char* Out_Port_Array[MAX_NUMBER_PORT];
static int out_port_num = 0;
static int server_socket_id = -1;
@@ -62,6 +76,10 @@ static int sendto_sock; // 22.Feb.2017 - RM - Kludge
static int prev_sendto_sock; // 22.Feb.2017 - RM - Kludge
static int pid_file_created; // 10.Mar.2017 - RM
+extern char* __progname; // 26.Feb.2017 May not be portable to non-GNU systems.
+
+void Vhpi_Exit(int sig);
+
struct my_struct {
char val[1024];
char key[1024];
@@ -70,6 +88,7 @@ struct my_struct {
static struct my_struct *s, *users, *tmp = NULL;
+
/* 17.Mar.2017 - RM - Get the process id of ngspice program.*/
static int get_ngspice_pid(void)
{
@@ -81,45 +100,45 @@ static int get_ngspice_pid(void)
if ((dirp = opendir("/proc/")) == NULL)
{
- perror("opendir /proc failed");
- exit(-1);
+ perror("opendir /proc failed");
+ exit(-1);
}
while ((dir_entry = readdir(dirp)) != NULL)
{
- char* nptr;
- int valid_num = 0;
-
- int tmp = strtol(dir_entry->d_name, &nptr, 10);
- if ((errno == ERANGE) && (tmp == LONG_MAX || tmp == LONG_MIN))
- {
- perror("strtol"); // Number out of range.
- return(-1);
- }
- if (dir_entry->d_name == nptr)
- {
- continue; // No digits found.
- }
- if (tmp)
- {
- sprintf(path, "/proc/%s/comm", dir_entry->d_name);
- if ((fp = fopen(path, "r")) != NULL)
- {
- fscanf(fp, "%s", rd_buff);
- if (strcmp(rd_buff, NGSPICE) == 0)
+ char* nptr;
+ int valid_num = 0;
+
+ int tmp = strtol(dir_entry->d_name, &nptr, 10);
+ if ((errno == ERANGE) && (tmp == LONG_MAX || tmp == LONG_MIN))
+ {
+ perror("strtol"); // Number out of range.
+ return(-1);
+ }
+ if (dir_entry->d_name == nptr)
{
- pid = (pid_t)tmp;
- break;
+ continue; // No digits found.
+ }
+ if (tmp)
+ {
+ sprintf(path, "/proc/%s/comm", dir_entry->d_name);
+ if ((fp = fopen(path, "r")) != NULL)
+ {
+ fscanf(fp, "%s", rd_buff);
+ if (strcmp(rd_buff, NGSPICE) == 0)
+ {
+ pid = (pid_t)tmp; // 5.July.2019 - RP - Kludge
+ }
+ }
}
- }
- }
}
-
+
if (fp) fclose(fp);
return(pid);
}
+
/* 23.Mar.2017 - RM - Pass the sock_port argument. We need this if a netlist
* uses more than one instance of the same test bench, so that we can uniquely
* identify the PID files.
@@ -128,30 +147,31 @@ static int get_ngspice_pid(void)
static void create_pid_file(int sock_port)
{
pid_t my_pid = getpid();
- pid_t ngspice_pid = get_ngspice_pid();
+ pid_t ngspice_pid = get_ngspice_pid();
+
if (ngspice_pid == -1)
{
- fprintf(stderr, "create_pid_file() Failed to get ngspice PID");
- syslog(LOG_ERR, "create_pid_file() Failed to get ngspice PID");
- exit(1);
+ fprintf(stderr, "create_pid_file() Failed to get ngspice PID");
+ syslog(LOG_ERR, "create_pid_file() Failed to get ngspice PID");
+ exit(1);
}
- sprintf(pid_filename, "/tmp/NGHDL_%d_%s_%d", ngspice_pid, __progname,
- sock_port);
- pid_file = fopen(pid_filename, "w");
+
+ sprintf(pid_filename, "/tmp/NGHDL_%d_%s_%d", ngspice_pid, __progname, sock_port);
+ pid_file = fopen(pid_filename, "a"); // 26.Sept.2019 - RP - Open file in append mode
+
if (pid_file)
{
- pid_file_created = 1;
- fprintf(pid_file,"%d\n", my_pid);
- fclose(pid_file);
+ pid_file_created = 1;
+ fprintf(pid_file,"%d\n", my_pid);
+ fclose(pid_file);
} else {
perror("fopen() - PID file");
- syslog(LOG_ERR, "create_pid_file(): Unable to open PID file in /tmp");
+ syslog(LOG_ERR, "create_pid_file(): Unable to open PID file in /tmp");
exit(1);
}
-
- return;
}
+
#ifdef DEBUG
static char* curtim(void)
{
@@ -170,18 +190,18 @@ static char* curtim(void)
}
#endif
+
#ifdef DEBUG
static void print_hash_table(void)
{
struct my_struct *sptr;
for(sptr=users; sptr != NULL; sptr=sptr->hh.next)
- {
- syslog(LOG_INFO, "Hash table:val:%s: key: %s", sptr->val, sptr->key);
- }
+ syslog(LOG_INFO, "Hash table:val:%s: key: %s", sptr->val, sptr->key);
}
#endif
+
static void parse_buffer(int sock_id, char* receive_buffer)
{
static int rcvnum;
@@ -202,308 +222,198 @@ static void parse_buffer(int sock_id, char* receive_buffer)
ptr1 = rest;
while(var=strtok_r(token, ":", &value))
{
- s = (struct my_struct*)malloc(sizeof(struct my_struct));
- strncpy(s->key, var, 10);
- strncpy(s->val, value, 10);
- HASH_ADD_STR(users, key, s );
- break;
+ s = (struct my_struct*)malloc(sizeof(struct my_struct));
+ strncpy(s->key, var, 64);
+ strncpy(s->val, value, 64);
+ HASH_ADD_STR(users, key, s );
+ break;
}
}
s = (struct my_struct*)malloc(sizeof(struct my_struct));
- strncpy(s->key, "sock_id", 10);
- snprintf(s->val,10, "%d", sock_id);
+ strncpy(s->key, "sock_id", 64);
+ snprintf(s->val,64, "%d", sock_id);
HASH_ADD_STR(users, key, s);
}
-//
+
//Create Server and listen for client connections.
-//
-static int create_server(int port_number,int max_connections)
+// 26.Sept.2019 - RP - added parameter of socket ip
+static int create_server(int port_number, char my_ip[], int max_connections)
{
- int sockfd, reuse = 1;
- struct sockaddr_in serv_addr;
-
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
- if (sockfd < 0)
- {
- fprintf(stderr, "%s- Error: in opening socket on port %d\n",
- __progname, port_number);
- exit(1);
- }
-
-/* 20.Mar.2017 - RM - SO_REUSEADDR option. To take care of TIME_WAIT state.*/
- int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
- if (ret < 0)
- {
- syslog(LOG_ERR, "create_server:setsockopt() failed....");
- }
-
- bzero((char *) &serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = INADDR_ANY;
- serv_addr.sin_port = htons(port_number);
-
- if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
- {
- fprintf(stderr,"%s- Error: could not bind socket to port %d\n",
- __progname, port_number);
- syslog(LOG_ERR, "Error: could not bind socket to port %d", port_number);
+ int sockfd, reuse = 1;
+ struct sockaddr_in serv_addr;
- close(sockfd);
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
- exit(1);
- }
+ if (sockfd < 0)
+ {
+ fprintf(stderr, "%s- Error: in opening socket at server \n", __progname);
+ //exit(1);
+ return -1;
+ }
- // Start listening on the server.
- listen(sockfd, max_connections);
+ /* 20.Mar.2017 - RM - SO_REUSEADDR option. To take care of TIME_WAIT state.*/
+ int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
- return sockfd;
+ /* 08.Nov.2019 - RP - SO_REUSEPORT and SO_DONTROUTE option.*/
+ ret += setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof(int));
+ ret += setsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE, &reuse, sizeof(int));
+
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "create_server:setsockopt() failed....");
+ // close(sockfd);
+ // return -1;
+ }
+
+ bzero((char *) &serv_addr, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = inet_addr(my_ip); // 26.Sept.2019 - RP - Bind to specific IP only
+ serv_addr.sin_port = htons(port_number);
+
+ if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
+ {
+ fprintf(stderr,"%s- Error: could not bind socket to port %d\n",
+ __progname, port_number);
+ syslog(LOG_ERR, "Error: could not bind socket to port %d", port_number);
+ close(sockfd);
+ exit(1);
+ }
+
+ // Start listening on the server.
+ listen(sockfd, max_connections);
+
+ return sockfd;
}
-// The server to wait (non-blocking) for a client connection.
+
+// The server to wait (blocking) for a client connection.
static int connect_to_client(int server_fd)
{
- int ret_val = 1;
+ int ret_val = 0;
int newsockfd = -1;
socklen_t clilen;
- struct sockaddr_in cli_addr;
- fd_set c_set;
- struct timeval time_limit;
-
- time_limit.tv_sec = 0;
- time_limit.tv_usec = 1000;
+ struct sockaddr_in cli_addr;
clilen = sizeof(cli_addr);
- FD_ZERO(&c_set);
- FD_SET(server_fd, &c_set);
-
- select(server_fd + 1, &c_set, NULL, NULL, &time_limit);
-
- ret_val = FD_ISSET(server_fd, &c_set);
-
- if(ret_val)
+ /* 08.Nov.2019 - RP - Blocking Socket (Accept) */
+ newsockfd = accept(server_fd, (struct sockaddr *) &cli_addr, &clilen);
+ if (newsockfd >= 0)
+ {
+ syslog(LOG_INFO, "SRV:%d New Client Connection CLT:%d", server_fd, newsockfd);
+ }
+ else
{
- newsockfd = accept(server_fd, (struct sockaddr *) &cli_addr, &clilen);
- if (newsockfd >= 0)
- {
- syslog(LOG_INFO, "SRV:%d New Client Connection CLT:%d",
- server_fd, newsockfd);
- }
- else
- {
- syslog(LOG_ERR,"Error: failed in accept(), socket=%d", server_fd);
+ syslog(LOG_ERR,"Error: failed in accept(), socket=%d", server_fd);
exit(1);
- }
- }
- return(newsockfd);
-}
+ }
-//
-// Check if we can read from the socket..
-//
-static int can_read_from_socket(int socket_id)
-{
- struct timeval time_limit;
- time_limit.tv_sec = 0;
- time_limit.tv_usec = 1000;
-
- fd_set c_set;
- FD_ZERO(&c_set);
- FD_SET(socket_id, &c_set);
-
- int npending = select(socket_id + 1, &c_set, NULL, NULL, &time_limit);
- if (npending == -1)
- {
- npending = errno;
- syslog(LOG_ERR, "can_read_from_socket:select() ERRNO=%d",npending);
- return(-100);
- }
- return(FD_ISSET(socket_id, &c_set));
+ return newsockfd;
}
-//
-// Check if we can write to the socket..
-//
-static int can_write_to_socket(int socket_id)
-{
- struct timeval time_limit;
- time_limit.tv_sec = 0;
- time_limit.tv_usec = 1000;
-
- fd_set c_set;
- FD_ZERO(&c_set);
- FD_SET(socket_id, &c_set);
-
- int npending = select(socket_id + 1, NULL, &c_set, NULL, &time_limit);
- if (npending == -1)
- {
- npending = errno;
-
- syslog(LOG_ERR, "can_write_to_socket() select() ERRNO=%d",npending);
-
- return (-100);
- } else if (npending == 0) { // select() timed out...
- return(0);
- }
- return(FD_ISSET(socket_id,&c_set));
-}
//Receive string from socket and put it inside buffer.
-static int receive_string(int sock_id, char* buffer)
+static void receive_string(int sock_id, char* buffer)
{
- int nbytes = 0;
- int ret;
-
- while(1)
- {
- ret = can_read_from_socket(sock_id);
- if (ret == 0)
- { // select() had timed out. Retry...
- usleep(1000);
- continue;
- } else
- if (ret == -100)
- {
- return(-1);
- }
- break;
- }
-
+ int nbytes = 0;
+
+ /* 08.Nov.2019 - RP - Blocking Socket - Receive */
nbytes = recv(sock_id, buffer, MAX_BUF_SIZE, 0);
- if (nbytes < 0)
+ if (nbytes <= 0)
{
- perror("READ FAILURE");
+ perror("READ FAILURE");
exit(1);
}
- return(nbytes);
-}
+}
-static void set_non_blocking(int sock_id)
-{
- int x;
- x = fcntl(sock_id, F_GETFL, 0);
- fcntl(sock_id, F_SETFL, x | O_NONBLOCK);
- syslog(LOG_INFO, "Setting server to non blocking state.");
-}
static void Data_Send(int sockid)
-{
- static int trnum;
- char* out;
-
- int i;
- char colon = ':';
- char semicolon = ';';
- int wrt_retries = 0;
- int ret;
-
- s = NULL;
- int found = 0;
-
- out = calloc(1, 1024);
-
- for (i=0;i<out_port_num;i++)
- {
- HASH_FIND_STR(users,Out_Port_Array[i],s);
- if (strcmp(Out_Port_Array[i], s->key) == 0)
- {
- found=1;
- break;
- }
- }
-
- if(found)
- {
- strncat(out, s->key, strlen(s->key));
- strncat(out, &colon, 1);
- strncat(out, s->val, strlen(s->val));
- strncat(out, &semicolon, 1);
-
- while(1)
- {
- if (wrt_retries > 2) // 22.Feb.2017 - Kludge
- {
- free(out);
- return;
- }
- ret = can_write_to_socket(sockid);
- if (ret > 0) break;
- if( ret == -100)
- {
- syslog(LOG_ERR,"Send aborted to CLT:%d buffer:%s ret=%d",
- sockid, out,ret);
- free(out);
- return;
- }
- else // select() timed out. Retry....
- {
- usleep(1000);
- wrt_retries++;
- }
- }
- }
- else
- {
- syslog(LOG_ERR,"The %s's value not found in the table.",
- Out_Port_Array[i]);
- free(out);
- return;
- }
-
- if ((send(sockid, out, strlen(out), 0)) == -1)
+{
+ static int trnum;
+ char* out;
+
+ int i;
+ char colon = ':';
+ char semicolon = ';';
+ int wrt_retries = 0;
+ int ret;
+
+ s = NULL;
+
+ out = calloc(1, 2048);
+
+ // 5.July.2019 - RP - loop to send all ports at once for an event
+ for (i=0; i<out_port_num; i++)
+ {
+ HASH_FIND_STR(users,Out_Port_Array[i],s);
+ if (strcmp(Out_Port_Array[i], s->key) == 0)
+ {
+ strncat(out, s->key, strlen(s->key));
+ strncat(out, &colon, 1);
+ strncat(out, s->val, strlen(s->val));
+ strncat(out, &semicolon, 1);
+ }
+ else
+ {
+ syslog(LOG_ERR,"The %s's value not found in the table.",
+ Out_Port_Array[i]);
+ free(out);
+ return;
+ }
+ }
+
+ /* 08.Nov.2019 - RP - Blocking Socket (Send) */
+ if ((send(sockid, out, strlen(out), 0)) == -1)
{
- syslog(LOG_ERR,"Failure sending to CLT:%d buffer:%s", sockid, out);
- exit(1);
+ syslog(LOG_ERR,"Failure sending to CLT:%d buffer:%s", sockid, out);
+ exit(1);
}
- syslog(LOG_INFO,"SNT:TRNUM:%d to CLT:%d buffer: %s", trnum++, sockid, out);
- free(out);
+ syslog(LOG_INFO,"SNT:TRNUM:%d to CLT:%d buffer: %s", trnum++, sockid, out);
+ free(out);
}
-void Vhpi_Initialize(int sock_port)
+
+// 26.Sept.2019 - RP - added parameter of socket ip
+void Vhpi_Initialize(int sock_port, char sock_ip[])
{
DEFAULT_SERVER_PORT = sock_port;
signal(SIGINT,Vhpi_Exit);
signal(SIGTERM,Vhpi_Exit);
-
signal(SIGUSR1, Vhpi_Exit); //10.Mar.2017 - RM
int try_limit = 100;
while(try_limit > 0)
{
- server_socket_id = create_server(DEFAULT_SERVER_PORT,DEFAULT_MAX_CONNECTIONS);
- if(server_socket_id > 0)
- {
+ // 26.Sept.2019 - RP
+ server_socket_id = create_server(DEFAULT_SERVER_PORT, sock_ip, DEFAULT_MAX_CONNECTIONS);
+
+ if(server_socket_id >= 0)
+ {
syslog(LOG_INFO,"Started the server on port %d SRV:%d",
DEFAULT_SERVER_PORT, server_socket_id);
- set_non_blocking(server_socket_id);
break;
}
- else
- {
- syslog(LOG_ERR,"Could not start server on port %d,will try again",
+
+ syslog(LOG_ERR,"Could not start server on port %d,will try again",
DEFAULT_SERVER_PORT);
usleep(1000);
try_limit--;
-
+
if(try_limit==0)
{
- syslog(LOG_ERR,
- "Error:Tried to start server on port %d, failed..giving up.",
- DEFAULT_SERVER_PORT);
- exit(1);
- }
-
- }
+ syslog(LOG_ERR,
+ "Error:Tried to start server on port %d, failed..giving up.",
+ DEFAULT_SERVER_PORT);
+ exit(1);
+ }
}
- //
- //Reading Output Port name and storing in Out_Port_Array;
- //
+
+ //Reading Output Port name and storing in Out_Port_Array;
char* line = NULL;
size_t len = 0;
ssize_t read;
@@ -512,145 +422,92 @@ void Vhpi_Initialize(int sock_port)
struct timespec ts;
fp=fopen("connection_info.txt","r");
- if (! fp)
+ if (!fp)
{
- syslog(LOG_ERR,"Vhpi_Initialize: Failed to open connection_info.txt. Exiting...");
- exit(1);
+ syslog(LOG_ERR,"Vhpi_Initialize: Failed to open connection_info.txt. Exiting...");
+ exit(1);
}
line = (char*) malloc(80);
while ((read = getline(&line, &len, fp)) != -1)
{
- if (strstr(line,"OUT") != NULL || strstr(line,"out") != NULL )
- {
- strtok_r(line, " ",&token);
- Out_Port_Array[out_port_num] = line;
- out_port_num++;
- }
- line = (char*) malloc(80);
+ if (strstr(line,"OUT") != NULL || strstr(line,"out") != NULL)
+ {
+ strtok_r(line, " ",&token);
+ Out_Port_Array[out_port_num] = line;
+ out_port_num++;
+ }
+ line = (char*) malloc(80);
}
fclose(fp);
-
free(line);
ts.tv_sec = 2;
ts.tv_nsec = 0;
nanosleep(&ts, NULL);
-// 10.Mar.2017 - RM - Create PID file for the test bench.
+ // 10.Mar.2017 - RM - Create PID file for the test bench.
create_pid_file(sock_port);
}
+
+
void Vhpi_Set_Port_Value(char *port_name,char *port_value,int port_width)
{
-
- s = (struct my_struct*)malloc(sizeof(struct my_struct));
- strncpy(s->key, port_name,10);
- strncpy(s->val,port_value,10);
- HASH_ADD_STR( users, key, s );
-
+ s = (struct my_struct*)malloc(sizeof(struct my_struct));
+ strncpy(s->key, port_name,64);
+ strncpy(s->val,port_value,64);
+ HASH_ADD_STR( users, key, s );
}
+
void Vhpi_Get_Port_Value(char* port_name,char* port_value,int port_width)
{
-
- HASH_FIND_STR(users,port_name,s);
- if(s)
- {
- snprintf(port_value,sizeof(port_value),"%s",s->val);
-
- HASH_DEL(users, s);
- free(s);
- s=NULL;
- }
+ HASH_FIND_STR(users,port_name,s);
+ if(s)
+ {
+ snprintf(port_value,sizeof(port_value),"%s",s->val);
+ HASH_DEL(users, s);
+ free(s);
+ s=NULL;
+ }
}
+
void Vhpi_Listen()
{
- int new_sock;
+ sendto_sock = connect_to_client(server_socket_id); // 22.Feb.2017 - RM - Kludge
+ char receive_buffer[MAX_BUF_SIZE];
+ receive_string(sendto_sock, receive_buffer);
+
+ syslog(LOG_INFO, "Vhpi_Listen:New socket connection CLT:%d",sendto_sock);
- while(1)
+ if(strcmp(receive_buffer, "END")==0)
{
- new_sock=connect_to_client(server_socket_id);
- if(new_sock > 0)
- {
- char receive_buffer[MAX_BUF_SIZE];
- int n = receive_string(new_sock, receive_buffer);
- if(n > 0)
- {
- sendto_sock = new_sock; // 22.Feb.2017 - RM - Kludge
- syslog(LOG_INFO,
- "Vhpi_Listen:New socket connection CLT:%d",new_sock);
- if(strcmp(receive_buffer, "END")==0)
- {
- syslog(LOG_INFO,
- "RCVD:CLOSE REQUEST from CLT:%d", new_sock);
- Vhpi_Exit(0);
- }
- else
- {
- parse_buffer(new_sock,receive_buffer);
- }
- break;
- }
- }
- else
- {
- break;
- }
- }
+ syslog(LOG_INFO, "RCVD:CLOSE REQUEST from CLT:%d", sendto_sock);
+ Vhpi_Exit(0);
+ }
+
+ parse_buffer(sendto_sock, receive_buffer);
}
void Vhpi_Send()
{
- int sockid;
- char* out;
-
-// Traverse the list of finished jobs and send out the resulting port values..
// 22.Feb.2017 - RM - Kludge
-// log_server=fopen("server.log","a");
-// fprintf(log_server, "%s Vhpi_Send() called\n", curtim());
-
-// fprintf(log_server,"Vhpi_Send()-------------------\n");
-// print_hash_table();
-// fprintf(log_server,"----------------------------------------\n");
-// HASH_FIND_STR(users,"sock_id",s);
-// if(s)
-// {
-// sockid=atoi(s->val);
-// }
-// else
-// {
-// fprintf(log_server,"%s Socket id not in table - key=%s val=%s\n",
-// curtim(),
-// users->key, users->val);
-// }
-// Data_Send(sockid);
-
if (prev_sendto_sock != sendto_sock)
{
- Data_Send(sendto_sock);
- prev_sendto_sock = sendto_sock;
+ Data_Send(sendto_sock);
+
+ close(prev_sendto_sock); // 08.Nov.2019 - RP - Close previous socket
+ prev_sendto_sock = sendto_sock;
}
-// 22.Feb.2017 End kludge
-
+// 22.Feb.2017 End kludge
}
-void Vhpi_Close()
-{
- close(server_socket_id);
- syslog(LOG_INFO, "*** Closed VHPI link. ***");
-}
void Vhpi_Exit(int sig)
-{
- Vhpi_Close();
-
-// 10.Mar.2017 - RM
- if (pid_file_created)
- remove(pid_filename);
-
- syslog(LOG_INFO, "*** Exiting ***");
-
+{
+ close(server_socket_id);
+ syslog(LOG_INFO, "*** Closed VHPI link. Exiting... ***");
exit(0);
-}
+} \ No newline at end of file
diff --git a/src/ghdlserver/ghdlserver.h b/src/ghdlserver/ghdlserver.h
index 9dc8afc..9f23f0b 100644
--- a/src/ghdlserver/ghdlserver.h
+++ b/src/ghdlserver/ghdlserver.h
@@ -21,8 +21,7 @@
int DEFAULT_SERVER_PORT;
//Vhpi Functions.
-void Vhpi_Initialize(int sock_port);
-void Vhpi_Close();
+void Vhpi_Initialize(int sock_port, char sock_ip[]); /* 26.Sept.2019 - RP */
void Vhpi_Exit();
void Vhpi_Listen();
void Vhpi_Send();
diff --git a/src/model_generation.py b/src/model_generation.py
index 15dc3e6..dffd690 100644
--- a/src/model_generation.py
+++ b/src/model_generation.py
@@ -41,6 +41,7 @@ for item in vhdl_data:
#print "Scan Data",scan_data
port_info=[]
+port_vector_info = []
for item in scan_data:
print "Scan Data :",item
@@ -67,7 +68,12 @@ for item in scan_data:
lhs=temp.split(item)[0]
rhs=temp.split(item)[1]
bit_info=re.compile(r"\s*downto\s*",flags=re.I).split(rhs)[0]
- port_info.append(lhs+":"+str(int(bit_info)+int(1)))
+ if bit_info:
+ port_info.append(lhs+":"+str(int(bit_info)+int(1)))
+ port_vector_info.append(1)
+ else:
+ port_info.append(lhs+":"+str(int(1)))
+ port_vector_info.append(0)
print "Port Info :",port_info
@@ -92,7 +98,9 @@ data=read_file.readlines()
read_file.close()
#Extracting input and output port list from data
+print "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
for line in data:
+ print line
if re.match(r'^\s*$', line):
pass
#print "Blank Line"
@@ -135,7 +143,7 @@ cfunc=open('cfunc.mod','w')
print "Building content for cfunc.mod file"
comment='''/* This is cfunc.mod file auto generated by gen_con_info.py
-Developed by Fahim at IIT Bombay */ \n
+Developed by Fahim, Rahul at IIT Bombay */ \n
'''
header='''
@@ -205,10 +213,12 @@ systime_info='''
time_t systime;
systime = time(NULL);
printf(ctime(&systime));
- printf("Client-Initialising ngspice \\n");
+ printf("Client-Initialising GHDL...");
fprintf(log_client,"Setup Client Server Connection at %s \\n",ctime(&systime));
'''
+
+
init_else='''
printf("Client-Inside else of INIT \\n");
fprintf(log_client,"Inside else of INIT \\n");
@@ -216,46 +226,88 @@ init_else='''
'''
els_evt_ptr=[]
-els_evt_count1=[]
+els_evt_count1=0
+els_evt_count2=0
for item in output_port:
- els_evt_count2=0
els_evt_ptr.append("_op_"+item.split(":")[0]+" = cm_event_get_ptr("+str(els_evt_count1)+","+str(els_evt_count2)+");")
els_evt_count2=els_evt_count2+1
els_evt_ptr.append("_op_"+item.split(":")[0]+"_old"+" = cm_event_get_ptr("+str(els_evt_count1)+","+str(els_evt_count2)+");")
els_evt_count1=els_evt_count1+1
-client_setup='''
- /* Client setup */
- //Default hostname assignment
- host = gethostbyname("127.0.0.1");
- printf("Client-Creating Client Socket \\n");
- fprintf(log_client,"Creating client socket \\n");
+client_setup_ip='''
+ /* Client Setup IP Addr */
+ FILE *fptr;
+ int ip_count = 0;
+ char* my_ip = malloc(16);
+
+ char ip_filename[40];
+ sprintf(ip_filename, "/tmp/NGHDL_COMMON_IP_%d.txt", getpid());
+
+ fptr = fopen(ip_filename, "r");
+ if (fptr)
+ {
+ char line[20];
+ while(fscanf(fptr, "%s", line) == 1) {
+ ip_count++;
+ }
+
+ fclose(fptr);
+ }
+
+ if (ip_count < 255) {
+ sprintf(my_ip, "127.0.0.%d", ip_count+1);
+ } else {
+ sprintf(my_ip, "127.0.%d.1", (ip_count+1)%256);
+ }
+
+ fptr = fopen(ip_filename, "a");
+ if (fptr)
+ {
+ fprintf(fptr, "%s\\n", my_ip);
+ fclose(fptr);
+ } else {
+ perror("fopen() - Common IP");
+ exit(1);
+ }
+
+ STATIC_VAR(my_ip) = my_ip;
+'''
+
+client_fetch_ip='''
+ /* Client Fetch IP Addr */
+
+ char* my_ip = STATIC_VAR(my_ip);
+
+ host = gethostbyname(my_ip);
+ printf("\\n\\nClient-Creating Socket \\n");
+ fprintf(log_client,"Creating client socket \\n");
'''
+
create_socket='''
- //Creating socket for client
- if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- perror("Client-Error while creating client Socket \\n");
- fprintf(log_client,"Error while creating client sockte \\n");
- exit(1);
- }
-
- printf("Client-Client Socket created successfully \\n");
- printf("Client- Socket Id : %d \\n",socket_fd);
- fprintf(log_client,"Client-Client Socket created successfully \\n");
- fprintf(log_client,"Client- Socket Id : %d \\n",socket_fd);
-
- // memset(&server_addr, 0, sizeof(server_addr));
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(sock_port);
- server_addr.sin_addr = *((struct in_addr *)host->h_addr);
- bzero(&(server_addr.sin_zero),8);
+ //Creating socket for client
+ if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+ perror("Client-Error while creating client Socket \\n");
+ fprintf(log_client,"Error while creating client socket \\n");
+ exit(1);
+ }
+
+ printf("Client-Client Socket created successfully \\n");
+ printf("Client- Socket Id : %d \\n",socket_fd);
+ fprintf(log_client,"Client-Client Socket created successfully \\n");
+ fprintf(log_client,"Client- Socket Id : %d \\n",socket_fd);
+
+ // memset(&server_addr, 0, sizeof(server_addr));
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(sock_port);
+ server_addr.sin_addr = *((struct in_addr *)host->h_addr);
+ bzero(&(server_addr.sin_zero),8);
'''
connect_server='''
- printf("Client-Connecting to server \\n");
+ printf("Client-Connecting to server \\n");
fprintf(log_client,"Client-Connecting to server \\n");
//Conneting to server
@@ -418,9 +470,9 @@ els_time_limit='''
fprintf(log_client,"Socket Id : %d & Message sent : %s for END signal \\n",socket_fd,send_data);
}
flag++;
- close(socket_fd);
}
+ close(socket_fd);
'''
@@ -463,10 +515,12 @@ for item in cm_event_get_ptr:
cfunc.write("\n")
cfunc.write(systime_info)
cfunc.write("\n")
-cfunc.write("\t\tchar command[1024];")
-cfunc.write('\t\tsnprintf(command,1024,"'+home+'/ngspice-nghdl/src/xspice/icm/ghdl/'+fname.split('.')[0]+'/DUTghdl/start_server.sh %d &",sock_port);\n')
-cfunc.write('\t\tsystem(command);')
-cfunc.write("\t}")
+cfunc.write(client_setup_ip)
+cfunc.write("\n")
+cfunc.write("\t\tchar command[1024];\n")
+cfunc.write('\t\tsnprintf(command,1024,"'+home+'/ngspice-nghdl/src/xspice/icm/ghdl/'+fname.split('.')[0]+'/DUTghdl/start_server.sh %d %s &",sock_port, my_ip);')
+cfunc.write('\n\t\tsystem(command);')
+cfunc.write("\n\t}")
cfunc.write("\n")
cfunc.write("\telse\n\t{\n")
@@ -476,7 +530,7 @@ for item in els_evt_ptr:
cfunc.write("\t}")
cfunc.write("\n\n")
cfunc.write("\tif(flag==0)\n\t{")
-cfunc.write(client_setup)
+cfunc.write(client_fetch_ip)
cfunc.write(create_socket)
cfunc.write(connect_server)
cfunc.write(time_limit)
@@ -590,6 +644,16 @@ Null_Allowed: yes no
'''
+static_table='''
+
+STATIC_VAR_TABLE:
+
+Static_Var_Name: my_ip
+Data_Type: pointer
+Description: "connect to ghdlserver through this ip"
+
+'''
+
#Writing all the content in ifspec file
ifspec.write(ifspec_comment)
@@ -605,6 +669,8 @@ for item in out_port_table:
ifspec.write("\n")
ifspec.write(parameter_table)
+ifspec.write("\n")
+ifspec.write(static_table)
ifspec.close()
@@ -612,8 +678,11 @@ ifspec.close()
print "Starting with testbench file"
testbench=open(fname.split('.')[0]+'_tb.vhdl','w')
+print fname.split('.')[0] + '_tb.vhdl'
#comment
-comment_vhdl="--------------------------------------------------------------------------------\n--This testbench has been created by Ambikeshwar Srivastava, FOSSEE, IIT Bombay\n-------------------------------------------------------------------------------"
+comment_vhdl="--------------------------------------------------------------------------------\n--This testbench has been created by Ambikeshwar Srivastava, FOSSEE, IIT Bombay\n--------------------------------------------------------------------------------\n"
+comment_vhdl+="--------------------------------------------------------------------------------\n--Modified by Rahul Paknikar, FOSSEE, IIT Bombay\n"
+comment_vhdl+="--retrieves the IP-Addr from sock_pkg and forwards it to the ghdlserver\n--------------------------------------------------------------------------------\n"
#Adding header, entity and architecture statement
tb_header='''
library ieee;
@@ -636,16 +705,32 @@ arch="architecture "+fname.split('.')[0]+"_tb_beh of "+fname.split('.')[0]+"_tb
components=[]
components.append("\tcomponent "+fname.split('.')[0]+" is\n\t\tport(\n\t\t\t\t")
+port_vector_count = 0
+
for item in input_port:
- components.append(item.split(':')[0]+": in std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
- #if item.split(":")[1] != '1':
- # components.append(item.split(':')[0]+": in std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
- #else:
- # components.append(item.split(':')[0]+": in std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
+ if port_vector_info[port_vector_count]:
+ components.append(item.split(':')[0]+": in std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
+ else:
+ components.append(item.split(':')[0]+": in std_logic;\n\t\t\t\t")
+
+ port_vector_count += 1
+ #if item.split(":")[1] != '1':
+ # components.append(item.split(':')[0]+": in std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
+ #else:
+ # components.append(item.split(':')[0]+": in std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
for item in output_port[:-1]:
- components.append(item.split(':')[0]+": out std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
-components.append(output_port[-1].split(':')[0]+": out std_logic_vector("+str(int(output_port[-1].split(':')[1])-int(1))+" downto 0)\n\t\t\t\t")
+ if port_vector_info[port_vector_count]:
+ components.append(item.split(':')[0]+": out std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n\t\t\t\t")
+ else:
+ components.append(item.split(':')[0]+": out std_logic;\n\t\t\t\t")
+
+ port_vector_count += 1
+
+if port_vector_info[port_vector_count]:
+ components.append(output_port[-1].split(':')[0]+": out std_logic_vector("+str(int(output_port[-1].split(':')[1])-int(1))+" downto 0)\n\t\t\t\t")
+else:
+ components.append(output_port[-1].split(':')[0]+": out std_logic\n\t\t\t\t")
#if item.split(":")[1] != '1':
# components.append(item.split(':')[0]+": out std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0)\n\t\t\t\t")
#else:
@@ -658,8 +743,15 @@ components.append("\tend component;\n\n")
signals=[]
signals.append("\tsignal clk_s : std_logic := '0';\n")
+port_vector_count = 0
+
for item in input_port:
- signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")
+ if port_vector_info[port_vector_count]:
+ signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")
+ else:
+ signals.append("\tsignal "+item.split(':')[0]+": std_logic;\n")
+ port_vector_count += 1
+
#if item.split(":")[1] != '1':
# signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")
#else:
@@ -667,7 +759,11 @@ for item in input_port:
for item in output_port:
- signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")
+ if port_vector_info[port_vector_count]:
+ signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")
+ else:
+ signals.append("\tsignal "+item.split(':')[0]+": std_logic;\n")
+ port_vector_count += 1
#if item.split(":")[1] != '1':
# signals.append("\tsignal "+item.split(':')[0]+": std_logic_vector("+str(int(item.split(':')[1])-int(1))+" downto 0);\n")
#else:
@@ -692,7 +788,7 @@ map.append("\t\t\t);")
tb_clk= "clk_s <= not clk_s after 5 us;\n\n"
#Adding Process block for Vhpi
process_Vhpi=[]
-process_Vhpi.append("\tprocess\n\t\tvariable sock_port : integer;\n\t\tbegin\n\t\tsock_port := sock_pkg_fun;\n\t\tVhpi_Initialize(sock_port);\n\t\twait until clk_s = '1';\n\t\twhile true loop\n\t\t\twait until clk_s = '0';\n\t\t\tVhpi_Listen;\n\t\t\twait for 1 us;\n\t\t\tVhpi_Send;\n\t\tend loop;\n\t\twait;\n\tend process;\n\n")
+process_Vhpi.append("\tprocess\n\t\tvariable sock_port : integer;\n\t\ttype string_ptr is access string;\n\t\tvariable sock_ip : string_ptr;\n\t\tbegin\n\t\tsock_port := sock_port_fun;\n\t\tsock_ip := new string'(sock_ip_fun);\n\t\tVhpi_Initialize(sock_port, Pack_String_To_Vhpi_String(sock_ip.all));\n\t\twait until clk_s = '1';\n\t\twhile true loop\n\t\t\twait until clk_s = '0';\n\t\t\tVhpi_Listen;\n\t\t\twait for 1 us;\n\t\t\tVhpi_Send;\n\t\tend loop;\n\t\twait;\n\tend process;\n\n")
#Adding process block
process=[]
process.append("\tprocess\n\n")
@@ -708,17 +804,28 @@ process.append("\tbegin\n")
process.append("\t\twhile true loop\n")
process.append("\t\t\twait until clk_s = '0';\n\n")
+port_vector_count = 0
+
for item in input_port:
process.append('\t\t\tobj_ref := Pack_String_To_Vhpi_String("'+item.split(':')[0]+'");\n')
process.append('\t\t\tVhpi_Get_Port_Value(obj_ref,'+item.split(':')[0]+'_v,'+item.split(':')[1]+');\n')
process.append('\t\t\tassert false report "Get port value '+item.split(':')[0]+' returns " &'+item.split(':')[0]+'_v severity note;\n')
- process.append('\t\t\t'+item.split(':')[0]+' <= Unpack_String('+item.split(':')[0]+'_v,'+item.split(':')[1]+');\n')
+ if port_vector_info[port_vector_count]:
+ process.append('\t\t\t'+item.split(':')[0]+' <= Unpack_String('+item.split(':')[0]+'_v,'+item.split(':')[1]+');\n')
+ else:
+ process.append('\t\t\t'+item.split(':')[0]+' <= To_Std_Logic('+item.split(':')[0]+'_v'+');\n')
+ port_vector_count += 1
process.append("\n")
process.append('\t\t\twait for 1 us;\n')
for item in output_port:
- process.append('\t\t\t'+item.split(':')[0]+'_v := Pack_String_To_Vhpi_String(Convert_SLV_To_String('+item.split(':')[0]+'));\n')
+ if port_vector_info[port_vector_count]:
+ process.append('\t\t\t'+item.split(':')[0]+'_v := Pack_String_To_Vhpi_String(Convert_SLV_To_String('+item.split(':')[0]+'));\n')
+ else:
+ process.append('\t\t\t'+item.split(':')[0]+'_v := Pack_String_To_Vhpi_String(To_String('+item.split(':')[0]+'));\n')
+ port_vector_count += 1
+
process.append('\t\t\tobj_ref := Pack_String_To_Vhpi_String("'+item.split(':')[0]+'");\n')
process.append('\t\t\tVhpi_Set_Port_Value(obj_ref,'+item.split(':')[0]+'_v,'+item.split(':')[1]+');\n')
process.append('\t\t\tassert false report "Set port value '+item.split(':')[0]+' returns " &'+item.split(':')[0]+'_v severity note;\n')
@@ -764,12 +871,9 @@ start_server = open('start_server.sh','w')
start_server.write("#!/bin/bash\n\n")
start_server.write("###This server run ghdl testebench for infinite time till ngspice send END signal to stop it\n\n")
-start_server.write("#gcc -c ghdlserver.c\n")
-start_server.write("#ghdl -a Utility_Package.vhdl &&\n")
-start_server.write("#ghdl -a Vhpi_Package.vhdl &&\n")
start_server.write("cd "+home+"/ngspice-nghdl/src/xspice/icm/ghdl/"+fname.split('.')[0]+"/DUTghdl/\n")
start_server.write("chmod 775 sock_pkg_create.sh &&\n")
-start_server.write("./sock_pkg_create.sh $1 &&\n")
+start_server.write("./sock_pkg_create.sh $1 $2 &&\n")
start_server.write("ghdl -a sock_pkg.vhdl &&\n")
start_server.write("ghdl -a "+fname+" &&\n")
start_server.write("ghdl -a "+fname.split('.')[0]+"_tb.vhdl &&\n")
@@ -783,21 +887,24 @@ start_server.close()
sock_pkg_create = open('sock_pkg_create.sh','w')
sock_pkg_create.write("#!/bin/bash\n\n")
-sock_pkg_create.write("##This file create sock_pkg_create.vhdl file and set the instance id from parameter based on parameter\n\n")
+sock_pkg_create.write("##This file creates sock_pkg.vhdl file and sets the port and ip from parameters passed to it\n\n")
sock_pkg_create.write("echo \"library ieee;\n")
sock_pkg_create.write("package sock_pkg is\n")
-sock_pkg_create.write("\tfunction sock_pkg_fun return integer;\n")
+sock_pkg_create.write("\tfunction sock_port_fun return integer;\n")
+sock_pkg_create.write("\tfunction sock_ip_fun return string;\n")
sock_pkg_create.write("end;\n\n")
-sock_pkg_create.write("\tpackage body sock_pkg is\n")
-sock_pkg_create.write("\t function sock_pkg_fun return integer is")
-sock_pkg_create.write("\t\tvariable sock_id : integer;\n")
+sock_pkg_create.write("package body sock_pkg is\n")
+sock_pkg_create.write("\tfunction sock_port_fun return integer is\n")
+sock_pkg_create.write("\t\tvariable sock_port : integer;\n")
sock_pkg_create.write("\t\t\tbegin\n")
-sock_pkg_create.write("\t\t\t\tsock_id := $1;\n")
-sock_pkg_create.write("\t\t\t\treturn sock_id;\n")
-sock_pkg_create.write("\t\t\tend function;\n")
-sock_pkg_create.write("\t\tend package body;\" > sock_pkg.vhdl")
-
-
-
-
-
+sock_pkg_create.write("\t\t\t\tsock_port := $1;\n")
+sock_pkg_create.write("\t\t\t\treturn sock_port;\n")
+sock_pkg_create.write("\t\t\tend function;\n\n")
+sock_pkg_create.write("\tfunction sock_ip_fun return string is\n")
+sock_pkg_create.write("\t\ttype string_ptr is access string;\n")
+sock_pkg_create.write("\t\tvariable sock_ip : string_ptr;\n")
+sock_pkg_create.write("\t\t\tbegin\n")
+sock_pkg_create.write('\t\t\t\tsock_ip := new string\'(\\"$2\\");\n')
+sock_pkg_create.write("\t\t\t\treturn sock_ip.all;\n")
+sock_pkg_create.write("\t\t\tend function;\n\n")
+sock_pkg_create.write("\t\tend package body;\" > sock_pkg.vhdl") \ No newline at end of file
diff --git a/src/ngspice_ghdl.py b/src/ngspice_ghdl.py
index 0a9e88c..a4c3637 100755
--- a/src/ngspice_ghdl.py
+++ b/src/ngspice_ghdl.py
@@ -31,6 +31,7 @@ class Mainwindow(QtGui.QWidget):
#Printing LICENCE file on terminal
fileopen = open(self.licensefile, 'r')
print fileopen.read()
+ fileopen.close()
self.file_list = [] #to keep the supporting files
self.initUI()
@@ -75,7 +76,6 @@ class Mainwindow(QtGui.QWidget):
self.show()
-
def closeWindow(self):
try:
self.process.close()
@@ -84,12 +84,14 @@ class Mainwindow(QtGui.QWidget):
print "Close button clicked"
quit()
+
def browseFile(self):
print "Browse button clicked"
self.filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.')
self.ledit.setText(self.filename)
print "Vhdl file uploaded to process :", self.filename
+
def addFiles(self):
print "Starts adding supporting files"
title = self.addbtn.text()
@@ -137,13 +139,11 @@ class Mainwindow(QtGui.QWidget):
else:
print "Exiting application"
quit()
-
-
-
else:
print "Creating model "+self.modelname+" directory"
os.mkdir(self.modelname)
+
def addingModelInModpath(self):
print "Adding Model "+self.modelname+" in Modpath file "+self.digital_home
#Adding name of model in the modpath file
@@ -222,6 +222,7 @@ class Mainwindow(QtGui.QWidget):
cmd = " make"
print "Running Make command in "+self.release_home
path = os.getcwd()
+ self.process = QtCore.QProcess(self)
self.process.start(cmd)
self.process.setProcessChannelMode(QtCore.QProcess.MergedChannels)
QtCore.QObject.connect(self.process, QtCore.SIGNAL("readyReadStandardOutput()"), self, QtCore.SLOT("readStdOutput()"))
@@ -231,6 +232,7 @@ class Mainwindow(QtGui.QWidget):
print "There is error in 'make' "
quit()
+
def runMakeInstall(self):
print "run Make Install Called"
try:
@@ -241,8 +243,10 @@ class Mainwindow(QtGui.QWidget):
self.process.close()
except:
pass
- self.process.finished.connect(self.createSchematicLib)
+
+ self.process = QtCore.QProcess(self)
self.process.start(cmd)
+ self.process.finished.connect(self.createSchematicLib)
self.process.setProcessChannelMode(QtCore.QProcess.MergedChannels)
QtCore.QObject.connect(self.process, QtCore.SIGNAL("readyReadStandardOutput()"), self, QtCore.SLOT("readStdOutput()"))
os.chdir(self.cur_dir)
@@ -251,11 +255,13 @@ class Mainwindow(QtGui.QWidget):
print "There is error during in 'make install' "
quit()
+
def createSchematicLib(self):
if Appconfig.esimFlag == 1:
print 'Creating library files.................................'
- self.schematicLib = AutoSchematic(self.modelname)
- self.schematicLib.createKicadLibrary()
+ schematicLib = AutoSchematic(self.modelname)
+ schematicLib.createKicadLibrary()
+
def uploadModle(self):
print "Upload button clicked"
@@ -277,8 +283,8 @@ class Mainwindow(QtGui.QWidget):
self.runMakeInstall()
else:
QtGui.QMessageBox.about(self,'Message','''<b>Important Message.</b><br/><br/>This accepts only <b>.vhdl</b> file ''')
- except:
- QtGui.QMessageBox.about(self, 'Message','''<b>Error</b><br/><br/> select a <b>.vhdl</b> file ''')
+ except Exception as e:
+ QtGui.QMessageBox.about(self, 'Message','''<b>Error</b><br/><br/> ''' + str(e))
class FileRemover(QtGui.QWidget):
diff --git a/src/outitf.c b/src/outitf.c
index ce3e910..fba5224 100644
--- a/src/outitf.c
+++ b/src/outitf.c
@@ -1,15 +1,19 @@
/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1988 Wayne A. Christopher, U. C. Berkeley CAD Group
-Modified: 2000 AlansFixes
+Modified: 2000 AlansFixes, 2013/2015 patch by Krzysztof Blaszkowski
**********/
/**************************************************************************
* 10.Mar.2017 - RM - Added a dirty fix to handle orphan FOSSEE test bench
* processes. The following static functions were added in the process:
* o nghdl_orphan_tb()
* o nghdl_tb_SIGUSR1()
- **************************************************************************
- */
+ **************************************************************************/
+/**************************************************************************
+ * 22.Oct.2019 - RP - Read all the PIDs and send kill signal to all those
+ * processes. Also, Remove the common file of used IPs and PIDs for this
+ * Ngspice's instance rather than depending on GHDLServer to do the same.
+ **************************************************************************/
/*
* This module replaces the old "writedata" routines in nutmeg.
* Unlike the writedata routines, the OUT routines are only called by
@@ -53,8 +57,8 @@ extern char *spice_analysis_get_description(int index);
static int beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analName,
char *refName, int refType, int numNames, char **dataNames, int dataType,
bool windowed, runDesc **runp);
-static int addDataDesc(runDesc *run, char *name, int type, int ind);
-static int addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind);
+static int addDataDesc(runDesc *run, char *name, int type, int ind, int meminit);
+static int addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind, int meminit);
static void fileInit(runDesc *run);
static void fileInit_pass2(runDesc *run);
static void fileStartPoint(FILE *fp, bool bin, int num);
@@ -70,6 +74,8 @@ static bool parseSpecial(char *name, char *dev, char *param, char *ind);
static bool name_eq(char *n1, char *n2);
static bool getSpecial(dataDesc *desc, runDesc *run, IFvalue *val);
static void freeRun(runDesc *run);
+static int InterpFileAdd(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr);
+static int InterpPlotAdd(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr);
/*Output data to spice module*/
#ifdef TCL_MODULE
@@ -84,6 +90,11 @@ extern void sh_vecinit(runDesc *run);
extern bool orflag;
#endif
+// fixme
+// ugly hack to work around missing api to specify the "type" of signals
+int fixme_onoise_type = SV_NOTYPE;
+int fixme_inoise_type = SV_NOTYPE;
+
#define DOUBLE_PRECISION 15
@@ -94,36 +105,56 @@ static size_t column, rowbuflen;
static bool shouldstop = FALSE; /* Tell simulator to stop next time it asks. */
+static bool interpolated = FALSE;
+static double *valueold, *valuenew;
+
+#ifdef SHARED_MODULE
+static bool savenone = FALSE;
+#endif
+
/* 10.Mar.2017 - RM - Added nghdl_tb_SIGUSR1().*/
static void nghdl_tb_SIGUSR1(char* pid_file)
{
int ret;
char line[80];
char* nptr;
+ pid_t pid[256], tmp;
+ int count=0, i;
FILE* fp = fopen(pid_file, "r");
if (fp)
{
- if (fscanf(fp, "%s", line) != EOF)
- {
- fclose(fp);
- pid_t pid = (pid_t) strtol(line, &nptr, 10);
- // PID is converted to a decimal value.
- if ((errno != ERANGE) && (errno!= EINVAL))
- {
- if (pid)
- {
- // Check if a process with this pid really exists.
- ret = kill(pid, 0);
- if (ret == 0)
- {
- kill(pid, SIGUSR1);
- }
- }
- }
- }
+ /* 22.Oct.2019 - RP - Scan and store all the PIDs in this file */
+ while (fscanf(fp, "%s", line) == 1)
+ {
+ // PID is converted to a decimal value.
+ tmp = (pid_t) strtol(line, &nptr, 10);
+ if ((errno != ERANGE) && (errno!= EINVAL))
+ {
+ pid[count++] = tmp;
+ }
+ }
+
+ fclose(fp);
}
+
+ /* 22.Oct.2019 - RP - Kill all the active PIDs */
+ for(i=0; i<count; i++)
+ {
+ if (pid[i])
+ {
+ // Check if a process with this pid really exists.
+ ret = kill(pid[i], 0);
+ if (ret == 0)
+ {
+ kill(pid[i], SIGUSR1);
+ }
+ }
+ }
+
+ // 22.Oct.2019 - RP
+ remove(pid_file);
}
/* 10.Mar.2017 - RM - Added nghdl_orphan_tb().*/
@@ -139,35 +170,40 @@ static void nghdl_orphan_tb(void)
if ((dirfd = opendir(dir)) == NULL)
{
- fprintf(stderr, "nghdl_orphan_tb(): Cannot open /tmp\n");
+ fprintf(stderr, "nghdl_orphan_tb(): Cannot open /tmp\n");
return;
}
-/* Loop through /tmp directories looking for "NGHDL_<my pid>*" files.*/
+ /* Loop through /tmp directories looking for "NGHDL_<my pid>*" files.*/
while ((dirp = readdir(dirfd)) != NULL)
{
- struct stat stbuf;
- sprintf(filename_tmp, "/tmp/%s", dirp->d_name);
- if (strstr(filename_tmp, pid_file_prefix))
- {
- if (stat(filename_tmp, &stbuf) == -1)
- {
- fprintf(stderr,
+ struct stat stbuf;
+ sprintf(filename_tmp, "/tmp/%s", dirp->d_name);
+ if (strstr(filename_tmp, pid_file_prefix))
+ {
+ if (stat(filename_tmp, &stbuf) == -1)
+ {
+ fprintf(stderr,
"nghdl_orphan_tb: stat() failed; ERRNO=%d on file:%s\n",
errno, filename_tmp);
- continue;
- }
-
- if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
- {
- continue;
- }
- else
- {
- nghdl_tb_SIGUSR1(filename_tmp);
- }
- }
+ continue;
+ }
+
+ if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
+ {
+ continue;
+ }
+ else
+ {
+ nghdl_tb_SIGUSR1(filename_tmp);
+ }
+ }
}
+
+ // 22.Oct.2019 - RP
+ char ip_filename[40];
+ sprintf(ip_filename, "/tmp/NGHDL_COMMON_IP_%d.txt", getpid());
+ remove(ip_filename);
}
/* End 10.Mar.2017 - RM */
@@ -220,9 +256,11 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
bool saveall = TRUE;
bool savealli = FALSE;
char *an_name;
+ int initmem;
/*to resume a run saj
*All it does is reassign the file pointer and return (requires *runp to be NULL if this is not needed)
*/
+
if (dataType == 666 && numNames == 666) {
run = *runp;
run->writeOut = ft_getOutReq(&run->fp, &run->runPlot, &run->binary,
@@ -232,10 +270,16 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
/*end saj*/
/* Check to see if we want to print informational data. */
- if (cp_getvar("printinfo", CP_BOOL, NULL))
+ if (cp_getvar("printinfo", CP_BOOL, NULL, 0))
fprintf(cp_err, "(debug printing enabled)\n");
- *runp = run = alloc(struct runDesc);
+ /* Check to see if we want to save only interpolated data. */
+ if (cp_getvar("interp", CP_BOOL, NULL, 0)) {
+ interpolated = TRUE;
+ fprintf(cp_out, "Warning: Interpolated raw file data!\n\n");
+ }
+
+ *runp = run = TMALLOC(struct runDesc, 1);
/* First fill in some general information. */
run->analysis = analysisPtr;
@@ -281,12 +325,27 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
saves[i].used = 1;
continue;
}
+#ifdef SHARED_MODULE
+ /* this may happen if shared ngspice*/
+ if (cieq(saves[i].name, "none")) {
+ savenone = TRUE;
+ saveall = TRUE;
+ savesused[i] = TRUE;
+ saves[i].used = 1;
+ continue;
+ }
+#endif
}
}
+ if (numsaves && !saveall)
+ initmem = numsaves;
+ else
+ initmem = numNames;
+
/* Pass 0. */
if (refName) {
- addDataDesc(run, refName, refType, -1);
+ addDataDesc(run, refName, refType, -1, initmem);
for (i = 0; i < numsaves; i++)
if (!savesused[i] && name_eq(saves[i].name, refName)) {
savesused[i] = TRUE;
@@ -303,7 +362,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
if (!savesused[i])
for (j = 0; j < numNames; j++)
if (name_eq(saves[i].name, dataNames[j])) {
- addDataDesc(run, dataNames[j], dataType, j);
+ addDataDesc(run, dataNames[j], dataType, j, initmem);
savesused[i] = TRUE;
saves[i].used = 1;
break;
@@ -319,7 +378,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
!strstr(dataNames[i], "#emitter") &&
!strstr(dataNames[i], "#base"))
{
- addDataDesc(run, dataNames[i], dataType, i);
+ addDataDesc(run, dataNames[i], dataType, i, initmem);
}
}
@@ -349,17 +408,17 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
} else if (strstr(ch, "#emitter")) {
strcpy(ch, "[ie]");
if (parseSpecial(tmpname, namebuf, parambuf, depbuf))
- addSpecialDesc(run, tmpname, namebuf, parambuf, depind);
+ addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem);
strcpy(ch, "[is]");
} else if (strstr(ch, "#drain")) {
strcpy(ch, "[id]");
if (parseSpecial(tmpname, namebuf, parambuf, depbuf))
- addSpecialDesc(run, tmpname, namebuf, parambuf, depind);
+ addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem);
strcpy(ch, "[ig]");
} else if (strstr(ch, "#source")) {
strcpy(ch, "[is]");
if (parseSpecial(tmpname, namebuf, parambuf, depbuf))
- addSpecialDesc(run, tmpname, namebuf, parambuf, depind);
+ addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem);
strcpy(ch, "[ib]");
} else if (strstr(ch, "#internal") && (tmpname[1] == 'd')) {
strcpy(ch, "[id]");
@@ -373,7 +432,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
fprintf(stderr,
"Warning : unexpected dependent variable on %s\n", tmpname);
} else {
- addSpecialDesc(run, tmpname, namebuf, parambuf, depind);
+ addSpecialDesc(run, tmpname, namebuf, parambuf, depind, initmem);
}
}
}
@@ -410,7 +469,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
depbuf, saves[i].name);
continue;
}
- addDataDesc(run, dataNames[j], dataType, j);
+ addDataDesc(run, dataNames[j], dataType, j, initmem);
savesused[i] = TRUE;
saves[i].used = 1;
depind = j;
@@ -419,7 +478,7 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
}
}
- addSpecialDesc(run, saves[i].name, namebuf, parambuf, depind);
+ addSpecialDesc(run, saves[i].name, namebuf, parambuf, depind, initmem);
}
if (numsaves) {
@@ -455,6 +514,14 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
}
}
+ /* define storage for old and new data, to allow interpolation */
+ if (interpolated && run->circuit->CKTcurJob->JOBtype == 4) {
+ valueold = TMALLOC(double, run->numData);
+ for (i = 0; i < run->numData; i++)
+ valueold[i] = 0.0;
+ valuenew = TMALLOC(double, run->numData);
+ }
+
/*Start BLT, initilises the blt vectors saj*/
#ifdef TCL_MODULE
blt_init(run);
@@ -465,20 +532,28 @@ beginPlot(JOB *analysisPtr, CKTcircuit *circuitPtr, char *cktName, char *analNam
return (OK);
}
-
+/* Initialze memory for the list of all vectors in the current plot.
+ Add a standard vector to this plot */
static int
-addDataDesc(runDesc *run, char *name, int type, int ind)
+addDataDesc(runDesc *run, char *name, int type, int ind, int meminit)
{
dataDesc *data;
- if (!run->numData)
- run->data = TMALLOC(dataDesc, 1);
- else
- run->data = TREALLOC(dataDesc, run->data, run->numData + 1);
+ /* initialize memory (for all vectors or given by 'save') */
+ if (!run->numData) {
+ /* even if input 0, do a malloc */
+ run->data = TMALLOC(dataDesc, ++meminit);
+ run->maxData = meminit;
+ }
+ /* If there is need for more memory */
+ else if (run->numData == run->maxData) {
+ run->maxData = (int)(run->maxData * 1.1) + 1;
+ run->data = TREALLOC(dataDesc, run->data, run->maxData);
+ }
data = &run->data[run->numData];
/* so freeRun will get nice NULL pointers for the fields we don't set */
- bzero(data, sizeof(dataDesc));
+ memset(data, 0, sizeof(dataDesc));
data->name = copy(name);
data->type = type;
@@ -495,30 +570,40 @@ addDataDesc(runDesc *run, char *name, int type, int ind)
return (OK);
}
-
+/* Initialze memory for the list of all vectors in the current plot.
+ Add a special vector (e.g. @q1[ib]) to this plot */
static int
-addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind)
+addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind, int meminit)
{
dataDesc *data;
- char *unique; /* unique char * from back-end */
+ char *unique, *freeunique; /* unique char * from back-end */
+ int ret;
- if (!run->numData)
- run->data = TMALLOC(dataDesc, 1);
- else
- run->data = TREALLOC(dataDesc, run->data, run->numData + 1);
+ if (!run->numData) {
+ /* even if input 0, do a malloc */
+ run->data = TMALLOC(dataDesc, ++meminit);
+ run->maxData = meminit;
+ }
+ else if (run->numData == run->maxData) {
+ run->maxData = (int)(run->maxData * 1.1) + 1;
+ run->data = TREALLOC(dataDesc, run->data, run->maxData);
+ }
data = &run->data[run->numData];
/* so freeRun will get nice NULL pointers for the fields we don't set */
- bzero(data, sizeof(dataDesc));
+ memset(data, 0, sizeof(dataDesc));
data->name = copy(name);
- unique = copy(devname);
+ freeunique = unique = copy(devname);
- /* MW. My "special" routine here */
- INPinsertNofree(&unique, ft_curckt->ci_symtab);
+ /* unique will be overridden, if it already exists */
+ ret = INPinsertNofree(&unique, ft_curckt->ci_symtab);
data->specName = unique;
+ if (ret == E_EXISTS)
+ tfree(freeunique);
+
data->specParamName = copy(param);
data->specIndex = depind;
@@ -532,6 +617,56 @@ addSpecialDesc(runDesc *run, char *name, char *devname, char *param, int depind)
}
+static void
+OUTpD_memory(runDesc *run, IFvalue *refValue, IFvalue *valuePtr)
+{
+ int i, n = run->numData;
+
+ for (i = 0; i < n; i++) {
+
+ dataDesc *d;
+
+#ifdef TCL_MODULE
+ /*Locks the blt vector to stop access*/
+ blt_lockvec(i);
+#endif
+
+ d = &run->data[i];
+
+ if (d->outIndex == -1) {
+ if (d->type == IF_REAL)
+ plotAddRealValue(d, refValue->rValue);
+ else if (d->type == IF_COMPLEX)
+ plotAddComplexValue(d, refValue->cValue);
+ } else if (d->regular) {
+ if (d->type == IF_REAL)
+ plotAddRealValue(d, valuePtr->v.vec.rVec[d->outIndex]);
+ else if (d->type == IF_COMPLEX)
+ plotAddComplexValue(d, valuePtr->v.vec.cVec[d->outIndex]);
+ } else {
+ IFvalue val;
+
+ /* should pre-check instance */
+ if (!getSpecial(d, run, &val))
+ continue;
+
+ if (d->type == IF_REAL)
+ plotAddRealValue(d, val.rValue);
+ else if (d->type == IF_COMPLEX)
+ plotAddComplexValue(d, val.cValue);
+ else
+ fprintf(stderr, "OUTpData: unsupported data type\n");
+ }
+
+#ifdef TCL_MODULE
+ /*relinks and unlocks vector*/
+ blt_relink(i, d->vec);
+#endif
+
+ }
+}
+
+
int
OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
{
@@ -543,8 +678,18 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
#ifdef TCL_MODULE
steps_completed = run->pointCount;
#endif
-
- if (run->writeOut) {
+ /* interpolated batch mode output to file in transient analysis */
+ if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && run->writeOut) {
+ InterpFileAdd(run, refValue, valuePtr);
+ return (OK);
+ }
+ /* interpolated interactive or control mode output to plot in transient analysis */
+ else if (interpolated && run->circuit->CKTcurJob->JOBtype == 4 && !(run->writeOut)) {
+ InterpPlotAdd(run, refValue, valuePtr);
+ return (OK);
+ }
+ /* standard batch mode output to file */
+ else if (run->writeOut) {
if (run->pointCount == 1)
fileInit_pass2(run);
@@ -559,7 +704,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
every quarter of a second, to give some feedback without using
too much CPU time */
#ifndef HAS_WINGUI
- if (!orflag) {
+ if (!orflag && !ft_norefprint) {
currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
fprintf(stderr, " Reference value : % 12.5e\r",
@@ -574,7 +719,7 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
fileAddRealValue(run->fp, run->binary, refValue->rValue);
#ifndef HAS_WINGUI
- if (!orflag) {
+ if (!orflag && !ft_norefprint) {
currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
fprintf(stderr, " Reference value : % 12.5e\r",
@@ -642,7 +787,6 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
}
-
fileEndPoint(run->fp, run->binary);
/* Check that the write to disk completed successfully, otherwise abort */
@@ -654,11 +798,13 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
} else {
+ OUTpD_memory(run, refValue, valuePtr);
+
/* This is interactive mode. Update the screen with the reference
variable just the same */
#ifndef HAS_WINGUI
- if (!orflag) {
+ if (!orflag && !ft_norefprint) {
currclock = clock();
if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
if (run->isComplex) {
@@ -673,45 +819,6 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
}
#endif
- for (i = 0; i < run->numData; i++) {
-
-#ifdef TCL_MODULE
- /*Locks the blt vector to stop access*/
- blt_lockvec(i);
-#endif
-
- if (run->data[i].outIndex == -1) {
- if (run->data[i].type == IF_REAL)
- plotAddRealValue(&run->data[i], refValue->rValue);
- else if (run->data[i].type == IF_COMPLEX)
- plotAddComplexValue(&run->data[i], refValue->cValue);
- } else if (run->data[i].regular) {
- if (run->data[i].type == IF_REAL)
- plotAddRealValue(&run->data[i],
- valuePtr->v.vec.rVec[run->data[i].outIndex]);
- else if (run->data[i].type == IF_COMPLEX)
- plotAddComplexValue(&run->data[i],
- valuePtr->v.vec.cVec[run->data[i].outIndex]);
- } else {
- IFvalue val;
- /* should pre-check instance */
- if (!getSpecial(&run->data[i], run, &val))
- continue;
- if (run->data[i].type == IF_REAL)
- plotAddRealValue(&run->data[i], val.rValue);
- else if (run->data[i].type == IF_COMPLEX)
- plotAddComplexValue(&run->data[i], val.cValue);
- else
- fprintf(stderr, "OUTpData: unsupported data type\n");
- }
-
-#ifdef TCL_MODULE
- /*relinks and unlocks vector*/
- blt_relink(i, (run->data[i]).vec);
-#endif
-
- }
-
gr_iplot(run->runPlot);
}
@@ -728,7 +835,6 @@ OUTpData(runDesc *plotPtr, IFvalue *refValue, IFvalue *valuePtr)
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTwReference(void *plotPtr, IFvalue *valuePtr, void **refPtr)
{
@@ -740,7 +846,6 @@ OUTwReference(void *plotPtr, IFvalue *valuePtr, void **refPtr)
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTwData(runDesc *plotPtr, int dataIndex, IFvalue *valuePtr, void *refPtr)
{
@@ -753,7 +858,6 @@ OUTwData(runDesc *plotPtr, int dataIndex, IFvalue *valuePtr, void *refPtr)
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTwEnd(runDesc *plotPtr)
{
@@ -766,22 +870,22 @@ OUTwEnd(runDesc *plotPtr)
int
OUTendPlot(runDesc *plotPtr)
{
- runDesc *run = plotPtr; // FIXME
-
- if (run->writeOut) {
- fileEnd(run);
+ if (plotPtr->writeOut) {
+ fileEnd(plotPtr);
} else {
gr_end_iplot();
- plotEnd(run);
+ plotEnd(plotPtr);
}
- freeRun(run);
+ tfree(valueold);
+ tfree(valuenew);
+
+ freeRun(plotPtr);
return (OK);
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTbeginDomain(runDesc *plotPtr, IFuid refName, int refType, IFvalue *outerRefValue)
{
@@ -794,7 +898,6 @@ OUTbeginDomain(runDesc *plotPtr, IFuid refName, int refType, IFvalue *outerRefVa
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTendDomain(runDesc *plotPtr)
{
@@ -804,7 +907,6 @@ OUTendDomain(runDesc *plotPtr)
}
-/* ARGSUSED */ /* until some code gets written */
int
OUTattributes(runDesc *plotPtr, IFuid varName, int param, IFvalue *value)
{
@@ -897,6 +999,42 @@ fileInit(runDesc *run)
}
+static int
+guess_type(const char *name)
+{
+ int type;
+
+ if (substring("#branch", name))
+ type = SV_CURRENT;
+ else if (cieq(name, "time"))
+ type = SV_TIME;
+ else if (cieq(name, "frequency"))
+ type = SV_FREQUENCY;
+ else if (ciprefix("inoise", name))
+ type = fixme_inoise_type;
+ else if (ciprefix("onoise", name))
+ type = fixme_onoise_type;
+ else if (cieq(name, "temp-sweep"))
+ type = SV_TEMP;
+ else if (cieq(name, "res-sweep"))
+ type = SV_RES;
+ else if ((*name == '@') && substring("[g", name)) /* token starting with [g */
+ type = SV_ADMITTANCE;
+ else if ((*name == '@') && substring("[c", name))
+ type = SV_CAPACITANCE;
+ else if ((*name == '@') && substring("[i", name))
+ type = SV_CURRENT;
+ else if ((*name == '@') && substring("[q", name))
+ type = SV_CHARGE;
+ else if ((*name == '@') && substring("[p]", name)) /* token is exactly [p] */
+ type = SV_POWER;
+ else
+ type = SV_VOLTAGE;
+
+ return type;
+}
+
+
static void
fileInit_pass2(runDesc *run)
{
@@ -906,26 +1044,7 @@ fileInit_pass2(runDesc *run)
char *name = run->data[i].name;
- if (substring("#branch", name))
- type = SV_CURRENT;
- else if (cieq(name, "time"))
- type = SV_TIME;
- else if (cieq(name, "frequency"))
- type = SV_FREQUENCY;
- else if (cieq(name, "temp-sweep"))
- type = SV_TEMP;
- else if (cieq(name, "res-sweep"))
- type = SV_RES;
- else if ((*name == '@') && (substring("[g", name)))
- type = SV_ADMITTANCE;
- else if ((*name == '@') && (substring("[c", name)))
- type = SV_CAPACITANCE;
- else if ((*name == '@') && (substring("[i", name)))
- type = SV_CURRENT;
- else if ((*name == '@') && (substring("[q", name)))
- type = SV_CHARGE;
- else
- type = SV_VOLTAGE;
+ type = guess_type(name);
if (type == SV_CURRENT) {
char *branch = strstr(name, "#branch");
@@ -957,7 +1076,7 @@ fileInit_pass2(runDesc *run)
rowbuflen *= 2;
rowbuf = TMALLOC(double, rowbuflen);
} else {
- // fIXME rowbuflen = 0;
+ rowbuflen = 0;
rowbuf = NULL;
}
}
@@ -998,7 +1117,6 @@ fileAddComplexValue(FILE *fp, bool bin, IFcomplex value)
}
-/* ARGSUSED */ /* until some code gets written */
static void
fileEndPoint(FILE *fp, bool bin)
{
@@ -1015,12 +1133,13 @@ fileEndPoint(FILE *fp, bool bin)
static void
fileEnd(runDesc *run)
{
-/* 10.Mar.2017 - RM - Check if any orphan test benches are running. If any are
- * found, force them to exit.
- */
- nghdl_orphan_tb();
+ /* 10.Mar.2017 - RM - Check if any orphan test benches are running. If any are
+ * found, force them to exit.
+ */
+ nghdl_orphan_tb();
+
+ /* End 10.Mar.2017 */
-/* End 10.Mar.2017 */
if (run->fp != stdout) {
long place = ftell(run->fp);
@@ -1035,10 +1154,7 @@ fileEnd(runDesc *run)
fflush(run->fp);
- if (run->binary) {
- /* deallocate row buffer */
- tfree(rowbuf);
- }
+ tfree(rowbuf);
}
@@ -1048,9 +1164,7 @@ static void
plotInit(runDesc *run)
{
struct plot *pl = plot_alloc(run->type);
- char buf[100];
struct dvec *v;
- dataDesc *dd;
int i;
pl->pl_title = copy(run->name);
@@ -1069,71 +1183,83 @@ plotInit(runDesc *run)
run->isComplex = TRUE;
for (i = 0; i < run->numData; i++) {
- dd = &run->data[i];
- v = alloc(struct dvec);
- if (isdigit(*dd->name)) {
- (void) sprintf(buf, "V(%s)", dd->name);
- v->v_name = copy(buf);
- } else {
- v->v_name = copy(dd->name);
- }
- if (substring("#branch", v->v_name))
- v->v_type = SV_CURRENT;
- else if (cieq(v->v_name, "time"))
- v->v_type = SV_TIME;
- else if (cieq(v->v_name, "frequency"))
- v->v_type = SV_FREQUENCY;
- else if (cieq(v->v_name, "onoise_spectrum"))
- v->v_type = SV_OUTPUT_N_DENS;
- else if (cieq(v->v_name, "onoise_integrated"))
- v->v_type = SV_OUTPUT_NOISE;
- else if (cieq(v->v_name, "inoise_spectrum"))
- v->v_type = SV_INPUT_N_DENS;
- else if (cieq(v->v_name, "inoise_integrated"))
- v->v_type = SV_INPUT_NOISE;
- else if (cieq(v->v_name, "temp-sweep"))
- v->v_type = SV_TEMP;
- else if (cieq(v->v_name, "res-sweep"))
- v->v_type = SV_RES;
- else if ((*(v->v_name) == '@') && (substring("[g", v->v_name)))
- v->v_type = SV_ADMITTANCE;
- else if ((*(v->v_name) == '@') && (substring("[c", v->v_name)))
- v->v_type = SV_CAPACITANCE;
- else if ((*(v->v_name) == '@') && (substring("[i", v->v_name)))
- v->v_type = SV_CURRENT;
- else if ((*(v->v_name) == '@') && (substring("[q", v->v_name)))
- v->v_type = SV_CHARGE;
+ dataDesc *dd = &run->data[i];
+ char *name;
+
+ if (isdigit_c(dd->name[0]))
+ name = tprintf("V(%s)", dd->name);
else
- v->v_type = SV_VOLTAGE;
- v->v_length = 0;
- v->v_scale = NULL;
- if (!run->isComplex) {
- v->v_flags = VF_REAL;
- v->v_realdata = NULL;
- } else {
- v->v_flags = VF_COMPLEX;
- v->v_compdata = NULL;
- }
+ name = copy(dd->name);
- v->v_flags |= VF_PERMANENT;
+ v = dvec_alloc(name,
+ guess_type(name),
+ run->isComplex
+ ? (VF_COMPLEX | VF_PERMANENT)
+ : (VF_REAL | VF_PERMANENT),
+ 0, NULL);
vec_new(v);
dd->vec = v;
}
}
+/* prepare the vector length data for memory allocation
+ If new, and tran or pss, length is TSTOP / TSTEP plus some margin.
+ If allocated length is exceeded, check progress. When > 20% then extrapolate memory needed,
+ if less than 20% then just double the size.
+ If not tran or pss, return fixed value (1024) of memory to be added.
+ */
+static inline int
+vlength2delta(int len)
+{
+#ifdef SHARED_MODULE
+ if (savenone)
+ /* We need just a vector length of 1 */
+ return 1;
+#endif
+ /* TSTOP / TSTEP */
+ int points = ft_curckt->ci_ckt->CKTtimeListSize;
+ /* transient and pss analysis (points > 0) upon start */
+ if (len == 0 && points > 0) {
+ /* number of timesteps plus some overhead */
+ return points + 100;
+ }
+ /* transient and pss if original estimate is exceeded */
+ else if (points > 0) {
+ /* check where we are */
+ double timerel = ft_curckt->ci_ckt->CKTtime / ft_curckt->ci_ckt->CKTfinalTime;
+ /* return an estimate of the appropriate number of time points, if more than 20% of
+ the anticipated total time has passed */
+ if (timerel > 0.2)
+ return (int)(len / timerel) - len + 1;
+ /* If not, just double the available memory */
+ else
+ return len;
+ }
+ /* other analysis types that do not set CKTtimeListSize */
+ else
+ return 1024;
+}
+
static void
plotAddRealValue(dataDesc *desc, double value)
{
struct dvec *v = desc->vec;
+#ifdef SHARED_MODULE
+ if (savenone)
+ /* always save new data to same location */
+ v->v_length = 0;
+#endif
+
+ if (v->v_length >= v->v_alloc_length)
+ dvec_extend(v, v->v_length + vlength2delta(v->v_length));
+
if (isreal(v)) {
- v->v_realdata = TREALLOC(double, v->v_realdata, v->v_length + 1);
v->v_realdata[v->v_length] = value;
} else {
/* a real parading as a VF_COMPLEX */
- v->v_compdata = TREALLOC(ngcomplex_t, v->v_compdata, v->v_length + 1);
v->v_compdata[v->v_length].cx_real = value;
v->v_compdata[v->v_length].cx_imag = 0.0;
}
@@ -1148,7 +1274,14 @@ plotAddComplexValue(dataDesc *desc, IFcomplex value)
{
struct dvec *v = desc->vec;
- v->v_compdata = TREALLOC(ngcomplex_t, v->v_compdata, v->v_length + 1);
+#ifdef SHARED_MODULE
+ if (savenone)
+ v->v_length = 0;
+#endif
+
+ if (v->v_length >= v->v_alloc_length)
+ dvec_extend(v, v->v_length + vlength2delta(v->v_length));
+
v->v_compdata[v->v_length].cx_real = value.real;
v->v_compdata[v->v_length].cx_imag = value.imag;
@@ -1157,18 +1290,17 @@ plotAddComplexValue(dataDesc *desc, IFcomplex value)
}
-/* ARGSUSED */ /* until some code gets written */
static void
plotEnd(runDesc *run)
{
-/* 10.Mar.2017 - RM */
- nghdl_orphan_tb();
-/* End 10.Mar.2017 */
+ /* 10.Mar.2017 - RM */
+ nghdl_orphan_tb();
+ /* End 10.Mar.2017 */
- fprintf(stderr, "\n");
fprintf(stdout, "\nNo. of Data Rows : %d\n", run->pointCount);
}
+
/* ParseSpecial takes something of the form "@name[param,index]" and rips
* out name, param, andstrchr.
*/
@@ -1327,7 +1459,7 @@ OUTerror(int flags, char *format, IFuid *names)
char buf[BSIZE_SP], *s, *bptr;
int nindex = 0;
- if ((flags == ERR_INFO) && cp_getvar("printinfo", CP_BOOL, NULL))
+ if ((flags == ERR_INFO) && cp_getvar("printinfo", CP_BOOL, NULL, 0))
return;
for (m = msgs; m->flag; m++)
@@ -1352,3 +1484,328 @@ OUTerror(int flags, char *format, IFuid *names)
fprintf(cp_err, "%s\n", buf);
fflush(cp_err);
}
+
+
+void
+OUTerrorf(int flags, const char *format, ...)
+{
+ struct mesg *m;
+ va_list args;
+
+ if ((flags == ERR_INFO) && cp_getvar("printinfo", CP_BOOL, NULL, 0))
+ return;
+
+ for (m = msgs; m->flag; m++)
+ if (flags & m->flag)
+ fprintf(cp_err, "%s: ", m->string);
+
+ va_start (args, format);
+
+ vfprintf(cp_err, format, args);
+ fputc('\n', cp_err);
+
+ fflush(cp_err);
+
+ va_end(args);
+}
+
+
+static int
+InterpFileAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr)
+{
+ int i;
+ static double timeold = 0.0, timenew = 0.0, timestep = 0.0;
+ bool nodata = FALSE;
+ bool interpolatenow = FALSE;
+
+ if (run->pointCount == 1) {
+ fileInit_pass2(run);
+ timestep = run->circuit->CKTinitTime + run->circuit->CKTstep;
+ }
+
+ if (run->refIndex != -1) {
+ /* Save first time step */
+ if (refValue->rValue == run->circuit->CKTinitTime) {
+ timeold = refValue->rValue;
+ fileStartPoint(run->fp, run->binary, run->pointCount);
+ fileAddRealValue(run->fp, run->binary, run->circuit->CKTinitTime);
+ interpolatenow = nodata = FALSE;
+ }
+ /* Save last time step */
+ else if (refValue->rValue == run->circuit->CKTfinalTime) {
+ timeold = refValue->rValue;
+ fileStartPoint(run->fp, run->binary, run->pointCount);
+ fileAddRealValue(run->fp, run->binary, run->circuit->CKTfinalTime);
+ interpolatenow = nodata = FALSE;
+ }
+ /* Save exact point */
+ else if (refValue->rValue == timestep) {
+ timeold = refValue->rValue;
+ fileStartPoint(run->fp, run->binary, run->pointCount);
+ fileAddRealValue(run->fp, run->binary, timestep);
+ timestep += run->circuit->CKTstep;
+ interpolatenow = nodata = FALSE;
+ }
+ else if (refValue->rValue > timestep) {
+ /* add the next time step value to the vector */
+ fileStartPoint(run->fp, run->binary, run->pointCount);
+ timenew = refValue->rValue;
+ fileAddRealValue(run->fp, run->binary, timestep);
+ timestep += run->circuit->CKTstep;
+ nodata = FALSE;
+ interpolatenow = TRUE;
+ }
+ else {
+ /* Do not save this step */
+ run->pointCount--;
+ timeold = refValue->rValue;
+ nodata = TRUE;
+ interpolatenow = FALSE;
+ }
+#ifndef HAS_WINGUI
+ if (!orflag && !ft_norefprint) {
+ currclock = clock();
+ if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
+ fprintf(stderr, " Reference value : % 12.5e\r",
+ refValue->rValue);
+ lastclock = currclock;
+ }
+ }
+#endif
+
+ }
+
+ for (i = 0; i < run->numData; i++) {
+ /* we've already printed reference vec first */
+ if (run->data[i].outIndex == -1)
+ continue;
+
+#ifdef TCL_MODULE
+ blt_add(i, refValue ? refValue->rValue : NAN);
+#endif
+
+ if (run->data[i].regular) {
+ /* Store value or interpolate and store or do not store any value to file */
+ if (!interpolatenow && !nodata) {
+ /* store the first or last value */
+ valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ fileAddRealValue(run->fp, run->binary, valueold[i]);
+ }
+ else if (interpolatenow) {
+ /* Interpolate time if actual time is greater than proposed next time step */
+ double newval;
+ valuenew[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i];
+ fileAddRealValue(run->fp, run->binary, newval);
+ valueold[i] = valuenew[i];
+ }
+ else if (nodata)
+ /* Just keep the transient output value corresponding to timeold,
+ but do not store to file */
+ valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ } else {
+ IFvalue val;
+ /* should pre-check instance */
+ if (!getSpecial(&run->data[i], run, &val)) {
+
+ /* If this is the first data point, print a warning for any unrecognized
+ variables, since this has not already been checked */
+ if (run->pointCount == 1)
+ fprintf(stderr, "Warning: unrecognized variable - %s\n",
+ run->data[i].name);
+ val.rValue = 0;
+ fileAddRealValue(run->fp, run->binary, val.rValue);
+ continue;
+ }
+ if (!interpolatenow && !nodata) {
+ /* store the first or last value */
+ valueold[i] = val.rValue;
+ fileAddRealValue(run->fp, run->binary, valueold[i]);
+ }
+ else if (interpolatenow) {
+ /* Interpolate time if actual time is greater than proposed next time step */
+ double newval;
+ valuenew[i] = val.rValue;
+ newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i];
+ fileAddRealValue(run->fp, run->binary, newval);
+ valueold[i] = valuenew[i];
+ }
+ else if (nodata)
+ /* Just keep the transient output value corresponding to timeold,
+ but do not store to file */
+ valueold[i] = val.rValue;
+ }
+
+#ifdef TCL_MODULE
+ blt_add(i, valuePtr->v.vec.rVec [run->data[i].outIndex]);
+#endif
+
+ }
+
+ fileEndPoint(run->fp, run->binary);
+
+ /* Check that the write to disk completed successfully, otherwise abort */
+ if (ferror(run->fp)) {
+ fprintf(stderr, "Warning: rawfile write error !!\n");
+ shouldstop = TRUE;
+ }
+
+ if (ft_bpcheck(run->runPlot, run->pointCount) == FALSE)
+ shouldstop = TRUE;
+
+#ifdef TCL_MODULE
+ Tcl_ExecutePerLoop();
+#elif defined SHARED_MODULE
+ sh_ExecutePerLoop();
+#endif
+ return(OK);
+}
+
+static int
+InterpPlotAdd(runDesc *run, IFvalue *refValue, IFvalue *valuePtr)
+{
+ int i, iscale = -1;
+ static double timeold = 0.0, timenew = 0.0, timestep = 0.0;
+ bool nodata = FALSE;
+ bool interpolatenow = FALSE;
+
+ if (run->pointCount == 1)
+ timestep = run->circuit->CKTinitTime + run->circuit->CKTstep;
+
+ /* find the scale vector */
+ for (i = 0; i < run->numData; i++)
+ if (run->data[i].outIndex == -1) {
+ iscale = i;
+ break;
+ }
+ if (iscale == -1)
+ fprintf(stderr, "Error: no scale vector found\n");
+
+#ifdef TCL_MODULE
+ /*Locks the blt vector to stop access*/
+ blt_lockvec(iscale);
+#endif
+
+ /* Save first time step */
+ if (refValue->rValue == run->circuit->CKTinitTime) {
+ timeold = refValue->rValue;
+ plotAddRealValue(&run->data[iscale], refValue->rValue);
+ interpolatenow = nodata = FALSE;
+ }
+ /* Save last time step */
+ else if (refValue->rValue == run->circuit->CKTfinalTime) {
+ timeold = refValue->rValue;
+ plotAddRealValue(&run->data[iscale], run->circuit->CKTfinalTime);
+ interpolatenow = nodata = FALSE;
+ }
+ /* Save exact point */
+ else if (refValue->rValue == timestep) {
+ timeold = refValue->rValue;
+ plotAddRealValue(&run->data[iscale], timestep);
+ timestep += run->circuit->CKTstep;
+ interpolatenow = nodata = FALSE;
+ }
+ else if (refValue->rValue > timestep) {
+ /* add the next time step value to the vector */
+ timenew = refValue->rValue;
+ plotAddRealValue(&run->data[iscale], timestep);
+ timestep += run->circuit->CKTstep;
+ nodata = FALSE;
+ interpolatenow = TRUE;
+ }
+ else {
+ /* Do not save this step */
+ run->pointCount--;
+ timeold = refValue->rValue;
+ nodata = TRUE;
+ interpolatenow = FALSE;
+ }
+
+#ifdef TCL_MODULE
+ /*relinks and unlocks vector*/
+ blt_relink(iscale, (run->data[iscale]).vec);
+#endif
+
+#ifndef HAS_WINGUI
+ if (!orflag && !ft_norefprint) {
+ currclock = clock();
+ if ((currclock-lastclock) > (0.25*CLOCKS_PER_SEC)) {
+ fprintf(stderr, " Reference value : % 12.5e\r",
+ refValue->rValue);
+ lastclock = currclock;
+ }
+ }
+#endif
+
+ for (i = 0; i < run->numData; i++) {
+ if (i == iscale)
+ continue;
+
+#ifdef TCL_MODULE
+ /*Locks the blt vector to stop access*/
+ blt_lockvec(i);
+#endif
+
+ if (run->data[i].regular) {
+ /* Store value or interpolate and store or do not store any value to file */
+ if (!interpolatenow && !nodata) {
+ /* store the first or last value */
+ valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ plotAddRealValue(&run->data[i], valueold[i]);
+ }
+ else if (interpolatenow) {
+ /* Interpolate time if actual time is greater than proposed next time step */
+ double newval;
+ valuenew[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i];
+ plotAddRealValue(&run->data[i], newval);
+ valueold[i] = valuenew[i];
+ }
+ else if (nodata)
+ /* Just keep the transient output value corresponding to timeold,
+ but do not store to file */
+ valueold[i] = valuePtr->v.vec.rVec [run->data[i].outIndex];
+ } else {
+ IFvalue val;
+ /* should pre-check instance */
+ if (!getSpecial(&run->data[i], run, &val))
+ continue;
+ if (!interpolatenow && !nodata) {
+ /* store the first or last value */
+ valueold[i] = val.rValue;
+ plotAddRealValue(&run->data[i], valueold[i]);
+ }
+ else if (interpolatenow) {
+ /* Interpolate time if actual time is greater than proposed next time step */
+ double newval;
+ valuenew[i] = val.rValue;
+ newval = (timestep - run->circuit->CKTstep - timeold)/(timenew - timeold) * (valuenew[i] - valueold[i]) + valueold[i];
+ plotAddRealValue(&run->data[i], newval);
+ valueold[i] = valuenew[i];
+ }
+ else if (nodata)
+ /* Just keep the transient output value corresponding to timeold,
+ but do not store to file */
+ valueold[i] = val.rValue;
+ }
+
+#ifdef TCL_MODULE
+ /*relinks and unlocks vector*/
+ blt_relink(i, (run->data[i]).vec);
+#endif
+
+ }
+
+ gr_iplot(run->runPlot);
+
+ if (ft_bpcheck(run->runPlot, run->pointCount) == FALSE)
+ shouldstop = TRUE;
+
+#ifdef TCL_MODULE
+ Tcl_ExecutePerLoop();
+#elif defined SHARED_MODULE
+ sh_ExecutePerLoop();
+#endif
+
+ return(OK);
+}