diff options
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 Binary files differnew file mode 100644 index 0000000..6df02cb --- /dev/null +++ b/ghdl-0.36.tar.gz 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 Binary files differnew file mode 100644 index 0000000..22e48fd --- /dev/null +++ b/nghdl_document.pdf diff --git a/ngspice-nghdl.tar.gz b/ngspice-nghdl.tar.gz Binary files differindex 4996cdc..ac9262c 100644 --- a/ngspice-nghdl.tar.gz +++ b/ngspice-nghdl.tar.gz 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); +} |